mdebug

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 511f74d0b8278686633b0a0a23a0ceb96154e138
parent d41764edb947e68e7c23da4ec1f1fc9d04101cf8
Author: Brian Swetland <swetland@frotz.net>
Date:   Sat, 20 Jun 2015 18:59:19 -0700

linenoise: add mechnism for preempting linenoise control of stdio

Diffstat:
Mtools/linenoise.c | 100+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Mtools/linenoise.h | 4++++
2 files changed, 102 insertions(+), 2 deletions(-)

diff --git a/tools/linenoise.c b/tools/linenoise.c @@ -715,6 +715,97 @@ void linenoiseEditDeletePrevWord(struct linenoiseState *l) { refreshLine(l); } +#ifndef LINENOISE_INTERRUPTIBLE +#define linenoiseRead(l, buf, count) read((*(l)).ifd, buf, count) +#define linenoiseLock() do {} while (0) +#define linenoiseUnlock() do {} while (0) +#else +#include <pthread.h> +#include <poll.h> + +static pthread_mutex_t linenoise_lock = PTHREAD_MUTEX_INITIALIZER; +static int linenoise_active = 0; +static int linenoise_repaint = 0; +static int linenoise_pipefds[2] = { -1, -1 }; + +/* allow linenoise to be interruptible */ +void linenoiseInit(void) { + if (pipe(linenoise_pipefds) < 0) ; +} + +/* Call before writing to stdout when linenoise may be active in + * another thread. This will suspend linenoise activity and + * clear the text entry line. linenoiseResume() must be called + * after your io is complete so that linenoise may continue. */ +void linenoisePause(void) { + pthread_mutex_lock(&linenoise_lock); + if (linenoise_active) { + if (write(1, "\x1b[0G\x1b[0K", 8) < 0) ; + disableRawMode(STDIN_FILENO); + } +} + +/* Call when io is done after you've called linenoisePause() + * to suspend linenoise processing during your io. */ +void linenoiseResume(void) { + if (linenoise_active) { + char x = 0; + linenoise_repaint = 1; + enableRawMode(STDIN_FILENO); + if (write(linenoise_pipefds[1], &x, 1) < 0) ; + } + pthread_mutex_unlock(&linenoise_lock); +} + +void linenoiseLock(void) { + pthread_mutex_lock(&linenoise_lock); + linenoise_active = 1; +} + +void linenoiseUnlock(void) { + linenoise_active = 0; + pthread_mutex_unlock(&linenoise_lock); +} + +ssize_t linenoiseRead(struct linenoiseState *l, void *ptr, int len) { + struct pollfd fds[2]; + int nfds, r; + + for(;;) { + fds[0].fd = l->ifd; + fds[0].events = POLLIN; + fds[0].revents = 0; + if (linenoise_pipefds[0] < 0) { + nfds = 1; + fds[1].fd = linenoise_pipefds[0]; + fds[1].events = POLLIN; + } else { + nfds = 2; + } + fds[1].revents = 0; + + /* wait for input or refresh request */ + pthread_mutex_unlock(&linenoise_lock); + r = poll(fds, nfds, -1); + pthread_mutex_lock(&linenoise_lock); + + if (linenoise_repaint) { + linenoise_repaint = 0; + refreshLine(l); + } + if (r < 0) return -1; + if (fds[1].revents & POLLIN) { + char x; + if (read(linenoise_pipefds[0], &x, 1) < 0) ; + continue; + } + if (fds[0].revents & POLLIN) { + return read(l->ifd, ptr, len); + } + } +} +#endif + /* This function is the core of the line editing capability of linenoise. * It expects 'fd' to be already in "raw mode" so that every key pressed * will be returned ASAP to read(). @@ -755,7 +846,7 @@ static int linenoiseEdit(int stdin_fd, int stdout_fd, char *buf, size_t buflen, int nread; char seq[3]; - nread = read(l.ifd,&c,1); + nread = linenoiseRead(&l,&c,1); if (nread <= 0) return l.len; /* Only autocomplete when the callback is set. It returns < 0 when @@ -946,10 +1037,15 @@ static int linenoiseRaw(char *buf, size_t buflen, const char *prompt) { } } else { /* Interactive editing. */ - if (enableRawMode(STDIN_FILENO) == -1) return -1; + linenoiseLock(); + if (enableRawMode(STDIN_FILENO) == -1) { + linenoiseUnlock(); + return -1; + } count = linenoiseEdit(STDIN_FILENO, STDOUT_FILENO, buf, buflen, prompt); disableRawMode(STDIN_FILENO); printf("\n"); + linenoiseUnlock(); } return count; } diff --git a/tools/linenoise.h b/tools/linenoise.h @@ -61,6 +61,10 @@ void linenoiseClearScreen(void); void linenoiseSetMultiLine(int ml); void linenoisePrintKeyCodes(void); +void linenoiseInit(void); +void linenoisePause(void); +void linenoiseResume(void); + #ifdef __cplusplus } #endif