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