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