xref: /reactos/dll/win32/riched20/richole.c (revision f2df3bf0)
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 COBJMACROS
26 
27 #include "windef.h"
28 #include "winbase.h"
29 #include "wingdi.h"
30 #include "winuser.h"
31 #include "ole2.h"
32 #include "richole.h"
33 #include "editor.h"
34 #include "richedit.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 #include "initguid.h"
43 
44 DEFINE_GUID(LIBID_tom, 0x8cc497c9, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xaa, 0x00, 0x47, 0xbe, 0x5d);
45 DEFINE_GUID(IID_ITextServices, 0x8d33f740, 0xcf58, 0x11ce, 0xa8, 0x9d, 0x00, 0xaa, 0x00, 0x6c, 0xad, 0xc5);
46 DEFINE_GUID(IID_ITextHost, 0x13e670f4,0x1a5a,0x11cf,0xab,0xeb,0x00,0xaa,0x00,0xb6,0x5e,0xa1);
47 DEFINE_GUID(IID_ITextHost2, 0x13e670f5,0x1a5a,0x11cf,0xab,0xeb,0x00,0xaa,0x00,0xb6,0x5e,0xa1);
48 DEFINE_GUID(IID_ITextDocument, 0x8cc497c0, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xaa, 0x00, 0x47, 0xbe, 0x5d);
49 DEFINE_GUID(IID_ITextRange, 0x8cc497c2, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xaa, 0x00, 0x47, 0xbe, 0x5d);
50 DEFINE_GUID(IID_ITextSelection, 0x8cc497c1, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xaa, 0x00, 0x47, 0xbe, 0x5d);
51 DEFINE_GUID(IID_ITextFont, 0x8cc497c3, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xaa, 0x00, 0x47, 0xbe, 0x5d);
52 DEFINE_GUID(IID_ITextPara, 0x8cc497c4, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xaa, 0x00, 0x47, 0xbe, 0x5d);
53 
54 static ITypeLib *typelib;
55 
56 enum tid_t {
57     NULL_tid,
58     ITextDocument_tid,
59     ITextRange_tid,
60     ITextSelection_tid,
61     ITextFont_tid,
62     ITextPara_tid,
63     LAST_tid
64 };
65 
66 static const IID * const tid_ids[] =
67 {
68     &IID_NULL,
69     &IID_ITextDocument,
70     &IID_ITextRange,
71     &IID_ITextSelection,
72     &IID_ITextFont,
73     &IID_ITextPara,
74 };
75 static ITypeInfo *typeinfos[LAST_tid];
76 
77 static HRESULT load_typelib(void)
78 {
79     ITypeLib *tl;
80     HRESULT hr;
81 
82     hr = LoadRegTypeLib(&LIBID_tom, 1, 0, LOCALE_SYSTEM_DEFAULT, &tl);
83     if (FAILED(hr)) {
84         ERR("LoadRegTypeLib failed: %08x\n", hr);
85         return hr;
86     }
87 
88     if (InterlockedCompareExchangePointer((void**)&typelib, tl, NULL))
89         ITypeLib_Release(tl);
90     return hr;
91 }
92 
93 void release_typelib(void)
94 {
95     unsigned i;
96 
97     if (!typelib)
98         return;
99 
100     for (i = 0; i < sizeof(typeinfos)/sizeof(*typeinfos); i++)
101         if (typeinfos[i])
102             ITypeInfo_Release(typeinfos[i]);
103 
104     ITypeLib_Release(typelib);
105 }
106 
107 static HRESULT get_typeinfo(enum tid_t tid, ITypeInfo **typeinfo)
108 {
109     HRESULT hr;
110 
111     if (!typelib)
112         hr = load_typelib();
113     if (!typelib)
114         return hr;
115 
116     if (!typeinfos[tid])
117     {
118         ITypeInfo *ti;
119 
120         hr = ITypeLib_GetTypeInfoOfGuid(typelib, tid_ids[tid], &ti);
121         if (FAILED(hr))
122         {
123             ERR("GetTypeInfoOfGuid(%s) failed: %08x\n", debugstr_guid(tid_ids[tid]), hr);
124             return hr;
125         }
126 
127         if (InterlockedCompareExchangePointer((void**)(typeinfos+tid), ti, NULL))
128             ITypeInfo_Release(ti);
129     }
130 
131     *typeinfo = typeinfos[tid];
132     return S_OK;
133 }
134 
135 /* private IID used to get back IRichEditOleImpl pointer */
136 DEFINE_GUID(IID_Igetrichole, 0xe3ce5c7a, 0x8247, 0x4622, 0x81, 0xad, 0x11, 0x81, 0x02, 0xaa, 0x01, 0x30);
137 
138 typedef struct ITextSelectionImpl ITextSelectionImpl;
139 typedef struct IOleClientSiteImpl IOleClientSiteImpl;
140 typedef struct ITextRangeImpl ITextRangeImpl;
141 
142 enum textfont_prop_id {
143     FONT_ALLCAPS = 0,
144     FONT_ANIMATION,
145     FONT_BACKCOLOR,
146     FONT_BOLD,
147     FONT_EMBOSS,
148     FONT_FORECOLOR,
149     FONT_HIDDEN,
150     FONT_ENGRAVE,
151     FONT_ITALIC,
152     FONT_KERNING,
153     FONT_LANGID,
154     FONT_NAME,
155     FONT_OUTLINE,
156     FONT_POSITION,
157     FONT_PROTECTED,
158     FONT_SHADOW,
159     FONT_SIZE,
160     FONT_SMALLCAPS,
161     FONT_SPACING,
162     FONT_STRIKETHROUGH,
163     FONT_SUBSCRIPT,
164     FONT_SUPERSCRIPT,
165     FONT_UNDERLINE,
166     FONT_WEIGHT,
167     FONT_PROPID_LAST,
168     FONT_PROPID_FIRST = FONT_ALLCAPS
169 };
170 
171 static const DWORD textfont_prop_masks[][2] = {
172     { CFM_ALLCAPS,     CFE_ALLCAPS },
173     { CFM_ANIMATION },
174     { CFM_BACKCOLOR,   CFE_AUTOBACKCOLOR },
175     { CFM_BOLD,        CFE_BOLD },
176     { CFM_EMBOSS,      CFE_EMBOSS },
177     { CFM_COLOR,       CFE_AUTOCOLOR },
178     { CFM_HIDDEN,      CFE_HIDDEN },
179     { CFM_IMPRINT,     CFE_IMPRINT },
180     { CFM_ITALIC,      CFE_ITALIC },
181     { CFM_KERNING },
182     { CFM_LCID },
183     { CFM_FACE },
184     { CFM_OUTLINE,     CFE_OUTLINE },
185     { CFM_OFFSET },
186     { CFM_PROTECTED,   CFE_PROTECTED },
187     { CFM_SHADOW,      CFE_SHADOW },
188     { CFM_SIZE },
189     { CFM_SMALLCAPS,   CFE_SMALLCAPS },
190     { CFM_SPACING },
191     { CFM_STRIKEOUT,   CFE_STRIKEOUT },
192     { CFM_SUBSCRIPT,   CFE_SUBSCRIPT },
193     { CFM_SUPERSCRIPT, CFE_SUPERSCRIPT },
194     { CFM_UNDERLINE,   CFE_UNDERLINE },
195     { CFM_WEIGHT }
196 };
197 
198 typedef union {
199     FLOAT f;
200     LONG  l;
201     BSTR  str;
202 } textfont_prop_val;
203 
204 enum range_update_op {
205     RANGE_UPDATE_DELETE
206 };
207 
208 typedef struct IRichEditOleImpl {
209     IUnknown IUnknown_inner;
210     IRichEditOle IRichEditOle_iface;
211     ITextDocument ITextDocument_iface;
212     IUnknown *outer_unk;
213     LONG ref;
214 
215     ME_TextEditor *editor;
216     ITextSelectionImpl *txtSel;
217 
218     struct list rangelist;
219     struct list clientsites;
220 } IRichEditOleImpl;
221 
222 struct reole_child {
223     struct list entry;
224     IRichEditOleImpl *reole;
225 };
226 
227 struct ITextRangeImpl {
228     struct reole_child child;
229     ITextRange ITextRange_iface;
230     LONG ref;
231     LONG start, end;
232 };
233 
234 struct ITextSelectionImpl {
235     ITextSelection ITextSelection_iface;
236     LONG ref;
237 
238     IRichEditOleImpl *reOle;
239 };
240 
241 typedef struct ITextFontImpl {
242     ITextFont ITextFont_iface;
243     LONG ref;
244 
245     ITextRange *range;
246     textfont_prop_val props[FONT_PROPID_LAST];
247     BOOL get_cache_enabled;
248     BOOL set_cache_enabled;
249 } ITextFontImpl;
250 
251 typedef struct ITextParaImpl {
252     ITextPara ITextPara_iface;
253     LONG ref;
254 
255     ITextRange *range;
256 } ITextParaImpl;
257 
258 struct IOleClientSiteImpl {
259     struct reole_child child;
260     IOleClientSite IOleClientSite_iface;
261     IOleInPlaceSite IOleInPlaceSite_iface;
262     LONG ref;
263 };
264 
265 static inline IRichEditOleImpl *impl_from_IRichEditOle(IRichEditOle *iface)
266 {
267     return CONTAINING_RECORD(iface, IRichEditOleImpl, IRichEditOle_iface);
268 }
269 
270 static inline IRichEditOleImpl *impl_from_ITextDocument(ITextDocument *iface)
271 {
272     return CONTAINING_RECORD(iface, IRichEditOleImpl, ITextDocument_iface);
273 }
274 
275 static inline IRichEditOleImpl *impl_from_IUnknown(IUnknown *iface)
276 {
277     return CONTAINING_RECORD(iface, IRichEditOleImpl, IUnknown_inner);
278 }
279 
280 static inline IOleClientSiteImpl *impl_from_IOleInPlaceSite(IOleInPlaceSite *iface)
281 {
282     return CONTAINING_RECORD(iface, IOleClientSiteImpl, IOleInPlaceSite_iface);
283 }
284 
285 static inline ITextRangeImpl *impl_from_ITextRange(ITextRange *iface)
286 {
287     return CONTAINING_RECORD(iface, ITextRangeImpl, ITextRange_iface);
288 }
289 
290 static inline ITextSelectionImpl *impl_from_ITextSelection(ITextSelection *iface)
291 {
292     return CONTAINING_RECORD(iface, ITextSelectionImpl, ITextSelection_iface);
293 }
294 
295 static inline ITextFontImpl *impl_from_ITextFont(ITextFont *iface)
296 {
297     return CONTAINING_RECORD(iface, ITextFontImpl, ITextFont_iface);
298 }
299 
300 static inline ITextParaImpl *impl_from_ITextPara(ITextPara *iface)
301 {
302     return CONTAINING_RECORD(iface, ITextParaImpl, ITextPara_iface);
303 }
304 
305 static HRESULT create_textfont(ITextRange*, const ITextFontImpl*, ITextFont**);
306 static HRESULT create_textpara(ITextRange*, ITextPara**);
307 static ITextSelectionImpl *CreateTextSelection(IRichEditOleImpl*);
308 
309 static HRESULT textrange_get_storylength(ME_TextEditor *editor, LONG *length)
310 {
311     if (!length)
312         return E_INVALIDARG;
313 
314     *length = ME_GetTextLength(editor) + 1;
315     return S_OK;
316 }
317 
318 static void textranges_update_ranges(IRichEditOleImpl *reole, LONG start, LONG end, enum range_update_op op)
319 {
320     ITextRangeImpl *range;
321 
322     LIST_FOR_EACH_ENTRY(range, &reole->rangelist, ITextRangeImpl, child.entry) {
323         switch (op)
324         {
325         case RANGE_UPDATE_DELETE:
326             /* range fully covered by deleted range - collapse to insertion point */
327             if (range->start >= start && range->end <= end)
328                 range->start = range->end = start;
329             /* deleted range cuts from the right */
330             else if (range->start < start && range->end <= end)
331                 range->end = start;
332             /* deleted range cuts from the left */
333             else if (range->start >= start && range->end > end) {
334                 range->start = start;
335                 range->end -= end - start;
336             }
337             /* deleted range cuts within */
338             else
339                 range->end -= end - start;
340             break;
341         default:
342             FIXME("unknown update op, %d\n", op);
343         }
344     }
345 }
346 
347 static inline BOOL is_equal_textfont_prop_value(enum textfont_prop_id propid, textfont_prop_val *left,
348     textfont_prop_val *right)
349 {
350     switch (propid)
351     {
352     case FONT_ALLCAPS:
353     case FONT_ANIMATION:
354     case FONT_BACKCOLOR:
355     case FONT_BOLD:
356     case FONT_EMBOSS:
357     case FONT_FORECOLOR:
358     case FONT_HIDDEN:
359     case FONT_ENGRAVE:
360     case FONT_ITALIC:
361     case FONT_KERNING:
362     case FONT_LANGID:
363     case FONT_OUTLINE:
364     case FONT_PROTECTED:
365     case FONT_SHADOW:
366     case FONT_SMALLCAPS:
367     case FONT_STRIKETHROUGH:
368     case FONT_SUBSCRIPT:
369     case FONT_SUPERSCRIPT:
370     case FONT_UNDERLINE:
371     case FONT_WEIGHT:
372         return left->l == right->l;
373     case FONT_NAME:
374         return !strcmpW(left->str, right->str);
375     case FONT_POSITION:
376     case FONT_SIZE:
377     case FONT_SPACING:
378        return left->f == right->f;
379     default:
380         FIXME("unhandled font property %d\n", propid);
381         return FALSE;
382     }
383 }
384 
385 static inline void init_textfont_prop_value(enum textfont_prop_id propid, textfont_prop_val *v)
386 {
387     switch (propid)
388     {
389     case FONT_ALLCAPS:
390     case FONT_ANIMATION:
391     case FONT_BACKCOLOR:
392     case FONT_BOLD:
393     case FONT_EMBOSS:
394     case FONT_FORECOLOR:
395     case FONT_HIDDEN:
396     case FONT_ENGRAVE:
397     case FONT_ITALIC:
398     case FONT_KERNING:
399     case FONT_LANGID:
400     case FONT_OUTLINE:
401     case FONT_PROTECTED:
402     case FONT_SHADOW:
403     case FONT_SMALLCAPS:
404     case FONT_STRIKETHROUGH:
405     case FONT_SUBSCRIPT:
406     case FONT_SUPERSCRIPT:
407     case FONT_UNDERLINE:
408     case FONT_WEIGHT:
409         v->l = tomUndefined;
410         return;
411     case FONT_NAME:
412         v->str = NULL;
413         return;
414     case FONT_POSITION:
415     case FONT_SIZE:
416     case FONT_SPACING:
417         v->f = tomUndefined;
418         return;
419     default:
420         FIXME("unhandled font property %d\n", propid);
421         v->l = tomUndefined;
422         return;
423     }
424 }
425 
426 static inline FLOAT twips_to_points(LONG value)
427 {
428     return value * 72.0 / 1440;
429 }
430 
431 static inline FLOAT points_to_twips(FLOAT value)
432 {
433     return value * 1440 / 72.0;
434 }
435 
436 static HRESULT get_textfont_prop_for_pos(const IRichEditOleImpl *reole, int pos, enum textfont_prop_id propid,
437     textfont_prop_val *value)
438 {
439     ME_Cursor from, to;
440     CHARFORMAT2W fmt;
441 
442     memset(&fmt, 0, sizeof(fmt));
443     fmt.cbSize = sizeof(fmt);
444     fmt.dwMask = textfont_prop_masks[propid][0];
445 
446     ME_CursorFromCharOfs(reole->editor, pos, &from);
447     to = from;
448     ME_MoveCursorChars(reole->editor, &to, 1, FALSE);
449     ME_GetCharFormat(reole->editor, &from, &to, &fmt);
450 
451     switch (propid)
452     {
453     case FONT_ALLCAPS:
454     case FONT_BOLD:
455     case FONT_EMBOSS:
456     case FONT_HIDDEN:
457     case FONT_ENGRAVE:
458     case FONT_ITALIC:
459     case FONT_OUTLINE:
460     case FONT_PROTECTED:
461     case FONT_SHADOW:
462     case FONT_SMALLCAPS:
463     case FONT_STRIKETHROUGH:
464     case FONT_SUBSCRIPT:
465     case FONT_SUPERSCRIPT:
466     case FONT_UNDERLINE:
467         value->l = fmt.dwEffects & textfont_prop_masks[propid][1] ? tomTrue : tomFalse;
468         break;
469     case FONT_ANIMATION:
470         value->l = fmt.bAnimation;
471         break;
472     case FONT_BACKCOLOR:
473         value->l = fmt.dwEffects & CFE_AUTOBACKCOLOR ? GetSysColor(COLOR_WINDOW) : fmt.crBackColor;
474         break;
475     case FONT_FORECOLOR:
476         value->l = fmt.dwEffects & CFE_AUTOCOLOR ? GetSysColor(COLOR_WINDOWTEXT) : fmt.crTextColor;
477         break;
478     case FONT_KERNING:
479         value->f = twips_to_points(fmt.wKerning);
480         break;
481     case FONT_LANGID:
482         value->l = fmt.lcid;
483         break;
484     case FONT_NAME:
485         /* this case is used exclusively by GetName() */
486         value->str = SysAllocString(fmt.szFaceName);
487         if (!value->str)
488             return E_OUTOFMEMORY;
489         break;
490     case FONT_POSITION:
491         value->f = twips_to_points(fmt.yOffset);
492         break;
493     case FONT_SIZE:
494         value->f = twips_to_points(fmt.yHeight);
495         break;
496     case FONT_SPACING:
497         value->f = fmt.sSpacing;
498         break;
499     case FONT_WEIGHT:
500         value->l = fmt.wWeight;
501         break;
502     default:
503         FIXME("unhandled font property %d\n", propid);
504         return E_FAIL;
505     }
506 
507     return S_OK;
508 }
509 
510 static inline const IRichEditOleImpl *get_range_reole(ITextRange *range)
511 {
512     IRichEditOleImpl *reole = NULL;
513     ITextRange_QueryInterface(range, &IID_Igetrichole, (void**)&reole);
514     return reole;
515 }
516 
517 static void textrange_set_font(ITextRange *range, ITextFont *font)
518 {
519     CHARFORMAT2W fmt;
520     HRESULT hr;
521     LONG value;
522     BSTR str;
523     FLOAT f;
524 
525 #define CHARFORMAT_SET_B_FIELD(mask, value) \
526     if (hr == S_OK && value != tomUndefined) { \
527         fmt.dwMask |= CFM_##mask; \
528         if (value == tomTrue) fmt.dwEffects |= CFE_##mask; \
529     } \
530 
531     /* fill format data from font */
532     memset(&fmt, 0, sizeof(fmt));
533     fmt.cbSize = sizeof(fmt);
534 
535     value = tomUndefined;
536     hr = ITextFont_GetAllCaps(font, &value);
537     CHARFORMAT_SET_B_FIELD(ALLCAPS, value);
538 
539     value = tomUndefined;
540     hr = ITextFont_GetBold(font, &value);
541     CHARFORMAT_SET_B_FIELD(BOLD, value);
542 
543     value = tomUndefined;
544     hr = ITextFont_GetEmboss(font, &value);
545     CHARFORMAT_SET_B_FIELD(EMBOSS, value);
546 
547     value = tomUndefined;
548     hr = ITextFont_GetHidden(font, &value);
549     CHARFORMAT_SET_B_FIELD(HIDDEN, value);
550 
551     value = tomUndefined;
552     hr = ITextFont_GetEngrave(font, &value);
553     CHARFORMAT_SET_B_FIELD(IMPRINT, value);
554 
555     value = tomUndefined;
556     hr = ITextFont_GetItalic(font, &value);
557     CHARFORMAT_SET_B_FIELD(ITALIC, value);
558 
559     value = tomUndefined;
560     hr = ITextFont_GetOutline(font, &value);
561     CHARFORMAT_SET_B_FIELD(OUTLINE, value);
562 
563     value = tomUndefined;
564     hr = ITextFont_GetProtected(font, &value);
565     CHARFORMAT_SET_B_FIELD(PROTECTED, value);
566 
567     value = tomUndefined;
568     hr = ITextFont_GetShadow(font, &value);
569     CHARFORMAT_SET_B_FIELD(SHADOW, value);
570 
571     value = tomUndefined;
572     hr = ITextFont_GetSmallCaps(font, &value);
573     CHARFORMAT_SET_B_FIELD(SMALLCAPS, value);
574 
575     value = tomUndefined;
576     hr = ITextFont_GetStrikeThrough(font, &value);
577     CHARFORMAT_SET_B_FIELD(STRIKEOUT, value);
578 
579     value = tomUndefined;
580     hr = ITextFont_GetSubscript(font, &value);
581     CHARFORMAT_SET_B_FIELD(SUBSCRIPT, value);
582 
583     value = tomUndefined;
584     hr = ITextFont_GetSuperscript(font, &value);
585     CHARFORMAT_SET_B_FIELD(SUPERSCRIPT, value);
586 
587     value = tomUndefined;
588     hr = ITextFont_GetUnderline(font, &value);
589     CHARFORMAT_SET_B_FIELD(UNDERLINE, value);
590 
591 #undef CHARFORMAT_SET_B_FIELD
592 
593     value = tomUndefined;
594     hr = ITextFont_GetAnimation(font, &value);
595     if (hr == S_OK && value != tomUndefined) {
596         fmt.dwMask |= CFM_ANIMATION;
597         fmt.bAnimation = value;
598     }
599 
600     value = tomUndefined;
601     hr = ITextFont_GetBackColor(font, &value);
602     if (hr == S_OK && value != tomUndefined) {
603         fmt.dwMask |= CFM_BACKCOLOR;
604         if (value == tomAutoColor)
605             fmt.dwEffects |= CFE_AUTOBACKCOLOR;
606         else
607             fmt.crBackColor = value;
608     }
609 
610     value = tomUndefined;
611     hr = ITextFont_GetForeColor(font, &value);
612     if (hr == S_OK && value != tomUndefined) {
613         fmt.dwMask |= CFM_COLOR;
614         if (value == tomAutoColor)
615             fmt.dwEffects |= CFE_AUTOCOLOR;
616         else
617             fmt.crTextColor = value;
618     }
619 
620     value = tomUndefined;
621     hr = ITextFont_GetKerning(font, &f);
622     if (hr == S_OK && f != tomUndefined) {
623         fmt.dwMask |= CFM_KERNING;
624         fmt.wKerning = points_to_twips(f);
625     }
626 
627     value = tomUndefined;
628     hr = ITextFont_GetLanguageID(font, &value);
629     if (hr == S_OK && value != tomUndefined) {
630         fmt.dwMask |= CFM_LCID;
631         fmt.lcid = value;
632     }
633 
634     if (ITextFont_GetName(font, &str) == S_OK) {
635         fmt.dwMask |= CFM_FACE;
636         lstrcpynW(fmt.szFaceName, str, sizeof(fmt.szFaceName)/sizeof(WCHAR));
637         SysFreeString(str);
638     }
639 
640     hr = ITextFont_GetPosition(font, &f);
641     if (hr == S_OK && f != tomUndefined) {
642         fmt.dwMask |= CFM_OFFSET;
643         fmt.yOffset = points_to_twips(f);
644     }
645 
646     hr = ITextFont_GetSize(font, &f);
647     if (hr == S_OK && f != tomUndefined) {
648         fmt.dwMask |= CFM_SIZE;
649         fmt.yHeight = points_to_twips(f);
650     }
651 
652     hr = ITextFont_GetSpacing(font, &f);
653     if (hr == S_OK && f != tomUndefined) {
654         fmt.dwMask |= CFM_SPACING;
655         fmt.sSpacing = f;
656     }
657 
658     hr = ITextFont_GetWeight(font, &value);
659     if (hr == S_OK && value != tomUndefined) {
660         fmt.dwMask |= CFM_WEIGHT;
661         fmt.wWeight = value;
662     }
663 
664     if (fmt.dwMask) {
665         const IRichEditOleImpl *reole = get_range_reole(range);
666         ME_Cursor from, to;
667         LONG start, end;
668 
669         ITextRange_GetStart(range, &start);
670         ITextRange_GetEnd(range, &end);
671 
672         ME_CursorFromCharOfs(reole->editor, start, &from);
673         ME_CursorFromCharOfs(reole->editor, end, &to);
674         ME_SetCharFormat(reole->editor, &from, &to, &fmt);
675     }
676 }
677 
678 static HRESULT get_textfont_prop(const ITextFontImpl *font, enum textfont_prop_id propid, textfont_prop_val *value)
679 {
680     const IRichEditOleImpl *reole;
681     textfont_prop_val v;
682     LONG start, end, i;
683     HRESULT hr;
684 
685     /* when font is not attached to any range use cached values */
686     if (!font->range || font->get_cache_enabled) {
687         *value = font->props[propid];
688         return S_OK;
689     }
690 
691     if (!(reole = get_range_reole(font->range)))
692         return CO_E_RELEASED;
693 
694     init_textfont_prop_value(propid, value);
695 
696     ITextRange_GetStart(font->range, &start);
697     ITextRange_GetEnd(font->range, &end);
698 
699     /* iterate trough a range to see if property value is consistent */
700     hr = get_textfont_prop_for_pos(reole, start, propid, &v);
701     if (FAILED(hr))
702         return hr;
703 
704     for (i = start + 1; i < end; i++) {
705         textfont_prop_val cur;
706 
707         hr = get_textfont_prop_for_pos(reole, i, propid, &cur);
708         if (FAILED(hr))
709             return hr;
710 
711         if (!is_equal_textfont_prop_value(propid, &v, &cur))
712             return S_OK;
713     }
714 
715     *value = v;
716     return S_OK;
717 }
718 
719 static HRESULT get_textfont_propf(const ITextFontImpl *font, enum textfont_prop_id propid, FLOAT *value)
720 {
721     textfont_prop_val v;
722     HRESULT hr;
723 
724     if (!value)
725         return E_INVALIDARG;
726 
727     hr = get_textfont_prop(font, propid, &v);
728     *value = v.f;
729     return hr;
730 }
731 
732 static HRESULT get_textfont_propl(const ITextFontImpl *font, enum textfont_prop_id propid, LONG *value)
733 {
734     textfont_prop_val v;
735     HRESULT hr;
736 
737     if (!value)
738         return E_INVALIDARG;
739 
740     hr = get_textfont_prop(font, propid, &v);
741     *value = v.l;
742     return hr;
743 }
744 
745 /* Value should already have a terminal value, for boolean properties it means tomToggle is not handled */
746 static HRESULT set_textfont_prop(ITextFontImpl *font, enum textfont_prop_id propid, const textfont_prop_val *value)
747 {
748     const IRichEditOleImpl *reole;
749     ME_Cursor from, to;
750     CHARFORMAT2W fmt;
751     LONG start, end;
752 
753     /* when font is not attached to any range use cache */
754     if (!font->range || font->set_cache_enabled) {
755         if (propid == FONT_NAME) {
756             SysFreeString(font->props[propid].str);
757             font->props[propid].str = SysAllocString(value->str);
758         }
759         else
760             font->props[propid] = *value;
761         return S_OK;
762     }
763 
764     if (!(reole = get_range_reole(font->range)))
765         return CO_E_RELEASED;
766 
767     memset(&fmt, 0, sizeof(fmt));
768     fmt.cbSize = sizeof(fmt);
769     fmt.dwMask = textfont_prop_masks[propid][0];
770 
771     switch (propid)
772     {
773     case FONT_ALLCAPS:
774     case FONT_BOLD:
775     case FONT_EMBOSS:
776     case FONT_HIDDEN:
777     case FONT_ENGRAVE:
778     case FONT_ITALIC:
779     case FONT_OUTLINE:
780     case FONT_PROTECTED:
781     case FONT_SHADOW:
782     case FONT_SMALLCAPS:
783     case FONT_STRIKETHROUGH:
784     case FONT_SUBSCRIPT:
785     case FONT_SUPERSCRIPT:
786     case FONT_UNDERLINE:
787         fmt.dwEffects = value->l == tomTrue ? textfont_prop_masks[propid][1] : 0;
788         break;
789     case FONT_ANIMATION:
790         fmt.bAnimation = value->l;
791         break;
792     case FONT_BACKCOLOR:
793     case FONT_FORECOLOR:
794         if (value->l == tomAutoColor)
795             fmt.dwEffects = textfont_prop_masks[propid][1];
796         else if (propid == FONT_BACKCOLOR)
797             fmt.crBackColor = value->l;
798         else
799             fmt.crTextColor = value->l;
800         break;
801     case FONT_KERNING:
802         fmt.wKerning = value->f;
803         break;
804     case FONT_LANGID:
805         fmt.lcid = value->l;
806         break;
807     case FONT_POSITION:
808         fmt.yOffset = value->f;
809         break;
810     case FONT_SIZE:
811         fmt.yHeight = value->f;
812         break;
813     case FONT_SPACING:
814         fmt.sSpacing = value->f;
815         break;
816     case FONT_WEIGHT:
817         fmt.wWeight = value->l;
818         break;
819     case FONT_NAME:
820         lstrcpynW(fmt.szFaceName, value->str, sizeof(fmt.szFaceName)/sizeof(WCHAR));
821         break;
822     default:
823         FIXME("unhandled font property %d\n", propid);
824         return E_FAIL;
825     }
826 
827     ITextRange_GetStart(font->range, &start);
828     ITextRange_GetEnd(font->range, &end);
829 
830     ME_CursorFromCharOfs(reole->editor, start, &from);
831     ME_CursorFromCharOfs(reole->editor, end, &to);
832     ME_SetCharFormat(reole->editor, &from, &to, &fmt);
833 
834     return S_OK;
835 }
836 
837 static inline HRESULT set_textfont_propl(ITextFontImpl *font, enum textfont_prop_id propid, LONG value)
838 {
839     textfont_prop_val v;
840     v.l = value;
841     return set_textfont_prop(font, propid, &v);
842 }
843 
844 static inline HRESULT set_textfont_propf(ITextFontImpl *font, enum textfont_prop_id propid, FLOAT value)
845 {
846     textfont_prop_val v;
847     v.f = value;
848     return set_textfont_prop(font, propid, &v);
849 }
850 
851 static HRESULT set_textfont_propd(ITextFontImpl *font, enum textfont_prop_id propid, LONG value)
852 {
853     textfont_prop_val v;
854 
855     switch (value)
856     {
857     case tomUndefined:
858         return S_OK;
859     case tomToggle: {
860         LONG oldvalue;
861         get_textfont_propl(font, propid, &oldvalue);
862         if (oldvalue == tomFalse)
863             value = tomTrue;
864         else if (oldvalue == tomTrue)
865             value = tomFalse;
866         else
867             return E_INVALIDARG;
868         /* fallthrough */
869     }
870     case tomTrue:
871     case tomFalse:
872         v.l = value;
873         return set_textfont_prop(font, propid, &v);
874     default:
875         return E_INVALIDARG;
876     }
877 }
878 
879 static HRESULT textfont_getname_from_range(ITextRange *range, BSTR *ret)
880 {
881     const IRichEditOleImpl *reole;
882     textfont_prop_val v;
883     HRESULT hr;
884     LONG start;
885 
886     if (!(reole = get_range_reole(range)))
887         return CO_E_RELEASED;
888 
889     ITextRange_GetStart(range, &start);
890     hr = get_textfont_prop_for_pos(reole, start, FONT_NAME, &v);
891     *ret = v.str;
892     return hr;
893 }
894 
895 static void textfont_cache_range_props(ITextFontImpl *font)
896 {
897     enum textfont_prop_id propid;
898     for (propid = FONT_PROPID_FIRST; propid < FONT_PROPID_LAST; propid++) {
899         if (propid == FONT_NAME)
900             textfont_getname_from_range(font->range, &font->props[propid].str);
901         else
902             get_textfont_prop(font, propid, &font->props[propid]);
903     }
904 }
905 
906 static HRESULT textrange_expand(ITextRange *range, LONG unit, LONG *delta)
907 {
908     LONG expand_start, expand_end;
909 
910     switch (unit)
911     {
912     case tomStory:
913         expand_start = 0;
914         ITextRange_GetStoryLength(range, &expand_end);
915         break;
916     default:
917         FIXME("unit %d is not supported\n", unit);
918         return E_NOTIMPL;
919     }
920 
921     if (delta) {
922         LONG start, end;
923 
924         ITextRange_GetStart(range, &start);
925         ITextRange_GetEnd(range, &end);
926         *delta = expand_end - expand_start - (end - start);
927     }
928 
929     ITextRange_SetStart(range, expand_start);
930     ITextRange_SetEnd(range, expand_end);
931 
932     return S_OK;
933 }
934 
935 static HRESULT WINAPI IRichEditOleImpl_inner_fnQueryInterface(IUnknown *iface, REFIID riid, LPVOID *ppvObj)
936 {
937     IRichEditOleImpl *This = impl_from_IUnknown(iface);
938 
939     TRACE("%p %s\n", This, debugstr_guid(riid));
940 
941     *ppvObj = NULL;
942     if (IsEqualGUID(riid, &IID_IUnknown))
943         *ppvObj = &This->IUnknown_inner;
944     else if (IsEqualGUID(riid, &IID_IRichEditOle))
945         *ppvObj = &This->IRichEditOle_iface;
946     else if (IsEqualGUID(riid, &IID_ITextDocument))
947         *ppvObj = &This->ITextDocument_iface;
948     if (*ppvObj)
949     {
950         IUnknown_AddRef((IUnknown *)*ppvObj);
951         return S_OK;
952     }
953 
954     if (IsEqualGUID(riid, &IID_ITextServices))
955     {
956         static int once;
957         if (!once++) FIXME("%p: unhandled interface IID_ITextServices\n", This);
958         return E_NOINTERFACE;
959     }
960 
961     FIXME("%p: unhandled interface %s\n", This, debugstr_guid(riid));
962 
963     return E_NOINTERFACE;
964 }
965 
966 static ULONG WINAPI IRichEditOleImpl_inner_fnAddRef(IUnknown *iface)
967 {
968     IRichEditOleImpl *This = impl_from_IUnknown(iface);
969     ULONG ref = InterlockedIncrement(&This->ref);
970 
971     TRACE("%p ref = %u\n", This, ref);
972 
973     return ref;
974 }
975 
976 static ULONG WINAPI IRichEditOleImpl_inner_fnRelease(IUnknown *iface)
977 {
978     IRichEditOleImpl *This = impl_from_IUnknown(iface);
979     ULONG ref = InterlockedDecrement(&This->ref);
980 
981     TRACE ("%p ref=%u\n", This, ref);
982 
983     if (!ref)
984     {
985         IOleClientSiteImpl *clientsite;
986         ITextRangeImpl *txtRge;
987 
988         This->editor->reOle = NULL;
989         if (This->txtSel) {
990             This->txtSel->reOle = NULL;
991             ITextSelection_Release(&This->txtSel->ITextSelection_iface);
992         }
993 
994         LIST_FOR_EACH_ENTRY(txtRge, &This->rangelist, ITextRangeImpl, child.entry)
995             txtRge->child.reole = NULL;
996 
997         LIST_FOR_EACH_ENTRY(clientsite, &This->clientsites, IOleClientSiteImpl, child.entry)
998             clientsite->child.reole = NULL;
999 
1000         heap_free(This);
1001     }
1002     return ref;
1003 }
1004 
1005 static const IUnknownVtbl reo_unk_vtbl =
1006 {
1007     IRichEditOleImpl_inner_fnQueryInterface,
1008     IRichEditOleImpl_inner_fnAddRef,
1009     IRichEditOleImpl_inner_fnRelease
1010 };
1011 
1012 static HRESULT WINAPI
1013 IRichEditOle_fnQueryInterface(IRichEditOle *me, REFIID riid, LPVOID *ppvObj)
1014 {
1015     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1016     return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
1017 }
1018 
1019 static ULONG WINAPI
1020 IRichEditOle_fnAddRef(IRichEditOle *me)
1021 {
1022     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1023     return IUnknown_AddRef(This->outer_unk);
1024 }
1025 
1026 static ULONG WINAPI
1027 IRichEditOle_fnRelease(IRichEditOle *me)
1028 {
1029     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1030     return IUnknown_Release(This->outer_unk);
1031 }
1032 
1033 static HRESULT WINAPI
1034 IRichEditOle_fnActivateAs(IRichEditOle *me, REFCLSID rclsid, REFCLSID rclsidAs)
1035 {
1036     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1037     FIXME("stub %p\n",This);
1038     return E_NOTIMPL;
1039 }
1040 
1041 static HRESULT WINAPI
1042 IRichEditOle_fnContextSensitiveHelp(IRichEditOle *me, BOOL fEnterMode)
1043 {
1044     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1045     FIXME("stub %p\n",This);
1046     return E_NOTIMPL;
1047 }
1048 
1049 static HRESULT WINAPI
1050 IRichEditOle_fnConvertObject(IRichEditOle *me, LONG iob,
1051                REFCLSID rclsidNew, LPCSTR lpstrUserTypeNew)
1052 {
1053     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1054     FIXME("stub %p\n",This);
1055     return E_NOTIMPL;
1056 }
1057 
1058 static inline IOleClientSiteImpl *impl_from_IOleClientSite(IOleClientSite *iface)
1059 {
1060     return CONTAINING_RECORD(iface, IOleClientSiteImpl, IOleClientSite_iface);
1061 }
1062 
1063 static HRESULT WINAPI
1064 IOleClientSite_fnQueryInterface(IOleClientSite *me, REFIID riid, LPVOID *ppvObj)
1065 {
1066     IOleClientSiteImpl *This = impl_from_IOleClientSite(me);
1067     TRACE("%p %s\n", me, debugstr_guid(riid) );
1068 
1069     *ppvObj = NULL;
1070     if (IsEqualGUID(riid, &IID_IUnknown) ||
1071         IsEqualGUID(riid, &IID_IOleClientSite))
1072         *ppvObj = me;
1073     else if (IsEqualGUID(riid, &IID_IOleWindow) ||
1074              IsEqualGUID(riid, &IID_IOleInPlaceSite))
1075         *ppvObj = &This->IOleInPlaceSite_iface;
1076     if (*ppvObj)
1077     {
1078         IOleClientSite_AddRef(me);
1079         return S_OK;
1080     }
1081     FIXME("%p: unhandled interface %s\n", me, debugstr_guid(riid) );
1082 
1083     return E_NOINTERFACE;
1084 }
1085 
1086 static ULONG WINAPI IOleClientSite_fnAddRef(IOleClientSite *iface)
1087 {
1088     IOleClientSiteImpl *This = impl_from_IOleClientSite(iface);
1089     ULONG ref = InterlockedIncrement(&This->ref);
1090     TRACE("(%p)->(%u)\n", This, ref);
1091     return ref;
1092 }
1093 
1094 static ULONG WINAPI IOleClientSite_fnRelease(IOleClientSite *iface)
1095 {
1096     IOleClientSiteImpl *This = impl_from_IOleClientSite(iface);
1097     ULONG ref = InterlockedDecrement(&This->ref);
1098 
1099     TRACE("(%p)->(%u)\n", This, ref);
1100 
1101     if (ref == 0) {
1102         if (This->child.reole) {
1103             list_remove(&This->child.entry);
1104             This->child.reole = NULL;
1105         }
1106         heap_free(This);
1107     }
1108     return ref;
1109 }
1110 
1111 static HRESULT WINAPI IOleClientSite_fnSaveObject(IOleClientSite *iface)
1112 {
1113     IOleClientSiteImpl *This = impl_from_IOleClientSite(iface);
1114     if (!This->child.reole)
1115         return CO_E_RELEASED;
1116 
1117     FIXME("stub %p\n", iface);
1118     return E_NOTIMPL;
1119 }
1120 
1121 static HRESULT WINAPI IOleClientSite_fnGetMoniker(IOleClientSite *iface, DWORD dwAssign,
1122         DWORD dwWhichMoniker, IMoniker **ppmk)
1123 {
1124     IOleClientSiteImpl *This = impl_from_IOleClientSite(iface);
1125     if (!This->child.reole)
1126         return CO_E_RELEASED;
1127 
1128     FIXME("stub %p\n", iface);
1129     return E_NOTIMPL;
1130 }
1131 
1132 static HRESULT WINAPI IOleClientSite_fnGetContainer(IOleClientSite *iface,
1133         IOleContainer **ppContainer)
1134 {
1135     IOleClientSiteImpl *This = impl_from_IOleClientSite(iface);
1136     if (!This->child.reole)
1137         return CO_E_RELEASED;
1138 
1139     FIXME("stub %p\n", iface);
1140     return E_NOTIMPL;
1141 }
1142 
1143 static HRESULT WINAPI IOleClientSite_fnShowObject(IOleClientSite *iface)
1144 {
1145     IOleClientSiteImpl *This = impl_from_IOleClientSite(iface);
1146     if (!This->child.reole)
1147         return CO_E_RELEASED;
1148 
1149     FIXME("stub %p\n", iface);
1150     return E_NOTIMPL;
1151 }
1152 
1153 static HRESULT WINAPI IOleClientSite_fnOnShowWindow(IOleClientSite *iface, BOOL fShow)
1154 {
1155     IOleClientSiteImpl *This = impl_from_IOleClientSite(iface);
1156     if (!This->child.reole)
1157         return CO_E_RELEASED;
1158 
1159     FIXME("stub %p\n", iface);
1160     return E_NOTIMPL;
1161 }
1162 
1163 static HRESULT WINAPI IOleClientSite_fnRequestNewObjectLayout(IOleClientSite *iface)
1164 {
1165     IOleClientSiteImpl *This = impl_from_IOleClientSite(iface);
1166     if (!This->child.reole)
1167         return CO_E_RELEASED;
1168 
1169     FIXME("stub %p\n", iface);
1170     return E_NOTIMPL;
1171 }
1172 
1173 static const IOleClientSiteVtbl ocst = {
1174     IOleClientSite_fnQueryInterface,
1175     IOleClientSite_fnAddRef,
1176     IOleClientSite_fnRelease,
1177     IOleClientSite_fnSaveObject,
1178     IOleClientSite_fnGetMoniker,
1179     IOleClientSite_fnGetContainer,
1180     IOleClientSite_fnShowObject,
1181     IOleClientSite_fnOnShowWindow,
1182     IOleClientSite_fnRequestNewObjectLayout
1183 };
1184 
1185 /* IOleInPlaceSite interface */
1186 static HRESULT STDMETHODCALLTYPE IOleInPlaceSite_fnQueryInterface(IOleInPlaceSite *iface, REFIID riid, void **ppvObj)
1187 {
1188     IOleClientSiteImpl *This = impl_from_IOleInPlaceSite(iface);
1189     return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppvObj);
1190 }
1191 
1192 static ULONG STDMETHODCALLTYPE IOleInPlaceSite_fnAddRef(IOleInPlaceSite *iface)
1193 {
1194     IOleClientSiteImpl *This = impl_from_IOleInPlaceSite(iface);
1195     return IOleClientSite_AddRef(&This->IOleClientSite_iface);
1196 }
1197 
1198 static ULONG STDMETHODCALLTYPE IOleInPlaceSite_fnRelease(IOleInPlaceSite *iface)
1199 {
1200     IOleClientSiteImpl *This = impl_from_IOleInPlaceSite(iface);
1201     return IOleClientSite_Release(&This->IOleClientSite_iface);
1202 }
1203 
1204 static HRESULT STDMETHODCALLTYPE IOleInPlaceSite_fnGetWindow(IOleInPlaceSite *iface, HWND *phwnd)
1205 {
1206     IOleClientSiteImpl *This = impl_from_IOleInPlaceSite(iface);
1207 
1208     TRACE("(%p)->(%p)\n", This, phwnd);
1209 
1210     if (!This->child.reole)
1211         return CO_E_RELEASED;
1212 
1213     if (!phwnd)
1214         return E_INVALIDARG;
1215 
1216     *phwnd = This->child.reole->editor->hWnd;
1217     return S_OK;
1218 }
1219 
1220 static HRESULT STDMETHODCALLTYPE IOleInPlaceSite_fnContextSensitiveHelp(IOleInPlaceSite *iface, BOOL fEnterMode)
1221 {
1222     IOleClientSiteImpl *This = impl_from_IOleInPlaceSite(iface);
1223     FIXME("not implemented: (%p)->(%d)\n", This, fEnterMode);
1224     return E_NOTIMPL;
1225 }
1226 
1227 static HRESULT STDMETHODCALLTYPE IOleInPlaceSite_fnCanInPlaceActivate(IOleInPlaceSite *iface)
1228 {
1229     IOleClientSiteImpl *This = impl_from_IOleInPlaceSite(iface);
1230     FIXME("not implemented: (%p)\n", This);
1231     return E_NOTIMPL;
1232 }
1233 
1234 static HRESULT STDMETHODCALLTYPE IOleInPlaceSite_fnOnInPlaceActivate(IOleInPlaceSite *iface)
1235 {
1236     IOleClientSiteImpl *This = impl_from_IOleInPlaceSite(iface);
1237     FIXME("not implemented: (%p)\n", This);
1238     return E_NOTIMPL;
1239 }
1240 
1241 static HRESULT STDMETHODCALLTYPE IOleInPlaceSite_fnOnUIActivate(IOleInPlaceSite *iface)
1242 {
1243     IOleClientSiteImpl *This = impl_from_IOleInPlaceSite(iface);
1244     FIXME("not implemented: (%p)\n", This);
1245     return E_NOTIMPL;
1246 }
1247 
1248 static HRESULT STDMETHODCALLTYPE IOleInPlaceSite_fnGetWindowContext(IOleInPlaceSite *iface, IOleInPlaceFrame **ppFrame,
1249                                                                     IOleInPlaceUIWindow **ppDoc, LPRECT lprcPosRect,
1250                                                                     LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo)
1251 {
1252     IOleClientSiteImpl *This = impl_from_IOleInPlaceSite(iface);
1253     FIXME("not implemented: (%p)->(%p %p %p %p %p)\n", This, ppFrame, ppDoc, lprcPosRect, lprcClipRect, lpFrameInfo);
1254     return E_NOTIMPL;
1255 }
1256 
1257 static HRESULT STDMETHODCALLTYPE IOleInPlaceSite_fnScroll(IOleInPlaceSite *iface, SIZE scrollExtent)
1258 {
1259     IOleClientSiteImpl *This = impl_from_IOleInPlaceSite(iface);
1260     FIXME("not implemented: (%p)\n", This);
1261     return E_NOTIMPL;
1262 }
1263 
1264 static HRESULT STDMETHODCALLTYPE IOleInPlaceSite_fnOnUIDeactivate(IOleInPlaceSite *iface, BOOL fUndoable)
1265 {
1266     IOleClientSiteImpl *This = impl_from_IOleInPlaceSite(iface);
1267     FIXME("not implemented: (%p)->(%d)\n", This, fUndoable);
1268     return E_NOTIMPL;
1269 }
1270 
1271 static HRESULT STDMETHODCALLTYPE IOleInPlaceSite_fnOnInPlaceDeactivate(IOleInPlaceSite *iface)
1272 {
1273     IOleClientSiteImpl *This = impl_from_IOleInPlaceSite(iface);
1274     FIXME("not implemented: (%p)\n", This);
1275     return E_NOTIMPL;
1276 }
1277 
1278 static HRESULT STDMETHODCALLTYPE IOleInPlaceSite_fnDiscardUndoState(IOleInPlaceSite *iface)
1279 {
1280     IOleClientSiteImpl *This = impl_from_IOleInPlaceSite(iface);
1281     FIXME("not implemented: (%p)\n", This);
1282     return E_NOTIMPL;
1283 }
1284 
1285 static HRESULT STDMETHODCALLTYPE IOleInPlaceSite_fnDeactivateAndUndo(IOleInPlaceSite *iface)
1286 {
1287     IOleClientSiteImpl *This = impl_from_IOleInPlaceSite(iface);
1288     FIXME("not implemented: (%p)\n", This);
1289     return E_NOTIMPL;
1290 }
1291 
1292 static HRESULT STDMETHODCALLTYPE IOleInPlaceSite_fnOnPosRectChange(IOleInPlaceSite *iface, LPCRECT lprcPosRect)
1293 {
1294     IOleClientSiteImpl *This = impl_from_IOleInPlaceSite(iface);
1295     FIXME("not implemented: (%p)->(%p)\n", This, lprcPosRect);
1296     return E_NOTIMPL;
1297 }
1298 
1299 static const IOleInPlaceSiteVtbl olestvt =
1300 {
1301     IOleInPlaceSite_fnQueryInterface,
1302     IOleInPlaceSite_fnAddRef,
1303     IOleInPlaceSite_fnRelease,
1304     IOleInPlaceSite_fnGetWindow,
1305     IOleInPlaceSite_fnContextSensitiveHelp,
1306     IOleInPlaceSite_fnCanInPlaceActivate,
1307     IOleInPlaceSite_fnOnInPlaceActivate,
1308     IOleInPlaceSite_fnOnUIActivate,
1309     IOleInPlaceSite_fnGetWindowContext,
1310     IOleInPlaceSite_fnScroll,
1311     IOleInPlaceSite_fnOnUIDeactivate,
1312     IOleInPlaceSite_fnOnInPlaceDeactivate,
1313     IOleInPlaceSite_fnDiscardUndoState,
1314     IOleInPlaceSite_fnDeactivateAndUndo,
1315     IOleInPlaceSite_fnOnPosRectChange
1316 };
1317 
1318 static HRESULT CreateOleClientSite(IRichEditOleImpl *reOle, IOleClientSite **ret)
1319 {
1320     IOleClientSiteImpl *clientSite = heap_alloc(sizeof *clientSite);
1321 
1322     if (!clientSite)
1323         return E_OUTOFMEMORY;
1324 
1325     clientSite->IOleClientSite_iface.lpVtbl = &ocst;
1326     clientSite->IOleInPlaceSite_iface.lpVtbl = &olestvt;
1327     clientSite->ref = 1;
1328     clientSite->child.reole = reOle;
1329     list_add_head(&reOle->clientsites, &clientSite->child.entry);
1330 
1331     *ret = &clientSite->IOleClientSite_iface;
1332     return S_OK;
1333 }
1334 
1335 static HRESULT WINAPI
1336 IRichEditOle_fnGetClientSite(IRichEditOle *me, IOleClientSite **clientsite)
1337 {
1338     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1339 
1340     TRACE("(%p)->(%p)\n", This, clientsite);
1341 
1342     if (!clientsite)
1343         return E_INVALIDARG;
1344 
1345     return CreateOleClientSite(This, clientsite);
1346 }
1347 
1348 static HRESULT WINAPI
1349 IRichEditOle_fnGetClipboardData(IRichEditOle *me, CHARRANGE *lpchrg,
1350                DWORD reco, LPDATAOBJECT *lplpdataobj)
1351 {
1352     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1353     ME_Cursor start;
1354     int nChars;
1355 
1356     TRACE("(%p,%p,%d)\n",This, lpchrg, reco);
1357     if(!lplpdataobj)
1358         return E_INVALIDARG;
1359     if(!lpchrg) {
1360         int nFrom, nTo, nStartCur = ME_GetSelectionOfs(This->editor, &nFrom, &nTo);
1361         start = This->editor->pCursors[nStartCur];
1362         nChars = nTo - nFrom;
1363     } else {
1364         ME_CursorFromCharOfs(This->editor, lpchrg->cpMin, &start);
1365         nChars = lpchrg->cpMax - lpchrg->cpMin;
1366     }
1367     return ME_GetDataObject(This->editor, &start, nChars, lplpdataobj);
1368 }
1369 
1370 static LONG WINAPI IRichEditOle_fnGetLinkCount(IRichEditOle *me)
1371 {
1372     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1373     FIXME("stub %p\n",This);
1374     return E_NOTIMPL;
1375 }
1376 
1377 static HRESULT WINAPI
1378 IRichEditOle_fnGetObject(IRichEditOle *me, LONG iob,
1379                REOBJECT *lpreobject, DWORD dwFlags)
1380 {
1381     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1382     struct re_object *reobj = NULL;
1383     LONG count = 0;
1384 
1385     TRACE("(%p)->(%x, %p, %x)\n", This, iob, lpreobject, dwFlags);
1386 
1387     if (!lpreobject || !lpreobject->cbStruct)
1388         return E_INVALIDARG;
1389 
1390     if (iob == REO_IOB_USE_CP)
1391     {
1392         ME_Cursor cursor;
1393 
1394         TRACE("character offset: %d\n", lpreobject->cp);
1395         ME_CursorFromCharOfs(This->editor, lpreobject->cp, &cursor);
1396         if (!cursor.pRun->member.run.reobj)
1397             return E_INVALIDARG;
1398         else
1399             reobj = cursor.pRun->member.run.reobj;
1400     }
1401     else
1402     {
1403         if (iob > IRichEditOle_GetObjectCount(me))
1404             return E_INVALIDARG;
1405         LIST_FOR_EACH_ENTRY(reobj, &This->editor->reobj_list, struct re_object, entry)
1406         {
1407             if (count == iob)
1408                 break;
1409             count++;
1410         }
1411     }
1412     ME_CopyReObject(lpreobject, &reobj->obj, dwFlags);
1413     return S_OK;
1414 }
1415 
1416 static LONG WINAPI
1417 IRichEditOle_fnGetObjectCount(IRichEditOle *me)
1418 {
1419     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1420     TRACE("(%p)\n",This);
1421     return list_count(&This->editor->reobj_list);
1422 }
1423 
1424 static HRESULT WINAPI
1425 IRichEditOle_fnHandsOffStorage(IRichEditOle *me, LONG iob)
1426 {
1427     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1428     FIXME("stub %p\n",This);
1429     return E_NOTIMPL;
1430 }
1431 
1432 static HRESULT WINAPI
1433 IRichEditOle_fnImportDataObject(IRichEditOle *me, LPDATAOBJECT lpdataobj,
1434                CLIPFORMAT cf, HGLOBAL hMetaPict)
1435 {
1436     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1437     FIXME("stub %p\n",This);
1438     return E_NOTIMPL;
1439 }
1440 
1441 static HRESULT WINAPI
1442 IRichEditOle_fnInPlaceDeactivate(IRichEditOle *me)
1443 {
1444     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1445     FIXME("stub %p\n",This);
1446     return E_NOTIMPL;
1447 }
1448 
1449 static HRESULT WINAPI
1450 IRichEditOle_fnInsertObject(IRichEditOle *me, REOBJECT *reo)
1451 {
1452     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1453 
1454     TRACE("(%p,%p)\n", This, reo);
1455 
1456     if (!reo)
1457         return E_INVALIDARG;
1458 
1459     if (reo->cbStruct < sizeof(*reo)) return STG_E_INVALIDPARAMETER;
1460 
1461     ME_InsertOLEFromCursor(This->editor, reo, 0);
1462     ME_CommitUndo(This->editor);
1463     ME_UpdateRepaint(This->editor, FALSE);
1464     return S_OK;
1465 }
1466 
1467 static HRESULT WINAPI IRichEditOle_fnSaveCompleted(IRichEditOle *me, LONG iob,
1468                LPSTORAGE lpstg)
1469 {
1470     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1471     FIXME("stub %p\n",This);
1472     return E_NOTIMPL;
1473 }
1474 
1475 static HRESULT WINAPI
1476 IRichEditOle_fnSetDvaspect(IRichEditOle *me, LONG iob, DWORD dvaspect)
1477 {
1478     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1479     FIXME("stub %p\n",This);
1480     return E_NOTIMPL;
1481 }
1482 
1483 static HRESULT WINAPI IRichEditOle_fnSetHostNames(IRichEditOle *me,
1484                LPCSTR lpstrContainerApp, LPCSTR lpstrContainerObj)
1485 {
1486     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1487     FIXME("stub %p %s %s\n",This, lpstrContainerApp, lpstrContainerObj);
1488     return E_NOTIMPL;
1489 }
1490 
1491 static HRESULT WINAPI
1492 IRichEditOle_fnSetLinkAvailable(IRichEditOle *me, LONG iob, BOOL fAvailable)
1493 {
1494     IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1495     FIXME("stub %p\n",This);
1496     return E_NOTIMPL;
1497 }
1498 
1499 static const IRichEditOleVtbl revt = {
1500     IRichEditOle_fnQueryInterface,
1501     IRichEditOle_fnAddRef,
1502     IRichEditOle_fnRelease,
1503     IRichEditOle_fnGetClientSite,
1504     IRichEditOle_fnGetObjectCount,
1505     IRichEditOle_fnGetLinkCount,
1506     IRichEditOle_fnGetObject,
1507     IRichEditOle_fnInsertObject,
1508     IRichEditOle_fnConvertObject,
1509     IRichEditOle_fnActivateAs,
1510     IRichEditOle_fnSetHostNames,
1511     IRichEditOle_fnSetLinkAvailable,
1512     IRichEditOle_fnSetDvaspect,
1513     IRichEditOle_fnHandsOffStorage,
1514     IRichEditOle_fnSaveCompleted,
1515     IRichEditOle_fnInPlaceDeactivate,
1516     IRichEditOle_fnContextSensitiveHelp,
1517     IRichEditOle_fnGetClipboardData,
1518     IRichEditOle_fnImportDataObject
1519 };
1520 
1521 /* ITextRange interface */
1522 static HRESULT WINAPI ITextRange_fnQueryInterface(ITextRange *me, REFIID riid, void **ppvObj)
1523 {
1524     ITextRangeImpl *This = impl_from_ITextRange(me);
1525 
1526     *ppvObj = NULL;
1527     if (IsEqualGUID(riid, &IID_IUnknown)
1528         || IsEqualGUID(riid, &IID_IDispatch)
1529         || IsEqualGUID(riid, &IID_ITextRange))
1530     {
1531         *ppvObj = me;
1532         ITextRange_AddRef(me);
1533         return S_OK;
1534     }
1535     else if (IsEqualGUID(riid, &IID_Igetrichole))
1536     {
1537         *ppvObj = This->child.reole;
1538         return S_OK;
1539     }
1540 
1541     return E_NOINTERFACE;
1542 }
1543 
1544 static ULONG WINAPI ITextRange_fnAddRef(ITextRange *me)
1545 {
1546     ITextRangeImpl *This = impl_from_ITextRange(me);
1547     return InterlockedIncrement(&This->ref);
1548 }
1549 
1550 static ULONG WINAPI ITextRange_fnRelease(ITextRange *me)
1551 {
1552     ITextRangeImpl *This = impl_from_ITextRange(me);
1553     ULONG ref = InterlockedDecrement(&This->ref);
1554 
1555     TRACE ("%p ref=%u\n", This, ref);
1556     if (ref == 0)
1557     {
1558         if (This->child.reole)
1559         {
1560             list_remove(&This->child.entry);
1561             This->child.reole = NULL;
1562         }
1563         heap_free(This);
1564     }
1565     return ref;
1566 }
1567 
1568 static HRESULT WINAPI ITextRange_fnGetTypeInfoCount(ITextRange *me, UINT *pctinfo)
1569 {
1570     ITextRangeImpl *This = impl_from_ITextRange(me);
1571     TRACE("(%p)->(%p)\n", This, pctinfo);
1572     *pctinfo = 1;
1573     return S_OK;
1574 }
1575 
1576 static HRESULT WINAPI ITextRange_fnGetTypeInfo(ITextRange *me, UINT iTInfo, LCID lcid,
1577                                                ITypeInfo **ppTInfo)
1578 {
1579     ITextRangeImpl *This = impl_from_ITextRange(me);
1580     HRESULT hr;
1581 
1582     TRACE("(%p)->(%u,%d,%p)\n", This, iTInfo, lcid, ppTInfo);
1583 
1584     hr = get_typeinfo(ITextRange_tid, ppTInfo);
1585     if (SUCCEEDED(hr))
1586         ITypeInfo_AddRef(*ppTInfo);
1587     return hr;
1588 }
1589 
1590 static HRESULT WINAPI ITextRange_fnGetIDsOfNames(ITextRange *me, REFIID riid, LPOLESTR *rgszNames,
1591                                                  UINT cNames, LCID lcid, DISPID *rgDispId)
1592 {
1593     ITextRangeImpl *This = impl_from_ITextRange(me);
1594     ITypeInfo *ti;
1595     HRESULT hr;
1596 
1597     TRACE("(%p)->(%s, %p, %u, %d, %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid,
1598             rgDispId);
1599 
1600     hr = get_typeinfo(ITextRange_tid, &ti);
1601     if (SUCCEEDED(hr))
1602         hr = ITypeInfo_GetIDsOfNames(ti, rgszNames, cNames, rgDispId);
1603     return hr;
1604 }
1605 
1606 static HRESULT WINAPI ITextRange_fnInvoke(ITextRange *me, DISPID dispIdMember, REFIID riid,
1607                                           LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1608                                           VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
1609                                           UINT *puArgErr)
1610 {
1611     ITextRangeImpl *This = impl_from_ITextRange(me);
1612     ITypeInfo *ti;
1613     HRESULT hr;
1614 
1615     TRACE("(%p)->(%d, %s, %d, %u, %p, %p, %p, %p)\n", This, dispIdMember, debugstr_guid(riid),
1616             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1617 
1618     hr = get_typeinfo(ITextRange_tid, &ti);
1619     if (SUCCEEDED(hr))
1620         hr = ITypeInfo_Invoke(ti, me, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1621     return hr;
1622 }
1623 
1624 static HRESULT WINAPI ITextRange_fnGetText(ITextRange *me, BSTR *str)
1625 {
1626     ITextRangeImpl *This = impl_from_ITextRange(me);
1627     ME_TextEditor *editor;
1628     ME_Cursor start, end;
1629     int length;
1630     BOOL bEOP;
1631 
1632     TRACE("(%p)->(%p)\n", This, str);
1633 
1634     if (!This->child.reole)
1635         return CO_E_RELEASED;
1636 
1637     if (!str)
1638         return E_INVALIDARG;
1639 
1640     /* return early for degenerate range */
1641     if (This->start == This->end) {
1642         *str = NULL;
1643         return S_OK;
1644     }
1645 
1646     editor = This->child.reole->editor;
1647     ME_CursorFromCharOfs(editor, This->start, &start);
1648     ME_CursorFromCharOfs(editor, This->end, &end);
1649 
1650     length = This->end - This->start;
1651     *str = SysAllocStringLen(NULL, length);
1652     if (!*str)
1653         return E_OUTOFMEMORY;
1654 
1655     bEOP = (end.pRun->next->type == diTextEnd && This->end > ME_GetTextLength(editor));
1656     ME_GetTextW(editor, *str, length, &start, length, FALSE, bEOP);
1657     return S_OK;
1658 }
1659 
1660 static HRESULT WINAPI ITextRange_fnSetText(ITextRange *me, BSTR str)
1661 {
1662     ITextRangeImpl *This = impl_from_ITextRange(me);
1663     ME_TextEditor *editor;
1664     ME_Cursor cursor;
1665     ME_Style *style;
1666     int len;
1667 
1668     TRACE("(%p)->(%s)\n", This, debugstr_w(str));
1669 
1670     if (!This->child.reole)
1671         return CO_E_RELEASED;
1672 
1673     editor = This->child.reole->editor;
1674 
1675     /* delete only where's something to delete */
1676     if (This->start != This->end) {
1677         ME_CursorFromCharOfs(editor, This->start, &cursor);
1678         ME_InternalDeleteText(editor, &cursor, This->end - This->start, FALSE);
1679     }
1680 
1681     if (!str || !*str) {
1682         /* will update this range as well */
1683         textranges_update_ranges(This->child.reole, This->start, This->end, RANGE_UPDATE_DELETE);
1684         return S_OK;
1685     }
1686 
1687     /* it's safer not to rely on stored BSTR length */
1688     len = strlenW(str);
1689     cursor = editor->pCursors[0];
1690     ME_CursorFromCharOfs(editor, This->start, &editor->pCursors[0]);
1691     style = ME_GetInsertStyle(editor, 0);
1692     ME_InsertTextFromCursor(editor, 0, str, len, style);
1693     ME_ReleaseStyle(style);
1694     editor->pCursors[0] = cursor;
1695 
1696     if (len < This->end - This->start)
1697         textranges_update_ranges(This->child.reole, This->start + len, This->end, RANGE_UPDATE_DELETE);
1698     else
1699         This->end = len - This->start;
1700 
1701     return S_OK;
1702 }
1703 
1704 static HRESULT range_GetChar(ME_TextEditor *editor, ME_Cursor *cursor, LONG *pch)
1705 {
1706     WCHAR wch[2];
1707 
1708     ME_GetTextW(editor, wch, 1, cursor, 1, FALSE, cursor->pRun->next->type == diTextEnd);
1709     *pch = wch[0];
1710 
1711     return S_OK;
1712 }
1713 
1714 static HRESULT WINAPI ITextRange_fnGetChar(ITextRange *me, LONG *pch)
1715 {
1716     ITextRangeImpl *This = impl_from_ITextRange(me);
1717     ME_TextEditor *editor;
1718     ME_Cursor cursor;
1719 
1720     TRACE("(%p)->(%p)\n", This, pch);
1721 
1722     if (!This->child.reole)
1723         return CO_E_RELEASED;
1724 
1725     if (!pch)
1726         return E_INVALIDARG;
1727 
1728     editor = This->child.reole->editor;
1729     ME_CursorFromCharOfs(editor, This->start, &cursor);
1730     return range_GetChar(editor, &cursor, pch);
1731 }
1732 
1733 static HRESULT WINAPI ITextRange_fnSetChar(ITextRange *me, LONG ch)
1734 {
1735     ITextRangeImpl *This = impl_from_ITextRange(me);
1736 
1737     FIXME("(%p)->(%x): stub\n", This, ch);
1738 
1739     if (!This->child.reole)
1740         return CO_E_RELEASED;
1741 
1742     return E_NOTIMPL;
1743 }
1744 
1745 static HRESULT CreateITextRange(IRichEditOleImpl *reOle, LONG start, LONG end, ITextRange** ppRange);
1746 
1747 static HRESULT WINAPI ITextRange_fnGetDuplicate(ITextRange *me, ITextRange **ppRange)
1748 {
1749     ITextRangeImpl *This = impl_from_ITextRange(me);
1750 
1751     TRACE("(%p)->(%p)\n", This, ppRange);
1752 
1753     if (!This->child.reole)
1754         return CO_E_RELEASED;
1755 
1756     if (!ppRange)
1757         return E_INVALIDARG;
1758 
1759     return CreateITextRange(This->child.reole, This->start, This->end, ppRange);
1760 }
1761 
1762 static HRESULT WINAPI ITextRange_fnGetFormattedText(ITextRange *me, ITextRange **range)
1763 {
1764     ITextRangeImpl *This = impl_from_ITextRange(me);
1765 
1766     FIXME("(%p)->(%p): stub\n", This, range);
1767 
1768     if (!This->child.reole)
1769         return CO_E_RELEASED;
1770 
1771     return E_NOTIMPL;
1772 }
1773 
1774 static HRESULT WINAPI ITextRange_fnSetFormattedText(ITextRange *me, ITextRange *range)
1775 {
1776     ITextRangeImpl *This = impl_from_ITextRange(me);
1777 
1778     FIXME("(%p)->(%p): stub\n", This, range);
1779 
1780     if (!This->child.reole)
1781         return CO_E_RELEASED;
1782 
1783     return E_NOTIMPL;
1784 }
1785 
1786 static HRESULT WINAPI ITextRange_fnGetStart(ITextRange *me, LONG *start)
1787 {
1788     ITextRangeImpl *This = impl_from_ITextRange(me);
1789 
1790     TRACE("(%p)->(%p)\n", This, start);
1791 
1792     if (!This->child.reole)
1793         return CO_E_RELEASED;
1794 
1795     if (!start)
1796         return E_INVALIDARG;
1797 
1798     *start = This->start;
1799     return S_OK;
1800 }
1801 
1802 static HRESULT textrange_setstart(const IRichEditOleImpl *reole, LONG value, LONG *start, LONG *end)
1803 {
1804     int len;
1805 
1806     if (value < 0)
1807         value = 0;
1808 
1809     if (value == *start)
1810         return S_FALSE;
1811 
1812     if (value <= *end) {
1813         *start = value;
1814         return S_OK;
1815     }
1816 
1817     len = ME_GetTextLength(reole->editor);
1818     *start = *end = value > len ? len : value;
1819     return S_OK;
1820 }
1821 
1822 static HRESULT WINAPI ITextRange_fnSetStart(ITextRange *me, LONG value)
1823 {
1824     ITextRangeImpl *This = impl_from_ITextRange(me);
1825 
1826     TRACE("(%p)->(%d)\n", This, value);
1827 
1828     if (!This->child.reole)
1829         return CO_E_RELEASED;
1830 
1831     return textrange_setstart(This->child.reole, value, &This->start, &This->end);
1832 }
1833 
1834 static HRESULT WINAPI ITextRange_fnGetEnd(ITextRange *me, LONG *end)
1835 {
1836     ITextRangeImpl *This = impl_from_ITextRange(me);
1837 
1838     TRACE("(%p)->(%p)\n", This, end);
1839 
1840     if (!This->child.reole)
1841         return CO_E_RELEASED;
1842 
1843     if (!end)
1844         return E_INVALIDARG;
1845 
1846     *end = This->end;
1847     return S_OK;
1848 }
1849 
1850 static HRESULT textrange_setend(const IRichEditOleImpl *reole, LONG value, LONG *start, LONG *end)
1851 {
1852     int len;
1853 
1854     if (value == *end)
1855         return S_FALSE;
1856 
1857     if (value < *start) {
1858         *start = *end = max(0, value);
1859         return S_OK;
1860     }
1861 
1862     len = ME_GetTextLength(reole->editor);
1863     *end = value > len ? len + 1 : value;
1864     return S_OK;
1865 }
1866 
1867 static HRESULT WINAPI ITextRange_fnSetEnd(ITextRange *me, LONG value)
1868 {
1869     ITextRangeImpl *This = impl_from_ITextRange(me);
1870 
1871     TRACE("(%p)->(%d)\n", This, value);
1872 
1873     if (!This->child.reole)
1874         return CO_E_RELEASED;
1875 
1876     return textrange_setend(This->child.reole, value, &This->start, &This->end);
1877 }
1878 
1879 static HRESULT WINAPI ITextRange_fnGetFont(ITextRange *me, ITextFont **font)
1880 {
1881     ITextRangeImpl *This = impl_from_ITextRange(me);
1882 
1883     TRACE("(%p)->(%p)\n", This, font);
1884 
1885     if (!This->child.reole)
1886         return CO_E_RELEASED;
1887 
1888     if (!font)
1889         return E_INVALIDARG;
1890 
1891     return create_textfont(me, NULL, font);
1892 }
1893 
1894 static HRESULT WINAPI ITextRange_fnSetFont(ITextRange *me, ITextFont *font)
1895 {
1896     ITextRangeImpl *This = impl_from_ITextRange(me);
1897 
1898     TRACE("(%p)->(%p)\n", This, font);
1899 
1900     if (!font)
1901         return E_INVALIDARG;
1902 
1903     if (!This->child.reole)
1904         return CO_E_RELEASED;
1905 
1906     textrange_set_font(me, font);
1907     return S_OK;
1908 }
1909 
1910 static HRESULT WINAPI ITextRange_fnGetPara(ITextRange *me, ITextPara **para)
1911 {
1912     ITextRangeImpl *This = impl_from_ITextRange(me);
1913 
1914     TRACE("(%p)->(%p)\n", This, para);
1915 
1916     if (!This->child.reole)
1917         return CO_E_RELEASED;
1918 
1919     if (!para)
1920         return E_INVALIDARG;
1921 
1922     return create_textpara(me, para);
1923 }
1924 
1925 static HRESULT WINAPI ITextRange_fnSetPara(ITextRange *me, ITextPara *para)
1926 {
1927     ITextRangeImpl *This = impl_from_ITextRange(me);
1928 
1929     FIXME("(%p)->(%p): stub\n", This, para);
1930 
1931     if (!This->child.reole)
1932         return CO_E_RELEASED;
1933 
1934     return E_NOTIMPL;
1935 }
1936 
1937 static HRESULT WINAPI ITextRange_fnGetStoryLength(ITextRange *me, LONG *length)
1938 {
1939     ITextRangeImpl *This = impl_from_ITextRange(me);
1940 
1941     TRACE("(%p)->(%p)\n", This, length);
1942 
1943     if (!This->child.reole)
1944         return CO_E_RELEASED;
1945 
1946     return textrange_get_storylength(This->child.reole->editor, length);
1947 }
1948 
1949 static HRESULT WINAPI ITextRange_fnGetStoryType(ITextRange *me, LONG *value)
1950 {
1951     ITextRangeImpl *This = impl_from_ITextRange(me);
1952 
1953     TRACE("(%p)->(%p)\n", This, value);
1954 
1955     if (!This->child.reole)
1956         return CO_E_RELEASED;
1957 
1958     if (!value)
1959         return E_INVALIDARG;
1960 
1961     *value = tomUnknownStory;
1962     return S_OK;
1963 }
1964 
1965 static HRESULT range_Collapse(LONG bStart, LONG *start, LONG *end)
1966 {
1967   if (*end == *start)
1968       return S_FALSE;
1969 
1970   if (bStart == tomEnd)
1971       *start = *end;
1972   else
1973       *end = *start;
1974   return S_OK;
1975 }
1976 
1977 static HRESULT WINAPI ITextRange_fnCollapse(ITextRange *me, LONG bStart)
1978 {
1979     ITextRangeImpl *This = impl_from_ITextRange(me);
1980 
1981     TRACE("(%p)->(%d)\n", This, bStart);
1982 
1983     if (!This->child.reole)
1984         return CO_E_RELEASED;
1985 
1986     return range_Collapse(bStart, &This->start, &This->end);
1987 }
1988 
1989 static HRESULT WINAPI ITextRange_fnExpand(ITextRange *me, LONG unit, LONG *delta)
1990 {
1991     ITextRangeImpl *This = impl_from_ITextRange(me);
1992 
1993     TRACE("(%p)->(%d %p)\n", This, unit, delta);
1994 
1995     if (!This->child.reole)
1996         return CO_E_RELEASED;
1997 
1998     return textrange_expand(me, unit, delta);
1999 }
2000 
2001 static HRESULT WINAPI ITextRange_fnGetIndex(ITextRange *me, LONG unit, LONG *index)
2002 {
2003     ITextRangeImpl *This = impl_from_ITextRange(me);
2004 
2005     FIXME("(%p)->(%d %p): stub\n", This, unit, index);
2006 
2007     if (!This->child.reole)
2008         return CO_E_RELEASED;
2009 
2010     return E_NOTIMPL;
2011 }
2012 
2013 static HRESULT WINAPI ITextRange_fnSetIndex(ITextRange *me, LONG unit, LONG index,
2014                                             LONG extend)
2015 {
2016     ITextRangeImpl *This = impl_from_ITextRange(me);
2017 
2018     FIXME("(%p)->(%d %d %d): stub\n", This, unit, index, extend);
2019 
2020     if (!This->child.reole)
2021         return CO_E_RELEASED;
2022 
2023     return E_NOTIMPL;
2024 }
2025 
2026 static void cp2range(ME_TextEditor *editor, LONG *cp1, LONG *cp2)
2027 {
2028     int len = ME_GetTextLength(editor) + 1;
2029     *cp1 = max(*cp1, 0);
2030     *cp2 = max(*cp2, 0);
2031     *cp1 = min(*cp1, len);
2032     *cp2 = min(*cp2, len);
2033     if (*cp1 > *cp2)
2034     {
2035         int tmp = *cp1;
2036         *cp1 = *cp2;
2037         *cp2 = tmp;
2038     }
2039     if (*cp1 == len)
2040         *cp1 = *cp2 = len - 1;
2041 }
2042 
2043 static HRESULT WINAPI ITextRange_fnSetRange(ITextRange *me, LONG anchor, LONG active)
2044 {
2045     ITextRangeImpl *This = impl_from_ITextRange(me);
2046 
2047     FIXME("(%p)->(%d %d): stub\n", This, anchor, active);
2048 
2049     if (!This->child.reole)
2050         return CO_E_RELEASED;
2051 
2052     cp2range(This->child.reole->editor, &anchor, &active);
2053     if (anchor == This->start && active == This->end)
2054         return S_FALSE;
2055 
2056     This->start = anchor;
2057     This->end = active;
2058     return S_OK;
2059 }
2060 
2061 static HRESULT textrange_inrange(LONG start, LONG end, ITextRange *range, LONG *ret)
2062 {
2063     LONG from, to, v;
2064 
2065     if (!ret)
2066         ret = &v;
2067 
2068     if (FAILED(ITextRange_GetStart(range, &from)) || FAILED(ITextRange_GetEnd(range, &to))) {
2069         *ret = tomFalse;
2070     }
2071     else
2072         *ret = (start >= from && end <= to) ? tomTrue : tomFalse;
2073     return *ret == tomTrue ? S_OK : S_FALSE;
2074 }
2075 
2076 static HRESULT WINAPI ITextRange_fnInRange(ITextRange *me, ITextRange *range, LONG *ret)
2077 {
2078     ITextRangeImpl *This = impl_from_ITextRange(me);
2079 
2080     TRACE("(%p)->(%p %p)\n", This, range, ret);
2081 
2082     if (ret)
2083         *ret = tomFalse;
2084 
2085     if (!This->child.reole)
2086         return CO_E_RELEASED;
2087 
2088     if (!range)
2089         return S_FALSE;
2090 
2091     return textrange_inrange(This->start, This->end, range, ret);
2092 }
2093 
2094 static HRESULT WINAPI ITextRange_fnInStory(ITextRange *me, ITextRange *pRange, LONG *ret)
2095 {
2096     ITextRangeImpl *This = impl_from_ITextRange(me);
2097 
2098     FIXME("(%p)->(%p): stub\n", This, ret);
2099 
2100     if (!This->child.reole)
2101         return CO_E_RELEASED;
2102 
2103     return E_NOTIMPL;
2104 }
2105 
2106 static HRESULT textrange_isequal(LONG start, LONG end, ITextRange *range, LONG *ret)
2107 {
2108     LONG from, to, v;
2109 
2110     if (!ret)
2111         ret = &v;
2112 
2113     if (FAILED(ITextRange_GetStart(range, &from)) || FAILED(ITextRange_GetEnd(range, &to))) {
2114         *ret = tomFalse;
2115     }
2116     else
2117         *ret = (start == from && end == to) ? tomTrue : tomFalse;
2118     return *ret == tomTrue ? S_OK : S_FALSE;
2119 }
2120 
2121 static HRESULT WINAPI ITextRange_fnIsEqual(ITextRange *me, ITextRange *range, LONG *ret)
2122 {
2123     ITextRangeImpl *This = impl_from_ITextRange(me);
2124 
2125     TRACE("(%p)->(%p %p)\n", This, range, ret);
2126 
2127     if (ret)
2128         *ret = tomFalse;
2129 
2130     if (!This->child.reole)
2131         return CO_E_RELEASED;
2132 
2133     if (!range)
2134         return S_FALSE;
2135 
2136     return textrange_isequal(This->start, This->end, range, ret);
2137 }
2138 
2139 static HRESULT WINAPI ITextRange_fnSelect(ITextRange *me)
2140 {
2141     ITextRangeImpl *This = impl_from_ITextRange(me);
2142 
2143     TRACE("(%p)\n", This);
2144 
2145     if (!This->child.reole)
2146         return CO_E_RELEASED;
2147 
2148     ME_SetSelection(This->child.reole->editor, This->start, This->end);
2149     return S_OK;
2150 }
2151 
2152 static HRESULT WINAPI ITextRange_fnStartOf(ITextRange *me, LONG unit, LONG extend,
2153                                            LONG *delta)
2154 {
2155     ITextRangeImpl *This = impl_from_ITextRange(me);
2156 
2157     FIXME("(%p)->(%d %d %p): stub\n", This, unit, extend, delta);
2158 
2159     if (!This->child.reole)
2160         return CO_E_RELEASED;
2161 
2162     return E_NOTIMPL;
2163 }
2164 
2165 static HRESULT WINAPI ITextRange_fnEndOf(ITextRange *me, LONG unit, LONG extend,
2166                                          LONG *delta)
2167 {
2168     ITextRangeImpl *This = impl_from_ITextRange(me);
2169 
2170     FIXME("(%p)->(%d %d %p): stub\n", This, unit, extend, delta);
2171 
2172     if (!This->child.reole)
2173         return CO_E_RELEASED;
2174 
2175     return E_NOTIMPL;
2176 }
2177 
2178 static HRESULT WINAPI ITextRange_fnMove(ITextRange *me, LONG unit, LONG count, LONG *delta)
2179 {
2180     ITextRangeImpl *This = impl_from_ITextRange(me);
2181 
2182     FIXME("(%p)->(%d %d %p): stub\n", This, unit, count, delta);
2183 
2184     if (!This->child.reole)
2185         return CO_E_RELEASED;
2186 
2187     return E_NOTIMPL;
2188 }
2189 
2190 static HRESULT WINAPI ITextRange_fnMoveStart(ITextRange *me, LONG unit, LONG count,
2191                                              LONG *delta)
2192 {
2193     ITextRangeImpl *This = impl_from_ITextRange(me);
2194 
2195     FIXME("(%p)->(%d %d %p): stub\n", This, unit, count, delta);
2196 
2197     if (!This->child.reole)
2198         return CO_E_RELEASED;
2199 
2200     return E_NOTIMPL;
2201 }
2202 
2203 static HRESULT textrange_moveend(ITextRange *range, LONG unit, LONG count, LONG *delta)
2204 {
2205     LONG old_start, old_end, new_start, new_end;
2206     HRESULT hr = S_OK;
2207 
2208     if (!count)
2209     {
2210         if (delta)
2211             *delta = 0;
2212         return S_FALSE;
2213     }
2214 
2215     ITextRange_GetStart(range, &old_start);
2216     ITextRange_GetEnd(range, &old_end);
2217     switch (unit)
2218     {
2219     case tomStory:
2220         if (count < 0)
2221             new_start = new_end = 0;
2222         else
2223         {
2224             new_start = old_start;
2225             ITextRange_GetStoryLength(range, &new_end);
2226         }
2227         if (delta)
2228         {
2229             if (new_end < old_end)
2230                 *delta = -1;
2231             else if (new_end == old_end)
2232                 *delta = 0;
2233             else
2234                 *delta = 1;
2235         }
2236         break;
2237     default:
2238         FIXME("unit %d is not supported\n", unit);
2239         return E_NOTIMPL;
2240     }
2241     if (new_end == old_end)
2242         hr = S_FALSE;
2243     ITextRange_SetStart(range, new_start);
2244     ITextRange_SetEnd(range, new_end);
2245 
2246     return hr;
2247 }
2248 
2249 static HRESULT WINAPI ITextRange_fnMoveEnd(ITextRange *me, LONG unit, LONG count,
2250                                            LONG *delta)
2251 {
2252     ITextRangeImpl *This = impl_from_ITextRange(me);
2253 
2254     TRACE("(%p)->(%d %d %p)\n", This, unit, count, delta);
2255 
2256     if (!This->child.reole)
2257         return CO_E_RELEASED;
2258 
2259     return textrange_moveend(me, unit, count, delta);
2260 }
2261 
2262 static HRESULT WINAPI ITextRange_fnMoveWhile(ITextRange *me, VARIANT *charset, LONG count,
2263                                              LONG *delta)
2264 {
2265     ITextRangeImpl *This = impl_from_ITextRange(me);
2266 
2267     FIXME("(%p)->(%s %d %p): stub\n", This, debugstr_variant(charset), count, delta);
2268 
2269     if (!This->child.reole)
2270         return CO_E_RELEASED;
2271 
2272     return E_NOTIMPL;
2273 }
2274 
2275 static HRESULT WINAPI ITextRange_fnMoveStartWhile(ITextRange *me, VARIANT *charset, LONG count,
2276                                                   LONG *delta)
2277 {
2278     ITextRangeImpl *This = impl_from_ITextRange(me);
2279 
2280     FIXME("(%p)->(%s %d %p): stub\n", This, debugstr_variant(charset), count, delta);
2281 
2282     if (!This->child.reole)
2283         return CO_E_RELEASED;
2284 
2285     return E_NOTIMPL;
2286 }
2287 
2288 static HRESULT WINAPI ITextRange_fnMoveEndWhile(ITextRange *me, VARIANT *charset, LONG count,
2289                                                 LONG *delta)
2290 {
2291     ITextRangeImpl *This = impl_from_ITextRange(me);
2292 
2293     FIXME("(%p)->(%s %d %p): stub\n", This, debugstr_variant(charset), count, delta);
2294 
2295     if (!This->child.reole)
2296         return CO_E_RELEASED;
2297 
2298     return E_NOTIMPL;
2299 }
2300 
2301 static HRESULT WINAPI ITextRange_fnMoveUntil(ITextRange *me, VARIANT *charset, LONG count,
2302                                              LONG *delta)
2303 {
2304     ITextRangeImpl *This = impl_from_ITextRange(me);
2305 
2306     FIXME("(%p)->(%s %d %p): stub\n", This, debugstr_variant(charset), count, delta);
2307 
2308     if (!This->child.reole)
2309         return CO_E_RELEASED;
2310 
2311     return E_NOTIMPL;
2312 }
2313 
2314 static HRESULT WINAPI ITextRange_fnMoveStartUntil(ITextRange *me, VARIANT *charset, LONG count,
2315                                                   LONG *delta)
2316 {
2317     ITextRangeImpl *This = impl_from_ITextRange(me);
2318 
2319     FIXME("(%p)->(%s %d %p): stub\n", This, debugstr_variant(charset), count, delta);
2320 
2321     if (!This->child.reole)
2322         return CO_E_RELEASED;
2323 
2324     return E_NOTIMPL;
2325 }
2326 
2327 static HRESULT WINAPI ITextRange_fnMoveEndUntil(ITextRange *me, VARIANT *charset, LONG count,
2328                                                 LONG *delta)
2329 {
2330     ITextRangeImpl *This = impl_from_ITextRange(me);
2331 
2332     FIXME("(%p)->(%s %d %p): stub\n", This, debugstr_variant(charset), count, delta);
2333 
2334     if (!This->child.reole)
2335         return CO_E_RELEASED;
2336 
2337     return E_NOTIMPL;
2338 }
2339 
2340 static HRESULT WINAPI ITextRange_fnFindText(ITextRange *me, BSTR text, LONG count, LONG flags,
2341                                             LONG *length)
2342 {
2343     ITextRangeImpl *This = impl_from_ITextRange(me);
2344 
2345     FIXME("(%p)->(%s %d %x %p): stub\n", This, debugstr_w(text), count, flags, length);
2346 
2347     if (!This->child.reole)
2348         return CO_E_RELEASED;
2349 
2350     return E_NOTIMPL;
2351 }
2352 
2353 static HRESULT WINAPI ITextRange_fnFindTextStart(ITextRange *me, BSTR text, LONG count,
2354                                                  LONG flags, LONG *length)
2355 {
2356     ITextRangeImpl *This = impl_from_ITextRange(me);
2357 
2358     FIXME("(%p)->(%s %d %x %p): stub\n", This, debugstr_w(text), count, flags, length);
2359 
2360     if (!This->child.reole)
2361         return CO_E_RELEASED;
2362 
2363     return E_NOTIMPL;
2364 }
2365 
2366 static HRESULT WINAPI ITextRange_fnFindTextEnd(ITextRange *me, BSTR text, LONG count,
2367                                                LONG flags, LONG *length)
2368 {
2369     ITextRangeImpl *This = impl_from_ITextRange(me);
2370 
2371     FIXME("(%p)->(%s %d %x %p): stub\n", This, debugstr_w(text), count, flags, length);
2372 
2373     if (!This->child.reole)
2374         return CO_E_RELEASED;
2375 
2376     return E_NOTIMPL;
2377 }
2378 
2379 static HRESULT WINAPI ITextRange_fnDelete(ITextRange *me, LONG unit, LONG count, LONG *delta)
2380 {
2381     ITextRangeImpl *This = impl_from_ITextRange(me);
2382 
2383     FIXME("(%p)->(%d %d %p): stub\n", This, unit, count, delta);
2384 
2385     if (!This->child.reole)
2386         return CO_E_RELEASED;
2387 
2388     return E_NOTIMPL;
2389 }
2390 
2391 static HRESULT WINAPI ITextRange_fnCut(ITextRange *me, VARIANT *v)
2392 {
2393     ITextRangeImpl *This = impl_from_ITextRange(me);
2394 
2395     FIXME("(%p)->(%p): stub\n", This, v);
2396 
2397     if (!This->child.reole)
2398         return CO_E_RELEASED;
2399 
2400     return E_NOTIMPL;
2401 }
2402 
2403 static HRESULT WINAPI ITextRange_fnCopy(ITextRange *me, VARIANT *v)
2404 {
2405     ITextRangeImpl *This = impl_from_ITextRange(me);
2406 
2407     FIXME("(%p)->(%p): stub\n", This, v);
2408 
2409     if (!This->child.reole)
2410         return CO_E_RELEASED;
2411 
2412     return E_NOTIMPL;
2413 }
2414 
2415 static HRESULT WINAPI ITextRange_fnPaste(ITextRange *me, VARIANT *v, LONG format)
2416 {
2417     ITextRangeImpl *This = impl_from_ITextRange(me);
2418 
2419     FIXME("(%p)->(%s %x): stub\n", This, debugstr_variant(v), format);
2420 
2421     if (!This->child.reole)
2422         return CO_E_RELEASED;
2423 
2424     return E_NOTIMPL;
2425 }
2426 
2427 static HRESULT WINAPI ITextRange_fnCanPaste(ITextRange *me, VARIANT *v, LONG format, LONG *ret)
2428 {
2429     ITextRangeImpl *This = impl_from_ITextRange(me);
2430 
2431     FIXME("(%p)->(%s %x %p): stub\n", This, debugstr_variant(v), format, ret);
2432 
2433     if (!This->child.reole)
2434         return CO_E_RELEASED;
2435 
2436     return E_NOTIMPL;
2437 }
2438 
2439 static HRESULT WINAPI ITextRange_fnCanEdit(ITextRange *me, LONG *ret)
2440 {
2441     ITextRangeImpl *This = impl_from_ITextRange(me);
2442 
2443     FIXME("(%p)->(%p): stub\n", This, ret);
2444 
2445     if (!This->child.reole)
2446         return CO_E_RELEASED;
2447 
2448     return E_NOTIMPL;
2449 }
2450 
2451 static HRESULT WINAPI ITextRange_fnChangeCase(ITextRange *me, LONG type)
2452 {
2453     ITextRangeImpl *This = impl_from_ITextRange(me);
2454 
2455     FIXME("(%p)->(%d): stub\n", This, type);
2456 
2457     if (!This->child.reole)
2458         return CO_E_RELEASED;
2459 
2460     return E_NOTIMPL;
2461 }
2462 
2463 static HRESULT WINAPI ITextRange_fnGetPoint(ITextRange *me, LONG type, LONG *cx, LONG *cy)
2464 {
2465     ITextRangeImpl *This = impl_from_ITextRange(me);
2466 
2467     FIXME("(%p)->(%d %p %p): stub\n", This, type, cx, cy);
2468 
2469     if (!This->child.reole)
2470         return CO_E_RELEASED;
2471 
2472     return E_NOTIMPL;
2473 }
2474 
2475 static HRESULT WINAPI ITextRange_fnSetPoint(ITextRange *me, LONG x, LONG y, LONG type,
2476                                             LONG extend)
2477 {
2478     ITextRangeImpl *This = impl_from_ITextRange(me);
2479 
2480     FIXME("(%p)->(%d %d %d %d): stub\n", This, x, y, type, extend);
2481 
2482     if (!This->child.reole)
2483         return CO_E_RELEASED;
2484 
2485     return E_NOTIMPL;
2486 }
2487 
2488 static HRESULT WINAPI ITextRange_fnScrollIntoView(ITextRange *me, LONG value)
2489 {
2490     ITextRangeImpl *This = impl_from_ITextRange(me);
2491     ME_TextEditor *editor;
2492     ME_Cursor cursor;
2493     int x, y, height;
2494 
2495     TRACE("(%p)->(%d)\n", This, value);
2496 
2497     if (!This->child.reole)
2498         return CO_E_RELEASED;
2499 
2500     editor = This->child.reole->editor;
2501 
2502     switch (value)
2503     {
2504     case tomStart:
2505         ME_CursorFromCharOfs(editor, This->start, &cursor);
2506         ME_GetCursorCoordinates(editor, &cursor, &x, &y, &height);
2507         break;
2508     default:
2509         FIXME("bStart value %d not handled\n", value);
2510         return E_NOTIMPL;
2511     }
2512     ME_ScrollAbs(editor, x, y);
2513     return S_OK;
2514 }
2515 
2516 static HRESULT WINAPI ITextRange_fnGetEmbeddedObject(ITextRange *me, IUnknown **ppv)
2517 {
2518     ITextRangeImpl *This = impl_from_ITextRange(me);
2519 
2520     FIXME("(%p)->(%p): stub\n", This, ppv);
2521 
2522     if (!This->child.reole)
2523         return CO_E_RELEASED;
2524 
2525     return E_NOTIMPL;
2526 }
2527 
2528 static const ITextRangeVtbl trvt = {
2529     ITextRange_fnQueryInterface,
2530     ITextRange_fnAddRef,
2531     ITextRange_fnRelease,
2532     ITextRange_fnGetTypeInfoCount,
2533     ITextRange_fnGetTypeInfo,
2534     ITextRange_fnGetIDsOfNames,
2535     ITextRange_fnInvoke,
2536     ITextRange_fnGetText,
2537     ITextRange_fnSetText,
2538     ITextRange_fnGetChar,
2539     ITextRange_fnSetChar,
2540     ITextRange_fnGetDuplicate,
2541     ITextRange_fnGetFormattedText,
2542     ITextRange_fnSetFormattedText,
2543     ITextRange_fnGetStart,
2544     ITextRange_fnSetStart,
2545     ITextRange_fnGetEnd,
2546     ITextRange_fnSetEnd,
2547     ITextRange_fnGetFont,
2548     ITextRange_fnSetFont,
2549     ITextRange_fnGetPara,
2550     ITextRange_fnSetPara,
2551     ITextRange_fnGetStoryLength,
2552     ITextRange_fnGetStoryType,
2553     ITextRange_fnCollapse,
2554     ITextRange_fnExpand,
2555     ITextRange_fnGetIndex,
2556     ITextRange_fnSetIndex,
2557     ITextRange_fnSetRange,
2558     ITextRange_fnInRange,
2559     ITextRange_fnInStory,
2560     ITextRange_fnIsEqual,
2561     ITextRange_fnSelect,
2562     ITextRange_fnStartOf,
2563     ITextRange_fnEndOf,
2564     ITextRange_fnMove,
2565     ITextRange_fnMoveStart,
2566     ITextRange_fnMoveEnd,
2567     ITextRange_fnMoveWhile,
2568     ITextRange_fnMoveStartWhile,
2569     ITextRange_fnMoveEndWhile,
2570     ITextRange_fnMoveUntil,
2571     ITextRange_fnMoveStartUntil,
2572     ITextRange_fnMoveEndUntil,
2573     ITextRange_fnFindText,
2574     ITextRange_fnFindTextStart,
2575     ITextRange_fnFindTextEnd,
2576     ITextRange_fnDelete,
2577     ITextRange_fnCut,
2578     ITextRange_fnCopy,
2579     ITextRange_fnPaste,
2580     ITextRange_fnCanPaste,
2581     ITextRange_fnCanEdit,
2582     ITextRange_fnChangeCase,
2583     ITextRange_fnGetPoint,
2584     ITextRange_fnSetPoint,
2585     ITextRange_fnScrollIntoView,
2586     ITextRange_fnGetEmbeddedObject
2587 };
2588 
2589 /* ITextFont */
2590 static HRESULT WINAPI TextFont_QueryInterface(ITextFont *iface, REFIID riid, void **ppv)
2591 {
2592     ITextFontImpl *This = impl_from_ITextFont(iface);
2593 
2594     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
2595 
2596     if (IsEqualIID(riid, &IID_ITextFont) ||
2597         IsEqualIID(riid, &IID_IDispatch) ||
2598         IsEqualIID(riid, &IID_IUnknown))
2599     {
2600         *ppv = iface;
2601         ITextFont_AddRef(iface);
2602         return S_OK;
2603     }
2604 
2605     *ppv = NULL;
2606     return E_NOINTERFACE;
2607 }
2608 
2609 static ULONG WINAPI TextFont_AddRef(ITextFont *iface)
2610 {
2611     ITextFontImpl *This = impl_from_ITextFont(iface);
2612     ULONG ref = InterlockedIncrement(&This->ref);
2613     TRACE("(%p)->(%u)\n", This, ref);
2614     return ref;
2615 }
2616 
2617 static ULONG WINAPI TextFont_Release(ITextFont *iface)
2618 {
2619     ITextFontImpl *This = impl_from_ITextFont(iface);
2620     ULONG ref = InterlockedDecrement(&This->ref);
2621 
2622     TRACE("(%p)->(%u)\n", This, ref);
2623 
2624     if (!ref)
2625     {
2626         if (This->range)
2627             ITextRange_Release(This->range);
2628         SysFreeString(This->props[FONT_NAME].str);
2629         heap_free(This);
2630     }
2631 
2632     return ref;
2633 }
2634 
2635 static HRESULT WINAPI TextFont_GetTypeInfoCount(ITextFont *iface, UINT *pctinfo)
2636 {
2637     ITextFontImpl *This = impl_from_ITextFont(iface);
2638     TRACE("(%p)->(%p)\n", This, pctinfo);
2639     *pctinfo = 1;
2640     return S_OK;
2641 }
2642 
2643 static HRESULT WINAPI TextFont_GetTypeInfo(ITextFont *iface, UINT iTInfo, LCID lcid,
2644     ITypeInfo **ppTInfo)
2645 {
2646     ITextFontImpl *This = impl_from_ITextFont(iface);
2647     HRESULT hr;
2648 
2649     TRACE("(%p)->(%u,%d,%p)\n", This, iTInfo, lcid, ppTInfo);
2650 
2651     hr = get_typeinfo(ITextFont_tid, ppTInfo);
2652     if (SUCCEEDED(hr))
2653         ITypeInfo_AddRef(*ppTInfo);
2654     return hr;
2655 }
2656 
2657 static HRESULT WINAPI TextFont_GetIDsOfNames(ITextFont *iface, REFIID riid,
2658     LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
2659 {
2660     ITextFontImpl *This = impl_from_ITextFont(iface);
2661     ITypeInfo *ti;
2662     HRESULT hr;
2663 
2664     TRACE("(%p)->(%s, %p, %u, %d, %p)\n", This, debugstr_guid(riid),
2665             rgszNames, cNames, lcid, rgDispId);
2666 
2667     hr = get_typeinfo(ITextFont_tid, &ti);
2668     if (SUCCEEDED(hr))
2669         hr = ITypeInfo_GetIDsOfNames(ti, rgszNames, cNames, rgDispId);
2670     return hr;
2671 }
2672 
2673 static HRESULT WINAPI TextFont_Invoke(
2674     ITextFont *iface,
2675     DISPID dispIdMember,
2676     REFIID riid,
2677     LCID lcid,
2678     WORD wFlags,
2679     DISPPARAMS *pDispParams,
2680     VARIANT *pVarResult,
2681     EXCEPINFO *pExcepInfo,
2682     UINT *puArgErr)
2683 {
2684     ITextFontImpl *This = impl_from_ITextFont(iface);
2685     ITypeInfo *ti;
2686     HRESULT hr;
2687 
2688     TRACE("(%p)->(%d, %s, %d, %u, %p, %p, %p, %p)\n", This, dispIdMember, debugstr_guid(riid),
2689             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2690 
2691     hr = get_typeinfo(ITextFont_tid, &ti);
2692     if (SUCCEEDED(hr))
2693         hr = ITypeInfo_Invoke(ti, iface, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2694     return hr;
2695 }
2696 
2697 static HRESULT WINAPI TextFont_GetDuplicate(ITextFont *iface, ITextFont **ret)
2698 {
2699     ITextFontImpl *This = impl_from_ITextFont(iface);
2700 
2701     TRACE("(%p)->(%p)\n", This, ret);
2702 
2703     if (!ret)
2704         return E_INVALIDARG;
2705 
2706     *ret = NULL;
2707     if (This->range && !get_range_reole(This->range))
2708         return CO_E_RELEASED;
2709 
2710     return create_textfont(NULL, This, ret);
2711 }
2712 
2713 static HRESULT WINAPI TextFont_SetDuplicate(ITextFont *iface, ITextFont *pFont)
2714 {
2715     ITextFontImpl *This = impl_from_ITextFont(iface);
2716     FIXME("(%p)->(%p): stub\n", This, pFont);
2717 
2718     if (This->range && !get_range_reole(This->range))
2719         return CO_E_RELEASED;
2720 
2721     return E_NOTIMPL;
2722 }
2723 
2724 static HRESULT WINAPI TextFont_CanChange(ITextFont *iface, LONG *ret)
2725 {
2726     ITextFontImpl *This = impl_from_ITextFont(iface);
2727     FIXME("(%p)->(%p): stub\n", This, ret);
2728 
2729     if (This->range && !get_range_reole(This->range))
2730         return CO_E_RELEASED;
2731 
2732     return E_NOTIMPL;
2733 }
2734 
2735 static HRESULT WINAPI TextFont_IsEqual(ITextFont *iface, ITextFont *font, LONG *ret)
2736 {
2737     ITextFontImpl *This = impl_from_ITextFont(iface);
2738     FIXME("(%p)->(%p %p): stub\n", This, font, ret);
2739 
2740     if (This->range && !get_range_reole(This->range))
2741         return CO_E_RELEASED;
2742 
2743     return E_NOTIMPL;
2744 }
2745 
2746 static void textfont_reset_to_default(ITextFontImpl *font)
2747 {
2748     enum textfont_prop_id id;
2749 
2750     for (id = FONT_PROPID_FIRST; id < FONT_PROPID_LAST; id++) {
2751         switch (id)
2752         {
2753         case FONT_ALLCAPS:
2754         case FONT_ANIMATION:
2755         case FONT_BOLD:
2756         case FONT_EMBOSS:
2757         case FONT_HIDDEN:
2758         case FONT_ENGRAVE:
2759         case FONT_ITALIC:
2760         case FONT_OUTLINE:
2761         case FONT_PROTECTED:
2762         case FONT_SHADOW:
2763         case FONT_SMALLCAPS:
2764         case FONT_STRIKETHROUGH:
2765         case FONT_SUBSCRIPT:
2766         case FONT_SUPERSCRIPT:
2767         case FONT_UNDERLINE:
2768             font->props[id].l = tomFalse;
2769             break;
2770         case FONT_BACKCOLOR:
2771         case FONT_FORECOLOR:
2772             font->props[id].l = tomAutoColor;
2773             break;
2774         case FONT_KERNING:
2775         case FONT_POSITION:
2776         case FONT_SIZE:
2777         case FONT_SPACING:
2778             font->props[id].f = 0.0;
2779             break;
2780         case FONT_LANGID:
2781             font->props[id].l = GetSystemDefaultLCID();
2782             break;
2783         case FONT_NAME: {
2784             static const WCHAR sysW[] = {'S','y','s','t','e','m',0};
2785             SysFreeString(font->props[id].str);
2786             font->props[id].str = SysAllocString(sysW);
2787             break;
2788         }
2789         case FONT_WEIGHT:
2790             font->props[id].l = FW_NORMAL;
2791             break;
2792         default:
2793             FIXME("font property %d not handled\n", id);
2794         }
2795     }
2796 }
2797 
2798 static void textfont_reset_to_undefined(ITextFontImpl *font)
2799 {
2800     enum textfont_prop_id id;
2801 
2802     for (id = FONT_PROPID_FIRST; id < FONT_PROPID_LAST; id++) {
2803         switch (id)
2804         {
2805         case FONT_ALLCAPS:
2806         case FONT_ANIMATION:
2807         case FONT_BOLD:
2808         case FONT_EMBOSS:
2809         case FONT_HIDDEN:
2810         case FONT_ENGRAVE:
2811         case FONT_ITALIC:
2812         case FONT_OUTLINE:
2813         case FONT_PROTECTED:
2814         case FONT_SHADOW:
2815         case FONT_SMALLCAPS:
2816         case FONT_STRIKETHROUGH:
2817         case FONT_SUBSCRIPT:
2818         case FONT_SUPERSCRIPT:
2819         case FONT_UNDERLINE:
2820         case FONT_BACKCOLOR:
2821         case FONT_FORECOLOR:
2822         case FONT_LANGID:
2823         case FONT_WEIGHT:
2824             font->props[id].l = tomUndefined;
2825             break;
2826         case FONT_KERNING:
2827         case FONT_POSITION:
2828         case FONT_SIZE:
2829         case FONT_SPACING:
2830             font->props[id].f = tomUndefined;
2831             break;
2832         case FONT_NAME:
2833             break;
2834         default:
2835             FIXME("font property %d not handled\n", id);
2836         }
2837     }
2838 }
2839 
2840 static void textfont_apply_range_props(ITextFontImpl *font)
2841 {
2842     enum textfont_prop_id propid;
2843     for (propid = FONT_PROPID_FIRST; propid < FONT_PROPID_LAST; propid++)
2844         set_textfont_prop(font, propid, &font->props[propid]);
2845 }
2846 
2847 static HRESULT WINAPI TextFont_Reset(ITextFont *iface, LONG value)
2848 {
2849     ITextFontImpl *This = impl_from_ITextFont(iface);
2850 
2851     TRACE("(%p)->(%d)\n", This, value);
2852 
2853     /* If font is attached to a range, released or not, we can't
2854        reset to undefined */
2855     if (This->range) {
2856         if (!get_range_reole(This->range))
2857             return CO_E_RELEASED;
2858 
2859         switch (value)
2860         {
2861         case tomUndefined:
2862             return E_INVALIDARG;
2863         case tomCacheParms:
2864             textfont_cache_range_props(This);
2865             This->get_cache_enabled = TRUE;
2866             break;
2867         case tomTrackParms:
2868             This->get_cache_enabled = FALSE;
2869             break;
2870         case tomApplyLater:
2871             This->set_cache_enabled = TRUE;
2872             break;
2873         case tomApplyNow:
2874             This->set_cache_enabled = FALSE;
2875             textfont_apply_range_props(This);
2876             break;
2877         case tomUsePoints:
2878         case tomUseTwips:
2879             return E_INVALIDARG;
2880         default:
2881             FIXME("reset mode %d not supported\n", value);
2882         }
2883 
2884         return S_OK;
2885     }
2886     else {
2887         switch (value)
2888         {
2889         /* reset to global defaults */
2890         case tomDefault:
2891             textfont_reset_to_default(This);
2892             return S_OK;
2893         /* all properties are set to tomUndefined, font name is retained */
2894         case tomUndefined:
2895             textfont_reset_to_undefined(This);
2896             return S_OK;
2897         case tomApplyNow:
2898         case tomApplyLater:
2899         case tomTrackParms:
2900         case tomCacheParms:
2901             return S_OK;
2902         case tomUsePoints:
2903         case tomUseTwips:
2904             return E_INVALIDARG;
2905         }
2906     }
2907 
2908     FIXME("reset mode %d not supported\n", value);
2909     return E_NOTIMPL;
2910 }
2911 
2912 static HRESULT WINAPI TextFont_GetStyle(ITextFont *iface, LONG *value)
2913 {
2914     ITextFontImpl *This = impl_from_ITextFont(iface);
2915     FIXME("(%p)->(%p): stub\n", This, value);
2916 
2917     if (This->range && !get_range_reole(This->range))
2918         return CO_E_RELEASED;
2919 
2920     return E_NOTIMPL;
2921 }
2922 
2923 static HRESULT WINAPI TextFont_SetStyle(ITextFont *iface, LONG value)
2924 {
2925     ITextFontImpl *This = impl_from_ITextFont(iface);
2926     FIXME("(%p)->(%d): stub\n", This, value);
2927 
2928     if (This->range && !get_range_reole(This->range))
2929         return CO_E_RELEASED;
2930 
2931     return E_NOTIMPL;
2932 }
2933 
2934 static HRESULT WINAPI TextFont_GetAllCaps(ITextFont *iface, LONG *value)
2935 {
2936     ITextFontImpl *This = impl_from_ITextFont(iface);
2937     TRACE("(%p)->(%p)\n", This, value);
2938     return get_textfont_propl(This, FONT_ALLCAPS, value);
2939 }
2940 
2941 static HRESULT WINAPI TextFont_SetAllCaps(ITextFont *iface, LONG value)
2942 {
2943     ITextFontImpl *This = impl_from_ITextFont(iface);
2944     TRACE("(%p)->(%d)\n", This, value);
2945     return set_textfont_propd(This, FONT_ALLCAPS, value);
2946 }
2947 
2948 static HRESULT WINAPI TextFont_GetAnimation(ITextFont *iface, LONG *value)
2949 {
2950     ITextFontImpl *This = impl_from_ITextFont(iface);
2951     TRACE("(%p)->(%p)\n", This, value);
2952     return get_textfont_propl(This, FONT_ANIMATION, value);
2953 }
2954 
2955 static HRESULT WINAPI TextFont_SetAnimation(ITextFont *iface, LONG value)
2956 {
2957     ITextFontImpl *This = impl_from_ITextFont(iface);
2958 
2959     TRACE("(%p)->(%d)\n", This, value);
2960 
2961     if (value < tomNoAnimation || value > tomAnimationMax)
2962         return E_INVALIDARG;
2963 
2964     return set_textfont_propl(This, FONT_ANIMATION, value);
2965 }
2966 
2967 static HRESULT WINAPI TextFont_GetBackColor(ITextFont *iface, LONG *value)
2968 {
2969     ITextFontImpl *This = impl_from_ITextFont(iface);
2970     TRACE("(%p)->(%p)\n", This, value);
2971     return get_textfont_propl(This, FONT_BACKCOLOR, value);
2972 }
2973 
2974 static HRESULT WINAPI TextFont_SetBackColor(ITextFont *iface, LONG value)
2975 {
2976     ITextFontImpl *This = impl_from_ITextFont(iface);
2977     TRACE("(%p)->(%d)\n", This, value);
2978     return set_textfont_propl(This, FONT_BACKCOLOR, value);
2979 }
2980 
2981 static HRESULT WINAPI TextFont_GetBold(ITextFont *iface, LONG *value)
2982 {
2983     ITextFontImpl *This = impl_from_ITextFont(iface);
2984     TRACE("(%p)->(%p)\n", This, value);
2985     return get_textfont_propl(This, FONT_BOLD, value);
2986 }
2987 
2988 static HRESULT WINAPI TextFont_SetBold(ITextFont *iface, LONG value)
2989 {
2990     ITextFontImpl *This = impl_from_ITextFont(iface);
2991     TRACE("(%p)->(%d)\n", This, value);
2992     return set_textfont_propd(This, FONT_BOLD, value);
2993 }
2994 
2995 static HRESULT WINAPI TextFont_GetEmboss(ITextFont *iface, LONG *value)
2996 {
2997     ITextFontImpl *This = impl_from_ITextFont(iface);
2998     TRACE("(%p)->(%p)\n", This, value);
2999     return get_textfont_propl(This, FONT_EMBOSS, value);
3000 }
3001 
3002 static HRESULT WINAPI TextFont_SetEmboss(ITextFont *iface, LONG value)
3003 {
3004     ITextFontImpl *This = impl_from_ITextFont(iface);
3005     TRACE("(%p)->(%d)\n", This, value);
3006     return set_textfont_propd(This, FONT_EMBOSS, value);
3007 }
3008 
3009 static HRESULT WINAPI TextFont_GetForeColor(ITextFont *iface, LONG *value)
3010 {
3011     ITextFontImpl *This = impl_from_ITextFont(iface);
3012     TRACE("(%p)->(%p)\n", This, value);
3013     return get_textfont_propl(This, FONT_FORECOLOR, value);
3014 }
3015 
3016 static HRESULT WINAPI TextFont_SetForeColor(ITextFont *iface, LONG value)
3017 {
3018     ITextFontImpl *This = impl_from_ITextFont(iface);
3019     TRACE("(%p)->(%d)\n", This, value);
3020     return set_textfont_propl(This, FONT_FORECOLOR, value);
3021 }
3022 
3023 static HRESULT WINAPI TextFont_GetHidden(ITextFont *iface, LONG *value)
3024 {
3025     ITextFontImpl *This = impl_from_ITextFont(iface);
3026     TRACE("(%p)->(%p)\n", This, value);
3027     return get_textfont_propl(This, FONT_HIDDEN, value);
3028 }
3029 
3030 static HRESULT WINAPI TextFont_SetHidden(ITextFont *iface, LONG value)
3031 {
3032     ITextFontImpl *This = impl_from_ITextFont(iface);
3033     TRACE("(%p)->(%d)\n", This, value);
3034     return set_textfont_propd(This, FONT_HIDDEN, value);
3035 }
3036 
3037 static HRESULT WINAPI TextFont_GetEngrave(ITextFont *iface, LONG *value)
3038 {
3039     ITextFontImpl *This = impl_from_ITextFont(iface);
3040     TRACE("(%p)->(%p)\n", This, value);
3041     return get_textfont_propl(This, FONT_ENGRAVE, value);
3042 }
3043 
3044 static HRESULT WINAPI TextFont_SetEngrave(ITextFont *iface, LONG value)
3045 {
3046     ITextFontImpl *This = impl_from_ITextFont(iface);
3047     TRACE("(%p)->(%d)\n", This, value);
3048     return set_textfont_propd(This, FONT_ENGRAVE, value);
3049 }
3050 
3051 static HRESULT WINAPI TextFont_GetItalic(ITextFont *iface, LONG *value)
3052 {
3053     ITextFontImpl *This = impl_from_ITextFont(iface);
3054     TRACE("(%p)->(%p)\n", This, value);
3055     return get_textfont_propl(This, FONT_ITALIC, value);
3056 }
3057 
3058 static HRESULT WINAPI TextFont_SetItalic(ITextFont *iface, LONG value)
3059 {
3060     ITextFontImpl *This = impl_from_ITextFont(iface);
3061     TRACE("(%p)->(%d)\n", This, value);
3062     return set_textfont_propd(This, FONT_ITALIC, value);
3063 }
3064 
3065 static HRESULT WINAPI TextFont_GetKerning(ITextFont *iface, FLOAT *value)
3066 {
3067     ITextFontImpl *This = impl_from_ITextFont(iface);
3068     TRACE("(%p)->(%p)\n", This, value);
3069     return get_textfont_propf(This, FONT_KERNING, value);
3070 }
3071 
3072 static HRESULT WINAPI TextFont_SetKerning(ITextFont *iface, FLOAT value)
3073 {
3074     ITextFontImpl *This = impl_from_ITextFont(iface);
3075     TRACE("(%p)->(%.2f)\n", This, value);
3076     return set_textfont_propf(This, FONT_KERNING, value);
3077 }
3078 
3079 static HRESULT WINAPI TextFont_GetLanguageID(ITextFont *iface, LONG *value)
3080 {
3081     ITextFontImpl *This = impl_from_ITextFont(iface);
3082     TRACE("(%p)->(%p)\n", This, value);
3083     return get_textfont_propl(This, FONT_LANGID, value);
3084 }
3085 
3086 static HRESULT WINAPI TextFont_SetLanguageID(ITextFont *iface, LONG value)
3087 {
3088     ITextFontImpl *This = impl_from_ITextFont(iface);
3089     TRACE("(%p)->(%d)\n", This, value);
3090     return set_textfont_propl(This, FONT_LANGID, value);
3091 }
3092 
3093 static HRESULT WINAPI TextFont_GetName(ITextFont *iface, BSTR *value)
3094 {
3095     ITextFontImpl *This = impl_from_ITextFont(iface);
3096 
3097     TRACE("(%p)->(%p)\n", This, value);
3098 
3099     if (!value)
3100         return E_INVALIDARG;
3101 
3102     *value = NULL;
3103 
3104     if (!This->range) {
3105         if (This->props[FONT_NAME].str)
3106             *value = SysAllocString(This->props[FONT_NAME].str);
3107         else
3108             *value = SysAllocStringLen(NULL, 0);
3109         return *value ? S_OK : E_OUTOFMEMORY;
3110     }
3111 
3112     return textfont_getname_from_range(This->range, value);
3113 }
3114 
3115 static HRESULT WINAPI TextFont_SetName(ITextFont *iface, BSTR value)
3116 {
3117     ITextFontImpl *This = impl_from_ITextFont(iface);
3118     textfont_prop_val v;
3119 
3120     TRACE("(%p)->(%s)\n", This, debugstr_w(value));
3121 
3122     v.str = value;
3123     return set_textfont_prop(This, FONT_NAME, &v);
3124 }
3125 
3126 static HRESULT WINAPI TextFont_GetOutline(ITextFont *iface, LONG *value)
3127 {
3128     ITextFontImpl *This = impl_from_ITextFont(iface);
3129     TRACE("(%p)->(%p)\n", This, value);
3130     return get_textfont_propl(This, FONT_OUTLINE, value);
3131 }
3132 
3133 static HRESULT WINAPI TextFont_SetOutline(ITextFont *iface, LONG value)
3134 {
3135     ITextFontImpl *This = impl_from_ITextFont(iface);
3136     TRACE("(%p)->(%d)\n", This, value);
3137     return set_textfont_propd(This, FONT_OUTLINE, value);
3138 }
3139 
3140 static HRESULT WINAPI TextFont_GetPosition(ITextFont *iface, FLOAT *value)
3141 {
3142     ITextFontImpl *This = impl_from_ITextFont(iface);
3143     TRACE("(%p)->(%p)\n", This, value);
3144     return get_textfont_propf(This, FONT_POSITION, value);
3145 }
3146 
3147 static HRESULT WINAPI TextFont_SetPosition(ITextFont *iface, FLOAT value)
3148 {
3149     ITextFontImpl *This = impl_from_ITextFont(iface);
3150     TRACE("(%p)->(%.2f)\n", This, value);
3151     return set_textfont_propf(This, FONT_POSITION, value);
3152 }
3153 
3154 static HRESULT WINAPI TextFont_GetProtected(ITextFont *iface, LONG *value)
3155 {
3156     ITextFontImpl *This = impl_from_ITextFont(iface);
3157     TRACE("(%p)->(%p)\n", This, value);
3158     return get_textfont_propl(This, FONT_PROTECTED, value);
3159 }
3160 
3161 static HRESULT WINAPI TextFont_SetProtected(ITextFont *iface, LONG value)
3162 {
3163     ITextFontImpl *This = impl_from_ITextFont(iface);
3164     TRACE("(%p)->(%d)\n", This, value);
3165     return set_textfont_propd(This, FONT_PROTECTED, value);
3166 }
3167 
3168 static HRESULT WINAPI TextFont_GetShadow(ITextFont *iface, LONG *value)
3169 {
3170     ITextFontImpl *This = impl_from_ITextFont(iface);
3171     TRACE("(%p)->(%p)\n", This, value);
3172     return get_textfont_propl(This, FONT_SHADOW, value);
3173 }
3174 
3175 static HRESULT WINAPI TextFont_SetShadow(ITextFont *iface, LONG value)
3176 {
3177     ITextFontImpl *This = impl_from_ITextFont(iface);
3178     TRACE("(%p)->(%d)\n", This, value);
3179     return set_textfont_propd(This, FONT_SHADOW, value);
3180 }
3181 
3182 static HRESULT WINAPI TextFont_GetSize(ITextFont *iface, FLOAT *value)
3183 {
3184     ITextFontImpl *This = impl_from_ITextFont(iface);
3185     TRACE("(%p)->(%p)\n", This, value);
3186     return get_textfont_propf(This, FONT_SIZE, value);
3187 }
3188 
3189 static HRESULT WINAPI TextFont_SetSize(ITextFont *iface, FLOAT value)
3190 {
3191     ITextFontImpl *This = impl_from_ITextFont(iface);
3192     TRACE("(%p)->(%.2f)\n", This, value);
3193     return set_textfont_propf(This, FONT_SIZE, value);
3194 }
3195 
3196 static HRESULT WINAPI TextFont_GetSmallCaps(ITextFont *iface, LONG *value)
3197 {
3198     ITextFontImpl *This = impl_from_ITextFont(iface);
3199     TRACE("(%p)->(%p)\n", This, value);
3200     return get_textfont_propl(This, FONT_SMALLCAPS, value);
3201 }
3202 
3203 static HRESULT WINAPI TextFont_SetSmallCaps(ITextFont *iface, LONG value)
3204 {
3205     ITextFontImpl *This = impl_from_ITextFont(iface);
3206     TRACE("(%p)->(%d)\n", This, value);
3207     return set_textfont_propd(This, FONT_SMALLCAPS, value);
3208 }
3209 
3210 static HRESULT WINAPI TextFont_GetSpacing(ITextFont *iface, FLOAT *value)
3211 {
3212     ITextFontImpl *This = impl_from_ITextFont(iface);
3213     TRACE("(%p)->(%p)\n", This, value);
3214     return get_textfont_propf(This, FONT_SPACING, value);
3215 }
3216 
3217 static HRESULT WINAPI TextFont_SetSpacing(ITextFont *iface, FLOAT value)
3218 {
3219     ITextFontImpl *This = impl_from_ITextFont(iface);
3220     TRACE("(%p)->(%.2f)\n", This, value);
3221     return set_textfont_propf(This, FONT_SPACING, value);
3222 }
3223 
3224 static HRESULT WINAPI TextFont_GetStrikeThrough(ITextFont *iface, LONG *value)
3225 {
3226     ITextFontImpl *This = impl_from_ITextFont(iface);
3227     TRACE("(%p)->(%p)\n", This, value);
3228     return get_textfont_propl(This, FONT_STRIKETHROUGH, value);
3229 }
3230 
3231 static HRESULT WINAPI TextFont_SetStrikeThrough(ITextFont *iface, LONG value)
3232 {
3233     ITextFontImpl *This = impl_from_ITextFont(iface);
3234     TRACE("(%p)->(%d)\n", This, value);
3235     return set_textfont_propd(This, FONT_STRIKETHROUGH, value);
3236 }
3237 
3238 static HRESULT WINAPI TextFont_GetSubscript(ITextFont *iface, LONG *value)
3239 {
3240     ITextFontImpl *This = impl_from_ITextFont(iface);
3241     TRACE("(%p)->(%p)\n", This, value);
3242     return get_textfont_propl(This, FONT_SUBSCRIPT, value);
3243 }
3244 
3245 static HRESULT WINAPI TextFont_SetSubscript(ITextFont *iface, LONG value)
3246 {
3247     ITextFontImpl *This = impl_from_ITextFont(iface);
3248     TRACE("(%p)->(%d)\n", This, value);
3249     return set_textfont_propd(This, FONT_SUBSCRIPT, value);
3250 }
3251 
3252 static HRESULT WINAPI TextFont_GetSuperscript(ITextFont *iface, LONG *value)
3253 {
3254     ITextFontImpl *This = impl_from_ITextFont(iface);
3255     TRACE("(%p)->(%p)\n", This, value);
3256     return get_textfont_propl(This, FONT_SUPERSCRIPT, value);
3257 }
3258 
3259 static HRESULT WINAPI TextFont_SetSuperscript(ITextFont *iface, LONG value)
3260 {
3261     ITextFontImpl *This = impl_from_ITextFont(iface);
3262     TRACE("(%p)->(%d)\n", This, value);
3263     return set_textfont_propd(This, FONT_SUPERSCRIPT, value);
3264 }
3265 
3266 static HRESULT WINAPI TextFont_GetUnderline(ITextFont *iface, LONG *value)
3267 {
3268     ITextFontImpl *This = impl_from_ITextFont(iface);
3269     TRACE("(%p)->(%p)\n", This, value);
3270     return get_textfont_propl(This, FONT_UNDERLINE, value);
3271 }
3272 
3273 static HRESULT WINAPI TextFont_SetUnderline(ITextFont *iface, LONG value)
3274 {
3275     ITextFontImpl *This = impl_from_ITextFont(iface);
3276     TRACE("(%p)->(%d)\n", This, value);
3277     return set_textfont_propd(This, FONT_UNDERLINE, value);
3278 }
3279 
3280 static HRESULT WINAPI TextFont_GetWeight(ITextFont *iface, LONG *value)
3281 {
3282     ITextFontImpl *This = impl_from_ITextFont(iface);
3283     TRACE("(%p)->(%p)\n", This, value);
3284     return get_textfont_propl(This, FONT_WEIGHT, value);
3285 }
3286 
3287 static HRESULT WINAPI TextFont_SetWeight(ITextFont *iface, LONG value)
3288 {
3289     ITextFontImpl *This = impl_from_ITextFont(iface);
3290     TRACE("(%p)->(%d)\n", This, value);
3291     return set_textfont_propl(This, FONT_WEIGHT, value);
3292 }
3293 
3294 static ITextFontVtbl textfontvtbl = {
3295     TextFont_QueryInterface,
3296     TextFont_AddRef,
3297     TextFont_Release,
3298     TextFont_GetTypeInfoCount,
3299     TextFont_GetTypeInfo,
3300     TextFont_GetIDsOfNames,
3301     TextFont_Invoke,
3302     TextFont_GetDuplicate,
3303     TextFont_SetDuplicate,
3304     TextFont_CanChange,
3305     TextFont_IsEqual,
3306     TextFont_Reset,
3307     TextFont_GetStyle,
3308     TextFont_SetStyle,
3309     TextFont_GetAllCaps,
3310     TextFont_SetAllCaps,
3311     TextFont_GetAnimation,
3312     TextFont_SetAnimation,
3313     TextFont_GetBackColor,
3314     TextFont_SetBackColor,
3315     TextFont_GetBold,
3316     TextFont_SetBold,
3317     TextFont_GetEmboss,
3318     TextFont_SetEmboss,
3319     TextFont_GetForeColor,
3320     TextFont_SetForeColor,
3321     TextFont_GetHidden,
3322     TextFont_SetHidden,
3323     TextFont_GetEngrave,
3324     TextFont_SetEngrave,
3325     TextFont_GetItalic,
3326     TextFont_SetItalic,
3327     TextFont_GetKerning,
3328     TextFont_SetKerning,
3329     TextFont_GetLanguageID,
3330     TextFont_SetLanguageID,
3331     TextFont_GetName,
3332     TextFont_SetName,
3333     TextFont_GetOutline,
3334     TextFont_SetOutline,
3335     TextFont_GetPosition,
3336     TextFont_SetPosition,
3337     TextFont_GetProtected,
3338     TextFont_SetProtected,
3339     TextFont_GetShadow,
3340     TextFont_SetShadow,
3341     TextFont_GetSize,
3342     TextFont_SetSize,
3343     TextFont_GetSmallCaps,
3344     TextFont_SetSmallCaps,
3345     TextFont_GetSpacing,
3346     TextFont_SetSpacing,
3347     TextFont_GetStrikeThrough,
3348     TextFont_SetStrikeThrough,
3349     TextFont_GetSubscript,
3350     TextFont_SetSubscript,
3351     TextFont_GetSuperscript,
3352     TextFont_SetSuperscript,
3353     TextFont_GetUnderline,
3354     TextFont_SetUnderline,
3355     TextFont_GetWeight,
3356     TextFont_SetWeight
3357 };
3358 
3359 static HRESULT create_textfont(ITextRange *range, const ITextFontImpl *src, ITextFont **ret)
3360 {
3361     ITextFontImpl *font;
3362 
3363     *ret = NULL;
3364     font = heap_alloc(sizeof(*font));
3365     if (!font)
3366         return E_OUTOFMEMORY;
3367 
3368     font->ITextFont_iface.lpVtbl = &textfontvtbl;
3369     font->ref = 1;
3370 
3371     if (src) {
3372         font->range = NULL;
3373         font->get_cache_enabled = TRUE;
3374         font->set_cache_enabled = TRUE;
3375         memcpy(&font->props, &src->props, sizeof(font->props));
3376         if (font->props[FONT_NAME].str)
3377             font->props[FONT_NAME].str = SysAllocString(font->props[FONT_NAME].str);
3378     }
3379     else {
3380         font->range = range;
3381         ITextRange_AddRef(range);
3382 
3383         /* cache current properties */
3384         font->get_cache_enabled = FALSE;
3385         font->set_cache_enabled = FALSE;
3386         textfont_cache_range_props(font);
3387     }
3388 
3389     *ret = &font->ITextFont_iface;
3390     return S_OK;
3391 }
3392 
3393 /* ITextPara */
3394 static HRESULT WINAPI TextPara_QueryInterface(ITextPara *iface, REFIID riid, void **ppv)
3395 {
3396     ITextParaImpl *This = impl_from_ITextPara(iface);
3397 
3398     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
3399 
3400     if (IsEqualIID(riid, &IID_ITextPara) ||
3401         IsEqualIID(riid, &IID_IDispatch) ||
3402         IsEqualIID(riid, &IID_IUnknown))
3403     {
3404         *ppv = iface;
3405         ITextPara_AddRef(iface);
3406         return S_OK;
3407     }
3408 
3409     *ppv = NULL;
3410     return E_NOINTERFACE;
3411 }
3412 
3413 static ULONG WINAPI TextPara_AddRef(ITextPara *iface)
3414 {
3415     ITextParaImpl *This = impl_from_ITextPara(iface);
3416     ULONG ref = InterlockedIncrement(&This->ref);
3417     TRACE("(%p)->(%u)\n", This, ref);
3418     return ref;
3419 }
3420 
3421 static ULONG WINAPI TextPara_Release(ITextPara *iface)
3422 {
3423     ITextParaImpl *This = impl_from_ITextPara(iface);
3424     ULONG ref = InterlockedDecrement(&This->ref);
3425 
3426     TRACE("(%p)->(%u)\n", This, ref);
3427 
3428     if (!ref)
3429     {
3430         ITextRange_Release(This->range);
3431         heap_free(This);
3432     }
3433 
3434     return ref;
3435 }
3436 
3437 static IRichEditOleImpl *para_get_reole(ITextParaImpl *This)
3438 {
3439     if (This->range)
3440     {
3441         ITextRangeImpl *rng = impl_from_ITextRange(This->range);
3442         return rng->child.reole;
3443     }
3444     return NULL;
3445 }
3446 
3447 static HRESULT WINAPI TextPara_GetTypeInfoCount(ITextPara *iface, UINT *pctinfo)
3448 {
3449     ITextParaImpl *This = impl_from_ITextPara(iface);
3450     TRACE("(%p)->(%p)\n", This, pctinfo);
3451     *pctinfo = 1;
3452     return S_OK;
3453 }
3454 
3455 static HRESULT WINAPI TextPara_GetTypeInfo(ITextPara *iface, UINT iTInfo, LCID lcid,
3456     ITypeInfo **ppTInfo)
3457 {
3458     ITextParaImpl *This = impl_from_ITextPara(iface);
3459     HRESULT hr;
3460 
3461     TRACE("(%p)->(%u,%d,%p)\n", This, iTInfo, lcid, ppTInfo);
3462 
3463     hr = get_typeinfo(ITextPara_tid, ppTInfo);
3464     if (SUCCEEDED(hr))
3465         ITypeInfo_AddRef(*ppTInfo);
3466     return hr;
3467 }
3468 
3469 static HRESULT WINAPI TextPara_GetIDsOfNames(ITextPara *iface, REFIID riid,
3470     LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
3471 {
3472     ITextParaImpl *This = impl_from_ITextPara(iface);
3473     ITypeInfo *ti;
3474     HRESULT hr;
3475 
3476     TRACE("(%p)->(%s, %p, %u, %d, %p)\n", This, debugstr_guid(riid), rgszNames,
3477             cNames, lcid, rgDispId);
3478 
3479     hr = get_typeinfo(ITextPara_tid, &ti);
3480     if (SUCCEEDED(hr))
3481         hr = ITypeInfo_GetIDsOfNames(ti, rgszNames, cNames, rgDispId);
3482     return hr;
3483 }
3484 
3485 static HRESULT WINAPI TextPara_Invoke(
3486     ITextPara *iface,
3487     DISPID dispIdMember,
3488     REFIID riid,
3489     LCID lcid,
3490     WORD wFlags,
3491     DISPPARAMS *pDispParams,
3492     VARIANT *pVarResult,
3493     EXCEPINFO *pExcepInfo,
3494     UINT *puArgErr)
3495 {
3496     ITextParaImpl *This = impl_from_ITextPara(iface);
3497     ITypeInfo *ti;
3498     HRESULT hr;
3499 
3500     TRACE("(%p)->(%d, %s, %d, %u, %p, %p, %p, %p)\n", This, dispIdMember,
3501             debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult,
3502             pExcepInfo, puArgErr);
3503 
3504     hr = get_typeinfo(ITextPara_tid, &ti);
3505     if (SUCCEEDED(hr))
3506         hr = ITypeInfo_Invoke(ti, iface, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
3507     return hr;
3508 }
3509 
3510 static HRESULT WINAPI TextPara_GetDuplicate(ITextPara *iface, ITextPara **ret)
3511 {
3512     ITextParaImpl *This = impl_from_ITextPara(iface);
3513     FIXME("(%p)->(%p)\n", This, ret);
3514 
3515     if (!para_get_reole(This))
3516         return CO_E_RELEASED;
3517 
3518     return E_NOTIMPL;
3519 }
3520 
3521 static HRESULT WINAPI TextPara_SetDuplicate(ITextPara *iface, ITextPara *para)
3522 {
3523     ITextParaImpl *This = impl_from_ITextPara(iface);
3524     FIXME("(%p)->(%p)\n", This, para);
3525 
3526     if (!para_get_reole(This))
3527         return CO_E_RELEASED;
3528 
3529     return E_NOTIMPL;
3530 }
3531 
3532 static HRESULT WINAPI TextPara_CanChange(ITextPara *iface, LONG *ret)
3533 {
3534     ITextParaImpl *This = impl_from_ITextPara(iface);
3535     FIXME("(%p)->(%p)\n", This, ret);
3536 
3537     if (!para_get_reole(This))
3538         return CO_E_RELEASED;
3539 
3540     return E_NOTIMPL;
3541 }
3542 
3543 static HRESULT WINAPI TextPara_IsEqual(ITextPara *iface, ITextPara *para, LONG *ret)
3544 {
3545     ITextParaImpl *This = impl_from_ITextPara(iface);
3546     FIXME("(%p)->(%p %p)\n", This, para, ret);
3547 
3548     if (!para_get_reole(This))
3549         return CO_E_RELEASED;
3550 
3551     return E_NOTIMPL;
3552 }
3553 
3554 static HRESULT WINAPI TextPara_Reset(ITextPara *iface, LONG value)
3555 {
3556     ITextParaImpl *This = impl_from_ITextPara(iface);
3557     FIXME("(%p)->(%d)\n", This, value);
3558 
3559     if (!para_get_reole(This))
3560         return CO_E_RELEASED;
3561 
3562     return E_NOTIMPL;
3563 }
3564 
3565 static HRESULT WINAPI TextPara_GetStyle(ITextPara *iface, LONG *value)
3566 {
3567     ITextParaImpl *This = impl_from_ITextPara(iface);
3568     FIXME("(%p)->(%p)\n", This, value);
3569 
3570     if (!para_get_reole(This))
3571         return CO_E_RELEASED;
3572 
3573     return E_NOTIMPL;
3574 }
3575 
3576 static HRESULT WINAPI TextPara_SetStyle(ITextPara *iface, LONG value)
3577 {
3578     ITextParaImpl *This = impl_from_ITextPara(iface);
3579     FIXME("(%p)->(%d)\n", This, value);
3580 
3581     if (!para_get_reole(This))
3582         return CO_E_RELEASED;
3583 
3584     return E_NOTIMPL;
3585 }
3586 
3587 static HRESULT WINAPI TextPara_GetAlignment(ITextPara *iface, LONG *value)
3588 {
3589     ITextParaImpl *This = impl_from_ITextPara(iface);
3590     static int once;
3591 
3592     if (!once++) FIXME("(%p)->(%p)\n", This, value);
3593 
3594     if (!para_get_reole(This))
3595         return CO_E_RELEASED;
3596 
3597     return E_NOTIMPL;
3598 }
3599 
3600 static HRESULT WINAPI TextPara_SetAlignment(ITextPara *iface, LONG value)
3601 {
3602     ITextParaImpl *This = impl_from_ITextPara(iface);
3603     FIXME("(%p)->(%d)\n", This, value);
3604 
3605     if (!para_get_reole(This))
3606         return CO_E_RELEASED;
3607 
3608     return E_NOTIMPL;
3609 }
3610 
3611 static HRESULT WINAPI TextPara_GetHyphenation(ITextPara *iface, LONG *value)
3612 {
3613     ITextParaImpl *This = impl_from_ITextPara(iface);
3614     FIXME("(%p)->(%p)\n", This, value);
3615 
3616     if (!para_get_reole(This))
3617         return CO_E_RELEASED;
3618 
3619     return E_NOTIMPL;
3620 }
3621 
3622 static HRESULT WINAPI TextPara_SetHyphenation(ITextPara *iface, LONG value)
3623 {
3624     ITextParaImpl *This = impl_from_ITextPara(iface);
3625     FIXME("(%p)->(%d)\n", This, value);
3626 
3627     if (!para_get_reole(This))
3628         return CO_E_RELEASED;
3629 
3630     return E_NOTIMPL;
3631 }
3632 
3633 static HRESULT WINAPI TextPara_GetFirstLineIndent(ITextPara *iface, FLOAT *value)
3634 {
3635     ITextParaImpl *This = impl_from_ITextPara(iface);
3636     FIXME("(%p)->(%p)\n", This, value);
3637 
3638     if (!para_get_reole(This))
3639         return CO_E_RELEASED;
3640 
3641     return E_NOTIMPL;
3642 }
3643 
3644 static HRESULT WINAPI TextPara_GetKeepTogether(ITextPara *iface, LONG *value)
3645 {
3646     ITextParaImpl *This = impl_from_ITextPara(iface);
3647     FIXME("(%p)->(%p)\n", This, value);
3648 
3649     if (!para_get_reole(This))
3650         return CO_E_RELEASED;
3651 
3652     return E_NOTIMPL;
3653 }
3654 
3655 static HRESULT WINAPI TextPara_SetKeepTogether(ITextPara *iface, LONG value)
3656 {
3657     ITextParaImpl *This = impl_from_ITextPara(iface);
3658     FIXME("(%p)->(%d)\n", This, value);
3659 
3660     if (!para_get_reole(This))
3661         return CO_E_RELEASED;
3662 
3663     return E_NOTIMPL;
3664 }
3665 
3666 static HRESULT WINAPI TextPara_GetKeepWithNext(ITextPara *iface, LONG *value)
3667 {
3668     ITextParaImpl *This = impl_from_ITextPara(iface);
3669     FIXME("(%p)->(%p)\n", This, value);
3670 
3671     if (!para_get_reole(This))
3672         return CO_E_RELEASED;
3673 
3674     return E_NOTIMPL;
3675 }
3676 
3677 static HRESULT WINAPI TextPara_SetKeepWithNext(ITextPara *iface, LONG value)
3678 {
3679     ITextParaImpl *This = impl_from_ITextPara(iface);
3680     FIXME("(%p)->(%d)\n", This, value);
3681 
3682     if (!para_get_reole(This))
3683         return CO_E_RELEASED;
3684 
3685     return E_NOTIMPL;
3686 }
3687 
3688 static HRESULT WINAPI TextPara_GetLeftIndent(ITextPara *iface, FLOAT *value)
3689 {
3690     ITextParaImpl *This = impl_from_ITextPara(iface);
3691     FIXME("(%p)->(%p)\n", This, value);
3692 
3693     if (!para_get_reole(This))
3694         return CO_E_RELEASED;
3695 
3696     return E_NOTIMPL;
3697 }
3698 
3699 static HRESULT WINAPI TextPara_GetLineSpacing(ITextPara *iface, FLOAT *value)
3700 {
3701     ITextParaImpl *This = impl_from_ITextPara(iface);
3702     FIXME("(%p)->(%p)\n", This, value);
3703 
3704     if (!para_get_reole(This))
3705         return CO_E_RELEASED;
3706 
3707     return E_NOTIMPL;
3708 }
3709 
3710 static HRESULT WINAPI TextPara_GetLineSpacingRule(ITextPara *iface, LONG *value)
3711 {
3712     ITextParaImpl *This = impl_from_ITextPara(iface);
3713     FIXME("(%p)->(%p)\n", This, value);
3714 
3715     if (!para_get_reole(This))
3716         return CO_E_RELEASED;
3717 
3718     return E_NOTIMPL;
3719 }
3720 
3721 static HRESULT WINAPI TextPara_GetListAlignment(ITextPara *iface, LONG *value)
3722 {
3723     ITextParaImpl *This = impl_from_ITextPara(iface);
3724     FIXME("(%p)->(%p)\n", This, value);
3725 
3726     if (!para_get_reole(This))
3727         return CO_E_RELEASED;
3728 
3729     return E_NOTIMPL;
3730 }
3731 
3732 static HRESULT WINAPI TextPara_SetListAlignment(ITextPara *iface, LONG value)
3733 {
3734     ITextParaImpl *This = impl_from_ITextPara(iface);
3735     FIXME("(%p)->(%d)\n", This, value);
3736 
3737     if (!para_get_reole(This))
3738         return CO_E_RELEASED;
3739 
3740     return E_NOTIMPL;
3741 }
3742 
3743 static HRESULT WINAPI TextPara_GetListLevelIndex(ITextPara *iface, LONG *value)
3744 {
3745     ITextParaImpl *This = impl_from_ITextPara(iface);
3746     FIXME("(%p)->(%p)\n", This, value);
3747 
3748     if (!para_get_reole(This))
3749         return CO_E_RELEASED;
3750 
3751     return E_NOTIMPL;
3752 }
3753 
3754 static HRESULT WINAPI TextPara_SetListLevelIndex(ITextPara *iface, LONG value)
3755 {
3756     ITextParaImpl *This = impl_from_ITextPara(iface);
3757     FIXME("(%p)->(%d)\n", This, value);
3758 
3759     if (!para_get_reole(This))
3760         return CO_E_RELEASED;
3761 
3762     return E_NOTIMPL;
3763 }
3764 
3765 static HRESULT WINAPI TextPara_GetListStart(ITextPara *iface, LONG *value)
3766 {
3767     ITextParaImpl *This = impl_from_ITextPara(iface);
3768     FIXME("(%p)->(%p)\n", This, value);
3769 
3770     if (!para_get_reole(This))
3771         return CO_E_RELEASED;
3772 
3773     return E_NOTIMPL;
3774 }
3775 
3776 static HRESULT WINAPI TextPara_SetListStart(ITextPara *iface, LONG value)
3777 {
3778     ITextParaImpl *This = impl_from_ITextPara(iface);
3779     FIXME("(%p)->(%d)\n", This, value);
3780 
3781     if (!para_get_reole(This))
3782         return CO_E_RELEASED;
3783 
3784     return E_NOTIMPL;
3785 }
3786 
3787 static HRESULT WINAPI TextPara_GetListTab(ITextPara *iface, FLOAT *value)
3788 {
3789     ITextParaImpl *This = impl_from_ITextPara(iface);
3790     FIXME("(%p)->(%p)\n", This, value);
3791 
3792     if (!para_get_reole(This))
3793         return CO_E_RELEASED;
3794 
3795     return E_NOTIMPL;
3796 }
3797 
3798 static HRESULT WINAPI TextPara_SetListTab(ITextPara *iface, FLOAT value)
3799 {
3800     ITextParaImpl *This = impl_from_ITextPara(iface);
3801     FIXME("(%p)->(%.2f)\n", This, value);
3802 
3803     if (!para_get_reole(This))
3804         return CO_E_RELEASED;
3805 
3806     return E_NOTIMPL;
3807 }
3808 
3809 static HRESULT WINAPI TextPara_GetListType(ITextPara *iface, LONG *value)
3810 {
3811     ITextParaImpl *This = impl_from_ITextPara(iface);
3812     FIXME("(%p)->(%p)\n", This, value);
3813 
3814     if (!para_get_reole(This))
3815         return CO_E_RELEASED;
3816 
3817     return E_NOTIMPL;
3818 }
3819 
3820 static HRESULT WINAPI TextPara_SetListType(ITextPara *iface, LONG value)
3821 {
3822     ITextParaImpl *This = impl_from_ITextPara(iface);
3823     FIXME("(%p)->(%d)\n", This, value);
3824 
3825     if (!para_get_reole(This))
3826         return CO_E_RELEASED;
3827 
3828     return E_NOTIMPL;
3829 }
3830 
3831 static HRESULT WINAPI TextPara_GetNoLineNumber(ITextPara *iface, LONG *value)
3832 {
3833     ITextParaImpl *This = impl_from_ITextPara(iface);
3834     FIXME("(%p)->(%p)\n", This, value);
3835 
3836     if (!para_get_reole(This))
3837         return CO_E_RELEASED;
3838 
3839     return E_NOTIMPL;
3840 }
3841 
3842 static HRESULT WINAPI TextPara_SetNoLineNumber(ITextPara *iface, LONG value)
3843 {
3844     ITextParaImpl *This = impl_from_ITextPara(iface);
3845     FIXME("(%p)->(%d)\n", This, value);
3846 
3847     if (!para_get_reole(This))
3848         return CO_E_RELEASED;
3849 
3850     return E_NOTIMPL;
3851 }
3852 
3853 static HRESULT WINAPI TextPara_GetPageBreakBefore(ITextPara *iface, LONG *value)
3854 {
3855     ITextParaImpl *This = impl_from_ITextPara(iface);
3856     FIXME("(%p)->(%p)\n", This, value);
3857 
3858     if (!para_get_reole(This))
3859         return CO_E_RELEASED;
3860 
3861     return E_NOTIMPL;
3862 }
3863 
3864 static HRESULT WINAPI TextPara_SetPageBreakBefore(ITextPara *iface, LONG value)
3865 {
3866     ITextParaImpl *This = impl_from_ITextPara(iface);
3867     FIXME("(%p)->(%d)\n", This, value);
3868 
3869     if (!para_get_reole(This))
3870         return CO_E_RELEASED;
3871 
3872     return E_NOTIMPL;
3873 }
3874 
3875 static HRESULT WINAPI TextPara_GetRightIndent(ITextPara *iface, FLOAT *value)
3876 {
3877     ITextParaImpl *This = impl_from_ITextPara(iface);
3878     FIXME("(%p)->(%p)\n", This, value);
3879 
3880     if (!para_get_reole(This))
3881         return CO_E_RELEASED;
3882 
3883     return E_NOTIMPL;
3884 }
3885 
3886 static HRESULT WINAPI TextPara_SetRightIndent(ITextPara *iface, FLOAT value)
3887 {
3888     ITextParaImpl *This = impl_from_ITextPara(iface);
3889     FIXME("(%p)->(%.2f)\n", This, value);
3890 
3891     if (!para_get_reole(This))
3892         return CO_E_RELEASED;
3893 
3894     return E_NOTIMPL;
3895 }
3896 
3897 static HRESULT WINAPI TextPara_SetIndents(ITextPara *iface, FLOAT StartIndent, FLOAT LeftIndent, FLOAT RightIndent)
3898 {
3899     ITextParaImpl *This = impl_from_ITextPara(iface);
3900     FIXME("(%p)->(%.2f %.2f %.2f)\n", This, StartIndent, LeftIndent, RightIndent);
3901 
3902     if (!para_get_reole(This))
3903         return CO_E_RELEASED;
3904 
3905     return E_NOTIMPL;
3906 }
3907 
3908 static HRESULT WINAPI TextPara_SetLineSpacing(ITextPara *iface, LONG LineSpacingRule, FLOAT LineSpacing)
3909 {
3910     ITextParaImpl *This = impl_from_ITextPara(iface);
3911     FIXME("(%p)->(%d %.2f)\n", This, LineSpacingRule, LineSpacing);
3912 
3913     if (!para_get_reole(This))
3914         return CO_E_RELEASED;
3915 
3916     return E_NOTIMPL;
3917 }
3918 
3919 static HRESULT WINAPI TextPara_GetSpaceAfter(ITextPara *iface, FLOAT *value)
3920 {
3921     ITextParaImpl *This = impl_from_ITextPara(iface);
3922     FIXME("(%p)->(%p)\n", This, value);
3923 
3924     if (!para_get_reole(This))
3925         return CO_E_RELEASED;
3926 
3927     return E_NOTIMPL;
3928 }
3929 
3930 static HRESULT WINAPI TextPara_SetSpaceAfter(ITextPara *iface, FLOAT value)
3931 {
3932     ITextParaImpl *This = impl_from_ITextPara(iface);
3933     FIXME("(%p)->(%.2f)\n", This, value);
3934 
3935     if (!para_get_reole(This))
3936         return CO_E_RELEASED;
3937 
3938     return E_NOTIMPL;
3939 }
3940 
3941 static HRESULT WINAPI TextPara_GetSpaceBefore(ITextPara *iface, FLOAT *value)
3942 {
3943     ITextParaImpl *This = impl_from_ITextPara(iface);
3944     FIXME("(%p)->(%p)\n", This, value);
3945 
3946     if (!para_get_reole(This))
3947         return CO_E_RELEASED;
3948 
3949     return E_NOTIMPL;
3950 }
3951 
3952 static HRESULT WINAPI TextPara_SetSpaceBefore(ITextPara *iface, FLOAT value)
3953 {
3954     ITextParaImpl *This = impl_from_ITextPara(iface);
3955     FIXME("(%p)->(%.2f)\n", This, value);
3956 
3957     if (!para_get_reole(This))
3958         return CO_E_RELEASED;
3959 
3960     return E_NOTIMPL;
3961 }
3962 
3963 static HRESULT WINAPI TextPara_GetWidowControl(ITextPara *iface, LONG *value)
3964 {
3965     ITextParaImpl *This = impl_from_ITextPara(iface);
3966     FIXME("(%p)->(%p)\n", This, value);
3967 
3968     if (!para_get_reole(This))
3969         return CO_E_RELEASED;
3970 
3971     return E_NOTIMPL;
3972 }
3973 
3974 static HRESULT WINAPI TextPara_SetWidowControl(ITextPara *iface, LONG value)
3975 {
3976     ITextParaImpl *This = impl_from_ITextPara(iface);
3977     FIXME("(%p)->(%d)\n", This, value);
3978 
3979     if (!para_get_reole(This))
3980         return CO_E_RELEASED;
3981 
3982     return E_NOTIMPL;
3983 }
3984 
3985 static HRESULT WINAPI TextPara_GetTabCount(ITextPara *iface, LONG *value)
3986 {
3987     ITextParaImpl *This = impl_from_ITextPara(iface);
3988     FIXME("(%p)->(%p)\n", This, value);
3989 
3990     if (!para_get_reole(This))
3991         return CO_E_RELEASED;
3992 
3993     return E_NOTIMPL;
3994 }
3995 
3996 static HRESULT WINAPI TextPara_AddTab(ITextPara *iface, FLOAT tbPos, LONG tbAlign, LONG tbLeader)
3997 {
3998     ITextParaImpl *This = impl_from_ITextPara(iface);
3999     FIXME("(%p)->(%.2f %d %d)\n", This, tbPos, tbAlign, tbLeader);
4000 
4001     if (!para_get_reole(This))
4002         return CO_E_RELEASED;
4003 
4004     return E_NOTIMPL;
4005 }
4006 
4007 static HRESULT WINAPI TextPara_ClearAllTabs(ITextPara *iface)
4008 {
4009     ITextParaImpl *This = impl_from_ITextPara(iface);
4010     FIXME("(%p)\n", This);
4011 
4012     if (!para_get_reole(This))
4013         return CO_E_RELEASED;
4014 
4015     return E_NOTIMPL;
4016 }
4017 
4018 static HRESULT WINAPI TextPara_DeleteTab(ITextPara *iface, FLOAT pos)
4019 {
4020     ITextParaImpl *This = impl_from_ITextPara(iface);
4021     FIXME("(%p)->(%.2f)\n", This, pos);
4022 
4023     if (!para_get_reole(This))
4024         return CO_E_RELEASED;
4025 
4026     return E_NOTIMPL;
4027 }
4028 
4029 static HRESULT WINAPI TextPara_GetTab(ITextPara *iface, LONG iTab, FLOAT *ptbPos, LONG *ptbAlign, LONG *ptbLeader)
4030 {
4031     ITextParaImpl *This = impl_from_ITextPara(iface);
4032     FIXME("(%p)->(%d %p %p %p)\n", This, iTab, ptbPos, ptbAlign, ptbLeader);
4033 
4034     if (!para_get_reole(This))
4035         return CO_E_RELEASED;
4036 
4037     return E_NOTIMPL;
4038 }
4039 
4040 static ITextParaVtbl textparavtbl = {
4041     TextPara_QueryInterface,
4042     TextPara_AddRef,
4043     TextPara_Release,
4044     TextPara_GetTypeInfoCount,
4045     TextPara_GetTypeInfo,
4046     TextPara_GetIDsOfNames,
4047     TextPara_Invoke,
4048     TextPara_GetDuplicate,
4049     TextPara_SetDuplicate,
4050     TextPara_CanChange,
4051     TextPara_IsEqual,
4052     TextPara_Reset,
4053     TextPara_GetStyle,
4054     TextPara_SetStyle,
4055     TextPara_GetAlignment,
4056     TextPara_SetAlignment,
4057     TextPara_GetHyphenation,
4058     TextPara_SetHyphenation,
4059     TextPara_GetFirstLineIndent,
4060     TextPara_GetKeepTogether,
4061     TextPara_SetKeepTogether,
4062     TextPara_GetKeepWithNext,
4063     TextPara_SetKeepWithNext,
4064     TextPara_GetLeftIndent,
4065     TextPara_GetLineSpacing,
4066     TextPara_GetLineSpacingRule,
4067     TextPara_GetListAlignment,
4068     TextPara_SetListAlignment,
4069     TextPara_GetListLevelIndex,
4070     TextPara_SetListLevelIndex,
4071     TextPara_GetListStart,
4072     TextPara_SetListStart,
4073     TextPara_GetListTab,
4074     TextPara_SetListTab,
4075     TextPara_GetListType,
4076     TextPara_SetListType,
4077     TextPara_GetNoLineNumber,
4078     TextPara_SetNoLineNumber,
4079     TextPara_GetPageBreakBefore,
4080     TextPara_SetPageBreakBefore,
4081     TextPara_GetRightIndent,
4082     TextPara_SetRightIndent,
4083     TextPara_SetIndents,
4084     TextPara_SetLineSpacing,
4085     TextPara_GetSpaceAfter,
4086     TextPara_SetSpaceAfter,
4087     TextPara_GetSpaceBefore,
4088     TextPara_SetSpaceBefore,
4089     TextPara_GetWidowControl,
4090     TextPara_SetWidowControl,
4091     TextPara_GetTabCount,
4092     TextPara_AddTab,
4093     TextPara_ClearAllTabs,
4094     TextPara_DeleteTab,
4095     TextPara_GetTab
4096 };
4097 
4098 static HRESULT create_textpara(ITextRange *range, ITextPara **ret)
4099 {
4100     ITextParaImpl *para;
4101 
4102     *ret = NULL;
4103     para = heap_alloc(sizeof(*para));
4104     if (!para)
4105         return E_OUTOFMEMORY;
4106 
4107     para->ITextPara_iface.lpVtbl = &textparavtbl;
4108     para->ref = 1;
4109     para->range = range;
4110     ITextRange_AddRef(range);
4111 
4112     *ret = &para->ITextPara_iface;
4113     return S_OK;
4114 }
4115 
4116 /* ITextDocument */
4117 static HRESULT WINAPI
4118 ITextDocument_fnQueryInterface(ITextDocument* me, REFIID riid,
4119     void** ppvObject)
4120 {
4121     IRichEditOleImpl *This = impl_from_ITextDocument(me);
4122     return IRichEditOle_QueryInterface(&This->IRichEditOle_iface, riid, ppvObject);
4123 }
4124 
4125 static ULONG WINAPI
4126 ITextDocument_fnAddRef(ITextDocument* me)
4127 {
4128     IRichEditOleImpl *This = impl_from_ITextDocument(me);
4129     return IRichEditOle_AddRef(&This->IRichEditOle_iface);
4130 }
4131 
4132 static ULONG WINAPI
4133 ITextDocument_fnRelease(ITextDocument* me)
4134 {
4135     IRichEditOleImpl *This = impl_from_ITextDocument(me);
4136     return IRichEditOle_Release(&This->IRichEditOle_iface);
4137 }
4138 
4139 static HRESULT WINAPI
4140 ITextDocument_fnGetTypeInfoCount(ITextDocument* me,
4141     UINT* pctinfo)
4142 {
4143     IRichEditOleImpl *This = impl_from_ITextDocument(me);
4144     TRACE("(%p)->(%p)\n", This, pctinfo);
4145     *pctinfo = 1;
4146     return S_OK;
4147 }
4148 
4149 static HRESULT WINAPI
4150 ITextDocument_fnGetTypeInfo(ITextDocument* me, UINT iTInfo, LCID lcid,
4151     ITypeInfo** ppTInfo)
4152 {
4153     IRichEditOleImpl *This = impl_from_ITextDocument(me);
4154     HRESULT hr;
4155 
4156     TRACE("(%p)->(%u,%d,%p)\n", This, iTInfo, lcid, ppTInfo);
4157 
4158     hr = get_typeinfo(ITextDocument_tid, ppTInfo);
4159     if (SUCCEEDED(hr))
4160         ITypeInfo_AddRef(*ppTInfo);
4161     return hr;
4162 }
4163 
4164 static HRESULT WINAPI
4165 ITextDocument_fnGetIDsOfNames(ITextDocument* me, REFIID riid,
4166     LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId)
4167 {
4168     IRichEditOleImpl *This = impl_from_ITextDocument(me);
4169     ITypeInfo *ti;
4170     HRESULT hr;
4171 
4172     TRACE("(%p)->(%s, %p, %u, %d, %p)\n", This, debugstr_guid(riid),
4173             rgszNames, cNames, lcid, rgDispId);
4174 
4175     hr = get_typeinfo(ITextDocument_tid, &ti);
4176     if (SUCCEEDED(hr))
4177         hr = ITypeInfo_GetIDsOfNames(ti, rgszNames, cNames, rgDispId);
4178     return hr;
4179 }
4180 
4181 static HRESULT WINAPI
4182 ITextDocument_fnInvoke(ITextDocument* me, DISPID dispIdMember,
4183     REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
4184     VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
4185 {
4186     IRichEditOleImpl *This = impl_from_ITextDocument(me);
4187     ITypeInfo *ti;
4188     HRESULT hr;
4189 
4190     TRACE("(%p)->(%d, %s, %d, %u, %p, %p, %p, %p)\n", This, dispIdMember,
4191             debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult,
4192             pExcepInfo, puArgErr);
4193 
4194     hr = get_typeinfo(ITextDocument_tid, &ti);
4195     if (SUCCEEDED(hr))
4196         hr = ITypeInfo_Invoke(ti, me, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
4197     return hr;
4198 }
4199 
4200 static HRESULT WINAPI
4201 ITextDocument_fnGetName(ITextDocument* me, BSTR* pName)
4202 {
4203     IRichEditOleImpl *This = impl_from_ITextDocument(me);
4204     FIXME("stub %p\n",This);
4205     return E_NOTIMPL;
4206 }
4207 
4208 static HRESULT WINAPI
4209 ITextDocument_fnGetSelection(ITextDocument *me, ITextSelection **selection)
4210 {
4211     IRichEditOleImpl *This = impl_from_ITextDocument(me);
4212 
4213     TRACE("(%p)->(%p)\n", me, selection);
4214 
4215     if (!selection)
4216       return E_INVALIDARG;
4217 
4218     if (!This->txtSel) {
4219       This->txtSel = CreateTextSelection(This);
4220       if (!This->txtSel) {
4221         *selection = NULL;
4222         return E_OUTOFMEMORY;
4223       }
4224     }
4225 
4226     *selection = &This->txtSel->ITextSelection_iface;
4227     ITextSelection_AddRef(*selection);
4228     return S_OK;
4229 }
4230 
4231 static HRESULT WINAPI
4232 ITextDocument_fnGetStoryCount(ITextDocument* me, LONG* pCount)
4233 {
4234     IRichEditOleImpl *This = impl_from_ITextDocument(me);
4235     FIXME("stub %p\n",This);
4236     return E_NOTIMPL;
4237 }
4238 
4239 static HRESULT WINAPI
4240 ITextDocument_fnGetStoryRanges(ITextDocument* me,
4241     ITextStoryRanges** ppStories)
4242 {
4243     IRichEditOleImpl *This = impl_from_ITextDocument(me);
4244     FIXME("stub %p\n",This);
4245     return E_NOTIMPL;
4246 }
4247 
4248 static HRESULT WINAPI
4249 ITextDocument_fnGetSaved(ITextDocument* me, LONG* pValue)
4250 {
4251     IRichEditOleImpl *This = impl_from_ITextDocument(me);
4252     FIXME("stub %p\n",This);
4253     return E_NOTIMPL;
4254 }
4255 
4256 static HRESULT WINAPI
4257 ITextDocument_fnSetSaved(ITextDocument* me, LONG Value)
4258 {
4259     IRichEditOleImpl *This = impl_from_ITextDocument(me);
4260     FIXME("stub %p\n",This);
4261     return E_NOTIMPL;
4262 }
4263 
4264 static HRESULT WINAPI
4265 ITextDocument_fnGetDefaultTabStop(ITextDocument* me, float* pValue)
4266 {
4267     IRichEditOleImpl *This = impl_from_ITextDocument(me);
4268     FIXME("stub %p\n",This);
4269     return E_NOTIMPL;
4270 }
4271 
4272 static HRESULT WINAPI
4273 ITextDocument_fnSetDefaultTabStop(ITextDocument* me, float Value)
4274 {
4275     IRichEditOleImpl *This = impl_from_ITextDocument(me);
4276     FIXME("stub %p\n",This);
4277     return E_NOTIMPL;
4278 }
4279 
4280 static HRESULT WINAPI
4281 ITextDocument_fnNew(ITextDocument* me)
4282 {
4283     IRichEditOleImpl *This = impl_from_ITextDocument(me);
4284     FIXME("stub %p\n",This);
4285     return E_NOTIMPL;
4286 }
4287 
4288 static HRESULT WINAPI
4289 ITextDocument_fnOpen(ITextDocument* me, VARIANT* pVar, LONG Flags,
4290     LONG CodePage)
4291 {
4292     IRichEditOleImpl *This = impl_from_ITextDocument(me);
4293     FIXME("stub %p\n",This);
4294     return E_NOTIMPL;
4295 }
4296 
4297 static HRESULT WINAPI
4298 ITextDocument_fnSave(ITextDocument* me, VARIANT* pVar, LONG Flags,
4299     LONG CodePage)
4300 {
4301     IRichEditOleImpl *This = impl_from_ITextDocument(me);
4302     FIXME("stub %p\n",This);
4303     return E_NOTIMPL;
4304 }
4305 
4306 static HRESULT WINAPI
4307 ITextDocument_fnFreeze(ITextDocument* me, LONG* pCount)
4308 {
4309     IRichEditOleImpl *This = impl_from_ITextDocument(me);
4310     FIXME("stub %p\n",This);
4311     return E_NOTIMPL;
4312 }
4313 
4314 static HRESULT WINAPI
4315 ITextDocument_fnUnfreeze(ITextDocument* me, LONG* pCount)
4316 {
4317     IRichEditOleImpl *This = impl_from_ITextDocument(me);
4318     FIXME("stub %p\n",This);
4319     return E_NOTIMPL;
4320 }
4321 
4322 static HRESULT WINAPI
4323 ITextDocument_fnBeginEditCollection(ITextDocument* me)
4324 {
4325     IRichEditOleImpl *This = impl_from_ITextDocument(me);
4326     FIXME("stub %p\n",This);
4327     return E_NOTIMPL;
4328 }
4329 
4330 static HRESULT WINAPI
4331 ITextDocument_fnEndEditCollection(ITextDocument* me)
4332 {
4333     IRichEditOleImpl *This = impl_from_ITextDocument(me);
4334     FIXME("stub %p\n",This);
4335     return E_NOTIMPL;
4336 }
4337 
4338 static HRESULT WINAPI
4339 ITextDocument_fnUndo(ITextDocument* me, LONG Count, LONG* prop)
4340 {
4341     IRichEditOleImpl *This = impl_from_ITextDocument(me);
4342     FIXME("stub %p\n",This);
4343     return E_NOTIMPL;
4344 }
4345 
4346 static HRESULT WINAPI
4347 ITextDocument_fnRedo(ITextDocument* me, LONG Count, LONG* prop)
4348 {
4349     IRichEditOleImpl *This = impl_from_ITextDocument(me);
4350     FIXME("stub %p\n",This);
4351     return E_NOTIMPL;
4352 }
4353 
4354 static HRESULT CreateITextRange(IRichEditOleImpl *reOle, LONG start, LONG end, ITextRange** ppRange)
4355 {
4356     ITextRangeImpl *txtRge = heap_alloc(sizeof(ITextRangeImpl));
4357 
4358     if (!txtRge)
4359         return E_OUTOFMEMORY;
4360     txtRge->ITextRange_iface.lpVtbl = &trvt;
4361     txtRge->ref = 1;
4362     txtRge->child.reole = reOle;
4363     txtRge->start = start;
4364     txtRge->end = end;
4365     list_add_head(&reOle->rangelist, &txtRge->child.entry);
4366     *ppRange = &txtRge->ITextRange_iface;
4367     return S_OK;
4368 }
4369 
4370 static HRESULT WINAPI
4371 ITextDocument_fnRange(ITextDocument* me, LONG cp1, LONG cp2,
4372     ITextRange** ppRange)
4373 {
4374     IRichEditOleImpl *This = impl_from_ITextDocument(me);
4375 
4376     TRACE("%p %p %d %d\n", This, ppRange, cp1, cp2);
4377     if (!ppRange)
4378         return E_INVALIDARG;
4379 
4380     cp2range(This->editor, &cp1, &cp2);
4381     return CreateITextRange(This, cp1, cp2, ppRange);
4382 }
4383 
4384 static HRESULT WINAPI
4385 ITextDocument_fnRangeFromPoint(ITextDocument* me, LONG x, LONG y,
4386     ITextRange** ppRange)
4387 {
4388     IRichEditOleImpl *This = impl_from_ITextDocument(me);
4389     FIXME("stub %p\n",This);
4390     return E_NOTIMPL;
4391 }
4392 
4393 static const ITextDocumentVtbl tdvt = {
4394     ITextDocument_fnQueryInterface,
4395     ITextDocument_fnAddRef,
4396     ITextDocument_fnRelease,
4397     ITextDocument_fnGetTypeInfoCount,
4398     ITextDocument_fnGetTypeInfo,
4399     ITextDocument_fnGetIDsOfNames,
4400     ITextDocument_fnInvoke,
4401     ITextDocument_fnGetName,
4402     ITextDocument_fnGetSelection,
4403     ITextDocument_fnGetStoryCount,
4404     ITextDocument_fnGetStoryRanges,
4405     ITextDocument_fnGetSaved,
4406     ITextDocument_fnSetSaved,
4407     ITextDocument_fnGetDefaultTabStop,
4408     ITextDocument_fnSetDefaultTabStop,
4409     ITextDocument_fnNew,
4410     ITextDocument_fnOpen,
4411     ITextDocument_fnSave,
4412     ITextDocument_fnFreeze,
4413     ITextDocument_fnUnfreeze,
4414     ITextDocument_fnBeginEditCollection,
4415     ITextDocument_fnEndEditCollection,
4416     ITextDocument_fnUndo,
4417     ITextDocument_fnRedo,
4418     ITextDocument_fnRange,
4419     ITextDocument_fnRangeFromPoint
4420 };
4421 
4422 /* ITextSelection */
4423 static HRESULT WINAPI ITextSelection_fnQueryInterface(
4424     ITextSelection *me,
4425     REFIID riid,
4426     void **ppvObj)
4427 {
4428     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4429 
4430     *ppvObj = NULL;
4431     if (IsEqualGUID(riid, &IID_IUnknown)
4432         || IsEqualGUID(riid, &IID_IDispatch)
4433         || IsEqualGUID(riid, &IID_ITextRange)
4434         || IsEqualGUID(riid, &IID_ITextSelection))
4435     {
4436         *ppvObj = me;
4437         ITextSelection_AddRef(me);
4438         return S_OK;
4439     }
4440     else if (IsEqualGUID(riid, &IID_Igetrichole))
4441     {
4442         *ppvObj = This->reOle;
4443         return S_OK;
4444     }
4445 
4446     return E_NOINTERFACE;
4447 }
4448 
4449 static ULONG WINAPI ITextSelection_fnAddRef(ITextSelection *me)
4450 {
4451     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4452     return InterlockedIncrement(&This->ref);
4453 }
4454 
4455 static ULONG WINAPI ITextSelection_fnRelease(ITextSelection *me)
4456 {
4457     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4458     ULONG ref = InterlockedDecrement(&This->ref);
4459     if (ref == 0)
4460         heap_free(This);
4461     return ref;
4462 }
4463 
4464 static HRESULT WINAPI ITextSelection_fnGetTypeInfoCount(ITextSelection *me, UINT *pctinfo)
4465 {
4466     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4467     TRACE("(%p)->(%p)\n", This, pctinfo);
4468     *pctinfo = 1;
4469     return S_OK;
4470 }
4471 
4472 static HRESULT WINAPI ITextSelection_fnGetTypeInfo(ITextSelection *me, UINT iTInfo, LCID lcid,
4473     ITypeInfo **ppTInfo)
4474 {
4475     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4476     HRESULT hr;
4477 
4478     TRACE("(%p)->(%u,%d,%p)\n", This, iTInfo, lcid, ppTInfo);
4479 
4480     hr = get_typeinfo(ITextSelection_tid, ppTInfo);
4481     if (SUCCEEDED(hr))
4482         ITypeInfo_AddRef(*ppTInfo);
4483     return hr;
4484 }
4485 
4486 static HRESULT WINAPI ITextSelection_fnGetIDsOfNames(ITextSelection *me, REFIID riid,
4487     LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
4488 {
4489     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4490     ITypeInfo *ti;
4491     HRESULT hr;
4492 
4493     TRACE("(%p)->(%s, %p, %u, %d, %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid,
4494             rgDispId);
4495 
4496     hr = get_typeinfo(ITextSelection_tid, &ti);
4497     if (SUCCEEDED(hr))
4498         hr = ITypeInfo_GetIDsOfNames(ti, rgszNames, cNames, rgDispId);
4499     return hr;
4500 }
4501 
4502 static HRESULT WINAPI ITextSelection_fnInvoke(
4503     ITextSelection *me,
4504     DISPID dispIdMember,
4505     REFIID riid,
4506     LCID lcid,
4507     WORD wFlags,
4508     DISPPARAMS *pDispParams,
4509     VARIANT *pVarResult,
4510     EXCEPINFO *pExcepInfo,
4511     UINT *puArgErr)
4512 {
4513     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4514     ITypeInfo *ti;
4515     HRESULT hr;
4516 
4517     TRACE("(%p)->(%d, %s, %d, %u, %p, %p, %p, %p)\n", This, dispIdMember, debugstr_guid(riid), lcid,
4518             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
4519 
4520     hr = get_typeinfo(ITextSelection_tid, &ti);
4521     if (SUCCEEDED(hr))
4522         hr = ITypeInfo_Invoke(ti, me, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
4523     return hr;
4524 }
4525 
4526 /*** ITextRange methods ***/
4527 static HRESULT WINAPI ITextSelection_fnGetText(ITextSelection *me, BSTR *pbstr)
4528 {
4529     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4530     ME_Cursor *start = NULL, *end = NULL;
4531     int nChars, endOfs;
4532     BOOL bEOP;
4533 
4534     TRACE("(%p)->(%p)\n", This, pbstr);
4535 
4536     if (!This->reOle)
4537         return CO_E_RELEASED;
4538 
4539     if (!pbstr)
4540         return E_INVALIDARG;
4541 
4542     ME_GetSelection(This->reOle->editor, &start, &end);
4543     endOfs = ME_GetCursorOfs(end);
4544     nChars = endOfs - ME_GetCursorOfs(start);
4545     if (!nChars)
4546     {
4547         *pbstr = NULL;
4548         return S_OK;
4549     }
4550 
4551     *pbstr = SysAllocStringLen(NULL, nChars);
4552     if (!*pbstr)
4553         return E_OUTOFMEMORY;
4554 
4555     bEOP = (end->pRun->next->type == diTextEnd && endOfs > ME_GetTextLength(This->reOle->editor));
4556     ME_GetTextW(This->reOle->editor, *pbstr, nChars, start, nChars, FALSE, bEOP);
4557     TRACE("%s\n", wine_dbgstr_w(*pbstr));
4558 
4559     return S_OK;
4560 }
4561 
4562 static HRESULT WINAPI ITextSelection_fnSetText(ITextSelection *me, BSTR str)
4563 {
4564     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4565     ME_TextEditor *editor;
4566     int len, to, from;
4567 
4568     TRACE("(%p)->(%s)\n", This, debugstr_w(str));
4569 
4570     if (!This->reOle)
4571         return CO_E_RELEASED;
4572 
4573     editor = This->reOle->editor;
4574     len = strlenW(str);
4575     ME_GetSelectionOfs(editor, &from, &to);
4576     ME_ReplaceSel(editor, FALSE, str, len);
4577 
4578     if (len < to - from)
4579         textranges_update_ranges(This->reOle, from, len, RANGE_UPDATE_DELETE);
4580 
4581     return S_OK;
4582 }
4583 
4584 static HRESULT WINAPI ITextSelection_fnGetChar(ITextSelection *me, LONG *pch)
4585 {
4586     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4587     ME_Cursor *start = NULL, *end = NULL;
4588 
4589     TRACE("(%p)->(%p)\n", This, pch);
4590 
4591     if (!This->reOle)
4592         return CO_E_RELEASED;
4593 
4594     if (!pch)
4595         return E_INVALIDARG;
4596 
4597     ME_GetSelection(This->reOle->editor, &start, &end);
4598     return range_GetChar(This->reOle->editor, start, pch);
4599 }
4600 
4601 static HRESULT WINAPI ITextSelection_fnSetChar(ITextSelection *me, LONG ch)
4602 {
4603     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4604 
4605     FIXME("(%p)->(%x): stub\n", This, ch);
4606 
4607     if (!This->reOle)
4608         return CO_E_RELEASED;
4609 
4610     return E_NOTIMPL;
4611 }
4612 
4613 static HRESULT WINAPI ITextSelection_fnGetDuplicate(ITextSelection *me, ITextRange **range)
4614 {
4615     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4616     LONG start, end;
4617 
4618     TRACE("(%p)->(%p)\n", This, range);
4619 
4620     if (!This->reOle)
4621         return CO_E_RELEASED;
4622 
4623     if (!range)
4624         return E_INVALIDARG;
4625 
4626     ITextSelection_GetStart(me, &start);
4627     ITextSelection_GetEnd(me, &end);
4628     return CreateITextRange(This->reOle, start, end, range);
4629 }
4630 
4631 static HRESULT WINAPI ITextSelection_fnGetFormattedText(ITextSelection *me, ITextRange **range)
4632 {
4633     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4634 
4635     FIXME("(%p)->(%p): stub\n", This, range);
4636 
4637     if (!This->reOle)
4638         return CO_E_RELEASED;
4639 
4640     return E_NOTIMPL;
4641 }
4642 
4643 static HRESULT WINAPI ITextSelection_fnSetFormattedText(ITextSelection *me, ITextRange *range)
4644 {
4645     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4646 
4647     FIXME("(%p)->(%p): stub\n", This, range);
4648 
4649     if (!This->reOle)
4650         return CO_E_RELEASED;
4651 
4652     FIXME("not implemented\n");
4653     return E_NOTIMPL;
4654 }
4655 
4656 static HRESULT WINAPI ITextSelection_fnGetStart(ITextSelection *me, LONG *pcpFirst)
4657 {
4658     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4659     LONG lim;
4660 
4661     TRACE("(%p)->(%p)\n", This, pcpFirst);
4662 
4663     if (!This->reOle)
4664         return CO_E_RELEASED;
4665 
4666     if (!pcpFirst)
4667         return E_INVALIDARG;
4668     ME_GetSelectionOfs(This->reOle->editor, pcpFirst, &lim);
4669     return S_OK;
4670 }
4671 
4672 static HRESULT WINAPI ITextSelection_fnSetStart(ITextSelection *me, LONG value)
4673 {
4674     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4675     LONG start, end;
4676     HRESULT hr;
4677 
4678     TRACE("(%p)->(%d)\n", This, value);
4679 
4680     if (!This->reOle)
4681         return CO_E_RELEASED;
4682 
4683     ME_GetSelectionOfs(This->reOle->editor, &start, &end);
4684     hr = textrange_setstart(This->reOle, value, &start, &end);
4685     if (hr == S_OK)
4686         ME_SetSelection(This->reOle->editor, start, end);
4687 
4688     return hr;
4689 }
4690 
4691 static HRESULT WINAPI ITextSelection_fnGetEnd(ITextSelection *me, LONG *pcpLim)
4692 {
4693     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4694     LONG first;
4695 
4696     TRACE("(%p)->(%p)\n", This, pcpLim);
4697 
4698     if (!This->reOle)
4699         return CO_E_RELEASED;
4700 
4701     if (!pcpLim)
4702         return E_INVALIDARG;
4703     ME_GetSelectionOfs(This->reOle->editor, &first, pcpLim);
4704     return S_OK;
4705 }
4706 
4707 static HRESULT WINAPI ITextSelection_fnSetEnd(ITextSelection *me, LONG value)
4708 {
4709     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4710     LONG start, end;
4711     HRESULT hr;
4712 
4713     TRACE("(%p)->(%d)\n", This, value);
4714 
4715     if (!This->reOle)
4716         return CO_E_RELEASED;
4717 
4718     ME_GetSelectionOfs(This->reOle->editor, &start, &end);
4719     hr = textrange_setend(This->reOle, value, &start, &end);
4720     if (hr == S_OK)
4721         ME_SetSelection(This->reOle->editor, start, end);
4722 
4723     return hr;
4724 }
4725 
4726 static HRESULT WINAPI ITextSelection_fnGetFont(ITextSelection *me, ITextFont **font)
4727 {
4728     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4729     ITextRange *range = NULL;
4730     HRESULT hr;
4731 
4732     TRACE("(%p)->(%p)\n", This, font);
4733 
4734     if (!This->reOle)
4735         return CO_E_RELEASED;
4736 
4737     if (!font)
4738         return E_INVALIDARG;
4739 
4740     ITextSelection_QueryInterface(me, &IID_ITextRange, (void**)&range);
4741     hr = create_textfont(range, NULL, font);
4742     ITextRange_Release(range);
4743     return hr;
4744 }
4745 
4746 static HRESULT WINAPI ITextSelection_fnSetFont(ITextSelection *me, ITextFont *font)
4747 {
4748     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4749     ITextRange *range = NULL;
4750 
4751     TRACE("(%p)->(%p)\n", This, font);
4752 
4753     if (!font)
4754         return E_INVALIDARG;
4755 
4756     if (!This->reOle)
4757         return CO_E_RELEASED;
4758 
4759     ITextSelection_QueryInterface(me, &IID_ITextRange, (void**)&range);
4760     textrange_set_font(range, font);
4761     ITextRange_Release(range);
4762     return S_OK;
4763 }
4764 
4765 static HRESULT WINAPI ITextSelection_fnGetPara(ITextSelection *me, ITextPara **para)
4766 {
4767     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4768     ITextRange *range = NULL;
4769     HRESULT hr;
4770 
4771     TRACE("(%p)->(%p)\n", This, para);
4772 
4773     if (!This->reOle)
4774         return CO_E_RELEASED;
4775 
4776     if (!para)
4777         return E_INVALIDARG;
4778 
4779     ITextSelection_QueryInterface(me, &IID_ITextRange, (void**)&range);
4780     hr = create_textpara(range, para);
4781     ITextRange_Release(range);
4782     return hr;
4783 }
4784 
4785 static HRESULT WINAPI ITextSelection_fnSetPara(ITextSelection *me, ITextPara *para)
4786 {
4787     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4788 
4789     FIXME("(%p)->(%p): stub\n", This, para);
4790 
4791     if (!This->reOle)
4792         return CO_E_RELEASED;
4793 
4794     FIXME("not implemented\n");
4795     return E_NOTIMPL;
4796 }
4797 
4798 static HRESULT WINAPI ITextSelection_fnGetStoryLength(ITextSelection *me, LONG *length)
4799 {
4800     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4801 
4802     TRACE("(%p)->(%p)\n", This, length);
4803 
4804     if (!This->reOle)
4805         return CO_E_RELEASED;
4806 
4807     return textrange_get_storylength(This->reOle->editor, length);
4808 }
4809 
4810 static HRESULT WINAPI ITextSelection_fnGetStoryType(ITextSelection *me, LONG *value)
4811 {
4812     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4813 
4814     TRACE("(%p)->(%p)\n", This, value);
4815 
4816     if (!This->reOle)
4817         return CO_E_RELEASED;
4818 
4819     if (!value)
4820         return E_INVALIDARG;
4821 
4822     *value = tomUnknownStory;
4823     return S_OK;
4824 }
4825 
4826 static HRESULT WINAPI ITextSelection_fnCollapse(ITextSelection *me, LONG bStart)
4827 {
4828     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4829     LONG start, end;
4830     HRESULT hres;
4831 
4832     TRACE("(%p)->(%d)\n", This, bStart);
4833 
4834     if (!This->reOle)
4835         return CO_E_RELEASED;
4836 
4837     ME_GetSelectionOfs(This->reOle->editor, &start, &end);
4838     hres = range_Collapse(bStart, &start, &end);
4839     if (SUCCEEDED(hres))
4840         ME_SetSelection(This->reOle->editor, start, end);
4841     return hres;
4842 }
4843 
4844 static HRESULT WINAPI ITextSelection_fnExpand(ITextSelection *me, LONG unit, LONG *delta)
4845 {
4846     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4847     ITextRange *range = NULL;
4848     HRESULT hr;
4849 
4850     TRACE("(%p)->(%d %p)\n", This, unit, delta);
4851 
4852     if (!This->reOle)
4853         return CO_E_RELEASED;
4854 
4855     ITextSelection_QueryInterface(me, &IID_ITextRange, (void**)&range);
4856     hr = textrange_expand(range, unit, delta);
4857     ITextRange_Release(range);
4858     return hr;
4859 }
4860 
4861 static HRESULT WINAPI ITextSelection_fnGetIndex(ITextSelection *me, LONG unit, LONG *index)
4862 {
4863     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4864 
4865     FIXME("(%p)->(%d %p): stub\n", This, unit, index);
4866 
4867     if (!This->reOle)
4868         return CO_E_RELEASED;
4869 
4870     return E_NOTIMPL;
4871 }
4872 
4873 static HRESULT WINAPI ITextSelection_fnSetIndex(ITextSelection *me, LONG unit, LONG index,
4874     LONG extend)
4875 {
4876     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4877 
4878     FIXME("(%p)->(%d %d %d): stub\n", This, unit, index, extend);
4879 
4880     if (!This->reOle)
4881         return CO_E_RELEASED;
4882 
4883     return E_NOTIMPL;
4884 }
4885 
4886 static HRESULT WINAPI ITextSelection_fnSetRange(ITextSelection *me, LONG anchor, LONG active)
4887 {
4888     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4889 
4890     FIXME("(%p)->(%d %d): stub\n", This, anchor, active);
4891 
4892     if (!This->reOle)
4893         return CO_E_RELEASED;
4894 
4895     return E_NOTIMPL;
4896 }
4897 
4898 static HRESULT WINAPI ITextSelection_fnInRange(ITextSelection *me, ITextRange *range, LONG *ret)
4899 {
4900     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4901     ITextSelection *selection = NULL;
4902     LONG start, end;
4903 
4904     TRACE("(%p)->(%p %p)\n", This, range, ret);
4905 
4906     if (ret)
4907         *ret = tomFalse;
4908 
4909     if (!This->reOle)
4910         return CO_E_RELEASED;
4911 
4912     if (!range)
4913         return S_FALSE;
4914 
4915     ITextRange_QueryInterface(range, &IID_ITextSelection, (void**)&selection);
4916     if (!selection)
4917         return S_FALSE;
4918     ITextSelection_Release(selection);
4919 
4920     ITextSelection_GetStart(me, &start);
4921     ITextSelection_GetEnd(me, &end);
4922     return textrange_inrange(start, end, range, ret);
4923 }
4924 
4925 static HRESULT WINAPI ITextSelection_fnInStory(ITextSelection *me, ITextRange *range, LONG *ret)
4926 {
4927     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4928 
4929     FIXME("(%p)->(%p %p): stub\n", This, range, ret);
4930 
4931     if (!This->reOle)
4932         return CO_E_RELEASED;
4933 
4934     return E_NOTIMPL;
4935 }
4936 
4937 static HRESULT WINAPI ITextSelection_fnIsEqual(ITextSelection *me, ITextRange *range, LONG *ret)
4938 {
4939     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4940     ITextSelection *selection = NULL;
4941     LONG start, end;
4942 
4943     TRACE("(%p)->(%p %p)\n", This, range, ret);
4944 
4945     if (ret)
4946         *ret = tomFalse;
4947 
4948     if (!This->reOle)
4949         return CO_E_RELEASED;
4950 
4951     if (!range)
4952         return S_FALSE;
4953 
4954     ITextRange_QueryInterface(range, &IID_ITextSelection, (void**)&selection);
4955     if (!selection)
4956         return S_FALSE;
4957     ITextSelection_Release(selection);
4958 
4959     ITextSelection_GetStart(me, &start);
4960     ITextSelection_GetEnd(me, &end);
4961     return textrange_isequal(start, end, range, ret);
4962 }
4963 
4964 static HRESULT WINAPI ITextSelection_fnSelect(ITextSelection *me)
4965 {
4966     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4967 
4968     TRACE("(%p)\n", This);
4969 
4970     if (!This->reOle)
4971         return CO_E_RELEASED;
4972 
4973     /* nothing to do */
4974     return S_OK;
4975 }
4976 
4977 static HRESULT WINAPI ITextSelection_fnStartOf(ITextSelection *me, LONG unit, LONG extend,
4978     LONG *delta)
4979 {
4980     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4981 
4982     FIXME("(%p)->(%d %d %p): stub\n", This, unit, extend, delta);
4983 
4984     if (!This->reOle)
4985         return CO_E_RELEASED;
4986 
4987     return E_NOTIMPL;
4988 }
4989 
4990 static HRESULT WINAPI ITextSelection_fnEndOf(ITextSelection *me, LONG unit, LONG extend,
4991     LONG *delta)
4992 {
4993     ITextSelectionImpl *This = impl_from_ITextSelection(me);
4994 
4995     FIXME("(%p)->(%d %d %p): stub\n", This, unit, extend, delta);
4996 
4997     if (!This->reOle)
4998         return CO_E_RELEASED;
4999 
5000     return E_NOTIMPL;
5001 }
5002 
5003 static HRESULT WINAPI ITextSelection_fnMove(ITextSelection *me, LONG unit, LONG count, LONG *delta)
5004 {
5005     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5006 
5007     FIXME("(%p)->(%d %d %p): stub\n", This, unit, count, delta);
5008 
5009     if (!This->reOle)
5010         return CO_E_RELEASED;
5011 
5012     return E_NOTIMPL;
5013 }
5014 
5015 static HRESULT WINAPI ITextSelection_fnMoveStart(ITextSelection *me, LONG unit, LONG count,
5016     LONG *delta)
5017 {
5018     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5019 
5020     FIXME("(%p)->(%d %d %p): stub\n", This, unit, count, delta);
5021 
5022     if (!This->reOle)
5023         return CO_E_RELEASED;
5024 
5025     return E_NOTIMPL;
5026 }
5027 
5028 static HRESULT WINAPI ITextSelection_fnMoveEnd(ITextSelection *me, LONG unit, LONG count,
5029     LONG *delta)
5030 {
5031     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5032     ITextRange *range = NULL;
5033     HRESULT hr;
5034 
5035     TRACE("(%p)->(%d %d %p)\n", This, unit, count, delta);
5036 
5037     if (!This->reOle)
5038         return CO_E_RELEASED;
5039 
5040     ITextSelection_QueryInterface(me, &IID_ITextRange, (void**)&range);
5041     hr = textrange_moveend(range, unit, count, delta);
5042     ITextRange_Release(range);
5043     return hr;
5044 }
5045 
5046 static HRESULT WINAPI ITextSelection_fnMoveWhile(ITextSelection *me, VARIANT *charset, LONG count,
5047     LONG *delta)
5048 {
5049     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5050 
5051     FIXME("(%p)->(%s %d %p): stub\n", This, debugstr_variant(charset), count, delta);
5052 
5053     if (!This->reOle)
5054         return CO_E_RELEASED;
5055 
5056     return E_NOTIMPL;
5057 }
5058 
5059 static HRESULT WINAPI ITextSelection_fnMoveStartWhile(ITextSelection *me, VARIANT *charset, LONG count,
5060     LONG *delta)
5061 {
5062     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5063 
5064     FIXME("(%p)->(%s %d %p): stub\n", This, debugstr_variant(charset), count, delta);
5065 
5066     if (!This->reOle)
5067         return CO_E_RELEASED;
5068 
5069     return E_NOTIMPL;
5070 }
5071 
5072 static HRESULT WINAPI ITextSelection_fnMoveEndWhile(ITextSelection *me, VARIANT *charset, LONG count,
5073     LONG *delta)
5074 {
5075     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5076 
5077     FIXME("(%p)->(%s %d %p): stub\n", This, debugstr_variant(charset), count, delta);
5078 
5079     if (!This->reOle)
5080         return CO_E_RELEASED;
5081 
5082     return E_NOTIMPL;
5083 }
5084 
5085 static HRESULT WINAPI ITextSelection_fnMoveUntil(ITextSelection *me, VARIANT *charset, LONG count,
5086     LONG *delta)
5087 {
5088     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5089 
5090     FIXME("(%p)->(%s %d %p): stub\n", This, debugstr_variant(charset), count, delta);
5091 
5092     if (!This->reOle)
5093         return CO_E_RELEASED;
5094 
5095     return E_NOTIMPL;
5096 }
5097 
5098 static HRESULT WINAPI ITextSelection_fnMoveStartUntil(ITextSelection *me, VARIANT *charset, LONG count,
5099     LONG *delta)
5100 {
5101     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5102 
5103     FIXME("(%p)->(%s %d %p): stub\n", This, debugstr_variant(charset), count, delta);
5104 
5105     if (!This->reOle)
5106         return CO_E_RELEASED;
5107 
5108     return E_NOTIMPL;
5109 }
5110 
5111 static HRESULT WINAPI ITextSelection_fnMoveEndUntil(ITextSelection *me, VARIANT *charset, LONG count,
5112     LONG *delta)
5113 {
5114     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5115 
5116     FIXME("(%p)->(%s %d %p): stub\n", This, debugstr_variant(charset), count, delta);
5117 
5118     if (!This->reOle)
5119         return CO_E_RELEASED;
5120 
5121     return E_NOTIMPL;
5122 }
5123 
5124 static HRESULT WINAPI ITextSelection_fnFindText(ITextSelection *me, BSTR text, LONG count, LONG flags,
5125     LONG *length)
5126 {
5127     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5128 
5129     FIXME("(%p)->(%s %d %x %p): stub\n", This, debugstr_w(text), count, flags, length);
5130 
5131     if (!This->reOle)
5132         return CO_E_RELEASED;
5133 
5134     FIXME("not implemented\n");
5135     return E_NOTIMPL;
5136 }
5137 
5138 static HRESULT WINAPI ITextSelection_fnFindTextStart(ITextSelection *me, BSTR text, LONG count,
5139     LONG flags, LONG *length)
5140 {
5141     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5142 
5143     FIXME("(%p)->(%s %d %x %p): stub\n", This, debugstr_w(text), count, flags, length);
5144 
5145     if (!This->reOle)
5146         return CO_E_RELEASED;
5147 
5148     return E_NOTIMPL;
5149 }
5150 
5151 static HRESULT WINAPI ITextSelection_fnFindTextEnd(ITextSelection *me, BSTR text, LONG count,
5152     LONG flags, LONG *length)
5153 {
5154     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5155 
5156     FIXME("(%p)->(%s %d %x %p): stub\n", This, debugstr_w(text), count, flags, length);
5157 
5158     if (!This->reOle)
5159         return CO_E_RELEASED;
5160 
5161     return E_NOTIMPL;
5162 }
5163 
5164 static HRESULT WINAPI ITextSelection_fnDelete(ITextSelection *me, LONG unit, LONG count,
5165     LONG *delta)
5166 {
5167     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5168 
5169     FIXME("(%p)->(%d %d %p): stub\n", This, unit, count, delta);
5170 
5171     if (!This->reOle)
5172         return CO_E_RELEASED;
5173 
5174     return E_NOTIMPL;
5175 }
5176 
5177 static HRESULT WINAPI ITextSelection_fnCut(ITextSelection *me, VARIANT *v)
5178 {
5179     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5180 
5181     FIXME("(%p)->(%p): stub\n", This, v);
5182 
5183     if (!This->reOle)
5184         return CO_E_RELEASED;
5185 
5186     return E_NOTIMPL;
5187 }
5188 
5189 static HRESULT WINAPI ITextSelection_fnCopy(ITextSelection *me, VARIANT *v)
5190 {
5191     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5192 
5193     FIXME("(%p)->(%p): stub\n", This, v);
5194 
5195     if (!This->reOle)
5196         return CO_E_RELEASED;
5197 
5198     return E_NOTIMPL;
5199 }
5200 
5201 static HRESULT WINAPI ITextSelection_fnPaste(ITextSelection *me, VARIANT *v, LONG format)
5202 {
5203     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5204 
5205     FIXME("(%p)->(%s %x): stub\n", This, debugstr_variant(v), format);
5206 
5207     if (!This->reOle)
5208         return CO_E_RELEASED;
5209 
5210     return E_NOTIMPL;
5211 }
5212 
5213 static HRESULT WINAPI ITextSelection_fnCanPaste(ITextSelection *me, VARIANT *v, LONG format,
5214     LONG *ret)
5215 {
5216     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5217 
5218     FIXME("(%p)->(%s %x %p): stub\n", This, debugstr_variant(v), format, ret);
5219 
5220     if (!This->reOle)
5221         return CO_E_RELEASED;
5222 
5223     return E_NOTIMPL;
5224 }
5225 
5226 static HRESULT WINAPI ITextSelection_fnCanEdit(ITextSelection *me, LONG *ret)
5227 {
5228     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5229 
5230     FIXME("(%p)->(%p): stub\n", This, ret);
5231 
5232     if (!This->reOle)
5233         return CO_E_RELEASED;
5234 
5235     return E_NOTIMPL;
5236 }
5237 
5238 static HRESULT WINAPI ITextSelection_fnChangeCase(ITextSelection *me, LONG type)
5239 {
5240     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5241 
5242     FIXME("(%p)->(%d): stub\n", This, type);
5243 
5244     if (!This->reOle)
5245         return CO_E_RELEASED;
5246 
5247     return E_NOTIMPL;
5248 }
5249 
5250 static HRESULT WINAPI ITextSelection_fnGetPoint(ITextSelection *me, LONG type, LONG *cx, LONG *cy)
5251 {
5252     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5253 
5254     FIXME("(%p)->(%d %p %p): stub\n", This, type, cx, cy);
5255 
5256     if (!This->reOle)
5257         return CO_E_RELEASED;
5258 
5259     return E_NOTIMPL;
5260 }
5261 
5262 static HRESULT WINAPI ITextSelection_fnSetPoint(ITextSelection *me, LONG x, LONG y, LONG type,
5263     LONG extend)
5264 {
5265     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5266 
5267     FIXME("(%p)->(%d %d %d %d): stub\n", This, x, y, type, extend);
5268 
5269     if (!This->reOle)
5270         return CO_E_RELEASED;
5271 
5272     return E_NOTIMPL;
5273 }
5274 
5275 static HRESULT WINAPI ITextSelection_fnScrollIntoView(ITextSelection *me, LONG value)
5276 {
5277     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5278 
5279     FIXME("(%p)->(%d): stub\n", This, value);
5280 
5281     if (!This->reOle)
5282         return CO_E_RELEASED;
5283 
5284     return E_NOTIMPL;
5285 }
5286 
5287 static HRESULT WINAPI ITextSelection_fnGetEmbeddedObject(ITextSelection *me, IUnknown **ppv)
5288 {
5289     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5290 
5291     FIXME("(%p)->(%p): stub\n", This, ppv);
5292 
5293     if (!This->reOle)
5294         return CO_E_RELEASED;
5295 
5296     return E_NOTIMPL;
5297 }
5298 
5299 /*** ITextSelection methods ***/
5300 static HRESULT WINAPI ITextSelection_fnGetFlags(ITextSelection *me, LONG *flags)
5301 {
5302     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5303 
5304     FIXME("(%p)->(%p): stub\n", This, flags);
5305 
5306     if (!This->reOle)
5307         return CO_E_RELEASED;
5308 
5309     return E_NOTIMPL;
5310 }
5311 
5312 static HRESULT WINAPI ITextSelection_fnSetFlags(ITextSelection *me, LONG flags)
5313 {
5314     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5315 
5316     FIXME("(%p)->(%x): stub\n", This, flags);
5317 
5318     if (!This->reOle)
5319         return CO_E_RELEASED;
5320 
5321     return E_NOTIMPL;
5322 }
5323 
5324 static HRESULT WINAPI ITextSelection_fnGetType(ITextSelection *me, LONG *type)
5325 {
5326     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5327 
5328     FIXME("(%p)->(%p): stub\n", This, type);
5329 
5330     if (!This->reOle)
5331         return CO_E_RELEASED;
5332 
5333     return E_NOTIMPL;
5334 }
5335 
5336 static HRESULT WINAPI ITextSelection_fnMoveLeft(ITextSelection *me, LONG unit, LONG count,
5337     LONG extend, LONG *delta)
5338 {
5339     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5340 
5341     FIXME("(%p)->(%d %d %d %p): stub\n", This, unit, count, extend, delta);
5342 
5343     if (!This->reOle)
5344         return CO_E_RELEASED;
5345 
5346     return E_NOTIMPL;
5347 }
5348 
5349 static HRESULT WINAPI ITextSelection_fnMoveRight(ITextSelection *me, LONG unit, LONG count,
5350     LONG extend, LONG *delta)
5351 {
5352     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5353 
5354     FIXME("(%p)->(%d %d %d %p): stub\n", This, unit, count, extend, delta);
5355 
5356     if (!This->reOle)
5357         return CO_E_RELEASED;
5358 
5359     return E_NOTIMPL;
5360 }
5361 
5362 static HRESULT WINAPI ITextSelection_fnMoveUp(ITextSelection *me, LONG unit, LONG count,
5363     LONG extend, LONG *delta)
5364 {
5365     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5366 
5367     FIXME("(%p)->(%d %d %d %p): stub\n", This, unit, count, extend, delta);
5368 
5369     if (!This->reOle)
5370         return CO_E_RELEASED;
5371 
5372     return E_NOTIMPL;
5373 }
5374 
5375 static HRESULT WINAPI ITextSelection_fnMoveDown(ITextSelection *me, LONG unit, LONG count,
5376     LONG extend, LONG *delta)
5377 {
5378     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5379 
5380     FIXME("(%p)->(%d %d %d %p): stub\n", This, unit, count, extend, delta);
5381 
5382     if (!This->reOle)
5383         return CO_E_RELEASED;
5384 
5385     return E_NOTIMPL;
5386 }
5387 
5388 static HRESULT WINAPI ITextSelection_fnHomeKey(ITextSelection *me, LONG unit, LONG extend,
5389     LONG *delta)
5390 {
5391     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5392 
5393     FIXME("(%p)->(%d %d %p): stub\n", This, unit, extend, delta);
5394 
5395     if (!This->reOle)
5396         return CO_E_RELEASED;
5397 
5398     return E_NOTIMPL;
5399 }
5400 
5401 static HRESULT WINAPI ITextSelection_fnEndKey(ITextSelection *me, LONG unit, LONG extend,
5402     LONG *delta)
5403 {
5404     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5405 
5406     FIXME("(%p)->(%d %d %p): stub\n", This, unit, extend, delta);
5407 
5408     if (!This->reOle)
5409         return CO_E_RELEASED;
5410 
5411     return E_NOTIMPL;
5412 }
5413 
5414 static HRESULT WINAPI ITextSelection_fnTypeText(ITextSelection *me, BSTR text)
5415 {
5416     ITextSelectionImpl *This = impl_from_ITextSelection(me);
5417 
5418     FIXME("(%p)->(%s): stub\n", This, debugstr_w(text));
5419 
5420     if (!This->reOle)
5421         return CO_E_RELEASED;
5422 
5423     return E_NOTIMPL;
5424 }
5425 
5426 static const ITextSelectionVtbl tsvt = {
5427     ITextSelection_fnQueryInterface,
5428     ITextSelection_fnAddRef,
5429     ITextSelection_fnRelease,
5430     ITextSelection_fnGetTypeInfoCount,
5431     ITextSelection_fnGetTypeInfo,
5432     ITextSelection_fnGetIDsOfNames,
5433     ITextSelection_fnInvoke,
5434     ITextSelection_fnGetText,
5435     ITextSelection_fnSetText,
5436     ITextSelection_fnGetChar,
5437     ITextSelection_fnSetChar,
5438     ITextSelection_fnGetDuplicate,
5439     ITextSelection_fnGetFormattedText,
5440     ITextSelection_fnSetFormattedText,
5441     ITextSelection_fnGetStart,
5442     ITextSelection_fnSetStart,
5443     ITextSelection_fnGetEnd,
5444     ITextSelection_fnSetEnd,
5445     ITextSelection_fnGetFont,
5446     ITextSelection_fnSetFont,
5447     ITextSelection_fnGetPara,
5448     ITextSelection_fnSetPara,
5449     ITextSelection_fnGetStoryLength,
5450     ITextSelection_fnGetStoryType,
5451     ITextSelection_fnCollapse,
5452     ITextSelection_fnExpand,
5453     ITextSelection_fnGetIndex,
5454     ITextSelection_fnSetIndex,
5455     ITextSelection_fnSetRange,
5456     ITextSelection_fnInRange,
5457     ITextSelection_fnInStory,
5458     ITextSelection_fnIsEqual,
5459     ITextSelection_fnSelect,
5460     ITextSelection_fnStartOf,
5461     ITextSelection_fnEndOf,
5462     ITextSelection_fnMove,
5463     ITextSelection_fnMoveStart,
5464     ITextSelection_fnMoveEnd,
5465     ITextSelection_fnMoveWhile,
5466     ITextSelection_fnMoveStartWhile,
5467     ITextSelection_fnMoveEndWhile,
5468     ITextSelection_fnMoveUntil,
5469     ITextSelection_fnMoveStartUntil,
5470     ITextSelection_fnMoveEndUntil,
5471     ITextSelection_fnFindText,
5472     ITextSelection_fnFindTextStart,
5473     ITextSelection_fnFindTextEnd,
5474     ITextSelection_fnDelete,
5475     ITextSelection_fnCut,
5476     ITextSelection_fnCopy,
5477     ITextSelection_fnPaste,
5478     ITextSelection_fnCanPaste,
5479     ITextSelection_fnCanEdit,
5480     ITextSelection_fnChangeCase,
5481     ITextSelection_fnGetPoint,
5482     ITextSelection_fnSetPoint,
5483     ITextSelection_fnScrollIntoView,
5484     ITextSelection_fnGetEmbeddedObject,
5485     ITextSelection_fnGetFlags,
5486     ITextSelection_fnSetFlags,
5487     ITextSelection_fnGetType,
5488     ITextSelection_fnMoveLeft,
5489     ITextSelection_fnMoveRight,
5490     ITextSelection_fnMoveUp,
5491     ITextSelection_fnMoveDown,
5492     ITextSelection_fnHomeKey,
5493     ITextSelection_fnEndKey,
5494     ITextSelection_fnTypeText
5495 };
5496 
5497 static ITextSelectionImpl *
5498 CreateTextSelection(IRichEditOleImpl *reOle)
5499 {
5500     ITextSelectionImpl *txtSel = heap_alloc(sizeof *txtSel);
5501     if (!txtSel)
5502         return NULL;
5503 
5504     txtSel->ITextSelection_iface.lpVtbl = &tsvt;
5505     txtSel->ref = 1;
5506     txtSel->reOle = reOle;
5507     return txtSel;
5508 }
5509 
5510 LRESULT CreateIRichEditOle(IUnknown *outer_unk, ME_TextEditor *editor, LPVOID *ppvObj)
5511 {
5512     IRichEditOleImpl *reo;
5513 
5514     reo = heap_alloc(sizeof(IRichEditOleImpl));
5515     if (!reo)
5516         return 0;
5517 
5518     reo->IUnknown_inner.lpVtbl = &reo_unk_vtbl;
5519     reo->IRichEditOle_iface.lpVtbl = &revt;
5520     reo->ITextDocument_iface.lpVtbl = &tdvt;
5521     reo->ref = 1;
5522     reo->editor = editor;
5523     reo->txtSel = NULL;
5524 
5525     TRACE("Created %p\n",reo);
5526     list_init(&reo->rangelist);
5527     list_init(&reo->clientsites);
5528     if (outer_unk)
5529         reo->outer_unk = outer_unk;
5530     else
5531         reo->outer_unk = &reo->IUnknown_inner;
5532     *ppvObj = &reo->IRichEditOle_iface;
5533 
5534     return 1;
5535 }
5536 
5537 static void convert_sizel(const ME_Context *c, const SIZEL* szl, SIZE* sz)
5538 {
5539   /* sizel is in .01 millimeters, sz in pixels */
5540   sz->cx = MulDiv(szl->cx, c->dpi.cx, 2540);
5541   sz->cy = MulDiv(szl->cy, c->dpi.cy, 2540);
5542 }
5543 
5544 /******************************************************************************
5545  * ME_GetOLEObjectSize
5546  *
5547  * Sets run extent for OLE objects.
5548  */
5549 void ME_GetOLEObjectSize(const ME_Context *c, ME_Run *run, SIZE *pSize)
5550 {
5551   IDataObject*  ido;
5552   FORMATETC     fmt;
5553   STGMEDIUM     stgm;
5554   DIBSECTION    dibsect;
5555   ENHMETAHEADER emh;
5556 
5557   assert(run->nFlags & MERF_GRAPHICS);
5558   assert(run->reobj);
5559 
5560   if (run->reobj->obj.sizel.cx != 0 || run->reobj->obj.sizel.cy != 0)
5561   {
5562     convert_sizel(c, &run->reobj->obj.sizel, pSize);
5563     if (c->editor->nZoomNumerator != 0)
5564     {
5565       pSize->cx = MulDiv(pSize->cx, c->editor->nZoomNumerator, c->editor->nZoomDenominator);
5566       pSize->cy = MulDiv(pSize->cy, c->editor->nZoomNumerator, c->editor->nZoomDenominator);
5567     }
5568     return;
5569   }
5570 
5571   if (!run->reobj->obj.poleobj)
5572   {
5573     pSize->cx = pSize->cy = 0;
5574     return;
5575   }
5576 
5577   if (IOleObject_QueryInterface(run->reobj->obj.poleobj, &IID_IDataObject, (void**)&ido) != S_OK)
5578   {
5579       FIXME("Query Interface IID_IDataObject failed!\n");
5580       pSize->cx = pSize->cy = 0;
5581       return;
5582   }
5583   fmt.cfFormat = CF_BITMAP;
5584   fmt.ptd = NULL;
5585   fmt.dwAspect = DVASPECT_CONTENT;
5586   fmt.lindex = -1;
5587   fmt.tymed = TYMED_GDI;
5588   if (IDataObject_GetData(ido, &fmt, &stgm) != S_OK)
5589   {
5590     fmt.cfFormat = CF_ENHMETAFILE;
5591     fmt.tymed = TYMED_ENHMF;
5592     if (IDataObject_GetData(ido, &fmt, &stgm) != S_OK)
5593     {
5594       FIXME("unsupported format\n");
5595       pSize->cx = pSize->cy = 0;
5596       IDataObject_Release(ido);
5597       return;
5598     }
5599   }
5600   IDataObject_Release(ido);
5601 
5602   switch (stgm.tymed)
5603   {
5604   case TYMED_GDI:
5605     GetObjectW(stgm.u.hBitmap, sizeof(dibsect), &dibsect);
5606     pSize->cx = dibsect.dsBm.bmWidth;
5607     pSize->cy = dibsect.dsBm.bmHeight;
5608     break;
5609   case TYMED_ENHMF:
5610     GetEnhMetaFileHeader(stgm.u.hEnhMetaFile, sizeof(emh), &emh);
5611     pSize->cx = emh.rclBounds.right - emh.rclBounds.left;
5612     pSize->cy = emh.rclBounds.bottom - emh.rclBounds.top;
5613     break;
5614   default:
5615     FIXME("Unsupported tymed %d\n", stgm.tymed);
5616     break;
5617   }
5618   ReleaseStgMedium(&stgm);
5619   if (c->editor->nZoomNumerator != 0)
5620   {
5621     pSize->cx = MulDiv(pSize->cx, c->editor->nZoomNumerator, c->editor->nZoomDenominator);
5622     pSize->cy = MulDiv(pSize->cy, c->editor->nZoomNumerator, c->editor->nZoomDenominator);
5623   }
5624 }
5625 
5626 void ME_DrawOLE(ME_Context *c, int x, int y, ME_Run *run, BOOL selected)
5627 {
5628   IDataObject*  ido;
5629   FORMATETC     fmt;
5630   STGMEDIUM     stgm;
5631   DIBSECTION    dibsect;
5632   ENHMETAHEADER emh;
5633   HDC           hMemDC;
5634   SIZE          sz;
5635   BOOL          has_size;
5636   HBITMAP       old_bm;
5637   RECT          rc;
5638 
5639   assert(run->nFlags & MERF_GRAPHICS);
5640   assert(run->reobj);
5641   if (IOleObject_QueryInterface(run->reobj->obj.poleobj, &IID_IDataObject, (void**)&ido) != S_OK)
5642   {
5643     FIXME("Couldn't get interface\n");
5644     return;
5645   }
5646   has_size = run->reobj->obj.sizel.cx != 0 || run->reobj->obj.sizel.cy != 0;
5647   fmt.cfFormat = CF_BITMAP;
5648   fmt.ptd = NULL;
5649   fmt.dwAspect = DVASPECT_CONTENT;
5650   fmt.lindex = -1;
5651   fmt.tymed = TYMED_GDI;
5652   if (IDataObject_GetData(ido, &fmt, &stgm) != S_OK)
5653   {
5654     fmt.cfFormat = CF_ENHMETAFILE;
5655     fmt.tymed = TYMED_ENHMF;
5656     if (IDataObject_GetData(ido, &fmt, &stgm) != S_OK)
5657     {
5658       FIXME("Couldn't get storage medium\n");
5659       IDataObject_Release(ido);
5660       return;
5661     }
5662   }
5663   IDataObject_Release(ido);
5664 
5665   switch (stgm.tymed)
5666   {
5667   case TYMED_GDI:
5668     GetObjectW(stgm.u.hBitmap, sizeof(dibsect), &dibsect);
5669     hMemDC = CreateCompatibleDC(c->hDC);
5670     old_bm = SelectObject(hMemDC, stgm.u.hBitmap);
5671     if (has_size)
5672     {
5673       convert_sizel(c, &run->reobj->obj.sizel, &sz);
5674     } else {
5675       sz.cx = dibsect.dsBm.bmWidth;
5676       sz.cy = dibsect.dsBm.bmHeight;
5677     }
5678     if (c->editor->nZoomNumerator != 0)
5679     {
5680       sz.cx = MulDiv(sz.cx, c->editor->nZoomNumerator, c->editor->nZoomDenominator);
5681       sz.cy = MulDiv(sz.cy, c->editor->nZoomNumerator, c->editor->nZoomDenominator);
5682     }
5683     StretchBlt(c->hDC, x, y - sz.cy, sz.cx, sz.cy,
5684                hMemDC, 0, 0, dibsect.dsBm.bmWidth, dibsect.dsBm.bmHeight, SRCCOPY);
5685 
5686     SelectObject(hMemDC, old_bm);
5687     DeleteDC(hMemDC);
5688     break;
5689   case TYMED_ENHMF:
5690     GetEnhMetaFileHeader(stgm.u.hEnhMetaFile, sizeof(emh), &emh);
5691     if (has_size)
5692     {
5693       convert_sizel(c, &run->reobj->obj.sizel, &sz);
5694     } else {
5695       sz.cx = emh.rclBounds.right - emh.rclBounds.left;
5696       sz.cy = emh.rclBounds.bottom - emh.rclBounds.top;
5697     }
5698     if (c->editor->nZoomNumerator != 0)
5699     {
5700       sz.cx = MulDiv(sz.cx, c->editor->nZoomNumerator, c->editor->nZoomDenominator);
5701       sz.cy = MulDiv(sz.cy, c->editor->nZoomNumerator, c->editor->nZoomDenominator);
5702     }
5703 
5704     rc.left = x;
5705     rc.top = y - sz.cy;
5706     rc.right = x + sz.cx;
5707     rc.bottom = y;
5708     PlayEnhMetaFile(c->hDC, stgm.u.hEnhMetaFile, &rc);
5709     break;
5710   default:
5711     FIXME("Unsupported tymed %d\n", stgm.tymed);
5712     selected = FALSE;
5713     break;
5714   }
5715   ReleaseStgMedium(&stgm);
5716 
5717   if (selected && !c->editor->bHideSelection)
5718     PatBlt(c->hDC, x, y - sz.cy, sz.cx, sz.cy, DSTINVERT);
5719 }
5720 
5721 void ME_DeleteReObject(struct re_object *reobj)
5722 {
5723     if (reobj->obj.poleobj)   IOleObject_Release(reobj->obj.poleobj);
5724     if (reobj->obj.pstg)      IStorage_Release(reobj->obj.pstg);
5725     if (reobj->obj.polesite)  IOleClientSite_Release(reobj->obj.polesite);
5726     heap_free(reobj);
5727 }
5728 
5729 void ME_CopyReObject(REOBJECT *dst, const REOBJECT *src, DWORD flags)
5730 {
5731     *dst = *src;
5732     dst->poleobj = NULL;
5733     dst->pstg = NULL;
5734     dst->polesite = NULL;
5735 
5736     if ((flags & REO_GETOBJ_POLEOBJ) && src->poleobj)
5737     {
5738         dst->poleobj = src->poleobj;
5739         IOleObject_AddRef(dst->poleobj);
5740     }
5741     if ((flags & REO_GETOBJ_PSTG) && src->pstg)
5742     {
5743         dst->pstg = src->pstg;
5744         IStorage_AddRef(dst->pstg);
5745     }
5746     if ((flags & REO_GETOBJ_POLESITE) && src->polesite)
5747     {
5748         dst->polesite = src->polesite;
5749         IOleClientSite_AddRef(dst->polesite);
5750     }
5751 }
5752 
5753 void ME_GetITextDocumentInterface(IRichEditOle *iface, LPVOID *ppvObj)
5754 {
5755     IRichEditOleImpl *This = impl_from_IRichEditOle(iface);
5756     *ppvObj = &This->ITextDocument_iface;
5757 }
5758