From 5fc00dee32de8d31b7220c338810e86043eb87ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20L=C3=BCbking?= Date: Tue, 6 Sep 2016 00:34:20 +0200 Subject: Improve utf-8 support Operate on inverse iscntrl check which allows us to avoid wide character conversions. --- src/FbTk/TextBox.cc | 85 ++++++++++++++++++++++++++--------------------------- 1 file changed, 41 insertions(+), 44 deletions(-) diff --git a/src/FbTk/TextBox.cc b/src/FbTk/TextBox.cc index 9cddd7f..2cfec30 100644 --- a/src/FbTk/TextBox.cc +++ b/src/FbTk/TextBox.cc @@ -60,6 +60,8 @@ TextBox::TextBox(int screen_num, m_select_pos(std::string::npos), m_xic(0) { + if (App::instance()->inputModule()) + m_xic = XCreateIC(App::instance()->inputModule(), XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, window(), NULL); FbTk::EventManager::instance()->add(*this, *this); } @@ -74,12 +76,15 @@ TextBox::TextBox(const FbWindow &parent, m_end_pos(0), m_select_pos(std::string::npos), m_xic(0) { - + if (App::instance()->inputModule()) + m_xic = XCreateIC(App::instance()->inputModule(), XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, window(), NULL); FbTk::EventManager::instance()->add(*this, *this); } TextBox::~TextBox() { - + if (m_xic) + XFree(m_xic); + m_xic = 0; } void TextBox::setText(const FbTk::BiDiString &text) { @@ -290,11 +295,17 @@ void TextBox::keyPressEvent(XKeyEvent &event) { KeySym ks; char keychar[20]; - int count = 1; - if (m_xic) - count = Xutf8LookupString(m_xic, &event, keychar, 20, &ks, 0); - else + if (m_xic) { + Status status; + int count = Xutf8LookupString(m_xic, &event, keychar, sizeof(keychar), &ks, &status); + if (status == XBufferOverflow) + return; + keychar[count] = '\0'; + } + else { XLookupString(&event, keychar, 1, &ks, 0); + keychar[1] = '\0'; + } // a modifier key by itself doesn't do anything if (IsModifierKey(ks)) return; @@ -366,7 +377,7 @@ void TextBox::keyPressEvent(XKeyEvent &event) { adjustPos(); } break; - case 'a': + case XK_a: selectAll(); break; } @@ -394,56 +405,45 @@ void TextBox::keyPressEvent(XKeyEvent &event) { case XK_Delete: deleteForward(); break; +#define SET_SINGLE_BYTE(_B_) keychar[0] = _B_; keychar[1] = '\0' case XK_KP_Insert: - keychar[0] = '0'; + SET_SINGLE_BYTE('0'); break; case XK_KP_End: - keychar[0] = '1'; + SET_SINGLE_BYTE('1'); break; case XK_KP_Down: - keychar[0] = '2'; + SET_SINGLE_BYTE('2'); break; case XK_KP_Page_Down: - keychar[0] = '3'; + SET_SINGLE_BYTE('3'); break; case XK_KP_Left: - keychar[0] = '4'; + SET_SINGLE_BYTE('4'); break; case XK_KP_Begin: - keychar[0] = '5'; + SET_SINGLE_BYTE('5'); break; case XK_KP_Right: - keychar[0] = '6'; + SET_SINGLE_BYTE('6'); break; case XK_KP_Home: - keychar[0] = '7'; + SET_SINGLE_BYTE('7'); break; case XK_KP_Up: - keychar[0] = '8'; + SET_SINGLE_BYTE('8'); break; case XK_KP_Page_Up: - keychar[0] = '9'; + SET_SINGLE_BYTE('9'); break; case XK_KP_Delete: - keychar[0] = ','; + SET_SINGLE_BYTE(','); break; +#undef SET_SINGLE_BYTE } } - if (count > 1 && count < 20) { - wchar_t wc; - count = mbrtowc(&wc, keychar, count, 0); - if (count > 0 && iswprint(wc)) { - keychar[count] = '\0'; - std::string val; - val += (char*)keychar; - insertText(val); - m_select_pos = std::string::npos; - } - } - if (isprint(keychar[0])) { - std::string val; - val += keychar[0]; - insertText(val); + if ((m_xic && !std::iscntrl(*keychar)) || std::isprint(*keychar)) { + insertText(std::string(keychar)); m_select_pos = std::string::npos; } if ((event.state & ShiftMask) != ShiftMask) @@ -454,17 +454,10 @@ void TextBox::keyPressEvent(XKeyEvent &event) { void TextBox::handleEvent(XEvent &event) { if (event.type == KeymapNotify) { XRefreshKeyboardMapping(&event.xmapping); - } else if (event.type == FocusIn) { - if (!m_xic && App::instance()->inputModule()) - m_xic = XCreateIC(App::instance()->inputModule(), XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, window(), NULL); - if (m_xic) - XSetICFocus(m_xic); - } else if (event.type == FocusIn) { - if (m_xic) { - XUnsetICFocus(m_xic); - XFree(m_xic); - m_xic = 0; - } + } else if (event.type == FocusIn && m_xic) { + XSetICFocus(m_xic); + } else if (event.type == FocusOut && m_xic) { + XUnsetICFocus(m_xic); } } @@ -590,6 +583,10 @@ TextBox::StringRange TextBox::charRange(std::string::size_type pos) const { }; StringRange range = {pos, pos}; + + if (!m_xic) + return range; + FbString t = text(); if (pos < 0 || pos >= t.size() || t.at(pos) > 0) // invalid pos or ASCII -- cgit v0.11.2