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