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