diff --git a/FunctionBar.c b/FunctionBar.c index 08500373b..2e9aa07a6 100644 --- a/FunctionBar.c +++ b/FunctionBar.c @@ -92,6 +92,25 @@ int FunctionBar_draw(const FunctionBar* this) { return FunctionBar_drawExtra(this, NULL, -1, false); } +static size_t FunctionBar_displayWidth(const char *s) { + size_t slen = strlen(s); + size_t width = 0, i = 0; + + mbtowc(NULL, 0, 0); + + while (i < slen) { + wchar_t wch; + int mblen = mbtowc(&wch, s + i, slen - i); + if (mblen <= 0) { + return slen; + } + i += mblen; + width += wcwidth(wch); + } + + return width; +} + int FunctionBar_drawExtra(const FunctionBar* this, const char* buffer, int attr, bool setCursor) { int cursorX = 0; attrset(CRT_colors[FUNCTION_BAR]); @@ -113,7 +132,8 @@ int FunctionBar_drawExtra(const FunctionBar* this, const char* buffer, int attr, attrset(attr); } mvaddstr(LINES - 1, x, buffer); - x += strlen(buffer); + x += FunctionBar_displayWidth(buffer); + cursorX = x; } diff --git a/IncSet.c b/IncSet.c index 71edf1cee..7cce6ac2e 100644 --- a/IncSet.c +++ b/IncSet.c @@ -10,8 +10,10 @@ in the source distribution for its full text. #include "IncSet.h" #include -#include +#include #include +#include +#include #include "CRT.h" #include "ListItem.h" @@ -155,6 +157,23 @@ static bool IncMode_find(const IncMode* mode, Panel* panel, IncMode_GetPanelValu } } +static int IncSet_backspaceLen(const char *s, size_t slen) { + size_t i = 0; + int mblen = 0; + + mbtowc(NULL, 0, 0); + + while (i < slen) { + mblen = mbtowc(NULL, s + i, slen - i); + if (mblen <= 0) { + return slen - i; + } + i += mblen; + } + + return mblen; +} + bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue getPanelValue, Vector* lines) { if (ch == ERR) return true; @@ -169,7 +188,7 @@ bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue IncMode_find(mode, panel, getPanelValue, ch == KEY_F(3) ? 1 : -1); doSearch = false; - } else if (0 < ch && ch < 255 && isprint((unsigned char)ch)) { + } else if (iswprint(Panel_getLastWkey())) { if (mode->index < INCMODE_MAX) { mode->buffer[mode->index] = (char) ch; mode->index++; @@ -183,8 +202,9 @@ bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue } } else if (ch == KEY_BACKSPACE || ch == 127) { if (mode->index > 0) { - mode->index--; + mode->index -= IncSet_backspaceLen(mode->buffer, mode->index); mode->buffer[mode->index] = 0; + if (mode->isFilter) { filterChanged = true; if (mode->index == 0) { diff --git a/Panel.c b/Panel.c index 4ea03f66d..42054a8fd 100644 --- a/Panel.c +++ b/Panel.c @@ -9,6 +9,7 @@ in the source distribution for its full text. #include #include +#include #include #include #include @@ -22,6 +23,8 @@ in the source distribution for its full text. #include "XUtils.h" +static wint_t last_wkey = 0; + const PanelClass Panel_class = { .super = { .extends = Class(Object), @@ -503,5 +506,39 @@ int Panel_getCh(Panel* this) { #ifdef HAVE_SET_ESCDELAY set_escdelay(25); #endif - return getch(); + +#ifdef HAVE_LIBNCURSESW + static char mbbuf[MB_LEN_MAX]; + static size_t mbbuf_len = 0, mbbuf_i = 0; + + if (mbbuf_i < mbbuf_len) { + return mbbuf[mbbuf_i++]; + } + + wint_t wkey; + int wchrv = get_wch(&wkey); + wchar_t wch = (wchar_t)wkey; + + if (wchrv == OK) { + mbbuf_i = 0; + mbbuf_len = wcrtomb(mbbuf, wch, NULL); + if (mbbuf_len == (size_t)-1) { + mbbuf_len = 0; + return wkey; + } + last_wkey = wkey; + return mbbuf[mbbuf_i++]; + } else if (wchrv == KEY_CODE_YES) { + last_wkey = 0; + return wch; + } + + return ERR; +#else + return last_wkey = getch(); +#endif +} + +wint_t Panel_getLastWkey(void) { + return last_wkey; } diff --git a/Panel.h b/Panel.h index 33d532e82..9b2e0275b 100644 --- a/Panel.h +++ b/Panel.h @@ -11,6 +11,7 @@ in the source distribution for its full text. #include #include +#include #include "CRT.h" #include "FunctionBar.h" @@ -140,4 +141,6 @@ HandlerResult Panel_selectByTyping(Panel* this, int ch); int Panel_getCh(Panel* this); +wint_t Panel_getLastWkey(void); + #endif