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