aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2010-05-17 00:45:44 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2010-05-17 00:45:44 +0200
commit248c324f7c6d407467ab3ad9057dfe33fb2723d8 (patch)
tree2f9831a30685bfdee75872bf58639a527144eec2
parentd9a3e89f501800c3e7c779b7e9545a5c80134593 (diff)
downloadbusybox-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.c67
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
416static 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) */
418static void input_backward(unsigned num) 430static 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
472static 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 */