diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-05-17 00:45:44 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-05-17 00:45:44 +0200 |
commit | 248c324f7c6d407467ab3ad9057dfe33fb2723d8 (patch) | |
tree | 2f9831a30685bfdee75872bf58639a527144eec2 | |
parent | d9a3e89f501800c3e7c779b7e9545a5c80134593 (diff) | |
download | busybox-w32-248c324f7c6d407467ab3ad9057dfe33fb2723d8.tar.gz busybox-w32-248c324f7c6d407467ab3ad9057dfe33fb2723d8.tar.bz2 busybox-w32-248c324f7c6d407467ab3ad9057dfe33fb2723d8.zip |
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>
-rw-r--r-- | libbb/lineedit.c | 67 |
1 files changed, 46 insertions, 21 deletions
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index bc089ab1c..836fc0089 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
@@ -413,12 +413,22 @@ static void beep(void) | |||
413 | bb_putchar('\007'); | 413 | bb_putchar('\007'); |
414 | } | 414 | } |
415 | 415 | ||
416 | static void put_prompt(void) | ||
417 | { | ||
418 | unsigned w; | ||
419 | |||
420 | out1str(cmdedit_prompt); | ||
421 | fflush_all(); | ||
422 | cursor = 0; | ||
423 | w = cmdedit_termw; /* read volatile var once */ | ||
424 | cmdedit_y = cmdedit_prmt_len / w; /* new quasireal y */ | ||
425 | cmdedit_x = cmdedit_prmt_len % w; | ||
426 | } | ||
427 | |||
416 | /* Move back one character */ | 428 | /* Move back one character */ |
417 | /* (optimized for slow terminals) */ | 429 | /* (optimized for slow terminals) */ |
418 | static void input_backward(unsigned num) | 430 | static void input_backward(unsigned num) |
419 | { | 431 | { |
420 | int count_y; | ||
421 | |||
422 | if (num > cursor) | 432 | if (num > cursor) |
423 | num = cursor; | 433 | num = cursor; |
424 | if (num == 0) | 434 | if (num == 0) |
@@ -456,29 +466,44 @@ static void input_backward(unsigned num) | |||
456 | } | 466 | } |
457 | 467 | ||
458 | /* Need to go one or more lines up */ | 468 | /* Need to go one or more lines up */ |
459 | //FIXME: this does not work correctly if prev line has one "unfilled" screen position | 469 | if (ENABLE_UNICODE_WIDE_WCHARS) { |
460 | //caused by wide unicode char not fitting in that one screen position. | 470 | /* With wide chars, it is hard to "backtrack" |
461 | num -= cmdedit_x; | 471 | * and reliably figure out where to put cursor. |
462 | { | 472 | * Example (<> is a wide char; # is an ordinary char, _ cursor): |
463 | unsigned w = cmdedit_termw; /* volatile var */ | 473 | * |prompt: <><> | |
474 | * |<><><><><><> | | ||
475 | * |_ | | ||
476 | * and user presses left arrow. num = 1, cmdedit_x = 0, | ||
477 | * We need to go up one line, and then - how do we know that | ||
478 | * we need to go *10* positions to the right? Because | ||
479 | * |prompt: <>#<>| | ||
480 | * |<><><>#<><><>| | ||
481 | * |_ | | ||
482 | * in this situation we need to go *11* positions to the right. | ||
483 | * | ||
484 | * A simpler thing to do is to redraw everything from the start | ||
485 | * up to new cursor position (which is already known): | ||
486 | */ | ||
487 | unsigned sv_cursor; | ||
488 | if (cmdedit_y > 0) /* up to start y */ | ||
489 | printf("\033[%uA", cmdedit_y); | ||
490 | bb_putchar('\r'); | ||
491 | cmdedit_y = 0; | ||
492 | sv_cursor = cursor; | ||
493 | put_prompt(); /* sets cursor to 0 */ | ||
494 | while (cursor < sv_cursor) | ||
495 | put_cur_glyph_and_inc_cursor(); | ||
496 | } else { | ||
497 | int count_y; | ||
498 | unsigned w; | ||
499 | num -= cmdedit_x; | ||
500 | w = cmdedit_termw; /* read volatile var once */ | ||
464 | count_y = 1 + (num / w); | 501 | count_y = 1 + (num / w); |
465 | cmdedit_y -= count_y; | 502 | cmdedit_y -= count_y; |
466 | cmdedit_x = w * count_y - num; | 503 | cmdedit_x = w * count_y - num; |
504 | /* go to 1st column; go up; go to correct column */ | ||
505 | printf("\r" "\033[%uA" "\033[%uC", count_y, cmdedit_x); | ||
467 | } | 506 | } |
468 | /* go to 1st column; go up; go to correct column */ | ||
469 | printf("\r" "\033[%uA" "\033[%uC", count_y, cmdedit_x); | ||
470 | } | ||
471 | |||
472 | static void put_prompt(void) | ||
473 | { | ||
474 | unsigned w; | ||
475 | |||
476 | out1str(cmdedit_prompt); | ||
477 | fflush_all(); | ||
478 | cursor = 0; | ||
479 | w = cmdedit_termw; /* read volatile var once */ | ||
480 | cmdedit_y = cmdedit_prmt_len / w; /* new quasireal y */ | ||
481 | cmdedit_x = cmdedit_prmt_len % w; | ||
482 | } | 507 | } |
483 | 508 | ||
484 | /* draw prompt, editor line, and clear tail */ | 509 | /* draw prompt, editor line, and clear tail */ |