aboutsummaryrefslogtreecommitdiff
path: root/libbb/lineedit.c
diff options
context:
space:
mode:
authorNguyễn Thái Ngọc Duy <pclouds@gmail.com>2010-09-14 11:41:16 +1000
committerNguyễn Thái Ngọc Duy <pclouds@gmail.com>2010-09-14 11:41:16 +1000
commit743d85e7d1c2a721baf020b9d79f45f0df2420a9 (patch)
tree9e551b726ac2bf9fd8eafb2764e7237f352bb429 /libbb/lineedit.c
parent87911f4fcd86f7abc0aefba8e9cbec2ac9d127e4 (diff)
parentc7f95d23f6bc7e17a3b79decf83eb362b389e53a (diff)
downloadbusybox-w32-743d85e7d1c2a721baf020b9d79f45f0df2420a9.tar.gz
busybox-w32-743d85e7d1c2a721baf020b9d79f45f0df2420a9.tar.bz2
busybox-w32-743d85e7d1c2a721baf020b9d79f45f0df2420a9.zip
Merge branch 'origin/master' (early part)
Diffstat (limited to 'libbb/lineedit.c')
-rw-r--r--libbb/lineedit.c320
1 files changed, 214 insertions, 106 deletions
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 9a04c38bf..f7faf4639 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -42,14 +42,10 @@
42#include "libbb.h" 42#include "libbb.h"
43#include "unicode.h" 43#include "unicode.h"
44 44
45/* FIXME: obsolete CONFIG item? */
46#define ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT 0
47
48#ifdef TEST 45#ifdef TEST
49# define ENABLE_FEATURE_EDITING 0 46# define ENABLE_FEATURE_EDITING 0
50# define ENABLE_FEATURE_TAB_COMPLETION 0 47# define ENABLE_FEATURE_TAB_COMPLETION 0
51# define ENABLE_FEATURE_USERNAME_COMPLETION 0 48# define ENABLE_FEATURE_USERNAME_COMPLETION 0
52# define ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT 0
53#endif 49#endif
54 50
55 51
@@ -66,9 +62,13 @@
66#endif 62#endif
67 63
68 64
65#define SEQ_CLEAR_TILL_END_OF_SCREEN "\033[J"
66//#define SEQ_CLEAR_TILL_END_OF_LINE "\033[K"
67
68
69#undef CHAR_T 69#undef CHAR_T
70#if ENABLE_UNICODE_SUPPORT 70#if ENABLE_UNICODE_SUPPORT
71# define BB_NUL L'\0' 71# define BB_NUL ((wchar_t)0)
72# define CHAR_T wchar_t 72# define CHAR_T wchar_t
73static bool BB_isspace(CHAR_T c) { return ((unsigned)c < 256 && isspace(c)); } 73static bool BB_isspace(CHAR_T c) { return ((unsigned)c < 256 && isspace(c)); }
74# if ENABLE_FEATURE_EDITING_VI 74# if ENABLE_FEATURE_EDITING_VI
@@ -92,6 +92,14 @@ static bool BB_ispunct(CHAR_T c) { return ((unsigned)c < 256 && ispunct(c)); }
92#endif 92#endif
93 93
94 94
95# if ENABLE_UNICODE_PRESERVE_BROKEN
96# define unicode_mark_raw_byte(wc) ((wc) | 0x20000000)
97# define unicode_is_raw_byte(wc) ((wc) & 0x20000000)
98# else
99# define unicode_is_raw_byte(wc) 0
100# endif
101
102
95enum { 103enum {
96 /* We use int16_t for positions, need to limit line len */ 104 /* We use int16_t for positions, need to limit line len */
97 MAX_LINELEN = CONFIG_FEATURE_EDITING_MAX_LEN < 0x7ff0 105 MAX_LINELEN = CONFIG_FEATURE_EDITING_MAX_LEN < 0x7ff0
@@ -208,42 +216,107 @@ static size_t load_string(const char *src, int maxsize)
208 ssize_t len = mbstowcs(command_ps, src, maxsize - 1); 216 ssize_t len = mbstowcs(command_ps, src, maxsize - 1);
209 if (len < 0) 217 if (len < 0)
210 len = 0; 218 len = 0;
211 command_ps[len] = L'\0'; 219 command_ps[len] = 0;
212 return len; 220 return len;
213} 221}
214static size_t save_string(char *dst, int maxsize) 222static unsigned save_string(char *dst, unsigned maxsize)
215{ 223{
224# if !ENABLE_UNICODE_PRESERVE_BROKEN
216 ssize_t len = wcstombs(dst, command_ps, maxsize - 1); 225 ssize_t len = wcstombs(dst, command_ps, maxsize - 1);
217 if (len < 0) 226 if (len < 0)
218 len = 0; 227 len = 0;
219 dst[len] = '\0'; 228 dst[len] = '\0';
220 return len; 229 return len;
230# else
231 unsigned dstpos = 0;
232 unsigned srcpos = 0;
233
234 maxsize--;
235 while (dstpos < maxsize) {
236 wchar_t wc;
237 int n = srcpos;
238 while ((wc = command_ps[srcpos]) != 0
239 && !unicode_is_raw_byte(wc)
240 ) {
241 srcpos++;
242 }
243 command_ps[srcpos] = 0;
244 n = wcstombs(dst + dstpos, command_ps + n, maxsize - dstpos);
245 if (n < 0) /* should not happen */
246 break;
247 dstpos += n;
248 if (wc == 0) /* usually is */
249 break;
250 /* We do have invalid byte here! */
251 command_ps[srcpos] = wc; /* restore it */
252 srcpos++;
253 if (dstpos == maxsize)
254 break;
255 dst[dstpos++] = (char) wc;
256 }
257 dst[dstpos] = '\0';
258 return dstpos;
259# endif
221} 260}
222/* I thought just fputwc(c, stdout) would work. But no... */ 261/* I thought just fputwc(c, stdout) would work. But no... */
223static void BB_PUTCHAR(wchar_t c) 262static void BB_PUTCHAR(wchar_t c)
224{ 263{
225 char buf[MB_CUR_MAX + 1]; 264 char buf[MB_CUR_MAX + 1];
226 mbstate_t mbst = { 0 }; 265 mbstate_t mbst = { 0 };
227 ssize_t len = wcrtomb(buf, c, &mbst); 266 ssize_t len;
228 267
268 len = wcrtomb(buf, c, &mbst);
229 if (len > 0) { 269 if (len > 0) {
230 buf[len] = '\0'; 270 buf[len] = '\0';
231 fputs(buf, stdout); 271 fputs(buf, stdout);
232 } 272 }
233} 273}
234#else 274# if ENABLE_UNICODE_COMBINING_WCHARS || ENABLE_UNICODE_WIDE_WCHARS
275static wchar_t adjust_width_and_validate_wc(unsigned *width_adj, wchar_t wc)
276# else
277static wchar_t adjust_width_and_validate_wc(wchar_t wc)
278# define adjust_width_and_validate_wc(width_adj, wc) \
279 ((*(width_adj))++, adjust_width_and_validate_wc(wc))
280# endif
281{
282 int w = 1;
283
284 if (unicode_status == UNICODE_ON) {
285 if (wc > CONFIG_LAST_SUPPORTED_WCHAR) {
286 /* note: also true for unicode_is_raw_byte(wc) */
287 goto subst;
288 }
289 w = wcwidth(wc);
290 if ((ENABLE_UNICODE_COMBINING_WCHARS && w < 0)
291 || (!ENABLE_UNICODE_COMBINING_WCHARS && w <= 0)
292 || (!ENABLE_UNICODE_WIDE_WCHARS && w > 1)
293 ) {
294 subst:
295 w = 1;
296 wc = CONFIG_SUBST_WCHAR;
297 }
298 }
299
300# if ENABLE_UNICODE_COMBINING_WCHARS || ENABLE_UNICODE_WIDE_WCHARS
301 *width_adj += w;
302#endif
303 return wc;
304}
305#else /* !UNICODE */
235static size_t load_string(const char *src, int maxsize) 306static size_t load_string(const char *src, int maxsize)
236{ 307{
237 safe_strncpy(command_ps, src, maxsize); 308 safe_strncpy(command_ps, src, maxsize);
238 return strlen(command_ps); 309 return strlen(command_ps);
239} 310}
240# if ENABLE_FEATURE_TAB_COMPLETION 311# if ENABLE_FEATURE_TAB_COMPLETION
241static void save_string(char *dst, int maxsize) 312static void save_string(char *dst, unsigned maxsize)
242{ 313{
243 safe_strncpy(dst, command_ps, maxsize); 314 safe_strncpy(dst, command_ps, maxsize);
244} 315}
245# endif 316# endif
246# define BB_PUTCHAR(c) bb_putchar(c) 317# define BB_PUTCHAR(c) bb_putchar(c)
318/* Should never be called: */
319int adjust_width_and_validate_wc(unsigned *width_adj, int wc);
247#endif 320#endif
248 321
249 322
@@ -251,38 +324,35 @@ static void save_string(char *dst, int maxsize)
251 * Advance cursor on screen. If we reached right margin, scroll text up 324 * Advance cursor on screen. If we reached right margin, scroll text up
252 * and remove terminal margin effect by printing 'next_char' */ 325 * and remove terminal margin effect by printing 'next_char' */
253#define HACK_FOR_WRONG_WIDTH 1 326#define HACK_FOR_WRONG_WIDTH 1
254#if HACK_FOR_WRONG_WIDTH 327static void put_cur_glyph_and_inc_cursor(void)
255static void cmdedit_set_out_char(void)
256#define cmdedit_set_out_char(next_char) cmdedit_set_out_char()
257#else
258static void cmdedit_set_out_char(int next_char)
259#endif
260{ 328{
261 CHAR_T c = command_ps[cursor]; 329 CHAR_T c = command_ps[cursor];
330 unsigned width = 0;
331 int ofs_to_right;
262 332
263 if (c == BB_NUL) { 333 if (c == BB_NUL) {
264 /* erase character after end of input string */ 334 /* erase character after end of input string */
265 c = ' '; 335 c = ' ';
336 } else {
337 /* advance cursor only if we aren't at the end yet */
338 cursor++;
339 if (unicode_status == UNICODE_ON) {
340 IF_UNICODE_WIDE_WCHARS(width = cmdedit_x;)
341 c = adjust_width_and_validate_wc(&cmdedit_x, c);
342 IF_UNICODE_WIDE_WCHARS(width = cmdedit_x - width;)
343 } else {
344 cmdedit_x++;
345 }
266 } 346 }
267#if ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT 347
268 /* Display non-printable characters in reverse */ 348 ofs_to_right = cmdedit_x - cmdedit_termw;
269 if (!BB_isprint(c)) { 349 if (!ENABLE_UNICODE_WIDE_WCHARS || ofs_to_right <= 0) {
270 if (c >= 128) 350 /* c fits on this line */
271 c -= 128;
272 if (c < ' ')
273 c += '@';
274 if (c == 127)
275 c = '?';
276 printf("\033[7m%c\033[0m", c);
277 } else
278#endif
279 {
280 BB_PUTCHAR(c); 351 BB_PUTCHAR(c);
281 } 352 }
282 if (++cmdedit_x >= cmdedit_termw) { 353
283 /* terminal is scrolled down */ 354 if (ofs_to_right >= 0) {
284 cmdedit_y++; 355 /* we go to the next line */
285 cmdedit_x = 0;
286#if HACK_FOR_WRONG_WIDTH 356#if HACK_FOR_WRONG_WIDTH
287 /* This works better if our idea of term width is wrong 357 /* This works better if our idea of term width is wrong
288 * and it is actually wider (often happens on serial lines). 358 * and it is actually wider (often happens on serial lines).
@@ -293,55 +363,83 @@ static void cmdedit_set_out_char(int next_char)
293 * this will break things: there will be one extra empty line */ 363 * this will break things: there will be one extra empty line */
294 puts("\r"); /* + implicit '\n' */ 364 puts("\r"); /* + implicit '\n' */
295#else 365#else
296 /* Works ok only if cmdedit_termw is correct */ 366 /* VT-10x terminals don't wrap cursor to next line when last char
297 /* destroy "(auto)margin" */ 367 * on the line is printed - cursor stays "over" this char.
298 bb_putchar(next_char); 368 * Need to print _next_ char too (first one to appear on next line)
369 * to make cursor move down to next line.
370 */
371 /* Works ok only if cmdedit_termw is correct. */
372 c = command_ps[cursor];
373 if (c == BB_NUL)
374 c = ' ';
375 BB_PUTCHAR(c);
299 bb_putchar('\b'); 376 bb_putchar('\b');
300#endif 377#endif
378 cmdedit_y++;
379 if (!ENABLE_UNICODE_WIDE_WCHARS || ofs_to_right == 0) {
380 width = 0;
381 } else { /* ofs_to_right > 0 */
382 /* wide char c didn't fit on prev line */
383 BB_PUTCHAR(c);
384 }
385 cmdedit_x = width;
301 } 386 }
302// Huh? What if command_ps[cursor] == BB_NUL (we are at the end already?)
303 cursor++;
304} 387}
305 388
306/* Move to end of line (by printing all chars till the end) */ 389/* Move to end of line (by printing all chars till the end) */
307static void input_end(void) 390static void put_till_end_and_adv_cursor(void)
308{ 391{
309 while (cursor < command_len) 392 while (cursor < command_len)
310 cmdedit_set_out_char(' '); 393 put_cur_glyph_and_inc_cursor();
311} 394}
312 395
313/* Go to the next line */ 396/* Go to the next line */
314static void goto_new_line(void) 397static void goto_new_line(void)
315{ 398{
316 input_end(); 399 put_till_end_and_adv_cursor();
317 if (cmdedit_x) 400 if (cmdedit_x != 0)
318 bb_putchar('\n'); 401 bb_putchar('\n');
319} 402}
320 403
321 404static void beep(void)
322static void out1str(const char *s)
323{ 405{
324 if (s) 406 bb_putchar('\007');
325 fputs(s, stdout);
326} 407}
327 408
328static void beep(void) 409static void put_prompt(void)
329{ 410{
330 bb_putchar('\007'); 411 unsigned w;
412
413 fputs(cmdedit_prompt, stdout);
414 fflush_all();
415 cursor = 0;
416 w = cmdedit_termw; /* read volatile var once */
417 cmdedit_y = cmdedit_prmt_len / w; /* new quasireal y */
418 cmdedit_x = cmdedit_prmt_len % w;
331} 419}
332 420
333/* Move back one character */ 421/* Move back one character */
334/* (optimized for slow terminals) */ 422/* (optimized for slow terminals) */
335static void input_backward(unsigned num) 423static void input_backward(unsigned num)
336{ 424{
337 int count_y;
338
339 if (num > cursor) 425 if (num > cursor)
340 num = cursor; 426 num = cursor;
341 if (!num) 427 if (num == 0)
342 return; 428 return;
343 cursor -= num; 429 cursor -= num;
344 430
431 if ((ENABLE_UNICODE_COMBINING_WCHARS || ENABLE_UNICODE_WIDE_WCHARS)
432 && unicode_status == UNICODE_ON
433 ) {
434 /* correct NUM to be equal to _screen_ width */
435 int n = num;
436 num = 0;
437 while (--n >= 0)
438 adjust_width_and_validate_wc(&num, command_ps[cursor + n]);
439 if (num == 0)
440 return;
441 }
442
345 if (cmdedit_x >= num) { 443 if (cmdedit_x >= num) {
346 cmdedit_x -= num; 444 cmdedit_x -= num;
347 if (num <= 4) { 445 if (num <= 4) {
@@ -361,38 +459,61 @@ static void input_backward(unsigned num)
361 } 459 }
362 460
363 /* Need to go one or more lines up */ 461 /* Need to go one or more lines up */
364 num -= cmdedit_x; 462 if (ENABLE_UNICODE_WIDE_WCHARS) {
365 { 463 /* With wide chars, it is hard to "backtrack"
366 unsigned w = cmdedit_termw; /* volatile var */ 464 * and reliably figure out where to put cursor.
367 count_y = 1 + (num / w); 465 * Example (<> is a wide char; # is an ordinary char, _ cursor):
368 cmdedit_y -= count_y; 466 * |prompt: <><> |
369 cmdedit_x = w * count_y - num; 467 * |<><><><><><> |
468 * |_ |
469 * and user presses left arrow. num = 1, cmdedit_x = 0,
470 * We need to go up one line, and then - how do we know that
471 * we need to go *10* positions to the right? Because
472 * |prompt: <>#<>|
473 * |<><><>#<><><>|
474 * |_ |
475 * in this situation we need to go *11* positions to the right.
476 *
477 * A simpler thing to do is to redraw everything from the start
478 * up to new cursor position (which is already known):
479 */
480 unsigned sv_cursor;
481 /* go to 1st column; go up to first line */
482 printf("\r" "\033[%uA", cmdedit_y);
483 cmdedit_y = 0;
484 sv_cursor = cursor;
485 put_prompt(); /* sets cursor to 0 */
486 while (cursor < sv_cursor)
487 put_cur_glyph_and_inc_cursor();
488 } else {
489 int lines_up;
490 unsigned width;
491 /* num = chars to go back from the beginning of current line: */
492 num -= cmdedit_x;
493 width = cmdedit_termw; /* read volatile var once */
494 /* num=1...w: one line up, w+1...2w: two, etc: */
495 lines_up = 1 + (num - 1) / width;
496 cmdedit_x = (width * cmdedit_y - num) % width;
497 cmdedit_y -= lines_up;
498 /* go to 1st column; go up */
499 printf("\r" "\033[%uA", lines_up);
500 /* go to correct column.
501 * xterm, konsole, Linux VT interpret 0 as 1 below! wow.
502 * need to *make sure* we skip it if cmdedit_x == 0 */
503 if (cmdedit_x)
504 printf("\033[%uC", cmdedit_x);
370 } 505 }
371 /* go to 1st column; go up; go to correct column */
372 printf("\r" "\033[%dA" "\033[%dC", count_y, cmdedit_x);
373}
374
375static void put_prompt(void)
376{
377 unsigned w;
378
379 out1str(cmdedit_prompt);
380 fflush_all();
381 cursor = 0;
382 w = cmdedit_termw; /* read volatile var once */
383 cmdedit_y = cmdedit_prmt_len / w; /* new quasireal y */
384 cmdedit_x = cmdedit_prmt_len % w;
385} 506}
386 507
387/* draw prompt, editor line, and clear tail */ 508/* draw prompt, editor line, and clear tail */
388static void redraw(int y, int back_cursor) 509static void redraw(int y, int back_cursor)
389{ 510{
390 if (y > 0) /* up to start y */ 511 if (y > 0) /* up y lines */
391 printf("\033[%uA", y); 512 printf("\033[%uA", y);
392 bb_putchar('\r'); 513 bb_putchar('\r');
393 put_prompt(); 514 put_prompt();
394 input_end(); /* rewrite */ 515 put_till_end_and_adv_cursor();
395 printf("\033[J"); /* erase after cursor */ 516 printf(SEQ_CLEAR_TILL_END_OF_SCREEN);
396 input_backward(back_cursor); 517 input_backward(back_cursor);
397} 518}
398 519
@@ -426,8 +547,9 @@ static void input_delete(int save)
426 * simplified into (command_len - j) */ 547 * simplified into (command_len - j) */
427 (command_len - j) * sizeof(command_ps[0])); 548 (command_len - j) * sizeof(command_ps[0]));
428 command_len--; 549 command_len--;
429 input_end(); /* rewrite new line */ 550 put_till_end_and_adv_cursor();
430 cmdedit_set_out_char(' '); /* erase char */ 551 /* Last char is still visible, erase it (and more) */
552 printf(SEQ_CLEAR_TILL_END_OF_SCREEN);
431 input_backward(cursor - j); /* back to old pos cursor */ 553 input_backward(cursor - j); /* back to old pos cursor */
432} 554}
433 555
@@ -445,7 +567,7 @@ static void put(void)
445 (command_len - cursor + 1) * sizeof(command_ps[0])); 567 (command_len - cursor + 1) * sizeof(command_ps[0]));
446 memcpy(command_ps + cursor, delbuf, j * sizeof(command_ps[0])); 568 memcpy(command_ps + cursor, delbuf, j * sizeof(command_ps[0]));
447 command_len += j; 569 command_len += j;
448 input_end(); /* rewrite new line */ 570 put_till_end_and_adv_cursor();
449 input_backward(cursor - ocursor - j + 1); /* at end of new text */ 571 input_backward(cursor - ocursor - j + 1); /* at end of new text */
450} 572}
451#endif 573#endif
@@ -463,7 +585,7 @@ static void input_backspace(void)
463static void input_forward(void) 585static void input_forward(void)
464{ 586{
465 if (cursor < command_len) 587 if (cursor < command_len)
466 cmdedit_set_out_char(command_ps[cursor + 1]); 588 put_cur_glyph_and_inc_cursor();
467} 589}
468 590
469#if ENABLE_FEATURE_TAB_COMPLETION 591#if ENABLE_FEATURE_TAB_COMPLETION
@@ -721,21 +843,13 @@ static NOINLINE int find_match(char *matchBuf, int *len_with_quotes)
721 } 843 }
722 844
723 /* mask \+symbol and convert '\t' to ' ' */ 845 /* mask \+symbol and convert '\t' to ' ' */
724 for (i = j = 0; matchBuf[i]; i++, j++) 846 for (i = j = 0; matchBuf[i]; i++, j++) {
725 if (matchBuf[i] == '\\') { 847 if (matchBuf[i] == '\\') {
726 collapse_pos(j, j + 1); 848 collapse_pos(j, j + 1);
727 int_buf[j] |= QUOT; 849 int_buf[j] |= QUOT;
728 i++; 850 i++;
729#if ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT
730 if (matchBuf[i] == '\t') /* algorithm equivalent */
731 int_buf[j] = ' ' | QUOT;
732#endif
733 } 851 }
734#if ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT 852 }
735 else if (matchBuf[i] == '\t')
736 int_buf[j] = ' ';
737#endif
738
739 /* mask "symbols" or 'symbols' */ 853 /* mask "symbols" or 'symbols' */
740 c2 = 0; 854 c2 = 0;
741 for (i = 0; int_buf[i]; i++) { 855 for (i = 0; int_buf[i]; i++) {
@@ -1509,7 +1623,7 @@ static void ask_terminal(void)
1509 pfd.events = POLLIN; 1623 pfd.events = POLLIN;
1510 if (safe_poll(&pfd, 1, 0) == 0) { 1624 if (safe_poll(&pfd, 1, 0) == 0) {
1511 S.sent_ESC_br6n = 1; 1625 S.sent_ESC_br6n = 1;
1512 out1str("\033" "[6n"); 1626 fputs("\033" "[6n", stdout);
1513 fflush_all(); /* make terminal see it ASAP! */ 1627 fflush_all(); /* make terminal see it ASAP! */
1514 } 1628 }
1515} 1629}
@@ -1727,13 +1841,11 @@ static int lineedit_read_key(char *read_key_buffer)
1727 pushback: 1841 pushback:
1728 /* Invalid sequence. Save all "bad bytes" except first */ 1842 /* Invalid sequence. Save all "bad bytes" except first */
1729 read_key_ungets(read_key_buffer, unicode_buf + 1, unicode_idx - 1); 1843 read_key_ungets(read_key_buffer, unicode_buf + 1, unicode_idx - 1);
1730 /* 1844# if !ENABLE_UNICODE_PRESERVE_BROKEN
1731 * ic = unicode_buf[0] sounds even better, but currently
1732 * this does not work: wchar_t[] -> char[] conversion
1733 * when lineedit finishes mangles such "raw bytes"
1734 * (by misinterpreting them as unicode chars):
1735 */
1736 ic = CONFIG_SUBST_WCHAR; 1845 ic = CONFIG_SUBST_WCHAR;
1846# else
1847 ic = unicode_mark_raw_byte(unicode_buf[0]);
1848# endif
1737 } else { 1849 } else {
1738 /* Valid unicode char, return its code */ 1850 /* Valid unicode char, return its code */
1739 ic = wc; 1851 ic = wc;
@@ -1925,7 +2037,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
1925 case CTRL('E'): 2037 case CTRL('E'):
1926 vi_case('$'|VI_CMDMODE_BIT:) 2038 vi_case('$'|VI_CMDMODE_BIT:)
1927 /* Control-e -- End of line */ 2039 /* Control-e -- End of line */
1928 input_end(); 2040 put_till_end_and_adv_cursor();
1929 break; 2041 break;
1930 case CTRL('F'): 2042 case CTRL('F'):
1931 vi_case('l'|VI_CMDMODE_BIT:) 2043 vi_case('l'|VI_CMDMODE_BIT:)
@@ -1954,12 +2066,12 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
1954 /* Control-k -- clear to end of line */ 2066 /* Control-k -- clear to end of line */
1955 command_ps[cursor] = BB_NUL; 2067 command_ps[cursor] = BB_NUL;
1956 command_len = cursor; 2068 command_len = cursor;
1957 printf("\033[J"); 2069 printf(SEQ_CLEAR_TILL_END_OF_SCREEN);
1958 break; 2070 break;
1959 case CTRL('L'): 2071 case CTRL('L'):
1960 vi_case(CTRL('L')|VI_CMDMODE_BIT:) 2072 vi_case(CTRL('L')|VI_CMDMODE_BIT:)
1961 /* Control-l -- clear screen */ 2073 /* Control-l -- clear screen */
1962 printf("\033[H"); 2074 printf("\033[H"); /* cursor to top,left */
1963 redraw(0, command_len - cursor); 2075 redraw(0, command_len - cursor);
1964 break; 2076 break;
1965#if MAX_HISTORY > 0 2077#if MAX_HISTORY > 0
@@ -2010,7 +2122,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
2010 vi_cmdmode = 0; 2122 vi_cmdmode = 0;
2011 break; 2123 break;
2012 case 'A'|VI_CMDMODE_BIT: 2124 case 'A'|VI_CMDMODE_BIT:
2013 input_end(); 2125 put_till_end_and_adv_cursor();
2014 vi_cmdmode = 0; 2126 vi_cmdmode = 0;
2015 break; 2127 break;
2016 case 'x'|VI_CMDMODE_BIT: 2128 case 'x'|VI_CMDMODE_BIT:
@@ -2170,7 +2282,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
2170 input_backward(cursor); 2282 input_backward(cursor);
2171 break; 2283 break;
2172 case KEYCODE_END: 2284 case KEYCODE_END:
2173 input_end(); 2285 put_till_end_and_adv_cursor();
2174 break; 2286 break;
2175 2287
2176 default: 2288 default:
@@ -2230,7 +2342,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
2230 /* We are at the end, append */ 2342 /* We are at the end, append */
2231 command_ps[cursor] = ic; 2343 command_ps[cursor] = ic;
2232 command_ps[cursor + 1] = BB_NUL; 2344 command_ps[cursor + 1] = BB_NUL;
2233 cmdedit_set_out_char(' '); 2345 put_cur_glyph_and_inc_cursor();
2234 if (unicode_bidi_isrtl(ic)) 2346 if (unicode_bidi_isrtl(ic))
2235 input_backward(1); 2347 input_backward(1);
2236 } else { 2348 } else {
@@ -2243,8 +2355,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
2243 /* is right-to-left char, or neutral one (e.g. comma) was just added to rtl text? */ 2355 /* is right-to-left char, or neutral one (e.g. comma) was just added to rtl text? */
2244 if (!isrtl_str()) 2356 if (!isrtl_str())
2245 sc++; /* no */ 2357 sc++; /* no */
2246 /* rewrite from cursor */ 2358 put_till_end_and_adv_cursor();
2247 input_end();
2248 /* to prev x pos + 1 */ 2359 /* to prev x pos + 1 */
2249 input_backward(cursor - sc); 2360 input_backward(cursor - sc);
2250 } 2361 }
@@ -2345,9 +2456,6 @@ int main(int argc, char **argv)
2345 "% "; 2456 "% ";
2346#endif 2457#endif
2347 2458
2348#if ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT
2349 setlocale(LC_ALL, "");
2350#endif
2351 while (1) { 2459 while (1) {
2352 int l; 2460 int l;
2353 l = read_line_input(prompt, buff); 2461 l = read_line_input(prompt, buff);