From ff9e7fa2ce2e7ee2f1f09d436c796463e449363f Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Wed, 6 May 2009 20:39:23 +1000 Subject: libbb/lineedit: simple adaptation to support tab-completion in ash this is far from perfect as a vt100 emulation, but enough to make ash's tab completion work. --- libbb/lineedit.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/libbb/lineedit.c b/libbb/lineedit.c index b950d7f26..b349bc6f2 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -62,6 +62,25 @@ static line_input_t *state; +#ifdef __MINGW32__ +struct termios { + int c_lflag; + int c_cc[3]; +}; +#define safe_read(fd,buf,n) wincon_read(fd,buf,n) +/* True value does not matter because it's emulated */ +#define ICANON 1 +#define ECHO 2 +#define ECHONL 4 +#define ISIG 8 + +#define VMIN 0 +#define VTIME 1 +#define VINTR 2 + +static int wincon_read(int fd, char *buf, int size); +#endif + static struct termios initial_settings, new_settings; static volatile unsigned cmdedit_termw = 80; /* actual terminal width */ @@ -1208,10 +1227,15 @@ static void parse_prompt(const char *prmt_ptr) } #endif +#ifdef __MINGW32__ +#define setTermSettings(fd, argp) +#define getTermSettings(fd, argp) ((struct termios *)argp)->c_lflag = ECHO; +#else #define setTermSettings(fd, argp) tcsetattr(fd, TCSANOW, argp) #define getTermSettings(fd, argp) tcgetattr(fd, argp); static sighandler_t previous_SIGWINCH_handler; +#endif static void cmdedit_setwidth(unsigned w, int redraw_flg) { @@ -1230,8 +1254,10 @@ static void win_changed(int nsig) int width; get_terminal_width_height(0, &width, NULL); cmdedit_setwidth(width, nsig /* - just a yes/no flag */); +#ifndef __MINGW32__ if (nsig == SIGWINCH) signal(SIGWINCH, win_changed); /* rearm ourself */ +#endif } /* @@ -1295,8 +1321,10 @@ int read_line_input(const char* prompt, char* command, int maxsize, line_input_t new_settings.c_cc[VINTR] = _POSIX_VDISABLE; setTermSettings(0, (void *) &new_settings); +#ifndef __MINGW32__ /* Now initialize things */ previous_SIGWINCH_handler = signal(SIGWINCH, win_changed); +#endif win_changed(0); /* do initial resizing */ #if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR { @@ -1727,8 +1755,10 @@ int read_line_input(const char* prompt, char* command, int maxsize, line_input_t #endif /* restore initial_settings */ setTermSettings(STDIN_FILENO, (void *) &initial_settings); +#ifndef __MINGW32__ /* restore SIGWINCH handler */ signal(SIGWINCH, previous_SIGWINCH_handler); +#endif fflush(stdout); return command_len; } @@ -1740,6 +1770,46 @@ line_input_t *new_line_input_t(int flags) return n; } +#ifdef __MINGW32__ +#include +#include +#include "strbuf.h" + +#undef safe_read +static int wincon_read(int fd, char *buf, int size) +{ + static struct strbuf input = STRBUF_INIT; + HANDLE cin = GetStdHandle(STD_INPUT_HANDLE); + static int initialized = 0; + + if (fd != 0) + die("wincon_read is for stdin only"); + if (cin == INVALID_HANDLE_VALUE) + return safe_read(fd, buf, size); + if (!initialized) { + SetConsoleMode(cin, ENABLE_ECHO_INPUT); + initialized = 1; + } + while (input.len < size) { + INPUT_RECORD record; + DWORD nevent = 0, nevent_out; + int ch; + + if (!ReadConsoleInput(cin, &record, 1, &nevent_out)) + return -1; + if (record.EventType != KEY_EVENT || !record.Event.KeyEvent.bKeyDown) + continue; + ch = record.Event.KeyEvent.uChar.AsciiChar; + /* Ctrl-X is handled by ReadConsoleInput, Alt-X is not needed anyway */ + strbuf_addch(&input, ch); + } + memcpy(buf, input.buf, size); + memcpy(input.buf, input.buf+size, input.len-size+1); + strbuf_setlen(&input, input.len-size); + return size; +} +#endif + #else #undef read_line_input -- cgit v1.2.3-55-g6feb