blob: ea9125280d2dec710021f2d9d5fe572cf411e679 [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);
Yegappan Lakshmanan142ed772023-01-26 12:00:00 +000086 if (new == NULL)
87 return;
88
89 if (ta_str != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000090 {
Yegappan Lakshmanan142ed772023-01-26 12:00:00 +000091 mch_memmove(new, ta_str + ta_off, (size_t)(ta_len - ta_off));
92 mch_memmove(new + ta_len - ta_off, s, (size_t)len);
93 vim_free(ta_str);
Bram Moolenaar071d4272004-06-13 20:20:40 +000094 }
Yegappan Lakshmanan142ed772023-01-26 12:00:00 +000095 else
96 mch_memmove(new, s, (size_t)len);
97 ta_str = new;
98 ta_len = newlen;
99 ta_off = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000100}
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)
Bram Moolenaar6ed545e2022-05-09 20:09:23 +0100202 * invoke-timer-callback;
Bram Moolenaare40b9d42019-01-27 16:55:47 +0100203 * wait-for-character();
204 * if (character available)
Bram Moolenaar6ed545e2022-05-09 20:09:23 +0100205 * break;
Bram Moolenaare40b9d42019-01-27 16:55:47 +0100206 * }
207 *
208 * wait-for-character() does:
209 * while (not timed out)
210 * {
211 * Wait for event;
212 * if (something on channel)
Bram Moolenaar6ed545e2022-05-09 20:09:23 +0100213 * 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;
Bram Moolenaare40b9d42019-01-27 16:55:47 +0100220 * }
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;
Yee Cheng Chin4314e4f2022-10-08 13:50:05 +0100463# if defined(FEAT_JOB_CHANNEL) || defined(FEAT_SOUND_CANBERRA) || defined(FEAT_SOUND_MACOSX)
Bram Moolenaar28e67e02019-08-15 23:05:49 +0200464 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()))
Yee Cheng Chin4314e4f2022-10-08 13:50:05 +0100471# if defined(FEAT_SOUND_CANBERRA) || defined(FEAT_SOUND_MACOSX)
Bram Moolenaar28e67e02019-08-15 23:05:49 +0200472 ||
473# endif
Bram Moolenaarc46af532019-01-09 22:24:49 +0100474# endif
Yee Cheng Chin4314e4f2022-10-08 13:50:05 +0100475# if defined(FEAT_SOUND_CANBERRA) || defined(FEAT_SOUND_MACOSX)
Bram Moolenaar28e67e02019-08-15 23:05:49 +0200476 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;
Bram Moolenaareda1da02019-11-17 17:06:33 +0100541 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 Moolenaare1242042021-12-16 20:56:57 +0000578 emsg(_(e_shell_option_is_empty));
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!
Bram Moolenaarc41badb2021-06-07 22:04:52 +0200811 * When "overwrite" is FALSE input typed later is kept.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000812 */
813 void
Bram Moolenaarc41badb2021-06-07 22:04:52 +0200814set_input_buf(char_u *p, int overwrite)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000815{
816 garray_T *gap = (garray_T *)p;
817
Yegappan Lakshmanan142ed772023-01-26 12:00:00 +0000818 if (gap == NULL)
819 return;
820
821 if (gap->ga_data != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000822 {
Yegappan Lakshmanan142ed772023-01-26 12:00:00 +0000823 if (overwrite || inbufcount + gap->ga_len >= INBUFLEN)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000824 {
Yegappan Lakshmanan142ed772023-01-26 12:00:00 +0000825 mch_memmove(inbuf, gap->ga_data, gap->ga_len);
826 inbufcount = gap->ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000827 }
Yegappan Lakshmanan142ed772023-01-26 12:00:00 +0000828 else
829 {
830 mch_memmove(inbuf + gap->ga_len, inbuf, inbufcount);
831 mch_memmove(inbuf, gap->ga_data, gap->ga_len);
832 inbufcount += gap->ga_len;
833 }
834 vim_free(gap->ga_data);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000835 }
Yegappan Lakshmanan142ed772023-01-26 12:00:00 +0000836 vim_free(gap);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000837}
Bram Moolenaar071d4272004-06-13 20:20:40 +0000838
Bram Moolenaar071d4272004-06-13 20:20:40 +0000839/*
840 * Add the given bytes to the input buffer
841 * Special keys start with CSI. A real CSI must have been translated to
842 * CSI KS_EXTRA KE_CSI. K_SPECIAL doesn't require translation.
843 */
844 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100845add_to_input_buf(char_u *s, int len)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000846{
847 if (inbufcount + len > INBUFLEN + MAX_KEY_CODE_LEN)
Bram Moolenaare38eab22019-12-05 21:50:01 +0100848 return; // Shouldn't ever happen!
Bram Moolenaar071d4272004-06-13 20:20:40 +0000849
Bram Moolenaar071d4272004-06-13 20:20:40 +0000850 while (len--)
851 inbuf[inbufcount++] = *s++;
852}
Bram Moolenaar071d4272004-06-13 20:20:40 +0000853
Bram Moolenaar071d4272004-06-13 20:20:40 +0000854/*
855 * Add "str[len]" to the input buffer while escaping CSI bytes.
856 */
857 void
858add_to_input_buf_csi(char_u *str, int len)
859{
860 int i;
861 char_u buf[2];
862
863 for (i = 0; i < len; ++i)
864 {
865 add_to_input_buf(str + i, 1);
866 if (str[i] == CSI)
867 {
Bram Moolenaare38eab22019-12-05 21:50:01 +0100868 // Turn CSI into K_CSI.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000869 buf[0] = KS_EXTRA;
870 buf[1] = (int)KE_CSI;
871 add_to_input_buf(buf, 2);
872 }
873 }
874}
Bram Moolenaar071d4272004-06-13 20:20:40 +0000875
Bram Moolenaare38eab22019-12-05 21:50:01 +0100876/*
877 * Remove everything from the input buffer. Called when ^C is found.
878 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000879 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100880trash_input_buf(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000881{
882 inbufcount = 0;
883}
Bram Moolenaar071d4272004-06-13 20:20:40 +0000884
885/*
886 * Read as much data from the input buffer as possible up to maxlen, and store
887 * it in buf.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000888 */
889 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100890read_from_input_buf(char_u *buf, long maxlen)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000891{
Bram Moolenaare38eab22019-12-05 21:50:01 +0100892 if (inbufcount == 0) // if the buffer is empty, fill it
Bram Moolenaar071d4272004-06-13 20:20:40 +0000893 fill_input_buf(TRUE);
894 if (maxlen > inbufcount)
895 maxlen = inbufcount;
896 mch_memmove(buf, inbuf, (size_t)maxlen);
897 inbufcount -= maxlen;
Bram Moolenaarb74e0462022-06-10 14:52:35 +0100898 // check "maxlen" to avoid clang warning
899 if (inbufcount > 0 && maxlen > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000900 mch_memmove(inbuf, inbuf + maxlen, (size_t)inbufcount);
901 return (int)maxlen;
902}
903
904 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +0100905fill_input_buf(int exit_on_error UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000906{
Bram Moolenaard0573012017-10-28 21:11:06 +0200907#if defined(UNIX) || defined(VMS) || defined(MACOS_X)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000908 int len;
909 int try;
910 static int did_read_something = FALSE;
Bram Moolenaare38eab22019-12-05 21:50:01 +0100911 static char_u *rest = NULL; // unconverted rest of previous read
Bram Moolenaar071d4272004-06-13 20:20:40 +0000912 static int restlen = 0;
913 int unconverted;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000914#endif
915
916#ifdef FEAT_GUI
Bram Moolenaar54ee7752005-05-31 22:22:17 +0000917 if (gui.in_use
918# ifdef NO_CONSOLE_INPUT
Bram Moolenaare38eab22019-12-05 21:50:01 +0100919 // Don't use the GUI input when the window hasn't been opened yet.
920 // We get here from ui_inchar() when we should try reading from stdin.
Bram Moolenaar54ee7752005-05-31 22:22:17 +0000921 && !no_console_input()
922# endif
923 )
Bram Moolenaar071d4272004-06-13 20:20:40 +0000924 {
925 gui_mch_update();
926 return;
927 }
928#endif
Bram Moolenaard0573012017-10-28 21:11:06 +0200929#if defined(UNIX) || defined(VMS) || defined(MACOS_X)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000930 if (vim_is_input_buf_full())
931 return;
932 /*
933 * Fill_input_buf() is only called when we really need a character.
934 * If we can't get any, but there is some in the buffer, just return.
935 * If we can't get any, and there isn't any in the buffer, we give up and
936 * exit Vim.
937 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000938 if (rest != NULL)
939 {
Bram Moolenaare38eab22019-12-05 21:50:01 +0100940 // Use remainder of previous call, starts with an invalid character
941 // that may become valid when reading more.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000942 if (restlen > INBUFLEN - inbufcount)
943 unconverted = INBUFLEN - inbufcount;
944 else
945 unconverted = restlen;
946 mch_memmove(inbuf + inbufcount, rest, unconverted);
947 if (unconverted == restlen)
Bram Moolenaard23a8232018-02-10 18:45:26 +0100948 VIM_CLEAR(rest);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000949 else
950 {
951 restlen -= unconverted;
952 mch_memmove(rest, rest + unconverted, restlen);
953 }
954 inbufcount += unconverted;
955 }
956 else
957 unconverted = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000958
Bram Moolenaare38eab22019-12-05 21:50:01 +0100959 len = 0; // to avoid gcc warning
Bram Moolenaar071d4272004-06-13 20:20:40 +0000960 for (try = 0; try < 100; ++try)
961 {
Bram Moolenaar4e601e32018-04-24 13:29:51 +0200962 size_t readlen = (size_t)((INBUFLEN - inbufcount)
Bram Moolenaar9645e2d2020-03-20 20:48:49 +0100963 / input_conv.vc_factor);
Bram Moolenaar4e601e32018-04-24 13:29:51 +0200964# ifdef VMS
Bram Moolenaar49943732018-04-24 20:27:26 +0200965 len = vms_read((char *)inbuf + inbufcount, readlen);
Bram Moolenaar4e601e32018-04-24 13:29:51 +0200966# else
967 len = read(read_cmd_fd, (char *)inbuf + inbufcount, readlen);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000968# endif
Bram Moolenaar4c5678f2022-11-30 18:12:19 +0000969# ifdef FEAT_EVAL
Bram Moolenaar7ca86fe2020-09-03 19:25:11 +0200970 if (len > 0)
971 {
972 inbuf[inbufcount + len] = NUL;
973 ch_log(NULL, "raw key input: \"%s\"", inbuf + inbufcount);
974 }
975# endif
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000976
Bram Moolenaar071d4272004-06-13 20:20:40 +0000977 if (len > 0 || got_int)
978 break;
979 /*
980 * If reading stdin results in an error, continue reading stderr.
981 * This helps when using "foo | xargs vim".
982 */
983 if (!did_read_something && !isatty(read_cmd_fd) && read_cmd_fd == 0)
984 {
985 int m = cur_tmode;
986
Bram Moolenaare38eab22019-12-05 21:50:01 +0100987 // We probably set the wrong file descriptor to raw mode. Switch
988 // back to cooked mode, use another descriptor and set the mode to
989 // what it was.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000990 settmode(TMODE_COOK);
991#ifdef HAVE_DUP
Bram Moolenaare38eab22019-12-05 21:50:01 +0100992 // Use stderr for stdin, also works for shell commands.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000993 close(0);
Bram Moolenaar42335f52018-09-13 15:33:43 +0200994 vim_ignored = dup(2);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000995#else
Bram Moolenaare38eab22019-12-05 21:50:01 +0100996 read_cmd_fd = 2; // read from stderr instead of stdin
Bram Moolenaar071d4272004-06-13 20:20:40 +0000997#endif
998 settmode(m);
999 }
1000 if (!exit_on_error)
1001 return;
1002 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001003 if (len <= 0 && !got_int)
1004 read_error_exit();
1005 if (len > 0)
1006 did_read_something = TRUE;
1007 if (got_int)
1008 {
Bram Moolenaare38eab22019-12-05 21:50:01 +01001009 // Interrupted, pretend a CTRL-C was typed.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001010 inbuf[0] = 3;
1011 inbufcount = 1;
1012 }
1013 else
1014 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001015 /*
1016 * May perform conversion on the input characters.
1017 * Include the unconverted rest of the previous call.
1018 * If there is an incomplete char at the end it is kept for the next
1019 * time, reading more bytes should make conversion possible.
1020 * Don't do this in the unlikely event that the input buffer is too
1021 * small ("rest" still contains more bytes).
1022 */
1023 if (input_conv.vc_type != CONV_NONE)
1024 {
1025 inbufcount -= unconverted;
1026 len = convert_input_safe(inbuf + inbufcount,
1027 len + unconverted, INBUFLEN - inbufcount,
1028 rest == NULL ? &rest : NULL, &restlen);
1029 }
Bram Moolenaar35cfd792021-12-25 15:13:18 +00001030 while (len > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001031 {
Bram Moolenaar339c1bd2021-01-02 20:14:23 +01001032 // If a CTRL-C was typed, remove it from the buffer and set
Bram Moolenaar35cfd792021-12-25 15:13:18 +00001033 // got_int. Also recognize CTRL-C with modifyOtherKeys set, lower
1034 // and upper case, in two forms.
David Leadbeater67ec6552023-10-26 22:00:34 +02001035 // If terminal key protocols are in use, we expect to receive
1036 // Ctrl_C as an escape sequence, ignore a raw Ctrl_C as this could
1037 // be paste data.
1038 if (ctrl_c_interrupts
1039 && ((inbuf[inbufcount] == Ctrl_C && !key_protocol_enabled())
Bram Moolenaar339c1bd2021-01-02 20:14:23 +01001040 || (len >= 10 && STRNCMP(inbuf + inbufcount,
Bram Moolenaar02faa942021-01-02 16:17:18 +01001041 "\033[27;5;99~", 10) == 0)
Bram Moolenaar35cfd792021-12-25 15:13:18 +00001042 || (len >= 10 && STRNCMP(inbuf + inbufcount,
1043 "\033[27;5;67~", 10) == 0)
Bram Moolenaar02faa942021-01-02 16:17:18 +01001044 || (len >= 7 && STRNCMP(inbuf + inbufcount,
Bram Moolenaar35cfd792021-12-25 15:13:18 +00001045 "\033[99;5u", 7) == 0)
1046 || (len >= 7 && STRNCMP(inbuf + inbufcount,
1047 "\033[67;5u", 7) == 0)))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001048 {
Bram Moolenaare38eab22019-12-05 21:50:01 +01001049 // remove everything typed before the CTRL-C
Bram Moolenaar35cfd792021-12-25 15:13:18 +00001050 mch_memmove(inbuf, inbuf + inbufcount, (size_t)(len));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001051 inbufcount = 0;
1052 got_int = TRUE;
1053 }
Bram Moolenaar35cfd792021-12-25 15:13:18 +00001054 --len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001055 ++inbufcount;
1056 }
1057 }
Bram Moolenaar74ee5e22019-12-13 18:13:22 +01001058#endif // UNIX || VMS || MACOS_X
Bram Moolenaar071d4272004-06-13 20:20:40 +00001059}
Bram Moolenaar74ee5e22019-12-13 18:13:22 +01001060#endif // USE_INPUT_BUF
Bram Moolenaar071d4272004-06-13 20:20:40 +00001061
1062/*
1063 * Exit because of an input read error.
1064 */
1065 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +01001066read_error_exit(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001067{
Bram Moolenaare38eab22019-12-05 21:50:01 +01001068 if (silent_mode) // Normal way to exit for "ex -s"
Bram Moolenaar071d4272004-06-13 20:20:40 +00001069 getout(0);
1070 STRCPY(IObuff, _("Vim: Error reading input, exiting...\n"));
1071 preserve_exit();
1072}
1073
1074#if defined(CURSOR_SHAPE) || defined(PROTO)
1075/*
1076 * May update the shape of the cursor.
1077 */
1078 void
Bram Moolenaar3cd43cc2017-08-12 19:51:41 +02001079ui_cursor_shape_forced(int forced)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001080{
1081# ifdef FEAT_GUI
1082 if (gui.in_use)
1083 gui_update_cursor_later();
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00001084 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00001085# endif
Bram Moolenaar3cd43cc2017-08-12 19:51:41 +02001086 term_cursor_mode(forced);
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00001087
Bram Moolenaar071d4272004-06-13 20:20:40 +00001088# ifdef MCH_CURSOR_SHAPE
1089 mch_update_cursor();
1090# endif
Bram Moolenaarf5963f72010-07-23 22:10:27 +02001091
1092# ifdef FEAT_CONCEAL
Bram Moolenaarea042672021-06-29 20:22:32 +02001093 conceal_check_cursor_line(FALSE);
Bram Moolenaarf5963f72010-07-23 22:10:27 +02001094# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001095}
Bram Moolenaar3cd43cc2017-08-12 19:51:41 +02001096
1097 void
1098ui_cursor_shape(void)
1099{
1100 ui_cursor_shape_forced(FALSE);
1101}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001102#endif
1103
Bram Moolenaar071d4272004-06-13 20:20:40 +00001104/*
1105 * Check bounds for column number
1106 */
1107 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +01001108check_col(int col)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001109{
1110 if (col < 0)
1111 return 0;
=?UTF-8?q?Dundar=20G=C3=B6c?=420fabc2022-01-28 15:28:04 +00001112 if (col >= screen_Columns)
1113 return screen_Columns - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001114 return col;
1115}
1116
1117/*
1118 * Check bounds for row number
1119 */
1120 int
Bram Moolenaar764b23c2016-01-30 21:10:09 +01001121check_row(int row)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001122{
1123 if (row < 0)
1124 return 0;
=?UTF-8?q?Dundar=20G=C3=B6c?=420fabc2022-01-28 15:28:04 +00001125 if (row >= screen_Rows)
1126 return screen_Rows - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001127 return row;
1128}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001129
Bram Moolenaar071d4272004-06-13 20:20:40 +00001130/*
Christopher Plewright44c22092022-11-15 17:43:36 +00001131 * Return length of line "lnum" in screen cells for horizontal scrolling.
1132 */
1133 long
1134scroll_line_len(linenr_T lnum)
1135{
1136 char_u *p = ml_get(lnum);
1137 colnr_T col = 0;
1138
1139 if (*p != NUL)
1140 for (;;)
1141 {
1142 int w = chartabsize(p, col);
1143 MB_PTR_ADV(p);
1144 if (*p == NUL) // don't count the last character
1145 break;
1146 col += w;
1147 }
1148 return col;
1149}
1150
1151/*
1152 * Find the longest visible line number. This is used for horizontal
1153 * scrolling. If this is not possible (or not desired, by setting 'h' in
1154 * "guioptions") then the current line number is returned.
1155 */
1156 linenr_T
1157ui_find_longest_lnum(void)
1158{
1159 linenr_T ret = 0;
1160
1161 // Calculate maximum for horizontal scrollbar. Check for reasonable
1162 // line numbers, topline and botline can be invalid when displaying is
1163 // postponed.
1164 if (
1165# ifdef FEAT_GUI
1166 (!gui.in_use || vim_strchr(p_go, GO_HORSCROLL) == NULL) &&
1167# endif
1168 curwin->w_topline <= curwin->w_cursor.lnum
1169 && curwin->w_botline > curwin->w_cursor.lnum
1170 && curwin->w_botline <= curbuf->b_ml.ml_line_count + 1)
1171 {
1172 linenr_T lnum;
1173 long n;
1174 long max = 0;
1175
1176 // Use maximum of all visible lines. Remember the lnum of the
1177 // longest line, closest to the cursor line. Used when scrolling
1178 // below.
1179 for (lnum = curwin->w_topline; lnum < curwin->w_botline; ++lnum)
1180 {
1181 n = scroll_line_len(lnum);
1182 if (n > max)
1183 {
1184 max = n;
1185 ret = lnum;
1186 }
1187 else if (n == max && abs((int)(lnum - curwin->w_cursor.lnum))
1188 < abs((int)(ret - curwin->w_cursor.lnum)))
1189 ret = lnum;
1190 }
1191 }
1192 else
1193 // Use cursor line only.
1194 ret = curwin->w_cursor.lnum;
1195
1196 return ret;
1197}
1198
1199/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00001200 * Called when focus changed. Used for the GUI or for systems where this can
1201 * be done in the console (Win32).
1202 */
1203 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +01001204ui_focus_change(
Bram Moolenaare38eab22019-12-05 21:50:01 +01001205 int in_focus) // TRUE if focus gained.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001206{
1207 static time_t last_time = (time_t)0;
1208 int need_redraw = FALSE;
1209
Bram Moolenaare38eab22019-12-05 21:50:01 +01001210 // When activated: Check if any file was modified outside of Vim.
1211 // Only do this when not done within the last two seconds (could get
1212 // several events in a row).
Bram Moolenaar071d4272004-06-13 20:20:40 +00001213 if (in_focus && last_time + 2 < time(NULL))
1214 {
1215 need_redraw = check_timestamps(
1216# ifdef FEAT_GUI
1217 gui.in_use
1218# else
1219 FALSE
1220# endif
1221 );
1222 last_time = time(NULL);
1223 }
1224
Bram Moolenaara48d4e42021-12-08 22:13:38 +00001225#ifdef FEAT_TERMINAL
1226 term_focus_change(in_focus);
1227#endif
1228
Bram Moolenaar071d4272004-06-13 20:20:40 +00001229 /*
1230 * Fire the focus gained/lost autocommand.
1231 */
1232 need_redraw |= apply_autocmds(in_focus ? EVENT_FOCUSGAINED
1233 : EVENT_FOCUSLOST, NULL, NULL, FALSE, curbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001234
1235 if (need_redraw)
Bram Moolenaare5050712021-12-09 10:51:05 +00001236 redraw_after_callback(TRUE, TRUE);
Bram Moolenaar651fca82021-11-29 20:39:38 +00001237
Bram Moolenaare38eab22019-12-05 21:50:01 +01001238 // File may have been changed from 'readonly' to 'noreadonly'
Bram Moolenaar071d4272004-06-13 20:20:40 +00001239 if (need_maketitle)
1240 maketitle();
Bram Moolenaar071d4272004-06-13 20:20:40 +00001241}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001242
Bram Moolenaarf2bd8ef2018-03-04 18:08:14 +01001243#if defined(HAVE_INPUT_METHOD) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001244/*
1245 * Save current Input Method status to specified place.
1246 */
1247 void
Bram Moolenaar764b23c2016-01-30 21:10:09 +01001248im_save_status(long *psave)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001249{
Bram Moolenaare38eab22019-12-05 21:50:01 +01001250 // Don't save when 'imdisable' is set or "xic" is NULL, IM is always
1251 // disabled then (but might start later).
1252 // Also don't save when inside a mapping, vgetc_im_active has not been set
1253 // then.
1254 // And don't save when the keys were stuffed (e.g., for a "." command).
1255 // And don't save when the GUI is running but our window doesn't have
1256 // input focus (e.g., when a find dialog is open).
Bram Moolenaar071d4272004-06-13 20:20:40 +00001257 if (!p_imdisable && KeyTyped && !KeyStuffed
1258# ifdef FEAT_XIM
1259 && xic != NULL
1260# endif
1261# ifdef FEAT_GUI
1262 && (!gui.in_use || gui.in_focus)
1263# endif
1264 )
1265 {
Bram Moolenaare38eab22019-12-05 21:50:01 +01001266 // Do save when IM is on, or IM is off and saved status is on.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001267 if (vgetc_im_active)
1268 *psave = B_IMODE_IM;
1269 else if (*psave == B_IMODE_IM)
1270 *psave = B_IMODE_NONE;
1271 }
1272}
1273#endif