diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2009-05-17 18:44:54 +0400 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-05-17 18:44:54 +0400 |
commit | 020f40693a08b836abdea74f3823a0bce0378ec5 (patch) | |
tree | 4ae11c9b2156cccc1af8904c11c195b25b2886b0 /libbb/lineedit.c | |
parent | 071ede1e5de784820f39c2546000c08d74b12f6d (diff) |
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.c | 42 |
1 files changed, 33 insertions, 9 deletions
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index ccf3e0dc8..e1404fb68 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) { |