mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
ui: Refactor input buffer handling
All input buffer code was moved to os/input.c, and `inbuf` is now a `RBuffer` instance(which abstracts static buffer manipulation).
This commit is contained in:
parent
68de5d79a2
commit
42112e04a9
@ -21,6 +21,8 @@
|
|||||||
#include "nvim/eval_defs.h"
|
#include "nvim/eval_defs.h"
|
||||||
// for proftime_T
|
// for proftime_T
|
||||||
#include "nvim/profile.h"
|
#include "nvim/profile.h"
|
||||||
|
// for String
|
||||||
|
#include "nvim/api/private/defs.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flags for w_valid.
|
* Flags for w_valid.
|
||||||
@ -311,9 +313,7 @@ typedef struct {
|
|||||||
int old_mod_mask;
|
int old_mod_mask;
|
||||||
buffheader_T save_readbuf1;
|
buffheader_T save_readbuf1;
|
||||||
buffheader_T save_readbuf2;
|
buffheader_T save_readbuf2;
|
||||||
#ifdef USE_INPUT_BUF
|
String save_inputbuf;
|
||||||
char_u *save_inputbuf;
|
|
||||||
#endif
|
|
||||||
} tasave_T;
|
} tasave_T;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
#include "nvim/ui.h"
|
#include "nvim/ui.h"
|
||||||
#include "nvim/undo.h"
|
#include "nvim/undo.h"
|
||||||
#include "nvim/os/event.h"
|
#include "nvim/os/event.h"
|
||||||
|
#include "nvim/os/input.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These buffers are used for storing:
|
* These buffers are used for storing:
|
||||||
@ -1201,9 +1202,7 @@ void save_typeahead(tasave_T *tp)
|
|||||||
readbuf1.bh_first.b_next = NULL;
|
readbuf1.bh_first.b_next = NULL;
|
||||||
tp->save_readbuf2 = readbuf2;
|
tp->save_readbuf2 = readbuf2;
|
||||||
readbuf2.bh_first.b_next = NULL;
|
readbuf2.bh_first.b_next = NULL;
|
||||||
# ifdef USE_INPUT_BUF
|
tp->save_inputbuf = input_buffer_save();
|
||||||
tp->save_inputbuf = get_input_buf();
|
|
||||||
# endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1224,9 +1223,7 @@ void restore_typeahead(tasave_T *tp)
|
|||||||
readbuf1 = tp->save_readbuf1;
|
readbuf1 = tp->save_readbuf1;
|
||||||
free_buff(&readbuf2);
|
free_buff(&readbuf2);
|
||||||
readbuf2 = tp->save_readbuf2;
|
readbuf2 = tp->save_readbuf2;
|
||||||
# ifdef USE_INPUT_BUF
|
input_buffer_restore(tp->save_inputbuf);
|
||||||
set_input_buf(tp->save_inputbuf);
|
|
||||||
# endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2551,21 +2548,6 @@ fix_input_buffer (
|
|||||||
return len;
|
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[!] : show all key mappings
|
||||||
* map[!] {lhs} : show key mapping for {lhs}
|
* map[!] {lhs} : show key mapping for {lhs}
|
||||||
|
@ -3803,50 +3803,6 @@ int convert_setup_ext(vimconv_T *vcp, char_u *from, bool from_unicode_is_utf8,
|
|||||||
return OK;
|
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".
|
* Convert text "ptr[*lenp]" according to "vcp".
|
||||||
* Returns the result in allocated memory and sets "*lenp".
|
* Returns the result in allocated memory and sets "*lenp".
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include <uv.h>
|
#include <uv.h>
|
||||||
|
|
||||||
|
#include "nvim/api/private/defs.h"
|
||||||
#include "nvim/os/input.h"
|
#include "nvim/os/input.h"
|
||||||
#include "nvim/os/event.h"
|
#include "nvim/os/event.h"
|
||||||
#include "nvim/os/signal.h"
|
#include "nvim/os/signal.h"
|
||||||
@ -12,11 +13,15 @@
|
|||||||
#include "nvim/ascii.h"
|
#include "nvim/ascii.h"
|
||||||
#include "nvim/vim.h"
|
#include "nvim/vim.h"
|
||||||
#include "nvim/ui.h"
|
#include "nvim/ui.h"
|
||||||
|
#include "nvim/memory.h"
|
||||||
|
#include "nvim/keymap.h"
|
||||||
|
#include "nvim/mbyte.h"
|
||||||
#include "nvim/fileio.h"
|
#include "nvim/fileio.h"
|
||||||
#include "nvim/getchar.h"
|
#include "nvim/getchar.h"
|
||||||
#include "nvim/term.h"
|
#include "nvim/term.h"
|
||||||
|
|
||||||
#define READ_BUFFER_SIZE 256
|
#define READ_BUFFER_SIZE 0xffff
|
||||||
|
#define INPUT_BUFFER_SIZE 4096
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
kInputNone,
|
kInputNone,
|
||||||
@ -25,6 +30,7 @@ typedef enum {
|
|||||||
} InbufPollResult;
|
} InbufPollResult;
|
||||||
|
|
||||||
static RStream *read_stream;
|
static RStream *read_stream;
|
||||||
|
static RBuffer *read_buffer, *input_buffer;
|
||||||
static bool eof = false, started_reading = false;
|
static bool eof = false, started_reading = false;
|
||||||
|
|
||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
@ -35,12 +41,15 @@ static bool eof = false, started_reading = false;
|
|||||||
|
|
||||||
void input_init(void)
|
void input_init(void)
|
||||||
{
|
{
|
||||||
|
input_buffer = rbuffer_new(INPUT_BUFFER_SIZE + MAX_KEY_CODE_LEN);
|
||||||
|
|
||||||
if (embedded_mode) {
|
if (embedded_mode) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
read_buffer = rbuffer_new(READ_BUFFER_SIZE);
|
||||||
read_stream = rstream_new(read_cb,
|
read_stream = rstream_new(read_cb,
|
||||||
rbuffer_new(READ_BUFFER_SIZE),
|
read_buffer,
|
||||||
NULL,
|
NULL,
|
||||||
NULL);
|
NULL);
|
||||||
rstream_set_file(read_stream, read_cmd_fd);
|
rstream_set_file(read_stream, read_cmd_fd);
|
||||||
@ -66,17 +75,6 @@ void input_stop(void)
|
|||||||
rstream_stop(read_stream);
|
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.
|
// 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, 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 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
|
// Check if a character is available for reading
|
||||||
@ -135,7 +134,7 @@ bool os_char_avail(void)
|
|||||||
void os_breakcheck(void)
|
void os_breakcheck(void)
|
||||||
{
|
{
|
||||||
if (curr_tmode == TMODE_RAW && input_poll(0))
|
if (curr_tmode == TMODE_RAW && input_poll(0))
|
||||||
fill_input_buf(false);
|
convert_input();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Test whether a file descriptor refers to a terminal.
|
/// 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 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)
|
static bool input_poll(int32_t ms)
|
||||||
{
|
{
|
||||||
if (embedded_mode) {
|
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
|
// This is a replacement for the old `WaitForChar` function in os_unix.c
|
||||||
static InbufPollResult inbuf_poll(int32_t ms)
|
static InbufPollResult inbuf_poll(int32_t ms)
|
||||||
{
|
{
|
||||||
if (input_available()) {
|
if (typebuf_was_filled || rbuffer_pending(input_buffer)) {
|
||||||
return kInputAvail;
|
return kInputAvail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,6 +233,60 @@ static void read_cb(RStream *rstream, void *data, bool at_eof)
|
|||||||
started_reading = true;
|
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 int push_event_key(uint8_t *buf, int maxlen)
|
||||||
{
|
{
|
||||||
static const uint8_t key[3] = { K_SPECIAL, KS_EXTRA, KE_EVENT };
|
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
|
// Check if there's pending input
|
||||||
bool input_ready(void)
|
static bool input_ready(void)
|
||||||
{
|
{
|
||||||
return rstream_pending(read_stream) > 0 || eof;
|
return rstream_pending(read_stream) > 0 || eof;
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "nvim/api/private/defs.h"
|
||||||
|
|
||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
# include "os/input.h.generated.h"
|
# include "os/input.h.generated.h"
|
||||||
#endif
|
#endif
|
||||||
|
242
src/nvim/ui.c
242
src/nvim/ui.c
@ -228,247 +228,6 @@ void ui_breakcheck(void)
|
|||||||
* for them.
|
* 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.
|
* Exit because of an input read error.
|
||||||
*/
|
*/
|
||||||
@ -954,3 +713,4 @@ void im_save_status(long *psave)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -339,10 +339,6 @@ enum {
|
|||||||
#define fnamencmp(x, y, n) vim_fnamencmp((char_u *)(x), (char_u *)(y), \
|
#define fnamencmp(x, y, n) vim_fnamencmp((char_u *)(x), (char_u *)(y), \
|
||||||
(size_t)(n))
|
(size_t)(n))
|
||||||
|
|
||||||
#if defined(UNIX) || defined(FEAT_GUI)
|
|
||||||
# define USE_INPUT_BUF
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef EINTR
|
#ifndef EINTR
|
||||||
# define read_eintr(fd, buf, count) vim_read((fd), (buf), (count))
|
# define read_eintr(fd, buf, count) vim_read((fd), (buf), (count))
|
||||||
# define write_eintr(fd, buf, count) vim_write((fd), (buf), (count))
|
# define write_eintr(fd, buf, count) vim_write((fd), (buf), (count))
|
||||||
|
Loading…
Reference in New Issue
Block a user