1 /* 2 * ITfRange implementation 3 * 4 * Copyright 2009 Aric Stewart, CodeWeavers 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include <stdarg.h> 22 23 #define COBJMACROS 24 25 #include "wine/debug.h" 26 #include "windef.h" 27 #include "winbase.h" 28 #include "winreg.h" 29 #include "winuser.h" 30 #include "shlwapi.h" 31 #include "winerror.h" 32 #include "objbase.h" 33 34 #include "msctf.h" 35 #include "msctf_internal.h" 36 37 WINE_DEFAULT_DEBUG_CHANNEL(msctf); 38 39 typedef struct tagRange { 40 ITfRange ITfRange_iface; 41 /* const ITfRangeACPVtb *RangeACPVtbl; */ 42 LONG refCount; 43 44 ITextStoreACP *pITextStoreACP; 45 ITfContext *pITfContext; 46 47 DWORD lockType; 48 TfGravity gravityStart, gravityEnd; 49 DWORD anchorStart, anchorEnd; 50 51 } Range; 52 53 static inline Range *impl_from_ITfRange(ITfRange *iface) 54 { 55 return CONTAINING_RECORD(iface, Range, ITfRange_iface); 56 } 57 58 static void Range_Destructor(Range *This) 59 { 60 TRACE("destroying %p\n", This); 61 HeapFree(GetProcessHeap(),0,This); 62 } 63 64 static HRESULT WINAPI Range_QueryInterface(ITfRange *iface, REFIID iid, LPVOID *ppvOut) 65 { 66 Range *This = impl_from_ITfRange(iface); 67 *ppvOut = NULL; 68 69 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfRange)) 70 { 71 *ppvOut = &This->ITfRange_iface; 72 } 73 74 if (*ppvOut) 75 { 76 ITfRange_AddRef(iface); 77 return S_OK; 78 } 79 80 WARN("unsupported interface: %s\n", debugstr_guid(iid)); 81 return E_NOINTERFACE; 82 } 83 84 static ULONG WINAPI Range_AddRef(ITfRange *iface) 85 { 86 Range *This = impl_from_ITfRange(iface); 87 return InterlockedIncrement(&This->refCount); 88 } 89 90 static ULONG WINAPI Range_Release(ITfRange *iface) 91 { 92 Range *This = impl_from_ITfRange(iface); 93 ULONG ret; 94 95 ret = InterlockedDecrement(&This->refCount); 96 if (ret == 0) 97 Range_Destructor(This); 98 return ret; 99 } 100 101 /***************************************************** 102 * ITfRange functions 103 *****************************************************/ 104 105 static HRESULT WINAPI Range_GetText(ITfRange *iface, TfEditCookie ec, 106 DWORD dwFlags, WCHAR *pchText, ULONG cchMax, ULONG *pcch) 107 { 108 Range *This = impl_from_ITfRange(iface); 109 FIXME("STUB:(%p)\n",This); 110 return E_NOTIMPL; 111 } 112 113 static HRESULT WINAPI Range_SetText(ITfRange *iface, TfEditCookie ec, 114 DWORD dwFlags, const WCHAR *pchText, LONG cch) 115 { 116 Range *This = impl_from_ITfRange(iface); 117 FIXME("STUB:(%p)\n",This); 118 return E_NOTIMPL; 119 } 120 121 static HRESULT WINAPI Range_GetFormattedText(ITfRange *iface, TfEditCookie ec, 122 IDataObject **ppDataObject) 123 { 124 Range *This = impl_from_ITfRange(iface); 125 FIXME("STUB:(%p)\n",This); 126 return E_NOTIMPL; 127 } 128 129 static HRESULT WINAPI Range_GetEmbedded(ITfRange *iface, TfEditCookie ec, 130 REFGUID rguidService, REFIID riid, IUnknown **ppunk) 131 { 132 Range *This = impl_from_ITfRange(iface); 133 FIXME("STUB:(%p)\n",This); 134 return E_NOTIMPL; 135 } 136 137 static HRESULT WINAPI Range_InsertEmbedded(ITfRange *iface, TfEditCookie ec, 138 DWORD dwFlags, IDataObject *pDataObject) 139 { 140 Range *This = impl_from_ITfRange(iface); 141 FIXME("STUB:(%p)\n",This); 142 return E_NOTIMPL; 143 } 144 145 static HRESULT WINAPI Range_ShiftStart(ITfRange *iface, TfEditCookie ec, 146 LONG cchReq, LONG *pcch, const TF_HALTCOND *pHalt) 147 { 148 Range *This = impl_from_ITfRange(iface); 149 FIXME("STUB:(%p)\n",This); 150 return E_NOTIMPL; 151 } 152 153 static HRESULT WINAPI Range_ShiftEnd(ITfRange *iface, TfEditCookie ec, 154 LONG cchReq, LONG *pcch, const TF_HALTCOND *pHalt) 155 { 156 Range *This = impl_from_ITfRange(iface); 157 FIXME("STUB:(%p)\n",This); 158 return E_NOTIMPL; 159 } 160 161 static HRESULT WINAPI Range_ShiftStartToRange(ITfRange *iface, TfEditCookie ec, 162 ITfRange *pRange, TfAnchor aPos) 163 { 164 Range *This = impl_from_ITfRange(iface); 165 FIXME("STUB:(%p)\n",This); 166 return E_NOTIMPL; 167 } 168 169 static HRESULT WINAPI Range_ShiftEndToRange(ITfRange *iface, TfEditCookie ec, 170 ITfRange *pRange, TfAnchor aPos) 171 { 172 Range *This = impl_from_ITfRange(iface); 173 FIXME("STUB:(%p)\n",This); 174 return E_NOTIMPL; 175 } 176 177 static HRESULT WINAPI Range_ShiftStartRegion(ITfRange *iface, TfEditCookie ec, 178 TfShiftDir dir, BOOL *pfNoRegion) 179 { 180 Range *This = impl_from_ITfRange(iface); 181 FIXME("STUB:(%p)\n",This); 182 return E_NOTIMPL; 183 } 184 185 static HRESULT WINAPI Range_ShiftEndRegion(ITfRange *iface, TfEditCookie ec, 186 TfShiftDir dir, BOOL *pfNoRegion) 187 { 188 Range *This = impl_from_ITfRange(iface); 189 FIXME("STUB:(%p)\n",This); 190 return E_NOTIMPL; 191 } 192 193 static HRESULT WINAPI Range_IsEmpty(ITfRange *iface, TfEditCookie ec, 194 BOOL *pfEmpty) 195 { 196 Range *This = impl_from_ITfRange(iface); 197 FIXME("STUB:(%p)\n",This); 198 return E_NOTIMPL; 199 } 200 201 static HRESULT WINAPI Range_Collapse(ITfRange *iface, TfEditCookie ec, 202 TfAnchor aPos) 203 { 204 Range *This = impl_from_ITfRange(iface); 205 TRACE("(%p) %i %i\n",This,ec,aPos); 206 207 switch (aPos) 208 { 209 case TF_ANCHOR_START: 210 This->anchorEnd = This->anchorStart; 211 break; 212 case TF_ANCHOR_END: 213 This->anchorStart = This->anchorEnd; 214 break; 215 default: 216 return E_INVALIDARG; 217 } 218 219 return S_OK; 220 } 221 222 static HRESULT WINAPI Range_IsEqualStart(ITfRange *iface, TfEditCookie ec, 223 ITfRange *pWith, TfAnchor aPos, BOOL *pfEqual) 224 { 225 Range *This = impl_from_ITfRange(iface); 226 FIXME("STUB:(%p)\n",This); 227 return E_NOTIMPL; 228 } 229 230 static HRESULT WINAPI Range_IsEqualEnd(ITfRange *iface, TfEditCookie ec, 231 ITfRange *pWith, TfAnchor aPos, BOOL *pfEqual) 232 { 233 Range *This = impl_from_ITfRange(iface); 234 FIXME("STUB:(%p)\n",This); 235 return E_NOTIMPL; 236 } 237 238 static HRESULT WINAPI Range_CompareStart(ITfRange *iface, TfEditCookie ec, 239 ITfRange *pWith, TfAnchor aPos, LONG *plResult) 240 { 241 Range *This = impl_from_ITfRange(iface); 242 FIXME("STUB:(%p)\n",This); 243 return E_NOTIMPL; 244 } 245 246 static HRESULT WINAPI Range_CompareEnd(ITfRange *iface, TfEditCookie ec, 247 ITfRange *pWith, TfAnchor aPos, LONG *plResult) 248 { 249 Range *This = impl_from_ITfRange(iface); 250 FIXME("STUB:(%p)\n",This); 251 return E_NOTIMPL; 252 } 253 254 static HRESULT WINAPI Range_AdjustForInsert(ITfRange *iface, TfEditCookie ec, 255 ULONG cchInsert, BOOL *pfInsertOk) 256 { 257 Range *This = impl_from_ITfRange(iface); 258 FIXME("STUB:(%p)\n",This); 259 return E_NOTIMPL; 260 } 261 262 static HRESULT WINAPI Range_GetGravity(ITfRange *iface, 263 TfGravity *pgStart, TfGravity *pgEnd) 264 { 265 Range *This = impl_from_ITfRange(iface); 266 FIXME("STUB:(%p)\n",This); 267 return E_NOTIMPL; 268 } 269 270 static HRESULT WINAPI Range_SetGravity(ITfRange *iface, TfEditCookie ec, 271 TfGravity gStart, TfGravity gEnd) 272 { 273 Range *This = impl_from_ITfRange(iface); 274 FIXME("STUB:(%p)\n",This); 275 return E_NOTIMPL; 276 } 277 278 static HRESULT WINAPI Range_Clone(ITfRange *iface, ITfRange **ppClone) 279 { 280 Range *This = impl_from_ITfRange(iface); 281 FIXME("STUB:(%p)\n",This); 282 return E_NOTIMPL; 283 } 284 285 static HRESULT WINAPI Range_GetContext(ITfRange *iface, ITfContext **ppContext) 286 { 287 Range *This = impl_from_ITfRange(iface); 288 TRACE("(%p)\n",This); 289 if (!ppContext) 290 return E_INVALIDARG; 291 *ppContext = This->pITfContext; 292 return S_OK; 293 } 294 295 static const ITfRangeVtbl Range_RangeVtbl = 296 { 297 Range_QueryInterface, 298 Range_AddRef, 299 Range_Release, 300 301 Range_GetText, 302 Range_SetText, 303 Range_GetFormattedText, 304 Range_GetEmbedded, 305 Range_InsertEmbedded, 306 Range_ShiftStart, 307 Range_ShiftEnd, 308 Range_ShiftStartToRange, 309 Range_ShiftEndToRange, 310 Range_ShiftStartRegion, 311 Range_ShiftEndRegion, 312 Range_IsEmpty, 313 Range_Collapse, 314 Range_IsEqualStart, 315 Range_IsEqualEnd, 316 Range_CompareStart, 317 Range_CompareEnd, 318 Range_AdjustForInsert, 319 Range_GetGravity, 320 Range_SetGravity, 321 Range_Clone, 322 Range_GetContext 323 }; 324 325 HRESULT Range_Constructor(ITfContext *context, ITextStoreACP *textstore, DWORD lockType, DWORD anchorStart, DWORD anchorEnd, ITfRange **ppOut) 326 { 327 Range *This; 328 329 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Range)); 330 if (This == NULL) 331 return E_OUTOFMEMORY; 332 333 TRACE("(%p) %p %p\n",This, context, textstore); 334 335 This->ITfRange_iface.lpVtbl = &Range_RangeVtbl; 336 This->refCount = 1; 337 This->pITfContext = context; 338 This->pITextStoreACP = textstore; 339 This->lockType = lockType; 340 This->anchorStart = anchorStart; 341 This->anchorEnd = anchorEnd; 342 343 *ppOut = &This->ITfRange_iface; 344 TRACE("returning %p\n", *ppOut); 345 346 return S_OK; 347 } 348 349 /* Internal conversion functions */ 350 351 HRESULT TF_SELECTION_to_TS_SELECTION_ACP(const TF_SELECTION *tf, TS_SELECTION_ACP *tsAcp) 352 { 353 Range *This; 354 355 if (!tf || !tsAcp || !tf->range) 356 return E_INVALIDARG; 357 358 This = impl_from_ITfRange(tf->range); 359 360 tsAcp->acpStart = This->anchorStart; 361 tsAcp->acpEnd = This->anchorEnd; 362 tsAcp->style.ase = tf->style.ase; 363 tsAcp->style.fInterimChar = tf->style.fInterimChar; 364 return S_OK; 365 } 366