msctf: Add internal functions for managing active text services.

oldstable
Aric Stewart 2009-05-07 14:27:29 -05:00 committed by Alexandre Julliard
parent 7be9c71eac
commit aaa15671f4
2 changed files with 185 additions and 0 deletions

View File

@ -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
*/

View File

@ -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 */