diff --git a/widget/src/os2/nsModule.cpp b/widget/src/os2/nsModule.cpp index 9d32ddb1ddfe..cb36768a7ae8 100644 --- a/widget/src/os2/nsModule.cpp +++ b/widget/src/os2/nsModule.cpp @@ -53,8 +53,6 @@ #define KBD_CTRL KBD_CONTROL #endif -static void GetKeyboardName( char *buff); - nsWidgetModuleData::nsWidgetModuleData() {} @@ -109,24 +107,6 @@ void nsWidgetModuleData::Init( nsIAppShell *aPrimaevalAppShell) converter = 0; supplantConverter = FALSE; - // create unicode keyboard object - char kbdname[8]; - UniChar unikbdname[8]; - GetKeyboardName( kbdname); - for( int i = 0; i < 8; i++) - unikbdname[i] = kbdname[i]; - - if( UniCreateKeyboard( &hKeyboard, unikbdname, 0) != ULS_SUCCESS) - { - unikbdname[2] = L'\0'; - if( UniCreateKeyboard( &hKeyboard, unikbdname, 0) != ULS_SUCCESS) - hKeyboard = 0; - } -#ifdef DEBUG - else - printf( "Widget library loaded keyboard table for %s\n", kbdname); -#endif - #if 0 mWindows = nsnull; #endif @@ -134,9 +114,6 @@ void nsWidgetModuleData::Init( nsIAppShell *aPrimaevalAppShell) nsWidgetModuleData::~nsWidgetModuleData() { - if( hKeyboard) - UniDestroyKeyboard( hKeyboard); - if( converter) UniFreeUconvObject( converter); @@ -224,6 +201,94 @@ HPOINTER nsWidgetModuleData::GetFrameIcon() return hptrFrameIcon; } +int nsWidgetModuleData::CreateUcsConverter() +{ + // Create a converter from unicode to a codepage which PM can display. + UniChar codepage[20]; + int unirc = UniMapCpToUcsCp( 0, codepage, 20); + if( unirc == ULS_SUCCESS) + { + unirc = UniCreateUconvObject( codepage, &converter); + // XXX do we need to set substitution options here? +#ifdef DEBUG + if( unirc == ULS_SUCCESS) + { + printf( "Widget library created unicode converter for cp %s\n", + ConvertFromUcs( (PRUnichar *) codepage)); + } +#endif + } + if( unirc != ULS_SUCCESS) + { + printf( "Couldn't create widget unicode converter.\n"); + } + + return unirc; +} + +// Conversion from appropriate codepage to unicode +PRUnichar *nsWidgetModuleData::ConvertToUcs( const char *szText, + PRUnichar *pBuffer, + ULONG ulSize) +{ + if( supplantConverter) + { + // We couldn't create a converter for some reason, so do this 'by hand'. + // Note this algorithm is fine for most of most western charsets, but + // fails dismally for various glyphs, baltic, points east... + ULONG ulCount = 0; + PRUnichar *pSave = pBuffer; + while( *szText && ulCount < ulSize - 1) // (one for terminator) + { + *pBuffer = (PRUnichar)((SHORT)*szText & 0x00FF); + pBuffer++; + szText++; + ulCount++; + } + + // terminate string + *pBuffer = (PRUnichar)0; + + return pSave; + } + + if( !converter) + { + if( CreateUcsConverter() != ULS_SUCCESS) + { + supplantConverter = TRUE; + return ConvertToUcs( szText, pBuffer, ulSize); + } + } + + // Have converter, now get it to work... + + char *szString = (char *)szText; + size_t szLen = strlen( szText) + 1; + size_t ucsLen = ulSize; + size_t cSubs = 0; + + UniChar *tmp = pBuffer; // function alters the out pointer + + int unirc = UniUconvToUcs( converter, (void **)&szText, &szLen, + &tmp, &ucsLen, &cSubs); + + if( unirc == UCONV_E2BIG) // k3w1 + { + // terminate output string (truncating) + *(pBuffer + ulSize - 1) = (PRUnichar)0; + } + else if( unirc != ULS_SUCCESS) + { + printf( "UniUconvToUcs failed, rc %X\n", unirc); + supplantConverter = TRUE; + pBuffer = ConvertToUcs( szText, pBuffer, ulSize); + supplantConverter = FALSE; + } + + return pBuffer; +} + // Conversion from unicode to appropriate codepage char *nsWidgetModuleData::ConvertFromUcs( const PRUnichar *pText, char *szBuffer, ULONG ulSize) @@ -251,25 +316,9 @@ char *nsWidgetModuleData::ConvertFromUcs( const PRUnichar *pText, if( !converter) { - // Create a converter from unicode to a codepage which PM can display. - UniChar codepage[20]; - int unirc = UniMapCpToUcsCp( 0, codepage, 20); - if( unirc == ULS_SUCCESS) - { - unirc = UniCreateUconvObject( codepage, &converter); - // XXX do we need to set substitution options here? -#ifdef DEBUG - if( unirc == ULS_SUCCESS) - { - printf( "Widget library created unicode converter for cp %s\n", - ConvertFromUcs( (PRUnichar *) codepage)); - } -#endif - } - if( unirc != ULS_SUCCESS) + if( CreateUcsConverter() != ULS_SUCCESS) { supplantConverter = TRUE; - printf( "Couldn't create widget unicode converter.\n"); return ConvertFromUcs( pText, szBuffer, ulSize); } } @@ -340,93 +389,6 @@ const char *nsWidgetModuleData::ConvertFromUcs( const nsString &aString) return szRet; } -// Wrapper around UniTranslateKey to deal with shift-state etc. -int nsWidgetModuleData::TranslateKey( VSCAN scan, UniChar *pChar, VDKEY *vdkey) -{ - int unirc = 1; - - // bail if we've not got a keyboard - if( !hKeyboard) return unirc; - - // XXX Right, this seems madly wrong, but I'm not sure what else to do. - // We need to work out the 'effective shift state' before calling - // UniTranslateKey(). This is derived from the state of the keyboard - // and the current scancode. Unfortunately, the only way I can find - // the current state of the various keys is by doing this on each - // keypress! - // - // XXX Anything else to test? Layers? Or are they just deadkey applications? - // Are deadkeys meant to go in here? - - ULONG sstate = 0; - - if( WinIsKeyDown(VK_SHIFT)) sstate |= KBD_SHIFT; - // We should not be passing these to UniTranslateKey because they affect the char code. - // We want the actual key that is being pressed. Passing Ctrl+A to UniTranslateKey - // returns the ASCII code for Ctrl+A -// if( WinIsKeyDown(VK_CTRL)) sstate |= KBD_CTRL; -// if( WinIsKeyDown(VK_ALT)) sstate |= KBD_ALT; - if( WinIsKeyDown(VK_ALTGRAF)) sstate |= KBD_ALTGR; - - #define TOGGLED(vk) (WinGetKeyState(HWND_DESKTOP,vk) & 1) - - if( TOGGLED(VK_CAPSLOCK)) sstate |= KBD_CAPSLOCK; - if( TOGGLED(VK_NUMLOCK)) sstate |= KBD_NUMLOCK; - if( TOGGLED(VK_SCRLLOCK)) sstate |= KBD_SCROLLLOCK; - - USHIFTSTATE uss = { sstate, 0, 0 }; - - unirc = UniUpdateShiftState( hKeyboard, &uss, scan, 0); - if( unirc == ULS_SUCCESS) - { - BYTE bBiosScancode; - unirc = UniTranslateKey( hKeyboard, - uss.Effective, - scan, - pChar, - vdkey, - &bBiosScancode); - } - - return unirc; -} - -static void GetKeyboardName( char *buff) -{ - HFILE hKeyboard = 0; - ULONG ulAction; - - strcpy( buff, "UK"); - - if( !DosOpen( "KBD$", &hKeyboard, &ulAction, 0, FILE_NORMAL, FILE_OPEN, - OPEN_ACCESS_READONLY | OPEN_SHARE_DENYWRITE, NULL)) - { - ULONG ulDataLen; -#pragma pack(2) - struct { USHORT usLength; USHORT usCp; CHAR ach[8];} kcp; -#pragma pack() - - kcp.usLength = ulDataLen = sizeof kcp; - - if( !DosDevIOCtl( hKeyboard, IOCTL_KEYBOARD, KBD_QUERYKBDCODEPAGESUPPORT, - 0, 0, 0, - &kcp, ulDataLen, &ulDataLen)) - { - int length; - strcpy( buff, kcp.ach); - strcat( buff, kcp.ach+strlen(kcp.ach)+1); - // Strip off white space at the end of the keyboard name - length = strlen(buff); - while( length && buff[--length] == ' ') - { - buff[length] = '\0'; - } - } - - DosClose( hKeyboard); - } -} - ATOM nsWidgetModuleData::GetAtom( const char *atomname) { ATOM atom = WinAddAtom( WinQuerySystemAtomTable(), atomname); diff --git a/widget/src/os2/nsWidgetDefs.h b/widget/src/os2/nsWidgetDefs.h index a9c90240cb75..cd74aac202a5 100644 --- a/widget/src/os2/nsWidgetDefs.h +++ b/widget/src/os2/nsWidgetDefs.h @@ -63,6 +63,9 @@ class nsWidgetModuleData HPOINTER GetPointer( nsCursor aCursor); HPOINTER GetFrameIcon(); + // local->Unicode cp. conversion + PRUnichar *ConvertToUcs( const char *szText, PRUnichar *pBuffer, ULONG ulSize); + // Unicode->local cp. conversions char *ConvertFromUcs( const PRUnichar *pText, char *szBuffer, ULONG ulSize); char *ConvertFromUcs( const nsString &aStr, char *szBuffer, ULONG ulSize); @@ -70,10 +73,6 @@ class nsWidgetModuleData const char *ConvertFromUcs( const PRUnichar *pText); const char *ConvertFromUcs( const nsString &aStr); - // Unicode keyboard utility stuff - KHAND hKeyboard; - int TranslateKey( VSCAN scan, UniChar *aChar, VDKEY *vdkey); - // Atom service; clients don't need to bother about freeing them. ATOM GetAtom( const char *atomname); ATOM GetAtom( const nsString &atomname); @@ -95,6 +94,9 @@ class nsWidgetModuleData nsHashtable *mWindows; #endif + // Utility function for creating the Unicode conversion object + int CreateUcsConverter(); + UconvObject converter; BOOL supplantConverter; diff --git a/widget/src/os2/nsWindow.cpp b/widget/src/os2/nsWindow.cpp index 7749289ba113..245b3e0dd39a 100644 --- a/widget/src/os2/nsWindow.cpp +++ b/widget/src/os2/nsWindow.cpp @@ -73,7 +73,6 @@ #include #include -#include #ifdef DEBUG_sobotka static int WINDOWCOUNT = 0; @@ -1700,6 +1699,7 @@ PRBool nsWindow::OnKey( MPARAM mp1, MPARAM mp2) nsKeyEvent event; USHORT fsFlags = SHORT1FROMMP(mp1); USHORT usVKey = SHORT2FROMMP(mp2); + USHORT usChar = SHORT1FROMMP(mp2); UCHAR uchScan = CHAR4FROMMP(mp1); int unirc = ULS_SUCCESS; @@ -1714,13 +1714,6 @@ PRBool nsWindow::OnKey( MPARAM mp1, MPARAM mp2) // Now check if it's a dead-key if( fsFlags & KC_DEADKEY) { - UniChar tmp; - unirc = gModuleData.TranslateKey( uchScan, &tmp, &mDeadKey); - if( unirc == ULS_SUCCESS) - mHaveDeadKey = TRUE; - else - printf( "Couldn't translate dead key\n"); - // XXX CUA says we're supposed to give some kind of feedback `display the // dead key glyph'. I'm not sure if we can use the COMPOSE messages // to do this -- it should really be done by someone who can test it @@ -1763,36 +1756,29 @@ PRBool nsWindow::OnKey( MPARAM mp1, MPARAM mp2) event.message = NS_KEY_PRESS; - VDKEY vdkeyTmp; - unirc = gModuleData.TranslateKey( uchScan, (UniChar*) &event.charCode, - &vdkeyTmp); - - if( mHaveDeadKey && (fsFlags & KC_COMPOSITE) && unirc == ULS_SUCCESS) + if( usChar) { - unirc = UniTranslateDeadkey( gModuleData.hKeyboard, -#ifdef XP_OS2_VACPP - mDeadKey, -#else - &mDeadKey, -#endif - (UniChar) event.charCode, - (UniChar*) &event.charCode, - &mDeadKey); - mHaveDeadKey = FALSE; - } + USHORT inbuf[2]; + UniChar outbuf[4]; + inbuf[0] = usChar; + inbuf[1] = '\0'; + outbuf[0] = (UniChar)0; - if( unirc != ULS_SUCCESS) - { - printf( "UniTranslate[Dead]Key returned %u\n", unirc); - event.charCode = CHAR2FROMMP(mp2); - } + gModuleData.ConvertToUcs( (char *)inbuf, (PRUnichar *)outbuf, 4); - if( !event.isControl && !event.isAlt && event.charCode != 0) - { - if (!(fsFlags & KC_VIRTUALKEY)) + event.charCode = outbuf[0]; + + if( event.isControl && !event.isShift && event.charCode >= 'A' && event.charCode <= 'Z' ) { - event.isShift = PR_FALSE; - event.keyCode = 0; + event.charCode = tolower(event.charCode); + } + else if( !event.isControl && !event.isAlt && event.charCode != 0) + { + if (!(fsFlags & KC_VIRTUALKEY)) + { + event.isShift = PR_FALSE; // OS2TODO - Why do we need this? + event.keyCode = 0; + } } }