xref: /vim-8.2.3635/src/ui.c (revision e48a2dd3)
1 /* vi:set ts=8 sts=4 sw=4:
2  *
3  * VIM - Vi IMproved	by Bram Moolenaar
4  *
5  * Do ":help uganda"  in Vim to read copying and usage conditions.
6  * Do ":help credits" in Vim to see a list of people who contributed.
7  * See README.txt for an overview of the Vim source code.
8  */
9 
10 /*
11  * ui.c: functions that handle the user interface.
12  * 1. Keyboard input stuff, and a bit of windowing stuff.  These are called
13  *    before the machine specific stuff (mch_*) so that we can call the GUI
14  *    stuff instead if the GUI is running.
15  * 2. Clipboard stuff.
16  * 3. Input buffer stuff.
17  */
18 
19 #include "vim.h"
20 
21     void
22 ui_write(s, len)
23     char_u  *s;
24     int	    len;
25 {
26 #ifdef FEAT_GUI
27     if (gui.in_use && !gui.dying && !gui.starting)
28     {
29 	gui_write(s, len);
30 	if (p_wd)
31 	    gui_wait_for_chars(p_wd);
32 	return;
33     }
34 #endif
35 #ifndef NO_CONSOLE
36     /* Don't output anything in silent mode ("ex -s") unless 'verbose' set */
37     if (!(silent_mode && p_verbose == 0))
38     {
39 #ifdef FEAT_MBYTE
40 	char_u	*tofree = NULL;
41 
42 	if (output_conv.vc_type != CONV_NONE)
43 	{
44 	    /* Convert characters from 'encoding' to 'termencoding'. */
45 	    tofree = string_convert(&output_conv, s, &len);
46 	    if (tofree != NULL)
47 		s = tofree;
48 	}
49 #endif
50 
51 	mch_write(s, len);
52 
53 #ifdef FEAT_MBYTE
54 	if (output_conv.vc_type != CONV_NONE)
55 	    vim_free(tofree);
56 #endif
57     }
58 #endif
59 }
60 
61 #if defined(UNIX) || defined(VMS) || defined(PROTO) || defined(WIN3264)
62 /*
63  * When executing an external program, there may be some typed characters that
64  * are not consumed by it.  Give them back to ui_inchar() and they are stored
65  * here for the next call.
66  */
67 static char_u *ta_str = NULL;
68 static int ta_off;	/* offset for next char to use when ta_str != NULL */
69 static int ta_len;	/* length of ta_str when it's not NULL*/
70 
71     void
72 ui_inchar_undo(s, len)
73     char_u	*s;
74     int		len;
75 {
76     char_u  *new;
77     int	    newlen;
78 
79     newlen = len;
80     if (ta_str != NULL)
81 	newlen += ta_len - ta_off;
82     new = alloc(newlen);
83     if (new != NULL)
84     {
85 	if (ta_str != NULL)
86 	{
87 	    mch_memmove(new, ta_str + ta_off, (size_t)(ta_len - ta_off));
88 	    mch_memmove(new + ta_len - ta_off, s, (size_t)len);
89 	    vim_free(ta_str);
90 	}
91 	else
92 	    mch_memmove(new, s, (size_t)len);
93 	ta_str = new;
94 	ta_len = newlen;
95 	ta_off = 0;
96     }
97 }
98 #endif
99 
100 /*
101  * ui_inchar(): low level input funcion.
102  * Get characters from the keyboard.
103  * Return the number of characters that are available.
104  * If "wtime" == 0 do not wait for characters.
105  * If "wtime" == -1 wait forever for characters.
106  * If "wtime" > 0 wait "wtime" milliseconds for a character.
107  *
108  * "tb_change_cnt" is the value of typebuf.tb_change_cnt if "buf" points into
109  * it.  When typebuf.tb_change_cnt changes (e.g., when a message is received
110  * from a remote client) "buf" can no longer be used.  "tb_change_cnt" is NULL
111  * otherwise.
112  */
113     int
114 ui_inchar(buf, maxlen, wtime, tb_change_cnt)
115     char_u	*buf;
116     int		maxlen;
117     long	wtime;	    /* don't use "time", MIPS cannot handle it */
118     int		tb_change_cnt;
119 {
120     int		retval = 0;
121 
122 #if defined(FEAT_GUI) && (defined(UNIX) || defined(VMS))
123     /*
124      * Use the typeahead if there is any.
125      */
126     if (ta_str != NULL)
127     {
128 	if (maxlen >= ta_len - ta_off)
129 	{
130 	    mch_memmove(buf, ta_str + ta_off, (size_t)ta_len);
131 	    vim_free(ta_str);
132 	    ta_str = NULL;
133 	    return ta_len;
134 	}
135 	mch_memmove(buf, ta_str + ta_off, (size_t)maxlen);
136 	ta_off += maxlen;
137 	return maxlen;
138     }
139 #endif
140 
141 #ifdef FEAT_PROFILE
142     if (do_profiling == PROF_YES && wtime != 0)
143 	prof_inchar_enter();
144 #endif
145 
146 #ifdef NO_CONSOLE_INPUT
147     /* Don't wait for character input when the window hasn't been opened yet.
148      * Do try reading, this works when redirecting stdin from a file.
149      * Must return something, otherwise we'll loop forever.  If we run into
150      * this very often we probably got stuck, exit Vim. */
151     if (no_console_input())
152     {
153 	static int count = 0;
154 
155 # ifndef NO_CONSOLE
156 	retval = mch_inchar(buf, maxlen, (wtime >= 0 && wtime < 10)
157 						? 10L : wtime, tb_change_cnt);
158 	if (retval > 0 || typebuf_changed(tb_change_cnt) || wtime >= 0)
159 	    goto theend;
160 # endif
161 	if (wtime == -1 && ++count == 1000)
162 	    read_error_exit();
163 	buf[0] = CAR;
164 	retval = 1;
165 	goto theend;
166     }
167 #endif
168 
169     /* If we are going to wait for some time or block... */
170     if (wtime == -1 || wtime > 100L)
171     {
172 	/* ... allow signals to kill us. */
173 	(void)vim_handle_signal(SIGNAL_UNBLOCK);
174 
175 	/* ... there is no need for CTRL-C to interrupt something, don't let
176 	 * it set got_int when it was mapped. */
177 	if (mapped_ctrl_c)
178 	    ctrl_c_interrupts = FALSE;
179     }
180 
181 #ifdef FEAT_GUI
182     if (gui.in_use)
183     {
184 	if (gui_wait_for_chars(wtime) && !typebuf_changed(tb_change_cnt))
185 	    retval = read_from_input_buf(buf, (long)maxlen);
186     }
187 #endif
188 #ifndef NO_CONSOLE
189 # ifdef FEAT_GUI
190     else
191 # endif
192     {
193 	retval = mch_inchar(buf, maxlen, wtime, tb_change_cnt);
194     }
195 #endif
196 
197     if (wtime == -1 || wtime > 100L)
198 	/* block SIGHUP et al. */
199 	(void)vim_handle_signal(SIGNAL_BLOCK);
200 
201     ctrl_c_interrupts = TRUE;
202 
203 #ifdef NO_CONSOLE_INPUT
204 theend:
205 #endif
206 #ifdef FEAT_PROFILE
207     if (do_profiling == PROF_YES && wtime != 0)
208 	prof_inchar_exit();
209 #endif
210     return retval;
211 }
212 
213 /*
214  * return non-zero if a character is available
215  */
216     int
217 ui_char_avail()
218 {
219 #ifdef FEAT_GUI
220     if (gui.in_use)
221     {
222 	gui_mch_update();
223 	return input_available();
224     }
225 #endif
226 #ifndef NO_CONSOLE
227 # ifdef NO_CONSOLE_INPUT
228     if (no_console_input())
229 	return 0;
230 # endif
231     return mch_char_avail();
232 #else
233     return 0;
234 #endif
235 }
236 
237 /*
238  * Delay for the given number of milliseconds.	If ignoreinput is FALSE then we
239  * cancel the delay if a key is hit.
240  */
241     void
242 ui_delay(msec, ignoreinput)
243     long	msec;
244     int		ignoreinput;
245 {
246 #ifdef FEAT_GUI
247     if (gui.in_use && !ignoreinput)
248 	gui_wait_for_chars(msec);
249     else
250 #endif
251 	mch_delay(msec, ignoreinput);
252 }
253 
254 /*
255  * If the machine has job control, use it to suspend the program,
256  * otherwise fake it by starting a new shell.
257  * When running the GUI iconify the window.
258  */
259     void
260 ui_suspend()
261 {
262 #ifdef FEAT_GUI
263     if (gui.in_use)
264     {
265 	gui_mch_iconify();
266 	return;
267     }
268 #endif
269     mch_suspend();
270 }
271 
272 #if !defined(UNIX) || !defined(SIGTSTP) || defined(PROTO) || defined(__BEOS__)
273 /*
274  * When the OS can't really suspend, call this function to start a shell.
275  * This is never called in the GUI.
276  */
277     void
278 suspend_shell()
279 {
280     if (*p_sh == NUL)
281 	EMSG(_(e_shellempty));
282     else
283     {
284 	MSG_PUTS(_("new shell started\n"));
285 	do_shell(NULL, 0);
286     }
287 }
288 #endif
289 
290 /*
291  * Try to get the current Vim shell size.  Put the result in Rows and Columns.
292  * Use the new sizes as defaults for 'columns' and 'lines'.
293  * Return OK when size could be determined, FAIL otherwise.
294  */
295     int
296 ui_get_shellsize()
297 {
298     int	    retval;
299 
300 #ifdef FEAT_GUI
301     if (gui.in_use)
302 	retval = gui_get_shellsize();
303     else
304 #endif
305 	retval = mch_get_shellsize();
306 
307     check_shellsize();
308 
309     /* adjust the default for 'lines' and 'columns' */
310     if (retval == OK)
311     {
312 	set_number_default("lines", Rows);
313 	set_number_default("columns", Columns);
314     }
315     return retval;
316 }
317 
318 /*
319  * Set the size of the Vim shell according to Rows and Columns, if possible.
320  * The gui_set_shellsize() or mch_set_shellsize() function will try to set the
321  * new size.  If this is not possible, it will adjust Rows and Columns.
322  */
323     void
324 ui_set_shellsize(mustset)
325     int		mustset UNUSED;	/* set by the user */
326 {
327 #ifdef FEAT_GUI
328     if (gui.in_use)
329 	gui_set_shellsize(mustset,
330 # ifdef WIN3264
331 		TRUE
332 # else
333 		FALSE
334 # endif
335 		, RESIZE_BOTH);
336     else
337 #endif
338 	mch_set_shellsize();
339 }
340 
341 /*
342  * Called when Rows and/or Columns changed.  Adjust scroll region and mouse
343  * region.
344  */
345     void
346 ui_new_shellsize()
347 {
348     if (full_screen && !exiting)
349     {
350 #ifdef FEAT_GUI
351 	if (gui.in_use)
352 	    gui_new_shellsize();
353 	else
354 #endif
355 	    mch_new_shellsize();
356     }
357 }
358 
359     void
360 ui_breakcheck()
361 {
362 #ifdef FEAT_GUI
363     if (gui.in_use)
364 	gui_mch_update();
365     else
366 #endif
367 	mch_breakcheck();
368 }
369 
370 /*****************************************************************************
371  * Functions for copying and pasting text between applications.
372  * This is always included in a GUI version, but may also be included when the
373  * clipboard and mouse is available to a terminal version such as xterm.
374  * Note: there are some more functions in ops.c that handle selection stuff.
375  *
376  * Also note that the majority of functions here deal with the X 'primary'
377  * (visible - for Visual mode use) selection, and only that. There are no
378  * versions of these for the 'clipboard' selection, as Visual mode has no use
379  * for them.
380  */
381 
382 #if defined(FEAT_CLIPBOARD) || defined(PROTO)
383 
384 static void clip_copy_selection __ARGS((VimClipboard *clip));
385 
386 /*
387  * Selection stuff using Visual mode, for cutting and pasting text to other
388  * windows.
389  */
390 
391 /*
392  * Call this to initialise the clipboard.  Pass it FALSE if the clipboard code
393  * is included, but the clipboard can not be used, or TRUE if the clipboard can
394  * be used.  Eg unix may call this with FALSE, then call it again with TRUE if
395  * the GUI starts.
396  */
397     void
398 clip_init(can_use)
399     int	    can_use;
400 {
401     VimClipboard *cb;
402 
403     cb = &clip_star;
404     for (;;)
405     {
406 	cb->available  = can_use;
407 	cb->owned      = FALSE;
408 	cb->start.lnum = 0;
409 	cb->start.col  = 0;
410 	cb->end.lnum   = 0;
411 	cb->end.col    = 0;
412 	cb->state      = SELECT_CLEARED;
413 
414 	if (cb == &clip_plus)
415 	    break;
416 	cb = &clip_plus;
417     }
418 }
419 
420 /*
421  * Check whether the VIsual area has changed, and if so try to become the owner
422  * of the selection, and free any old converted selection we may still have
423  * lying around.  If the VIsual mode has ended, make a copy of what was
424  * selected so we can still give it to others.	Will probably have to make sure
425  * this is called whenever VIsual mode is ended.
426  */
427     void
428 clip_update_selection(clip)
429     VimClipboard    *clip;
430 {
431     pos_T	    start, end;
432 
433     /* If visual mode is only due to a redo command ("."), then ignore it */
434     if (!redo_VIsual_busy && VIsual_active && (State & NORMAL))
435     {
436 	if (lt(VIsual, curwin->w_cursor))
437 	{
438 	    start = VIsual;
439 	    end = curwin->w_cursor;
440 #ifdef FEAT_MBYTE
441 	    if (has_mbyte)
442 		end.col += (*mb_ptr2len)(ml_get_cursor()) - 1;
443 #endif
444 	}
445 	else
446 	{
447 	    start = curwin->w_cursor;
448 	    end = VIsual;
449 	}
450 	if (!equalpos(clip->start, start)
451 		|| !equalpos(clip->end, end)
452 		|| clip->vmode != VIsual_mode)
453 	{
454 	    clip_clear_selection(clip);
455 	    clip->start = start;
456 	    clip->end = end;
457 	    clip->vmode = VIsual_mode;
458 	    clip_free_selection(clip);
459 	    clip_own_selection(clip);
460 	    clip_gen_set_selection(clip);
461 	}
462     }
463 }
464 
465     void
466 clip_own_selection(cbd)
467     VimClipboard	*cbd;
468 {
469     /*
470      * Also want to check somehow that we are reading from the keyboard rather
471      * than a mapping etc.
472      */
473 #ifdef FEAT_X11
474     /* Always own the selection, we might have lost it without being
475      * notified, e.g. during a ":sh" command. */
476     if (cbd->available)
477     {
478 	int was_owned = cbd->owned;
479 
480 	cbd->owned = (clip_gen_own_selection(cbd) == OK);
481 	if (!was_owned && (cbd == &clip_star || cbd == &clip_plus))
482 	{
483 	    /* May have to show a different kind of highlighting for the
484 	     * selected area.  There is no specific redraw command for this,
485 	     * just redraw all windows on the current buffer. */
486 	    if (cbd->owned
487 		    && (get_real_state() == VISUAL
488 					    || get_real_state() == SELECTMODE)
489 		    && (cbd == &clip_star ? clip_isautosel_star()
490 						      : clip_isautosel_plus())
491 		    && hl_attr(HLF_V) != hl_attr(HLF_VNC))
492 		redraw_curbuf_later(INVERTED_ALL);
493 	}
494     }
495 #else
496     /* Only own the clibpard when we didn't own it yet. */
497     if (!cbd->owned && cbd->available)
498 	cbd->owned = (clip_gen_own_selection(cbd) == OK);
499 #endif
500 }
501 
502     void
503 clip_lose_selection(cbd)
504     VimClipboard	*cbd;
505 {
506 #ifdef FEAT_X11
507     int	    was_owned = cbd->owned;
508 #endif
509     int     visual_selection = FALSE;
510 
511     if (cbd == &clip_star || cbd == &clip_plus)
512 	visual_selection = TRUE;
513 
514     clip_free_selection(cbd);
515     cbd->owned = FALSE;
516     if (visual_selection)
517 	clip_clear_selection(cbd);
518     clip_gen_lose_selection(cbd);
519 #ifdef FEAT_X11
520     if (visual_selection)
521     {
522 	/* May have to show a different kind of highlighting for the selected
523 	 * area.  There is no specific redraw command for this, just redraw all
524 	 * windows on the current buffer. */
525 	if (was_owned
526 		&& (get_real_state() == VISUAL
527 					    || get_real_state() == SELECTMODE)
528 		&& (cbd == &clip_star ?
529 				clip_isautosel_star() : clip_isautosel_plus())
530 		&& hl_attr(HLF_V) != hl_attr(HLF_VNC))
531 	{
532 	    update_curbuf(INVERTED_ALL);
533 	    setcursor();
534 	    cursor_on();
535 	    out_flush();
536 # ifdef FEAT_GUI
537 	    if (gui.in_use)
538 		gui_update_cursor(TRUE, FALSE);
539 # endif
540 	}
541     }
542 #endif
543 }
544 
545     static void
546 clip_copy_selection(clip)
547     VimClipboard	*clip;
548 {
549     if (VIsual_active && (State & NORMAL) && clip->available)
550     {
551 	clip_update_selection(clip);
552 	clip_free_selection(clip);
553 	clip_own_selection(clip);
554 	if (clip->owned)
555 	    clip_get_selection(clip);
556 	clip_gen_set_selection(clip);
557     }
558 }
559 
560 /*
561  * Called when Visual mode is ended: update the selection.
562  */
563     void
564 clip_auto_select()
565 {
566     if (clip_isautosel_star())
567 	clip_copy_selection(&clip_star);
568     if (clip_isautosel_plus())
569 	clip_copy_selection(&clip_plus);
570 }
571 
572 /*
573  * Return TRUE if automatic selection of Visual area is desired for the *
574  * register.
575  */
576     int
577 clip_isautosel_star()
578 {
579     return (
580 #ifdef FEAT_GUI
581 	    gui.in_use ? (vim_strchr(p_go, GO_ASEL) != NULL) :
582 #endif
583 	    clip_autoselect_star);
584 }
585 
586 /*
587  * Return TRUE if automatic selection of Visual area is desired for the +
588  * register.
589  */
590     int
591 clip_isautosel_plus()
592 {
593     return (
594 #ifdef FEAT_GUI
595 	    gui.in_use ? (vim_strchr(p_go, GO_ASELPLUS) != NULL) :
596 #endif
597 	    clip_autoselect_plus);
598 }
599 
600 
601 /*
602  * Stuff for general mouse selection, without using Visual mode.
603  */
604 
605 static int clip_compare_pos __ARGS((int row1, int col1, int row2, int col2));
606 static void clip_invert_area __ARGS((int, int, int, int, int how));
607 static void clip_invert_rectangle __ARGS((int row, int col, int height, int width, int invert));
608 static void clip_get_word_boundaries __ARGS((VimClipboard *, int, int));
609 static int  clip_get_line_end __ARGS((int));
610 static void clip_update_modeless_selection __ARGS((VimClipboard *, int, int,
611 						    int, int));
612 
613 /* flags for clip_invert_area() */
614 #define CLIP_CLEAR	1
615 #define CLIP_SET	2
616 #define CLIP_TOGGLE	3
617 
618 /*
619  * Start, continue or end a modeless selection.  Used when editing the
620  * command-line and in the cmdline window.
621  */
622     void
623 clip_modeless(button, is_click, is_drag)
624     int		button;
625     int		is_click;
626     int		is_drag;
627 {
628     int		repeat;
629 
630     repeat = ((clip_star.mode == SELECT_MODE_CHAR
631 		|| clip_star.mode == SELECT_MODE_LINE)
632 					      && (mod_mask & MOD_MASK_2CLICK))
633 	    || (clip_star.mode == SELECT_MODE_WORD
634 					     && (mod_mask & MOD_MASK_3CLICK));
635     if (is_click && button == MOUSE_RIGHT)
636     {
637 	/* Right mouse button: If there was no selection, start one.
638 	 * Otherwise extend the existing selection. */
639 	if (clip_star.state == SELECT_CLEARED)
640 	    clip_start_selection(mouse_col, mouse_row, FALSE);
641 	clip_process_selection(button, mouse_col, mouse_row, repeat);
642     }
643     else if (is_click)
644 	clip_start_selection(mouse_col, mouse_row, repeat);
645     else if (is_drag)
646     {
647 	/* Don't try extending a selection if there isn't one.  Happens when
648 	 * button-down is in the cmdline and them moving mouse upwards. */
649 	if (clip_star.state != SELECT_CLEARED)
650 	    clip_process_selection(button, mouse_col, mouse_row, repeat);
651     }
652     else /* release */
653 	clip_process_selection(MOUSE_RELEASE, mouse_col, mouse_row, FALSE);
654 }
655 
656 /*
657  * Compare two screen positions ala strcmp()
658  */
659     static int
660 clip_compare_pos(row1, col1, row2, col2)
661     int		row1;
662     int		col1;
663     int		row2;
664     int		col2;
665 {
666     if (row1 > row2) return(1);
667     if (row1 < row2) return(-1);
668     if (col1 > col2) return(1);
669     if (col1 < col2) return(-1);
670 		     return(0);
671 }
672 
673 /*
674  * Start the selection
675  */
676     void
677 clip_start_selection(col, row, repeated_click)
678     int		col;
679     int		row;
680     int		repeated_click;
681 {
682     VimClipboard	*cb = &clip_star;
683 
684     if (cb->state == SELECT_DONE)
685 	clip_clear_selection(cb);
686 
687     row = check_row(row);
688     col = check_col(col);
689 #ifdef FEAT_MBYTE
690     col = mb_fix_col(col, row);
691 #endif
692 
693     cb->start.lnum  = row;
694     cb->start.col   = col;
695     cb->end	    = cb->start;
696     cb->origin_row  = (short_u)cb->start.lnum;
697     cb->state	    = SELECT_IN_PROGRESS;
698 
699     if (repeated_click)
700     {
701 	if (++cb->mode > SELECT_MODE_LINE)
702 	    cb->mode = SELECT_MODE_CHAR;
703     }
704     else
705 	cb->mode = SELECT_MODE_CHAR;
706 
707 #ifdef FEAT_GUI
708     /* clear the cursor until the selection is made */
709     if (gui.in_use)
710 	gui_undraw_cursor();
711 #endif
712 
713     switch (cb->mode)
714     {
715 	case SELECT_MODE_CHAR:
716 	    cb->origin_start_col = cb->start.col;
717 	    cb->word_end_col = clip_get_line_end((int)cb->start.lnum);
718 	    break;
719 
720 	case SELECT_MODE_WORD:
721 	    clip_get_word_boundaries(cb, (int)cb->start.lnum, cb->start.col);
722 	    cb->origin_start_col = cb->word_start_col;
723 	    cb->origin_end_col	 = cb->word_end_col;
724 
725 	    clip_invert_area((int)cb->start.lnum, cb->word_start_col,
726 			    (int)cb->end.lnum, cb->word_end_col, CLIP_SET);
727 	    cb->start.col = cb->word_start_col;
728 	    cb->end.col   = cb->word_end_col;
729 	    break;
730 
731 	case SELECT_MODE_LINE:
732 	    clip_invert_area((int)cb->start.lnum, 0, (int)cb->start.lnum,
733 			    (int)Columns, CLIP_SET);
734 	    cb->start.col = 0;
735 	    cb->end.col   = Columns;
736 	    break;
737     }
738 
739     cb->prev = cb->start;
740 
741 #ifdef DEBUG_SELECTION
742     printf("Selection started at (%u,%u)\n", cb->start.lnum, cb->start.col);
743 #endif
744 }
745 
746 /*
747  * Continue processing the selection
748  */
749     void
750 clip_process_selection(button, col, row, repeated_click)
751     int		button;
752     int		col;
753     int		row;
754     int_u	repeated_click;
755 {
756     VimClipboard	*cb = &clip_star;
757     int			diff;
758     int			slen = 1;	/* cursor shape width */
759 
760     if (button == MOUSE_RELEASE)
761     {
762 	/* Check to make sure we have something selected */
763 	if (cb->start.lnum == cb->end.lnum && cb->start.col == cb->end.col)
764 	{
765 #ifdef FEAT_GUI
766 	    if (gui.in_use)
767 		gui_update_cursor(FALSE, FALSE);
768 #endif
769 	    cb->state = SELECT_CLEARED;
770 	    return;
771 	}
772 
773 #ifdef DEBUG_SELECTION
774 	printf("Selection ended: (%u,%u) to (%u,%u)\n", cb->start.lnum,
775 		cb->start.col, cb->end.lnum, cb->end.col);
776 #endif
777 	if (clip_isautosel_star()
778 		|| (
779 #ifdef FEAT_GUI
780 		    gui.in_use ? (vim_strchr(p_go, GO_ASELML) != NULL) :
781 #endif
782 		    clip_autoselectml))
783 	    clip_copy_modeless_selection(FALSE);
784 #ifdef FEAT_GUI
785 	if (gui.in_use)
786 	    gui_update_cursor(FALSE, FALSE);
787 #endif
788 
789 	cb->state = SELECT_DONE;
790 	return;
791     }
792 
793     row = check_row(row);
794     col = check_col(col);
795 #ifdef FEAT_MBYTE
796     col = mb_fix_col(col, row);
797 #endif
798 
799     if (col == (int)cb->prev.col && row == cb->prev.lnum && !repeated_click)
800 	return;
801 
802     /*
803      * When extending the selection with the right mouse button, swap the
804      * start and end if the position is before half the selection
805      */
806     if (cb->state == SELECT_DONE && button == MOUSE_RIGHT)
807     {
808 	/*
809 	 * If the click is before the start, or the click is inside the
810 	 * selection and the start is the closest side, set the origin to the
811 	 * end of the selection.
812 	 */
813 	if (clip_compare_pos(row, col, (int)cb->start.lnum, cb->start.col) < 0
814 		|| (clip_compare_pos(row, col,
815 					   (int)cb->end.lnum, cb->end.col) < 0
816 		    && (((cb->start.lnum == cb->end.lnum
817 			    && cb->end.col - col > col - cb->start.col))
818 			|| ((diff = (cb->end.lnum - row) -
819 						   (row - cb->start.lnum)) > 0
820 			    || (diff == 0 && col < (int)(cb->start.col +
821 							 cb->end.col) / 2)))))
822 	{
823 	    cb->origin_row = (short_u)cb->end.lnum;
824 	    cb->origin_start_col = cb->end.col - 1;
825 	    cb->origin_end_col = cb->end.col;
826 	}
827 	else
828 	{
829 	    cb->origin_row = (short_u)cb->start.lnum;
830 	    cb->origin_start_col = cb->start.col;
831 	    cb->origin_end_col = cb->start.col;
832 	}
833 	if (cb->mode == SELECT_MODE_WORD && !repeated_click)
834 	    cb->mode = SELECT_MODE_CHAR;
835     }
836 
837     /* set state, for when using the right mouse button */
838     cb->state = SELECT_IN_PROGRESS;
839 
840 #ifdef DEBUG_SELECTION
841     printf("Selection extending to (%d,%d)\n", row, col);
842 #endif
843 
844     if (repeated_click && ++cb->mode > SELECT_MODE_LINE)
845 	cb->mode = SELECT_MODE_CHAR;
846 
847     switch (cb->mode)
848     {
849 	case SELECT_MODE_CHAR:
850 	    /* If we're on a different line, find where the line ends */
851 	    if (row != cb->prev.lnum)
852 		cb->word_end_col = clip_get_line_end(row);
853 
854 	    /* See if we are before or after the origin of the selection */
855 	    if (clip_compare_pos(row, col, cb->origin_row,
856 						   cb->origin_start_col) >= 0)
857 	    {
858 		if (col >= (int)cb->word_end_col)
859 		    clip_update_modeless_selection(cb, cb->origin_row,
860 			    cb->origin_start_col, row, (int)Columns);
861 		else
862 		{
863 #ifdef FEAT_MBYTE
864 		    if (has_mbyte && mb_lefthalve(row, col))
865 			slen = 2;
866 #endif
867 		    clip_update_modeless_selection(cb, cb->origin_row,
868 			    cb->origin_start_col, row, col + slen);
869 		}
870 	    }
871 	    else
872 	    {
873 #ifdef FEAT_MBYTE
874 		if (has_mbyte
875 			&& mb_lefthalve(cb->origin_row, cb->origin_start_col))
876 		    slen = 2;
877 #endif
878 		if (col >= (int)cb->word_end_col)
879 		    clip_update_modeless_selection(cb, row, cb->word_end_col,
880 			    cb->origin_row, cb->origin_start_col + slen);
881 		else
882 		    clip_update_modeless_selection(cb, row, col,
883 			    cb->origin_row, cb->origin_start_col + slen);
884 	    }
885 	    break;
886 
887 	case SELECT_MODE_WORD:
888 	    /* If we are still within the same word, do nothing */
889 	    if (row == cb->prev.lnum && col >= (int)cb->word_start_col
890 		    && col < (int)cb->word_end_col && !repeated_click)
891 		return;
892 
893 	    /* Get new word boundaries */
894 	    clip_get_word_boundaries(cb, row, col);
895 
896 	    /* Handle being after the origin point of selection */
897 	    if (clip_compare_pos(row, col, cb->origin_row,
898 		    cb->origin_start_col) >= 0)
899 		clip_update_modeless_selection(cb, cb->origin_row,
900 			cb->origin_start_col, row, cb->word_end_col);
901 	    else
902 		clip_update_modeless_selection(cb, row, cb->word_start_col,
903 			cb->origin_row, cb->origin_end_col);
904 	    break;
905 
906 	case SELECT_MODE_LINE:
907 	    if (row == cb->prev.lnum && !repeated_click)
908 		return;
909 
910 	    if (clip_compare_pos(row, col, cb->origin_row,
911 		    cb->origin_start_col) >= 0)
912 		clip_update_modeless_selection(cb, cb->origin_row, 0, row,
913 			(int)Columns);
914 	    else
915 		clip_update_modeless_selection(cb, row, 0, cb->origin_row,
916 			(int)Columns);
917 	    break;
918     }
919 
920     cb->prev.lnum = row;
921     cb->prev.col  = col;
922 
923 #ifdef DEBUG_SELECTION
924 	printf("Selection is: (%u,%u) to (%u,%u)\n", cb->start.lnum,
925 		cb->start.col, cb->end.lnum, cb->end.col);
926 #endif
927 }
928 
929 # if defined(FEAT_GUI) || defined(PROTO)
930 /*
931  * Redraw part of the selection if character at "row,col" is inside of it.
932  * Only used for the GUI.
933  */
934     void
935 clip_may_redraw_selection(row, col, len)
936     int		row, col;
937     int		len;
938 {
939     int		start = col;
940     int		end = col + len;
941 
942     if (clip_star.state != SELECT_CLEARED
943 	    && row >= clip_star.start.lnum
944 	    && row <= clip_star.end.lnum)
945     {
946 	if (row == clip_star.start.lnum && start < (int)clip_star.start.col)
947 	    start = clip_star.start.col;
948 	if (row == clip_star.end.lnum && end > (int)clip_star.end.col)
949 	    end = clip_star.end.col;
950 	if (end > start)
951 	    clip_invert_area(row, start, row, end, 0);
952     }
953 }
954 # endif
955 
956 /*
957  * Called from outside to clear selected region from the display
958  */
959     void
960 clip_clear_selection(cbd)
961     VimClipboard    *cbd;
962 {
963 
964     if (cbd->state == SELECT_CLEARED)
965 	return;
966 
967     clip_invert_area((int)cbd->start.lnum, cbd->start.col, (int)cbd->end.lnum,
968 						     cbd->end.col, CLIP_CLEAR);
969     cbd->state = SELECT_CLEARED;
970 }
971 
972 /*
973  * Clear the selection if any lines from "row1" to "row2" are inside of it.
974  */
975     void
976 clip_may_clear_selection(row1, row2)
977     int	row1, row2;
978 {
979     if (clip_star.state == SELECT_DONE
980 	    && row2 >= clip_star.start.lnum
981 	    && row1 <= clip_star.end.lnum)
982 	clip_clear_selection(&clip_star);
983 }
984 
985 /*
986  * Called before the screen is scrolled up or down.  Adjusts the line numbers
987  * of the selection.  Call with big number when clearing the screen.
988  */
989     void
990 clip_scroll_selection(rows)
991     int	    rows;		/* negative for scroll down */
992 {
993     int	    lnum;
994 
995     if (clip_star.state == SELECT_CLEARED)
996 	return;
997 
998     lnum = clip_star.start.lnum - rows;
999     if (lnum <= 0)
1000 	clip_star.start.lnum = 0;
1001     else if (lnum >= screen_Rows)	/* scrolled off of the screen */
1002 	clip_star.state = SELECT_CLEARED;
1003     else
1004 	clip_star.start.lnum = lnum;
1005 
1006     lnum = clip_star.end.lnum - rows;
1007     if (lnum < 0)			/* scrolled off of the screen */
1008 	clip_star.state = SELECT_CLEARED;
1009     else if (lnum >= screen_Rows)
1010 	clip_star.end.lnum = screen_Rows - 1;
1011     else
1012 	clip_star.end.lnum = lnum;
1013 }
1014 
1015 /*
1016  * Invert a region of the display between a starting and ending row and column
1017  * Values for "how":
1018  * CLIP_CLEAR:  undo inversion
1019  * CLIP_SET:    set inversion
1020  * CLIP_TOGGLE: set inversion if pos1 < pos2, undo inversion otherwise.
1021  * 0: invert (GUI only).
1022  */
1023     static void
1024 clip_invert_area(row1, col1, row2, col2, how)
1025     int		row1;
1026     int		col1;
1027     int		row2;
1028     int		col2;
1029     int		how;
1030 {
1031     int		invert = FALSE;
1032 
1033     if (how == CLIP_SET)
1034 	invert = TRUE;
1035 
1036     /* Swap the from and to positions so the from is always before */
1037     if (clip_compare_pos(row1, col1, row2, col2) > 0)
1038     {
1039 	int tmp_row, tmp_col;
1040 
1041 	tmp_row = row1;
1042 	tmp_col = col1;
1043 	row1	= row2;
1044 	col1	= col2;
1045 	row2	= tmp_row;
1046 	col2	= tmp_col;
1047     }
1048     else if (how == CLIP_TOGGLE)
1049 	invert = TRUE;
1050 
1051     /* If all on the same line, do it the easy way */
1052     if (row1 == row2)
1053     {
1054 	clip_invert_rectangle(row1, col1, 1, col2 - col1, invert);
1055     }
1056     else
1057     {
1058 	/* Handle a piece of the first line */
1059 	if (col1 > 0)
1060 	{
1061 	    clip_invert_rectangle(row1, col1, 1, (int)Columns - col1, invert);
1062 	    row1++;
1063 	}
1064 
1065 	/* Handle a piece of the last line */
1066 	if (col2 < Columns - 1)
1067 	{
1068 	    clip_invert_rectangle(row2, 0, 1, col2, invert);
1069 	    row2--;
1070 	}
1071 
1072 	/* Handle the rectangle thats left */
1073 	if (row2 >= row1)
1074 	    clip_invert_rectangle(row1, 0, row2 - row1 + 1, (int)Columns,
1075 								      invert);
1076     }
1077 }
1078 
1079 /*
1080  * Invert or un-invert a rectangle of the screen.
1081  * "invert" is true if the result is inverted.
1082  */
1083     static void
1084 clip_invert_rectangle(row, col, height, width, invert)
1085     int		row;
1086     int		col;
1087     int		height;
1088     int		width;
1089     int		invert;
1090 {
1091 #ifdef FEAT_GUI
1092     if (gui.in_use)
1093 	gui_mch_invert_rectangle(row, col, height, width);
1094     else
1095 #endif
1096 	screen_draw_rectangle(row, col, height, width, invert);
1097 }
1098 
1099 /*
1100  * Copy the currently selected area into the '*' register so it will be
1101  * available for pasting.
1102  * When "both" is TRUE also copy to the '+' register.
1103  */
1104     void
1105 clip_copy_modeless_selection(both)
1106     int		both UNUSED;
1107 {
1108     char_u	*buffer;
1109     char_u	*bufp;
1110     int		row;
1111     int		start_col;
1112     int		end_col;
1113     int		line_end_col;
1114     int		add_newline_flag = FALSE;
1115     int		len;
1116 #ifdef FEAT_MBYTE
1117     char_u	*p;
1118 #endif
1119     int		row1 = clip_star.start.lnum;
1120     int		col1 = clip_star.start.col;
1121     int		row2 = clip_star.end.lnum;
1122     int		col2 = clip_star.end.col;
1123 
1124     /* Can't use ScreenLines unless initialized */
1125     if (ScreenLines == NULL)
1126 	return;
1127 
1128     /*
1129      * Make sure row1 <= row2, and if row1 == row2 that col1 <= col2.
1130      */
1131     if (row1 > row2)
1132     {
1133 	row = row1; row1 = row2; row2 = row;
1134 	row = col1; col1 = col2; col2 = row;
1135     }
1136     else if (row1 == row2 && col1 > col2)
1137     {
1138 	row = col1; col1 = col2; col2 = row;
1139     }
1140 #ifdef FEAT_MBYTE
1141     /* correct starting point for being on right halve of double-wide char */
1142     p = ScreenLines + LineOffset[row1];
1143     if (enc_dbcs != 0)
1144 	col1 -= (*mb_head_off)(p, p + col1);
1145     else if (enc_utf8 && p[col1] == 0)
1146 	--col1;
1147 #endif
1148 
1149     /* Create a temporary buffer for storing the text */
1150     len = (row2 - row1 + 1) * Columns + 1;
1151 #ifdef FEAT_MBYTE
1152     if (enc_dbcs != 0)
1153 	len *= 2;	/* max. 2 bytes per display cell */
1154     else if (enc_utf8)
1155 	len *= MB_MAXBYTES;
1156 #endif
1157     buffer = lalloc((long_u)len, TRUE);
1158     if (buffer == NULL)	    /* out of memory */
1159 	return;
1160 
1161     /* Process each row in the selection */
1162     for (bufp = buffer, row = row1; row <= row2; row++)
1163     {
1164 	if (row == row1)
1165 	    start_col = col1;
1166 	else
1167 	    start_col = 0;
1168 
1169 	if (row == row2)
1170 	    end_col = col2;
1171 	else
1172 	    end_col = Columns;
1173 
1174 	line_end_col = clip_get_line_end(row);
1175 
1176 	/* See if we need to nuke some trailing whitespace */
1177 	if (end_col >= Columns && (row < row2 || end_col > line_end_col))
1178 	{
1179 	    /* Get rid of trailing whitespace */
1180 	    end_col = line_end_col;
1181 	    if (end_col < start_col)
1182 		end_col = start_col;
1183 
1184 	    /* If the last line extended to the end, add an extra newline */
1185 	    if (row == row2)
1186 		add_newline_flag = TRUE;
1187 	}
1188 
1189 	/* If after the first row, we need to always add a newline */
1190 	if (row > row1 && !LineWraps[row - 1])
1191 	    *bufp++ = NL;
1192 
1193 	if (row < screen_Rows && end_col <= screen_Columns)
1194 	{
1195 #ifdef FEAT_MBYTE
1196 	    if (enc_dbcs != 0)
1197 	    {
1198 		int	i;
1199 
1200 		p = ScreenLines + LineOffset[row];
1201 		for (i = start_col; i < end_col; ++i)
1202 		    if (enc_dbcs == DBCS_JPNU && p[i] == 0x8e)
1203 		    {
1204 			/* single-width double-byte char */
1205 			*bufp++ = 0x8e;
1206 			*bufp++ = ScreenLines2[LineOffset[row] + i];
1207 		    }
1208 		    else
1209 		    {
1210 			*bufp++ = p[i];
1211 			if (MB_BYTE2LEN(p[i]) == 2)
1212 			    *bufp++ = p[++i];
1213 		    }
1214 	    }
1215 	    else if (enc_utf8)
1216 	    {
1217 		int	off;
1218 		int	i;
1219 		int	ci;
1220 
1221 		off = LineOffset[row];
1222 		for (i = start_col; i < end_col; ++i)
1223 		{
1224 		    /* The base character is either in ScreenLinesUC[] or
1225 		     * ScreenLines[]. */
1226 		    if (ScreenLinesUC[off + i] == 0)
1227 			*bufp++ = ScreenLines[off + i];
1228 		    else
1229 		    {
1230 			bufp += utf_char2bytes(ScreenLinesUC[off + i], bufp);
1231 			for (ci = 0; ci < Screen_mco; ++ci)
1232 			{
1233 			    /* Add a composing character. */
1234 			    if (ScreenLinesC[ci][off + i] == 0)
1235 				break;
1236 			    bufp += utf_char2bytes(ScreenLinesC[ci][off + i],
1237 									bufp);
1238 			}
1239 		    }
1240 		    /* Skip right halve of double-wide character. */
1241 		    if (ScreenLines[off + i + 1] == 0)
1242 			++i;
1243 		}
1244 	    }
1245 	    else
1246 #endif
1247 	    {
1248 		STRNCPY(bufp, ScreenLines + LineOffset[row] + start_col,
1249 							 end_col - start_col);
1250 		bufp += end_col - start_col;
1251 	    }
1252 	}
1253     }
1254 
1255     /* Add a newline at the end if the selection ended there */
1256     if (add_newline_flag)
1257 	*bufp++ = NL;
1258 
1259     /* First cleanup any old selection and become the owner. */
1260     clip_free_selection(&clip_star);
1261     clip_own_selection(&clip_star);
1262 
1263     /* Yank the text into the '*' register. */
1264     clip_yank_selection(MCHAR, buffer, (long)(bufp - buffer), &clip_star);
1265 
1266     /* Make the register contents available to the outside world. */
1267     clip_gen_set_selection(&clip_star);
1268 
1269 #ifdef FEAT_X11
1270     if (both)
1271     {
1272 	/* Do the same for the '+' register. */
1273 	clip_free_selection(&clip_plus);
1274 	clip_own_selection(&clip_plus);
1275 	clip_yank_selection(MCHAR, buffer, (long)(bufp - buffer), &clip_plus);
1276 	clip_gen_set_selection(&clip_plus);
1277     }
1278 #endif
1279     vim_free(buffer);
1280 }
1281 
1282 /*
1283  * Find the starting and ending positions of the word at the given row and
1284  * column.  Only white-separated words are recognized here.
1285  */
1286 #define CHAR_CLASS(c)	(c <= ' ' ? ' ' : vim_iswordc(c))
1287 
1288     static void
1289 clip_get_word_boundaries(cb, row, col)
1290     VimClipboard	*cb;
1291     int			row;
1292     int			col;
1293 {
1294     int		start_class;
1295     int		temp_col;
1296     char_u	*p;
1297 #ifdef FEAT_MBYTE
1298     int		mboff;
1299 #endif
1300 
1301     if (row >= screen_Rows || col >= screen_Columns || ScreenLines == NULL)
1302 	return;
1303 
1304     p = ScreenLines + LineOffset[row];
1305 #ifdef FEAT_MBYTE
1306     /* Correct for starting in the right halve of a double-wide char */
1307     if (enc_dbcs != 0)
1308 	col -= dbcs_screen_head_off(p, p + col);
1309     else if (enc_utf8 && p[col] == 0)
1310 	--col;
1311 #endif
1312     start_class = CHAR_CLASS(p[col]);
1313 
1314     temp_col = col;
1315     for ( ; temp_col > 0; temp_col--)
1316 #ifdef FEAT_MBYTE
1317 	if (enc_dbcs != 0
1318 		   && (mboff = dbcs_screen_head_off(p, p + temp_col - 1)) > 0)
1319 	    temp_col -= mboff;
1320 	else
1321 #endif
1322 	if (CHAR_CLASS(p[temp_col - 1]) != start_class
1323 #ifdef FEAT_MBYTE
1324 		&& !(enc_utf8 && p[temp_col - 1] == 0)
1325 #endif
1326 		)
1327 	    break;
1328     cb->word_start_col = temp_col;
1329 
1330     temp_col = col;
1331     for ( ; temp_col < screen_Columns; temp_col++)
1332 #ifdef FEAT_MBYTE
1333 	if (enc_dbcs != 0 && dbcs_ptr2cells(p + temp_col) == 2)
1334 	    ++temp_col;
1335 	else
1336 #endif
1337 	if (CHAR_CLASS(p[temp_col]) != start_class
1338 #ifdef FEAT_MBYTE
1339 		&& !(enc_utf8 && p[temp_col] == 0)
1340 #endif
1341 		)
1342 	    break;
1343     cb->word_end_col = temp_col;
1344 }
1345 
1346 /*
1347  * Find the column position for the last non-whitespace character on the given
1348  * line.
1349  */
1350     static int
1351 clip_get_line_end(row)
1352     int		row;
1353 {
1354     int	    i;
1355 
1356     if (row >= screen_Rows || ScreenLines == NULL)
1357 	return 0;
1358     for (i = screen_Columns; i > 0; i--)
1359 	if (ScreenLines[LineOffset[row] + i - 1] != ' ')
1360 	    break;
1361     return i;
1362 }
1363 
1364 /*
1365  * Update the currently selected region by adding and/or subtracting from the
1366  * beginning or end and inverting the changed area(s).
1367  */
1368     static void
1369 clip_update_modeless_selection(cb, row1, col1, row2, col2)
1370     VimClipboard    *cb;
1371     int		    row1;
1372     int		    col1;
1373     int		    row2;
1374     int		    col2;
1375 {
1376     /* See if we changed at the beginning of the selection */
1377     if (row1 != cb->start.lnum || col1 != (int)cb->start.col)
1378     {
1379 	clip_invert_area(row1, col1, (int)cb->start.lnum, cb->start.col,
1380 								 CLIP_TOGGLE);
1381 	cb->start.lnum = row1;
1382 	cb->start.col  = col1;
1383     }
1384 
1385     /* See if we changed at the end of the selection */
1386     if (row2 != cb->end.lnum || col2 != (int)cb->end.col)
1387     {
1388 	clip_invert_area((int)cb->end.lnum, cb->end.col, row2, col2,
1389 								 CLIP_TOGGLE);
1390 	cb->end.lnum = row2;
1391 	cb->end.col  = col2;
1392     }
1393 }
1394 
1395     int
1396 clip_gen_own_selection(cbd)
1397     VimClipboard	*cbd;
1398 {
1399 #ifdef FEAT_XCLIPBOARD
1400 # ifdef FEAT_GUI
1401     if (gui.in_use)
1402 	return clip_mch_own_selection(cbd);
1403     else
1404 # endif
1405 	return clip_xterm_own_selection(cbd);
1406 #else
1407     return clip_mch_own_selection(cbd);
1408 #endif
1409 }
1410 
1411     void
1412 clip_gen_lose_selection(cbd)
1413     VimClipboard	*cbd;
1414 {
1415 #ifdef FEAT_XCLIPBOARD
1416 # ifdef FEAT_GUI
1417     if (gui.in_use)
1418 	clip_mch_lose_selection(cbd);
1419     else
1420 # endif
1421 	clip_xterm_lose_selection(cbd);
1422 #else
1423     clip_mch_lose_selection(cbd);
1424 #endif
1425 }
1426 
1427     void
1428 clip_gen_set_selection(cbd)
1429     VimClipboard	*cbd;
1430 {
1431 #ifdef FEAT_XCLIPBOARD
1432 # ifdef FEAT_GUI
1433     if (gui.in_use)
1434 	clip_mch_set_selection(cbd);
1435     else
1436 # endif
1437 	clip_xterm_set_selection(cbd);
1438 #else
1439     clip_mch_set_selection(cbd);
1440 #endif
1441 }
1442 
1443     void
1444 clip_gen_request_selection(cbd)
1445     VimClipboard	*cbd;
1446 {
1447 #ifdef FEAT_XCLIPBOARD
1448 # ifdef FEAT_GUI
1449     if (gui.in_use)
1450 	clip_mch_request_selection(cbd);
1451     else
1452 # endif
1453 	clip_xterm_request_selection(cbd);
1454 #else
1455     clip_mch_request_selection(cbd);
1456 #endif
1457 }
1458 
1459 #endif /* FEAT_CLIPBOARD */
1460 
1461 /*****************************************************************************
1462  * Functions that handle the input buffer.
1463  * This is used for any GUI version, and the unix terminal version.
1464  *
1465  * For Unix, the input characters are buffered to be able to check for a
1466  * CTRL-C.  This should be done with signals, but I don't know how to do that
1467  * in a portable way for a tty in RAW mode.
1468  *
1469  * For the client-server code in the console the received keys are put in the
1470  * input buffer.
1471  */
1472 
1473 #if defined(USE_INPUT_BUF) || defined(PROTO)
1474 
1475 /*
1476  * Internal typeahead buffer.  Includes extra space for long key code
1477  * descriptions which would otherwise overflow.  The buffer is considered full
1478  * when only this extra space (or part of it) remains.
1479  */
1480 #if defined(FEAT_SUN_WORKSHOP) || defined(FEAT_NETBEANS_INTG) \
1481 	|| defined(FEAT_CLIENTSERVER)
1482    /*
1483     * Sun WorkShop and NetBeans stuff debugger commands into the input buffer.
1484     * This requires a larger buffer...
1485     * (Madsen) Go with this for remote input as well ...
1486     */
1487 # define INBUFLEN 4096
1488 #else
1489 # define INBUFLEN 250
1490 #endif
1491 
1492 static char_u	inbuf[INBUFLEN + MAX_KEY_CODE_LEN];
1493 static int	inbufcount = 0;	    /* number of chars in inbuf[] */
1494 
1495 /*
1496  * vim_is_input_buf_full(), vim_is_input_buf_empty(), add_to_input_buf(), and
1497  * trash_input_buf() are functions for manipulating the input buffer.  These
1498  * are used by the gui_* calls when a GUI is used to handle keyboard input.
1499  */
1500 
1501     int
1502 vim_is_input_buf_full()
1503 {
1504     return (inbufcount >= INBUFLEN);
1505 }
1506 
1507     int
1508 vim_is_input_buf_empty()
1509 {
1510     return (inbufcount == 0);
1511 }
1512 
1513 #if defined(FEAT_OLE) || defined(PROTO)
1514     int
1515 vim_free_in_input_buf()
1516 {
1517     return (INBUFLEN - inbufcount);
1518 }
1519 #endif
1520 
1521 #if defined(FEAT_GUI_GTK) || defined(PROTO)
1522     int
1523 vim_used_in_input_buf()
1524 {
1525     return inbufcount;
1526 }
1527 #endif
1528 
1529 #if defined(FEAT_EVAL) || defined(FEAT_EX_EXTRA) || defined(PROTO)
1530 /*
1531  * Return the current contents of the input buffer and make it empty.
1532  * The returned pointer must be passed to set_input_buf() later.
1533  */
1534     char_u *
1535 get_input_buf()
1536 {
1537     garray_T	*gap;
1538 
1539     /* We use a growarray to store the data pointer and the length. */
1540     gap = (garray_T *)alloc((unsigned)sizeof(garray_T));
1541     if (gap != NULL)
1542     {
1543 	/* Add one to avoid a zero size. */
1544 	gap->ga_data = alloc((unsigned)inbufcount + 1);
1545 	if (gap->ga_data != NULL)
1546 	    mch_memmove(gap->ga_data, inbuf, (size_t)inbufcount);
1547 	gap->ga_len = inbufcount;
1548     }
1549     trash_input_buf();
1550     return (char_u *)gap;
1551 }
1552 
1553 /*
1554  * Restore the input buffer with a pointer returned from get_input_buf().
1555  * The allocated memory is freed, this only works once!
1556  */
1557     void
1558 set_input_buf(p)
1559     char_u	*p;
1560 {
1561     garray_T	*gap = (garray_T *)p;
1562 
1563     if (gap != NULL)
1564     {
1565 	if (gap->ga_data != NULL)
1566 	{
1567 	    mch_memmove(inbuf, gap->ga_data, gap->ga_len);
1568 	    inbufcount = gap->ga_len;
1569 	    vim_free(gap->ga_data);
1570 	}
1571 	vim_free(gap);
1572     }
1573 }
1574 #endif
1575 
1576 #if defined(FEAT_GUI) \
1577 	|| defined(FEAT_MOUSE_GPM) || defined(FEAT_SYSMOUSE) \
1578 	|| defined(FEAT_XCLIPBOARD) || defined(VMS) \
1579 	|| defined(FEAT_SNIFF) || defined(FEAT_CLIENTSERVER) \
1580 	|| defined(PROTO)
1581 /*
1582  * Add the given bytes to the input buffer
1583  * Special keys start with CSI.  A real CSI must have been translated to
1584  * CSI KS_EXTRA KE_CSI.  K_SPECIAL doesn't require translation.
1585  */
1586     void
1587 add_to_input_buf(s, len)
1588     char_u  *s;
1589     int	    len;
1590 {
1591     if (inbufcount + len > INBUFLEN + MAX_KEY_CODE_LEN)
1592 	return;	    /* Shouldn't ever happen! */
1593 
1594 #ifdef FEAT_HANGULIN
1595     if ((State & (INSERT|CMDLINE)) && hangul_input_state_get())
1596 	if ((len = hangul_input_process(s, len)) == 0)
1597 	    return;
1598 #endif
1599 
1600     while (len--)
1601 	inbuf[inbufcount++] = *s++;
1602 }
1603 #endif
1604 
1605 #if ((defined(FEAT_XIM) || defined(FEAT_DND)) && defined(FEAT_GUI_GTK)) \
1606 	|| defined(FEAT_GUI_MSWIN) \
1607 	|| defined(FEAT_GUI_MAC) \
1608 	|| (defined(FEAT_MBYTE) && defined(FEAT_MBYTE_IME)) \
1609 	|| (defined(FEAT_GUI) && (!defined(USE_ON_FLY_SCROLL) \
1610 		|| defined(FEAT_MENU))) \
1611 	|| defined(PROTO)
1612 /*
1613  * Add "str[len]" to the input buffer while escaping CSI bytes.
1614  */
1615     void
1616 add_to_input_buf_csi(char_u *str, int len)
1617 {
1618     int		i;
1619     char_u	buf[2];
1620 
1621     for (i = 0; i < len; ++i)
1622     {
1623 	add_to_input_buf(str + i, 1);
1624 	if (str[i] == CSI)
1625 	{
1626 	    /* Turn CSI into K_CSI. */
1627 	    buf[0] = KS_EXTRA;
1628 	    buf[1] = (int)KE_CSI;
1629 	    add_to_input_buf(buf, 2);
1630 	}
1631     }
1632 }
1633 #endif
1634 
1635 #if defined(FEAT_HANGULIN) || defined(PROTO)
1636     void
1637 push_raw_key(s, len)
1638     char_u  *s;
1639     int	    len;
1640 {
1641     while (len--)
1642 	inbuf[inbufcount++] = *s++;
1643 }
1644 #endif
1645 
1646 #if defined(FEAT_GUI) || defined(FEAT_EVAL) || defined(FEAT_EX_EXTRA) \
1647 	|| defined(PROTO)
1648 /* Remove everything from the input buffer.  Called when ^C is found */
1649     void
1650 trash_input_buf()
1651 {
1652     inbufcount = 0;
1653 }
1654 #endif
1655 
1656 /*
1657  * Read as much data from the input buffer as possible up to maxlen, and store
1658  * it in buf.
1659  * Note: this function used to be Read() in unix.c
1660  */
1661     int
1662 read_from_input_buf(buf, maxlen)
1663     char_u  *buf;
1664     long    maxlen;
1665 {
1666     if (inbufcount == 0)	/* if the buffer is empty, fill it */
1667 	fill_input_buf(TRUE);
1668     if (maxlen > inbufcount)
1669 	maxlen = inbufcount;
1670     mch_memmove(buf, inbuf, (size_t)maxlen);
1671     inbufcount -= maxlen;
1672     if (inbufcount)
1673 	mch_memmove(inbuf, inbuf + maxlen, (size_t)inbufcount);
1674     return (int)maxlen;
1675 }
1676 
1677     void
1678 fill_input_buf(exit_on_error)
1679     int	exit_on_error UNUSED;
1680 {
1681 #if defined(UNIX) || defined(OS2) || defined(VMS) || defined(MACOS_X_UNIX)
1682     int		len;
1683     int		try;
1684     static int	did_read_something = FALSE;
1685 # ifdef FEAT_MBYTE
1686     static char_u *rest = NULL;	    /* unconverted rest of previous read */
1687     static int	restlen = 0;
1688     int		unconverted;
1689 # endif
1690 #endif
1691 
1692 #ifdef FEAT_GUI
1693     if (gui.in_use
1694 # ifdef NO_CONSOLE_INPUT
1695     /* Don't use the GUI input when the window hasn't been opened yet.
1696      * We get here from ui_inchar() when we should try reading from stdin. */
1697 	    && !no_console_input()
1698 # endif
1699        )
1700     {
1701 	gui_mch_update();
1702 	return;
1703     }
1704 #endif
1705 #if defined(UNIX) || defined(OS2) || defined(VMS) || defined(MACOS_X_UNIX)
1706     if (vim_is_input_buf_full())
1707 	return;
1708     /*
1709      * Fill_input_buf() is only called when we really need a character.
1710      * If we can't get any, but there is some in the buffer, just return.
1711      * If we can't get any, and there isn't any in the buffer, we give up and
1712      * exit Vim.
1713      */
1714 # ifdef __BEOS__
1715     /*
1716      * On the BeBox version (for now), all input is secretly performed within
1717      * beos_select() which is called from RealWaitForChar().
1718      */
1719     while (!vim_is_input_buf_full() && RealWaitForChar(read_cmd_fd, 0, NULL))
1720 	    ;
1721     len = inbufcount;
1722     inbufcount = 0;
1723 # else
1724 
1725 #  ifdef FEAT_SNIFF
1726     if (sniff_request_waiting)
1727     {
1728 	add_to_input_buf((char_u *)"\233sniff",6); /* results in K_SNIFF */
1729 	sniff_request_waiting = 0;
1730 	want_sniff_request = 0;
1731 	return;
1732     }
1733 #  endif
1734 
1735 # ifdef FEAT_MBYTE
1736     if (rest != NULL)
1737     {
1738 	/* Use remainder of previous call, starts with an invalid character
1739 	 * that may become valid when reading more. */
1740 	if (restlen > INBUFLEN - inbufcount)
1741 	    unconverted = INBUFLEN - inbufcount;
1742 	else
1743 	    unconverted = restlen;
1744 	mch_memmove(inbuf + inbufcount, rest, unconverted);
1745 	if (unconverted == restlen)
1746 	{
1747 	    vim_free(rest);
1748 	    rest = NULL;
1749 	}
1750 	else
1751 	{
1752 	    restlen -= unconverted;
1753 	    mch_memmove(rest, rest + unconverted, restlen);
1754 	}
1755 	inbufcount += unconverted;
1756     }
1757     else
1758 	unconverted = 0;
1759 #endif
1760 
1761     len = 0;	/* to avoid gcc warning */
1762     for (try = 0; try < 100; ++try)
1763     {
1764 #  ifdef VMS
1765 	len = vms_read(
1766 #  else
1767 	len = read(read_cmd_fd,
1768 #  endif
1769 	    (char *)inbuf + inbufcount, (size_t)((INBUFLEN - inbufcount)
1770 #  ifdef FEAT_MBYTE
1771 		/ input_conv.vc_factor
1772 #  endif
1773 		));
1774 #  if 0
1775 		)	/* avoid syntax highlight error */
1776 #  endif
1777 
1778 	if (len > 0 || got_int)
1779 	    break;
1780 	/*
1781 	 * If reading stdin results in an error, continue reading stderr.
1782 	 * This helps when using "foo | xargs vim".
1783 	 */
1784 	if (!did_read_something && !isatty(read_cmd_fd) && read_cmd_fd == 0)
1785 	{
1786 	    int m = cur_tmode;
1787 
1788 	    /* We probably set the wrong file descriptor to raw mode.  Switch
1789 	     * back to cooked mode, use another descriptor and set the mode to
1790 	     * what it was. */
1791 	    settmode(TMODE_COOK);
1792 #ifdef HAVE_DUP
1793 	    /* Use stderr for stdin, also works for shell commands. */
1794 	    close(0);
1795 	    ignored = dup(2);
1796 #else
1797 	    read_cmd_fd = 2;	/* read from stderr instead of stdin */
1798 #endif
1799 	    settmode(m);
1800 	}
1801 	if (!exit_on_error)
1802 	    return;
1803     }
1804 # endif
1805     if (len <= 0 && !got_int)
1806 	read_error_exit();
1807     if (len > 0)
1808 	did_read_something = TRUE;
1809     if (got_int)
1810     {
1811 	/* Interrupted, pretend a CTRL-C was typed. */
1812 	inbuf[0] = 3;
1813 	inbufcount = 1;
1814     }
1815     else
1816     {
1817 # ifdef FEAT_MBYTE
1818 	/*
1819 	 * May perform conversion on the input characters.
1820 	 * Include the unconverted rest of the previous call.
1821 	 * If there is an incomplete char at the end it is kept for the next
1822 	 * time, reading more bytes should make conversion possible.
1823 	 * Don't do this in the unlikely event that the input buffer is too
1824 	 * small ("rest" still contains more bytes).
1825 	 */
1826 	if (input_conv.vc_type != CONV_NONE)
1827 	{
1828 	    inbufcount -= unconverted;
1829 	    len = convert_input_safe(inbuf + inbufcount,
1830 				     len + unconverted, INBUFLEN - inbufcount,
1831 				       rest == NULL ? &rest : NULL, &restlen);
1832 	}
1833 # endif
1834 	while (len-- > 0)
1835 	{
1836 	    /*
1837 	     * if a CTRL-C was typed, remove it from the buffer and set got_int
1838 	     */
1839 	    if (inbuf[inbufcount] == 3 && ctrl_c_interrupts)
1840 	    {
1841 		/* remove everything typed before the CTRL-C */
1842 		mch_memmove(inbuf, inbuf + inbufcount, (size_t)(len + 1));
1843 		inbufcount = 0;
1844 		got_int = TRUE;
1845 	    }
1846 	    ++inbufcount;
1847 	}
1848     }
1849 #endif /* UNIX or OS2 or VMS*/
1850 }
1851 #endif /* defined(UNIX) || defined(FEAT_GUI) || defined(OS2)  || defined(VMS) */
1852 
1853 /*
1854  * Exit because of an input read error.
1855  */
1856     void
1857 read_error_exit()
1858 {
1859     if (silent_mode)	/* Normal way to exit for "ex -s" */
1860 	getout(0);
1861     STRCPY(IObuff, _("Vim: Error reading input, exiting...\n"));
1862     preserve_exit();
1863 }
1864 
1865 #if defined(CURSOR_SHAPE) || defined(PROTO)
1866 /*
1867  * May update the shape of the cursor.
1868  */
1869     void
1870 ui_cursor_shape()
1871 {
1872 # ifdef FEAT_GUI
1873     if (gui.in_use)
1874 	gui_update_cursor_later();
1875     else
1876 # endif
1877 	term_cursor_shape();
1878 
1879 # ifdef MCH_CURSOR_SHAPE
1880     mch_update_cursor();
1881 # endif
1882 
1883 # ifdef FEAT_CONCEAL
1884     conceal_check_cursur_line();
1885 # endif
1886 }
1887 #endif
1888 
1889 #if defined(FEAT_CLIPBOARD) || defined(FEAT_GUI) || defined(FEAT_RIGHTLEFT) \
1890 	|| defined(FEAT_MBYTE) || defined(PROTO)
1891 /*
1892  * Check bounds for column number
1893  */
1894     int
1895 check_col(col)
1896     int	    col;
1897 {
1898     if (col < 0)
1899 	return 0;
1900     if (col >= (int)screen_Columns)
1901 	return (int)screen_Columns - 1;
1902     return col;
1903 }
1904 
1905 /*
1906  * Check bounds for row number
1907  */
1908     int
1909 check_row(row)
1910     int	    row;
1911 {
1912     if (row < 0)
1913 	return 0;
1914     if (row >= (int)screen_Rows)
1915 	return (int)screen_Rows - 1;
1916     return row;
1917 }
1918 #endif
1919 
1920 /*
1921  * Stuff for the X clipboard.  Shared between VMS and Unix.
1922  */
1923 
1924 #if defined(FEAT_XCLIPBOARD) || defined(FEAT_GUI_X11) || defined(PROTO)
1925 # include <X11/Xatom.h>
1926 # include <X11/Intrinsic.h>
1927 
1928 /*
1929  * Open the application context (if it hasn't been opened yet).
1930  * Used for Motif and Athena GUI and the xterm clipboard.
1931  */
1932     void
1933 open_app_context()
1934 {
1935     if (app_context == NULL)
1936     {
1937 	XtToolkitInitialize();
1938 	app_context = XtCreateApplicationContext();
1939     }
1940 }
1941 
1942 static Atom	vim_atom;	/* Vim's own special selection format */
1943 #ifdef FEAT_MBYTE
1944 static Atom	vimenc_atom;	/* Vim's extended selection format */
1945 static Atom	utf8_atom;
1946 #endif
1947 static Atom	compound_text_atom;
1948 static Atom	text_atom;
1949 static Atom	targets_atom;
1950 static Atom	timestamp_atom;	/* Used to get a timestamp */
1951 
1952     void
1953 x11_setup_atoms(dpy)
1954     Display	*dpy;
1955 {
1956     vim_atom	       = XInternAtom(dpy, VIM_ATOM_NAME,   False);
1957 #ifdef FEAT_MBYTE
1958     vimenc_atom	       = XInternAtom(dpy, VIMENC_ATOM_NAME,False);
1959     utf8_atom	       = XInternAtom(dpy, "UTF8_STRING",   False);
1960 #endif
1961     compound_text_atom = XInternAtom(dpy, "COMPOUND_TEXT", False);
1962     text_atom	       = XInternAtom(dpy, "TEXT",	   False);
1963     targets_atom       = XInternAtom(dpy, "TARGETS",	   False);
1964     clip_star.sel_atom = XA_PRIMARY;
1965     clip_plus.sel_atom = XInternAtom(dpy, "CLIPBOARD",	   False);
1966     timestamp_atom     = XInternAtom(dpy, "TIMESTAMP",	   False);
1967 }
1968 
1969 /*
1970  * X Selection stuff, for cutting and pasting text to other windows.
1971  */
1972 
1973 static Boolean	clip_x11_convert_selection_cb __ARGS((Widget, Atom *, Atom *, Atom *, XtPointer *, long_u *, int *));
1974 static void  clip_x11_lose_ownership_cb __ARGS((Widget, Atom *));
1975 static void clip_x11_timestamp_cb __ARGS((Widget w, XtPointer n, XEvent *event, Boolean *cont));
1976 static void  clip_x11_request_selection_cb __ARGS((Widget, XtPointer, Atom *, Atom *, XtPointer, long_u *, int *));
1977 
1978 /*
1979  * Property callback to get a timestamp for XtOwnSelection.
1980  */
1981     static void
1982 clip_x11_timestamp_cb(w, n, event, cont)
1983     Widget	w;
1984     XtPointer	n UNUSED;
1985     XEvent	*event;
1986     Boolean	*cont UNUSED;
1987 {
1988     Atom	    actual_type;
1989     int		    format;
1990     unsigned  long  nitems, bytes_after;
1991     unsigned char   *prop=NULL;
1992     XPropertyEvent  *xproperty=&event->xproperty;
1993 
1994     /* Must be a property notify, state can't be Delete (True), has to be
1995      * one of the supported selection types. */
1996     if (event->type != PropertyNotify || xproperty->state
1997 	    || (xproperty->atom != clip_star.sel_atom
1998 				    && xproperty->atom != clip_plus.sel_atom))
1999 	return;
2000 
2001     if (XGetWindowProperty(xproperty->display, xproperty->window,
2002 	  xproperty->atom, 0, 0, False, timestamp_atom, &actual_type, &format,
2003 						&nitems, &bytes_after, &prop))
2004 	return;
2005 
2006     if (prop)
2007 	XFree(prop);
2008 
2009     /* Make sure the property type is "TIMESTAMP" and it's 32 bits. */
2010     if (actual_type != timestamp_atom || format != 32)
2011 	return;
2012 
2013     /* Get the selection, using the event timestamp. */
2014     if (XtOwnSelection(w, xproperty->atom, xproperty->time,
2015 	    clip_x11_convert_selection_cb, clip_x11_lose_ownership_cb,
2016 	    NULL) == OK)
2017     {
2018 	/* Set the "owned" flag now, there may have been a call to
2019 	 * lose_ownership_cb in between. */
2020 	if (xproperty->atom == clip_plus.sel_atom)
2021 	    clip_plus.owned = TRUE;
2022 	else
2023 	    clip_star.owned = TRUE;
2024     }
2025 }
2026 
2027     void
2028 x11_setup_selection(w)
2029     Widget	w;
2030 {
2031     XtAddEventHandler(w, PropertyChangeMask, False,
2032 	    /*(XtEventHandler)*/clip_x11_timestamp_cb, (XtPointer)NULL);
2033 }
2034 
2035     static void
2036 clip_x11_request_selection_cb(w, success, sel_atom, type, value, length,
2037 			      format)
2038     Widget	w UNUSED;
2039     XtPointer	success;
2040     Atom	*sel_atom;
2041     Atom	*type;
2042     XtPointer	value;
2043     long_u	*length;
2044     int		*format;
2045 {
2046     int		motion_type = MAUTO;
2047     long_u	len;
2048     char_u	*p;
2049     char	**text_list = NULL;
2050     VimClipboard	*cbd;
2051 #ifdef FEAT_MBYTE
2052     char_u	*tmpbuf = NULL;
2053 #endif
2054 
2055     if (*sel_atom == clip_plus.sel_atom)
2056 	cbd = &clip_plus;
2057     else
2058 	cbd = &clip_star;
2059 
2060     if (value == NULL || *length == 0)
2061     {
2062 	clip_free_selection(cbd);	/* nothing received, clear register */
2063 	*(int *)success = FALSE;
2064 	return;
2065     }
2066     p = (char_u *)value;
2067     len = *length;
2068     if (*type == vim_atom)
2069     {
2070 	motion_type = *p++;
2071 	len--;
2072     }
2073 
2074 #ifdef FEAT_MBYTE
2075     else if (*type == vimenc_atom)
2076     {
2077 	char_u		*enc;
2078 	vimconv_T	conv;
2079 	int		convlen;
2080 
2081 	motion_type = *p++;
2082 	--len;
2083 
2084 	enc = p;
2085 	p += STRLEN(p) + 1;
2086 	len -= p - enc;
2087 
2088 	/* If the encoding of the text is different from 'encoding', attempt
2089 	 * converting it. */
2090 	conv.vc_type = CONV_NONE;
2091 	convert_setup(&conv, enc, p_enc);
2092 	if (conv.vc_type != CONV_NONE)
2093 	{
2094 	    convlen = len;	/* Need to use an int here. */
2095 	    tmpbuf = string_convert(&conv, p, &convlen);
2096 	    len = convlen;
2097 	    if (tmpbuf != NULL)
2098 		p = tmpbuf;
2099 	    convert_setup(&conv, NULL, NULL);
2100 	}
2101     }
2102 #endif
2103 
2104     else if (*type == compound_text_atom
2105 #ifdef FEAT_MBYTE
2106 	    || *type == utf8_atom
2107 #endif
2108 	    || (
2109 #ifdef FEAT_MBYTE
2110 		enc_dbcs != 0 &&
2111 #endif
2112 		*type == text_atom))
2113     {
2114 	XTextProperty	text_prop;
2115 	int		n_text = 0;
2116 	int		status;
2117 
2118 	text_prop.value = (unsigned char *)value;
2119 	text_prop.encoding = *type;
2120 	text_prop.format = *format;
2121 	text_prop.nitems = len;
2122 	status = XmbTextPropertyToTextList(X_DISPLAY, &text_prop,
2123 							 &text_list, &n_text);
2124 	if (status != Success || n_text < 1)
2125 	{
2126 	    *(int *)success = FALSE;
2127 	    return;
2128 	}
2129 	p = (char_u *)text_list[0];
2130 	len = STRLEN(p);
2131     }
2132     clip_yank_selection(motion_type, p, (long)len, cbd);
2133 
2134     if (text_list != NULL)
2135 	XFreeStringList(text_list);
2136 #ifdef FEAT_MBYTE
2137     vim_free(tmpbuf);
2138 #endif
2139     XtFree((char *)value);
2140     *(int *)success = TRUE;
2141 }
2142 
2143     void
2144 clip_x11_request_selection(myShell, dpy, cbd)
2145     Widget	myShell;
2146     Display	*dpy;
2147     VimClipboard	*cbd;
2148 {
2149     XEvent	event;
2150     Atom	type;
2151     static int	success;
2152     int		i;
2153     time_t	start_time;
2154     int		timed_out = FALSE;
2155 
2156     for (i =
2157 #ifdef FEAT_MBYTE
2158 	    0
2159 #else
2160 	    1
2161 #endif
2162 	    ; i < 6; i++)
2163     {
2164 	switch (i)
2165 	{
2166 #ifdef FEAT_MBYTE
2167 	    case 0:  type = vimenc_atom;	break;
2168 #endif
2169 	    case 1:  type = vim_atom;		break;
2170 #ifdef FEAT_MBYTE
2171 	    case 2:  type = utf8_atom;		break;
2172 #endif
2173 	    case 3:  type = compound_text_atom; break;
2174 	    case 4:  type = text_atom;		break;
2175 	    default: type = XA_STRING;
2176 	}
2177 #ifdef FEAT_MBYTE
2178 	if (type == utf8_atom && !enc_utf8)
2179 	    /* Only request utf-8 when 'encoding' is utf8. */
2180 	    continue;
2181 #endif
2182 	success = MAYBE;
2183 	XtGetSelectionValue(myShell, cbd->sel_atom, type,
2184 	    clip_x11_request_selection_cb, (XtPointer)&success, CurrentTime);
2185 
2186 	/* Make sure the request for the selection goes out before waiting for
2187 	 * a response. */
2188 	XFlush(dpy);
2189 
2190 	/*
2191 	 * Wait for result of selection request, otherwise if we type more
2192 	 * characters, then they will appear before the one that requested the
2193 	 * paste!  Don't worry, we will catch up with any other events later.
2194 	 */
2195 	start_time = time(NULL);
2196 	while (success == MAYBE)
2197 	{
2198 	    if (XCheckTypedEvent(dpy, SelectionNotify, &event)
2199 		    || XCheckTypedEvent(dpy, SelectionRequest, &event)
2200 		    || XCheckTypedEvent(dpy, PropertyNotify, &event))
2201 	    {
2202 		/* This is where clip_x11_request_selection_cb() should be
2203 		 * called.  It may actually happen a bit later, so we loop
2204 		 * until "success" changes.
2205 		 * We may get a SelectionRequest here and if we don't handle
2206 		 * it we hang.  KDE klipper does this, for example.
2207 		 * We need to handle a PropertyNotify for large selections. */
2208 		XtDispatchEvent(&event);
2209 		continue;
2210 	    }
2211 
2212 	    /* Time out after 2 to 3 seconds to avoid that we hang when the
2213 	     * other process doesn't respond.  Note that the SelectionNotify
2214 	     * event may still come later when the selection owner comes back
2215 	     * to life and the text gets inserted unexpectedly.  Don't know
2216 	     * why that happens or how to avoid that :-(. */
2217 	    if (time(NULL) > start_time + 2)
2218 	    {
2219 		timed_out = TRUE;
2220 		break;
2221 	    }
2222 
2223 	    /* Do we need this?  Probably not. */
2224 	    XSync(dpy, False);
2225 
2226 	    /* Wait for 1 msec to avoid that we eat up all CPU time. */
2227 	    ui_delay(1L, TRUE);
2228 	}
2229 
2230 	if (success == TRUE)
2231 	    return;
2232 
2233 	/* don't do a retry with another type after timing out, otherwise we
2234 	 * hang for 15 seconds. */
2235 	if (timed_out)
2236 	    break;
2237     }
2238 
2239     /* Final fallback position - use the X CUT_BUFFER0 store */
2240     yank_cut_buffer0(dpy, cbd);
2241 }
2242 
2243     static Boolean
2244 clip_x11_convert_selection_cb(w, sel_atom, target, type, value, length, format)
2245     Widget	w UNUSED;
2246     Atom	*sel_atom;
2247     Atom	*target;
2248     Atom	*type;
2249     XtPointer	*value;
2250     long_u	*length;
2251     int		*format;
2252 {
2253     char_u	*string;
2254     char_u	*result;
2255     int		motion_type;
2256     VimClipboard	*cbd;
2257     int		i;
2258 
2259     if (*sel_atom == clip_plus.sel_atom)
2260 	cbd = &clip_plus;
2261     else
2262 	cbd = &clip_star;
2263 
2264     if (!cbd->owned)
2265 	return False;	    /* Shouldn't ever happen */
2266 
2267     /* requestor wants to know what target types we support */
2268     if (*target == targets_atom)
2269     {
2270 	Atom *array;
2271 
2272 	if ((array = (Atom *)XtMalloc((unsigned)(sizeof(Atom) * 7))) == NULL)
2273 	    return False;
2274 	*value = (XtPointer)array;
2275 	i = 0;
2276 	array[i++] = targets_atom;
2277 #ifdef FEAT_MBYTE
2278 	array[i++] = vimenc_atom;
2279 #endif
2280 	array[i++] = vim_atom;
2281 #ifdef FEAT_MBYTE
2282 	if (enc_utf8)
2283 	    array[i++] = utf8_atom;
2284 #endif
2285 	array[i++] = XA_STRING;
2286 	array[i++] = text_atom;
2287 	array[i++] = compound_text_atom;
2288 
2289 	*type = XA_ATOM;
2290 	/* This used to be: *format = sizeof(Atom) * 8; but that caused
2291 	 * crashes on 64 bit machines. (Peter Derr) */
2292 	*format = 32;
2293 	*length = i;
2294 	return True;
2295     }
2296 
2297     if (       *target != XA_STRING
2298 #ifdef FEAT_MBYTE
2299 	    && *target != vimenc_atom
2300 	    && *target != utf8_atom
2301 #endif
2302 	    && *target != vim_atom
2303 	    && *target != text_atom
2304 	    && *target != compound_text_atom)
2305 	return False;
2306 
2307     clip_get_selection(cbd);
2308     motion_type = clip_convert_selection(&string, length, cbd);
2309     if (motion_type < 0)
2310 	return False;
2311 
2312     /* For our own format, the first byte contains the motion type */
2313     if (*target == vim_atom)
2314 	(*length)++;
2315 
2316 #ifdef FEAT_MBYTE
2317     /* Our own format with encoding: motion 'encoding' NUL text */
2318     if (*target == vimenc_atom)
2319 	*length += STRLEN(p_enc) + 2;
2320 #endif
2321 
2322     *value = XtMalloc((Cardinal)*length);
2323     result = (char_u *)*value;
2324     if (result == NULL)
2325     {
2326 	vim_free(string);
2327 	return False;
2328     }
2329 
2330     if (*target == XA_STRING
2331 #ifdef FEAT_MBYTE
2332 	    || (*target == utf8_atom && enc_utf8)
2333 #endif
2334 	    )
2335     {
2336 	mch_memmove(result, string, (size_t)(*length));
2337 	*type = *target;
2338     }
2339     else if (*target == compound_text_atom || *target == text_atom)
2340     {
2341 	XTextProperty	text_prop;
2342 	char		*string_nt = (char *)alloc((unsigned)*length + 1);
2343 
2344 	/* create NUL terminated string which XmbTextListToTextProperty wants */
2345 	mch_memmove(string_nt, string, (size_t)*length);
2346 	string_nt[*length] = NUL;
2347 	XmbTextListToTextProperty(X_DISPLAY, (char **)&string_nt, 1,
2348 					      XCompoundTextStyle, &text_prop);
2349 	vim_free(string_nt);
2350 	XtFree(*value);			/* replace with COMPOUND text */
2351 	*value = (XtPointer)(text_prop.value);	/*    from plain text */
2352 	*length = text_prop.nitems;
2353 	*type = compound_text_atom;
2354     }
2355 
2356 #ifdef FEAT_MBYTE
2357     else if (*target == vimenc_atom)
2358     {
2359 	int l = STRLEN(p_enc);
2360 
2361 	result[0] = motion_type;
2362 	STRCPY(result + 1, p_enc);
2363 	mch_memmove(result + l + 2, string, (size_t)(*length - l - 2));
2364 	*type = vimenc_atom;
2365     }
2366 #endif
2367 
2368     else
2369     {
2370 	result[0] = motion_type;
2371 	mch_memmove(result + 1, string, (size_t)(*length - 1));
2372 	*type = vim_atom;
2373     }
2374     *format = 8;	    /* 8 bits per char */
2375     vim_free(string);
2376     return True;
2377 }
2378 
2379     static void
2380 clip_x11_lose_ownership_cb(w, sel_atom)
2381     Widget  w UNUSED;
2382     Atom    *sel_atom;
2383 {
2384     if (*sel_atom == clip_plus.sel_atom)
2385 	clip_lose_selection(&clip_plus);
2386     else
2387 	clip_lose_selection(&clip_star);
2388 }
2389 
2390     void
2391 clip_x11_lose_selection(myShell, cbd)
2392     Widget		myShell;
2393     VimClipboard	*cbd;
2394 {
2395     XtDisownSelection(myShell, cbd->sel_atom, CurrentTime);
2396 }
2397 
2398     int
2399 clip_x11_own_selection(myShell, cbd)
2400     Widget		myShell;
2401     VimClipboard	*cbd;
2402 {
2403     /* When using the GUI we have proper timestamps, use the one of the last
2404      * event.  When in the console we don't get events (the terminal gets
2405      * them), Get the time by a zero-length append, clip_x11_timestamp_cb will
2406      * be called with the current timestamp.  */
2407 #ifdef FEAT_GUI
2408     if (gui.in_use)
2409     {
2410 	if (XtOwnSelection(myShell, cbd->sel_atom,
2411 	       XtLastTimestampProcessed(XtDisplay(myShell)),
2412 	       clip_x11_convert_selection_cb, clip_x11_lose_ownership_cb,
2413 	       NULL) == False)
2414 	    return FAIL;
2415     }
2416     else
2417 #endif
2418     {
2419 	if (!XChangeProperty(XtDisplay(myShell), XtWindow(myShell),
2420 		  cbd->sel_atom, timestamp_atom, 32, PropModeAppend, NULL, 0))
2421 	    return FAIL;
2422     }
2423     /* Flush is required in a terminal as nothing else is doing it. */
2424     XFlush(XtDisplay(myShell));
2425     return OK;
2426 }
2427 
2428 /*
2429  * Send the current selection to the clipboard.  Do nothing for X because we
2430  * will fill in the selection only when requested by another app.
2431  */
2432     void
2433 clip_x11_set_selection(cbd)
2434     VimClipboard *cbd UNUSED;
2435 {
2436 }
2437 #endif
2438 
2439 #if defined(FEAT_XCLIPBOARD) || defined(FEAT_GUI_X11) \
2440     || defined(FEAT_GUI_GTK) || defined(PROTO)
2441 /*
2442  * Get the contents of the X CUT_BUFFER0 and put it in "cbd".
2443  */
2444     void
2445 yank_cut_buffer0(dpy, cbd)
2446     Display		*dpy;
2447     VimClipboard	*cbd;
2448 {
2449     int		nbytes = 0;
2450     char_u	*buffer = (char_u *)XFetchBuffer(dpy, &nbytes, 0);
2451 
2452     if (nbytes > 0)
2453     {
2454 #ifdef FEAT_MBYTE
2455 	int  done = FALSE;
2456 
2457 	/* CUT_BUFFER0 is supposed to be always latin1.  Convert to 'enc' when
2458 	 * using a multi-byte encoding.  Conversion between two 8-bit
2459 	 * character sets usually fails and the text might actually be in
2460 	 * 'enc' anyway. */
2461 	if (has_mbyte)
2462 	{
2463 	    char_u	*conv_buf;
2464 	    vimconv_T	vc;
2465 
2466 	    vc.vc_type = CONV_NONE;
2467 	    if (convert_setup(&vc, (char_u *)"latin1", p_enc) == OK)
2468 	    {
2469 		conv_buf = string_convert(&vc, buffer, &nbytes);
2470 		if (conv_buf != NULL)
2471 		{
2472 		    clip_yank_selection(MCHAR, conv_buf, (long)nbytes, cbd);
2473 		    vim_free(conv_buf);
2474 		    done = TRUE;
2475 		}
2476 		convert_setup(&vc, NULL, NULL);
2477 	    }
2478 	}
2479 	if (!done)  /* use the text without conversion */
2480 #endif
2481 	    clip_yank_selection(MCHAR, buffer, (long)nbytes, cbd);
2482 	XFree((void *)buffer);
2483 	if (p_verbose > 0)
2484 	{
2485 	    verbose_enter();
2486 	    verb_msg((char_u *)_("Used CUT_BUFFER0 instead of empty selection"));
2487 	    verbose_leave();
2488 	}
2489     }
2490 }
2491 #endif
2492 
2493 #if defined(FEAT_MOUSE) || defined(PROTO)
2494 
2495 /*
2496  * Move the cursor to the specified row and column on the screen.
2497  * Change current window if necessary.	Returns an integer with the
2498  * CURSOR_MOVED bit set if the cursor has moved or unset otherwise.
2499  *
2500  * The MOUSE_FOLD_CLOSE bit is set when clicked on the '-' in a fold column.
2501  * The MOUSE_FOLD_OPEN bit is set when clicked on the '+' in a fold column.
2502  *
2503  * If flags has MOUSE_FOCUS, then the current window will not be changed, and
2504  * if the mouse is outside the window then the text will scroll, or if the
2505  * mouse was previously on a status line, then the status line may be dragged.
2506  *
2507  * If flags has MOUSE_MAY_VIS, then VIsual mode will be started before the
2508  * cursor is moved unless the cursor was on a status line.
2509  * This function returns one of IN_UNKNOWN, IN_BUFFER, IN_STATUS_LINE or
2510  * IN_SEP_LINE depending on where the cursor was clicked.
2511  *
2512  * If flags has MOUSE_MAY_STOP_VIS, then Visual mode will be stopped, unless
2513  * the mouse is on the status line of the same window.
2514  *
2515  * If flags has MOUSE_DID_MOVE, nothing is done if the mouse didn't move since
2516  * the last call.
2517  *
2518  * If flags has MOUSE_SETPOS, nothing is done, only the current position is
2519  * remembered.
2520  */
2521     int
2522 jump_to_mouse(flags, inclusive, which_button)
2523     int		flags;
2524     int		*inclusive;	/* used for inclusive operator, can be NULL */
2525     int		which_button;	/* MOUSE_LEFT, MOUSE_RIGHT, MOUSE_MIDDLE */
2526 {
2527     static int	on_status_line = 0;	/* #lines below bottom of window */
2528 #ifdef FEAT_VERTSPLIT
2529     static int	on_sep_line = 0;	/* on separator right of window */
2530 #endif
2531     static int	prev_row = -1;
2532     static int	prev_col = -1;
2533     static win_T *dragwin = NULL;	/* window being dragged */
2534     static int	did_drag = FALSE;	/* drag was noticed */
2535 
2536     win_T	*wp, *old_curwin;
2537     pos_T	old_cursor;
2538     int		count;
2539     int		first;
2540     int		row = mouse_row;
2541     int		col = mouse_col;
2542 #ifdef FEAT_FOLDING
2543     int		mouse_char;
2544 #endif
2545 
2546     mouse_past_bottom = FALSE;
2547     mouse_past_eol = FALSE;
2548 
2549     if (flags & MOUSE_RELEASED)
2550     {
2551 	/* On button release we may change window focus if positioned on a
2552 	 * status line and no dragging happened. */
2553 	if (dragwin != NULL && !did_drag)
2554 	    flags &= ~(MOUSE_FOCUS | MOUSE_DID_MOVE);
2555 	dragwin = NULL;
2556 	did_drag = FALSE;
2557     }
2558 
2559     if ((flags & MOUSE_DID_MOVE)
2560 	    && prev_row == mouse_row
2561 	    && prev_col == mouse_col)
2562     {
2563 retnomove:
2564 	/* before moving the cursor for a left click which is NOT in a status
2565 	 * line, stop Visual mode */
2566 	if (on_status_line)
2567 	    return IN_STATUS_LINE;
2568 #ifdef FEAT_VERTSPLIT
2569 	if (on_sep_line)
2570 	    return IN_SEP_LINE;
2571 #endif
2572 #ifdef FEAT_VISUAL
2573 	if (flags & MOUSE_MAY_STOP_VIS)
2574 	{
2575 	    end_visual_mode();
2576 	    redraw_curbuf_later(INVERTED);	/* delete the inversion */
2577 	}
2578 #endif
2579 #if defined(FEAT_CMDWIN) && defined(FEAT_CLIPBOARD)
2580 	/* Continue a modeless selection in another window. */
2581 	if (cmdwin_type != 0 && row < W_WINROW(curwin))
2582 	    return IN_OTHER_WIN;
2583 #endif
2584 	return IN_BUFFER;
2585     }
2586 
2587     prev_row = mouse_row;
2588     prev_col = mouse_col;
2589 
2590     if (flags & MOUSE_SETPOS)
2591 	goto retnomove;				/* ugly goto... */
2592 
2593 #ifdef FEAT_FOLDING
2594     /* Remember the character under the mouse, it might be a '-' or '+' in the
2595      * fold column. */
2596     if (row >= 0 && row < Rows && col >= 0 && col <= Columns
2597 						       && ScreenLines != NULL)
2598 	mouse_char = ScreenLines[LineOffset[row] + col];
2599     else
2600 	mouse_char = ' ';
2601 #endif
2602 
2603     old_curwin = curwin;
2604     old_cursor = curwin->w_cursor;
2605 
2606     if (!(flags & MOUSE_FOCUS))
2607     {
2608 	if (row < 0 || col < 0)			/* check if it makes sense */
2609 	    return IN_UNKNOWN;
2610 
2611 #ifdef FEAT_WINDOWS
2612 	/* find the window where the row is in */
2613 	wp = mouse_find_win(&row, &col);
2614 #else
2615 	wp = firstwin;
2616 #endif
2617 	dragwin = NULL;
2618 	/*
2619 	 * winpos and height may change in win_enter()!
2620 	 */
2621 	if (row >= wp->w_height)		/* In (or below) status line */
2622 	{
2623 	    on_status_line = row - wp->w_height + 1;
2624 	    dragwin = wp;
2625 	}
2626 	else
2627 	    on_status_line = 0;
2628 #ifdef FEAT_VERTSPLIT
2629 	if (col >= wp->w_width)		/* In separator line */
2630 	{
2631 	    on_sep_line = col - wp->w_width + 1;
2632 	    dragwin = wp;
2633 	}
2634 	else
2635 	    on_sep_line = 0;
2636 
2637 	/* The rightmost character of the status line might be a vertical
2638 	 * separator character if there is no connecting window to the right. */
2639 	if (on_status_line && on_sep_line)
2640 	{
2641 	    if (stl_connected(wp))
2642 		on_sep_line = 0;
2643 	    else
2644 		on_status_line = 0;
2645 	}
2646 #endif
2647 
2648 #ifdef FEAT_VISUAL
2649 	/* Before jumping to another buffer, or moving the cursor for a left
2650 	 * click, stop Visual mode. */
2651 	if (VIsual_active
2652 		&& (wp->w_buffer != curwin->w_buffer
2653 		    || (!on_status_line
2654 # ifdef FEAT_VERTSPLIT
2655 			&& !on_sep_line
2656 # endif
2657 # ifdef FEAT_FOLDING
2658 			&& (
2659 #  ifdef FEAT_RIGHTLEFT
2660 			    wp->w_p_rl ? col < W_WIDTH(wp) - wp->w_p_fdc :
2661 #  endif
2662 			    col >= wp->w_p_fdc
2663 #  ifdef FEAT_CMDWIN
2664 				  + (cmdwin_type == 0 && wp == curwin ? 0 : 1)
2665 #  endif
2666 			    )
2667 # endif
2668 			&& (flags & MOUSE_MAY_STOP_VIS))))
2669 	{
2670 	    end_visual_mode();
2671 	    redraw_curbuf_later(INVERTED);	/* delete the inversion */
2672 	}
2673 #endif
2674 #ifdef FEAT_CMDWIN
2675 	if (cmdwin_type != 0 && wp != curwin)
2676 	{
2677 	    /* A click outside the command-line window: Use modeless
2678 	     * selection if possible.  Allow dragging the status lines. */
2679 # ifdef FEAT_VERTSPLIT
2680 	    on_sep_line = 0;
2681 # endif
2682 # ifdef FEAT_CLIPBOARD
2683 	    if (on_status_line)
2684 		return IN_STATUS_LINE;
2685 	    return IN_OTHER_WIN;
2686 # else
2687 	    row = 0;
2688 	    col += wp->w_wincol;
2689 	    wp = curwin;
2690 # endif
2691 	}
2692 #endif
2693 #ifdef FEAT_WINDOWS
2694 	/* Only change window focus when not clicking on or dragging the
2695 	 * status line.  Do change focus when releasing the mouse button
2696 	 * (MOUSE_FOCUS was set above if we dragged first). */
2697 	if (dragwin == NULL || (flags & MOUSE_RELEASED))
2698 	    win_enter(wp, TRUE);		/* can make wp invalid! */
2699 # ifdef CHECK_DOUBLE_CLICK
2700 	/* set topline, to be able to check for double click ourselves */
2701 	if (curwin != old_curwin)
2702 	    set_mouse_topline(curwin);
2703 # endif
2704 #endif
2705 	if (on_status_line)			/* In (or below) status line */
2706 	{
2707 	    /* Don't use start_arrow() if we're in the same window */
2708 	    if (curwin == old_curwin)
2709 		return IN_STATUS_LINE;
2710 	    else
2711 		return IN_STATUS_LINE | CURSOR_MOVED;
2712 	}
2713 #ifdef FEAT_VERTSPLIT
2714 	if (on_sep_line)			/* In (or below) status line */
2715 	{
2716 	    /* Don't use start_arrow() if we're in the same window */
2717 	    if (curwin == old_curwin)
2718 		return IN_SEP_LINE;
2719 	    else
2720 		return IN_SEP_LINE | CURSOR_MOVED;
2721 	}
2722 #endif
2723 
2724 	curwin->w_cursor.lnum = curwin->w_topline;
2725 #ifdef FEAT_GUI
2726 	/* remember topline, needed for double click */
2727 	gui_prev_topline = curwin->w_topline;
2728 # ifdef FEAT_DIFF
2729 	gui_prev_topfill = curwin->w_topfill;
2730 # endif
2731 #endif
2732     }
2733     else if (on_status_line && which_button == MOUSE_LEFT)
2734     {
2735 #ifdef FEAT_WINDOWS
2736 	if (dragwin != NULL)
2737 	{
2738 	    /* Drag the status line */
2739 	    count = row - dragwin->w_winrow - dragwin->w_height + 1
2740 							     - on_status_line;
2741 	    win_drag_status_line(dragwin, count);
2742 	    did_drag |= count;
2743 	}
2744 #endif
2745 	return IN_STATUS_LINE;			/* Cursor didn't move */
2746     }
2747 #ifdef FEAT_VERTSPLIT
2748     else if (on_sep_line && which_button == MOUSE_LEFT)
2749     {
2750 	if (dragwin != NULL)
2751 	{
2752 	    /* Drag the separator column */
2753 	    count = col - dragwin->w_wincol - dragwin->w_width + 1
2754 								- on_sep_line;
2755 	    win_drag_vsep_line(dragwin, count);
2756 	    did_drag |= count;
2757 	}
2758 	return IN_SEP_LINE;			/* Cursor didn't move */
2759     }
2760 #endif
2761     else /* keep_window_focus must be TRUE */
2762     {
2763 #ifdef FEAT_VISUAL
2764 	/* before moving the cursor for a left click, stop Visual mode */
2765 	if (flags & MOUSE_MAY_STOP_VIS)
2766 	{
2767 	    end_visual_mode();
2768 	    redraw_curbuf_later(INVERTED);	/* delete the inversion */
2769 	}
2770 #endif
2771 
2772 #if defined(FEAT_CMDWIN) && defined(FEAT_CLIPBOARD)
2773 	/* Continue a modeless selection in another window. */
2774 	if (cmdwin_type != 0 && row < W_WINROW(curwin))
2775 	    return IN_OTHER_WIN;
2776 #endif
2777 
2778 	row -= W_WINROW(curwin);
2779 #ifdef FEAT_VERTSPLIT
2780 	col -= W_WINCOL(curwin);
2781 #endif
2782 
2783 	/*
2784 	 * When clicking beyond the end of the window, scroll the screen.
2785 	 * Scroll by however many rows outside the window we are.
2786 	 */
2787 	if (row < 0)
2788 	{
2789 	    count = 0;
2790 	    for (first = TRUE; curwin->w_topline > 1; )
2791 	    {
2792 #ifdef FEAT_DIFF
2793 		if (curwin->w_topfill < diff_check(curwin, curwin->w_topline))
2794 		    ++count;
2795 		else
2796 #endif
2797 		    count += plines(curwin->w_topline - 1);
2798 		if (!first && count > -row)
2799 		    break;
2800 		first = FALSE;
2801 #ifdef FEAT_FOLDING
2802 		hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
2803 #endif
2804 #ifdef FEAT_DIFF
2805 		if (curwin->w_topfill < diff_check(curwin, curwin->w_topline))
2806 		    ++curwin->w_topfill;
2807 		else
2808 #endif
2809 		{
2810 		    --curwin->w_topline;
2811 #ifdef FEAT_DIFF
2812 		    curwin->w_topfill = 0;
2813 #endif
2814 		}
2815 	    }
2816 #ifdef FEAT_DIFF
2817 	    check_topfill(curwin, FALSE);
2818 #endif
2819 	    curwin->w_valid &=
2820 		      ~(VALID_WROW|VALID_CROW|VALID_BOTLINE|VALID_BOTLINE_AP);
2821 	    redraw_later(VALID);
2822 	    row = 0;
2823 	}
2824 	else if (row >= curwin->w_height)
2825 	{
2826 	    count = 0;
2827 	    for (first = TRUE; curwin->w_topline < curbuf->b_ml.ml_line_count; )
2828 	    {
2829 #ifdef FEAT_DIFF
2830 		if (curwin->w_topfill > 0)
2831 		    ++count;
2832 		else
2833 #endif
2834 		    count += plines(curwin->w_topline);
2835 		if (!first && count > row - curwin->w_height + 1)
2836 		    break;
2837 		first = FALSE;
2838 #ifdef FEAT_FOLDING
2839 		if (hasFolding(curwin->w_topline, NULL, &curwin->w_topline)
2840 			&& curwin->w_topline == curbuf->b_ml.ml_line_count)
2841 		    break;
2842 #endif
2843 #ifdef FEAT_DIFF
2844 		if (curwin->w_topfill > 0)
2845 		    --curwin->w_topfill;
2846 		else
2847 #endif
2848 		{
2849 		    ++curwin->w_topline;
2850 #ifdef FEAT_DIFF
2851 		    curwin->w_topfill =
2852 				   diff_check_fill(curwin, curwin->w_topline);
2853 #endif
2854 		}
2855 	    }
2856 #ifdef FEAT_DIFF
2857 	    check_topfill(curwin, FALSE);
2858 #endif
2859 	    redraw_later(VALID);
2860 	    curwin->w_valid &=
2861 		      ~(VALID_WROW|VALID_CROW|VALID_BOTLINE|VALID_BOTLINE_AP);
2862 	    row = curwin->w_height - 1;
2863 	}
2864 	else if (row == 0)
2865 	{
2866 	    /* When dragging the mouse, while the text has been scrolled up as
2867 	     * far as it goes, moving the mouse in the top line should scroll
2868 	     * the text down (done later when recomputing w_topline). */
2869 	    if (mouse_dragging > 0
2870 		    && curwin->w_cursor.lnum
2871 				       == curwin->w_buffer->b_ml.ml_line_count
2872 		    && curwin->w_cursor.lnum == curwin->w_topline)
2873 		curwin->w_valid &= ~(VALID_TOPLINE);
2874 	}
2875     }
2876 
2877 #ifdef FEAT_FOLDING
2878     /* Check for position outside of the fold column. */
2879     if (
2880 # ifdef FEAT_RIGHTLEFT
2881 	    curwin->w_p_rl ? col < W_WIDTH(curwin) - curwin->w_p_fdc :
2882 # endif
2883 	    col >= curwin->w_p_fdc
2884 #  ifdef FEAT_CMDWIN
2885 				+ (cmdwin_type == 0 ? 0 : 1)
2886 #  endif
2887        )
2888 	mouse_char = ' ';
2889 #endif
2890 
2891     /* compute the position in the buffer line from the posn on the screen */
2892     if (mouse_comp_pos(curwin, &row, &col, &curwin->w_cursor.lnum))
2893 	mouse_past_bottom = TRUE;
2894 
2895 #ifdef FEAT_VISUAL
2896     /* Start Visual mode before coladvance(), for when 'sel' != "old" */
2897     if ((flags & MOUSE_MAY_VIS) && !VIsual_active)
2898     {
2899 	check_visual_highlight();
2900 	VIsual = old_cursor;
2901 	VIsual_active = TRUE;
2902 	VIsual_reselect = TRUE;
2903 	/* if 'selectmode' contains "mouse", start Select mode */
2904 	may_start_select('o');
2905 	setmouse();
2906 	if (p_smd && msg_silent == 0)
2907 	    redraw_cmdline = TRUE;	/* show visual mode later */
2908     }
2909 #endif
2910 
2911     curwin->w_curswant = col;
2912     curwin->w_set_curswant = FALSE;	/* May still have been TRUE */
2913     if (coladvance(col) == FAIL)	/* Mouse click beyond end of line */
2914     {
2915 	if (inclusive != NULL)
2916 	    *inclusive = TRUE;
2917 	mouse_past_eol = TRUE;
2918     }
2919     else if (inclusive != NULL)
2920 	*inclusive = FALSE;
2921 
2922     count = IN_BUFFER;
2923     if (curwin != old_curwin || curwin->w_cursor.lnum != old_cursor.lnum
2924 	    || curwin->w_cursor.col != old_cursor.col)
2925 	count |= CURSOR_MOVED;		/* Cursor has moved */
2926 
2927 #ifdef FEAT_FOLDING
2928     if (mouse_char == '+')
2929 	count |= MOUSE_FOLD_OPEN;
2930     else if (mouse_char != ' ')
2931 	count |= MOUSE_FOLD_CLOSE;
2932 #endif
2933 
2934     return count;
2935 }
2936 
2937 /*
2938  * Compute the position in the buffer line from the posn on the screen in
2939  * window "win".
2940  * Returns TRUE if the position is below the last line.
2941  */
2942     int
2943 mouse_comp_pos(win, rowp, colp, lnump)
2944     win_T	*win;
2945     int		*rowp;
2946     int		*colp;
2947     linenr_T	*lnump;
2948 {
2949     int		col = *colp;
2950     int		row = *rowp;
2951     linenr_T	lnum;
2952     int		retval = FALSE;
2953     int		off;
2954     int		count;
2955 
2956 #ifdef FEAT_RIGHTLEFT
2957     if (win->w_p_rl)
2958 	col = W_WIDTH(win) - 1 - col;
2959 #endif
2960 
2961     lnum = win->w_topline;
2962 
2963     while (row > 0)
2964     {
2965 #ifdef FEAT_DIFF
2966 	/* Don't include filler lines in "count" */
2967 	if (win->w_p_diff
2968 # ifdef FEAT_FOLDING
2969 		&& !hasFoldingWin(win, lnum, NULL, NULL, TRUE, NULL)
2970 # endif
2971 		)
2972 	{
2973 	    if (lnum == win->w_topline)
2974 		row -= win->w_topfill;
2975 	    else
2976 		row -= diff_check_fill(win, lnum);
2977 	    count = plines_win_nofill(win, lnum, TRUE);
2978 	}
2979 	else
2980 #endif
2981 	    count = plines_win(win, lnum, TRUE);
2982 	if (count > row)
2983 	    break;	/* Position is in this buffer line. */
2984 #ifdef FEAT_FOLDING
2985 	(void)hasFoldingWin(win, lnum, NULL, &lnum, TRUE, NULL);
2986 #endif
2987 	if (lnum == win->w_buffer->b_ml.ml_line_count)
2988 	{
2989 	    retval = TRUE;
2990 	    break;		/* past end of file */
2991 	}
2992 	row -= count;
2993 	++lnum;
2994     }
2995 
2996     if (!retval)
2997     {
2998 	/* Compute the column without wrapping. */
2999 	off = win_col_off(win) - win_col_off2(win);
3000 	if (col < off)
3001 	    col = off;
3002 	col += row * (W_WIDTH(win) - off);
3003 	/* add skip column (for long wrapping line) */
3004 	col += win->w_skipcol;
3005     }
3006 
3007     if (!win->w_p_wrap)
3008 	col += win->w_leftcol;
3009 
3010     /* skip line number and fold column in front of the line */
3011     col -= win_col_off(win);
3012     if (col < 0)
3013     {
3014 #ifdef FEAT_NETBEANS_INTG
3015 	netbeans_gutter_click(lnum);
3016 #endif
3017 	col = 0;
3018     }
3019 
3020     *colp = col;
3021     *rowp = row;
3022     *lnump = lnum;
3023     return retval;
3024 }
3025 
3026 #if defined(FEAT_WINDOWS) || defined(PROTO)
3027 /*
3028  * Find the window at screen position "*rowp" and "*colp".  The positions are
3029  * updated to become relative to the top-left of the window.
3030  */
3031     win_T *
3032 mouse_find_win(rowp, colp)
3033     int		*rowp;
3034     int		*colp UNUSED;
3035 {
3036     frame_T	*fp;
3037 
3038     fp = topframe;
3039     *rowp -= firstwin->w_winrow;
3040     for (;;)
3041     {
3042 	if (fp->fr_layout == FR_LEAF)
3043 	    break;
3044 #ifdef FEAT_VERTSPLIT
3045 	if (fp->fr_layout == FR_ROW)
3046 	{
3047 	    for (fp = fp->fr_child; fp->fr_next != NULL; fp = fp->fr_next)
3048 	    {
3049 		if (*colp < fp->fr_width)
3050 		    break;
3051 		*colp -= fp->fr_width;
3052 	    }
3053 	}
3054 #endif
3055 	else    /* fr_layout == FR_COL */
3056 	{
3057 	    for (fp = fp->fr_child; fp->fr_next != NULL; fp = fp->fr_next)
3058 	    {
3059 		if (*rowp < fp->fr_height)
3060 		    break;
3061 		*rowp -= fp->fr_height;
3062 	    }
3063 	}
3064     }
3065     return fp->fr_win;
3066 }
3067 #endif
3068 
3069 #if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MAC) \
3070 	|| defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) \
3071 	|| defined(FEAT_GUI_PHOTON) || defined(PROTO)
3072 /*
3073  * Translate window coordinates to buffer position without any side effects
3074  */
3075     int
3076 get_fpos_of_mouse(mpos)
3077     pos_T	*mpos;
3078 {
3079     win_T	*wp;
3080     int		row = mouse_row;
3081     int		col = mouse_col;
3082 
3083     if (row < 0 || col < 0)		/* check if it makes sense */
3084 	return IN_UNKNOWN;
3085 
3086 #ifdef FEAT_WINDOWS
3087     /* find the window where the row is in */
3088     wp = mouse_find_win(&row, &col);
3089 #else
3090     wp = firstwin;
3091 #endif
3092     /*
3093      * winpos and height may change in win_enter()!
3094      */
3095     if (row >= wp->w_height)	/* In (or below) status line */
3096 	return IN_STATUS_LINE;
3097 #ifdef FEAT_VERTSPLIT
3098     if (col >= wp->w_width)	/* In vertical separator line */
3099 	return IN_SEP_LINE;
3100 #endif
3101 
3102     if (wp != curwin)
3103 	return IN_UNKNOWN;
3104 
3105     /* compute the position in the buffer line from the posn on the screen */
3106     if (mouse_comp_pos(curwin, &row, &col, &mpos->lnum))
3107 	return IN_STATUS_LINE; /* past bottom */
3108 
3109     mpos->col = vcol2col(wp, mpos->lnum, col);
3110 
3111     if (mpos->col > 0)
3112 	--mpos->col;
3113 #ifdef FEAT_VIRTUALEDIT
3114     mpos->coladd = 0;
3115 #endif
3116     return IN_BUFFER;
3117 }
3118 
3119 /*
3120  * Convert a virtual (screen) column to a character column.
3121  * The first column is one.
3122  */
3123     int
3124 vcol2col(wp, lnum, vcol)
3125     win_T	*wp;
3126     linenr_T	lnum;
3127     int		vcol;
3128 {
3129     /* try to advance to the specified column */
3130     int		count = 0;
3131     char_u	*ptr;
3132     char_u	*start;
3133 
3134     start = ptr = ml_get_buf(wp->w_buffer, lnum, FALSE);
3135     while (count <= vcol && *ptr != NUL)
3136     {
3137 	count += win_lbr_chartabsize(wp, ptr, count, NULL);
3138 	mb_ptr_adv(ptr);
3139     }
3140     return (int)(ptr - start);
3141 }
3142 #endif
3143 
3144 #endif /* FEAT_MOUSE */
3145 
3146 #if defined(FEAT_GUI) || defined(WIN3264) || defined(PROTO)
3147 /*
3148  * Called when focus changed.  Used for the GUI or for systems where this can
3149  * be done in the console (Win32).
3150  */
3151     void
3152 ui_focus_change(in_focus)
3153     int		in_focus;	/* TRUE if focus gained. */
3154 {
3155     static time_t	last_time = (time_t)0;
3156     int			need_redraw = FALSE;
3157 
3158     /* When activated: Check if any file was modified outside of Vim.
3159      * Only do this when not done within the last two seconds (could get
3160      * several events in a row). */
3161     if (in_focus && last_time + 2 < time(NULL))
3162     {
3163 	need_redraw = check_timestamps(
3164 # ifdef FEAT_GUI
3165 		gui.in_use
3166 # else
3167 		FALSE
3168 # endif
3169 		);
3170 	last_time = time(NULL);
3171     }
3172 
3173 #ifdef FEAT_AUTOCMD
3174     /*
3175      * Fire the focus gained/lost autocommand.
3176      */
3177     need_redraw |= apply_autocmds(in_focus ? EVENT_FOCUSGAINED
3178 				: EVENT_FOCUSLOST, NULL, NULL, FALSE, curbuf);
3179 #endif
3180 
3181     if (need_redraw)
3182     {
3183 	/* Something was executed, make sure the cursor is put back where it
3184 	 * belongs. */
3185 	need_wait_return = FALSE;
3186 
3187 	if (State & CMDLINE)
3188 	    redrawcmdline();
3189 	else if (State == HITRETURN || State == SETWSIZE || State == ASKMORE
3190 		|| State == EXTERNCMD || State == CONFIRM || exmode_active)
3191 	    repeat_message();
3192 	else if ((State & NORMAL) || (State & INSERT))
3193 	{
3194 	    if (must_redraw != 0)
3195 		update_screen(0);
3196 	    setcursor();
3197 	}
3198 	cursor_on();	    /* redrawing may have switched it off */
3199 	out_flush();
3200 # ifdef FEAT_GUI
3201 	if (gui.in_use)
3202 	{
3203 	    gui_update_cursor(FALSE, TRUE);
3204 	    gui_update_scrollbars(FALSE);
3205 	}
3206 # endif
3207     }
3208 #ifdef FEAT_TITLE
3209     /* File may have been changed from 'readonly' to 'noreadonly' */
3210     if (need_maketitle)
3211 	maketitle();
3212 #endif
3213 }
3214 #endif
3215 
3216 #if defined(USE_IM_CONTROL) || defined(PROTO)
3217 /*
3218  * Save current Input Method status to specified place.
3219  */
3220     void
3221 im_save_status(psave)
3222     long *psave;
3223 {
3224     /* Don't save when 'imdisable' is set or "xic" is NULL, IM is always
3225      * disabled then (but might start later).
3226      * Also don't save when inside a mapping, vgetc_im_active has not been set
3227      * then.
3228      * And don't save when the keys were stuffed (e.g., for a "." command).
3229      * And don't save when the GUI is running but our window doesn't have
3230      * input focus (e.g., when a find dialog is open). */
3231     if (!p_imdisable && KeyTyped && !KeyStuffed
3232 # ifdef FEAT_XIM
3233 	    && xic != NULL
3234 # endif
3235 # ifdef FEAT_GUI
3236 	    && (!gui.in_use || gui.in_focus)
3237 # endif
3238 	)
3239     {
3240 	/* Do save when IM is on, or IM is off and saved status is on. */
3241 	if (vgetc_im_active)
3242 	    *psave = B_IMODE_IM;
3243 	else if (*psave == B_IMODE_IM)
3244 	    *psave = B_IMODE_NONE;
3245     }
3246 }
3247 #endif
3248