1 /* 2 * RichEdit - functions and interfaces around CreateTextServices 3 * 4 * Copyright 2005, 2006, Maarten Lankhorst 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 #include "wine/port.h" 23 24 #define COBJMACROS 25 26 #include "editor.h" 27 #include "ole2.h" 28 #include "oleauto.h" 29 #include "richole.h" 30 #include "tom.h" 31 #include "imm.h" 32 #include "textserv.h" 33 #include "wine/debug.h" 34 #include "editstr.h" 35 36 #ifdef __i386__ /* thiscall functions are i386-specific */ 37 38 #define THISCALL(func) (void *) __thiscall_ ## func 39 #define DEFINE_THISCALL_WRAPPER(func,args) \ 40 extern HRESULT __thiscall_ ## func(void); \ 41 __ASM_GLOBAL_FUNC(__thiscall_ ## func, \ 42 "popl %eax\n\t" \ 43 "pushl %ecx\n\t" \ 44 "pushl %eax\n\t" \ 45 "jmp " __ASM_NAME(#func) __ASM_STDCALL(args) ) 46 #else /* __i386__ */ 47 48 #define THISCALL(func) func 49 #define DEFINE_THISCALL_WRAPPER(func,args) /* nothing */ 50 51 #endif /* __i386__ */ 52 53 WINE_DEFAULT_DEBUG_CHANNEL(richedit); 54 55 typedef struct ITextServicesImpl { 56 IUnknown IUnknown_inner; 57 ITextServices ITextServices_iface; 58 IUnknown *outer_unk; 59 LONG ref; 60 ITextHost *pMyHost; 61 CRITICAL_SECTION csTxtSrv; 62 ME_TextEditor *editor; 63 char spare[256]; 64 } ITextServicesImpl; 65 66 static inline ITextServicesImpl *impl_from_IUnknown(IUnknown *iface) 67 { 68 return CONTAINING_RECORD(iface, ITextServicesImpl, IUnknown_inner); 69 } 70 71 static HRESULT WINAPI ITextServicesImpl_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) 72 { 73 ITextServicesImpl *This = impl_from_IUnknown(iface); 74 75 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv); 76 77 if (IsEqualIID(riid, &IID_IUnknown)) 78 *ppv = &This->IUnknown_inner; 79 else if (IsEqualIID(riid, &IID_ITextServices)) 80 *ppv = &This->ITextServices_iface; 81 else if (IsEqualIID(riid, &IID_IRichEditOle) || IsEqualIID(riid, &IID_ITextDocument) || 82 IsEqualIID(riid, &IID_ITextDocument2Old)) { 83 if (!This->editor->reOle) 84 if (!CreateIRichEditOle(This->outer_unk, This->editor, (void **)(&This->editor->reOle))) 85 return E_OUTOFMEMORY; 86 if (IsEqualIID(riid, &IID_ITextDocument) || IsEqualIID(riid, &IID_ITextDocument2Old)) 87 ME_GetITextDocument2OldInterface(This->editor->reOle, ppv); 88 else 89 *ppv = This->editor->reOle; 90 } else { 91 *ppv = NULL; 92 FIXME("Unknown interface: %s\n", debugstr_guid(riid)); 93 return E_NOINTERFACE; 94 } 95 96 IUnknown_AddRef((IUnknown*)*ppv); 97 return S_OK; 98 } 99 100 static ULONG WINAPI ITextServicesImpl_AddRef(IUnknown *iface) 101 { 102 ITextServicesImpl *This = impl_from_IUnknown(iface); 103 LONG ref = InterlockedIncrement(&This->ref); 104 105 TRACE("(%p) ref=%d\n", This, ref); 106 107 return ref; 108 } 109 110 static ULONG WINAPI ITextServicesImpl_Release(IUnknown *iface) 111 { 112 ITextServicesImpl *This = impl_from_IUnknown(iface); 113 LONG ref = InterlockedDecrement(&This->ref); 114 115 TRACE("(%p) ref=%d\n", This, ref); 116 117 if (!ref) 118 { 119 ME_DestroyEditor(This->editor); 120 This->csTxtSrv.DebugInfo->Spare[0] = 0; 121 DeleteCriticalSection(&This->csTxtSrv); 122 CoTaskMemFree(This); 123 } 124 return ref; 125 } 126 127 static const IUnknownVtbl textservices_inner_vtbl = 128 { 129 ITextServicesImpl_QueryInterface, 130 ITextServicesImpl_AddRef, 131 ITextServicesImpl_Release 132 }; 133 134 static inline ITextServicesImpl *impl_from_ITextServices(ITextServices *iface) 135 { 136 return CONTAINING_RECORD(iface, ITextServicesImpl, ITextServices_iface); 137 } 138 139 static HRESULT WINAPI fnTextSrv_QueryInterface(ITextServices *iface, REFIID riid, void **ppv) 140 { 141 ITextServicesImpl *This = impl_from_ITextServices(iface); 142 return IUnknown_QueryInterface(This->outer_unk, riid, ppv); 143 } 144 145 static ULONG WINAPI fnTextSrv_AddRef(ITextServices *iface) 146 { 147 ITextServicesImpl *This = impl_from_ITextServices(iface); 148 return IUnknown_AddRef(This->outer_unk); 149 } 150 151 static ULONG WINAPI fnTextSrv_Release(ITextServices *iface) 152 { 153 ITextServicesImpl *This = impl_from_ITextServices(iface); 154 return IUnknown_Release(This->outer_unk); 155 } 156 157 DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxSendMessage(ITextServices *iface, UINT msg, WPARAM wparam, 158 LPARAM lparam, LRESULT *plresult) 159 { 160 ITextServicesImpl *This = impl_from_ITextServices(iface); 161 HRESULT hresult; 162 LRESULT lresult; 163 164 lresult = ME_HandleMessage(This->editor, msg, wparam, lparam, TRUE, &hresult); 165 if (plresult) *plresult = lresult; 166 return hresult; 167 } 168 169 DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxDraw(ITextServices *iface, DWORD dwDrawAspect, LONG lindex, 170 void *pvAspect, DVTARGETDEVICE *ptd, HDC hdcDraw, HDC hdcTargetDev, 171 LPCRECTL lprcBounds, LPCRECTL lprcWBounds, LPRECT lprcUpdate, 172 BOOL (CALLBACK * pfnContinue)(DWORD), DWORD dwContinue, 173 LONG lViewId) 174 { 175 ITextServicesImpl *This = impl_from_ITextServices(iface); 176 177 FIXME("%p: STUB\n", This); 178 return E_NOTIMPL; 179 } 180 181 DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxGetHScroll(ITextServices *iface, LONG *plMin, LONG *plMax, LONG *plPos, 182 LONG *plPage, BOOL *pfEnabled) 183 { 184 ITextServicesImpl *This = impl_from_ITextServices(iface); 185 186 if (plMin) 187 *plMin = This->editor->horz_si.nMin; 188 if (plMax) 189 *plMax = This->editor->horz_si.nMax; 190 if (plPos) 191 *plPos = This->editor->horz_si.nPos; 192 if (plPage) 193 *plPage = This->editor->horz_si.nPage; 194 if (pfEnabled) 195 *pfEnabled = (This->editor->styleFlags & WS_HSCROLL) != 0; 196 return S_OK; 197 } 198 199 DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxGetVScroll(ITextServices *iface, LONG *plMin, LONG *plMax, LONG *plPos, 200 LONG *plPage, BOOL *pfEnabled) 201 { 202 ITextServicesImpl *This = impl_from_ITextServices(iface); 203 204 if (plMin) 205 *plMin = This->editor->vert_si.nMin; 206 if (plMax) 207 *plMax = This->editor->vert_si.nMax; 208 if (plPos) 209 *plPos = This->editor->vert_si.nPos; 210 if (plPage) 211 *plPage = This->editor->vert_si.nPage; 212 if (pfEnabled) 213 *pfEnabled = (This->editor->styleFlags & WS_VSCROLL) != 0; 214 return S_OK; 215 } 216 217 DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_OnTxSetCursor(ITextServices *iface, DWORD dwDrawAspect, LONG lindex, 218 void *pvAspect, DVTARGETDEVICE *ptd, HDC hdcDraw, 219 HDC hicTargetDev, LPCRECT lprcClient, INT x, INT y) 220 { 221 ITextServicesImpl *This = impl_from_ITextServices(iface); 222 223 FIXME("%p: STUB\n", This); 224 return E_NOTIMPL; 225 } 226 227 DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxQueryHitPoint(ITextServices *iface, DWORD dwDrawAspect, LONG lindex, 228 void *pvAspect, DVTARGETDEVICE *ptd, HDC hdcDraw, 229 HDC hicTargetDev, LPCRECT lprcClient, INT x, INT y, 230 DWORD *pHitResult) 231 { 232 ITextServicesImpl *This = impl_from_ITextServices(iface); 233 234 FIXME("%p: STUB\n", This); 235 return E_NOTIMPL; 236 } 237 238 DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_OnTxInplaceActivate(ITextServices *iface, LPCRECT prcClient) 239 { 240 ITextServicesImpl *This = impl_from_ITextServices(iface); 241 242 FIXME("%p: STUB\n", This); 243 return E_NOTIMPL; 244 } 245 246 DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_OnTxInplaceDeactivate(ITextServices *iface) 247 { 248 ITextServicesImpl *This = impl_from_ITextServices(iface); 249 250 FIXME("%p: STUB\n", This); 251 return E_NOTIMPL; 252 } 253 254 DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_OnTxUIActivate(ITextServices *iface) 255 { 256 ITextServicesImpl *This = impl_from_ITextServices(iface); 257 258 FIXME("%p: STUB\n", This); 259 return E_NOTIMPL; 260 } 261 262 DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_OnTxUIDeactivate(ITextServices *iface) 263 { 264 ITextServicesImpl *This = impl_from_ITextServices(iface); 265 266 FIXME("%p: STUB\n", This); 267 return E_NOTIMPL; 268 } 269 270 DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxGetText(ITextServices *iface, BSTR *pbstrText) 271 { 272 ITextServicesImpl *This = impl_from_ITextServices(iface); 273 int length; 274 275 length = ME_GetTextLength(This->editor); 276 if (length) 277 { 278 ME_Cursor start; 279 BSTR bstr; 280 bstr = SysAllocStringByteLen(NULL, length * sizeof(WCHAR)); 281 if (bstr == NULL) 282 return E_OUTOFMEMORY; 283 284 ME_CursorFromCharOfs(This->editor, 0, &start); 285 ME_GetTextW(This->editor, bstr, length, &start, INT_MAX, FALSE, FALSE); 286 *pbstrText = bstr; 287 } else { 288 *pbstrText = NULL; 289 } 290 291 return S_OK; 292 } 293 294 DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxSetText(ITextServices *iface, LPCWSTR pszText) 295 { 296 ITextServicesImpl *This = impl_from_ITextServices(iface); 297 ME_Cursor cursor; 298 299 ME_SetCursorToStart(This->editor, &cursor); 300 ME_InternalDeleteText(This->editor, &cursor, ME_GetTextLength(This->editor), FALSE); 301 if(pszText) 302 ME_InsertTextFromCursor(This->editor, 0, pszText, -1, This->editor->pBuffer->pDefaultStyle); 303 ME_SetSelection(This->editor, 0, 0); 304 This->editor->nModifyStep = 0; 305 OleFlushClipboard(); 306 ME_EmptyUndoStack(This->editor); 307 ME_UpdateRepaint(This->editor, FALSE); 308 309 return S_OK; 310 } 311 312 DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxGetCurTargetX(ITextServices *iface, LONG *x) 313 { 314 ITextServicesImpl *This = impl_from_ITextServices(iface); 315 316 FIXME("%p: STUB\n", This); 317 return E_NOTIMPL; 318 } 319 320 DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxGetBaseLinePos(ITextServices *iface, LONG *x) 321 { 322 ITextServicesImpl *This = impl_from_ITextServices(iface); 323 324 FIXME("%p: STUB\n", This); 325 return E_NOTIMPL; 326 } 327 328 DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxGetNaturalSize(ITextServices *iface, DWORD dwAspect, HDC hdcDraw, 329 HDC hicTargetDev, DVTARGETDEVICE *ptd, DWORD dwMode, 330 const SIZEL *psizelExtent, LONG *pwidth, LONG *pheight) 331 { 332 ITextServicesImpl *This = impl_from_ITextServices(iface); 333 334 FIXME("%p: STUB\n", This); 335 return E_NOTIMPL; 336 } 337 338 DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxGetDropTarget(ITextServices *iface, IDropTarget **ppDropTarget) 339 { 340 ITextServicesImpl *This = impl_from_ITextServices(iface); 341 342 FIXME("%p: STUB\n", This); 343 return E_NOTIMPL; 344 } 345 346 DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_OnTxPropertyBitsChange(ITextServices *iface, DWORD dwMask, DWORD dwBits) 347 { 348 ITextServicesImpl *This = impl_from_ITextServices(iface); 349 350 FIXME("%p: STUB\n", This); 351 return E_NOTIMPL; 352 } 353 354 DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxGetCachedSize(ITextServices *iface, DWORD *pdwWidth, DWORD *pdwHeight) 355 { 356 ITextServicesImpl *This = impl_from_ITextServices(iface); 357 358 FIXME("%p: STUB\n", This); 359 return E_NOTIMPL; 360 } 361 362 DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSendMessage,20) 363 DEFINE_THISCALL_WRAPPER(fnTextSrv_TxDraw,52) 364 DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetHScroll,24) 365 DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetVScroll,24) 366 DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxSetCursor,40) 367 DEFINE_THISCALL_WRAPPER(fnTextSrv_TxQueryHitPoint,44) 368 DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxInplaceActivate,8) 369 DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxInplaceDeactivate,4) 370 DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIActivate,4) 371 DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIDeactivate,4) 372 DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetText,8) 373 DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSetText,8) 374 DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCurTargetX,8) 375 DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetBaseLinePos,8) 376 DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetNaturalSize,36) 377 DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetDropTarget,8) 378 DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxPropertyBitsChange,12) 379 DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCachedSize,12) 380 381 static const ITextServicesVtbl textservices_vtbl = 382 { 383 fnTextSrv_QueryInterface, 384 fnTextSrv_AddRef, 385 fnTextSrv_Release, 386 THISCALL(fnTextSrv_TxSendMessage), 387 THISCALL(fnTextSrv_TxDraw), 388 THISCALL(fnTextSrv_TxGetHScroll), 389 THISCALL(fnTextSrv_TxGetVScroll), 390 THISCALL(fnTextSrv_OnTxSetCursor), 391 THISCALL(fnTextSrv_TxQueryHitPoint), 392 THISCALL(fnTextSrv_OnTxInplaceActivate), 393 THISCALL(fnTextSrv_OnTxInplaceDeactivate), 394 THISCALL(fnTextSrv_OnTxUIActivate), 395 THISCALL(fnTextSrv_OnTxUIDeactivate), 396 THISCALL(fnTextSrv_TxGetText), 397 THISCALL(fnTextSrv_TxSetText), 398 THISCALL(fnTextSrv_TxGetCurTargetX), 399 THISCALL(fnTextSrv_TxGetBaseLinePos), 400 THISCALL(fnTextSrv_TxGetNaturalSize), 401 THISCALL(fnTextSrv_TxGetDropTarget), 402 THISCALL(fnTextSrv_OnTxPropertyBitsChange), 403 THISCALL(fnTextSrv_TxGetCachedSize) 404 }; 405 406 /****************************************************************** 407 * CreateTextServices (RICHED20.4) 408 */ 409 HRESULT WINAPI CreateTextServices(IUnknown *pUnkOuter, ITextHost *pITextHost, IUnknown **ppUnk) 410 { 411 ITextServicesImpl *ITextImpl; 412 413 TRACE("%p %p --> %p\n", pUnkOuter, pITextHost, ppUnk); 414 if (pITextHost == NULL) 415 return E_POINTER; 416 417 ITextImpl = CoTaskMemAlloc(sizeof(*ITextImpl)); 418 if (ITextImpl == NULL) 419 return E_OUTOFMEMORY; 420 InitializeCriticalSection(&ITextImpl->csTxtSrv); 421 ITextImpl->csTxtSrv.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ITextServicesImpl.csTxtSrv"); 422 ITextImpl->ref = 1; 423 ITextHost_AddRef(pITextHost); 424 ITextImpl->pMyHost = pITextHost; 425 ITextImpl->IUnknown_inner.lpVtbl = &textservices_inner_vtbl; 426 ITextImpl->ITextServices_iface.lpVtbl = &textservices_vtbl; 427 ITextImpl->editor = ME_MakeEditor(pITextHost, FALSE); 428 429 if (pUnkOuter) 430 ITextImpl->outer_unk = pUnkOuter; 431 else 432 ITextImpl->outer_unk = &ITextImpl->IUnknown_inner; 433 434 *ppUnk = &ITextImpl->IUnknown_inner; 435 return S_OK; 436 } 437