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