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