diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/nvim/buffer_defs.h | 6 | ||||
| -rw-r--r-- | src/nvim/getchar.c | 24 | ||||
| -rw-r--r-- | src/nvim/mbyte.c | 44 | ||||
| -rw-r--r-- | src/nvim/os/input.c | 108 | ||||
| -rw-r--r-- | src/nvim/os/input.h | 2 | ||||
| -rw-r--r-- | src/nvim/ui.c | 242 | ||||
| -rw-r--r-- | src/nvim/vim.h | 4 | 
7 files changed, 100 insertions, 330 deletions
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 84d55fb730..6d097010ac 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -21,6 +21,8 @@  #include "nvim/eval_defs.h"  // for proftime_T  #include "nvim/profile.h" +// for String +#include "nvim/api/private/defs.h"  /*   * Flags for w_valid. @@ -311,9 +313,7 @@ typedef struct {    int old_mod_mask;    buffheader_T save_readbuf1;    buffheader_T save_readbuf2; -#ifdef USE_INPUT_BUF -  char_u              *save_inputbuf; -#endif +  String save_inputbuf;  } tasave_T;  /* diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index c3f6e2c2b6..fd60664b7b 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -50,6 +50,7 @@  #include "nvim/ui.h"  #include "nvim/undo.h"  #include "nvim/os/event.h" +#include "nvim/os/input.h"  /*   * These buffers are used for storing: @@ -1201,9 +1202,7 @@ void save_typeahead(tasave_T *tp)    readbuf1.bh_first.b_next = NULL;    tp->save_readbuf2 = readbuf2;    readbuf2.bh_first.b_next = NULL; -# ifdef USE_INPUT_BUF -  tp->save_inputbuf = get_input_buf(); -# endif +  tp->save_inputbuf = input_buffer_save();  }  /* @@ -1224,9 +1223,7 @@ void restore_typeahead(tasave_T *tp)    readbuf1 = tp->save_readbuf1;    free_buff(&readbuf2);    readbuf2 = tp->save_readbuf2; -# ifdef USE_INPUT_BUF -  set_input_buf(tp->save_inputbuf); -# endif +  input_buffer_restore(tp->save_inputbuf);  }  /* @@ -2551,21 +2548,6 @@ fix_input_buffer (    return len;  } -#if defined(USE_INPUT_BUF) || defined(PROTO) -/* - * Return TRUE when bytes are in the input buffer or in the typeahead buffer. - * Normally the input buffer would be sufficient, but feedkeys() may insert - * characters in the typeahead buffer while we are waiting for input to arrive. - */ -int input_available(void) -{ -  return !vim_is_input_buf_empty() -         || typebuf_was_filled -  ; -} - -#endif -  /*   * map[!]		    : show all key mappings   * map[!] {lhs}		    : show key mapping for {lhs} diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c index 7ba4409180..cb33c2e666 100644 --- a/src/nvim/mbyte.c +++ b/src/nvim/mbyte.c @@ -3803,50 +3803,6 @@ int convert_setup_ext(vimconv_T *vcp, char_u *from, bool from_unicode_is_utf8,    return OK;  } -#if defined(FEAT_GUI) || defined(WIN3264) || defined(PROTO) -/* - * Do conversion on typed input characters in-place. - * The input and output are not NUL terminated! - * Returns the length after conversion. - */ -int convert_input(char_u *ptr, int len, int maxlen) -{ -  return convert_input_safe(ptr, len, maxlen, NULL, NULL); -} -#endif - -/* - * Like convert_input(), but when there is an incomplete byte sequence at the - * end return that as an allocated string in "restp" and set "*restlenp" to - * the length.  If "restp" is NULL it is not used. - */ -int convert_input_safe(char_u *ptr, int len, int maxlen, char_u **restp, -                       int *restlenp) -{ -  char_u      *d; -  int dlen = len; -  int unconvertlen = 0; - -  d = string_convert_ext(&input_conv, ptr, &dlen, -      restp == NULL ? NULL : &unconvertlen); -  if (d != NULL) { -    if (dlen <= maxlen) { -      if (unconvertlen > 0) { -        /* Move the unconverted characters to allocated memory. */ -        *restp = xmalloc(unconvertlen); -        memmove(*restp, ptr + len - unconvertlen, unconvertlen); -        *restlenp = unconvertlen; -      } -      memmove(ptr, d, dlen); -    } else -      /* result is too long, keep the unconverted text (the caller must -       * have done something wrong!) */ -      dlen = len; -    free(d); -  } -  return dlen; -} -  /*   * Convert text "ptr[*lenp]" according to "vcp".   * Returns the result in allocated memory and sets "*lenp". diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c index 511dfd7b07..71b590ceaa 100644 --- a/src/nvim/os/input.c +++ b/src/nvim/os/input.c @@ -4,6 +4,7 @@  #include <uv.h> +#include "nvim/api/private/defs.h"  #include "nvim/os/input.h"  #include "nvim/os/event.h"  #include "nvim/os/signal.h" @@ -12,11 +13,15 @@  #include "nvim/ascii.h"  #include "nvim/vim.h"  #include "nvim/ui.h" +#include "nvim/memory.h" +#include "nvim/keymap.h" +#include "nvim/mbyte.h"  #include "nvim/fileio.h"  #include "nvim/getchar.h"  #include "nvim/term.h" -#define READ_BUFFER_SIZE 256 +#define READ_BUFFER_SIZE 0xffff +#define INPUT_BUFFER_SIZE 4096  typedef enum {    kInputNone, @@ -25,6 +30,7 @@ typedef enum {  } InbufPollResult;  static RStream *read_stream; +static RBuffer *read_buffer, *input_buffer;  static bool eof = false, started_reading = false;  #ifdef INCLUDE_GENERATED_DECLARATIONS @@ -35,12 +41,15 @@ static bool eof = false, started_reading = false;  void input_init(void)  { +  input_buffer = rbuffer_new(INPUT_BUFFER_SIZE + MAX_KEY_CODE_LEN); +    if (embedded_mode) {      return;    } +  read_buffer = rbuffer_new(READ_BUFFER_SIZE);    read_stream = rstream_new(read_cb, -                            rbuffer_new(READ_BUFFER_SIZE), +                            read_buffer,                              NULL,                              NULL);    rstream_set_file(read_stream, read_cmd_fd); @@ -66,17 +75,6 @@ void input_stop(void)    rstream_stop(read_stream);  } -// Copies (at most `count`) of was read from `read_cmd_fd` into `buf` -uint32_t input_read(char *buf, uint32_t count) -{ -  if (embedded_mode) { -    return 0; -  } - -  return rstream_read(read_stream, buf, count); -} - -  // Low level input function.  int os_inchar(uint8_t *buf, int maxlen, int32_t ms, int tb_change_cnt)  { @@ -121,7 +119,8 @@ int os_inchar(uint8_t *buf, int maxlen, int32_t ms, int tb_change_cnt)      return 0;    } -  return read_from_input_buf(buf, (int64_t)maxlen); +  convert_input(); +  return rbuffer_read(input_buffer, (char *)buf, maxlen);  }  // Check if a character is available for reading @@ -135,7 +134,7 @@ bool os_char_avail(void)  void os_breakcheck(void)  {    if (curr_tmode == TMODE_RAW && input_poll(0)) -    fill_input_buf(false); +    convert_input();  }  /// Test whether a file descriptor refers to a terminal. @@ -147,6 +146,27 @@ bool os_isatty(int fd)      return uv_guess_handle(fd) == UV_TTY;  } +/// Return the contents of the input buffer and make it empty. The returned +/// pointer must be passed to `input_buffer_restore()` later. +String input_buffer_save(void) +{ +  size_t inbuf_size = rbuffer_pending(input_buffer); +  String rv = { +    .data = xmemdup(rbuffer_data(input_buffer), inbuf_size), +    .size = inbuf_size +  }; +  rbuffer_consumed(input_buffer, inbuf_size); +  return rv; +} + +/// Restore the contents of the input buffer and free `str` +void input_buffer_restore(String str) +{ +  rbuffer_consumed(input_buffer, rbuffer_pending(input_buffer)); +  rbuffer_write(input_buffer, str.data, str.size); +  free(str.data); +} +  static bool input_poll(int32_t ms)  {    if (embedded_mode) { @@ -165,7 +185,7 @@ static bool input_poll(int32_t ms)  // This is a replacement for the old `WaitForChar` function in os_unix.c  static InbufPollResult inbuf_poll(int32_t ms)  { -  if (input_available()) { +  if (typebuf_was_filled || rbuffer_pending(input_buffer)) {      return kInputAvail;    } @@ -213,6 +233,60 @@ static void read_cb(RStream *rstream, void *data, bool at_eof)    started_reading = true;  } +static void convert_input(void) +{ +  if (!rbuffer_available(input_buffer)) { +    // No input buffer space +    return; +  } + +  bool convert = input_conv.vc_type != CONV_NONE; +  // Set unconverted data/length +  char *data = rbuffer_data(read_buffer); +  size_t data_length = rbuffer_pending(read_buffer); +  size_t converted_length = data_length; + +  if (convert) { +    // Perform input conversion according to `input_conv` +    size_t unconverted_length; +    data = (char *)string_convert_ext(&input_conv, +                                      (uint8_t *)data, +                                      (int *)&converted_length, +                                      (int *)&unconverted_length); +    data_length = rbuffer_pending(read_buffer) - unconverted_length; +  } + +  // Write processed data to input buffer +  size_t consumed = rbuffer_write(input_buffer, data, data_length); +  // Adjust raw buffer pointers +  rbuffer_consumed(read_buffer, consumed); + +  if (convert) { +    // data points to memory allocated by `string_convert_ext`, free it. +    free(data); +  } + +  if (!ctrl_c_interrupts) { +    return; +  } + +  char *inbuf = rbuffer_data(input_buffer); +  size_t count = rbuffer_pending(input_buffer), consume_count = 0; + +  for (int i = count - 1; i >= 0; i--) { +    if (inbuf[i] == 3) { +      consume_count = i + 1; +      break; +    } +  } + +  if (consume_count) { +    // Remove everything typed before the CTRL-C +    rbuffer_consumed(input_buffer, consume_count); +    got_int = true; +  } +} +  static int push_event_key(uint8_t *buf, int maxlen)  {    static const uint8_t key[3] = { K_SPECIAL, KS_EXTRA, KE_EVENT }; @@ -228,7 +302,7 @@ static int push_event_key(uint8_t *buf, int maxlen)  }  // Check if there's pending input -bool input_ready(void) +static bool input_ready(void)  {    return rstream_pending(read_stream) > 0 || eof;  } diff --git a/src/nvim/os/input.h b/src/nvim/os/input.h index 7543950b4f..5902677a35 100644 --- a/src/nvim/os/input.h +++ b/src/nvim/os/input.h @@ -4,6 +4,8 @@  #include <stdint.h>  #include <stdbool.h> +#include "nvim/api/private/defs.h" +  #ifdef INCLUDE_GENERATED_DECLARATIONS  # include "os/input.h.generated.h"  #endif diff --git a/src/nvim/ui.c b/src/nvim/ui.c index d51fbd162b..2c5f7158f6 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -228,247 +228,6 @@ void ui_breakcheck(void)   * for them.   */ - -/***************************************************************************** - * Functions that handle the input buffer. - * This is used for any GUI version, and the unix terminal version. - * - * For Unix, the input characters are buffered to be able to check for a - * CTRL-C.  This should be done with signals, but I don't know how to do that - * in a portable way for a tty in RAW mode. - * - * For the client-server code in the console the received keys are put in the - * input buffer. - */ - -#if defined(USE_INPUT_BUF) || defined(PROTO) - -/* - * Internal typeahead buffer.  Includes extra space for long key code - * descriptions which would otherwise overflow.  The buffer is considered full - * when only this extra space (or part of it) remains. - */ -# define INBUFLEN 4096 - -static char_u inbuf[INBUFLEN + MAX_KEY_CODE_LEN]; -static int inbufcount = 0;          /* number of chars in inbuf[] */ - -/* - * vim_is_input_buf_full(), vim_is_input_buf_empty(), add_to_input_buf(), and - * trash_input_buf() are functions for manipulating the input buffer.  These - * are used by the gui_* calls when a GUI is used to handle keyboard input. - */ - -int vim_is_input_buf_full(void) -{ -  return inbufcount >= INBUFLEN; -} - -int vim_is_input_buf_empty(void) -{ -  return inbufcount == 0; -} - -/* - * Return the current contents of the input buffer and make it empty. - * The returned pointer must be passed to set_input_buf() later. - */ -char_u *get_input_buf(void) -{ -  /* We use a growarray to store the data pointer and the length. */ -  garray_T *gap = xmalloc(sizeof(garray_T)); -  /* Add one to avoid a zero size. */ -  gap->ga_data = xmalloc(inbufcount + 1); -  if (gap->ga_data != NULL) -    memmove(gap->ga_data, inbuf, (size_t)inbufcount); -  gap->ga_len = inbufcount; - -  trash_input_buf(); -  return (char_u *)gap; -} - -/* - * Restore the input buffer with a pointer returned from get_input_buf(). - * The allocated memory is freed, this only works once! - */ -void set_input_buf(char_u *p) -{ -  garray_T    *gap = (garray_T *)p; - -  if (gap != NULL) { -    if (gap->ga_data != NULL) { -      memmove(inbuf, gap->ga_data, gap->ga_len); -      inbufcount = gap->ga_len; -      free(gap->ga_data); -    } -    free(gap); -  } -} - -#if defined(FEAT_GUI) \ -  || defined(FEAT_MOUSE_GPM) || defined(FEAT_SYSMOUSE) \ -  || defined(FEAT_XCLIPBOARD) || defined(PROTO) -/* - * Add the given bytes to the input buffer - * Special keys start with CSI.  A real CSI must have been translated to - * CSI KS_EXTRA KE_CSI.  K_SPECIAL doesn't require translation. - */ -void add_to_input_buf(char_u *s, int len) -{ -  if (inbufcount + len > INBUFLEN + MAX_KEY_CODE_LEN) -    return;         /* Shouldn't ever happen! */ - -  if ((State & (INSERT|CMDLINE)) && hangul_input_state_get()) -    if ((len = hangul_input_process(s, len)) == 0) -      return; - -  while (len--) -    inbuf[inbufcount++] = *s++; -} -#endif - -#if ((defined(FEAT_XIM) || defined(FEAT_DND)) && defined(FEAT_GUI_GTK)) \ -  || defined(FEAT_GUI_MSWIN) \ -  || defined(FEAT_GUI_MAC) \ -  || defined(FEAT_MBYTE_IME) \ -  || defined(FEAT_GUI) \ -  || defined(PROTO) -/* - * Add "str[len]" to the input buffer while escaping CSI bytes. - */ -void add_to_input_buf_csi(char_u *str, int len)          { -  int i; -  char_u buf[2]; - -  for (i = 0; i < len; ++i) { -    add_to_input_buf(str + i, 1); -    if (str[i] == CSI) { -      /* Turn CSI into K_CSI. */ -      buf[0] = KS_EXTRA; -      buf[1] = (int)KE_CSI; -      add_to_input_buf(buf, 2); -    } -  } -} - -#endif - -/* Remove everything from the input buffer.  Called when ^C is found */ -void trash_input_buf(void) -{ -  inbufcount = 0; -} - -/* - * Read as much data from the input buffer as possible up to maxlen, and store - * it in buf. - * Note: this function used to be Read() in unix.c - */ -int read_from_input_buf(char_u *buf, long maxlen) -{ -  if (inbufcount == 0)          /* if the buffer is empty, fill it */ -    fill_input_buf(true); -  if (maxlen > inbufcount) -    maxlen = inbufcount; -  memmove(buf, inbuf, (size_t)maxlen); -  inbufcount -= maxlen; -  if (inbufcount) -    memmove(inbuf, inbuf + maxlen, (size_t)inbufcount); -  return (int)maxlen; -} - -void fill_input_buf(bool exit_on_error) -{ -#if defined(UNIX) || defined(MACOS_X_UNIX) -  int len; -  int try; -  static char_u *rest = NULL;       /* unconverted rest of previous read */ -  static int restlen = 0; -  int unconverted; -#endif - -#if defined(UNIX) || defined(MACOS_X_UNIX) -  if (vim_is_input_buf_full()) -    return; -  /* -   * Fill_input_buf() is only called when we really need a character. -   * If we can't get any, but there is some in the buffer, just return. -   * If we can't get any, and there isn't any in the buffer, we give up and -   * exit Vim. -   */ - - -  if (rest != NULL) { -    /* Use remainder of previous call, starts with an invalid character -     * that may become valid when reading more. */ -    if (restlen > INBUFLEN - inbufcount) -      unconverted = INBUFLEN - inbufcount; -    else -      unconverted = restlen; -    memmove(inbuf + inbufcount, rest, unconverted); -    if (unconverted == restlen) { -      free(rest); -      rest = NULL; -    } else { -      restlen -= unconverted; -      memmove(rest, rest + unconverted, restlen); -    } -    inbufcount += unconverted; -  } else -    unconverted = 0; - -  len = 0;      /* to avoid gcc warning */ -  for (try = 0; try < 100; ++try) { -    len = input_read( -        (char *)inbuf + inbufcount, -        (size_t)((INBUFLEN - inbufcount) / input_conv.vc_factor)); - -    if (len > 0 || got_int) -      break; - -    if (!exit_on_error) -      return; -  } - -  if (len <= 0 && !got_int) -    read_error_exit(); - -  if (got_int) { -    /* Interrupted, pretend a CTRL-C was typed. */ -    inbuf[0] = 3; -    inbufcount = 1; -  } else { -    /* -     * May perform conversion on the input characters. -     * Include the unconverted rest of the previous call. -     * If there is an incomplete char at the end it is kept for the next -     * time, reading more bytes should make conversion possible. -     * Don't do this in the unlikely event that the input buffer is too -     * small ("rest" still contains more bytes). -     */ -    if (input_conv.vc_type != CONV_NONE) { -      inbufcount -= unconverted; -      len = convert_input_safe(inbuf + inbufcount, -          len + unconverted, INBUFLEN - inbufcount, -          rest == NULL ? &rest : NULL, &restlen); -    } -    while (len-- > 0) { -      /* -       * if a CTRL-C was typed, remove it from the buffer and set got_int -       */ -      if (inbuf[inbufcount] == 3 && ctrl_c_interrupts) { -        /* remove everything typed before the CTRL-C */ -        memmove(inbuf, inbuf + inbufcount, (size_t)(len + 1)); -        inbufcount = 0; -        got_int = TRUE; -      } -      ++inbufcount; -    } -  } -#endif /* UNIX */ -} -#endif /* defined(UNIX) || defined(FEAT_GUI) */ -  /*   * Exit because of an input read error.   */ @@ -954,3 +713,4 @@ void im_save_status(long *psave)    }  }  #endif + diff --git a/src/nvim/vim.h b/src/nvim/vim.h index 3ef291ef7c..47ed223e81 100644 --- a/src/nvim/vim.h +++ b/src/nvim/vim.h @@ -339,10 +339,6 @@ enum {  #define fnamencmp(x, y, n) vim_fnamencmp((char_u *)(x), (char_u *)(y), \      (size_t)(n)) -#if defined(UNIX) || defined(FEAT_GUI) -# define USE_INPUT_BUF -#endif -  #ifndef EINTR  # define read_eintr(fd, buf, count) vim_read((fd), (buf), (count))  # define write_eintr(fd, buf, count) vim_write((fd), (buf), (count))  | 
