[RICHED20]
[reactos.git] / reactos / dll / win32 / riched20 / txtsrv.c
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 "editor.h"
22
23 #ifdef __i386__ /* thiscall functions are i386-specific */
24
25 #define THISCALL(func) __thiscall_ ## func
26 #define DEFINE_THISCALL_WRAPPER(func,args) \
27 extern typeof(func) THISCALL(func); \
28 __ASM_STDCALL_FUNC(__thiscall_ ## func, args, \
29 "popl %eax\n\t" \
30 "pushl %ecx\n\t" \
31 "pushl %eax\n\t" \
32 "jmp " __ASM_NAME(#func) __ASM_STDCALL(args) )
33 #else /* __i386__ */
34
35 #define THISCALL(func) func
36 #define DEFINE_THISCALL_WRAPPER(func,args) /* nothing */
37
38 #endif /* __i386__ */
39
40 WINE_DEFAULT_DEBUG_CHANNEL(richedit);
41
42 typedef struct ITextServicesImpl {
43 IUnknown IUnknown_inner;
44 ITextServices ITextServices_iface;
45 IUnknown *outer_unk;
46 LONG ref;
47 ITextHost *pMyHost;
48 CRITICAL_SECTION csTxtSrv;
49 ME_TextEditor *editor;
50 char spare[256];
51 } ITextServicesImpl;
52
53 static inline ITextServicesImpl *impl_from_IUnknown(IUnknown *iface)
54 {
55 return CONTAINING_RECORD(iface, ITextServicesImpl, IUnknown_inner);
56 }
57
58 static HRESULT WINAPI ITextServicesImpl_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
59 {
60 ITextServicesImpl *This = impl_from_IUnknown(iface);
61
62 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
63
64 if (IsEqualIID(riid, &IID_IUnknown))
65 *ppv = &This->IUnknown_inner;
66 else if (IsEqualIID(riid, &IID_ITextServices))
67 *ppv = &This->ITextServices_iface;
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 ITextHost_Release(This->pMyHost);
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 *plMin = This->editor->horz_si.nMin;
165 *plMax = This->editor->horz_si.nMax;
166 *plPos = This->editor->horz_si.nPos;
167 *plPage = This->editor->horz_si.nPage;
168 *pfEnabled = (This->editor->styleFlags & WS_HSCROLL) != 0;
169 return S_OK;
170 }
171
172 DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxGetVScroll(ITextServices *iface, LONG *plMin, LONG *plMax, LONG *plPos,
173 LONG *plPage, BOOL *pfEnabled)
174 {
175 ITextServicesImpl *This = impl_from_ITextServices(iface);
176
177 *plMin = This->editor->vert_si.nMin;
178 *plMax = This->editor->vert_si.nMax;
179 *plPos = This->editor->vert_si.nPos;
180 *plPage = This->editor->vert_si.nPage;
181 *pfEnabled = (This->editor->styleFlags & WS_VSCROLL) != 0;
182 return S_OK;
183 }
184
185 DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_OnTxSetCursor(ITextServices *iface, DWORD dwDrawAspect, LONG lindex,
186 void *pvAspect, DVTARGETDEVICE *ptd, HDC hdcDraw,
187 HDC hicTargetDev, LPCRECT lprcClient, INT x, INT y)
188 {
189 ITextServicesImpl *This = impl_from_ITextServices(iface);
190
191 FIXME("%p: STUB\n", This);
192 return E_NOTIMPL;
193 }
194
195 DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxQueryHitPoint(ITextServices *iface, DWORD dwDrawAspect, LONG lindex,
196 void *pvAspect, DVTARGETDEVICE *ptd, HDC hdcDraw,
197 HDC hicTargetDev, LPCRECT lprcClient, INT x, INT y,
198 DWORD *pHitResult)
199 {
200 ITextServicesImpl *This = impl_from_ITextServices(iface);
201
202 FIXME("%p: STUB\n", This);
203 return E_NOTIMPL;
204 }
205
206 DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_OnTxInplaceActivate(ITextServices *iface, LPCRECT prcClient)
207 {
208 ITextServicesImpl *This = impl_from_ITextServices(iface);
209
210 FIXME("%p: STUB\n", This);
211 return E_NOTIMPL;
212 }
213
214 DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_OnTxInplaceDeactivate(ITextServices *iface)
215 {
216 ITextServicesImpl *This = impl_from_ITextServices(iface);
217
218 FIXME("%p: STUB\n", This);
219 return E_NOTIMPL;
220 }
221
222 DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_OnTxUIActivate(ITextServices *iface)
223 {
224 ITextServicesImpl *This = impl_from_ITextServices(iface);
225
226 FIXME("%p: STUB\n", This);
227 return E_NOTIMPL;
228 }
229
230 DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_OnTxUIDeactivate(ITextServices *iface)
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_TxGetText(ITextServices *iface, BSTR *pbstrText)
239 {
240 ITextServicesImpl *This = impl_from_ITextServices(iface);
241 int length;
242
243 length = ME_GetTextLength(This->editor);
244 if (length)
245 {
246 ME_Cursor start;
247 BSTR bstr;
248 bstr = SysAllocStringByteLen(NULL, length * sizeof(WCHAR));
249 if (bstr == NULL)
250 return E_OUTOFMEMORY;
251
252 ME_CursorFromCharOfs(This->editor, 0, &start);
253 ME_GetTextW(This->editor, bstr, length, &start, INT_MAX, FALSE, FALSE);
254 *pbstrText = bstr;
255 } else {
256 *pbstrText = NULL;
257 }
258
259 return S_OK;
260 }
261
262 DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxSetText(ITextServices *iface, LPCWSTR pszText)
263 {
264 ITextServicesImpl *This = impl_from_ITextServices(iface);
265 ME_Cursor cursor;
266
267 ME_SetCursorToStart(This->editor, &cursor);
268 ME_InternalDeleteText(This->editor, &cursor,
269 ME_GetTextLength(This->editor), FALSE);
270 ME_InsertTextFromCursor(This->editor, 0, pszText, -1,
271 This->editor->pBuffer->pDefaultStyle);
272 ME_SetSelection(This->editor, 0, 0);
273 This->editor->nModifyStep = 0;
274 OleFlushClipboard();
275 ME_EmptyUndoStack(This->editor);
276 ME_UpdateRepaint(This->editor, FALSE);
277
278 return S_OK;
279 }
280
281 DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxGetCurTargetX(ITextServices *iface, LONG *x)
282 {
283 ITextServicesImpl *This = impl_from_ITextServices(iface);
284
285 FIXME("%p: STUB\n", This);
286 return E_NOTIMPL;
287 }
288
289 DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxGetBaseLinePos(ITextServices *iface, LONG *x)
290 {
291 ITextServicesImpl *This = impl_from_ITextServices(iface);
292
293 FIXME("%p: STUB\n", This);
294 return E_NOTIMPL;
295 }
296
297 DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxGetNaturalSize(ITextServices *iface, DWORD dwAspect, HDC hdcDraw,
298 HDC hicTargetDev, DVTARGETDEVICE *ptd, DWORD dwMode,
299 const SIZEL *psizelExtent, LONG *pwidth, LONG *pheight)
300 {
301 ITextServicesImpl *This = impl_from_ITextServices(iface);
302
303 FIXME("%p: STUB\n", This);
304 return E_NOTIMPL;
305 }
306
307 DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxGetDropTarget(ITextServices *iface, IDropTarget **ppDropTarget)
308 {
309 ITextServicesImpl *This = impl_from_ITextServices(iface);
310
311 FIXME("%p: STUB\n", This);
312 return E_NOTIMPL;
313 }
314
315 DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_OnTxPropertyBitsChange(ITextServices *iface, DWORD dwMask, DWORD dwBits)
316 {
317 ITextServicesImpl *This = impl_from_ITextServices(iface);
318
319 FIXME("%p: STUB\n", This);
320 return E_NOTIMPL;
321 }
322
323 DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxGetCachedSize(ITextServices *iface, DWORD *pdwWidth, DWORD *pdwHeight)
324 {
325 ITextServicesImpl *This = impl_from_ITextServices(iface);
326
327 FIXME("%p: STUB\n", This);
328 return E_NOTIMPL;
329 }
330
331 DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSendMessage,20)
332 DEFINE_THISCALL_WRAPPER(fnTextSrv_TxDraw,52)
333 DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetHScroll,24)
334 DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetVScroll,24)
335 DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxSetCursor,40)
336 DEFINE_THISCALL_WRAPPER(fnTextSrv_TxQueryHitPoint,44)
337 DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxInplaceActivate,8)
338 DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxInplaceDeactivate,4)
339 DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIActivate,4)
340 DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIDeactivate,4)
341 DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetText,8)
342 DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSetText,8)
343 DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCurTargetX,8)
344 DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetBaseLinePos,8)
345 DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetNaturalSize,36)
346 DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetDropTarget,8)
347 DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxPropertyBitsChange,12)
348 DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCachedSize,12)
349
350 static const ITextServicesVtbl textservices_vtbl =
351 {
352 fnTextSrv_QueryInterface,
353 fnTextSrv_AddRef,
354 fnTextSrv_Release,
355 THISCALL(fnTextSrv_TxSendMessage),
356 THISCALL(fnTextSrv_TxDraw),
357 THISCALL(fnTextSrv_TxGetHScroll),
358 THISCALL(fnTextSrv_TxGetVScroll),
359 THISCALL(fnTextSrv_OnTxSetCursor),
360 THISCALL(fnTextSrv_TxQueryHitPoint),
361 THISCALL(fnTextSrv_OnTxInplaceActivate),
362 THISCALL(fnTextSrv_OnTxInplaceDeactivate),
363 THISCALL(fnTextSrv_OnTxUIActivate),
364 THISCALL(fnTextSrv_OnTxUIDeactivate),
365 THISCALL(fnTextSrv_TxGetText),
366 THISCALL(fnTextSrv_TxSetText),
367 THISCALL(fnTextSrv_TxGetCurTargetX),
368 THISCALL(fnTextSrv_TxGetBaseLinePos),
369 THISCALL(fnTextSrv_TxGetNaturalSize),
370 THISCALL(fnTextSrv_TxGetDropTarget),
371 THISCALL(fnTextSrv_OnTxPropertyBitsChange),
372 THISCALL(fnTextSrv_TxGetCachedSize)
373 };
374
375 /******************************************************************
376 * CreateTextServices (RICHED20.4)
377 */
378 HRESULT WINAPI CreateTextServices(IUnknown *pUnkOuter, ITextHost *pITextHost, IUnknown **ppUnk)
379 {
380 ITextServicesImpl *ITextImpl;
381 HRESULT hres;
382 TRACE("%p %p --> %p\n", pUnkOuter, pITextHost, ppUnk);
383 if (pITextHost == NULL)
384 return E_POINTER;
385
386 ITextImpl = CoTaskMemAlloc(sizeof(*ITextImpl));
387 if (ITextImpl == NULL)
388 return E_OUTOFMEMORY;
389 InitializeCriticalSection(&ITextImpl->csTxtSrv);
390 ITextImpl->csTxtSrv.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ITextServicesImpl.csTxtSrv");
391 ITextImpl->ref = 1;
392 ITextHost_AddRef(pITextHost);
393 ITextImpl->pMyHost = pITextHost;
394 ITextImpl->IUnknown_inner.lpVtbl = &textservices_inner_vtbl;
395 ITextImpl->ITextServices_iface.lpVtbl = &textservices_vtbl;
396 ITextImpl->editor = ME_MakeEditor(pITextHost, FALSE);
397 ITextImpl->editor->exStyleFlags = 0;
398 ITextImpl->editor->rcFormat.left = 0;
399 ITextImpl->editor->rcFormat.top = 0;
400 ITextImpl->editor->rcFormat.right = 0;
401 ITextImpl->editor->rcFormat.bottom = 0;
402
403 ME_HandleMessage(ITextImpl->editor, WM_CREATE, 0, 0, TRUE, &hres);
404
405 if (pUnkOuter)
406 ITextImpl->outer_unk = pUnkOuter;
407 else
408 ITextImpl->outer_unk = &ITextImpl->IUnknown_inner;
409
410 *ppUnk = &ITextImpl->IUnknown_inner;
411 return S_OK;
412 }