You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
287 lines
8.4 KiB
287 lines
8.4 KiB
|
|
|
|
#include "private.h"
|
|
#include "cicsthkl.h"
|
|
|
|
#define LANGIDFROMHKL(x) LANGID(LOWORD(HandleToLong(x)))
|
|
|
|
const CHAR c_szCTFTIPKey[] = "SOFTWARE\\Microsoft\\CTF\\TIP\\";
|
|
const CHAR c_szLanguageProfileKey[] = "LanguageProfile\\";
|
|
const CHAR c_szSubstitutehKL[] = "SubstituteLayout";
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Function: cicsthkl_CLSIDToString
|
|
//
|
|
// Synopsis: Converts a CLSID to an mbcs string.
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
static const BYTE GuidMap[] = {3, 2, 1, 0, '-', 5, 4, '-', 7, 6, '-',
|
|
8, 9, '-', 10, 11, 12, 13, 14, 15};
|
|
|
|
static const char szDigits[] = "0123456789ABCDEF";
|
|
|
|
|
|
BOOL cicsthkl_CLSIDToStringA(REFGUID refGUID, char *pchA)
|
|
{
|
|
int i;
|
|
char *p = pchA;
|
|
|
|
const BYTE * pBytes = (const BYTE *) &refGUID;
|
|
|
|
*p++ = '{';
|
|
for (i = 0; i < sizeof(GuidMap); i++)
|
|
{
|
|
if (GuidMap[i] == '-')
|
|
{
|
|
*p++ = '-';
|
|
}
|
|
else
|
|
{
|
|
*p++ = szDigits[ (pBytes[GuidMap[i]] & 0xF0) >> 4 ];
|
|
*p++ = szDigits[ (pBytes[GuidMap[i]] & 0x0F) ];
|
|
}
|
|
}
|
|
|
|
*p++ = '}';
|
|
*p = '\0';
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// cicsthkl_AsciiToNum
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD cicsthkl_AsciiToNum( char *pszAscii)
|
|
{
|
|
DWORD dwNum = 0;
|
|
|
|
for (; *pszAscii; pszAscii++) {
|
|
if (*pszAscii >= '0' && *pszAscii <= '9') {
|
|
dwNum = (dwNum << 4) | (*pszAscii - '0');
|
|
} else if (*pszAscii >= 'A' && *pszAscii <= 'F') {
|
|
dwNum = (dwNum << 4) | (*pszAscii - 'A' + 0x000A);
|
|
} else if (*pszAscii >= 'a' && *pszAscii <= 'f') {
|
|
dwNum = (dwNum << 4) | (*pszAscii - 'a' + 0x000A);
|
|
} else {
|
|
return (0);
|
|
}
|
|
}
|
|
|
|
return (dwNum);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// cicsthkl_NumToA
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void cicsthkl_NumToAscii(DWORD dw, char *psz)
|
|
{
|
|
int n = 7;
|
|
while (n >= 0)
|
|
{
|
|
BYTE b = (BYTE)(dw >> (n * 4)) & 0x0F;
|
|
if (b < 0x0A)
|
|
*psz = (char)('0' + b);
|
|
else
|
|
*psz = (char)('A' + b - 0x0A);
|
|
psz++;
|
|
n--;
|
|
}
|
|
*psz = L'\0';
|
|
|
|
return;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetSubstituteHKLFromReg
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HKL GetSubstituteHKLFromReg(REFCLSID rclsid, LANGID langid, REFGUID rguid)
|
|
{
|
|
HKL hKL = NULL;
|
|
CHAR szKey[MAX_PATH];
|
|
CHAR szTempStr[64];
|
|
|
|
StringCchCopyA(szKey, ARRAYSIZE(szKey), c_szCTFTIPKey);
|
|
cicsthkl_CLSIDToStringA(rclsid, szTempStr);
|
|
StringCchCatA(szKey, ARRAYSIZE(szKey), szTempStr);
|
|
StringCchCatA(szKey, ARRAYSIZE(szKey), "\\");
|
|
StringCchCatA(szKey, ARRAYSIZE(szKey), c_szLanguageProfileKey);
|
|
StringCchPrintfA(szTempStr, ARRAYSIZE(szTempStr), "0x%08x", langid);
|
|
StringCchCatA(szKey, ARRAYSIZE(szKey), szTempStr);
|
|
StringCchCatA(szKey, ARRAYSIZE(szKey), "\\");
|
|
cicsthkl_CLSIDToStringA(rguid, szTempStr);
|
|
StringCchCatA(szKey, ARRAYSIZE(szKey), szTempStr);
|
|
|
|
HKEY hKey = NULL;
|
|
LONG lRes = RegOpenKeyExA(HKEY_LOCAL_MACHINE, szKey, 0, KEY_READ, &hKey);
|
|
if (lRes == ERROR_SUCCESS)
|
|
{
|
|
DWORD dwType = NULL;
|
|
char szValue[32];
|
|
DWORD dwCount = sizeof(szValue);
|
|
lRes = RegQueryValueExA(hKey,
|
|
(LPTSTR)c_szSubstitutehKL,
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE)szValue,
|
|
&dwCount);
|
|
|
|
if (lRes == ERROR_SUCCESS)
|
|
{
|
|
if ((szValue[0] == '0') &&
|
|
((szValue[1] == 'X') || (szValue[1] == 'x')))
|
|
hKL = (HKL)IntToPtr(cicsthkl_AsciiToNum(&szValue[2]));
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
return hKL;
|
|
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// [in] langid
|
|
// langid may be LOWORD of the return value of GetKeyboardLayout(0).
|
|
//
|
|
// The return value
|
|
// It returns NULL hKL
|
|
// - if Cicero does not have a focus
|
|
// - it there is no keyboard TIP running now
|
|
// - it the current keyboard TIP does not have a substitute layout.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT CicGetSubstitueHKL(LANGID langid, HKL *phkl, BOOL fCheckFocus)
|
|
{
|
|
HRESULT hr;
|
|
ITfThreadMgr *ptim;
|
|
|
|
*phkl = NULL;
|
|
|
|
if (fCheckFocus)
|
|
{
|
|
BOOL fFocusInCicero = FALSE;
|
|
if (SUCCEEDED(CoCreateInstance( CLSID_TF_ThreadMgr,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_ITfThreadMgr,
|
|
(void **)&ptim))) {
|
|
|
|
ITfDocumentMgr *pdim;
|
|
if (SUCCEEDED(ptim->GetFocus(&pdim)) && pdim)
|
|
{
|
|
fFocusInCicero = TRUE;
|
|
pdim->Release();
|
|
}
|
|
ptim->Release();
|
|
}
|
|
|
|
if (!fFocusInCicero)
|
|
{
|
|
//
|
|
// Cicero does not have a focus. Try GetKeyboardLayout(0).
|
|
//
|
|
return S_FALSE;
|
|
}
|
|
}
|
|
|
|
HKL hKL = NULL;
|
|
ITfInputProcessorProfiles *pPro;
|
|
|
|
if (SUCCEEDED(hr = CoCreateInstance(CLSID_TF_InputProcessorProfiles,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_ITfInputProcessorProfiles,
|
|
(void **)&pPro ))) {
|
|
CLSID clsid;
|
|
GUID guid;
|
|
|
|
ITfInputProcessorProfileSubstituteLayout *pProSubLayout;
|
|
|
|
if (SUCCEEDED(hr = pPro->GetDefaultLanguageProfile(langid,
|
|
GUID_TFCAT_TIP_KEYBOARD,
|
|
&clsid,
|
|
&guid)))
|
|
{
|
|
if (!IsEqualGUID(clsid, CLSID_NULL))
|
|
{
|
|
if (SUCCEEDED(hr = pPro->QueryInterface(IID_ITfInputProcessorProfileSubstituteLayout,
|
|
(void **)&pProSubLayout)))
|
|
{
|
|
hr = pProSubLayout->GetSubstituteKeyboardLayout(clsid,
|
|
langid,
|
|
guid,
|
|
&hKL);
|
|
pProSubLayout->Release();
|
|
}
|
|
else
|
|
{
|
|
hKL = GetSubstituteHKLFromReg(clsid, langid, guid);
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
}
|
|
pPro->Release();
|
|
}
|
|
|
|
//
|
|
// if hKL is NULL, please get hKL from GetKeybaordLayout(0).
|
|
//
|
|
*phkl = hKL;
|
|
return hr;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// CicSubstGetKeyboardLayout
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
extern "C" HKL WINAPI CicSubstGetKeyboardLayout(char *pszKLID)
|
|
{
|
|
HKL hkl = NULL;
|
|
HKL hklReal = GetKeyboardLayout(0);
|
|
|
|
if (SUCCEEDED(CicGetSubstitueHKL(LANGIDFROMHKL(hklReal), &hkl, TRUE)))
|
|
{
|
|
if (!hkl)
|
|
{
|
|
hkl = hklReal;
|
|
if (pszKLID)
|
|
GetKeyboardLayoutName(pszKLID);
|
|
}
|
|
else
|
|
{
|
|
if (pszKLID)
|
|
cicsthkl_NumToAscii((DWORD)HandleToLong(hkl), pszKLID);
|
|
}
|
|
}
|
|
return hkl;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// CicSubstGetDefaultKeyboardLayout
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
extern "C" HKL WINAPI CicSubstGetDefaultKeyboardLayout(LANGID langid)
|
|
{
|
|
HKL hkl = NULL;
|
|
|
|
CicGetSubstitueHKL(langid, &hkl, FALSE);
|
|
|
|
return hkl;
|
|
|
|
}
|