1 /* vi:set ts=8 sts=4 sw=4:
3 * VIM - Vi IMproved by Bram Moolenaar
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.
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.
16 * 3. Input buffer stuff.
27 if (gui
.in_use
&& !gui
.dying
&& !gui
.starting
)
31 gui_wait_for_chars(p_wd
);
36 /* Don't output anything in silent mode ("ex -s") unless 'verbose' set */
37 if (!(silent_mode
&& p_verbose
== 0))
40 char_u
*tofree
= NULL
;
42 if (output_conv
.vc_type
!= CONV_NONE
)
44 /* Convert characters from 'encoding' to 'termencoding'. */
45 tofree
= string_convert(&output_conv
, s
, &len
);
54 if (output_conv
.vc_type
!= CONV_NONE
)
61 #if defined(UNIX) || defined(VMS) || defined(PROTO)
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.
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*/
72 ui_inchar_undo(s
, len
)
81 newlen
+= ta_len
- ta_off
;
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
);
92 mch_memmove(new, s
, (size_t)len
);
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.
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
114 ui_inchar(buf
, maxlen
, wtime
, tb_change_cnt
)
117 long wtime
; /* don't use "time", MIPS cannot handle it */
122 #if defined(FEAT_GUI) && (defined(UNIX) || defined(VMS))
124 * Use the typeahead if there is any.
128 if (maxlen
>= ta_len
- ta_off
)
130 mch_memmove(buf
, ta_str
+ ta_off
, (size_t)ta_len
);
135 mch_memmove(buf
, ta_str
+ ta_off
, (size_t)maxlen
);
142 if (do_profiling
== PROF_YES
&& wtime
!= 0)
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())
153 static int count
= 0;
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)
161 if (wtime
== -1 && ++count
== 1000)
169 /* If we are going to wait for some time or block... */
170 if (wtime
== -1 || wtime
> 100L)
172 /* ... allow signals to kill us. */
173 (void)vim_handle_signal(SIGNAL_UNBLOCK
);
175 /* ... there is no need for CTRL-C to interrupt something, don't let
176 * it set got_int when it was mapped. */
178 ctrl_c_interrupts
= FALSE
;
184 if (gui_wait_for_chars(wtime
) && !typebuf_changed(tb_change_cnt
))
185 retval
= read_from_input_buf(buf
, (long)maxlen
);
193 retval
= mch_inchar(buf
, maxlen
, wtime
, tb_change_cnt
);
197 if (wtime
== -1 || wtime
> 100L)
198 /* block SIGHUP et al. */
199 (void)vim_handle_signal(SIGNAL_BLOCK
);
201 ctrl_c_interrupts
= TRUE
;
203 #ifdef NO_CONSOLE_INPUT
207 if (do_profiling
== PROF_YES
&& wtime
!= 0)
214 * return non-zero if a character is available
223 return input_available();
227 # ifdef NO_CONSOLE_INPUT
228 if (no_console_input())
231 return mch_char_avail();
238 * Delay for the given number of milliseconds. If ignoreinput is FALSE then we
239 * cancel the delay if a key is hit.
242 ui_delay(msec
, ignoreinput
)
247 if (gui
.in_use
&& !ignoreinput
)
248 gui_wait_for_chars(msec
);
252 #if defined(FEAT_GUI_MACVIM)
253 /* MacVim tries to be conservative with flushing, but when Vim takes a
254 * nap it really must flush (else timed error messages might not appear
255 * etc.). Note that gui_mch_wait_for_chars() already does force a
256 * flush, so only do it here. */
258 gui_macvim_force_flush();
260 mch_delay(msec
, ignoreinput
);
265 * If the machine has job control, use it to suspend the program,
266 * otherwise fake it by starting a new shell.
267 * When running the GUI iconify the window.
282 #if !defined(UNIX) || !defined(SIGTSTP) || defined(PROTO) || defined(__BEOS__)
284 * When the OS can't really suspend, call this function to start a shell.
285 * This is never called in the GUI.
291 EMSG(_(e_shellempty
));
294 MSG_PUTS(_("new shell started\n"));
301 * Try to get the current Vim shell size. Put the result in Rows and Columns.
302 * Use the new sizes as defaults for 'columns' and 'lines'.
303 * Return OK when size could be determined, FAIL otherwise.
312 # ifdef FEAT_GUI_MACVIM
313 || gui
.starting
/* TODO: Do this check for all GUIs? */
316 retval
= gui_get_shellsize();
319 retval
= mch_get_shellsize();
323 /* adjust the default for 'lines' and 'columns' */
326 set_number_default("lines", Rows
);
327 set_number_default("columns", Columns
);
333 * Set the size of the Vim shell according to Rows and Columns, if possible.
334 * The gui_set_shellsize() or mch_set_shellsize() function will try to set the
335 * new size. If this is not possible, it will adjust Rows and Columns.
338 ui_set_shellsize(mustset
)
339 int mustset UNUSED
; /* set by the user */
343 gui_set_shellsize(mustset
,
356 * Called when Rows and/or Columns changed. Adjust scroll region and mouse
362 if (full_screen
&& !exiting
)
384 /*****************************************************************************
385 * Functions for copying and pasting text between applications.
386 * This is always included in a GUI version, but may also be included when the
387 * clipboard and mouse is available to a terminal version such as xterm.
388 * Note: there are some more functions in ops.c that handle selection stuff.
390 * Also note that the majority of functions here deal with the X 'primary'
391 * (visible - for Visual mode use) selection, and only that. There are no
392 * versions of these for the 'clipboard' selection, as Visual mode has no use
396 #if defined(FEAT_CLIPBOARD) || defined(PROTO)
399 * Selection stuff using Visual mode, for cutting and pasting text to other
404 * Call this to initialise the clipboard. Pass it FALSE if the clipboard code
405 * is included, but the clipboard can not be used, or TRUE if the clipboard can
406 * be used. Eg unix may call this with FALSE, then call it again with TRUE if
418 cb
->available
= can_use
;
424 cb
->state
= SELECT_CLEARED
;
426 if (cb
== &clip_plus
)
433 * Check whether the VIsual area has changed, and if so try to become the owner
434 * of the selection, and free any old converted selection we may still have
435 * lying around. If the VIsual mode has ended, make a copy of what was
436 * selected so we can still give it to others. Will probably have to make sure
437 * this is called whenever VIsual mode is ended.
440 clip_update_selection()
444 /* If visual mode is only due to a redo command ("."), then ignore it */
445 if (!redo_VIsual_busy
&& VIsual_active
&& (State
& NORMAL
))
447 if (lt(VIsual
, curwin
->w_cursor
))
450 end
= curwin
->w_cursor
;
453 end
.col
+= (*mb_ptr2len
)(ml_get_cursor()) - 1;
458 start
= curwin
->w_cursor
;
461 if (!equalpos(clip_star
.start
, start
)
462 || !equalpos(clip_star
.end
, end
)
463 || clip_star
.vmode
!= VIsual_mode
)
465 clip_clear_selection();
466 clip_star
.start
= start
;
468 clip_star
.vmode
= VIsual_mode
;
469 clip_free_selection(&clip_star
);
470 clip_own_selection(&clip_star
);
471 clip_gen_set_selection(&clip_star
);
477 clip_own_selection(cbd
)
481 * Also want to check somehow that we are reading from the keyboard rather
482 * than a mapping etc.
484 if (!cbd
->owned
&& cbd
->available
)
486 cbd
->owned
= (clip_gen_own_selection(cbd
) == OK
);
488 if (cbd
== &clip_star
)
490 /* May have to show a different kind of highlighting for the
491 * selected area. There is no specific redraw command for this,
492 * just redraw all windows on the current buffer. */
494 && (get_real_state() == VISUAL
495 || get_real_state() == SELECTMODE
)
497 && hl_attr(HLF_V
) != hl_attr(HLF_VNC
))
498 redraw_curbuf_later(INVERTED_ALL
);
505 clip_lose_selection(cbd
)
509 int was_owned
= cbd
->owned
;
511 int visual_selection
= (cbd
== &clip_star
);
513 clip_free_selection(cbd
);
515 if (visual_selection
)
516 clip_clear_selection();
517 clip_gen_lose_selection(cbd
);
519 if (visual_selection
)
521 /* May have to show a different kind of highlighting for the selected
522 * area. There is no specific redraw command for this, just redraw all
523 * windows on the current buffer. */
525 && (get_real_state() == VISUAL
526 || get_real_state() == SELECTMODE
)
528 && hl_attr(HLF_V
) != hl_attr(HLF_VNC
))
530 update_curbuf(INVERTED_ALL
);
536 gui_update_cursor(TRUE
, FALSE
);
544 clip_copy_selection()
546 if (VIsual_active
&& (State
& NORMAL
) && clip_star
.available
)
548 if (clip_isautosel())
549 clip_update_selection();
550 clip_free_selection(&clip_star
);
551 clip_own_selection(&clip_star
);
553 clip_get_selection(&clip_star
);
554 clip_gen_set_selection(&clip_star
);
559 * Called when Visual mode is ended: update the selection.
564 if (clip_isautosel())
565 clip_copy_selection();
569 * Return TRUE if automatic selection of Visual area is desired.
576 gui
.in_use
? (vim_strchr(p_go
, GO_ASEL
) != NULL
) :
583 * Stuff for general mouse selection, without using Visual mode.
586 static int clip_compare_pos
__ARGS((int row1
, int col1
, int row2
, int col2
));
587 static void clip_invert_area
__ARGS((int, int, int, int, int how
));
588 static void clip_invert_rectangle
__ARGS((int row
, int col
, int height
, int width
, int invert
));
589 static void clip_get_word_boundaries
__ARGS((VimClipboard
*, int, int));
590 static int clip_get_line_end
__ARGS((int));
591 static void clip_update_modeless_selection
__ARGS((VimClipboard
*, int, int,
594 /* flags for clip_invert_area() */
597 #define CLIP_TOGGLE 3
600 * Start, continue or end a modeless selection. Used when editing the
601 * command-line and in the cmdline window.
604 clip_modeless(button
, is_click
, is_drag
)
611 repeat
= ((clip_star
.mode
== SELECT_MODE_CHAR
612 || clip_star
.mode
== SELECT_MODE_LINE
)
613 && (mod_mask
& MOD_MASK_2CLICK
))
614 || (clip_star
.mode
== SELECT_MODE_WORD
615 && (mod_mask
& MOD_MASK_3CLICK
));
616 if (is_click
&& button
== MOUSE_RIGHT
)
618 /* Right mouse button: If there was no selection, start one.
619 * Otherwise extend the existing selection. */
620 if (clip_star
.state
== SELECT_CLEARED
)
621 clip_start_selection(mouse_col
, mouse_row
, FALSE
);
622 clip_process_selection(button
, mouse_col
, mouse_row
, repeat
);
625 clip_start_selection(mouse_col
, mouse_row
, repeat
);
628 /* Don't try extending a selection if there isn't one. Happens when
629 * button-down is in the cmdline and them moving mouse upwards. */
630 if (clip_star
.state
!= SELECT_CLEARED
)
631 clip_process_selection(button
, mouse_col
, mouse_row
, repeat
);
634 clip_process_selection(MOUSE_RELEASE
, mouse_col
, mouse_row
, FALSE
);
638 * Compare two screen positions ala strcmp()
641 clip_compare_pos(row1
, col1
, row2
, col2
)
647 if (row1
> row2
) return(1);
648 if (row1
< row2
) return(-1);
649 if (col1
> col2
) return(1);
650 if (col1
< col2
) return(-1);
655 * Start the selection
658 clip_start_selection(col
, row
, repeated_click
)
663 VimClipboard
*cb
= &clip_star
;
665 if (cb
->state
== SELECT_DONE
)
666 clip_clear_selection();
668 row
= check_row(row
);
669 col
= check_col(col
);
671 col
= mb_fix_col(col
, row
);
674 cb
->start
.lnum
= row
;
677 cb
->origin_row
= (short_u
)cb
->start
.lnum
;
678 cb
->state
= SELECT_IN_PROGRESS
;
682 if (++cb
->mode
> SELECT_MODE_LINE
)
683 cb
->mode
= SELECT_MODE_CHAR
;
686 cb
->mode
= SELECT_MODE_CHAR
;
689 /* clear the cursor until the selection is made */
696 case SELECT_MODE_CHAR
:
697 cb
->origin_start_col
= cb
->start
.col
;
698 cb
->word_end_col
= clip_get_line_end((int)cb
->start
.lnum
);
701 case SELECT_MODE_WORD
:
702 clip_get_word_boundaries(cb
, (int)cb
->start
.lnum
, cb
->start
.col
);
703 cb
->origin_start_col
= cb
->word_start_col
;
704 cb
->origin_end_col
= cb
->word_end_col
;
706 clip_invert_area((int)cb
->start
.lnum
, cb
->word_start_col
,
707 (int)cb
->end
.lnum
, cb
->word_end_col
, CLIP_SET
);
708 cb
->start
.col
= cb
->word_start_col
;
709 cb
->end
.col
= cb
->word_end_col
;
712 case SELECT_MODE_LINE
:
713 clip_invert_area((int)cb
->start
.lnum
, 0, (int)cb
->start
.lnum
,
714 (int)Columns
, CLIP_SET
);
716 cb
->end
.col
= Columns
;
720 cb
->prev
= cb
->start
;
722 #ifdef DEBUG_SELECTION
723 printf("Selection started at (%u,%u)\n", cb
->start
.lnum
, cb
->start
.col
);
728 * Continue processing the selection
731 clip_process_selection(button
, col
, row
, repeated_click
)
735 int_u repeated_click
;
737 VimClipboard
*cb
= &clip_star
;
739 int slen
= 1; /* cursor shape width */
741 if (button
== MOUSE_RELEASE
)
743 /* Check to make sure we have something selected */
744 if (cb
->start
.lnum
== cb
->end
.lnum
&& cb
->start
.col
== cb
->end
.col
)
748 gui_update_cursor(FALSE
, FALSE
);
750 cb
->state
= SELECT_CLEARED
;
754 #ifdef DEBUG_SELECTION
755 printf("Selection ended: (%u,%u) to (%u,%u)\n", cb
->start
.lnum
,
756 cb
->start
.col
, cb
->end
.lnum
, cb
->end
.col
);
761 gui
.in_use
? (vim_strchr(p_go
, GO_ASELML
) != NULL
) :
764 clip_copy_modeless_selection(FALSE
);
767 gui_update_cursor(FALSE
, FALSE
);
770 cb
->state
= SELECT_DONE
;
774 row
= check_row(row
);
775 col
= check_col(col
);
777 col
= mb_fix_col(col
, row
);
780 if (col
== (int)cb
->prev
.col
&& row
== cb
->prev
.lnum
&& !repeated_click
)
784 * When extending the selection with the right mouse button, swap the
785 * start and end if the position is before half the selection
787 if (cb
->state
== SELECT_DONE
&& button
== MOUSE_RIGHT
)
790 * If the click is before the start, or the click is inside the
791 * selection and the start is the closest side, set the origin to the
792 * end of the selection.
794 if (clip_compare_pos(row
, col
, (int)cb
->start
.lnum
, cb
->start
.col
) < 0
795 || (clip_compare_pos(row
, col
,
796 (int)cb
->end
.lnum
, cb
->end
.col
) < 0
797 && (((cb
->start
.lnum
== cb
->end
.lnum
798 && cb
->end
.col
- col
> col
- cb
->start
.col
))
799 || ((diff
= (cb
->end
.lnum
- row
) -
800 (row
- cb
->start
.lnum
)) > 0
801 || (diff
== 0 && col
< (int)(cb
->start
.col
+
802 cb
->end
.col
) / 2)))))
804 cb
->origin_row
= (short_u
)cb
->end
.lnum
;
805 cb
->origin_start_col
= cb
->end
.col
- 1;
806 cb
->origin_end_col
= cb
->end
.col
;
810 cb
->origin_row
= (short_u
)cb
->start
.lnum
;
811 cb
->origin_start_col
= cb
->start
.col
;
812 cb
->origin_end_col
= cb
->start
.col
;
814 if (cb
->mode
== SELECT_MODE_WORD
&& !repeated_click
)
815 cb
->mode
= SELECT_MODE_CHAR
;
818 /* set state, for when using the right mouse button */
819 cb
->state
= SELECT_IN_PROGRESS
;
821 #ifdef DEBUG_SELECTION
822 printf("Selection extending to (%d,%d)\n", row
, col
);
825 if (repeated_click
&& ++cb
->mode
> SELECT_MODE_LINE
)
826 cb
->mode
= SELECT_MODE_CHAR
;
830 case SELECT_MODE_CHAR
:
831 /* If we're on a different line, find where the line ends */
832 if (row
!= cb
->prev
.lnum
)
833 cb
->word_end_col
= clip_get_line_end(row
);
835 /* See if we are before or after the origin of the selection */
836 if (clip_compare_pos(row
, col
, cb
->origin_row
,
837 cb
->origin_start_col
) >= 0)
839 if (col
>= (int)cb
->word_end_col
)
840 clip_update_modeless_selection(cb
, cb
->origin_row
,
841 cb
->origin_start_col
, row
, (int)Columns
);
845 if (has_mbyte
&& mb_lefthalve(row
, col
))
848 clip_update_modeless_selection(cb
, cb
->origin_row
,
849 cb
->origin_start_col
, row
, col
+ slen
);
856 && mb_lefthalve(cb
->origin_row
, cb
->origin_start_col
))
859 if (col
>= (int)cb
->word_end_col
)
860 clip_update_modeless_selection(cb
, row
, cb
->word_end_col
,
861 cb
->origin_row
, cb
->origin_start_col
+ slen
);
863 clip_update_modeless_selection(cb
, row
, col
,
864 cb
->origin_row
, cb
->origin_start_col
+ slen
);
868 case SELECT_MODE_WORD
:
869 /* If we are still within the same word, do nothing */
870 if (row
== cb
->prev
.lnum
&& col
>= (int)cb
->word_start_col
871 && col
< (int)cb
->word_end_col
&& !repeated_click
)
874 /* Get new word boundaries */
875 clip_get_word_boundaries(cb
, row
, col
);
877 /* Handle being after the origin point of selection */
878 if (clip_compare_pos(row
, col
, cb
->origin_row
,
879 cb
->origin_start_col
) >= 0)
880 clip_update_modeless_selection(cb
, cb
->origin_row
,
881 cb
->origin_start_col
, row
, cb
->word_end_col
);
883 clip_update_modeless_selection(cb
, row
, cb
->word_start_col
,
884 cb
->origin_row
, cb
->origin_end_col
);
887 case SELECT_MODE_LINE
:
888 if (row
== cb
->prev
.lnum
&& !repeated_click
)
891 if (clip_compare_pos(row
, col
, cb
->origin_row
,
892 cb
->origin_start_col
) >= 0)
893 clip_update_modeless_selection(cb
, cb
->origin_row
, 0, row
,
896 clip_update_modeless_selection(cb
, row
, 0, cb
->origin_row
,
904 #ifdef DEBUG_SELECTION
905 printf("Selection is: (%u,%u) to (%u,%u)\n", cb
->start
.lnum
,
906 cb
->start
.col
, cb
->end
.lnum
, cb
->end
.col
);
912 * Called after an Expose event to redraw the selection
915 clip_redraw_selection(x
, y
, w
, h
)
921 VimClipboard
*cb
= &clip_star
;
922 int row1
, col1
, row2
, col2
;
927 if (cb
->state
== SELECT_CLEARED
)
930 row1
= check_row(Y_2_ROW(y
));
931 col1
= check_col(X_2_COL(x
));
932 row2
= check_row(Y_2_ROW(y
+ h
- 1));
933 col2
= check_col(X_2_COL(x
+ w
- 1));
935 /* Limit the rows that need to be re-drawn */
936 if (cb
->start
.lnum
> row1
)
937 row1
= cb
->start
.lnum
;
938 if (cb
->end
.lnum
< row2
)
941 /* Look at each row that might need to be re-drawn */
942 for (row
= row1
; row
<= row2
; row
++)
944 /* For the first selection row, use the starting selection column */
945 if (row
== cb
->start
.lnum
)
946 start
= cb
->start
.col
;
950 /* For the last selection row, use the ending selection column */
951 if (row
== cb
->end
.lnum
)
963 gui_mch_invert_rectangle(row
, start
, 1, end
- start
);
968 # if defined(FEAT_GUI) || defined(PROTO)
970 * Redraw part of the selection if character at "row,col" is inside of it.
971 * Only used for the GUI.
974 clip_may_redraw_selection(row
, col
, len
)
981 if (clip_star
.state
!= SELECT_CLEARED
982 && row
>= clip_star
.start
.lnum
983 && row
<= clip_star
.end
.lnum
)
985 if (row
== clip_star
.start
.lnum
&& start
< (int)clip_star
.start
.col
)
986 start
= clip_star
.start
.col
;
987 if (row
== clip_star
.end
.lnum
&& end
> (int)clip_star
.end
.col
)
988 end
= clip_star
.end
.col
;
990 clip_invert_area(row
, start
, row
, end
, 0);
996 * Called from outside to clear selected region from the display
999 clip_clear_selection()
1001 VimClipboard
*cb
= &clip_star
;
1003 if (cb
->state
== SELECT_CLEARED
)
1006 clip_invert_area((int)cb
->start
.lnum
, cb
->start
.col
, (int)cb
->end
.lnum
,
1007 cb
->end
.col
, CLIP_CLEAR
);
1008 cb
->state
= SELECT_CLEARED
;
1012 * Clear the selection if any lines from "row1" to "row2" are inside of it.
1015 clip_may_clear_selection(row1
, row2
)
1018 if (clip_star
.state
== SELECT_DONE
1019 && row2
>= clip_star
.start
.lnum
1020 && row1
<= clip_star
.end
.lnum
)
1021 clip_clear_selection();
1025 * Called before the screen is scrolled up or down. Adjusts the line numbers
1026 * of the selection. Call with big number when clearing the screen.
1029 clip_scroll_selection(rows
)
1030 int rows
; /* negative for scroll down */
1034 if (clip_star
.state
== SELECT_CLEARED
)
1037 lnum
= clip_star
.start
.lnum
- rows
;
1039 clip_star
.start
.lnum
= 0;
1040 else if (lnum
>= screen_Rows
) /* scrolled off of the screen */
1041 clip_star
.state
= SELECT_CLEARED
;
1043 clip_star
.start
.lnum
= lnum
;
1045 lnum
= clip_star
.end
.lnum
- rows
;
1046 if (lnum
< 0) /* scrolled off of the screen */
1047 clip_star
.state
= SELECT_CLEARED
;
1048 else if (lnum
>= screen_Rows
)
1049 clip_star
.end
.lnum
= screen_Rows
- 1;
1051 clip_star
.end
.lnum
= lnum
;
1055 * Invert a region of the display between a starting and ending row and column
1057 * CLIP_CLEAR: undo inversion
1058 * CLIP_SET: set inversion
1059 * CLIP_TOGGLE: set inversion if pos1 < pos2, undo inversion otherwise.
1060 * 0: invert (GUI only).
1063 clip_invert_area(row1
, col1
, row2
, col2
, how
)
1072 if (how
== CLIP_SET
)
1075 /* Swap the from and to positions so the from is always before */
1076 if (clip_compare_pos(row1
, col1
, row2
, col2
) > 0)
1078 int tmp_row
, tmp_col
;
1087 else if (how
== CLIP_TOGGLE
)
1090 /* If all on the same line, do it the easy way */
1093 clip_invert_rectangle(row1
, col1
, 1, col2
- col1
, invert
);
1097 /* Handle a piece of the first line */
1100 clip_invert_rectangle(row1
, col1
, 1, (int)Columns
- col1
, invert
);
1104 /* Handle a piece of the last line */
1105 if (col2
< Columns
- 1)
1107 clip_invert_rectangle(row2
, 0, 1, col2
, invert
);
1111 /* Handle the rectangle thats left */
1113 clip_invert_rectangle(row1
, 0, row2
- row1
+ 1, (int)Columns
,
1119 * Invert or un-invert a rectangle of the screen.
1120 * "invert" is true if the result is inverted.
1123 clip_invert_rectangle(row
, col
, height
, width
, invert
)
1132 # ifdef FEAT_GUI_MACVIM
1133 gui_mch_invert_rectangle(row
, col
, height
, width
, invert
);
1135 gui_mch_invert_rectangle(row
, col
, height
, width
);
1139 screen_draw_rectangle(row
, col
, height
, width
, invert
);
1143 * Copy the currently selected area into the '*' register so it will be
1144 * available for pasting.
1145 * When "both" is TRUE also copy to the '+' register.
1148 clip_copy_modeless_selection(both
)
1157 int add_newline_flag
= FALSE
;
1162 int row1
= clip_star
.start
.lnum
;
1163 int col1
= clip_star
.start
.col
;
1164 int row2
= clip_star
.end
.lnum
;
1165 int col2
= clip_star
.end
.col
;
1167 /* Can't use ScreenLines unless initialized */
1168 if (ScreenLines
== NULL
)
1172 * Make sure row1 <= row2, and if row1 == row2 that col1 <= col2.
1176 row
= row1
; row1
= row2
; row2
= row
;
1177 row
= col1
; col1
= col2
; col2
= row
;
1179 else if (row1
== row2
&& col1
> col2
)
1181 row
= col1
; col1
= col2
; col2
= row
;
1184 /* correct starting point for being on right halve of double-wide char */
1185 p
= ScreenLines
+ LineOffset
[row1
];
1187 col1
-= (*mb_head_off
)(p
, p
+ col1
);
1188 else if (enc_utf8
&& p
[col1
] == 0)
1192 /* Create a temporary buffer for storing the text */
1193 len
= (row2
- row1
+ 1) * Columns
+ 1;
1196 len
*= 2; /* max. 2 bytes per display cell */
1200 buffer
= lalloc((long_u
)len
, TRUE
);
1201 if (buffer
== NULL
) /* out of memory */
1204 /* Process each row in the selection */
1205 for (bufp
= buffer
, row
= row1
; row
<= row2
; row
++)
1217 line_end_col
= clip_get_line_end(row
);
1219 /* See if we need to nuke some trailing whitespace */
1220 if (end_col
>= Columns
&& (row
< row2
|| end_col
> line_end_col
))
1222 /* Get rid of trailing whitespace */
1223 end_col
= line_end_col
;
1224 if (end_col
< start_col
)
1225 end_col
= start_col
;
1227 /* If the last line extended to the end, add an extra newline */
1229 add_newline_flag
= TRUE
;
1232 /* If after the first row, we need to always add a newline */
1233 if (row
> row1
&& !LineWraps
[row
- 1])
1236 if (row
< screen_Rows
&& end_col
<= screen_Columns
)
1243 p
= ScreenLines
+ LineOffset
[row
];
1244 for (i
= start_col
; i
< end_col
; ++i
)
1245 if (enc_dbcs
== DBCS_JPNU
&& p
[i
] == 0x8e)
1247 /* single-width double-byte char */
1249 *bufp
++ = ScreenLines2
[LineOffset
[row
] + i
];
1254 if (MB_BYTE2LEN(p
[i
]) == 2)
1264 off
= LineOffset
[row
];
1265 for (i
= start_col
; i
< end_col
; ++i
)
1267 /* The base character is either in ScreenLinesUC[] or
1269 if (ScreenLinesUC
[off
+ i
] == 0)
1270 *bufp
++ = ScreenLines
[off
+ i
];
1273 bufp
+= utf_char2bytes(ScreenLinesUC
[off
+ i
], bufp
);
1274 for (ci
= 0; ci
< Screen_mco
; ++ci
)
1276 /* Add a composing character. */
1277 if (ScreenLinesC
[ci
][off
+ i
] == 0)
1279 bufp
+= utf_char2bytes(ScreenLinesC
[ci
][off
+ i
],
1283 /* Skip right halve of double-wide character. */
1284 if (ScreenLines
[off
+ i
+ 1] == 0)
1291 STRNCPY(bufp
, ScreenLines
+ LineOffset
[row
] + start_col
,
1292 end_col
- start_col
);
1293 bufp
+= end_col
- start_col
;
1298 /* Add a newline at the end if the selection ended there */
1299 if (add_newline_flag
)
1302 /* First cleanup any old selection and become the owner. */
1303 clip_free_selection(&clip_star
);
1304 clip_own_selection(&clip_star
);
1306 /* Yank the text into the '*' register. */
1307 clip_yank_selection(MCHAR
, buffer
, (long)(bufp
- buffer
), &clip_star
);
1309 /* Make the register contents available to the outside world. */
1310 clip_gen_set_selection(&clip_star
);
1315 /* Do the same for the '+' register. */
1316 clip_free_selection(&clip_plus
);
1317 clip_own_selection(&clip_plus
);
1318 clip_yank_selection(MCHAR
, buffer
, (long)(bufp
- buffer
), &clip_plus
);
1319 clip_gen_set_selection(&clip_plus
);
1326 * Find the starting and ending positions of the word at the given row and
1327 * column. Only white-separated words are recognized here.
1329 #define CHAR_CLASS(c) (c <= ' ' ? ' ' : vim_iswordc(c))
1332 clip_get_word_boundaries(cb
, row
, col
)
1344 if (row
>= screen_Rows
|| col
>= screen_Columns
|| ScreenLines
== NULL
)
1347 p
= ScreenLines
+ LineOffset
[row
];
1349 /* Correct for starting in the right halve of a double-wide char */
1351 col
-= dbcs_screen_head_off(p
, p
+ col
);
1352 else if (enc_utf8
&& p
[col
] == 0)
1355 start_class
= CHAR_CLASS(p
[col
]);
1358 for ( ; temp_col
> 0; temp_col
--)
1361 && (mboff
= dbcs_screen_head_off(p
, p
+ temp_col
- 1)) > 0)
1365 if (CHAR_CLASS(p
[temp_col
- 1]) != start_class
1367 && !(enc_utf8
&& p
[temp_col
- 1] == 0)
1371 cb
->word_start_col
= temp_col
;
1374 for ( ; temp_col
< screen_Columns
; temp_col
++)
1376 if (enc_dbcs
!= 0 && dbcs_ptr2cells(p
+ temp_col
) == 2)
1380 if (CHAR_CLASS(p
[temp_col
]) != start_class
1382 && !(enc_utf8
&& p
[temp_col
] == 0)
1386 cb
->word_end_col
= temp_col
;
1390 * Find the column position for the last non-whitespace character on the given
1394 clip_get_line_end(row
)
1399 if (row
>= screen_Rows
|| ScreenLines
== NULL
)
1401 for (i
= screen_Columns
; i
> 0; i
--)
1402 if (ScreenLines
[LineOffset
[row
] + i
- 1] != ' ')
1408 * Update the currently selected region by adding and/or subtracting from the
1409 * beginning or end and inverting the changed area(s).
1412 clip_update_modeless_selection(cb
, row1
, col1
, row2
, col2
)
1419 /* See if we changed at the beginning of the selection */
1420 if (row1
!= cb
->start
.lnum
|| col1
!= (int)cb
->start
.col
)
1422 clip_invert_area(row1
, col1
, (int)cb
->start
.lnum
, cb
->start
.col
,
1424 cb
->start
.lnum
= row1
;
1425 cb
->start
.col
= col1
;
1428 /* See if we changed at the end of the selection */
1429 if (row2
!= cb
->end
.lnum
|| col2
!= (int)cb
->end
.col
)
1431 clip_invert_area((int)cb
->end
.lnum
, cb
->end
.col
, row2
, col2
,
1433 cb
->end
.lnum
= row2
;
1439 clip_gen_own_selection(cbd
)
1442 #ifdef FEAT_XCLIPBOARD
1445 return clip_mch_own_selection(cbd
);
1448 return clip_xterm_own_selection(cbd
);
1450 return clip_mch_own_selection(cbd
);
1455 clip_gen_lose_selection(cbd
)
1458 #ifdef FEAT_XCLIPBOARD
1461 clip_mch_lose_selection(cbd
);
1464 clip_xterm_lose_selection(cbd
);
1466 clip_mch_lose_selection(cbd
);
1471 clip_gen_set_selection(cbd
)
1474 #ifdef FEAT_XCLIPBOARD
1477 clip_mch_set_selection(cbd
);
1480 clip_xterm_set_selection(cbd
);
1482 clip_mch_set_selection(cbd
);
1487 clip_gen_request_selection(cbd
)
1490 #ifdef FEAT_XCLIPBOARD
1493 clip_mch_request_selection(cbd
);
1496 clip_xterm_request_selection(cbd
);
1498 clip_mch_request_selection(cbd
);
1502 #endif /* FEAT_CLIPBOARD */
1504 /*****************************************************************************
1505 * Functions that handle the input buffer.
1506 * This is used for any GUI version, and the unix terminal version.
1508 * For Unix, the input characters are buffered to be able to check for a
1509 * CTRL-C. This should be done with signals, but I don't know how to do that
1510 * in a portable way for a tty in RAW mode.
1512 * For the client-server code in the console the received keys are put in the
1516 #if defined(USE_INPUT_BUF) || defined(PROTO)
1519 * Internal typeahead buffer. Includes extra space for long key code
1520 * descriptions which would otherwise overflow. The buffer is considered full
1521 * when only this extra space (or part of it) remains.
1523 #if defined(FEAT_SUN_WORKSHOP) || defined(FEAT_NETBEANS_INTG) \
1524 || defined(FEAT_CLIENTSERVER)
1526 * Sun WorkShop and NetBeans stuff debugger commands into the input buffer.
1527 * This requires a larger buffer...
1528 * (Madsen) Go with this for remote input as well ...
1530 # define INBUFLEN 4096
1532 # define INBUFLEN 250
1535 static char_u inbuf
[INBUFLEN
+ MAX_KEY_CODE_LEN
];
1536 static int inbufcount
= 0; /* number of chars in inbuf[] */
1539 * vim_is_input_buf_full(), vim_is_input_buf_empty(), add_to_input_buf(), and
1540 * trash_input_buf() are functions for manipulating the input buffer. These
1541 * are used by the gui_* calls when a GUI is used to handle keyboard input.
1545 vim_is_input_buf_full()
1547 return (inbufcount
>= INBUFLEN
);
1551 vim_is_input_buf_empty()
1553 return (inbufcount
== 0);
1556 #if defined(FEAT_OLE) || defined(PROTO)
1558 vim_free_in_input_buf()
1560 return (INBUFLEN
- inbufcount
);
1564 #if defined(FEAT_GUI_GTK) || defined(PROTO)
1566 vim_used_in_input_buf()
1572 #if defined(FEAT_EVAL) || defined(FEAT_EX_EXTRA) || defined(PROTO)
1574 * Return the current contents of the input buffer and make it empty.
1575 * The returned pointer must be passed to set_input_buf() later.
1582 /* We use a growarray to store the data pointer and the length. */
1583 gap
= (garray_T
*)alloc((unsigned)sizeof(garray_T
));
1586 /* Add one to avoid a zero size. */
1587 gap
->ga_data
= alloc((unsigned)inbufcount
+ 1);
1588 if (gap
->ga_data
!= NULL
)
1589 mch_memmove(gap
->ga_data
, inbuf
, (size_t)inbufcount
);
1590 gap
->ga_len
= inbufcount
;
1593 return (char_u
*)gap
;
1597 * Restore the input buffer with a pointer returned from get_input_buf().
1598 * The allocated memory is freed, this only works once!
1604 garray_T
*gap
= (garray_T
*)p
;
1608 if (gap
->ga_data
!= NULL
)
1610 mch_memmove(inbuf
, gap
->ga_data
, gap
->ga_len
);
1611 inbufcount
= gap
->ga_len
;
1612 vim_free(gap
->ga_data
);
1619 #if defined(FEAT_GUI) \
1620 || defined(FEAT_MOUSE_GPM) || defined(FEAT_SYSMOUSE) \
1621 || defined(FEAT_XCLIPBOARD) || defined(VMS) \
1622 || defined(FEAT_SNIFF) || defined(FEAT_CLIENTSERVER) \
1625 * Add the given bytes to the input buffer
1626 * Special keys start with CSI. A real CSI must have been translated to
1627 * CSI KS_EXTRA KE_CSI. K_SPECIAL doesn't require translation.
1630 add_to_input_buf(s
, len
)
1634 if (inbufcount
+ len
> INBUFLEN
+ MAX_KEY_CODE_LEN
)
1635 return; /* Shouldn't ever happen! */
1637 #ifdef FEAT_HANGULIN
1638 if ((State
& (INSERT
|CMDLINE
)) && hangul_input_state_get())
1639 if ((len
= hangul_input_process(s
, len
)) == 0)
1644 inbuf
[inbufcount
++] = *s
++;
1648 #if ((defined(FEAT_XIM) || defined(FEAT_DND)) && defined(FEAT_GUI_GTK)) \
1649 || defined(FEAT_GUI_MSWIN) \
1650 || defined(FEAT_GUI_MAC) \
1651 || (defined(FEAT_MBYTE) && defined(FEAT_MBYTE_IME)) \
1652 || (defined(FEAT_GUI) && (!defined(USE_ON_FLY_SCROLL) \
1653 || defined(FEAT_MENU))) \
1656 * Add "str[len]" to the input buffer while escaping CSI bytes.
1659 add_to_input_buf_csi(char_u
*str
, int len
)
1664 for (i
= 0; i
< len
; ++i
)
1666 add_to_input_buf(str
+ i
, 1);
1669 /* Turn CSI into K_CSI. */
1671 buf
[1] = (int)KE_CSI
;
1672 add_to_input_buf(buf
, 2);
1678 #if defined(FEAT_HANGULIN) || defined(PROTO)
1680 push_raw_key (s
, len
)
1685 inbuf
[inbufcount
++] = *s
++;
1689 #if defined(FEAT_GUI) || defined(FEAT_EVAL) || defined(FEAT_EX_EXTRA) \
1691 /* Remove everything from the input buffer. Called when ^C is found */
1700 * Read as much data from the input buffer as possible up to maxlen, and store
1702 * Note: this function used to be Read() in unix.c
1705 read_from_input_buf(buf
, maxlen
)
1709 if (inbufcount
== 0) /* if the buffer is empty, fill it */
1710 fill_input_buf(TRUE
);
1711 if (maxlen
> inbufcount
)
1712 maxlen
= inbufcount
;
1713 mch_memmove(buf
, inbuf
, (size_t)maxlen
);
1714 inbufcount
-= maxlen
;
1716 mch_memmove(inbuf
, inbuf
+ maxlen
, (size_t)inbufcount
);
1721 fill_input_buf(exit_on_error
)
1722 int exit_on_error UNUSED
;
1724 #if defined(UNIX) || defined(OS2) || defined(VMS) || defined(MACOS_X_UNIX)
1727 static int did_read_something
= FALSE
;
1729 static char_u
*rest
= NULL
; /* unconverted rest of previous read */
1730 static int restlen
= 0;
1737 # ifdef NO_CONSOLE_INPUT
1738 /* Don't use the GUI input when the window hasn't been opened yet.
1739 * We get here from ui_inchar() when we should try reading from stdin. */
1740 && !no_console_input()
1748 #if defined(UNIX) || defined(OS2) || defined(VMS) || defined(MACOS_X_UNIX)
1749 if (vim_is_input_buf_full())
1752 * Fill_input_buf() is only called when we really need a character.
1753 * If we can't get any, but there is some in the buffer, just return.
1754 * If we can't get any, and there isn't any in the buffer, we give up and
1759 * On the BeBox version (for now), all input is secretly performed within
1760 * beos_select() which is called from RealWaitForChar().
1762 while (!vim_is_input_buf_full() && RealWaitForChar(read_cmd_fd
, 0, NULL
))
1769 if (sniff_request_waiting
)
1771 add_to_input_buf((char_u
*)"\233sniff",6); /* results in K_SNIFF */
1772 sniff_request_waiting
= 0;
1773 want_sniff_request
= 0;
1781 /* Use remainder of previous call, starts with an invalid character
1782 * that may become valid when reading more. */
1783 if (restlen
> INBUFLEN
- inbufcount
)
1784 unconverted
= INBUFLEN
- inbufcount
;
1786 unconverted
= restlen
;
1787 mch_memmove(inbuf
+ inbufcount
, rest
, unconverted
);
1788 if (unconverted
== restlen
)
1795 restlen
-= unconverted
;
1796 mch_memmove(rest
, rest
+ unconverted
, restlen
);
1798 inbufcount
+= unconverted
;
1804 len
= 0; /* to avoid gcc warning */
1805 for (try = 0; try < 100; ++try)
1810 len
= read(read_cmd_fd
,
1812 (char *)inbuf
+ inbufcount
, (size_t)((INBUFLEN
- inbufcount
)
1814 / input_conv
.vc_factor
1818 ) /* avoid syntax highlight error */
1821 if (len
> 0 || got_int
)
1824 * If reading stdin results in an error, continue reading stderr.
1825 * This helps when using "foo | xargs vim".
1827 if (!did_read_something
&& !isatty(read_cmd_fd
) && read_cmd_fd
== 0)
1831 /* We probably set the wrong file descriptor to raw mode. Switch
1832 * back to cooked mode, use another descriptor and set the mode to
1834 settmode(TMODE_COOK
);
1836 /* Use stderr for stdin, also works for shell commands. */
1840 read_cmd_fd
= 2; /* read from stderr instead of stdin */
1848 if (len
<= 0 && !got_int
)
1851 did_read_something
= TRUE
;
1854 /* Interrupted, pretend a CTRL-C was typed. */
1862 * May perform conversion on the input characters.
1863 * Include the unconverted rest of the previous call.
1864 * If there is an incomplete char at the end it is kept for the next
1865 * time, reading more bytes should make conversion possible.
1866 * Don't do this in the unlikely event that the input buffer is too
1867 * small ("rest" still contains more bytes).
1869 if (input_conv
.vc_type
!= CONV_NONE
)
1871 inbufcount
-= unconverted
;
1872 len
= convert_input_safe(inbuf
+ inbufcount
,
1873 len
+ unconverted
, INBUFLEN
- inbufcount
,
1874 rest
== NULL
? &rest
: NULL
, &restlen
);
1880 * if a CTRL-C was typed, remove it from the buffer and set got_int
1882 if (inbuf
[inbufcount
] == 3 && ctrl_c_interrupts
)
1884 /* remove everything typed before the CTRL-C */
1885 mch_memmove(inbuf
, inbuf
+ inbufcount
, (size_t)(len
+ 1));
1892 #endif /* UNIX or OS2 or VMS*/
1894 #endif /* defined(UNIX) || defined(FEAT_GUI) || defined(OS2) || defined(VMS) */
1897 * Exit because of an input read error.
1902 if (silent_mode
) /* Normal way to exit for "ex -s" */
1904 STRCPY(IObuff
, _("Vim: Error reading input, exiting...\n"));
1908 #if defined(CURSOR_SHAPE) || defined(PROTO)
1910 * May update the shape of the cursor.
1917 gui_update_cursor_later();
1920 term_cursor_shape();
1922 # ifdef MCH_CURSOR_SHAPE
1923 mch_update_cursor();
1928 #if defined(FEAT_CLIPBOARD) || defined(FEAT_GUI) || defined(FEAT_RIGHTLEFT) \
1929 || defined(FEAT_MBYTE) || defined(PROTO)
1931 * Check bounds for column number
1939 if (col
>= (int)screen_Columns
)
1940 return (int)screen_Columns
- 1;
1945 * Check bounds for row number
1953 if (row
>= (int)screen_Rows
)
1954 return (int)screen_Rows
- 1;
1960 * Stuff for the X clipboard. Shared between VMS and Unix.
1963 #if defined(FEAT_XCLIPBOARD) || defined(FEAT_GUI_X11) || defined(PROTO)
1964 # include <X11/Xatom.h>
1965 # include <X11/Intrinsic.h>
1968 * Open the application context (if it hasn't been opened yet).
1969 * Used for Motif and Athena GUI and the xterm clipboard.
1974 if (app_context
== NULL
)
1976 XtToolkitInitialize();
1977 app_context
= XtCreateApplicationContext();
1981 static Atom vim_atom
; /* Vim's own special selection format */
1983 static Atom vimenc_atom
; /* Vim's extended selection format */
1985 static Atom compound_text_atom
;
1986 static Atom text_atom
;
1987 static Atom targets_atom
;
1990 x11_setup_atoms(dpy
)
1993 vim_atom
= XInternAtom(dpy
, VIM_ATOM_NAME
, False
);
1995 vimenc_atom
= XInternAtom(dpy
, VIMENC_ATOM_NAME
,False
);
1997 compound_text_atom
= XInternAtom(dpy
, "COMPOUND_TEXT", False
);
1998 text_atom
= XInternAtom(dpy
, "TEXT", False
);
1999 targets_atom
= XInternAtom(dpy
, "TARGETS", False
);
2000 clip_star
.sel_atom
= XA_PRIMARY
;
2001 clip_plus
.sel_atom
= XInternAtom(dpy
, "CLIPBOARD", False
);
2005 * X Selection stuff, for cutting and pasting text to other windows.
2008 static void clip_x11_request_selection_cb
__ARGS((Widget
, XtPointer
, Atom
*, Atom
*, XtPointer
, long_u
*, int *));
2011 clip_x11_request_selection_cb(w
, success
, sel_atom
, type
, value
, length
,
2024 char **text_list
= NULL
;
2027 char_u
*tmpbuf
= NULL
;
2030 if (*sel_atom
== clip_plus
.sel_atom
)
2035 if (value
== NULL
|| *length
== 0)
2037 clip_free_selection(cbd
); /* nothing received, clear register */
2038 *(int *)success
= FALSE
;
2041 motion_type
= MCHAR
;
2042 p
= (char_u
*)value
;
2044 if (*type
== vim_atom
)
2051 else if (*type
== vimenc_atom
)
2064 /* If the encoding of the text is different from 'encoding', attempt
2066 conv
.vc_type
= CONV_NONE
;
2067 convert_setup(&conv
, enc
, p_enc
);
2068 if (conv
.vc_type
!= CONV_NONE
)
2070 convlen
= len
; /* Need to use an int here. */
2071 tmpbuf
= string_convert(&conv
, p
, &convlen
);
2075 convert_setup(&conv
, NULL
, NULL
);
2080 else if (*type
== compound_text_atom
|| (
2084 *type
== text_atom
))
2086 XTextProperty text_prop
;
2090 text_prop
.value
= (unsigned char *)value
;
2091 text_prop
.encoding
= *type
;
2092 text_prop
.format
= *format
;
2093 text_prop
.nitems
= len
;
2094 status
= XmbTextPropertyToTextList(X_DISPLAY
, &text_prop
,
2095 &text_list
, &n_text
);
2096 if (status
!= Success
|| n_text
< 1)
2098 *(int *)success
= FALSE
;
2101 p
= (char_u
*)text_list
[0];
2104 clip_yank_selection(motion_type
, p
, (long)len
, cbd
);
2106 if (text_list
!= NULL
)
2107 XFreeStringList(text_list
);
2111 XtFree((char *)value
);
2112 *(int *)success
= TRUE
;
2116 clip_x11_request_selection(myShell
, dpy
, cbd
)
2126 int timed_out
= FALSE
;
2139 case 0: type
= vimenc_atom
; break;
2141 case 1: type
= vim_atom
; break;
2142 case 2: type
= compound_text_atom
; break;
2143 case 3: type
= text_atom
; break;
2144 default: type
= XA_STRING
;
2147 XtGetSelectionValue(myShell
, cbd
->sel_atom
, type
,
2148 clip_x11_request_selection_cb
, (XtPointer
)&success
, CurrentTime
);
2150 /* Make sure the request for the selection goes out before waiting for
2155 * Wait for result of selection request, otherwise if we type more
2156 * characters, then they will appear before the one that requested the
2157 * paste! Don't worry, we will catch up with any other events later.
2159 start_time
= time(NULL
);
2160 while (success
== MAYBE
)
2162 if (XCheckTypedEvent(dpy
, SelectionNotify
, &event
)
2163 || XCheckTypedEvent(dpy
, SelectionRequest
, &event
)
2164 || XCheckTypedEvent(dpy
, PropertyNotify
, &event
))
2166 /* This is where clip_x11_request_selection_cb() should be
2167 * called. It may actually happen a bit later, so we loop
2168 * until "success" changes.
2169 * We may get a SelectionRequest here and if we don't handle
2170 * it we hang. KDE klipper does this, for example.
2171 * We need to handle a PropertyNotify for large selections. */
2172 XtDispatchEvent(&event
);
2176 /* Time out after 2 to 3 seconds to avoid that we hang when the
2177 * other process doesn't respond. Note that the SelectionNotify
2178 * event may still come later when the selection owner comes back
2179 * to life and the text gets inserted unexpectedly. Don't know
2180 * why that happens or how to avoid that :-(. */
2181 if (time(NULL
) > start_time
+ 2)
2187 /* Do we need this? Probably not. */
2190 /* Wait for 1 msec to avoid that we eat up all CPU time. */
2194 if (success
== TRUE
)
2197 /* don't do a retry with another type after timing out, otherwise we
2198 * hang for 15 seconds. */
2203 /* Final fallback position - use the X CUT_BUFFER0 store */
2204 yank_cut_buffer0(dpy
, cbd
);
2207 static Boolean clip_x11_convert_selection_cb
__ARGS((Widget
, Atom
*, Atom
*, Atom
*, XtPointer
*, long_u
*, int *));
2210 clip_x11_convert_selection_cb(w
, sel_atom
, target
, type
, value
, length
, format
)
2225 if (*sel_atom
== clip_plus
.sel_atom
)
2231 return False
; /* Shouldn't ever happen */
2233 /* requestor wants to know what target types we support */
2234 if (*target
== targets_atom
)
2238 if ((array
= (Atom
*)XtMalloc((unsigned)(sizeof(Atom
) * 6))) == NULL
)
2240 *value
= (XtPointer
)array
;
2242 array
[i
++] = XA_STRING
;
2243 array
[i
++] = targets_atom
;
2245 array
[i
++] = vimenc_atom
;
2247 array
[i
++] = vim_atom
;
2248 array
[i
++] = text_atom
;
2249 array
[i
++] = compound_text_atom
;
2251 /* This used to be: *format = sizeof(Atom) * 8; but that caused
2252 * crashes on 64 bit machines. (Peter Derr) */
2258 if ( *target
!= XA_STRING
2260 && *target
!= vimenc_atom
2262 && *target
!= vim_atom
2263 && *target
!= text_atom
2264 && *target
!= compound_text_atom
)
2267 clip_get_selection(cbd
);
2268 motion_type
= clip_convert_selection(&string
, length
, cbd
);
2269 if (motion_type
< 0)
2272 /* For our own format, the first byte contains the motion type */
2273 if (*target
== vim_atom
)
2277 /* Our own format with encoding: motion 'encoding' NUL text */
2278 if (*target
== vimenc_atom
)
2279 *length
+= STRLEN(p_enc
) + 2;
2282 *value
= XtMalloc((Cardinal
)*length
);
2283 result
= (char_u
*)*value
;
2290 if (*target
== XA_STRING
)
2292 mch_memmove(result
, string
, (size_t)(*length
));
2295 else if (*target
== compound_text_atom
2296 || *target
== text_atom
)
2298 XTextProperty text_prop
;
2299 char *string_nt
= (char *)alloc((unsigned)*length
+ 1);
2301 /* create NUL terminated string which XmbTextListToTextProperty wants */
2302 mch_memmove(string_nt
, string
, (size_t)*length
);
2303 string_nt
[*length
] = NUL
;
2304 XmbTextListToTextProperty(X_DISPLAY
, (char **)&string_nt
, 1,
2305 XCompoundTextStyle
, &text_prop
);
2306 vim_free(string_nt
);
2307 XtFree(*value
); /* replace with COMPOUND text */
2308 *value
= (XtPointer
)(text_prop
.value
); /* from plain text */
2309 *length
= text_prop
.nitems
;
2310 *type
= compound_text_atom
;
2314 else if (*target
== vimenc_atom
)
2316 int l
= STRLEN(p_enc
);
2318 result
[0] = motion_type
;
2319 STRCPY(result
+ 1, p_enc
);
2320 mch_memmove(result
+ l
+ 2, string
, (size_t)(*length
- l
- 2));
2321 *type
= vimenc_atom
;
2327 result
[0] = motion_type
;
2328 mch_memmove(result
+ 1, string
, (size_t)(*length
- 1));
2331 *format
= 8; /* 8 bits per char */
2336 static void clip_x11_lose_ownership_cb
__ARGS((Widget
, Atom
*));
2339 clip_x11_lose_ownership_cb(w
, sel_atom
)
2343 if (*sel_atom
== clip_plus
.sel_atom
)
2344 clip_lose_selection(&clip_plus
);
2346 clip_lose_selection(&clip_star
);
2350 clip_x11_lose_selection(myShell
, cbd
)
2354 XtDisownSelection(myShell
, cbd
->sel_atom
, CurrentTime
);
2358 clip_x11_own_selection(myShell
, cbd
)
2362 if (XtOwnSelection(myShell
, cbd
->sel_atom
, CurrentTime
,
2363 clip_x11_convert_selection_cb
, clip_x11_lose_ownership_cb
,
2370 * Send the current selection to the clipboard. Do nothing for X because we
2371 * will fill in the selection only when requested by another app.
2374 clip_x11_set_selection(cbd
)
2375 VimClipboard
*cbd UNUSED
;
2380 #if defined(FEAT_XCLIPBOARD) || defined(FEAT_GUI_X11) \
2381 || defined(FEAT_GUI_GTK) || defined(PROTO)
2383 * Get the contents of the X CUT_BUFFER0 and put it in "cbd".
2386 yank_cut_buffer0(dpy
, cbd
)
2391 char_u
*buffer
= (char_u
*)XFetchBuffer(dpy
, &nbytes
, 0);
2398 /* CUT_BUFFER0 is supposed to be always latin1. Convert to 'enc' when
2399 * using a multi-byte encoding. Conversion between two 8-bit
2400 * character sets usually fails and the text might actually be in
2404 char_u
*conv_buf
= buffer
;
2407 vc
.vc_type
= CONV_NONE
;
2408 if (convert_setup(&vc
, (char_u
*)"latin1", p_enc
) == OK
)
2410 conv_buf
= string_convert(&vc
, buffer
, &nbytes
);
2411 if (conv_buf
!= NULL
)
2413 clip_yank_selection(MCHAR
, conv_buf
, (long)nbytes
, cbd
);
2417 convert_setup(&vc
, NULL
, NULL
);
2420 if (!done
) /* use the text without conversion */
2422 clip_yank_selection(MCHAR
, buffer
, (long)nbytes
, cbd
);
2423 XFree((void *)buffer
);
2427 verb_msg((char_u
*)_("Used CUT_BUFFER0 instead of empty selection"));
2434 #if defined(FEAT_MOUSE) || defined(PROTO)
2437 * Move the cursor to the specified row and column on the screen.
2438 * Change current window if necessary. Returns an integer with the
2439 * CURSOR_MOVED bit set if the cursor has moved or unset otherwise.
2441 * The MOUSE_FOLD_CLOSE bit is set when clicked on the '-' in a fold column.
2442 * The MOUSE_FOLD_OPEN bit is set when clicked on the '+' in a fold column.
2444 * If flags has MOUSE_FOCUS, then the current window will not be changed, and
2445 * if the mouse is outside the window then the text will scroll, or if the
2446 * mouse was previously on a status line, then the status line may be dragged.
2448 * If flags has MOUSE_MAY_VIS, then VIsual mode will be started before the
2449 * cursor is moved unless the cursor was on a status line.
2450 * This function returns one of IN_UNKNOWN, IN_BUFFER, IN_STATUS_LINE or
2451 * IN_SEP_LINE depending on where the cursor was clicked.
2453 * If flags has MOUSE_MAY_STOP_VIS, then Visual mode will be stopped, unless
2454 * the mouse is on the status line of the same window.
2456 * If flags has MOUSE_DID_MOVE, nothing is done if the mouse didn't move since
2459 * If flags has MOUSE_SETPOS, nothing is done, only the current position is
2463 jump_to_mouse(flags
, inclusive
, which_button
)
2465 int *inclusive
; /* used for inclusive operator, can be NULL */
2466 int which_button
; /* MOUSE_LEFT, MOUSE_RIGHT, MOUSE_MIDDLE */
2468 static int on_status_line
= 0; /* #lines below bottom of window */
2469 #ifdef FEAT_VERTSPLIT
2470 static int on_sep_line
= 0; /* on separator right of window */
2472 static int prev_row
= -1;
2473 static int prev_col
= -1;
2474 static win_T
*dragwin
= NULL
; /* window being dragged */
2475 static int did_drag
= FALSE
; /* drag was noticed */
2477 win_T
*wp
, *old_curwin
;
2481 int row
= mouse_row
;
2482 int col
= mouse_col
;
2487 mouse_past_bottom
= FALSE
;
2488 mouse_past_eol
= FALSE
;
2490 if (flags
& MOUSE_RELEASED
)
2492 /* On button release we may change window focus if positioned on a
2493 * status line and no dragging happened. */
2494 if (dragwin
!= NULL
&& !did_drag
)
2495 flags
&= ~(MOUSE_FOCUS
| MOUSE_DID_MOVE
);
2500 if ((flags
& MOUSE_DID_MOVE
)
2501 && prev_row
== mouse_row
2502 && prev_col
== mouse_col
)
2505 /* before moving the cursor for a left click which is NOT in a status
2506 * line, stop Visual mode */
2508 return IN_STATUS_LINE
;
2509 #ifdef FEAT_VERTSPLIT
2514 if (flags
& MOUSE_MAY_STOP_VIS
)
2517 redraw_curbuf_later(INVERTED
); /* delete the inversion */
2520 #if defined(FEAT_CMDWIN) && defined(FEAT_CLIPBOARD)
2521 /* Continue a modeless selection in another window. */
2522 if (cmdwin_type
!= 0 && row
< W_WINROW(curwin
))
2523 return IN_OTHER_WIN
;
2528 prev_row
= mouse_row
;
2529 prev_col
= mouse_col
;
2531 if (flags
& MOUSE_SETPOS
)
2532 goto retnomove
; /* ugly goto... */
2535 /* Remember the character under the mouse, it might be a '-' or '+' in the
2537 if (row
>= 0 && row
< Rows
&& col
>= 0 && col
<= Columns
2538 && ScreenLines
!= NULL
)
2539 mouse_char
= ScreenLines
[LineOffset
[row
] + col
];
2544 old_curwin
= curwin
;
2545 old_cursor
= curwin
->w_cursor
;
2547 if (!(flags
& MOUSE_FOCUS
))
2549 if (row
< 0 || col
< 0) /* check if it makes sense */
2553 /* find the window where the row is in */
2554 wp
= mouse_find_win(&row
, &col
);
2560 * winpos and height may change in win_enter()!
2562 if (row
>= wp
->w_height
) /* In (or below) status line */
2564 on_status_line
= row
- wp
->w_height
+ 1;
2569 #ifdef FEAT_VERTSPLIT
2570 if (col
>= wp
->w_width
) /* In separator line */
2572 on_sep_line
= col
- wp
->w_width
+ 1;
2578 /* The rightmost character of the status line might be a vertical
2579 * separator character if there is no connecting window to the right. */
2580 if (on_status_line
&& on_sep_line
)
2582 if (stl_connected(wp
))
2590 /* Before jumping to another buffer, or moving the cursor for a left
2591 * click, stop Visual mode. */
2593 && (wp
->w_buffer
!= curwin
->w_buffer
2595 # ifdef FEAT_VERTSPLIT
2598 # ifdef FEAT_FOLDING
2600 # ifdef FEAT_RIGHTLEFT
2601 wp
->w_p_rl
? col
< W_WIDTH(wp
) - wp
->w_p_fdc
:
2605 + (cmdwin_type
== 0 && wp
== curwin
? 0 : 1)
2609 && (flags
& MOUSE_MAY_STOP_VIS
))))
2612 redraw_curbuf_later(INVERTED
); /* delete the inversion */
2616 if (cmdwin_type
!= 0 && wp
!= curwin
)
2618 /* A click outside the command-line window: Use modeless
2619 * selection if possible. Allow dragging the status line of
2620 * windows just above the command-line window. */
2621 if (wp
->w_winrow
+ wp
->w_height
2622 != curwin
->w_prev
->w_winrow
+ curwin
->w_prev
->w_height
)
2627 # ifdef FEAT_VERTSPLIT
2630 # ifdef FEAT_CLIPBOARD
2632 return IN_STATUS_LINE
;
2633 return IN_OTHER_WIN
;
2636 col
+= wp
->w_wincol
;
2642 /* Only change window focus when not clicking on or dragging the
2643 * status line. Do change focus when releasing the mouse button
2644 * (MOUSE_FOCUS was set above if we dragged first). */
2645 if (dragwin
== NULL
|| (flags
& MOUSE_RELEASED
))
2646 win_enter(wp
, TRUE
); /* can make wp invalid! */
2647 # ifdef CHECK_DOUBLE_CLICK
2648 /* set topline, to be able to check for double click ourselves */
2649 if (curwin
!= old_curwin
)
2650 set_mouse_topline(curwin
);
2653 if (on_status_line
) /* In (or below) status line */
2655 /* Don't use start_arrow() if we're in the same window */
2656 if (curwin
== old_curwin
)
2657 return IN_STATUS_LINE
;
2659 return IN_STATUS_LINE
| CURSOR_MOVED
;
2661 #ifdef FEAT_VERTSPLIT
2662 if (on_sep_line
) /* In (or below) status line */
2664 /* Don't use start_arrow() if we're in the same window */
2665 if (curwin
== old_curwin
)
2668 return IN_SEP_LINE
| CURSOR_MOVED
;
2672 curwin
->w_cursor
.lnum
= curwin
->w_topline
;
2674 /* remember topline, needed for double click */
2675 gui_prev_topline
= curwin
->w_topline
;
2677 gui_prev_topfill
= curwin
->w_topfill
;
2681 else if (on_status_line
&& which_button
== MOUSE_LEFT
)
2684 if (dragwin
!= NULL
)
2686 /* Drag the status line */
2687 count
= row
- dragwin
->w_winrow
- dragwin
->w_height
+ 1
2689 win_drag_status_line(dragwin
, count
);
2693 return IN_STATUS_LINE
; /* Cursor didn't move */
2695 #ifdef FEAT_VERTSPLIT
2696 else if (on_sep_line
&& which_button
== MOUSE_LEFT
)
2698 if (dragwin
!= NULL
)
2700 /* Drag the separator column */
2701 count
= col
- dragwin
->w_wincol
- dragwin
->w_width
+ 1
2703 win_drag_vsep_line(dragwin
, count
);
2706 return IN_SEP_LINE
; /* Cursor didn't move */
2709 else /* keep_window_focus must be TRUE */
2712 /* before moving the cursor for a left click, stop Visual mode */
2713 if (flags
& MOUSE_MAY_STOP_VIS
)
2716 redraw_curbuf_later(INVERTED
); /* delete the inversion */
2720 #if defined(FEAT_CMDWIN) && defined(FEAT_CLIPBOARD)
2721 /* Continue a modeless selection in another window. */
2722 if (cmdwin_type
!= 0 && row
< W_WINROW(curwin
))
2723 return IN_OTHER_WIN
;
2726 row
-= W_WINROW(curwin
);
2727 #ifdef FEAT_VERTSPLIT
2728 col
-= W_WINCOL(curwin
);
2732 * When clicking beyond the end of the window, scroll the screen.
2733 * Scroll by however many rows outside the window we are.
2738 for (first
= TRUE
; curwin
->w_topline
> 1; )
2741 if (curwin
->w_topfill
< diff_check(curwin
, curwin
->w_topline
))
2745 count
+= plines(curwin
->w_topline
- 1);
2746 if (!first
&& count
> -row
)
2750 hasFolding(curwin
->w_topline
, &curwin
->w_topline
, NULL
);
2753 if (curwin
->w_topfill
< diff_check(curwin
, curwin
->w_topline
))
2754 ++curwin
->w_topfill
;
2758 --curwin
->w_topline
;
2760 curwin
->w_topfill
= 0;
2765 check_topfill(curwin
, FALSE
);
2768 ~(VALID_WROW
|VALID_CROW
|VALID_BOTLINE
|VALID_BOTLINE_AP
);
2769 redraw_later(VALID
);
2772 else if (row
>= curwin
->w_height
)
2775 for (first
= TRUE
; curwin
->w_topline
< curbuf
->b_ml
.ml_line_count
; )
2778 if (curwin
->w_topfill
> 0)
2782 count
+= plines(curwin
->w_topline
);
2783 if (!first
&& count
> row
- curwin
->w_height
+ 1)
2787 if (hasFolding(curwin
->w_topline
, NULL
, &curwin
->w_topline
)
2788 && curwin
->w_topline
== curbuf
->b_ml
.ml_line_count
)
2792 if (curwin
->w_topfill
> 0)
2793 --curwin
->w_topfill
;
2797 ++curwin
->w_topline
;
2800 diff_check_fill(curwin
, curwin
->w_topline
);
2805 check_topfill(curwin
, FALSE
);
2807 redraw_later(VALID
);
2809 ~(VALID_WROW
|VALID_CROW
|VALID_BOTLINE
|VALID_BOTLINE_AP
);
2810 row
= curwin
->w_height
- 1;
2814 /* When dragging the mouse, while the text has been scrolled up as
2815 * far as it goes, moving the mouse in the top line should scroll
2816 * the text down (done later when recomputing w_topline). */
2817 if (mouse_dragging
> 0
2818 && curwin
->w_cursor
.lnum
2819 == curwin
->w_buffer
->b_ml
.ml_line_count
2820 && curwin
->w_cursor
.lnum
== curwin
->w_topline
)
2821 curwin
->w_valid
&= ~(VALID_TOPLINE
);
2826 /* Check for position outside of the fold column. */
2828 # ifdef FEAT_RIGHTLEFT
2829 curwin
->w_p_rl
? col
< W_WIDTH(curwin
) - curwin
->w_p_fdc
:
2831 col
>= curwin
->w_p_fdc
2833 + (cmdwin_type
== 0 ? 0 : 1)
2839 /* compute the position in the buffer line from the posn on the screen */
2840 if (mouse_comp_pos(curwin
, &row
, &col
, &curwin
->w_cursor
.lnum
))
2841 mouse_past_bottom
= TRUE
;
2844 /* Start Visual mode before coladvance(), for when 'sel' != "old" */
2845 if ((flags
& MOUSE_MAY_VIS
) && !VIsual_active
)
2847 check_visual_highlight();
2848 VIsual
= old_cursor
;
2849 VIsual_active
= TRUE
;
2850 VIsual_reselect
= TRUE
;
2851 /* if 'selectmode' contains "mouse", start Select mode */
2852 may_start_select('o');
2854 if (p_smd
&& msg_silent
== 0)
2855 redraw_cmdline
= TRUE
; /* show visual mode later */
2859 curwin
->w_curswant
= col
;
2860 curwin
->w_set_curswant
= FALSE
; /* May still have been TRUE */
2861 if (coladvance(col
) == FAIL
) /* Mouse click beyond end of line */
2863 if (inclusive
!= NULL
)
2865 mouse_past_eol
= TRUE
;
2867 else if (inclusive
!= NULL
)
2871 if (curwin
!= old_curwin
|| curwin
->w_cursor
.lnum
!= old_cursor
.lnum
2872 || curwin
->w_cursor
.col
!= old_cursor
.col
)
2873 count
|= CURSOR_MOVED
; /* Cursor has moved */
2876 if (mouse_char
== '+')
2877 count
|= MOUSE_FOLD_OPEN
;
2878 else if (mouse_char
!= ' ')
2879 count
|= MOUSE_FOLD_CLOSE
;
2886 * Compute the position in the buffer line from the posn on the screen in
2888 * Returns TRUE if the position is below the last line.
2891 mouse_comp_pos(win
, rowp
, colp
, lnump
)
2904 #ifdef FEAT_RIGHTLEFT
2906 col
= W_WIDTH(win
) - 1 - col
;
2909 lnum
= win
->w_topline
;
2914 /* Don't include filler lines in "count" */
2916 # ifdef FEAT_FOLDING
2917 && !hasFoldingWin(win
, lnum
, NULL
, NULL
, TRUE
, NULL
)
2921 if (lnum
== win
->w_topline
)
2922 row
-= win
->w_topfill
;
2924 row
-= diff_check_fill(win
, lnum
);
2925 count
= plines_win_nofill(win
, lnum
, TRUE
);
2929 count
= plines_win(win
, lnum
, TRUE
);
2931 break; /* Position is in this buffer line. */
2933 (void)hasFoldingWin(win
, lnum
, NULL
, &lnum
, TRUE
, NULL
);
2935 if (lnum
== win
->w_buffer
->b_ml
.ml_line_count
)
2938 break; /* past end of file */
2946 /* Compute the column without wrapping. */
2947 off
= win_col_off(win
) - win_col_off2(win
);
2950 col
+= row
* (W_WIDTH(win
) - off
);
2951 /* add skip column (for long wrapping line) */
2952 col
+= win
->w_skipcol
;
2956 col
+= win
->w_leftcol
;
2958 /* skip line number and fold column in front of the line */
2959 col
-= win_col_off(win
);
2962 #ifdef FEAT_NETBEANS_INTG
2964 netbeans_gutter_click(lnum
);
2975 #if defined(FEAT_WINDOWS) || defined(PROTO)
2977 * Find the window at screen position "*rowp" and "*colp". The positions are
2978 * updated to become relative to the top-left of the window.
2981 mouse_find_win(rowp
, colp
)
2988 *rowp
-= firstwin
->w_winrow
;
2991 if (fp
->fr_layout
== FR_LEAF
)
2993 #ifdef FEAT_VERTSPLIT
2994 if (fp
->fr_layout
== FR_ROW
)
2996 for (fp
= fp
->fr_child
; fp
->fr_next
!= NULL
; fp
= fp
->fr_next
)
2998 if (*colp
< fp
->fr_width
)
3000 *colp
-= fp
->fr_width
;
3004 else /* fr_layout == FR_COL */
3006 for (fp
= fp
->fr_child
; fp
->fr_next
!= NULL
; fp
= fp
->fr_next
)
3008 if (*rowp
< fp
->fr_height
)
3010 *rowp
-= fp
->fr_height
;
3018 #if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) || defined (FEAT_GUI_MAC) \
3019 || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) \
3020 || defined(FEAT_GUI_PHOTON) || defined(PROTO) \
3021 || defined(FEAT_GUI_MACVIM)
3023 * Translate window coordinates to buffer position without any side effects
3026 get_fpos_of_mouse(mpos
)
3030 int row
= mouse_row
;
3031 int col
= mouse_col
;
3033 if (row
< 0 || col
< 0) /* check if it makes sense */
3037 /* find the window where the row is in */
3038 wp
= mouse_find_win(&row
, &col
);
3043 * winpos and height may change in win_enter()!
3045 if (row
>= wp
->w_height
) /* In (or below) status line */
3046 return IN_STATUS_LINE
;
3047 #ifdef FEAT_VERTSPLIT
3048 if (col
>= wp
->w_width
) /* In vertical separator line */
3055 /* compute the position in the buffer line from the posn on the screen */
3056 if (mouse_comp_pos(curwin
, &row
, &col
, &mpos
->lnum
))
3057 return IN_STATUS_LINE
; /* past bottom */
3059 mpos
->col
= vcol2col(wp
, mpos
->lnum
, col
);
3067 * Convert a virtual (screen) column to a character column.
3068 * The first column is one.
3071 vcol2col(wp
, lnum
, vcol
)
3076 /* try to advance to the specified column */
3081 start
= ptr
= ml_get_buf(wp
->w_buffer
, lnum
, FALSE
);
3082 while (count
<= vcol
&& *ptr
!= NUL
)
3084 count
+= win_lbr_chartabsize(wp
, ptr
, count
, NULL
);
3087 return (int)(ptr
- start
);
3091 #endif /* FEAT_MOUSE */
3093 #if defined(FEAT_GUI) || defined(WIN3264) || defined(PROTO)
3095 * Called when focus changed. Used for the GUI or for systems where this can
3096 * be done in the console (Win32).
3099 ui_focus_change(in_focus
)
3100 int in_focus
; /* TRUE if focus gained. */
3102 static time_t last_time
= (time_t)0;
3103 int need_redraw
= FALSE
;
3105 /* When activated: Check if any file was modified outside of Vim.
3106 * Only do this when not done within the last two seconds (could get
3107 * several events in a row). */
3108 if (in_focus
&& last_time
+ 2 < time(NULL
))
3110 need_redraw
= check_timestamps(
3117 last_time
= time(NULL
);
3122 * Fire the focus gained/lost autocommand.
3124 need_redraw
|= apply_autocmds(in_focus
? EVENT_FOCUSGAINED
3125 : EVENT_FOCUSLOST
, NULL
, NULL
, FALSE
, curbuf
);
3130 /* Something was executed, make sure the cursor is put back where it
3132 need_wait_return
= FALSE
;
3134 if (State
& CMDLINE
)
3136 else if (State
== HITRETURN
|| State
== SETWSIZE
|| State
== ASKMORE
3137 || State
== EXTERNCMD
|| State
== CONFIRM
|| exmode_active
)
3139 else if ((State
& NORMAL
) || (State
& INSERT
))
3141 if (must_redraw
!= 0)
3145 cursor_on(); /* redrawing may have switched it off */
3150 gui_update_cursor(FALSE
, TRUE
);
3151 gui_update_scrollbars(FALSE
);
3156 /* File may have been changed from 'readonly' to 'noreadonly' */
3163 #if defined(USE_IM_CONTROL) || defined(PROTO)
3165 * Save current Input Method status to specified place.
3168 im_save_status(psave
)
3171 /* Don't save when 'imdisable' is set or "xic" is NULL, IM is always
3172 * disabled then (but might start later).
3173 * Also don't save when inside a mapping, vgetc_im_active has not been set
3175 * And don't save when the keys were stuffed (e.g., for a "." command).
3176 * And don't save when the GUI is running but our window doesn't have
3177 * input focus (e.g., when a find dialog is open). */
3178 if (!p_imdisable
&& KeyTyped
&& !KeyStuffed
3179 # if defined(FEAT_XIM) && !defined(FEAT_GUI_MACVIM)
3183 && (!gui
.in_use
|| gui
.in_focus
)
3187 /* Do save when IM is on, or IM is off and saved status is on. */
3188 if (vgetc_im_active
)
3189 *psave
= B_IMODE_IM
;
3190 else if (*psave
== B_IMODE_IM
)
3191 *psave
= B_IMODE_NONE
;