зеркало из https://github.com/mozilla/gecko-dev.git
r=mkaply, a=blizzard Finally, real OS/2 keyboard support
This commit is contained in:
Родитель
cbca27c327
Коммит
a30aa10746
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -73,7 +73,6 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <unikbd.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче