diff options
author | Nguyễn Thái Ngọc Duy <pclouds@gmail.com> | 2009-05-06 20:39:23 +1000 |
---|---|---|
committer | Nguyễn Thái Ngọc Duy <pclouds@gmail.com> | 2009-05-06 20:39:23 +1000 |
commit | ff9e7fa2ce2e7ee2f1f09d436c796463e449363f (patch) | |
tree | 5225d58e89ec181c4f80aec97914623e48f14230 | |
parent | 045c0eb7df3c169f006c8167c52648446cbdacc3 (diff) | |
download | busybox-w32-ff9e7fa2ce2e7ee2f1f09d436c796463e449363f.tar.gz busybox-w32-ff9e7fa2ce2e7ee2f1f09d436c796463e449363f.tar.bz2 busybox-w32-ff9e7fa2ce2e7ee2f1f09d436c796463e449363f.zip |
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.
-rw-r--r-- | libbb/lineedit.c | 70 |
1 files changed, 70 insertions, 0 deletions
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 @@ | |||
62 | 62 | ||
63 | static line_input_t *state; | 63 | static line_input_t *state; |
64 | 64 | ||
65 | #ifdef __MINGW32__ | ||
66 | struct termios { | ||
67 | int c_lflag; | ||
68 | int c_cc[3]; | ||
69 | }; | ||
70 | #define safe_read(fd,buf,n) wincon_read(fd,buf,n) | ||
71 | /* True value does not matter because it's emulated */ | ||
72 | #define ICANON 1 | ||
73 | #define ECHO 2 | ||
74 | #define ECHONL 4 | ||
75 | #define ISIG 8 | ||
76 | |||
77 | #define VMIN 0 | ||
78 | #define VTIME 1 | ||
79 | #define VINTR 2 | ||
80 | |||
81 | static int wincon_read(int fd, char *buf, int size); | ||
82 | #endif | ||
83 | |||
65 | static struct termios initial_settings, new_settings; | 84 | static struct termios initial_settings, new_settings; |
66 | 85 | ||
67 | static volatile unsigned cmdedit_termw = 80; /* actual terminal width */ | 86 | static volatile unsigned cmdedit_termw = 80; /* actual terminal width */ |
@@ -1208,10 +1227,15 @@ static void parse_prompt(const char *prmt_ptr) | |||
1208 | } | 1227 | } |
1209 | #endif | 1228 | #endif |
1210 | 1229 | ||
1230 | #ifdef __MINGW32__ | ||
1231 | #define setTermSettings(fd, argp) | ||
1232 | #define getTermSettings(fd, argp) ((struct termios *)argp)->c_lflag = ECHO; | ||
1233 | #else | ||
1211 | #define setTermSettings(fd, argp) tcsetattr(fd, TCSANOW, argp) | 1234 | #define setTermSettings(fd, argp) tcsetattr(fd, TCSANOW, argp) |
1212 | #define getTermSettings(fd, argp) tcgetattr(fd, argp); | 1235 | #define getTermSettings(fd, argp) tcgetattr(fd, argp); |
1213 | 1236 | ||
1214 | static sighandler_t previous_SIGWINCH_handler; | 1237 | static sighandler_t previous_SIGWINCH_handler; |
1238 | #endif | ||
1215 | 1239 | ||
1216 | static void cmdedit_setwidth(unsigned w, int redraw_flg) | 1240 | static void cmdedit_setwidth(unsigned w, int redraw_flg) |
1217 | { | 1241 | { |
@@ -1230,8 +1254,10 @@ static void win_changed(int nsig) | |||
1230 | int width; | 1254 | int width; |
1231 | get_terminal_width_height(0, &width, NULL); | 1255 | get_terminal_width_height(0, &width, NULL); |
1232 | cmdedit_setwidth(width, nsig /* - just a yes/no flag */); | 1256 | cmdedit_setwidth(width, nsig /* - just a yes/no flag */); |
1257 | #ifndef __MINGW32__ | ||
1233 | if (nsig == SIGWINCH) | 1258 | if (nsig == SIGWINCH) |
1234 | signal(SIGWINCH, win_changed); /* rearm ourself */ | 1259 | signal(SIGWINCH, win_changed); /* rearm ourself */ |
1260 | #endif | ||
1235 | } | 1261 | } |
1236 | 1262 | ||
1237 | /* | 1263 | /* |
@@ -1295,8 +1321,10 @@ int read_line_input(const char* prompt, char* command, int maxsize, line_input_t | |||
1295 | new_settings.c_cc[VINTR] = _POSIX_VDISABLE; | 1321 | new_settings.c_cc[VINTR] = _POSIX_VDISABLE; |
1296 | setTermSettings(0, (void *) &new_settings); | 1322 | setTermSettings(0, (void *) &new_settings); |
1297 | 1323 | ||
1324 | #ifndef __MINGW32__ | ||
1298 | /* Now initialize things */ | 1325 | /* Now initialize things */ |
1299 | previous_SIGWINCH_handler = signal(SIGWINCH, win_changed); | 1326 | previous_SIGWINCH_handler = signal(SIGWINCH, win_changed); |
1327 | #endif | ||
1300 | win_changed(0); /* do initial resizing */ | 1328 | win_changed(0); /* do initial resizing */ |
1301 | #if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR | 1329 | #if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR |
1302 | { | 1330 | { |
@@ -1727,8 +1755,10 @@ int read_line_input(const char* prompt, char* command, int maxsize, line_input_t | |||
1727 | #endif | 1755 | #endif |
1728 | /* restore initial_settings */ | 1756 | /* restore initial_settings */ |
1729 | setTermSettings(STDIN_FILENO, (void *) &initial_settings); | 1757 | setTermSettings(STDIN_FILENO, (void *) &initial_settings); |
1758 | #ifndef __MINGW32__ | ||
1730 | /* restore SIGWINCH handler */ | 1759 | /* restore SIGWINCH handler */ |
1731 | signal(SIGWINCH, previous_SIGWINCH_handler); | 1760 | signal(SIGWINCH, previous_SIGWINCH_handler); |
1761 | #endif | ||
1732 | fflush(stdout); | 1762 | fflush(stdout); |
1733 | return command_len; | 1763 | return command_len; |
1734 | } | 1764 | } |
@@ -1740,6 +1770,46 @@ line_input_t *new_line_input_t(int flags) | |||
1740 | return n; | 1770 | return n; |
1741 | } | 1771 | } |
1742 | 1772 | ||
1773 | #ifdef __MINGW32__ | ||
1774 | #include <windef.h> | ||
1775 | #include <wincon.h> | ||
1776 | #include "strbuf.h" | ||
1777 | |||
1778 | #undef safe_read | ||
1779 | static int wincon_read(int fd, char *buf, int size) | ||
1780 | { | ||
1781 | static struct strbuf input = STRBUF_INIT; | ||
1782 | HANDLE cin = GetStdHandle(STD_INPUT_HANDLE); | ||
1783 | static int initialized = 0; | ||
1784 | |||
1785 | if (fd != 0) | ||
1786 | die("wincon_read is for stdin only"); | ||
1787 | if (cin == INVALID_HANDLE_VALUE) | ||
1788 | return safe_read(fd, buf, size); | ||
1789 | if (!initialized) { | ||
1790 | SetConsoleMode(cin, ENABLE_ECHO_INPUT); | ||
1791 | initialized = 1; | ||
1792 | } | ||
1793 | while (input.len < size) { | ||
1794 | INPUT_RECORD record; | ||
1795 | DWORD nevent = 0, nevent_out; | ||
1796 | int ch; | ||
1797 | |||
1798 | if (!ReadConsoleInput(cin, &record, 1, &nevent_out)) | ||
1799 | return -1; | ||
1800 | if (record.EventType != KEY_EVENT || !record.Event.KeyEvent.bKeyDown) | ||
1801 | continue; | ||
1802 | ch = record.Event.KeyEvent.uChar.AsciiChar; | ||
1803 | /* Ctrl-X is handled by ReadConsoleInput, Alt-X is not needed anyway */ | ||
1804 | strbuf_addch(&input, ch); | ||
1805 | } | ||
1806 | memcpy(buf, input.buf, size); | ||
1807 | memcpy(input.buf, input.buf+size, input.len-size+1); | ||
1808 | strbuf_setlen(&input, input.len-size); | ||
1809 | return size; | ||
1810 | } | ||
1811 | #endif | ||
1812 | |||
1743 | #else | 1813 | #else |
1744 | 1814 | ||
1745 | #undef read_line_input | 1815 | #undef read_line_input |