aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbfredl <bjorn.linse@gmail.com>2024-06-02 10:19:55 +0200
committerGitHub <noreply@github.com>2024-06-02 10:19:55 +0200
commit89dc8f8f4e754e70cbe1624f030fb61bded41bc2 (patch)
treed8b51b14bf2fe9ab47417639b69f63445bbc2e15
parent19be3d26830ced203631045f2f622e75e6d857a7 (diff)
parent6d6974eae685feeccac027287b4dee58730a7464 (diff)
downloadrneovim-89dc8f8f4e754e70cbe1624f030fb61bded41bc2.tar.gz
rneovim-89dc8f8f4e754e70cbe1624f030fb61bded41bc2.tar.bz2
rneovim-89dc8f8f4e754e70cbe1624f030fb61bded41bc2.zip
Merge pull request #29124 from bfredl/inputring
refactor(input): don't use a ring for input
-rw-r--r--src/nvim/api/vim.c2
-rw-r--r--src/nvim/main.c1
-rw-r--r--src/nvim/memory.c1
-rw-r--r--src/nvim/os/input.c111
4 files changed, 61 insertions, 54 deletions
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index f5c89fb283..26dc223948 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -314,7 +314,7 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_ks)
keys_esc = keys.data;
}
if (lowlevel) {
- input_enqueue_raw(cstr_as_string(keys_esc));
+ input_enqueue_raw(keys_esc, strlen(keys_esc));
} else {
ins_typebuf(keys_esc, (remap ? REMAP_YES : REMAP_NONE),
insert ? 0 : typebuf.tb_len, !typed, false);
diff --git a/src/nvim/main.c b/src/nvim/main.c
index ecd3274af4..5e243df975 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -155,7 +155,6 @@ void event_init(void)
loop_init(&main_loop, NULL);
resize_events = multiqueue_new_child(main_loop.events);
- input_init();
signal_init();
// mspgack-rpc initialization
channel_init();
diff --git a/src/nvim/memory.c b/src/nvim/memory.c
index 2afbd262ab..c4774d68f3 100644
--- a/src/nvim/memory.c
+++ b/src/nvim/memory.c
@@ -883,7 +883,6 @@ void free_all_mem(void)
decor_free_all_mem();
drawline_free_all_mem();
- input_free_all_mem();
if (ui_client_channel_id) {
ui_client_free_all_mem();
diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c
index cfe8696cdd..63eca0b6da 100644
--- a/src/nvim/os/input.c
+++ b/src/nvim/os/input.c
@@ -33,7 +33,7 @@
#include "nvim/state_defs.h"
#define READ_BUFFER_SIZE 0xfff
-#define INPUT_BUFFER_SIZE (READ_BUFFER_SIZE * 4)
+#define INPUT_BUFFER_SIZE ((READ_BUFFER_SIZE * 4) + MAX_KEY_CODE_LEN)
typedef enum {
kInputNone,
@@ -42,7 +42,10 @@ typedef enum {
} InbufPollResult;
static RStream read_stream = { .s.closed = true }; // Input before UI starts.
-static RBuffer *input_buffer = NULL;
+static char input_buffer[INPUT_BUFFER_SIZE];
+static char *input_read_pos = input_buffer;
+static char *input_write_pos = input_buffer;
+
static bool input_eof = false;
static bool blocking = false;
static int cursorhold_time = 0; ///< time waiting for CursorHold event
@@ -52,11 +55,6 @@ static int cursorhold_tb_change_cnt = 0; ///< tb_change_cnt when waiting starte
# include "os/input.c.generated.h"
#endif
-void input_init(void)
-{
- input_buffer = rbuffer_new(INPUT_BUFFER_SIZE + MAX_KEY_CODE_LEN);
-}
-
void input_start(void)
{
if (!read_stream.s.closed) {
@@ -78,13 +76,6 @@ void input_stop(void)
rstream_may_close(&read_stream);
}
-#ifdef EXITFREE
-void input_free_all_mem(void)
-{
- rbuffer_free(input_buffer);
-}
-#endif
-
static void cursorhold_event(void **argv)
{
event_T event = State & MODE_INSERT ? EVENT_CURSORHOLDI : EVENT_CURSORHOLD;
@@ -119,9 +110,12 @@ int os_inchar(uint8_t *buf, int maxlen, int ms, int tb_change_cnt, MultiQueue *e
restart_cursorhold_wait(tb_change_cnt);
}
- if (maxlen && rbuffer_size(input_buffer)) {
+ if (maxlen && input_available()) {
restart_cursorhold_wait(tb_change_cnt);
- return (int)rbuffer_read(input_buffer, (char *)buf, (size_t)maxlen);
+ size_t to_read = MIN((size_t)maxlen, input_available());
+ memcpy(buf, input_read_pos, to_read);
+ input_read_pos += to_read;
+ return (int)to_read;
}
// No risk of a UI flood, so disable CTRL-C "interrupt" behavior if it's mapped.
@@ -161,11 +155,14 @@ int os_inchar(uint8_t *buf, int maxlen, int ms, int tb_change_cnt, MultiQueue *e
return 0;
}
- if (maxlen && rbuffer_size(input_buffer)) {
+ if (maxlen && input_available()) {
restart_cursorhold_wait(tb_change_cnt);
- // Safe to convert rbuffer_read to int, it will never overflow since we use
- // relatively small buffers.
- return (int)rbuffer_read(input_buffer, (char *)buf, (size_t)maxlen);
+ // Safe to convert rbuffer_read to int, it will never overflow since
+ // INPUT_BUFFER_SIZE fits in an int
+ size_t to_read = MIN((size_t)maxlen, input_available());
+ memcpy(buf, input_read_pos, to_read);
+ input_read_pos += to_read;
+ return (int)to_read;
}
// If there are events, return the keys directly
@@ -247,11 +244,28 @@ bool os_isatty(int fd)
return uv_guess_handle(fd) == UV_TTY;
}
-void input_enqueue_raw(String keys)
+size_t input_available(void)
+{
+ return (size_t)(input_write_pos - input_read_pos);
+}
+
+static size_t input_space(void)
+{
+ return (size_t)(input_buffer + INPUT_BUFFER_SIZE - input_write_pos);
+}
+
+void input_enqueue_raw(const char *data, size_t size)
{
- if (keys.size > 0) {
- rbuffer_write(input_buffer, keys.data, keys.size);
+ if (input_read_pos > input_buffer) {
+ size_t available = input_available();
+ memmove(input_buffer, input_read_pos, available);
+ input_read_pos = input_buffer;
+ input_write_pos = input_buffer + available;
}
+
+ size_t to_write = MIN(size, input_space());
+ memcpy(input_write_pos, data, to_write);
+ input_write_pos += to_write;
}
size_t input_enqueue(String keys)
@@ -259,7 +273,7 @@ size_t input_enqueue(String keys)
const char *ptr = keys.data;
const char *end = ptr + keys.size;
- while (rbuffer_space(input_buffer) >= 19 && ptr < end) {
+ while (input_space() >= 19 && ptr < end) {
// A "<x>" form occupies at least 1 characters, and produces up
// to 19 characters (1 + 5 * 3 for the char and 3 for a modifier).
// In the case of K_SPECIAL (0x80), 3 bytes are escaped and needed,
@@ -272,7 +286,7 @@ size_t input_enqueue(String keys)
if (new_size) {
new_size = handle_mouse_event(&ptr, buf, new_size);
- rbuffer_write(input_buffer, (char *)buf, new_size);
+ input_enqueue_raw((char *)buf, new_size);
continue;
}
@@ -293,11 +307,11 @@ size_t input_enqueue(String keys)
// copy the character, escaping K_SPECIAL
if ((uint8_t)(*ptr) == K_SPECIAL) {
- rbuffer_write(input_buffer, (char *)&(uint8_t){ K_SPECIAL }, 1);
- rbuffer_write(input_buffer, (char *)&(uint8_t){ KS_SPECIAL }, 1);
- rbuffer_write(input_buffer, (char *)&(uint8_t){ KE_FILLER }, 1);
+ input_enqueue_raw((char *)&(uint8_t){ K_SPECIAL }, 1);
+ input_enqueue_raw((char *)&(uint8_t){ KS_SPECIAL }, 1);
+ input_enqueue_raw((char *)&(uint8_t){ KE_FILLER }, 1);
} else {
- rbuffer_write(input_buffer, ptr, 1);
+ input_enqueue_raw(ptr, 1);
}
ptr++;
}
@@ -422,7 +436,7 @@ static unsigned handle_mouse_event(const char **ptr, uint8_t *buf, unsigned bufs
return bufsize;
}
-size_t input_enqueue_mouse(int code, uint8_t modifier, int grid, int row, int col)
+void input_enqueue_mouse(int code, uint8_t modifier, int grid, int row, int col)
{
modifier |= check_multiclick(code, grid, row, col);
uint8_t buf[7];
@@ -442,8 +456,7 @@ size_t input_enqueue_mouse(int code, uint8_t modifier, int grid, int row, int co
mouse_col = col;
size_t written = 3 + (size_t)(p - buf);
- rbuffer_write(input_buffer, (char *)buf, written);
- return written;
+ input_enqueue_raw((char *)buf, written);
}
/// @return true if the main loop is blocked and waiting for input.
@@ -484,20 +497,15 @@ static InbufPollResult inbuf_poll(int ms, MultiQueue *events)
return input_eof ? kInputEof : kInputNone;
}
-bool input_available(void)
-{
- return rbuffer_size(input_buffer) != 0;
-}
-
static void input_read_cb(RStream *stream, RBuffer *buf, size_t c, void *data, bool at_eof)
{
if (at_eof) {
input_eof = true;
}
- assert(rbuffer_space(input_buffer) >= rbuffer_size(buf));
+ assert(input_space() >= rbuffer_size(buf));
RBUFFER_UNTIL_EMPTY(buf, ptr, len) {
- (void)rbuffer_write(input_buffer, ptr, len);
+ input_enqueue_raw(ptr, len);
rbuffer_consumed(buf, len);
}
}
@@ -508,23 +516,24 @@ static void process_ctrl_c(void)
return;
}
- size_t consume_count = 0;
- RBUFFER_EACH_REVERSE(input_buffer, c, i) {
- if ((uint8_t)c == Ctrl_C
- || ((uint8_t)c == 'C' && i >= 3
- && (uint8_t)(*rbuffer_get(input_buffer, i - 3)) == K_SPECIAL
- && (uint8_t)(*rbuffer_get(input_buffer, i - 2)) == KS_MODIFIER
- && (uint8_t)(*rbuffer_get(input_buffer, i - 1)) == MOD_MASK_CTRL)) {
- *rbuffer_get(input_buffer, i) = Ctrl_C;
+ size_t available = input_available();
+ ssize_t i;
+ for (i = (ssize_t)available - 1; i >= 0; i--) {
+ uint8_t c = (uint8_t)input_read_pos[i];
+ if (c == Ctrl_C
+ || (c == 'C' && i >= 3
+ && (uint8_t)input_read_pos[i - 3] == K_SPECIAL
+ && (uint8_t)input_read_pos[i - 2] == KS_MODIFIER
+ && (uint8_t)input_read_pos[i - 1] == MOD_MASK_CTRL)) {
+ input_read_pos[i] = Ctrl_C;
got_int = true;
- consume_count = i;
break;
}
}
- if (got_int && consume_count) {
+ if (got_int && i > 0) {
// Remove all unprocessed input (typeahead) before the CTRL-C.
- rbuffer_consumed(input_buffer, consume_count);
+ input_read_pos += i;
}
}
@@ -548,7 +557,7 @@ static int push_event_key(uint8_t *buf, int maxlen)
bool os_input_ready(MultiQueue *events)
{
return (typebuf_was_filled // API call filled typeahead
- || rbuffer_size(input_buffer) // Input buffer filled
+ || input_available() // Input buffer filled
|| pending_events(events)); // Events must be processed
}