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