blob: 6c1c1de0289a52f6dea887ba12a91e48bee0b1f4 [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 Moolenaar4c868302021-03-22 16:19:45 +010053 if (console && s[len - 1] == '\n')
54 fsync(1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000055
Bram Moolenaar4f974752019-02-17 17:44:42 +010056# if !defined(MSWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000057 if (output_conv.vc_type != CONV_NONE)
58 vim_free(tofree);
Bram Moolenaar264b74f2019-01-24 17:18:42 +010059# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000060 }
61#endif
62}
63
Bram Moolenaar4f974752019-02-17 17:44:42 +010064#if defined(UNIX) || defined(VMS) || defined(PROTO) || defined(MSWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000065/*
66 * When executing an external program, there may be some typed characters that
67 * are not consumed by it. Give them back to ui_inchar() and they are stored
68 * here for the next call.
69 */
70static char_u *ta_str = NULL;
Bram Moolenaare38eab22019-12-05 21:50:01 +010071static int ta_off; // offset for next char to use when ta_str != NULL
72static int ta_len; // length of ta_str when it's not NULL
Bram Moolenaar071d4272004-06-13 20:20:40 +000073
74 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +010075ui_inchar_undo(char_u *s, int len)
Bram Moolenaar071d4272004-06-13 20:20:40 +000076{
77 char_u *new;
78 int newlen;
79
80 newlen = len;
81 if (ta_str != NULL)
82 newlen += ta_len - ta_off;
83 new = alloc(newlen);
84 if (new != NULL)
85 {
86 if (ta_str != NULL)
87 {
88 mch_memmove(new, ta_str + ta_off, (size_t)(ta_len - ta_off));
89 mch_memmove(new + ta_len - ta_off, s, (size_t)len);
90 vim_free(ta_str);
91 }
92 else
93 mch_memmove(new, s, (size_t)len);
94 ta_str = new;
95 ta_len = newlen;
96 ta_off = 0;
97 }
98}
99#endif
100
101/*
Bram Moolenaarb6101cf2012-10-21 00:58:39 +0200102 * ui_inchar(): low level input function.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000103 * Get characters from the keyboard.
104 * Return the number of characters that are available.
105 * If "wtime" == 0 do not wait for characters.
106 * If "wtime" == -1 wait forever for characters.
107 * If "wtime" > 0 wait "wtime" milliseconds for a character.
108 *
109 * "tb_change_cnt" is the value of typebuf.tb_change_cnt if "buf" points into
110 * it. When typebuf.tb_change_cnt changes (e.g., when a message is received
111 * from a remote client) "buf" can no longer be used. "tb_change_cnt" is NULL
112 * otherwise.
113 */
114 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100115ui_inchar(
116 char_u *buf,
117 int maxlen,
Bram Moolenaare38eab22019-12-05 21:50:01 +0100118 long wtime, // don't use "time", MIPS cannot handle it
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100119 int tb_change_cnt)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000120{
121 int retval = 0;
122
123#if defined(FEAT_GUI) && (defined(UNIX) || defined(VMS))
124 /*
125 * Use the typeahead if there is any.
126 */
127 if (ta_str != NULL)
128 {
129 if (maxlen >= ta_len - ta_off)
130 {
131 mch_memmove(buf, ta_str + ta_off, (size_t)ta_len);
Bram Moolenaard23a8232018-02-10 18:45:26 +0100132 VIM_CLEAR(ta_str);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000133 return ta_len;
134 }
135 mch_memmove(buf, ta_str + ta_off, (size_t)maxlen);
136 ta_off += maxlen;
137 return maxlen;
138 }
139#endif
140
Bram Moolenaar05159a02005-02-26 23:04:13 +0000141#ifdef FEAT_PROFILE
Bram Moolenaarb3656ed2006-03-20 21:59:49 +0000142 if (do_profiling == PROF_YES && wtime != 0)
Bram Moolenaar05159a02005-02-26 23:04:13 +0000143 prof_inchar_enter();
144#endif
145
Bram Moolenaar071d4272004-06-13 20:20:40 +0000146#ifdef NO_CONSOLE_INPUT
Bram Moolenaare38eab22019-12-05 21:50:01 +0100147 // 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.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000151 if (no_console_input())
152 {
153 static int count = 0;
154
155# ifndef NO_CONSOLE
Bram Moolenaar13410242018-11-26 21:19:11 +0100156 retval = mch_inchar(buf, maxlen, wtime, tb_change_cnt);
Bram Moolenaar43b604c2005-03-22 23:06:55 +0000157 if (retval > 0 || typebuf_changed(tb_change_cnt) || wtime >= 0)
Bram Moolenaar05159a02005-02-26 23:04:13 +0000158 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000159# endif
160 if (wtime == -1 && ++count == 1000)
161 read_error_exit();
162 buf[0] = CAR;
Bram Moolenaar05159a02005-02-26 23:04:13 +0000163 retval = 1;
164 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000165 }
166#endif
167
Bram Moolenaare38eab22019-12-05 21:50:01 +0100168 // If we are going to wait for some time or block...
Bram Moolenaarc8da3112007-03-08 12:36:46 +0000169 if (wtime == -1 || wtime > 100L)
170 {
Bram Moolenaare38eab22019-12-05 21:50:01 +0100171 // ... allow signals to kill us.
Bram Moolenaarc8da3112007-03-08 12:36:46 +0000172 (void)vim_handle_signal(SIGNAL_UNBLOCK);
173
Bram Moolenaare38eab22019-12-05 21:50:01 +0100174 // ... there is no need for CTRL-C to interrupt something, don't let
175 // it set got_int when it was mapped.
Bram Moolenaar50008692015-01-14 16:08:32 +0100176 if ((mapped_ctrl_c | curbuf->b_mapped_ctrl_c) & get_real_state())
Bram Moolenaarc8da3112007-03-08 12:36:46 +0000177 ctrl_c_interrupts = FALSE;
178 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000179
Bram Moolenaare40b9d42019-01-27 16:55:47 +0100180 /*
181 * Here we call gui_inchar() or mch_inchar(), the GUI or machine-dependent
182 * input function. The functionality they implement is like this:
183 *
184 * while (not timed out)
185 * {
186 * handle-resize;
187 * parse-queued-messages;
188 * if (waited for 'updatetime')
189 * trigger-cursorhold;
190 * ui_wait_for_chars_or_timer()
191 * if (character available)
192 * break;
193 * }
194 *
195 * ui_wait_for_chars_or_timer() does:
196 *
197 * while (not timed out)
198 * {
199 * if (any-timer-triggered)
200 * invoke-timer-callback;
201 * wait-for-character();
202 * if (character available)
203 * break;
204 * }
205 *
206 * wait-for-character() does:
207 * while (not timed out)
208 * {
209 * Wait for event;
210 * if (something on channel)
211 * read/write channel;
212 * else if (resized)
213 * handle_resize();
214 * else if (system event)
215 * deal-with-system-event;
216 * else if (character available)
217 * break;
218 * }
219 *
220 */
221
Bram Moolenaar071d4272004-06-13 20:20:40 +0000222#ifdef FEAT_GUI
223 if (gui.in_use)
Bram Moolenaarc9e649a2017-12-18 18:14:47 +0100224 retval = gui_inchar(buf, maxlen, wtime, tb_change_cnt);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000225#endif
226#ifndef NO_CONSOLE
227# ifdef FEAT_GUI
228 else
229# endif
230 retval = mch_inchar(buf, maxlen, wtime, tb_change_cnt);
231#endif
232
Bram Moolenaarc8da3112007-03-08 12:36:46 +0000233 if (wtime == -1 || wtime > 100L)
Bram Moolenaare38eab22019-12-05 21:50:01 +0100234 // block SIGHUP et al.
Bram Moolenaarc8da3112007-03-08 12:36:46 +0000235 (void)vim_handle_signal(SIGNAL_BLOCK);
236
Bram Moolenaar071d4272004-06-13 20:20:40 +0000237 ctrl_c_interrupts = TRUE;
238
Bram Moolenaar05159a02005-02-26 23:04:13 +0000239#ifdef NO_CONSOLE_INPUT
240theend:
241#endif
242#ifdef FEAT_PROFILE
Bram Moolenaarb3656ed2006-03-20 21:59:49 +0000243 if (do_profiling == PROF_YES && wtime != 0)
Bram Moolenaar05159a02005-02-26 23:04:13 +0000244 prof_inchar_exit();
245#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000246 return retval;
247}
248
Bram Moolenaar95f0b6e2019-12-15 12:54:18 +0100249#if defined(UNIX) || defined(VMS) || defined(FEAT_GUI) || defined(PROTO)
Bram Moolenaare40b9d42019-01-27 16:55:47 +0100250/*
251 * Common code for mch_inchar() and gui_inchar(): Wait for a while or
252 * indefinitely until characters are available, dealing with timers and
253 * messages on channels.
254 *
255 * "buf" may be NULL if the available characters are not to be returned, only
256 * check if they are available.
257 *
258 * Return the number of characters that are available.
259 * If "wtime" == 0 do not wait for characters.
260 * If "wtime" == n wait a short time for characters.
261 * If "wtime" == -1 wait forever for characters.
262 */
263 int
264inchar_loop(
265 char_u *buf,
266 int maxlen,
267 long wtime, // don't use "time", MIPS cannot handle it
268 int tb_change_cnt,
269 int (*wait_func)(long wtime, int *interrupted, int ignore_input),
270 int (*resize_func)(int check_only))
271{
272 int len;
273 int interrupted = FALSE;
Bram Moolenaar12dfc9e2019-01-28 22:32:58 +0100274 int did_call_wait_func = FALSE;
Bram Moolenaare40b9d42019-01-27 16:55:47 +0100275 int did_start_blocking = FALSE;
276 long wait_time;
277 long elapsed_time = 0;
278#ifdef ELAPSED_FUNC
279 elapsed_T start_tv;
280
281 ELAPSED_INIT(start_tv);
282#endif
283
Bram Moolenaare38eab22019-12-05 21:50:01 +0100284 // repeat until we got a character or waited long enough
Bram Moolenaare40b9d42019-01-27 16:55:47 +0100285 for (;;)
286 {
Bram Moolenaare38eab22019-12-05 21:50:01 +0100287 // Check if window changed size while we were busy, perhaps the ":set
288 // columns=99" command was used.
Bram Moolenaare40b9d42019-01-27 16:55:47 +0100289 if (resize_func != NULL)
290 resize_func(FALSE);
291
292#ifdef MESSAGE_QUEUE
293 // Only process messages when waiting.
294 if (wtime != 0)
295 {
296 parse_queued_messages();
297 // If input was put directly in typeahead buffer bail out here.
298 if (typebuf_changed(tb_change_cnt))
299 return 0;
300 }
301#endif
302 if (wtime < 0 && did_start_blocking)
303 // blocking and already waited for p_ut
304 wait_time = -1;
305 else
306 {
307 if (wtime >= 0)
308 wait_time = wtime;
309 else
310 // going to block after p_ut
311 wait_time = p_ut;
312#ifdef ELAPSED_FUNC
313 elapsed_time = ELAPSED_FUNC(start_tv);
314#endif
315 wait_time -= elapsed_time;
Bram Moolenaar12dfc9e2019-01-28 22:32:58 +0100316
317 // If the waiting time is now zero or less, we timed out. However,
318 // loop at least once to check for characters and events. Matters
319 // when "wtime" is zero.
320 if (wait_time <= 0 && did_call_wait_func)
Bram Moolenaare40b9d42019-01-27 16:55:47 +0100321 {
322 if (wtime >= 0)
323 // no character available within "wtime"
324 return 0;
325
326 // No character available within 'updatetime'.
327 did_start_blocking = TRUE;
328 if (trigger_cursorhold() && maxlen >= 3
329 && !typebuf_changed(tb_change_cnt))
330 {
331 // Put K_CURSORHOLD in the input buffer or return it.
332 if (buf == NULL)
333 {
334 char_u ibuf[3];
335
336 ibuf[0] = CSI;
337 ibuf[1] = KS_EXTRA;
338 ibuf[2] = (int)KE_CURSORHOLD;
339 add_to_input_buf(ibuf, 3);
340 }
341 else
342 {
343 buf[0] = K_SPECIAL;
344 buf[1] = KS_EXTRA;
345 buf[2] = (int)KE_CURSORHOLD;
346 }
347 return 3;
348 }
349
350 // There is no character available within 'updatetime' seconds:
351 // flush all the swap files to disk. Also done when
352 // interrupted by SIGWINCH.
353 before_blocking();
354 continue;
355 }
356 }
357
358#ifdef FEAT_JOB_CHANNEL
359 if (wait_time < 0 || wait_time > 100L)
360 {
361 // Checking if a job ended requires polling. Do this at least
362 // every 100 msec.
363 if (has_pending_job())
364 wait_time = 100L;
365
366 // If there is readahead then parse_queued_messages() timed out and
367 // we should call it again soon.
368 if (channel_any_readahead())
369 wait_time = 10L;
370 }
371#endif
372#ifdef FEAT_BEVAL_GUI
373 if (p_beval && wait_time > 100L)
374 // The 'balloonexpr' may indirectly invoke a callback while waiting
375 // for a character, need to check often.
376 wait_time = 100L;
377#endif
378
379 // Wait for a character to be typed or another event, such as the winch
380 // signal or an event on the monitored file descriptors.
Bram Moolenaar12dfc9e2019-01-28 22:32:58 +0100381 did_call_wait_func = TRUE;
Bram Moolenaare40b9d42019-01-27 16:55:47 +0100382 if (wait_func(wait_time, &interrupted, FALSE))
383 {
384 // If input was put directly in typeahead buffer bail out here.
385 if (typebuf_changed(tb_change_cnt))
386 return 0;
387
388 // We might have something to return now.
389 if (buf == NULL)
390 // "buf" is NULL, we were just waiting, not actually getting
391 // input.
392 return input_available();
393
394 len = read_from_input_buf(buf, (long)maxlen);
395 if (len > 0)
396 return len;
397 continue;
398 }
399 // Timed out or interrupted with no character available.
400
401#ifndef ELAPSED_FUNC
402 // estimate the elapsed time
403 elapsed_time += wait_time;
404#endif
405
406 if ((resize_func != NULL && resize_func(TRUE))
Bram Moolenaar3e9d4d82019-01-27 17:08:40 +0100407#if defined(FEAT_CLIENTSERVER) && defined(UNIX)
Bram Moolenaare40b9d42019-01-27 16:55:47 +0100408 || server_waiting()
409#endif
410#ifdef MESSAGE_QUEUE
411 || interrupted
412#endif
413 || wait_time > 0
414 || (wtime < 0 && !did_start_blocking))
415 // no character available, but something to be done, keep going
416 continue;
417
418 // no character available or interrupted, return zero
419 break;
420 }
421 return 0;
422}
423#endif
424
Bram Moolenaarc46af532019-01-09 22:24:49 +0100425#if defined(FEAT_TIMERS) || defined(PROTO)
Bram Moolenaarc9e649a2017-12-18 18:14:47 +0100426/*
427 * Wait for a timer to fire or "wait_func" to return non-zero.
428 * Returns OK when something was read.
429 * Returns FAIL when it timed out or was interrupted.
430 */
431 int
432ui_wait_for_chars_or_timer(
433 long wtime,
434 int (*wait_func)(long wtime, int *interrupted, int ignore_input),
435 int *interrupted,
436 int ignore_input)
437{
438 int due_time;
439 long remaining = wtime;
440 int tb_change_cnt = typebuf.tb_change_cnt;
Bram Moolenaarc46af532019-01-09 22:24:49 +0100441# ifdef FEAT_JOB_CHANNEL
Bram Moolenaare299bbd2019-01-17 14:12:02 +0100442 int brief_wait = FALSE;
Bram Moolenaarc46af532019-01-09 22:24:49 +0100443# endif
Bram Moolenaarc9e649a2017-12-18 18:14:47 +0100444
Bram Moolenaarc46af532019-01-09 22:24:49 +0100445 // When waiting very briefly don't trigger timers.
Bram Moolenaarc9e649a2017-12-18 18:14:47 +0100446 if (wtime >= 0 && wtime < 10L)
447 return wait_func(wtime, NULL, ignore_input);
448
449 while (wtime < 0 || remaining > 0)
450 {
Bram Moolenaarc46af532019-01-09 22:24:49 +0100451 // Trigger timers and then get the time in wtime until the next one is
452 // due. Wait up to that time.
Bram Moolenaarc9e649a2017-12-18 18:14:47 +0100453 due_time = check_due_timer();
454 if (typebuf.tb_change_cnt != tb_change_cnt)
455 {
Bram Moolenaare38eab22019-12-05 21:50:01 +0100456 // timer may have used feedkeys()
Bram Moolenaarc9e649a2017-12-18 18:14:47 +0100457 return FAIL;
458 }
459 if (due_time <= 0 || (wtime > 0 && due_time > remaining))
460 due_time = remaining;
Bram Moolenaar28e67e02019-08-15 23:05:49 +0200461# if defined(FEAT_JOB_CHANNEL) || defined(FEAT_SOUND_CANBERRA)
462 if ((due_time < 0 || due_time > 10L) && (
463# if defined(FEAT_JOB_CHANNEL)
464 (
465# if defined(FEAT_GUI)
466 !gui.in_use &&
467# endif
468 (has_pending_job() || channel_any_readahead()))
469# ifdef FEAT_SOUND_CANBERRA
470 ||
471# endif
Bram Moolenaarc46af532019-01-09 22:24:49 +0100472# endif
Bram Moolenaar28e67e02019-08-15 23:05:49 +0200473# ifdef FEAT_SOUND_CANBERRA
474 has_any_sound_callback()
475# endif
476 ))
Bram Moolenaarc46af532019-01-09 22:24:49 +0100477 {
478 // There is a pending job or channel, should return soon in order
479 // to handle them ASAP. Do check for input briefly.
480 due_time = 10L;
Bram Moolenaar6cdce2a2019-09-07 23:25:09 +0200481# ifdef FEAT_JOB_CHANNEL
Bram Moolenaarc46af532019-01-09 22:24:49 +0100482 brief_wait = TRUE;
Bram Moolenaar6cdce2a2019-09-07 23:25:09 +0200483# endif
Bram Moolenaarc46af532019-01-09 22:24:49 +0100484 }
485# endif
Bram Moolenaarc9e649a2017-12-18 18:14:47 +0100486 if (wait_func(due_time, interrupted, ignore_input))
487 return OK;
Bram Moolenaarc46af532019-01-09 22:24:49 +0100488 if ((interrupted != NULL && *interrupted)
489# ifdef FEAT_JOB_CHANNEL
490 || brief_wait
491# endif
492 )
493 // Nothing available, but need to return so that side effects get
494 // handled, such as handling a message on a channel.
Bram Moolenaara338adc2018-01-31 20:51:47 +0100495 return FAIL;
Bram Moolenaarc9e649a2017-12-18 18:14:47 +0100496 if (wtime > 0)
497 remaining -= due_time;
498 }
499 return FAIL;
500}
501#endif
502
Bram Moolenaar071d4272004-06-13 20:20:40 +0000503/*
Bram Moolenaarc46af532019-01-09 22:24:49 +0100504 * Return non-zero if a character is available.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000505 */
506 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100507ui_char_avail(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000508{
509#ifdef FEAT_GUI
510 if (gui.in_use)
511 {
512 gui_mch_update();
513 return input_available();
514 }
515#endif
516#ifndef NO_CONSOLE
517# ifdef NO_CONSOLE_INPUT
518 if (no_console_input())
519 return 0;
520# endif
521 return mch_char_avail();
522#else
523 return 0;
524#endif
525}
526
527/*
528 * Delay for the given number of milliseconds. If ignoreinput is FALSE then we
529 * cancel the delay if a key is hit.
530 */
531 void
Bram Moolenaarb340bae2020-06-15 19:51:56 +0200532ui_delay(long msec_arg, int ignoreinput)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000533{
Bram Moolenaarb340bae2020-06-15 19:51:56 +0200534 long msec = msec_arg;
535
536#ifdef FEAT_EVAL
537 if (ui_delay_for_testing > 0)
538 msec = ui_delay_for_testing;
539#endif
Bram Moolenaareda1da02019-11-17 17:06:33 +0100540#ifdef FEAT_JOB_CHANNEL
541 ch_log(NULL, "ui_delay(%ld)", msec);
542#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000543#ifdef FEAT_GUI
544 if (gui.in_use && !ignoreinput)
Bram Moolenaarc9e649a2017-12-18 18:14:47 +0100545 gui_wait_for_chars(msec, typebuf.tb_change_cnt);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000546 else
547#endif
Bram Moolenaar0981c872020-08-23 14:28:37 +0200548 mch_delay(msec, ignoreinput ? MCH_DELAY_IGNOREINPUT : 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000549}
550
551/*
552 * If the machine has job control, use it to suspend the program,
553 * otherwise fake it by starting a new shell.
554 * When running the GUI iconify the window.
555 */
556 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100557ui_suspend(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000558{
559#ifdef FEAT_GUI
560 if (gui.in_use)
561 {
562 gui_mch_iconify();
563 return;
564 }
565#endif
566 mch_suspend();
567}
568
Bram Moolenaar041c7102020-05-30 18:14:57 +0200569#if !defined(UNIX) || !defined(SIGTSTP) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000570/*
571 * When the OS can't really suspend, call this function to start a shell.
572 * This is never called in the GUI.
573 */
574 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100575suspend_shell(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000576{
577 if (*p_sh == NUL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +0100578 emsg(_(e_shellempty));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000579 else
580 {
Bram Moolenaar32526b32019-01-19 17:43:09 +0100581 msg_puts(_("new shell started\n"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000582 do_shell(NULL, 0);
583 }
584}
585#endif
586
587/*
588 * Try to get the current Vim shell size. Put the result in Rows and Columns.
589 * Use the new sizes as defaults for 'columns' and 'lines'.
590 * Return OK when size could be determined, FAIL otherwise.
591 */
592 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100593ui_get_shellsize(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000594{
595 int retval;
596
597#ifdef FEAT_GUI
598 if (gui.in_use)
599 retval = gui_get_shellsize();
600 else
601#endif
602 retval = mch_get_shellsize();
603
604 check_shellsize();
605
Bram Moolenaare38eab22019-12-05 21:50:01 +0100606 // adjust the default for 'lines' and 'columns'
Bram Moolenaar071d4272004-06-13 20:20:40 +0000607 if (retval == OK)
608 {
609 set_number_default("lines", Rows);
610 set_number_default("columns", Columns);
611 }
612 return retval;
613}
614
615/*
616 * Set the size of the Vim shell according to Rows and Columns, if possible.
617 * The gui_set_shellsize() or mch_set_shellsize() function will try to set the
618 * new size. If this is not possible, it will adjust Rows and Columns.
619 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000620 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100621ui_set_shellsize(
Bram Moolenaare38eab22019-12-05 21:50:01 +0100622 int mustset UNUSED) // set by the user
Bram Moolenaar071d4272004-06-13 20:20:40 +0000623{
624#ifdef FEAT_GUI
625 if (gui.in_use)
Bram Moolenaar8968a312013-07-03 16:58:44 +0200626 gui_set_shellsize(mustset, TRUE, RESIZE_BOTH);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000627 else
628#endif
629 mch_set_shellsize();
630}
631
632/*
633 * Called when Rows and/or Columns changed. Adjust scroll region and mouse
634 * region.
635 */
636 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100637ui_new_shellsize(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000638{
639 if (full_screen && !exiting)
640 {
641#ifdef FEAT_GUI
642 if (gui.in_use)
643 gui_new_shellsize();
644 else
645#endif
646 mch_new_shellsize();
647 }
648}
649
Bram Moolenaar6bc93052019-04-06 20:00:19 +0200650#if ((defined(FEAT_EVAL) || defined(FEAT_TERMINAL)) \
Bram Moolenaar3d3f2172019-04-06 17:56:05 +0200651 && (defined(FEAT_GUI) \
Bram Moolenaar16c34c32019-04-06 22:01:24 +0200652 || defined(MSWIN) \
Bram Moolenaar3d3f2172019-04-06 17:56:05 +0200653 || (defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)))) \
Bram Moolenaarfa1e90c2019-04-06 17:47:40 +0200654 || defined(PROTO)
655/*
656 * Get the window position in pixels, if possible.
657 * Return FAIL when not possible.
658 */
659 int
Bram Moolenaarbd67aac2019-09-21 23:09:04 +0200660ui_get_winpos(int *x, int *y, varnumber_T timeout UNUSED)
Bram Moolenaarfa1e90c2019-04-06 17:47:40 +0200661{
662# ifdef FEAT_GUI
663 if (gui.in_use)
664 return gui_mch_get_winpos(x, y);
665# endif
Bram Moolenaarafde13b2019-04-28 19:46:49 +0200666# if defined(MSWIN) && (!defined(FEAT_GUI) || defined(VIMDLL))
Bram Moolenaar16c34c32019-04-06 22:01:24 +0200667 return mch_get_winpos(x, y);
Bram Moolenaar6bc93052019-04-06 20:00:19 +0200668# else
Bram Moolenaar16c34c32019-04-06 22:01:24 +0200669# if defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)
670 return term_get_winpos(x, y, timeout);
671# else
Bram Moolenaar6bc93052019-04-06 20:00:19 +0200672 return FAIL;
Bram Moolenaar16c34c32019-04-06 22:01:24 +0200673# endif
Bram Moolenaarfa1e90c2019-04-06 17:47:40 +0200674# endif
675}
676#endif
677
Bram Moolenaar071d4272004-06-13 20:20:40 +0000678 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100679ui_breakcheck(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000680{
Bram Moolenaarb9c31e72016-09-29 15:18:57 +0200681 ui_breakcheck_force(FALSE);
682}
683
684/*
685 * When "force" is true also check when the terminal is not in raw mode.
686 * This is useful to read input on channels.
687 */
688 void
689ui_breakcheck_force(int force)
690{
Bram Moolenaar48d23bb2018-11-20 02:42:43 +0100691 static int recursive = FALSE;
692 int save_updating_screen = updating_screen;
Bram Moolenaare3caa112017-01-31 22:07:42 +0100693
Bram Moolenaar48d23bb2018-11-20 02:42:43 +0100694 // We could be called recursively if stderr is redirected, calling
695 // fill_input_buf() calls settmode() when stdin isn't a tty. settmode()
696 // calls vgetorpeek() which calls ui_breakcheck() again.
697 if (recursive)
698 return;
699 recursive = TRUE;
700
701 // We do not want gui_resize_shell() to redraw the screen here.
Bram Moolenaare3caa112017-01-31 22:07:42 +0100702 ++updating_screen;
703
Bram Moolenaar071d4272004-06-13 20:20:40 +0000704#ifdef FEAT_GUI
705 if (gui.in_use)
706 gui_mch_update();
707 else
708#endif
Bram Moolenaarb9c31e72016-09-29 15:18:57 +0200709 mch_breakcheck(force);
Bram Moolenaare3caa112017-01-31 22:07:42 +0100710
Bram Moolenaar42335f52018-09-13 15:33:43 +0200711 if (save_updating_screen)
712 updating_screen = TRUE;
Bram Moolenaar0cb8ac72018-05-11 22:01:51 +0200713 else
Bram Moolenaar68a4b042019-05-29 22:28:29 +0200714 after_updating_screen(FALSE);
Bram Moolenaar48d23bb2018-11-20 02:42:43 +0100715
716 recursive = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000717}
718
Bram Moolenaare38eab22019-12-05 21:50:01 +0100719//////////////////////////////////////////////////////////////////////////////
Bram Moolenaare38eab22019-12-05 21:50:01 +0100720// Functions that handle the input buffer.
721// This is used for any GUI version, and the unix terminal version.
722//
723// For Unix, the input characters are buffered to be able to check for a
724// CTRL-C. This should be done with signals, but I don't know how to do that
725// in a portable way for a tty in RAW mode.
726//
727// For the client-server code in the console the received keys are put in the
728// input buffer.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000729
730#if defined(USE_INPUT_BUF) || defined(PROTO)
731
732/*
733 * Internal typeahead buffer. Includes extra space for long key code
734 * descriptions which would otherwise overflow. The buffer is considered full
735 * when only this extra space (or part of it) remains.
736 */
Bram Moolenaarbb1969b2019-01-17 15:45:25 +0100737#if defined(FEAT_JOB_CHANNEL) || defined(FEAT_CLIENTSERVER)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000738 /*
Bram Moolenaarbb1969b2019-01-17 15:45:25 +0100739 * NetBeans stuffs debugger commands into the input buffer.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000740 * This requires a larger buffer...
741 * (Madsen) Go with this for remote input as well ...
742 */
743# define INBUFLEN 4096
744#else
745# define INBUFLEN 250
746#endif
747
748static char_u inbuf[INBUFLEN + MAX_KEY_CODE_LEN];
Bram Moolenaare38eab22019-12-05 21:50:01 +0100749static int inbufcount = 0; // number of chars in inbuf[]
Bram Moolenaar071d4272004-06-13 20:20:40 +0000750
751/*
752 * vim_is_input_buf_full(), vim_is_input_buf_empty(), add_to_input_buf(), and
753 * trash_input_buf() are functions for manipulating the input buffer. These
754 * are used by the gui_* calls when a GUI is used to handle keyboard input.
755 */
756
757 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100758vim_is_input_buf_full(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000759{
760 return (inbufcount >= INBUFLEN);
761}
762
763 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100764vim_is_input_buf_empty(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000765{
766 return (inbufcount == 0);
767}
768
769#if defined(FEAT_OLE) || defined(PROTO)
770 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100771vim_free_in_input_buf(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000772{
773 return (INBUFLEN - inbufcount);
774}
775#endif
776
Bram Moolenaar241a8aa2005-12-06 20:04:44 +0000777#if defined(FEAT_GUI_GTK) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000778 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100779vim_used_in_input_buf(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000780{
781 return inbufcount;
782}
783#endif
784
Bram Moolenaar071d4272004-06-13 20:20:40 +0000785/*
786 * Return the current contents of the input buffer and make it empty.
787 * The returned pointer must be passed to set_input_buf() later.
788 */
789 char_u *
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100790get_input_buf(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000791{
792 garray_T *gap;
793
Bram Moolenaare38eab22019-12-05 21:50:01 +0100794 // We use a growarray to store the data pointer and the length.
Bram Moolenaarc799fe22019-05-28 23:08:19 +0200795 gap = ALLOC_ONE(garray_T);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000796 if (gap != NULL)
797 {
Bram Moolenaare38eab22019-12-05 21:50:01 +0100798 // Add one to avoid a zero size.
Bram Moolenaar18a4ba22019-05-24 19:39:03 +0200799 gap->ga_data = alloc(inbufcount + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000800 if (gap->ga_data != NULL)
801 mch_memmove(gap->ga_data, inbuf, (size_t)inbufcount);
802 gap->ga_len = inbufcount;
803 }
804 trash_input_buf();
805 return (char_u *)gap;
806}
807
808/*
809 * Restore the input buffer with a pointer returned from get_input_buf().
810 * The allocated memory is freed, this only works once!
811 */
812 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100813set_input_buf(char_u *p)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000814{
815 garray_T *gap = (garray_T *)p;
816
817 if (gap != NULL)
818 {
819 if (gap->ga_data != NULL)
820 {
821 mch_memmove(inbuf, gap->ga_data, gap->ga_len);
822 inbufcount = gap->ga_len;
823 vim_free(gap->ga_data);
824 }
825 vim_free(gap);
826 }
827}
Bram Moolenaar071d4272004-06-13 20:20:40 +0000828
Bram Moolenaar071d4272004-06-13 20:20:40 +0000829/*
830 * Add the given bytes to the input buffer
831 * Special keys start with CSI. A real CSI must have been translated to
832 * CSI KS_EXTRA KE_CSI. K_SPECIAL doesn't require translation.
833 */
834 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100835add_to_input_buf(char_u *s, int len)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000836{
837 if (inbufcount + len > INBUFLEN + MAX_KEY_CODE_LEN)
Bram Moolenaare38eab22019-12-05 21:50:01 +0100838 return; // Shouldn't ever happen!
Bram Moolenaar071d4272004-06-13 20:20:40 +0000839
Bram Moolenaar071d4272004-06-13 20:20:40 +0000840 while (len--)
841 inbuf[inbufcount++] = *s++;
842}
Bram Moolenaar071d4272004-06-13 20:20:40 +0000843
Bram Moolenaar071d4272004-06-13 20:20:40 +0000844/*
845 * Add "str[len]" to the input buffer while escaping CSI bytes.
846 */
847 void
848add_to_input_buf_csi(char_u *str, int len)
849{
850 int i;
851 char_u buf[2];
852
853 for (i = 0; i < len; ++i)
854 {
855 add_to_input_buf(str + i, 1);
856 if (str[i] == CSI)
857 {
Bram Moolenaare38eab22019-12-05 21:50:01 +0100858 // Turn CSI into K_CSI.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000859 buf[0] = KS_EXTRA;
860 buf[1] = (int)KE_CSI;
861 add_to_input_buf(buf, 2);
862 }
863 }
864}
Bram Moolenaar071d4272004-06-13 20:20:40 +0000865
Bram Moolenaare38eab22019-12-05 21:50:01 +0100866/*
867 * Remove everything from the input buffer. Called when ^C is found.
868 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000869 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100870trash_input_buf(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000871{
872 inbufcount = 0;
873}
Bram Moolenaar071d4272004-06-13 20:20:40 +0000874
875/*
876 * Read as much data from the input buffer as possible up to maxlen, and store
877 * it in buf.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000878 */
879 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100880read_from_input_buf(char_u *buf, long maxlen)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000881{
Bram Moolenaare38eab22019-12-05 21:50:01 +0100882 if (inbufcount == 0) // if the buffer is empty, fill it
Bram Moolenaar071d4272004-06-13 20:20:40 +0000883 fill_input_buf(TRUE);
884 if (maxlen > inbufcount)
885 maxlen = inbufcount;
886 mch_memmove(buf, inbuf, (size_t)maxlen);
887 inbufcount -= maxlen;
888 if (inbufcount)
889 mch_memmove(inbuf, inbuf + maxlen, (size_t)inbufcount);
890 return (int)maxlen;
891}
892
893 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100894fill_input_buf(int exit_on_error UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000895{
Bram Moolenaard0573012017-10-28 21:11:06 +0200896#if defined(UNIX) || defined(VMS) || defined(MACOS_X)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000897 int len;
898 int try;
899 static int did_read_something = FALSE;
Bram Moolenaare38eab22019-12-05 21:50:01 +0100900 static char_u *rest = NULL; // unconverted rest of previous read
Bram Moolenaar071d4272004-06-13 20:20:40 +0000901 static int restlen = 0;
902 int unconverted;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000903#endif
904
905#ifdef FEAT_GUI
Bram Moolenaar54ee7752005-05-31 22:22:17 +0000906 if (gui.in_use
907# ifdef NO_CONSOLE_INPUT
Bram Moolenaare38eab22019-12-05 21:50:01 +0100908 // Don't use the GUI input when the window hasn't been opened yet.
909 // We get here from ui_inchar() when we should try reading from stdin.
Bram Moolenaar54ee7752005-05-31 22:22:17 +0000910 && !no_console_input()
911# endif
912 )
Bram Moolenaar071d4272004-06-13 20:20:40 +0000913 {
914 gui_mch_update();
915 return;
916 }
917#endif
Bram Moolenaard0573012017-10-28 21:11:06 +0200918#if defined(UNIX) || defined(VMS) || defined(MACOS_X)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000919 if (vim_is_input_buf_full())
920 return;
921 /*
922 * Fill_input_buf() is only called when we really need a character.
923 * If we can't get any, but there is some in the buffer, just return.
924 * If we can't get any, and there isn't any in the buffer, we give up and
925 * exit Vim.
926 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000927 if (rest != NULL)
928 {
Bram Moolenaare38eab22019-12-05 21:50:01 +0100929 // Use remainder of previous call, starts with an invalid character
930 // that may become valid when reading more.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000931 if (restlen > INBUFLEN - inbufcount)
932 unconverted = INBUFLEN - inbufcount;
933 else
934 unconverted = restlen;
935 mch_memmove(inbuf + inbufcount, rest, unconverted);
936 if (unconverted == restlen)
Bram Moolenaard23a8232018-02-10 18:45:26 +0100937 VIM_CLEAR(rest);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000938 else
939 {
940 restlen -= unconverted;
941 mch_memmove(rest, rest + unconverted, restlen);
942 }
943 inbufcount += unconverted;
944 }
945 else
946 unconverted = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000947
Bram Moolenaare38eab22019-12-05 21:50:01 +0100948 len = 0; // to avoid gcc warning
Bram Moolenaar071d4272004-06-13 20:20:40 +0000949 for (try = 0; try < 100; ++try)
950 {
Bram Moolenaar4e601e32018-04-24 13:29:51 +0200951 size_t readlen = (size_t)((INBUFLEN - inbufcount)
Bram Moolenaar9645e2d2020-03-20 20:48:49 +0100952 / input_conv.vc_factor);
Bram Moolenaar4e601e32018-04-24 13:29:51 +0200953# ifdef VMS
Bram Moolenaar49943732018-04-24 20:27:26 +0200954 len = vms_read((char *)inbuf + inbufcount, readlen);
Bram Moolenaar4e601e32018-04-24 13:29:51 +0200955# else
956 len = read(read_cmd_fd, (char *)inbuf + inbufcount, readlen);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000957# endif
Bram Moolenaar7ca86fe2020-09-03 19:25:11 +0200958# ifdef FEAT_JOB_CHANNEL
959 if (len > 0)
960 {
961 inbuf[inbufcount + len] = NUL;
962 ch_log(NULL, "raw key input: \"%s\"", inbuf + inbufcount);
963 }
964# endif
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000965
Bram Moolenaar071d4272004-06-13 20:20:40 +0000966 if (len > 0 || got_int)
967 break;
968 /*
969 * If reading stdin results in an error, continue reading stderr.
970 * This helps when using "foo | xargs vim".
971 */
972 if (!did_read_something && !isatty(read_cmd_fd) && read_cmd_fd == 0)
973 {
974 int m = cur_tmode;
975
Bram Moolenaare38eab22019-12-05 21:50:01 +0100976 // We probably set the wrong file descriptor to raw mode. Switch
977 // back to cooked mode, use another descriptor and set the mode to
978 // what it was.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000979 settmode(TMODE_COOK);
980#ifdef HAVE_DUP
Bram Moolenaare38eab22019-12-05 21:50:01 +0100981 // Use stderr for stdin, also works for shell commands.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000982 close(0);
Bram Moolenaar42335f52018-09-13 15:33:43 +0200983 vim_ignored = dup(2);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000984#else
Bram Moolenaare38eab22019-12-05 21:50:01 +0100985 read_cmd_fd = 2; // read from stderr instead of stdin
Bram Moolenaar071d4272004-06-13 20:20:40 +0000986#endif
987 settmode(m);
988 }
989 if (!exit_on_error)
990 return;
991 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000992 if (len <= 0 && !got_int)
993 read_error_exit();
994 if (len > 0)
995 did_read_something = TRUE;
996 if (got_int)
997 {
Bram Moolenaare38eab22019-12-05 21:50:01 +0100998 // Interrupted, pretend a CTRL-C was typed.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000999 inbuf[0] = 3;
1000 inbufcount = 1;
1001 }
1002 else
1003 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001004 /*
1005 * May perform conversion on the input characters.
1006 * Include the unconverted rest of the previous call.
1007 * If there is an incomplete char at the end it is kept for the next
1008 * time, reading more bytes should make conversion possible.
1009 * Don't do this in the unlikely event that the input buffer is too
1010 * small ("rest" still contains more bytes).
1011 */
1012 if (input_conv.vc_type != CONV_NONE)
1013 {
1014 inbufcount -= unconverted;
1015 len = convert_input_safe(inbuf + inbufcount,
1016 len + unconverted, INBUFLEN - inbufcount,
1017 rest == NULL ? &rest : NULL, &restlen);
1018 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001019 while (len-- > 0)
1020 {
Bram Moolenaar339c1bd2021-01-02 20:14:23 +01001021 // If a CTRL-C was typed, remove it from the buffer and set
1022 // got_int. Also recognize CTRL-C with modifyOtherKeys set, in two
1023 // forms.
Bram Moolenaar9645e2d2020-03-20 20:48:49 +01001024 if (ctrl_c_interrupts && (inbuf[inbufcount] == 3
Bram Moolenaar339c1bd2021-01-02 20:14:23 +01001025 || (len >= 10 && STRNCMP(inbuf + inbufcount,
Bram Moolenaar02faa942021-01-02 16:17:18 +01001026 "\033[27;5;99~", 10) == 0)
1027 || (len >= 7 && STRNCMP(inbuf + inbufcount,
1028 "\033[99;5u", 7) == 0)))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001029 {
Bram Moolenaare38eab22019-12-05 21:50:01 +01001030 // remove everything typed before the CTRL-C
Bram Moolenaar071d4272004-06-13 20:20:40 +00001031 mch_memmove(inbuf, inbuf + inbufcount, (size_t)(len + 1));
1032 inbufcount = 0;
1033 got_int = TRUE;
1034 }
1035 ++inbufcount;
1036 }
1037 }
Bram Moolenaar74ee5e22019-12-13 18:13:22 +01001038#endif // UNIX || VMS || MACOS_X
Bram Moolenaar071d4272004-06-13 20:20:40 +00001039}
Bram Moolenaar74ee5e22019-12-13 18:13:22 +01001040#endif // USE_INPUT_BUF
Bram Moolenaar071d4272004-06-13 20:20:40 +00001041
1042/*
1043 * Exit because of an input read error.
1044 */
1045 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +01001046read_error_exit(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001047{
Bram Moolenaare38eab22019-12-05 21:50:01 +01001048 if (silent_mode) // Normal way to exit for "ex -s"
Bram Moolenaar071d4272004-06-13 20:20:40 +00001049 getout(0);
1050 STRCPY(IObuff, _("Vim: Error reading input, exiting...\n"));
1051 preserve_exit();
1052}
1053
1054#if defined(CURSOR_SHAPE) || defined(PROTO)
1055/*
1056 * May update the shape of the cursor.
1057 */
1058 void
Bram Moolenaar3cd43cc2017-08-12 19:51:41 +02001059ui_cursor_shape_forced(int forced)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001060{
1061# ifdef FEAT_GUI
1062 if (gui.in_use)
1063 gui_update_cursor_later();
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00001064 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00001065# endif
Bram Moolenaar3cd43cc2017-08-12 19:51:41 +02001066 term_cursor_mode(forced);
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00001067
Bram Moolenaar071d4272004-06-13 20:20:40 +00001068# ifdef MCH_CURSOR_SHAPE
1069 mch_update_cursor();
1070# endif
Bram Moolenaarf5963f72010-07-23 22:10:27 +02001071
1072# ifdef FEAT_CONCEAL
Bram Moolenaarb9464822018-05-10 15:09:49 +02001073 conceal_check_cursor_line();
Bram Moolenaarf5963f72010-07-23 22:10:27 +02001074# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001075}
Bram Moolenaar3cd43cc2017-08-12 19:51:41 +02001076
1077 void
1078ui_cursor_shape(void)
1079{
1080 ui_cursor_shape_forced(FALSE);
1081}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001082#endif
1083
Bram Moolenaar071d4272004-06-13 20:20:40 +00001084/*
1085 * Check bounds for column number
1086 */
1087 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +01001088check_col(int col)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001089{
1090 if (col < 0)
1091 return 0;
1092 if (col >= (int)screen_Columns)
1093 return (int)screen_Columns - 1;
1094 return col;
1095}
1096
1097/*
1098 * Check bounds for row number
1099 */
1100 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +01001101check_row(int row)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001102{
1103 if (row < 0)
1104 return 0;
1105 if (row >= (int)screen_Rows)
1106 return (int)screen_Rows - 1;
1107 return row;
1108}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001109
Bram Moolenaar071d4272004-06-13 20:20:40 +00001110/*
1111 * Called when focus changed. Used for the GUI or for systems where this can
1112 * be done in the console (Win32).
1113 */
1114 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +01001115ui_focus_change(
Bram Moolenaare38eab22019-12-05 21:50:01 +01001116 int in_focus) // TRUE if focus gained.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001117{
1118 static time_t last_time = (time_t)0;
1119 int need_redraw = FALSE;
1120
Bram Moolenaare38eab22019-12-05 21:50:01 +01001121 // When activated: Check if any file was modified outside of Vim.
1122 // Only do this when not done within the last two seconds (could get
1123 // several events in a row).
Bram Moolenaar071d4272004-06-13 20:20:40 +00001124 if (in_focus && last_time + 2 < time(NULL))
1125 {
1126 need_redraw = check_timestamps(
1127# ifdef FEAT_GUI
1128 gui.in_use
1129# else
1130 FALSE
1131# endif
1132 );
1133 last_time = time(NULL);
1134 }
1135
Bram Moolenaar071d4272004-06-13 20:20:40 +00001136 /*
1137 * Fire the focus gained/lost autocommand.
1138 */
1139 need_redraw |= apply_autocmds(in_focus ? EVENT_FOCUSGAINED
1140 : EVENT_FOCUSLOST, NULL, NULL, FALSE, curbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001141
1142 if (need_redraw)
1143 {
Bram Moolenaare38eab22019-12-05 21:50:01 +01001144 // Something was executed, make sure the cursor is put back where it
1145 // belongs.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001146 need_wait_return = FALSE;
1147
1148 if (State & CMDLINE)
1149 redrawcmdline();
1150 else if (State == HITRETURN || State == SETWSIZE || State == ASKMORE
1151 || State == EXTERNCMD || State == CONFIRM || exmode_active)
1152 repeat_message();
1153 else if ((State & NORMAL) || (State & INSERT))
1154 {
1155 if (must_redraw != 0)
1156 update_screen(0);
1157 setcursor();
1158 }
Bram Moolenaare38eab22019-12-05 21:50:01 +01001159 cursor_on(); // redrawing may have switched it off
Bram Moolenaara338adc2018-01-31 20:51:47 +01001160 out_flush_cursor(FALSE, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001161# ifdef FEAT_GUI
1162 if (gui.in_use)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001163 gui_update_scrollbars(FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001164# endif
1165 }
1166#ifdef FEAT_TITLE
Bram Moolenaare38eab22019-12-05 21:50:01 +01001167 // File may have been changed from 'readonly' to 'noreadonly'
Bram Moolenaar071d4272004-06-13 20:20:40 +00001168 if (need_maketitle)
1169 maketitle();
1170#endif
1171}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001172
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01001173#if defined(HAVE_INPUT_METHOD) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001174/*
1175 * Save current Input Method status to specified place.
1176 */
1177 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +01001178im_save_status(long *psave)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001179{
Bram Moolenaare38eab22019-12-05 21:50:01 +01001180 // Don't save when 'imdisable' is set or "xic" is NULL, IM is always
1181 // disabled then (but might start later).
1182 // Also don't save when inside a mapping, vgetc_im_active has not been set
1183 // then.
1184 // And don't save when the keys were stuffed (e.g., for a "." command).
1185 // And don't save when the GUI is running but our window doesn't have
1186 // input focus (e.g., when a find dialog is open).
Bram Moolenaar071d4272004-06-13 20:20:40 +00001187 if (!p_imdisable && KeyTyped && !KeyStuffed
1188# ifdef FEAT_XIM
1189 && xic != NULL
1190# endif
1191# ifdef FEAT_GUI
1192 && (!gui.in_use || gui.in_focus)
1193# endif
1194 )
1195 {
Bram Moolenaare38eab22019-12-05 21:50:01 +01001196 // Do save when IM is on, or IM is off and saved status is on.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001197 if (vgetc_im_active)
1198 *psave = B_IMODE_IM;
1199 else if (*psave == B_IMODE_IM)
1200 *psave = B_IMODE_NONE;
1201 }
1202}
1203#endif