aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNguyễn Thái Ngọc Duy <pclouds@gmail.com>2009-05-06 20:39:23 +1000
committerNguyễn Thái Ngọc Duy <pclouds@gmail.com>2009-05-06 20:39:23 +1000
commitff9e7fa2ce2e7ee2f1f09d436c796463e449363f (patch)
tree5225d58e89ec181c4f80aec97914623e48f14230
parent045c0eb7df3c169f006c8167c52648446cbdacc3 (diff)
downloadbusybox-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.c70
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
63static line_input_t *state; 63static line_input_t *state;
64 64
65#ifdef __MINGW32__
66struct 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
81static int wincon_read(int fd, char *buf, int size);
82#endif
83
65static struct termios initial_settings, new_settings; 84static struct termios initial_settings, new_settings;
66 85
67static volatile unsigned cmdedit_termw = 80; /* actual terminal width */ 86static 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
1214static sighandler_t previous_SIGWINCH_handler; 1237static sighandler_t previous_SIGWINCH_handler;
1238#endif
1215 1239
1216static void cmdedit_setwidth(unsigned w, int redraw_flg) 1240static 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
1779static 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