Aric Stewart : msctf: Add internal functions for managing active text services.

Alexandre Julliard julliard at winehq.org
Fri May 8 08:06:28 CDT 2009


Module: wine
Branch: master
Commit: aaa15671f4f3025a01fc9c5ee35ef40314f97b67
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=aaa15671f4f3025a01fc9c5ee35ef40314f97b67

Author: Aric Stewart <aric at codeweavers.com>
Date:   Thu May  7 14:27:29 2009 -0500

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(+), 0 deletions(-)

diff --git a/dlls/msctf/msctf.c b/dlls/msctf/msctf.c
index 711ae51..57cd477 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 826c09d..7bfc221 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 */




More information about the wine-cvs mailing list