xref: /vim-8.2.3635/src/mouse.c (revision 4f3c57f7)
1b20b9e14SBram Moolenaar /* vi:set ts=8 sts=4 sw=4 noet:
2b20b9e14SBram Moolenaar  *
3b20b9e14SBram Moolenaar  * VIM - Vi IMproved	by Bram Moolenaar
4b20b9e14SBram Moolenaar  *
5b20b9e14SBram Moolenaar  * Do ":help uganda"  in Vim to read copying and usage conditions.
6b20b9e14SBram Moolenaar  * Do ":help credits" in Vim to see a list of people who contributed.
7b20b9e14SBram Moolenaar  * See README.txt for an overview of the Vim source code.
8b20b9e14SBram Moolenaar  */
9b20b9e14SBram Moolenaar 
10b20b9e14SBram Moolenaar /*
11b20b9e14SBram Moolenaar  * mouse.c: mouse handling functions
12b20b9e14SBram Moolenaar  */
13b20b9e14SBram Moolenaar 
14b20b9e14SBram Moolenaar #include "vim.h"
15b20b9e14SBram Moolenaar 
1685c3502eSBram Moolenaar #ifdef CHECK_DOUBLE_CLICK
1785c3502eSBram Moolenaar /*
1885c3502eSBram Moolenaar  * Return the duration from t1 to t2 in milliseconds.
1985c3502eSBram Moolenaar  */
2085c3502eSBram Moolenaar     static long
time_diff_ms(struct timeval * t1,struct timeval * t2)2185c3502eSBram Moolenaar time_diff_ms(struct timeval *t1, struct timeval *t2)
2285c3502eSBram Moolenaar {
2385c3502eSBram Moolenaar     // This handles wrapping of tv_usec correctly without any special case.
2485c3502eSBram Moolenaar     // Example of 2 pairs (tv_sec, tv_usec) with a duration of 5 ms:
2585c3502eSBram Moolenaar     //	   t1 = (1, 998000) t2 = (2, 3000) gives:
2685c3502eSBram Moolenaar     //	   (2 - 1) * 1000 + (3000 - 998000) / 1000 -> 5 ms.
2785c3502eSBram Moolenaar     return (t2->tv_sec - t1->tv_sec) * 1000
2885c3502eSBram Moolenaar 	 + (t2->tv_usec - t1->tv_usec) / 1000;
2985c3502eSBram Moolenaar }
3085c3502eSBram Moolenaar #endif
3185c3502eSBram Moolenaar 
32b20b9e14SBram Moolenaar /*
33b20b9e14SBram Moolenaar  * Get class of a character for selection: same class means same word.
34b20b9e14SBram Moolenaar  * 0: blank
35b20b9e14SBram Moolenaar  * 1: punctuation groups
36b20b9e14SBram Moolenaar  * 2: normal word character
37b20b9e14SBram Moolenaar  * >2: multi-byte word character.
38b20b9e14SBram Moolenaar  */
39b20b9e14SBram Moolenaar     static int
get_mouse_class(char_u * p)40b20b9e14SBram Moolenaar get_mouse_class(char_u *p)
41b20b9e14SBram Moolenaar {
42b20b9e14SBram Moolenaar     int		c;
43b20b9e14SBram Moolenaar 
44b20b9e14SBram Moolenaar     if (has_mbyte && MB_BYTE2LEN(p[0]) > 1)
45b20b9e14SBram Moolenaar 	return mb_get_class(p);
46b20b9e14SBram Moolenaar 
47b20b9e14SBram Moolenaar     c = *p;
48b20b9e14SBram Moolenaar     if (c == ' ' || c == '\t')
49b20b9e14SBram Moolenaar 	return 0;
50b20b9e14SBram Moolenaar 
51b20b9e14SBram Moolenaar     if (vim_iswordc(c))
52b20b9e14SBram Moolenaar 	return 2;
53b20b9e14SBram Moolenaar 
54b20b9e14SBram Moolenaar     // There are a few special cases where we want certain combinations of
55b20b9e14SBram Moolenaar     // characters to be considered as a single word.  These are things like
56b20b9e14SBram Moolenaar     // "->", "/ *", "*=", "+=", "&=", "<=", ">=", "!=" etc.  Otherwise, each
57b20b9e14SBram Moolenaar     // character is in its own class.
58b20b9e14SBram Moolenaar     if (c != NUL && vim_strchr((char_u *)"-+*/%<>&|^!=", c) != NULL)
59b20b9e14SBram Moolenaar 	return 1;
60b20b9e14SBram Moolenaar     return c;
61b20b9e14SBram Moolenaar }
62b20b9e14SBram Moolenaar 
63b20b9e14SBram Moolenaar /*
64b20b9e14SBram Moolenaar  * Move "pos" back to the start of the word it's in.
65b20b9e14SBram Moolenaar  */
66b20b9e14SBram Moolenaar     static void
find_start_of_word(pos_T * pos)67b20b9e14SBram Moolenaar find_start_of_word(pos_T *pos)
68b20b9e14SBram Moolenaar {
69b20b9e14SBram Moolenaar     char_u	*line;
70b20b9e14SBram Moolenaar     int		cclass;
71b20b9e14SBram Moolenaar     int		col;
72b20b9e14SBram Moolenaar 
73b20b9e14SBram Moolenaar     line = ml_get(pos->lnum);
74b20b9e14SBram Moolenaar     cclass = get_mouse_class(line + pos->col);
75b20b9e14SBram Moolenaar 
76b20b9e14SBram Moolenaar     while (pos->col > 0)
77b20b9e14SBram Moolenaar     {
78b20b9e14SBram Moolenaar 	col = pos->col - 1;
79b20b9e14SBram Moolenaar 	col -= (*mb_head_off)(line, line + col);
80b20b9e14SBram Moolenaar 	if (get_mouse_class(line + col) != cclass)
81b20b9e14SBram Moolenaar 	    break;
82b20b9e14SBram Moolenaar 	pos->col = col;
83b20b9e14SBram Moolenaar     }
84b20b9e14SBram Moolenaar }
85b20b9e14SBram Moolenaar 
86b20b9e14SBram Moolenaar /*
87b20b9e14SBram Moolenaar  * Move "pos" forward to the end of the word it's in.
88b20b9e14SBram Moolenaar  * When 'selection' is "exclusive", the position is just after the word.
89b20b9e14SBram Moolenaar  */
90b20b9e14SBram Moolenaar     static void
find_end_of_word(pos_T * pos)91b20b9e14SBram Moolenaar find_end_of_word(pos_T *pos)
92b20b9e14SBram Moolenaar {
93b20b9e14SBram Moolenaar     char_u	*line;
94b20b9e14SBram Moolenaar     int		cclass;
95b20b9e14SBram Moolenaar     int		col;
96b20b9e14SBram Moolenaar 
97b20b9e14SBram Moolenaar     line = ml_get(pos->lnum);
98b20b9e14SBram Moolenaar     if (*p_sel == 'e' && pos->col > 0)
99b20b9e14SBram Moolenaar     {
100b20b9e14SBram Moolenaar 	--pos->col;
101b20b9e14SBram Moolenaar 	pos->col -= (*mb_head_off)(line, line + pos->col);
102b20b9e14SBram Moolenaar     }
103b20b9e14SBram Moolenaar     cclass = get_mouse_class(line + pos->col);
104b20b9e14SBram Moolenaar     while (line[pos->col] != NUL)
105b20b9e14SBram Moolenaar     {
106b20b9e14SBram Moolenaar 	col = pos->col + (*mb_ptr2len)(line + pos->col);
107b20b9e14SBram Moolenaar 	if (get_mouse_class(line + col) != cclass)
108b20b9e14SBram Moolenaar 	{
109b20b9e14SBram Moolenaar 	    if (*p_sel == 'e')
110b20b9e14SBram Moolenaar 		pos->col = col;
111b20b9e14SBram Moolenaar 	    break;
112b20b9e14SBram Moolenaar 	}
113b20b9e14SBram Moolenaar 	pos->col = col;
114b20b9e14SBram Moolenaar     }
115b20b9e14SBram Moolenaar }
116b20b9e14SBram Moolenaar 
117910c378dSBram Moolenaar #if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) \
118910c378dSBram Moolenaar 	    || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) \
119097148e8SBram Moolenaar 	    || defined(FEAT_GUI_PHOTON) \
120910c378dSBram Moolenaar 	    || defined(FEAT_TERM_POPUP_MENU)
121910c378dSBram Moolenaar # define USE_POPUP_SETPOS
122910c378dSBram Moolenaar # define NEED_VCOL2COL
123910c378dSBram Moolenaar 
124910c378dSBram Moolenaar /*
125910c378dSBram Moolenaar  * Translate window coordinates to buffer position without any side effects
126910c378dSBram Moolenaar  */
127910c378dSBram Moolenaar     static int
get_fpos_of_mouse(pos_T * mpos)128910c378dSBram Moolenaar get_fpos_of_mouse(pos_T *mpos)
129910c378dSBram Moolenaar {
130910c378dSBram Moolenaar     win_T	*wp;
131910c378dSBram Moolenaar     int		row = mouse_row;
132910c378dSBram Moolenaar     int		col = mouse_col;
133910c378dSBram Moolenaar 
134910c378dSBram Moolenaar     if (row < 0 || col < 0)		// check if it makes sense
135910c378dSBram Moolenaar 	return IN_UNKNOWN;
136910c378dSBram Moolenaar 
137910c378dSBram Moolenaar     // find the window where the row is in
138910c378dSBram Moolenaar     wp = mouse_find_win(&row, &col, FAIL_POPUP);
139910c378dSBram Moolenaar     if (wp == NULL)
140910c378dSBram Moolenaar 	return IN_UNKNOWN;
141910c378dSBram Moolenaar     // winpos and height may change in win_enter()!
142910c378dSBram Moolenaar     if (row >= wp->w_height)	// In (or below) status line
143910c378dSBram Moolenaar 	return IN_STATUS_LINE;
144910c378dSBram Moolenaar     if (col >= wp->w_width)	// In vertical separator line
145910c378dSBram Moolenaar 	return IN_SEP_LINE;
146910c378dSBram Moolenaar 
147910c378dSBram Moolenaar     if (wp != curwin)
148910c378dSBram Moolenaar 	return IN_UNKNOWN;
149910c378dSBram Moolenaar 
150910c378dSBram Moolenaar     // compute the position in the buffer line from the posn on the screen
151910c378dSBram Moolenaar     if (mouse_comp_pos(curwin, &row, &col, &mpos->lnum, NULL))
152910c378dSBram Moolenaar 	return IN_STATUS_LINE; // past bottom
153910c378dSBram Moolenaar 
154910c378dSBram Moolenaar     mpos->col = vcol2col(wp, mpos->lnum, col);
155910c378dSBram Moolenaar 
156910c378dSBram Moolenaar     if (mpos->col > 0)
157910c378dSBram Moolenaar 	--mpos->col;
158910c378dSBram Moolenaar     mpos->coladd = 0;
159910c378dSBram Moolenaar     return IN_BUFFER;
160910c378dSBram Moolenaar }
161910c378dSBram Moolenaar #endif
162910c378dSBram Moolenaar 
163b20b9e14SBram Moolenaar /*
164b20b9e14SBram Moolenaar  * Do the appropriate action for the current mouse click in the current mode.
165b20b9e14SBram Moolenaar  * Not used for Command-line mode.
166b20b9e14SBram Moolenaar  *
167b20b9e14SBram Moolenaar  * Normal and Visual Mode:
168b20b9e14SBram Moolenaar  * event	 modi-	position      visual	   change   action
169b20b9e14SBram Moolenaar  *		 fier	cursor			   window
170b20b9e14SBram Moolenaar  * left press	  -	yes	    end		    yes
171b20b9e14SBram Moolenaar  * left press	  C	yes	    end		    yes	    "^]" (2)
172b20b9e14SBram Moolenaar  * left press	  S	yes	end (popup: extend) yes	    "*" (2)
173b20b9e14SBram Moolenaar  * left drag	  -	yes	start if moved	    no
174b20b9e14SBram Moolenaar  * left relse	  -	yes	start if moved	    no
175b20b9e14SBram Moolenaar  * middle press	  -	yes	 if not active	    no	    put register
176b20b9e14SBram Moolenaar  * middle press	  -	yes	 if active	    no	    yank and put
177b20b9e14SBram Moolenaar  * right press	  -	yes	start or extend	    yes
178b20b9e14SBram Moolenaar  * right press	  S	yes	no change	    yes	    "#" (2)
179b20b9e14SBram Moolenaar  * right drag	  -	yes	extend		    no
180b20b9e14SBram Moolenaar  * right relse	  -	yes	extend		    no
181b20b9e14SBram Moolenaar  *
182b20b9e14SBram Moolenaar  * Insert or Replace Mode:
183b20b9e14SBram Moolenaar  * event	 modi-	position      visual	   change   action
184b20b9e14SBram Moolenaar  *		 fier	cursor			   window
185b20b9e14SBram Moolenaar  * left press	  -	yes	(cannot be active)  yes
186b20b9e14SBram Moolenaar  * left press	  C	yes	(cannot be active)  yes	    "CTRL-O^]" (2)
187b20b9e14SBram Moolenaar  * left press	  S	yes	(cannot be active)  yes	    "CTRL-O*" (2)
188b20b9e14SBram Moolenaar  * left drag	  -	yes	start or extend (1) no	    CTRL-O (1)
189b20b9e14SBram Moolenaar  * left relse	  -	yes	start or extend (1) no	    CTRL-O (1)
190b20b9e14SBram Moolenaar  * middle press	  -	no	(cannot be active)  no	    put register
191b20b9e14SBram Moolenaar  * right press	  -	yes	start or extend	    yes	    CTRL-O
192b20b9e14SBram Moolenaar  * right press	  S	yes	(cannot be active)  yes	    "CTRL-O#" (2)
193b20b9e14SBram Moolenaar  *
194b20b9e14SBram Moolenaar  * (1) only if mouse pointer moved since press
195b20b9e14SBram Moolenaar  * (2) only if click is in same buffer
196b20b9e14SBram Moolenaar  *
197b20b9e14SBram Moolenaar  * Return TRUE if start_arrow() should be called for edit mode.
198b20b9e14SBram Moolenaar  */
199b20b9e14SBram Moolenaar     int
do_mouse(oparg_T * oap,int c,int dir,long count,int fixindent)200b20b9e14SBram Moolenaar do_mouse(
201b20b9e14SBram Moolenaar     oparg_T	*oap,		// operator argument, can be NULL
202b20b9e14SBram Moolenaar     int		c,		// K_LEFTMOUSE, etc
203b20b9e14SBram Moolenaar     int		dir,		// Direction to 'put' if necessary
204b20b9e14SBram Moolenaar     long	count,
205b20b9e14SBram Moolenaar     int		fixindent)	// PUT_FIXINDENT if fixing indent necessary
206b20b9e14SBram Moolenaar {
207b20b9e14SBram Moolenaar     static int	do_always = FALSE;	// ignore 'mouse' setting next time
208b20b9e14SBram Moolenaar     static int	got_click = FALSE;	// got a click some time back
209b20b9e14SBram Moolenaar 
210b20b9e14SBram Moolenaar     int		which_button;	// MOUSE_LEFT, _MIDDLE or _RIGHT
211b20b9e14SBram Moolenaar     int		is_click = FALSE; // If FALSE it's a drag or release event
212b20b9e14SBram Moolenaar     int		is_drag = FALSE;  // If TRUE it's a drag event
213b20b9e14SBram Moolenaar     int		jump_flags = 0;	// flags for jump_to_mouse()
214b20b9e14SBram Moolenaar     pos_T	start_visual;
215b20b9e14SBram Moolenaar     int		moved;		// Has cursor moved?
216b20b9e14SBram Moolenaar     int		in_status_line;	// mouse in status line
217b20b9e14SBram Moolenaar     static int	in_tab_line = FALSE; // mouse clicked in tab line
218b20b9e14SBram Moolenaar     int		in_sep_line;	// mouse in vertical separator line
219b20b9e14SBram Moolenaar     int		c1, c2;
220b20b9e14SBram Moolenaar #if defined(FEAT_FOLDING)
221b20b9e14SBram Moolenaar     pos_T	save_cursor;
222b20b9e14SBram Moolenaar #endif
223b20b9e14SBram Moolenaar     win_T	*old_curwin = curwin;
224b20b9e14SBram Moolenaar     static pos_T orig_cursor;
225b20b9e14SBram Moolenaar     colnr_T	leftcol, rightcol;
226b20b9e14SBram Moolenaar     pos_T	end_visual;
227b20b9e14SBram Moolenaar     int		diff;
228b20b9e14SBram Moolenaar     int		old_active = VIsual_active;
229b20b9e14SBram Moolenaar     int		old_mode = VIsual_mode;
230b20b9e14SBram Moolenaar     int		regname;
231b20b9e14SBram Moolenaar 
232b20b9e14SBram Moolenaar #if defined(FEAT_FOLDING)
233b20b9e14SBram Moolenaar     save_cursor = curwin->w_cursor;
234b20b9e14SBram Moolenaar #endif
235b20b9e14SBram Moolenaar 
236b20b9e14SBram Moolenaar     // When GUI is active, always recognize mouse events, otherwise:
237b20b9e14SBram Moolenaar     // - Ignore mouse event in normal mode if 'mouse' doesn't include 'n'.
238b20b9e14SBram Moolenaar     // - Ignore mouse event in visual mode if 'mouse' doesn't include 'v'.
239b20b9e14SBram Moolenaar     // - For command line and insert mode 'mouse' is checked before calling
240b20b9e14SBram Moolenaar     //	 do_mouse().
241b20b9e14SBram Moolenaar     if (do_always)
242b20b9e14SBram Moolenaar 	do_always = FALSE;
243b20b9e14SBram Moolenaar     else
244b20b9e14SBram Moolenaar #ifdef FEAT_GUI
245b20b9e14SBram Moolenaar 	if (!gui.in_use)
246b20b9e14SBram Moolenaar #endif
247b20b9e14SBram Moolenaar 	{
248b20b9e14SBram Moolenaar 	    if (VIsual_active)
249b20b9e14SBram Moolenaar 	    {
250b20b9e14SBram Moolenaar 		if (!mouse_has(MOUSE_VISUAL))
251b20b9e14SBram Moolenaar 		    return FALSE;
252b20b9e14SBram Moolenaar 	    }
253b20b9e14SBram Moolenaar 	    else if (State == NORMAL && !mouse_has(MOUSE_NORMAL))
254b20b9e14SBram Moolenaar 		return FALSE;
255b20b9e14SBram Moolenaar 	}
256b20b9e14SBram Moolenaar 
257b20b9e14SBram Moolenaar     for (;;)
258b20b9e14SBram Moolenaar     {
259b20b9e14SBram Moolenaar 	which_button = get_mouse_button(KEY2TERMCAP1(c), &is_click, &is_drag);
260b20b9e14SBram Moolenaar 	if (is_drag)
261b20b9e14SBram Moolenaar 	{
262b20b9e14SBram Moolenaar 	    // If the next character is the same mouse event then use that
263b20b9e14SBram Moolenaar 	    // one. Speeds up dragging the status line.
264b20b9e14SBram Moolenaar 	    if (vpeekc() != NUL)
265b20b9e14SBram Moolenaar 	    {
266b20b9e14SBram Moolenaar 		int nc;
267b20b9e14SBram Moolenaar 		int save_mouse_row = mouse_row;
268b20b9e14SBram Moolenaar 		int save_mouse_col = mouse_col;
269b20b9e14SBram Moolenaar 
270b20b9e14SBram Moolenaar 		// Need to get the character, peeking doesn't get the actual
271b20b9e14SBram Moolenaar 		// one.
272b20b9e14SBram Moolenaar 		nc = safe_vgetc();
273b20b9e14SBram Moolenaar 		if (c == nc)
274b20b9e14SBram Moolenaar 		    continue;
275b20b9e14SBram Moolenaar 		vungetc(nc);
276b20b9e14SBram Moolenaar 		mouse_row = save_mouse_row;
277b20b9e14SBram Moolenaar 		mouse_col = save_mouse_col;
278b20b9e14SBram Moolenaar 	    }
279b20b9e14SBram Moolenaar 	}
280b20b9e14SBram Moolenaar 	break;
281b20b9e14SBram Moolenaar     }
282b20b9e14SBram Moolenaar 
283b20b9e14SBram Moolenaar     if (c == K_MOUSEMOVE)
284b20b9e14SBram Moolenaar     {
285b20b9e14SBram Moolenaar 	// Mouse moved without a button pressed.
286b20b9e14SBram Moolenaar #ifdef FEAT_BEVAL_TERM
287b20b9e14SBram Moolenaar 	ui_may_remove_balloon();
288b20b9e14SBram Moolenaar 	if (p_bevalterm)
289b20b9e14SBram Moolenaar 	{
290b20b9e14SBram Moolenaar 	    profile_setlimit(p_bdlay, &bevalexpr_due);
291b20b9e14SBram Moolenaar 	    bevalexpr_due_set = TRUE;
292b20b9e14SBram Moolenaar 	}
293b20b9e14SBram Moolenaar #endif
29405ad5ff0SBram Moolenaar #ifdef FEAT_PROP_POPUP
295b20b9e14SBram Moolenaar 	popup_handle_mouse_moved();
296b20b9e14SBram Moolenaar #endif
297b20b9e14SBram Moolenaar 	return FALSE;
298b20b9e14SBram Moolenaar     }
299b20b9e14SBram Moolenaar 
300b20b9e14SBram Moolenaar #ifdef FEAT_MOUSESHAPE
301b20b9e14SBram Moolenaar     // May have stopped dragging the status or separator line.  The pointer is
302b20b9e14SBram Moolenaar     // most likely still on the status or separator line.
303b20b9e14SBram Moolenaar     if (!is_drag && drag_status_line)
304b20b9e14SBram Moolenaar     {
305b20b9e14SBram Moolenaar 	drag_status_line = FALSE;
306b20b9e14SBram Moolenaar 	update_mouseshape(SHAPE_IDX_STATUS);
307b20b9e14SBram Moolenaar     }
308b20b9e14SBram Moolenaar     if (!is_drag && drag_sep_line)
309b20b9e14SBram Moolenaar     {
310b20b9e14SBram Moolenaar 	drag_sep_line = FALSE;
311b20b9e14SBram Moolenaar 	update_mouseshape(SHAPE_IDX_VSEP);
312b20b9e14SBram Moolenaar     }
313b20b9e14SBram Moolenaar #endif
314b20b9e14SBram Moolenaar 
315b20b9e14SBram Moolenaar     // Ignore drag and release events if we didn't get a click.
316b20b9e14SBram Moolenaar     if (is_click)
317b20b9e14SBram Moolenaar 	got_click = TRUE;
318b20b9e14SBram Moolenaar     else
319b20b9e14SBram Moolenaar     {
320b20b9e14SBram Moolenaar 	if (!got_click)			// didn't get click, ignore
321b20b9e14SBram Moolenaar 	    return FALSE;
322b20b9e14SBram Moolenaar 	if (!is_drag)			// release, reset got_click
323b20b9e14SBram Moolenaar 	{
324b20b9e14SBram Moolenaar 	    got_click = FALSE;
325b20b9e14SBram Moolenaar 	    if (in_tab_line)
326b20b9e14SBram Moolenaar 	    {
327b20b9e14SBram Moolenaar 		in_tab_line = FALSE;
328b20b9e14SBram Moolenaar 		return FALSE;
329b20b9e14SBram Moolenaar 	    }
330b20b9e14SBram Moolenaar 	}
331b20b9e14SBram Moolenaar     }
332b20b9e14SBram Moolenaar 
333b20b9e14SBram Moolenaar     // CTRL right mouse button does CTRL-T
334b20b9e14SBram Moolenaar     if (is_click && (mod_mask & MOD_MASK_CTRL) && which_button == MOUSE_RIGHT)
335b20b9e14SBram Moolenaar     {
336b20b9e14SBram Moolenaar 	if (State & INSERT)
337b20b9e14SBram Moolenaar 	    stuffcharReadbuff(Ctrl_O);
338b20b9e14SBram Moolenaar 	if (count > 1)
339b20b9e14SBram Moolenaar 	    stuffnumReadbuff(count);
340b20b9e14SBram Moolenaar 	stuffcharReadbuff(Ctrl_T);
341b20b9e14SBram Moolenaar 	got_click = FALSE;		// ignore drag&release now
342b20b9e14SBram Moolenaar 	return FALSE;
343b20b9e14SBram Moolenaar     }
344b20b9e14SBram Moolenaar 
345b20b9e14SBram Moolenaar     // CTRL only works with left mouse button
346b20b9e14SBram Moolenaar     if ((mod_mask & MOD_MASK_CTRL) && which_button != MOUSE_LEFT)
347b20b9e14SBram Moolenaar 	return FALSE;
348b20b9e14SBram Moolenaar 
349b20b9e14SBram Moolenaar     // When a modifier is down, ignore drag and release events, as well as
350b20b9e14SBram Moolenaar     // multiple clicks and the middle mouse button.
351b20b9e14SBram Moolenaar     // Accept shift-leftmouse drags when 'mousemodel' is "popup.*".
352b20b9e14SBram Moolenaar     if ((mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL | MOD_MASK_ALT
353b20b9e14SBram Moolenaar 							     | MOD_MASK_META))
354b20b9e14SBram Moolenaar 	    && (!is_click
355b20b9e14SBram Moolenaar 		|| (mod_mask & MOD_MASK_MULTI_CLICK)
356b20b9e14SBram Moolenaar 		|| which_button == MOUSE_MIDDLE)
357b20b9e14SBram Moolenaar 	    && !((mod_mask & (MOD_MASK_SHIFT|MOD_MASK_ALT))
358b20b9e14SBram Moolenaar 		&& mouse_model_popup()
359b20b9e14SBram Moolenaar 		&& which_button == MOUSE_LEFT)
360b20b9e14SBram Moolenaar 	    && !((mod_mask & MOD_MASK_ALT)
361b20b9e14SBram Moolenaar 		&& !mouse_model_popup()
362b20b9e14SBram Moolenaar 		&& which_button == MOUSE_RIGHT)
363b20b9e14SBram Moolenaar 	    )
364b20b9e14SBram Moolenaar 	return FALSE;
365b20b9e14SBram Moolenaar 
366b20b9e14SBram Moolenaar     // If the button press was used as the movement command for an operator
367b20b9e14SBram Moolenaar     // (eg "d<MOUSE>"), or it is the middle button that is held down, ignore
368b20b9e14SBram Moolenaar     // drag/release events.
369b20b9e14SBram Moolenaar     if (!is_click && which_button == MOUSE_MIDDLE)
370b20b9e14SBram Moolenaar 	return FALSE;
371b20b9e14SBram Moolenaar 
372b20b9e14SBram Moolenaar     if (oap != NULL)
373b20b9e14SBram Moolenaar 	regname = oap->regname;
374b20b9e14SBram Moolenaar     else
375b20b9e14SBram Moolenaar 	regname = 0;
376b20b9e14SBram Moolenaar 
377b20b9e14SBram Moolenaar     // Middle mouse button does a 'put' of the selected text
378b20b9e14SBram Moolenaar     if (which_button == MOUSE_MIDDLE)
379b20b9e14SBram Moolenaar     {
380b20b9e14SBram Moolenaar 	if (State == NORMAL)
381b20b9e14SBram Moolenaar 	{
382b20b9e14SBram Moolenaar 	    // If an operator was pending, we don't know what the user wanted
383b20b9e14SBram Moolenaar 	    // to do. Go back to normal mode: Clear the operator and beep().
384b20b9e14SBram Moolenaar 	    if (oap != NULL && oap->op_type != OP_NOP)
385b20b9e14SBram Moolenaar 	    {
386b20b9e14SBram Moolenaar 		clearopbeep(oap);
387b20b9e14SBram Moolenaar 		return FALSE;
388b20b9e14SBram Moolenaar 	    }
389b20b9e14SBram Moolenaar 
390b20b9e14SBram Moolenaar 	    // If visual was active, yank the highlighted text and put it
391b20b9e14SBram Moolenaar 	    // before the mouse pointer position.
392b20b9e14SBram Moolenaar 	    // In Select mode replace the highlighted text with the clipboard.
393b20b9e14SBram Moolenaar 	    if (VIsual_active)
394b20b9e14SBram Moolenaar 	    {
395b20b9e14SBram Moolenaar 		if (VIsual_select)
396b20b9e14SBram Moolenaar 		{
397b20b9e14SBram Moolenaar 		    stuffcharReadbuff(Ctrl_G);
398b20b9e14SBram Moolenaar 		    stuffReadbuff((char_u *)"\"+p");
399b20b9e14SBram Moolenaar 		}
400b20b9e14SBram Moolenaar 		else
401b20b9e14SBram Moolenaar 		{
402b20b9e14SBram Moolenaar 		    stuffcharReadbuff('y');
403b20b9e14SBram Moolenaar 		    stuffcharReadbuff(K_MIDDLEMOUSE);
404b20b9e14SBram Moolenaar 		}
405b20b9e14SBram Moolenaar 		do_always = TRUE;	// ignore 'mouse' setting next time
406b20b9e14SBram Moolenaar 		return FALSE;
407b20b9e14SBram Moolenaar 	    }
408b20b9e14SBram Moolenaar 	    // The rest is below jump_to_mouse()
409b20b9e14SBram Moolenaar 	}
410b20b9e14SBram Moolenaar 
411b20b9e14SBram Moolenaar 	else if ((State & INSERT) == 0)
412b20b9e14SBram Moolenaar 	    return FALSE;
413b20b9e14SBram Moolenaar 
414b20b9e14SBram Moolenaar 	// Middle click in insert mode doesn't move the mouse, just insert the
415b20b9e14SBram Moolenaar 	// contents of a register.  '.' register is special, can't insert that
416b20b9e14SBram Moolenaar 	// with do_put().
417b20b9e14SBram Moolenaar 	// Also paste at the cursor if the current mode isn't in 'mouse' (only
418b20b9e14SBram Moolenaar 	// happens for the GUI).
419b20b9e14SBram Moolenaar 	if ((State & INSERT) || !mouse_has(MOUSE_NORMAL))
420b20b9e14SBram Moolenaar 	{
421b20b9e14SBram Moolenaar 	    if (regname == '.')
422b20b9e14SBram Moolenaar 		insert_reg(regname, TRUE);
423b20b9e14SBram Moolenaar 	    else
424b20b9e14SBram Moolenaar 	    {
425b20b9e14SBram Moolenaar #ifdef FEAT_CLIPBOARD
426b20b9e14SBram Moolenaar 		if (clip_star.available && regname == 0)
427b20b9e14SBram Moolenaar 		    regname = '*';
428b20b9e14SBram Moolenaar #endif
429b20b9e14SBram Moolenaar 		if ((State & REPLACE_FLAG) && !yank_register_mline(regname))
430b20b9e14SBram Moolenaar 		    insert_reg(regname, TRUE);
431b20b9e14SBram Moolenaar 		else
432b20b9e14SBram Moolenaar 		{
433c3516f7eSBram Moolenaar 		    do_put(regname, NULL, BACKWARD, 1L,
434c3516f7eSBram Moolenaar 						      fixindent | PUT_CURSEND);
435b20b9e14SBram Moolenaar 
436b20b9e14SBram Moolenaar 		    // Repeat it with CTRL-R CTRL-O r or CTRL-R CTRL-P r
437b20b9e14SBram Moolenaar 		    AppendCharToRedobuff(Ctrl_R);
438b20b9e14SBram Moolenaar 		    AppendCharToRedobuff(fixindent ? Ctrl_P : Ctrl_O);
439b20b9e14SBram Moolenaar 		    AppendCharToRedobuff(regname == 0 ? '"' : regname);
440b20b9e14SBram Moolenaar 		}
441b20b9e14SBram Moolenaar 	    }
442b20b9e14SBram Moolenaar 	    return FALSE;
443b20b9e14SBram Moolenaar 	}
444b20b9e14SBram Moolenaar     }
445b20b9e14SBram Moolenaar 
446b20b9e14SBram Moolenaar     // When dragging or button-up stay in the same window.
447b20b9e14SBram Moolenaar     if (!is_click)
448b20b9e14SBram Moolenaar 	jump_flags |= MOUSE_FOCUS | MOUSE_DID_MOVE;
449b20b9e14SBram Moolenaar 
450b20b9e14SBram Moolenaar     start_visual.lnum = 0;
451b20b9e14SBram Moolenaar 
452b20b9e14SBram Moolenaar     // Check for clicking in the tab page line.
453b20b9e14SBram Moolenaar     if (mouse_row == 0 && firstwin->w_winrow > 0)
454b20b9e14SBram Moolenaar     {
455b20b9e14SBram Moolenaar 	if (is_drag)
456b20b9e14SBram Moolenaar 	{
457b20b9e14SBram Moolenaar 	    if (in_tab_line)
458b20b9e14SBram Moolenaar 	    {
459b20b9e14SBram Moolenaar 		c1 = TabPageIdxs[mouse_col];
460b20b9e14SBram Moolenaar 		tabpage_move(c1 <= 0 ? 9999 : c1 < tabpage_index(curtab)
461b20b9e14SBram Moolenaar 								? c1 - 1 : c1);
462b20b9e14SBram Moolenaar 	    }
463b20b9e14SBram Moolenaar 	    return FALSE;
464b20b9e14SBram Moolenaar 	}
465b20b9e14SBram Moolenaar 
466b20b9e14SBram Moolenaar 	// click in a tab selects that tab page
467b20b9e14SBram Moolenaar 	if (is_click
468b20b9e14SBram Moolenaar # ifdef FEAT_CMDWIN
469b20b9e14SBram Moolenaar 		&& cmdwin_type == 0
470b20b9e14SBram Moolenaar # endif
471b20b9e14SBram Moolenaar 		&& mouse_col < Columns)
472b20b9e14SBram Moolenaar 	{
473b20b9e14SBram Moolenaar 	    in_tab_line = TRUE;
474b20b9e14SBram Moolenaar 	    c1 = TabPageIdxs[mouse_col];
475b20b9e14SBram Moolenaar 	    if (c1 >= 0)
476b20b9e14SBram Moolenaar 	    {
477b20b9e14SBram Moolenaar 		if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK)
478b20b9e14SBram Moolenaar 		{
479b20b9e14SBram Moolenaar 		    // double click opens new page
480*4f3c57f7SBram Moolenaar 		    end_visual_mode_keep_button();
481b20b9e14SBram Moolenaar 		    tabpage_new();
482b20b9e14SBram Moolenaar 		    tabpage_move(c1 == 0 ? 9999 : c1 - 1);
483b20b9e14SBram Moolenaar 		}
484b20b9e14SBram Moolenaar 		else
485b20b9e14SBram Moolenaar 		{
486b20b9e14SBram Moolenaar 		    // Go to specified tab page, or next one if not clicking
487b20b9e14SBram Moolenaar 		    // on a label.
488b20b9e14SBram Moolenaar 		    goto_tabpage(c1);
489b20b9e14SBram Moolenaar 
490b20b9e14SBram Moolenaar 		    // It's like clicking on the status line of a window.
491b20b9e14SBram Moolenaar 		    if (curwin != old_curwin)
492*4f3c57f7SBram Moolenaar 			end_visual_mode_keep_button();
493b20b9e14SBram Moolenaar 		}
494b20b9e14SBram Moolenaar 	    }
495b20b9e14SBram Moolenaar 	    else
496b20b9e14SBram Moolenaar 	    {
497b20b9e14SBram Moolenaar 		tabpage_T	*tp;
498b20b9e14SBram Moolenaar 
499b20b9e14SBram Moolenaar 		// Close the current or specified tab page.
500b20b9e14SBram Moolenaar 		if (c1 == -999)
501b20b9e14SBram Moolenaar 		    tp = curtab;
502b20b9e14SBram Moolenaar 		else
503b20b9e14SBram Moolenaar 		    tp = find_tabpage(-c1);
504b20b9e14SBram Moolenaar 		if (tp == curtab)
505b20b9e14SBram Moolenaar 		{
506b20b9e14SBram Moolenaar 		    if (first_tabpage->tp_next != NULL)
507b20b9e14SBram Moolenaar 			tabpage_close(FALSE);
508b20b9e14SBram Moolenaar 		}
509b20b9e14SBram Moolenaar 		else if (tp != NULL)
510b20b9e14SBram Moolenaar 		    tabpage_close_other(tp, FALSE);
511b20b9e14SBram Moolenaar 	    }
512b20b9e14SBram Moolenaar 	}
513b20b9e14SBram Moolenaar 	return TRUE;
514b20b9e14SBram Moolenaar     }
515b20b9e14SBram Moolenaar     else if (is_drag && in_tab_line)
516b20b9e14SBram Moolenaar     {
517b20b9e14SBram Moolenaar 	c1 = TabPageIdxs[mouse_col];
518b20b9e14SBram Moolenaar 	tabpage_move(c1 <= 0 ? 9999 : c1 - 1);
519b20b9e14SBram Moolenaar 	return FALSE;
520b20b9e14SBram Moolenaar     }
521b20b9e14SBram Moolenaar 
522b20b9e14SBram Moolenaar     // When 'mousemodel' is "popup" or "popup_setpos", translate mouse events:
523b20b9e14SBram Moolenaar     // right button up   -> pop-up menu
524b20b9e14SBram Moolenaar     // shift-left button -> right button
525b20b9e14SBram Moolenaar     // alt-left button   -> alt-right button
526b20b9e14SBram Moolenaar     if (mouse_model_popup())
527b20b9e14SBram Moolenaar     {
528b20b9e14SBram Moolenaar 	if (which_button == MOUSE_RIGHT
529b20b9e14SBram Moolenaar 			    && !(mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)))
530b20b9e14SBram Moolenaar 	{
531910c378dSBram Moolenaar #ifdef USE_POPUP_SETPOS
532b20b9e14SBram Moolenaar # ifdef FEAT_GUI
533b20b9e14SBram Moolenaar 	    if (gui.in_use)
534b20b9e14SBram Moolenaar 	    {
535b20b9e14SBram Moolenaar #  if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) \
536097148e8SBram Moolenaar 			  || defined(FEAT_GUI_PHOTON)
537b20b9e14SBram Moolenaar 		if (!is_click)
538b20b9e14SBram Moolenaar 		    // Ignore right button release events, only shows the popup
539b20b9e14SBram Moolenaar 		    // menu on the button down event.
540b20b9e14SBram Moolenaar 		    return FALSE;
541b20b9e14SBram Moolenaar #  endif
542b3f74069SBram Moolenaar #  if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_HAIKU)
543b20b9e14SBram Moolenaar 		if (is_click || is_drag)
544b20b9e14SBram Moolenaar 		    // Ignore right button down and drag mouse events.  Windows
545b20b9e14SBram Moolenaar 		    // only shows the popup menu on the button up event.
546b20b9e14SBram Moolenaar 		    return FALSE;
547b20b9e14SBram Moolenaar #  endif
548b20b9e14SBram Moolenaar 	    }
549b20b9e14SBram Moolenaar # endif
550b20b9e14SBram Moolenaar # if defined(FEAT_GUI) && defined(FEAT_TERM_POPUP_MENU)
551b20b9e14SBram Moolenaar 	    else
552b20b9e14SBram Moolenaar # endif
553b20b9e14SBram Moolenaar # if defined(FEAT_TERM_POPUP_MENU)
554b20b9e14SBram Moolenaar 	    if (!is_click)
555b20b9e14SBram Moolenaar 		// Ignore right button release events, only shows the popup
556b20b9e14SBram Moolenaar 		// menu on the button down event.
557b20b9e14SBram Moolenaar 		return FALSE;
558b20b9e14SBram Moolenaar #endif
559b20b9e14SBram Moolenaar 
560b20b9e14SBram Moolenaar 	    jump_flags = 0;
561b20b9e14SBram Moolenaar 	    if (STRCMP(p_mousem, "popup_setpos") == 0)
562b20b9e14SBram Moolenaar 	    {
563b20b9e14SBram Moolenaar 		// First set the cursor position before showing the popup
564b20b9e14SBram Moolenaar 		// menu.
565b20b9e14SBram Moolenaar 		if (VIsual_active)
566b20b9e14SBram Moolenaar 		{
567b20b9e14SBram Moolenaar 		    pos_T    m_pos;
568b20b9e14SBram Moolenaar 
569b20b9e14SBram Moolenaar 		    // set MOUSE_MAY_STOP_VIS if we are outside the
570b20b9e14SBram Moolenaar 		    // selection or the current window (might have false
571b20b9e14SBram Moolenaar 		    // negative here)
572b20b9e14SBram Moolenaar 		    if (mouse_row < curwin->w_winrow
573b20b9e14SBram Moolenaar 			 || mouse_row
574b20b9e14SBram Moolenaar 				  > (curwin->w_winrow + curwin->w_height))
575b20b9e14SBram Moolenaar 			jump_flags = MOUSE_MAY_STOP_VIS;
576b20b9e14SBram Moolenaar 		    else if (get_fpos_of_mouse(&m_pos) != IN_BUFFER)
577b20b9e14SBram Moolenaar 			jump_flags = MOUSE_MAY_STOP_VIS;
578b20b9e14SBram Moolenaar 		    else
579b20b9e14SBram Moolenaar 		    {
580b20b9e14SBram Moolenaar 			if ((LT_POS(curwin->w_cursor, VIsual)
581b20b9e14SBram Moolenaar 				    && (LT_POS(m_pos, curwin->w_cursor)
582b20b9e14SBram Moolenaar 					|| LT_POS(VIsual, m_pos)))
583b20b9e14SBram Moolenaar 				|| (LT_POS(VIsual, curwin->w_cursor)
584b20b9e14SBram Moolenaar 				    && (LT_POS(m_pos, VIsual)
585b20b9e14SBram Moolenaar 				      || LT_POS(curwin->w_cursor, m_pos))))
586b20b9e14SBram Moolenaar 			{
587b20b9e14SBram Moolenaar 			    jump_flags = MOUSE_MAY_STOP_VIS;
588b20b9e14SBram Moolenaar 			}
589b20b9e14SBram Moolenaar 			else if (VIsual_mode == Ctrl_V)
590b20b9e14SBram Moolenaar 			{
591b20b9e14SBram Moolenaar 			    getvcols(curwin, &curwin->w_cursor, &VIsual,
592b20b9e14SBram Moolenaar 						     &leftcol, &rightcol);
593b20b9e14SBram Moolenaar 			    getvcol(curwin, &m_pos, NULL, &m_pos.col, NULL);
594b20b9e14SBram Moolenaar 			    if (m_pos.col < leftcol || m_pos.col > rightcol)
595b20b9e14SBram Moolenaar 				jump_flags = MOUSE_MAY_STOP_VIS;
596b20b9e14SBram Moolenaar 			}
597b20b9e14SBram Moolenaar 		    }
598b20b9e14SBram Moolenaar 		}
599b20b9e14SBram Moolenaar 		else
600b20b9e14SBram Moolenaar 		    jump_flags = MOUSE_MAY_STOP_VIS;
601b20b9e14SBram Moolenaar 	    }
602b20b9e14SBram Moolenaar 	    if (jump_flags)
603b20b9e14SBram Moolenaar 	    {
604b20b9e14SBram Moolenaar 		jump_flags = jump_to_mouse(jump_flags, NULL, which_button);
605b20b9e14SBram Moolenaar 		update_curbuf(VIsual_active ? INVERTED : VALID);
606b20b9e14SBram Moolenaar 		setcursor();
607b20b9e14SBram Moolenaar 		out_flush();    // Update before showing popup menu
608b20b9e14SBram Moolenaar 	    }
609b20b9e14SBram Moolenaar # ifdef FEAT_MENU
610b20b9e14SBram Moolenaar 	    show_popupmenu();
611b20b9e14SBram Moolenaar 	    got_click = FALSE;	// ignore release events
612b20b9e14SBram Moolenaar # endif
613b20b9e14SBram Moolenaar 	    return (jump_flags & CURSOR_MOVED) != 0;
614b20b9e14SBram Moolenaar #else
615b20b9e14SBram Moolenaar 	    return FALSE;
616b20b9e14SBram Moolenaar #endif
617b20b9e14SBram Moolenaar 	}
618b20b9e14SBram Moolenaar 	if (which_button == MOUSE_LEFT
619b20b9e14SBram Moolenaar 				&& (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_ALT)))
620b20b9e14SBram Moolenaar 	{
621b20b9e14SBram Moolenaar 	    which_button = MOUSE_RIGHT;
622b20b9e14SBram Moolenaar 	    mod_mask &= ~MOD_MASK_SHIFT;
623b20b9e14SBram Moolenaar 	}
624b20b9e14SBram Moolenaar     }
625b20b9e14SBram Moolenaar 
626b20b9e14SBram Moolenaar     if ((State & (NORMAL | INSERT))
627b20b9e14SBram Moolenaar 			    && !(mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)))
628b20b9e14SBram Moolenaar     {
629b20b9e14SBram Moolenaar 	if (which_button == MOUSE_LEFT)
630b20b9e14SBram Moolenaar 	{
631b20b9e14SBram Moolenaar 	    if (is_click)
632b20b9e14SBram Moolenaar 	    {
633b20b9e14SBram Moolenaar 		// stop Visual mode for a left click in a window, but not when
634b20b9e14SBram Moolenaar 		// on a status line
635b20b9e14SBram Moolenaar 		if (VIsual_active)
636b20b9e14SBram Moolenaar 		    jump_flags |= MOUSE_MAY_STOP_VIS;
637b20b9e14SBram Moolenaar 	    }
638b20b9e14SBram Moolenaar 	    else if (mouse_has(MOUSE_VISUAL))
639b20b9e14SBram Moolenaar 		jump_flags |= MOUSE_MAY_VIS;
640b20b9e14SBram Moolenaar 	}
641b20b9e14SBram Moolenaar 	else if (which_button == MOUSE_RIGHT)
642b20b9e14SBram Moolenaar 	{
643b20b9e14SBram Moolenaar 	    if (is_click && VIsual_active)
644b20b9e14SBram Moolenaar 	    {
645b20b9e14SBram Moolenaar 		// Remember the start and end of visual before moving the
646b20b9e14SBram Moolenaar 		// cursor.
647b20b9e14SBram Moolenaar 		if (LT_POS(curwin->w_cursor, VIsual))
648b20b9e14SBram Moolenaar 		{
649b20b9e14SBram Moolenaar 		    start_visual = curwin->w_cursor;
650b20b9e14SBram Moolenaar 		    end_visual = VIsual;
651b20b9e14SBram Moolenaar 		}
652b20b9e14SBram Moolenaar 		else
653b20b9e14SBram Moolenaar 		{
654b20b9e14SBram Moolenaar 		    start_visual = VIsual;
655b20b9e14SBram Moolenaar 		    end_visual = curwin->w_cursor;
656b20b9e14SBram Moolenaar 		}
657b20b9e14SBram Moolenaar 	    }
658b20b9e14SBram Moolenaar 	    jump_flags |= MOUSE_FOCUS;
659b20b9e14SBram Moolenaar 	    if (mouse_has(MOUSE_VISUAL))
660b20b9e14SBram Moolenaar 		jump_flags |= MOUSE_MAY_VIS;
661b20b9e14SBram Moolenaar 	}
662b20b9e14SBram Moolenaar     }
663b20b9e14SBram Moolenaar 
664b20b9e14SBram Moolenaar     // If an operator is pending, ignore all drags and releases until the
665b20b9e14SBram Moolenaar     // next mouse click.
666b20b9e14SBram Moolenaar     if (!is_drag && oap != NULL && oap->op_type != OP_NOP)
667b20b9e14SBram Moolenaar     {
668b20b9e14SBram Moolenaar 	got_click = FALSE;
669b20b9e14SBram Moolenaar 	oap->motion_type = MCHAR;
670b20b9e14SBram Moolenaar     }
671b20b9e14SBram Moolenaar 
672b20b9e14SBram Moolenaar     // When releasing the button let jump_to_mouse() know.
673b20b9e14SBram Moolenaar     if (!is_click && !is_drag)
674b20b9e14SBram Moolenaar 	jump_flags |= MOUSE_RELEASED;
675b20b9e14SBram Moolenaar 
676b20b9e14SBram Moolenaar     // JUMP!
677b20b9e14SBram Moolenaar     jump_flags = jump_to_mouse(jump_flags,
678b20b9e14SBram Moolenaar 			oap == NULL ? NULL : &(oap->inclusive), which_button);
679b20b9e14SBram Moolenaar 
680b20b9e14SBram Moolenaar #ifdef FEAT_MENU
681b20b9e14SBram Moolenaar     // A click in the window toolbar has no side effects.
682b20b9e14SBram Moolenaar     if (jump_flags & MOUSE_WINBAR)
683b20b9e14SBram Moolenaar 	return FALSE;
684b20b9e14SBram Moolenaar #endif
685b20b9e14SBram Moolenaar     moved = (jump_flags & CURSOR_MOVED);
686b20b9e14SBram Moolenaar     in_status_line = (jump_flags & IN_STATUS_LINE);
687b20b9e14SBram Moolenaar     in_sep_line = (jump_flags & IN_SEP_LINE);
688b20b9e14SBram Moolenaar 
689b20b9e14SBram Moolenaar #ifdef FEAT_NETBEANS_INTG
690b20b9e14SBram Moolenaar     if (isNetbeansBuffer(curbuf)
691b20b9e14SBram Moolenaar 			    && !(jump_flags & (IN_STATUS_LINE | IN_SEP_LINE)))
692b20b9e14SBram Moolenaar     {
693b20b9e14SBram Moolenaar 	int key = KEY2TERMCAP1(c);
694b20b9e14SBram Moolenaar 
695b20b9e14SBram Moolenaar 	if (key == (int)KE_LEFTRELEASE || key == (int)KE_MIDDLERELEASE
696b20b9e14SBram Moolenaar 					       || key == (int)KE_RIGHTRELEASE)
697b20b9e14SBram Moolenaar 	    netbeans_button_release(which_button);
698b20b9e14SBram Moolenaar     }
699b20b9e14SBram Moolenaar #endif
700b20b9e14SBram Moolenaar 
701b20b9e14SBram Moolenaar     // When jumping to another window, clear a pending operator.  That's a bit
702b20b9e14SBram Moolenaar     // friendlier than beeping and not jumping to that window.
703b20b9e14SBram Moolenaar     if (curwin != old_curwin && oap != NULL && oap->op_type != OP_NOP)
704b20b9e14SBram Moolenaar 	clearop(oap);
705b20b9e14SBram Moolenaar 
706b20b9e14SBram Moolenaar #ifdef FEAT_FOLDING
707b20b9e14SBram Moolenaar     if (mod_mask == 0
708b20b9e14SBram Moolenaar 	    && !is_drag
709b20b9e14SBram Moolenaar 	    && (jump_flags & (MOUSE_FOLD_CLOSE | MOUSE_FOLD_OPEN))
710b20b9e14SBram Moolenaar 	    && which_button == MOUSE_LEFT)
711b20b9e14SBram Moolenaar     {
712b20b9e14SBram Moolenaar 	// open or close a fold at this line
713b20b9e14SBram Moolenaar 	if (jump_flags & MOUSE_FOLD_OPEN)
714b20b9e14SBram Moolenaar 	    openFold(curwin->w_cursor.lnum, 1L);
715b20b9e14SBram Moolenaar 	else
716b20b9e14SBram Moolenaar 	    closeFold(curwin->w_cursor.lnum, 1L);
717b20b9e14SBram Moolenaar 	// don't move the cursor if still in the same window
718b20b9e14SBram Moolenaar 	if (curwin == old_curwin)
719b20b9e14SBram Moolenaar 	    curwin->w_cursor = save_cursor;
720b20b9e14SBram Moolenaar     }
721b20b9e14SBram Moolenaar #endif
722b20b9e14SBram Moolenaar 
723b20b9e14SBram Moolenaar #if defined(FEAT_CLIPBOARD) && defined(FEAT_CMDWIN)
724b20b9e14SBram Moolenaar     if ((jump_flags & IN_OTHER_WIN) && !VIsual_active && clip_star.available)
725b20b9e14SBram Moolenaar     {
726b20b9e14SBram Moolenaar 	clip_modeless(which_button, is_click, is_drag);
727b20b9e14SBram Moolenaar 	return FALSE;
728b20b9e14SBram Moolenaar     }
729b20b9e14SBram Moolenaar #endif
730b20b9e14SBram Moolenaar 
731b20b9e14SBram Moolenaar     // Set global flag that we are extending the Visual area with mouse
732b20b9e14SBram Moolenaar     // dragging; temporarily minimize 'scrolloff'.
733b20b9e14SBram Moolenaar     if (VIsual_active && is_drag && get_scrolloff_value())
734b20b9e14SBram Moolenaar     {
735b20b9e14SBram Moolenaar 	// In the very first line, allow scrolling one line
736b20b9e14SBram Moolenaar 	if (mouse_row == 0)
737b20b9e14SBram Moolenaar 	    mouse_dragging = 2;
738b20b9e14SBram Moolenaar 	else
739b20b9e14SBram Moolenaar 	    mouse_dragging = 1;
740b20b9e14SBram Moolenaar     }
741b20b9e14SBram Moolenaar 
742b20b9e14SBram Moolenaar     // When dragging the mouse above the window, scroll down.
743b20b9e14SBram Moolenaar     if (is_drag && mouse_row < 0 && !in_status_line)
744b20b9e14SBram Moolenaar     {
745b20b9e14SBram Moolenaar 	scroll_redraw(FALSE, 1L);
746b20b9e14SBram Moolenaar 	mouse_row = 0;
747b20b9e14SBram Moolenaar     }
748b20b9e14SBram Moolenaar 
749b20b9e14SBram Moolenaar     if (start_visual.lnum)		// right click in visual mode
750b20b9e14SBram Moolenaar     {
751b20b9e14SBram Moolenaar        // When ALT is pressed make Visual mode blockwise.
752b20b9e14SBram Moolenaar        if (mod_mask & MOD_MASK_ALT)
753b20b9e14SBram Moolenaar 	   VIsual_mode = Ctrl_V;
754b20b9e14SBram Moolenaar 
755b20b9e14SBram Moolenaar 	// In Visual-block mode, divide the area in four, pick up the corner
756b20b9e14SBram Moolenaar 	// that is in the quarter that the cursor is in.
757b20b9e14SBram Moolenaar 	if (VIsual_mode == Ctrl_V)
758b20b9e14SBram Moolenaar 	{
759b20b9e14SBram Moolenaar 	    getvcols(curwin, &start_visual, &end_visual, &leftcol, &rightcol);
760b20b9e14SBram Moolenaar 	    if (curwin->w_curswant > (leftcol + rightcol) / 2)
761b20b9e14SBram Moolenaar 		end_visual.col = leftcol;
762b20b9e14SBram Moolenaar 	    else
763b20b9e14SBram Moolenaar 		end_visual.col = rightcol;
764b20b9e14SBram Moolenaar 	    if (curwin->w_cursor.lnum >=
765b20b9e14SBram Moolenaar 				    (start_visual.lnum + end_visual.lnum) / 2)
766b20b9e14SBram Moolenaar 		end_visual.lnum = start_visual.lnum;
767b20b9e14SBram Moolenaar 
768b20b9e14SBram Moolenaar 	    // move VIsual to the right column
769b20b9e14SBram Moolenaar 	    start_visual = curwin->w_cursor;	    // save the cursor pos
770b20b9e14SBram Moolenaar 	    curwin->w_cursor = end_visual;
771b20b9e14SBram Moolenaar 	    coladvance(end_visual.col);
772b20b9e14SBram Moolenaar 	    VIsual = curwin->w_cursor;
773b20b9e14SBram Moolenaar 	    curwin->w_cursor = start_visual;	    // restore the cursor
774b20b9e14SBram Moolenaar 	}
775b20b9e14SBram Moolenaar 	else
776b20b9e14SBram Moolenaar 	{
777b20b9e14SBram Moolenaar 	    // If the click is before the start of visual, change the start.
778b20b9e14SBram Moolenaar 	    // If the click is after the end of visual, change the end.  If
779b20b9e14SBram Moolenaar 	    // the click is inside the visual, change the closest side.
780b20b9e14SBram Moolenaar 	    if (LT_POS(curwin->w_cursor, start_visual))
781b20b9e14SBram Moolenaar 		VIsual = end_visual;
782b20b9e14SBram Moolenaar 	    else if (LT_POS(end_visual, curwin->w_cursor))
783b20b9e14SBram Moolenaar 		VIsual = start_visual;
784b20b9e14SBram Moolenaar 	    else
785b20b9e14SBram Moolenaar 	    {
786b20b9e14SBram Moolenaar 		// In the same line, compare column number
787b20b9e14SBram Moolenaar 		if (end_visual.lnum == start_visual.lnum)
788b20b9e14SBram Moolenaar 		{
789b20b9e14SBram Moolenaar 		    if (curwin->w_cursor.col - start_visual.col >
790b20b9e14SBram Moolenaar 				    end_visual.col - curwin->w_cursor.col)
791b20b9e14SBram Moolenaar 			VIsual = start_visual;
792b20b9e14SBram Moolenaar 		    else
793b20b9e14SBram Moolenaar 			VIsual = end_visual;
794b20b9e14SBram Moolenaar 		}
795b20b9e14SBram Moolenaar 
796b20b9e14SBram Moolenaar 		// In different lines, compare line number
797b20b9e14SBram Moolenaar 		else
798b20b9e14SBram Moolenaar 		{
799b20b9e14SBram Moolenaar 		    diff = (curwin->w_cursor.lnum - start_visual.lnum) -
800b20b9e14SBram Moolenaar 				(end_visual.lnum - curwin->w_cursor.lnum);
801b20b9e14SBram Moolenaar 
802b20b9e14SBram Moolenaar 		    if (diff > 0)		// closest to end
803b20b9e14SBram Moolenaar 			VIsual = start_visual;
804b20b9e14SBram Moolenaar 		    else if (diff < 0)	// closest to start
805b20b9e14SBram Moolenaar 			VIsual = end_visual;
806b20b9e14SBram Moolenaar 		    else			// in the middle line
807b20b9e14SBram Moolenaar 		    {
808b20b9e14SBram Moolenaar 			if (curwin->w_cursor.col <
809b20b9e14SBram Moolenaar 					(start_visual.col + end_visual.col) / 2)
810b20b9e14SBram Moolenaar 			    VIsual = end_visual;
811b20b9e14SBram Moolenaar 			else
812b20b9e14SBram Moolenaar 			    VIsual = start_visual;
813b20b9e14SBram Moolenaar 		    }
814b20b9e14SBram Moolenaar 		}
815b20b9e14SBram Moolenaar 	    }
816b20b9e14SBram Moolenaar 	}
817b20b9e14SBram Moolenaar     }
818b20b9e14SBram Moolenaar     // If Visual mode started in insert mode, execute "CTRL-O"
819b20b9e14SBram Moolenaar     else if ((State & INSERT) && VIsual_active)
820b20b9e14SBram Moolenaar 	stuffcharReadbuff(Ctrl_O);
821b20b9e14SBram Moolenaar 
822b20b9e14SBram Moolenaar     // Middle mouse click: Put text before cursor.
823b20b9e14SBram Moolenaar     if (which_button == MOUSE_MIDDLE)
824b20b9e14SBram Moolenaar     {
825b20b9e14SBram Moolenaar #ifdef FEAT_CLIPBOARD
826b20b9e14SBram Moolenaar 	if (clip_star.available && regname == 0)
827b20b9e14SBram Moolenaar 	    regname = '*';
828b20b9e14SBram Moolenaar #endif
829b20b9e14SBram Moolenaar 	if (yank_register_mline(regname))
830b20b9e14SBram Moolenaar 	{
831b20b9e14SBram Moolenaar 	    if (mouse_past_bottom)
832b20b9e14SBram Moolenaar 		dir = FORWARD;
833b20b9e14SBram Moolenaar 	}
834b20b9e14SBram Moolenaar 	else if (mouse_past_eol)
835b20b9e14SBram Moolenaar 	    dir = FORWARD;
836b20b9e14SBram Moolenaar 
837b20b9e14SBram Moolenaar 	if (fixindent)
838b20b9e14SBram Moolenaar 	{
839b20b9e14SBram Moolenaar 	    c1 = (dir == BACKWARD) ? '[' : ']';
840b20b9e14SBram Moolenaar 	    c2 = 'p';
841b20b9e14SBram Moolenaar 	}
842b20b9e14SBram Moolenaar 	else
843b20b9e14SBram Moolenaar 	{
844b20b9e14SBram Moolenaar 	    c1 = (dir == FORWARD) ? 'p' : 'P';
845b20b9e14SBram Moolenaar 	    c2 = NUL;
846b20b9e14SBram Moolenaar 	}
847b20b9e14SBram Moolenaar 	prep_redo(regname, count, NUL, c1, NUL, c2, NUL);
848b20b9e14SBram Moolenaar 
849b20b9e14SBram Moolenaar 	// Remember where the paste started, so in edit() Insstart can be set
850b20b9e14SBram Moolenaar 	// to this position
851b20b9e14SBram Moolenaar 	if (restart_edit != 0)
852b20b9e14SBram Moolenaar 	    where_paste_started = curwin->w_cursor;
853c3516f7eSBram Moolenaar 	do_put(regname, NULL, dir, count, fixindent | PUT_CURSEND);
854b20b9e14SBram Moolenaar     }
855b20b9e14SBram Moolenaar 
856b20b9e14SBram Moolenaar #if defined(FEAT_QUICKFIX)
857b20b9e14SBram Moolenaar     // Ctrl-Mouse click or double click in a quickfix window jumps to the
858b20b9e14SBram Moolenaar     // error under the mouse pointer.
859b20b9e14SBram Moolenaar     else if (((mod_mask & MOD_MASK_CTRL)
860b20b9e14SBram Moolenaar 		|| (mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK)
861b20b9e14SBram Moolenaar 	    && bt_quickfix(curbuf))
862b20b9e14SBram Moolenaar     {
863b20b9e14SBram Moolenaar 	if (curwin->w_llist_ref == NULL)	// quickfix window
864b20b9e14SBram Moolenaar 	    do_cmdline_cmd((char_u *)".cc");
865b20b9e14SBram Moolenaar 	else					// location list window
866b20b9e14SBram Moolenaar 	    do_cmdline_cmd((char_u *)".ll");
867b20b9e14SBram Moolenaar 	got_click = FALSE;		// ignore drag&release now
868b20b9e14SBram Moolenaar     }
869b20b9e14SBram Moolenaar #endif
870b20b9e14SBram Moolenaar 
871b20b9e14SBram Moolenaar     // Ctrl-Mouse click (or double click in a help window) jumps to the tag
872b20b9e14SBram Moolenaar     // under the mouse pointer.
873b20b9e14SBram Moolenaar     else if ((mod_mask & MOD_MASK_CTRL) || (curbuf->b_help
874b20b9e14SBram Moolenaar 		     && (mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK))
875b20b9e14SBram Moolenaar     {
876b20b9e14SBram Moolenaar 	if (State & INSERT)
877b20b9e14SBram Moolenaar 	    stuffcharReadbuff(Ctrl_O);
878b20b9e14SBram Moolenaar 	stuffcharReadbuff(Ctrl_RSB);
879b20b9e14SBram Moolenaar 	got_click = FALSE;		// ignore drag&release now
880b20b9e14SBram Moolenaar     }
881b20b9e14SBram Moolenaar 
882b20b9e14SBram Moolenaar     // Shift-Mouse click searches for the next occurrence of the word under
883b20b9e14SBram Moolenaar     // the mouse pointer
884b20b9e14SBram Moolenaar     else if ((mod_mask & MOD_MASK_SHIFT))
885b20b9e14SBram Moolenaar     {
886b20b9e14SBram Moolenaar 	if ((State & INSERT) || (VIsual_active && VIsual_select))
887b20b9e14SBram Moolenaar 	    stuffcharReadbuff(Ctrl_O);
888b20b9e14SBram Moolenaar 	if (which_button == MOUSE_LEFT)
889b20b9e14SBram Moolenaar 	    stuffcharReadbuff('*');
890b20b9e14SBram Moolenaar 	else	// MOUSE_RIGHT
891b20b9e14SBram Moolenaar 	    stuffcharReadbuff('#');
892b20b9e14SBram Moolenaar     }
893b20b9e14SBram Moolenaar 
894b20b9e14SBram Moolenaar     // Handle double clicks, unless on status line
895b20b9e14SBram Moolenaar     else if (in_status_line)
896b20b9e14SBram Moolenaar     {
897b20b9e14SBram Moolenaar #ifdef FEAT_MOUSESHAPE
898b20b9e14SBram Moolenaar 	if ((is_drag || is_click) && !drag_status_line)
899b20b9e14SBram Moolenaar 	{
900b20b9e14SBram Moolenaar 	    drag_status_line = TRUE;
901b20b9e14SBram Moolenaar 	    update_mouseshape(-1);
902b20b9e14SBram Moolenaar 	}
903b20b9e14SBram Moolenaar #endif
904b20b9e14SBram Moolenaar     }
905b20b9e14SBram Moolenaar     else if (in_sep_line)
906b20b9e14SBram Moolenaar     {
907b20b9e14SBram Moolenaar #ifdef FEAT_MOUSESHAPE
908b20b9e14SBram Moolenaar 	if ((is_drag || is_click) && !drag_sep_line)
909b20b9e14SBram Moolenaar 	{
910b20b9e14SBram Moolenaar 	    drag_sep_line = TRUE;
911b20b9e14SBram Moolenaar 	    update_mouseshape(-1);
912b20b9e14SBram Moolenaar 	}
913b20b9e14SBram Moolenaar #endif
914b20b9e14SBram Moolenaar     }
915b20b9e14SBram Moolenaar     else if ((mod_mask & MOD_MASK_MULTI_CLICK) && (State & (NORMAL | INSERT))
916b20b9e14SBram Moolenaar 	     && mouse_has(MOUSE_VISUAL))
917b20b9e14SBram Moolenaar     {
918b20b9e14SBram Moolenaar 	if (is_click || !VIsual_active)
919b20b9e14SBram Moolenaar 	{
920b20b9e14SBram Moolenaar 	    if (VIsual_active)
921b20b9e14SBram Moolenaar 		orig_cursor = VIsual;
922b20b9e14SBram Moolenaar 	    else
923b20b9e14SBram Moolenaar 	    {
924b20b9e14SBram Moolenaar 		check_visual_highlight();
925b20b9e14SBram Moolenaar 		VIsual = curwin->w_cursor;
926b20b9e14SBram Moolenaar 		orig_cursor = VIsual;
927b20b9e14SBram Moolenaar 		VIsual_active = TRUE;
928b20b9e14SBram Moolenaar 		VIsual_reselect = TRUE;
929b20b9e14SBram Moolenaar 		// start Select mode if 'selectmode' contains "mouse"
930b20b9e14SBram Moolenaar 		may_start_select('o');
931b20b9e14SBram Moolenaar 		setmouse();
932b20b9e14SBram Moolenaar 	    }
933b20b9e14SBram Moolenaar 	    if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK)
934b20b9e14SBram Moolenaar 	    {
935b20b9e14SBram Moolenaar 		// Double click with ALT pressed makes it blockwise.
936b20b9e14SBram Moolenaar 		if (mod_mask & MOD_MASK_ALT)
937b20b9e14SBram Moolenaar 		    VIsual_mode = Ctrl_V;
938b20b9e14SBram Moolenaar 		else
939b20b9e14SBram Moolenaar 		    VIsual_mode = 'v';
940b20b9e14SBram Moolenaar 	    }
941b20b9e14SBram Moolenaar 	    else if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_3CLICK)
942b20b9e14SBram Moolenaar 		VIsual_mode = 'V';
943b20b9e14SBram Moolenaar 	    else if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_4CLICK)
944b20b9e14SBram Moolenaar 		VIsual_mode = Ctrl_V;
945b20b9e14SBram Moolenaar #ifdef FEAT_CLIPBOARD
946b20b9e14SBram Moolenaar 	    // Make sure the clipboard gets updated.  Needed because start and
947b20b9e14SBram Moolenaar 	    // end may still be the same, and the selection needs to be owned
948b20b9e14SBram Moolenaar 	    clip_star.vmode = NUL;
949b20b9e14SBram Moolenaar #endif
950b20b9e14SBram Moolenaar 	}
951b20b9e14SBram Moolenaar 	// A double click selects a word or a block.
952b20b9e14SBram Moolenaar 	if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK)
953b20b9e14SBram Moolenaar 	{
954b20b9e14SBram Moolenaar 	    pos_T	*pos = NULL;
955b20b9e14SBram Moolenaar 	    int		gc;
956b20b9e14SBram Moolenaar 
957b20b9e14SBram Moolenaar 	    if (is_click)
958b20b9e14SBram Moolenaar 	    {
959b20b9e14SBram Moolenaar 		// If the character under the cursor (skipping white space) is
960b20b9e14SBram Moolenaar 		// not a word character, try finding a match and select a (),
961b20b9e14SBram Moolenaar 		// {}, [], #if/#endif, etc. block.
962b20b9e14SBram Moolenaar 		end_visual = curwin->w_cursor;
963b20b9e14SBram Moolenaar 		while (gc = gchar_pos(&end_visual), VIM_ISWHITE(gc))
964b20b9e14SBram Moolenaar 		    inc(&end_visual);
965b20b9e14SBram Moolenaar 		if (oap != NULL)
966b20b9e14SBram Moolenaar 		    oap->motion_type = MCHAR;
967b20b9e14SBram Moolenaar 		if (oap != NULL
968b20b9e14SBram Moolenaar 			&& VIsual_mode == 'v'
969b20b9e14SBram Moolenaar 			&& !vim_iswordc(gchar_pos(&end_visual))
970b20b9e14SBram Moolenaar 			&& EQUAL_POS(curwin->w_cursor, VIsual)
971b20b9e14SBram Moolenaar 			&& (pos = findmatch(oap, NUL)) != NULL)
972b20b9e14SBram Moolenaar 		{
973b20b9e14SBram Moolenaar 		    curwin->w_cursor = *pos;
974b20b9e14SBram Moolenaar 		    if (oap->motion_type == MLINE)
975b20b9e14SBram Moolenaar 			VIsual_mode = 'V';
976b20b9e14SBram Moolenaar 		    else if (*p_sel == 'e')
977b20b9e14SBram Moolenaar 		    {
978b20b9e14SBram Moolenaar 			if (LT_POS(curwin->w_cursor, VIsual))
979b20b9e14SBram Moolenaar 			    ++VIsual.col;
980b20b9e14SBram Moolenaar 			else
981b20b9e14SBram Moolenaar 			    ++curwin->w_cursor.col;
982b20b9e14SBram Moolenaar 		    }
983b20b9e14SBram Moolenaar 		}
984b20b9e14SBram Moolenaar 	    }
985b20b9e14SBram Moolenaar 
986b20b9e14SBram Moolenaar 	    if (pos == NULL && (is_click || is_drag))
987b20b9e14SBram Moolenaar 	    {
988b20b9e14SBram Moolenaar 		// When not found a match or when dragging: extend to include
989b20b9e14SBram Moolenaar 		// a word.
990b20b9e14SBram Moolenaar 		if (LT_POS(curwin->w_cursor, orig_cursor))
991b20b9e14SBram Moolenaar 		{
992b20b9e14SBram Moolenaar 		    find_start_of_word(&curwin->w_cursor);
993b20b9e14SBram Moolenaar 		    find_end_of_word(&VIsual);
994b20b9e14SBram Moolenaar 		}
995b20b9e14SBram Moolenaar 		else
996b20b9e14SBram Moolenaar 		{
997b20b9e14SBram Moolenaar 		    find_start_of_word(&VIsual);
998b20b9e14SBram Moolenaar 		    if (*p_sel == 'e' && *ml_get_cursor() != NUL)
999b20b9e14SBram Moolenaar 			curwin->w_cursor.col +=
1000b20b9e14SBram Moolenaar 					 (*mb_ptr2len)(ml_get_cursor());
1001b20b9e14SBram Moolenaar 		    find_end_of_word(&curwin->w_cursor);
1002b20b9e14SBram Moolenaar 		}
1003b20b9e14SBram Moolenaar 	    }
1004b20b9e14SBram Moolenaar 	    curwin->w_set_curswant = TRUE;
1005b20b9e14SBram Moolenaar 	}
1006b20b9e14SBram Moolenaar 	if (is_click)
1007b20b9e14SBram Moolenaar 	    redraw_curbuf_later(INVERTED);	// update the inversion
1008b20b9e14SBram Moolenaar     }
1009b20b9e14SBram Moolenaar     else if (VIsual_active && !old_active)
1010b20b9e14SBram Moolenaar     {
1011b20b9e14SBram Moolenaar 	if (mod_mask & MOD_MASK_ALT)
1012b20b9e14SBram Moolenaar 	    VIsual_mode = Ctrl_V;
1013b20b9e14SBram Moolenaar 	else
1014b20b9e14SBram Moolenaar 	    VIsual_mode = 'v';
1015b20b9e14SBram Moolenaar     }
1016b20b9e14SBram Moolenaar 
1017b20b9e14SBram Moolenaar     // If Visual mode changed show it later.
1018b20b9e14SBram Moolenaar     if ((!VIsual_active && old_active && mode_displayed)
1019b20b9e14SBram Moolenaar 	    || (VIsual_active && p_smd && msg_silent == 0
1020b20b9e14SBram Moolenaar 				 && (!old_active || VIsual_mode != old_mode)))
1021b20b9e14SBram Moolenaar 	redraw_cmdline = TRUE;
1022b20b9e14SBram Moolenaar 
1023b20b9e14SBram Moolenaar     return moved;
1024b20b9e14SBram Moolenaar }
1025b20b9e14SBram Moolenaar 
1026b20b9e14SBram Moolenaar     void
ins_mouse(int c)1027b20b9e14SBram Moolenaar ins_mouse(int c)
1028b20b9e14SBram Moolenaar {
1029b20b9e14SBram Moolenaar     pos_T	tpos;
1030b20b9e14SBram Moolenaar     win_T	*old_curwin = curwin;
1031b20b9e14SBram Moolenaar 
1032b20b9e14SBram Moolenaar # ifdef FEAT_GUI
1033b20b9e14SBram Moolenaar     // When GUI is active, also move/paste when 'mouse' is empty
1034b20b9e14SBram Moolenaar     if (!gui.in_use)
1035b20b9e14SBram Moolenaar # endif
1036b20b9e14SBram Moolenaar 	if (!mouse_has(MOUSE_INSERT))
1037b20b9e14SBram Moolenaar 	    return;
1038b20b9e14SBram Moolenaar 
1039b20b9e14SBram Moolenaar     undisplay_dollar();
1040b20b9e14SBram Moolenaar     tpos = curwin->w_cursor;
1041b20b9e14SBram Moolenaar     if (do_mouse(NULL, c, BACKWARD, 1L, 0))
1042b20b9e14SBram Moolenaar     {
1043b20b9e14SBram Moolenaar 	win_T	*new_curwin = curwin;
1044b20b9e14SBram Moolenaar 
1045b20b9e14SBram Moolenaar 	if (curwin != old_curwin && win_valid(old_curwin))
1046b20b9e14SBram Moolenaar 	{
1047b20b9e14SBram Moolenaar 	    // Mouse took us to another window.  We need to go back to the
1048b20b9e14SBram Moolenaar 	    // previous one to stop insert there properly.
1049b20b9e14SBram Moolenaar 	    curwin = old_curwin;
1050b20b9e14SBram Moolenaar 	    curbuf = curwin->w_buffer;
1051b20b9e14SBram Moolenaar #ifdef FEAT_JOB_CHANNEL
1052b20b9e14SBram Moolenaar 	    if (bt_prompt(curbuf))
1053b20b9e14SBram Moolenaar 		// Restart Insert mode when re-entering the prompt buffer.
1054b20b9e14SBram Moolenaar 		curbuf->b_prompt_insert = 'A';
1055b20b9e14SBram Moolenaar #endif
1056b20b9e14SBram Moolenaar 	}
1057b20b9e14SBram Moolenaar 	start_arrow(curwin == old_curwin ? &tpos : NULL);
1058b20b9e14SBram Moolenaar 	if (curwin != new_curwin && win_valid(new_curwin))
1059b20b9e14SBram Moolenaar 	{
1060b20b9e14SBram Moolenaar 	    curwin = new_curwin;
1061b20b9e14SBram Moolenaar 	    curbuf = curwin->w_buffer;
1062b20b9e14SBram Moolenaar 	}
1063b20b9e14SBram Moolenaar # ifdef FEAT_CINDENT
1064b20b9e14SBram Moolenaar 	set_can_cindent(TRUE);
1065b20b9e14SBram Moolenaar # endif
1066b20b9e14SBram Moolenaar     }
1067b20b9e14SBram Moolenaar 
1068b20b9e14SBram Moolenaar     // redraw status lines (in case another window became active)
1069b20b9e14SBram Moolenaar     redraw_statuslines();
1070b20b9e14SBram Moolenaar }
1071b20b9e14SBram Moolenaar 
1072b20b9e14SBram Moolenaar     void
ins_mousescroll(int dir)1073b20b9e14SBram Moolenaar ins_mousescroll(int dir)
1074b20b9e14SBram Moolenaar {
1075b20b9e14SBram Moolenaar     pos_T	tpos;
1076b20b9e14SBram Moolenaar     win_T	*old_curwin = curwin, *wp;
1077b20b9e14SBram Moolenaar     int		did_scroll = FALSE;
1078b20b9e14SBram Moolenaar 
1079b20b9e14SBram Moolenaar     tpos = curwin->w_cursor;
1080b20b9e14SBram Moolenaar 
1081b20b9e14SBram Moolenaar     if (mouse_row >= 0 && mouse_col >= 0)
1082b20b9e14SBram Moolenaar     {
1083b20b9e14SBram Moolenaar 	int row, col;
1084b20b9e14SBram Moolenaar 
1085b20b9e14SBram Moolenaar 	row = mouse_row;
1086b20b9e14SBram Moolenaar 	col = mouse_col;
1087b20b9e14SBram Moolenaar 
1088b20b9e14SBram Moolenaar 	// find the window at the pointer coordinates
1089b20b9e14SBram Moolenaar 	wp = mouse_find_win(&row, &col, FIND_POPUP);
1090b20b9e14SBram Moolenaar 	if (wp == NULL)
1091b20b9e14SBram Moolenaar 	    return;
1092b20b9e14SBram Moolenaar 	curwin = wp;
1093b20b9e14SBram Moolenaar 	curbuf = curwin->w_buffer;
1094b20b9e14SBram Moolenaar     }
1095b20b9e14SBram Moolenaar     if (curwin == old_curwin)
1096b20b9e14SBram Moolenaar 	undisplay_dollar();
1097b20b9e14SBram Moolenaar 
1098b20b9e14SBram Moolenaar     // Don't scroll the window in which completion is being done.
1099b20b9e14SBram Moolenaar     if (!pum_visible() || curwin != old_curwin)
1100b20b9e14SBram Moolenaar     {
1101b20b9e14SBram Moolenaar 	if (dir == MSCR_DOWN || dir == MSCR_UP)
1102b20b9e14SBram Moolenaar 	{
1103b20b9e14SBram Moolenaar 	    if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))
1104b20b9e14SBram Moolenaar 		scroll_redraw(dir,
1105b20b9e14SBram Moolenaar 			(long)(curwin->w_botline - curwin->w_topline));
1106b20b9e14SBram Moolenaar 	    else
1107b20b9e14SBram Moolenaar 		scroll_redraw(dir, 3L);
110805ad5ff0SBram Moolenaar # ifdef FEAT_PROP_POPUP
1109b20b9e14SBram Moolenaar 	if (WIN_IS_POPUP(curwin))
1110b20b9e14SBram Moolenaar 	    popup_set_firstline(curwin);
1111b20b9e14SBram Moolenaar # endif
1112b20b9e14SBram Moolenaar 	}
1113b20b9e14SBram Moolenaar #ifdef FEAT_GUI
1114b20b9e14SBram Moolenaar 	else
1115b20b9e14SBram Moolenaar 	{
1116b20b9e14SBram Moolenaar 	    int val, step = 6;
1117b20b9e14SBram Moolenaar 
1118b20b9e14SBram Moolenaar 	    if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))
1119b20b9e14SBram Moolenaar 		step = curwin->w_width;
1120b20b9e14SBram Moolenaar 	    val = curwin->w_leftcol + (dir == MSCR_RIGHT ? -step : step);
1121b20b9e14SBram Moolenaar 	    if (val < 0)
1122b20b9e14SBram Moolenaar 		val = 0;
1123b20b9e14SBram Moolenaar 	    gui_do_horiz_scroll(val, TRUE);
1124b20b9e14SBram Moolenaar 	}
1125b20b9e14SBram Moolenaar #endif
1126b20b9e14SBram Moolenaar 	did_scroll = TRUE;
1127b20b9e14SBram Moolenaar     }
1128b20b9e14SBram Moolenaar 
1129b20b9e14SBram Moolenaar     curwin->w_redr_status = TRUE;
1130b20b9e14SBram Moolenaar 
1131b20b9e14SBram Moolenaar     curwin = old_curwin;
1132b20b9e14SBram Moolenaar     curbuf = curwin->w_buffer;
1133b20b9e14SBram Moolenaar 
1134b20b9e14SBram Moolenaar     // The popup menu may overlay the window, need to redraw it.
1135b20b9e14SBram Moolenaar     // TODO: Would be more efficient to only redraw the windows that are
1136b20b9e14SBram Moolenaar     // overlapped by the popup menu.
1137b20b9e14SBram Moolenaar     if (pum_visible() && did_scroll)
1138b20b9e14SBram Moolenaar     {
1139b20b9e14SBram Moolenaar 	redraw_all_later(NOT_VALID);
1140b20b9e14SBram Moolenaar 	ins_compl_show_pum();
1141b20b9e14SBram Moolenaar     }
1142b20b9e14SBram Moolenaar 
1143b20b9e14SBram Moolenaar     if (!EQUAL_POS(curwin->w_cursor, tpos))
1144b20b9e14SBram Moolenaar     {
1145b20b9e14SBram Moolenaar 	start_arrow(&tpos);
1146b20b9e14SBram Moolenaar # ifdef FEAT_CINDENT
1147b20b9e14SBram Moolenaar 	set_can_cindent(TRUE);
1148b20b9e14SBram Moolenaar # endif
1149b20b9e14SBram Moolenaar     }
1150b20b9e14SBram Moolenaar }
1151b20b9e14SBram Moolenaar 
1152b20b9e14SBram Moolenaar /*
1153b20b9e14SBram Moolenaar  * Return TRUE if "c" is a mouse key.
1154b20b9e14SBram Moolenaar  */
1155b20b9e14SBram Moolenaar     int
is_mouse_key(int c)1156b20b9e14SBram Moolenaar is_mouse_key(int c)
1157b20b9e14SBram Moolenaar {
1158b20b9e14SBram Moolenaar     return c == K_LEFTMOUSE
1159b20b9e14SBram Moolenaar 	|| c == K_LEFTMOUSE_NM
1160b20b9e14SBram Moolenaar 	|| c == K_LEFTDRAG
1161b20b9e14SBram Moolenaar 	|| c == K_LEFTRELEASE
1162b20b9e14SBram Moolenaar 	|| c == K_LEFTRELEASE_NM
1163b20b9e14SBram Moolenaar 	|| c == K_MOUSEMOVE
1164b20b9e14SBram Moolenaar 	|| c == K_MIDDLEMOUSE
1165b20b9e14SBram Moolenaar 	|| c == K_MIDDLEDRAG
1166b20b9e14SBram Moolenaar 	|| c == K_MIDDLERELEASE
1167b20b9e14SBram Moolenaar 	|| c == K_RIGHTMOUSE
1168b20b9e14SBram Moolenaar 	|| c == K_RIGHTDRAG
1169b20b9e14SBram Moolenaar 	|| c == K_RIGHTRELEASE
1170b20b9e14SBram Moolenaar 	|| c == K_MOUSEDOWN
1171b20b9e14SBram Moolenaar 	|| c == K_MOUSEUP
1172b20b9e14SBram Moolenaar 	|| c == K_MOUSELEFT
1173b20b9e14SBram Moolenaar 	|| c == K_MOUSERIGHT
1174b20b9e14SBram Moolenaar 	|| c == K_X1MOUSE
1175b20b9e14SBram Moolenaar 	|| c == K_X1DRAG
1176b20b9e14SBram Moolenaar 	|| c == K_X1RELEASE
1177b20b9e14SBram Moolenaar 	|| c == K_X2MOUSE
1178b20b9e14SBram Moolenaar 	|| c == K_X2DRAG
1179b20b9e14SBram Moolenaar 	|| c == K_X2RELEASE;
1180b20b9e14SBram Moolenaar }
1181b20b9e14SBram Moolenaar 
1182b20b9e14SBram Moolenaar static struct mousetable
1183b20b9e14SBram Moolenaar {
1184b20b9e14SBram Moolenaar     int	    pseudo_code;	// Code for pseudo mouse event
1185b20b9e14SBram Moolenaar     int	    button;		// Which mouse button is it?
1186b20b9e14SBram Moolenaar     int	    is_click;		// Is it a mouse button click event?
1187b20b9e14SBram Moolenaar     int	    is_drag;		// Is it a mouse drag event?
1188b20b9e14SBram Moolenaar } mouse_table[] =
1189b20b9e14SBram Moolenaar {
1190b20b9e14SBram Moolenaar     {(int)KE_LEFTMOUSE,		MOUSE_LEFT,	TRUE,	FALSE},
1191b20b9e14SBram Moolenaar #ifdef FEAT_GUI
1192b20b9e14SBram Moolenaar     {(int)KE_LEFTMOUSE_NM,	MOUSE_LEFT,	TRUE,	FALSE},
1193b20b9e14SBram Moolenaar #endif
1194b20b9e14SBram Moolenaar     {(int)KE_LEFTDRAG,		MOUSE_LEFT,	FALSE,	TRUE},
1195b20b9e14SBram Moolenaar     {(int)KE_LEFTRELEASE,	MOUSE_LEFT,	FALSE,	FALSE},
1196b20b9e14SBram Moolenaar #ifdef FEAT_GUI
1197b20b9e14SBram Moolenaar     {(int)KE_LEFTRELEASE_NM,	MOUSE_LEFT,	FALSE,	FALSE},
1198b20b9e14SBram Moolenaar #endif
1199b20b9e14SBram Moolenaar     {(int)KE_MIDDLEMOUSE,	MOUSE_MIDDLE,	TRUE,	FALSE},
1200b20b9e14SBram Moolenaar     {(int)KE_MIDDLEDRAG,	MOUSE_MIDDLE,	FALSE,	TRUE},
1201b20b9e14SBram Moolenaar     {(int)KE_MIDDLERELEASE,	MOUSE_MIDDLE,	FALSE,	FALSE},
1202b20b9e14SBram Moolenaar     {(int)KE_RIGHTMOUSE,	MOUSE_RIGHT,	TRUE,	FALSE},
1203b20b9e14SBram Moolenaar     {(int)KE_RIGHTDRAG,		MOUSE_RIGHT,	FALSE,	TRUE},
1204b20b9e14SBram Moolenaar     {(int)KE_RIGHTRELEASE,	MOUSE_RIGHT,	FALSE,	FALSE},
1205b20b9e14SBram Moolenaar     {(int)KE_X1MOUSE,		MOUSE_X1,	TRUE,	FALSE},
1206b20b9e14SBram Moolenaar     {(int)KE_X1DRAG,		MOUSE_X1,	FALSE,	TRUE},
1207b20b9e14SBram Moolenaar     {(int)KE_X1RELEASE,		MOUSE_X1,	FALSE,	FALSE},
1208b20b9e14SBram Moolenaar     {(int)KE_X2MOUSE,		MOUSE_X2,	TRUE,	FALSE},
1209b20b9e14SBram Moolenaar     {(int)KE_X2DRAG,		MOUSE_X2,	FALSE,	TRUE},
1210b20b9e14SBram Moolenaar     {(int)KE_X2RELEASE,		MOUSE_X2,	FALSE,	FALSE},
1211b20b9e14SBram Moolenaar     // DRAG without CLICK
1212b20b9e14SBram Moolenaar     {(int)KE_MOUSEMOVE,		MOUSE_RELEASE,	FALSE,	TRUE},
1213b20b9e14SBram Moolenaar     // RELEASE without CLICK
1214b20b9e14SBram Moolenaar     {(int)KE_IGNORE,		MOUSE_RELEASE,	FALSE,	FALSE},
1215b20b9e14SBram Moolenaar     {0,				0,		0,	0},
1216b20b9e14SBram Moolenaar };
1217b20b9e14SBram Moolenaar 
1218b20b9e14SBram Moolenaar /*
1219b20b9e14SBram Moolenaar  * Look up the given mouse code to return the relevant information in the other
1220b20b9e14SBram Moolenaar  * arguments.  Return which button is down or was released.
1221b20b9e14SBram Moolenaar  */
1222b20b9e14SBram Moolenaar     int
get_mouse_button(int code,int * is_click,int * is_drag)1223b20b9e14SBram Moolenaar get_mouse_button(int code, int *is_click, int *is_drag)
1224b20b9e14SBram Moolenaar {
1225b20b9e14SBram Moolenaar     int	    i;
1226b20b9e14SBram Moolenaar 
1227b20b9e14SBram Moolenaar     for (i = 0; mouse_table[i].pseudo_code; i++)
1228b20b9e14SBram Moolenaar 	if (code == mouse_table[i].pseudo_code)
1229b20b9e14SBram Moolenaar 	{
1230b20b9e14SBram Moolenaar 	    *is_click = mouse_table[i].is_click;
1231b20b9e14SBram Moolenaar 	    *is_drag = mouse_table[i].is_drag;
1232b20b9e14SBram Moolenaar 	    return mouse_table[i].button;
1233b20b9e14SBram Moolenaar 	}
1234b20b9e14SBram Moolenaar     return 0;	    // Shouldn't get here
1235b20b9e14SBram Moolenaar }
1236b20b9e14SBram Moolenaar 
1237b20b9e14SBram Moolenaar /*
1238b20b9e14SBram Moolenaar  * Return the appropriate pseudo mouse event token (KE_LEFTMOUSE etc) based on
1239b20b9e14SBram Moolenaar  * the given information about which mouse button is down, and whether the
1240b20b9e14SBram Moolenaar  * mouse was clicked, dragged or released.
1241b20b9e14SBram Moolenaar  */
1242b20b9e14SBram Moolenaar     int
get_pseudo_mouse_code(int button,int is_click,int is_drag)1243b20b9e14SBram Moolenaar get_pseudo_mouse_code(
1244b20b9e14SBram Moolenaar     int	    button,	// eg MOUSE_LEFT
1245b20b9e14SBram Moolenaar     int	    is_click,
1246b20b9e14SBram Moolenaar     int	    is_drag)
1247b20b9e14SBram Moolenaar {
1248b20b9e14SBram Moolenaar     int	    i;
1249b20b9e14SBram Moolenaar 
1250b20b9e14SBram Moolenaar     for (i = 0; mouse_table[i].pseudo_code; i++)
1251b20b9e14SBram Moolenaar 	if (button == mouse_table[i].button
1252b20b9e14SBram Moolenaar 	    && is_click == mouse_table[i].is_click
1253b20b9e14SBram Moolenaar 	    && is_drag == mouse_table[i].is_drag)
1254b20b9e14SBram Moolenaar 	{
1255b20b9e14SBram Moolenaar #ifdef FEAT_GUI
1256b20b9e14SBram Moolenaar 	    // Trick: a non mappable left click and release has mouse_col -1
1257b20b9e14SBram Moolenaar 	    // or added MOUSE_COLOFF.  Used for 'mousefocus' in
1258b20b9e14SBram Moolenaar 	    // gui_mouse_moved()
1259b20b9e14SBram Moolenaar 	    if (mouse_col < 0 || mouse_col > MOUSE_COLOFF)
1260b20b9e14SBram Moolenaar 	    {
1261b20b9e14SBram Moolenaar 		if (mouse_col < 0)
1262b20b9e14SBram Moolenaar 		    mouse_col = 0;
1263b20b9e14SBram Moolenaar 		else
1264b20b9e14SBram Moolenaar 		    mouse_col -= MOUSE_COLOFF;
1265b20b9e14SBram Moolenaar 		if (mouse_table[i].pseudo_code == (int)KE_LEFTMOUSE)
1266b20b9e14SBram Moolenaar 		    return (int)KE_LEFTMOUSE_NM;
1267b20b9e14SBram Moolenaar 		if (mouse_table[i].pseudo_code == (int)KE_LEFTRELEASE)
1268b20b9e14SBram Moolenaar 		    return (int)KE_LEFTRELEASE_NM;
1269b20b9e14SBram Moolenaar 	    }
1270b20b9e14SBram Moolenaar #endif
1271b20b9e14SBram Moolenaar 	    return mouse_table[i].pseudo_code;
1272b20b9e14SBram Moolenaar 	}
1273b20b9e14SBram Moolenaar     return (int)KE_IGNORE;	    // not recognized, ignore it
1274b20b9e14SBram Moolenaar }
1275b20b9e14SBram Moolenaar 
1276b20b9e14SBram Moolenaar # define HMT_NORMAL	1
1277b20b9e14SBram Moolenaar # define HMT_NETTERM	2
1278b20b9e14SBram Moolenaar # define HMT_DEC	4
1279b20b9e14SBram Moolenaar # define HMT_JSBTERM	8
1280b20b9e14SBram Moolenaar # define HMT_PTERM	16
1281b20b9e14SBram Moolenaar # define HMT_URXVT	32
1282b20b9e14SBram Moolenaar # define HMT_GPM	64
1283b20b9e14SBram Moolenaar # define HMT_SGR	128
1284b20b9e14SBram Moolenaar # define HMT_SGR_REL	256
1285b20b9e14SBram Moolenaar static int has_mouse_termcode = 0;
1286b20b9e14SBram Moolenaar 
1287b20b9e14SBram Moolenaar     void
set_mouse_termcode(int n,char_u * s)1288b20b9e14SBram Moolenaar set_mouse_termcode(
1289b20b9e14SBram Moolenaar     int		n,	// KS_MOUSE, KS_NETTERM_MOUSE or KS_DEC_MOUSE
1290b20b9e14SBram Moolenaar     char_u	*s)
1291b20b9e14SBram Moolenaar {
1292b20b9e14SBram Moolenaar     char_u	name[2];
1293b20b9e14SBram Moolenaar 
1294b20b9e14SBram Moolenaar     name[0] = n;
1295b20b9e14SBram Moolenaar     name[1] = KE_FILLER;
1296b20b9e14SBram Moolenaar     add_termcode(name, s, FALSE);
1297b20b9e14SBram Moolenaar #   ifdef FEAT_MOUSE_JSB
1298b20b9e14SBram Moolenaar     if (n == KS_JSBTERM_MOUSE)
1299b20b9e14SBram Moolenaar 	has_mouse_termcode |= HMT_JSBTERM;
1300b20b9e14SBram Moolenaar     else
1301b20b9e14SBram Moolenaar #   endif
1302b20b9e14SBram Moolenaar #   ifdef FEAT_MOUSE_NET
1303b20b9e14SBram Moolenaar     if (n == KS_NETTERM_MOUSE)
1304b20b9e14SBram Moolenaar 	has_mouse_termcode |= HMT_NETTERM;
1305b20b9e14SBram Moolenaar     else
1306b20b9e14SBram Moolenaar #   endif
1307b20b9e14SBram Moolenaar #   ifdef FEAT_MOUSE_DEC
1308b20b9e14SBram Moolenaar     if (n == KS_DEC_MOUSE)
1309b20b9e14SBram Moolenaar 	has_mouse_termcode |= HMT_DEC;
1310b20b9e14SBram Moolenaar     else
1311b20b9e14SBram Moolenaar #   endif
1312b20b9e14SBram Moolenaar #   ifdef FEAT_MOUSE_PTERM
1313b20b9e14SBram Moolenaar     if (n == KS_PTERM_MOUSE)
1314b20b9e14SBram Moolenaar 	has_mouse_termcode |= HMT_PTERM;
1315b20b9e14SBram Moolenaar     else
1316b20b9e14SBram Moolenaar #   endif
1317b20b9e14SBram Moolenaar #   ifdef FEAT_MOUSE_URXVT
1318b20b9e14SBram Moolenaar     if (n == KS_URXVT_MOUSE)
1319b20b9e14SBram Moolenaar 	has_mouse_termcode |= HMT_URXVT;
1320b20b9e14SBram Moolenaar     else
1321b20b9e14SBram Moolenaar #   endif
1322b20b9e14SBram Moolenaar #   ifdef FEAT_MOUSE_GPM
1323b20b9e14SBram Moolenaar     if (n == KS_GPM_MOUSE)
1324b20b9e14SBram Moolenaar 	has_mouse_termcode |= HMT_GPM;
1325b20b9e14SBram Moolenaar     else
1326b20b9e14SBram Moolenaar #   endif
1327b20b9e14SBram Moolenaar     if (n == KS_SGR_MOUSE)
1328b20b9e14SBram Moolenaar 	has_mouse_termcode |= HMT_SGR;
1329b20b9e14SBram Moolenaar     else if (n == KS_SGR_MOUSE_RELEASE)
1330b20b9e14SBram Moolenaar 	has_mouse_termcode |= HMT_SGR_REL;
1331b20b9e14SBram Moolenaar     else
1332b20b9e14SBram Moolenaar 	has_mouse_termcode |= HMT_NORMAL;
1333b20b9e14SBram Moolenaar }
1334b20b9e14SBram Moolenaar 
1335a1cb1d1dSBram Moolenaar # if defined(UNIX) || defined(VMS) || defined(PROTO)
1336b20b9e14SBram Moolenaar     void
del_mouse_termcode(int n)1337b20b9e14SBram Moolenaar del_mouse_termcode(
1338b20b9e14SBram Moolenaar     int		n)	// KS_MOUSE, KS_NETTERM_MOUSE or KS_DEC_MOUSE
1339b20b9e14SBram Moolenaar {
1340b20b9e14SBram Moolenaar     char_u	name[2];
1341b20b9e14SBram Moolenaar 
1342b20b9e14SBram Moolenaar     name[0] = n;
1343b20b9e14SBram Moolenaar     name[1] = KE_FILLER;
1344b20b9e14SBram Moolenaar     del_termcode(name);
1345b20b9e14SBram Moolenaar #   ifdef FEAT_MOUSE_JSB
1346b20b9e14SBram Moolenaar     if (n == KS_JSBTERM_MOUSE)
1347b20b9e14SBram Moolenaar 	has_mouse_termcode &= ~HMT_JSBTERM;
1348b20b9e14SBram Moolenaar     else
1349b20b9e14SBram Moolenaar #   endif
1350b20b9e14SBram Moolenaar #   ifdef FEAT_MOUSE_NET
1351b20b9e14SBram Moolenaar     if (n == KS_NETTERM_MOUSE)
1352b20b9e14SBram Moolenaar 	has_mouse_termcode &= ~HMT_NETTERM;
1353b20b9e14SBram Moolenaar     else
1354b20b9e14SBram Moolenaar #   endif
1355b20b9e14SBram Moolenaar #   ifdef FEAT_MOUSE_DEC
1356b20b9e14SBram Moolenaar     if (n == KS_DEC_MOUSE)
1357b20b9e14SBram Moolenaar 	has_mouse_termcode &= ~HMT_DEC;
1358b20b9e14SBram Moolenaar     else
1359b20b9e14SBram Moolenaar #   endif
1360b20b9e14SBram Moolenaar #   ifdef FEAT_MOUSE_PTERM
1361b20b9e14SBram Moolenaar     if (n == KS_PTERM_MOUSE)
1362b20b9e14SBram Moolenaar 	has_mouse_termcode &= ~HMT_PTERM;
1363b20b9e14SBram Moolenaar     else
1364b20b9e14SBram Moolenaar #   endif
1365b20b9e14SBram Moolenaar #   ifdef FEAT_MOUSE_URXVT
1366b20b9e14SBram Moolenaar     if (n == KS_URXVT_MOUSE)
1367b20b9e14SBram Moolenaar 	has_mouse_termcode &= ~HMT_URXVT;
1368b20b9e14SBram Moolenaar     else
1369b20b9e14SBram Moolenaar #   endif
1370b20b9e14SBram Moolenaar #   ifdef FEAT_MOUSE_GPM
1371b20b9e14SBram Moolenaar     if (n == KS_GPM_MOUSE)
1372b20b9e14SBram Moolenaar 	has_mouse_termcode &= ~HMT_GPM;
1373b20b9e14SBram Moolenaar     else
1374b20b9e14SBram Moolenaar #   endif
1375b20b9e14SBram Moolenaar     if (n == KS_SGR_MOUSE)
1376b20b9e14SBram Moolenaar 	has_mouse_termcode &= ~HMT_SGR;
1377b20b9e14SBram Moolenaar     else if (n == KS_SGR_MOUSE_RELEASE)
1378b20b9e14SBram Moolenaar 	has_mouse_termcode &= ~HMT_SGR_REL;
1379b20b9e14SBram Moolenaar     else
1380b20b9e14SBram Moolenaar 	has_mouse_termcode &= ~HMT_NORMAL;
1381b20b9e14SBram Moolenaar }
1382b20b9e14SBram Moolenaar # endif
1383b20b9e14SBram Moolenaar 
1384b20b9e14SBram Moolenaar /*
1385b20b9e14SBram Moolenaar  * setmouse() - switch mouse on/off depending on current mode and 'mouse'
1386b20b9e14SBram Moolenaar  */
1387b20b9e14SBram Moolenaar     void
setmouse(void)1388b20b9e14SBram Moolenaar setmouse(void)
1389b20b9e14SBram Moolenaar {
1390b20b9e14SBram Moolenaar     int	    checkfor;
1391b20b9e14SBram Moolenaar 
1392b20b9e14SBram Moolenaar # ifdef FEAT_MOUSESHAPE
1393b20b9e14SBram Moolenaar     update_mouseshape(-1);
1394b20b9e14SBram Moolenaar # endif
1395b20b9e14SBram Moolenaar 
1396a1cb1d1dSBram Moolenaar     // Should be outside proc, but may break MOUSESHAPE
1397b20b9e14SBram Moolenaar #  ifdef FEAT_GUI
1398b20b9e14SBram Moolenaar     // In the GUI the mouse is always enabled.
1399b20b9e14SBram Moolenaar     if (gui.in_use)
1400b20b9e14SBram Moolenaar 	return;
1401b20b9e14SBram Moolenaar #  endif
1402b20b9e14SBram Moolenaar     // be quick when mouse is off
1403b20b9e14SBram Moolenaar     if (*p_mouse == NUL || has_mouse_termcode == 0)
1404b20b9e14SBram Moolenaar 	return;
1405b20b9e14SBram Moolenaar 
1406b20b9e14SBram Moolenaar     // don't switch mouse on when not in raw mode (Ex mode)
1407b20b9e14SBram Moolenaar     if (cur_tmode != TMODE_RAW)
1408b20b9e14SBram Moolenaar     {
1409b20b9e14SBram Moolenaar 	mch_setmouse(FALSE);
1410b20b9e14SBram Moolenaar 	return;
1411b20b9e14SBram Moolenaar     }
1412b20b9e14SBram Moolenaar 
1413b20b9e14SBram Moolenaar     if (VIsual_active)
1414b20b9e14SBram Moolenaar 	checkfor = MOUSE_VISUAL;
1415b20b9e14SBram Moolenaar     else if (State == HITRETURN || State == ASKMORE || State == SETWSIZE)
1416b20b9e14SBram Moolenaar 	checkfor = MOUSE_RETURN;
1417b20b9e14SBram Moolenaar     else if (State & INSERT)
1418b20b9e14SBram Moolenaar 	checkfor = MOUSE_INSERT;
1419b20b9e14SBram Moolenaar     else if (State & CMDLINE)
1420b20b9e14SBram Moolenaar 	checkfor = MOUSE_COMMAND;
1421b20b9e14SBram Moolenaar     else if (State == CONFIRM || State == EXTERNCMD)
1422b20b9e14SBram Moolenaar 	checkfor = ' '; // don't use mouse for ":confirm" or ":!cmd"
1423b20b9e14SBram Moolenaar     else
1424b20b9e14SBram Moolenaar 	checkfor = MOUSE_NORMAL;    // assume normal mode
1425b20b9e14SBram Moolenaar 
1426b20b9e14SBram Moolenaar     if (mouse_has(checkfor))
1427b20b9e14SBram Moolenaar 	mch_setmouse(TRUE);
1428b20b9e14SBram Moolenaar     else
1429b20b9e14SBram Moolenaar 	mch_setmouse(FALSE);
1430b20b9e14SBram Moolenaar }
1431b20b9e14SBram Moolenaar 
1432b20b9e14SBram Moolenaar /*
1433b20b9e14SBram Moolenaar  * Return TRUE if
1434b20b9e14SBram Moolenaar  * - "c" is in 'mouse', or
1435b20b9e14SBram Moolenaar  * - 'a' is in 'mouse' and "c" is in MOUSE_A, or
1436b20b9e14SBram Moolenaar  * - the current buffer is a help file and 'h' is in 'mouse' and we are in a
1437b20b9e14SBram Moolenaar  *   normal editing mode (not at hit-return message).
1438b20b9e14SBram Moolenaar  */
1439b20b9e14SBram Moolenaar     int
mouse_has(int c)1440b20b9e14SBram Moolenaar mouse_has(int c)
1441b20b9e14SBram Moolenaar {
1442b20b9e14SBram Moolenaar     char_u	*p;
1443b20b9e14SBram Moolenaar 
1444b20b9e14SBram Moolenaar     for (p = p_mouse; *p; ++p)
1445b20b9e14SBram Moolenaar 	switch (*p)
1446b20b9e14SBram Moolenaar 	{
1447b20b9e14SBram Moolenaar 	    case 'a': if (vim_strchr((char_u *)MOUSE_A, c) != NULL)
1448b20b9e14SBram Moolenaar 			  return TRUE;
1449b20b9e14SBram Moolenaar 		      break;
1450b20b9e14SBram Moolenaar 	    case MOUSE_HELP: if (c != MOUSE_RETURN && curbuf->b_help)
1451b20b9e14SBram Moolenaar 				 return TRUE;
1452b20b9e14SBram Moolenaar 			     break;
1453b20b9e14SBram Moolenaar 	    default: if (c == *p) return TRUE; break;
1454b20b9e14SBram Moolenaar 	}
1455b20b9e14SBram Moolenaar     return FALSE;
1456b20b9e14SBram Moolenaar }
1457b20b9e14SBram Moolenaar 
1458b20b9e14SBram Moolenaar /*
1459b20b9e14SBram Moolenaar  * Return TRUE when 'mousemodel' is set to "popup" or "popup_setpos".
1460b20b9e14SBram Moolenaar  */
1461b20b9e14SBram Moolenaar     int
mouse_model_popup(void)1462b20b9e14SBram Moolenaar mouse_model_popup(void)
1463b20b9e14SBram Moolenaar {
1464b20b9e14SBram Moolenaar     return (p_mousem[0] == 'p');
1465b20b9e14SBram Moolenaar }
1466b20b9e14SBram Moolenaar 
1467b20b9e14SBram Moolenaar /*
1468b20b9e14SBram Moolenaar  * Move the cursor to the specified row and column on the screen.
1469b20b9e14SBram Moolenaar  * Change current window if necessary.	Returns an integer with the
1470b20b9e14SBram Moolenaar  * CURSOR_MOVED bit set if the cursor has moved or unset otherwise.
1471b20b9e14SBram Moolenaar  *
1472b20b9e14SBram Moolenaar  * The MOUSE_FOLD_CLOSE bit is set when clicked on the '-' in a fold column.
1473b20b9e14SBram Moolenaar  * The MOUSE_FOLD_OPEN bit is set when clicked on the '+' in a fold column.
1474b20b9e14SBram Moolenaar  *
1475b20b9e14SBram Moolenaar  * If flags has MOUSE_FOCUS, then the current window will not be changed, and
1476b20b9e14SBram Moolenaar  * if the mouse is outside the window then the text will scroll, or if the
1477b20b9e14SBram Moolenaar  * mouse was previously on a status line, then the status line may be dragged.
1478b20b9e14SBram Moolenaar  *
1479b20b9e14SBram Moolenaar  * If flags has MOUSE_MAY_VIS, then VIsual mode will be started before the
1480b20b9e14SBram Moolenaar  * cursor is moved unless the cursor was on a status line.
1481b20b9e14SBram Moolenaar  * This function returns one of IN_UNKNOWN, IN_BUFFER, IN_STATUS_LINE or
1482b20b9e14SBram Moolenaar  * IN_SEP_LINE depending on where the cursor was clicked.
1483b20b9e14SBram Moolenaar  *
1484b20b9e14SBram Moolenaar  * If flags has MOUSE_MAY_STOP_VIS, then Visual mode will be stopped, unless
1485b20b9e14SBram Moolenaar  * the mouse is on the status line of the same window.
1486b20b9e14SBram Moolenaar  *
1487b20b9e14SBram Moolenaar  * If flags has MOUSE_DID_MOVE, nothing is done if the mouse didn't move since
1488b20b9e14SBram Moolenaar  * the last call.
1489b20b9e14SBram Moolenaar  *
1490b20b9e14SBram Moolenaar  * If flags has MOUSE_SETPOS, nothing is done, only the current position is
1491b20b9e14SBram Moolenaar  * remembered.
1492b20b9e14SBram Moolenaar  */
1493b20b9e14SBram Moolenaar     int
jump_to_mouse(int flags,int * inclusive,int which_button)1494b20b9e14SBram Moolenaar jump_to_mouse(
1495b20b9e14SBram Moolenaar     int		flags,
1496b20b9e14SBram Moolenaar     int		*inclusive,	// used for inclusive operator, can be NULL
1497b20b9e14SBram Moolenaar     int		which_button)	// MOUSE_LEFT, MOUSE_RIGHT, MOUSE_MIDDLE
1498b20b9e14SBram Moolenaar {
1499b20b9e14SBram Moolenaar     static int	on_status_line = 0;	// #lines below bottom of window
1500b20b9e14SBram Moolenaar     static int	on_sep_line = 0;	// on separator right of window
1501b20b9e14SBram Moolenaar #ifdef FEAT_MENU
1502b20b9e14SBram Moolenaar     static int  in_winbar = FALSE;
1503b20b9e14SBram Moolenaar #endif
150405ad5ff0SBram Moolenaar #ifdef FEAT_PROP_POPUP
1505b20b9e14SBram Moolenaar     static int   in_popup_win = FALSE;
1506b20b9e14SBram Moolenaar     static win_T *click_in_popup_win = NULL;
1507b20b9e14SBram Moolenaar #endif
1508b20b9e14SBram Moolenaar     static int	prev_row = -1;
1509b20b9e14SBram Moolenaar     static int	prev_col = -1;
1510b20b9e14SBram Moolenaar     static win_T *dragwin = NULL;	// window being dragged
1511b20b9e14SBram Moolenaar     static int	did_drag = FALSE;	// drag was noticed
1512b20b9e14SBram Moolenaar 
1513b20b9e14SBram Moolenaar     win_T	*wp, *old_curwin;
1514b20b9e14SBram Moolenaar     pos_T	old_cursor;
1515b20b9e14SBram Moolenaar     int		count;
1516b20b9e14SBram Moolenaar     int		first;
1517b20b9e14SBram Moolenaar     int		row = mouse_row;
1518b20b9e14SBram Moolenaar     int		col = mouse_col;
1519b20b9e14SBram Moolenaar #ifdef FEAT_FOLDING
1520b20b9e14SBram Moolenaar     int		mouse_char;
1521b20b9e14SBram Moolenaar #endif
1522b20b9e14SBram Moolenaar 
1523b20b9e14SBram Moolenaar     mouse_past_bottom = FALSE;
1524b20b9e14SBram Moolenaar     mouse_past_eol = FALSE;
1525b20b9e14SBram Moolenaar 
1526b20b9e14SBram Moolenaar     if (flags & MOUSE_RELEASED)
1527b20b9e14SBram Moolenaar     {
1528b20b9e14SBram Moolenaar 	// On button release we may change window focus if positioned on a
1529b20b9e14SBram Moolenaar 	// status line and no dragging happened.
1530b20b9e14SBram Moolenaar 	if (dragwin != NULL && !did_drag)
1531b20b9e14SBram Moolenaar 	    flags &= ~(MOUSE_FOCUS | MOUSE_DID_MOVE);
1532b20b9e14SBram Moolenaar 	dragwin = NULL;
1533b20b9e14SBram Moolenaar 	did_drag = FALSE;
153405ad5ff0SBram Moolenaar #ifdef FEAT_PROP_POPUP
1535b20b9e14SBram Moolenaar 	if (click_in_popup_win != NULL && popup_dragwin == NULL)
1536b20b9e14SBram Moolenaar 	    popup_close_for_mouse_click(click_in_popup_win);
1537b20b9e14SBram Moolenaar 
1538b20b9e14SBram Moolenaar 	popup_dragwin = NULL;
1539b20b9e14SBram Moolenaar 	click_in_popup_win = NULL;
1540b20b9e14SBram Moolenaar #endif
1541b20b9e14SBram Moolenaar     }
1542b20b9e14SBram Moolenaar 
1543b20b9e14SBram Moolenaar     if ((flags & MOUSE_DID_MOVE)
1544b20b9e14SBram Moolenaar 	    && prev_row == mouse_row
1545b20b9e14SBram Moolenaar 	    && prev_col == mouse_col)
1546b20b9e14SBram Moolenaar     {
1547b20b9e14SBram Moolenaar retnomove:
1548b20b9e14SBram Moolenaar 	// before moving the cursor for a left click which is NOT in a status
1549b20b9e14SBram Moolenaar 	// line, stop Visual mode
1550b20b9e14SBram Moolenaar 	if (on_status_line)
1551b20b9e14SBram Moolenaar 	    return IN_STATUS_LINE;
1552b20b9e14SBram Moolenaar 	if (on_sep_line)
1553b20b9e14SBram Moolenaar 	    return IN_SEP_LINE;
1554b20b9e14SBram Moolenaar #ifdef FEAT_MENU
1555b20b9e14SBram Moolenaar 	if (in_winbar)
1556b20b9e14SBram Moolenaar 	{
1557b20b9e14SBram Moolenaar 	    // A quick second click may arrive as a double-click, but we use it
1558b20b9e14SBram Moolenaar 	    // as a second click in the WinBar.
1559b20b9e14SBram Moolenaar 	    if ((mod_mask & MOD_MASK_MULTI_CLICK) && !(flags & MOUSE_RELEASED))
1560b20b9e14SBram Moolenaar 	    {
1561b20b9e14SBram Moolenaar 		wp = mouse_find_win(&row, &col, FAIL_POPUP);
1562b20b9e14SBram Moolenaar 		if (wp == NULL)
1563b20b9e14SBram Moolenaar 		    return IN_UNKNOWN;
1564b20b9e14SBram Moolenaar 		winbar_click(wp, col);
1565b20b9e14SBram Moolenaar 	    }
1566b20b9e14SBram Moolenaar 	    return IN_OTHER_WIN | MOUSE_WINBAR;
1567b20b9e14SBram Moolenaar 	}
1568b20b9e14SBram Moolenaar #endif
1569b20b9e14SBram Moolenaar 	if (flags & MOUSE_MAY_STOP_VIS)
1570b20b9e14SBram Moolenaar 	{
1571*4f3c57f7SBram Moolenaar 	    end_visual_mode_keep_button();
1572b20b9e14SBram Moolenaar 	    redraw_curbuf_later(INVERTED);	// delete the inversion
1573b20b9e14SBram Moolenaar 	}
1574b20b9e14SBram Moolenaar #if defined(FEAT_CMDWIN) && defined(FEAT_CLIPBOARD)
1575b20b9e14SBram Moolenaar 	// Continue a modeless selection in another window.
1576b20b9e14SBram Moolenaar 	if (cmdwin_type != 0 && row < curwin->w_winrow)
1577b20b9e14SBram Moolenaar 	    return IN_OTHER_WIN;
1578b20b9e14SBram Moolenaar #endif
157905ad5ff0SBram Moolenaar #ifdef FEAT_PROP_POPUP
1580b20b9e14SBram Moolenaar 	// Continue a modeless selection in a popup window or dragging it.
1581b20b9e14SBram Moolenaar 	if (in_popup_win)
1582b20b9e14SBram Moolenaar 	{
1583b20b9e14SBram Moolenaar 	    click_in_popup_win = NULL;  // don't close it on release
1584b20b9e14SBram Moolenaar 	    if (popup_dragwin != NULL)
1585b20b9e14SBram Moolenaar 	    {
1586b20b9e14SBram Moolenaar 		// dragging a popup window
1587b20b9e14SBram Moolenaar 		popup_drag(popup_dragwin);
1588b20b9e14SBram Moolenaar 		return IN_UNKNOWN;
1589b20b9e14SBram Moolenaar 	    }
1590b20b9e14SBram Moolenaar 	    return IN_OTHER_WIN;
1591b20b9e14SBram Moolenaar 	}
1592b20b9e14SBram Moolenaar #endif
1593b20b9e14SBram Moolenaar 	return IN_BUFFER;
1594b20b9e14SBram Moolenaar     }
1595b20b9e14SBram Moolenaar 
1596b20b9e14SBram Moolenaar     prev_row = mouse_row;
1597b20b9e14SBram Moolenaar     prev_col = mouse_col;
1598b20b9e14SBram Moolenaar 
1599b20b9e14SBram Moolenaar     if (flags & MOUSE_SETPOS)
1600b20b9e14SBram Moolenaar 	goto retnomove;				// ugly goto...
1601b20b9e14SBram Moolenaar 
1602b20b9e14SBram Moolenaar #ifdef FEAT_FOLDING
1603b20b9e14SBram Moolenaar     // Remember the character under the mouse, it might be a '-' or '+' in the
1604b20b9e14SBram Moolenaar     // fold column.
1605b20b9e14SBram Moolenaar     if (row >= 0 && row < Rows && col >= 0 && col <= Columns
1606b20b9e14SBram Moolenaar 						       && ScreenLines != NULL)
1607b20b9e14SBram Moolenaar 	mouse_char = ScreenLines[LineOffset[row] + col];
1608b20b9e14SBram Moolenaar     else
1609b20b9e14SBram Moolenaar 	mouse_char = ' ';
1610b20b9e14SBram Moolenaar #endif
1611b20b9e14SBram Moolenaar 
1612b20b9e14SBram Moolenaar     old_curwin = curwin;
1613b20b9e14SBram Moolenaar     old_cursor = curwin->w_cursor;
1614b20b9e14SBram Moolenaar 
1615b20b9e14SBram Moolenaar     if (!(flags & MOUSE_FOCUS))
1616b20b9e14SBram Moolenaar     {
1617b20b9e14SBram Moolenaar 	if (row < 0 || col < 0)			// check if it makes sense
1618b20b9e14SBram Moolenaar 	    return IN_UNKNOWN;
1619b20b9e14SBram Moolenaar 
1620b20b9e14SBram Moolenaar 	// find the window where the row is in and adjust "row" and "col" to be
1621b20b9e14SBram Moolenaar 	// relative to top-left of the window
1622b20b9e14SBram Moolenaar 	wp = mouse_find_win(&row, &col, FIND_POPUP);
1623b20b9e14SBram Moolenaar 	if (wp == NULL)
1624b20b9e14SBram Moolenaar 	    return IN_UNKNOWN;
1625b20b9e14SBram Moolenaar 	dragwin = NULL;
1626b20b9e14SBram Moolenaar 
162705ad5ff0SBram Moolenaar #ifdef FEAT_PROP_POPUP
1628b20b9e14SBram Moolenaar 	// Click in a popup window may start dragging or modeless selection,
1629b20b9e14SBram Moolenaar 	// but not much else.
1630b20b9e14SBram Moolenaar 	if (WIN_IS_POPUP(wp))
1631b20b9e14SBram Moolenaar 	{
1632b20b9e14SBram Moolenaar 	    on_sep_line = 0;
1633b20b9e14SBram Moolenaar 	    in_popup_win = TRUE;
1634b20b9e14SBram Moolenaar 	    if (which_button == MOUSE_LEFT && popup_close_if_on_X(wp, row, col))
1635b20b9e14SBram Moolenaar 	    {
1636b20b9e14SBram Moolenaar 		return IN_UNKNOWN;
1637b20b9e14SBram Moolenaar 	    }
1638b20b9e14SBram Moolenaar 	    else if ((wp->w_popup_flags & (POPF_DRAG | POPF_RESIZE))
1639b20b9e14SBram Moolenaar 					      && popup_on_border(wp, row, col))
1640b20b9e14SBram Moolenaar 	    {
1641b20b9e14SBram Moolenaar 		popup_dragwin = wp;
1642b20b9e14SBram Moolenaar 		popup_start_drag(wp, row, col);
1643b20b9e14SBram Moolenaar 		return IN_UNKNOWN;
1644b20b9e14SBram Moolenaar 	    }
1645b20b9e14SBram Moolenaar 	    // Only close on release, otherwise it's not possible to drag or do
1646b20b9e14SBram Moolenaar 	    // modeless selection.
1647b20b9e14SBram Moolenaar 	    else if (wp->w_popup_close == POPCLOSE_CLICK
1648b20b9e14SBram Moolenaar 		    && which_button == MOUSE_LEFT)
1649b20b9e14SBram Moolenaar 	    {
1650b20b9e14SBram Moolenaar 		click_in_popup_win = wp;
1651b20b9e14SBram Moolenaar 	    }
1652b20b9e14SBram Moolenaar 	    else if (which_button == MOUSE_LEFT)
1653b20b9e14SBram Moolenaar 		// If the click is in the scrollbar, may scroll up/down.
1654b20b9e14SBram Moolenaar 		popup_handle_scrollbar_click(wp, row, col);
1655b20b9e14SBram Moolenaar # ifdef FEAT_CLIPBOARD
1656b20b9e14SBram Moolenaar 	    return IN_OTHER_WIN;
1657b20b9e14SBram Moolenaar # else
1658b20b9e14SBram Moolenaar 	    return IN_UNKNOWN;
1659b20b9e14SBram Moolenaar # endif
1660b20b9e14SBram Moolenaar 	}
1661b20b9e14SBram Moolenaar 	in_popup_win = FALSE;
1662b20b9e14SBram Moolenaar 	popup_dragwin = NULL;
1663b20b9e14SBram Moolenaar #endif
1664b20b9e14SBram Moolenaar #ifdef FEAT_MENU
1665b20b9e14SBram Moolenaar 	if (row == -1)
1666b20b9e14SBram Moolenaar 	{
1667b20b9e14SBram Moolenaar 	    // A click in the window toolbar does not enter another window or
1668b20b9e14SBram Moolenaar 	    // change Visual highlighting.
1669b20b9e14SBram Moolenaar 	    winbar_click(wp, col);
1670b20b9e14SBram Moolenaar 	    in_winbar = TRUE;
1671b20b9e14SBram Moolenaar 	    return IN_OTHER_WIN | MOUSE_WINBAR;
1672b20b9e14SBram Moolenaar 	}
1673b20b9e14SBram Moolenaar 	in_winbar = FALSE;
1674b20b9e14SBram Moolenaar #endif
1675b20b9e14SBram Moolenaar 
1676b20b9e14SBram Moolenaar 	// winpos and height may change in win_enter()!
1677b20b9e14SBram Moolenaar 	if (row >= wp->w_height)		// In (or below) status line
1678b20b9e14SBram Moolenaar 	{
1679b20b9e14SBram Moolenaar 	    on_status_line = row - wp->w_height + 1;
1680b20b9e14SBram Moolenaar 	    dragwin = wp;
1681b20b9e14SBram Moolenaar 	}
1682b20b9e14SBram Moolenaar 	else
1683b20b9e14SBram Moolenaar 	    on_status_line = 0;
1684b20b9e14SBram Moolenaar 	if (col >= wp->w_width)		// In separator line
1685b20b9e14SBram Moolenaar 	{
1686b20b9e14SBram Moolenaar 	    on_sep_line = col - wp->w_width + 1;
1687b20b9e14SBram Moolenaar 	    dragwin = wp;
1688b20b9e14SBram Moolenaar 	}
1689b20b9e14SBram Moolenaar 	else
1690b20b9e14SBram Moolenaar 	    on_sep_line = 0;
1691b20b9e14SBram Moolenaar 
1692b20b9e14SBram Moolenaar 	// The rightmost character of the status line might be a vertical
1693b20b9e14SBram Moolenaar 	// separator character if there is no connecting window to the right.
1694b20b9e14SBram Moolenaar 	if (on_status_line && on_sep_line)
1695b20b9e14SBram Moolenaar 	{
1696b20b9e14SBram Moolenaar 	    if (stl_connected(wp))
1697b20b9e14SBram Moolenaar 		on_sep_line = 0;
1698b20b9e14SBram Moolenaar 	    else
1699b20b9e14SBram Moolenaar 		on_status_line = 0;
1700b20b9e14SBram Moolenaar 	}
1701b20b9e14SBram Moolenaar 
1702b20b9e14SBram Moolenaar 	// Before jumping to another buffer, or moving the cursor for a left
1703b20b9e14SBram Moolenaar 	// click, stop Visual mode.
1704b20b9e14SBram Moolenaar 	if (VIsual_active
1705b20b9e14SBram Moolenaar 		&& (wp->w_buffer != curwin->w_buffer
1706b20b9e14SBram Moolenaar 		    || (!on_status_line && !on_sep_line
1707b20b9e14SBram Moolenaar #ifdef FEAT_FOLDING
1708b20b9e14SBram Moolenaar 			&& (
1709b20b9e14SBram Moolenaar # ifdef FEAT_RIGHTLEFT
1710b20b9e14SBram Moolenaar 			    wp->w_p_rl ? col < wp->w_width - wp->w_p_fdc :
1711b20b9e14SBram Moolenaar # endif
1712b20b9e14SBram Moolenaar 			    col >= wp->w_p_fdc
1713b20b9e14SBram Moolenaar # ifdef FEAT_CMDWIN
1714b20b9e14SBram Moolenaar 				  + (cmdwin_type == 0 && wp == curwin ? 0 : 1)
1715b20b9e14SBram Moolenaar # endif
1716b20b9e14SBram Moolenaar 			    )
1717b20b9e14SBram Moolenaar #endif
1718b20b9e14SBram Moolenaar 			&& (flags & MOUSE_MAY_STOP_VIS))))
1719b20b9e14SBram Moolenaar 	{
1720*4f3c57f7SBram Moolenaar 	    end_visual_mode_keep_button();
1721b20b9e14SBram Moolenaar 	    redraw_curbuf_later(INVERTED);	// delete the inversion
1722b20b9e14SBram Moolenaar 	}
1723b20b9e14SBram Moolenaar #ifdef FEAT_CMDWIN
1724b20b9e14SBram Moolenaar 	if (cmdwin_type != 0 && wp != curwin)
1725b20b9e14SBram Moolenaar 	{
1726b20b9e14SBram Moolenaar 	    // A click outside the command-line window: Use modeless
1727b20b9e14SBram Moolenaar 	    // selection if possible.  Allow dragging the status lines.
1728b20b9e14SBram Moolenaar 	    on_sep_line = 0;
1729b20b9e14SBram Moolenaar # ifdef FEAT_CLIPBOARD
1730b20b9e14SBram Moolenaar 	    if (on_status_line)
1731b20b9e14SBram Moolenaar 		return IN_STATUS_LINE;
1732b20b9e14SBram Moolenaar 	    return IN_OTHER_WIN;
1733b20b9e14SBram Moolenaar # else
1734b20b9e14SBram Moolenaar 	    row = 0;
1735b20b9e14SBram Moolenaar 	    col += wp->w_wincol;
1736b20b9e14SBram Moolenaar 	    wp = curwin;
1737b20b9e14SBram Moolenaar # endif
1738b20b9e14SBram Moolenaar 	}
1739b20b9e14SBram Moolenaar #endif
1740219c7d06SBram Moolenaar #if defined(FEAT_PROP_POPUP) && defined(FEAT_TERMINAL)
1741219c7d06SBram Moolenaar 	if (popup_is_popup(curwin) && curbuf->b_term != NULL)
1742219c7d06SBram Moolenaar 	    // terminal in popup window: don't jump to another window
1743219c7d06SBram Moolenaar 	    return IN_OTHER_WIN;
1744219c7d06SBram Moolenaar #endif
1745b20b9e14SBram Moolenaar 	// Only change window focus when not clicking on or dragging the
1746b20b9e14SBram Moolenaar 	// status line.  Do change focus when releasing the mouse button
1747b20b9e14SBram Moolenaar 	// (MOUSE_FOCUS was set above if we dragged first).
1748b20b9e14SBram Moolenaar 	if (dragwin == NULL || (flags & MOUSE_RELEASED))
1749b20b9e14SBram Moolenaar 	    win_enter(wp, TRUE);		// can make wp invalid!
1750b20b9e14SBram Moolenaar 
1751b20b9e14SBram Moolenaar 	if (curwin != old_curwin)
1752b20b9e14SBram Moolenaar 	{
1753b20b9e14SBram Moolenaar #ifdef CHECK_DOUBLE_CLICK
1754b20b9e14SBram Moolenaar 	    // set topline, to be able to check for double click ourselves
1755b20b9e14SBram Moolenaar 	    set_mouse_topline(curwin);
1756b20b9e14SBram Moolenaar #endif
1757b20b9e14SBram Moolenaar #ifdef FEAT_TERMINAL
1758b20b9e14SBram Moolenaar 	    // when entering a terminal window may change state
1759b20b9e14SBram Moolenaar 	    term_win_entered();
1760b20b9e14SBram Moolenaar #endif
1761b20b9e14SBram Moolenaar 	}
1762b20b9e14SBram Moolenaar 	if (on_status_line)			// In (or below) status line
1763b20b9e14SBram Moolenaar 	{
1764b20b9e14SBram Moolenaar 	    // Don't use start_arrow() if we're in the same window
1765b20b9e14SBram Moolenaar 	    if (curwin == old_curwin)
1766b20b9e14SBram Moolenaar 		return IN_STATUS_LINE;
1767b20b9e14SBram Moolenaar 	    else
1768b20b9e14SBram Moolenaar 		return IN_STATUS_LINE | CURSOR_MOVED;
1769b20b9e14SBram Moolenaar 	}
1770b20b9e14SBram Moolenaar 	if (on_sep_line)			// In (or below) status line
1771b20b9e14SBram Moolenaar 	{
1772b20b9e14SBram Moolenaar 	    // Don't use start_arrow() if we're in the same window
1773b20b9e14SBram Moolenaar 	    if (curwin == old_curwin)
1774b20b9e14SBram Moolenaar 		return IN_SEP_LINE;
1775b20b9e14SBram Moolenaar 	    else
1776b20b9e14SBram Moolenaar 		return IN_SEP_LINE | CURSOR_MOVED;
1777b20b9e14SBram Moolenaar 	}
1778b20b9e14SBram Moolenaar 
1779b20b9e14SBram Moolenaar 	curwin->w_cursor.lnum = curwin->w_topline;
1780b20b9e14SBram Moolenaar #ifdef FEAT_GUI
1781b20b9e14SBram Moolenaar 	// remember topline, needed for double click
1782b20b9e14SBram Moolenaar 	gui_prev_topline = curwin->w_topline;
1783b20b9e14SBram Moolenaar # ifdef FEAT_DIFF
1784b20b9e14SBram Moolenaar 	gui_prev_topfill = curwin->w_topfill;
1785b20b9e14SBram Moolenaar # endif
1786b20b9e14SBram Moolenaar #endif
1787b20b9e14SBram Moolenaar     }
1788b20b9e14SBram Moolenaar     else if (on_status_line && which_button == MOUSE_LEFT)
1789b20b9e14SBram Moolenaar     {
1790b20b9e14SBram Moolenaar 	if (dragwin != NULL)
1791b20b9e14SBram Moolenaar 	{
1792b20b9e14SBram Moolenaar 	    // Drag the status line
1793b20b9e14SBram Moolenaar 	    count = row - dragwin->w_winrow - dragwin->w_height + 1
1794b20b9e14SBram Moolenaar 							     - on_status_line;
1795b20b9e14SBram Moolenaar 	    win_drag_status_line(dragwin, count);
1796b20b9e14SBram Moolenaar 	    did_drag |= count;
1797b20b9e14SBram Moolenaar 	}
1798b20b9e14SBram Moolenaar 	return IN_STATUS_LINE;			// Cursor didn't move
1799b20b9e14SBram Moolenaar     }
1800b20b9e14SBram Moolenaar     else if (on_sep_line && which_button == MOUSE_LEFT)
1801b20b9e14SBram Moolenaar     {
1802b20b9e14SBram Moolenaar 	if (dragwin != NULL)
1803b20b9e14SBram Moolenaar 	{
1804b20b9e14SBram Moolenaar 	    // Drag the separator column
1805b20b9e14SBram Moolenaar 	    count = col - dragwin->w_wincol - dragwin->w_width + 1
1806b20b9e14SBram Moolenaar 								- on_sep_line;
1807b20b9e14SBram Moolenaar 	    win_drag_vsep_line(dragwin, count);
1808b20b9e14SBram Moolenaar 	    did_drag |= count;
1809b20b9e14SBram Moolenaar 	}
1810b20b9e14SBram Moolenaar 	return IN_SEP_LINE;			// Cursor didn't move
1811b20b9e14SBram Moolenaar     }
1812b20b9e14SBram Moolenaar #ifdef FEAT_MENU
1813b20b9e14SBram Moolenaar     else if (in_winbar)
1814b20b9e14SBram Moolenaar     {
1815b20b9e14SBram Moolenaar 	// After a click on the window toolbar don't start Visual mode.
1816b20b9e14SBram Moolenaar 	return IN_OTHER_WIN | MOUSE_WINBAR;
1817b20b9e14SBram Moolenaar     }
1818b20b9e14SBram Moolenaar #endif
1819b20b9e14SBram Moolenaar     else // keep_window_focus must be TRUE
1820b20b9e14SBram Moolenaar     {
1821b20b9e14SBram Moolenaar 	// before moving the cursor for a left click, stop Visual mode
1822b20b9e14SBram Moolenaar 	if (flags & MOUSE_MAY_STOP_VIS)
1823b20b9e14SBram Moolenaar 	{
1824*4f3c57f7SBram Moolenaar 	    end_visual_mode_keep_button();
1825b20b9e14SBram Moolenaar 	    redraw_curbuf_later(INVERTED);	// delete the inversion
1826b20b9e14SBram Moolenaar 	}
1827b20b9e14SBram Moolenaar 
1828b20b9e14SBram Moolenaar #if defined(FEAT_CMDWIN) && defined(FEAT_CLIPBOARD)
1829b20b9e14SBram Moolenaar 	// Continue a modeless selection in another window.
1830b20b9e14SBram Moolenaar 	if (cmdwin_type != 0 && row < curwin->w_winrow)
1831b20b9e14SBram Moolenaar 	    return IN_OTHER_WIN;
1832b20b9e14SBram Moolenaar #endif
183305ad5ff0SBram Moolenaar #ifdef FEAT_PROP_POPUP
1834b20b9e14SBram Moolenaar 	if (in_popup_win)
1835b20b9e14SBram Moolenaar 	{
1836b20b9e14SBram Moolenaar 	    if (popup_dragwin != NULL)
1837b20b9e14SBram Moolenaar 	    {
1838b20b9e14SBram Moolenaar 		// dragging a popup window
1839b20b9e14SBram Moolenaar 		popup_drag(popup_dragwin);
1840b20b9e14SBram Moolenaar 		return IN_UNKNOWN;
1841b20b9e14SBram Moolenaar 	    }
1842b20b9e14SBram Moolenaar 	    // continue a modeless selection in a popup window
1843b20b9e14SBram Moolenaar 	    click_in_popup_win = NULL;
1844b20b9e14SBram Moolenaar 	    return IN_OTHER_WIN;
1845b20b9e14SBram Moolenaar 	}
1846b20b9e14SBram Moolenaar #endif
1847b20b9e14SBram Moolenaar 
1848b20b9e14SBram Moolenaar 	row -= W_WINROW(curwin);
1849b20b9e14SBram Moolenaar 	col -= curwin->w_wincol;
1850b20b9e14SBram Moolenaar 
1851b20b9e14SBram Moolenaar 	// When clicking beyond the end of the window, scroll the screen.
1852b20b9e14SBram Moolenaar 	// Scroll by however many rows outside the window we are.
1853b20b9e14SBram Moolenaar 	if (row < 0)
1854b20b9e14SBram Moolenaar 	{
1855b20b9e14SBram Moolenaar 	    count = 0;
1856b20b9e14SBram Moolenaar 	    for (first = TRUE; curwin->w_topline > 1; )
1857b20b9e14SBram Moolenaar 	    {
1858b20b9e14SBram Moolenaar #ifdef FEAT_DIFF
1859b20b9e14SBram Moolenaar 		if (curwin->w_topfill < diff_check(curwin, curwin->w_topline))
1860b20b9e14SBram Moolenaar 		    ++count;
1861b20b9e14SBram Moolenaar 		else
1862b20b9e14SBram Moolenaar #endif
1863b20b9e14SBram Moolenaar 		    count += plines(curwin->w_topline - 1);
1864b20b9e14SBram Moolenaar 		if (!first && count > -row)
1865b20b9e14SBram Moolenaar 		    break;
1866b20b9e14SBram Moolenaar 		first = FALSE;
1867b20b9e14SBram Moolenaar #ifdef FEAT_FOLDING
1868b20b9e14SBram Moolenaar 		(void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
1869b20b9e14SBram Moolenaar #endif
1870b20b9e14SBram Moolenaar #ifdef FEAT_DIFF
1871b20b9e14SBram Moolenaar 		if (curwin->w_topfill < diff_check(curwin, curwin->w_topline))
1872b20b9e14SBram Moolenaar 		    ++curwin->w_topfill;
1873b20b9e14SBram Moolenaar 		else
1874b20b9e14SBram Moolenaar #endif
1875b20b9e14SBram Moolenaar 		{
1876b20b9e14SBram Moolenaar 		    --curwin->w_topline;
1877b20b9e14SBram Moolenaar #ifdef FEAT_DIFF
1878b20b9e14SBram Moolenaar 		    curwin->w_topfill = 0;
1879b20b9e14SBram Moolenaar #endif
1880b20b9e14SBram Moolenaar 		}
1881b20b9e14SBram Moolenaar 	    }
1882b20b9e14SBram Moolenaar #ifdef FEAT_DIFF
1883b20b9e14SBram Moolenaar 	    check_topfill(curwin, FALSE);
1884b20b9e14SBram Moolenaar #endif
1885b20b9e14SBram Moolenaar 	    curwin->w_valid &=
1886b20b9e14SBram Moolenaar 		      ~(VALID_WROW|VALID_CROW|VALID_BOTLINE|VALID_BOTLINE_AP);
1887b20b9e14SBram Moolenaar 	    redraw_later(VALID);
1888b20b9e14SBram Moolenaar 	    row = 0;
1889b20b9e14SBram Moolenaar 	}
1890b20b9e14SBram Moolenaar 	else if (row >= curwin->w_height)
1891b20b9e14SBram Moolenaar 	{
1892b20b9e14SBram Moolenaar 	    count = 0;
1893b20b9e14SBram Moolenaar 	    for (first = TRUE; curwin->w_topline < curbuf->b_ml.ml_line_count; )
1894b20b9e14SBram Moolenaar 	    {
1895b20b9e14SBram Moolenaar #ifdef FEAT_DIFF
1896b20b9e14SBram Moolenaar 		if (curwin->w_topfill > 0)
1897b20b9e14SBram Moolenaar 		    ++count;
1898b20b9e14SBram Moolenaar 		else
1899b20b9e14SBram Moolenaar #endif
1900b20b9e14SBram Moolenaar 		    count += plines(curwin->w_topline);
1901b20b9e14SBram Moolenaar 		if (!first && count > row - curwin->w_height + 1)
1902b20b9e14SBram Moolenaar 		    break;
1903b20b9e14SBram Moolenaar 		first = FALSE;
1904b20b9e14SBram Moolenaar #ifdef FEAT_FOLDING
1905b20b9e14SBram Moolenaar 		if (hasFolding(curwin->w_topline, NULL, &curwin->w_topline)
1906b20b9e14SBram Moolenaar 			&& curwin->w_topline == curbuf->b_ml.ml_line_count)
1907b20b9e14SBram Moolenaar 		    break;
1908b20b9e14SBram Moolenaar #endif
1909b20b9e14SBram Moolenaar #ifdef FEAT_DIFF
1910b20b9e14SBram Moolenaar 		if (curwin->w_topfill > 0)
1911b20b9e14SBram Moolenaar 		    --curwin->w_topfill;
1912b20b9e14SBram Moolenaar 		else
1913b20b9e14SBram Moolenaar #endif
1914b20b9e14SBram Moolenaar 		{
1915b20b9e14SBram Moolenaar 		    ++curwin->w_topline;
1916b20b9e14SBram Moolenaar #ifdef FEAT_DIFF
1917b20b9e14SBram Moolenaar 		    curwin->w_topfill =
1918b20b9e14SBram Moolenaar 				   diff_check_fill(curwin, curwin->w_topline);
1919b20b9e14SBram Moolenaar #endif
1920b20b9e14SBram Moolenaar 		}
1921b20b9e14SBram Moolenaar 	    }
1922b20b9e14SBram Moolenaar #ifdef FEAT_DIFF
1923b20b9e14SBram Moolenaar 	    check_topfill(curwin, FALSE);
1924b20b9e14SBram Moolenaar #endif
1925b20b9e14SBram Moolenaar 	    redraw_later(VALID);
1926b20b9e14SBram Moolenaar 	    curwin->w_valid &=
1927b20b9e14SBram Moolenaar 		      ~(VALID_WROW|VALID_CROW|VALID_BOTLINE|VALID_BOTLINE_AP);
1928b20b9e14SBram Moolenaar 	    row = curwin->w_height - 1;
1929b20b9e14SBram Moolenaar 	}
1930b20b9e14SBram Moolenaar 	else if (row == 0)
1931b20b9e14SBram Moolenaar 	{
1932b20b9e14SBram Moolenaar 	    // When dragging the mouse, while the text has been scrolled up as
1933b20b9e14SBram Moolenaar 	    // far as it goes, moving the mouse in the top line should scroll
1934b20b9e14SBram Moolenaar 	    // the text down (done later when recomputing w_topline).
1935b20b9e14SBram Moolenaar 	    if (mouse_dragging > 0
1936b20b9e14SBram Moolenaar 		    && curwin->w_cursor.lnum
1937b20b9e14SBram Moolenaar 				       == curwin->w_buffer->b_ml.ml_line_count
1938b20b9e14SBram Moolenaar 		    && curwin->w_cursor.lnum == curwin->w_topline)
1939b20b9e14SBram Moolenaar 		curwin->w_valid &= ~(VALID_TOPLINE);
1940b20b9e14SBram Moolenaar 	}
1941b20b9e14SBram Moolenaar     }
1942b20b9e14SBram Moolenaar 
1943b20b9e14SBram Moolenaar #ifdef FEAT_FOLDING
1944b20b9e14SBram Moolenaar     // Check for position outside of the fold column.
1945b20b9e14SBram Moolenaar     if (
1946b20b9e14SBram Moolenaar # ifdef FEAT_RIGHTLEFT
1947b20b9e14SBram Moolenaar 	    curwin->w_p_rl ? col < curwin->w_width - curwin->w_p_fdc :
1948b20b9e14SBram Moolenaar # endif
1949b20b9e14SBram Moolenaar 	    col >= curwin->w_p_fdc
1950b20b9e14SBram Moolenaar #  ifdef FEAT_CMDWIN
1951b20b9e14SBram Moolenaar 				+ (cmdwin_type == 0 ? 0 : 1)
1952b20b9e14SBram Moolenaar #  endif
1953b20b9e14SBram Moolenaar        )
1954b20b9e14SBram Moolenaar 	mouse_char = ' ';
1955b20b9e14SBram Moolenaar #endif
1956b20b9e14SBram Moolenaar 
1957b20b9e14SBram Moolenaar     // compute the position in the buffer line from the posn on the screen
1958b20b9e14SBram Moolenaar     if (mouse_comp_pos(curwin, &row, &col, &curwin->w_cursor.lnum, NULL))
1959b20b9e14SBram Moolenaar 	mouse_past_bottom = TRUE;
1960b20b9e14SBram Moolenaar 
1961b20b9e14SBram Moolenaar     // Start Visual mode before coladvance(), for when 'sel' != "old"
1962b20b9e14SBram Moolenaar     if ((flags & MOUSE_MAY_VIS) && !VIsual_active)
1963b20b9e14SBram Moolenaar     {
1964b20b9e14SBram Moolenaar 	check_visual_highlight();
1965b20b9e14SBram Moolenaar 	VIsual = old_cursor;
1966b20b9e14SBram Moolenaar 	VIsual_active = TRUE;
1967b20b9e14SBram Moolenaar 	VIsual_reselect = TRUE;
1968b20b9e14SBram Moolenaar 	// if 'selectmode' contains "mouse", start Select mode
1969b20b9e14SBram Moolenaar 	may_start_select('o');
1970b20b9e14SBram Moolenaar 	setmouse();
1971b20b9e14SBram Moolenaar 	if (p_smd && msg_silent == 0)
1972b20b9e14SBram Moolenaar 	    redraw_cmdline = TRUE;	// show visual mode later
1973b20b9e14SBram Moolenaar     }
1974b20b9e14SBram Moolenaar 
1975b20b9e14SBram Moolenaar     curwin->w_curswant = col;
1976b20b9e14SBram Moolenaar     curwin->w_set_curswant = FALSE;	// May still have been TRUE
1977b20b9e14SBram Moolenaar     if (coladvance(col) == FAIL)	// Mouse click beyond end of line
1978b20b9e14SBram Moolenaar     {
1979b20b9e14SBram Moolenaar 	if (inclusive != NULL)
1980b20b9e14SBram Moolenaar 	    *inclusive = TRUE;
1981b20b9e14SBram Moolenaar 	mouse_past_eol = TRUE;
1982b20b9e14SBram Moolenaar     }
1983b20b9e14SBram Moolenaar     else if (inclusive != NULL)
1984b20b9e14SBram Moolenaar 	*inclusive = FALSE;
1985b20b9e14SBram Moolenaar 
1986b20b9e14SBram Moolenaar     count = IN_BUFFER;
1987b20b9e14SBram Moolenaar     if (curwin != old_curwin || curwin->w_cursor.lnum != old_cursor.lnum
1988b20b9e14SBram Moolenaar 	    || curwin->w_cursor.col != old_cursor.col)
1989b20b9e14SBram Moolenaar 	count |= CURSOR_MOVED;		// Cursor has moved
1990b20b9e14SBram Moolenaar 
1991b20b9e14SBram Moolenaar # ifdef FEAT_FOLDING
19923aca5a6fSBram Moolenaar     if (mouse_char == fill_foldclosed)
1993b20b9e14SBram Moolenaar 	count |= MOUSE_FOLD_OPEN;
1994b20b9e14SBram Moolenaar     else if (mouse_char != ' ')
1995b20b9e14SBram Moolenaar 	count |= MOUSE_FOLD_CLOSE;
1996b20b9e14SBram Moolenaar # endif
1997b20b9e14SBram Moolenaar 
1998b20b9e14SBram Moolenaar     return count;
1999b20b9e14SBram Moolenaar }
2000b20b9e14SBram Moolenaar 
2001b20b9e14SBram Moolenaar /*
2002b20b9e14SBram Moolenaar  * Mouse scroll wheel: Default action is to scroll three lines, or one page
2003b20b9e14SBram Moolenaar  * when Shift or Ctrl is used.
2004b20b9e14SBram Moolenaar  * K_MOUSEUP (cap->arg == 1) or K_MOUSEDOWN (cap->arg == 0) or
2005b20b9e14SBram Moolenaar  * K_MOUSELEFT (cap->arg == -1) or K_MOUSERIGHT (cap->arg == -2)
2006b20b9e14SBram Moolenaar  */
2007b20b9e14SBram Moolenaar     void
nv_mousescroll(cmdarg_T * cap)2008b20b9e14SBram Moolenaar nv_mousescroll(cmdarg_T *cap)
2009b20b9e14SBram Moolenaar {
2010b20b9e14SBram Moolenaar     win_T *old_curwin = curwin, *wp;
2011b20b9e14SBram Moolenaar 
2012b20b9e14SBram Moolenaar     if (mouse_row >= 0 && mouse_col >= 0)
2013b20b9e14SBram Moolenaar     {
2014b20b9e14SBram Moolenaar 	int row, col;
2015b20b9e14SBram Moolenaar 
2016b20b9e14SBram Moolenaar 	row = mouse_row;
2017b20b9e14SBram Moolenaar 	col = mouse_col;
2018b20b9e14SBram Moolenaar 
2019b20b9e14SBram Moolenaar 	// find the window at the pointer coordinates
2020b20b9e14SBram Moolenaar 	wp = mouse_find_win(&row, &col, FIND_POPUP);
2021b20b9e14SBram Moolenaar 	if (wp == NULL)
2022b20b9e14SBram Moolenaar 	    return;
202305ad5ff0SBram Moolenaar #ifdef FEAT_PROP_POPUP
2024b20b9e14SBram Moolenaar 	if (WIN_IS_POPUP(wp) && !wp->w_has_scrollbar)
2025b20b9e14SBram Moolenaar 	    return;
2026b20b9e14SBram Moolenaar #endif
2027b20b9e14SBram Moolenaar 	curwin = wp;
2028b20b9e14SBram Moolenaar 	curbuf = curwin->w_buffer;
2029b20b9e14SBram Moolenaar     }
2030b20b9e14SBram Moolenaar 
2031b20b9e14SBram Moolenaar     if (cap->arg == MSCR_UP || cap->arg == MSCR_DOWN)
2032b20b9e14SBram Moolenaar     {
2033b20b9e14SBram Moolenaar # ifdef FEAT_TERMINAL
2034b20b9e14SBram Moolenaar 	if (term_use_loop())
2035b20b9e14SBram Moolenaar 	    // This window is a terminal window, send the mouse event there.
2036b20b9e14SBram Moolenaar 	    // Set "typed" to FALSE to avoid an endless loop.
20371e814bc0SBram Moolenaar 	    send_keys_to_term(curbuf->b_term, cap->cmdchar, mod_mask, FALSE);
2038b20b9e14SBram Moolenaar 	else
2039b20b9e14SBram Moolenaar # endif
2040b20b9e14SBram Moolenaar 	if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))
2041b20b9e14SBram Moolenaar 	{
2042b20b9e14SBram Moolenaar 	    (void)onepage(cap->arg ? FORWARD : BACKWARD, 1L);
2043b20b9e14SBram Moolenaar 	}
2044b20b9e14SBram Moolenaar 	else
2045b20b9e14SBram Moolenaar 	{
2046b20b9e14SBram Moolenaar 	    // Don't scroll more than half the window height.
2047b20b9e14SBram Moolenaar 	    if (curwin->w_height < 6)
2048b20b9e14SBram Moolenaar 	    {
2049b20b9e14SBram Moolenaar 		cap->count1 = curwin->w_height / 2;
2050b20b9e14SBram Moolenaar 		if (cap->count1 == 0)
2051b20b9e14SBram Moolenaar 		    cap->count1 = 1;
2052b20b9e14SBram Moolenaar 	    }
2053b20b9e14SBram Moolenaar 	    else
2054b20b9e14SBram Moolenaar 		cap->count1 = 3;
2055b20b9e14SBram Moolenaar 	    cap->count0 = cap->count1;
2056b20b9e14SBram Moolenaar 	    nv_scroll_line(cap);
2057b20b9e14SBram Moolenaar 	}
205805ad5ff0SBram Moolenaar #ifdef FEAT_PROP_POPUP
2059b20b9e14SBram Moolenaar 	if (WIN_IS_POPUP(curwin))
2060b20b9e14SBram Moolenaar 	    popup_set_firstline(curwin);
2061b20b9e14SBram Moolenaar #endif
2062b20b9e14SBram Moolenaar     }
2063b20b9e14SBram Moolenaar # ifdef FEAT_GUI
2064b20b9e14SBram Moolenaar     else
2065b20b9e14SBram Moolenaar     {
2066b20b9e14SBram Moolenaar 	// Horizontal scroll - only allowed when 'wrap' is disabled
2067b20b9e14SBram Moolenaar 	if (!curwin->w_p_wrap)
2068b20b9e14SBram Moolenaar 	{
2069b20b9e14SBram Moolenaar 	    int val, step = 6;
2070b20b9e14SBram Moolenaar 
2071b20b9e14SBram Moolenaar 	    if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))
2072b20b9e14SBram Moolenaar 		step = curwin->w_width;
2073b20b9e14SBram Moolenaar 	    val = curwin->w_leftcol + (cap->arg == MSCR_RIGHT ? -step : +step);
2074b20b9e14SBram Moolenaar 	    if (val < 0)
2075b20b9e14SBram Moolenaar 		val = 0;
2076b20b9e14SBram Moolenaar 
2077b20b9e14SBram Moolenaar 	    gui_do_horiz_scroll(val, TRUE);
2078b20b9e14SBram Moolenaar 	}
2079b20b9e14SBram Moolenaar     }
2080b20b9e14SBram Moolenaar # endif
2081b20b9e14SBram Moolenaar # ifdef FEAT_SYN_HL
2082b20b9e14SBram Moolenaar     if (curwin != old_curwin && curwin->w_p_cul)
2083b20b9e14SBram Moolenaar 	redraw_for_cursorline(curwin);
2084b20b9e14SBram Moolenaar # endif
2085b20b9e14SBram Moolenaar 
2086b20b9e14SBram Moolenaar     curwin->w_redr_status = TRUE;
2087b20b9e14SBram Moolenaar 
2088b20b9e14SBram Moolenaar     curwin = old_curwin;
2089b20b9e14SBram Moolenaar     curbuf = curwin->w_buffer;
2090b20b9e14SBram Moolenaar }
2091b20b9e14SBram Moolenaar 
2092b20b9e14SBram Moolenaar /*
2093b20b9e14SBram Moolenaar  * Mouse clicks and drags.
2094b20b9e14SBram Moolenaar  */
2095b20b9e14SBram Moolenaar     void
nv_mouse(cmdarg_T * cap)2096b20b9e14SBram Moolenaar nv_mouse(cmdarg_T *cap)
2097b20b9e14SBram Moolenaar {
2098b20b9e14SBram Moolenaar     (void)do_mouse(cap->oap, cap->cmdchar, BACKWARD, cap->count1, 0);
2099b20b9e14SBram Moolenaar }
2100b8ff5c27SBram Moolenaar 
210185eee5b9SBram Moolenaar static int	held_button = MOUSE_RELEASE;
210285eee5b9SBram Moolenaar 
210385eee5b9SBram Moolenaar     void
reset_held_button()210485eee5b9SBram Moolenaar reset_held_button()
210585eee5b9SBram Moolenaar {
210685eee5b9SBram Moolenaar     held_button = MOUSE_RELEASE;
210785eee5b9SBram Moolenaar }
210885eee5b9SBram Moolenaar 
2109b8ff5c27SBram Moolenaar /*
2110b8ff5c27SBram Moolenaar  * Check if typebuf 'tp' contains a terminal mouse code and returns the
2111b8ff5c27SBram Moolenaar  * modifiers found in typebuf in 'modifiers'.
2112b8ff5c27SBram Moolenaar  */
2113b8ff5c27SBram Moolenaar     int
check_termcode_mouse(char_u * tp,int * slen,char_u * key_name,char_u * modifiers_start,int idx,int * modifiers)2114b8ff5c27SBram Moolenaar check_termcode_mouse(
2115b8ff5c27SBram Moolenaar     char_u	*tp,
2116b8ff5c27SBram Moolenaar     int		*slen,
2117b8ff5c27SBram Moolenaar     char_u	*key_name,
2118b8ff5c27SBram Moolenaar     char_u	*modifiers_start,
2119b8ff5c27SBram Moolenaar     int		idx,
2120b8ff5c27SBram Moolenaar     int		*modifiers)
2121b8ff5c27SBram Moolenaar {
2122b8ff5c27SBram Moolenaar     int		j;
2123b8ff5c27SBram Moolenaar     char_u	*p;
2124b8ff5c27SBram Moolenaar # if !defined(UNIX) || defined(FEAT_MOUSE_XTERM) || defined(FEAT_GUI) \
2125b8ff5c27SBram Moolenaar     || defined(FEAT_MOUSE_GPM) || defined(FEAT_SYSMOUSE)
2126b8ff5c27SBram Moolenaar     char_u	bytes[6];
2127b8ff5c27SBram Moolenaar     int		num_bytes;
2128b8ff5c27SBram Moolenaar # endif
2129b8ff5c27SBram Moolenaar     int		mouse_code = 0;	    // init for GCC
2130b8ff5c27SBram Moolenaar     int		is_click, is_drag;
2131d58d4f90SBram Moolenaar     int		is_release, release_is_ambiguous;
2132b8ff5c27SBram Moolenaar     int		wheel_code = 0;
2133b8ff5c27SBram Moolenaar     int		current_button;
2134b8ff5c27SBram Moolenaar     static int	orig_num_clicks = 1;
2135b8ff5c27SBram Moolenaar     static int	orig_mouse_code = 0x0;
2136b8ff5c27SBram Moolenaar # ifdef CHECK_DOUBLE_CLICK
2137b8ff5c27SBram Moolenaar     static int	orig_mouse_col = 0;
2138b8ff5c27SBram Moolenaar     static int	orig_mouse_row = 0;
2139b8ff5c27SBram Moolenaar     static struct timeval  orig_mouse_time = {0, 0};
2140b8ff5c27SBram Moolenaar     // time of previous mouse click
2141b8ff5c27SBram Moolenaar     struct timeval  mouse_time;		// time of current mouse click
2142b8ff5c27SBram Moolenaar     long	timediff;		// elapsed time in msec
2143b8ff5c27SBram Moolenaar # endif
2144b8ff5c27SBram Moolenaar 
2145d58d4f90SBram Moolenaar     is_click = is_drag = is_release = release_is_ambiguous = FALSE;
2146b8ff5c27SBram Moolenaar 
2147b8ff5c27SBram Moolenaar # if !defined(UNIX) || defined(FEAT_MOUSE_XTERM) || defined(FEAT_GUI) \
2148b8ff5c27SBram Moolenaar     || defined(FEAT_MOUSE_GPM) || defined(FEAT_SYSMOUSE)
2149b8ff5c27SBram Moolenaar     if (key_name[0] == KS_MOUSE
2150b8ff5c27SBram Moolenaar #  ifdef FEAT_MOUSE_GPM
2151b8ff5c27SBram Moolenaar 	    || key_name[0] == KS_GPM_MOUSE
2152b8ff5c27SBram Moolenaar #  endif
2153b8ff5c27SBram Moolenaar        )
2154b8ff5c27SBram Moolenaar     {
2155b8ff5c27SBram Moolenaar 	/*
215613c04631SBram Moolenaar 	 * For xterm we get "<t_mouse>scr", where s == encoded button state:
2157b8ff5c27SBram Moolenaar 	 *	   0x20 = left button down
2158b8ff5c27SBram Moolenaar 	 *	   0x21 = middle button down
2159b8ff5c27SBram Moolenaar 	 *	   0x22 = right button down
2160b8ff5c27SBram Moolenaar 	 *	   0x23 = any button release
2161b8ff5c27SBram Moolenaar 	 *	   0x60 = button 4 down (scroll wheel down)
2162b8ff5c27SBram Moolenaar 	 *	   0x61 = button 5 down (scroll wheel up)
2163b8ff5c27SBram Moolenaar 	 *	add 0x04 for SHIFT
2164b8ff5c27SBram Moolenaar 	 *	add 0x08 for ALT
2165b8ff5c27SBram Moolenaar 	 *	add 0x10 for CTRL
2166b8ff5c27SBram Moolenaar 	 *	add 0x20 for mouse drag (0x40 is drag with left button)
2167b8ff5c27SBram Moolenaar 	 *	add 0x40 for mouse move (0x80 is move, 0x81 too)
2168b8ff5c27SBram Moolenaar 	 *		 0x43 (drag + release) is also move
2169b8ff5c27SBram Moolenaar 	 *  c == column + ' ' + 1 == column + 33
2170b8ff5c27SBram Moolenaar 	 *  r == row + ' ' + 1 == row + 33
2171b8ff5c27SBram Moolenaar 	 *
217213c04631SBram Moolenaar 	 * The coordinates are passed on through global variables.  Ugly, but
217313c04631SBram Moolenaar 	 * this avoids trouble with mouse clicks at an unexpected moment and
217413c04631SBram Moolenaar 	 * allows for mapping them.
2175b8ff5c27SBram Moolenaar 	 */
2176b8ff5c27SBram Moolenaar 	for (;;)
2177b8ff5c27SBram Moolenaar 	{
2178b8ff5c27SBram Moolenaar #  ifdef FEAT_GUI
2179b8ff5c27SBram Moolenaar 	    if (gui.in_use)
2180b8ff5c27SBram Moolenaar 	    {
2181b8ff5c27SBram Moolenaar 		// GUI uses more bits for columns > 223
2182b8ff5c27SBram Moolenaar 		num_bytes = get_bytes_from_buf(tp + *slen, bytes, 5);
2183b8ff5c27SBram Moolenaar 		if (num_bytes == -1)	// not enough coordinates
2184b8ff5c27SBram Moolenaar 		    return -1;
2185b8ff5c27SBram Moolenaar 		mouse_code = bytes[0];
2186b8ff5c27SBram Moolenaar 		mouse_col = 128 * (bytes[1] - ' ' - 1)
2187b8ff5c27SBram Moolenaar 		    + bytes[2] - ' ' - 1;
2188b8ff5c27SBram Moolenaar 		mouse_row = 128 * (bytes[3] - ' ' - 1)
2189b8ff5c27SBram Moolenaar 		    + bytes[4] - ' ' - 1;
2190b8ff5c27SBram Moolenaar 	    }
2191b8ff5c27SBram Moolenaar 	    else
2192b8ff5c27SBram Moolenaar #  endif
2193b8ff5c27SBram Moolenaar 	    {
2194b8ff5c27SBram Moolenaar 		num_bytes = get_bytes_from_buf(tp + *slen, bytes, 3);
2195b8ff5c27SBram Moolenaar 		if (num_bytes == -1)	// not enough coordinates
2196b8ff5c27SBram Moolenaar 		    return -1;
2197b8ff5c27SBram Moolenaar 		mouse_code = bytes[0];
2198b8ff5c27SBram Moolenaar 		mouse_col = bytes[1] - ' ' - 1;
2199b8ff5c27SBram Moolenaar 		mouse_row = bytes[2] - ' ' - 1;
2200b8ff5c27SBram Moolenaar 	    }
2201b8ff5c27SBram Moolenaar 	    *slen += num_bytes;
2202b8ff5c27SBram Moolenaar 
220313c04631SBram Moolenaar 	    // If the following bytes is also a mouse code and it has the same
220413c04631SBram Moolenaar 	    // code, dump this one and get the next.  This makes dragging a
220513c04631SBram Moolenaar 	    // whole lot faster.
2206b8ff5c27SBram Moolenaar #  ifdef FEAT_GUI
2207b8ff5c27SBram Moolenaar 	    if (gui.in_use)
2208b8ff5c27SBram Moolenaar 		j = 3;
2209b8ff5c27SBram Moolenaar 	    else
2210b8ff5c27SBram Moolenaar #  endif
2211b8ff5c27SBram Moolenaar 		j = get_termcode_len(idx);
2212b8ff5c27SBram Moolenaar 	    if (STRNCMP(tp, tp + *slen, (size_t)j) == 0
2213b8ff5c27SBram Moolenaar 		    && tp[*slen + j] == mouse_code
2214b8ff5c27SBram Moolenaar 		    && tp[*slen + j + 1] != NUL
2215b8ff5c27SBram Moolenaar 		    && tp[*slen + j + 2] != NUL
2216b8ff5c27SBram Moolenaar #  ifdef FEAT_GUI
2217b8ff5c27SBram Moolenaar 		    && (!gui.in_use
2218b8ff5c27SBram Moolenaar 			|| (tp[*slen + j + 3] != NUL
2219b8ff5c27SBram Moolenaar 			    && tp[*slen + j + 4] != NUL))
2220b8ff5c27SBram Moolenaar #  endif
2221b8ff5c27SBram Moolenaar 	       )
2222b8ff5c27SBram Moolenaar 		*slen += j;
2223b8ff5c27SBram Moolenaar 	    else
2224b8ff5c27SBram Moolenaar 		break;
2225b8ff5c27SBram Moolenaar 	}
2226b8ff5c27SBram Moolenaar     }
2227b8ff5c27SBram Moolenaar 
2228b8ff5c27SBram Moolenaar     if (key_name[0] == KS_URXVT_MOUSE
2229b8ff5c27SBram Moolenaar 	    || key_name[0] == KS_SGR_MOUSE
2230b8ff5c27SBram Moolenaar 	    || key_name[0] == KS_SGR_MOUSE_RELEASE)
2231b8ff5c27SBram Moolenaar     {
2232b8ff5c27SBram Moolenaar 	// URXVT 1015 mouse reporting mode:
223313c04631SBram Moolenaar 	// Almost identical to xterm mouse mode, except the values are decimal
223413c04631SBram Moolenaar 	// instead of bytes.
2235b8ff5c27SBram Moolenaar 	//
2236b8ff5c27SBram Moolenaar 	// \033[%d;%d;%dM
2237b8ff5c27SBram Moolenaar 	//	       ^-- row
2238b8ff5c27SBram Moolenaar 	//	    ^----- column
2239b8ff5c27SBram Moolenaar 	//	 ^-------- code
2240b8ff5c27SBram Moolenaar 	//
2241b8ff5c27SBram Moolenaar 	// SGR 1006 mouse reporting mode:
224213c04631SBram Moolenaar 	// Almost identical to xterm mouse mode, except the values are decimal
224313c04631SBram Moolenaar 	// instead of bytes.
2244b8ff5c27SBram Moolenaar 	//
2245b8ff5c27SBram Moolenaar 	// \033[<%d;%d;%dM
2246b8ff5c27SBram Moolenaar 	//	       ^-- row
2247b8ff5c27SBram Moolenaar 	//	    ^----- column
2248b8ff5c27SBram Moolenaar 	//	 ^-------- code
2249b8ff5c27SBram Moolenaar 	//
2250b8ff5c27SBram Moolenaar 	// \033[<%d;%d;%dm        : mouse release event
2251b8ff5c27SBram Moolenaar 	//	       ^-- row
2252b8ff5c27SBram Moolenaar 	//	    ^----- column
2253b8ff5c27SBram Moolenaar 	//	 ^-------- code
2254b8ff5c27SBram Moolenaar 	p = modifiers_start;
2255b8ff5c27SBram Moolenaar 	if (p == NULL)
2256b8ff5c27SBram Moolenaar 	    return -1;
2257b8ff5c27SBram Moolenaar 
2258b8ff5c27SBram Moolenaar 	mouse_code = getdigits(&p);
2259b8ff5c27SBram Moolenaar 	if (*p++ != ';')
2260b8ff5c27SBram Moolenaar 	    return -1;
2261b8ff5c27SBram Moolenaar 
2262b8ff5c27SBram Moolenaar 	// when mouse reporting is SGR, add 32 to mouse code
2263b8ff5c27SBram Moolenaar 	if (key_name[0] == KS_SGR_MOUSE
2264b8ff5c27SBram Moolenaar 		|| key_name[0] == KS_SGR_MOUSE_RELEASE)
2265b8ff5c27SBram Moolenaar 	    mouse_code += 32;
2266b8ff5c27SBram Moolenaar 
2267b8ff5c27SBram Moolenaar 	mouse_col = getdigits(&p) - 1;
2268b8ff5c27SBram Moolenaar 	if (*p++ != ';')
2269b8ff5c27SBram Moolenaar 	    return -1;
2270b8ff5c27SBram Moolenaar 
2271b8ff5c27SBram Moolenaar 	mouse_row = getdigits(&p) - 1;
2272b8ff5c27SBram Moolenaar 
227313c04631SBram Moolenaar 	// The modifiers were the mouse coordinates, not the modifier keys
227413c04631SBram Moolenaar 	// (alt/shift/ctrl/meta) state.
2275b8ff5c27SBram Moolenaar 	*modifiers = 0;
2276b8ff5c27SBram Moolenaar     }
2277b8ff5c27SBram Moolenaar 
2278d58d4f90SBram Moolenaar     if (key_name[0] == KS_SGR_MOUSE
2279d58d4f90SBram Moolenaar 	    || key_name[0] == KS_SGR_MOUSE_RELEASE)
2280d58d4f90SBram Moolenaar     {
2281d58d4f90SBram Moolenaar 	if (key_name[0] == KS_SGR_MOUSE_RELEASE)
228213c04631SBram Moolenaar 	{
2283d58d4f90SBram Moolenaar 	    is_release = TRUE;
228413c04631SBram Moolenaar 	    // This is used below to set held_button.
228513c04631SBram Moolenaar 	    mouse_code |= MOUSE_RELEASE;
228613c04631SBram Moolenaar 	}
2287d58d4f90SBram Moolenaar     }
2288d58d4f90SBram Moolenaar     else
2289d58d4f90SBram Moolenaar     {
2290d58d4f90SBram Moolenaar 	release_is_ambiguous = TRUE;
2291d58d4f90SBram Moolenaar 	if ((mouse_code & MOUSE_RELEASE) == MOUSE_RELEASE)
2292d58d4f90SBram Moolenaar 	    is_release = TRUE;
2293d58d4f90SBram Moolenaar     }
2294d58d4f90SBram Moolenaar 
2295b8ff5c27SBram Moolenaar     if (key_name[0] == KS_MOUSE
2296b8ff5c27SBram Moolenaar #  ifdef FEAT_MOUSE_GPM
2297b8ff5c27SBram Moolenaar 	    || key_name[0] == KS_GPM_MOUSE
2298b8ff5c27SBram Moolenaar #  endif
2299b8ff5c27SBram Moolenaar #  ifdef FEAT_MOUSE_URXVT
2300b8ff5c27SBram Moolenaar 	    || key_name[0] == KS_URXVT_MOUSE
2301b8ff5c27SBram Moolenaar #  endif
2302b8ff5c27SBram Moolenaar 	    || key_name[0] == KS_SGR_MOUSE
2303b8ff5c27SBram Moolenaar 	    || key_name[0] == KS_SGR_MOUSE_RELEASE)
2304b8ff5c27SBram Moolenaar     {
2305b8ff5c27SBram Moolenaar #  if !defined(MSWIN)
2306b8ff5c27SBram Moolenaar 	/*
230713c04631SBram Moolenaar 	 * Handle old style mouse events.
2308b8ff5c27SBram Moolenaar 	 * Recognize the xterm mouse wheel, but not in the GUI, the
2309b8ff5c27SBram Moolenaar 	 * Linux console with GPM and the MS-DOS or Win32 console
2310b8ff5c27SBram Moolenaar 	 * (multi-clicks use >= 0x60).
2311b8ff5c27SBram Moolenaar 	 */
2312b8ff5c27SBram Moolenaar 	if (mouse_code >= MOUSEWHEEL_LOW
2313b8ff5c27SBram Moolenaar #   ifdef FEAT_GUI
2314b8ff5c27SBram Moolenaar 		&& !gui.in_use
2315b8ff5c27SBram Moolenaar #   endif
2316b8ff5c27SBram Moolenaar #   ifdef FEAT_MOUSE_GPM
2317b8ff5c27SBram Moolenaar 		&& key_name[0] != KS_GPM_MOUSE
2318b8ff5c27SBram Moolenaar #   endif
2319b8ff5c27SBram Moolenaar 	   )
2320b8ff5c27SBram Moolenaar 	{
2321a1cb1d1dSBram Moolenaar #   if defined(UNIX)
2322b8ff5c27SBram Moolenaar 	    if (use_xterm_mouse() > 1 && mouse_code >= 0x80)
2323b8ff5c27SBram Moolenaar 		// mouse-move event, using MOUSE_DRAG works
2324b8ff5c27SBram Moolenaar 		mouse_code = MOUSE_DRAG;
2325b8ff5c27SBram Moolenaar 	    else
2326b8ff5c27SBram Moolenaar #   endif
2327b8ff5c27SBram Moolenaar 		// Keep the mouse_code before it's changed, so that we
2328b8ff5c27SBram Moolenaar 		// remember that it was a mouse wheel click.
2329b8ff5c27SBram Moolenaar 		wheel_code = mouse_code;
2330b8ff5c27SBram Moolenaar 	}
2331b8ff5c27SBram Moolenaar #   ifdef FEAT_MOUSE_XTERM
2332b8ff5c27SBram Moolenaar 	else if (held_button == MOUSE_RELEASE
2333b8ff5c27SBram Moolenaar #    ifdef FEAT_GUI
2334b8ff5c27SBram Moolenaar 		&& !gui.in_use
2335b8ff5c27SBram Moolenaar #    endif
2336b8ff5c27SBram Moolenaar 		&& (mouse_code == 0x23 || mouse_code == 0x24
2337b8ff5c27SBram Moolenaar 		    || mouse_code == 0x40 || mouse_code == 0x41))
2338b8ff5c27SBram Moolenaar 	{
2339b8ff5c27SBram Moolenaar 	    // Apparently 0x23 and 0x24 are used by rxvt scroll wheel.
2340b8ff5c27SBram Moolenaar 	    // And 0x40 and 0x41 are used by some xterm emulator.
2341b8ff5c27SBram Moolenaar 	    wheel_code = mouse_code - (mouse_code >= 0x40 ? 0x40 : 0x23)
2342b8ff5c27SBram Moolenaar 		+ MOUSEWHEEL_LOW;
2343b8ff5c27SBram Moolenaar 	}
2344b8ff5c27SBram Moolenaar #   endif
2345b8ff5c27SBram Moolenaar 
2346a1cb1d1dSBram Moolenaar #   if defined(UNIX)
2347b8ff5c27SBram Moolenaar 	else if (use_xterm_mouse() > 1)
2348b8ff5c27SBram Moolenaar 	{
2349b8ff5c27SBram Moolenaar 	    if (mouse_code & MOUSE_DRAG_XTERM)
2350b8ff5c27SBram Moolenaar 		mouse_code |= MOUSE_DRAG;
2351b8ff5c27SBram Moolenaar 	}
2352b8ff5c27SBram Moolenaar #   endif
2353b8ff5c27SBram Moolenaar #   ifdef FEAT_XCLIPBOARD
2354b8ff5c27SBram Moolenaar 	else if (!(mouse_code & MOUSE_DRAG & ~MOUSE_CLICK_MASK))
2355b8ff5c27SBram Moolenaar 	{
2356d58d4f90SBram Moolenaar 	    if (is_release)
2357b8ff5c27SBram Moolenaar 		stop_xterm_trace();
2358b8ff5c27SBram Moolenaar 	    else
2359b8ff5c27SBram Moolenaar 		start_xterm_trace(mouse_code);
2360b8ff5c27SBram Moolenaar 	}
2361b8ff5c27SBram Moolenaar #   endif
2362b8ff5c27SBram Moolenaar #  endif
2363b8ff5c27SBram Moolenaar     }
2364b8ff5c27SBram Moolenaar # endif // !UNIX || FEAT_MOUSE_XTERM
2365b8ff5c27SBram Moolenaar # ifdef FEAT_MOUSE_NET
2366b8ff5c27SBram Moolenaar     if (key_name[0] == KS_NETTERM_MOUSE)
2367b8ff5c27SBram Moolenaar     {
2368b8ff5c27SBram Moolenaar 	int mc, mr;
2369b8ff5c27SBram Moolenaar 
2370b8ff5c27SBram Moolenaar 	// expect a rather limited sequence like: balancing {
2371b8ff5c27SBram Moolenaar 	// \033}6,45\r
2372b8ff5c27SBram Moolenaar 	// '6' is the row, 45 is the column
2373b8ff5c27SBram Moolenaar 	p = tp + *slen;
2374b8ff5c27SBram Moolenaar 	mr = getdigits(&p);
2375b8ff5c27SBram Moolenaar 	if (*p++ != ',')
2376b8ff5c27SBram Moolenaar 	    return -1;
2377b8ff5c27SBram Moolenaar 	mc = getdigits(&p);
2378b8ff5c27SBram Moolenaar 	if (*p++ != '\r')
2379b8ff5c27SBram Moolenaar 	    return -1;
2380b8ff5c27SBram Moolenaar 
2381b8ff5c27SBram Moolenaar 	mouse_col = mc - 1;
2382b8ff5c27SBram Moolenaar 	mouse_row = mr - 1;
2383b8ff5c27SBram Moolenaar 	mouse_code = MOUSE_LEFT;
2384b8ff5c27SBram Moolenaar 	*slen += (int)(p - (tp + *slen));
2385b8ff5c27SBram Moolenaar     }
2386b8ff5c27SBram Moolenaar # endif	// FEAT_MOUSE_NET
2387b8ff5c27SBram Moolenaar # ifdef FEAT_MOUSE_JSB
2388b8ff5c27SBram Moolenaar     if (key_name[0] == KS_JSBTERM_MOUSE)
2389b8ff5c27SBram Moolenaar     {
2390b8ff5c27SBram Moolenaar 	int mult, val, iter, button, status;
2391b8ff5c27SBram Moolenaar 
2392b8ff5c27SBram Moolenaar 	/*
2393b8ff5c27SBram Moolenaar 	 * JSBTERM Input Model
2394b8ff5c27SBram Moolenaar 	 * \033[0~zw uniq escape sequence
2395b8ff5c27SBram Moolenaar 	 * (L-x)  Left button pressed - not pressed x not reporting
2396b8ff5c27SBram Moolenaar 	 * (M-x)  Middle button pressed - not pressed x not reporting
2397b8ff5c27SBram Moolenaar 	 * (R-x)  Right button pressed - not pressed x not reporting
239813c04631SBram Moolenaar 	 * (SDmdu)  Single , Double click, m: mouse move, d: button down,
239913c04631SBram Moolenaar 		      *						   u: button up
2400b8ff5c27SBram Moolenaar 	 *  ###   X cursor position padded to 3 digits
2401b8ff5c27SBram Moolenaar 	 *  ###   Y cursor position padded to 3 digits
2402b8ff5c27SBram Moolenaar 	 * (s-x)  SHIFT key pressed - not pressed x not reporting
2403b8ff5c27SBram Moolenaar 	 * (c-x)  CTRL key pressed - not pressed x not reporting
2404b8ff5c27SBram Moolenaar 	 * \033\\ terminating sequence
2405b8ff5c27SBram Moolenaar 	 */
2406b8ff5c27SBram Moolenaar 	p = tp + *slen;
2407b8ff5c27SBram Moolenaar 	button = mouse_code = 0;
2408b8ff5c27SBram Moolenaar 	switch (*p++)
2409b8ff5c27SBram Moolenaar 	{
2410b8ff5c27SBram Moolenaar 	    case 'L': button = 1; break;
2411b8ff5c27SBram Moolenaar 	    case '-': break;
2412b8ff5c27SBram Moolenaar 	    case 'x': break; // ignore sequence
2413b8ff5c27SBram Moolenaar 	    default:  return -1; // Unknown Result
2414b8ff5c27SBram Moolenaar 	}
2415b8ff5c27SBram Moolenaar 	switch (*p++)
2416b8ff5c27SBram Moolenaar 	{
2417b8ff5c27SBram Moolenaar 	    case 'M': button |= 2; break;
2418b8ff5c27SBram Moolenaar 	    case '-': break;
2419b8ff5c27SBram Moolenaar 	    case 'x': break; // ignore sequence
2420b8ff5c27SBram Moolenaar 	    default:  return -1; // Unknown Result
2421b8ff5c27SBram Moolenaar 	}
2422b8ff5c27SBram Moolenaar 	switch (*p++)
2423b8ff5c27SBram Moolenaar 	{
2424b8ff5c27SBram Moolenaar 	    case 'R': button |= 4; break;
2425b8ff5c27SBram Moolenaar 	    case '-': break;
2426b8ff5c27SBram Moolenaar 	    case 'x': break; // ignore sequence
2427b8ff5c27SBram Moolenaar 	    default:  return -1; // Unknown Result
2428b8ff5c27SBram Moolenaar 	}
2429b8ff5c27SBram Moolenaar 	status = *p++;
2430b8ff5c27SBram Moolenaar 	for (val = 0, mult = 100, iter = 0; iter < 3; iter++,
2431b8ff5c27SBram Moolenaar 		mult /= 10, p++)
2432b8ff5c27SBram Moolenaar 	    if (*p >= '0' && *p <= '9')
2433b8ff5c27SBram Moolenaar 		val += (*p - '0') * mult;
2434b8ff5c27SBram Moolenaar 	    else
2435b8ff5c27SBram Moolenaar 		return -1;
2436b8ff5c27SBram Moolenaar 	mouse_col = val;
2437b8ff5c27SBram Moolenaar 	for (val = 0, mult = 100, iter = 0; iter < 3; iter++,
2438b8ff5c27SBram Moolenaar 		mult /= 10, p++)
2439b8ff5c27SBram Moolenaar 	    if (*p >= '0' && *p <= '9')
2440b8ff5c27SBram Moolenaar 		val += (*p - '0') * mult;
2441b8ff5c27SBram Moolenaar 	    else
2442b8ff5c27SBram Moolenaar 		return -1;
2443b8ff5c27SBram Moolenaar 	mouse_row = val;
2444b8ff5c27SBram Moolenaar 	switch (*p++)
2445b8ff5c27SBram Moolenaar 	{
2446b8ff5c27SBram Moolenaar 	    case 's': button |= 8; break;  // SHIFT key Pressed
2447b8ff5c27SBram Moolenaar 	    case '-': break;  // Not Pressed
2448b8ff5c27SBram Moolenaar 	    case 'x': break;  // Not Reporting
2449b8ff5c27SBram Moolenaar 	    default:  return -1; // Unknown Result
2450b8ff5c27SBram Moolenaar 	}
2451b8ff5c27SBram Moolenaar 	switch (*p++)
2452b8ff5c27SBram Moolenaar 	{
2453b8ff5c27SBram Moolenaar 	    case 'c': button |= 16; break;  // CTRL key Pressed
2454b8ff5c27SBram Moolenaar 	    case '-': break;  // Not Pressed
2455b8ff5c27SBram Moolenaar 	    case 'x': break;  // Not Reporting
2456b8ff5c27SBram Moolenaar 	    default:  return -1; // Unknown Result
2457b8ff5c27SBram Moolenaar 	}
2458b8ff5c27SBram Moolenaar 	if (*p++ != '\033')
2459b8ff5c27SBram Moolenaar 	    return -1;
2460b8ff5c27SBram Moolenaar 	if (*p++ != '\\')
2461b8ff5c27SBram Moolenaar 	    return -1;
2462b8ff5c27SBram Moolenaar 	switch (status)
2463b8ff5c27SBram Moolenaar 	{
2464b8ff5c27SBram Moolenaar 	    case 'D': // Double Click
2465b8ff5c27SBram Moolenaar 	    case 'S': // Single Click
2466b8ff5c27SBram Moolenaar 		if (button & 1) mouse_code |= MOUSE_LEFT;
2467b8ff5c27SBram Moolenaar 		if (button & 2) mouse_code |= MOUSE_MIDDLE;
2468b8ff5c27SBram Moolenaar 		if (button & 4) mouse_code |= MOUSE_RIGHT;
2469b8ff5c27SBram Moolenaar 		if (button & 8) mouse_code |= MOUSE_SHIFT;
2470b8ff5c27SBram Moolenaar 		if (button & 16) mouse_code |= MOUSE_CTRL;
2471b8ff5c27SBram Moolenaar 		break;
2472b8ff5c27SBram Moolenaar 	    case 'm': // Mouse move
2473b8ff5c27SBram Moolenaar 		if (button & 1) mouse_code |= MOUSE_LEFT;
2474b8ff5c27SBram Moolenaar 		if (button & 2) mouse_code |= MOUSE_MIDDLE;
2475b8ff5c27SBram Moolenaar 		if (button & 4) mouse_code |= MOUSE_RIGHT;
2476b8ff5c27SBram Moolenaar 		if (button & 8) mouse_code |= MOUSE_SHIFT;
2477b8ff5c27SBram Moolenaar 		if (button & 16) mouse_code |= MOUSE_CTRL;
2478b8ff5c27SBram Moolenaar 		if ((button & 7) != 0)
2479b8ff5c27SBram Moolenaar 		{
2480b8ff5c27SBram Moolenaar 		    held_button = mouse_code;
2481b8ff5c27SBram Moolenaar 		    mouse_code |= MOUSE_DRAG;
2482b8ff5c27SBram Moolenaar 		}
2483b8ff5c27SBram Moolenaar 		is_drag = TRUE;
2484b8ff5c27SBram Moolenaar 		showmode();
2485b8ff5c27SBram Moolenaar 		break;
2486b8ff5c27SBram Moolenaar 	    case 'd': // Button Down
2487b8ff5c27SBram Moolenaar 		if (button & 1) mouse_code |= MOUSE_LEFT;
2488b8ff5c27SBram Moolenaar 		if (button & 2) mouse_code |= MOUSE_MIDDLE;
2489b8ff5c27SBram Moolenaar 		if (button & 4) mouse_code |= MOUSE_RIGHT;
2490b8ff5c27SBram Moolenaar 		if (button & 8) mouse_code |= MOUSE_SHIFT;
2491b8ff5c27SBram Moolenaar 		if (button & 16) mouse_code |= MOUSE_CTRL;
2492b8ff5c27SBram Moolenaar 		break;
2493b8ff5c27SBram Moolenaar 	    case 'u': // Button Up
2494d58d4f90SBram Moolenaar 		is_release = TRUE;
2495b8ff5c27SBram Moolenaar 		if (button & 1)
2496d58d4f90SBram Moolenaar 		    mouse_code |= MOUSE_LEFT;
2497b8ff5c27SBram Moolenaar 		if (button & 2)
2498d58d4f90SBram Moolenaar 		    mouse_code |= MOUSE_MIDDLE;
2499b8ff5c27SBram Moolenaar 		if (button & 4)
2500d58d4f90SBram Moolenaar 		    mouse_code |= MOUSE_RIGHT;
2501b8ff5c27SBram Moolenaar 		if (button & 8)
2502b8ff5c27SBram Moolenaar 		    mouse_code |= MOUSE_SHIFT;
2503b8ff5c27SBram Moolenaar 		if (button & 16)
2504b8ff5c27SBram Moolenaar 		    mouse_code |= MOUSE_CTRL;
2505b8ff5c27SBram Moolenaar 		break;
2506b8ff5c27SBram Moolenaar 	    default: return -1; // Unknown Result
2507b8ff5c27SBram Moolenaar 	}
2508b8ff5c27SBram Moolenaar 
2509b8ff5c27SBram Moolenaar 	*slen += (p - (tp + *slen));
2510b8ff5c27SBram Moolenaar     }
2511b8ff5c27SBram Moolenaar # endif // FEAT_MOUSE_JSB
2512b8ff5c27SBram Moolenaar # ifdef FEAT_MOUSE_DEC
2513b8ff5c27SBram Moolenaar     if (key_name[0] == KS_DEC_MOUSE)
2514b8ff5c27SBram Moolenaar     {
2515b8ff5c27SBram Moolenaar 	/*
2516b8ff5c27SBram Moolenaar 	 * The DEC Locator Input Model
2517b8ff5c27SBram Moolenaar 	 * Netterm delivers the code sequence:
2518b8ff5c27SBram Moolenaar 	 *  \033[2;4;24;80&w  (left button down)
2519b8ff5c27SBram Moolenaar 	 *  \033[3;0;24;80&w  (left button up)
2520b8ff5c27SBram Moolenaar 	 *  \033[6;1;24;80&w  (right button down)
2521b8ff5c27SBram Moolenaar 	 *  \033[7;0;24;80&w  (right button up)
2522b8ff5c27SBram Moolenaar 	 * CSI Pe ; Pb ; Pr ; Pc ; Pp & w
2523b8ff5c27SBram Moolenaar 	 * Pe is the event code
2524b8ff5c27SBram Moolenaar 	 * Pb is the button code
2525b8ff5c27SBram Moolenaar 	 * Pr is the row coordinate
2526b8ff5c27SBram Moolenaar 	 * Pc is the column coordinate
2527b8ff5c27SBram Moolenaar 	 * Pp is the third coordinate (page number)
2528b8ff5c27SBram Moolenaar 	 * Pe, the event code indicates what event caused this report
2529b8ff5c27SBram Moolenaar 	 *    The following event codes are defined:
253013c04631SBram Moolenaar 	 *    0 - request, the terminal received an explicit request for a
253113c04631SBram Moolenaar 	 *        locator report, but the locator is unavailable
253213c04631SBram Moolenaar 	 *    1 - request, the terminal received an explicit request for a
253313c04631SBram Moolenaar 	 *        locator report
2534b8ff5c27SBram Moolenaar 	 *    2 - left button down
2535b8ff5c27SBram Moolenaar 	 *    3 - left button up
2536b8ff5c27SBram Moolenaar 	 *    4 - middle button down
2537b8ff5c27SBram Moolenaar 	 *    5 - middle button up
2538b8ff5c27SBram Moolenaar 	 *    6 - right button down
2539b8ff5c27SBram Moolenaar 	 *    7 - right button up
2540b8ff5c27SBram Moolenaar 	 *    8 - fourth button down
2541b8ff5c27SBram Moolenaar 	 *    9 - fourth button up
2542b8ff5c27SBram Moolenaar 	 *    10 - locator outside filter rectangle
254313c04631SBram Moolenaar 	 * Pb, the button code, ASCII decimal 0-15 indicating which buttons are
254413c04631SBram Moolenaar 	 *   down if any. The state of the four buttons on the locator
254513c04631SBram Moolenaar 	 *   correspond to the low four bits of the decimal value, "1" means
254613c04631SBram Moolenaar 	 *   button depressed
2547b8ff5c27SBram Moolenaar 	 *   0 - no buttons down,
2548b8ff5c27SBram Moolenaar 	 *   1 - right,
2549b8ff5c27SBram Moolenaar 	 *   2 - middle,
2550b8ff5c27SBram Moolenaar 	 *   4 - left,
2551b8ff5c27SBram Moolenaar 	 *   8 - fourth
2552b8ff5c27SBram Moolenaar 	 * Pr is the row coordinate of the locator position in the page,
255313c04631SBram Moolenaar 	 *   encoded as an ASCII decimal value.  If Pr is omitted, the locator
255413c04631SBram Moolenaar 	 *   position is undefined (outside the terminal window for example).
255513c04631SBram Moolenaar 	 * Pc is the column coordinate of the locator position in the page,
255613c04631SBram Moolenaar 	 *   encoded as an ASCII decimal value.  If Pc is omitted, the locator
255713c04631SBram Moolenaar 	 *   position is undefined (outside the terminal window for example).
255813c04631SBram Moolenaar 	 * Pp is the page coordinate of the locator position encoded as an
255913c04631SBram Moolenaar 	 *   ASCII decimal value.  The page coordinate may be omitted if the
256013c04631SBram Moolenaar 	 *   locator is on page one (the default).  We ignore it anyway.
2561b8ff5c27SBram Moolenaar 	 */
2562b8ff5c27SBram Moolenaar 	int Pe, Pb, Pr, Pc;
2563b8ff5c27SBram Moolenaar 
2564b8ff5c27SBram Moolenaar 	p = tp + *slen;
2565b8ff5c27SBram Moolenaar 
2566b8ff5c27SBram Moolenaar 	// get event status
2567b8ff5c27SBram Moolenaar 	Pe = getdigits(&p);
2568b8ff5c27SBram Moolenaar 	if (*p++ != ';')
2569b8ff5c27SBram Moolenaar 	    return -1;
2570b8ff5c27SBram Moolenaar 
2571b8ff5c27SBram Moolenaar 	// get button status
2572b8ff5c27SBram Moolenaar 	Pb = getdigits(&p);
2573b8ff5c27SBram Moolenaar 	if (*p++ != ';')
2574b8ff5c27SBram Moolenaar 	    return -1;
2575b8ff5c27SBram Moolenaar 
2576b8ff5c27SBram Moolenaar 	// get row status
2577b8ff5c27SBram Moolenaar 	Pr = getdigits(&p);
2578b8ff5c27SBram Moolenaar 	if (*p++ != ';')
2579b8ff5c27SBram Moolenaar 	    return -1;
2580b8ff5c27SBram Moolenaar 
2581b8ff5c27SBram Moolenaar 	// get column status
2582b8ff5c27SBram Moolenaar 	Pc = getdigits(&p);
2583b8ff5c27SBram Moolenaar 
2584b8ff5c27SBram Moolenaar 	// the page parameter is optional
2585b8ff5c27SBram Moolenaar 	if (*p == ';')
2586b8ff5c27SBram Moolenaar 	{
2587b8ff5c27SBram Moolenaar 	    p++;
2588b8ff5c27SBram Moolenaar 	    (void)getdigits(&p);
2589b8ff5c27SBram Moolenaar 	}
2590b8ff5c27SBram Moolenaar 	if (*p++ != '&')
2591b8ff5c27SBram Moolenaar 	    return -1;
2592b8ff5c27SBram Moolenaar 	if (*p++ != 'w')
2593b8ff5c27SBram Moolenaar 	    return -1;
2594b8ff5c27SBram Moolenaar 
2595b8ff5c27SBram Moolenaar 	mouse_code = 0;
2596b8ff5c27SBram Moolenaar 	switch (Pe)
2597b8ff5c27SBram Moolenaar 	{
2598b8ff5c27SBram Moolenaar 	    case  0: return -1; // position request while unavailable
2599b8ff5c27SBram Moolenaar 	    case  1: // a response to a locator position request includes
2600b8ff5c27SBram Moolenaar 		     //	the status of all buttons
2601b8ff5c27SBram Moolenaar 		     Pb &= 7;   // mask off and ignore fourth button
2602b8ff5c27SBram Moolenaar 		     if (Pb & 4)
2603b8ff5c27SBram Moolenaar 			 mouse_code  = MOUSE_LEFT;
2604b8ff5c27SBram Moolenaar 		     if (Pb & 2)
2605b8ff5c27SBram Moolenaar 			 mouse_code  = MOUSE_MIDDLE;
2606b8ff5c27SBram Moolenaar 		     if (Pb & 1)
2607b8ff5c27SBram Moolenaar 			 mouse_code  = MOUSE_RIGHT;
2608b8ff5c27SBram Moolenaar 		     if (Pb)
2609b8ff5c27SBram Moolenaar 		     {
2610b8ff5c27SBram Moolenaar 			 held_button = mouse_code;
2611b8ff5c27SBram Moolenaar 			 mouse_code |= MOUSE_DRAG;
2612b8ff5c27SBram Moolenaar 			 WantQueryMouse = TRUE;
2613b8ff5c27SBram Moolenaar 		     }
2614b8ff5c27SBram Moolenaar 		     is_drag = TRUE;
2615b8ff5c27SBram Moolenaar 		     showmode();
2616b8ff5c27SBram Moolenaar 		     break;
2617b8ff5c27SBram Moolenaar 	    case  2: mouse_code = MOUSE_LEFT;
2618b8ff5c27SBram Moolenaar 		     WantQueryMouse = TRUE;
2619b8ff5c27SBram Moolenaar 		     break;
2620d58d4f90SBram Moolenaar 	    case  3: mouse_code = MOUSE_LEFT;
2621d58d4f90SBram Moolenaar 		     is_release = TRUE;
2622b8ff5c27SBram Moolenaar 		     break;
2623b8ff5c27SBram Moolenaar 	    case  4: mouse_code = MOUSE_MIDDLE;
2624b8ff5c27SBram Moolenaar 		     WantQueryMouse = TRUE;
2625b8ff5c27SBram Moolenaar 		     break;
2626d58d4f90SBram Moolenaar 	    case  5: mouse_code = MOUSE_MIDDLE;
2627d58d4f90SBram Moolenaar 		     is_release = TRUE;
2628b8ff5c27SBram Moolenaar 		     break;
2629b8ff5c27SBram Moolenaar 	    case  6: mouse_code = MOUSE_RIGHT;
2630b8ff5c27SBram Moolenaar 		     WantQueryMouse = TRUE;
2631b8ff5c27SBram Moolenaar 		     break;
2632d58d4f90SBram Moolenaar 	    case  7: mouse_code = MOUSE_RIGHT;
2633d58d4f90SBram Moolenaar 		     is_release = TRUE;
2634b8ff5c27SBram Moolenaar 		     break;
2635b8ff5c27SBram Moolenaar 	    case  8: return -1; // fourth button down
2636b8ff5c27SBram Moolenaar 	    case  9: return -1; // fourth button up
2637b8ff5c27SBram Moolenaar 	    case 10: return -1; // mouse outside of filter rectangle
2638b8ff5c27SBram Moolenaar 	    default: return -1; // should never occur
2639b8ff5c27SBram Moolenaar 	}
2640b8ff5c27SBram Moolenaar 
2641b8ff5c27SBram Moolenaar 	mouse_col = Pc - 1;
2642b8ff5c27SBram Moolenaar 	mouse_row = Pr - 1;
2643b8ff5c27SBram Moolenaar 
2644b8ff5c27SBram Moolenaar 	*slen += (int)(p - (tp + *slen));
2645b8ff5c27SBram Moolenaar     }
2646b8ff5c27SBram Moolenaar # endif // FEAT_MOUSE_DEC
2647b8ff5c27SBram Moolenaar # ifdef FEAT_MOUSE_PTERM
2648b8ff5c27SBram Moolenaar     if (key_name[0] == KS_PTERM_MOUSE)
2649b8ff5c27SBram Moolenaar     {
2650b8ff5c27SBram Moolenaar 	int button, num_clicks, action;
2651b8ff5c27SBram Moolenaar 
2652b8ff5c27SBram Moolenaar 	p = tp + *slen;
2653b8ff5c27SBram Moolenaar 
2654b8ff5c27SBram Moolenaar 	action = getdigits(&p);
2655b8ff5c27SBram Moolenaar 	if (*p++ != ';')
2656b8ff5c27SBram Moolenaar 	    return -1;
2657b8ff5c27SBram Moolenaar 
2658b8ff5c27SBram Moolenaar 	mouse_row = getdigits(&p);
2659b8ff5c27SBram Moolenaar 	if (*p++ != ';')
2660b8ff5c27SBram Moolenaar 	    return -1;
2661b8ff5c27SBram Moolenaar 	mouse_col = getdigits(&p);
2662b8ff5c27SBram Moolenaar 	if (*p++ != ';')
2663b8ff5c27SBram Moolenaar 	    return -1;
2664b8ff5c27SBram Moolenaar 
2665b8ff5c27SBram Moolenaar 	button = getdigits(&p);
2666b8ff5c27SBram Moolenaar 	mouse_code = 0;
2667b8ff5c27SBram Moolenaar 
2668b8ff5c27SBram Moolenaar 	switch (button)
2669b8ff5c27SBram Moolenaar 	{
2670b8ff5c27SBram Moolenaar 	    case 4: mouse_code = MOUSE_LEFT; break;
2671b8ff5c27SBram Moolenaar 	    case 1: mouse_code = MOUSE_RIGHT; break;
2672b8ff5c27SBram Moolenaar 	    case 2: mouse_code = MOUSE_MIDDLE; break;
2673b8ff5c27SBram Moolenaar 	    default: return -1;
2674b8ff5c27SBram Moolenaar 	}
2675b8ff5c27SBram Moolenaar 
2676b8ff5c27SBram Moolenaar 	switch (action)
2677b8ff5c27SBram Moolenaar 	{
2678b8ff5c27SBram Moolenaar 	    case 31: // Initial press
2679b8ff5c27SBram Moolenaar 		if (*p++ != ';')
2680b8ff5c27SBram Moolenaar 		    return -1;
2681b8ff5c27SBram Moolenaar 
2682b8ff5c27SBram Moolenaar 		num_clicks = getdigits(&p); // Not used
2683b8ff5c27SBram Moolenaar 		break;
2684b8ff5c27SBram Moolenaar 
2685b8ff5c27SBram Moolenaar 	    case 32: // Release
2686d58d4f90SBram Moolenaar 		is_release = TRUE;
2687b8ff5c27SBram Moolenaar 		break;
2688b8ff5c27SBram Moolenaar 
2689b8ff5c27SBram Moolenaar 	    case 33: // Drag
2690b8ff5c27SBram Moolenaar 		held_button = mouse_code;
2691b8ff5c27SBram Moolenaar 		mouse_code |= MOUSE_DRAG;
2692b8ff5c27SBram Moolenaar 		break;
2693b8ff5c27SBram Moolenaar 
2694b8ff5c27SBram Moolenaar 	    default:
2695b8ff5c27SBram Moolenaar 		return -1;
2696b8ff5c27SBram Moolenaar 	}
2697b8ff5c27SBram Moolenaar 
2698b8ff5c27SBram Moolenaar 	if (*p++ != 't')
2699b8ff5c27SBram Moolenaar 	    return -1;
2700b8ff5c27SBram Moolenaar 
2701b8ff5c27SBram Moolenaar 	*slen += (p - (tp + *slen));
2702b8ff5c27SBram Moolenaar     }
2703b8ff5c27SBram Moolenaar # endif // FEAT_MOUSE_PTERM
2704b8ff5c27SBram Moolenaar 
2705b8ff5c27SBram Moolenaar     // Interpret the mouse code
2706b8ff5c27SBram Moolenaar     current_button = (mouse_code & MOUSE_CLICK_MASK);
2707d58d4f90SBram Moolenaar     if (is_release)
2708d58d4f90SBram Moolenaar 	current_button |= MOUSE_RELEASE;
2709d58d4f90SBram Moolenaar 
2710b8ff5c27SBram Moolenaar     if (current_button == MOUSE_RELEASE
2711b8ff5c27SBram Moolenaar # ifdef FEAT_MOUSE_XTERM
2712b8ff5c27SBram Moolenaar 	    && wheel_code == 0
2713b8ff5c27SBram Moolenaar # endif
2714b8ff5c27SBram Moolenaar        )
2715b8ff5c27SBram Moolenaar     {
2716b8ff5c27SBram Moolenaar 	/*
271713c04631SBram Moolenaar 	 * If we get a mouse drag or release event when there is no mouse
271813c04631SBram Moolenaar 	 * button held down (held_button == MOUSE_RELEASE), produce a K_IGNORE
271913c04631SBram Moolenaar 	 * below.
272013c04631SBram Moolenaar 	 * (can happen when you hold down two buttons and then let them go, or
272113c04631SBram Moolenaar 	 * click in the menu bar, but not on a menu, and drag into the text).
2722b8ff5c27SBram Moolenaar 	 */
2723b8ff5c27SBram Moolenaar 	if ((mouse_code & MOUSE_DRAG) == MOUSE_DRAG)
2724b8ff5c27SBram Moolenaar 	    is_drag = TRUE;
2725b8ff5c27SBram Moolenaar 	current_button = held_button;
2726b8ff5c27SBram Moolenaar     }
2727b8ff5c27SBram Moolenaar     else if (wheel_code == 0)
2728b8ff5c27SBram Moolenaar     {
2729b8ff5c27SBram Moolenaar # ifdef CHECK_DOUBLE_CLICK
2730b8ff5c27SBram Moolenaar #  ifdef FEAT_MOUSE_GPM
2731b8ff5c27SBram Moolenaar 	/*
273213c04631SBram Moolenaar 	 * Only for Unix, when GUI not active, we handle multi-clicks here, but
273313c04631SBram Moolenaar 	 * not for GPM mouse events.
2734b8ff5c27SBram Moolenaar 	 */
2735b8ff5c27SBram Moolenaar #   ifdef FEAT_GUI
2736b8ff5c27SBram Moolenaar 	if (key_name[0] != KS_GPM_MOUSE && !gui.in_use)
2737b8ff5c27SBram Moolenaar #   else
2738b8ff5c27SBram Moolenaar 	    if (key_name[0] != KS_GPM_MOUSE)
2739b8ff5c27SBram Moolenaar #   endif
2740b8ff5c27SBram Moolenaar #  else
2741b8ff5c27SBram Moolenaar #   ifdef FEAT_GUI
2742b8ff5c27SBram Moolenaar 		if (!gui.in_use)
2743b8ff5c27SBram Moolenaar #   endif
2744b8ff5c27SBram Moolenaar #  endif
2745b8ff5c27SBram Moolenaar 		{
2746b8ff5c27SBram Moolenaar 		    /*
2747b8ff5c27SBram Moolenaar 		     * Compute the time elapsed since the previous mouse click.
2748b8ff5c27SBram Moolenaar 		     */
2749b8ff5c27SBram Moolenaar 		    gettimeofday(&mouse_time, NULL);
2750b8ff5c27SBram Moolenaar 		    if (orig_mouse_time.tv_sec == 0)
2751b8ff5c27SBram Moolenaar 		    {
2752b8ff5c27SBram Moolenaar 			/*
2753b8ff5c27SBram Moolenaar 			 * Avoid computing the difference between mouse_time
2754b8ff5c27SBram Moolenaar 			 * and orig_mouse_time for the first click, as the
2755b8ff5c27SBram Moolenaar 			 * difference would be huge and would cause
2756b8ff5c27SBram Moolenaar 			 * multiplication overflow.
2757b8ff5c27SBram Moolenaar 			 */
2758b8ff5c27SBram Moolenaar 			timediff = p_mouset;
2759b8ff5c27SBram Moolenaar 		    }
2760b8ff5c27SBram Moolenaar 		    else
276185c3502eSBram Moolenaar 			timediff = time_diff_ms(&orig_mouse_time, &mouse_time);
2762b8ff5c27SBram Moolenaar 		    orig_mouse_time = mouse_time;
2763b8ff5c27SBram Moolenaar 		    if (mouse_code == orig_mouse_code
2764b8ff5c27SBram Moolenaar 			    && timediff < p_mouset
2765b8ff5c27SBram Moolenaar 			    && orig_num_clicks != 4
2766b8ff5c27SBram Moolenaar 			    && orig_mouse_col == mouse_col
2767b8ff5c27SBram Moolenaar 			    && orig_mouse_row == mouse_row
2768b8ff5c27SBram Moolenaar 			    && (is_mouse_topline(curwin)
2769b8ff5c27SBram Moolenaar 				// Double click in tab pages line also works
2770b8ff5c27SBram Moolenaar 				// when window contents changes.
2771b8ff5c27SBram Moolenaar 				|| (mouse_row == 0 && firstwin->w_winrow > 0))
2772b8ff5c27SBram Moolenaar 		       )
2773b8ff5c27SBram Moolenaar 			++orig_num_clicks;
2774b8ff5c27SBram Moolenaar 		    else
2775b8ff5c27SBram Moolenaar 			orig_num_clicks = 1;
2776b8ff5c27SBram Moolenaar 		    orig_mouse_col = mouse_col;
2777b8ff5c27SBram Moolenaar 		    orig_mouse_row = mouse_row;
2778b8ff5c27SBram Moolenaar 		    set_mouse_topline(curwin);
2779b8ff5c27SBram Moolenaar 		}
2780b8ff5c27SBram Moolenaar #  if defined(FEAT_GUI) || defined(FEAT_MOUSE_GPM)
2781b8ff5c27SBram Moolenaar 		else
2782b8ff5c27SBram Moolenaar 		    orig_num_clicks = NUM_MOUSE_CLICKS(mouse_code);
2783b8ff5c27SBram Moolenaar #  endif
2784b8ff5c27SBram Moolenaar # else
2785b8ff5c27SBram Moolenaar 	orig_num_clicks = NUM_MOUSE_CLICKS(mouse_code);
2786b8ff5c27SBram Moolenaar # endif
2787b8ff5c27SBram Moolenaar 	is_click = TRUE;
2788b8ff5c27SBram Moolenaar 	orig_mouse_code = mouse_code;
2789b8ff5c27SBram Moolenaar     }
2790b8ff5c27SBram Moolenaar     if (!is_drag)
2791b8ff5c27SBram Moolenaar 	held_button = mouse_code & MOUSE_CLICK_MASK;
2792b8ff5c27SBram Moolenaar 
2793b8ff5c27SBram Moolenaar     /*
2794b8ff5c27SBram Moolenaar      * Translate the actual mouse event into a pseudo mouse event.
2795b8ff5c27SBram Moolenaar      * First work out what modifiers are to be used.
2796b8ff5c27SBram Moolenaar      */
2797b8ff5c27SBram Moolenaar     if (orig_mouse_code & MOUSE_SHIFT)
2798b8ff5c27SBram Moolenaar 	*modifiers |= MOD_MASK_SHIFT;
2799b8ff5c27SBram Moolenaar     if (orig_mouse_code & MOUSE_CTRL)
2800b8ff5c27SBram Moolenaar 	*modifiers |= MOD_MASK_CTRL;
2801b8ff5c27SBram Moolenaar     if (orig_mouse_code & MOUSE_ALT)
2802b8ff5c27SBram Moolenaar 	*modifiers |= MOD_MASK_ALT;
2803b8ff5c27SBram Moolenaar     if (orig_num_clicks == 2)
2804b8ff5c27SBram Moolenaar 	*modifiers |= MOD_MASK_2CLICK;
2805b8ff5c27SBram Moolenaar     else if (orig_num_clicks == 3)
2806b8ff5c27SBram Moolenaar 	*modifiers |= MOD_MASK_3CLICK;
2807b8ff5c27SBram Moolenaar     else if (orig_num_clicks == 4)
2808b8ff5c27SBram Moolenaar 	*modifiers |= MOD_MASK_4CLICK;
2809b8ff5c27SBram Moolenaar 
281013c04631SBram Moolenaar     // Work out our pseudo mouse event. Note that MOUSE_RELEASE gets added,
281113c04631SBram Moolenaar     // then it's not mouse up/down.
2812b8ff5c27SBram Moolenaar     key_name[0] = KS_EXTRA;
2813d58d4f90SBram Moolenaar     if (wheel_code != 0 && (!is_release || release_is_ambiguous))
2814b8ff5c27SBram Moolenaar     {
2815b8ff5c27SBram Moolenaar 	if (wheel_code & MOUSE_CTRL)
2816b8ff5c27SBram Moolenaar 	    *modifiers |= MOD_MASK_CTRL;
2817b8ff5c27SBram Moolenaar 	if (wheel_code & MOUSE_ALT)
2818b8ff5c27SBram Moolenaar 	    *modifiers |= MOD_MASK_ALT;
2819d58d4f90SBram Moolenaar 
2820d58d4f90SBram Moolenaar 	if (wheel_code & 1 && wheel_code & 2)
2821d58d4f90SBram Moolenaar 	    key_name[1] = (int)KE_MOUSELEFT;
2822d58d4f90SBram Moolenaar 	else if (wheel_code & 2)
2823d58d4f90SBram Moolenaar 	    key_name[1] = (int)KE_MOUSERIGHT;
2824d58d4f90SBram Moolenaar 	else if (wheel_code & 1)
2825d58d4f90SBram Moolenaar 	    key_name[1] = (int)KE_MOUSEUP;
2826d58d4f90SBram Moolenaar 	else
2827d58d4f90SBram Moolenaar 	    key_name[1] = (int)KE_MOUSEDOWN;
2828d58d4f90SBram Moolenaar 
2829b8ff5c27SBram Moolenaar 	held_button = MOUSE_RELEASE;
2830b8ff5c27SBram Moolenaar     }
2831b8ff5c27SBram Moolenaar     else
283213c04631SBram Moolenaar 	key_name[1] = get_pseudo_mouse_code(current_button, is_click, is_drag);
2833b8ff5c27SBram Moolenaar 
283413c04631SBram Moolenaar 
283513c04631SBram Moolenaar     // Make sure the mouse position is valid.  Some terminals may return weird
283613c04631SBram Moolenaar     // values.
2837b8ff5c27SBram Moolenaar     if (mouse_col >= Columns)
2838b8ff5c27SBram Moolenaar 	mouse_col = Columns - 1;
2839b8ff5c27SBram Moolenaar     if (mouse_row >= Rows)
2840b8ff5c27SBram Moolenaar 	mouse_row = Rows - 1;
2841b8ff5c27SBram Moolenaar 
2842b8ff5c27SBram Moolenaar     return 0;
2843b8ff5c27SBram Moolenaar }
2844b20b9e14SBram Moolenaar 
2845b20b9e14SBram Moolenaar // Functions also used for popup windows.
2846b20b9e14SBram Moolenaar 
2847b20b9e14SBram Moolenaar /*
2848b20b9e14SBram Moolenaar  * Compute the buffer line position from the screen position "rowp" / "colp" in
2849b20b9e14SBram Moolenaar  * window "win".
2850452143c6SBram Moolenaar  * "plines_cache" can be NULL (no cache) or an array with "Rows" entries that
2851452143c6SBram Moolenaar  * caches the plines_win() result from a previous call.  Entry is zero if not
2852452143c6SBram Moolenaar  * computed yet.  There must be no text or setting changes since the entry is
2853452143c6SBram Moolenaar  * put in the cache.
2854b20b9e14SBram Moolenaar  * Returns TRUE if the position is below the last line.
2855b20b9e14SBram Moolenaar  */
2856b20b9e14SBram Moolenaar     int
mouse_comp_pos(win_T * win,int * rowp,int * colp,linenr_T * lnump,int * plines_cache)2857b20b9e14SBram Moolenaar mouse_comp_pos(
2858b20b9e14SBram Moolenaar     win_T	*win,
2859b20b9e14SBram Moolenaar     int		*rowp,
2860b20b9e14SBram Moolenaar     int		*colp,
2861b20b9e14SBram Moolenaar     linenr_T	*lnump,
2862b20b9e14SBram Moolenaar     int		*plines_cache)
2863b20b9e14SBram Moolenaar {
2864b20b9e14SBram Moolenaar     int		col = *colp;
2865b20b9e14SBram Moolenaar     int		row = *rowp;
2866b20b9e14SBram Moolenaar     linenr_T	lnum;
2867b20b9e14SBram Moolenaar     int		retval = FALSE;
2868b20b9e14SBram Moolenaar     int		off;
2869b20b9e14SBram Moolenaar     int		count;
2870b20b9e14SBram Moolenaar 
2871b20b9e14SBram Moolenaar #ifdef FEAT_RIGHTLEFT
2872b20b9e14SBram Moolenaar     if (win->w_p_rl)
2873b20b9e14SBram Moolenaar 	col = win->w_width - 1 - col;
2874b20b9e14SBram Moolenaar #endif
2875b20b9e14SBram Moolenaar 
2876b20b9e14SBram Moolenaar     lnum = win->w_topline;
2877b20b9e14SBram Moolenaar 
2878b20b9e14SBram Moolenaar     while (row > 0)
2879b20b9e14SBram Moolenaar     {
2880b20b9e14SBram Moolenaar 	int cache_idx = lnum - win->w_topline;
2881b20b9e14SBram Moolenaar 
2882452143c6SBram Moolenaar 	// Only "Rows" lines are cached, with folding we'll run out of entries
2883452143c6SBram Moolenaar 	// and use the slow way.
2884452143c6SBram Moolenaar 	if (plines_cache != NULL && cache_idx < Rows
2885452143c6SBram Moolenaar 						&& plines_cache[cache_idx] > 0)
2886b20b9e14SBram Moolenaar 	    count = plines_cache[cache_idx];
2887b20b9e14SBram Moolenaar 	else
2888b20b9e14SBram Moolenaar 	{
2889b20b9e14SBram Moolenaar #ifdef FEAT_DIFF
2890b20b9e14SBram Moolenaar 	    // Don't include filler lines in "count"
2891b20b9e14SBram Moolenaar 	    if (win->w_p_diff
2892b20b9e14SBram Moolenaar # ifdef FEAT_FOLDING
2893b20b9e14SBram Moolenaar 		    && !hasFoldingWin(win, lnum, NULL, NULL, TRUE, NULL)
2894b20b9e14SBram Moolenaar # endif
2895b20b9e14SBram Moolenaar 		    )
2896b20b9e14SBram Moolenaar 	    {
2897b20b9e14SBram Moolenaar 		if (lnum == win->w_topline)
2898b20b9e14SBram Moolenaar 		    row -= win->w_topfill;
2899b20b9e14SBram Moolenaar 		else
2900b20b9e14SBram Moolenaar 		    row -= diff_check_fill(win, lnum);
2901b20b9e14SBram Moolenaar 		count = plines_win_nofill(win, lnum, TRUE);
2902b20b9e14SBram Moolenaar 	    }
2903b20b9e14SBram Moolenaar 	    else
2904b20b9e14SBram Moolenaar #endif
2905b20b9e14SBram Moolenaar 		count = plines_win(win, lnum, TRUE);
2906452143c6SBram Moolenaar 	    if (plines_cache != NULL && cache_idx < Rows)
2907b20b9e14SBram Moolenaar 		plines_cache[cache_idx] = count;
2908b20b9e14SBram Moolenaar 	}
2909b20b9e14SBram Moolenaar 	if (count > row)
2910b20b9e14SBram Moolenaar 	    break;	// Position is in this buffer line.
2911b20b9e14SBram Moolenaar #ifdef FEAT_FOLDING
2912b20b9e14SBram Moolenaar 	(void)hasFoldingWin(win, lnum, NULL, &lnum, TRUE, NULL);
2913b20b9e14SBram Moolenaar #endif
2914b20b9e14SBram Moolenaar 	if (lnum == win->w_buffer->b_ml.ml_line_count)
2915b20b9e14SBram Moolenaar 	{
2916b20b9e14SBram Moolenaar 	    retval = TRUE;
2917b20b9e14SBram Moolenaar 	    break;		// past end of file
2918b20b9e14SBram Moolenaar 	}
2919b20b9e14SBram Moolenaar 	row -= count;
2920b20b9e14SBram Moolenaar 	++lnum;
2921b20b9e14SBram Moolenaar     }
2922b20b9e14SBram Moolenaar 
2923b20b9e14SBram Moolenaar     if (!retval)
2924b20b9e14SBram Moolenaar     {
2925b20b9e14SBram Moolenaar 	// Compute the column without wrapping.
2926b20b9e14SBram Moolenaar 	off = win_col_off(win) - win_col_off2(win);
2927b20b9e14SBram Moolenaar 	if (col < off)
2928b20b9e14SBram Moolenaar 	    col = off;
2929b20b9e14SBram Moolenaar 	col += row * (win->w_width - off);
2930b20b9e14SBram Moolenaar 	// add skip column (for long wrapping line)
2931b20b9e14SBram Moolenaar 	col += win->w_skipcol;
2932b20b9e14SBram Moolenaar     }
2933b20b9e14SBram Moolenaar 
2934b20b9e14SBram Moolenaar     if (!win->w_p_wrap)
2935b20b9e14SBram Moolenaar 	col += win->w_leftcol;
2936b20b9e14SBram Moolenaar 
2937b20b9e14SBram Moolenaar     // skip line number and fold column in front of the line
2938b20b9e14SBram Moolenaar     col -= win_col_off(win);
2939dbfa795dSBram Moolenaar     if (col <= 0)
2940b20b9e14SBram Moolenaar     {
2941b20b9e14SBram Moolenaar #ifdef FEAT_NETBEANS_INTG
2942dbfa795dSBram Moolenaar 	// if mouse is clicked on the gutter, then inform the netbeans server
2943dbfa795dSBram Moolenaar 	if (*colp < win_col_off(win))
2944b20b9e14SBram Moolenaar 	    netbeans_gutter_click(lnum);
2945b20b9e14SBram Moolenaar #endif
2946b20b9e14SBram Moolenaar 	col = 0;
2947b20b9e14SBram Moolenaar     }
2948b20b9e14SBram Moolenaar 
2949b20b9e14SBram Moolenaar     *colp = col;
2950b20b9e14SBram Moolenaar     *rowp = row;
2951b20b9e14SBram Moolenaar     *lnump = lnum;
2952b20b9e14SBram Moolenaar     return retval;
2953b20b9e14SBram Moolenaar }
2954b20b9e14SBram Moolenaar 
2955b20b9e14SBram Moolenaar /*
2956b20b9e14SBram Moolenaar  * Find the window at screen position "*rowp" and "*colp".  The positions are
2957b20b9e14SBram Moolenaar  * updated to become relative to the top-left of the window.
2958b20b9e14SBram Moolenaar  * When "popup" is FAIL_POPUP and the position is in a popup window then NULL
2959b20b9e14SBram Moolenaar  * is returned.  When "popup" is IGNORE_POPUP then do not even check popup
2960b20b9e14SBram Moolenaar  * windows.
2961b20b9e14SBram Moolenaar  * Returns NULL when something is wrong.
2962b20b9e14SBram Moolenaar  */
2963b20b9e14SBram Moolenaar     win_T *
mouse_find_win(int * rowp,int * colp,mouse_find_T popup UNUSED)2964b20b9e14SBram Moolenaar mouse_find_win(int *rowp, int *colp, mouse_find_T popup UNUSED)
2965b20b9e14SBram Moolenaar {
2966b20b9e14SBram Moolenaar     frame_T	*fp;
2967b20b9e14SBram Moolenaar     win_T	*wp;
2968b20b9e14SBram Moolenaar 
296905ad5ff0SBram Moolenaar #ifdef FEAT_PROP_POPUP
2970b20b9e14SBram Moolenaar     win_T	*pwp = NULL;
2971b20b9e14SBram Moolenaar 
2972b20b9e14SBram Moolenaar     if (popup != IGNORE_POPUP)
2973b20b9e14SBram Moolenaar     {
2974afe45b68SBram Moolenaar 	popup_reset_handled(POPUP_HANDLED_1);
2975afe45b68SBram Moolenaar 	while ((wp = find_next_popup(TRUE, POPUP_HANDLED_1)) != NULL)
2976b20b9e14SBram Moolenaar 	{
2977b20b9e14SBram Moolenaar 	    if (*rowp >= wp->w_winrow && *rowp < wp->w_winrow + popup_height(wp)
2978b20b9e14SBram Moolenaar 		    && *colp >= wp->w_wincol
2979b20b9e14SBram Moolenaar 				    && *colp < wp->w_wincol + popup_width(wp))
2980b20b9e14SBram Moolenaar 		pwp = wp;
2981b20b9e14SBram Moolenaar 	}
2982b20b9e14SBram Moolenaar 	if (pwp != NULL)
2983b20b9e14SBram Moolenaar 	{
2984b20b9e14SBram Moolenaar 	    if (popup == FAIL_POPUP)
2985b20b9e14SBram Moolenaar 		return NULL;
2986b20b9e14SBram Moolenaar 	    *rowp -= pwp->w_winrow;
2987b20b9e14SBram Moolenaar 	    *colp -= pwp->w_wincol;
2988b20b9e14SBram Moolenaar 	    return pwp;
2989b20b9e14SBram Moolenaar 	}
2990b20b9e14SBram Moolenaar     }
2991b20b9e14SBram Moolenaar #endif
2992b20b9e14SBram Moolenaar 
2993b20b9e14SBram Moolenaar     fp = topframe;
2994b20b9e14SBram Moolenaar     *rowp -= firstwin->w_winrow;
2995b20b9e14SBram Moolenaar     for (;;)
2996b20b9e14SBram Moolenaar     {
2997b20b9e14SBram Moolenaar 	if (fp->fr_layout == FR_LEAF)
2998b20b9e14SBram Moolenaar 	    break;
2999b20b9e14SBram Moolenaar 	if (fp->fr_layout == FR_ROW)
3000b20b9e14SBram Moolenaar 	{
3001b20b9e14SBram Moolenaar 	    for (fp = fp->fr_child; fp->fr_next != NULL; fp = fp->fr_next)
3002b20b9e14SBram Moolenaar 	    {
3003b20b9e14SBram Moolenaar 		if (*colp < fp->fr_width)
3004b20b9e14SBram Moolenaar 		    break;
3005b20b9e14SBram Moolenaar 		*colp -= fp->fr_width;
3006b20b9e14SBram Moolenaar 	    }
3007b20b9e14SBram Moolenaar 	}
3008b20b9e14SBram Moolenaar 	else    // fr_layout == FR_COL
3009b20b9e14SBram Moolenaar 	{
3010b20b9e14SBram Moolenaar 	    for (fp = fp->fr_child; fp->fr_next != NULL; fp = fp->fr_next)
3011b20b9e14SBram Moolenaar 	    {
3012b20b9e14SBram Moolenaar 		if (*rowp < fp->fr_height)
3013b20b9e14SBram Moolenaar 		    break;
3014b20b9e14SBram Moolenaar 		*rowp -= fp->fr_height;
3015b20b9e14SBram Moolenaar 	    }
3016b20b9e14SBram Moolenaar 	}
3017b20b9e14SBram Moolenaar     }
3018b20b9e14SBram Moolenaar     // When using a timer that closes a window the window might not actually
3019b20b9e14SBram Moolenaar     // exist.
3020b20b9e14SBram Moolenaar     FOR_ALL_WINDOWS(wp)
3021b20b9e14SBram Moolenaar 	if (wp == fp->fr_win)
3022b20b9e14SBram Moolenaar 	{
3023b20b9e14SBram Moolenaar #ifdef FEAT_MENU
3024b20b9e14SBram Moolenaar 	    *rowp -= wp->w_winbar_height;
3025b20b9e14SBram Moolenaar #endif
3026b20b9e14SBram Moolenaar 	    return wp;
3027b20b9e14SBram Moolenaar 	}
3028b20b9e14SBram Moolenaar     return NULL;
3029b20b9e14SBram Moolenaar }
3030b20b9e14SBram Moolenaar 
303105ad5ff0SBram Moolenaar #if defined(NEED_VCOL2COL) || defined(FEAT_BEVAL) || defined(FEAT_PROP_POPUP) \
3032b20b9e14SBram Moolenaar 	|| defined(PROTO)
3033b20b9e14SBram Moolenaar /*
3034b20b9e14SBram Moolenaar  * Convert a virtual (screen) column to a character column.
3035b20b9e14SBram Moolenaar  * The first column is one.
3036b20b9e14SBram Moolenaar  */
3037b20b9e14SBram Moolenaar     int
vcol2col(win_T * wp,linenr_T lnum,int vcol)3038b20b9e14SBram Moolenaar vcol2col(win_T *wp, linenr_T lnum, int vcol)
3039b20b9e14SBram Moolenaar {
3040b20b9e14SBram Moolenaar     // try to advance to the specified column
3041b20b9e14SBram Moolenaar     int		count = 0;
3042b20b9e14SBram Moolenaar     char_u	*ptr;
3043b20b9e14SBram Moolenaar     char_u	*line;
3044b20b9e14SBram Moolenaar 
3045b20b9e14SBram Moolenaar     line = ptr = ml_get_buf(wp->w_buffer, lnum, FALSE);
3046b20b9e14SBram Moolenaar     while (count < vcol && *ptr != NUL)
3047b20b9e14SBram Moolenaar     {
3048b20b9e14SBram Moolenaar 	count += win_lbr_chartabsize(wp, line, ptr, count, NULL);
3049b20b9e14SBram Moolenaar 	MB_PTR_ADV(ptr);
3050b20b9e14SBram Moolenaar     }
3051b20b9e14SBram Moolenaar     return (int)(ptr - line);
3052b20b9e14SBram Moolenaar }
3053b20b9e14SBram Moolenaar #endif
3054db3a2051SBram Moolenaar 
3055db3a2051SBram Moolenaar #if defined(FEAT_EVAL) || defined(PROTO)
3056db3a2051SBram Moolenaar     void
f_getmousepos(typval_T * argvars UNUSED,typval_T * rettv)3057db3a2051SBram Moolenaar f_getmousepos(typval_T *argvars UNUSED, typval_T *rettv)
3058db3a2051SBram Moolenaar {
3059db3a2051SBram Moolenaar     dict_T	*d;
3060db3a2051SBram Moolenaar     win_T	*wp;
3061db3a2051SBram Moolenaar     int		row = mouse_row;
3062db3a2051SBram Moolenaar     int		col = mouse_col;
3063db3a2051SBram Moolenaar     varnumber_T winid = 0;
3064db3a2051SBram Moolenaar     varnumber_T winrow = 0;
3065db3a2051SBram Moolenaar     varnumber_T wincol = 0;
3066abe12a1aSBram Moolenaar     linenr_T	line = 0;
3067db3a2051SBram Moolenaar     varnumber_T column = 0;
3068db3a2051SBram Moolenaar 
3069db3a2051SBram Moolenaar     if (rettv_dict_alloc(rettv) != OK)
3070db3a2051SBram Moolenaar 	return;
3071db3a2051SBram Moolenaar     d = rettv->vval.v_dict;
3072db3a2051SBram Moolenaar 
3073db3a2051SBram Moolenaar     dict_add_number(d, "screenrow", (varnumber_T)mouse_row + 1);
3074db3a2051SBram Moolenaar     dict_add_number(d, "screencol", (varnumber_T)mouse_col + 1);
3075db3a2051SBram Moolenaar 
3076db3a2051SBram Moolenaar     wp = mouse_find_win(&row, &col, FIND_POPUP);
3077db3a2051SBram Moolenaar     if (wp != NULL)
3078db3a2051SBram Moolenaar     {
3079db3a2051SBram Moolenaar 	int	top_off = 0;
3080db3a2051SBram Moolenaar 	int	left_off = 0;
3081db3a2051SBram Moolenaar 	int	height = wp->w_height + wp->w_status_height;
3082db3a2051SBram Moolenaar 
308305ad5ff0SBram Moolenaar #ifdef FEAT_PROP_POPUP
3084db3a2051SBram Moolenaar 	if (WIN_IS_POPUP(wp))
3085db3a2051SBram Moolenaar 	{
3086db3a2051SBram Moolenaar 	    top_off = popup_top_extra(wp);
3087db3a2051SBram Moolenaar 	    left_off = popup_left_extra(wp);
3088db3a2051SBram Moolenaar 	    height = popup_height(wp);
3089db3a2051SBram Moolenaar 	}
3090db3a2051SBram Moolenaar #endif
3091db3a2051SBram Moolenaar 	if (row < height)
3092db3a2051SBram Moolenaar 	{
3093db3a2051SBram Moolenaar 	    winid = wp->w_id;
3094db3a2051SBram Moolenaar 	    winrow = row + 1;
3095db3a2051SBram Moolenaar 	    wincol = col + 1;
3096db3a2051SBram Moolenaar 	    row -= top_off;
3097db3a2051SBram Moolenaar 	    col -= left_off;
3098db3a2051SBram Moolenaar 	    if (row >= 0 && row < wp->w_height && col >= 0 && col < wp->w_width)
3099db3a2051SBram Moolenaar 	    {
31000a5aa7b2SBram Moolenaar 		char_u	*p;
31010a5aa7b2SBram Moolenaar 		int	count;
31020a5aa7b2SBram Moolenaar 
3103db3a2051SBram Moolenaar 		mouse_comp_pos(wp, &row, &col, &line, NULL);
31040a5aa7b2SBram Moolenaar 
31050a5aa7b2SBram Moolenaar 		// limit to text length plus one
31060a5aa7b2SBram Moolenaar 		p = ml_get_buf(wp->w_buffer, line, FALSE);
31070a5aa7b2SBram Moolenaar 		count = (int)STRLEN(p);
31080a5aa7b2SBram Moolenaar 		if (col > count)
31090a5aa7b2SBram Moolenaar 		    col = count;
31100a5aa7b2SBram Moolenaar 
3111db3a2051SBram Moolenaar 		column = col + 1;
3112db3a2051SBram Moolenaar 	    }
3113db3a2051SBram Moolenaar 	}
3114db3a2051SBram Moolenaar     }
3115db3a2051SBram Moolenaar     dict_add_number(d, "winid", winid);
3116db3a2051SBram Moolenaar     dict_add_number(d, "winrow", winrow);
3117db3a2051SBram Moolenaar     dict_add_number(d, "wincol", wincol);
3118abe12a1aSBram Moolenaar     dict_add_number(d, "line", (varnumber_T)line);
3119db3a2051SBram Moolenaar     dict_add_number(d, "column", column);
3120db3a2051SBram Moolenaar }
3121db3a2051SBram Moolenaar #endif
3122