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