HELP!Is the textBox of QuickGUI supported for IME with OIS ?

jingjie

24-06-2007 06:43:31

:D First, the QuickGUI is easy use and good design.
I wanna get the QuickGUI instead of CEGUI.
Before I used CEGUI to be typing chinese IME into EditBox or MultiEditBox , it is successful to display by receiving of Windows message WM_CHAR.
I don't understand that the textbox of QuickGUI how to supprted this feature with OIS KeyEvent.
To see:
http://www.cegui.org.uk/phpBB2/viewtopic.php?t=1052&highlight=
bool keyPressed( const OIS::KeyEvent &arg )
{
if( arg.key == OIS::KC_ESCAPE )
mShutdownRequested = true;
QuickGUI::GUIManager::getSingleton().injectKeyDown(static_cast<QuickGUI::KeyCode>(arg.key));
QuickGUI::GUIManager::getSingleton().injectChar( arg.text );
return true;
}

To see this:

#include <ctype.h>
inline int __cdecl isLeadByte(int _C)
{return ((unsigned char)(_C) & 0x80); }
(b)Modified wndProc()::case WM_CHAR to deal with Multi-Bye into Unicode then injectChar() is working well;

case WM_CHAR:
{
static char MultiByte[2]={0};
static bool isHaveMultiByte = false;
if (isHaveMultiByte)
{
isHaveMultiByte = false;
MultiByte[1] = (unsigned char) wParam;
int iLengthUnicode = 0;
wchar_t szUnicode;
MultiByteToWideChar(CP_ACP, 0, (char*)MultiByte, 2, &szUnicode, 1);
CEGUI::System::getSingleton().injectChar((CEGUI::utf32) szUnicode);
break;
}else{
if(isLeadByte(wParam))
{
isHaveMultiByte = true;
MultiByte[0] = (unsigned char)wParam;
}else {
CEGUI::System::getSingleton().injectChar((CEGUI::utf32)wParam);
break;
}
}
}

Above that code , will arg.text of OIS::KeyEvent return the unicode character(like chinese) when I finish to type it by the IME?
On OIS::KeyEvent , Before QuickGUI::GUIManager::getSingleton().injectChar , should I translate MultiByteToWideChar by myself?

Master kungfoomasta, if you have any solution , could you tell me?
Thanks.

kungfoomasta

24-06-2007 08:08:37

Unfortunately I don't know anything about unicode, or its use.. :oops:

QuickGUI::KeyCode is the same as OIS::KeyCode:


namespace OIS
{
//! Keyboard scan codes
enum KeyCode
{
KC_UNASSIGNED = 0x00,
KC_ESCAPE = 0x01,
KC_1 = 0x02,
KC_2 = 0x03,
...


And OIS::KeyEvent class:


/**
Specialised for key events
*/
class _OISExport KeyEvent : public EventArg
{
public:
KeyEvent( Object* obj, KeyCode kc, unsigned int txt ) : EventArg(obj), key(kc), text(txt) {}
virtual ~KeyEvent() {}

//! KeyCode of event
const KeyCode key;
//! Text character, depends on current TextTranslationMode
unsigned int text;
};


Do you use OIS with a non english keyboard? I haven't tried this, but maybe it will still register and give valid data? Sorry I'm not helping much.. I'm not familiar with unicode and using foreign IME for text.. :( I think people have used Ogre::TextAreaOverlayElement with unicode languages, maybe somebody on the Help forums knows more.

Off topic: Your code snippet reminds me of Windows Mobile code. :lol:

jingjie

24-06-2007 10:16:33

Unfortunately I don't know anything about unicode, or its use.. :oops:
:

:oops: unicode character is solved for displaying the language of all countries.
For Chinese language, it's code point from 19868 to 40868.
if you want to prodouce "世" glyph , "世" must be transfer UTF8 Format which its codepoint is 19990.
note:
:P the meaning of "世" in English is "a generation".
In the English language system , we usually use a single byte "char" to have enough to indicate all character A~Z and other symbols(like , . @ etc). For multi-bytes solution,we combine two bytes to indicate our chinese language instead of insufficient single byte.
When I finish to type chinese with IME , then Windows WM_CHAR Message will post two bytes that first byte is "Lead Byte" to indicate one Chinese character.
For unicode solution,we store letters and other characters by assigning a number for each one.like "世" code point is 19990.
To see :
http://www.unicode.org/standard/WhatIsUnicode.html


//check Lead byte
inline int __cdecl isLeadByte(int _C)
{return ((unsigned char)(_C) & 0x80); }

case WM_CHAR:
{
//multi-bytes stores here.
static char MultiByte[2]={0};
static bool isHaveMultiByte = false;
//WM_CHAR post second byte to store it on MultiByte[1].
if (isHaveMultiByte)
{
isHaveMultiByte = false;
MultiByte[1] = (unsigned char) wParam;
int iLengthUnicode = 0;
wchar_t szUnicode;
//we translate multiBytes into Unicode , becuase CEGUI::injectChar
//supports unicode.
MultiByteToWideChar(CP_ACP, 0, (char*)MultiByte, 2, &szUnicode, 1);
CEGUI::System::getSingleton().injectChar((CEGUI::utf32) szUnicode);
break;
}else{
//WM_CHAR post first lead byte to store it on MultiByte[0].
if(isLeadByte(wParam))
{
isHaveMultiByte = true;
MultiByte[0] = (unsigned char)wParam;
}else {
CEGUI::System::getSingleton().injectChar((CEGUI::utf32)wParam);
break;
}
}
}

Above that code, QuickGui::injectChar is supported unicode UTF8,16,32
then MultiBytes MultiByte[2] must be translated into unicode system by MultiByteToWideChar.



Do you use OIS with a non english keyboard?

:cry: No , I don't use OIS with non english keyboard.
the implementation of OIS v1.0 on Win32 is by DirectInput.
To see this:
http://www.cegui.org.uk/wiki/index.php/DirectInput_to_CEGUI_utf32

I trace source code of OIS ver1 that found "int n32Keyboard::_translateText( KeyCode kc )" implementation is almost the same with "CEGUI::utf32 keycodeToUTF32( unsigned int scanCode)
".


This current implementation only supports 5 diacritic, making the following code compatible with both English and French languages

:cry: It saids that the implementation is compatible with both English and French languages. But others is compatible ? I am not sure.

To compares:

int Win32Keyboard::_translateText( KeyCode kc )
{
if( mTextMode == Off )
return 0;

BYTE keyState[256];
HKL layout = GetKeyboardLayout(0);
if( GetKeyboardState(keyState) == 0 )
return 0;

unsigned int vk = MapVirtualKeyEx(kc, 3, layout);
if( vk == 0 )
return 0;

unsigned char buff[3] = {0,0,0};
int ascii = ToAsciiEx(vk, kc, keyState, (LPWORD) buff, 0, layout);
//WCHAR wide[3];
//int ascii = ToUnicodeEx(vk, kc, keyState, wide, 3, 0, layout);
if(ascii == 1 && deadKey != '\0' )
{
// A dead key is stored and we have just converted a character key
// Combine the two into a single character
WCHAR wcBuff[3] = {buff[0], deadKey, '\0'};
WCHAR out[3];

deadKey = '\0';
if(FoldStringW(MAP_PRECOMPOSED, (LPWSTR)wcBuff, 3, (LPWSTR)out, 3))
return out[0];
}
else if (ascii == 1)
{ // We have a single character
deadKey = '\0';
return buff[0];
}
else if(ascii == 2)
{ // Convert a non-combining diacritical mark into a combining diacritical mark
// Combining versions range from 0x300 to 0x36F; only 5 (for French) have been mapped below
// http://www.fileformat.info/info/unicode/block/combining_diacritical_marks/images.htm
switch(buff[0]) {
case 0x5E: // Circumflex accent: ?
deadKey = 0x302; break;
case 0x60: // Grave accent: ?
deadKey = 0x300; break;
case 0xA8: // Diaeresis: ?
deadKey = 0x308; break;
case 0xB4: // Acute accent: ?
deadKey = 0x301; break;
case 0xB8: // Cedilla: ?
deadKey = 0x327; break;
default:
deadKey = buff[0]; break;
}
}

return 0;
}





CEGUI::utf32 keycodeToUTF32( unsigned int scanCode)
{
CEGUI::utf32 utf = 0;

BYTE keyboardState[256];
unsigned char ucBuffer[3];
static WCHAR deadKey = '\0';

// Retrieve the keyboard layout in order to perform the necessary convertions
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

// Retrieve the keyboard state
// Handles CAPS-lock and SHIFT states
if (GetKeyboardState(keyboardState) == FALSE)
return utf;

/* 0. Convert virtual-key code into a scan code
1. Convert scan code into a virtual-key code
Does not distinguish between left- and right-hand keys.
2. Convert virtual-key code into an unshifted character value
in the low order word of the return value. Dead keys (diacritics)
are indicated by setting the top bit of the return value.
3. Windows NT/2000/XP: Convert scan code into a virtual-key
Distinguishes between left- and right-hand keys.*/
UINT virtualKey = MapVirtualKeyEx(scanCode, 3, hklKeyboardLayout);
if (virtualKey == 0) // No translation possible
return utf;

/* Parameter 5:
0. No menu is active
1. A menu is active
Return values:
Negative. Returned a dead key
0. No translation available
1. A translation exists
2. Dead-key could not be combined with character */
int ascii = ToAsciiEx(virtualKey, scanCode, keyboardState, (LPWORD) ucBuffer, 0, hklKeyboardLayout);
if(deadKey != '\0' && ascii == 1)
{
// A dead key is stored and we have just converted a character key
// Combine the two into a single character
WCHAR wcBuffer[3];
WCHAR out[3];
wcBuffer[0] = ucBuffer[0];
wcBuffer[1] = deadKey;
wcBuffer[2] = '\0';
if( FoldStringW(MAP_PRECOMPOSED, (LPWSTR) wcBuffer, 3, (LPWSTR) out, 3) )
utf = out[0];
else
{
// FoldStringW failed
DWORD dw = GetLastError();
switch(dw)
{
case ERROR_INSUFFICIENT_BUFFER:
case ERROR_INVALID_FLAGS:
case ERROR_INVALID_PARAMETER:
break;
}
}
deadKey = '\0';
}
else if (ascii == 1)
{
// We have a single character
utf = ucBuffer[0];
deadKey = '\0';
}
else
{
// Convert a non-combining diacritical mark into a combining diacritical mark
switch(ucBuffer[0])
{
case 0x5E: // Circumflex accent: â
deadKey = 0x302;
break;
case 0x60: // Grave accent: à
deadKey = 0x300;
break;
case 0xA8: // Diaeresis: ü
deadKey = 0x308;
break;
case 0xB4: // Acute accent: é
deadKey = 0x301;
break;
case 0xB8: // Cedilla: ç
deadKey = 0x327;
break;
default:
deadKey = ucBuffer[0];
}
}

return utf;
}