sane.ds: Danish translation.
[wine] / dlls / riched20 / richole.c
1 /*
2  * RichEdit GUIDs and OLE interface
3  *
4  * Copyright 2004 by Krzysztof Foltman
5  * Copyright 2004 Aric Stewart
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <stdarg.h>
23
24 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
26 #define COBJMACROS
27
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wingdi.h"
31 #include "winuser.h"
32 #include "ole2.h"
33 #include "richole.h"
34 #include "editor.h"
35 #include "tom.h"
36 #include "wine/debug.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(richedit);
39
40 /* there is no way to be consistent across different sets of headers - mingw, Wine, Win32 SDK*/
41
42 /* FIXME: the next 6 lines should be in textserv.h */
43 #include "initguid.h"
44 #define TEXTSERV_GUID(name, l, w1, w2, b1, b2) \
45     DEFINE_GUID(name, l, w1, w2, b1, b2, 0x00, 0xaa, 0x00, 0x6c, 0xad, 0xc5)
46
47 TEXTSERV_GUID(IID_ITextServices, 0x8d33f740, 0xcf58, 0x11ce, 0xa8, 0x9d);
48 TEXTSERV_GUID(IID_ITextHost, 0xc5bdd8d0, 0xd26e, 0x11ce, 0xa8, 0x9e);
49 TEXTSERV_GUID(IID_ITextHost2, 0xc5bdd8d0, 0xd26e, 0x11ce, 0xa8, 0x9e);
50 DEFINE_GUID(IID_ITextDocument, 0x8cc497c0, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xaa, 0x00, 0x47, 0xbe, 0x5d);
51
52 typedef struct IRichEditOleImpl {
53     const IRichEditOleVtbl *lpRichEditOleVtbl;
54     const ITextDocumentVtbl *lpTextDocumentVtbl;
55     LONG ref;
56
57     ME_TextEditor *editor;
58 } IRichEditOleImpl;
59
60 static inline IRichEditOleImpl *impl_from_IRichEditOle(IRichEditOle *iface)
61 {
62     return (IRichEditOleImpl *)((BYTE*)iface - FIELD_OFFSET(IRichEditOleImpl, lpRichEditOleVtbl));
63 }
64
65 static inline IRichEditOleImpl *impl_from_ITextDocument(ITextDocument *iface)
66 {
67     return (IRichEditOleImpl *)((BYTE*)iface - FIELD_OFFSET(IRichEditOleImpl, lpTextDocumentVtbl));
68 }
69
70 static HRESULT WINAPI
71 IRichEditOle_fnQueryInterface(IRichEditOle *me, REFIID riid, LPVOID *ppvObj)
72 {
73     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
74
75     TRACE("%p %s\n", This, debugstr_guid(riid) );
76
77     *ppvObj = NULL;
78     if (IsEqualGUID(riid, &IID_IUnknown) ||
79         IsEqualGUID(riid, &IID_IRichEditOle))
80         *ppvObj = &This->lpRichEditOleVtbl;
81     else if (IsEqualGUID(riid, &IID_ITextDocument))
82         *ppvObj = &This->lpTextDocumentVtbl;
83     if (*ppvObj)
84     {
85         IRichEditOle_AddRef(me);
86         return S_OK;
87     }
88     FIXME("%p: unhandled interface %s\n", This, debugstr_guid(riid) );
89  
90     return E_NOINTERFACE;   
91 }
92
93 static ULONG WINAPI
94 IRichEditOle_fnAddRef(IRichEditOle *me)
95 {
96     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
97     ULONG ref = InterlockedIncrement( &This->ref );
98
99     TRACE("%p ref = %u\n", This, ref);
100
101     return ref;
102 }
103
104 static ULONG WINAPI
105 IRichEditOle_fnRelease(IRichEditOle *me)
106 {
107     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
108     ULONG ref = InterlockedDecrement(&This->ref);
109
110     TRACE ("%p ref=%u\n", This, ref);
111
112     if (!ref)
113     {
114         TRACE ("Destroying %p\n", This);
115         heap_free(This);
116     }
117     return ref;
118 }
119
120 static HRESULT WINAPI
121 IRichEditOle_fnActivateAs(IRichEditOle *me, REFCLSID rclsid, REFCLSID rclsidAs)
122 {
123     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
124     FIXME("stub %p\n",This);
125     return E_NOTIMPL;
126 }
127
128 static HRESULT WINAPI
129 IRichEditOle_fnContextSensitiveHelp(IRichEditOle *me, BOOL fEnterMode)
130 {
131     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
132     FIXME("stub %p\n",This);
133     return E_NOTIMPL;
134 }
135
136 static HRESULT WINAPI
137 IRichEditOle_fnConvertObject(IRichEditOle *me, LONG iob,
138                REFCLSID rclsidNew, LPCSTR lpstrUserTypeNew)
139 {
140     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
141     FIXME("stub %p\n",This);
142     return E_NOTIMPL;
143 }
144
145 static HRESULT WINAPI
146 IRichEditOle_fnGetClientSite(IRichEditOle *me,
147                LPOLECLIENTSITE *lplpolesite)
148 {
149     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
150     FIXME("stub %p\n",This);
151     return E_NOTIMPL;
152 }
153
154 static HRESULT WINAPI
155 IRichEditOle_fnGetClipboardData(IRichEditOle *me, CHARRANGE *lpchrg,
156                DWORD reco, LPDATAOBJECT *lplpdataobj)
157 {
158     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
159     CHARRANGE tmpchrg;
160
161     TRACE("(%p,%p,%d)\n",This, lpchrg, reco);
162     if(!lplpdataobj)
163         return E_INVALIDARG;
164     if(!lpchrg) {
165         ME_GetSelection(This->editor, &tmpchrg.cpMin, &tmpchrg.cpMax);
166         lpchrg = &tmpchrg;
167     }
168     return ME_GetDataObject(This->editor, lpchrg, lplpdataobj);
169 }
170
171 static LONG WINAPI IRichEditOle_fnGetLinkCount(IRichEditOle *me)
172 {
173     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
174     FIXME("stub %p\n",This);
175     return E_NOTIMPL;
176 }
177
178 static HRESULT WINAPI
179 IRichEditOle_fnGetObject(IRichEditOle *me, LONG iob,
180                REOBJECT *lpreobject, DWORD dwFlags)
181 {
182     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
183     FIXME("stub %p\n",This);
184     return E_NOTIMPL;
185 }
186
187 static LONG WINAPI
188 IRichEditOle_fnGetObjectCount(IRichEditOle *me)
189 {
190     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
191     FIXME("stub %p\n",This);
192     return E_NOTIMPL;
193 }
194
195 static HRESULT WINAPI
196 IRichEditOle_fnHandsOffStorage(IRichEditOle *me, LONG iob)
197 {
198     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
199     FIXME("stub %p\n",This);
200     return E_NOTIMPL;
201 }
202
203 static HRESULT WINAPI
204 IRichEditOle_fnImportDataObject(IRichEditOle *me, LPDATAOBJECT lpdataobj,
205                CLIPFORMAT cf, HGLOBAL hMetaPict)
206 {
207     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
208     FIXME("stub %p\n",This);
209     return E_NOTIMPL;
210 }
211
212 static HRESULT WINAPI
213 IRichEditOle_fnInPlaceDeactivate(IRichEditOle *me)
214 {
215     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
216     FIXME("stub %p\n",This);
217     return E_NOTIMPL;
218 }
219
220 static HRESULT WINAPI
221 IRichEditOle_fnInsertObject(IRichEditOle *me, REOBJECT *reo)
222 {
223     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
224     TRACE("(%p,%p)\n", This, reo);
225
226     if (reo->cbStruct < sizeof(*reo)) return STG_E_INVALIDPARAMETER;
227     if (reo->poleobj)   IOleObject_AddRef(reo->poleobj);
228     if (reo->pstg)      IStorage_AddRef(reo->pstg);
229     if (reo->polesite)  IOleClientSite_AddRef(reo->polesite);
230
231     ME_InsertOLEFromCursor(This->editor, reo, 0);
232     return S_OK;
233 }
234
235 static HRESULT WINAPI IRichEditOle_fnSaveCompleted(IRichEditOle *me, LONG iob,
236                LPSTORAGE lpstg)
237 {
238     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
239     FIXME("stub %p\n",This);
240     return E_NOTIMPL;
241 }
242
243 static HRESULT WINAPI
244 IRichEditOle_fnSetDvaspect(IRichEditOle *me, LONG iob, DWORD dvaspect)
245 {
246     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
247     FIXME("stub %p\n",This);
248     return E_NOTIMPL;
249 }
250
251 static HRESULT WINAPI IRichEditOle_fnSetHostNames(IRichEditOle *me,
252                LPCSTR lpstrContainerApp, LPCSTR lpstrContainerObj)
253 {
254     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
255     FIXME("stub %p %s %s\n",This, lpstrContainerApp, lpstrContainerObj);
256     return E_NOTIMPL;
257 }
258
259 static HRESULT WINAPI
260 IRichEditOle_fnSetLinkAvailable(IRichEditOle *me, LONG iob, BOOL fAvailable)
261 {
262     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
263     FIXME("stub %p\n",This);
264     return E_NOTIMPL;
265 }
266
267 static const IRichEditOleVtbl revt = {
268     IRichEditOle_fnQueryInterface,
269     IRichEditOle_fnAddRef,
270     IRichEditOle_fnRelease,
271     IRichEditOle_fnGetClientSite,
272     IRichEditOle_fnGetObjectCount,
273     IRichEditOle_fnGetLinkCount,
274     IRichEditOle_fnGetObject,
275     IRichEditOle_fnInsertObject,
276     IRichEditOle_fnConvertObject,
277     IRichEditOle_fnActivateAs,
278     IRichEditOle_fnSetHostNames,
279     IRichEditOle_fnSetLinkAvailable,
280     IRichEditOle_fnSetDvaspect,
281     IRichEditOle_fnHandsOffStorage,
282     IRichEditOle_fnSaveCompleted,
283     IRichEditOle_fnInPlaceDeactivate,
284     IRichEditOle_fnContextSensitiveHelp,
285     IRichEditOle_fnGetClipboardData,
286     IRichEditOle_fnImportDataObject
287 };
288
289 static HRESULT WINAPI
290 ITextDocument_fnQueryInterface(ITextDocument* me, REFIID riid,
291     void** ppvObject)
292 {
293     IRichEditOleImpl *This = impl_from_ITextDocument(me);
294     return IRichEditOle_fnQueryInterface((IRichEditOle*)&This->lpRichEditOleVtbl,
295             riid, ppvObject);
296 }
297
298 static ULONG WINAPI
299 ITextDocument_fnAddRef(ITextDocument* me)
300 {
301     IRichEditOleImpl *This = impl_from_ITextDocument(me);
302     return IRichEditOle_fnAddRef((IRichEditOle*)&This->lpRichEditOleVtbl);
303 }
304
305 static ULONG WINAPI
306 ITextDocument_fnRelease(ITextDocument* me)
307 {
308     IRichEditOleImpl *This = impl_from_ITextDocument(me);
309     return IRichEditOle_fnRelease((IRichEditOle*)&This->lpRichEditOleVtbl);
310 }
311
312 static HRESULT WINAPI
313 ITextDocument_fnGetTypeInfoCount(ITextDocument* me,
314     UINT* pctinfo)
315 {
316     IRichEditOleImpl *This = impl_from_ITextDocument(me);
317     FIXME("stub %p\n",This);
318     return E_NOTIMPL;
319 }
320
321 static HRESULT WINAPI
322 ITextDocument_fnGetTypeInfo(ITextDocument* me, UINT iTInfo, LCID lcid,
323     ITypeInfo** ppTInfo)
324 {
325     IRichEditOleImpl *This = impl_from_ITextDocument(me);
326     FIXME("stub %p\n",This);
327     return E_NOTIMPL;
328 }
329
330 static HRESULT WINAPI
331 ITextDocument_fnGetIDsOfNames(ITextDocument* me, REFIID riid,
332     LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId)
333 {
334     IRichEditOleImpl *This = impl_from_ITextDocument(me);
335     FIXME("stub %p\n",This);
336     return E_NOTIMPL;
337 }
338
339 static HRESULT WINAPI
340 ITextDocument_fnInvoke(ITextDocument* me, DISPID dispIdMember,
341     REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
342     VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
343 {
344     IRichEditOleImpl *This = impl_from_ITextDocument(me);
345     FIXME("stub %p\n",This);
346     return E_NOTIMPL;
347 }
348
349 static HRESULT WINAPI
350 ITextDocument_fnGetName(ITextDocument* me, BSTR* pName)
351 {
352     IRichEditOleImpl *This = impl_from_ITextDocument(me);
353     FIXME("stub %p\n",This);
354     return E_NOTIMPL;
355 }
356
357 static HRESULT WINAPI
358 ITextDocument_fnGetSelection(ITextDocument* me, ITextSelection** ppSel)
359 {
360     IRichEditOleImpl *This = impl_from_ITextDocument(me);
361     FIXME("stub %p\n",This);
362     return E_NOTIMPL;
363 }
364
365 static HRESULT WINAPI
366 ITextDocument_fnGetStoryCount(ITextDocument* me, long* pCount)
367 {
368     IRichEditOleImpl *This = impl_from_ITextDocument(me);
369     FIXME("stub %p\n",This);
370     return E_NOTIMPL;
371 }
372
373 static HRESULT WINAPI
374 ITextDocument_fnGetStoryRanges(ITextDocument* me,
375     ITextStoryRanges** ppStories)
376 {
377     IRichEditOleImpl *This = impl_from_ITextDocument(me);
378     FIXME("stub %p\n",This);
379     return E_NOTIMPL;
380 }
381
382 static HRESULT WINAPI
383 ITextDocument_fnGetSaved(ITextDocument* me, long* pValue)
384 {
385     IRichEditOleImpl *This = impl_from_ITextDocument(me);
386     FIXME("stub %p\n",This);
387     return E_NOTIMPL;
388 }
389
390 static HRESULT WINAPI
391 ITextDocument_fnSetSaved(ITextDocument* me, long Value)
392 {
393     IRichEditOleImpl *This = impl_from_ITextDocument(me);
394     FIXME("stub %p\n",This);
395     return E_NOTIMPL;
396 }
397
398 static HRESULT WINAPI
399 ITextDocument_fnGetDefaultTabStop(ITextDocument* me, float* pValue)
400 {
401     IRichEditOleImpl *This = impl_from_ITextDocument(me);
402     FIXME("stub %p\n",This);
403     return E_NOTIMPL;
404 }
405
406 static HRESULT WINAPI
407 ITextDocument_fnSetDefaultTabStop(ITextDocument* me, float Value)
408 {
409     IRichEditOleImpl *This = impl_from_ITextDocument(me);
410     FIXME("stub %p\n",This);
411     return E_NOTIMPL;
412 }
413
414 static HRESULT WINAPI
415 ITextDocument_fnNew(ITextDocument* me)
416 {
417     IRichEditOleImpl *This = impl_from_ITextDocument(me);
418     FIXME("stub %p\n",This);
419     return E_NOTIMPL;
420 }
421
422 static HRESULT WINAPI
423 ITextDocument_fnOpen(ITextDocument* me, VARIANT* pVar, long Flags,
424     long CodePage)
425 {
426     IRichEditOleImpl *This = impl_from_ITextDocument(me);
427     FIXME("stub %p\n",This);
428     return E_NOTIMPL;
429 }
430
431 static HRESULT WINAPI
432 ITextDocument_fnSave(ITextDocument* me, VARIANT* pVar, long Flags,
433     long CodePage)
434 {
435     IRichEditOleImpl *This = impl_from_ITextDocument(me);
436     FIXME("stub %p\n",This);
437     return E_NOTIMPL;
438 }
439
440 static HRESULT WINAPI
441 ITextDocument_fnFreeze(ITextDocument* me, long* pCount)
442 {
443     IRichEditOleImpl *This = impl_from_ITextDocument(me);
444     FIXME("stub %p\n",This);
445     return E_NOTIMPL;
446 }
447
448 static HRESULT WINAPI
449 ITextDocument_fnUnfreeze(ITextDocument* me, long* pCount)
450 {
451     IRichEditOleImpl *This = impl_from_ITextDocument(me);
452     FIXME("stub %p\n",This);
453     return E_NOTIMPL;
454 }
455
456 static HRESULT WINAPI
457 ITextDocument_fnBeginEditCollection(ITextDocument* me)
458 {
459     IRichEditOleImpl *This = impl_from_ITextDocument(me);
460     FIXME("stub %p\n",This);
461     return E_NOTIMPL;
462 }
463
464 static HRESULT WINAPI
465 ITextDocument_fnEndEditCollection(ITextDocument* me)
466 {
467     IRichEditOleImpl *This = impl_from_ITextDocument(me);
468     FIXME("stub %p\n",This);
469     return E_NOTIMPL;
470 }
471
472 static HRESULT WINAPI
473 ITextDocument_fnUndo(ITextDocument* me, long Count, long* prop)
474 {
475     IRichEditOleImpl *This = impl_from_ITextDocument(me);
476     FIXME("stub %p\n",This);
477     return E_NOTIMPL;
478 }
479
480 static HRESULT WINAPI
481 ITextDocument_fnRedo(ITextDocument* me, long Count, long* prop)
482 {
483     IRichEditOleImpl *This = impl_from_ITextDocument(me);
484     FIXME("stub %p\n",This);
485     return E_NOTIMPL;
486 }
487
488 static HRESULT WINAPI
489 ITextDocument_fnRange(ITextDocument* me, long cp1, long cp2,
490     ITextRange** ppRange)
491 {
492     IRichEditOleImpl *This = impl_from_ITextDocument(me);
493     FIXME("stub %p\n",This);
494     return E_NOTIMPL;
495 }
496
497 static HRESULT WINAPI
498 ITextDocument_fnRangeFromPoint(ITextDocument* me, long x, long y,
499     ITextRange** ppRange)
500 {
501     IRichEditOleImpl *This = impl_from_ITextDocument(me);
502     FIXME("stub %p\n",This);
503     return E_NOTIMPL;
504 }
505
506 static const ITextDocumentVtbl tdvt = {
507     ITextDocument_fnQueryInterface,
508     ITextDocument_fnAddRef,
509     ITextDocument_fnRelease,
510     ITextDocument_fnGetTypeInfoCount,
511     ITextDocument_fnGetTypeInfo,
512     ITextDocument_fnGetIDsOfNames,
513     ITextDocument_fnInvoke,
514     ITextDocument_fnGetName,
515     ITextDocument_fnGetSelection,
516     ITextDocument_fnGetStoryCount,
517     ITextDocument_fnGetStoryRanges,
518     ITextDocument_fnGetSaved,
519     ITextDocument_fnSetSaved,
520     ITextDocument_fnGetDefaultTabStop,
521     ITextDocument_fnSetDefaultTabStop,
522     ITextDocument_fnNew,
523     ITextDocument_fnOpen,
524     ITextDocument_fnSave,
525     ITextDocument_fnFreeze,
526     ITextDocument_fnUnfreeze,
527     ITextDocument_fnBeginEditCollection,
528     ITextDocument_fnEndEditCollection,
529     ITextDocument_fnUndo,
530     ITextDocument_fnRedo,
531     ITextDocument_fnRange,
532     ITextDocument_fnRangeFromPoint
533 };
534
535 LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *ppObj)
536 {
537     IRichEditOleImpl *reo;
538
539     reo = heap_alloc(sizeof(IRichEditOleImpl));
540     if (!reo)
541         return 0;
542
543     reo->lpRichEditOleVtbl = &revt;
544     reo->lpTextDocumentVtbl = &tdvt;
545     reo->ref = 1;
546     reo->editor = editor;
547     TRACE("Created %p\n",reo);
548     *ppObj = (LPVOID) reo;
549
550     return 1;
551 }
552
553 static void convert_sizel(ME_Context *c, const SIZEL* szl, SIZE* sz)
554 {
555   /* sizel is in .01 millimeters, sz in pixels */
556   sz->cx = MulDiv(szl->cx, c->dpi.cx, 2540);
557   sz->cy = MulDiv(szl->cy, c->dpi.cy, 2540);
558 }
559
560 /******************************************************************************
561  * ME_GetOLEObjectSize
562  *
563  * Sets run extent for OLE objects.
564  */
565 void ME_GetOLEObjectSize(ME_Context *c, ME_Run *run, SIZE *pSize)
566 {
567   IDataObject*  ido;
568   FORMATETC     fmt;
569   STGMEDIUM     stgm;
570   DIBSECTION    dibsect;
571   ENHMETAHEADER emh;
572
573   assert(run->nFlags & MERF_GRAPHICS);
574   assert(run->ole_obj);
575
576   if (run->ole_obj->sizel.cx != 0 || run->ole_obj->sizel.cy != 0)
577   {
578     convert_sizel(c, &run->ole_obj->sizel, pSize);
579     return;
580   }
581
582   IOleObject_QueryInterface(run->ole_obj->poleobj, &IID_IDataObject, (void**)&ido);
583   fmt.cfFormat = CF_BITMAP;
584   fmt.ptd = NULL;
585   fmt.dwAspect = DVASPECT_CONTENT;
586   fmt.lindex = -1;
587   fmt.tymed = TYMED_GDI;
588   if (IDataObject_GetData(ido, &fmt, &stgm) != S_OK)
589   {
590     fmt.cfFormat = CF_ENHMETAFILE;
591     fmt.tymed = TYMED_ENHMF;
592     if (IDataObject_GetData(ido, &fmt, &stgm) != S_OK)
593     {
594       FIXME("unsupported format\n");
595       pSize->cx = pSize->cy = 0;
596       IDataObject_Release(ido);
597       return;
598     }
599   }
600
601   switch (stgm.tymed)
602   {
603   case TYMED_GDI:
604     GetObjectW(stgm.u.hBitmap, sizeof(dibsect), &dibsect);
605     pSize->cx = dibsect.dsBm.bmWidth;
606     pSize->cy = dibsect.dsBm.bmHeight;
607     if (!stgm.pUnkForRelease) DeleteObject(stgm.u.hBitmap);
608     break;
609   case TYMED_ENHMF:
610     GetEnhMetaFileHeader(stgm.u.hEnhMetaFile, sizeof(emh), &emh);
611     pSize->cx = emh.rclBounds.right - emh.rclBounds.left;
612     pSize->cy = emh.rclBounds.bottom - emh.rclBounds.top;
613     if (!stgm.pUnkForRelease) DeleteEnhMetaFile(stgm.u.hEnhMetaFile);
614     break;
615   default:
616     FIXME("Unsupported tymed %d\n", stgm.tymed);
617     break;
618   }
619   IDataObject_Release(ido);
620   if (c->editor->nZoomNumerator != 0)
621   {
622     pSize->cx = MulDiv(pSize->cx, c->editor->nZoomNumerator, c->editor->nZoomDenominator);
623     pSize->cy = MulDiv(pSize->cy, c->editor->nZoomNumerator, c->editor->nZoomDenominator);
624   }
625 }
626
627 void ME_DrawOLE(ME_Context *c, int x, int y, ME_Run *run,
628                 ME_Paragraph *para, BOOL selected)
629 {
630   IDataObject*  ido;
631   FORMATETC     fmt;
632   STGMEDIUM     stgm;
633   DIBSECTION    dibsect;
634   ENHMETAHEADER emh;
635   HDC           hMemDC;
636   SIZE          sz;
637   BOOL          has_size;
638
639   assert(run->nFlags & MERF_GRAPHICS);
640   assert(run->ole_obj);
641   if (IOleObject_QueryInterface(run->ole_obj->poleobj, &IID_IDataObject, (void**)&ido) != S_OK)
642   {
643     FIXME("Couldn't get interface\n");
644     return;
645   }
646   has_size = run->ole_obj->sizel.cx != 0 || run->ole_obj->sizel.cy != 0;
647   fmt.cfFormat = CF_BITMAP;
648   fmt.ptd = NULL;
649   fmt.dwAspect = DVASPECT_CONTENT;
650   fmt.lindex = -1;
651   fmt.tymed = TYMED_GDI;
652   if (IDataObject_GetData(ido, &fmt, &stgm) != S_OK)
653   {
654     fmt.cfFormat = CF_ENHMETAFILE;
655     fmt.tymed = TYMED_ENHMF;
656     if (IDataObject_GetData(ido, &fmt, &stgm) != S_OK)
657     {
658       FIXME("Couldn't get storage medium\n");
659       IDataObject_Release(ido);
660       return;
661     }
662   }
663   switch (stgm.tymed)
664   {
665   case TYMED_GDI:
666     GetObjectW(stgm.u.hBitmap, sizeof(dibsect), &dibsect);
667     hMemDC = CreateCompatibleDC(c->hDC);
668     SelectObject(hMemDC, stgm.u.hBitmap);
669     if (!has_size && c->editor->nZoomNumerator == 0)
670     {
671       sz.cx = dibsect.dsBm.bmWidth;
672       sz.cy = dibsect.dsBm.bmHeight;
673       BitBlt(c->hDC, x, y - dibsect.dsBm.bmHeight,
674              dibsect.dsBm.bmWidth, dibsect.dsBm.bmHeight,
675              hMemDC, 0, 0, SRCCOPY);
676     }
677     else
678     {
679       if (has_size)
680       {
681         convert_sizel(c, &run->ole_obj->sizel, &sz);
682       }
683       else
684       {
685         sz.cx = MulDiv(dibsect.dsBm.bmWidth,
686                        c->editor->nZoomNumerator, c->editor->nZoomDenominator);
687         sz.cy = MulDiv(dibsect.dsBm.bmHeight,
688                        c->editor->nZoomNumerator, c->editor->nZoomDenominator);
689       }
690       StretchBlt(c->hDC, x, y - sz.cy, sz.cx, sz.cy,
691                  hMemDC, 0, 0, dibsect.dsBm.bmWidth, dibsect.dsBm.bmHeight, SRCCOPY);
692     }
693     if (!stgm.pUnkForRelease) DeleteObject(stgm.u.hBitmap);
694     break;
695   case TYMED_ENHMF:
696     GetEnhMetaFileHeader(stgm.u.hEnhMetaFile, sizeof(emh), &emh);
697     if (!has_size && c->editor->nZoomNumerator == 0)
698     {
699       sz.cy = emh.rclBounds.bottom - emh.rclBounds.top;
700       sz.cx = emh.rclBounds.right - emh.rclBounds.left;
701     }
702     else
703     {
704       if (has_size)
705       {
706         convert_sizel(c, &run->ole_obj->sizel, &sz);
707       }
708       else
709       {
710         sz.cy = MulDiv(emh.rclBounds.bottom - emh.rclBounds.top,
711                        c->editor->nZoomNumerator, c->editor->nZoomDenominator);
712         sz.cx = MulDiv(emh.rclBounds.right - emh.rclBounds.left,
713                        c->editor->nZoomNumerator, c->editor->nZoomDenominator);
714       }
715     }
716     {
717       RECT    rc;
718
719       rc.left = x;
720       rc.top = y - sz.cy;
721       rc.right = x + sz.cx;
722       rc.bottom = y;
723       PlayEnhMetaFile(c->hDC, stgm.u.hEnhMetaFile, &rc);
724     }
725     if (!stgm.pUnkForRelease) DeleteEnhMetaFile(stgm.u.hEnhMetaFile);
726     break;
727   default:
728     FIXME("Unsupported tymed %d\n", stgm.tymed);
729     selected = FALSE;
730     break;
731   }
732   if (selected && !c->editor->bHideSelection)
733     PatBlt(c->hDC, x, y - sz.cy, sz.cx, sz.cy, DSTINVERT);
734   IDataObject_Release(ido);
735 }
736
737 void ME_DeleteReObject(REOBJECT* reo)
738 {
739     if (reo->poleobj)   IOleObject_Release(reo->poleobj);
740     if (reo->pstg)      IStorage_Release(reo->pstg);
741     if (reo->polesite)  IOleClientSite_Release(reo->polesite);
742     FREE_OBJ(reo);
743 }
744
745 void ME_CopyReObject(REOBJECT* dst, const REOBJECT* src)
746 {
747     *dst = *src;
748
749     if (dst->poleobj)   IOleObject_AddRef(dst->poleobj);
750     if (dst->pstg)      IStorage_AddRef(dst->pstg);
751     if (dst->polesite)  IOleClientSite_AddRef(dst->polesite);
752 }