aboutsummaryrefslogtreecommitdiff
path: root/libbb/lineedit.c
diff options
context:
space:
mode:
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 ccf3e0dc8..e1404fb68 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -86,8 +86,8 @@ struct lineedit_statics {
86 volatile unsigned cmdedit_termw; /* = 80; */ /* actual terminal width */ 86 volatile unsigned cmdedit_termw; /* = 80; */ /* actual terminal width */
87 sighandler_t previous_SIGWINCH_handler; 87 sighandler_t previous_SIGWINCH_handler;
88 88
89 unsigned cmdedit_x; /* real x terminal position */ 89 unsigned cmdedit_x; /* real x (col) terminal position */
90 unsigned cmdedit_y; /* pseudoreal y terminal position */ 90 unsigned cmdedit_y; /* pseudoreal y (row) terminal position */
91 unsigned cmdedit_prmt_len; /* length of prompt (without colors etc) */ 91 unsigned cmdedit_prmt_len; /* length of prompt (without colors etc) */
92 92
93 unsigned cursor; 93 unsigned cursor;
@@ -299,6 +299,16 @@ static void input_backward(unsigned num)
299 299
300static void put_prompt(void) 300static void put_prompt(void)
301{ 301{
302#if ENABLE_FEATURE_EDITING_ASK_TERMINAL
303 /* Ask terminal where is cursor now.
304 * lineedit_read_key handles response and corrects
305 * our idea of current cursor position.
306 * Testcase: run "echo -n long_line_long_line_long_line",
307 * then type in a long, wrapping command and try to
308 * delete it using backspace key.
309 */
310 out1str("\033" "[6n");
311#endif
302 out1str(cmdedit_prompt); 312 out1str(cmdedit_prompt);
303 cursor = 0; 313 cursor = 0;
304 { 314 {
@@ -1430,18 +1440,33 @@ static void win_changed(int nsig)
1430 signal(SIGWINCH, win_changed); /* rearm ourself */ 1440 signal(SIGWINCH, win_changed); /* rearm ourself */
1431} 1441}
1432 1442
1433static int lineedit_read_key(smalluint *read_key_bufsize, char *read_key_buffer) 1443static int lineedit_read_key(char *read_key_buffer)
1434{ 1444{
1435 int ic; 1445 int64_t ic;
1436 struct pollfd pfd; 1446 struct pollfd pfd;
1447
1437 pfd.fd = STDIN_FILENO; 1448 pfd.fd = STDIN_FILENO;
1438 pfd.events = POLLIN; 1449 pfd.events = POLLIN;
1439 do { 1450 do {
1451 poll_again:
1440 /* Wait for input. Can't just call read_key, it will return 1452 /* Wait for input. Can't just call read_key, it will return
1441 * at once if stdin is in non-blocking mode. */ 1453 * at once if stdin is in non-blocking mode. */
1442 safe_poll(&pfd, 1, -1); 1454 safe_poll(&pfd, 1, -1);
1443 /* note: read_key sets errno to 0 on success: */ 1455 /* note: read_key sets errno to 0 on success: */
1444 ic = read_key(STDIN_FILENO, read_key_bufsize, read_key_buffer); 1456 ic = read_key(STDIN_FILENO, read_key_buffer);
1457 if (ENABLE_FEATURE_EDITING_ASK_TERMINAL
1458 && (int32_t)ic == KEYCODE_CURSOR_POS
1459 ) {
1460 int col = ((ic >> 32) & 0x7fff) - 1;
1461 if (col > 0) {
1462 cmdedit_x += col;
1463 while (cmdedit_x >= cmdedit_termw) {
1464 cmdedit_x -= cmdedit_termw;
1465 cmdedit_y++;
1466 }
1467 }
1468 goto poll_again;
1469 }
1445 } while (errno == EAGAIN); 1470 } while (errno == EAGAIN);
1446 return ic; 1471 return ic;
1447} 1472}
@@ -1482,7 +1507,6 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
1482#endif 1507#endif
1483 struct termios initial_settings; 1508 struct termios initial_settings;
1484 struct termios new_settings; 1509 struct termios new_settings;
1485 smalluint read_key_bufsize;
1486 char read_key_buffer[KEYCODE_BUFFER_SIZE]; 1510 char read_key_buffer[KEYCODE_BUFFER_SIZE];
1487 1511
1488 INIT_S(); 1512 INIT_S();
@@ -1561,7 +1585,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
1561 1585
1562 while (1) { 1586 while (1) {
1563 fflush(NULL); 1587 fflush(NULL);
1564 ic = lineedit_read_key(&read_key_bufsize, read_key_buffer); 1588 ic = lineedit_read_key(read_key_buffer);
1565 1589
1566#if ENABLE_FEATURE_EDITING_VI 1590#if ENABLE_FEATURE_EDITING_VI
1567 newdelflag = 1; 1591 newdelflag = 1;
@@ -1738,7 +1762,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
1738 sc = cursor; 1762 sc = cursor;
1739 prev_ic = ic; 1763 prev_ic = ic;
1740 1764
1741 ic = lineedit_read_key(&read_key_bufsize, read_key_buffer); 1765 ic = lineedit_read_key(read_key_buffer);
1742 if (errno) /* error */ 1766 if (errno) /* error */
1743 goto prepare_to_die; 1767 goto prepare_to_die;
1744 1768
@@ -1801,7 +1825,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
1801 put(); 1825 put();
1802 break; 1826 break;
1803 case 'r'|VI_CMDMODE_BIT: 1827 case 'r'|VI_CMDMODE_BIT:
1804 ic = lineedit_read_key(&read_key_bufsize, read_key_buffer); 1828 ic = lineedit_read_key(read_key_buffer);
1805 if (errno) /* error */ 1829 if (errno) /* error */
1806 goto prepare_to_die; 1830 goto prepare_to_die;
1807 if (ic < ' ' || ic > 255) { 1831 if (ic < ' ' || ic > 255) {