blob: 19d9e21525240de2110ac6081889bad170670af8 [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 Moolenaar764b23c2016-01-30 21:10:09 +010021ui_write(char_u *s, int len)
Bram Moolenaar071d4272004-06-13 20:20:40 +000022{
23#ifdef FEAT_GUI
24 if (gui.in_use && !gui.dying && !gui.starting)
25 {
26 gui_write(s, len);
27 if (p_wd)
Bram Moolenaarc9e649a2017-12-18 18:14:47 +010028 gui_wait_for_chars(p_wd, typebuf.tb_change_cnt);
Bram Moolenaar071d4272004-06-13 20:20:40 +000029 return;
30 }
31#endif
32#ifndef NO_CONSOLE
Bram Moolenaare38eab22019-12-05 21:50:01 +010033 // Don't output anything in silent mode ("ex -s") unless 'verbose' set
Bram Moolenaar071d4272004-06-13 20:20:40 +000034 if (!(silent_mode && p_verbose == 0))
35 {
Bram Moolenaar4f974752019-02-17 17:44:42 +010036#if !defined(MSWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000037 char_u *tofree = NULL;
38
39 if (output_conv.vc_type != CONV_NONE)
40 {
Bram Moolenaare38eab22019-12-05 21:50:01 +010041 // Convert characters from 'encoding' to 'termencoding'.
Bram Moolenaar071d4272004-06-13 20:20:40 +000042 tofree = string_convert(&output_conv, s, &len);
43 if (tofree != NULL)
44 s = tofree;
45 }
46#endif
47
48 mch_write(s, len);
49
Bram Moolenaar4f974752019-02-17 17:44:42 +010050# if !defined(MSWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000051 if (output_conv.vc_type != CONV_NONE)
52 vim_free(tofree);
Bram Moolenaar264b74f2019-01-24 17:18:42 +010053# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000054 }
55#endif
56}
57
Bram Moolenaar4f974752019-02-17 17:44:42 +010058#if defined(UNIX) || defined(VMS) || defined(PROTO) || defined(MSWIN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000059/*
60 * When executing an external program, there may be some typed characters that
61 * are not consumed by it. Give them back to ui_inchar() and they are stored
62 * here for the next call.
63 */
64static char_u *ta_str = NULL;
Bram Moolenaare38eab22019-12-05 21:50:01 +010065static int ta_off; // offset for next char to use when ta_str != NULL
66static int ta_len; // length of ta_str when it's not NULL
Bram Moolenaar071d4272004-06-13 20:20:40 +000067
68 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +010069ui_inchar_undo(char_u *s, int len)
Bram Moolenaar071d4272004-06-13 20:20:40 +000070{
71 char_u *new;
72 int newlen;
73
74 newlen = len;
75 if (ta_str != NULL)
76 newlen += ta_len - ta_off;
77 new = alloc(newlen);
78 if (new != NULL)
79 {
80 if (ta_str != NULL)
81 {
82 mch_memmove(new, ta_str + ta_off, (size_t)(ta_len - ta_off));
83 mch_memmove(new + ta_len - ta_off, s, (size_t)len);
84 vim_free(ta_str);
85 }
86 else
87 mch_memmove(new, s, (size_t)len);
88 ta_str = new;
89 ta_len = newlen;
90 ta_off = 0;
91 }
92}
93#endif
94
95/*
Bram Moolenaarb6101cf2012-10-21 00:58:39 +020096 * ui_inchar(): low level input function.
Bram Moolenaar071d4272004-06-13 20:20:40 +000097 * Get characters from the keyboard.
98 * Return the number of characters that are available.
99 * If "wtime" == 0 do not wait for characters.
100 * If "wtime" == -1 wait forever for characters.
101 * If "wtime" > 0 wait "wtime" milliseconds for a character.
102 *
103 * "tb_change_cnt" is the value of typebuf.tb_change_cnt if "buf" points into
104 * it. When typebuf.tb_change_cnt changes (e.g., when a message is received
105 * from a remote client) "buf" can no longer be used. "tb_change_cnt" is NULL
106 * otherwise.
107 */
108 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100109ui_inchar(
110 char_u *buf,
111 int maxlen,
Bram Moolenaare38eab22019-12-05 21:50:01 +0100112 long wtime, // don't use "time", MIPS cannot handle it
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100113 int tb_change_cnt)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000114{
115 int retval = 0;
116
117#if defined(FEAT_GUI) && (defined(UNIX) || defined(VMS))
118 /*
119 * Use the typeahead if there is any.
120 */
121 if (ta_str != NULL)
122 {
123 if (maxlen >= ta_len - ta_off)
124 {
125 mch_memmove(buf, ta_str + ta_off, (size_t)ta_len);
Bram Moolenaard23a8232018-02-10 18:45:26 +0100126 VIM_CLEAR(ta_str);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000127 return ta_len;
128 }
129 mch_memmove(buf, ta_str + ta_off, (size_t)maxlen);
130 ta_off += maxlen;
131 return maxlen;
132 }
133#endif
134
Bram Moolenaar05159a02005-02-26 23:04:13 +0000135#ifdef FEAT_PROFILE
Bram Moolenaarb3656ed2006-03-20 21:59:49 +0000136 if (do_profiling == PROF_YES && wtime != 0)
Bram Moolenaar05159a02005-02-26 23:04:13 +0000137 prof_inchar_enter();
138#endif
139
Bram Moolenaar071d4272004-06-13 20:20:40 +0000140#ifdef NO_CONSOLE_INPUT
Bram Moolenaare38eab22019-12-05 21:50:01 +0100141 // Don't wait for character input when the window hasn't been opened yet.
142 // Do try reading, this works when redirecting stdin from a file.
143 // Must return something, otherwise we'll loop forever. If we run into
144 // this very often we probably got stuck, exit Vim.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000145 if (no_console_input())
146 {
147 static int count = 0;
148
149# ifndef NO_CONSOLE
Bram Moolenaar13410242018-11-26 21:19:11 +0100150 retval = mch_inchar(buf, maxlen, wtime, tb_change_cnt);
Bram Moolenaar43b604c2005-03-22 23:06:55 +0000151 if (retval > 0 || typebuf_changed(tb_change_cnt) || wtime >= 0)
Bram Moolenaar05159a02005-02-26 23:04:13 +0000152 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000153# endif
154 if (wtime == -1 && ++count == 1000)
155 read_error_exit();
156 buf[0] = CAR;
Bram Moolenaar05159a02005-02-26 23:04:13 +0000157 retval = 1;
158 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000159 }
160#endif
161
Bram Moolenaare38eab22019-12-05 21:50:01 +0100162 // If we are going to wait for some time or block...
Bram Moolenaarc8da3112007-03-08 12:36:46 +0000163 if (wtime == -1 || wtime > 100L)
164 {
Bram Moolenaare38eab22019-12-05 21:50:01 +0100165 // ... allow signals to kill us.
Bram Moolenaarc8da3112007-03-08 12:36:46 +0000166 (void)vim_handle_signal(SIGNAL_UNBLOCK);
167
Bram Moolenaare38eab22019-12-05 21:50:01 +0100168 // ... there is no need for CTRL-C to interrupt something, don't let
169 // it set got_int when it was mapped.
Bram Moolenaar50008692015-01-14 16:08:32 +0100170 if ((mapped_ctrl_c | curbuf->b_mapped_ctrl_c) & get_real_state())
Bram Moolenaarc8da3112007-03-08 12:36:46 +0000171 ctrl_c_interrupts = FALSE;
172 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000173
Bram Moolenaare40b9d42019-01-27 16:55:47 +0100174 /*
175 * Here we call gui_inchar() or mch_inchar(), the GUI or machine-dependent
176 * input function. The functionality they implement is like this:
177 *
178 * while (not timed out)
179 * {
180 * handle-resize;
181 * parse-queued-messages;
182 * if (waited for 'updatetime')
183 * trigger-cursorhold;
184 * ui_wait_for_chars_or_timer()
185 * if (character available)
186 * break;
187 * }
188 *
189 * ui_wait_for_chars_or_timer() does:
190 *
191 * while (not timed out)
192 * {
193 * if (any-timer-triggered)
194 * invoke-timer-callback;
195 * wait-for-character();
196 * if (character available)
197 * break;
198 * }
199 *
200 * wait-for-character() does:
201 * while (not timed out)
202 * {
203 * Wait for event;
204 * if (something on channel)
205 * read/write channel;
206 * else if (resized)
207 * handle_resize();
208 * else if (system event)
209 * deal-with-system-event;
210 * else if (character available)
211 * break;
212 * }
213 *
214 */
215
Bram Moolenaar071d4272004-06-13 20:20:40 +0000216#ifdef FEAT_GUI
217 if (gui.in_use)
Bram Moolenaarc9e649a2017-12-18 18:14:47 +0100218 retval = gui_inchar(buf, maxlen, wtime, tb_change_cnt);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000219#endif
220#ifndef NO_CONSOLE
221# ifdef FEAT_GUI
222 else
223# endif
224 retval = mch_inchar(buf, maxlen, wtime, tb_change_cnt);
225#endif
226
Bram Moolenaarc8da3112007-03-08 12:36:46 +0000227 if (wtime == -1 || wtime > 100L)
Bram Moolenaare38eab22019-12-05 21:50:01 +0100228 // block SIGHUP et al.
Bram Moolenaarc8da3112007-03-08 12:36:46 +0000229 (void)vim_handle_signal(SIGNAL_BLOCK);
230
Bram Moolenaar071d4272004-06-13 20:20:40 +0000231 ctrl_c_interrupts = TRUE;
232
Bram Moolenaar05159a02005-02-26 23:04:13 +0000233#ifdef NO_CONSOLE_INPUT
234theend:
235#endif
236#ifdef FEAT_PROFILE
Bram Moolenaarb3656ed2006-03-20 21:59:49 +0000237 if (do_profiling == PROF_YES && wtime != 0)
Bram Moolenaar05159a02005-02-26 23:04:13 +0000238 prof_inchar_exit();
239#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000240 return retval;
241}
242
Bram Moolenaar95f0b6e2019-12-15 12:54:18 +0100243#if defined(UNIX) || defined(VMS) || defined(FEAT_GUI) || defined(PROTO)
Bram Moolenaare40b9d42019-01-27 16:55:47 +0100244/*
245 * Common code for mch_inchar() and gui_inchar(): Wait for a while or
246 * indefinitely until characters are available, dealing with timers and
247 * messages on channels.
248 *
249 * "buf" may be NULL if the available characters are not to be returned, only
250 * check if they are available.
251 *
252 * Return the number of characters that are available.
253 * If "wtime" == 0 do not wait for characters.
254 * If "wtime" == n wait a short time for characters.
255 * If "wtime" == -1 wait forever for characters.
256 */
257 int
258inchar_loop(
259 char_u *buf,
260 int maxlen,
261 long wtime, // don't use "time", MIPS cannot handle it
262 int tb_change_cnt,
263 int (*wait_func)(long wtime, int *interrupted, int ignore_input),
264 int (*resize_func)(int check_only))
265{
266 int len;
267 int interrupted = FALSE;
Bram Moolenaar12dfc9e2019-01-28 22:32:58 +0100268 int did_call_wait_func = FALSE;
Bram Moolenaare40b9d42019-01-27 16:55:47 +0100269 int did_start_blocking = FALSE;
270 long wait_time;
271 long elapsed_time = 0;
272#ifdef ELAPSED_FUNC
273 elapsed_T start_tv;
274
275 ELAPSED_INIT(start_tv);
276#endif
277
Bram Moolenaare38eab22019-12-05 21:50:01 +0100278 // repeat until we got a character or waited long enough
Bram Moolenaare40b9d42019-01-27 16:55:47 +0100279 for (;;)
280 {
Bram Moolenaare38eab22019-12-05 21:50:01 +0100281 // Check if window changed size while we were busy, perhaps the ":set
282 // columns=99" command was used.
Bram Moolenaare40b9d42019-01-27 16:55:47 +0100283 if (resize_func != NULL)
284 resize_func(FALSE);
285
286#ifdef MESSAGE_QUEUE
287 // Only process messages when waiting.
288 if (wtime != 0)
289 {
290 parse_queued_messages();
291 // If input was put directly in typeahead buffer bail out here.
292 if (typebuf_changed(tb_change_cnt))
293 return 0;
294 }
295#endif
296 if (wtime < 0 && did_start_blocking)
297 // blocking and already waited for p_ut
298 wait_time = -1;
299 else
300 {
301 if (wtime >= 0)
302 wait_time = wtime;
303 else
304 // going to block after p_ut
305 wait_time = p_ut;
306#ifdef ELAPSED_FUNC
307 elapsed_time = ELAPSED_FUNC(start_tv);
308#endif
309 wait_time -= elapsed_time;
Bram Moolenaar12dfc9e2019-01-28 22:32:58 +0100310
311 // If the waiting time is now zero or less, we timed out. However,
312 // loop at least once to check for characters and events. Matters
313 // when "wtime" is zero.
314 if (wait_time <= 0 && did_call_wait_func)
Bram Moolenaare40b9d42019-01-27 16:55:47 +0100315 {
316 if (wtime >= 0)
317 // no character available within "wtime"
318 return 0;
319
320 // No character available within 'updatetime'.
321 did_start_blocking = TRUE;
322 if (trigger_cursorhold() && maxlen >= 3
323 && !typebuf_changed(tb_change_cnt))
324 {
325 // Put K_CURSORHOLD in the input buffer or return it.
326 if (buf == NULL)
327 {
328 char_u ibuf[3];
329
330 ibuf[0] = CSI;
331 ibuf[1] = KS_EXTRA;
332 ibuf[2] = (int)KE_CURSORHOLD;
333 add_to_input_buf(ibuf, 3);
334 }
335 else
336 {
337 buf[0] = K_SPECIAL;
338 buf[1] = KS_EXTRA;
339 buf[2] = (int)KE_CURSORHOLD;
340 }
341 return 3;
342 }
343
344 // There is no character available within 'updatetime' seconds:
345 // flush all the swap files to disk. Also done when
346 // interrupted by SIGWINCH.
347 before_blocking();
348 continue;
349 }
350 }
351
352#ifdef FEAT_JOB_CHANNEL
353 if (wait_time < 0 || wait_time > 100L)
354 {
355 // Checking if a job ended requires polling. Do this at least
356 // every 100 msec.
357 if (has_pending_job())
358 wait_time = 100L;
359
360 // If there is readahead then parse_queued_messages() timed out and
361 // we should call it again soon.
362 if (channel_any_readahead())
363 wait_time = 10L;
364 }
365#endif
366#ifdef FEAT_BEVAL_GUI
367 if (p_beval && wait_time > 100L)
368 // The 'balloonexpr' may indirectly invoke a callback while waiting
369 // for a character, need to check often.
370 wait_time = 100L;
371#endif
372
373 // Wait for a character to be typed or another event, such as the winch
374 // signal or an event on the monitored file descriptors.
Bram Moolenaar12dfc9e2019-01-28 22:32:58 +0100375 did_call_wait_func = TRUE;
Bram Moolenaare40b9d42019-01-27 16:55:47 +0100376 if (wait_func(wait_time, &interrupted, FALSE))
377 {
378 // If input was put directly in typeahead buffer bail out here.
379 if (typebuf_changed(tb_change_cnt))
380 return 0;
381
382 // We might have something to return now.
383 if (buf == NULL)
384 // "buf" is NULL, we were just waiting, not actually getting
385 // input.
386 return input_available();
387
388 len = read_from_input_buf(buf, (long)maxlen);
389 if (len > 0)
390 return len;
391 continue;
392 }
393 // Timed out or interrupted with no character available.
394
395#ifndef ELAPSED_FUNC
396 // estimate the elapsed time
397 elapsed_time += wait_time;
398#endif
399
400 if ((resize_func != NULL && resize_func(TRUE))
Bram Moolenaar3e9d4d82019-01-27 17:08:40 +0100401#if defined(FEAT_CLIENTSERVER) && defined(UNIX)
Bram Moolenaare40b9d42019-01-27 16:55:47 +0100402 || server_waiting()
403#endif
404#ifdef MESSAGE_QUEUE
405 || interrupted
406#endif
407 || wait_time > 0
408 || (wtime < 0 && !did_start_blocking))
409 // no character available, but something to be done, keep going
410 continue;
411
412 // no character available or interrupted, return zero
413 break;
414 }
415 return 0;
416}
417#endif
418
Bram Moolenaarc46af532019-01-09 22:24:49 +0100419#if defined(FEAT_TIMERS) || defined(PROTO)
Bram Moolenaarc9e649a2017-12-18 18:14:47 +0100420/*
421 * Wait for a timer to fire or "wait_func" to return non-zero.
422 * Returns OK when something was read.
423 * Returns FAIL when it timed out or was interrupted.
424 */
425 int
426ui_wait_for_chars_or_timer(
427 long wtime,
428 int (*wait_func)(long wtime, int *interrupted, int ignore_input),
429 int *interrupted,
430 int ignore_input)
431{
432 int due_time;
433 long remaining = wtime;
434 int tb_change_cnt = typebuf.tb_change_cnt;
Bram Moolenaarc46af532019-01-09 22:24:49 +0100435# ifdef FEAT_JOB_CHANNEL
Bram Moolenaare299bbd2019-01-17 14:12:02 +0100436 int brief_wait = FALSE;
Bram Moolenaarc46af532019-01-09 22:24:49 +0100437# endif
Bram Moolenaarc9e649a2017-12-18 18:14:47 +0100438
Bram Moolenaarc46af532019-01-09 22:24:49 +0100439 // When waiting very briefly don't trigger timers.
Bram Moolenaarc9e649a2017-12-18 18:14:47 +0100440 if (wtime >= 0 && wtime < 10L)
441 return wait_func(wtime, NULL, ignore_input);
442
443 while (wtime < 0 || remaining > 0)
444 {
Bram Moolenaarc46af532019-01-09 22:24:49 +0100445 // Trigger timers and then get the time in wtime until the next one is
446 // due. Wait up to that time.
Bram Moolenaarc9e649a2017-12-18 18:14:47 +0100447 due_time = check_due_timer();
448 if (typebuf.tb_change_cnt != tb_change_cnt)
449 {
Bram Moolenaare38eab22019-12-05 21:50:01 +0100450 // timer may have used feedkeys()
Bram Moolenaarc9e649a2017-12-18 18:14:47 +0100451 return FAIL;
452 }
453 if (due_time <= 0 || (wtime > 0 && due_time > remaining))
454 due_time = remaining;
Bram Moolenaar28e67e02019-08-15 23:05:49 +0200455# if defined(FEAT_JOB_CHANNEL) || defined(FEAT_SOUND_CANBERRA)
456 if ((due_time < 0 || due_time > 10L) && (
457# if defined(FEAT_JOB_CHANNEL)
458 (
459# if defined(FEAT_GUI)
460 !gui.in_use &&
461# endif
462 (has_pending_job() || channel_any_readahead()))
463# ifdef FEAT_SOUND_CANBERRA
464 ||
465# endif
Bram Moolenaarc46af532019-01-09 22:24:49 +0100466# endif
Bram Moolenaar28e67e02019-08-15 23:05:49 +0200467# ifdef FEAT_SOUND_CANBERRA
468 has_any_sound_callback()
469# endif
470 ))
Bram Moolenaarc46af532019-01-09 22:24:49 +0100471 {
472 // There is a pending job or channel, should return soon in order
473 // to handle them ASAP. Do check for input briefly.
474 due_time = 10L;
Bram Moolenaar6cdce2a2019-09-07 23:25:09 +0200475# ifdef FEAT_JOB_CHANNEL
Bram Moolenaarc46af532019-01-09 22:24:49 +0100476 brief_wait = TRUE;
Bram Moolenaar6cdce2a2019-09-07 23:25:09 +0200477# endif
Bram Moolenaarc46af532019-01-09 22:24:49 +0100478 }
479# endif
Bram Moolenaarc9e649a2017-12-18 18:14:47 +0100480 if (wait_func(due_time, interrupted, ignore_input))
481 return OK;
Bram Moolenaarc46af532019-01-09 22:24:49 +0100482 if ((interrupted != NULL && *interrupted)
483# ifdef FEAT_JOB_CHANNEL
484 || brief_wait
485# endif
486 )
487 // Nothing available, but need to return so that side effects get
488 // handled, such as handling a message on a channel.
Bram Moolenaara338adc2018-01-31 20:51:47 +0100489 return FAIL;
Bram Moolenaarc9e649a2017-12-18 18:14:47 +0100490 if (wtime > 0)
491 remaining -= due_time;
492 }
493 return FAIL;
494}
495#endif
496
Bram Moolenaar071d4272004-06-13 20:20:40 +0000497/*
Bram Moolenaarc46af532019-01-09 22:24:49 +0100498 * Return non-zero if a character is available.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000499 */
500 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100501ui_char_avail(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000502{
503#ifdef FEAT_GUI
504 if (gui.in_use)
505 {
506 gui_mch_update();
507 return input_available();
508 }
509#endif
510#ifndef NO_CONSOLE
511# ifdef NO_CONSOLE_INPUT
512 if (no_console_input())
513 return 0;
514# endif
515 return mch_char_avail();
516#else
517 return 0;
518#endif
519}
520
521/*
522 * Delay for the given number of milliseconds. If ignoreinput is FALSE then we
523 * cancel the delay if a key is hit.
524 */
525 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100526ui_delay(long msec, int ignoreinput)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000527{
Bram Moolenaareda1da02019-11-17 17:06:33 +0100528#ifdef FEAT_JOB_CHANNEL
529 ch_log(NULL, "ui_delay(%ld)", msec);
530#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000531#ifdef FEAT_GUI
532 if (gui.in_use && !ignoreinput)
Bram Moolenaarc9e649a2017-12-18 18:14:47 +0100533 gui_wait_for_chars(msec, typebuf.tb_change_cnt);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000534 else
535#endif
536 mch_delay(msec, ignoreinput);
537}
538
539/*
540 * If the machine has job control, use it to suspend the program,
541 * otherwise fake it by starting a new shell.
542 * When running the GUI iconify the window.
543 */
544 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100545ui_suspend(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000546{
547#ifdef FEAT_GUI
548 if (gui.in_use)
549 {
550 gui_mch_iconify();
551 return;
552 }
553#endif
554 mch_suspend();
555}
556
Bram Moolenaar041c7102020-05-30 18:14:57 +0200557#if !defined(UNIX) || !defined(SIGTSTP) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000558/*
559 * When the OS can't really suspend, call this function to start a shell.
560 * This is never called in the GUI.
561 */
562 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100563suspend_shell(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000564{
565 if (*p_sh == NUL)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +0100566 emsg(_(e_shellempty));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000567 else
568 {
Bram Moolenaar32526b32019-01-19 17:43:09 +0100569 msg_puts(_("new shell started\n"));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000570 do_shell(NULL, 0);
571 }
572}
573#endif
574
575/*
576 * Try to get the current Vim shell size. Put the result in Rows and Columns.
577 * Use the new sizes as defaults for 'columns' and 'lines'.
578 * Return OK when size could be determined, FAIL otherwise.
579 */
580 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100581ui_get_shellsize(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000582{
583 int retval;
584
585#ifdef FEAT_GUI
586 if (gui.in_use)
587 retval = gui_get_shellsize();
588 else
589#endif
590 retval = mch_get_shellsize();
591
592 check_shellsize();
593
Bram Moolenaare38eab22019-12-05 21:50:01 +0100594 // adjust the default for 'lines' and 'columns'
Bram Moolenaar071d4272004-06-13 20:20:40 +0000595 if (retval == OK)
596 {
597 set_number_default("lines", Rows);
598 set_number_default("columns", Columns);
599 }
600 return retval;
601}
602
603/*
604 * Set the size of the Vim shell according to Rows and Columns, if possible.
605 * The gui_set_shellsize() or mch_set_shellsize() function will try to set the
606 * new size. If this is not possible, it will adjust Rows and Columns.
607 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000608 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100609ui_set_shellsize(
Bram Moolenaare38eab22019-12-05 21:50:01 +0100610 int mustset UNUSED) // set by the user
Bram Moolenaar071d4272004-06-13 20:20:40 +0000611{
612#ifdef FEAT_GUI
613 if (gui.in_use)
Bram Moolenaar8968a312013-07-03 16:58:44 +0200614 gui_set_shellsize(mustset, TRUE, RESIZE_BOTH);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000615 else
616#endif
617 mch_set_shellsize();
618}
619
620/*
621 * Called when Rows and/or Columns changed. Adjust scroll region and mouse
622 * region.
623 */
624 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100625ui_new_shellsize(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000626{
627 if (full_screen && !exiting)
628 {
629#ifdef FEAT_GUI
630 if (gui.in_use)
631 gui_new_shellsize();
632 else
633#endif
634 mch_new_shellsize();
635 }
636}
637
Bram Moolenaar6bc93052019-04-06 20:00:19 +0200638#if ((defined(FEAT_EVAL) || defined(FEAT_TERMINAL)) \
Bram Moolenaar3d3f2172019-04-06 17:56:05 +0200639 && (defined(FEAT_GUI) \
Bram Moolenaar16c34c32019-04-06 22:01:24 +0200640 || defined(MSWIN) \
Bram Moolenaar3d3f2172019-04-06 17:56:05 +0200641 || (defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)))) \
Bram Moolenaarfa1e90c2019-04-06 17:47:40 +0200642 || defined(PROTO)
643/*
644 * Get the window position in pixels, if possible.
645 * Return FAIL when not possible.
646 */
647 int
Bram Moolenaarbd67aac2019-09-21 23:09:04 +0200648ui_get_winpos(int *x, int *y, varnumber_T timeout UNUSED)
Bram Moolenaarfa1e90c2019-04-06 17:47:40 +0200649{
650# ifdef FEAT_GUI
651 if (gui.in_use)
652 return gui_mch_get_winpos(x, y);
653# endif
Bram Moolenaarafde13b2019-04-28 19:46:49 +0200654# if defined(MSWIN) && (!defined(FEAT_GUI) || defined(VIMDLL))
Bram Moolenaar16c34c32019-04-06 22:01:24 +0200655 return mch_get_winpos(x, y);
Bram Moolenaar6bc93052019-04-06 20:00:19 +0200656# else
Bram Moolenaar16c34c32019-04-06 22:01:24 +0200657# if defined(HAVE_TGETENT) && defined(FEAT_TERMRESPONSE)
658 return term_get_winpos(x, y, timeout);
659# else
Bram Moolenaar6bc93052019-04-06 20:00:19 +0200660 return FAIL;
Bram Moolenaar16c34c32019-04-06 22:01:24 +0200661# endif
Bram Moolenaarfa1e90c2019-04-06 17:47:40 +0200662# endif
663}
664#endif
665
Bram Moolenaar071d4272004-06-13 20:20:40 +0000666 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100667ui_breakcheck(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000668{
Bram Moolenaarb9c31e72016-09-29 15:18:57 +0200669 ui_breakcheck_force(FALSE);
670}
671
672/*
673 * When "force" is true also check when the terminal is not in raw mode.
674 * This is useful to read input on channels.
675 */
676 void
677ui_breakcheck_force(int force)
678{
Bram Moolenaar48d23bb2018-11-20 02:42:43 +0100679 static int recursive = FALSE;
680 int save_updating_screen = updating_screen;
Bram Moolenaare3caa112017-01-31 22:07:42 +0100681
Bram Moolenaar48d23bb2018-11-20 02:42:43 +0100682 // We could be called recursively if stderr is redirected, calling
683 // fill_input_buf() calls settmode() when stdin isn't a tty. settmode()
684 // calls vgetorpeek() which calls ui_breakcheck() again.
685 if (recursive)
686 return;
687 recursive = TRUE;
688
689 // We do not want gui_resize_shell() to redraw the screen here.
Bram Moolenaare3caa112017-01-31 22:07:42 +0100690 ++updating_screen;
691
Bram Moolenaar071d4272004-06-13 20:20:40 +0000692#ifdef FEAT_GUI
693 if (gui.in_use)
694 gui_mch_update();
695 else
696#endif
Bram Moolenaarb9c31e72016-09-29 15:18:57 +0200697 mch_breakcheck(force);
Bram Moolenaare3caa112017-01-31 22:07:42 +0100698
Bram Moolenaar42335f52018-09-13 15:33:43 +0200699 if (save_updating_screen)
700 updating_screen = TRUE;
Bram Moolenaar0cb8ac72018-05-11 22:01:51 +0200701 else
Bram Moolenaar68a4b042019-05-29 22:28:29 +0200702 after_updating_screen(FALSE);
Bram Moolenaar48d23bb2018-11-20 02:42:43 +0100703
704 recursive = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000705}
706
Bram Moolenaare38eab22019-12-05 21:50:01 +0100707//////////////////////////////////////////////////////////////////////////////
Bram Moolenaare38eab22019-12-05 21:50:01 +0100708// Functions that handle the input buffer.
709// This is used for any GUI version, and the unix terminal version.
710//
711// For Unix, the input characters are buffered to be able to check for a
712// CTRL-C. This should be done with signals, but I don't know how to do that
713// in a portable way for a tty in RAW mode.
714//
715// For the client-server code in the console the received keys are put in the
716// input buffer.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000717
718#if defined(USE_INPUT_BUF) || defined(PROTO)
719
720/*
721 * Internal typeahead buffer. Includes extra space for long key code
722 * descriptions which would otherwise overflow. The buffer is considered full
723 * when only this extra space (or part of it) remains.
724 */
Bram Moolenaarbb1969b2019-01-17 15:45:25 +0100725#if defined(FEAT_JOB_CHANNEL) || defined(FEAT_CLIENTSERVER)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000726 /*
Bram Moolenaarbb1969b2019-01-17 15:45:25 +0100727 * NetBeans stuffs debugger commands into the input buffer.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000728 * This requires a larger buffer...
729 * (Madsen) Go with this for remote input as well ...
730 */
731# define INBUFLEN 4096
732#else
733# define INBUFLEN 250
734#endif
735
736static char_u inbuf[INBUFLEN + MAX_KEY_CODE_LEN];
Bram Moolenaare38eab22019-12-05 21:50:01 +0100737static int inbufcount = 0; // number of chars in inbuf[]
Bram Moolenaar071d4272004-06-13 20:20:40 +0000738
739/*
740 * vim_is_input_buf_full(), vim_is_input_buf_empty(), add_to_input_buf(), and
741 * trash_input_buf() are functions for manipulating the input buffer. These
742 * are used by the gui_* calls when a GUI is used to handle keyboard input.
743 */
744
745 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100746vim_is_input_buf_full(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000747{
748 return (inbufcount >= INBUFLEN);
749}
750
751 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100752vim_is_input_buf_empty(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000753{
754 return (inbufcount == 0);
755}
756
757#if defined(FEAT_OLE) || defined(PROTO)
758 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100759vim_free_in_input_buf(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000760{
761 return (INBUFLEN - inbufcount);
762}
763#endif
764
Bram Moolenaar241a8aa2005-12-06 20:04:44 +0000765#if defined(FEAT_GUI_GTK) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000766 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100767vim_used_in_input_buf(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000768{
769 return inbufcount;
770}
771#endif
772
Bram Moolenaar071d4272004-06-13 20:20:40 +0000773/*
774 * Return the current contents of the input buffer and make it empty.
775 * The returned pointer must be passed to set_input_buf() later.
776 */
777 char_u *
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100778get_input_buf(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000779{
780 garray_T *gap;
781
Bram Moolenaare38eab22019-12-05 21:50:01 +0100782 // We use a growarray to store the data pointer and the length.
Bram Moolenaarc799fe22019-05-28 23:08:19 +0200783 gap = ALLOC_ONE(garray_T);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000784 if (gap != NULL)
785 {
Bram Moolenaare38eab22019-12-05 21:50:01 +0100786 // Add one to avoid a zero size.
Bram Moolenaar18a4ba22019-05-24 19:39:03 +0200787 gap->ga_data = alloc(inbufcount + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000788 if (gap->ga_data != NULL)
789 mch_memmove(gap->ga_data, inbuf, (size_t)inbufcount);
790 gap->ga_len = inbufcount;
791 }
792 trash_input_buf();
793 return (char_u *)gap;
794}
795
796/*
797 * Restore the input buffer with a pointer returned from get_input_buf().
798 * The allocated memory is freed, this only works once!
799 */
800 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100801set_input_buf(char_u *p)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000802{
803 garray_T *gap = (garray_T *)p;
804
805 if (gap != NULL)
806 {
807 if (gap->ga_data != NULL)
808 {
809 mch_memmove(inbuf, gap->ga_data, gap->ga_len);
810 inbufcount = gap->ga_len;
811 vim_free(gap->ga_data);
812 }
813 vim_free(gap);
814 }
815}
Bram Moolenaar071d4272004-06-13 20:20:40 +0000816
Bram Moolenaar071d4272004-06-13 20:20:40 +0000817/*
818 * Add the given bytes to the input buffer
819 * Special keys start with CSI. A real CSI must have been translated to
820 * CSI KS_EXTRA KE_CSI. K_SPECIAL doesn't require translation.
821 */
822 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100823add_to_input_buf(char_u *s, int len)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000824{
825 if (inbufcount + len > INBUFLEN + MAX_KEY_CODE_LEN)
Bram Moolenaare38eab22019-12-05 21:50:01 +0100826 return; // Shouldn't ever happen!
Bram Moolenaar071d4272004-06-13 20:20:40 +0000827
Bram Moolenaar071d4272004-06-13 20:20:40 +0000828 while (len--)
829 inbuf[inbufcount++] = *s++;
830}
Bram Moolenaar071d4272004-06-13 20:20:40 +0000831
Bram Moolenaar071d4272004-06-13 20:20:40 +0000832/*
833 * Add "str[len]" to the input buffer while escaping CSI bytes.
834 */
835 void
836add_to_input_buf_csi(char_u *str, int len)
837{
838 int i;
839 char_u buf[2];
840
841 for (i = 0; i < len; ++i)
842 {
843 add_to_input_buf(str + i, 1);
844 if (str[i] == CSI)
845 {
Bram Moolenaare38eab22019-12-05 21:50:01 +0100846 // Turn CSI into K_CSI.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000847 buf[0] = KS_EXTRA;
848 buf[1] = (int)KE_CSI;
849 add_to_input_buf(buf, 2);
850 }
851 }
852}
Bram Moolenaar071d4272004-06-13 20:20:40 +0000853
Bram Moolenaare38eab22019-12-05 21:50:01 +0100854/*
855 * Remove everything from the input buffer. Called when ^C is found.
856 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000857 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100858trash_input_buf(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000859{
860 inbufcount = 0;
861}
Bram Moolenaar071d4272004-06-13 20:20:40 +0000862
863/*
864 * Read as much data from the input buffer as possible up to maxlen, and store
865 * it in buf.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000866 */
867 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100868read_from_input_buf(char_u *buf, long maxlen)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000869{
Bram Moolenaare38eab22019-12-05 21:50:01 +0100870 if (inbufcount == 0) // if the buffer is empty, fill it
Bram Moolenaar071d4272004-06-13 20:20:40 +0000871 fill_input_buf(TRUE);
872 if (maxlen > inbufcount)
873 maxlen = inbufcount;
874 mch_memmove(buf, inbuf, (size_t)maxlen);
875 inbufcount -= maxlen;
876 if (inbufcount)
877 mch_memmove(inbuf, inbuf + maxlen, (size_t)inbufcount);
878 return (int)maxlen;
879}
880
881 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100882fill_input_buf(int exit_on_error UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000883{
Bram Moolenaard0573012017-10-28 21:11:06 +0200884#if defined(UNIX) || defined(VMS) || defined(MACOS_X)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000885 int len;
886 int try;
887 static int did_read_something = FALSE;
Bram Moolenaare38eab22019-12-05 21:50:01 +0100888 static char_u *rest = NULL; // unconverted rest of previous read
Bram Moolenaar071d4272004-06-13 20:20:40 +0000889 static int restlen = 0;
890 int unconverted;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000891#endif
892
893#ifdef FEAT_GUI
Bram Moolenaar54ee7752005-05-31 22:22:17 +0000894 if (gui.in_use
895# ifdef NO_CONSOLE_INPUT
Bram Moolenaare38eab22019-12-05 21:50:01 +0100896 // Don't use the GUI input when the window hasn't been opened yet.
897 // We get here from ui_inchar() when we should try reading from stdin.
Bram Moolenaar54ee7752005-05-31 22:22:17 +0000898 && !no_console_input()
899# endif
900 )
Bram Moolenaar071d4272004-06-13 20:20:40 +0000901 {
902 gui_mch_update();
903 return;
904 }
905#endif
Bram Moolenaard0573012017-10-28 21:11:06 +0200906#if defined(UNIX) || defined(VMS) || defined(MACOS_X)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000907 if (vim_is_input_buf_full())
908 return;
909 /*
910 * Fill_input_buf() is only called when we really need a character.
911 * If we can't get any, but there is some in the buffer, just return.
912 * If we can't get any, and there isn't any in the buffer, we give up and
913 * exit Vim.
914 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000915 if (rest != NULL)
916 {
Bram Moolenaare38eab22019-12-05 21:50:01 +0100917 // Use remainder of previous call, starts with an invalid character
918 // that may become valid when reading more.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000919 if (restlen > INBUFLEN - inbufcount)
920 unconverted = INBUFLEN - inbufcount;
921 else
922 unconverted = restlen;
923 mch_memmove(inbuf + inbufcount, rest, unconverted);
924 if (unconverted == restlen)
Bram Moolenaard23a8232018-02-10 18:45:26 +0100925 VIM_CLEAR(rest);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000926 else
927 {
928 restlen -= unconverted;
929 mch_memmove(rest, rest + unconverted, restlen);
930 }
931 inbufcount += unconverted;
932 }
933 else
934 unconverted = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000935
Bram Moolenaare38eab22019-12-05 21:50:01 +0100936 len = 0; // to avoid gcc warning
Bram Moolenaar071d4272004-06-13 20:20:40 +0000937 for (try = 0; try < 100; ++try)
938 {
Bram Moolenaar4e601e32018-04-24 13:29:51 +0200939 size_t readlen = (size_t)((INBUFLEN - inbufcount)
Bram Moolenaar9645e2d2020-03-20 20:48:49 +0100940 / input_conv.vc_factor);
Bram Moolenaar4e601e32018-04-24 13:29:51 +0200941# ifdef VMS
Bram Moolenaar49943732018-04-24 20:27:26 +0200942 len = vms_read((char *)inbuf + inbufcount, readlen);
Bram Moolenaar4e601e32018-04-24 13:29:51 +0200943# else
944 len = read(read_cmd_fd, (char *)inbuf + inbufcount, readlen);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000945# endif
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000946
Bram Moolenaar071d4272004-06-13 20:20:40 +0000947 if (len > 0 || got_int)
948 break;
949 /*
950 * If reading stdin results in an error, continue reading stderr.
951 * This helps when using "foo | xargs vim".
952 */
953 if (!did_read_something && !isatty(read_cmd_fd) && read_cmd_fd == 0)
954 {
955 int m = cur_tmode;
956
Bram Moolenaare38eab22019-12-05 21:50:01 +0100957 // We probably set the wrong file descriptor to raw mode. Switch
958 // back to cooked mode, use another descriptor and set the mode to
959 // what it was.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000960 settmode(TMODE_COOK);
961#ifdef HAVE_DUP
Bram Moolenaare38eab22019-12-05 21:50:01 +0100962 // Use stderr for stdin, also works for shell commands.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000963 close(0);
Bram Moolenaar42335f52018-09-13 15:33:43 +0200964 vim_ignored = dup(2);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000965#else
Bram Moolenaare38eab22019-12-05 21:50:01 +0100966 read_cmd_fd = 2; // read from stderr instead of stdin
Bram Moolenaar071d4272004-06-13 20:20:40 +0000967#endif
968 settmode(m);
969 }
970 if (!exit_on_error)
971 return;
972 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000973 if (len <= 0 && !got_int)
974 read_error_exit();
975 if (len > 0)
976 did_read_something = TRUE;
977 if (got_int)
978 {
Bram Moolenaare38eab22019-12-05 21:50:01 +0100979 // Interrupted, pretend a CTRL-C was typed.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000980 inbuf[0] = 3;
981 inbufcount = 1;
982 }
983 else
984 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000985 /*
986 * May perform conversion on the input characters.
987 * Include the unconverted rest of the previous call.
988 * If there is an incomplete char at the end it is kept for the next
989 * time, reading more bytes should make conversion possible.
990 * Don't do this in the unlikely event that the input buffer is too
991 * small ("rest" still contains more bytes).
992 */
993 if (input_conv.vc_type != CONV_NONE)
994 {
995 inbufcount -= unconverted;
996 len = convert_input_safe(inbuf + inbufcount,
997 len + unconverted, INBUFLEN - inbufcount,
998 rest == NULL ? &rest : NULL, &restlen);
999 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001000 while (len-- > 0)
1001 {
1002 /*
Bram Moolenaar9645e2d2020-03-20 20:48:49 +01001003 * If a CTRL-C was typed, remove it from the buffer and set
1004 * got_int. Also recognize CTRL-C with modifyOtherKeys set.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001005 */
Bram Moolenaar9645e2d2020-03-20 20:48:49 +01001006 if (ctrl_c_interrupts && (inbuf[inbufcount] == 3
1007 || (len >= 9 && STRNCMP(inbuf + inbufcount,
Bram Moolenaar56ba21a2020-03-23 19:17:29 +01001008 "\033[27;5;99~", 10) == 0)))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001009 {
Bram Moolenaare38eab22019-12-05 21:50:01 +01001010 // remove everything typed before the CTRL-C
Bram Moolenaar071d4272004-06-13 20:20:40 +00001011 mch_memmove(inbuf, inbuf + inbufcount, (size_t)(len + 1));
1012 inbufcount = 0;
1013 got_int = TRUE;
1014 }
1015 ++inbufcount;
1016 }
1017 }
Bram Moolenaar74ee5e22019-12-13 18:13:22 +01001018#endif // UNIX || VMS || MACOS_X
Bram Moolenaar071d4272004-06-13 20:20:40 +00001019}
Bram Moolenaar74ee5e22019-12-13 18:13:22 +01001020#endif // USE_INPUT_BUF
Bram Moolenaar071d4272004-06-13 20:20:40 +00001021
1022/*
1023 * Exit because of an input read error.
1024 */
1025 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +01001026read_error_exit(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001027{
Bram Moolenaare38eab22019-12-05 21:50:01 +01001028 if (silent_mode) // Normal way to exit for "ex -s"
Bram Moolenaar071d4272004-06-13 20:20:40 +00001029 getout(0);
1030 STRCPY(IObuff, _("Vim: Error reading input, exiting...\n"));
1031 preserve_exit();
1032}
1033
1034#if defined(CURSOR_SHAPE) || defined(PROTO)
1035/*
1036 * May update the shape of the cursor.
1037 */
1038 void
Bram Moolenaar3cd43cc2017-08-12 19:51:41 +02001039ui_cursor_shape_forced(int forced)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001040{
1041# ifdef FEAT_GUI
1042 if (gui.in_use)
1043 gui_update_cursor_later();
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00001044 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00001045# endif
Bram Moolenaar3cd43cc2017-08-12 19:51:41 +02001046 term_cursor_mode(forced);
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00001047
Bram Moolenaar071d4272004-06-13 20:20:40 +00001048# ifdef MCH_CURSOR_SHAPE
1049 mch_update_cursor();
1050# endif
Bram Moolenaarf5963f72010-07-23 22:10:27 +02001051
1052# ifdef FEAT_CONCEAL
Bram Moolenaarb9464822018-05-10 15:09:49 +02001053 conceal_check_cursor_line();
Bram Moolenaarf5963f72010-07-23 22:10:27 +02001054# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001055}
Bram Moolenaar3cd43cc2017-08-12 19:51:41 +02001056
1057 void
1058ui_cursor_shape(void)
1059{
1060 ui_cursor_shape_forced(FALSE);
1061}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001062#endif
1063
Bram Moolenaar071d4272004-06-13 20:20:40 +00001064/*
1065 * Check bounds for column number
1066 */
1067 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +01001068check_col(int col)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001069{
1070 if (col < 0)
1071 return 0;
1072 if (col >= (int)screen_Columns)
1073 return (int)screen_Columns - 1;
1074 return col;
1075}
1076
1077/*
1078 * Check bounds for row number
1079 */
1080 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +01001081check_row(int row)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001082{
1083 if (row < 0)
1084 return 0;
1085 if (row >= (int)screen_Rows)
1086 return (int)screen_Rows - 1;
1087 return row;
1088}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001089
Bram Moolenaar4f974752019-02-17 17:44:42 +01001090#if defined(FEAT_GUI) || defined(MSWIN) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001091/*
1092 * Called when focus changed. Used for the GUI or for systems where this can
1093 * be done in the console (Win32).
1094 */
1095 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +01001096ui_focus_change(
Bram Moolenaare38eab22019-12-05 21:50:01 +01001097 int in_focus) // TRUE if focus gained.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001098{
1099 static time_t last_time = (time_t)0;
1100 int need_redraw = FALSE;
1101
Bram Moolenaare38eab22019-12-05 21:50:01 +01001102 // When activated: Check if any file was modified outside of Vim.
1103 // Only do this when not done within the last two seconds (could get
1104 // several events in a row).
Bram Moolenaar071d4272004-06-13 20:20:40 +00001105 if (in_focus && last_time + 2 < time(NULL))
1106 {
1107 need_redraw = check_timestamps(
1108# ifdef FEAT_GUI
1109 gui.in_use
1110# else
1111 FALSE
1112# endif
1113 );
1114 last_time = time(NULL);
1115 }
1116
Bram Moolenaar071d4272004-06-13 20:20:40 +00001117 /*
1118 * Fire the focus gained/lost autocommand.
1119 */
1120 need_redraw |= apply_autocmds(in_focus ? EVENT_FOCUSGAINED
1121 : EVENT_FOCUSLOST, NULL, NULL, FALSE, curbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001122
1123 if (need_redraw)
1124 {
Bram Moolenaare38eab22019-12-05 21:50:01 +01001125 // Something was executed, make sure the cursor is put back where it
1126 // belongs.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001127 need_wait_return = FALSE;
1128
1129 if (State & CMDLINE)
1130 redrawcmdline();
1131 else if (State == HITRETURN || State == SETWSIZE || State == ASKMORE
1132 || State == EXTERNCMD || State == CONFIRM || exmode_active)
1133 repeat_message();
1134 else if ((State & NORMAL) || (State & INSERT))
1135 {
1136 if (must_redraw != 0)
1137 update_screen(0);
1138 setcursor();
1139 }
Bram Moolenaare38eab22019-12-05 21:50:01 +01001140 cursor_on(); // redrawing may have switched it off
Bram Moolenaara338adc2018-01-31 20:51:47 +01001141 out_flush_cursor(FALSE, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001142# ifdef FEAT_GUI
1143 if (gui.in_use)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001144 gui_update_scrollbars(FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001145# endif
1146 }
1147#ifdef FEAT_TITLE
Bram Moolenaare38eab22019-12-05 21:50:01 +01001148 // File may have been changed from 'readonly' to 'noreadonly'
Bram Moolenaar071d4272004-06-13 20:20:40 +00001149 if (need_maketitle)
1150 maketitle();
1151#endif
1152}
1153#endif
1154
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01001155#if defined(HAVE_INPUT_METHOD) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001156/*
1157 * Save current Input Method status to specified place.
1158 */
1159 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +01001160im_save_status(long *psave)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001161{
Bram Moolenaare38eab22019-12-05 21:50:01 +01001162 // Don't save when 'imdisable' is set or "xic" is NULL, IM is always
1163 // disabled then (but might start later).
1164 // Also don't save when inside a mapping, vgetc_im_active has not been set
1165 // then.
1166 // And don't save when the keys were stuffed (e.g., for a "." command).
1167 // And don't save when the GUI is running but our window doesn't have
1168 // input focus (e.g., when a find dialog is open).
Bram Moolenaar071d4272004-06-13 20:20:40 +00001169 if (!p_imdisable && KeyTyped && !KeyStuffed
1170# ifdef FEAT_XIM
1171 && xic != NULL
1172# endif
1173# ifdef FEAT_GUI
1174 && (!gui.in_use || gui.in_focus)
1175# endif
1176 )
1177 {
Bram Moolenaare38eab22019-12-05 21:50:01 +01001178 // Do save when IM is on, or IM is off and saved status is on.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001179 if (vgetc_im_active)
1180 *psave = B_IMODE_IM;
1181 else if (*psave == B_IMODE_IM)
1182 *psave = B_IMODE_NONE;
1183 }
1184}
1185#endif