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