|
|
//+---------------------------------------------------------------------------
//
// File: dimm.cpp
//
// Contents: CActiveIMM methods without win32 mappings.
//
//----------------------------------------------------------------------------
#include "private.h"
#include "cdimm.h"
#include "globals.h"
#include "util.h"
//+---------------------------------------------------------------------------
//
// ctor
//
//----------------------------------------------------------------------------
CActiveIMM::CActiveIMM() { _cRef = 1; }
//+---------------------------------------------------------------------------
//
// _Init
//
//----------------------------------------------------------------------------
HRESULT CActiveIMM::_Init() { extern HRESULT CIME_CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObj);
HRESULT hr;
if (FAILED(hr=CIME_CreateInstance(NULL, IID_IActiveIME_Private, (void **)&_pActiveIME))) { _pActiveIME = NULL; return hr; }
_pActiveIME->ConnectIMM(this);
_InputContext._Init(_pActiveIME);
_ConnectTIM(_pActiveIME);
return hr; }
//+---------------------------------------------------------------------------
//
// dtor
//
//----------------------------------------------------------------------------
CActiveIMM::~CActiveIMM() { //
// unload the hooks
//
_UninitHooks();
POSITION pos = _mapWndFocus.GetStartPosition(); int index; for (index = 0; index < _mapWndFocus.GetCount(); index++) { HWND hWnd; ITfDocumentMgr* pdim; _mapWndFocus.GetNextAssoc(pos, hWnd, pdim); if (pdim) { pdim->Release(); } }
if (GetTimP()) { _UnconnectTIM(); }
if (_pActiveIME != NULL) { _pActiveIME->UnconnectIMM(); SafeReleaseClear(_pActiveIME); }
IMTLS_SetActiveIMM(NULL); }
//+---------------------------------------------------------------------------
//
// IsRealIme
//
//----------------------------------------------------------------------------
inline BOOL _IsIMEHKL(HKL hkl) { return ((((DWORD)(UINT_PTR)hkl) & 0xf0000000) == 0xe0000000) ? TRUE : FALSE; }
BOOL CActiveIMM::_IsRealIme(HKL hkl) { if (! hkl) { HRESULT hr = _GetKeyboardLayout(&hkl); if (FAILED(hr)) return FALSE; }
if (!_IsIMEHKL(hkl)) return FALSE;
BOOL fRet; if (_RealImeList.Lookup(hkl, fRet)) return fRet;
char szDesc[MAX_PATH +1]; char szDumbDesc[MAX_PATH +1];
UINT uCopied; if (FAILED(Imm32_GetDescription(hkl, ARRAYSIZE(szDesc), (CHARAW*)szDesc, &uCopied, FALSE))) return FALSE;
szDesc[ARRAYSIZE(szDesc) -1] = '\0';
wsprintf(szDumbDesc, "hkl%04x", LOWORD((UINT_PTR)hkl)); fRet = lstrcmp(szDumbDesc, szDesc) ? TRUE : FALSE;
_RealImeList.SetAt(hkl, fRet); return fRet; }
HRESULT CActiveIMM::IsRealImePublic(BOOL *pfReal) { if (pfReal) { *pfReal = _IsRealIme(0); } return S_OK; }
//+---------------------------------------------------------------------------
//
// QueryService
//
//----------------------------------------------------------------------------
HRESULT CActiveIMM::QueryService(REFGUID guidService, REFIID riid, void **ppv) { HRESULT hr; IServiceProvider* pISP;
Assert(ppv != NULL && *ppv == NULL);
hr = E_FAIL;
if (_pActiveIME->QueryInterface(IID_IServiceProvider, (void**)&pISP) == S_OK) { hr = pISP->QueryService(guidService, riid, ppv); pISP->Release(); }
return hr; }
//+---------------------------------------------------------------------------
//
// _GetKeyboardLayout
//
//----------------------------------------------------------------------------
HRESULT CActiveIMM::_GetKeyboardLayout(HKL* phkl) { extern HRESULT CAImmProfile_CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObj); HRESULT hr;
if (_IsAlreadyActivate()) { //
// Already called IActiveIMMApp::Activate
//
if (_AImeProfile == NULL) {
hr = CAImmProfile_CreateInstance(NULL, IID_IAImeProfile, (void**)&_AImeProfile);
if (FAILED(hr)) { TraceMsg(TF_ERROR, "CreateInstance(CAImeProfile) failed"); return hr; } } return _AImeProfile->GetKeyboardLayout(phkl); } else { //
// Not yet called IActiveIMMApp::Activate
// or
// called IActiveIMMApp::Deactivate
//
if (_AImeProfile == NULL) { hr = CAImmProfile_CreateInstance(NULL, IID_IAImeProfile, (void**)&_AImeProfile);
if (FAILED(hr)) { TraceMsg(TF_ERROR, "CreateInstance(CAImeProfile) failed"); return hr; } hr = _AImeProfile->GetKeyboardLayout(phkl); //
// Prevent memory leak when not ready Activate.
//
_AImeProfile->Release(); _AImeProfile = NULL; //
return hr; } else { return _AImeProfile->GetKeyboardLayout(phkl); } } }
//+---------------------------------------------------------------------------
//
// _ImeSelectHandler
//
//----------------------------------------------------------------------------
LRESULT CActiveIMM::_ImeSelectHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL fUnicode, HIMC hIMC)
/*
* If return TRUE: no call previous window procedure of IME window class. * In case of CCiceroIME::ActivateLayout/DeactivateLayout, return value might be * TRUE. * Otherwise, WM_IME_SELECT become from another module. In this case, should be * call previous window proc. */
{ //
// on FE-Win98, IMS_ACTIVATETHREADLAYOUT needs to be generate at ImeSelect.
// otherwise we may update InputContext before IME get ImeSelect(FALSE);
//
if (wParam && !IsOnNT() && IsOnImm()) _DefaultIMEWindow.SendIMEMessage(WM_IME_SYSTEM, (WPARAM)IMS_ACTIVATETHREADLAYOUT, lParam, IsWindowUnicode(_hFocusWnd), FALSE);
if (!_IsRealIme((HKL)lParam)) { /*
* We must re-create UI window of newly selected IME. */ if ((BOOL)wParam == TRUE) { //
// Create IME UI window.
//
if (_UIWindow.CreateUIWindow((HKL)lParam)) { //
// Set context and send notification to UI window.
//
_UIWindow.SetUIWindowContext(hIMC); _UIWindow.SendUIMessage(uMsg, wParam, lParam, fUnicode); } } else { _UIWindow.SendUIMessage(uMsg, wParam, lParam, fUnicode); _UIWindow.DestroyUIWindow(); } return TRUE; } else if (_DefaultIMEWindow.IsAIMEHandler()) return TRUE; else return FALSE; }
//+---------------------------------------------------------------------------
//
// _ImeWndFinalDestroyHandler
//
//----------------------------------------------------------------------------
void CActiveIMM::_ImeWndFinalDestroyHandler() { if (!_IsRealIme()) { //
// Destroy IME UI window.
//
_UIWindow.DestroyUIWindow(); } }
//+---------------------------------------------------------------------------
//
// _ActivateLayout
//
//----------------------------------------------------------------------------
void CActiveIMM::_ActivateLayout(HKL hSelKL, HKL hUnSelKL) { BOOL fUnicode = IsWindowUnicode(_hFocusWnd); BOOL bIsRealIme = _IsRealIme(hSelKL);
/*
* Select input context(s). */ SCE sce; sce.hSelKL = hSelKL; sce.hUnSelKL = hUnSelKL;
_InputContext.EnumInputContext(0, _SelectContextProc, (LPARAM)&sce);
if (! bIsRealIme || ! IsOnImm()) { if (hSelKL == NULL) { HRESULT hr = _GetKeyboardLayout(&hSelKL); }
_DefaultIMEWindow.SendIMEMessage(WM_IME_SELECT, TRUE, (LPARAM)(hSelKL), fUnicode); } }
//+---------------------------------------------------------------------------
//
// _DeactivateLayout
//
//----------------------------------------------------------------------------
void CActiveIMM::_DeactivateLayout(HKL hSelKL, HKL hUnSelKL) { BOOL fUnicode = IsWindowUnicode(_hFocusWnd); BOOL bIsRealIme = _IsRealIme(hUnSelKL);
if ((! bIsRealIme || ! IsOnImm()) && (hUnSelKL != hSelKL || (hUnSelKL == NULL && hSelKL == NULL))) {
#ifdef UNSELECTCHECK
//
// If hSelKL is real IME, All hIMC is already initialized by the IME
// we can not touch them from now on. We should stop doing in next
// NotifyIME calls.
//
if (_IsRealIme(hSelKL) && !IsOnNT()) { _InputContext.EnumInputContext(0, _UnSelectCheckProc, 0); } #endif UNSELECTCHECK
DWORD dwCPS = _GetIMEProperty(PROP_IME_PROPERTY) & IME_PROP_COMPLETE_ON_UNSELECT ? CPS_COMPLETE : CPS_CANCEL;
_InputContext.EnumInputContext(0, _NotifyIMEProc, dwCPS);
if (hUnSelKL == NULL) { HRESULT hr = _GetKeyboardLayout(&hUnSelKL); }
_DefaultIMEWindow.SendIMEMessage(WM_IME_SELECT, FALSE, (LPARAM)(hUnSelKL), fUnicode); }
/*
* Unselect input context(s). */ SCE sce; sce.hSelKL = hSelKL; sce.hUnSelKL = hUnSelKL; _InputContext.EnumInputContext(0, _UnSelectContextProc, (LPARAM)&sce); }
//+---------------------------------------------------------------------------
//
// _InitHooks
//
//----------------------------------------------------------------------------
BOOL CActiveIMM::_InitHooks() { GetTimP()->SetSysHookSink(this);
DWORD dwThreadId = GetCurrentThreadId();
#if 0
if (!_hHook[TH_GETMSG]) { _hHook[TH_GETMSG] = SetWindowsHookEx(WH_GETMESSAGE, _GetMsgProc, NULL, dwThreadId); } #endif
#ifdef CALLWNDPROC_HOOK
if (!_hHook[TH_WNDPROC]) { _hHook[TH_WNDPROC] = SetWindowsHookEx(WH_CALLWNDPROC, _CallWndProc, NULL, dwThreadId); } #endif // CALLWNDPROC_HOOK
#ifdef CALLWNDPROC_HOOK
if (!_hHook[TH_DEFIMEWNDPROC] && _DefaultIMEWindow.IsNeedRecovIMEWndProc()) #else
if (!_hHook[TH_DEFIMEWNDPROC]) #endif // CALLWNDPROC_HOOK
{ _hHook[TH_DEFIMEWNDPROC] = SetWindowsHookEx(WH_CALLWNDPROCRET, _DefImeWnd_CallWndProc, NULL, dwThreadId); }
#if 0
if (g_uACP != 932 && g_uACP != 949 && g_uACP != 950 && g_uACP != 936 && ! hShellHook) { hShellHook = SetWindowsHookEx(WH_SHELL, _ShellProc, NULL, dwThreadId); } #endif
return TRUE; }
//+---------------------------------------------------------------------------
//
// _UninitHooks
//
//----------------------------------------------------------------------------
void CActiveIMM::_UninitHooks() { #if 0
if (_hHook[TH_GETMSG]) { UnhookWindowsHookEx(_hHook[TH_GETMSG]); _hHook[TH_GETMSG] = NULL; } #endif
#ifdef CALLWNDPROC_HOOK
if (_hHook[TH_WNDPROC]) { UnhookWindowsHookEx(_hHook[TH_WNDPROC]); _hHook[TH_WNDPROC] = NULL; } #endif // CALLWNDPROC_HOOK
if (_hHook[TH_DEFIMEWNDPROC]) { UnhookWindowsHookEx(_hHook[TH_DEFIMEWNDPROC]); _hHook[TH_DEFIMEWNDPROC] = NULL; }
#if 0
if (g_uACP != 932 && g_uACP != 949 && g_uACP != 950 && g_uACP != 936 && hShellHook != NULL) { UnhookWindowsHookEx(hShellHook); hShellHook = NULL; } #endif
if (GetTimP()) { GetTimP()->SetSysHookSink(NULL); } }
//+---------------------------------------------------------------------------
//
// _OnImeSelect
//
//----------------------------------------------------------------------------
void CActiveIMM::_OnImeSelect(HKL hSelKL) { if (!_IsRealIme(hSelKL)) { // Don't check IMM32
_DefaultIMEWindow.SendIMEMessage(WM_IME_SELECT, TRUE, (LPARAM)(hSelKL), IsWindowUnicode(_hFocusWnd), FALSE); } }
//+---------------------------------------------------------------------------
//
// _OnImeUnselect
//
//----------------------------------------------------------------------------
void CActiveIMM::_OnImeUnselect(HKL hUnSelKL) { if (!_IsRealIme(hUnSelKL)) { // Don't check IMM32
_DefaultIMEWindow.SendIMEMessage(WM_IME_SELECT, FALSE, (LPARAM)(hUnSelKL), IsWindowUnicode(_hFocusWnd), FALSE); } }
//+---------------------------------------------------------------------------
//
// _OnImeActivateThreadLayout
//
//----------------------------------------------------------------------------
void CActiveIMM::_OnImeActivateThreadLayout(HKL hSelKL) { //
// on FE-Win98, IMS_ACTIVATETHREADLAYOUT needs to be generate at ImeSelect.
// otherwise we may update InputContext before IME get ImeSelect(FALSE);
//
if (!IsOnNT() && IsOnImm()) return;
// Don't check IMM32
_DefaultIMEWindow.SendIMEMessage(WM_IME_SYSTEM, (WPARAM)IMS_ACTIVATETHREADLAYOUT, (LPARAM)(hSelKL), IsWindowUnicode(_hFocusWnd), FALSE); }
//+---------------------------------------------------------------------------
//
// _AImeAssociateFocus
//
//----------------------------------------------------------------------------
HRESULT CActiveIMM::_AImeAssociateFocus(HWND hWnd, HIMC hIMC, DWORD dwFlags) { if (hIMC) { DIMM_IMCLock lpIMC(hIMC); if (lpIMC.Invalid()) return E_FAIL;
lpIMC->hWnd = hWnd; }
return _pActiveIME->AssociateFocus(hWnd, hIMC, dwFlags); }
//+---------------------------------------------------------------------------
//
// _ResizePrivateIMCC
//
//----------------------------------------------------------------------------
HRESULT CActiveIMM::_ResizePrivateIMCC(IN HIMC hIMC, IN DWORD dwPrivateSize) { /*
* Resize private IMCC method. * * If IsRealIme() was true, should not resize private IMCC to ActiveIME's size. * */ if (!_IsRealIme()) return _InputContext.ResizePrivateIMCC(hIMC, dwPrivateSize); else return S_OK; }
//+---------------------------------------------------------------------------
//
// _GetIMEWndClassName
//
//----------------------------------------------------------------------------
DWORD CActiveIMM::_GetIMEWndClassName(HKL hKL, LPWSTR lpsz, DWORD dwBufLen, UINT_PTR *pulPrivate) { return (!_IsRealIme(hKL)) ? _GetIMEWndClassName(lpsz, dwBufLen, pulPrivate) : 0L; }
DWORD CActiveIMM::_GetIMEWndClassName(LPWSTR lpsz, DWORD dwBufLen, UINT_PTR *pulPrivate) { DWORD len = wcslen(_IMEInfoEx.achWndClass);
if (lpsz == NULL || dwBufLen < len) { return len; } else { wcscpy(lpsz, _IMEInfoEx.achWndClass); *pulPrivate = _IMEInfoEx.dwPrivate; } return len; }
//+---------------------------------------------------------------------------
//
// _CallWindowProc
//
//----------------------------------------------------------------------------
LRESULT CActiveIMM::_CallWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { return _DefaultIMEWindow.CallWindowProc(hWnd, uMsg, wParam, lParam); }
//+---------------------------------------------------------------------------
//
// _SendUIMessage
//
//----------------------------------------------------------------------------
LRESULT CActiveIMM::_SendUIMessage(UINT Msg, WPARAM wParam, LPARAM lParam, BOOL fUnicode) { return (!_IsRealIme()) ? _UIWindow.SendUIMessage(Msg, wParam, lParam, fUnicode) : 0L; }
//+---------------------------------------------------------------------------
//
// _SetHookWndList
//
//----------------------------------------------------------------------------
BOOL CActiveIMM::_SetHookWndList(HWND hwnd) { TCHAR achMyClassName[MAX_PATH + 1]; int lenMyClassName = ::GetClassName(hwnd, achMyClassName, ARRAYSIZE(achMyClassName) - 1); achMyClassName[ARRAYSIZE(achMyClassName) -1] = TEXT('\0'); if (lenMyClassName) { CString cls(achMyClassName); if (cls.CompareNoCase(TEXT("IME")) == 0) { _HookWndList.SetAt(hwnd, TRUE); return TRUE; } }
DWORD dwStyle = GetClassLong(hwnd, GCL_STYLE); if (dwStyle & CS_IME) { _HookWndList.SetAt(hwnd, TRUE); return TRUE; }
_HookWndList.SetAt(hwnd, FALSE);
return FALSE; }
//+---------------------------------------------------------------------------
//
// OnPreFocusDIM
//
//----------------------------------------------------------------------------
HRESULT CActiveIMM::OnPreFocusDIM(HWND hWnd) { HIMC hIMC; if (SUCCEEDED(_InputContext.GetContext(hWnd, &hIMC))) { if (IsPresent(hWnd, TRUE)) { if (_InputContext._IsDefaultContext(hIMC)) { DIMM_IMCLock pIMC(hIMC); if (pIMC.Valid()) { // set the hWnd since this is a default context
pIMC->hWnd = hWnd; } } _AImeAssociateFocus(hWnd, hIMC, AIMMP_AFF_SETFOCUS); _SetMapWndFocus(hWnd); } else if (hIMC) { _AImeAssociateFocus(hWnd, hIMC, AIMMP_AFF_SETFOCUS | AIMMP_AFF_SETNULLDIM); } else { _AImeAssociateFocus(hWnd, NULL, AIMMP_AFF_SETFOCUS); } } else { _AImeAssociateFocus(hWnd, NULL, AIMMP_AFF_SETFOCUS); } return S_OK; }
//+---------------------------------------------------------------------------
//
// OnSysKeybaordProc
//
//----------------------------------------------------------------------------
STDAPI CActiveIMM::OnSysKeyboardProc(WPARAM wParam, LPARAM lParam) { HRESULT hr = S_FALSE; CActiveIMM *_this = GetTLS(); if (_this == NULL) return hr;
BOOL bIsRealIme = _IsRealIme();
BOOL fNoOnTrans;
if ((wParam != VK_PROCESSKEY) && !bIsRealIme) { // fNoOnTrans = (pTS->uMsgPumpOwnerRef == 0); // check this once so it doesn't get changed during the op
fNoOnTrans = TRUE;
if (HIWORD(lParam) & KF_UP) { // if this a key up event, clear the KF_REPEAT flag
lParam &= ~(KF_REPEAT << 16); }
hr = _this->_ProcessKey(&wParam, &lParam, fNoOnTrans);
// wParam will be set 0 if _ProcessKey wants to eat it without consulting the ime
// (It might also be converted to VK_HANJA, etc.)
if (hr == S_OK && fNoOnTrans && wParam) { // nobody's using OnTranslateMessage to finish off the key now
hr = _this->_ToAsciiEx(wParam, lParam); } } #ifdef CICERO_3564
else if ((wParam == VK_PROCESSKEY) && ! bIsRealIme) { /*
* KOREAN: * Send VK_PROCESSKEY to finalize current composition string (NT4 behavior) * Post private message (WM_IME_SYSTEM::IMS_FINALIZE_COMPSTR) to let IMM finalize the composition string (NT5) */ IMTLS *ptls = IMTLS_GetOrAlloc(); if (ptls == NULL) return hr;
if (ptls->pAImeProfile == NULL) return hr;
LANGID langid; ptls->pAImeProfile->GetLangId(&langid);
if (PRIMARYLANGID(langid) == LANG_KOREAN) { hr = _this->_ToAsciiEx(wParam, lParam); } } #endif // CICERO_3564
return hr; }
//+---------------------------------------------------------------------------
//
// _SendIMENotify
//
// Inform IME and Apps Wnd about the change of composition window.
//----------------------------------------------------------------------------
HRESULT CActiveIMM::_SendIMENotify( HIMC hImc, HWND hWnd, DWORD dwAction, DWORD dwIndex, DWORD dwValue, WPARAM wParam, LPARAM lParam ) { if (dwAction != 0) { _AImeNotifyIME(hImc, dwAction, dwIndex, dwValue); }
if (hWnd != NULL && wParam != 0) { SendMessage(hWnd, WM_IME_NOTIFY, wParam, lParam); }
return S_OK; }
//+---------------------------------------------------------------------------
//
// _GetIMEProperty
//
//----------------------------------------------------------------------------
DWORD CActiveIMM::_GetIMEProperty(PROPERTY_TYPE iType) { switch (iType) { case PROP_PRIVATE_DATA_SIZE: return _IMEInfoEx.ImeInfo.dwPrivateDataSize; break; case PROP_IME_PROPERTY: return _IMEInfoEx.ImeInfo.fdwProperty; break; case PROP_CONVERSION_CAPS: return _IMEInfoEx.ImeInfo.fdwConversionCaps; break; case PROP_SENTENCE_CAPS: return _IMEInfoEx.ImeInfo.fdwSentenceCaps; break; case PROP_UI_CAPS: return _IMEInfoEx.ImeInfo.fdwUICaps; break; case PROP_SCS_CAPS: return _IMEInfoEx.ImeInfo.fdwSCSCaps; break; case PROP_SELECT_CAPS: return _IMEInfoEx.ImeInfo.fdwSelectCaps; break; default: return 0; } }
//+---------------------------------------------------------------------------
//
// HideOrRestoreToolbarWnd
//
//----------------------------------------------------------------------------
void CActiveIMM::HideOrRestoreToolbarWnd(BOOL fRestore) { ITfLangBarMgr *plbm; if (SUCCEEDED(TF_CreateLangBarMgr(&plbm))) { if (fRestore) { if (_dwPrevToolbarStatus) { plbm->ShowFloating(_dwPrevToolbarStatus); _dwPrevToolbarStatus = 0; } } else { if (SUCCEEDED(plbm->GetShowFloatingStatus(&_dwPrevToolbarStatus))) { BOOL fHide = TRUE; if (_dwPrevToolbarStatus & TF_SFT_DESKBAND) fHide = FALSE; //
// mask for show/hide
//
_dwPrevToolbarStatus &= (TF_SFT_SHOWNORMAL | TF_SFT_DOCK | TF_SFT_MINIMIZED | TF_SFT_HIDDEN);
if (fHide) plbm->ShowFloating(TF_SFT_HIDDEN); } } plbm->Release(); } }
//+---------------------------------------------------------------------------
//
// OnSysShellProc
//
//----------------------------------------------------------------------------
STDAPI CActiveIMM::OnSysShellProc(int nCode, WPARAM wParam, LPARAM lParam) { HRESULT hr = S_FALSE; CActiveIMM *_this = GetTLS(); if (_this == NULL) return hr;
switch (nCode) { case HSHELL_LANGUAGE: if (IsOn98() || IsOn95()) { //
// Windows 9x platform
// Alternative of WM_IME_SYSTEM::IMS_ACTIVATETHREADLAYOUT
//
_this->_OnImeActivateThreadLayout((HKL)lParam); } break; }
return hr; }
|