diff options
author | Eliseo Martínez <eliseomarmol@gmail.com> | 2014-05-12 02:25:17 +0200 |
---|---|---|
committer | Eliseo Martínez <eliseomarmol@gmail.com> | 2014-05-15 20:46:01 +0200 |
commit | da51dc9cf202772f60bd2da975dbef257bd9237c (patch) | |
tree | 5c16b93238a153f55634e9323077f30c8133970c /src/nvim/os/input.c | |
parent | ffe61e5ba1721340ca51d56bae3ddaca415fb5bc (diff) | |
download | rneovim-da51dc9cf202772f60bd2da975dbef257bd9237c.tar.gz rneovim-da51dc9cf202772f60bd2da975dbef257bd9237c.tar.bz2 rneovim-da51dc9cf202772f60bd2da975dbef257bd9237c.zip |
Introduce nvim namespace: Move files.
Move files from src/ to src/nvim/.
- src/nvim/ becomes the new root dir for nvim executable sources.
- src/libnvim/ is planned to become root dir of the neovim library.
Diffstat (limited to 'src/nvim/os/input.c')
-rw-r--r-- | src/nvim/os/input.c | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c new file mode 100644 index 0000000000..4310edd514 --- /dev/null +++ b/src/nvim/os/input.c @@ -0,0 +1,195 @@ +#include <string.h> +#include <stdint.h> +#include <stdbool.h> + +#include <uv.h> + +#include "os/input.h" +#include "os/event.h" +#include "os/rstream_defs.h" +#include "os/rstream.h" +#include "vim.h" +#include "ui.h" +#include "fileio.h" +#include "getchar.h" +#include "term.h" + +#define READ_BUFFER_SIZE 256 + +typedef enum { + kInputNone, + kInputAvail, + kInputEof +} InbufPollResult; + +static RStream *read_stream; +static bool eof = false, started_reading = false; + +static InbufPollResult inbuf_poll(int32_t ms); +static void stderr_switch(void); +static void read_cb(RStream *rstream, void *data, bool eof); +// Helper function used to push bytes from the 'event' key sequence partially +// between calls to os_inchar when maxlen < 3 +static int push_event_key(uint8_t *buf, int maxlen); + +void input_init() +{ + read_stream = rstream_new(read_cb, READ_BUFFER_SIZE, NULL, false); + rstream_set_file(read_stream, read_cmd_fd); +} + +// Check if there's pending input +bool input_ready() +{ + return rstream_available(read_stream) > 0 || eof; +} + +// Listen for input +void input_start() +{ + rstream_start(read_stream); +} + +// Stop listening for input +void input_stop() +{ + 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) +{ + 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) +{ + InbufPollResult result; + + if (event_is_pending()) { + // Return pending event bytes + return push_event_key(buf, maxlen); + } + + if (ms >= 0) { + if ((result = inbuf_poll(ms)) == kInputNone) { + return 0; + } + } else { + if ((result = inbuf_poll(p_ut)) == kInputNone) { + if (trigger_cursorhold() && maxlen >= 3 + && !typebuf_changed(tb_change_cnt)) { + buf[0] = K_SPECIAL; + buf[1] = KS_EXTRA; + buf[2] = KE_CURSORHOLD; + return 3; + } + + before_blocking(); + result = inbuf_poll(-1); + } + } + + // If there are pending events, return the keys directly + if (event_is_pending()) { + return push_event_key(buf, maxlen); + } + + // If input was put directly in typeahead buffer bail out here. + if (typebuf_changed(tb_change_cnt)) { + return 0; + } + + if (result == kInputEof) { + read_error_exit(); + return 0; + } + + return read_from_input_buf(buf, (int64_t)maxlen); +} + +// Check if a character is available for reading +bool os_char_avail() +{ + return inbuf_poll(0) == kInputAvail; +} + +// Check for CTRL-C typed by reading all available characters. +// In cooked mode we should get SIGINT, no need to check. +void os_breakcheck() +{ + if (curr_tmode == TMODE_RAW && event_poll(0)) + fill_input_buf(false); +} + +bool os_isatty(int fd) +{ + return uv_guess_handle(fd) == UV_TTY; +} + +// This is a replacement for the old `WaitForChar` function in os_unix.c +static InbufPollResult inbuf_poll(int32_t ms) +{ + if (input_available()) { + return kInputAvail; + } + + if (event_poll(ms)) { + return eof && rstream_available(read_stream) == 0 ? + kInputEof : + kInputAvail; + } + + return kInputNone; +} + +static void stderr_switch() +{ + int mode = cur_tmode; + // We probably set the wrong file descriptor to raw mode. Switch back to + // cooked mode + settmode(TMODE_COOK); + // Stop the idle handle + rstream_stop(read_stream); + // Use stderr for stdin, also works for shell commands. + read_cmd_fd = 2; + // Initialize and start the input stream + rstream_set_file(read_stream, read_cmd_fd); + rstream_start(read_stream); + // Set the mode back to what it was + settmode(mode); +} + +static void read_cb(RStream *rstream, void *data, bool at_eof) +{ + if (at_eof) { + if (!started_reading + && rstream_is_regular_file(rstream) + && os_isatty(STDERR_FILENO)) { + // Read error. Since stderr is a tty we switch to reading from it. This + // is for handling for cases like "foo | xargs vim" because xargs + // redirects stdin from /dev/null. Previously, this was done in ui.c + stderr_switch(); + } else { + eof = true; + } + } + + started_reading = true; +} + +static int push_event_key(uint8_t *buf, int maxlen) +{ + static const uint8_t key[3] = { K_SPECIAL, KS_EXTRA, KE_EVENT }; + static int key_idx = 0; + int buf_idx = 0; + + do { + buf[buf_idx++] = key[key_idx++]; + key_idx %= 3; + } while (key_idx > 0 && buf_idx < maxlen); + + return buf_idx; +} |