diff --git a/dlls/msctf/inputprocessor.c b/dlls/msctf/inputprocessor.c index 38e93688596..f5e5989c11b 100644 --- a/dlls/msctf/inputprocessor.c +++ b/dlls/msctf/inputprocessor.c @@ -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,23 @@ static const WCHAR szwEnabled[] = {'E','n','a','b','l','e','d',0}; 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; LONG refCount; LANGID currentLanguage; + + struct list LanguageProfileNotifySink; } InputProcessorProfiles; typedef struct tagProfilesEnumGuid { @@ -78,9 +92,30 @@ typedef struct tagEnumTfLanguageProfiles { 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); } @@ -122,6 +157,10 @@ static HRESULT WINAPI InputProcessorProfiles_QueryInterface(ITfInputProcessorPro { *ppvOut = This; } + else if (IsEqualIID(iid, &IID_ITfSource)) + { + *ppvOut = &This->SourceVtbl; + } if (*ppvOut) { @@ -536,6 +575,71 @@ static const ITfInputProcessorProfilesVtbl InputProcessorProfiles_InputProcessor 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) +{ + 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; + + FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid)); + return E_NOTIMPL; +} + +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,9 +651,12 @@ HRESULT InputProcessorProfiles_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut 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; return S_OK; diff --git a/dlls/msctf/msctf_internal.h b/dlls/msctf/msctf_internal.h index 0df88de853f..15950ed616c 100644 --- a/dlls/msctf/msctf_internal.h +++ b/dlls/msctf/msctf_internal.h @@ -24,6 +24,7 @@ #define COOKIE_MAGIC_TMSINK 0x0010 #define COOKIE_MAGIC_CONTEXTSINK 0x0020 #define COOKIE_MAGIC_GUIDATOM 0x0030 +#define COOKIE_MAGIC_IPPSINK 0x0040 extern DWORD tlsIndex; extern TfClientId processId;