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