lineedit: improve Unicode handling (still buggy though)
authorDenys Vlasenko <vda.linux@googlemail.com>
Mon, 19 Aug 2013 14:44:05 +0000 (16:44 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Mon, 19 Aug 2013 14:44:05 +0000 (16:44 +0200)
function                                             old     new   delta
unicode_strlen                                         -      31     +31
read_line_input                                     3876    3879      +3
lineedit_read_key                                    255     246      -9
parse_and_put_prompt                                 785     755     -30
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 1/2 up/down: 34/-39)             Total: -5 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
libbb/lineedit.c
libbb/unicode.c

index 1313dd5..ecf3066 100644 (file)
@@ -1763,7 +1763,7 @@ static void ask_terminal(void)
 static void parse_and_put_prompt(const char *prmt_ptr)
 {
        cmdedit_prompt = prmt_ptr;
-       cmdedit_prmt_len = strlen(prmt_ptr);
+       cmdedit_prmt_len = unicode_strlen(prmt_ptr);
        put_prompt();
 }
 #else
@@ -1781,7 +1781,7 @@ static void parse_and_put_prompt(const char *prmt_ptr)
        char c;
        char *pbuf;
 
-       cmdedit_prmt_len = 0;
+       /*cmdedit_prmt_len = 0; - already is */
 
        cbuf[1] = '\0'; /* never changes */
 
@@ -1915,7 +1915,8 @@ static void parse_and_put_prompt(const char *prmt_ptr)
                                }
                                case '[': case ']':
                                        if (c == flg_not_length) {
-                                               flg_not_length = (flg_not_length == '[' ? ']' : '[');
+                                               /* Toggle '['/']' hex 5b/5d */
+                                               flg_not_length ^= 6;
                                                continue;
                                        }
                                        break;
@@ -1925,8 +1926,13 @@ static void parse_and_put_prompt(const char *prmt_ptr)
                cbuf[0] = c;
                cur_prmt_len = strlen(pbuf);
                prmt_len += cur_prmt_len;
-               if (flg_not_length != ']')
+               if (flg_not_length != ']') {
+#if 0 /*ENABLE_UNICODE_SUPPORT - won't work, pbuf is one BYTE string here. FIXME */
+                       cmdedit_prmt_len += unicode_strlen(pbuf);
+#else
                        cmdedit_prmt_len += cur_prmt_len;
+#endif
+               }
                prmt_mem_ptr = strcat(xrealloc(prmt_mem_ptr, prmt_len+1), pbuf);
                free(free_me);
        } /* while */
@@ -1996,7 +2002,15 @@ static int lineedit_read_key(char *read_key_buffer, int timeout)
                        S.sent_ESC_br6n = 0;
                        if (cursor == 0) { /* otherwise it may be bogus */
                                int col = ((ic >> 32) & 0x7fff) - 1;
-                               if (col > cmdedit_prmt_len) {
+                               /*
+                                * Is col > cmdedit_prmt_len?
+                                * If yes (terminal says cursor is farther to the right
+                                * of where we think it should be),
+                                * the prompt wasn't printed starting at col 1,
+                                * there was additional text before it.
+                                */
+                               if ((int)(col - cmdedit_prmt_len) > 0) {
+                                       /* Fix our understanding of current x position */
                                        cmdedit_x += (col - cmdedit_prmt_len);
                                        while (cmdedit_x >= cmdedit_termw) {
                                                cmdedit_x -= cmdedit_termw;
@@ -2087,6 +2101,7 @@ static int32_t reverse_i_search(void)
        char read_key_buffer[KEYCODE_BUFFER_SIZE];
        const char *matched_history_line;
        const char *saved_prompt;
+       unsigned saved_prmt_len;
        int32_t ic;
 
        matched_history_line = NULL;
@@ -2095,6 +2110,7 @@ static int32_t reverse_i_search(void)
 
        /* Save and replace the prompt */
        saved_prompt = cmdedit_prompt;
+       saved_prmt_len = cmdedit_prmt_len;
        goto set_prompt;
 
        while (1) {
@@ -2170,7 +2186,7 @@ static int32_t reverse_i_search(void)
                                        free((char*)cmdedit_prompt);
  set_prompt:
                                        cmdedit_prompt = xasprintf("(reverse-i-search)'%s': ", match_buf);
-                                       cmdedit_prmt_len = strlen(cmdedit_prompt);
+                                       cmdedit_prmt_len = unicode_strlen(cmdedit_prompt);
                                        goto do_redraw;
                                }
                        }
@@ -2192,7 +2208,7 @@ static int32_t reverse_i_search(void)
 
        free((char*)cmdedit_prompt);
        cmdedit_prompt = saved_prompt;
-       cmdedit_prmt_len = strlen(cmdedit_prompt);
+       cmdedit_prmt_len = saved_prmt_len;
        redraw(cmdedit_y, command_len - cursor);
 
        return ic;
index 2e5dd5a..9c4da50 100644 (file)
@@ -43,8 +43,7 @@ void FAST_FUNC reinit_unicode(const char *LANG)
        setlocale(LC_CTYPE, LANG ? LANG : "");
 
        /* In unicode, this is a one character string */
-// can use unicode_strlen(string) too, but otherwise unicode_strlen() is unused
-       width = mbstowcs(NULL, unicode_0x394, INT_MAX);
+       width = unicode_strlen(unicode_0x394);
        unicode_status = (width == 1 ? UNICODE_ON : UNICODE_OFF);
 }
 
@@ -986,7 +985,6 @@ int FAST_FUNC unicode_bidi_is_neutral_wchar(wint_t wc)
 
 /* The rest is mostly same for libc and for "homegrown" support */
 
-#if 0 // UNUSED
 size_t FAST_FUNC unicode_strlen(const char *string)
 {
        size_t width = mbstowcs(NULL, string, INT_MAX);
@@ -994,7 +992,6 @@ size_t FAST_FUNC unicode_strlen(const char *string)
                return strlen(string);
        return width;
 }
-#endif
 
 size_t FAST_FUNC unicode_strwidth(const char *string)
 {