Author: dchapyshev Date: Sat May 23 14:31:01 2009 New Revision: 41065
URL: http://svn.reactos.org/svn/reactos?rev=41065&view=rev Log: - Sync msctf, mlang, inetmib1, inetcomm with Wine 1.1.22
Added: trunk/reactos/dll/win32/msctf/range.c (with props) Modified: trunk/reactos/dll/win32/inetcomm/smtptransport.c trunk/reactos/dll/win32/inetmib1/main.c trunk/reactos/dll/win32/mlang/mlang.c trunk/reactos/dll/win32/msctf/context.c trunk/reactos/dll/win32/msctf/documentmgr.c trunk/reactos/dll/win32/msctf/inputprocessor.c trunk/reactos/dll/win32/msctf/msctf.c trunk/reactos/dll/win32/msctf/msctf.rbuild trunk/reactos/dll/win32/msctf/msctf_internal.h trunk/reactos/dll/win32/msctf/threadmgr.c
Modified: trunk/reactos/dll/win32/inetcomm/smtptransport.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/inetcomm/smtptran... ============================================================================== --- trunk/reactos/dll/win32/inetcomm/smtptransport.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/inetcomm/smtptransport.c [iso-8859-1] Sat May 23 14:31:01 2009 @@ -732,7 +732,7 @@ SMTPTransport *This = (SMTPTransport *)iface; const char szCommandFormat[] = "MAIL FROM: <%s>\n"; char *szCommand; - int len = sizeof(szCommandFormat) - 2 /* "%s" */ + strlen(pszEmailFrom); + int len; HRESULT hr;
TRACE("(%s)\n", debugstr_a(pszEmailFrom)); @@ -740,6 +740,7 @@ if (!pszEmailFrom) return E_INVALIDARG;
+ len = sizeof(szCommandFormat) - 2 /* "%s" */ + strlen(pszEmailFrom); szCommand = HeapAlloc(GetProcessHeap(), 0, len); if (!szCommand) return E_OUTOFMEMORY; @@ -758,7 +759,7 @@ SMTPTransport *This = (SMTPTransport *)iface; const char szCommandFormat[] = "RCPT TO: <%s>\n"; char *szCommand; - int len = sizeof(szCommandFormat) - 2 /* "%s" */ + strlen(pszEmailTo); + int len; HRESULT hr;
TRACE("(%s)\n", debugstr_a(pszEmailTo)); @@ -766,6 +767,7 @@ if (!pszEmailTo) return E_INVALIDARG;
+ len = sizeof(szCommandFormat) - 2 /* "%s" */ + strlen(pszEmailTo); szCommand = HeapAlloc(GetProcessHeap(), 0, len); if (!szCommand) return E_OUTOFMEMORY; @@ -833,7 +835,7 @@ SMTPTransport *This = (SMTPTransport *)iface; const char szCommandFormat[] = "AUTH %s\n"; char *szCommand; - int len = sizeof(szCommandFormat) - 2 /* "%s" */ + strlen(pszAuthType); + int len; HRESULT hr;
TRACE("(%s)\n", debugstr_a(pszAuthType)); @@ -841,6 +843,7 @@ if (!pszAuthType) return E_INVALIDARG;
+ len = sizeof(szCommandFormat) - 2 /* "%s" */ + strlen(pszAuthType); szCommand = HeapAlloc(GetProcessHeap(), 0, len); if (!szCommand) return E_OUTOFMEMORY;
Modified: trunk/reactos/dll/win32/inetmib1/main.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/inetmib1/main.c?r... ============================================================================== --- trunk/reactos/dll/win32/inetmib1/main.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/inetmib1/main.c [iso-8859-1] Sat May 23 14:31:01 2009 @@ -143,7 +143,10 @@
copyInt(&pVarBind->value, &numIfs); if (bPduType == SNMP_PDU_GETNEXT) + { + SnmpUtilOidFree(&pVarBind->name); SnmpUtilOidCpy(&pVarBind->name, &numberOid); + } *pErrorStatus = SNMP_ERRORSTATUS_NOERROR; } else @@ -320,7 +323,27 @@ typedef void (*oidToKeyFunc)(AsnObjectIdentifier *oid, void *dst); typedef int (*compareFunc)(const void *key, const void *value);
-static UINT findValueInTable(AsnObjectIdentifier *oid, +/* Finds the first value in the table that matches key. Returns its 1-based + * index if found, or 0 if not found. + */ +static UINT findValueInTable(const void *key, + struct GenericTable *table, size_t tableEntrySize, compareFunc compare) +{ + UINT index = 0; + void *value; + + value = bsearch(key, table->entries, table->numEntries, tableEntrySize, + compare); + if (value) + index = ((BYTE *)value - (BYTE *)table->entries) / tableEntrySize + 1; + return index; +} + +/* Finds the first value in the table that matches oid, using makeKey to + * convert the oid to a key for comparison. Returns the value's 1-based + * index if found, or 0 if not found. + */ +static UINT findOidInTable(AsnObjectIdentifier *oid, struct GenericTable *table, size_t tableEntrySize, oidToKeyFunc makeKey, compareFunc compare) { @@ -329,14 +352,50 @@
if (key) { - void *value; - makeKey(oid, key); - value = bsearch(key, table->entries, table->numEntries, tableEntrySize, - compare); - if (value) - index = ((BYTE *)value - (BYTE *)table->entries) / tableEntrySize - + 1; + index = findValueInTable(key, table, tableEntrySize, compare); + HeapFree(GetProcessHeap(), 0, key); + } + return index; +} + +/* Finds the first successor to the value in the table that does matches oid, + * using makeKey to convert the oid to a key for comparison. A successor is + * a value that does not match oid, so if multiple entries match an oid, only + * the first will ever be returned using this method. + * Returns the successor's 1-based index if found, or 0 if not found. + */ +static UINT findNextOidInTable(AsnObjectIdentifier *oid, + struct GenericTable *table, size_t tableEntrySize, oidToKeyFunc makeKey, + compareFunc compare) +{ + UINT index = 0; + void *key = HeapAlloc(GetProcessHeap(), 0, tableEntrySize); + + if (key) + { + makeKey(oid, key); + index = findValueInTable(key, table, tableEntrySize, compare); + if (index == 0) + { + /* Not found in table. If it's less than the first entry, return + * the first index. Otherwise just return 0 and let the caller + * handle finding the successor. + */ + if (compare(key, table->entries) < 0) + index = 1; + } + else + { + /* Skip any entries that match the same key. This enumeration will + * be incomplete, but it's what Windows appears to do if there are + * multiple entries with the same index in a table, and it avoids + * an infinite loop. + */ + for (++index; index <= table->numEntries && compare(key, + &table->entries[tableEntrySize * index]) == 0; ++index) + ; + } HeapFree(GetProcessHeap(), 0, key); } return index; @@ -397,12 +456,12 @@ } else { - AsnObjectIdentifier ipOid = { instanceLen, + AsnObjectIdentifier instanceOid = { instanceLen, oid->ids + base->idLength + 1 };
- *instance = findValueInTable(&ipOid, table, tableEntrySize, - makeKey, compare) + 1; - if (*instance > table->numEntries) + *instance = findNextOidInTable(&instanceOid, table, + tableEntrySize, makeKey, compare); + if (!*instance || *instance > table->numEntries) ret = SNMP_ERRORSTATUS_NOSUCHNAME; } } @@ -418,10 +477,10 @@ ret = SNMP_ERRORSTATUS_NOSUCHNAME; else { - AsnObjectIdentifier ipOid = { instanceLen, + AsnObjectIdentifier instanceOid = { instanceLen, oid->ids + base->idLength + 1 };
- *instance = findValueInTable(&ipOid, table, tableEntrySize, + *instance = findOidInTable(&instanceOid, table, tableEntrySize, makeKey, compare); if (!*instance) ret = SNMP_ERRORSTATUS_NOSUCHNAME; @@ -440,6 +499,7 @@ AsnObjectIdentifier oid; INT ret;
+ SnmpUtilOidFree(dst); ret = SnmpUtilOidCpy(dst, base); if (ret) { @@ -1311,7 +1371,7 @@ * so we have to continue until an implementation handles the * query or we exhaust the table of supported OIDs. */ - for (; error == SNMP_ERRORSTATUS_NOSUCHNAME && + for (matchingIndex++; error == SNMP_ERRORSTATUS_NOSUCHNAME && matchingIndex < DEFINE_SIZEOF(supportedIDs); matchingIndex++) {
Modified: trunk/reactos/dll/win32/mlang/mlang.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/mlang/mlang.c?rev... ============================================================================== --- trunk/reactos/dll/win32/mlang/mlang.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/mlang/mlang.c [iso-8859-1] Sat May 23 14:31:01 2009 @@ -1939,7 +1939,7 @@ }
if (pdwCodePages) *pdwCodePages = cps; - if (pcchCodePages) *pcchCodePages = i; + if (pcchCodePages) *pcchCodePages = min( i + 1, cchSrc ); return S_OK; }
Modified: trunk/reactos/dll/win32/msctf/context.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msctf/context.c?r... ============================================================================== --- trunk/reactos/dll/win32/msctf/context.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/msctf/context.c [iso-8859-1] Sat May 23 14:31:01 2009 @@ -58,14 +58,24 @@ typedef struct tagContext { const ITfContextVtbl *ContextVtbl; const ITfSourceVtbl *SourceVtbl; + /* const ITfContextCompositionVtbl *ContextCompositionVtbl; */ + /* const ITfContextOwnerCompositionServicesVtbl *ContextOwnerCompositionServicesVtbl; */ + /* const ITfContextOwnerServicesVtbl *ContextOwnerServicesVtbl; */ + /* const ITfInsertAtSelectionVtbl *InsertAtSelectionVtbl; */ + /* const ITfMouseTrackerVtbl *MouseTrackerVtbl; */ + /* const ITfQueryEmbeddedVtbl *QueryEmbeddedVtbl; */ + /* const ITfSourceSingleVtbl *SourceSingleVtbl; */ LONG refCount; + BOOL connected;
TfClientId tidOwner; + TfEditCookie defaultCookie;
ITextStoreACP *pITextStoreACP; ITfContextOwnerCompositionSink *pITfContextOwnerCompositionSink;
ITextStoreACPSink *pITextStoreACPSink; + ITfEditSession* currentEditSession;
/* kept as separate lists to reduce unnecessary iterations */ struct list pContextKeyEventSink; @@ -76,9 +86,14 @@
} Context;
+typedef struct tagEditCookie { + DWORD lockType; + Context *pOwningContext; +} EditCookie;
typedef struct tagTextStoreACPSink { const ITextStoreACPSinkVtbl *TextStoreACPSinkVtbl; + /* const ITextStoreACPServicesVtbl *TextStoreACPServicesVtbl; */ LONG refCount;
Context *pContext; @@ -101,6 +116,7 @@ static void Context_Destructor(Context *This) { struct list *cursor, *cursor2; + EditCookie *cookie; TRACE("destroying %p\n", This);
if (This->pITextStoreACPSink) @@ -114,6 +130,13 @@
if (This->pITfContextOwnerCompositionSink) ITextStoreACPSink_Release(This->pITfContextOwnerCompositionSink); + + if (This->defaultCookie) + { + cookie = remove_Cookie(This->defaultCookie); + HeapFree(GetProcessHeap(),0,cookie); + This->defaultCookie = 0; + }
LIST_FOR_EACH_SAFE(cursor, cursor2, &This->pContextKeyEventSink) { @@ -197,9 +220,53 @@ TfClientId tid, ITfEditSession *pes, DWORD dwFlags, HRESULT *phrSession) { - Context *This = (Context *)iface; - FIXME("STUB:(%p)\n",This); - return E_NOTIMPL; + HRESULT hr; + Context *This = (Context *)iface; + DWORD dwLockFlags = 0x0; + TS_STATUS status; + + TRACE("(%p) %i %p %x %p\n",This, tid, pes, dwFlags, phrSession); + + if (!(dwFlags & TF_ES_READ) && !(dwFlags & TF_ES_READWRITE)) + { + *phrSession = E_FAIL; + return E_INVALIDARG; + } + + if (!This->pITextStoreACP) + { + FIXME("No ITextStoreACP avaliable\n"); + *phrSession = E_FAIL; + return E_FAIL; + } + + if (!(dwFlags & TF_ES_ASYNC)) + dwLockFlags |= TS_LF_SYNC; + + if ((dwFlags & TF_ES_READWRITE) == TF_ES_READWRITE) + dwLockFlags |= TS_LF_READWRITE; + else if (dwFlags & TF_ES_READ) + dwLockFlags |= TS_LF_READ; + + /* TODO: cache this */ + ITextStoreACP_GetStatus(This->pITextStoreACP, &status); + + if (((dwFlags & TF_ES_READWRITE) == TF_ES_READWRITE) && (status.dwDynamicFlags & TS_SD_READONLY)) + { + *phrSession = TS_E_READONLY; + return S_OK; + } + + if (FAILED (ITfEditSession_QueryInterface(pes, &IID_ITfEditSession, (LPVOID*)&This->currentEditSession))) + { + *phrSession = E_FAIL; + return E_INVALIDARG; + } + + + hr = ITextStoreACP_RequestLock(This->pITextStoreACP, dwLockFlags, phrSession); + + return hr; }
static HRESULT WINAPI Context_InWriteSession (ITfContext *iface, @@ -216,8 +283,59 @@ TF_SELECTION *pSelection, ULONG *pcFetched) { Context *This = (Context *)iface; - FIXME("STUB:(%p)\n",This); - return E_NOTIMPL; + EditCookie *cookie; + ULONG count, i; + ULONG totalFetched = 0; + HRESULT hr = S_OK; + + if (!pSelection || !pcFetched) + return E_INVALIDARG; + + *pcFetched = 0; + + if (!This->connected) + return TF_E_DISCONNECTED; + + if (get_Cookie_magic(ec)!=COOKIE_MAGIC_EDITCOOKIE) + return TF_E_NOLOCK; + + if (!This->pITextStoreACP) + { + FIXME("Context does not have a ITextStoreACP\n"); + return E_NOTIMPL; + } + + cookie = get_Cookie_data(ec); + + if (ulIndex == TF_DEFAULT_SELECTION) + count = 1; + else + count = ulCount; + + for (i = 0; i < count; i++) + { + DWORD fetched; + TS_SELECTION_ACP acps; + + hr = ITextStoreACP_GetSelection(This->pITextStoreACP, ulIndex + i, + 1, &acps, &fetched); + + if (hr == TS_E_NOLOCK) + return TF_E_NOLOCK; + else if (SUCCEEDED(hr)) + { + pSelection[totalFetched].style.ase = acps.style.ase; + pSelection[totalFetched].style.fInterimChar = acps.style.fInterimChar; + Range_Constructor(iface, This->pITextStoreACP, cookie->lockType, acps.acpStart, acps.acpEnd, &pSelection[totalFetched].range); + totalFetched ++; + } + else + break; + } + + *pcFetched = totalFetched; + + return hr; }
static HRESULT WINAPI Context_SetSelection (ITfContext *iface, @@ -232,16 +350,53 @@ TfEditCookie ec, ITfRange **ppStart) { Context *This = (Context *)iface; - FIXME("STUB:(%p)\n",This); - return E_NOTIMPL; + EditCookie *cookie; + TRACE("(%p) %i %p\n",This,ec,ppStart); + + if (!ppStart) + return E_INVALIDARG; + + *ppStart = NULL; + + if (!This->connected) + return TF_E_DISCONNECTED; + + if (get_Cookie_magic(ec)!=COOKIE_MAGIC_EDITCOOKIE) + return TF_E_NOLOCK; + + cookie = get_Cookie_data(ec); + return Range_Constructor(iface, This->pITextStoreACP, cookie->lockType, 0, 0, ppStart); }
static HRESULT WINAPI Context_GetEnd (ITfContext *iface, TfEditCookie ec, ITfRange **ppEnd) { Context *This = (Context *)iface; - FIXME("STUB:(%p)\n",This); - return E_NOTIMPL; + EditCookie *cookie; + LONG end; + TRACE("(%p) %i %p\n",This,ec,ppEnd); + + if (!ppEnd) + return E_INVALIDARG; + + *ppEnd = NULL; + + if (!This->connected) + return TF_E_DISCONNECTED; + + if (get_Cookie_magic(ec)!=COOKIE_MAGIC_EDITCOOKIE) + return TF_E_NOLOCK; + + if (!This->pITextStoreACP) + { + FIXME("Context does not have a ITextStoreACP\n"); + return E_NOTIMPL; + } + + cookie = get_Cookie_data(ec); + ITextStoreACP_GetEndACP(This->pITextStoreACP,&end); + + return Range_Constructor(iface, This->pITextStoreACP, cookie->lockType, end, end, ppEnd); }
static HRESULT WINAPI Context_GetActiveView (ITfContext *iface, @@ -376,7 +531,7 @@ es = HeapAlloc(GetProcessHeap(),0,sizeof(ContextSink)); if (!es) return E_OUTOFMEMORY; - if (!SUCCEEDED(IUnknown_QueryInterface(punk, riid, (LPVOID*)&es->interfaces.pITfTextEditSink))) + if (FAILED(IUnknown_QueryInterface(punk, riid, (LPVOID *)&es->interfaces.pITfTextEditSink))) { HeapFree(GetProcessHeap(),0,es); return CONNECT_E_CANNOTCONNECT; @@ -427,10 +582,18 @@ HRESULT Context_Constructor(TfClientId tidOwner, IUnknown *punk, ITfContext **ppOut, TfEditCookie *pecTextStore) { Context *This; + EditCookie *cookie;
This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Context)); if (This == NULL) return E_OUTOFMEMORY; + + cookie = HeapAlloc(GetProcessHeap(),0,sizeof(EditCookie)); + if (cookie == NULL) + { + HeapFree(GetProcessHeap(),0,This); + return E_OUTOFMEMORY; + }
TRACE("(%p) %x %p %p %p\n",This, tidOwner, punk, ppOut, pecTextStore);
@@ -438,16 +601,15 @@ This->SourceVtbl = &Context_SourceVtbl; This->refCount = 1; This->tidOwner = tidOwner; + This->connected = FALSE; + + cookie->lockType = TF_ES_READ; + cookie->pOwningContext = This;
if (punk) { - if (SUCCEEDED(IUnknown_QueryInterface(punk, &IID_ITextStoreACP, - (LPVOID*)&This->pITextStoreACP))) - { - if (SUCCEEDED(TextStoreACPSink_Constructor(&This->pITextStoreACPSink, This))) - ITextStoreACP_AdviseSink(This->pITextStoreACP, &IID_ITextStoreACPSink, - (IUnknown*)This->pITextStoreACPSink, TS_AS_ALL_SINKS); - } + IUnknown_QueryInterface(punk, &IID_ITextStoreACP, + (LPVOID*)&This->pITextStoreACP);
IUnknown_QueryInterface(punk, &IID_ITfContextOwnerCompositionSink, (LPVOID*)&This->pITfContextOwnerCompositionSink); @@ -456,10 +618,8 @@ FIXME("Unhandled pUnk\n"); }
- TRACE("returning %p\n", This); - *ppOut = (ITfContext*)This; - /* FIXME */ - *pecTextStore = 0xdeaddead; + This->defaultCookie = generate_Cookie(COOKIE_MAGIC_EDITCOOKIE,cookie); + *pecTextStore = This->defaultCookie;
list_init(&This->pContextKeyEventSink); list_init(&This->pEditTransactionSink); @@ -467,6 +627,37 @@ list_init(&This->pTextEditSink); list_init(&This->pTextLayoutSink);
+ *ppOut = (ITfContext*)This; + TRACE("returning %p\n", This); + + return S_OK; +} + +HRESULT Context_Initialize(ITfContext *iface) +{ + Context *This = (Context *)iface; + + if (This->pITextStoreACP) + { + if (SUCCEEDED(TextStoreACPSink_Constructor(&This->pITextStoreACPSink, This))) + ITextStoreACP_AdviseSink(This->pITextStoreACP, &IID_ITextStoreACPSink, + (IUnknown*)This->pITextStoreACPSink, TS_AS_ALL_SINKS); + } + This->connected = TRUE; + return S_OK; +} + +HRESULT Context_Uninitialize(ITfContext *iface) +{ + Context *This = (Context *)iface; + + if (This->pITextStoreACPSink) + { + ITextStoreACP_UnadviseSink(This->pITextStoreACP, (IUnknown*)This->pITextStoreACPSink); + if (ITextStoreACPSink_Release(This->pITextStoreACPSink) == 0) + This->pITextStoreACPSink = NULL; + } + This->connected = FALSE; return S_OK; }
@@ -564,8 +755,36 @@ DWORD dwLockFlags) { TextStoreACPSink *This = (TextStoreACPSink *)iface; - FIXME("STUB:(%p)\n",This); - return E_NOTIMPL; + HRESULT hr; + EditCookie *cookie; + TfEditCookie ec; + + TRACE("(%p) %x\n",This, dwLockFlags); + + if (!This->pContext || !This->pContext->currentEditSession) + { + ERR("OnLockGranted called on a context without a current edit session\n"); + return E_FAIL; + } + + cookie = HeapAlloc(GetProcessHeap(),0,sizeof(EditCookie)); + if (!cookie) + return E_OUTOFMEMORY; + + cookie->lockType = dwLockFlags; + cookie->pOwningContext = This->pContext; + ec = generate_Cookie(COOKIE_MAGIC_EDITCOOKIE, cookie); + + hr = ITfEditSession_DoEditSession(This->pContext->currentEditSession, ec); + + ITfEditSession_Release(This->pContext->currentEditSession); + This->pContext->currentEditSession = NULL; + + /* Edit Cookie is only valid during the edit session */ + cookie = remove_Cookie(ec); + HeapFree(GetProcessHeap(),0,cookie); + + return hr; }
static HRESULT WINAPI TextStoreACPSink_OnStartEditTransaction(ITextStoreACPSink *iface)
Modified: trunk/reactos/dll/win32/msctf/documentmgr.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msctf/documentmgr... ============================================================================== --- trunk/reactos/dll/win32/msctf/documentmgr.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/msctf/documentmgr.c [iso-8859-1] Sat May 23 14:31:01 2009 @@ -138,6 +138,7 @@ This->contextStack[0] = check;
ITfThreadMgrEventSink_OnPushContext(This->ThreadMgrSink,check); + Context_Initialize(check);
return S_OK; } @@ -153,11 +154,13 @@ { ITfThreadMgrEventSink_OnPopContext(This->ThreadMgrSink,This->contextStack[0]); ITfContext_Release(This->contextStack[0]); + Context_Uninitialize(This->contextStack[0]); } if (This->contextStack[1]) { ITfThreadMgrEventSink_OnPopContext(This->ThreadMgrSink,This->contextStack[1]); ITfContext_Release(This->contextStack[1]); + Context_Uninitialize(This->contextStack[1]); } This->contextStack[0] = This->contextStack[1] = NULL; ITfThreadMgrEventSink_OnUninitDocumentMgr(This->ThreadMgrSink, iface); @@ -172,6 +175,7 @@
ITfThreadMgrEventSink_OnPopContext(This->ThreadMgrSink,This->contextStack[0]); ITfContext_Release(This->contextStack[0]); + Context_Uninitialize(This->contextStack[0]); This->contextStack[0] = This->contextStack[1]; This->contextStack[1] = NULL;
Modified: trunk/reactos/dll/win32/msctf/inputprocessor.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msctf/inputproces... ============================================================================== --- trunk/reactos/dll/win32/msctf/inputprocessor.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/msctf/inputprocessor.c [iso-8859-1] Sat May 23 14:31:01 2009 @@ -32,8 +32,10 @@ #include "shlwapi.h" #include "winerror.h" #include "objbase.h" +#include "olectl.h"
#include "wine/unicode.h" +#include "wine/list.h"
#include "msctf.h" #include "msctf_internal.h" @@ -45,11 +47,26 @@ static const WCHAR szwTipfmt[] = {'%','s','\','%','s',0}; static const WCHAR szwFullLangfmt[] = {'%','s','\','%','s','\','%','s','\','0','x','%','0','8','x','\','%','s',0};
+typedef struct tagInputProcessorProfilesSink { + struct list entry; + union { + /* InputProcessorProfile Sinks */ + IUnknown *pIUnknown; + ITfLanguageProfileNotifySink *pITfLanguageProfileNotifySink; + } interfaces; +} InputProcessorProfilesSink; + typedef struct tagInputProcessorProfiles { const ITfInputProcessorProfilesVtbl *InputProcessorProfilesVtbl; + const ITfSourceVtbl *SourceVtbl; + /* const ITfInputProcessorProfileMgrVtbl *InputProcessorProfileMgrVtbl; */ + /* const ITfInputProcessorProfilesExVtbl *InputProcessorProfilesExVtbl; */ + /* const ITfInputProcessorProfileSubstituteLayoutVtbl *InputProcessorProfileSubstituteLayoutVtbl; */ LONG refCount;
LANGID currentLanguage; + + struct list LanguageProfileNotifySink; } InputProcessorProfiles;
typedef struct tagProfilesEnumGuid { @@ -78,9 +95,30 @@ static HRESULT ProfilesEnumGuid_Constructor(IEnumGUID **ppOut); static HRESULT EnumTfLanguageProfiles_Constructor(LANGID langid, IEnumTfLanguageProfiles **ppOut);
+static inline InputProcessorProfiles *impl_from_ITfSourceVtbl(ITfSource *iface) +{ + return (InputProcessorProfiles *)((char *)iface - FIELD_OFFSET(InputProcessorProfiles,SourceVtbl)); +} + +static void free_sink(InputProcessorProfilesSink *sink) +{ + IUnknown_Release(sink->interfaces.pIUnknown); + HeapFree(GetProcessHeap(),0,sink); +} + static void InputProcessorProfiles_Destructor(InputProcessorProfiles *This) { + struct list *cursor, *cursor2; TRACE("destroying %p\n", This); + + /* free sinks */ + LIST_FOR_EACH_SAFE(cursor, cursor2, &This->LanguageProfileNotifySink) + { + InputProcessorProfilesSink* sink = LIST_ENTRY(cursor,InputProcessorProfilesSink,entry); + list_remove(cursor); + free_sink(sink); + } + HeapFree(GetProcessHeap(),0,This); }
@@ -121,6 +159,10 @@ if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfInputProcessorProfiles)) { *ppvOut = This; + } + else if (IsEqualIID(iid, &IID_ITfSource)) + { + *ppvOut = &This->SourceVtbl; }
if (*ppvOut) @@ -536,6 +578,92 @@ InputProcessorProfiles_SubstituteKeyboardLayout };
+/***************************************************** + * ITfSource functions + *****************************************************/ +static HRESULT WINAPI IPPSource_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut) +{ + InputProcessorProfiles *This = impl_from_ITfSourceVtbl(iface); + return InputProcessorProfiles_QueryInterface((ITfInputProcessorProfiles *)This, iid, *ppvOut); +} + +static ULONG WINAPI IPPSource_AddRef(ITfSource *iface) +{ + InputProcessorProfiles *This = impl_from_ITfSourceVtbl(iface); + return InputProcessorProfiles_AddRef((ITfInputProcessorProfiles*)This); +} + +static ULONG WINAPI IPPSource_Release(ITfSource *iface) +{ + InputProcessorProfiles *This = impl_from_ITfSourceVtbl(iface); + return InputProcessorProfiles_Release((ITfInputProcessorProfiles *)This); +} + +static WINAPI HRESULT IPPSource_AdviseSink(ITfSource *iface, + REFIID riid, IUnknown *punk, DWORD *pdwCookie) +{ + InputProcessorProfilesSink *ipps; + InputProcessorProfiles *This = impl_from_ITfSourceVtbl(iface); + + TRACE("(%p) %s %p %p\n",This,debugstr_guid(riid),punk,pdwCookie); + + if (!riid || !punk || !pdwCookie) + return E_INVALIDARG; + + if (IsEqualIID(riid, &IID_ITfLanguageProfileNotifySink)) + { + ipps = HeapAlloc(GetProcessHeap(),0,sizeof(InputProcessorProfilesSink)); + if (!ipps) + return E_OUTOFMEMORY; + if (FAILED(IUnknown_QueryInterface(punk, riid, (LPVOID *)&ipps->interfaces.pITfLanguageProfileNotifySink))) + { + HeapFree(GetProcessHeap(),0,ipps); + return CONNECT_E_CANNOTCONNECT; + } + list_add_head(&This->LanguageProfileNotifySink,&ipps->entry); + *pdwCookie = generate_Cookie(COOKIE_MAGIC_IPPSINK, ipps); + } + else + { + FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid)); + return E_NOTIMPL; + } + + TRACE("cookie %x\n",*pdwCookie); + + return S_OK; +} + +static WINAPI HRESULT IPPSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie) +{ + InputProcessorProfilesSink *sink; + InputProcessorProfiles *This = impl_from_ITfSourceVtbl(iface); + + TRACE("(%p) %x\n",This,pdwCookie); + + if (get_Cookie_magic(pdwCookie)!=COOKIE_MAGIC_IPPSINK) + return E_INVALIDARG; + + sink = (InputProcessorProfilesSink*)remove_Cookie(pdwCookie); + if (!sink) + return CONNECT_E_NOCONNECTION; + + list_remove(&sink->entry); + free_sink(sink); + + return S_OK; +} + +static const ITfSourceVtbl InputProcessorProfiles_SourceVtbl = +{ + IPPSource_QueryInterface, + IPPSource_AddRef, + IPPSource_Release, + + IPPSource_AdviseSink, + IPPSource_UnadviseSink, +}; + HRESULT InputProcessorProfiles_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut) { InputProcessorProfiles *This; @@ -547,8 +675,11 @@ return E_OUTOFMEMORY;
This->InputProcessorProfilesVtbl= &InputProcessorProfiles_InputProcessorProfilesVtbl; + This->SourceVtbl = &InputProcessorProfiles_SourceVtbl; This->refCount = 1; This->currentLanguage = GetUserDefaultLCID(); + + list_init(&This->LanguageProfileNotifySink);
TRACE("returning %p\n", This); *ppOut = (IUnknown *)This;
Modified: trunk/reactos/dll/win32/msctf/msctf.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msctf/msctf.c?rev... ============================================================================== --- trunk/reactos/dll/win32/msctf/msctf.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/msctf/msctf.c [iso-8859-1] Sat May 23 14:31:01 2009 @@ -55,6 +55,7 @@ TF_LANGUAGEPROFILE LanguageProfile; ITfTextInputProcessor *pITfTextInputProcessor; ITfThreadMgr *pITfThreadMgr; + ITfKeyEventSink *pITfKeyEventSink; TfClientId tid; } ActivatedTextService;
@@ -357,14 +358,6 @@ 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); @@ -378,6 +371,7 @@ actsvr->pITfTextInputProcessor = NULL; actsvr->LanguageProfile = *lp; actsvr->LanguageProfile.fActive = TRUE; + actsvr->pITfKeyEventSink = NULL;
/* get TIP category */ if (SUCCEEDED(CategoryMgr_Constructor(NULL,(IUnknown**)&catmgr))) @@ -401,6 +395,14 @@
if (activated > 0) activate_given_ts(actsvr, tm); + + entry = HeapAlloc(GetProcessHeap(),0,sizeof(AtsEntry)); + + if (!entry) + { + HeapFree(GetProcessHeap(),0,actsvr); + return E_OUTOFMEMORY; + }
entry->ats = actsvr; list_add_head(&AtsList, &entry->entry); @@ -454,6 +456,50 @@ deactivate_given_ts(ats->ats);
return S_OK; +} + +CLSID get_textservice_clsid(TfClientId tid) +{ + AtsEntry *ats; + + LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry) + if (ats->ats->tid == tid) + return ats->ats->LanguageProfile.clsid; + return GUID_NULL; +} + +HRESULT get_textservice_sink(TfClientId tid, REFCLSID iid, IUnknown **sink) +{ + AtsEntry *ats; + + if (!IsEqualCLSID(iid,&IID_ITfKeyEventSink)) + return E_NOINTERFACE; + + LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry) + if (ats->ats->tid == tid) + { + *sink = (IUnknown*)ats->ats->pITfKeyEventSink; + return S_OK; + } + + return E_FAIL; +} + +HRESULT set_textservice_sink(TfClientId tid, REFCLSID iid, IUnknown* sink) +{ + AtsEntry *ats; + + if (!IsEqualCLSID(iid,&IID_ITfKeyEventSink)) + return E_NOINTERFACE; + + LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry) + if (ats->ats->tid == tid) + { + ats->ats->pITfKeyEventSink = (ITfKeyEventSink*)sink; + return S_OK; + } + + return E_FAIL; }
/*************************************************************************
Modified: trunk/reactos/dll/win32/msctf/msctf.rbuild URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msctf/msctf.rbuil... ============================================================================== --- trunk/reactos/dll/win32/msctf/msctf.rbuild [iso-8859-1] (original) +++ trunk/reactos/dll/win32/msctf/msctf.rbuild [iso-8859-1] Sat May 23 14:31:01 2009 @@ -13,6 +13,7 @@ <file>documentmgr.c</file> <file>inputprocessor.c</file> <file>msctf.c</file> + <file>range.c</file> <file>regsvr.c</file> <file>threadmgr.c</file> <file>version.rc</file>
Modified: trunk/reactos/dll/win32/msctf/msctf_internal.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msctf/msctf_inter... ============================================================================== --- trunk/reactos/dll/win32/msctf/msctf_internal.h [iso-8859-1] (original) +++ trunk/reactos/dll/win32/msctf/msctf_internal.h [iso-8859-1] Sat May 23 14:31:01 2009 @@ -24,6 +24,8 @@ #define COOKIE_MAGIC_TMSINK 0x0010 #define COOKIE_MAGIC_CONTEXTSINK 0x0020 #define COOKIE_MAGIC_GUIDATOM 0x0030 +#define COOKIE_MAGIC_IPPSINK 0x0040 +#define COOKIE_MAGIC_EDITCOOKIE 0x0050
extern DWORD tlsIndex; extern TfClientId processId; @@ -33,6 +35,10 @@ extern HRESULT Context_Constructor(TfClientId tidOwner, IUnknown *punk, ITfContext **ppOut, TfEditCookie *pecTextStore); extern HRESULT InputProcessorProfiles_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut); extern HRESULT CategoryMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut); +extern HRESULT Range_Constructor(ITfContext *context, ITextStoreACP *textstore, DWORD lockType, DWORD anchorStart, DWORD anchorEnd, ITfRange **ppOut); + +extern HRESULT Context_Initialize(ITfContext *cxt); +extern HRESULT Context_Uninitialize(ITfContext *cxt);
/* cookie function */ extern DWORD generate_Cookie(DWORD magic, LPVOID data); @@ -47,5 +53,9 @@ extern HRESULT activate_textservices(ITfThreadMgr *tm); extern HRESULT deactivate_textservices(void);
+extern CLSID get_textservice_clsid(TfClientId tid); +extern HRESULT get_textservice_sink(TfClientId tid, REFCLSID iid, IUnknown** sink); +extern HRESULT set_textservice_sink(TfClientId tid, REFCLSID iid, IUnknown* sink); + extern const WCHAR szwSystemTIPKey[]; #endif /* __WINE_MSCTF_I_H */
Added: trunk/reactos/dll/win32/msctf/range.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msctf/range.c?rev... ============================================================================== --- trunk/reactos/dll/win32/msctf/range.c (added) +++ trunk/reactos/dll/win32/msctf/range.c [iso-8859-1] Sat May 23 14:31:01 2009 @@ -1,0 +1,333 @@ +/* + * ITfRange implementation + * + * Copyright 2009 Aric Stewart, CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" + +#include <stdarg.h> + +#define COBJMACROS + +#include "wine/debug.h" +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "winuser.h" +#include "shlwapi.h" +#include "winerror.h" +#include "objbase.h" + +#include "wine/unicode.h" + +#include "msctf.h" +#include "msctf_internal.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msctf); + +typedef struct tagRange { + const ITfRangeVtbl *RangeVtbl; + /* const ITfRangeACPVtb *RangeACPVtbl; */ + LONG refCount; + + ITextStoreACP *pITextStoreACP; + ITfContext *pITfContext; + + DWORD lockType; + TfGravity gravityStart, gravityEnd; + DWORD anchorStart, anchorEnd; + +} Range; + +static void Range_Destructor(Range *This) +{ + TRACE("destroying %p\n", This); + HeapFree(GetProcessHeap(),0,This); +} + +static HRESULT WINAPI Range_QueryInterface(ITfRange *iface, REFIID iid, LPVOID *ppvOut) +{ + Range *This = (Range*)iface; + *ppvOut = NULL; + + if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfRange)) + { + *ppvOut = This; + } + + if (*ppvOut) + { + IUnknown_AddRef(iface); + return S_OK; + } + + WARN("unsupported interface: %s\n", debugstr_guid(iid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI Range_AddRef(ITfRange *iface) +{ + Range *This = (Range *)iface; + return InterlockedIncrement(&This->refCount); +} + +static ULONG WINAPI Range_Release(ITfRange *iface) +{ + Range *This = (Range *)iface; + ULONG ret; + + ret = InterlockedDecrement(&This->refCount); + if (ret == 0) + Range_Destructor(This); + return ret; +} + +/***************************************************** + * ITfRange functions + *****************************************************/ + +static HRESULT WINAPI Range_GetText(ITfRange *iface, TfEditCookie ec, + DWORD dwFlags, WCHAR *pchText, ULONG cchMax, ULONG *pcch) +{ + Range *This = (Range *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Range_SetText(ITfRange *iface, TfEditCookie ec, + DWORD dwFlags, const WCHAR *pchText, LONG cch) +{ + Range *This = (Range *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Range_GetFormattedText(ITfRange *iface, TfEditCookie ec, + IDataObject **ppDataObject) +{ + Range *This = (Range *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Range_GetEmbedded(ITfRange *iface, TfEditCookie ec, + REFGUID rguidService, REFIID riid, IUnknown **ppunk) +{ + Range *This = (Range *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Range_InsertEmbedded(ITfRange *iface, TfEditCookie ec, + DWORD dwFlags, IDataObject *pDataObject) +{ + Range *This = (Range *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Range_ShiftStart(ITfRange *iface, TfEditCookie ec, + LONG cchReq, LONG *pcch, const TF_HALTCOND *pHalt) +{ + Range *This = (Range *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Range_ShiftEnd(ITfRange *iface, TfEditCookie ec, + LONG cchReq, LONG *pcch, const TF_HALTCOND *pHalt) +{ + Range *This = (Range *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Range_ShiftStartToRange(ITfRange *iface, TfEditCookie ec, + ITfRange *pRange, TfAnchor aPos) +{ + Range *This = (Range *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Range_ShiftEndToRange(ITfRange *iface, TfEditCookie ec, + ITfRange *pRange, TfAnchor aPos) +{ + Range *This = (Range *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Range_ShiftStartRegion(ITfRange *iface, TfEditCookie ec, + TfShiftDir dir, BOOL *pfNoRegion) +{ + Range *This = (Range *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Range_ShiftEndRegion(ITfRange *iface, TfEditCookie ec, + TfShiftDir dir, BOOL *pfNoRegion) +{ + Range *This = (Range *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Range_IsEmpty(ITfRange *iface, TfEditCookie ec, + BOOL *pfEmpty) +{ + Range *This = (Range *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Range_Collapse(ITfRange *iface, TfEditCookie ec, + TfAnchor aPos) +{ + Range *This = (Range *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Range_IsEqualStart(ITfRange *iface, TfEditCookie ec, + ITfRange *pWith, TfAnchor aPos, BOOL *pfEqual) +{ + Range *This = (Range *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Range_IsEqualEnd(ITfRange *iface, TfEditCookie ec, + ITfRange *pWith, TfAnchor aPos, BOOL *pfEqual) +{ + Range *This = (Range *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Range_CompareStart(ITfRange *iface, TfEditCookie ec, + ITfRange *pWith, TfAnchor aPos, LONG *plResult) +{ + Range *This = (Range *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Range_CompareEnd(ITfRange *iface, TfEditCookie ec, + ITfRange *pWith, TfAnchor aPos, LONG *plResult) +{ + Range *This = (Range *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Range_AdjustForInsert(ITfRange *iface, TfEditCookie ec, + ULONG cchInsert, BOOL *pfInsertOk) +{ + Range *This = (Range *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Range_GetGravity(ITfRange *iface, + TfGravity *pgStart, TfGravity *pgEnd) +{ + Range *This = (Range *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Range_SetGravity(ITfRange *iface, TfEditCookie ec, + TfGravity gStart, TfGravity gEnd) +{ + Range *This = (Range *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Range_Clone(ITfRange *iface, ITfRange **ppClone) +{ + Range *This = (Range *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Range_GetContext(ITfRange *iface, ITfContext **ppContext) +{ + Range *This = (Range *)iface; + TRACE("(%p)\n",This); + if (!ppContext) + return E_INVALIDARG; + *ppContext = This->pITfContext; + return S_OK; +} + +static const ITfRangeVtbl Range_RangeVtbl = +{ + Range_QueryInterface, + Range_AddRef, + Range_Release, + + Range_GetText, + Range_SetText, + Range_GetFormattedText, + Range_GetEmbedded, + Range_InsertEmbedded, + Range_ShiftStart, + Range_ShiftEnd, + Range_ShiftStartToRange, + Range_ShiftEndToRange, + Range_ShiftStartRegion, + Range_ShiftEndRegion, + Range_IsEmpty, + Range_Collapse, + Range_IsEqualStart, + Range_IsEqualEnd, + Range_CompareStart, + Range_CompareEnd, + Range_AdjustForInsert, + Range_GetGravity, + Range_SetGravity, + Range_Clone, + Range_GetContext +}; + +HRESULT Range_Constructor(ITfContext *context, ITextStoreACP *textstore, DWORD lockType, DWORD anchorStart, DWORD anchorEnd, ITfRange **ppOut) +{ + Range *This; + + This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Range)); + if (This == NULL) + return E_OUTOFMEMORY; + + TRACE("(%p) %p %p\n",This, context, textstore); + + This->RangeVtbl= &Range_RangeVtbl; + This->refCount = 1; + This->pITfContext = context; + This->pITextStoreACP = textstore; + This->lockType = lockType; + This->anchorStart = anchorStart; + This->anchorEnd = anchorEnd; + + *ppOut = (ITfRange*)This; + TRACE("returning %p\n", This); + + return S_OK; +}
Propchange: trunk/reactos/dll/win32/msctf/range.c ------------------------------------------------------------------------------ svn:eol-style = native
Modified: trunk/reactos/dll/win32/msctf/threadmgr.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msctf/threadmgr.c... ============================================================================== --- trunk/reactos/dll/win32/msctf/threadmgr.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/msctf/threadmgr.c [iso-8859-1] Sat May 23 14:31:01 2009 @@ -71,12 +71,20 @@ const ITfKeystrokeMgrVtbl *KeystrokeMgrVtbl; const ITfMessagePumpVtbl *MessagePumpVtbl; const ITfClientIdVtbl *ClientIdVtbl; + /* const ITfThreadMgrExVtbl *ThreadMgrExVtbl; */ + /* const ITfConfigureSystemKeystrokeFeedVtbl *ConfigureSystemKeystrokeFeedVtbl; */ + /* const ITfLangBarItemMgrVtbl *LangBarItemMgrVtbl; */ + /* const ITfUIElementMgrVtbl *UIElementMgrVtbl; */ + /* const ITfSourceSingleVtbl *SourceSingleVtbl; */ LONG refCount;
const ITfThreadMgrEventSinkVtbl *ThreadMgrEventSinkVtbl; /* internal */
ITfDocumentMgr *focus; LONG activationCount; + + ITfKeyEventSink *forgroundKeyEventSink; + CLSID forgroundTextService;
struct list CurrentPreservedKeys;
@@ -434,7 +442,7 @@ tms = HeapAlloc(GetProcessHeap(),0,sizeof(ThreadMgrSink)); if (!tms) return E_OUTOFMEMORY; - if (!SUCCEEDED(IUnknown_QueryInterface(punk, riid, (LPVOID*)&tms->interfaces.pITfThreadMgrEventSink))) + if (FAILED(IUnknown_QueryInterface(punk, riid, (LPVOID *)&tms->interfaces.pITfThreadMgrEventSink))) { HeapFree(GetProcessHeap(),0,tms); return CONNECT_E_CANNOTCONNECT; @@ -509,24 +517,87 @@ TfClientId tid, ITfKeyEventSink *pSink, BOOL fForeground) { ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface); - FIXME("STUB:(%p)\n",This); - return E_NOTIMPL; + CLSID textservice; + ITfKeyEventSink *check = NULL; + + TRACE("(%p) %x %p %i\n",This,tid,pSink,fForeground); + + if (!tid || !pSink) + return E_INVALIDARG; + + textservice = get_textservice_clsid(tid); + if (IsEqualCLSID(&GUID_NULL,&textservice)) + return E_INVALIDARG; + + get_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown**)&check); + if (check != NULL) + return CONNECT_E_ADVISELIMIT; + + if (FAILED(IUnknown_QueryInterface(pSink,&IID_ITfKeyEventSink,(LPVOID*) &check))) + return E_INVALIDARG; + + set_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown*)check); + + if (fForeground) + { + if (This->forgroundKeyEventSink) + { + ITfKeyEventSink_OnSetFocus(This->forgroundKeyEventSink, FALSE); + ITfKeyEventSink_Release(This->forgroundKeyEventSink); + } + ITfKeyEventSink_AddRef(check); + ITfKeyEventSink_OnSetFocus(check, TRUE); + This->forgroundKeyEventSink = check; + This->forgroundTextService = textservice; + } + return S_OK; }
static HRESULT WINAPI KeystrokeMgr_UnadviseKeyEventSink(ITfKeystrokeMgr *iface, TfClientId tid) { ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface); - FIXME("STUB:(%p)\n",This); - return E_NOTIMPL; + CLSID textservice; + ITfKeyEventSink *check = NULL; + TRACE("(%p) %x\n",This,tid); + + if (!tid) + return E_INVALIDARG; + + textservice = get_textservice_clsid(tid); + if (IsEqualCLSID(&GUID_NULL,&textservice)) + return E_INVALIDARG; + + get_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown**)&check); + + if (!check) + return CONNECT_E_NOCONNECTION; + + set_textservice_sink(tid, &IID_ITfKeyEventSink, NULL); + ITfKeyEventSink_Release(check); + + if (This->forgroundKeyEventSink == check) + { + ITfKeyEventSink_Release(This->forgroundKeyEventSink); + This->forgroundKeyEventSink = NULL; + This->forgroundTextService = GUID_NULL; + } + return S_OK; }
static HRESULT WINAPI KeystrokeMgr_GetForeground(ITfKeystrokeMgr *iface, CLSID *pclsid) { ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface); - FIXME("STUB:(%p)\n",This); - return E_NOTIMPL; + TRACE("(%p) %p\n",This,pclsid); + if (!pclsid) + return E_INVALIDARG; + + if (IsEqualCLSID(&This->forgroundTextService,&GUID_NULL)) + return S_FALSE; + + *pclsid = This->forgroundTextService; + return S_OK; }
static HRESULT WINAPI KeystrokeMgr_TestKeyDown(ITfKeystrokeMgr *iface,