aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Lübking <thomas.luebking@gmail.com>2016-09-05 22:34:20 (GMT)
committerMathias Gumz <akira@fluxbox.org>2016-09-11 07:56:33 (GMT)
commit5fc00dee32de8d31b7220c338810e86043eb87ae (patch)
tree8d50da97d49b6c40f120f1062e74ffa97ba9b95a
parent5869f391c1fa39a9a9826ee16e11e15c4f10200a (diff)
downloadfluxbox-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.cc85
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
81TextBox::~TextBox() { 84TextBox::~TextBox() {
82 85 if (m_xic)
86 XFree(m_xic);
87 m_xic = 0;
83} 88}
84 89
85void TextBox::setText(const FbTk::BiDiString &text) { 90void 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) {
454void TextBox::handleEvent(XEvent &event) { 454void 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