diff options
Diffstat (limited to 'src/nvim/os/input.c')
| -rw-r--r-- | src/nvim/os/input.c | 82 | 
1 files changed, 46 insertions, 36 deletions
| diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c index a18d735ce6..d948a48b64 100644 --- a/src/nvim/os/input.c +++ b/src/nvim/os/input.c @@ -1,3 +1,4 @@ +#include <assert.h>  #include <string.h>  #include <stdint.h>  #include <stdbool.h> @@ -7,7 +8,6 @@  #include "nvim/api/private/defs.h"  #include "nvim/os/input.h"  #include "nvim/os/event.h" -#include "nvim/os/signal.h"  #include "nvim/os/rstream_defs.h"  #include "nvim/os/rstream.h"  #include "nvim/ascii.h" @@ -20,8 +20,8 @@  #include "nvim/getchar.h"  #include "nvim/term.h" -#define READ_BUFFER_SIZE 0xffff -#define INPUT_BUFFER_SIZE 4096 +#define READ_BUFFER_SIZE 0xfff +#define INPUT_BUFFER_SIZE (READ_BUFFER_SIZE * 4)  typedef enum {    kInputNone, @@ -48,10 +48,7 @@ void input_init(void)    }    read_buffer = rbuffer_new(READ_BUFFER_SIZE); -  read_stream = rstream_new(read_cb, -                            read_buffer, -                            NULL, -                            NULL); +  read_stream = rstream_new(read_cb, read_buffer, NULL);    rstream_set_file(read_stream, read_cmd_fd);  } @@ -76,7 +73,7 @@ void input_stop(void)  }  // Low level input function. -int os_inchar(uint8_t *buf, int maxlen, int32_t ms, int tb_change_cnt) +int os_inchar(uint8_t *buf, int maxlen, int ms, int tb_change_cnt)  {    InbufPollResult result; @@ -90,7 +87,7 @@ int os_inchar(uint8_t *buf, int maxlen, int32_t ms, int tb_change_cnt)        return 0;      }    } else { -    if ((result = inbuf_poll(p_ut)) == kInputNone) { +    if ((result = inbuf_poll((int)p_ut)) == kInputNone) {        if (trigger_cursorhold() && maxlen >= 3            && !typebuf_changed(tb_change_cnt)) {          buf[0] = K_SPECIAL; @@ -119,8 +116,9 @@ int os_inchar(uint8_t *buf, int maxlen, int32_t ms, int tb_change_cnt)      return 0;    } -  convert_input(); -  return rbuffer_read(input_buffer, (char *)buf, maxlen); +  // 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);  }  // Check if a character is available for reading @@ -133,8 +131,8 @@ bool os_char_avail(void)  // In cooked mode we should get SIGINT, no need to check.  void os_breakcheck(void)  { -  if (curr_tmode == TMODE_RAW && input_poll(0)) -    convert_input(); +  if (curr_tmode == TMODE_RAW) +    input_poll(0);  }  /// Test whether a file descriptor refers to a terminal. @@ -167,23 +165,21 @@ void input_buffer_restore(String str)    free(str.data);  } -static bool input_poll(int32_t ms) +size_t input_enqueue(String keys)  { -  if (embedded_mode) { -    EventSource input_sources[] = { signal_event_source(), NULL }; -    return event_poll(ms, input_sources); -  } - -  EventSource input_sources[] = { -    rstream_event_source(read_stream), -    NULL -  }; +  size_t rv = rbuffer_write(input_buffer, keys.data, keys.size); +  process_interrupts(); +  return rv; +} -  return input_ready() || event_poll(ms, input_sources) || input_ready(); +static bool input_poll(int ms) +{ +  event_poll_until(ms, input_ready()); +  return input_ready();  }  // This is a replacement for the old `WaitForChar` function in os_unix.c -static InbufPollResult inbuf_poll(int32_t ms) +static InbufPollResult inbuf_poll(int ms)  {    if (typebuf_was_filled || rbuffer_pending(input_buffer)) {      return kInputAvail; @@ -230,12 +226,14 @@ static void read_cb(RStream *rstream, void *data, bool at_eof)      }    } +  convert_input(); +  process_interrupts();    started_reading = true;  }  static void convert_input(void)  { -  if (!rbuffer_available(input_buffer)) { +  if (embedded_mode || !rbuffer_available(input_buffer)) {      // No input buffer space      return;    } @@ -248,24 +246,32 @@ static void convert_input(void)    if (convert) {      // Perform input conversion according to `input_conv` -    size_t unconverted_length; +    size_t unconverted_length = 0;      data = (char *)string_convert_ext(&input_conv,                                        (uint8_t *)data,                                        (int *)&converted_length,                                        (int *)&unconverted_length); -    data_length = rbuffer_pending(read_buffer) - unconverted_length; +    data_length -= unconverted_length;    } -  // Write processed data to input buffer -  size_t consumed = rbuffer_write(input_buffer, data, data_length); +  // The conversion code will be gone eventually, for now assume `input_buffer` +  // always has space for the converted data(it's many times the size of +  // `read_buffer`, so it's hard to imagine a scenario where the converted data +  // doesn't fit) +  assert(converted_length <= rbuffer_available(input_buffer)); +  // Write processed data to input buffer. +  (void)rbuffer_write(input_buffer, data, converted_length);    // Adjust raw buffer pointers -  rbuffer_consumed(read_buffer, consumed); +  rbuffer_consumed(read_buffer, data_length);    if (convert) {      // data points to memory allocated by `string_convert_ext`, free it.      free(data);    } +} +static void process_interrupts(void) +{    if (!ctrl_c_interrupts) {      return;    } @@ -273,17 +279,17 @@ static void convert_input(void)    char *inbuf = rbuffer_read_ptr(input_buffer);    size_t count = rbuffer_pending(input_buffer), consume_count = 0; -  for (int i = count - 1; i >= 0; i--) { +  for (int i = (int)count - 1; i >= 0; i--) {      if (inbuf[i] == 3) { -      consume_count = i + 1; +      got_int = true; +      consume_count = (size_t)i;        break;      }    } -  if (consume_count) { +  if (got_int) {      // Remove everything typed before the CTRL-C      rbuffer_consumed(input_buffer, consume_count); -    got_int = true;    }  } @@ -304,6 +310,10 @@ static int push_event_key(uint8_t *buf, int maxlen)  // Check if there's pending input  static bool input_ready(void)  { -  return rstream_pending(read_stream) > 0 || eof; +  return typebuf_was_filled ||                    // API call filled typeahead +         event_has_deferred() ||                  // Events must be processed +         (!embedded_mode && ( +            rbuffer_pending(input_buffer) > 0 ||  // Stdin input +            eof));                                // Stdin closed  } | 
