Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1382 lines
38 KiB

/**************************************************************************\
* Module Name: softkbdimx.cpp
*
* Copyright (c) 1985 - 2000, Microsoft Corporation
*
* Implement TIP interface for Soft Keyboard Input.
*
* History:
* 28-March-2000 weibz Created
\**************************************************************************/
#include "private.h"
#include "softkbdimx.h"
#include "globals.h"
#include "immxutil.h"
#include "proputil.h"
#include "funcprv.h"
#include "helpers.h"
#include "editcb.h"
#include "dispattr.h"
#include "computil.h"
#include "timsink.h"
#include "ats.h"
#include "lpns.h"
#include "regsvr.h"
#include "softkbdes.h"
#include "mui.h"
#include "regimx.h"
#include "xstring.h"
#include "cregkey.h"
extern REGTIPLANGPROFILE c_rgProf[];
// Implementation of CSoftkbdRegistry.
//+---------------------------------------------------------------------------
//
// ctor
//
//----------------------------------------------------------------------------
CSoftkbdRegistry::CSoftkbdRegistry()
{
extern void DllAddRef(void);
m_fInitialized = FALSE;
DllAddRef( );
}
//+---------------------------------------------------------------------------
//
// dtor
//
//----------------------------------------------------------------------------
CSoftkbdRegistry::~CSoftkbdRegistry()
{
extern void DllRelease(void);
if (m_rgLang.Count())
m_rgLang.Clear();
DllRelease();
}
// Generate the Current Lang Profile List from registry.
HRESULT CSoftkbdRegistry::_GenerateCurrentLangProfileList( )
{
HRESULT hr = S_OK;
CComPtr<IEnumTfLanguageProfiles> cpEnumTfLangProf;
if ( m_fInitialized == FALSE)
{
hr = CoCreateInstance(CLSID_TF_InputProcessorProfiles, NULL,
CLSCTX_INPROC_SERVER,
IID_ITfInputProcessorProfilesEx, (void**)&m_cpInputProcessorProfiles);
// Load profile name from resource.
LoadStringWrapW(g_hInst, IDS_SFTKBD_STANDARD_PROFILE, m_pwszStandard, 128);
LoadStringWrapW(g_hInst, IDS_SFTKBD_SYMBOL_PROFILE, m_pwszSymbol, 128);
char szFilePath[MAX_PATH];
GetModuleFileName(g_hInst, szFilePath, ARRAYSIZE(szFilePath));
StringCchCopyW(m_pwszIconFile, ARRAYSIZE(m_pwszIconFile), AtoW(szFilePath));
if ( hr == S_OK )
m_fInitialized = TRUE;
}
if (hr == S_OK)
{
LONG lret = ERROR_SUCCESS;
CMyRegKey regkey;
if (m_rgLang.Count())
m_rgLang.Clear();
// Get the Language profile list for all languages.
char szSoftkbdLangProfKey[MAX_PATH];
char szClsidStr[64];
StringCchCopyA(szSoftkbdLangProfKey, ARRAYSIZE(szSoftkbdLangProfKey), c_szCTFTIPKey);
CLSIDToStringA(CLSID_SoftkbdIMX, szClsidStr);
StringCchCatA(szSoftkbdLangProfKey, ARRAYSIZE(szSoftkbdLangProfKey), szClsidStr);
StringCchCatA(szSoftkbdLangProfKey, ARRAYSIZE(szSoftkbdLangProfKey), "\\");
StringCchCatA(szSoftkbdLangProfKey, ARRAYSIZE(szSoftkbdLangProfKey), c_szLanguageProfileKey);
lret = regkey.Open(HKEY_LOCAL_MACHINE,
szSoftkbdLangProfKey,
KEY_READ);
if ( ERROR_SUCCESS == lret )
{
char szProfileName[MAX_PATH];
char szLangIdName[MAX_PATH];
DWORD dwIndex = 0;
LANGID langid;
BOOL fStandExist = FALSE;
BOOL fSymExist = FALSE;
TCHAR achClsidStd[CLSID_STRLEN+1];
TCHAR achClsidSym[CLSID_STRLEN+1];
CMyRegKey regLangKey;
ULONG ulCount = 0;
CLSIDToStringA(c_guidProfile, achClsidStd);
CLSIDToStringA(c_guidProfileSym, achClsidSym);
// Enum the subkey for langid.
while ( ERROR_SUCCESS == regkey.EnumKey(dwIndex, szLangIdName, ARRAYSIZE(szLangIdName)))
{
lret = regLangKey.Open(regkey.m_hKey,
szLangIdName,
KEY_READ);
if ( ERROR_SUCCESS == lret )
{
char *pLangStr;
int iLangLen;
DWORD dwProfIndex;
pLangStr = szLangIdName;
if ( (tolower(pLangStr[0]) == '0') && (tolower(pLangStr[1]) == 'x'))
pLangStr += 2;
iLangLen = strlen(pLangStr);
langid = 0;
for ( int i=0; i<iLangLen; i++)
{
WORD wVchar;
char cLower;
cLower = (char)tolower(pLangStr[i]);
wVchar = 0;
if ((cLower <= '9') && (cLower >= '0'))
wVchar = cLower - '0';
if ((cLower <= 'f') && (cLower >= 'a' ))
wVchar = cLower - 'a' + 10;
langid = langid * 16 + wVchar;
}
fStandExist = fSymExist = FALSE;
dwProfIndex = 0;
while (!(fStandExist && fSymExist)
&& ERROR_SUCCESS == regLangKey.EnumKey(dwProfIndex, szProfileName, ARRAYSIZE(szProfileName)))
{
if ( !_stricmp(szProfileName, achClsidStd) )
fStandExist = TRUE;
else if ( !_stricmp(szProfileName, achClsidSym) )
fSymExist = TRUE;
dwProfIndex++;
}
if ( fStandExist && fSymExist )
{
LANGID *pLang;
m_rgLang.Append(1);
pLang = m_rgLang.GetPtr(ulCount);
if ( pLang )
{
ulCount ++;
*pLang = langid;
}
}
regLangKey.Close( );
}
dwIndex ++;
}
}
}
return hr;
}
// Add or Remove Language profile
HRESULT CSoftkbdRegistry::_SetSoftkbdTIP(LANGID langid, BOOL fEnable )
{
HRESULT hr = S_OK;
ULONG ulCount;
BOOL fAllLangExist = FALSE;
BOOL fLangExist = FALSE;
LANGID *pLangId = NULL;
hr = _GenerateCurrentLangProfileList( );
if ( hr != S_OK ) return hr;
ulCount = m_rgLang.Count();
if ( langid == 0 || langid == (LANGID)0xffff )
{
// Remove all the Profiles first.
for (ULONG i=0; i<ulCount; i++)
{
pLangId = m_rgLang.GetPtr(i);
if ( pLangId )
{
hr = m_cpInputProcessorProfiles->RemoveLanguageProfile(CLSID_SoftkbdIMX,
*pLangId,
c_guidProfile);
if (S_OK == hr)
hr = m_cpInputProcessorProfiles->RemoveLanguageProfile(CLSID_SoftkbdIMX,
*pLangId,
c_guidProfileSym);
}
}
if ( fEnable && hr == S_OK) // Add this profile for all languages.
{
hr = m_cpInputProcessorProfiles->AddLanguageProfile(CLSID_SoftkbdIMX,
(LANGID)0xffff,
c_guidProfile,
m_pwszStandard,
wcslen(m_pwszStandard),
m_pwszIconFile,
wcslen(m_pwszIconFile),
0);
if ( hr == S_OK )
{
// Set DisplayName for MUI supporting
hr = m_cpInputProcessorProfiles->SetLanguageProfileDisplayName(CLSID_SoftkbdIMX,
(LANGID)0xffff,
c_guidProfile,
m_pwszIconFile,
wcslen(m_pwszIconFile),
IDS_SFTKBD_STANDARD_PROFILE );
}
if ( hr == S_OK )
{
hr = m_cpInputProcessorProfiles->AddLanguageProfile(CLSID_SoftkbdIMX,
(LANGID)0xffff,
c_guidProfileSym,
m_pwszSymbol,
wcslen(m_pwszSymbol),
m_pwszIconFile,
wcslen(m_pwszIconFile),
1);
}
if ( hr == S_OK )
{
// Set DisplayName for MUI supporting
hr = m_cpInputProcessorProfiles->SetLanguageProfileDisplayName(CLSID_SoftkbdIMX,
(LANGID)0xffff,
c_guidProfileSym,
m_pwszIconFile,
wcslen(m_pwszIconFile),
IDS_SFTKBD_SYMBOL_PROFILE );
}
}
return hr;
}
// Check to see if this profile is already there
for (ULONG i=0; i<ulCount; i++)
{
if ( fAllLangExist && fLangExist )
break;
pLangId = m_rgLang.GetPtr(i);
if ( pLangId )
{
if ( *pLangId == (LANGID)0xffff)
fAllLangExist = TRUE;
if ( *pLangId == langid )
fLangExist = TRUE;
}
}
if ( fEnable )
{
if ( !fAllLangExist && !fLangExist )
{
hr = m_cpInputProcessorProfiles->AddLanguageProfile(CLSID_SoftkbdIMX,
langid,
c_guidProfile,
m_pwszStandard,
wcslen(m_pwszStandard),
m_pwszIconFile,
wcslen(m_pwszIconFile),
0);
if ( hr == S_OK )
{
// Set DisplayName for MUI supporting
hr = m_cpInputProcessorProfiles->SetLanguageProfileDisplayName(CLSID_SoftkbdIMX,
langid,
c_guidProfile,
m_pwszIconFile,
wcslen(m_pwszIconFile),
IDS_SFTKBD_STANDARD_PROFILE );
}
if ( hr == S_OK )
{
hr = m_cpInputProcessorProfiles->AddLanguageProfile(CLSID_SoftkbdIMX,
langid,
c_guidProfileSym,
m_pwszSymbol,
wcslen(m_pwszSymbol),
m_pwszIconFile,
wcslen(m_pwszIconFile),
1);
}
if ( hr == S_OK )
{
// Set DisplayName for MUI supporting
hr = m_cpInputProcessorProfiles->SetLanguageProfileDisplayName(CLSID_SoftkbdIMX,
langid,
c_guidProfileSym,
m_pwszIconFile,
wcslen(m_pwszIconFile),
IDS_SFTKBD_SYMBOL_PROFILE );
}
}
}
else
{
// Remove the specified or all Profiles.
for (ULONG i=0; i<ulCount; i++)
{
pLangId = m_rgLang.GetPtr(i);
if ( pLangId )
{
if ( fAllLangExist )
{
hr = m_cpInputProcessorProfiles->RemoveLanguageProfile(CLSID_SoftkbdIMX,
*pLangId,
c_guidProfile);
if ( S_OK == hr )
hr = m_cpInputProcessorProfiles->RemoveLanguageProfile(CLSID_SoftkbdIMX,
*pLangId,
c_guidProfileSym);
}
else if ( fLangExist )
{
if ( *pLangId == langid )
{
hr = m_cpInputProcessorProfiles->RemoveLanguageProfile(CLSID_SoftkbdIMX,
langid,
c_guidProfile);
if ( S_OK == hr )
hr = m_cpInputProcessorProfiles->RemoveLanguageProfile(CLSID_SoftkbdIMX,
langid,
c_guidProfileSym);
}
}
}
}
}
return hr;
}
HRESULT CSoftkbdRegistry::EnableSoftkbd(LANGID langid )
{
return _SetSoftkbdTIP(langid, TRUE);
}
HRESULT CSoftkbdRegistry::DisableSoftkbd(LANGID langid )
{
return _SetSoftkbdTIP(langid, FALSE);
}
//+---------------------------------------------------------------------------
//
// ctor
//
//----------------------------------------------------------------------------
CSoftkbdIMX::CSoftkbdIMX()
{
extern void DllAddRef(void);
_fInitialized = FALSE;
_SoftKbd = NULL;
_CurKbdType = KBDTYPE_NONE;
_CurLayout = NON_LAYOUT;
_tim = NULL;
_dim = NULL;
_pCes = NULL;
DllAddRef();
}
//+---------------------------------------------------------------------------
//
// dtor
//
//----------------------------------------------------------------------------
CSoftkbdIMX::~CSoftkbdIMX()
{
extern void DllRelease(void);
if ( _SoftKbd != NULL )
{
_SoftKbd->DestroySoftKeyboardWindow( );
}
if ( _hOwnerWnd != NULL )
DestroyWindow(_hOwnerWnd);
_fInitialized = FALSE;
if ( _SoftKbd != NULL )
{
if ( _KbdSymbol.pskbdes != NULL )
{
_SoftKbd->UnadviseSoftKeyboardEventSink(_KbdSymbol.dwSkbdESCookie);
_SoftKbd->UnadviseSoftKeyboardEventSink(_dwsftkbdwndesCookie);
delete _psftkbdwndes;
delete _KbdSymbol.pskbdes;
}
}
if ( _pCes != NULL )
{
_fOnOffSave = FALSE;
_pCes->_Unadvise();
SafeReleaseClear(_pCes);
}
SafeRelease(_SoftKbd);
SafeRelease(_pFuncPrv);
DllRelease();
}
//
// Only when GUID_COMPARTMENT_HANDWRITING_OPENCLOSE is set TRUE at the first
// time, this Initiliaze( ) could be called by the compartment event sink.
//
HRESULT CSoftkbdIMX::Initialize( )
{
HRESULT hr;
WCHAR *lpSymXMLResStr = L"IDSKD_SYMLAYOUT";
WCHAR wszModuleFile[MAX_PATH];
CHAR szModuleFile[MAX_PATH];
DWORD dwFileLen;
WNDCLASSEX wndclass;
INT wScreenWidth, wScreenHeight;
INT left, top, width, height;
RECT rcWork;
hr = S_OK;
if ( _fInitialized == TRUE )
{
// Initialization is already done.
return hr;
}
if ( GetClassInfoEx( g_hInst, c_szIMXOwnerWndClass, &wndclass) == 0 )
{
memset(&wndclass, 0, sizeof(wndclass));
wndclass.cbSize = sizeof(wndclass);
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.hInstance = g_hInst;
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.lpfnWndProc = _OwnerWndProc;
wndclass.lpszClassName = c_szIMXOwnerWndClass;
RegisterClassEx(&wndclass);
}
_hOwnerWnd = CreateWindowEx(0, c_szIMXOwnerWndClass, TEXT(""), WS_DISABLED, 0, 0, 0, 0, NULL, 0, g_hInst, 0);
// PerfConsider: use a static ctor instead of ole32/class factory/etc.
hr=CoCreateInstance(CLSID_SoftKbd, NULL, CLSCTX_INPROC_SERVER, IID_ISoftKbd, (void**)&_SoftKbd);
if (FAILED(hr) )
{
// assert(0);
return hr;
}
_SoftKbd->Initialize( );
// initialize Standard soft layout and Symbol Soft Layout.
_KbdStandard.dwSoftKbdLayout = SOFTKBD_US_STANDARD;
_KbdStandard.fStandard = TRUE;
_KbdStandard.dwNumLabels = 0; // for standard, this field is not really used.
_KbdStandard.dwCurLabel = 0;
_KbdStandard.pskbdes = NULL; // standard layout doesn't supply sftkbd event sink.
_KbdStandard.dwSkbdESCookie = 0;
_KbdSymbol.fStandard = FALSE;
_KbdSymbol.dwNumLabels = 2;
_KbdSymbol.dwCurLabel = 0;
dwFileLen = GetModuleFileNameA(g_hInst, szModuleFile, MAX_PATH);
if ( dwFileLen == 0 )
{
hr = E_FAIL;
goto CleanUp;
}
MultiByteToWideChar(CP_ACP, 0, szModuleFile, -1,
wszModuleFile, MAX_PATH);
hr = _SoftKbd->CreateSoftKeyboardLayoutFromResource(wszModuleFile, L"SKDFILE", lpSymXMLResStr,
&(_KbdSymbol.dwSoftKbdLayout) );
CHECKHR(hr);
_KbdSymbol.pskbdes = new CSoftKeyboardEventSink(this, _KbdSymbol.dwSoftKbdLayout);
if ( _KbdSymbol.pskbdes == NULL )
{
hr = E_FAIL;
goto CleanUp;
}
hr = _SoftKbd->AdviseSoftKeyboardEventSink(_KbdSymbol.dwSoftKbdLayout,
IID_ISoftKeyboardEventSink,
_KbdSymbol.pskbdes,
&(_KbdSymbol.dwSkbdESCookie) );
CHECKHR(hr);
_psftkbdwndes = new CSoftKbdWindowEventSink(this);
if ( _psftkbdwndes == NULL )
{
hr=E_FAIL;
goto CleanUp;
}
CHECKHR(_SoftKbd->AdviseSoftKeyboardEventSink(0,IID_ISoftKbdWindowEventSink,_psftkbdwndes, &(_dwsftkbdwndesCookie)) );
_CurLayout = _KbdStandard.dwSoftKbdLayout;
width = 400;
height = 172;
if ( S_OK != GetSoftKBDPosition( &left, &top ) )
{
// the compartment is not initialize.
SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWork, 0 );
wScreenWidth = (INT)(rcWork.right - rcWork.left + 1);
wScreenHeight = (INT)(rcWork.bottom - rcWork.top + 1);
left = wScreenWidth - width -2;
top = wScreenHeight - height - 1;
}
CHECKHR(_SoftKbd->CreateSoftKeyboardWindow(_hOwnerWnd,TITLEBAR_GRIPPER_BUTTON, left,top,width,height));
SetSoftKBDPosition(left, top );
if ( hr == S_OK )
{
LOGFONTW lfTextFont;
int iDpi;
int iPoint;
iDpi = 96;
iPoint = 9;
HDC hdc;
hdc = CreateIC("DISPLAY", NULL, NULL, NULL);
if (hdc)
{
iDpi = GetDeviceCaps(hdc, LOGPIXELSY);
DeleteDC(hdc);
memset(&lfTextFont, 0, sizeof(LOGFONTW) );
lfTextFont.lfHeight = -iPoint * iDpi / 72;
lfTextFont.lfWeight = 400;
lfTextFont.lfOutPrecision = OUT_TT_ONLY_PRECIS;
wcsncpy(lfTextFont.lfFaceName, L"Arial", ARRAYSIZE(lfTextFont.lfFaceName));
lfTextFont.lfCharSet = 0;
hr = _SoftKbd->SetSoftKeyboardTextFont(&lfTextFont);
}
}
_fInitialized = TRUE;
// or get the current layout from previous saved one.
CleanUp:
return hr;
}
//+---------------------------------------------------------------------------
//
// OnSetThreadFocus
//
//----------------------------------------------------------------------------
STDAPI CSoftkbdIMX::OnSetThreadFocus()
{
// Restore the ON/OFF status before KillThreadFocus( )
if ( _SoftKbd != NULL )
{
if ( _fOnOffSave )
{
// adjust the window position.
int xWnd, yWnd;
WORD width=0, height=0;
POINT OldPoint;
HRESULT hr;
_SoftKbd->GetSoftKeyboardPosSize(&OldPoint, &width, &height);
hr = GetSoftKBDPosition(&xWnd, &yWnd);
if ( hr == S_OK )
{
if ( (xWnd != OldPoint.x) || (yWnd != OldPoint.y) )
{
POINT NewPoint;
NewPoint.x = xWnd;
NewPoint.y = yWnd;
_SoftKbd->SetSoftKeyboardPosSize(NewPoint, width, height);
}
}
_ShowSoftKBDWindow(TRUE);
}
else
_SoftKbd->ShowSoftKeyboard(FALSE);
}
return S_OK;
}
//+---------------------------------------------------------------------------
//
// OnKillThreadFocus
//
//----------------------------------------------------------------------------
STDAPI CSoftkbdIMX::OnKillThreadFocus()
{
// keep the ON/OFF status so that OnSetThreadFocus( ) can restore it later
_fOnOffSave = GetSoftKBDOnOff( );
if ( _SoftKbd != NULL )
{
_SoftKbd->ShowSoftKeyboard( FALSE );
}
// release all the modifier keys except lock keys. that is , Shift, Alt, Ctrl,
keybd_event((BYTE)VK_SHIFT, (BYTE)KID_LSHFT, (DWORD)KEYEVENTF_KEYUP, 0);
keybd_event((BYTE)VK_MENU, (BYTE)KID_ALT, (DWORD)KEYEVENTF_KEYUP, 0);
keybd_event((BYTE)VK_LMENU, (BYTE)KID_ALT, (DWORD)KEYEVENTF_KEYUP, 0);
keybd_event((BYTE)VK_RMENU, (BYTE)KID_RALT, (DWORD)KEYEVENTF_KEYUP, 0);
keybd_event((BYTE)VK_CONTROL, (BYTE)KID_CTRL, (DWORD)KEYEVENTF_KEYUP, 0);
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Activate
//
//----------------------------------------------------------------------------
STDAPI CSoftkbdIMX::Activate(ITfThreadMgr *ptim, TfClientId tid)
{
ITfSource *source;
ITfLangBarItemMgr *plbim = NULL;
HRESULT hr;
Assert(_tim == NULL);
_tim = ptim;
_tim->AddRef();
_tid = tid;
_pProfile = NULL;
if (_tim->QueryInterface(IID_ITfSource, (void **)&source) == S_OK)
{
source->AdviseSink(IID_ITfThreadFocusSink, (ITfThreadFocusSink *)this, &_dwThreadFocusCookie);
source->Release();
}
//
// Add SoftKeyboard activate button into LangBarItemMgr.
//
if (FAILED(hr = GetService(_tim, IID_ITfLangBarItemMgr, (IUnknown **)&plbim)))
{
hr = E_FAIL;
goto CleanUp;
}
if (!(_plbi = new CLBarItem(this)))
{
hr = E_OUTOFMEMORY;
goto CleanUp;
}
plbim->AddItem(_plbi);
//
// get language ID.
//
_InitLangID();
if ( (_timActiveLangSink = new CActiveLanguageProfileNotifySink(_AlsCallback, this)) == NULL )
{
Assert(0);
hr = E_FAIL;
goto CleanUp;
}
_timActiveLangSink->_Advise(_tim);
if ( (_timLangSink = new CLanguageProfileNotifySink(_LsCallback, this)) == NULL )
{
Assert(0);
hr = E_FAIL;
goto CleanUp;
}
_timLangSink->_Advise(_pProfile);
_pFuncPrv = new CFunctionProvider(this);
if ( _pFuncPrv != NULL)
_pFuncPrv->_Advise(_tim);
// defaultly, hide the soft keyboard window.
_fOnOffSave = FALSE;
if (!(_pCes = new CCompartmentEventSink(_CompEventSinkCallback, this)))
{
hr = E_OUTOFMEMORY;
CHECKHR(hr);
}
CHECKHR(_pCes->_Advise(_tim, GUID_COMPARTMENT_HANDWRITING_OPENCLOSE, FALSE));
CHECKHR(_pCes->_Advise(_tim, GUID_COMPARTMENT_SOFTKBD_KBDLAYOUT, FALSE));
#if 0
if (_tim->IsThreadFocus(&fThreadFocus) == S_OK && fThreadFocus)
{
// init any UI
OnSetThreadFocus();
}
#endif
hr = S_OK;
CleanUp:
SafeRelease(plbim);
return hr;
}
//+---------------------------------------------------------------------------
//
// Deactivate
//
//----------------------------------------------------------------------------
STDAPI CSoftkbdIMX::Deactivate()
{
ITfSource *source;
ITfLangBarItemMgr *plbim = NULL;
// BOOL fThreadFocus;
HRESULT hr;
if (_tim->QueryInterface(IID_ITfSource, (void **)&source) == S_OK)
{
source->UnadviseSink(_dwThreadFocusCookie);
source->Release();
}
//
// Clean up SoftKeyboard activate button into LangBarItemMgr.
//
if (SUCCEEDED(hr = GetService(_tim, IID_ITfLangBarItemMgr, (IUnknown **)&plbim)))
{
plbim->RemoveItem(_plbi);
SafeReleaseClear(_plbi);
SafeReleaseClear(plbim);
}
if ( _timActiveLangSink != NULL )
{
_timActiveLangSink->_Unadvise( );
SafeReleaseClear(_timActiveLangSink);
}
if ( _timLangSink != NULL )
{
_timLangSink->_Unadvise( );
SafeReleaseClear(_timLangSink);
}
if ( _pFuncPrv != NULL )
{
_pFuncPrv->_Unadvise(_tim);
SafeReleaseClear(_pFuncPrv);
}
if ( _pCes != NULL )
{
if ( _SoftKbd != NULL )
_SoftKbd->ShowSoftKeyboard(FALSE);
_fOnOffSave = FALSE;
_pCes->_Unadvise();
SafeReleaseClear(_pCes);
}
SafeReleaseClear(_pProfile);
SafeReleaseClear(_tim);
TFUninitLib_Thread(&_libTLS);
hr = S_OK;
return hr;
}
//+---------------------------------------------------------------------------
//
// GetIC
//
//----------------------------------------------------------------------------
ITfContext *CSoftkbdIMX::GetIC()
{
ITfContext *pic = NULL;
if (!_tim)
{
Assert(0);
return NULL;
}
ITfDocumentMgr *pdim;
if (SUCCEEDED(_tim->GetFocus(&pdim)) && pdim)
{
// otherwise grab the top of the stack
pdim->GetTop(&pic);
pdim->Release();
}
return pic;
}
//+---------------------------------------------------------------------------
//
// _OnOffToggle
//
//----------------------------------------------------------------------------
void CSoftkbdIMX::_OnOffToggle( )
{
BOOL fOn = GetSoftKBDOnOff( );
SetSoftKBDOnOff(!fOn);
_UpdateUI();
}
//+---------------------------------------------------------------------------
//
// _EditSessionCallback
//
//----------------------------------------------------------------------------
HRESULT CSoftkbdIMX::_InputKeyLabel(TfEditCookie ec, ITfContext *pic, WCHAR *lpszLabel, UINT nLabLen)
{
HRESULT hr = S_OK;
ITfRange *pRange, *pSelection;
if ( pic )
{
TF_STATUS ts;
hr = pic->GetStatus(&ts);
if ( (S_OK == hr) && (TF_SD_READONLY & ts.dwDynamicFlags) )
{
// Readonly Doc, just return here!
return hr;
}
if (GetSelectionSimple(ec, pic, &pSelection) == S_OK)
{
if (SUCCEEDED(pSelection->Clone(&pRange)))
{
BOOL fInsertOk = FALSE;
hr = pRange->AdjustForInsert(ec, nLabLen, &fInsertOk);
if (S_OK == hr && fInsertOk)
{
SetTextAndProperty(&_libTLS, ec, pic, pRange, lpszLabel, nLabLen, _langid, NULL);
_MySetSelectionSimple(ec, pic, pRange);
}
pRange->Release();
}
pSelection->Release();
}
}
return hr;
}
HRESULT CSoftkbdIMX::_EditSessionCallback(TfEditCookie ec, CEditSession *pes)
{
CSoftkbdIMX *_this;
HRESULT hr;
hr = S_OK;
switch (pes->_state.u)
{
case ESCB_KEYLABEL :
{
WCHAR *lpszLabel;
UINT nLabLen;
lpszLabel = (WCHAR *)(pes->_state.lParam);
if ( lpszLabel == NULL )
{
hr = E_FAIL;
return hr;
}
nLabLen = wcslen(lpszLabel);
_this = (CSoftkbdIMX *)pes->_state.pv;
hr = _this->_InputKeyLabel(ec,
pes->_state.pic,
lpszLabel,
nLabLen);
SafeFreePointer(lpszLabel);
break;
}
default :
break;
}
return hr;
}
//
// Show or Hide the soft keyboard window based on current setting.
//
HRESULT CSoftkbdIMX::_ShowSoftKBDWindow( BOOL fShow )
{
HRESULT hr;
hr = S_OK;
if ( fShow && ( _fInitialized == FALSE ) )
// call the initialize function
// to get the ISoftKbd.
{
Initialize( );
}
if ( _SoftKbd == NULL )
{
hr = E_FAIL;
return hr;
}
if ( fShow ) {
DWORD dwSoftLayout;
if ( _CurKbdType == KBDTYPE_STANDARD )
{
// Standard soft kbd was selected.
WORD prmlangid;
prmlangid = PRIMARYLANGID(_langid);
switch ( prmlangid ) {
case LANG_JAPANESE :
// Lang JPN is activated.
// select the standard layout to J 106-k.
_KbdStandard.dwSoftKbdLayout = SOFTKBD_JPN_STANDARD;
break;
case LANG_AZERI :
case LANG_BELARUSIAN :
case LANG_CHINESE :
case LANG_KOREAN :
case LANG_RUSSIAN :
case LANG_THAI :
case LANG_URDU :
case LANG_UZBEK :
_KbdStandard.dwSoftKbdLayout = SOFTKBD_US_STANDARD;
break;
case LANG_ENGLISH :
if ( SUBLANGID(_langid) != SUBLANG_ENGLISH_US )
_KbdStandard.dwSoftKbdLayout = SOFTKBD_EURO_STANDARD;
else
_KbdStandard.dwSoftKbdLayout = SOFTKBD_US_STANDARD;
break;
default :
_KbdStandard.dwSoftKbdLayout = SOFTKBD_EURO_STANDARD;
break;
}
// the current layout is standard layout.
// we need to set the correct standard layout id based on current lang profile.
dwSoftLayout = _KbdStandard.dwSoftKbdLayout;
_CurLayout = dwSoftLayout;
CHECKHR(_SoftKbd->SelectSoftKeyboard(dwSoftLayout));
CHECKHR(_SoftKbd->SetKeyboardLabelText(GetKeyboardLayout(0)));
}
else if ( _CurKbdType == KBDTYPE_SYMBOL)
{
// This is symbol soft keyboard layout
//
DWORD dwCurLabel;
dwSoftLayout = _KbdSymbol.dwSoftKbdLayout;
dwCurLabel = _KbdSymbol.dwCurLabel;
CHECKHR(_SoftKbd->SelectSoftKeyboard(dwSoftLayout));
CHECKHR(_SoftKbd->SetKeyboardLabelTextCombination(dwCurLabel));
}
// TIP is ON, so we need to show soft keyboard.
CHECKHR(_SoftKbd->ShowSoftKeyboard(TRUE));
}
else
{
// TIP is going to close.
// close the soft keyboard window also.
CHECKHR(_SoftKbd->ShowSoftKeyboard(FALSE));
}
CleanUp:
return hr;
}
//+---------------------------------------------------------------------------
//
// _CompEventSinkCallback
//
//----------------------------------------------------------------------------
HRESULT CSoftkbdIMX::_CompEventSinkCallback(void *pv, REFGUID rguid)
{
CSoftkbdIMX *_this = (CSoftkbdIMX *)pv;
BOOL fOn;
HRESULT hr;
hr = S_OK;
if ( IsEqualGUID(rguid, GUID_COMPARTMENT_HANDWRITING_OPENCLOSE) )
{
fOn = _this->GetSoftKBDOnOff( );
CHECKHR(_this->_ShowSoftKBDWindow(fOn));
//
// Open/Close status was updated, we need to update Langbar button's
// toggle state.
//
_this->_plbi->UpdateToggle();
}
else if ( IsEqualGUID(rguid, GUID_COMPARTMENT_SOFTKBD_KBDLAYOUT) )
{
DWORD dwSoftLayout;
if ( _this->_SoftKbd == NULL )
{
hr = E_FAIL;
return hr;
}
dwSoftLayout = _this->GetSoftKBDLayout( );
_this->_CurLayout = dwSoftLayout;
if ( dwSoftLayout == (_this->_KbdStandard).dwSoftKbdLayout )
{
// this is standard layout.
_this->_CurKbdType = KBDTYPE_STANDARD;
CHECKHR(_this->_SoftKbd->SelectSoftKeyboard(dwSoftLayout));
CHECKHR(_this->_SoftKbd->SetKeyboardLabelText(GetKeyboardLayout(0)));
}
else if ( dwSoftLayout == (_this->_KbdSymbol).dwSoftKbdLayout )
{
// this is symbol layout.
DWORD dwCurLabel;
_this->_CurKbdType = KBDTYPE_SYMBOL;
dwCurLabel = (_this->_KbdSymbol).dwCurLabel;
CHECKHR(_this->_SoftKbd->SelectSoftKeyboard(dwSoftLayout));
CHECKHR(_this->_SoftKbd->SetKeyboardLabelTextCombination(dwCurLabel));
}
if ( _this->GetSoftKBDOnOff( ) )
CHECKHR(_this->_SoftKbd->ShowSoftKeyboard(TRUE));
}
_this->_UpdateUI();
CleanUp:
return hr;
}
//+---------------------------------------------------------------------------
//
// _UpdateUI
//
//----------------------------------------------------------------------------
void CSoftkbdIMX::_UpdateUI()
{
}
//+---------------------------------------------------------------------------
//
// _MySetSelectionSimple
//
//----------------------------------------------------------------------------
HRESULT CSoftkbdIMX::_MySetSelectionSimple(TfEditCookie ec, ITfContext *pic, ITfRange *range)
{
TF_SELECTION sel;
sel.range = range;
sel.style.ase = TF_AE_NONE;
sel.style.fInterimChar = FALSE;
range->Collapse(ec, TF_ANCHOR_END);
return pic->SetSelection(ec, 1, &sel);
}
HRESULT CSoftkbdIMX::_LsCallback(BOOL fChanged, LANGID langid, BOOL *pfAccept, void *pv)
{
HRESULT hr = S_OK;
GUID guidProfile;
LANGID lang;
TraceMsg(TF_GENERAL, "CSoftkbdIMX::_LsCallback is called, langid=%x fChanged=%d", langid, fChanged);
CSoftkbdIMX *_this = (CSoftkbdIMX *)pv;
if (!fChanged)
{
if ( pfAccept )
*pfAccept = TRUE;
return hr;
}
hr = _this->_pProfile->GetActiveLanguageProfile(CLSID_SoftkbdIMX, &lang, &guidProfile);
if ( hr == S_OK )
{
_this->_langid = lang;
if ( IsEqualGUID(guidProfile, c_guidProfile) )
{
// Standard soft kbd is selected.
TraceMsg(TF_GENERAL, "Standard Softkbd is selected");
_this->_CurKbdType = KBDTYPE_STANDARD;
}
else if ( IsEqualGUID(guidProfile, c_guidProfileSym) )
{
// This is symbol soft keyboard layout
//
TraceMsg(TF_GENERAL, "Symbol Softkbd is selected");
_this->_CurKbdType = KBDTYPE_SYMBOL;
}
if ( (_this->GetSoftKBDOnOff( ) == TRUE) )
_this->_ShowSoftKBDWindow(TRUE);
}
return hr;
}
HRESULT CSoftkbdIMX::_AlsCallback(REFCLSID clsid, REFGUID guidProfile, BOOL fActivated, void *pv)
{
HRESULT hr;
ITfInputProcessorProfiles *pProfile = NULL;
hr = S_OK;
CSoftkbdIMX *_this = (CSoftkbdIMX *)pv;
// if this is not for SoftKbdIMX TIP,
// we just ignore it.
if (IsEqualGUID(clsid, CLSID_SoftkbdIMX))
{
// if this is not for our registered profile guid, just ignore it.
if ( !IsEqualGUID(guidProfile, c_guidProfile) && !IsEqualGUID(guidProfile, c_guidProfileSym) )
return hr;
TraceMsg(TF_GENERAL, "CSoftkbdIMX::_AlsCallback is called for this tip fActivated=%d", fActivated);
if ( fActivated == FALSE )
{
if ( _this->GetSoftKBDOnOff( ) )
{
if ( _this->_SoftKbd != NULL )
(_this->_SoftKbd)->ShowSoftKeyboard(FALSE);
}
return hr;
}
if ( IsEqualGUID(guidProfile, c_guidProfile) )
{
// Standard soft kbd is selected.
TraceMsg(TF_GENERAL, "Standard Softkbd is selected");
_this->_CurKbdType = KBDTYPE_STANDARD;
}
else if ( IsEqualGUID(guidProfile, c_guidProfileSym) )
{
// This is symbol soft keyboard layout
//
TraceMsg(TF_GENERAL, "Symbol Softkbd is selected");
_this->_CurKbdType = KBDTYPE_SYMBOL;
}
if ( (_this->GetSoftKBDOnOff( ) == TRUE) )
_this->_ShowSoftKBDWindow(TRUE);
}
else if (IsEqualGUID(clsid, GUID_NULL))
{
// This is keyboard layout change without language change.
if ( _this->GetSoftKBDOnOff( ) && fActivated)
{
_this->_ShowSoftKBDWindow(fActivated);
}
}
return hr;
}