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