Wrecked Games

Please login or register.

Login with username, password and session length
Advanced search  

News:

We're just that awesome.

Author Topic: Multilingual Keyboard  (Read 3091 times)

Rackle

  • Regular
  • *
  • Karma: +0/-0
  • Posts: 26
    • View Profile
Multilingual Keyboard
« on: November 15, 2005, 12:46:12 PM »

Quote
As far as Unicode support. I have looked into the ToUnicode method of the Win32API, you do not really need to use WM_ messages. All you need (from my intial look) was a KeyCode -scancode (done) and Virtual Code (can be done with MapVirtual key or something like that IIRC), and the state of the keyboard buffer as returned from GetDeviceState (Done - contained in the char [256] array of Win32keyboard). So, using message loop for Unicode support does not seem neccessary at this point - though, thigns can always change.


I've researched the functions to translate WM_CHAR messages into UTF-16 but have not yet tested them out.  I'm french so I can test how these pesky accents (dead key followed by a simple letter key) are handled to generate ? ? ? ?.  Sadly the ToUnicode Win32 API is for Windows NT so not convenient at all for us.

Input is one part of the problem, with properly displaying these "Unicode" characters being the second part.  I read a message somewhere (probably on the CEGUI board) about Ogre not mapping/exporting/something every characters/glyphs from the fonts.  This part is fuzzy right now.
Logged

pjcast

  • Administrator
  • Veteran
  • *****
  • Karma: +1/-0
  • Posts: 2661
    • View Profile
    • http://www.wreckedgames.com
Multilingual Keyboard
« Reply #1 on: November 15, 2005, 12:52:33 PM »

Yes, localized keyboard support seems to be evry difficult. Can you explain why ToUnicode does not work in this situation? I have yet to try to do anything in particulr with Unicode, so I have no idea really.

However, I do want to keep the same interface (if possible) that is currently used to trasnlate the keyPressed message into the appropriate character value that code (for instance) be injected into CEGUI. If the current keypressed was not a printable character (as in a dead key or whatnot.. I am still unsre why exactly it is called a dead key, as it just sounds like some sort of shift key) than 0 can still be returned.
Logged

Rackle

  • Regular
  • *
  • Karma: +0/-0
  • Posts: 26
    • View Profile
Multilingual Keyboard
« Reply #2 on: November 15, 2005, 01:26:27 PM »

The ToUnicode function translates the specified virtual-key code and keyboard state to the corresponding Unicode character or characters.

Function Information
  Minimum DLL Version user32.dll
  Header Declared in Winuser.h, include Windows.h
  Import library User32.lib
  Minimum operating systems Windows NT 3.1


Quote
I am still unsure why exactly it is called a dead key, as it just sounds like some sort of shift key)


The shift, control and alt keys are pressed at the same time the letter key is pressed.  To generate an upper case E you press both VK_SHIFT and VK_E.  Dead keys are more complex than this.  

There are two types of dead keys.  A simple dead key is a keyboard key that is pressed down and then released, followed by the regular letter.  To generate the letter ? I press the key to the right of the P, release it, and then press the VK_E key.  To generate the uppercase letter ? I press the key to the right of the P, release it,  and then press both the VK_SHIFT and the VK_E keys.

A complex dead key involves pressing down the right alt key and another key, releasing them, and then pressing a regular letter.  To generate the letter ? I press the alt-gr (the right alt) key followed by the key to the right of the P, release both these keys, and then press the VK_E key.  To generate the uppercase letter ? I press the alt-gr (the right alt) key followed by the key to the right of the P, release both these keys, and then press both the VK_SHIFT and the VK_E keys.

On my current keyboard I can also press the apostrophe key (two keys to the right of the letter L) to directly create a ?, and VK_SHIFT followed by this "apostrophe" to create an uppercase ?.  The next key to the right (third to the right of the letter L) is mapped to the ? and when VK_SHIFT is down I generate the uppercase ?.  These "shortcuts" exist because these two letters ? and ? are very common but ? is not and so it requires the alt-gr + key to the right of the P, release both, and then press the VK_U key.

Reproducing these scenarios through DirectInput would require some work.  Trapping a WM_CHAR simplifies this greatly; you receive the end result of the work done by TranslateMessage().
Logged

pjcast

  • Administrator
  • Veteran
  • *****
  • Karma: +1/-0
  • Posts: 2661
    • View Profile
    • http://www.wreckedgames.com
Multilingual Keyboard
« Reply #3 on: November 15, 2005, 01:37:59 PM »

Hmm, seems like a horible way to type (fast). I think this can still be handled without the WM_ message.. Hopefully anyway. As this still needs to be handled on other OS's that do not have a Windows Message WM_.

How does SDL (if you have any experience using that) handle deadkey combinations like you described? I am pretty sure it uses a combination of ToAscii and other things when dealing with Unicode. I think CEGUI demos use SDL as input, if you wouldn't mind giving it a try. I don't think SDL (though, might be wrong) uses WM_ messages for keyboard input.. But, if it does, then maybe we can also use the loop ourselves.. but, I am hesitant, as that would be the only really needed use - I would likely have a setting for enableUnicode (much like SDL does) to avoid the extra processing.
Logged

Rackle

  • Regular
  • *
  • Karma: +0/-0
  • Posts: 26
    • View Profile
Multilingual Keyboard
« Reply #4 on: November 15, 2005, 01:38:30 PM »

Found my notes on the Windows functions to convert keys into ascii:

HKL hklKeyboardLayout = GetKeyboardLayout(0); // 0 means current thread
// This seemingly cannot fail
// If this value is cached then the application must respond to WM_INPUTLANGCHANGE


BYTE diks[256];
HRESULT hr = mlpDIKeyboard->GetDeviceState( sizeof(diks), diks);


UINT uiScanCode = MapVirtualKeyEx( diks[DIK_A],
                                   0, // Convert DIK_ code to scan code
                                   hklKeyboardLayout);
if(!uiScanCode)
  // Error converting to a scancode


BYTE buffer[2];
int iAscii = ToAsciiEx( DIK_A,
                        uiScanCode,
                        diks,
                        buffer,
                        0, // 1 means a menu is active, 0 means no menu
                        hklKeyboardLayout);
if(iAscii > 0)
{
  // We have 1 or 2 characters in our buffer
  // If we have 2 characters then a dead key could not be combined
  //   with the virtual key to form a single character.  But is the
  //   first digit the virtual key or the dead key?
}
else if(iAscii == 0)
{
  // Virtual key could not be translated
}
else if(iAscii == -1)
{
  // The virtual key corresponds to a dead key (accent or diacritic)
  // Dead keys require an additional input to be resolved into a value
}


I don't see how these would map a complex dead key.  Maybe by keeping all these keys pressed at the same time on the keyboard scan (the diks array).  Or maybe the ToAscii function receives the last key pressed and the keyboard scan/state is set to reflect the dead keys that were previously pressed.  Is the source code to TranslateMessage available somewhere?  How does Windows do it?

The DirectX 9.0 SDK has code to implement an IME in DirectX.  The answer could be there:

Microsoft DirectX 9.0 SDK\Samples\C++\Common\DXUTgui.h
Microsoft DirectX 9.0 SDK\Samples\C++\Common\DXUTgui.cpp
Logged

Rackle

  • Regular
  • *
  • Karma: +0/-0
  • Posts: 26
    • View Profile
Multilingual Keyboard
« Reply #5 on: November 15, 2005, 01:53:29 PM »

Quote
this still needs to be handled on other OS's that do not have a Windows Message WM_.


I would think each platform would have its own way of generating text characters, each requiring a different process/manipulation.  But the end result would be a common function returning this UTF-16 or UTF-32 (Unicode)  character.
Logged

pjcast

  • Administrator
  • Veteran
  • *****
  • Karma: +1/-0
  • Posts: 2661
    • View Profile
    • http://www.wreckedgames.com
Multilingual Keyboard
« Reply #6 on: November 15, 2005, 02:14:21 PM »

I looked through X a little, and there is probably some method to do something like this... Though, finding good ducumentation on X is a pita.. MSDN is truly a godsend in that regards.

That code you posted looks amazingly similiar to the SDL code that handles unicode generation - I looked at it some time ago to figure out how to maybe handle unicode stuff. As for how windows manages it with complex dead key combinations, perhaps it does not very well (when using that method) - as internet searching seems to show.

I think you may be right about the answer lying with DirectX's IME control stuff.
Logged

pjcast

  • Administrator
  • Veteran
  • *****
  • Karma: +1/-0
  • Posts: 2661
    • View Profile
    • http://www.wreckedgames.com
Multilingual Keyboard
« Reply #7 on: November 15, 2005, 03:21:27 PM »

After thinking about this.. and looking around.. It becomes overwhelmingly apparent that on Windows, a WinProc (using WM_CHAR) is a neccessity for this without having to reinvent the wheel. :evil: Very dissapointing.

Ok, my take on this.. This will need to be a runtime time setting.. Defaulting to the current use of symbol mapping's based off a loaded in Map File. As, I do not want to take over the Apps WinProc unless the app wants OIS to.

Ok, so, say a method named enableWindowEvents(bool)... That will override, completely (WinProc & Custom User Data). It will not call the old WinProc.. As we have removed it's data (In Ogre's case, the demo app can just deal with what Ogre would have done anyway). Now, this new winproc will allow a listener class to be registered with it, so it can fire off various event calls... In addition, it will send off a keyboard event if buffered input is true, something like keyboardCharInput( .. ); from the WM_CHAR event... And, equivilent X implementation can be made to (as it already uses X Events - though, the difference is, X Events loops can recieve different messages per connection, unlike Win32 which recieves all window events).

How does that sound? Of course, this will not be until version 0.5.0.
Logged

Rackle

  • Regular
  • *
  • Karma: +0/-0
  • Posts: 26
    • View Profile
Multilingual Keyboard
« Reply #8 on: November 15, 2005, 05:45:35 PM »

I was thinking more and more about the "OS Listener" and liking it more and more.  Win32 messages being intercepted and triggerring off functions in a class, doing nothing by default but allowing programmers to override the default functions and implementing their own code, such as responding to the WM_ACTIVATE to automatically reacquire the mouse.  In the same vein, WM_CHAR could trigger off a keyReleased to a KeyListener.  This idea wants to be developped further.

I've never liked Map Files as they seem too static.  But they are somewhat easy to generate and manage.  For me map files are mainly to be used with action mapping, something I have not put much thought into.

My intentions are to listen to both WM_CHAR and DirectInput to process the keyboard.  WM_CHAR messages would be discarded, until text input was activated.  DirectInput would always be active, to respond to hotkeys.  When WM_CHAR would be activated it would consume the messages that it is meant to handle, such as letters, left/right character navigation, ctrl-left/right word navigation, home/end to go to beginning or end, up/down to scroll through typed commands, etc.  But anything not consumed would trickle down to the DirectInput system to be treated as a hotkey aka action mapping.
Logged

pjcast

  • Administrator
  • Veteran
  • *****
  • Karma: +1/-0
  • Posts: 2661
    • View Profile
    • http://www.wreckedgames.com
Multilingual Keyboard
« Reply #9 on: November 16, 2005, 01:53:19 PM »

The only thing about this that I question... is, if OIS is using the WinProc for messages, why not just use that for key and mouse messages too... Is there really an advantage to using both Win32 WinProc and DirectInput simultaneously for Mouse & Keyboard when the message loop is enabled? I wonder...
Logged

Rackle

  • Regular
  • *
  • Karma: +0/-0
  • Posts: 26
    • View Profile
Multilingual Keyboard
« Reply #10 on: November 16, 2005, 02:01:41 PM »

What I've read is that WM_CHAR/WM_MBUTTON handling is supposedly slow whereas scanning the keyboard state through DirectInput is very fast.  What the actual values are I do not know.

Text input is inherently slow.  After all, how fast can a super fast typist type letters?  Even by just smashing keys at random I do not seem to be able to overcome the WM_CHAR method:  alfjlsadjflsajflsdjflksjduoewifewjfijwe.

There could be other factors involved, such as the message queue delaying the delivery of messages when the PC is working hard.

All of this is pure conjectures, not backed by any data.
Logged

pjcast

  • Administrator
  • Veteran
  • *****
  • Karma: +1/-0
  • Posts: 2661
    • View Profile
    • http://www.wreckedgames.com
Multilingual Keyboard
« Reply #11 on: November 16, 2005, 02:09:07 PM »

Yeah.. This would just involve some tests.. But, I doubt we would see any noticable difference between directX and WinProc for this. Heck, i read somewhere (but I cannot find it again, or even verify the accuracy) that DirectInput8 was no longer even accessing the hardware, but was really just wrapping up the WinProc or something. Somethings to think about for the version .5 release.

<rant>Till then though, I really need to get crackin on the DX Force Feedback support... Linux will just have to sit and wait until a following release when I can get a Controller that works on linux with FF, or someone does the testing, work there... As, I've done everything I could except uploading FF effects there...</rant> I think thins here at school have cooled down enough for me to dedicate more time back to OIS.
Logged