txtsrv.c 12.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 * RichEdit - functions and interfaces around CreateTextServices
 *
 * Copyright 2005, 2006, Maarten Lankhorst
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * 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 22 23 24 25 26 27 28 29
 */

#include "config.h"
#include "wine/port.h"

#define NONAMELESSSTRUCT
#define NONAMELESSUNION
#define COBJMACROS

#include "editor.h"
#include "ole2.h"
30
#include "oleauto.h"
31 32 33 34 35 36 37 38 39
#include "richole.h"
#include "imm.h"
#include "textserv.h"
#include "wine/debug.h"
#include "editstr.h"

#ifdef __i386__  /* thiscall functions are i386-specific */

#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 44 45
                   "popl %eax\n\t" \
                   "pushl %ecx\n\t" \
                   "pushl %eax\n\t" \
46
                   "jmp " __ASM_NAME(#func) __ASM_STDCALL(args) )
47 48 49
#else /* __i386__ */

#define THISCALL(func) func
50
#define DEFINE_THISCALL_WRAPPER(func,args) /* nothing */
51 52 53 54 55 56

#endif /* __i386__ */

WINE_DEFAULT_DEBUG_CHANNEL(richedit);

typedef struct ITextServicesImpl {
57
   ITextServices ITextServices_iface;
58 59 60
   ITextHost *pMyHost;
   LONG ref;
   CRITICAL_SECTION csTxtSrv;
61
   ME_TextEditor *editor;
62
   char spare[256];
63 64 65 66 67 68 69 70 71 72 73 74
} ITextServicesImpl;

static const ITextServicesVtbl textservices_Vtbl;

/******************************************************************
 *        CreateTextServices (RICHED20.4)
 */
HRESULT WINAPI CreateTextServices(IUnknown  * pUnkOuter,
                                  ITextHost * pITextHost,
                                  IUnknown  **ppUnk)
{
   ITextServicesImpl *ITextImpl;
75
   HRESULT hres;
76 77 78 79 80 81 82 83
   TRACE("%p %p --> %p\n", pUnkOuter, pITextHost, ppUnk);
   if (pITextHost == NULL)
      return E_POINTER;

   ITextImpl = CoTaskMemAlloc(sizeof(*ITextImpl));
   if (ITextImpl == NULL)
      return E_OUTOFMEMORY;
   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->ITextServices_iface.lpVtbl = &textservices_Vtbl;
89
   ITextImpl->editor = ME_MakeEditor(pITextHost, FALSE);
90
   ITextImpl->editor->exStyleFlags = 0;
91 92 93 94 95
   ITextImpl->editor->rcFormat.left = 0;
   ITextImpl->editor->rcFormat.top = 0;
   ITextImpl->editor->rcFormat.right = 0;
   ITextImpl->editor->rcFormat.bottom = 0;

96
   ME_HandleMessage(ITextImpl->editor, WM_CREATE, 0, 0, TRUE, &hres);
97 98 99 100 101 102 103

   if (pUnkOuter)
   {
      FIXME("Support aggregation\n");
      return CLASS_E_NOAGGREGATION;
   }

104
   *ppUnk = (IUnknown *)&ITextImpl->ITextServices_iface;
105 106 107
   return S_OK;
}

108 109 110 111
static inline ITextServicesImpl *impl_from_ITextServices(ITextServices *iface)
{
   return CONTAINING_RECORD(iface, ITextServicesImpl, ITextServices_iface);
}
112

113
static HRESULT WINAPI fnTextSrv_QueryInterface(ITextServices *iface, REFIID riid, void **ppv)
114
{
115 116
   ITextServicesImpl *This = impl_from_ITextServices(iface);

117 118 119
   TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppv);
   *ppv = NULL;
   if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_ITextServices))
120
      *ppv = This;
121 122 123 124 125 126 127 128 129 130 131 132 133

   if (*ppv)
   {
      IUnknown_AddRef((IUnknown *)(*ppv));
      TRACE ("-- Interface = %p\n", *ppv);
      return S_OK;
   }
   FIXME("Unknown interface: %s\n", debugstr_guid(riid));
   return E_NOINTERFACE;
}

static ULONG WINAPI fnTextSrv_AddRef(ITextServices *iface)
{
134
   ITextServicesImpl *This = impl_from_ITextServices(iface);
135 136
   DWORD ref = InterlockedIncrement(&This->ref);

137
   TRACE("(%p/%p)->() AddRef from %d\n", This, iface, ref - 1);
138 139 140 141 142
   return ref;
}

static ULONG WINAPI fnTextSrv_Release(ITextServices *iface)
{
143
   ITextServicesImpl *This = impl_from_ITextServices(iface);
144 145
   DWORD ref = InterlockedDecrement(&This->ref);

146
   TRACE("(%p/%p)->() Release from %d\n", This, iface, ref + 1);
147 148 149 150

   if (!ref)
   {
      ITextHost_Release(This->pMyHost);
151
      This->csTxtSrv.DebugInfo->Spare[0] = 0;
152 153 154 155 156 157
      DeleteCriticalSection(&This->csTxtSrv);
      CoTaskMemFree(This);
   }
   return ref;
}

158
DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxSendMessage(ITextServices *iface, UINT msg, WPARAM wparam,
159
                                       LPARAM lparam, LRESULT *plresult)
160
{
161
   ITextServicesImpl *This = impl_from_ITextServices(iface);
162
   HRESULT hresult;
163
   LRESULT lresult;
164

165 166
   lresult = ME_HandleMessage(This->editor, msg, wparam, lparam, TRUE, &hresult);
   if (plresult) *plresult = lresult;
167
   return hresult;
168 169
}

170
DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxDraw(ITextServices *iface, DWORD dwDrawAspect, LONG lindex,
171 172 173
                                void *pvAspect, DVTARGETDEVICE *ptd, HDC hdcDraw, HDC hdcTargetDev,
                                LPCRECTL lprcBounds, LPCRECTL lprcWBounds, LPRECT lprcUpdate,
                                BOOL (CALLBACK * pfnContinue)(DWORD), DWORD dwContinue,
174 175
                                LONG lViewId)
{
176
   ITextServicesImpl *This = impl_from_ITextServices(iface);
177 178 179 180 181

   FIXME("%p: STUB\n", This);
   return E_NOTIMPL;
}

182
DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxGetHScroll(ITextServices *iface, LONG *plMin, LONG *plMax, LONG *plPos,
183
                                      LONG *plPage, BOOL *pfEnabled)
184
{
185
   ITextServicesImpl *This = impl_from_ITextServices(iface);
186

187 188 189 190 191 192
   *plMin = This->editor->horz_si.nMin;
   *plMax = This->editor->horz_si.nMax;
   *plPos = This->editor->horz_si.nPos;
   *plPage = This->editor->horz_si.nPage;
   *pfEnabled = (This->editor->styleFlags & WS_HSCROLL) != 0;
   return S_OK;
193 194
}

195
DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxGetVScroll(ITextServices *iface, LONG *plMin, LONG *plMax, LONG *plPos,
196
                                      LONG *plPage, BOOL *pfEnabled)
197
{
198
   ITextServicesImpl *This = impl_from_ITextServices(iface);
199

200 201 202 203 204 205
   *plMin = This->editor->vert_si.nMin;
   *plMax = This->editor->vert_si.nMax;
   *plPos = This->editor->vert_si.nPos;
   *plPage = This->editor->vert_si.nPage;
   *pfEnabled = (This->editor->styleFlags & WS_VSCROLL) != 0;
   return S_OK;
206 207
}

208
DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_OnTxSetCursor(ITextServices *iface, DWORD dwDrawAspect, LONG lindex,
209 210
                                       void *pvAspect, DVTARGETDEVICE *ptd, HDC hdcDraw,
                                       HDC hicTargetDev, LPCRECT lprcClient, INT x, INT y)
211
{
212
   ITextServicesImpl *This = impl_from_ITextServices(iface);
213 214 215 216 217

   FIXME("%p: STUB\n", This);
   return E_NOTIMPL;
}

218
DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxQueryHitPoint(ITextServices *iface, DWORD dwDrawAspect, LONG lindex,
219 220 221
                                         void *pvAspect, DVTARGETDEVICE *ptd, HDC hdcDraw,
                                         HDC hicTargetDev, LPCRECT lprcClient, INT x, INT y,
                                         DWORD *pHitResult)
222
{
223
   ITextServicesImpl *This = impl_from_ITextServices(iface);
224 225 226 227 228

   FIXME("%p: STUB\n", This);
   return E_NOTIMPL;
}

229
DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_OnTxInplaceActivate(ITextServices *iface, LPCRECT prcClient)
230
{
231
   ITextServicesImpl *This = impl_from_ITextServices(iface);
232 233 234 235 236

   FIXME("%p: STUB\n", This);
   return E_NOTIMPL;
}

237
DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_OnTxInplaceDeactivate(ITextServices *iface)
238
{
239
   ITextServicesImpl *This = impl_from_ITextServices(iface);
240 241 242 243 244

   FIXME("%p: STUB\n", This);
   return E_NOTIMPL;
}

245
DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_OnTxUIActivate(ITextServices *iface)
246
{
247
   ITextServicesImpl *This = impl_from_ITextServices(iface);
248 249 250 251 252

   FIXME("%p: STUB\n", This);
   return E_NOTIMPL;
}

253
DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_OnTxUIDeactivate(ITextServices *iface)
254
{
255
   ITextServicesImpl *This = impl_from_ITextServices(iface);
256 257 258 259 260

   FIXME("%p: STUB\n", This);
   return E_NOTIMPL;
}

261
DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxGetText(ITextServices *iface, BSTR *pbstrText)
262
{
263
   ITextServicesImpl *This = impl_from_ITextServices(iface);
264
   int length;
265

266 267 268
   length = ME_GetTextLength(This->editor);
   if (length)
   {
269
      ME_Cursor start;
270 271 272 273 274
      BSTR bstr;
      bstr = SysAllocStringByteLen(NULL, length * sizeof(WCHAR));
      if (bstr == NULL)
         return E_OUTOFMEMORY;

275 276
      ME_CursorFromCharOfs(This->editor, 0, &start);
      ME_GetTextW(This->editor, bstr, length, &start, INT_MAX, FALSE);
277 278 279 280 281 282
      *pbstrText = bstr;
   } else {
      *pbstrText = NULL;
   }

   return S_OK;
283 284
}

285
DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxSetText(ITextServices *iface, LPCWSTR pszText)
286
{
287
   ITextServicesImpl *This = impl_from_ITextServices(iface);
288
   ME_Cursor cursor;
289

290 291 292
   ME_SetCursorToStart(This->editor, &cursor);
   ME_InternalDeleteText(This->editor, &cursor,
                         ME_GetTextLength(This->editor), FALSE);
293 294 295 296 297 298
   ME_InsertTextFromCursor(This->editor, 0, pszText, -1,
                           This->editor->pBuffer->pDefaultStyle);
   ME_SetSelection(This->editor, 0, 0);
   This->editor->nModifyStep = 0;
   OleFlushClipboard();
   ME_EmptyUndoStack(This->editor);
299
   ME_UpdateRepaint(This->editor, FALSE);
300 301

   return S_OK;
302 303
}

304
DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxGetCurrentTargetX(ITextServices *iface, LONG *x)
305
{
306
   ITextServicesImpl *This = impl_from_ITextServices(iface);
307 308 309 310 311

   FIXME("%p: STUB\n", This);
   return E_NOTIMPL;
}

312
DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxGetBaseLinePos(ITextServices *iface, LONG *x)
313
{
314
   ITextServicesImpl *This = impl_from_ITextServices(iface);
315 316 317 318 319

   FIXME("%p: STUB\n", This);
   return E_NOTIMPL;
}

320
DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxGetNaturalSize(ITextServices *iface, DWORD dwAspect, HDC hdcDraw,
321 322
                                          HDC hicTargetDev, DVTARGETDEVICE *ptd, DWORD dwMode,
                                          const SIZEL *psizelExtent, LONG *pwidth, LONG *pheight)
323
{
324
   ITextServicesImpl *This = impl_from_ITextServices(iface);
325 326 327 328 329

   FIXME("%p: STUB\n", This);
   return E_NOTIMPL;
}

330
DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxGetDropTarget(ITextServices *iface, IDropTarget **ppDropTarget)
331
{
332
   ITextServicesImpl *This = impl_from_ITextServices(iface);
333 334 335 336 337

   FIXME("%p: STUB\n", This);
   return E_NOTIMPL;
}

338
DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_OnTxPropertyBitsChange(ITextServices *iface, DWORD dwMask, DWORD dwBits)
339
{
340
   ITextServicesImpl *This = impl_from_ITextServices(iface);
341 342 343 344 345

   FIXME("%p: STUB\n", This);
   return E_NOTIMPL;
}

346
DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxGetCachedSize(ITextServices *iface, DWORD *pdwWidth, DWORD *pdwHeight)
347
{
348
   ITextServicesImpl *This = impl_from_ITextServices(iface);
349 350 351 352 353

   FIXME("%p: STUB\n", This);
   return E_NOTIMPL;
}

354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSendMessage,20)
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxDraw,52)
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetHScroll,24)
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetVScroll,24)
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxSetCursor,40)
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxQueryHitPoint,44)
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxInplaceActivate,8)
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxInplaceDeactivate,4)
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIActivate,4)
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIDeactivate,4)
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetText,8)
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSetText,8)
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCurrentTargetX,8)
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetBaseLinePos,8)
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetNaturalSize,36)
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetDropTarget,8)
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxPropertyBitsChange,12)
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCachedSize,12)
372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396

static const ITextServicesVtbl textservices_Vtbl =
{
   fnTextSrv_QueryInterface,
   fnTextSrv_AddRef,
   fnTextSrv_Release,
   THISCALL(fnTextSrv_TxSendMessage),
   THISCALL(fnTextSrv_TxDraw),
   THISCALL(fnTextSrv_TxGetHScroll),
   THISCALL(fnTextSrv_TxGetVScroll),
   THISCALL(fnTextSrv_OnTxSetCursor),
   THISCALL(fnTextSrv_TxQueryHitPoint),
   THISCALL(fnTextSrv_OnTxInplaceActivate),
   THISCALL(fnTextSrv_OnTxInplaceDeactivate),
   THISCALL(fnTextSrv_OnTxUIActivate),
   THISCALL(fnTextSrv_OnTxUIDeactivate),
   THISCALL(fnTextSrv_TxGetText),
   THISCALL(fnTextSrv_TxSetText),
   THISCALL(fnTextSrv_TxGetCurrentTargetX),
   THISCALL(fnTextSrv_TxGetBaseLinePos),
   THISCALL(fnTextSrv_TxGetNaturalSize),
   THISCALL(fnTextSrv_TxGetDropTarget),
   THISCALL(fnTextSrv_OnTxPropertyBitsChange),
   THISCALL(fnTextSrv_TxGetCachedSize)
};