1 /* 2 * ITfContext 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 #include "olectl.h" 34 35 #include "msctf.h" 36 #include "msctf_internal.h" 37 38 WINE_DEFAULT_DEBUG_CHANNEL(msctf); 39 40 typedef struct tagContext { 41 ITfContext ITfContext_iface; 42 ITfSource ITfSource_iface; 43 /* const ITfContextCompositionVtbl *ContextCompositionVtbl; */ 44 ITfContextOwnerCompositionServices ITfContextOwnerCompositionServices_iface; 45 /* const ITfContextOwnerServicesVtbl *ContextOwnerServicesVtbl; */ 46 ITfInsertAtSelection ITfInsertAtSelection_iface; 47 /* const ITfMouseTrackerVtbl *MouseTrackerVtbl; */ 48 /* const ITfQueryEmbeddedVtbl *QueryEmbeddedVtbl; */ 49 ITfSourceSingle ITfSourceSingle_iface; 50 ITextStoreACPSink ITextStoreACPSink_iface; 51 ITextStoreACPServices ITextStoreACPServices_iface; 52 LONG refCount; 53 BOOL connected; 54 55 /* Aggregation */ 56 ITfCompartmentMgr *CompartmentMgr; 57 58 TfClientId tidOwner; 59 TfEditCookie defaultCookie; 60 TS_STATUS documentStatus; 61 ITfDocumentMgr *manager; 62 63 ITextStoreACP *pITextStoreACP; 64 ITfContextOwnerCompositionSink *pITfContextOwnerCompositionSink; 65 66 ITfEditSession* currentEditSession; 67 68 /* kept as separate lists to reduce unnecessary iterations */ 69 struct list pContextKeyEventSink; 70 struct list pEditTransactionSink; 71 struct list pStatusSink; 72 struct list pTextEditSink; 73 struct list pTextLayoutSink; 74 75 } Context; 76 77 typedef struct tagEditCookie { 78 DWORD lockType; 79 Context *pOwningContext; 80 } EditCookie; 81 82 static inline Context *impl_from_ITfContext(ITfContext *iface) 83 { 84 return CONTAINING_RECORD(iface, Context, ITfContext_iface); 85 } 86 87 static inline Context *impl_from_ITfSource(ITfSource *iface) 88 { 89 return CONTAINING_RECORD(iface, Context, ITfSource_iface); 90 } 91 92 static inline Context *impl_from_ITfContextOwnerCompositionServices(ITfContextOwnerCompositionServices *iface) 93 { 94 return CONTAINING_RECORD(iface, Context, ITfContextOwnerCompositionServices_iface); 95 } 96 97 static inline Context *impl_from_ITfInsertAtSelection(ITfInsertAtSelection *iface) 98 { 99 return CONTAINING_RECORD(iface, Context, ITfInsertAtSelection_iface); 100 } 101 102 static inline Context *impl_from_ITfSourceSingle(ITfSourceSingle* iface) 103 { 104 return CONTAINING_RECORD(iface, Context, ITfSourceSingle_iface); 105 } 106 107 static inline Context *impl_from_ITextStoreACPSink(ITextStoreACPSink *iface) 108 { 109 return CONTAINING_RECORD(iface, Context, ITextStoreACPSink_iface); 110 } 111 112 static inline Context *impl_from_ITextStoreACPServices(ITextStoreACPServices *iface) 113 { 114 return CONTAINING_RECORD(iface, Context, ITextStoreACPServices_iface); 115 } 116 117 static void Context_Destructor(Context *This) 118 { 119 EditCookie *cookie; 120 TRACE("destroying %p\n", This); 121 122 if (This->pITextStoreACP) 123 ITextStoreACP_Release(This->pITextStoreACP); 124 125 if (This->pITfContextOwnerCompositionSink) 126 ITfContextOwnerCompositionSink_Release(This->pITfContextOwnerCompositionSink); 127 128 if (This->defaultCookie) 129 { 130 cookie = remove_Cookie(This->defaultCookie); 131 HeapFree(GetProcessHeap(),0,cookie); 132 This->defaultCookie = 0; 133 } 134 135 free_sinks(&This->pContextKeyEventSink); 136 free_sinks(&This->pEditTransactionSink); 137 free_sinks(&This->pStatusSink); 138 free_sinks(&This->pTextEditSink); 139 free_sinks(&This->pTextLayoutSink); 140 141 CompartmentMgr_Destructor(This->CompartmentMgr); 142 HeapFree(GetProcessHeap(),0,This); 143 } 144 145 static HRESULT WINAPI Context_QueryInterface(ITfContext *iface, REFIID iid, LPVOID *ppvOut) 146 { 147 Context *This = impl_from_ITfContext(iface); 148 *ppvOut = NULL; 149 150 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfContext)) 151 { 152 *ppvOut = &This->ITfContext_iface; 153 } 154 else if (IsEqualIID(iid, &IID_ITfSource)) 155 { 156 *ppvOut = &This->ITfSource_iface; 157 } 158 else if (IsEqualIID(iid, &IID_ITfContextOwnerCompositionServices)) 159 { 160 *ppvOut = &This->ITfContextOwnerCompositionServices_iface; 161 } 162 else if (IsEqualIID(iid, &IID_ITfInsertAtSelection)) 163 { 164 *ppvOut = &This->ITfInsertAtSelection_iface; 165 } 166 else if (IsEqualIID(iid, &IID_ITfCompartmentMgr)) 167 { 168 *ppvOut = This->CompartmentMgr; 169 } 170 else if (IsEqualIID(iid, &IID_ITfSourceSingle)) 171 { 172 *ppvOut = &This->ITfSourceSingle_iface; 173 } 174 175 if (*ppvOut) 176 { 177 ITfContext_AddRef(iface); 178 return S_OK; 179 } 180 181 WARN("unsupported interface: %s\n", debugstr_guid(iid)); 182 return E_NOINTERFACE; 183 } 184 185 static ULONG WINAPI Context_AddRef(ITfContext *iface) 186 { 187 Context *This = impl_from_ITfContext(iface); 188 return InterlockedIncrement(&This->refCount); 189 } 190 191 static ULONG WINAPI Context_Release(ITfContext *iface) 192 { 193 Context *This = impl_from_ITfContext(iface); 194 ULONG ret; 195 196 ret = InterlockedDecrement(&This->refCount); 197 if (ret == 0) 198 Context_Destructor(This); 199 return ret; 200 } 201 202 /***************************************************** 203 * ITfContext functions 204 *****************************************************/ 205 static HRESULT WINAPI Context_RequestEditSession (ITfContext *iface, 206 TfClientId tid, ITfEditSession *pes, DWORD dwFlags, 207 HRESULT *phrSession) 208 { 209 Context *This = impl_from_ITfContext(iface); 210 HRESULT hr; 211 DWORD dwLockFlags = 0x0; 212 213 TRACE("(%p) %i %p %x %p\n",This, tid, pes, dwFlags, phrSession); 214 215 if (!(dwFlags & TF_ES_READ) && !(dwFlags & TF_ES_READWRITE)) 216 { 217 *phrSession = E_FAIL; 218 return E_INVALIDARG; 219 } 220 221 if (!This->pITextStoreACP) 222 { 223 FIXME("No ITextStoreACP available\n"); 224 *phrSession = E_FAIL; 225 return E_FAIL; 226 } 227 228 if (!(dwFlags & TF_ES_ASYNC)) 229 dwLockFlags |= TS_LF_SYNC; 230 231 if ((dwFlags & TF_ES_READWRITE) == TF_ES_READWRITE) 232 dwLockFlags |= TS_LF_READWRITE; 233 else if (dwFlags & TF_ES_READ) 234 dwLockFlags |= TS_LF_READ; 235 236 if (!This->documentStatus.dwDynamicFlags) 237 ITextStoreACP_GetStatus(This->pITextStoreACP, &This->documentStatus); 238 239 if (((dwFlags & TF_ES_READWRITE) == TF_ES_READWRITE) && (This->documentStatus.dwDynamicFlags & TS_SD_READONLY)) 240 { 241 *phrSession = TS_E_READONLY; 242 return S_OK; 243 } 244 245 if (FAILED (ITfEditSession_QueryInterface(pes, &IID_ITfEditSession, (LPVOID*)&This->currentEditSession))) 246 { 247 *phrSession = E_FAIL; 248 return E_INVALIDARG; 249 } 250 251 hr = ITextStoreACP_RequestLock(This->pITextStoreACP, dwLockFlags, phrSession); 252 253 return hr; 254 } 255 256 static HRESULT WINAPI Context_InWriteSession (ITfContext *iface, 257 TfClientId tid, 258 BOOL *pfWriteSession) 259 { 260 Context *This = impl_from_ITfContext(iface); 261 FIXME("STUB:(%p)\n",This); 262 return E_NOTIMPL; 263 } 264 265 static HRESULT WINAPI Context_GetSelection (ITfContext *iface, 266 TfEditCookie ec, ULONG ulIndex, ULONG ulCount, 267 TF_SELECTION *pSelection, ULONG *pcFetched) 268 { 269 Context *This = impl_from_ITfContext(iface); 270 EditCookie *cookie; 271 ULONG count, i; 272 ULONG totalFetched = 0; 273 HRESULT hr = S_OK; 274 275 if (!pSelection || !pcFetched) 276 return E_INVALIDARG; 277 278 *pcFetched = 0; 279 280 if (!This->connected) 281 return TF_E_DISCONNECTED; 282 283 if (get_Cookie_magic(ec)!=COOKIE_MAGIC_EDITCOOKIE) 284 return TF_E_NOLOCK; 285 286 if (!This->pITextStoreACP) 287 { 288 FIXME("Context does not have a ITextStoreACP\n"); 289 return E_NOTIMPL; 290 } 291 292 cookie = get_Cookie_data(ec); 293 294 if (ulIndex == TF_DEFAULT_SELECTION) 295 count = 1; 296 else 297 count = ulCount; 298 299 for (i = 0; i < count; i++) 300 { 301 DWORD fetched; 302 TS_SELECTION_ACP acps; 303 304 hr = ITextStoreACP_GetSelection(This->pITextStoreACP, ulIndex + i, 305 1, &acps, &fetched); 306 307 if (hr == TS_E_NOLOCK) 308 return TF_E_NOLOCK; 309 else if (SUCCEEDED(hr)) 310 { 311 pSelection[totalFetched].style.ase = acps.style.ase; 312 pSelection[totalFetched].style.fInterimChar = acps.style.fInterimChar; 313 Range_Constructor(iface, This->pITextStoreACP, cookie->lockType, acps.acpStart, acps.acpEnd, &pSelection[totalFetched].range); 314 totalFetched ++; 315 } 316 else 317 break; 318 } 319 320 *pcFetched = totalFetched; 321 322 return hr; 323 } 324 325 static HRESULT WINAPI Context_SetSelection (ITfContext *iface, 326 TfEditCookie ec, ULONG ulCount, const TF_SELECTION *pSelection) 327 { 328 Context *This = impl_from_ITfContext(iface); 329 TS_SELECTION_ACP *acp; 330 ULONG i; 331 HRESULT hr; 332 333 TRACE("(%p) %i %i %p\n",This,ec,ulCount,pSelection); 334 335 if (!This->pITextStoreACP) 336 { 337 FIXME("Context does not have a ITextStoreACP\n"); 338 return E_NOTIMPL; 339 } 340 341 if (get_Cookie_magic(ec)!=COOKIE_MAGIC_EDITCOOKIE) 342 return TF_E_NOLOCK; 343 344 acp = HeapAlloc(GetProcessHeap(), 0, sizeof(TS_SELECTION_ACP) * ulCount); 345 if (!acp) 346 return E_OUTOFMEMORY; 347 348 for (i = 0; i < ulCount; i++) 349 if (FAILED(TF_SELECTION_to_TS_SELECTION_ACP(&pSelection[i], &acp[i]))) 350 { 351 TRACE("Selection Conversion Failed\n"); 352 HeapFree(GetProcessHeap(), 0 , acp); 353 return E_FAIL; 354 } 355 356 hr = ITextStoreACP_SetSelection(This->pITextStoreACP, ulCount, acp); 357 358 HeapFree(GetProcessHeap(), 0, acp); 359 360 return hr; 361 } 362 363 static HRESULT WINAPI Context_GetStart (ITfContext *iface, 364 TfEditCookie ec, ITfRange **ppStart) 365 { 366 Context *This = impl_from_ITfContext(iface); 367 EditCookie *cookie; 368 TRACE("(%p) %i %p\n",This,ec,ppStart); 369 370 if (!ppStart) 371 return E_INVALIDARG; 372 373 *ppStart = NULL; 374 375 if (!This->connected) 376 return TF_E_DISCONNECTED; 377 378 if (get_Cookie_magic(ec)!=COOKIE_MAGIC_EDITCOOKIE) 379 return TF_E_NOLOCK; 380 381 cookie = get_Cookie_data(ec); 382 return Range_Constructor(iface, This->pITextStoreACP, cookie->lockType, 0, 0, ppStart); 383 } 384 385 static HRESULT WINAPI Context_GetEnd (ITfContext *iface, 386 TfEditCookie ec, ITfRange **ppEnd) 387 { 388 Context *This = impl_from_ITfContext(iface); 389 EditCookie *cookie; 390 LONG end; 391 TRACE("(%p) %i %p\n",This,ec,ppEnd); 392 393 if (!ppEnd) 394 return E_INVALIDARG; 395 396 *ppEnd = NULL; 397 398 if (!This->connected) 399 return TF_E_DISCONNECTED; 400 401 if (get_Cookie_magic(ec)!=COOKIE_MAGIC_EDITCOOKIE) 402 return TF_E_NOLOCK; 403 404 if (!This->pITextStoreACP) 405 { 406 FIXME("Context does not have a ITextStoreACP\n"); 407 return E_NOTIMPL; 408 } 409 410 cookie = get_Cookie_data(ec); 411 ITextStoreACP_GetEndACP(This->pITextStoreACP,&end); 412 413 return Range_Constructor(iface, This->pITextStoreACP, cookie->lockType, end, end, ppEnd); 414 } 415 416 static HRESULT WINAPI Context_GetActiveView (ITfContext *iface, 417 ITfContextView **ppView) 418 { 419 Context *This = impl_from_ITfContext(iface); 420 FIXME("STUB:(%p)\n",This); 421 return E_NOTIMPL; 422 } 423 424 static HRESULT WINAPI Context_EnumViews (ITfContext *iface, 425 IEnumTfContextViews **ppEnum) 426 { 427 Context *This = impl_from_ITfContext(iface); 428 FIXME("STUB:(%p)\n",This); 429 return E_NOTIMPL; 430 } 431 432 static HRESULT WINAPI Context_GetStatus (ITfContext *iface, 433 TF_STATUS *pdcs) 434 { 435 Context *This = impl_from_ITfContext(iface); 436 TRACE("(%p) %p\n",This,pdcs); 437 438 if (!This->connected) 439 return TF_E_DISCONNECTED; 440 441 if (!pdcs) 442 return E_INVALIDARG; 443 444 if (!This->pITextStoreACP) 445 { 446 FIXME("Context does not have a ITextStoreACP\n"); 447 return E_NOTIMPL; 448 } 449 450 ITextStoreACP_GetStatus(This->pITextStoreACP, &This->documentStatus); 451 452 *pdcs = This->documentStatus; 453 454 return S_OK; 455 } 456 457 static HRESULT WINAPI Context_GetProperty (ITfContext *iface, 458 REFGUID guidProp, ITfProperty **ppProp) 459 { 460 Context *This = impl_from_ITfContext(iface); 461 FIXME("STUB:(%p)\n",This); 462 return E_NOTIMPL; 463 } 464 465 static HRESULT WINAPI Context_GetAppProperty (ITfContext *iface, 466 REFGUID guidProp, ITfReadOnlyProperty **ppProp) 467 { 468 Context *This = impl_from_ITfContext(iface); 469 FIXME("STUB:(%p)\n",This); 470 return E_NOTIMPL; 471 } 472 473 static HRESULT WINAPI Context_TrackProperties (ITfContext *iface, 474 const GUID **prgProp, ULONG cProp, const GUID **prgAppProp, 475 ULONG cAppProp, ITfReadOnlyProperty **ppProperty) 476 { 477 Context *This = impl_from_ITfContext(iface); 478 FIXME("STUB:(%p)\n",This); 479 return E_NOTIMPL; 480 } 481 482 static HRESULT WINAPI Context_EnumProperties (ITfContext *iface, 483 IEnumTfProperties **ppEnum) 484 { 485 Context *This = impl_from_ITfContext(iface); 486 FIXME("STUB:(%p)\n",This); 487 return E_NOTIMPL; 488 } 489 490 static HRESULT WINAPI Context_GetDocumentMgr (ITfContext *iface, 491 ITfDocumentMgr **ppDm) 492 { 493 Context *This = impl_from_ITfContext(iface); 494 TRACE("(%p) %p\n",This,ppDm); 495 496 if (!ppDm) 497 return E_INVALIDARG; 498 499 *ppDm = This->manager; 500 if (!This->manager) 501 return S_FALSE; 502 503 ITfDocumentMgr_AddRef(This->manager); 504 505 return S_OK; 506 } 507 508 static HRESULT WINAPI Context_CreateRangeBackup (ITfContext *iface, 509 TfEditCookie ec, ITfRange *pRange, ITfRangeBackup **ppBackup) 510 { 511 Context *This = impl_from_ITfContext(iface); 512 FIXME("STUB:(%p)\n",This); 513 return E_NOTIMPL; 514 } 515 516 static const ITfContextVtbl ContextVtbl = 517 { 518 Context_QueryInterface, 519 Context_AddRef, 520 Context_Release, 521 Context_RequestEditSession, 522 Context_InWriteSession, 523 Context_GetSelection, 524 Context_SetSelection, 525 Context_GetStart, 526 Context_GetEnd, 527 Context_GetActiveView, 528 Context_EnumViews, 529 Context_GetStatus, 530 Context_GetProperty, 531 Context_GetAppProperty, 532 Context_TrackProperties, 533 Context_EnumProperties, 534 Context_GetDocumentMgr, 535 Context_CreateRangeBackup 536 }; 537 538 /***************************************************** 539 * ITfSource functions 540 *****************************************************/ 541 static HRESULT WINAPI ContextSource_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut) 542 { 543 Context *This = impl_from_ITfSource(iface); 544 return ITfContext_QueryInterface(&This->ITfContext_iface, iid, ppvOut); 545 } 546 547 static ULONG WINAPI ContextSource_AddRef(ITfSource *iface) 548 { 549 Context *This = impl_from_ITfSource(iface); 550 return ITfContext_AddRef(&This->ITfContext_iface); 551 } 552 553 static ULONG WINAPI ContextSource_Release(ITfSource *iface) 554 { 555 Context *This = impl_from_ITfSource(iface); 556 return ITfContext_Release(&This->ITfContext_iface); 557 } 558 559 static HRESULT WINAPI ContextSource_AdviseSink(ITfSource *iface, 560 REFIID riid, IUnknown *punk, DWORD *pdwCookie) 561 { 562 Context *This = impl_from_ITfSource(iface); 563 564 TRACE("(%p) %s %p %p\n",This,debugstr_guid(riid),punk,pdwCookie); 565 566 if (!riid || !punk || !pdwCookie) 567 return E_INVALIDARG; 568 569 if (IsEqualIID(riid, &IID_ITfTextEditSink)) 570 return advise_sink(&This->pTextEditSink, &IID_ITfTextEditSink, COOKIE_MAGIC_CONTEXTSINK, punk, pdwCookie); 571 572 FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid)); 573 return E_NOTIMPL; 574 } 575 576 static HRESULT WINAPI ContextSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie) 577 { 578 Context *This = impl_from_ITfSource(iface); 579 580 TRACE("(%p) %x\n",This,pdwCookie); 581 582 if (get_Cookie_magic(pdwCookie)!=COOKIE_MAGIC_CONTEXTSINK) 583 return E_INVALIDARG; 584 585 return unadvise_sink(pdwCookie); 586 } 587 588 static const ITfSourceVtbl ContextSourceVtbl = 589 { 590 ContextSource_QueryInterface, 591 ContextSource_AddRef, 592 ContextSource_Release, 593 ContextSource_AdviseSink, 594 ContextSource_UnadviseSink 595 }; 596 597 /***************************************************** 598 * ITfContextOwnerCompositionServices functions 599 *****************************************************/ 600 static HRESULT WINAPI ContextOwnerCompositionServices_QueryInterface(ITfContextOwnerCompositionServices *iface, 601 REFIID iid, LPVOID *ppvOut) 602 { 603 Context *This = impl_from_ITfContextOwnerCompositionServices(iface); 604 return ITfContext_QueryInterface(&This->ITfContext_iface, iid, ppvOut); 605 } 606 607 static ULONG WINAPI ContextOwnerCompositionServices_AddRef(ITfContextOwnerCompositionServices *iface) 608 { 609 Context *This = impl_from_ITfContextOwnerCompositionServices(iface); 610 return ITfContext_AddRef(&This->ITfContext_iface); 611 } 612 613 static ULONG WINAPI ContextOwnerCompositionServices_Release(ITfContextOwnerCompositionServices *iface) 614 { 615 Context *This = impl_from_ITfContextOwnerCompositionServices(iface); 616 return ITfContext_Release(&This->ITfContext_iface); 617 } 618 619 static HRESULT WINAPI ContextOwnerCompositionServices_StartComposition(ITfContextOwnerCompositionServices *iface, 620 TfEditCookie ecWrite, ITfRange *pCompositionRange, ITfCompositionSink *pSink, ITfComposition **ppComposition) 621 { 622 Context *This = impl_from_ITfContextOwnerCompositionServices(iface); 623 FIXME("STUB:(%p) %#x %p %p %p\n", This, ecWrite, pCompositionRange, pSink, ppComposition); 624 return E_NOTIMPL; 625 } 626 627 static HRESULT WINAPI ContextOwnerCompositionServices_EnumCompositions(ITfContextOwnerCompositionServices *iface, 628 IEnumITfCompositionView **ppEnum) 629 { 630 Context *This = impl_from_ITfContextOwnerCompositionServices(iface); 631 FIXME("STUB:(%p) %p\n", This, ppEnum); 632 return E_NOTIMPL; 633 } 634 635 static HRESULT WINAPI ContextOwnerCompositionServices_FindComposition(ITfContextOwnerCompositionServices *iface, 636 TfEditCookie ecRead, ITfRange *pTestRange, IEnumITfCompositionView **ppEnum) 637 { 638 Context *This = impl_from_ITfContextOwnerCompositionServices(iface); 639 FIXME("STUB:(%p) %#x %p %p\n", This, ecRead, pTestRange, ppEnum); 640 return E_NOTIMPL; 641 } 642 643 static HRESULT WINAPI ContextOwnerCompositionServices_TakeOwnership(ITfContextOwnerCompositionServices *iface, 644 TfEditCookie ecWrite, ITfCompositionView *pComposition, ITfCompositionSink *pSink, ITfComposition **ppComposition) 645 { 646 Context *This = impl_from_ITfContextOwnerCompositionServices(iface); 647 FIXME("STUB:(%p) %#x %p %p %p\n", This, ecWrite, pComposition, pSink, ppComposition); 648 return E_NOTIMPL; 649 } 650 651 static HRESULT WINAPI ContextOwnerCompositionServices_TerminateComposition(ITfContextOwnerCompositionServices *iface, 652 ITfCompositionView *pComposition) 653 { 654 Context *This = impl_from_ITfContextOwnerCompositionServices(iface); 655 FIXME("STUB:(%p) %p\n", This, pComposition); 656 return E_NOTIMPL; 657 } 658 659 static const ITfContextOwnerCompositionServicesVtbl ContextOwnerCompositionServicesVtbl = 660 { 661 ContextOwnerCompositionServices_QueryInterface, 662 ContextOwnerCompositionServices_AddRef, 663 ContextOwnerCompositionServices_Release, 664 ContextOwnerCompositionServices_StartComposition, 665 ContextOwnerCompositionServices_EnumCompositions, 666 ContextOwnerCompositionServices_FindComposition, 667 ContextOwnerCompositionServices_TakeOwnership, 668 ContextOwnerCompositionServices_TerminateComposition 669 }; 670 671 /***************************************************** 672 * ITfInsertAtSelection functions 673 *****************************************************/ 674 static HRESULT WINAPI InsertAtSelection_QueryInterface(ITfInsertAtSelection *iface, REFIID iid, LPVOID *ppvOut) 675 { 676 Context *This = impl_from_ITfInsertAtSelection(iface); 677 return ITfContext_QueryInterface(&This->ITfContext_iface, iid, ppvOut); 678 } 679 680 static ULONG WINAPI InsertAtSelection_AddRef(ITfInsertAtSelection *iface) 681 { 682 Context *This = impl_from_ITfInsertAtSelection(iface); 683 return ITfContext_AddRef(&This->ITfContext_iface); 684 } 685 686 static ULONG WINAPI InsertAtSelection_Release(ITfInsertAtSelection *iface) 687 { 688 Context *This = impl_from_ITfInsertAtSelection(iface); 689 return ITfContext_Release(&This->ITfContext_iface); 690 } 691 692 static HRESULT WINAPI InsertAtSelection_InsertTextAtSelection( 693 ITfInsertAtSelection *iface, TfEditCookie ec, DWORD dwFlags, 694 const WCHAR *pchText, LONG cch, ITfRange **ppRange) 695 { 696 Context *This = impl_from_ITfInsertAtSelection(iface); 697 EditCookie *cookie; 698 LONG acpStart, acpEnd; 699 TS_TEXTCHANGE change; 700 HRESULT hr; 701 702 TRACE("(%p) %i %x %s %p\n",This, ec, dwFlags, debugstr_wn(pchText,cch), ppRange); 703 704 if (!This->connected) 705 return TF_E_DISCONNECTED; 706 707 if (get_Cookie_magic(ec)!=COOKIE_MAGIC_EDITCOOKIE) 708 return TF_E_NOLOCK; 709 710 cookie = get_Cookie_data(ec); 711 712 if ((cookie->lockType & TS_LF_READWRITE) != TS_LF_READWRITE ) 713 return TS_E_READONLY; 714 715 if (!This->pITextStoreACP) 716 { 717 FIXME("Context does not have a ITextStoreACP\n"); 718 return E_NOTIMPL; 719 } 720 721 hr = ITextStoreACP_InsertTextAtSelection(This->pITextStoreACP, dwFlags, pchText, cch, &acpStart, &acpEnd, &change); 722 if (SUCCEEDED(hr)) 723 Range_Constructor(&This->ITfContext_iface, This->pITextStoreACP, cookie->lockType, change.acpStart, change.acpNewEnd, ppRange); 724 725 return hr; 726 } 727 728 static HRESULT WINAPI InsertAtSelection_InsertEmbeddedAtSelection( 729 ITfInsertAtSelection *iface, TfEditCookie ec, DWORD dwFlags, 730 IDataObject *pDataObject, ITfRange **ppRange) 731 { 732 Context *This = impl_from_ITfInsertAtSelection(iface); 733 FIXME("STUB:(%p)\n",This); 734 return E_NOTIMPL; 735 } 736 737 static const ITfInsertAtSelectionVtbl InsertAtSelectionVtbl = 738 { 739 InsertAtSelection_QueryInterface, 740 InsertAtSelection_AddRef, 741 InsertAtSelection_Release, 742 InsertAtSelection_InsertTextAtSelection, 743 InsertAtSelection_InsertEmbeddedAtSelection, 744 }; 745 746 /***************************************************** 747 * ITfSourceSingle functions 748 *****************************************************/ 749 static HRESULT WINAPI SourceSingle_QueryInterface(ITfSourceSingle *iface, REFIID iid, LPVOID *ppvOut) 750 { 751 Context *This = impl_from_ITfSourceSingle(iface); 752 return ITfContext_QueryInterface(&This->ITfContext_iface, iid, ppvOut); 753 } 754 755 static ULONG WINAPI SourceSingle_AddRef(ITfSourceSingle *iface) 756 { 757 Context *This = impl_from_ITfSourceSingle(iface); 758 return ITfContext_AddRef(&This->ITfContext_iface); 759 } 760 761 static ULONG WINAPI SourceSingle_Release(ITfSourceSingle *iface) 762 { 763 Context *This = impl_from_ITfSourceSingle(iface); 764 return ITfContext_Release(&This->ITfContext_iface); 765 } 766 767 static HRESULT WINAPI SourceSingle_AdviseSingleSink( ITfSourceSingle *iface, 768 TfClientId tid, REFIID riid, IUnknown *punk) 769 { 770 Context *This = impl_from_ITfSourceSingle(iface); 771 FIXME("STUB:(%p) %i %s %p\n",This, tid, debugstr_guid(riid),punk); 772 return E_NOTIMPL; 773 } 774 775 static HRESULT WINAPI SourceSingle_UnadviseSingleSink( ITfSourceSingle *iface, 776 TfClientId tid, REFIID riid) 777 { 778 Context *This = impl_from_ITfSourceSingle(iface); 779 FIXME("STUB:(%p) %i %s\n",This, tid, debugstr_guid(riid)); 780 return E_NOTIMPL; 781 } 782 783 static const ITfSourceSingleVtbl ContextSourceSingleVtbl = 784 { 785 SourceSingle_QueryInterface, 786 SourceSingle_AddRef, 787 SourceSingle_Release, 788 SourceSingle_AdviseSingleSink, 789 SourceSingle_UnadviseSingleSink, 790 }; 791 792 /************************************************************************** 793 * ITextStoreACPSink 794 **************************************************************************/ 795 796 static HRESULT WINAPI TextStoreACPSink_QueryInterface(ITextStoreACPSink *iface, REFIID iid, LPVOID *ppvOut) 797 { 798 Context *This = impl_from_ITextStoreACPSink(iface); 799 800 *ppvOut = NULL; 801 802 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITextStoreACPSink)) 803 { 804 *ppvOut = &This->ITextStoreACPSink_iface; 805 } 806 else if (IsEqualIID(iid, &IID_ITextStoreACPServices)) 807 *ppvOut = &This->ITextStoreACPServices_iface; 808 809 if (*ppvOut) 810 { 811 ITextStoreACPSink_AddRef(iface); 812 return S_OK; 813 } 814 815 WARN("unsupported interface: %s\n", debugstr_guid(iid)); 816 return E_NOINTERFACE; 817 } 818 819 static ULONG WINAPI TextStoreACPSink_AddRef(ITextStoreACPSink *iface) 820 { 821 Context *This = impl_from_ITextStoreACPSink(iface); 822 return ITfContext_AddRef(&This->ITfContext_iface); 823 } 824 825 static ULONG WINAPI TextStoreACPSink_Release(ITextStoreACPSink *iface) 826 { 827 Context *This = impl_from_ITextStoreACPSink(iface); 828 return ITfContext_Release(&This->ITfContext_iface); 829 } 830 831 /***************************************************** 832 * ITextStoreACPSink functions 833 *****************************************************/ 834 835 static HRESULT WINAPI TextStoreACPSink_OnTextChange(ITextStoreACPSink *iface, 836 DWORD dwFlags, const TS_TEXTCHANGE *pChange) 837 { 838 Context *This = impl_from_ITextStoreACPSink(iface); 839 FIXME("STUB:(%p)\n",This); 840 return S_OK; 841 } 842 843 static HRESULT WINAPI TextStoreACPSink_OnSelectionChange(ITextStoreACPSink *iface) 844 { 845 Context *This = impl_from_ITextStoreACPSink(iface); 846 FIXME("STUB:(%p)\n",This); 847 return S_OK; 848 } 849 850 static HRESULT WINAPI TextStoreACPSink_OnLayoutChange(ITextStoreACPSink *iface, 851 TsLayoutCode lcode, TsViewCookie vcView) 852 { 853 Context *This = impl_from_ITextStoreACPSink(iface); 854 FIXME("STUB:(%p)\n",This); 855 return S_OK; 856 } 857 858 static HRESULT WINAPI TextStoreACPSink_OnStatusChange(ITextStoreACPSink *iface, 859 DWORD dwFlags) 860 { 861 Context *This = impl_from_ITextStoreACPSink(iface); 862 HRESULT hr, hrSession; 863 864 TRACE("(%p) %x\n",This, dwFlags); 865 866 if (!This->pITextStoreACP) 867 { 868 FIXME("Context does not have a ITextStoreACP\n"); 869 return E_NOTIMPL; 870 } 871 872 hr = ITextStoreACP_RequestLock(This->pITextStoreACP, TS_LF_READ, &hrSession); 873 874 if(SUCCEEDED(hr) && SUCCEEDED(hrSession)) 875 This->documentStatus.dwDynamicFlags = dwFlags; 876 877 return S_OK; 878 } 879 880 static HRESULT WINAPI TextStoreACPSink_OnAttrsChange(ITextStoreACPSink *iface, 881 LONG acpStart, LONG acpEnd, ULONG cAttrs, const TS_ATTRID *paAttrs) 882 { 883 Context *This = impl_from_ITextStoreACPSink(iface); 884 FIXME("STUB:(%p)\n",This); 885 return E_NOTIMPL; 886 } 887 888 static HRESULT WINAPI TextStoreACPSink_OnLockGranted(ITextStoreACPSink *iface, 889 DWORD dwLockFlags) 890 { 891 Context *This = impl_from_ITextStoreACPSink(iface); 892 HRESULT hr; 893 EditCookie *cookie,*sinkcookie; 894 TfEditCookie ec; 895 struct list *cursor; 896 897 TRACE("(%p) %x\n",This, dwLockFlags); 898 899 if (!This->currentEditSession) 900 { 901 FIXME("OnLockGranted called for something other than an EditSession\n"); 902 return S_OK; 903 } 904 905 cookie = HeapAlloc(GetProcessHeap(),0,sizeof(EditCookie)); 906 if (!cookie) 907 return E_OUTOFMEMORY; 908 909 sinkcookie = HeapAlloc(GetProcessHeap(),0,sizeof(EditCookie)); 910 if (!sinkcookie) 911 { 912 HeapFree(GetProcessHeap(), 0, cookie); 913 return E_OUTOFMEMORY; 914 } 915 916 cookie->lockType = dwLockFlags; 917 cookie->pOwningContext = This; 918 ec = generate_Cookie(COOKIE_MAGIC_EDITCOOKIE, cookie); 919 920 hr = ITfEditSession_DoEditSession(This->currentEditSession, ec); 921 922 if ((dwLockFlags&TS_LF_READWRITE) == TS_LF_READWRITE) 923 { 924 ITfTextEditSink *sink; 925 TfEditCookie sc; 926 927 sinkcookie->lockType = TS_LF_READ; 928 sinkcookie->pOwningContext = This; 929 sc = generate_Cookie(COOKIE_MAGIC_EDITCOOKIE, sinkcookie); 930 931 /*TODO: implement ITfEditRecord */ 932 SINK_FOR_EACH(cursor, &This->pTextEditSink, ITfTextEditSink, sink) 933 { 934 ITfTextEditSink_OnEndEdit(sink, &This->ITfContext_iface, sc, NULL); 935 } 936 sinkcookie = remove_Cookie(sc); 937 } 938 HeapFree(GetProcessHeap(),0,sinkcookie); 939 940 ITfEditSession_Release(This->currentEditSession); 941 This->currentEditSession = NULL; 942 943 /* Edit Cookie is only valid during the edit session */ 944 cookie = remove_Cookie(ec); 945 HeapFree(GetProcessHeap(),0,cookie); 946 947 return hr; 948 } 949 950 static HRESULT WINAPI TextStoreACPSink_OnStartEditTransaction(ITextStoreACPSink *iface) 951 { 952 Context *This = impl_from_ITextStoreACPSink(iface); 953 FIXME("STUB:(%p)\n",This); 954 return E_NOTIMPL; 955 } 956 957 static HRESULT WINAPI TextStoreACPSink_OnEndEditTransaction(ITextStoreACPSink *iface) 958 { 959 Context *This = impl_from_ITextStoreACPSink(iface); 960 FIXME("STUB:(%p)\n",This); 961 return E_NOTIMPL; 962 } 963 964 static const ITextStoreACPSinkVtbl TextStoreACPSinkVtbl = 965 { 966 TextStoreACPSink_QueryInterface, 967 TextStoreACPSink_AddRef, 968 TextStoreACPSink_Release, 969 TextStoreACPSink_OnTextChange, 970 TextStoreACPSink_OnSelectionChange, 971 TextStoreACPSink_OnLayoutChange, 972 TextStoreACPSink_OnStatusChange, 973 TextStoreACPSink_OnAttrsChange, 974 TextStoreACPSink_OnLockGranted, 975 TextStoreACPSink_OnStartEditTransaction, 976 TextStoreACPSink_OnEndEditTransaction 977 }; 978 979 static HRESULT WINAPI TextStoreACPServices_QueryInterface(ITextStoreACPServices *iface, REFIID riid, void **obj) 980 { 981 Context *This = impl_from_ITextStoreACPServices(iface); 982 return ITextStoreACPSink_QueryInterface(&This->ITextStoreACPSink_iface, riid, obj); 983 } 984 985 static ULONG WINAPI TextStoreACPServices_AddRef(ITextStoreACPServices *iface) 986 { 987 Context *This = impl_from_ITextStoreACPServices(iface); 988 return ITextStoreACPSink_AddRef(&This->ITextStoreACPSink_iface); 989 } 990 991 static ULONG WINAPI TextStoreACPServices_Release(ITextStoreACPServices *iface) 992 { 993 Context *This = impl_from_ITextStoreACPServices(iface); 994 return ITextStoreACPSink_Release(&This->ITextStoreACPSink_iface); 995 } 996 997 static HRESULT WINAPI TextStoreACPServices_Serialize(ITextStoreACPServices *iface, ITfProperty *prop, ITfRange *range, 998 TF_PERSISTENT_PROPERTY_HEADER_ACP *header, IStream *stream) 999 { 1000 Context *This = impl_from_ITextStoreACPServices(iface); 1001 1002 FIXME("stub: %p %p %p %p %p\n", This, prop, range, header, stream); 1003 1004 return E_NOTIMPL; 1005 } 1006 1007 static HRESULT WINAPI TextStoreACPServices_Unserialize(ITextStoreACPServices *iface, ITfProperty *prop, 1008 const TF_PERSISTENT_PROPERTY_HEADER_ACP *header, IStream *stream, ITfPersistentPropertyLoaderACP *loader) 1009 { 1010 Context *This = impl_from_ITextStoreACPServices(iface); 1011 1012 FIXME("stub: %p %p %p %p %p\n", This, prop, header, stream, loader); 1013 1014 return E_NOTIMPL; 1015 } 1016 1017 static HRESULT WINAPI TextStoreACPServices_ForceLoadProperty(ITextStoreACPServices *iface, ITfProperty *prop) 1018 { 1019 Context *This = impl_from_ITextStoreACPServices(iface); 1020 1021 FIXME("stub: %p %p\n", This, prop); 1022 1023 return E_NOTIMPL; 1024 } 1025 1026 static HRESULT WINAPI TextStoreACPServices_CreateRange(ITextStoreACPServices *iface, 1027 LONG start, LONG end, ITfRangeACP **range) 1028 { 1029 Context *This = impl_from_ITextStoreACPServices(iface); 1030 1031 FIXME("stub: %p %d %d %p\n", This, start, end, range); 1032 1033 return S_OK; 1034 } 1035 1036 static const ITextStoreACPServicesVtbl TextStoreACPServicesVtbl = 1037 { 1038 TextStoreACPServices_QueryInterface, 1039 TextStoreACPServices_AddRef, 1040 TextStoreACPServices_Release, 1041 TextStoreACPServices_Serialize, 1042 TextStoreACPServices_Unserialize, 1043 TextStoreACPServices_ForceLoadProperty, 1044 TextStoreACPServices_CreateRange 1045 }; 1046 1047 HRESULT Context_Constructor(TfClientId tidOwner, IUnknown *punk, ITfDocumentMgr *mgr, ITfContext **ppOut, TfEditCookie *pecTextStore) 1048 { 1049 Context *This; 1050 EditCookie *cookie; 1051 1052 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Context)); 1053 if (This == NULL) 1054 return E_OUTOFMEMORY; 1055 1056 cookie = HeapAlloc(GetProcessHeap(),0,sizeof(EditCookie)); 1057 if (cookie == NULL) 1058 { 1059 HeapFree(GetProcessHeap(),0,This); 1060 return E_OUTOFMEMORY; 1061 } 1062 1063 TRACE("(%p) %x %p %p %p\n",This, tidOwner, punk, ppOut, pecTextStore); 1064 1065 This->ITfContext_iface.lpVtbl= &ContextVtbl; 1066 This->ITfSource_iface.lpVtbl = &ContextSourceVtbl; 1067 This->ITfContextOwnerCompositionServices_iface.lpVtbl = &ContextOwnerCompositionServicesVtbl; 1068 This->ITfInsertAtSelection_iface.lpVtbl = &InsertAtSelectionVtbl; 1069 This->ITfSourceSingle_iface.lpVtbl = &ContextSourceSingleVtbl; 1070 This->ITextStoreACPSink_iface.lpVtbl = &TextStoreACPSinkVtbl; 1071 This->ITextStoreACPServices_iface.lpVtbl = &TextStoreACPServicesVtbl; 1072 This->refCount = 1; 1073 This->tidOwner = tidOwner; 1074 This->connected = FALSE; 1075 This->manager = mgr; 1076 1077 CompartmentMgr_Constructor((IUnknown*)&This->ITfContext_iface, &IID_IUnknown, (IUnknown**)&This->CompartmentMgr); 1078 1079 cookie->lockType = TF_ES_READ; 1080 cookie->pOwningContext = This; 1081 1082 if (punk) 1083 { 1084 IUnknown_QueryInterface(punk, &IID_ITextStoreACP, 1085 (LPVOID*)&This->pITextStoreACP); 1086 1087 IUnknown_QueryInterface(punk, &IID_ITfContextOwnerCompositionSink, 1088 (LPVOID*)&This->pITfContextOwnerCompositionSink); 1089 1090 if (!This->pITextStoreACP && !This->pITfContextOwnerCompositionSink) 1091 FIXME("Unhandled pUnk\n"); 1092 } 1093 1094 This->defaultCookie = generate_Cookie(COOKIE_MAGIC_EDITCOOKIE,cookie); 1095 *pecTextStore = This->defaultCookie; 1096 1097 list_init(&This->pContextKeyEventSink); 1098 list_init(&This->pEditTransactionSink); 1099 list_init(&This->pStatusSink); 1100 list_init(&This->pTextEditSink); 1101 list_init(&This->pTextLayoutSink); 1102 1103 *ppOut = &This->ITfContext_iface; 1104 TRACE("returning %p\n", *ppOut); 1105 1106 return S_OK; 1107 } 1108 1109 HRESULT Context_Initialize(ITfContext *iface, ITfDocumentMgr *manager) 1110 { 1111 Context *This = impl_from_ITfContext(iface); 1112 1113 if (This->pITextStoreACP) 1114 ITextStoreACP_AdviseSink(This->pITextStoreACP, &IID_ITextStoreACPSink, 1115 (IUnknown*)&This->ITextStoreACPSink_iface, TS_AS_ALL_SINKS); 1116 This->connected = TRUE; 1117 This->manager = manager; 1118 return S_OK; 1119 } 1120 1121 HRESULT Context_Uninitialize(ITfContext *iface) 1122 { 1123 Context *This = impl_from_ITfContext(iface); 1124 1125 if (This->pITextStoreACP) 1126 ITextStoreACP_UnadviseSink(This->pITextStoreACP, (IUnknown*)&This->ITextStoreACPSink_iface); 1127 This->connected = FALSE; 1128 This->manager = NULL; 1129 return S_OK; 1130 } 1131