From aaa15671f4f3025a01fc9c5ee35ef40314f97b67 Mon Sep 17 00:00:00 2001 From: Aric Stewart Date: Thu, 7 May 2009 14:27:29 -0500 Subject: [PATCH] msctf: Add internal functions for managing active text services. --- dlls/msctf/msctf.c | 179 ++++++++++++++++++++++++++++++++++++ dlls/msctf/msctf_internal.h | 6 ++ 2 files changed, 185 insertions(+) diff --git a/dlls/msctf/msctf.c b/dlls/msctf/msctf.c index 711ae517742..57cd4779756 100644 --- a/dlls/msctf/msctf.c +++ b/dlls/msctf/msctf.c @@ -26,6 +26,7 @@ #define COBJMACROS #include "wine/debug.h" +#include "wine/list.h" #include "windef.h" #include "winbase.h" #include "winreg.h" @@ -50,10 +51,25 @@ typedef struct LPVOID data; } CookieInternal; +typedef struct { + TF_LANGUAGEPROFILE LanguageProfile; + ITfTextInputProcessor *pITfTextInputProcessor; + ITfThreadMgr *pITfThreadMgr; + TfClientId tid; +} ActivatedTextService; + +typedef struct +{ + struct list entry; + ActivatedTextService *ats; +} AtsEntry; + static CookieInternal *cookies; static UINT id_last; static UINT array_size; +static struct list AtsList = LIST_INIT(AtsList); + DWORD tlsIndex = 0; const WCHAR szwSystemTIPKey[] = {'S','O','F','T','W','A','R','E','\\','M','i','c','r','o','s','o','f','t','\\','C','T','F','\\','T','I','P',0}; @@ -264,6 +280,169 @@ DWORD enumerate_Cookie(DWORD magic, DWORD *index) return 0x0; } +/***************************************************************************** + * Active Text Service Management + *****************************************************************************/ +static HRESULT activate_given_ts(ActivatedTextService *actsvr, ITfThreadMgr* tm) +{ + HRESULT hr; + + /* Already Active? */ + if (actsvr->pITfTextInputProcessor) + return S_OK; + + hr = CoCreateInstance (&actsvr->LanguageProfile.clsid, NULL, CLSCTX_INPROC_SERVER, + &IID_ITfTextInputProcessor, (void**)&actsvr->pITfTextInputProcessor); + if (FAILED(hr)) return hr; + + hr = ITfTextInputProcessor_Activate(actsvr->pITfTextInputProcessor, tm, actsvr->tid); + if (FAILED(hr)) + { + ITfTextInputProcessor_Release(actsvr->pITfTextInputProcessor); + actsvr->pITfTextInputProcessor = NULL; + return hr; + } + + actsvr->pITfThreadMgr = tm; + ITfThreadMgr_AddRef(tm); + return hr; +} + +static HRESULT deactivate_given_ts(ActivatedTextService *actsvr) +{ + HRESULT hr = S_OK; + + if (actsvr->pITfTextInputProcessor) + { + hr = ITfTextInputProcessor_Deactivate(actsvr->pITfTextInputProcessor); + ITfTextInputProcessor_Release(actsvr->pITfTextInputProcessor); + ITfThreadMgr_Release(actsvr->pITfThreadMgr); + actsvr->pITfTextInputProcessor = NULL; + actsvr->pITfThreadMgr = NULL; + } + + return hr; +} + +static void deactivate_remove_conflicting_ts(REFCLSID catid) +{ + AtsEntry *ats, *cursor2; + + LIST_FOR_EACH_ENTRY_SAFE(ats, cursor2, &AtsList, AtsEntry, entry) + { + if (IsEqualCLSID(catid,&ats->ats->LanguageProfile.catid)) + { + deactivate_given_ts(ats->ats); + list_remove(&ats->entry); + HeapFree(GetProcessHeap(),0,ats->ats); + HeapFree(GetProcessHeap(),0,ats); + /* we are guarenteeing there is only 1 */ + break; + } + } +} + +HRESULT add_active_textservice(TF_LANGUAGEPROFILE *lp) +{ + ActivatedTextService *actsvr; + ITfCategoryMgr *catmgr; + AtsEntry *entry; + ITfThreadMgr *tm = (ITfThreadMgr*)TlsGetValue(tlsIndex); + ITfClientId *clientid; + + if (!tm) return E_UNEXPECTED; + + actsvr = HeapAlloc(GetProcessHeap(),0,sizeof(ActivatedTextService)); + if (!actsvr) return E_OUTOFMEMORY; + + entry = HeapAlloc(GetProcessHeap(),0,sizeof(AtsEntry)); + + if (!entry) + { + HeapFree(GetProcessHeap(),0,actsvr); + return E_OUTOFMEMORY; + } + + ITfThreadMgr_QueryInterface(tm,&IID_ITfClientId,(LPVOID)&clientid); + ITfClientId_GetClientId(clientid, &lp->clsid, &actsvr->tid); + ITfClientId_Release(clientid); + + if (!actsvr->tid) + { + HeapFree(GetProcessHeap(),0,actsvr); + return E_OUTOFMEMORY; + } + + actsvr->pITfTextInputProcessor = NULL; + actsvr->LanguageProfile = *lp; + actsvr->LanguageProfile.fActive = TRUE; + + /* get TIP category */ + if (SUCCEEDED(CategoryMgr_Constructor(NULL,(IUnknown**)&catmgr))) + { + static const GUID *list[3] = {&GUID_TFCAT_TIP_SPEECH, &GUID_TFCAT_TIP_KEYBOARD, &GUID_TFCAT_TIP_HANDWRITING}; + + ITfCategoryMgr_FindClosestCategory(catmgr, + &actsvr->LanguageProfile.clsid, &actsvr->LanguageProfile.catid, + list, 3); + + ITfCategoryMgr_Release(catmgr); + } + else + { + ERR("CategoryMgr construction failed\n"); + actsvr->LanguageProfile.catid = GUID_NULL; + } + + if (!IsEqualGUID(&actsvr->LanguageProfile.catid,&GUID_NULL)) + deactivate_remove_conflicting_ts(&actsvr->LanguageProfile.catid); + + entry->ats = actsvr; + list_add_head(&AtsList, &entry->entry); + + return S_OK; +} + +BOOL get_active_textservice(REFCLSID rclsid, TF_LANGUAGEPROFILE *profile) +{ + AtsEntry *ats; + + LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry) + { + if (IsEqualCLSID(rclsid,&ats->ats->LanguageProfile.clsid)) + { + if (profile) + *profile = ats->ats->LanguageProfile; + return TRUE; + } + } + return FALSE; +} + +HRESULT activate_textservices(ITfThreadMgr *tm) +{ + HRESULT hr = S_OK; + AtsEntry *ats; + + LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry) + { + hr = activate_given_ts(ats->ats, tm); + if (FAILED(hr)) + FIXME("Failed to activate text service\n"); + } + return hr; +} + +HRESULT deactivate_textservices(void) +{ + AtsEntry *ats; + + LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry) + deactivate_given_ts(ats->ats); + + return S_OK; +} + /************************************************************************* * MSCTF DllMain */ diff --git a/dlls/msctf/msctf_internal.h b/dlls/msctf/msctf_internal.h index 826c09d58cb..7bfc22157b6 100644 --- a/dlls/msctf/msctf_internal.h +++ b/dlls/msctf/msctf_internal.h @@ -40,5 +40,11 @@ extern LPVOID get_Cookie_data(DWORD id); extern LPVOID remove_Cookie(DWORD id); extern DWORD enumerate_Cookie(DWORD magic, DWORD *index); +/* activated text services functions */ +extern HRESULT add_active_textservice(TF_LANGUAGEPROFILE *lp); +extern BOOL get_active_textservice(REFCLSID rclsid, TF_LANGUAGEPROFILE *lp); +extern HRESULT activate_textservices(ITfThreadMgr *tm); +extern HRESULT deactivate_textservices(void); + extern const WCHAR szwSystemTIPKey[]; #endif /* __WINE_MSCTF_I_H */