xref: /vim-8.2.3635/src/ui.c (revision fc39ecf8)
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 #ifdef FEAT_MBYTE
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 #ifdef FEAT_MBYTE
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     while (len--)
1727 	inbuf[inbufcount++] = *s++;
1728 }
1729 #endif
1730 
1731 #if defined(FEAT_GUI) || defined(FEAT_EVAL) || defined(FEAT_EX_EXTRA) \
1732 	|| defined(PROTO)
1733 /* Remove everything from the input buffer.  Called when ^C is found */
1734     void
1735 trash_input_buf()
1736 {
1737     inbufcount = 0;
1738 }
1739 #endif
1740 
1741 /*
1742  * Read as much data from the input buffer as possible up to maxlen, and store
1743  * it in buf.
1744  * Note: this function used to be Read() in unix.c
1745  */
1746     int
1747 read_from_input_buf(buf, maxlen)
1748     char_u  *buf;
1749     long    maxlen;
1750 {
1751     if (inbufcount == 0)	/* if the buffer is empty, fill it */
1752 	fill_input_buf(TRUE);
1753     if (maxlen > inbufcount)
1754 	maxlen = inbufcount;
1755     mch_memmove(buf, inbuf, (size_t)maxlen);
1756     inbufcount -= maxlen;
1757     if (inbufcount)
1758 	mch_memmove(inbuf, inbuf + maxlen, (size_t)inbufcount);
1759     return (int)maxlen;
1760 }
1761 
1762     void
1763 fill_input_buf(exit_on_error)
1764     int	exit_on_error UNUSED;
1765 {
1766 #if defined(UNIX) || defined(OS2) || defined(VMS) || defined(MACOS_X_UNIX)
1767     int		len;
1768     int		try;
1769     static int	did_read_something = FALSE;
1770 # ifdef FEAT_MBYTE
1771     static char_u *rest = NULL;	    /* unconverted rest of previous read */
1772     static int	restlen = 0;
1773     int		unconverted;
1774 # endif
1775 #endif
1776 
1777 #ifdef FEAT_GUI
1778     if (gui.in_use
1779 # ifdef NO_CONSOLE_INPUT
1780     /* Don't use the GUI input when the window hasn't been opened yet.
1781      * We get here from ui_inchar() when we should try reading from stdin. */
1782 	    && !no_console_input()
1783 # endif
1784        )
1785     {
1786 	gui_mch_update();
1787 	return;
1788     }
1789 #endif
1790 #if defined(UNIX) || defined(OS2) || defined(VMS) || defined(MACOS_X_UNIX)
1791     if (vim_is_input_buf_full())
1792 	return;
1793     /*
1794      * Fill_input_buf() is only called when we really need a character.
1795      * If we can't get any, but there is some in the buffer, just return.
1796      * If we can't get any, and there isn't any in the buffer, we give up and
1797      * exit Vim.
1798      */
1799 # ifdef __BEOS__
1800     /*
1801      * On the BeBox version (for now), all input is secretly performed within
1802      * beos_select() which is called from RealWaitForChar().
1803      */
1804     while (!vim_is_input_buf_full() && RealWaitForChar(read_cmd_fd, 0, NULL))
1805 	    ;
1806     len = inbufcount;
1807     inbufcount = 0;
1808 # else
1809 
1810 #  ifdef FEAT_SNIFF
1811     if (sniff_request_waiting)
1812     {
1813 	add_to_input_buf((char_u *)"\233sniff",6); /* results in K_SNIFF */
1814 	sniff_request_waiting = 0;
1815 	want_sniff_request = 0;
1816 	return;
1817     }
1818 #  endif
1819 
1820 # ifdef FEAT_MBYTE
1821     if (rest != NULL)
1822     {
1823 	/* Use remainder of previous call, starts with an invalid character
1824 	 * that may become valid when reading more. */
1825 	if (restlen > INBUFLEN - inbufcount)
1826 	    unconverted = INBUFLEN - inbufcount;
1827 	else
1828 	    unconverted = restlen;
1829 	mch_memmove(inbuf + inbufcount, rest, unconverted);
1830 	if (unconverted == restlen)
1831 	{
1832 	    vim_free(rest);
1833 	    rest = NULL;
1834 	}
1835 	else
1836 	{
1837 	    restlen -= unconverted;
1838 	    mch_memmove(rest, rest + unconverted, restlen);
1839 	}
1840 	inbufcount += unconverted;
1841     }
1842     else
1843 	unconverted = 0;
1844 #endif
1845 
1846     len = 0;	/* to avoid gcc warning */
1847     for (try = 0; try < 100; ++try)
1848     {
1849 #  ifdef VMS
1850 	len = vms_read(
1851 #  else
1852 	len = read(read_cmd_fd,
1853 #  endif
1854 	    (char *)inbuf + inbufcount, (size_t)((INBUFLEN - inbufcount)
1855 #  ifdef FEAT_MBYTE
1856 		/ input_conv.vc_factor
1857 #  endif
1858 		));
1859 #  if 0
1860 		)	/* avoid syntax highlight error */
1861 #  endif
1862 
1863 	if (len > 0 || got_int)
1864 	    break;
1865 	/*
1866 	 * If reading stdin results in an error, continue reading stderr.
1867 	 * This helps when using "foo | xargs vim".
1868 	 */
1869 	if (!did_read_something && !isatty(read_cmd_fd) && read_cmd_fd == 0)
1870 	{
1871 	    int m = cur_tmode;
1872 
1873 	    /* We probably set the wrong file descriptor to raw mode.  Switch
1874 	     * back to cooked mode, use another descriptor and set the mode to
1875 	     * what it was. */
1876 	    settmode(TMODE_COOK);
1877 #ifdef HAVE_DUP
1878 	    /* Use stderr for stdin, also works for shell commands. */
1879 	    close(0);
1880 	    ignored = dup(2);
1881 #else
1882 	    read_cmd_fd = 2;	/* read from stderr instead of stdin */
1883 #endif
1884 	    settmode(m);
1885 	}
1886 	if (!exit_on_error)
1887 	    return;
1888     }
1889 # endif
1890     if (len <= 0 && !got_int)
1891 	read_error_exit();
1892     if (len > 0)
1893 	did_read_something = TRUE;
1894     if (got_int)
1895     {
1896 	/* Interrupted, pretend a CTRL-C was typed. */
1897 	inbuf[0] = 3;
1898 	inbufcount = 1;
1899     }
1900     else
1901     {
1902 # ifdef FEAT_MBYTE
1903 	/*
1904 	 * May perform conversion on the input characters.
1905 	 * Include the unconverted rest of the previous call.
1906 	 * If there is an incomplete char at the end it is kept for the next
1907 	 * time, reading more bytes should make conversion possible.
1908 	 * Don't do this in the unlikely event that the input buffer is too
1909 	 * small ("rest" still contains more bytes).
1910 	 */
1911 	if (input_conv.vc_type != CONV_NONE)
1912 	{
1913 	    inbufcount -= unconverted;
1914 	    len = convert_input_safe(inbuf + inbufcount,
1915 				     len + unconverted, INBUFLEN - inbufcount,
1916 				       rest == NULL ? &rest : NULL, &restlen);
1917 	}
1918 # endif
1919 	while (len-- > 0)
1920 	{
1921 	    /*
1922 	     * if a CTRL-C was typed, remove it from the buffer and set got_int
1923 	     */
1924 	    if (inbuf[inbufcount] == 3 && ctrl_c_interrupts)
1925 	    {
1926 		/* remove everything typed before the CTRL-C */
1927 		mch_memmove(inbuf, inbuf + inbufcount, (size_t)(len + 1));
1928 		inbufcount = 0;
1929 		got_int = TRUE;
1930 	    }
1931 	    ++inbufcount;
1932 	}
1933     }
1934 #endif /* UNIX or OS2 or VMS*/
1935 }
1936 #endif /* defined(UNIX) || defined(FEAT_GUI) || defined(OS2)  || defined(VMS) */
1937 
1938 /*
1939  * Exit because of an input read error.
1940  */
1941     void
1942 read_error_exit()
1943 {
1944     if (silent_mode)	/* Normal way to exit for "ex -s" */
1945 	getout(0);
1946     STRCPY(IObuff, _("Vim: Error reading input, exiting...\n"));
1947     preserve_exit();
1948 }
1949 
1950 #if defined(CURSOR_SHAPE) || defined(PROTO)
1951 /*
1952  * May update the shape of the cursor.
1953  */
1954     void
1955 ui_cursor_shape()
1956 {
1957 # ifdef FEAT_GUI
1958     if (gui.in_use)
1959 	gui_update_cursor_later();
1960     else
1961 # endif
1962 	term_cursor_shape();
1963 
1964 # ifdef MCH_CURSOR_SHAPE
1965     mch_update_cursor();
1966 # endif
1967 
1968 # ifdef FEAT_CONCEAL
1969     conceal_check_cursur_line();
1970 # endif
1971 }
1972 #endif
1973 
1974 #if defined(FEAT_CLIPBOARD) || defined(FEAT_GUI) || defined(FEAT_RIGHTLEFT) \
1975 	|| defined(FEAT_MBYTE) || defined(PROTO)
1976 /*
1977  * Check bounds for column number
1978  */
1979     int
1980 check_col(col)
1981     int	    col;
1982 {
1983     if (col < 0)
1984 	return 0;
1985     if (col >= (int)screen_Columns)
1986 	return (int)screen_Columns - 1;
1987     return col;
1988 }
1989 
1990 /*
1991  * Check bounds for row number
1992  */
1993     int
1994 check_row(row)
1995     int	    row;
1996 {
1997     if (row < 0)
1998 	return 0;
1999     if (row >= (int)screen_Rows)
2000 	return (int)screen_Rows - 1;
2001     return row;
2002 }
2003 #endif
2004 
2005 /*
2006  * Stuff for the X clipboard.  Shared between VMS and Unix.
2007  */
2008 
2009 #if defined(FEAT_XCLIPBOARD) || defined(FEAT_GUI_X11) || defined(PROTO)
2010 # include <X11/Xatom.h>
2011 # include <X11/Intrinsic.h>
2012 
2013 /*
2014  * Open the application context (if it hasn't been opened yet).
2015  * Used for Motif and Athena GUI and the xterm clipboard.
2016  */
2017     void
2018 open_app_context()
2019 {
2020     if (app_context == NULL)
2021     {
2022 	XtToolkitInitialize();
2023 	app_context = XtCreateApplicationContext();
2024     }
2025 }
2026 
2027 static Atom	vim_atom;	/* Vim's own special selection format */
2028 #ifdef FEAT_MBYTE
2029 static Atom	vimenc_atom;	/* Vim's extended selection format */
2030 static Atom	utf8_atom;
2031 #endif
2032 static Atom	compound_text_atom;
2033 static Atom	text_atom;
2034 static Atom	targets_atom;
2035 static Atom	timestamp_atom;	/* Used to get a timestamp */
2036 
2037     void
2038 x11_setup_atoms(dpy)
2039     Display	*dpy;
2040 {
2041     vim_atom	       = XInternAtom(dpy, VIM_ATOM_NAME,   False);
2042 #ifdef FEAT_MBYTE
2043     vimenc_atom	       = XInternAtom(dpy, VIMENC_ATOM_NAME,False);
2044     utf8_atom	       = XInternAtom(dpy, "UTF8_STRING",   False);
2045 #endif
2046     compound_text_atom = XInternAtom(dpy, "COMPOUND_TEXT", False);
2047     text_atom	       = XInternAtom(dpy, "TEXT",	   False);
2048     targets_atom       = XInternAtom(dpy, "TARGETS",	   False);
2049     clip_star.sel_atom = XA_PRIMARY;
2050     clip_plus.sel_atom = XInternAtom(dpy, "CLIPBOARD",	   False);
2051     timestamp_atom     = XInternAtom(dpy, "TIMESTAMP",	   False);
2052 }
2053 
2054 /*
2055  * X Selection stuff, for cutting and pasting text to other windows.
2056  */
2057 
2058 static Boolean	clip_x11_convert_selection_cb __ARGS((Widget, Atom *, Atom *, Atom *, XtPointer *, long_u *, int *));
2059 static void  clip_x11_lose_ownership_cb __ARGS((Widget, Atom *));
2060 static void clip_x11_timestamp_cb __ARGS((Widget w, XtPointer n, XEvent *event, Boolean *cont));
2061 static void  clip_x11_request_selection_cb __ARGS((Widget, XtPointer, Atom *, Atom *, XtPointer, long_u *, int *));
2062 
2063 /*
2064  * Property callback to get a timestamp for XtOwnSelection.
2065  */
2066     static void
2067 clip_x11_timestamp_cb(w, n, event, cont)
2068     Widget	w;
2069     XtPointer	n UNUSED;
2070     XEvent	*event;
2071     Boolean	*cont UNUSED;
2072 {
2073     Atom	    actual_type;
2074     int		    format;
2075     unsigned  long  nitems, bytes_after;
2076     unsigned char   *prop=NULL;
2077     XPropertyEvent  *xproperty=&event->xproperty;
2078 
2079     /* Must be a property notify, state can't be Delete (True), has to be
2080      * one of the supported selection types. */
2081     if (event->type != PropertyNotify || xproperty->state
2082 	    || (xproperty->atom != clip_star.sel_atom
2083 				    && xproperty->atom != clip_plus.sel_atom))
2084 	return;
2085 
2086     if (XGetWindowProperty(xproperty->display, xproperty->window,
2087 	  xproperty->atom, 0, 0, False, timestamp_atom, &actual_type, &format,
2088 						&nitems, &bytes_after, &prop))
2089 	return;
2090 
2091     if (prop)
2092 	XFree(prop);
2093 
2094     /* Make sure the property type is "TIMESTAMP" and it's 32 bits. */
2095     if (actual_type != timestamp_atom || format != 32)
2096 	return;
2097 
2098     /* Get the selection, using the event timestamp. */
2099     if (XtOwnSelection(w, xproperty->atom, xproperty->time,
2100 	    clip_x11_convert_selection_cb, clip_x11_lose_ownership_cb,
2101 	    NULL) == OK)
2102     {
2103 	/* Set the "owned" flag now, there may have been a call to
2104 	 * lose_ownership_cb in between. */
2105 	if (xproperty->atom == clip_plus.sel_atom)
2106 	    clip_plus.owned = TRUE;
2107 	else
2108 	    clip_star.owned = TRUE;
2109     }
2110 }
2111 
2112     void
2113 x11_setup_selection(w)
2114     Widget	w;
2115 {
2116     XtAddEventHandler(w, PropertyChangeMask, False,
2117 	    /*(XtEventHandler)*/clip_x11_timestamp_cb, (XtPointer)NULL);
2118 }
2119 
2120     static void
2121 clip_x11_request_selection_cb(w, success, sel_atom, type, value, length,
2122 			      format)
2123     Widget	w UNUSED;
2124     XtPointer	success;
2125     Atom	*sel_atom;
2126     Atom	*type;
2127     XtPointer	value;
2128     long_u	*length;
2129     int		*format;
2130 {
2131     int		motion_type = MAUTO;
2132     long_u	len;
2133     char_u	*p;
2134     char	**text_list = NULL;
2135     VimClipboard	*cbd;
2136 #ifdef FEAT_MBYTE
2137     char_u	*tmpbuf = NULL;
2138 #endif
2139 
2140     if (*sel_atom == clip_plus.sel_atom)
2141 	cbd = &clip_plus;
2142     else
2143 	cbd = &clip_star;
2144 
2145     if (value == NULL || *length == 0)
2146     {
2147 	clip_free_selection(cbd);	/* nothing received, clear register */
2148 	*(int *)success = FALSE;
2149 	return;
2150     }
2151     p = (char_u *)value;
2152     len = *length;
2153     if (*type == vim_atom)
2154     {
2155 	motion_type = *p++;
2156 	len--;
2157     }
2158 
2159 #ifdef FEAT_MBYTE
2160     else if (*type == vimenc_atom)
2161     {
2162 	char_u		*enc;
2163 	vimconv_T	conv;
2164 	int		convlen;
2165 
2166 	motion_type = *p++;
2167 	--len;
2168 
2169 	enc = p;
2170 	p += STRLEN(p) + 1;
2171 	len -= p - enc;
2172 
2173 	/* If the encoding of the text is different from 'encoding', attempt
2174 	 * converting it. */
2175 	conv.vc_type = CONV_NONE;
2176 	convert_setup(&conv, enc, p_enc);
2177 	if (conv.vc_type != CONV_NONE)
2178 	{
2179 	    convlen = len;	/* Need to use an int here. */
2180 	    tmpbuf = string_convert(&conv, p, &convlen);
2181 	    len = convlen;
2182 	    if (tmpbuf != NULL)
2183 		p = tmpbuf;
2184 	    convert_setup(&conv, NULL, NULL);
2185 	}
2186     }
2187 #endif
2188 
2189     else if (*type == compound_text_atom
2190 #ifdef FEAT_MBYTE
2191 	    || *type == utf8_atom
2192 #endif
2193 	    || (
2194 #ifdef FEAT_MBYTE
2195 		enc_dbcs != 0 &&
2196 #endif
2197 		*type == text_atom))
2198     {
2199 	XTextProperty	text_prop;
2200 	int		n_text = 0;
2201 	int		status;
2202 
2203 	text_prop.value = (unsigned char *)value;
2204 	text_prop.encoding = *type;
2205 	text_prop.format = *format;
2206 	text_prop.nitems = len;
2207 #if defined(FEAT_MBYTE) && defined(X_HAVE_UTF8_STRING)
2208 	if (*type == utf8_atom)
2209 	    status = Xutf8TextPropertyToTextList(X_DISPLAY, &text_prop,
2210 							 &text_list, &n_text);
2211 	else
2212 #endif
2213 	    status = XmbTextPropertyToTextList(X_DISPLAY, &text_prop,
2214 							 &text_list, &n_text);
2215 	if (status != Success || n_text < 1)
2216 	{
2217 	    *(int *)success = FALSE;
2218 	    return;
2219 	}
2220 	p = (char_u *)text_list[0];
2221 	len = STRLEN(p);
2222     }
2223     clip_yank_selection(motion_type, p, (long)len, cbd);
2224 
2225     if (text_list != NULL)
2226 	XFreeStringList(text_list);
2227 #ifdef FEAT_MBYTE
2228     vim_free(tmpbuf);
2229 #endif
2230     XtFree((char *)value);
2231     *(int *)success = TRUE;
2232 }
2233 
2234     void
2235 clip_x11_request_selection(myShell, dpy, cbd)
2236     Widget	myShell;
2237     Display	*dpy;
2238     VimClipboard	*cbd;
2239 {
2240     XEvent	event;
2241     Atom	type;
2242     static int	success;
2243     int		i;
2244     time_t	start_time;
2245     int		timed_out = FALSE;
2246 
2247     for (i =
2248 #ifdef FEAT_MBYTE
2249 	    0
2250 #else
2251 	    1
2252 #endif
2253 	    ; i < 6; i++)
2254     {
2255 	switch (i)
2256 	{
2257 #ifdef FEAT_MBYTE
2258 	    case 0:  type = vimenc_atom;	break;
2259 #endif
2260 	    case 1:  type = vim_atom;		break;
2261 #ifdef FEAT_MBYTE
2262 	    case 2:  type = utf8_atom;		break;
2263 #endif
2264 	    case 3:  type = compound_text_atom; break;
2265 	    case 4:  type = text_atom;		break;
2266 	    default: type = XA_STRING;
2267 	}
2268 #ifdef FEAT_MBYTE
2269 	if (type == utf8_atom
2270 # if defined(X_HAVE_UTF8_STRING)
2271 		&& !enc_utf8
2272 # endif
2273 		)
2274 	    /* Only request utf-8 when 'encoding' is utf8 and
2275 	     * Xutf8TextPropertyToTextList is available. */
2276 	    continue;
2277 #endif
2278 	success = MAYBE;
2279 	XtGetSelectionValue(myShell, cbd->sel_atom, type,
2280 	    clip_x11_request_selection_cb, (XtPointer)&success, CurrentTime);
2281 
2282 	/* Make sure the request for the selection goes out before waiting for
2283 	 * a response. */
2284 	XFlush(dpy);
2285 
2286 	/*
2287 	 * Wait for result of selection request, otherwise if we type more
2288 	 * characters, then they will appear before the one that requested the
2289 	 * paste!  Don't worry, we will catch up with any other events later.
2290 	 */
2291 	start_time = time(NULL);
2292 	while (success == MAYBE)
2293 	{
2294 	    if (XCheckTypedEvent(dpy, SelectionNotify, &event)
2295 		    || XCheckTypedEvent(dpy, SelectionRequest, &event)
2296 		    || XCheckTypedEvent(dpy, PropertyNotify, &event))
2297 	    {
2298 		/* This is where clip_x11_request_selection_cb() should be
2299 		 * called.  It may actually happen a bit later, so we loop
2300 		 * until "success" changes.
2301 		 * We may get a SelectionRequest here and if we don't handle
2302 		 * it we hang.  KDE klipper does this, for example.
2303 		 * We need to handle a PropertyNotify for large selections. */
2304 		XtDispatchEvent(&event);
2305 		continue;
2306 	    }
2307 
2308 	    /* Time out after 2 to 3 seconds to avoid that we hang when the
2309 	     * other process doesn't respond.  Note that the SelectionNotify
2310 	     * event may still come later when the selection owner comes back
2311 	     * to life and the text gets inserted unexpectedly.  Don't know
2312 	     * why that happens or how to avoid that :-(. */
2313 	    if (time(NULL) > start_time + 2)
2314 	    {
2315 		timed_out = TRUE;
2316 		break;
2317 	    }
2318 
2319 	    /* Do we need this?  Probably not. */
2320 	    XSync(dpy, False);
2321 
2322 	    /* Wait for 1 msec to avoid that we eat up all CPU time. */
2323 	    ui_delay(1L, TRUE);
2324 	}
2325 
2326 	if (success == TRUE)
2327 	    return;
2328 
2329 	/* don't do a retry with another type after timing out, otherwise we
2330 	 * hang for 15 seconds. */
2331 	if (timed_out)
2332 	    break;
2333     }
2334 
2335     /* Final fallback position - use the X CUT_BUFFER0 store */
2336     yank_cut_buffer0(dpy, cbd);
2337 }
2338 
2339     static Boolean
2340 clip_x11_convert_selection_cb(w, sel_atom, target, type, value, length, format)
2341     Widget	w UNUSED;
2342     Atom	*sel_atom;
2343     Atom	*target;
2344     Atom	*type;
2345     XtPointer	*value;
2346     long_u	*length;
2347     int		*format;
2348 {
2349     char_u	*string;
2350     char_u	*result;
2351     int		motion_type;
2352     VimClipboard	*cbd;
2353     int		i;
2354 
2355     if (*sel_atom == clip_plus.sel_atom)
2356 	cbd = &clip_plus;
2357     else
2358 	cbd = &clip_star;
2359 
2360     if (!cbd->owned)
2361 	return False;	    /* Shouldn't ever happen */
2362 
2363     /* requestor wants to know what target types we support */
2364     if (*target == targets_atom)
2365     {
2366 	Atom *array;
2367 
2368 	if ((array = (Atom *)XtMalloc((unsigned)(sizeof(Atom) * 7))) == NULL)
2369 	    return False;
2370 	*value = (XtPointer)array;
2371 	i = 0;
2372 	array[i++] = targets_atom;
2373 #ifdef FEAT_MBYTE
2374 	array[i++] = vimenc_atom;
2375 #endif
2376 	array[i++] = vim_atom;
2377 #ifdef FEAT_MBYTE
2378 	if (enc_utf8)
2379 	    array[i++] = utf8_atom;
2380 #endif
2381 	array[i++] = XA_STRING;
2382 	array[i++] = text_atom;
2383 	array[i++] = compound_text_atom;
2384 
2385 	*type = XA_ATOM;
2386 	/* This used to be: *format = sizeof(Atom) * 8; but that caused
2387 	 * crashes on 64 bit machines. (Peter Derr) */
2388 	*format = 32;
2389 	*length = i;
2390 	return True;
2391     }
2392 
2393     if (       *target != XA_STRING
2394 #ifdef FEAT_MBYTE
2395 	    && *target != vimenc_atom
2396 	    && (*target != utf8_atom || !enc_utf8)
2397 #endif
2398 	    && *target != vim_atom
2399 	    && *target != text_atom
2400 	    && *target != compound_text_atom)
2401 	return False;
2402 
2403     clip_get_selection(cbd);
2404     motion_type = clip_convert_selection(&string, length, cbd);
2405     if (motion_type < 0)
2406 	return False;
2407 
2408     /* For our own format, the first byte contains the motion type */
2409     if (*target == vim_atom)
2410 	(*length)++;
2411 
2412 #ifdef FEAT_MBYTE
2413     /* Our own format with encoding: motion 'encoding' NUL text */
2414     if (*target == vimenc_atom)
2415 	*length += STRLEN(p_enc) + 2;
2416 #endif
2417 
2418     *value = XtMalloc((Cardinal)*length);
2419     result = (char_u *)*value;
2420     if (result == NULL)
2421     {
2422 	vim_free(string);
2423 	return False;
2424     }
2425 
2426     if (*target == XA_STRING
2427 #ifdef FEAT_MBYTE
2428 	    || (*target == utf8_atom && enc_utf8)
2429 #endif
2430 	    )
2431     {
2432 	mch_memmove(result, string, (size_t)(*length));
2433 	*type = *target;
2434     }
2435     else if (*target == compound_text_atom || *target == text_atom)
2436     {
2437 	XTextProperty	text_prop;
2438 	char		*string_nt = (char *)alloc((unsigned)*length + 1);
2439 	int		conv_result;
2440 
2441 	/* create NUL terminated string which XmbTextListToTextProperty wants */
2442 	mch_memmove(string_nt, string, (size_t)*length);
2443 	string_nt[*length] = NUL;
2444 	conv_result = XmbTextListToTextProperty(X_DISPLAY, (char **)&string_nt,
2445 					   1, XCompoundTextStyle, &text_prop);
2446 	vim_free(string_nt);
2447 	XtFree(*value);			/* replace with COMPOUND text */
2448 	if (conv_result != Success)
2449 	{
2450 	    vim_free(string);
2451 	    return False;
2452 	}
2453 	*value = (XtPointer)(text_prop.value);	/*    from plain text */
2454 	*length = text_prop.nitems;
2455 	*type = compound_text_atom;
2456     }
2457 
2458 #ifdef FEAT_MBYTE
2459     else if (*target == vimenc_atom)
2460     {
2461 	int l = STRLEN(p_enc);
2462 
2463 	result[0] = motion_type;
2464 	STRCPY(result + 1, p_enc);
2465 	mch_memmove(result + l + 2, string, (size_t)(*length - l - 2));
2466 	*type = vimenc_atom;
2467     }
2468 #endif
2469 
2470     else
2471     {
2472 	result[0] = motion_type;
2473 	mch_memmove(result + 1, string, (size_t)(*length - 1));
2474 	*type = vim_atom;
2475     }
2476     *format = 8;	    /* 8 bits per char */
2477     vim_free(string);
2478     return True;
2479 }
2480 
2481     static void
2482 clip_x11_lose_ownership_cb(w, sel_atom)
2483     Widget  w UNUSED;
2484     Atom    *sel_atom;
2485 {
2486     if (*sel_atom == clip_plus.sel_atom)
2487 	clip_lose_selection(&clip_plus);
2488     else
2489 	clip_lose_selection(&clip_star);
2490 }
2491 
2492     void
2493 clip_x11_lose_selection(myShell, cbd)
2494     Widget		myShell;
2495     VimClipboard	*cbd;
2496 {
2497     XtDisownSelection(myShell, cbd->sel_atom,
2498 				XtLastTimestampProcessed(XtDisplay(myShell)));
2499 }
2500 
2501     int
2502 clip_x11_own_selection(myShell, cbd)
2503     Widget		myShell;
2504     VimClipboard	*cbd;
2505 {
2506     /* When using the GUI we have proper timestamps, use the one of the last
2507      * event.  When in the console we don't get events (the terminal gets
2508      * them), Get the time by a zero-length append, clip_x11_timestamp_cb will
2509      * be called with the current timestamp.  */
2510 #ifdef FEAT_GUI
2511     if (gui.in_use)
2512     {
2513 	if (XtOwnSelection(myShell, cbd->sel_atom,
2514 	       XtLastTimestampProcessed(XtDisplay(myShell)),
2515 	       clip_x11_convert_selection_cb, clip_x11_lose_ownership_cb,
2516 	       NULL) == False)
2517 	    return FAIL;
2518     }
2519     else
2520 #endif
2521     {
2522 	if (!XChangeProperty(XtDisplay(myShell), XtWindow(myShell),
2523 		  cbd->sel_atom, timestamp_atom, 32, PropModeAppend, NULL, 0))
2524 	    return FAIL;
2525     }
2526     /* Flush is required in a terminal as nothing else is doing it. */
2527     XFlush(XtDisplay(myShell));
2528     return OK;
2529 }
2530 
2531 /*
2532  * Send the current selection to the clipboard.  Do nothing for X because we
2533  * will fill in the selection only when requested by another app.
2534  */
2535     void
2536 clip_x11_set_selection(cbd)
2537     VimClipboard *cbd UNUSED;
2538 {
2539 }
2540 
2541     int
2542 clip_x11_owner_exists(cbd)
2543     VimClipboard	*cbd;
2544 {
2545     return XGetSelectionOwner(X_DISPLAY, cbd->sel_atom) != None;
2546 }
2547 #endif
2548 
2549 #if defined(FEAT_XCLIPBOARD) || defined(FEAT_GUI_X11) \
2550     || defined(FEAT_GUI_GTK) || defined(PROTO)
2551 /*
2552  * Get the contents of the X CUT_BUFFER0 and put it in "cbd".
2553  */
2554     void
2555 yank_cut_buffer0(dpy, cbd)
2556     Display		*dpy;
2557     VimClipboard	*cbd;
2558 {
2559     int		nbytes = 0;
2560     char_u	*buffer = (char_u *)XFetchBuffer(dpy, &nbytes, 0);
2561 
2562     if (nbytes > 0)
2563     {
2564 #ifdef FEAT_MBYTE
2565 	int  done = FALSE;
2566 
2567 	/* CUT_BUFFER0 is supposed to be always latin1.  Convert to 'enc' when
2568 	 * using a multi-byte encoding.  Conversion between two 8-bit
2569 	 * character sets usually fails and the text might actually be in
2570 	 * 'enc' anyway. */
2571 	if (has_mbyte)
2572 	{
2573 	    char_u	*conv_buf;
2574 	    vimconv_T	vc;
2575 
2576 	    vc.vc_type = CONV_NONE;
2577 	    if (convert_setup(&vc, (char_u *)"latin1", p_enc) == OK)
2578 	    {
2579 		conv_buf = string_convert(&vc, buffer, &nbytes);
2580 		if (conv_buf != NULL)
2581 		{
2582 		    clip_yank_selection(MCHAR, conv_buf, (long)nbytes, cbd);
2583 		    vim_free(conv_buf);
2584 		    done = TRUE;
2585 		}
2586 		convert_setup(&vc, NULL, NULL);
2587 	    }
2588 	}
2589 	if (!done)  /* use the text without conversion */
2590 #endif
2591 	    clip_yank_selection(MCHAR, buffer, (long)nbytes, cbd);
2592 	XFree((void *)buffer);
2593 	if (p_verbose > 0)
2594 	{
2595 	    verbose_enter();
2596 	    verb_msg((char_u *)_("Used CUT_BUFFER0 instead of empty selection"));
2597 	    verbose_leave();
2598 	}
2599     }
2600 }
2601 #endif
2602 
2603 #if defined(FEAT_MOUSE) || defined(PROTO)
2604 
2605 /*
2606  * Move the cursor to the specified row and column on the screen.
2607  * Change current window if necessary.	Returns an integer with the
2608  * CURSOR_MOVED bit set if the cursor has moved or unset otherwise.
2609  *
2610  * The MOUSE_FOLD_CLOSE bit is set when clicked on the '-' in a fold column.
2611  * The MOUSE_FOLD_OPEN bit is set when clicked on the '+' in a fold column.
2612  *
2613  * If flags has MOUSE_FOCUS, then the current window will not be changed, and
2614  * if the mouse is outside the window then the text will scroll, or if the
2615  * mouse was previously on a status line, then the status line may be dragged.
2616  *
2617  * If flags has MOUSE_MAY_VIS, then VIsual mode will be started before the
2618  * cursor is moved unless the cursor was on a status line.
2619  * This function returns one of IN_UNKNOWN, IN_BUFFER, IN_STATUS_LINE or
2620  * IN_SEP_LINE depending on where the cursor was clicked.
2621  *
2622  * If flags has MOUSE_MAY_STOP_VIS, then Visual mode will be stopped, unless
2623  * the mouse is on the status line of the same window.
2624  *
2625  * If flags has MOUSE_DID_MOVE, nothing is done if the mouse didn't move since
2626  * the last call.
2627  *
2628  * If flags has MOUSE_SETPOS, nothing is done, only the current position is
2629  * remembered.
2630  */
2631     int
2632 jump_to_mouse(flags, inclusive, which_button)
2633     int		flags;
2634     int		*inclusive;	/* used for inclusive operator, can be NULL */
2635     int		which_button;	/* MOUSE_LEFT, MOUSE_RIGHT, MOUSE_MIDDLE */
2636 {
2637     static int	on_status_line = 0;	/* #lines below bottom of window */
2638 #ifdef FEAT_VERTSPLIT
2639     static int	on_sep_line = 0;	/* on separator right of window */
2640 #endif
2641     static int	prev_row = -1;
2642     static int	prev_col = -1;
2643     static win_T *dragwin = NULL;	/* window being dragged */
2644     static int	did_drag = FALSE;	/* drag was noticed */
2645 
2646     win_T	*wp, *old_curwin;
2647     pos_T	old_cursor;
2648     int		count;
2649     int		first;
2650     int		row = mouse_row;
2651     int		col = mouse_col;
2652 #ifdef FEAT_FOLDING
2653     int		mouse_char;
2654 #endif
2655 
2656     mouse_past_bottom = FALSE;
2657     mouse_past_eol = FALSE;
2658 
2659     if (flags & MOUSE_RELEASED)
2660     {
2661 	/* On button release we may change window focus if positioned on a
2662 	 * status line and no dragging happened. */
2663 	if (dragwin != NULL && !did_drag)
2664 	    flags &= ~(MOUSE_FOCUS | MOUSE_DID_MOVE);
2665 	dragwin = NULL;
2666 	did_drag = FALSE;
2667     }
2668 
2669     if ((flags & MOUSE_DID_MOVE)
2670 	    && prev_row == mouse_row
2671 	    && prev_col == mouse_col)
2672     {
2673 retnomove:
2674 	/* before moving the cursor for a left click which is NOT in a status
2675 	 * line, stop Visual mode */
2676 	if (on_status_line)
2677 	    return IN_STATUS_LINE;
2678 #ifdef FEAT_VERTSPLIT
2679 	if (on_sep_line)
2680 	    return IN_SEP_LINE;
2681 #endif
2682 	if (flags & MOUSE_MAY_STOP_VIS)
2683 	{
2684 	    end_visual_mode();
2685 	    redraw_curbuf_later(INVERTED);	/* delete the inversion */
2686 	}
2687 #if defined(FEAT_CMDWIN) && defined(FEAT_CLIPBOARD)
2688 	/* Continue a modeless selection in another window. */
2689 	if (cmdwin_type != 0 && row < W_WINROW(curwin))
2690 	    return IN_OTHER_WIN;
2691 #endif
2692 	return IN_BUFFER;
2693     }
2694 
2695     prev_row = mouse_row;
2696     prev_col = mouse_col;
2697 
2698     if (flags & MOUSE_SETPOS)
2699 	goto retnomove;				/* ugly goto... */
2700 
2701 #ifdef FEAT_FOLDING
2702     /* Remember the character under the mouse, it might be a '-' or '+' in the
2703      * fold column. */
2704     if (row >= 0 && row < Rows && col >= 0 && col <= Columns
2705 						       && ScreenLines != NULL)
2706 	mouse_char = ScreenLines[LineOffset[row] + col];
2707     else
2708 	mouse_char = ' ';
2709 #endif
2710 
2711     old_curwin = curwin;
2712     old_cursor = curwin->w_cursor;
2713 
2714     if (!(flags & MOUSE_FOCUS))
2715     {
2716 	if (row < 0 || col < 0)			/* check if it makes sense */
2717 	    return IN_UNKNOWN;
2718 
2719 #ifdef FEAT_WINDOWS
2720 	/* find the window where the row is in */
2721 	wp = mouse_find_win(&row, &col);
2722 #else
2723 	wp = firstwin;
2724 #endif
2725 	dragwin = NULL;
2726 	/*
2727 	 * winpos and height may change in win_enter()!
2728 	 */
2729 	if (row >= wp->w_height)		/* In (or below) status line */
2730 	{
2731 	    on_status_line = row - wp->w_height + 1;
2732 	    dragwin = wp;
2733 	}
2734 	else
2735 	    on_status_line = 0;
2736 #ifdef FEAT_VERTSPLIT
2737 	if (col >= wp->w_width)		/* In separator line */
2738 	{
2739 	    on_sep_line = col - wp->w_width + 1;
2740 	    dragwin = wp;
2741 	}
2742 	else
2743 	    on_sep_line = 0;
2744 
2745 	/* The rightmost character of the status line might be a vertical
2746 	 * separator character if there is no connecting window to the right. */
2747 	if (on_status_line && on_sep_line)
2748 	{
2749 	    if (stl_connected(wp))
2750 		on_sep_line = 0;
2751 	    else
2752 		on_status_line = 0;
2753 	}
2754 #endif
2755 
2756 	/* Before jumping to another buffer, or moving the cursor for a left
2757 	 * click, stop Visual mode. */
2758 	if (VIsual_active
2759 		&& (wp->w_buffer != curwin->w_buffer
2760 		    || (!on_status_line
2761 #ifdef FEAT_VERTSPLIT
2762 			&& !on_sep_line
2763 #endif
2764 #ifdef FEAT_FOLDING
2765 			&& (
2766 # ifdef FEAT_RIGHTLEFT
2767 			    wp->w_p_rl ? col < W_WIDTH(wp) - wp->w_p_fdc :
2768 # endif
2769 			    col >= wp->w_p_fdc
2770 # ifdef FEAT_CMDWIN
2771 				  + (cmdwin_type == 0 && wp == curwin ? 0 : 1)
2772 # endif
2773 			    )
2774 #endif
2775 			&& (flags & MOUSE_MAY_STOP_VIS))))
2776 	{
2777 	    end_visual_mode();
2778 	    redraw_curbuf_later(INVERTED);	/* delete the inversion */
2779 	}
2780 #ifdef FEAT_CMDWIN
2781 	if (cmdwin_type != 0 && wp != curwin)
2782 	{
2783 	    /* A click outside the command-line window: Use modeless
2784 	     * selection if possible.  Allow dragging the status lines. */
2785 # ifdef FEAT_VERTSPLIT
2786 	    on_sep_line = 0;
2787 # endif
2788 # ifdef FEAT_CLIPBOARD
2789 	    if (on_status_line)
2790 		return IN_STATUS_LINE;
2791 	    return IN_OTHER_WIN;
2792 # else
2793 	    row = 0;
2794 	    col += wp->w_wincol;
2795 	    wp = curwin;
2796 # endif
2797 	}
2798 #endif
2799 #ifdef FEAT_WINDOWS
2800 	/* Only change window focus when not clicking on or dragging the
2801 	 * status line.  Do change focus when releasing the mouse button
2802 	 * (MOUSE_FOCUS was set above if we dragged first). */
2803 	if (dragwin == NULL || (flags & MOUSE_RELEASED))
2804 	    win_enter(wp, TRUE);		/* can make wp invalid! */
2805 # ifdef CHECK_DOUBLE_CLICK
2806 	/* set topline, to be able to check for double click ourselves */
2807 	if (curwin != old_curwin)
2808 	    set_mouse_topline(curwin);
2809 # endif
2810 #endif
2811 	if (on_status_line)			/* In (or below) status line */
2812 	{
2813 	    /* Don't use start_arrow() if we're in the same window */
2814 	    if (curwin == old_curwin)
2815 		return IN_STATUS_LINE;
2816 	    else
2817 		return IN_STATUS_LINE | CURSOR_MOVED;
2818 	}
2819 #ifdef FEAT_VERTSPLIT
2820 	if (on_sep_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_SEP_LINE;
2825 	    else
2826 		return IN_SEP_LINE | CURSOR_MOVED;
2827 	}
2828 #endif
2829 
2830 	curwin->w_cursor.lnum = curwin->w_topline;
2831 #ifdef FEAT_GUI
2832 	/* remember topline, needed for double click */
2833 	gui_prev_topline = curwin->w_topline;
2834 # ifdef FEAT_DIFF
2835 	gui_prev_topfill = curwin->w_topfill;
2836 # endif
2837 #endif
2838     }
2839     else if (on_status_line && which_button == MOUSE_LEFT)
2840     {
2841 #ifdef FEAT_WINDOWS
2842 	if (dragwin != NULL)
2843 	{
2844 	    /* Drag the status line */
2845 	    count = row - dragwin->w_winrow - dragwin->w_height + 1
2846 							     - on_status_line;
2847 	    win_drag_status_line(dragwin, count);
2848 	    did_drag |= count;
2849 	}
2850 #endif
2851 	return IN_STATUS_LINE;			/* Cursor didn't move */
2852     }
2853 #ifdef FEAT_VERTSPLIT
2854     else if (on_sep_line && which_button == MOUSE_LEFT)
2855     {
2856 	if (dragwin != NULL)
2857 	{
2858 	    /* Drag the separator column */
2859 	    count = col - dragwin->w_wincol - dragwin->w_width + 1
2860 								- on_sep_line;
2861 	    win_drag_vsep_line(dragwin, count);
2862 	    did_drag |= count;
2863 	}
2864 	return IN_SEP_LINE;			/* Cursor didn't move */
2865     }
2866 #endif
2867     else /* keep_window_focus must be TRUE */
2868     {
2869 	/* before moving the cursor for a left click, stop Visual mode */
2870 	if (flags & MOUSE_MAY_STOP_VIS)
2871 	{
2872 	    end_visual_mode();
2873 	    redraw_curbuf_later(INVERTED);	/* delete the inversion */
2874 	}
2875 
2876 #if defined(FEAT_CMDWIN) && defined(FEAT_CLIPBOARD)
2877 	/* Continue a modeless selection in another window. */
2878 	if (cmdwin_type != 0 && row < W_WINROW(curwin))
2879 	    return IN_OTHER_WIN;
2880 #endif
2881 
2882 	row -= W_WINROW(curwin);
2883 #ifdef FEAT_VERTSPLIT
2884 	col -= W_WINCOL(curwin);
2885 #endif
2886 
2887 	/*
2888 	 * When clicking beyond the end of the window, scroll the screen.
2889 	 * Scroll by however many rows outside the window we are.
2890 	 */
2891 	if (row < 0)
2892 	{
2893 	    count = 0;
2894 	    for (first = TRUE; curwin->w_topline > 1; )
2895 	    {
2896 #ifdef FEAT_DIFF
2897 		if (curwin->w_topfill < diff_check(curwin, curwin->w_topline))
2898 		    ++count;
2899 		else
2900 #endif
2901 		    count += plines(curwin->w_topline - 1);
2902 		if (!first && count > -row)
2903 		    break;
2904 		first = FALSE;
2905 #ifdef FEAT_FOLDING
2906 		(void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
2907 #endif
2908 #ifdef FEAT_DIFF
2909 		if (curwin->w_topfill < diff_check(curwin, curwin->w_topline))
2910 		    ++curwin->w_topfill;
2911 		else
2912 #endif
2913 		{
2914 		    --curwin->w_topline;
2915 #ifdef FEAT_DIFF
2916 		    curwin->w_topfill = 0;
2917 #endif
2918 		}
2919 	    }
2920 #ifdef FEAT_DIFF
2921 	    check_topfill(curwin, FALSE);
2922 #endif
2923 	    curwin->w_valid &=
2924 		      ~(VALID_WROW|VALID_CROW|VALID_BOTLINE|VALID_BOTLINE_AP);
2925 	    redraw_later(VALID);
2926 	    row = 0;
2927 	}
2928 	else if (row >= curwin->w_height)
2929 	{
2930 	    count = 0;
2931 	    for (first = TRUE; curwin->w_topline < curbuf->b_ml.ml_line_count; )
2932 	    {
2933 #ifdef FEAT_DIFF
2934 		if (curwin->w_topfill > 0)
2935 		    ++count;
2936 		else
2937 #endif
2938 		    count += plines(curwin->w_topline);
2939 		if (!first && count > row - curwin->w_height + 1)
2940 		    break;
2941 		first = FALSE;
2942 #ifdef FEAT_FOLDING
2943 		if (hasFolding(curwin->w_topline, NULL, &curwin->w_topline)
2944 			&& curwin->w_topline == curbuf->b_ml.ml_line_count)
2945 		    break;
2946 #endif
2947 #ifdef FEAT_DIFF
2948 		if (curwin->w_topfill > 0)
2949 		    --curwin->w_topfill;
2950 		else
2951 #endif
2952 		{
2953 		    ++curwin->w_topline;
2954 #ifdef FEAT_DIFF
2955 		    curwin->w_topfill =
2956 				   diff_check_fill(curwin, curwin->w_topline);
2957 #endif
2958 		}
2959 	    }
2960 #ifdef FEAT_DIFF
2961 	    check_topfill(curwin, FALSE);
2962 #endif
2963 	    redraw_later(VALID);
2964 	    curwin->w_valid &=
2965 		      ~(VALID_WROW|VALID_CROW|VALID_BOTLINE|VALID_BOTLINE_AP);
2966 	    row = curwin->w_height - 1;
2967 	}
2968 	else if (row == 0)
2969 	{
2970 	    /* When dragging the mouse, while the text has been scrolled up as
2971 	     * far as it goes, moving the mouse in the top line should scroll
2972 	     * the text down (done later when recomputing w_topline). */
2973 	    if (mouse_dragging > 0
2974 		    && curwin->w_cursor.lnum
2975 				       == curwin->w_buffer->b_ml.ml_line_count
2976 		    && curwin->w_cursor.lnum == curwin->w_topline)
2977 		curwin->w_valid &= ~(VALID_TOPLINE);
2978 	}
2979     }
2980 
2981 #ifdef FEAT_FOLDING
2982     /* Check for position outside of the fold column. */
2983     if (
2984 # ifdef FEAT_RIGHTLEFT
2985 	    curwin->w_p_rl ? col < W_WIDTH(curwin) - curwin->w_p_fdc :
2986 # endif
2987 	    col >= curwin->w_p_fdc
2988 #  ifdef FEAT_CMDWIN
2989 				+ (cmdwin_type == 0 ? 0 : 1)
2990 #  endif
2991        )
2992 	mouse_char = ' ';
2993 #endif
2994 
2995     /* compute the position in the buffer line from the posn on the screen */
2996     if (mouse_comp_pos(curwin, &row, &col, &curwin->w_cursor.lnum))
2997 	mouse_past_bottom = TRUE;
2998 
2999     /* Start Visual mode before coladvance(), for when 'sel' != "old" */
3000     if ((flags & MOUSE_MAY_VIS) && !VIsual_active)
3001     {
3002 	check_visual_highlight();
3003 	VIsual = old_cursor;
3004 	VIsual_active = TRUE;
3005 	VIsual_reselect = TRUE;
3006 	/* if 'selectmode' contains "mouse", start Select mode */
3007 	may_start_select('o');
3008 	setmouse();
3009 	if (p_smd && msg_silent == 0)
3010 	    redraw_cmdline = TRUE;	/* show visual mode later */
3011     }
3012 
3013     curwin->w_curswant = col;
3014     curwin->w_set_curswant = FALSE;	/* May still have been TRUE */
3015     if (coladvance(col) == FAIL)	/* Mouse click beyond end of line */
3016     {
3017 	if (inclusive != NULL)
3018 	    *inclusive = TRUE;
3019 	mouse_past_eol = TRUE;
3020     }
3021     else if (inclusive != NULL)
3022 	*inclusive = FALSE;
3023 
3024     count = IN_BUFFER;
3025     if (curwin != old_curwin || curwin->w_cursor.lnum != old_cursor.lnum
3026 	    || curwin->w_cursor.col != old_cursor.col)
3027 	count |= CURSOR_MOVED;		/* Cursor has moved */
3028 
3029 #ifdef FEAT_FOLDING
3030     if (mouse_char == '+')
3031 	count |= MOUSE_FOLD_OPEN;
3032     else if (mouse_char != ' ')
3033 	count |= MOUSE_FOLD_CLOSE;
3034 #endif
3035 
3036     return count;
3037 }
3038 
3039 /*
3040  * Compute the position in the buffer line from the posn on the screen in
3041  * window "win".
3042  * Returns TRUE if the position is below the last line.
3043  */
3044     int
3045 mouse_comp_pos(win, rowp, colp, lnump)
3046     win_T	*win;
3047     int		*rowp;
3048     int		*colp;
3049     linenr_T	*lnump;
3050 {
3051     int		col = *colp;
3052     int		row = *rowp;
3053     linenr_T	lnum;
3054     int		retval = FALSE;
3055     int		off;
3056     int		count;
3057 
3058 #ifdef FEAT_RIGHTLEFT
3059     if (win->w_p_rl)
3060 	col = W_WIDTH(win) - 1 - col;
3061 #endif
3062 
3063     lnum = win->w_topline;
3064 
3065     while (row > 0)
3066     {
3067 #ifdef FEAT_DIFF
3068 	/* Don't include filler lines in "count" */
3069 	if (win->w_p_diff
3070 # ifdef FEAT_FOLDING
3071 		&& !hasFoldingWin(win, lnum, NULL, NULL, TRUE, NULL)
3072 # endif
3073 		)
3074 	{
3075 	    if (lnum == win->w_topline)
3076 		row -= win->w_topfill;
3077 	    else
3078 		row -= diff_check_fill(win, lnum);
3079 	    count = plines_win_nofill(win, lnum, TRUE);
3080 	}
3081 	else
3082 #endif
3083 	    count = plines_win(win, lnum, TRUE);
3084 	if (count > row)
3085 	    break;	/* Position is in this buffer line. */
3086 #ifdef FEAT_FOLDING
3087 	(void)hasFoldingWin(win, lnum, NULL, &lnum, TRUE, NULL);
3088 #endif
3089 	if (lnum == win->w_buffer->b_ml.ml_line_count)
3090 	{
3091 	    retval = TRUE;
3092 	    break;		/* past end of file */
3093 	}
3094 	row -= count;
3095 	++lnum;
3096     }
3097 
3098     if (!retval)
3099     {
3100 	/* Compute the column without wrapping. */
3101 	off = win_col_off(win) - win_col_off2(win);
3102 	if (col < off)
3103 	    col = off;
3104 	col += row * (W_WIDTH(win) - off);
3105 	/* add skip column (for long wrapping line) */
3106 	col += win->w_skipcol;
3107     }
3108 
3109     if (!win->w_p_wrap)
3110 	col += win->w_leftcol;
3111 
3112     /* skip line number and fold column in front of the line */
3113     col -= win_col_off(win);
3114     if (col < 0)
3115     {
3116 #ifdef FEAT_NETBEANS_INTG
3117 	netbeans_gutter_click(lnum);
3118 #endif
3119 	col = 0;
3120     }
3121 
3122     *colp = col;
3123     *rowp = row;
3124     *lnump = lnum;
3125     return retval;
3126 }
3127 
3128 #if defined(FEAT_WINDOWS) || defined(PROTO)
3129 /*
3130  * Find the window at screen position "*rowp" and "*colp".  The positions are
3131  * updated to become relative to the top-left of the window.
3132  */
3133     win_T *
3134 mouse_find_win(rowp, colp)
3135     int		*rowp;
3136     int		*colp UNUSED;
3137 {
3138     frame_T	*fp;
3139 
3140     fp = topframe;
3141     *rowp -= firstwin->w_winrow;
3142     for (;;)
3143     {
3144 	if (fp->fr_layout == FR_LEAF)
3145 	    break;
3146 #ifdef FEAT_VERTSPLIT
3147 	if (fp->fr_layout == FR_ROW)
3148 	{
3149 	    for (fp = fp->fr_child; fp->fr_next != NULL; fp = fp->fr_next)
3150 	    {
3151 		if (*colp < fp->fr_width)
3152 		    break;
3153 		*colp -= fp->fr_width;
3154 	    }
3155 	}
3156 #endif
3157 	else    /* fr_layout == FR_COL */
3158 	{
3159 	    for (fp = fp->fr_child; fp->fr_next != NULL; fp = fp->fr_next)
3160 	    {
3161 		if (*rowp < fp->fr_height)
3162 		    break;
3163 		*rowp -= fp->fr_height;
3164 	    }
3165 	}
3166     }
3167     return fp->fr_win;
3168 }
3169 #endif
3170 
3171 #if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MAC) \
3172 	|| defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) \
3173 	|| defined(FEAT_GUI_PHOTON) || defined(PROTO)
3174 /*
3175  * Translate window coordinates to buffer position without any side effects
3176  */
3177     int
3178 get_fpos_of_mouse(mpos)
3179     pos_T	*mpos;
3180 {
3181     win_T	*wp;
3182     int		row = mouse_row;
3183     int		col = mouse_col;
3184 
3185     if (row < 0 || col < 0)		/* check if it makes sense */
3186 	return IN_UNKNOWN;
3187 
3188 #ifdef FEAT_WINDOWS
3189     /* find the window where the row is in */
3190     wp = mouse_find_win(&row, &col);
3191 #else
3192     wp = firstwin;
3193 #endif
3194     /*
3195      * winpos and height may change in win_enter()!
3196      */
3197     if (row >= wp->w_height)	/* In (or below) status line */
3198 	return IN_STATUS_LINE;
3199 #ifdef FEAT_VERTSPLIT
3200     if (col >= wp->w_width)	/* In vertical separator line */
3201 	return IN_SEP_LINE;
3202 #endif
3203 
3204     if (wp != curwin)
3205 	return IN_UNKNOWN;
3206 
3207     /* compute the position in the buffer line from the posn on the screen */
3208     if (mouse_comp_pos(curwin, &row, &col, &mpos->lnum))
3209 	return IN_STATUS_LINE; /* past bottom */
3210 
3211     mpos->col = vcol2col(wp, mpos->lnum, col);
3212 
3213     if (mpos->col > 0)
3214 	--mpos->col;
3215 #ifdef FEAT_VIRTUALEDIT
3216     mpos->coladd = 0;
3217 #endif
3218     return IN_BUFFER;
3219 }
3220 
3221 /*
3222  * Convert a virtual (screen) column to a character column.
3223  * The first column is one.
3224  */
3225     int
3226 vcol2col(wp, lnum, vcol)
3227     win_T	*wp;
3228     linenr_T	lnum;
3229     int		vcol;
3230 {
3231     /* try to advance to the specified column */
3232     int		count = 0;
3233     char_u	*ptr;
3234     char_u	*line;
3235 
3236     line = ptr = ml_get_buf(wp->w_buffer, lnum, FALSE);
3237     while (count < vcol && *ptr != NUL)
3238     {
3239 	count += win_lbr_chartabsize(wp, line, ptr, count, NULL);
3240 	mb_ptr_adv(ptr);
3241     }
3242     return (int)(ptr - line);
3243 }
3244 #endif
3245 
3246 #endif /* FEAT_MOUSE */
3247 
3248 #if defined(FEAT_GUI) || defined(WIN3264) || defined(PROTO)
3249 /*
3250  * Called when focus changed.  Used for the GUI or for systems where this can
3251  * be done in the console (Win32).
3252  */
3253     void
3254 ui_focus_change(in_focus)
3255     int		in_focus;	/* TRUE if focus gained. */
3256 {
3257     static time_t	last_time = (time_t)0;
3258     int			need_redraw = FALSE;
3259 
3260     /* When activated: Check if any file was modified outside of Vim.
3261      * Only do this when not done within the last two seconds (could get
3262      * several events in a row). */
3263     if (in_focus && last_time + 2 < time(NULL))
3264     {
3265 	need_redraw = check_timestamps(
3266 # ifdef FEAT_GUI
3267 		gui.in_use
3268 # else
3269 		FALSE
3270 # endif
3271 		);
3272 	last_time = time(NULL);
3273     }
3274 
3275 #ifdef FEAT_AUTOCMD
3276     /*
3277      * Fire the focus gained/lost autocommand.
3278      */
3279     need_redraw |= apply_autocmds(in_focus ? EVENT_FOCUSGAINED
3280 				: EVENT_FOCUSLOST, NULL, NULL, FALSE, curbuf);
3281 #endif
3282 
3283     if (need_redraw)
3284     {
3285 	/* Something was executed, make sure the cursor is put back where it
3286 	 * belongs. */
3287 	need_wait_return = FALSE;
3288 
3289 	if (State & CMDLINE)
3290 	    redrawcmdline();
3291 	else if (State == HITRETURN || State == SETWSIZE || State == ASKMORE
3292 		|| State == EXTERNCMD || State == CONFIRM || exmode_active)
3293 	    repeat_message();
3294 	else if ((State & NORMAL) || (State & INSERT))
3295 	{
3296 	    if (must_redraw != 0)
3297 		update_screen(0);
3298 	    setcursor();
3299 	}
3300 	cursor_on();	    /* redrawing may have switched it off */
3301 	out_flush();
3302 # ifdef FEAT_GUI
3303 	if (gui.in_use)
3304 	{
3305 	    gui_update_cursor(FALSE, TRUE);
3306 	    gui_update_scrollbars(FALSE);
3307 	}
3308 # endif
3309     }
3310 #ifdef FEAT_TITLE
3311     /* File may have been changed from 'readonly' to 'noreadonly' */
3312     if (need_maketitle)
3313 	maketitle();
3314 #endif
3315 }
3316 #endif
3317 
3318 #if defined(USE_IM_CONTROL) || defined(PROTO)
3319 /*
3320  * Save current Input Method status to specified place.
3321  */
3322     void
3323 im_save_status(psave)
3324     long *psave;
3325 {
3326     /* Don't save when 'imdisable' is set or "xic" is NULL, IM is always
3327      * disabled then (but might start later).
3328      * Also don't save when inside a mapping, vgetc_im_active has not been set
3329      * then.
3330      * And don't save when the keys were stuffed (e.g., for a "." command).
3331      * And don't save when the GUI is running but our window doesn't have
3332      * input focus (e.g., when a find dialog is open). */
3333     if (!p_imdisable && KeyTyped && !KeyStuffed
3334 # ifdef FEAT_XIM
3335 	    && xic != NULL
3336 # endif
3337 # ifdef FEAT_GUI
3338 	    && (!gui.in_use || gui.in_focus)
3339 # endif
3340 	)
3341     {
3342 	/* Do save when IM is on, or IM is off and saved status is on. */
3343 	if (vgetc_im_active)
3344 	    *psave = B_IMODE_IM;
3345 	else if (*psave == B_IMODE_IM)
3346 	    *psave = B_IMODE_NONE;
3347     }
3348 }
3349 #endif
3350