diff options
author | Thomas Lübking <thomas.luebking@gmail.com> | 2016-09-05 22:34:20 (GMT) |
---|---|---|
committer | Mathias Gumz <akira@fluxbox.org> | 2016-09-11 07:56:33 (GMT) |
commit | 5fc00dee32de8d31b7220c338810e86043eb87ae (patch) | |
tree | 8d50da97d49b6c40f120f1062e74ffa97ba9b95a | |
parent | 5869f391c1fa39a9a9826ee16e11e15c4f10200a (diff) | |
download | fluxbox-5fc00dee32de8d31b7220c338810e86043eb87ae.zip fluxbox-5fc00dee32de8d31b7220c338810e86043eb87ae.tar.bz2 |
Improve utf-8 support
Operate on inverse iscntrl check which allows us to avoid wide character
conversions.
-rw-r--r-- | src/FbTk/TextBox.cc | 85 |
1 files 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, | |||
60 | m_select_pos(std::string::npos), | 60 | m_select_pos(std::string::npos), |
61 | m_xic(0) { | 61 | m_xic(0) { |
62 | 62 | ||
63 | if (App::instance()->inputModule()) | ||
64 | m_xic = XCreateIC(App::instance()->inputModule(), XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, window(), NULL); | ||
63 | FbTk::EventManager::instance()->add(*this, *this); | 65 | FbTk::EventManager::instance()->add(*this, *this); |
64 | } | 66 | } |
65 | 67 | ||
@@ -74,12 +76,15 @@ TextBox::TextBox(const FbWindow &parent, | |||
74 | m_end_pos(0), | 76 | m_end_pos(0), |
75 | m_select_pos(std::string::npos), | 77 | m_select_pos(std::string::npos), |
76 | m_xic(0) { | 78 | m_xic(0) { |
77 | 79 | if (App::instance()->inputModule()) | |
80 | m_xic = XCreateIC(App::instance()->inputModule(), XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, window(), NULL); | ||
78 | FbTk::EventManager::instance()->add(*this, *this); | 81 | FbTk::EventManager::instance()->add(*this, *this); |
79 | } | 82 | } |
80 | 83 | ||
81 | TextBox::~TextBox() { | 84 | TextBox::~TextBox() { |
82 | 85 | if (m_xic) | |
86 | XFree(m_xic); | ||
87 | m_xic = 0; | ||
83 | } | 88 | } |
84 | 89 | ||
85 | void TextBox::setText(const FbTk::BiDiString &text) { | 90 | void TextBox::setText(const FbTk::BiDiString &text) { |
@@ -290,11 +295,17 @@ void TextBox::keyPressEvent(XKeyEvent &event) { | |||
290 | 295 | ||
291 | KeySym ks; | 296 | KeySym ks; |
292 | char keychar[20]; | 297 | char keychar[20]; |
293 | int count = 1; | 298 | if (m_xic) { |
294 | if (m_xic) | 299 | Status status; |
295 | count = Xutf8LookupString(m_xic, &event, keychar, 20, &ks, 0); | 300 | int count = Xutf8LookupString(m_xic, &event, keychar, sizeof(keychar), &ks, &status); |
296 | else | 301 | if (status == XBufferOverflow) |
302 | return; | ||
303 | keychar[count] = '\0'; | ||
304 | } | ||
305 | else { | ||
297 | XLookupString(&event, keychar, 1, &ks, 0); | 306 | XLookupString(&event, keychar, 1, &ks, 0); |
307 | keychar[1] = '\0'; | ||
308 | } | ||
298 | 309 | ||
299 | // a modifier key by itself doesn't do anything | 310 | // a modifier key by itself doesn't do anything |
300 | if (IsModifierKey(ks)) return; | 311 | if (IsModifierKey(ks)) return; |
@@ -366,7 +377,7 @@ void TextBox::keyPressEvent(XKeyEvent &event) { | |||
366 | adjustPos(); | 377 | adjustPos(); |
367 | } | 378 | } |
368 | break; | 379 | break; |
369 | case 'a': | 380 | case XK_a: |
370 | selectAll(); | 381 | selectAll(); |
371 | break; | 382 | break; |
372 | } | 383 | } |
@@ -394,56 +405,45 @@ void TextBox::keyPressEvent(XKeyEvent &event) { | |||
394 | case XK_Delete: | 405 | case XK_Delete: |
395 | deleteForward(); | 406 | deleteForward(); |
396 | break; | 407 | break; |
408 | #define SET_SINGLE_BYTE(_B_) keychar[0] = _B_; keychar[1] = '\0' | ||
397 | case XK_KP_Insert: | 409 | case XK_KP_Insert: |
398 | keychar[0] = '0'; | 410 | SET_SINGLE_BYTE('0'); |
399 | break; | 411 | break; |
400 | case XK_KP_End: | 412 | case XK_KP_End: |
401 | keychar[0] = '1'; | 413 | SET_SINGLE_BYTE('1'); |
402 | break; | 414 | break; |
403 | case XK_KP_Down: | 415 | case XK_KP_Down: |
404 | keychar[0] = '2'; | 416 | SET_SINGLE_BYTE('2'); |
405 | break; | 417 | break; |
406 | case XK_KP_Page_Down: | 418 | case XK_KP_Page_Down: |
407 | keychar[0] = '3'; | 419 | SET_SINGLE_BYTE('3'); |
408 | break; | 420 | break; |
409 | case XK_KP_Left: | 421 | case XK_KP_Left: |
410 | keychar[0] = '4'; | 422 | SET_SINGLE_BYTE('4'); |
411 | break; | 423 | break; |
412 | case XK_KP_Begin: | 424 | case XK_KP_Begin: |
413 | keychar[0] = '5'; | 425 | SET_SINGLE_BYTE('5'); |
414 | break; | 426 | break; |
415 | case XK_KP_Right: | 427 | case XK_KP_Right: |
416 | keychar[0] = '6'; | 428 | SET_SINGLE_BYTE('6'); |
417 | break; | 429 | break; |
418 | case XK_KP_Home: | 430 | case XK_KP_Home: |
419 | keychar[0] = '7'; | 431 | SET_SINGLE_BYTE('7'); |
420 | break; | 432 | break; |
421 | case XK_KP_Up: | 433 | case XK_KP_Up: |
422 | keychar[0] = '8'; | 434 | SET_SINGLE_BYTE('8'); |
423 | break; | 435 | break; |
424 | case XK_KP_Page_Up: | 436 | case XK_KP_Page_Up: |
425 | keychar[0] = '9'; | 437 | SET_SINGLE_BYTE('9'); |
426 | break; | 438 | break; |
427 | case XK_KP_Delete: | 439 | case XK_KP_Delete: |
428 | keychar[0] = ','; | 440 | SET_SINGLE_BYTE(','); |
429 | break; | 441 | break; |
442 | #undef SET_SINGLE_BYTE | ||
430 | } | 443 | } |
431 | } | 444 | } |
432 | if (count > 1 && count < 20) { | 445 | if ((m_xic && !std::iscntrl(*keychar)) || std::isprint(*keychar)) { |
433 | wchar_t wc; | 446 | insertText(std::string(keychar)); |
434 | count = mbrtowc(&wc, keychar, count, 0); | ||
435 | if (count > 0 && iswprint(wc)) { | ||
436 | keychar[count] = '\0'; | ||
437 | std::string val; | ||
438 | val += (char*)keychar; | ||
439 | insertText(val); | ||
440 | m_select_pos = std::string::npos; | ||
441 | } | ||
442 | } | ||
443 | if (isprint(keychar[0])) { | ||
444 | std::string val; | ||
445 | val += keychar[0]; | ||
446 | insertText(val); | ||
447 | m_select_pos = std::string::npos; | 447 | m_select_pos = std::string::npos; |
448 | } | 448 | } |
449 | if ((event.state & ShiftMask) != ShiftMask) | 449 | if ((event.state & ShiftMask) != ShiftMask) |
@@ -454,17 +454,10 @@ void TextBox::keyPressEvent(XKeyEvent &event) { | |||
454 | void TextBox::handleEvent(XEvent &event) { | 454 | void TextBox::handleEvent(XEvent &event) { |
455 | if (event.type == KeymapNotify) { | 455 | if (event.type == KeymapNotify) { |
456 | XRefreshKeyboardMapping(&event.xmapping); | 456 | XRefreshKeyboardMapping(&event.xmapping); |
457 | } else if (event.type == FocusIn) { | 457 | } else if (event.type == FocusIn && m_xic) { |
458 | if (!m_xic && App::instance()->inputModule()) | 458 | XSetICFocus(m_xic); |
459 | m_xic = XCreateIC(App::instance()->inputModule(), XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, window(), NULL); | 459 | } else if (event.type == FocusOut && m_xic) { |
460 | if (m_xic) | 460 | XUnsetICFocus(m_xic); |
461 | XSetICFocus(m_xic); | ||
462 | } else if (event.type == FocusIn) { | ||
463 | if (m_xic) { | ||
464 | XUnsetICFocus(m_xic); | ||
465 | XFree(m_xic); | ||
466 | m_xic = 0; | ||
467 | } | ||
468 | } | 461 | } |
469 | } | 462 | } |
470 | 463 | ||
@@ -590,6 +583,10 @@ TextBox::StringRange TextBox::charRange(std::string::size_type pos) const { | |||
590 | }; | 583 | }; |
591 | 584 | ||
592 | StringRange range = {pos, pos}; | 585 | StringRange range = {pos, pos}; |
586 | |||
587 | if (!m_xic) | ||
588 | return range; | ||
589 | |||
593 | FbString t = text(); | 590 | FbString t = text(); |
594 | 591 | ||
595 | if (pos < 0 || pos >= t.size() || t.at(pos) > 0) // invalid pos or ASCII | 592 | if (pos < 0 || pos >= t.size() || t.at(pos) > 0) // invalid pos or ASCII |