mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
fix(tui): handle padding requirements for visual bell (#20238)
This commit is contained in:
parent
875b58e094
commit
a0e6e767a6
@ -31,41 +31,57 @@ void loop_init(Loop *loop, void *data)
|
|||||||
loop->poll_timer.data = xmalloc(sizeof(bool)); // "timeout expired" flag
|
loop->poll_timer.data = xmalloc(sizeof(bool)); // "timeout expired" flag
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Processes one `Loop.uv` event (at most).
|
/// Process `Loop.uv` events with a timeout.
|
||||||
/// Processes all `Loop.fast_events` events.
|
|
||||||
/// Does NOT process `Loop.events`, that is an application-specific decision.
|
|
||||||
///
|
///
|
||||||
/// @param loop
|
/// @param loop
|
||||||
/// @param ms 0: non-blocking poll.
|
/// @param ms 0: non-blocking poll.
|
||||||
/// >0: timeout after `ms`.
|
/// > 0: timeout after `ms`.
|
||||||
/// <0: wait forever.
|
/// < 0: wait forever.
|
||||||
/// @returns true if `ms` timeout was reached
|
/// @param once true: process at most one `Loop.uv` event.
|
||||||
bool loop_poll_events(Loop *loop, int ms)
|
/// false: process until `ms` timeout (only has effect if `ms` > 0).
|
||||||
|
/// @return true if `ms` > 0 and was reached
|
||||||
|
bool loop_uv_run(Loop *loop, int ms, bool once)
|
||||||
{
|
{
|
||||||
if (loop->recursive++) {
|
if (loop->recursive++) {
|
||||||
abort(); // Should not re-enter uv_run
|
abort(); // Should not re-enter uv_run
|
||||||
}
|
}
|
||||||
|
|
||||||
uv_run_mode mode = UV_RUN_ONCE;
|
uv_run_mode mode = UV_RUN_ONCE;
|
||||||
bool timeout_expired = false;
|
bool *timeout_expired = loop->poll_timer.data;
|
||||||
|
*timeout_expired = false;
|
||||||
|
|
||||||
if (ms > 0) {
|
if (ms > 0) {
|
||||||
*((bool *)loop->poll_timer.data) = false; // reset "timeout expired" flag
|
// This timer ensures UV_RUN_ONCE does not block indefinitely for I/O.
|
||||||
// Dummy timer to ensure UV_RUN_ONCE does not block indefinitely for I/O.
|
|
||||||
uv_timer_start(&loop->poll_timer, timer_cb, (uint64_t)ms, (uint64_t)ms);
|
uv_timer_start(&loop->poll_timer, timer_cb, (uint64_t)ms, (uint64_t)ms);
|
||||||
} else if (ms == 0) {
|
} else if (ms == 0) {
|
||||||
// For ms == 0, do a non-blocking event poll.
|
// For ms == 0, do a non-blocking event poll.
|
||||||
mode = UV_RUN_NOWAIT;
|
mode = UV_RUN_NOWAIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
uv_run(&loop->uv, mode);
|
do {
|
||||||
|
uv_run(&loop->uv, mode);
|
||||||
|
} while (ms > 0 && !once && !*timeout_expired);
|
||||||
|
|
||||||
if (ms > 0) {
|
if (ms > 0) {
|
||||||
timeout_expired = *((bool *)loop->poll_timer.data);
|
|
||||||
uv_timer_stop(&loop->poll_timer);
|
uv_timer_stop(&loop->poll_timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
loop->recursive--; // Can re-enter uv_run now
|
loop->recursive--; // Can re-enter uv_run now
|
||||||
|
return *timeout_expired;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Processes one `Loop.uv` event (at most).
|
||||||
|
/// Processes all `Loop.fast_events` events.
|
||||||
|
/// Does NOT process `Loop.events`, that is an application-specific decision.
|
||||||
|
///
|
||||||
|
/// @param loop
|
||||||
|
/// @param ms 0: non-blocking poll.
|
||||||
|
/// > 0: timeout after `ms`.
|
||||||
|
/// < 0: wait forever.
|
||||||
|
/// @return true if `ms` > 0 and was reached
|
||||||
|
bool loop_poll_events(Loop *loop, int ms)
|
||||||
|
{
|
||||||
|
bool timeout_expired = loop_uv_run(loop, ms, true);
|
||||||
multiqueue_process_events(loop->fast_events);
|
multiqueue_process_events(loop->fast_events);
|
||||||
return timeout_expired;
|
return timeout_expired;
|
||||||
}
|
}
|
||||||
|
@ -1616,7 +1616,7 @@ static void unibi_goto(UI *ui, int row, int col)
|
|||||||
memset(&vars, 0, sizeof(vars)); \
|
memset(&vars, 0, sizeof(vars)); \
|
||||||
data->cork = true; \
|
data->cork = true; \
|
||||||
retry: \
|
retry: \
|
||||||
unibi_format(vars, vars + 26, str, data->params, out, ui, NULL, NULL); \
|
unibi_format(vars, vars + 26, str, data->params, out, ui, pad, ui); \
|
||||||
if (data->overflow) { \
|
if (data->overflow) { \
|
||||||
data->bufpos = orig_pos; \
|
data->bufpos = orig_pos; \
|
||||||
flush_buf(ui); \
|
flush_buf(ui); \
|
||||||
@ -1647,6 +1647,7 @@ static void out(void *ctx, const char *str, size_t len)
|
|||||||
|
|
||||||
if (len > available) {
|
if (len > available) {
|
||||||
if (data->cork) {
|
if (data->cork) {
|
||||||
|
// Called by unibi_format(): avoid flush_buf() halfway an escape sequence.
|
||||||
data->overflow = true;
|
data->overflow = true;
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
@ -1658,6 +1659,30 @@ static void out(void *ctx, const char *str, size_t len)
|
|||||||
data->bufpos += len;
|
data->bufpos += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Called by unibi_format() for padding instructions.
|
||||||
|
/// The following parameter descriptions are extracted from unibi_format(3) and terminfo(5).
|
||||||
|
///
|
||||||
|
/// @param ctx the same as `ctx2` passed to unibi_format()
|
||||||
|
/// @param delay the delay in tenths of milliseconds
|
||||||
|
/// @param scale padding is proportional to the number of lines affected
|
||||||
|
/// @param force padding is mandatory
|
||||||
|
static void pad(void *ctx, size_t delay, int scale FUNC_ATTR_UNUSED, int force)
|
||||||
|
{
|
||||||
|
if (!force) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UI *ui = ctx;
|
||||||
|
TUIData *data = ui->data;
|
||||||
|
|
||||||
|
if (data->overflow) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
flush_buf(ui);
|
||||||
|
loop_uv_run(data->loop, (int)(delay / 10), false);
|
||||||
|
}
|
||||||
|
|
||||||
static void unibi_set_if_empty(unibi_term *ut, enum unibi_string str, const char *val)
|
static void unibi_set_if_empty(unibi_term *ut, enum unibi_string str, const char *val)
|
||||||
{
|
{
|
||||||
if (!unibi_get_str(ut, str)) {
|
if (!unibi_get_str(ut, str)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user