lineedit: fix moving backwards across lines with wide chars

function                                             old     new   delta
input_backward                                       212     208      -4

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2010-05-17 00:45:44 +02:00
parent d9a3e89f50
commit 248c324f7c

View File

@ -413,12 +413,22 @@ static void beep(void)
bb_putchar('\007'); bb_putchar('\007');
} }
static void put_prompt(void)
{
unsigned w;
out1str(cmdedit_prompt);
fflush_all();
cursor = 0;
w = cmdedit_termw; /* read volatile var once */
cmdedit_y = cmdedit_prmt_len / w; /* new quasireal y */
cmdedit_x = cmdedit_prmt_len % w;
}
/* Move back one character */ /* Move back one character */
/* (optimized for slow terminals) */ /* (optimized for slow terminals) */
static void input_backward(unsigned num) static void input_backward(unsigned num)
{ {
int count_y;
if (num > cursor) if (num > cursor)
num = cursor; num = cursor;
if (num == 0) if (num == 0)
@ -456,29 +466,44 @@ static void input_backward(unsigned num)
} }
/* Need to go one or more lines up */ /* Need to go one or more lines up */
//FIXME: this does not work correctly if prev line has one "unfilled" screen position if (ENABLE_UNICODE_WIDE_WCHARS) {
//caused by wide unicode char not fitting in that one screen position. /* With wide chars, it is hard to "backtrack"
num -= cmdedit_x; * and reliably figure out where to put cursor.
{ * Example (<> is a wide char; # is an ordinary char, _ cursor):
unsigned w = cmdedit_termw; /* volatile var */ * |prompt: <><> |
* |<><><><><><> |
* |_ |
* and user presses left arrow. num = 1, cmdedit_x = 0,
* We need to go up one line, and then - how do we know that
* we need to go *10* positions to the right? Because
* |prompt: <>#<>|
* |<><><>#<><><>|
* |_ |
* in this situation we need to go *11* positions to the right.
*
* A simpler thing to do is to redraw everything from the start
* up to new cursor position (which is already known):
*/
unsigned sv_cursor;
if (cmdedit_y > 0) /* up to start y */
printf("\033[%uA", cmdedit_y);
bb_putchar('\r');
cmdedit_y = 0;
sv_cursor = cursor;
put_prompt(); /* sets cursor to 0 */
while (cursor < sv_cursor)
put_cur_glyph_and_inc_cursor();
} else {
int count_y;
unsigned w;
num -= cmdedit_x;
w = cmdedit_termw; /* read volatile var once */
count_y = 1 + (num / w); count_y = 1 + (num / w);
cmdedit_y -= count_y; cmdedit_y -= count_y;
cmdedit_x = w * count_y - num; cmdedit_x = w * count_y - num;
/* go to 1st column; go up; go to correct column */
printf("\r" "\033[%uA" "\033[%uC", count_y, cmdedit_x);
} }
/* go to 1st column; go up; go to correct column */
printf("\r" "\033[%uA" "\033[%uC", count_y, cmdedit_x);
}
static void put_prompt(void)
{
unsigned w;
out1str(cmdedit_prompt);
fflush_all();
cursor = 0;
w = cmdedit_termw; /* read volatile var once */
cmdedit_y = cmdedit_prmt_len / w; /* new quasireal y */
cmdedit_x = cmdedit_prmt_len % w;
} }
/* draw prompt, editor line, and clear tail */ /* draw prompt, editor line, and clear tail */