summaryrefslogtreecommitdiff
path: root/libbb/lineedit.c
diff options
context:
space:
mode:
authorDenys Vlasenko2009-05-17 16:44:54 +0200
committerDenys Vlasenko2009-05-17 16:44:54 +0200
commit020f40693a08b836abdea74f3823a0bce0378ec5 (patch)
tree4ae11c9b2156cccc1af8904c11c195b25b2886b0 /libbb/lineedit.c
parent071ede1e5de784820f39c2546000c08d74b12f6d (diff)
downloadbusybox-020f40693a08b836abdea74f3823a0bce0378ec5.zip
busybox-020f40693a08b836abdea74f3823a0bce0378ec5.tar.gz
line editing: add an option to emit ESC [ 6 n and use results
This makes line editing able to recognize case when cursor was not at the beginning of the line. It may also be adapted later to find out display size (serial line users would love it). Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'libbb/lineedit.c')
-rw-r--r--libbb/lineedit.c42
1 files changed, 33 insertions, 9 deletions
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index ccf3e0d..e1404fb 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -86,8 +86,8 @@ struct lineedit_statics {
volatile unsigned cmdedit_termw; /* = 80; */ /* actual terminal width */
sighandler_t previous_SIGWINCH_handler;
- unsigned cmdedit_x; /* real x terminal position */
- unsigned cmdedit_y; /* pseudoreal y terminal position */
+ unsigned cmdedit_x; /* real x (col) terminal position */
+ unsigned cmdedit_y; /* pseudoreal y (row) terminal position */
unsigned cmdedit_prmt_len; /* length of prompt (without colors etc) */
unsigned cursor;
@@ -299,6 +299,16 @@ static void input_backward(unsigned num)
static void put_prompt(void)
{
+#if ENABLE_FEATURE_EDITING_ASK_TERMINAL
+ /* Ask terminal where is cursor now.
+ * lineedit_read_key handles response and corrects
+ * our idea of current cursor position.
+ * Testcase: run "echo -n long_line_long_line_long_line",
+ * then type in a long, wrapping command and try to
+ * delete it using backspace key.
+ */
+ out1str("\033" "[6n");
+#endif
out1str(cmdedit_prompt);
cursor = 0;
{
@@ -1430,18 +1440,33 @@ static void win_changed(int nsig)
signal(SIGWINCH, win_changed); /* rearm ourself */
}
-static int lineedit_read_key(smalluint *read_key_bufsize, char *read_key_buffer)
+static int lineedit_read_key(char *read_key_buffer)
{
- int ic;
+ int64_t ic;
struct pollfd pfd;
+
pfd.fd = STDIN_FILENO;
pfd.events = POLLIN;
do {
+ poll_again:
/* Wait for input. Can't just call read_key, it will return
* at once if stdin is in non-blocking mode. */
safe_poll(&pfd, 1, -1);
/* note: read_key sets errno to 0 on success: */
- ic = read_key(STDIN_FILENO, read_key_bufsize, read_key_buffer);
+ ic = read_key(STDIN_FILENO, read_key_buffer);
+ if (ENABLE_FEATURE_EDITING_ASK_TERMINAL
+ && (int32_t)ic == KEYCODE_CURSOR_POS
+ ) {
+ int col = ((ic >> 32) & 0x7fff) - 1;
+ if (col > 0) {
+ cmdedit_x += col;
+ while (cmdedit_x >= cmdedit_termw) {
+ cmdedit_x -= cmdedit_termw;
+ cmdedit_y++;
+ }
+ }
+ goto poll_again;
+ }
} while (errno == EAGAIN);
return ic;
}
@@ -1482,7 +1507,6 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
#endif
struct termios initial_settings;
struct termios new_settings;
- smalluint read_key_bufsize;
char read_key_buffer[KEYCODE_BUFFER_SIZE];
INIT_S();
@@ -1561,7 +1585,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
while (1) {
fflush(NULL);
- ic = lineedit_read_key(&read_key_bufsize, read_key_buffer);
+ ic = lineedit_read_key(read_key_buffer);
#if ENABLE_FEATURE_EDITING_VI
newdelflag = 1;
@@ -1738,7 +1762,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
sc = cursor;
prev_ic = ic;
- ic = lineedit_read_key(&read_key_bufsize, read_key_buffer);
+ ic = lineedit_read_key(read_key_buffer);
if (errno) /* error */
goto prepare_to_die;
@@ -1801,7 +1825,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
put();
break;
case 'r'|VI_CMDMODE_BIT:
- ic = lineedit_read_key(&read_key_bufsize, read_key_buffer);
+ ic = lineedit_read_key(read_key_buffer);
if (errno) /* error */
goto prepare_to_die;
if (ic < ' ' || ic > 255) {