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