# Thai Input problem with TextEditor, I made it works

**URL:** <https://forum.juce.com/t/thai-input-problem-with-texteditor-i-made-it-works/1040>\
**Category:** Linux\
**Created:** [September 10, 2006, 10:52am UTC](https://forum.juce.com/t/thai-input-problem-with-texteditor-i-made-it-works/1040 "2006-09-10T10:52:54Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![chrjean](https://avatars.discourse-cdn.com/v4/letter/c/0ea827/32.png) [@chrjean](https://forum.juce.com/u/chrjean)\
**Post date:** [September 10, 2006, 10:52am UTC](https://forum.juce.com/t/thai-input-problem-with-texteditor-i-made-it-works/1040/1 "2006-09-10T10:52:54Z")

</div>

Dear all.

I have just discovered JUCE two days ago, and I’m quiet amazed.  
Following the tutorials and looking at the demo and project files I manage to write a small demo.

I read that JUCE was unicode and in facts, I can display my thai language as wanted. Either in label, drawFittedText or TextEditor. It is well displayed. To display the text, i switch my keyboard to thai, and I write the content directly in my .cpp file with emacs which save the file in unicode, then I compile, then run my application. The thai is displayed as wanted.

The problem is when I try to edit thai language in my TextEditor which is able to dispaly thai as initial text (by setting the right font), I jus’t can’t. At best he display the ASCII character which is on the same keyboard key as the thai character although my keyboard is switched to thai.

Even if i try to copy from my initial TextEditor display and paste to the TextEditor, it doesn’t work.

Does anybody has idea about that ?

Thanks.  
Christian.

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://forum.juce.com/u/jules)\
**Post date:** [September 11, 2006, 8:33am UTC](https://forum.juce.com/t/thai-input-problem-with-texteditor-i-made-it-works/1040/2 "2006-09-11T08:33:42Z")

</div>

Thanks - glad you’re enjoying it!

Must be the linux key input code that’s not handling unicode properly… I’ll make a note to look at this when I get chance, but if you want to check it out yourself, the place to look will be in juce\_linux\_Windowing.cpp

---

<div class="post-metadata">

**Author:** ![chrjean](https://avatars.discourse-cdn.com/v4/letter/c/0ea827/32.png) [@chrjean](https://forum.juce.com/u/chrjean)\
**Post date:** [September 11, 2006, 1:42pm UTC](https://forum.juce.com/t/thai-input-problem-with-texteditor-i-made-it-works/1040/3 "2006-09-11T13:42:33Z")

</div>

Thanks Jules, but I think it will be difficult for me(first time i did GUI) to solve the problem, but i won’t give up (open source power;-)).

Here some interesting things :

In my application I read a file, and i display the content of the file with the function loadFileAsString in the paint function provided with the demo. Everything display well.

I run my app, and I also run Yudit, in which i edit this file, i write some thai character, then I save the file as UTF-16 and magic the new content is displayed in the juce app.

The interesting thing is how I can use Yudit to input my thai, here only Yudit is involved :

I have 4 ways :

- Straight : I think in this mode, Yudit just get whatever is pressed from the keyboard, so if i set my xfce4-xkb-plugin, (which is initialised with setxkbmap fr,th), to french, a key press display the correct french char, but if it is set to thai, he displays the thai character as wanted.  
(It is the way I try to edit text in TextEditor)

- Thai input : if I use that method i don’t need to use my xfce4-xkb-plugin, switching it to thai to enter thai, (Yudit does the thing itself) the only problem is that all the character doesn’t match what I expected, it looks similar similar like using qwerty instead of azerty. (diiferent map)

- Unicode : if I use that method, if my xkb-plugin keyboard is set to french, i get what i want at least for ASCII char, get problem with accent, double char are displayed. if I try to enter thai, the same result. Each keystroke make appears two characteres, which doesn’t have glyph.

But if I hold on the key ALT while pressing my thai key, I got it right. if I hold on the ALT key while pressing a standard ASCII key is pressed, nothing is displayed, the cursor acknowledge the key stroke but it just doesn’t move.

- TIS-620 : Nearly the same as unicode.

CONCLUSION :  
I want to know if the following things that I’m thinking are correct :

- Is JUCE TextEditor is expecting UNICODE as input method ?

- The X keyboard doesn’t seem to use UNICODE otherwise Yudit should get it right while the UNICODE input method is used. shouldn’t need the ALT key.

- Is the ALT button has something to do with the fact that i can’t input my thai text in TextEditor (The french accent which are one key pressed can be input, but not character that need the ALT GR to be hold on, nor any other combining accent like ï)

- Maybe the ability to press ALT and my Thai char should work for TextEdit, but it doesn’t, nothing happens, it just ackowledge the keystroke and the the cursor doesn’t move.

I am a bit confused and I hope this remark can help.

OK I have Yudit source code, JUCE source Code, Xlib Source Code so i feel abit ashamed to ask for help 😉

Christian.

PS : Some of my LOCAL are set to fr\_FR.UTF-8 and some to en\_EN.UTF-8, I just told that if he can help.

---

<div class="post-metadata">

**Author:** ![chrjean](https://avatars.discourse-cdn.com/v4/letter/c/0ea827/32.png) [@chrjean](https://forum.juce.com/u/chrjean)\
**Post date:** [September 11, 2006, 5:47pm UTC](https://forum.juce.com/t/thai-input-problem-with-texteditor-i-made-it-works/1040/4 "2006-09-11T17:47:34Z")

</div>

The previous post is nearly deprecated.

I downloaded latest version of Yudit and now the only way I can input thai is :

Yudit Input method x-utf-8:en\_GB : if my xfce-xkb plugin is in french, i write french letter, if it is in thai, i write my thai letter.

The Thai input method : It doesn’t match my keyboard but the character are well displayed (still the same as before).

All the previous input : unicode, TIS-620, Straight doesn’t work anymore.

I’m bit lost, since I don’t have a clue about X key things, but I’m learning step by step.

Christian.

---

<div class="post-metadata">

**Author:** ![chrjean](https://avatars.discourse-cdn.com/v4/letter/c/0ea827/32.png) [@chrjean](https://forum.juce.com/u/chrjean)\
**Post date:** [September 18, 2006, 10:43pm UTC](https://forum.juce.com/t/thai-input-problem-with-texteditor-i-made-it-works/1040/5 "2006-09-18T22:43:20Z")

</div>

Hi,

after reading some stuff about xlib and XKBLib, I finally find a way to input my thai.

Here is what I have done but I think it’s ugly and he needs to be rewritten carefully, it may be a help to input other languages similar to thai.

The first thing I have done is in juce\_linux\_Windowing.cpp :

- in handleWindowMessage, for the case KeyPress,  
I replace  
KeySym sym = XKeycodeToKeysym (display, keyEvent-\>keycode, index);  
by  
char asci[64]; // Must not be above 64.  
KeySym sym;  
XLookupString(keyEvent, asci, sizeof(asci), &sym, 0);  
(Found this in yudit source code)

(XLookupString seems to be powerful and take care of group(language map: french and thai in my case) and level (shift, ctl, …))

if sym represent a thai caractere his value range vary from  
XK\_Thai\_kokai 0x0da1 to XK\_Thai\_lekkao 0x0df9

asci is a 3 bytes array if printed with printf from a utf-8 console it will display my thai caracter.

The problem I had is that i couldn’t give sym to handlePressKey because of the function  
insertTextAtCursor (String::keyCodeToString (key.getKeyCode()));

here keyCodeToString expect a keyCode that is coded only in one byte.  
The problem is that I didn’t know how to convert the sym into the asci array. If I knew I had rewritten this function.

So I realised that if I pass asci to the function  
insertTextAtCursor (); in TextEditor, it will display my charactere well.

Now the ugly thing happens :

- I modified the Class KeyPress to have a string member.  
(First I wanted to create a class KeyPressExt with inheritance from KeyPress it didn’t work)
- So I had function like getStr, setStr and a couple of constructor that take a String as a parameter.

So in the file juce\_linux\_Windowing following the above addition I added  
String str = String(asci);  
KeyPress kpe = KeyPress((int) sym, 0, str);

Then I added a test to call handleKeyPressExt only of my charactere typed is thai

if( (sym \>= XK\_Thai\_kokai) && (sym \<= XK\_Thai\_lekkao) ){  
keyPressed = false; //make sure the other things don’t happen  
printf(“sym is a thai char!\n”); // This for debug.  
// Use our own KeyPress handling  
handleKeyPressExt(kpe);  
}

Then I also added the function handleKeyPressExt which is as following :

void handleKeyPressExt (const KeyPress keyPress){  
updateCurrentModifiers();

```
if (Component::currentlyFocusedComponent->isValidComponent())
  Component::currentlyFocusedComponent->keyPressed(keyPress);
else
  component->keyPressed(keyPress);

```

}

The aim of that function was to skip the call to internalPressKey since I had already created my KeyPress object.

Then in TextEditor I added to the function keyPressed :

if (! isReadOnly())  
if ( (key.getKeyCode() \>= XK\_Thai\_kokai)  
&& (key.getKeyCode() \<= XK\_Thai\_lekkao))  
insertTextAtCursor (key.getStr());  
else{  
insertTextAtCursor (String::keyCodeToString (key.getKeyCode()));  
}  
lastTransactionTime = Time::getApproximateMillisecondCounter();

I did that to be careful, but i think I just could call getStr whatever is the keyCode.

To conclude what should be done :

- use XLookupString instead of XKeyCodeToKeysym
- Modify the keyCodeToString Function to handle value of keycode above 255.
- I think this would make it works for many languages similar to thai (thai, lao, indic, khmer, …)

To go further maybe we should use XIM method to really get a multilanguage capable library.

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://forum.juce.com/u/jules)\
**Post date:** [September 19, 2006, 10:07am UTC](https://forum.juce.com/t/thai-input-problem-with-texteditor-i-made-it-works/1040/6 "2006-09-19T10:07:57Z")

</div>

Great stuff. Thanks for finding out all that info.

I think the solution might actually be a lot simpler than what you’ve done there - it’s already possible to pass a unicode character to the handleKeyPress method. Try this:

[code] void handleWindowMessage (XEvent\* event)  
{  
switch (event-\>xany.type)  
{  
case 2: // ‘KeyPress’  
{  
XKeyEvent\* keyEvent = (XKeyEvent\*) &event-\>xkey;  
updateKeyStates (keyEvent-\>keycode, true);

```
            char utf8 [64];
            zeromem (utf8, sizeof (utf8));
            KeySym sym;
            XLookupString (keyEvent, utf8, sizeof (utf8), &sym, 0);
            int keyCode = (int) String::fromUTF8 ((const uint8*) utf8, sizeof (utf8) - 1) [0];

            if (keyCode < 0x20)
                keyCode = XKeycodeToKeysym (display, keyEvent->keycode, 
                                            (currentModifiers & ModifierKeys::shiftModifier) != 0 ? 1 : 0);

            const int oldMods = currentModifiers;
            bool keyPressed = false;

            const bool keyDownChange = (sym != NoSymbol) && ! updateKeyModifiersFromSym (sym, true);

            if ((sym & 0xff00) == 0xff00)
            {
                // Translate keypad
                if (sym == XK_KP_Divide)
                    keyCode = XK_slash;
                else if (sym == XK_KP_Multiply)
                    keyCode = XK_asterisk;
                else if (sym == XK_KP_Subtract)
                    keyCode = XK_hyphen;
                else if (sym == XK_KP_Add)
                    keyCode = XK_plus;
                else if (sym == XK_KP_Enter)
                    keyCode = XK_Return;
                else if (sym == XK_KP_Decimal)
                    keyCode = numLock ? XK_period : XK_Delete;
                else if (sym == XK_KP_0)
                    keyCode = numLock ? XK_0 : XK_Insert;
                else if (sym == XK_KP_1)
                    keyCode = numLock ? XK_1 : XK_End;
                else if (sym == XK_KP_2)
                    keyCode = numLock ? XK_2 : XK_Down;
                else if (sym == XK_KP_3)
                    keyCode = numLock ? XK_3 : XK_Page_Down;
                else if (sym == XK_KP_4)
                    keyCode = numLock ? XK_4 : XK_Left;
                else if (sym == XK_KP_5)
                    keyCode = XK_5;
                else if (sym == XK_KP_6)
                    keyCode = numLock ? XK_6 : XK_Right;
                else if (sym == XK_KP_7)
                    keyCode = numLock ? XK_7 : XK_Home;
                else if (sym == XK_KP_8)
                    keyCode = numLock ? XK_8 : XK_Up;
                else if (sym == XK_KP_9)
                    keyCode = numLock ? XK_9 : XK_Page_Up;

                switch (sym)
                {
                    case XK_Left:
                    case XK_Right:
                    case XK_Up:
                    case XK_Down:
                    case XK_Page_Up:
                    case XK_Page_Down:
                    case XK_End:
                    case XK_Home:
                    case XK_Delete:
                    case XK_Insert:
                        keyPressed = true;
                        keyCode = (sym & 0xff) | extendedKeyModifier;
                        break;
                    case XK_Tab:
                    case XK_Return:
                    case XK_Escape:
                    case XK_BackSpace:
                        keyPressed = true;
                        keyCode &= 0xff;
                        break;
                    default:
                    {
                        if (sym >= XK_F1 && sym <= XK_F12)
                        {
                            keyPressed = true;
                            keyCode = (sym & 0xff) | extendedKeyModifier;
                        }
                        break;
                    }
                }
            }

            if ((sym & 0xff00) == 0 && sym >= 8)
                keyPressed = true;

            if (oldMods != currentModifiers)
                handleModifierKeysChange();

            if (keyDownChange)
                handleKeyUpOrDown();

            if (keyPressed)
                handleKeyPress (keyCode);

            break;
        }

```

[/code]

and I also changed line 177, just in case it interferes with extended unicode chars:

`static const int extendedKeyModifier = 0x10000000;
`

---

<div class="post-metadata">

**Author:** ![chrjean](https://avatars.discourse-cdn.com/v4/letter/c/0ea827/32.png) [@chrjean](https://forum.juce.com/u/chrjean)\
**Post date:** [September 19, 2006, 3:40pm UTC](https://forum.juce.com/t/thai-input-problem-with-texteditor-i-made-it-works/1040/7 "2006-09-19T15:40:06Z")

</div>

Hi, Jules.

I downloaded the library, inserted your code, compile, …, didn’t work, i  
just needed to had this line :

```auto
if( (sym >= XK_Thai_kokai) && (sym <= XK_Thai_lekkao) )
		  keyPressed = true;
```

before (or after) that

```auto
if ((sym & 0xff00) == 0 && sym >= 8)
		  keyPressed = true;
```

Now it works just perfectly so that I will be able to insert thai language in application. I still have a small problem but it is not urgent and can wait is that in French I can’t input compound caracters such as ï (" i)or Ô(^O).

Anyway I’m already happy with what JUCE can do now, and it has been with great pleasure that I helped as I could.

Thanks.  
Christian.

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://forum.juce.com/u/jules)\
**Post date:** [September 19, 2006, 4:56pm UTC](https://forum.juce.com/t/thai-input-problem-with-texteditor-i-made-it-works/1040/8 "2006-09-19T16:56:39Z")

</div>

That’s good, but I’m not happy about hard-coding any thai characters in there - how about this tweak instead:

```auto
                if (utf8[0] != 0 || ((sym & 0xff00) == 0 && sym >= 8))
                    keyPressed = true;
```

---

<div class="post-metadata">

**Author:** ![chrjean](https://avatars.discourse-cdn.com/v4/letter/c/0ea827/32.png) [@chrjean](https://forum.juce.com/u/chrjean)\
**Post date:** [September 19, 2006, 6:54pm UTC](https://forum.juce.com/t/thai-input-problem-with-texteditor-i-made-it-works/1040/9 "2006-09-19T18:54:12Z")

</div>

Hi,

I just made that last change, it works perfectly. It’s even better, I didn’t like the idea to put thai caractere there too, but to be honest i don’t really understand what is the meaning of that line

```auto
((sym & 0xff00) == 0 && sym >= 8)). 
```

Many Thanks, now i think it will work with many other languages as well.

Christian.

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://forum.juce.com/u/jules)\
**Post date:** [September 20, 2006, 8:32am UTC](https://forum.juce.com/t/thai-input-problem-with-texteditor-i-made-it-works/1040/10 "2006-09-20T08:32:54Z")

</div>

Great, glad it’s working now!

---

<div class="post-metadata">

**Author:** ![kunitoki](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/kunitoki/32/15_2.png) [@kunitoki](https://forum.juce.com/u/kunitoki)\
**Post date:** [February 25, 2010, 1:10pm UTC](https://forum.juce.com/t/thai-input-problem-with-texteditor-i-made-it-works/1040/11 "2010-02-25T13:10:39Z")

</div>

summoning again this post, as i’ve encounter some problems on system with kernels compiled with default charset as UTF-8, i’m unable to type accented characters.

the fix is easy, we should trick X11 to use the default locale when processing a keypress. i don’t know if this could be done system wise one and for all in doPlatformSpecificInitialisation without broke anything else. so i came up with a RAII class to swap the locale when processing key events in windows.

```auto

//==============================================================================

class ScopedLocaleChange
{
public:
    ScopedLocaleChange()
        : oldLocale (::setlocale (LC_ALL, 0))
    {
        ::setlocale (LC_ALL, "");
    }
    
    ~ScopedLocaleChange()
    {
        ::setlocale (LC_ALL, oldLocale);
    }
    
private:
    const char* oldLocale;
};

// ...

    void handleWindowMessage (XEvent* event)
    {
        switch (event->xany.type)
        {
            case 2: // 'KeyPress'
            {
                ScopedXLock xlock;
                ScopedLocaleChange localeChange; 
```

in this way we are sure Xlib keysyms are translated correctly with all locales.

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://forum.juce.com/u/jules)\
**Post date:** [February 25, 2010, 1:41pm UTC](https://forum.juce.com/t/thai-input-problem-with-texteditor-i-made-it-works/1040/12 "2010-02-25T13:41:32Z")

</div>

ok… presumably this would have the same effect:

[code] char utf8 [64];  
zeromem (utf8, sizeof (utf8));  
KeySym sym;

```
            {
                const char* oldLocale = ::setlocale (LC_ALL, 0);
                ::setlocale (LC_ALL, "");
                XLookupString (keyEvent, utf8, sizeof (utf8), &sym, 0);
                ::setlocale (LC_ALL, oldLocale);
            }[/code]

```

Normally I love RAII, but I don’t like the idea of that char\* being kept and re-used silently at some random point later on… And since this is basically an dodgy old-style C hack, I think it’s better to keep the machinery of the hack obvious - if you hide it all in an elegant c++ structure, it’d be easy to look at this function in the future and not notice that the locale is being messed about with.

---

<div class="post-metadata">

**Author:** ![kunitoki](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/kunitoki/32/15_2.png) [@kunitoki](https://forum.juce.com/u/kunitoki)\
**Post date:** [February 25, 2010, 3:05pm UTC](https://forum.juce.com/t/thai-input-problem-with-texteditor-i-made-it-works/1040/13 "2010-02-25T15:05:33Z")

</div>

yes right !

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://forum.juce.com/u/jules)\
**Post date:** [May 12, 2017, 10:00am UTC](https://forum.juce.com/t/thai-input-problem-with-texteditor-i-made-it-works/1040/14 "2017-05-12T10:00:04Z")

</div>

Closed on May 12, 2017, 10:00am UTC


