lineedit: change how cmdedit_set_out_char works

Rename two badly names functions, use "clear to end of screen"
to eliminate annoying problems with clearing wide/combining chars,
and such. Run tested.

function                                             old     new   delta
put_cur_glyph_and_inc_cursor                           -     124    +124
put_till_end_and_adv_cursor                            -      24     +24
input_delete                                         125     130      +5
Ceos                                                   5       4      -1
Ceol                                                   5       4      -1
input_end                                             24       -     -24
cmdedit_set_out_char                                 122       -    -122
------------------------------------------------------------------------------
(add/remove: 2/2 grow/shrink: 1/2 up/down: 153/-148)            Total: 5 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2010-05-11 14:49:13 +02:00
parent da1382410b
commit 94043e8ad2
2 changed files with 43 additions and 34 deletions

View File

@ -65,8 +65,8 @@ static const char SOn[] ALIGN1 = "\033[0m";
/* terminal bell sequence */ /* terminal bell sequence */
static const char bell[] ALIGN1 = "\007"; static const char bell[] ALIGN1 = "\007";
/* Clear-end-of-line and Clear-end-of-screen ESC sequence */ /* Clear-end-of-line and Clear-end-of-screen ESC sequence */
static const char Ceol[] ALIGN1 = "\033[0K"; static const char Ceol[] ALIGN1 = "\033[K";
static const char Ceos[] ALIGN1 = "\033[0J"; static const char Ceos[] ALIGN1 = "\033[J";
/* Cursor motion arbitrary destination ESC sequence */ /* Cursor motion arbitrary destination ESC sequence */
static const char CMrc[] ALIGN1 = "\033[%d;%dH"; static const char CMrc[] ALIGN1 = "\033[%d;%dH";
/* Cursor motion up and down ESC sequence */ /* Cursor motion up and down ESC sequence */

View File

@ -66,6 +66,10 @@
#endif #endif
#define SEQ_CLEAR_TILL_END_OF_SCREEN "\033[J"
//#define SEQ_CLEAR_TILL_END_OF_LINE "\033[K"
#undef CHAR_T #undef CHAR_T
#if ENABLE_UNICODE_SUPPORT #if ENABLE_UNICODE_SUPPORT
# define BB_NUL ((wchar_t)0) # define BB_NUL ((wchar_t)0)
@ -221,13 +225,13 @@ static size_t load_string(const char *src, int maxsize)
} }
static unsigned save_string(char *dst, unsigned maxsize) static unsigned save_string(char *dst, unsigned maxsize)
{ {
#if !ENABLE_UNICODE_PRESERVE_BROKEN # if !ENABLE_UNICODE_PRESERVE_BROKEN
ssize_t len = wcstombs(dst, command_ps, maxsize - 1); ssize_t len = wcstombs(dst, command_ps, maxsize - 1);
if (len < 0) if (len < 0)
len = 0; len = 0;
dst[len] = '\0'; dst[len] = '\0';
return len; return len;
#else # else
unsigned dstpos = 0; unsigned dstpos = 0;
unsigned srcpos = 0; unsigned srcpos = 0;
@ -256,7 +260,7 @@ static unsigned save_string(char *dst, unsigned maxsize)
} }
dst[dstpos] = '\0'; dst[dstpos] = '\0';
return dstpos; return dstpos;
#endif # endif
} }
/* I thought just fputwc(c, stdout) would work. But no... */ /* I thought just fputwc(c, stdout) would work. But no... */
static void BB_PUTCHAR(wchar_t c) static void BB_PUTCHAR(wchar_t c)
@ -293,19 +297,19 @@ static void save_string(char *dst, unsigned maxsize)
* Advance cursor on screen. If we reached right margin, scroll text up * Advance cursor on screen. If we reached right margin, scroll text up
* and remove terminal margin effect by printing 'next_char' */ * and remove terminal margin effect by printing 'next_char' */
#define HACK_FOR_WRONG_WIDTH 1 #define HACK_FOR_WRONG_WIDTH 1
#if HACK_FOR_WRONG_WIDTH static void put_cur_glyph_and_inc_cursor(void)
static void cmdedit_set_out_char(void)
#define cmdedit_set_out_char(next_char) cmdedit_set_out_char()
#else
static void cmdedit_set_out_char(int next_char)
#endif
{ {
CHAR_T c = command_ps[cursor]; CHAR_T c = command_ps[cursor];
if (c == BB_NUL) { if (c == BB_NUL) {
/* erase character after end of input string */ /* erase character after end of input string */
c = ' '; c = ' ';
} else {
/* advance cursor only if we aren't at the end yet */
cursor++;
cmdedit_x++;
} }
#if ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT #if ENABLE_FEATURE_NONPRINTABLE_INVERSE_PUT
/* Display non-printable characters in reverse */ /* Display non-printable characters in reverse */
if (!BB_isprint(c)) { if (!BB_isprint(c)) {
@ -321,7 +325,7 @@ static void cmdedit_set_out_char(int next_char)
{ {
BB_PUTCHAR(c); BB_PUTCHAR(c);
} }
if (++cmdedit_x >= cmdedit_termw) { if (cmdedit_x >= cmdedit_termw) {
/* terminal is scrolled down */ /* terminal is scrolled down */
cmdedit_y++; cmdedit_y++;
cmdedit_x = 0; cmdedit_x = 0;
@ -335,27 +339,32 @@ static void cmdedit_set_out_char(int next_char)
* this will break things: there will be one extra empty line */ * this will break things: there will be one extra empty line */
puts("\r"); /* + implicit '\n' */ puts("\r"); /* + implicit '\n' */
#else #else
/* Works ok only if cmdedit_termw is correct */ /* VT-10x terminals don't wrap cursor to next line when last char
/* destroy "(auto)margin" */ * on the line is printed - cursor stays "over" this char.
bb_putchar(next_char); * Need to print _next_ char too (first one to appear on next line)
* to make cursor move down to next line.
*/
/* Works ok only if cmdedit_termw is correct. */
c = command_ps[cursor];
if (c == BB_NUL)
c = ' ';
BB_PUTCHAR(c);
bb_putchar('\b'); bb_putchar('\b');
#endif #endif
} }
// Huh? What if command_ps[cursor] == BB_NUL (we are at the end already?)
cursor++;
} }
/* Move to end of line (by printing all chars till the end) */ /* Move to end of line (by printing all chars till the end) */
static void input_end(void) static void put_till_end_and_adv_cursor(void)
{ {
while (cursor < command_len) while (cursor < command_len)
cmdedit_set_out_char(' '); put_cur_glyph_and_inc_cursor();
} }
/* Go to the next line */ /* Go to the next line */
static void goto_new_line(void) static void goto_new_line(void)
{ {
input_end(); put_till_end_and_adv_cursor();
if (cmdedit_x) if (cmdedit_x)
bb_putchar('\n'); bb_putchar('\n');
} }
@ -433,8 +442,8 @@ static void redraw(int y, int back_cursor)
printf("\033[%uA", y); printf("\033[%uA", y);
bb_putchar('\r'); bb_putchar('\r');
put_prompt(); put_prompt();
input_end(); /* rewrite */ put_till_end_and_adv_cursor();
printf("\033[J"); /* erase after cursor */ printf(SEQ_CLEAR_TILL_END_OF_SCREEN);
input_backward(back_cursor); input_backward(back_cursor);
} }
@ -468,8 +477,9 @@ static void input_delete(int save)
* simplified into (command_len - j) */ * simplified into (command_len - j) */
(command_len - j) * sizeof(command_ps[0])); (command_len - j) * sizeof(command_ps[0]));
command_len--; command_len--;
input_end(); /* rewrite new line */ put_till_end_and_adv_cursor();
cmdedit_set_out_char(' '); /* erase char */ /* Last char is still visible, erase it (and more) */
printf(SEQ_CLEAR_TILL_END_OF_SCREEN);
input_backward(cursor - j); /* back to old pos cursor */ input_backward(cursor - j); /* back to old pos cursor */
} }
@ -487,7 +497,7 @@ static void put(void)
(command_len - cursor + 1) * sizeof(command_ps[0])); (command_len - cursor + 1) * sizeof(command_ps[0]));
memcpy(command_ps + cursor, delbuf, j * sizeof(command_ps[0])); memcpy(command_ps + cursor, delbuf, j * sizeof(command_ps[0]));
command_len += j; command_len += j;
input_end(); /* rewrite new line */ put_till_end_and_adv_cursor();
input_backward(cursor - ocursor - j + 1); /* at end of new text */ input_backward(cursor - ocursor - j + 1); /* at end of new text */
} }
#endif #endif
@ -505,7 +515,7 @@ static void input_backspace(void)
static void input_forward(void) static void input_forward(void)
{ {
if (cursor < command_len) if (cursor < command_len)
cmdedit_set_out_char(command_ps[cursor + 1]); put_cur_glyph_and_inc_cursor();
} }
#if ENABLE_FEATURE_TAB_COMPLETION #if ENABLE_FEATURE_TAB_COMPLETION
@ -1955,7 +1965,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
case CTRL('E'): case CTRL('E'):
vi_case('$'|VI_CMDMODE_BIT:) vi_case('$'|VI_CMDMODE_BIT:)
/* Control-e -- End of line */ /* Control-e -- End of line */
input_end(); put_till_end_and_adv_cursor();
break; break;
case CTRL('F'): case CTRL('F'):
vi_case('l'|VI_CMDMODE_BIT:) vi_case('l'|VI_CMDMODE_BIT:)
@ -1984,12 +1994,12 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
/* Control-k -- clear to end of line */ /* Control-k -- clear to end of line */
command_ps[cursor] = BB_NUL; command_ps[cursor] = BB_NUL;
command_len = cursor; command_len = cursor;
printf("\033[J"); printf(SEQ_CLEAR_TILL_END_OF_SCREEN);
break; break;
case CTRL('L'): case CTRL('L'):
vi_case(CTRL('L')|VI_CMDMODE_BIT:) vi_case(CTRL('L')|VI_CMDMODE_BIT:)
/* Control-l -- clear screen */ /* Control-l -- clear screen */
printf("\033[H"); printf("\033[H"); /* cursor to top,left */
redraw(0, command_len - cursor); redraw(0, command_len - cursor);
break; break;
#if MAX_HISTORY > 0 #if MAX_HISTORY > 0
@ -2040,7 +2050,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
vi_cmdmode = 0; vi_cmdmode = 0;
break; break;
case 'A'|VI_CMDMODE_BIT: case 'A'|VI_CMDMODE_BIT:
input_end(); put_till_end_and_adv_cursor();
vi_cmdmode = 0; vi_cmdmode = 0;
break; break;
case 'x'|VI_CMDMODE_BIT: case 'x'|VI_CMDMODE_BIT:
@ -2200,7 +2210,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
input_backward(cursor); input_backward(cursor);
break; break;
case KEYCODE_END: case KEYCODE_END:
input_end(); put_till_end_and_adv_cursor();
break; break;
default: default:
@ -2260,7 +2270,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
/* We are at the end, append */ /* We are at the end, append */
command_ps[cursor] = ic; command_ps[cursor] = ic;
command_ps[cursor + 1] = BB_NUL; command_ps[cursor + 1] = BB_NUL;
cmdedit_set_out_char(' '); put_cur_glyph_and_inc_cursor();
if (unicode_bidi_isrtl(ic)) if (unicode_bidi_isrtl(ic))
input_backward(1); input_backward(1);
} else { } else {
@ -2273,8 +2283,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
/* is right-to-left char, or neutral one (e.g. comma) was just added to rtl text? */ /* is right-to-left char, or neutral one (e.g. comma) was just added to rtl text? */
if (!isrtl_str()) if (!isrtl_str())
sc++; /* no */ sc++; /* no */
/* rewrite from cursor */ put_till_end_and_adv_cursor();
input_end();
/* to prev x pos + 1 */ /* to prev x pos + 1 */
input_backward(cursor - sc); input_backward(cursor - sc);
} }