blob: a42393732fe7eed8aff6227986927646f0d2da1f [file] [log] [blame]
Bram Moolenaaredf3f972016-08-29 22:49:24 +02001/* vi:set ts=8 sts=4 sw=4 noet:
Bram Moolenaar071d4272004-06-13 20:20:40 +00002 *
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.
Bram Moolenaar45fffdf2020-03-24 21:42:01 +010015 * 2. Input buffer stuff.
Bram Moolenaar071d4272004-06-13 20:20:40 +000016 */
17
18#include "vim.h"
19
20 void
Bram Moolenaar4c868302021-03-22 16:19:45 +010021ui_write(char_u *s, int len, int console UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +000022{
23#ifdef FEAT_GUI
Bram Moolenaar4c868302021-03-22 16:19:45 +010024 if (gui.in_use && !gui.dying && !gui.starting
25# ifndef NO_CONSOLE
26 && !console
27# endif
28 )
Bram Moolenaar071d4272004-06-13 20:20:40 +000029 {
30 gui_write(s, len);
31 if (p_wd)
Bram Moolenaarc9e649a2017-12-18 18:14:47 +010032 gui_wait_for_chars(p_wd, typebuf.tb_change_cnt);
Bram Moolenaar071d4272004-06-13 20:20:40 +000033 return;
34 }
35#endif
36#ifndef NO_CONSOLE
Bram Moolenaare38eab22019-12-05 21:50:01 +010037 // Don't output anything in silent mode ("ex -s") unless 'verbose' set
Bram Moolenaar071d4272004-06-13 20:20:40 +000038 if (!(silent_mode && p_verbose == 0))
39 {
Bram Moolenaar4c868302021-03-22 16:19:45 +010040# if !defined(MSWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000041 char_u *tofree = NULL;
42
43 if (output_conv.vc_type != CONV_NONE)
44 {
Bram Moolenaare38eab22019-12-05 21:50:01 +010045 // Convert characters from 'encoding' to 'termencoding'.
Bram Moolenaar071d4272004-06-13 20:20:40 +000046 tofree = string_convert(&output_conv, s, &len);
47 if (tofree != NULL)
48 s = tofree;
49 }
Bram Moolenaar4c868302021-03-22 16:19:45 +010050# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000051
52 mch_write(s, len);
Bram Moolenaar5ea79a22021-03-22 16:45:35 +010053# if defined(HAVE_FSYNC)
Bram Moolenaar4c868302021-03-22 16:19:45 +010054 if (console && s[len - 1] == '\n')
Bram Moolenaar5ea79a22021-03-22 16:45:35 +010055 vim_fsync(1);
56# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000057
Bram Moolenaar4f974752019-02-17 17:44:42 +010058# if !defined(MSWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000059 if (output_conv.vc_type != CONV_NONE)
60 vim_free(tofree);
Bram Moolenaar264b74f2019-01-24 17:18:42 +010061# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000062 }
63#endif
64}
65
Bram Moolenaar4f974752019-02-17 17:44:42 +010066#if defined(UNIX) || defined(VMS) || defined(PROTO) || defined(MSWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000067/*
68 * When executing an external program, there may be some typed characters that
69 * are not consumed by it. Give them back to ui_inchar() and they are stored
70 * here for the next call.
71 */
72static char_u *ta_str = NULL;
Bram Moolenaare38eab22019-12-05 21:50:01 +010073static int ta_off; // offset for next char to use when ta_str != NULL
74static int ta_len; // length of ta_str when it's not NULL
Bram Moolenaar071d4272004-06-13 20:20:40 +000075
76 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +010077ui_inchar_undo(char_u *s, int len)
Bram Moolenaar071d4272004-06-13 20:20:40 +000078{
79 char_u *new;
80 int newlen;
81
82 newlen = len;
83 if (ta_str != NULL)
84 newlen += ta_len - ta_off;
85 new = alloc(newlen);
86 if (new != NULL)
87 {
88 if (ta_str != NULL)
89 {
90 mch_memmove(new, ta_str + ta_off, (size_t)(ta_len - ta_off));
91 mch_memmove(new + ta_len - ta_off, s, (size_t)len);
92 vim_free(ta_str);
93 }
94 else
95 mch_memmove(new, s, (size_t)len);
96 ta_str = new;
97 ta_len = newlen;
98 ta_off = 0;
99 }
100}
101#endif
102
103/*
Bram Moolenaarb6101cf2012-10-21 00:58:39 +0200104 * ui_inchar(): low level input function.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000105 * Get characters from the keyboard.
106 * Return the number of characters that are available.
107 * If "wtime" == 0 do not wait for characters.
108 * If "wtime" == -1 wait forever for characters.
109 * If "wtime" > 0 wait "wtime" milliseconds for a character.
110 *
111 * "tb_change_cnt" is the value of typebuf.tb_change_cnt if "buf" points into
112 * it. When typebuf.tb_change_cnt changes (e.g., when a message is received
113 * from a remote client) "buf" can no longer be used. "tb_change_cnt" is NULL
114 * otherwise.
115 */
116 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100117ui_inchar(
118 char_u *buf,
119 int maxlen,
Bram Moolenaare38eab22019-12-05 21:50:01 +0100120 long wtime, // don't use "time", MIPS cannot handle it
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100121 int tb_change_cnt)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000122{
123 int retval = 0;
124
125#if defined(FEAT_GUI) && (defined(UNIX) || defined(VMS))
126 /*
127 * Use the typeahead if there is any.
128 */
129 if (ta_str != NULL)
130 {
131 if (maxlen >= ta_len - ta_off)
132 {
133 mch_memmove(buf, ta_str + ta_off, (size_t)ta_len);
Bram Moolenaard23a8232018-02-10 18:45:26 +0100134 VIM_CLEAR(ta_str);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000135 return ta_len;
136 }
137 mch_memmove(buf, ta_str + ta_off, (size_t)maxlen);
138 ta_off += maxlen;
139 return maxlen;
140 }
141#endif
142
Bram Moolenaar05159a02005-02-26 23:04:13 +0000143#ifdef FEAT_PROFILE
Bram Moolenaarb3656ed2006-03-20 21:59:49 +0000144 if (do_profiling == PROF_YES && wtime != 0)
Bram Moolenaar05159a02005-02-26 23:04:13 +0000145 prof_inchar_enter();
146#endif
147
Bram Moolenaar071d4272004-06-13 20:20:40 +0000148#ifdef NO_CONSOLE_INPUT
Bram Moolenaare38eab22019-12-05 21:50:01 +0100149 // Don't wait for character input when the window hasn't been opened yet.
150 // Do try reading, this works when redirecting stdin from a file.
151 // Must return something, otherwise we'll loop forever. If we run into
152 // this very often we probably got stuck, exit Vim.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000153 if (no_console_input())
154 {
155 static int count = 0;
156
157# ifndef NO_CONSOLE
Bram Moolenaar13410242018-11-26 21:19:11 +0100158 retval = mch_inchar(buf, maxlen, wtime, tb_change_cnt);
Bram Moolenaar43b604c2005-03-22 23:06:55 +0000159 if (retval > 0 || typebuf_changed(tb_change_cnt) || wtime >= 0)
Bram Moolenaar05159a02005-02-26 23:04:13 +0000160 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000161# endif
162 if (wtime == -1 && ++count == 1000)
163 read_error_exit();
164 buf[0] = CAR;
Bram Moolenaar05159a02005-02-26 23:04:13 +0000165 retval = 1;
166 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000167 }
168#endif
169
Bram Moolenaare38eab22019-12-05 21:50:01 +0100170 // If we are going to wait for some time or block...
Bram Moolenaarc8da3112007-03-08 12:36:46 +0000171 if (wtime == -1 || wtime > 100L)
172 {
Bram Moolenaare38eab22019-12-05 21:50:01 +0100173 // ... allow signals to kill us.
Bram Moolenaarc8da3112007-03-08 12:36:46 +0000174 (void)vim_handle_signal(SIGNAL_UNBLOCK);
175
Bram Moolenaare38eab22019-12-05 21:50:01 +0100176 // ... there is no need for CTRL-C to interrupt something, don't let
177 // it set got_int when it was mapped.
Bram Moolenaar50008692015-01-14 16:08:32 +0100178 if ((mapped_ctrl_c | curbuf->b_mapped_ctrl_c) & get_real_state())
Bram Moolenaarc8da3112007-03-08 12:36:46 +0000179 ctrl_c_interrupts = FALSE;
180 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000181
Bram Moolenaare40b9d42019-01-27 16:55:47 +0100182 /*
183 * Here we call gui_inchar() or mch_inchar(), the GUI or machine-dependent
184 * input function. The functionality they implement is like this:
185 *
186 * while (not timed out)
187 * {
188 * handle-resize;
189 * parse-queued-messages;
190 * if (waited for 'updatetime')
191 * trigger-cursorhold;
192 * ui_wait_for_chars_or_timer()
193 * if (character available)
194 * break;
195 * }
196 *
197 * ui_wait_for_chars_or_timer() does:
198 *
199 * while (not timed out)
200 * {
201 * if (any-timer-triggered)
202 * invoke-timer-callback;
203 * wait-for-character();
204 * if (character available)
205 * break;
206 * }
207 *
208 * wait-for-character() does:
209 * while (not timed out)
210 * {
211 * Wait for event;
212 * if (something on channel)
213 * read/write channel;
214 * else if (resized)
215 * handle_resize();
216 * else if (system event)
217 * deal-with-system-event;
218 * else if (character available)
219 * break;
220 * }
221 *
222 */
223
Bram Moolenaar071d4272004-06-13 20:20:40 +0000224#ifdef FEAT_GUI
225 if (gui.in_use)
Bram Moolenaarc9e649a2017-12-18 18:14:47 +0100226 retval = gui_inchar(buf, maxlen, wtime, tb_change_cnt);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000227#endif
228#ifndef NO_CONSOLE
229# ifdef FEAT_GUI
230 else
231# endif
232 retval = mch_inchar(buf, maxlen, wtime, tb_change_cnt);
233#endif
234
Bram Moolenaarc8da3112007-03-08 12:36:46 +0000235 if (wtime == -1 || wtime > 100L)
Bram Moolenaare38eab22019-12-05 21:50:01 +0100236 // block SIGHUP et al.
Bram Moolenaarc8da3112007-03-08 12:36:46 +0000237 (void)vim_handle_signal(SIGNAL_BLOCK);
238
Bram Moolenaar071d4272004-06-13 20:20:40 +0000239 ctrl_c_interrupts = TRUE;
240
Bram Moolenaar05159a02005-02-26 23:04:13 +0000241#ifdef NO_CONSOLE_INPUT
242theend:
243#endif
244#ifdef FEAT_PROFILE
Bram Moolenaarb3656ed2006-03-20 21:59:49 +0000245 if (do_profiling == PROF_YES && wtime != 0)
Bram Moolenaar05159a02005-02-26 23:04:13 +0000246 prof_inchar_exit();
247#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000248 return retval;
249}
250
Bram Moolenaar95f0b6e2019-12-15 12:54:18 +0100251#if defined(UNIX) || defined(VMS) || defined(FEAT_GUI) || defined(PROTO)
Bram Moolenaare40b9d42019-01-27 16:55:47 +0100252/*
253 * Common code for mch_inchar() and gui_inchar(): Wait for a while or
254 * indefinitely until characters are available, dealing with timers and
255 * messages on channels.
256 *
257 * "buf" may be NULL if the available characters are not to be returned, only
258 * check if they are available.
259 *
260 * Return the number of characters that are available.
261 * If "wtime" == 0 do not wait for characters.
262 * If "wtime" == n wait a short time for characters.
263 * If "wtime" == -1 wait forever for characters.
264 */
265 int
266inchar_loop(
267 char_u *buf,
268 int maxlen,
269 long wtime, // don't use "time", MIPS cannot handle it
270 int tb_change_cnt,
271 int (*wait_func)(long wtime, int *interrupted, int ignore_input),
272 int (*resize_func)(int check_only))
273{
274 int len;
275 int interrupted = FALSE;
Bram Moolenaar12dfc9e2019-01-28 22:32:58 +0100276 int did_call_wait_func = FALSE;
Bram Moolenaare40b9d42019-01-27 16:55:47 +0100277 int did_start_blocking = FALSE;
278 long wait_time;
279 long elapsed_time = 0;
280#ifdef ELAPSED_FUNC
281 elapsed_T start_tv;
282
283 ELAPSED_INIT(start_tv);
284#endif
285
Bram Moolenaare38eab22019-12-05 21:50:01 +0100286 // repeat until we got a character or waited long enough
Bram Moolenaare40b9d42019-01-27 16:55:47 +0100287 for (;;)
288 {
Bram Moolenaare38eab22019-12-05 21:50:01 +0100289 // Check if window changed size while we were busy, perhaps the ":set
290 // columns=99" command was used.
Bram Moolenaare40b9d42019-01-27 16:55:47 +0100291 if (resize_func != NULL)
292 resize_func(FALSE);
293
294#ifdef MESSAGE_QUEUE
295 // Only process messages when waiting.
296 if (wtime != 0)
297 {
298 parse_queued_messages();
299 // If input was put directly in typeahead buffer bail out here.
300 if (typebuf_changed(tb_change_cnt))
301 return 0;
302 }
303#endif
304 if (wtime < 0 && did_start_blocking)
305 // blocking and already waited for p_ut
306 wait_time = -1;
307 else
308 {
309 if (wtime >= 0)
310 wait_time = wtime;
311 else
312 // going to block after p_ut
313 wait_time = p_ut;
314#ifdef ELAPSED_FUNC
315 elapsed_time = ELAPSED_FUNC(start_tv);
316#endif
317 wait_time -= elapsed_time;
Bram Moolenaar12dfc9e2019-01-28 22:32:58 +0100318
319 // If the waiting time is now zero or less, we timed out. However,
320 // loop at least once to check for characters and events. Matters
321 // when "wtime" is zero.
322 if (wait_time <= 0 && did_call_wait_func)
Bram Moolenaare40b9d42019-01-27 16:55:47 +0100323 {
324 if (wtime >= 0)
325 // no character available within "wtime"
326 return 0;
327
328 // No character available within 'updatetime'.
329 did_start_blocking = TRUE;
330 if (trigger_cursorhold() && maxlen >= 3
331 && !typebuf_changed(tb_change_cnt))
332 {
333 // Put K_CURSORHOLD in the input buffer or return it.
334 if (buf == NULL)
335 {
336 char_u ibuf[3];
337
338 ibuf[0] = CSI;
339 ibuf[1] = KS_EXTRA;
340 ibuf[2] = (int)KE_CURSORHOLD;
341 add_to_input_buf(ibuf, 3);
342 }
343 else
344 {
345 buf[0] = K_SPECIAL;
346 buf[1] = KS_EXTRA;
347 buf[2] = (int)KE_CURSORHOLD;
348 }
349 return 3;
350 }
351
352 // There is no character available within 'updatetime' seconds:
353 // flush all the swap files to disk. Also done when
354 // interrupted by SIGWINCH.
355 before_blocking();
356 continue;
357 }
358 }
359
360#ifdef FEAT_JOB_CHANNEL
361 if (wait_time < 0 || wait_time > 100L)
362 {
363 // Checking if a job ended requires polling. Do this at least
364 // every 100 msec.
365 if (has_pending_job())
366 wait_time = 100L;
367
368 // If there is readahead then parse_queued_messages() timed out and
369 // we should call it again soon.
370 if (channel_any_readahead())
371 wait_time = 10L;
372 }
373#endif
374#ifdef FEAT_BEVAL_GUI
375 if (p_beval && wait_time > 100L)
376 // The 'balloonexpr' may indirectly invoke a callback while waiting
377 // for a character, need to check often.
378 wait_time = 100L;
379#endif
380
381 // Wait for a character to be typed or another event, such as the winch
382 // signal or an event on the monitored file descriptors.
Bram Moolenaar12dfc9e2019-01-28 22:32:58 +0100383 did_call_wait_func = TRUE;
Bram Moolenaare40b9d42019-01-27 16:55:47 +0100384 if (wait_func(wait_time, &interrupted, FALSE))
385 {
386 // If input was put directly in typeahead buffer bail out here.
387 if (typebuf_changed(tb_change_cnt))
388 return 0;
389
390 // We might have something to return now.
391 if (buf == NULL)
392 // "buf" is NULL, we were just waiting, not actually getting
393 // input.
394 return input_available();
395
396 len = read_from_input_buf(buf, (long)maxlen);
397 if (len > 0)
398 return len;
399 continue;
400 }
401 // Timed out or interrupted with no character available.
402
403#ifndef ELAPSED_FUNC
404 // estimate the elapsed time
405 elapsed_time += wait_time;
406#endif
407
408 if ((resize_func != NULL && resize_func(TRUE))
Bram Moolenaar3e9d4d82019-01-27 17:08:40 +0100409#if defined(FEAT_CLIENTSERVER) && defined(UNIX)
Bram Moolenaare40b9d42019-01-27 16:55:47 +0100410 || server_waiting()
411#endif
412#ifdef MESSAGE_QUEUE
413 || interrupted
414#endif
415 || wait_time > 0
416 || (wtime < 0 && !did_start_blocking))
417 // no character available, but something to be done, keep going
418 continue;
419
420 // no character available or interrupted, return zero
421 break;
422 }
423 return 0;
424}
425#endif
426
Bram Moolenaarc46af532019-01-09 22:24:49 +0100427#if defined(FEAT_TIMERS) || defined(PROTO)
Bram Moolenaarc9e649a2017-12-18 18:14:47 +0100428/*
429 * Wait for a timer to fire or "wait_func" to return non-zero.
430 * Returns OK when something was read.
431 * Returns FAIL when it timed out or was interrupted.
432 */
433 int
434ui_wait_for_chars_or_timer(
435 long wtime,
436 int (*wait_func)(long wtime, int *interrupted, int ignore_input),
437 int *interrupted,
438 int ignore_input)
439{
440 int due_time;
441 long remaining = wtime;
442 int tb_change_cnt = typebuf.tb_change_cnt;
Bram Moolenaarc46af532019-01-09 22:24:49 +0100443# ifdef FEAT_JOB_CHANNEL
Bram Moolenaare299bbd2019-01-17 14:12:02 +0100444 int brief_wait = FALSE;
Bram Moolenaarc46af532019-01-09 22:24:49 +0100445# endif
Bram Moolenaarc9e649a2017-12-18 18:14:47 +0100446
Bram Moolenaarc46af532019-01-09 22:24:49 +0100447 // When waiting very briefly don't trigger timers.
Bram Moolenaarc9e649a2017-12-18 18:14:47 +0100448 if (wtime >= 0 && wtime < 10L)
449 return wait_func(wtime, NULL, ignore_input);
450
451 while (wtime < 0 || remaining > 0)
452 {
Bram Moolenaarc46af532019-01-09 22:24:49 +0100453 // Trigger timers and then get the time in wtime until the next one is
454 // due. Wait up to that time.
Bram Moolenaarc9e649a2017-12-18 18:14:47 +0100455 due_time = check_due_timer();
456 if (typebuf.tb_change_cnt != tb_change_cnt)
457 {
Bram Moolenaare38eab22019-12-05 21:50:01 +0100458 // timer may have used feedkeys()
Bram Moolenaarc9e649a2017-12-18 18:14:47 +0100459 return FAIL;
460 }
461 if (due_time <= 0 || (wtime > 0 && due_time > remaining))
462 due_time = remaining;
Bram Moolenaar28e67e02019-08-15 23:05:49 +0200463# if defined(FEAT_JOB_CHANNEL) || defined(FEAT_SOUND_CANBERRA)
464 if ((due_time < 0 || due_time > 10L) && (
465# if defined(FEAT_JOB_CHANNEL)
466 (
467# if defined(FEAT_GUI)
468 !gui.in_use &&
469# endif
470 (has_pending_job() || channel_any_readahead()))
471# ifdef FEAT_SOUND_CANBERRA
472 ||
473# endif
Bram Moolenaarc46af532019-01-09 22:24:49 +0100474# endif
Bram Moolenaar28e67e02019-08-15 23:05:49 +0200475# ifdef FEAT_SOUND_CANBERRA
476 has_any_sound_callback()
477# endif
478 ))
Bram Moolenaarc46af532019-01-09 22:24:49 +0100479 {
480 // There is a pending job or channel, should return soon in order
481 // to handle them ASAP. Do check for input briefly.
482 due_time = 10L;
Bram Moolenaar6cdce2a2019-09-07 23:25:09 +0200483# ifdef FEAT_JOB_CHANNEL
Bram Moolenaarc46af532019-01-09 22:24:49 +0100484 brief_wait = TRUE;
Bram Moolenaar6cdce2a2019-09-07 23:25:09 +0200485# endif
Bram Moolenaarc46af532019-01-09 22:24:49 +0100486 }
487# endif
Bram Moolenaarc9e649a2017-12-18 18:14:47 +0100488 if (wait_func(due_time, interrupted, ignore_input))
489 return OK;
Bram Moolenaarc46af532019-01-09 22:24:49 +0100490 if ((interrupted != NULL && *interrupted)
491# ifdef FEAT_JOB_CHANNEL
492 || brief_wait
493# endif
494 )
495 // Nothing available, but need to return so that side effects get
496 // handled, such as handling a message on a channel.
Bram Moolenaara338adc2018-01-31 20:51:47 +0100497 return FAIL;
Bram Moolenaarc9e649a2017-12-18 18:14:47 +0100498 if (wtime > 0)
499 remaining -= due_time;
500 }
501 return FAIL;
502}
503#endif
504
Bram Moolenaar071d4272004-06-13 20:20:40 +0000505/*
Bram Moolenaarc46af532019-01-09 22:24:49 +0100506 * Return non-zero if a character is available.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000507 */
508 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100509ui_char_avail(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000510{
511#ifdef FEAT_GUI
512 if (gui.in_use)
513 {
514 gui_mch_update();
515 return input_available();
516 }
517#endif
518#ifndef NO_CONSOLE
519# ifdef NO_CONSOLE_INPUT
520 if (no_console_input())
521 return 0;
522# endif
523 return mch_char_avail();
524#else
525 return 0;
526#endif
527}
528
529/*
530 * Delay for the given number of milliseconds. If ignoreinput is FALSE then we
531 * cancel the delay if a key is hit.
532 */
533 void
Bram Moolenaarb340bae2020-06-15 19:51:56 +0200534ui_delay(long msec_arg, int ignoreinput)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000535{
Bram Moolenaarb340bae2020-06-15 19:51:56 +0200536 long msec = msec_arg;
537
538#ifdef FEAT_EVAL
539 if (ui_delay_for_testing > 0)
540 msec = ui_delay_for_testing;
541#endif
Bram Moolenaareda1da02019-11-17 17:06:33 +0100542#ifdef FEAT_JOB_CHANNEL
543 ch_log(NULL, "ui_delay(%ld)", msec);
544#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000545#ifdef FEAT_GUI
546 if (gui.in_use && !ignoreinput)
Bram Moolenaarc9e649a2017-12-18 18:14:47 +0100547 gui_wait_for_chars(msec, typebuf.tb_change_cnt);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000548 else
549#endif
Bram Moolenaar0981c872020-08-23 14:28:37 +0200550 mch_delay(msec, ignoreinput ? MCH_DELAY_IGNOREINPUT : 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000551}
552
553/*
554 * If the machine has job control, use it to suspend the program,
555 * otherwise fake it by starting a new shell.
556 * When running the GUI iconify the window.
557 */
558 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100559ui_suspend(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000560{
561#ifdef FEAT_GUI
562 if (gui.in_use)
563 {
564 gui_mch_iconify();
565 return;
566 }
567#endif
568 mch_suspend();
569}
570
Bram Moolenaar041c7102020-05-30 18:14:57 +0200571#if !defined(UNIX) || !defined(SIGTSTP) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000572/*
573 * When the OS can't really suspend, call this function to start a shell.
574 * This is never called in the GUI.
575 */
576 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100577suspend_shell(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000578{
579 if (*p_sh == NUL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +0100580 emsg(_(e_shellempty));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000581 else
582 {
Bram Moolenaar32526b32019-01-19 17:43:09 +0100583 msg_puts(_("new shell started\n"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000584 do_shell(NULL, 0);
585 }
586}
587#endif
588
589/*
590 * Try to get the current Vim shell size. Put the result in Rows and Columns.
591 * Use the new sizes as defaults for 'columns' and 'lines'.
592 * Return OK when size could be determined, FAIL otherwise.
593 */
594 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100595ui_get_shellsize(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000596{
597 int retval;
598
599#ifdef FEAT_GUI
600 if (gui.in_use)
601 retval = gui_get_shellsize();
602 else
603#endif
604 retval = mch_get_shellsize();
605
606 check_shellsize();
607
Bram Moolenaare38eab22019-12-05 21:50:01 +0100608 // adjust the default for 'lines' and 'columns'
Bram Moolenaar071d4272004-06-13 20:20:40 +0000609 if (retval == OK)
610 {
611 set_number_default("lines", Rows);
612 set_number_default("columns", Columns);
613 }
614 return retval;
615}
616
617/*
618 * Set the size of the Vim shell according to Rows and Columns, if possible.
619 * The gui_set_shellsize() or mch_set_shellsize() function will try to set the
620 * new size. If this is not possible, it will adjust Rows and Columns.
621 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000622 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100623ui_set_shellsize(
Bram Moolenaare38eab22019-12-05 21:50:01 +0100624 int mustset UNUSED) // set by the user
Bram Moolenaar071d4272004-06-13 20:20:40 +0000625{
626#ifdef FEAT_GUI
627 if (gui.in_use)
Bram Moolenaar8968a312013-07-03 16:58:44 +0200628 gui_set_shellsize(mustset, TRUE, RESIZE_BOTH);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000629 else
630#endif
631 mch_set_shellsize();
632}
633
634/*
635 * Called when Rows and/or Columns changed. Adjust scroll region and mouse
636 * region.
637 */
638 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100639ui_new_shellsize(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000640{
641 if (full_screen && !exiting)
642 {
643#ifdef FEAT_GUI
644 if (gui.in_use)
645 gui_new_shellsize();
646 else
647#endif
648 mch_new_shellsize();
649 }
650}
651
Bram Moolenaar6bc93052019-04-06 20:00:19 +0200652#if ((defined(FEAT_EVAL) || defined(FEAT_TERMINAL)) \
Bram Moolenaar3d3f2172019-04-06 17:56:05 +0200653 && (defined(FEAT_GUI) \
Bram Moolenaar16c34c32019-04-06 22:01:24 +0200654 || defined(MSWIN) \
Bram Moolenaar3d3f2172019-04-06 17:56:05 +0200655 || (defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)))) \
Bram Moolenaarfa1e90c2019-04-06 17:47:40 +0200656 || defined(PROTO)
657/*
658 * Get the window position in pixels, if possible.
659 * Return FAIL when not possible.
660 */
661 int
Bram Moolenaarbd67aac2019-09-21 23:09:04 +0200662ui_get_winpos(int *x, int *y, varnumber_T timeout UNUSED)
Bram Moolenaarfa1e90c2019-04-06 17:47:40 +0200663{
664# ifdef FEAT_GUI
665 if (gui.in_use)
666 return gui_mch_get_winpos(x, y);
667# endif
Bram Moolenaarafde13b2019-04-28 19:46:49 +0200668# if defined(MSWIN) && (!defined(FEAT_GUI) || defined(VIMDLL))
Bram Moolenaar16c34c32019-04-06 22:01:24 +0200669 return mch_get_winpos(x, y);
Bram Moolenaar6bc93052019-04-06 20:00:19 +0200670# else
Bram Moolenaar16c34c32019-04-06 22:01:24 +0200671# if defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)
672 return term_get_winpos(x, y, timeout);
673# else
Bram Moolenaar6bc93052019-04-06 20:00:19 +0200674 return FAIL;
Bram Moolenaar16c34c32019-04-06 22:01:24 +0200675# endif
Bram Moolenaarfa1e90c2019-04-06 17:47:40 +0200676# endif
677}
678#endif
679
Bram Moolenaar071d4272004-06-13 20:20:40 +0000680 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100681ui_breakcheck(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000682{
Bram Moolenaarb9c31e72016-09-29 15:18:57 +0200683 ui_breakcheck_force(FALSE);
684}
685
686/*
687 * When "force" is true also check when the terminal is not in raw mode.
688 * This is useful to read input on channels.
689 */
690 void
691ui_breakcheck_force(int force)
692{
Bram Moolenaar48d23bb2018-11-20 02:42:43 +0100693 static int recursive = FALSE;
694 int save_updating_screen = updating_screen;
Bram Moolenaare3caa112017-01-31 22:07:42 +0100695
Bram Moolenaar48d23bb2018-11-20 02:42:43 +0100696 // We could be called recursively if stderr is redirected, calling
697 // fill_input_buf() calls settmode() when stdin isn't a tty. settmode()
698 // calls vgetorpeek() which calls ui_breakcheck() again.
699 if (recursive)
700 return;
701 recursive = TRUE;
702
703 // We do not want gui_resize_shell() to redraw the screen here.
Bram Moolenaare3caa112017-01-31 22:07:42 +0100704 ++updating_screen;
705
Bram Moolenaar071d4272004-06-13 20:20:40 +0000706#ifdef FEAT_GUI
707 if (gui.in_use)
708 gui_mch_update();
709 else
710#endif
Bram Moolenaarb9c31e72016-09-29 15:18:57 +0200711 mch_breakcheck(force);
Bram Moolenaare3caa112017-01-31 22:07:42 +0100712
Bram Moolenaar42335f52018-09-13 15:33:43 +0200713 if (save_updating_screen)
714 updating_screen = TRUE;
Bram Moolenaar0cb8ac72018-05-11 22:01:51 +0200715 else
Bram Moolenaar68a4b042019-05-29 22:28:29 +0200716 after_updating_screen(FALSE);
Bram Moolenaar48d23bb2018-11-20 02:42:43 +0100717
718 recursive = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000719}
720
Bram Moolenaare38eab22019-12-05 21:50:01 +0100721//////////////////////////////////////////////////////////////////////////////
Bram Moolenaare38eab22019-12-05 21:50:01 +0100722// Functions that handle the input buffer.
723// This is used for any GUI version, and the unix terminal version.
724//
725// For Unix, the input characters are buffered to be able to check for a
726// CTRL-C. This should be done with signals, but I don't know how to do that
727// in a portable way for a tty in RAW mode.
728//
729// For the client-server code in the console the received keys are put in the
730// input buffer.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000731
732#if defined(USE_INPUT_BUF) || defined(PROTO)
733
734/*
735 * Internal typeahead buffer. Includes extra space for long key code
736 * descriptions which would otherwise overflow. The buffer is considered full
737 * when only this extra space (or part of it) remains.
738 */
Bram Moolenaarbb1969b2019-01-17 15:45:25 +0100739#if defined(FEAT_JOB_CHANNEL) || defined(FEAT_CLIENTSERVER)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000740 /*
Bram Moolenaarbb1969b2019-01-17 15:45:25 +0100741 * NetBeans stuffs debugger commands into the input buffer.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000742 * This requires a larger buffer...
743 * (Madsen) Go with this for remote input as well ...
744 */
745# define INBUFLEN 4096
746#else
747# define INBUFLEN 250
748#endif
749
750static char_u inbuf[INBUFLEN + MAX_KEY_CODE_LEN];
Bram Moolenaare38eab22019-12-05 21:50:01 +0100751static int inbufcount = 0; // number of chars in inbuf[]
Bram Moolenaar071d4272004-06-13 20:20:40 +0000752
753/*
754 * vim_is_input_buf_full(), vim_is_input_buf_empty(), add_to_input_buf(), and
755 * trash_input_buf() are functions for manipulating the input buffer. These
756 * are used by the gui_* calls when a GUI is used to handle keyboard input.
757 */
758
759 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100760vim_is_input_buf_full(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000761{
762 return (inbufcount >= INBUFLEN);
763}
764
765 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100766vim_is_input_buf_empty(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000767{
768 return (inbufcount == 0);
769}
770
771#if defined(FEAT_OLE) || defined(PROTO)
772 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100773vim_free_in_input_buf(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000774{
775 return (INBUFLEN - inbufcount);
776}
777#endif
778
Bram Moolenaar241a8aa2005-12-06 20:04:44 +0000779#if defined(FEAT_GUI_GTK) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000780 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100781vim_used_in_input_buf(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000782{
783 return inbufcount;
784}
785#endif
786
Bram Moolenaar071d4272004-06-13 20:20:40 +0000787/*
788 * Return the current contents of the input buffer and make it empty.
789 * The returned pointer must be passed to set_input_buf() later.
790 */
791 char_u *
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100792get_input_buf(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000793{
794 garray_T *gap;
795
Bram Moolenaare38eab22019-12-05 21:50:01 +0100796 // We use a growarray to store the data pointer and the length.
Bram Moolenaarc799fe22019-05-28 23:08:19 +0200797 gap = ALLOC_ONE(garray_T);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000798 if (gap != NULL)
799 {
Bram Moolenaare38eab22019-12-05 21:50:01 +0100800 // Add one to avoid a zero size.
Bram Moolenaar18a4ba22019-05-24 19:39:03 +0200801 gap->ga_data = alloc(inbufcount + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000802 if (gap->ga_data != NULL)
803 mch_memmove(gap->ga_data, inbuf, (size_t)inbufcount);
804 gap->ga_len = inbufcount;
805 }
806 trash_input_buf();
807 return (char_u *)gap;
808}
809
810/*
811 * Restore the input buffer with a pointer returned from get_input_buf().
812 * The allocated memory is freed, this only works once!
813 */
814 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100815set_input_buf(char_u *p)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000816{
817 garray_T *gap = (garray_T *)p;
818
819 if (gap != NULL)
820 {
821 if (gap->ga_data != NULL)
822 {
823 mch_memmove(inbuf, gap->ga_data, gap->ga_len);
824 inbufcount = gap->ga_len;
825 vim_free(gap->ga_data);
826 }
827 vim_free(gap);
828 }
829}
Bram Moolenaar071d4272004-06-13 20:20:40 +0000830
Bram Moolenaar071d4272004-06-13 20:20:40 +0000831/*
832 * Add the given bytes to the input buffer
833 * Special keys start with CSI. A real CSI must have been translated to
834 * CSI KS_EXTRA KE_CSI. K_SPECIAL doesn't require translation.
835 */
836 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100837add_to_input_buf(char_u *s, int len)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000838{
839 if (inbufcount + len > INBUFLEN + MAX_KEY_CODE_LEN)
Bram Moolenaare38eab22019-12-05 21:50:01 +0100840 return; // Shouldn't ever happen!
Bram Moolenaar071d4272004-06-13 20:20:40 +0000841
Bram Moolenaar071d4272004-06-13 20:20:40 +0000842 while (len--)
843 inbuf[inbufcount++] = *s++;
844}
Bram Moolenaar071d4272004-06-13 20:20:40 +0000845
Bram Moolenaar071d4272004-06-13 20:20:40 +0000846/*
847 * Add "str[len]" to the input buffer while escaping CSI bytes.
848 */
849 void
850add_to_input_buf_csi(char_u *str, int len)
851{
852 int i;
853 char_u buf[2];
854
855 for (i = 0; i < len; ++i)
856 {
857 add_to_input_buf(str + i, 1);
858 if (str[i] == CSI)
859 {
Bram Moolenaare38eab22019-12-05 21:50:01 +0100860 // Turn CSI into K_CSI.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000861 buf[0] = KS_EXTRA;
862 buf[1] = (int)KE_CSI;
863 add_to_input_buf(buf, 2);
864 }
865 }
866}
Bram Moolenaar071d4272004-06-13 20:20:40 +0000867
Bram Moolenaare38eab22019-12-05 21:50:01 +0100868/*
869 * Remove everything from the input buffer. Called when ^C is found.
870 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000871 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100872trash_input_buf(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000873{
874 inbufcount = 0;
875}
Bram Moolenaar071d4272004-06-13 20:20:40 +0000876
877/*
878 * Read as much data from the input buffer as possible up to maxlen, and store
879 * it in buf.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000880 */
881 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100882read_from_input_buf(char_u *buf, long maxlen)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000883{
Bram Moolenaare38eab22019-12-05 21:50:01 +0100884 if (inbufcount == 0) // if the buffer is empty, fill it
Bram Moolenaar071d4272004-06-13 20:20:40 +0000885 fill_input_buf(TRUE);
886 if (maxlen > inbufcount)
887 maxlen = inbufcount;
888 mch_memmove(buf, inbuf, (size_t)maxlen);
889 inbufcount -= maxlen;
890 if (inbufcount)
891 mch_memmove(inbuf, inbuf + maxlen, (size_t)inbufcount);
892 return (int)maxlen;
893}
894
895 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100896fill_input_buf(int exit_on_error UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000897{
Bram Moolenaard0573012017-10-28 21:11:06 +0200898#if defined(UNIX) || defined(VMS) || defined(MACOS_X)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000899 int len;
900 int try;
901 static int did_read_something = FALSE;
Bram Moolenaare38eab22019-12-05 21:50:01 +0100902 static char_u *rest = NULL; // unconverted rest of previous read
Bram Moolenaar071d4272004-06-13 20:20:40 +0000903 static int restlen = 0;
904 int unconverted;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000905#endif
906
907#ifdef FEAT_GUI
Bram Moolenaar54ee7752005-05-31 22:22:17 +0000908 if (gui.in_use
909# ifdef NO_CONSOLE_INPUT
Bram Moolenaare38eab22019-12-05 21:50:01 +0100910 // Don't use the GUI input when the window hasn't been opened yet.
911 // We get here from ui_inchar() when we should try reading from stdin.
Bram Moolenaar54ee7752005-05-31 22:22:17 +0000912 && !no_console_input()
913# endif
914 )
Bram Moolenaar071d4272004-06-13 20:20:40 +0000915 {
916 gui_mch_update();
917 return;
918 }
919#endif
Bram Moolenaard0573012017-10-28 21:11:06 +0200920#if defined(UNIX) || defined(VMS) || defined(MACOS_X)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000921 if (vim_is_input_buf_full())
922 return;
923 /*
924 * Fill_input_buf() is only called when we really need a character.
925 * If we can't get any, but there is some in the buffer, just return.
926 * If we can't get any, and there isn't any in the buffer, we give up and
927 * exit Vim.
928 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000929 if (rest != NULL)
930 {
Bram Moolenaare38eab22019-12-05 21:50:01 +0100931 // Use remainder of previous call, starts with an invalid character
932 // that may become valid when reading more.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000933 if (restlen > INBUFLEN - inbufcount)
934 unconverted = INBUFLEN - inbufcount;
935 else
936 unconverted = restlen;
937 mch_memmove(inbuf + inbufcount, rest, unconverted);
938 if (unconverted == restlen)
Bram Moolenaard23a8232018-02-10 18:45:26 +0100939 VIM_CLEAR(rest);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000940 else
941 {
942 restlen -= unconverted;
943 mch_memmove(rest, rest + unconverted, restlen);
944 }
945 inbufcount += unconverted;
946 }
947 else
948 unconverted = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000949
Bram Moolenaare38eab22019-12-05 21:50:01 +0100950 len = 0; // to avoid gcc warning
Bram Moolenaar071d4272004-06-13 20:20:40 +0000951 for (try = 0; try < 100; ++try)
952 {
Bram Moolenaar4e601e32018-04-24 13:29:51 +0200953 size_t readlen = (size_t)((INBUFLEN - inbufcount)
Bram Moolenaar9645e2d2020-03-20 20:48:49 +0100954 / input_conv.vc_factor);
Bram Moolenaar4e601e32018-04-24 13:29:51 +0200955# ifdef VMS
Bram Moolenaar49943732018-04-24 20:27:26 +0200956 len = vms_read((char *)inbuf + inbufcount, readlen);
Bram Moolenaar4e601e32018-04-24 13:29:51 +0200957# else
958 len = read(read_cmd_fd, (char *)inbuf + inbufcount, readlen);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000959# endif
Bram Moolenaar7ca86fe2020-09-03 19:25:11 +0200960# ifdef FEAT_JOB_CHANNEL
961 if (len > 0)
962 {
963 inbuf[inbufcount + len] = NUL;
964 ch_log(NULL, "raw key input: \"%s\"", inbuf + inbufcount);
965 }
966# endif
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000967
Bram Moolenaar071d4272004-06-13 20:20:40 +0000968 if (len > 0 || got_int)
969 break;
970 /*
971 * If reading stdin results in an error, continue reading stderr.
972 * This helps when using "foo | xargs vim".
973 */
974 if (!did_read_something && !isatty(read_cmd_fd) && read_cmd_fd == 0)
975 {
976 int m = cur_tmode;
977
Bram Moolenaare38eab22019-12-05 21:50:01 +0100978 // We probably set the wrong file descriptor to raw mode. Switch
979 // back to cooked mode, use another descriptor and set the mode to
980 // what it was.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000981 settmode(TMODE_COOK);
982#ifdef HAVE_DUP
Bram Moolenaare38eab22019-12-05 21:50:01 +0100983 // Use stderr for stdin, also works for shell commands.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000984 close(0);
Bram Moolenaar42335f52018-09-13 15:33:43 +0200985 vim_ignored = dup(2);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000986#else
Bram Moolenaare38eab22019-12-05 21:50:01 +0100987 read_cmd_fd = 2; // read from stderr instead of stdin
Bram Moolenaar071d4272004-06-13 20:20:40 +0000988#endif
989 settmode(m);
990 }
991 if (!exit_on_error)
992 return;
993 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000994 if (len <= 0 && !got_int)
995 read_error_exit();
996 if (len > 0)
997 did_read_something = TRUE;
998 if (got_int)
999 {
Bram Moolenaare38eab22019-12-05 21:50:01 +01001000 // Interrupted, pretend a CTRL-C was typed.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001001 inbuf[0] = 3;
1002 inbufcount = 1;
1003 }
1004 else
1005 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001006 /*
1007 * May perform conversion on the input characters.
1008 * Include the unconverted rest of the previous call.
1009 * If there is an incomplete char at the end it is kept for the next
1010 * time, reading more bytes should make conversion possible.
1011 * Don't do this in the unlikely event that the input buffer is too
1012 * small ("rest" still contains more bytes).
1013 */
1014 if (input_conv.vc_type != CONV_NONE)
1015 {
1016 inbufcount -= unconverted;
1017 len = convert_input_safe(inbuf + inbufcount,
1018 len + unconverted, INBUFLEN - inbufcount,
1019 rest == NULL ? &rest : NULL, &restlen);
1020 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001021 while (len-- > 0)
1022 {
Bram Moolenaar339c1bd2021-01-02 20:14:23 +01001023 // If a CTRL-C was typed, remove it from the buffer and set
1024 // got_int. Also recognize CTRL-C with modifyOtherKeys set, in two
1025 // forms.
Bram Moolenaar9645e2d2020-03-20 20:48:49 +01001026 if (ctrl_c_interrupts && (inbuf[inbufcount] == 3
Bram Moolenaar339c1bd2021-01-02 20:14:23 +01001027 || (len >= 10 && STRNCMP(inbuf + inbufcount,
Bram Moolenaar02faa942021-01-02 16:17:18 +01001028 "\033[27;5;99~", 10) == 0)
1029 || (len >= 7 && STRNCMP(inbuf + inbufcount,
1030 "\033[99;5u", 7) == 0)))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001031 {
Bram Moolenaare38eab22019-12-05 21:50:01 +01001032 // remove everything typed before the CTRL-C
Bram Moolenaar071d4272004-06-13 20:20:40 +00001033 mch_memmove(inbuf, inbuf + inbufcount, (size_t)(len + 1));
1034 inbufcount = 0;
1035 got_int = TRUE;
1036 }
1037 ++inbufcount;
1038 }
1039 }
Bram Moolenaar74ee5e22019-12-13 18:13:22 +01001040#endif // UNIX || VMS || MACOS_X
Bram Moolenaar071d4272004-06-13 20:20:40 +00001041}
Bram Moolenaar74ee5e22019-12-13 18:13:22 +01001042#endif // USE_INPUT_BUF
Bram Moolenaar071d4272004-06-13 20:20:40 +00001043
1044/*
1045 * Exit because of an input read error.
1046 */
1047 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +01001048read_error_exit(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001049{
Bram Moolenaare38eab22019-12-05 21:50:01 +01001050 if (silent_mode) // Normal way to exit for "ex -s"
Bram Moolenaar071d4272004-06-13 20:20:40 +00001051 getout(0);
1052 STRCPY(IObuff, _("Vim: Error reading input, exiting...\n"));
1053 preserve_exit();
1054}
1055
1056#if defined(CURSOR_SHAPE) || defined(PROTO)
1057/*
1058 * May update the shape of the cursor.
1059 */
1060 void
Bram Moolenaar3cd43cc2017-08-12 19:51:41 +02001061ui_cursor_shape_forced(int forced)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001062{
1063# ifdef FEAT_GUI
1064 if (gui.in_use)
1065 gui_update_cursor_later();
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00001066 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00001067# endif
Bram Moolenaar3cd43cc2017-08-12 19:51:41 +02001068 term_cursor_mode(forced);
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00001069
Bram Moolenaar071d4272004-06-13 20:20:40 +00001070# ifdef MCH_CURSOR_SHAPE
1071 mch_update_cursor();
1072# endif
Bram Moolenaarf5963f72010-07-23 22:10:27 +02001073
1074# ifdef FEAT_CONCEAL
Bram Moolenaarb9464822018-05-10 15:09:49 +02001075 conceal_check_cursor_line();
Bram Moolenaarf5963f72010-07-23 22:10:27 +02001076# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001077}
Bram Moolenaar3cd43cc2017-08-12 19:51:41 +02001078
1079 void
1080ui_cursor_shape(void)
1081{
1082 ui_cursor_shape_forced(FALSE);
1083}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001084#endif
1085
Bram Moolenaar071d4272004-06-13 20:20:40 +00001086/*
1087 * Check bounds for column number
1088 */
1089 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +01001090check_col(int col)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001091{
1092 if (col < 0)
1093 return 0;
1094 if (col >= (int)screen_Columns)
1095 return (int)screen_Columns - 1;
1096 return col;
1097}
1098
1099/*
1100 * Check bounds for row number
1101 */
1102 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +01001103check_row(int row)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001104{
1105 if (row < 0)
1106 return 0;
1107 if (row >= (int)screen_Rows)
1108 return (int)screen_Rows - 1;
1109 return row;
1110}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001111
Bram Moolenaar071d4272004-06-13 20:20:40 +00001112/*
1113 * Called when focus changed. Used for the GUI or for systems where this can
1114 * be done in the console (Win32).
1115 */
1116 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +01001117ui_focus_change(
Bram Moolenaare38eab22019-12-05 21:50:01 +01001118 int in_focus) // TRUE if focus gained.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001119{
1120 static time_t last_time = (time_t)0;
1121 int need_redraw = FALSE;
1122
Bram Moolenaare38eab22019-12-05 21:50:01 +01001123 // When activated: Check if any file was modified outside of Vim.
1124 // Only do this when not done within the last two seconds (could get
1125 // several events in a row).
Bram Moolenaar071d4272004-06-13 20:20:40 +00001126 if (in_focus && last_time + 2 < time(NULL))
1127 {
1128 need_redraw = check_timestamps(
1129# ifdef FEAT_GUI
1130 gui.in_use
1131# else
1132 FALSE
1133# endif
1134 );
1135 last_time = time(NULL);
1136 }
1137
Bram Moolenaar071d4272004-06-13 20:20:40 +00001138 /*
1139 * Fire the focus gained/lost autocommand.
1140 */
1141 need_redraw |= apply_autocmds(in_focus ? EVENT_FOCUSGAINED
1142 : EVENT_FOCUSLOST, NULL, NULL, FALSE, curbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001143
1144 if (need_redraw)
1145 {
Bram Moolenaare38eab22019-12-05 21:50:01 +01001146 // Something was executed, make sure the cursor is put back where it
1147 // belongs.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001148 need_wait_return = FALSE;
1149
1150 if (State & CMDLINE)
1151 redrawcmdline();
1152 else if (State == HITRETURN || State == SETWSIZE || State == ASKMORE
1153 || State == EXTERNCMD || State == CONFIRM || exmode_active)
1154 repeat_message();
1155 else if ((State & NORMAL) || (State & INSERT))
1156 {
1157 if (must_redraw != 0)
1158 update_screen(0);
1159 setcursor();
1160 }
Bram Moolenaare38eab22019-12-05 21:50:01 +01001161 cursor_on(); // redrawing may have switched it off
Bram Moolenaara338adc2018-01-31 20:51:47 +01001162 out_flush_cursor(FALSE, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001163# ifdef FEAT_GUI
1164 if (gui.in_use)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001165 gui_update_scrollbars(FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001166# endif
1167 }
1168#ifdef FEAT_TITLE
Bram Moolenaare38eab22019-12-05 21:50:01 +01001169 // File may have been changed from 'readonly' to 'noreadonly'
Bram Moolenaar071d4272004-06-13 20:20:40 +00001170 if (need_maketitle)
1171 maketitle();
1172#endif
1173}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001174
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01001175#if defined(HAVE_INPUT_METHOD) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001176/*
1177 * Save current Input Method status to specified place.
1178 */
1179 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +01001180im_save_status(long *psave)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001181{
Bram Moolenaare38eab22019-12-05 21:50:01 +01001182 // Don't save when 'imdisable' is set or "xic" is NULL, IM is always
1183 // disabled then (but might start later).
1184 // Also don't save when inside a mapping, vgetc_im_active has not been set
1185 // then.
1186 // And don't save when the keys were stuffed (e.g., for a "." command).
1187 // And don't save when the GUI is running but our window doesn't have
1188 // input focus (e.g., when a find dialog is open).
Bram Moolenaar071d4272004-06-13 20:20:40 +00001189 if (!p_imdisable && KeyTyped && !KeyStuffed
1190# ifdef FEAT_XIM
1191 && xic != NULL
1192# endif
1193# ifdef FEAT_GUI
1194 && (!gui.in_use || gui.in_focus)
1195# endif
1196 )
1197 {
Bram Moolenaare38eab22019-12-05 21:50:01 +01001198 // Do save when IM is on, or IM is off and saved status is on.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001199 if (vgetc_im_active)
1200 *psave = B_IMODE_IM;
1201 else if (*psave == B_IMODE_IM)
1202 *psave = B_IMODE_NONE;
1203 }
1204}
1205#endif