170c426e8a24607cfbb4769263a8cef085edc2a4
[reactos.git] / dll / win32 / riched20 / richole.c
1 /*
2 * RichEdit GUIDs and OLE interface
3 *
4 * Copyright 2004 by Krzysztof Foltman
5 * Copyright 2004 Aric Stewart
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #include <stdarg.h>
23
24 #define NONAMELESSUNION
25 #define COBJMACROS
26
27 #include "windef.h"
28 #include "winbase.h"
29 #include "wingdi.h"
30 #include "winuser.h"
31 #include "ole2.h"
32 #include "richole.h"
33 #include "editor.h"
34 #include "richedit.h"
35 #include "tom.h"
36 #include "wine/debug.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(richedit);
39
40 /* there is no way to be consistent across different sets of headers - mingw, Wine, Win32 SDK*/
41
42 #include "initguid.h"
43
44 DEFINE_GUID(LIBID_tom, 0x8cc497c9, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xaa, 0x00, 0x47, 0xbe, 0x5d);
45 DEFINE_GUID(IID_ITextServices, 0x8d33f740, 0xcf58, 0x11ce, 0xa8, 0x9d, 0x00, 0xaa, 0x00, 0x6c, 0xad, 0xc5);
46 DEFINE_GUID(IID_ITextHost, 0x13e670f4,0x1a5a,0x11cf,0xab,0xeb,0x00,0xaa,0x00,0xb6,0x5e,0xa1);
47 DEFINE_GUID(IID_ITextHost2, 0x13e670f5,0x1a5a,0x11cf,0xab,0xeb,0x00,0xaa,0x00,0xb6,0x5e,0xa1);
48 DEFINE_GUID(IID_ITextDocument, 0x8cc497c0, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xaa, 0x00, 0x47, 0xbe, 0x5d);
49 DEFINE_GUID(IID_ITextRange, 0x8cc497c2, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xaa, 0x00, 0x47, 0xbe, 0x5d);
50 DEFINE_GUID(IID_ITextSelection, 0x8cc497c1, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xaa, 0x00, 0x47, 0xbe, 0x5d);
51 DEFINE_GUID(IID_ITextFont, 0x8cc497c3, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xaa, 0x00, 0x47, 0xbe, 0x5d);
52 DEFINE_GUID(IID_ITextPara, 0x8cc497c4, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xaa, 0x00, 0x47, 0xbe, 0x5d);
53
54 static ITypeLib *typelib;
55
56 enum tid_t {
57 NULL_tid,
58 ITextDocument_tid,
59 ITextRange_tid,
60 ITextSelection_tid,
61 ITextFont_tid,
62 ITextPara_tid,
63 LAST_tid
64 };
65
66 static const IID * const tid_ids[] =
67 {
68 &IID_NULL,
69 &IID_ITextDocument,
70 &IID_ITextRange,
71 &IID_ITextSelection,
72 &IID_ITextFont,
73 &IID_ITextPara,
74 };
75 static ITypeInfo *typeinfos[LAST_tid];
76
77 static HRESULT load_typelib(void)
78 {
79 ITypeLib *tl;
80 HRESULT hr;
81
82 hr = LoadRegTypeLib(&LIBID_tom, 1, 0, LOCALE_SYSTEM_DEFAULT, &tl);
83 if (FAILED(hr)) {
84 ERR("LoadRegTypeLib failed: %08x\n", hr);
85 return hr;
86 }
87
88 if (InterlockedCompareExchangePointer((void**)&typelib, tl, NULL))
89 ITypeLib_Release(tl);
90 return hr;
91 }
92
93 void release_typelib(void)
94 {
95 unsigned i;
96
97 if (!typelib)
98 return;
99
100 for (i = 0; i < sizeof(typeinfos)/sizeof(*typeinfos); i++)
101 if (typeinfos[i])
102 ITypeInfo_Release(typeinfos[i]);
103
104 ITypeLib_Release(typelib);
105 }
106
107 static HRESULT get_typeinfo(enum tid_t tid, ITypeInfo **typeinfo)
108 {
109 HRESULT hr;
110
111 if (!typelib)
112 hr = load_typelib();
113 if (!typelib)
114 return hr;
115
116 if (!typeinfos[tid])
117 {
118 ITypeInfo *ti;
119
120 hr = ITypeLib_GetTypeInfoOfGuid(typelib, tid_ids[tid], &ti);
121 if (FAILED(hr))
122 {
123 ERR("GetTypeInfoOfGuid(%s) failed: %08x\n", debugstr_guid(tid_ids[tid]), hr);
124 return hr;
125 }
126
127 if (InterlockedCompareExchangePointer((void**)(typeinfos+tid), ti, NULL))
128 ITypeInfo_Release(ti);
129 }
130
131 *typeinfo = typeinfos[tid];
132 return S_OK;
133 }
134
135 /* private IID used to get back IRichEditOleImpl pointer */
136 DEFINE_GUID(IID_Igetrichole, 0xe3ce5c7a, 0x8247, 0x4622, 0x81, 0xad, 0x11, 0x81, 0x02, 0xaa, 0x01, 0x30);
137
138 typedef struct ITextSelectionImpl ITextSelectionImpl;
139 typedef struct IOleClientSiteImpl IOleClientSiteImpl;
140 typedef struct ITextRangeImpl ITextRangeImpl;
141
142 enum textfont_prop_id {
143 FONT_ALLCAPS = 0,
144 FONT_ANIMATION,
145 FONT_BACKCOLOR,
146 FONT_BOLD,
147 FONT_EMBOSS,
148 FONT_FORECOLOR,
149 FONT_HIDDEN,
150 FONT_ENGRAVE,
151 FONT_ITALIC,
152 FONT_KERNING,
153 FONT_LANGID,
154 FONT_NAME,
155 FONT_OUTLINE,
156 FONT_POSITION,
157 FONT_PROTECTED,
158 FONT_SHADOW,
159 FONT_SIZE,
160 FONT_SMALLCAPS,
161 FONT_SPACING,
162 FONT_STRIKETHROUGH,
163 FONT_SUBSCRIPT,
164 FONT_SUPERSCRIPT,
165 FONT_UNDERLINE,
166 FONT_WEIGHT,
167 FONT_PROPID_LAST,
168 FONT_PROPID_FIRST = FONT_ALLCAPS
169 };
170
171 static const DWORD textfont_prop_masks[][2] = {
172 { CFM_ALLCAPS, CFE_ALLCAPS },
173 { CFM_ANIMATION },
174 { CFM_BACKCOLOR, CFE_AUTOBACKCOLOR },
175 { CFM_BOLD, CFE_BOLD },
176 { CFM_EMBOSS, CFE_EMBOSS },
177 { CFM_COLOR, CFE_AUTOCOLOR },
178 { CFM_HIDDEN, CFE_HIDDEN },
179 { CFM_IMPRINT, CFE_IMPRINT },
180 { CFM_ITALIC, CFE_ITALIC },
181 { CFM_KERNING },
182 { CFM_LCID },
183 { CFM_FACE },
184 { CFM_OUTLINE, CFE_OUTLINE },
185 { CFM_OFFSET },
186 { CFM_PROTECTED, CFE_PROTECTED },
187 { CFM_SHADOW, CFE_SHADOW },
188 { CFM_SIZE },
189 { CFM_SMALLCAPS, CFE_SMALLCAPS },
190 { CFM_SPACING },
191 { CFM_STRIKEOUT, CFE_STRIKEOUT },
192 { CFM_SUBSCRIPT, CFE_SUBSCRIPT },
193 { CFM_SUPERSCRIPT, CFE_SUPERSCRIPT },
194 { CFM_UNDERLINE, CFE_UNDERLINE },
195 { CFM_WEIGHT }
196 };
197
198 typedef union {
199 FLOAT f;
200 LONG l;
201 BSTR str;
202 } textfont_prop_val;
203
204 enum range_update_op {
205 RANGE_UPDATE_DELETE
206 };
207
208 typedef struct IRichEditOleImpl {
209 IUnknown IUnknown_inner;
210 IRichEditOle IRichEditOle_iface;
211 ITextDocument ITextDocument_iface;
212 IUnknown *outer_unk;
213 LONG ref;
214
215 ME_TextEditor *editor;
216 ITextSelectionImpl *txtSel;
217
218 struct list rangelist;
219 struct list clientsites;
220 } IRichEditOleImpl;
221
222 struct reole_child {
223 struct list entry;
224 IRichEditOleImpl *reole;
225 };
226
227 struct ITextRangeImpl {
228 struct reole_child child;
229 ITextRange ITextRange_iface;
230 LONG ref;
231 LONG start, end;
232 };
233
234 struct ITextSelectionImpl {
235 ITextSelection ITextSelection_iface;
236 LONG ref;
237
238 IRichEditOleImpl *reOle;
239 };
240
241 typedef struct ITextFontImpl {
242 ITextFont ITextFont_iface;
243 LONG ref;
244
245 ITextRange *range;
246 textfont_prop_val props[FONT_PROPID_LAST];
247 BOOL get_cache_enabled;
248 BOOL set_cache_enabled;
249 } ITextFontImpl;
250
251 typedef struct ITextParaImpl {
252 ITextPara ITextPara_iface;
253 LONG ref;
254
255 ITextRange *range;
256 } ITextParaImpl;
257
258 struct IOleClientSiteImpl {
259 struct reole_child child;
260 IOleClientSite IOleClientSite_iface;
261 IOleInPlaceSite IOleInPlaceSite_iface;
262 LONG ref;
263 };
264
265 static inline IRichEditOleImpl *impl_from_IRichEditOle(IRichEditOle *iface)
266 {
267 return CONTAINING_RECORD(iface, IRichEditOleImpl, IRichEditOle_iface);
268 }
269
270 static inline IRichEditOleImpl *impl_from_ITextDocument(ITextDocument *iface)
271 {
272 return CONTAINING_RECORD(iface, IRichEditOleImpl, ITextDocument_iface);
273 }
274
275 static inline IRichEditOleImpl *impl_from_IUnknown(IUnknown *iface)
276 {
277 return CONTAINING_RECORD(iface, IRichEditOleImpl, IUnknown_inner);
278 }
279
280 static inline IOleClientSiteImpl *impl_from_IOleInPlaceSite(IOleInPlaceSite *iface)
281 {
282 return CONTAINING_RECORD(iface, IOleClientSiteImpl, IOleInPlaceSite_iface);
283 }
284
285 static inline ITextRangeImpl *impl_from_ITextRange(ITextRange *iface)
286 {
287 return CONTAINING_RECORD(iface, ITextRangeImpl, ITextRange_iface);
288 }
289
290 static inline ITextSelectionImpl *impl_from_ITextSelection(ITextSelection *iface)
291 {
292 return CONTAINING_RECORD(iface, ITextSelectionImpl, ITextSelection_iface);
293 }
294
295 static inline ITextFontImpl *impl_from_ITextFont(ITextFont *iface)
296 {
297 return CONTAINING_RECORD(iface, ITextFontImpl, ITextFont_iface);
298 }
299
300 static inline ITextParaImpl *impl_from_ITextPara(ITextPara *iface)
301 {
302 return CONTAINING_RECORD(iface, ITextParaImpl, ITextPara_iface);
303 }
304
305 static HRESULT create_textfont(ITextRange*, const ITextFontImpl*, ITextFont**);
306 static HRESULT create_textpara(ITextRange*, ITextPara**);
307 static ITextSelectionImpl *CreateTextSelection(IRichEditOleImpl*);
308
309 static HRESULT textrange_get_storylength(ME_TextEditor *editor, LONG *length)
310 {
311 if (!length)
312 return E_INVALIDARG;
313
314 *length = ME_GetTextLength(editor) + 1;
315 return S_OK;
316 }
317
318 static void textranges_update_ranges(IRichEditOleImpl *reole, LONG start, LONG end, enum range_update_op op)
319 {
320 ITextRangeImpl *range;
321
322 LIST_FOR_EACH_ENTRY(range, &reole->rangelist, ITextRangeImpl, child.entry) {
323 switch (op)
324 {
325 case RANGE_UPDATE_DELETE:
326 /* range fully covered by deleted range - collapse to insertion point */
327 if (range->start >= start && range->end <= end)
328 range->start = range->end = start;
329 /* deleted range cuts from the right */
330 else if (range->start < start && range->end <= end)
331 range->end = start;
332 /* deleted range cuts from the left */
333 else if (range->start >= start && range->end > end) {
334 range->start = start;
335 range->end -= end - start;
336 }
337 /* deleted range cuts within */
338 else
339 range->end -= end - start;
340 break;
341 default:
342 FIXME("unknown update op, %d\n", op);
343 }
344 }
345 }
346
347 static inline BOOL is_equal_textfont_prop_value(enum textfont_prop_id propid, textfont_prop_val *left,
348 textfont_prop_val *right)
349 {
350 switch (propid)
351 {
352 case FONT_ALLCAPS:
353 case FONT_ANIMATION:
354 case FONT_BACKCOLOR:
355 case FONT_BOLD:
356 case FONT_EMBOSS:
357 case FONT_FORECOLOR:
358 case FONT_HIDDEN:
359 case FONT_ENGRAVE:
360 case FONT_ITALIC:
361 case FONT_KERNING:
362 case FONT_LANGID:
363 case FONT_OUTLINE:
364 case FONT_PROTECTED:
365 case FONT_SHADOW:
366 case FONT_SMALLCAPS:
367 case FONT_STRIKETHROUGH:
368 case FONT_SUBSCRIPT:
369 case FONT_SUPERSCRIPT:
370 case FONT_UNDERLINE:
371 case FONT_WEIGHT:
372 return left->l == right->l;
373 case FONT_NAME:
374 return !strcmpW(left->str, right->str);
375 case FONT_POSITION:
376 case FONT_SIZE:
377 case FONT_SPACING:
378 return left->f == right->f;
379 default:
380 FIXME("unhandled font property %d\n", propid);
381 return FALSE;
382 }
383 }
384
385 static inline void init_textfont_prop_value(enum textfont_prop_id propid, textfont_prop_val *v)
386 {
387 switch (propid)
388 {
389 case FONT_ALLCAPS:
390 case FONT_ANIMATION:
391 case FONT_BACKCOLOR:
392 case FONT_BOLD:
393 case FONT_EMBOSS:
394 case FONT_FORECOLOR:
395 case FONT_HIDDEN:
396 case FONT_ENGRAVE:
397 case FONT_ITALIC:
398 case FONT_KERNING:
399 case FONT_LANGID:
400 case FONT_OUTLINE:
401 case FONT_PROTECTED:
402 case FONT_SHADOW:
403 case FONT_SMALLCAPS:
404 case FONT_STRIKETHROUGH:
405 case FONT_SUBSCRIPT:
406 case FONT_SUPERSCRIPT:
407 case FONT_UNDERLINE:
408 case FONT_WEIGHT:
409 v->l = tomUndefined;
410 return;
411 case FONT_NAME:
412 v->str = NULL;
413 return;
414 case FONT_POSITION:
415 case FONT_SIZE:
416 case FONT_SPACING:
417 v->f = tomUndefined;
418 return;
419 default:
420 FIXME("unhandled font property %d\n", propid);
421 v->l = tomUndefined;
422 return;
423 }
424 }
425
426 static inline FLOAT twips_to_points(LONG value)
427 {
428 return value * 72.0 / 1440;
429 }
430
431 static inline FLOAT points_to_twips(FLOAT value)
432 {
433 return value * 1440 / 72.0;
434 }
435
436 static HRESULT get_textfont_prop_for_pos(const IRichEditOleImpl *reole, int pos, enum textfont_prop_id propid,
437 textfont_prop_val *value)
438 {
439 ME_Cursor from, to;
440 CHARFORMAT2W fmt;
441
442 memset(&fmt, 0, sizeof(fmt));
443 fmt.cbSize = sizeof(fmt);
444 fmt.dwMask = textfont_prop_masks[propid][0];
445
446 ME_CursorFromCharOfs(reole->editor, pos, &from);
447 to = from;
448 ME_MoveCursorChars(reole->editor, &to, 1, FALSE);
449 ME_GetCharFormat(reole->editor, &from, &to, &fmt);
450
451 switch (propid)
452 {
453 case FONT_ALLCAPS:
454 case FONT_BOLD:
455 case FONT_EMBOSS:
456 case FONT_HIDDEN:
457 case FONT_ENGRAVE:
458 case FONT_ITALIC:
459 case FONT_OUTLINE:
460 case FONT_PROTECTED:
461 case FONT_SHADOW:
462 case FONT_SMALLCAPS:
463 case FONT_STRIKETHROUGH:
464 case FONT_SUBSCRIPT:
465 case FONT_SUPERSCRIPT:
466 case FONT_UNDERLINE:
467 value->l = fmt.dwEffects & textfont_prop_masks[propid][1] ? tomTrue : tomFalse;
468 break;
469 case FONT_ANIMATION:
470 value->l = fmt.bAnimation;
471 break;
472 case FONT_BACKCOLOR:
473 value->l = fmt.dwEffects & CFE_AUTOBACKCOLOR ? GetSysColor(COLOR_WINDOW) : fmt.crBackColor;
474 break;
475 case FONT_FORECOLOR:
476 value->l = fmt.dwEffects & CFE_AUTOCOLOR ? GetSysColor(COLOR_WINDOWTEXT) : fmt.crTextColor;
477 break;
478 case FONT_KERNING:
479 value->f = twips_to_points(fmt.wKerning);
480 break;
481 case FONT_LANGID:
482 value->l = fmt.lcid;
483 break;
484 case FONT_NAME:
485 /* this case is used exclusively by GetName() */
486 value->str = SysAllocString(fmt.szFaceName);
487 if (!value->str)
488 return E_OUTOFMEMORY;
489 break;
490 case FONT_POSITION:
491 value->f = twips_to_points(fmt.yOffset);
492 break;
493 case FONT_SIZE:
494 value->f = twips_to_points(fmt.yHeight);
495 break;
496 case FONT_SPACING:
497 value->f = fmt.sSpacing;
498 break;
499 case FONT_WEIGHT:
500 value->l = fmt.wWeight;
501 break;
502 default:
503 FIXME("unhandled font property %d\n", propid);
504 return E_FAIL;
505 }
506
507 return S_OK;
508 }
509
510 static inline const IRichEditOleImpl *get_range_reole(ITextRange *range)
511 {
512 IRichEditOleImpl *reole = NULL;
513 ITextRange_QueryInterface(range, &IID_Igetrichole, (void**)&reole);
514 return reole;
515 }
516
517 static void textrange_set_font(ITextRange *range, ITextFont *font)
518 {
519 CHARFORMAT2W fmt;
520 HRESULT hr;
521 LONG value;
522 BSTR str;
523 FLOAT f;
524
525 #define CHARFORMAT_SET_B_FIELD(mask, value) \
526 if (hr == S_OK && value != tomUndefined) { \
527 fmt.dwMask |= CFM_##mask; \
528 if (value == tomTrue) fmt.dwEffects |= CFE_##mask; \
529 } \
530
531 /* fill format data from font */
532 memset(&fmt, 0, sizeof(fmt));
533 fmt.cbSize = sizeof(fmt);
534
535 value = tomUndefined;
536 hr = ITextFont_GetAllCaps(font, &value);
537 CHARFORMAT_SET_B_FIELD(ALLCAPS, value);
538
539 value = tomUndefined;
540 hr = ITextFont_GetBold(font, &value);
541 CHARFORMAT_SET_B_FIELD(BOLD, value);
542
543 value = tomUndefined;
544 hr = ITextFont_GetEmboss(font, &value);
545 CHARFORMAT_SET_B_FIELD(EMBOSS, value);
546
547 value = tomUndefined;
548 hr = ITextFont_GetHidden(font, &value);
549 CHARFORMAT_SET_B_FIELD(HIDDEN, value);
550
551 value = tomUndefined;
552 hr = ITextFont_GetEngrave(font, &value);
553 CHARFORMAT_SET_B_FIELD(IMPRINT, value);
554
555 value = tomUndefined;
556 hr = ITextFont_GetItalic(font, &value);
557 CHARFORMAT_SET_B_FIELD(ITALIC, value);
558
559 value = tomUndefined;
560 hr = ITextFont_GetOutline(font, &value);
561 CHARFORMAT_SET_B_FIELD(OUTLINE, value);
562
563 value = tomUndefined;
564 hr = ITextFont_GetProtected(font, &value);
565 CHARFORMAT_SET_B_FIELD(PROTECTED, value);
566
567 value = tomUndefined;
568 hr = ITextFont_GetShadow(font, &value);
569 CHARFORMAT_SET_B_FIELD(SHADOW, value);
570
571 value = tomUndefined;
572 hr = ITextFont_GetSmallCaps(font, &value);
573 CHARFORMAT_SET_B_FIELD(SMALLCAPS, value);
574
575 value = tomUndefined;
576 hr = ITextFont_GetStrikeThrough(font, &value);
577 CHARFORMAT_SET_B_FIELD(STRIKEOUT, value);
578
579 value = tomUndefined;
580 hr = ITextFont_GetSubscript(font, &value);
581 CHARFORMAT_SET_B_FIELD(SUBSCRIPT, value);
582
583 value = tomUndefined;
584 hr = ITextFont_GetSuperscript(font, &value);
585 CHARFORMAT_SET_B_FIELD(SUPERSCRIPT, value);
586
587 value = tomUndefined;
588 hr = ITextFont_GetUnderline(font, &value);
589 CHARFORMAT_SET_B_FIELD(UNDERLINE, value);
590
591 #undef CHARFORMAT_SET_B_FIELD
592
593 value = tomUndefined;
594 hr = ITextFont_GetAnimation(font, &value);
595 if (hr == S_OK && value != tomUndefined) {
596 fmt.dwMask |= CFM_ANIMATION;
597 fmt.bAnimation = value;
598 }
599
600 value = tomUndefined;
601 hr = ITextFont_GetBackColor(font, &value);
602 if (hr == S_OK && value != tomUndefined) {
603 fmt.dwMask |= CFM_BACKCOLOR;
604 if (value == tomAutoColor)
605 fmt.dwEffects |= CFE_AUTOBACKCOLOR;
606 else
607 fmt.crBackColor = value;
608 }
609
610 value = tomUndefined;
611 hr = ITextFont_GetForeColor(font, &value);
612 if (hr == S_OK && value != tomUndefined) {
613 fmt.dwMask |= CFM_COLOR;
614 if (value == tomAutoColor)
615 fmt.dwEffects |= CFE_AUTOCOLOR;
616 else
617 fmt.crTextColor = value;
618 }
619
620 value = tomUndefined;
621 hr = ITextFont_GetKerning(font, &f);
622 if (hr == S_OK && f != tomUndefined) {
623 fmt.dwMask |= CFM_KERNING;
624 fmt.wKerning = points_to_twips(f);
625 }
626
627 value = tomUndefined;
628 hr = ITextFont_GetLanguageID(font, &value);
629 if (hr == S_OK && value != tomUndefined) {
630 fmt.dwMask |= CFM_LCID;
631 fmt.lcid = value;
632 }
633
634 if (ITextFont_GetName(font, &str) == S_OK) {
635 fmt.dwMask |= CFM_FACE;
636 lstrcpynW(fmt.szFaceName, str, sizeof(fmt.szFaceName)/sizeof(WCHAR));
637 SysFreeString(str);
638 }
639
640 hr = ITextFont_GetPosition(font, &f);
641 if (hr == S_OK && f != tomUndefined) {
642 fmt.dwMask |= CFM_OFFSET;
643 fmt.yOffset = points_to_twips(f);
644 }
645
646 hr = ITextFont_GetSize(font, &f);
647 if (hr == S_OK && f != tomUndefined) {
648 fmt.dwMask |= CFM_SIZE;
649 fmt.yHeight = points_to_twips(f);
650 }
651
652 hr = ITextFont_GetSpacing(font, &f);
653 if (hr == S_OK && f != tomUndefined) {
654 fmt.dwMask |= CFM_SPACING;
655 fmt.sSpacing = f;
656 }
657
658 hr = ITextFont_GetWeight(font, &value);
659 if (hr == S_OK && value != tomUndefined) {
660 fmt.dwMask |= CFM_WEIGHT;
661 fmt.wWeight = value;
662 }
663
664 if (fmt.dwMask) {
665 const IRichEditOleImpl *reole = get_range_reole(range);
666 ME_Cursor from, to;
667 LONG start, end;
668
669 ITextRange_GetStart(range, &start);
670 ITextRange_GetEnd(range, &end);
671
672 ME_CursorFromCharOfs(reole->editor, start, &from);
673 ME_CursorFromCharOfs(reole->editor, end, &to);
674 ME_SetCharFormat(reole->editor, &from, &to, &fmt);
675 }
676 }
677
678 static HRESULT get_textfont_prop(const ITextFontImpl *font, enum textfont_prop_id propid, textfont_prop_val *value)
679 {
680 const IRichEditOleImpl *reole;
681 textfont_prop_val v;
682 LONG start, end, i;
683 HRESULT hr;
684
685 /* when font is not attached to any range use cached values */
686 if (!font->range || font->get_cache_enabled) {
687 *value = font->props[propid];
688 return S_OK;
689 }
690
691 if (!(reole = get_range_reole(font->range)))
692 return CO_E_RELEASED;
693
694 init_textfont_prop_value(propid, value);
695
696 ITextRange_GetStart(font->range, &start);
697 ITextRange_GetEnd(font->range, &end);
698
699 /* iterate trough a range to see if property value is consistent */
700 hr = get_textfont_prop_for_pos(reole, start, propid, &v);
701 if (FAILED(hr))
702 return hr;
703
704 for (i = start + 1; i < end; i++) {
705 textfont_prop_val cur;
706
707 hr = get_textfont_prop_for_pos(reole, i, propid, &cur);
708 if (FAILED(hr))
709 return hr;
710
711 if (!is_equal_textfont_prop_value(propid, &v, &cur))
712 return S_OK;
713 }
714
715 *value = v;
716 return S_OK;
717 }
718
719 static HRESULT get_textfont_propf(const ITextFontImpl *font, enum textfont_prop_id propid, FLOAT *value)
720 {
721 textfont_prop_val v;
722 HRESULT hr;
723
724 if (!value)
725 return E_INVALIDARG;
726
727 hr = get_textfont_prop(font, propid, &v);
728 *value = v.f;
729 return hr;
730 }
731
732 static HRESULT get_textfont_propl(const ITextFontImpl *font, enum textfont_prop_id propid, LONG *value)
733 {
734 textfont_prop_val v;
735 HRESULT hr;
736
737 if (!value)
738 return E_INVALIDARG;
739
740 hr = get_textfont_prop(font, propid, &v);
741 *value = v.l;
742 return hr;
743 }
744
745 /* Value should already have a terminal value, for boolean properties it means tomToggle is not handled */
746 static HRESULT set_textfont_prop(ITextFontImpl *font, enum textfont_prop_id propid, const textfont_prop_val *value)
747 {
748 const IRichEditOleImpl *reole;
749 ME_Cursor from, to;
750 CHARFORMAT2W fmt;
751 LONG start, end;
752
753 /* when font is not attached to any range use cache */
754 if (!font->range || font->set_cache_enabled) {
755 if (propid == FONT_NAME) {
756 SysFreeString(font->props[propid].str);
757 font->props[propid].str = SysAllocString(value->str);
758 }
759 else
760 font->props[propid] = *value;
761 return S_OK;
762 }
763
764 if (!(reole = get_range_reole(font->range)))
765 return CO_E_RELEASED;
766
767 memset(&fmt, 0, sizeof(fmt));
768 fmt.cbSize = sizeof(fmt);
769 fmt.dwMask = textfont_prop_masks[propid][0];
770
771 switch (propid)
772 {
773 case FONT_ALLCAPS:
774 case FONT_BOLD:
775 case FONT_EMBOSS:
776 case FONT_HIDDEN:
777 case FONT_ENGRAVE:
778 case FONT_ITALIC:
779 case FONT_OUTLINE:
780 case FONT_PROTECTED:
781 case FONT_SHADOW:
782 case FONT_SMALLCAPS:
783 case FONT_STRIKETHROUGH:
784 case FONT_SUBSCRIPT:
785 case FONT_SUPERSCRIPT:
786 case FONT_UNDERLINE:
787 fmt.dwEffects = value->l == tomTrue ? textfont_prop_masks[propid][1] : 0;
788 break;
789 case FONT_ANIMATION:
790 fmt.bAnimation = value->l;
791 break;
792 case FONT_BACKCOLOR:
793 case FONT_FORECOLOR:
794 if (value->l == tomAutoColor)
795 fmt.dwEffects = textfont_prop_masks[propid][1];
796 else if (propid == FONT_BACKCOLOR)
797 fmt.crBackColor = value->l;
798 else
799 fmt.crTextColor = value->l;
800 break;
801 case FONT_KERNING:
802 fmt.wKerning = value->f;
803 break;
804 case FONT_LANGID:
805 fmt.lcid = value->l;
806 break;
807 case FONT_POSITION:
808 fmt.yOffset = value->f;
809 break;
810 case FONT_SIZE:
811 fmt.yHeight = value->f;
812 break;
813 case FONT_SPACING:
814 fmt.sSpacing = value->f;
815 break;
816 case FONT_WEIGHT:
817 fmt.wWeight = value->l;
818 break;
819 case FONT_NAME:
820 lstrcpynW(fmt.szFaceName, value->str, sizeof(fmt.szFaceName)/sizeof(WCHAR));
821 break;
822 default:
823 FIXME("unhandled font property %d\n", propid);
824 return E_FAIL;
825 }
826
827 ITextRange_GetStart(font->range, &start);
828 ITextRange_GetEnd(font->range, &end);
829
830 ME_CursorFromCharOfs(reole->editor, start, &from);
831 ME_CursorFromCharOfs(reole->editor, end, &to);
832 ME_SetCharFormat(reole->editor, &from, &to, &fmt);
833
834 return S_OK;
835 }
836
837 static inline HRESULT set_textfont_propl(ITextFontImpl *font, enum textfont_prop_id propid, LONG value)
838 {
839 textfont_prop_val v;
840 v.l = value;
841 return set_textfont_prop(font, propid, &v);
842 }
843
844 static inline HRESULT set_textfont_propf(ITextFontImpl *font, enum textfont_prop_id propid, FLOAT value)
845 {
846 textfont_prop_val v;
847 v.f = value;
848 return set_textfont_prop(font, propid, &v);
849 }
850
851 static HRESULT set_textfont_propd(ITextFontImpl *font, enum textfont_prop_id propid, LONG value)
852 {
853 textfont_prop_val v;
854
855 switch (value)
856 {
857 case tomUndefined:
858 return S_OK;
859 case tomToggle: {
860 LONG oldvalue;
861 get_textfont_propl(font, propid, &oldvalue);
862 if (oldvalue == tomFalse)
863 value = tomTrue;
864 else if (oldvalue == tomTrue)
865 value = tomFalse;
866 else
867 return E_INVALIDARG;
868 /* fallthrough */
869 }
870 case tomTrue:
871 case tomFalse:
872 v.l = value;
873 return set_textfont_prop(font, propid, &v);
874 default:
875 return E_INVALIDARG;
876 }
877 }
878
879 static HRESULT textfont_getname_from_range(ITextRange *range, BSTR *ret)
880 {
881 const IRichEditOleImpl *reole;
882 textfont_prop_val v;
883 HRESULT hr;
884 LONG start;
885
886 if (!(reole = get_range_reole(range)))
887 return CO_E_RELEASED;
888
889 ITextRange_GetStart(range, &start);
890 hr = get_textfont_prop_for_pos(reole, start, FONT_NAME, &v);
891 *ret = v.str;
892 return hr;
893 }
894
895 static void textfont_cache_range_props(ITextFontImpl *font)
896 {
897 enum textfont_prop_id propid;
898 for (propid = FONT_PROPID_FIRST; propid < FONT_PROPID_LAST; propid++) {
899 if (propid == FONT_NAME)
900 textfont_getname_from_range(font->range, &font->props[propid].str);
901 else
902 get_textfont_prop(font, propid, &font->props[propid]);
903 }
904 }
905
906 static HRESULT textrange_expand(ITextRange *range, LONG unit, LONG *delta)
907 {
908 LONG expand_start, expand_end;
909
910 switch (unit)
911 {
912 case tomStory:
913 expand_start = 0;
914 ITextRange_GetStoryLength(range, &expand_end);
915 break;
916 default:
917 FIXME("unit %d is not supported\n", unit);
918 return E_NOTIMPL;
919 }
920
921 if (delta) {
922 LONG start, end;
923
924 ITextRange_GetStart(range, &start);
925 ITextRange_GetEnd(range, &end);
926 *delta = expand_end - expand_start - (end - start);
927 }
928
929 ITextRange_SetStart(range, expand_start);
930 ITextRange_SetEnd(range, expand_end);
931
932 return S_OK;
933 }
934
935 static HRESULT WINAPI IRichEditOleImpl_inner_fnQueryInterface(IUnknown *iface, REFIID riid, LPVOID *ppvObj)
936 {
937 IRichEditOleImpl *This = impl_from_IUnknown(iface);
938
939 TRACE("%p %s\n", This, debugstr_guid(riid));
940
941 *ppvObj = NULL;
942 if (IsEqualGUID(riid, &IID_IUnknown))
943 *ppvObj = &This->IUnknown_inner;
944 else if (IsEqualGUID(riid, &IID_IRichEditOle))
945 *ppvObj = &This->IRichEditOle_iface;
946 else if (IsEqualGUID(riid, &IID_ITextDocument))
947 *ppvObj = &This->ITextDocument_iface;
948 if (*ppvObj)
949 {
950 IUnknown_AddRef((IUnknown *)*ppvObj);
951 return S_OK;
952 }
953
954 if (IsEqualGUID(riid, &IID_ITextServices))
955 {
956 static int once;
957 if (!once++) FIXME("%p: unhandled interface IID_ITextServices\n", This);
958 return E_NOINTERFACE;
959 }
960
961 FIXME("%p: unhandled interface %s\n", This, debugstr_guid(riid));
962
963 return E_NOINTERFACE;
964 }
965
966 static ULONG WINAPI IRichEditOleImpl_inner_fnAddRef(IUnknown *iface)
967 {
968 IRichEditOleImpl *This = impl_from_IUnknown(iface);
969 ULONG ref = InterlockedIncrement(&This->ref);
970
971 TRACE("%p ref = %u\n", This, ref);
972
973 return ref;
974 }
975
976 static ULONG WINAPI IRichEditOleImpl_inner_fnRelease(IUnknown *iface)
977 {
978 IRichEditOleImpl *This = impl_from_IUnknown(iface);
979 ULONG ref = InterlockedDecrement(&This->ref);
980
981 TRACE ("%p ref=%u\n", This, ref);
982
983 if (!ref)
984 {
985 IOleClientSiteImpl *clientsite;
986 ITextRangeImpl *txtRge;
987
988 This->editor->reOle = NULL;
989 if (This->txtSel) {
990 This->txtSel->reOle = NULL;
991 ITextSelection_Release(&This->txtSel->ITextSelection_iface);
992 }
993
994 LIST_FOR_EACH_ENTRY(txtRge, &This->rangelist, ITextRangeImpl, child.entry)
995 txtRge->child.reole = NULL;
996
997 LIST_FOR_EACH_ENTRY(clientsite, &This->clientsites, IOleClientSiteImpl, child.entry)
998 clientsite->child.reole = NULL;
999
1000 heap_free(This);
1001 }
1002 return ref;
1003 }
1004
1005 static const IUnknownVtbl reo_unk_vtbl =
1006 {
1007 IRichEditOleImpl_inner_fnQueryInterface,
1008 IRichEditOleImpl_inner_fnAddRef,
1009 IRichEditOleImpl_inner_fnRelease
1010 };
1011
1012 static HRESULT WINAPI
1013 IRichEditOle_fnQueryInterface(IRichEditOle *me, REFIID riid, LPVOID *ppvObj)
1014 {
1015 IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1016 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
1017 }
1018
1019 static ULONG WINAPI
1020 IRichEditOle_fnAddRef(IRichEditOle *me)
1021 {
1022 IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1023 return IUnknown_AddRef(This->outer_unk);
1024 }
1025
1026 static ULONG WINAPI
1027 IRichEditOle_fnRelease(IRichEditOle *me)
1028 {
1029 IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1030 return IUnknown_Release(This->outer_unk);
1031 }
1032
1033 static HRESULT WINAPI
1034 IRichEditOle_fnActivateAs(IRichEditOle *me, REFCLSID rclsid, REFCLSID rclsidAs)
1035 {
1036 IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1037 FIXME("stub %p\n",This);
1038 return E_NOTIMPL;
1039 }
1040
1041 static HRESULT WINAPI
1042 IRichEditOle_fnContextSensitiveHelp(IRichEditOle *me, BOOL fEnterMode)
1043 {
1044 IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1045 FIXME("stub %p\n",This);
1046 return E_NOTIMPL;
1047 }
1048
1049 static HRESULT WINAPI
1050 IRichEditOle_fnConvertObject(IRichEditOle *me, LONG iob,
1051 REFCLSID rclsidNew, LPCSTR lpstrUserTypeNew)
1052 {
1053 IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1054 FIXME("stub %p\n",This);
1055 return E_NOTIMPL;
1056 }
1057
1058 static inline IOleClientSiteImpl *impl_from_IOleClientSite(IOleClientSite *iface)
1059 {
1060 return CONTAINING_RECORD(iface, IOleClientSiteImpl, IOleClientSite_iface);
1061 }
1062
1063 static HRESULT WINAPI
1064 IOleClientSite_fnQueryInterface(IOleClientSite *me, REFIID riid, LPVOID *ppvObj)
1065 {
1066 IOleClientSiteImpl *This = impl_from_IOleClientSite(me);
1067 TRACE("%p %s\n", me, debugstr_guid(riid) );
1068
1069 *ppvObj = NULL;
1070 if (IsEqualGUID(riid, &IID_IUnknown) ||
1071 IsEqualGUID(riid, &IID_IOleClientSite))
1072 *ppvObj = me;
1073 else if (IsEqualGUID(riid, &IID_IOleWindow) ||
1074 IsEqualGUID(riid, &IID_IOleInPlaceSite))
1075 *ppvObj = &This->IOleInPlaceSite_iface;
1076 if (*ppvObj)
1077 {
1078 IOleClientSite_AddRef(me);
1079 return S_OK;
1080 }
1081 FIXME("%p: unhandled interface %s\n", me, debugstr_guid(riid) );
1082
1083 return E_NOINTERFACE;
1084 }
1085
1086 static ULONG WINAPI IOleClientSite_fnAddRef(IOleClientSite *iface)
1087 {
1088 IOleClientSiteImpl *This = impl_from_IOleClientSite(iface);
1089 ULONG ref = InterlockedIncrement(&This->ref);
1090 TRACE("(%p)->(%u)\n", This, ref);
1091 return ref;
1092 }
1093
1094 static ULONG WINAPI IOleClientSite_fnRelease(IOleClientSite *iface)
1095 {
1096 IOleClientSiteImpl *This = impl_from_IOleClientSite(iface);
1097 ULONG ref = InterlockedDecrement(&This->ref);
1098
1099 TRACE("(%p)->(%u)\n", This, ref);
1100
1101 if (ref == 0) {
1102 if (This->child.reole) {
1103 list_remove(&This->child.entry);
1104 This->child.reole = NULL;
1105 }
1106 heap_free(This);
1107 }
1108 return ref;
1109 }
1110
1111 static HRESULT WINAPI IOleClientSite_fnSaveObject(IOleClientSite *iface)
1112 {
1113 IOleClientSiteImpl *This = impl_from_IOleClientSite(iface);
1114 if (!This->child.reole)
1115 return CO_E_RELEASED;
1116
1117 FIXME("stub %p\n", iface);
1118 return E_NOTIMPL;
1119 }
1120
1121 static HRESULT WINAPI IOleClientSite_fnGetMoniker(IOleClientSite *iface, DWORD dwAssign,
1122 DWORD dwWhichMoniker, IMoniker **ppmk)
1123 {
1124 IOleClientSiteImpl *This = impl_from_IOleClientSite(iface);
1125 if (!This->child.reole)
1126 return CO_E_RELEASED;
1127
1128 FIXME("stub %p\n", iface);
1129 return E_NOTIMPL;
1130 }
1131
1132 static HRESULT WINAPI IOleClientSite_fnGetContainer(IOleClientSite *iface,
1133 IOleContainer **ppContainer)
1134 {
1135 IOleClientSiteImpl *This = impl_from_IOleClientSite(iface);
1136 if (!This->child.reole)
1137 return CO_E_RELEASED;
1138
1139 FIXME("stub %p\n", iface);
1140 return E_NOTIMPL;
1141 }
1142
1143 static HRESULT WINAPI IOleClientSite_fnShowObject(IOleClientSite *iface)
1144 {
1145 IOleClientSiteImpl *This = impl_from_IOleClientSite(iface);
1146 if (!This->child.reole)
1147 return CO_E_RELEASED;
1148
1149 FIXME("stub %p\n", iface);
1150 return E_NOTIMPL;
1151 }
1152
1153 static HRESULT WINAPI IOleClientSite_fnOnShowWindow(IOleClientSite *iface, BOOL fShow)
1154 {
1155 IOleClientSiteImpl *This = impl_from_IOleClientSite(iface);
1156 if (!This->child.reole)
1157 return CO_E_RELEASED;
1158
1159 FIXME("stub %p\n", iface);
1160 return E_NOTIMPL;
1161 }
1162
1163 static HRESULT WINAPI IOleClientSite_fnRequestNewObjectLayout(IOleClientSite *iface)
1164 {
1165 IOleClientSiteImpl *This = impl_from_IOleClientSite(iface);
1166 if (!This->child.reole)
1167 return CO_E_RELEASED;
1168
1169 FIXME("stub %p\n", iface);
1170 return E_NOTIMPL;
1171 }
1172
1173 static const IOleClientSiteVtbl ocst = {
1174 IOleClientSite_fnQueryInterface,
1175 IOleClientSite_fnAddRef,
1176 IOleClientSite_fnRelease,
1177 IOleClientSite_fnSaveObject,
1178 IOleClientSite_fnGetMoniker,
1179 IOleClientSite_fnGetContainer,
1180 IOleClientSite_fnShowObject,
1181 IOleClientSite_fnOnShowWindow,
1182 IOleClientSite_fnRequestNewObjectLayout
1183 };
1184
1185 /* IOleInPlaceSite interface */
1186 static HRESULT STDMETHODCALLTYPE IOleInPlaceSite_fnQueryInterface(IOleInPlaceSite *iface, REFIID riid, void **ppvObj)
1187 {
1188 IOleClientSiteImpl *This = impl_from_IOleInPlaceSite(iface);
1189 return IOleClientSite_QueryInterface(&This->IOleClientSite_iface, riid, ppvObj);
1190 }
1191
1192 static ULONG STDMETHODCALLTYPE IOleInPlaceSite_fnAddRef(IOleInPlaceSite *iface)
1193 {
1194 IOleClientSiteImpl *This = impl_from_IOleInPlaceSite(iface);
1195 return IOleClientSite_AddRef(&This->IOleClientSite_iface);
1196 }
1197
1198 static ULONG STDMETHODCALLTYPE IOleInPlaceSite_fnRelease(IOleInPlaceSite *iface)
1199 {
1200 IOleClientSiteImpl *This = impl_from_IOleInPlaceSite(iface);
1201 return IOleClientSite_Release(&This->IOleClientSite_iface);
1202 }
1203
1204 static HRESULT STDMETHODCALLTYPE IOleInPlaceSite_fnGetWindow(IOleInPlaceSite *iface, HWND *phwnd)
1205 {
1206 IOleClientSiteImpl *This = impl_from_IOleInPlaceSite(iface);
1207
1208 TRACE("(%p)->(%p)\n", This, phwnd);
1209
1210 if (!This->child.reole)
1211 return CO_E_RELEASED;
1212
1213 if (!phwnd)
1214 return E_INVALIDARG;
1215
1216 *phwnd = This->child.reole->editor->hWnd;
1217 return S_OK;
1218 }
1219
1220 static HRESULT STDMETHODCALLTYPE IOleInPlaceSite_fnContextSensitiveHelp(IOleInPlaceSite *iface, BOOL fEnterMode)
1221 {
1222 IOleClientSiteImpl *This = impl_from_IOleInPlaceSite(iface);
1223 FIXME("not implemented: (%p)->(%d)\n", This, fEnterMode);
1224 return E_NOTIMPL;
1225 }
1226
1227 static HRESULT STDMETHODCALLTYPE IOleInPlaceSite_fnCanInPlaceActivate(IOleInPlaceSite *iface)
1228 {
1229 IOleClientSiteImpl *This = impl_from_IOleInPlaceSite(iface);
1230 FIXME("not implemented: (%p)\n", This);
1231 return E_NOTIMPL;
1232 }
1233
1234 static HRESULT STDMETHODCALLTYPE IOleInPlaceSite_fnOnInPlaceActivate(IOleInPlaceSite *iface)
1235 {
1236 IOleClientSiteImpl *This = impl_from_IOleInPlaceSite(iface);
1237 FIXME("not implemented: (%p)\n", This);
1238 return E_NOTIMPL;
1239 }
1240
1241 static HRESULT STDMETHODCALLTYPE IOleInPlaceSite_fnOnUIActivate(IOleInPlaceSite *iface)
1242 {
1243 IOleClientSiteImpl *This = impl_from_IOleInPlaceSite(iface);
1244 FIXME("not implemented: (%p)\n", This);
1245 return E_NOTIMPL;
1246 }
1247
1248 static HRESULT STDMETHODCALLTYPE IOleInPlaceSite_fnGetWindowContext(IOleInPlaceSite *iface, IOleInPlaceFrame **ppFrame,
1249 IOleInPlaceUIWindow **ppDoc, LPRECT lprcPosRect,
1250 LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo)
1251 {
1252 IOleClientSiteImpl *This = impl_from_IOleInPlaceSite(iface);
1253 FIXME("not implemented: (%p)->(%p %p %p %p %p)\n", This, ppFrame, ppDoc, lprcPosRect, lprcClipRect, lpFrameInfo);
1254 return E_NOTIMPL;
1255 }
1256
1257 static HRESULT STDMETHODCALLTYPE IOleInPlaceSite_fnScroll(IOleInPlaceSite *iface, SIZE scrollExtent)
1258 {
1259 IOleClientSiteImpl *This = impl_from_IOleInPlaceSite(iface);
1260 FIXME("not implemented: (%p)\n", This);
1261 return E_NOTIMPL;
1262 }
1263
1264 static HRESULT STDMETHODCALLTYPE IOleInPlaceSite_fnOnUIDeactivate(IOleInPlaceSite *iface, BOOL fUndoable)
1265 {
1266 IOleClientSiteImpl *This = impl_from_IOleInPlaceSite(iface);
1267 FIXME("not implemented: (%p)->(%d)\n", This, fUndoable);
1268 return E_NOTIMPL;
1269 }
1270
1271 static HRESULT STDMETHODCALLTYPE IOleInPlaceSite_fnOnInPlaceDeactivate(IOleInPlaceSite *iface)
1272 {
1273 IOleClientSiteImpl *This = impl_from_IOleInPlaceSite(iface);
1274 FIXME("not implemented: (%p)\n", This);
1275 return E_NOTIMPL;
1276 }
1277
1278 static HRESULT STDMETHODCALLTYPE IOleInPlaceSite_fnDiscardUndoState(IOleInPlaceSite *iface)
1279 {
1280 IOleClientSiteImpl *This = impl_from_IOleInPlaceSite(iface);
1281 FIXME("not implemented: (%p)\n", This);
1282 return E_NOTIMPL;
1283 }
1284
1285 static HRESULT STDMETHODCALLTYPE IOleInPlaceSite_fnDeactivateAndUndo(IOleInPlaceSite *iface)
1286 {
1287 IOleClientSiteImpl *This = impl_from_IOleInPlaceSite(iface);
1288 FIXME("not implemented: (%p)\n", This);
1289 return E_NOTIMPL;
1290 }
1291
1292 static HRESULT STDMETHODCALLTYPE IOleInPlaceSite_fnOnPosRectChange(IOleInPlaceSite *iface, LPCRECT lprcPosRect)
1293 {
1294 IOleClientSiteImpl *This = impl_from_IOleInPlaceSite(iface);
1295 FIXME("not implemented: (%p)->(%p)\n", This, lprcPosRect);
1296 return E_NOTIMPL;
1297 }
1298
1299 static const IOleInPlaceSiteVtbl olestvt =
1300 {
1301 IOleInPlaceSite_fnQueryInterface,
1302 IOleInPlaceSite_fnAddRef,
1303 IOleInPlaceSite_fnRelease,
1304 IOleInPlaceSite_fnGetWindow,
1305 IOleInPlaceSite_fnContextSensitiveHelp,
1306 IOleInPlaceSite_fnCanInPlaceActivate,
1307 IOleInPlaceSite_fnOnInPlaceActivate,
1308 IOleInPlaceSite_fnOnUIActivate,
1309 IOleInPlaceSite_fnGetWindowContext,
1310 IOleInPlaceSite_fnScroll,
1311 IOleInPlaceSite_fnOnUIDeactivate,
1312 IOleInPlaceSite_fnOnInPlaceDeactivate,
1313 IOleInPlaceSite_fnDiscardUndoState,
1314 IOleInPlaceSite_fnDeactivateAndUndo,
1315 IOleInPlaceSite_fnOnPosRectChange
1316 };
1317
1318 static HRESULT CreateOleClientSite(IRichEditOleImpl *reOle, IOleClientSite **ret)
1319 {
1320 IOleClientSiteImpl *clientSite = heap_alloc(sizeof *clientSite);
1321
1322 if (!clientSite)
1323 return E_OUTOFMEMORY;
1324
1325 clientSite->IOleClientSite_iface.lpVtbl = &ocst;
1326 clientSite->IOleInPlaceSite_iface.lpVtbl = &olestvt;
1327 clientSite->ref = 1;
1328 clientSite->child.reole = reOle;
1329 list_add_head(&reOle->clientsites, &clientSite->child.entry);
1330
1331 *ret = &clientSite->IOleClientSite_iface;
1332 return S_OK;
1333 }
1334
1335 static HRESULT WINAPI
1336 IRichEditOle_fnGetClientSite(IRichEditOle *me, IOleClientSite **clientsite)
1337 {
1338 IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1339
1340 TRACE("(%p)->(%p)\n", This, clientsite);
1341
1342 if (!clientsite)
1343 return E_INVALIDARG;
1344
1345 return CreateOleClientSite(This, clientsite);
1346 }
1347
1348 static HRESULT WINAPI
1349 IRichEditOle_fnGetClipboardData(IRichEditOle *me, CHARRANGE *lpchrg,
1350 DWORD reco, LPDATAOBJECT *lplpdataobj)
1351 {
1352 IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1353 ME_Cursor start;
1354 int nChars;
1355
1356 TRACE("(%p,%p,%d)\n",This, lpchrg, reco);
1357 if(!lplpdataobj)
1358 return E_INVALIDARG;
1359 if(!lpchrg) {
1360 int nFrom, nTo, nStartCur = ME_GetSelectionOfs(This->editor, &nFrom, &nTo);
1361 start = This->editor->pCursors[nStartCur];
1362 nChars = nTo - nFrom;
1363 } else {
1364 ME_CursorFromCharOfs(This->editor, lpchrg->cpMin, &start);
1365 nChars = lpchrg->cpMax - lpchrg->cpMin;
1366 }
1367 return ME_GetDataObject(This->editor, &start, nChars, lplpdataobj);
1368 }
1369
1370 static LONG WINAPI IRichEditOle_fnGetLinkCount(IRichEditOle *me)
1371 {
1372 IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1373 FIXME("stub %p\n",This);
1374 return E_NOTIMPL;
1375 }
1376
1377 static HRESULT WINAPI
1378 IRichEditOle_fnGetObject(IRichEditOle *me, LONG iob,
1379 REOBJECT *lpreobject, DWORD dwFlags)
1380 {
1381 IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1382 FIXME("stub %p\n",This);
1383 return E_NOTIMPL;
1384 }
1385
1386 static LONG WINAPI
1387 IRichEditOle_fnGetObjectCount(IRichEditOle *me)
1388 {
1389 IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1390 FIXME("stub %p\n",This);
1391 return 0;
1392 }
1393
1394 static HRESULT WINAPI
1395 IRichEditOle_fnHandsOffStorage(IRichEditOle *me, LONG iob)
1396 {
1397 IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1398 FIXME("stub %p\n",This);
1399 return E_NOTIMPL;
1400 }
1401
1402 static HRESULT WINAPI
1403 IRichEditOle_fnImportDataObject(IRichEditOle *me, LPDATAOBJECT lpdataobj,
1404 CLIPFORMAT cf, HGLOBAL hMetaPict)
1405 {
1406 IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1407 FIXME("stub %p\n",This);
1408 return E_NOTIMPL;
1409 }
1410
1411 static HRESULT WINAPI
1412 IRichEditOle_fnInPlaceDeactivate(IRichEditOle *me)
1413 {
1414 IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1415 FIXME("stub %p\n",This);
1416 return E_NOTIMPL;
1417 }
1418
1419 static HRESULT WINAPI
1420 IRichEditOle_fnInsertObject(IRichEditOle *me, REOBJECT *reo)
1421 {
1422 IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1423
1424 TRACE("(%p,%p)\n", This, reo);
1425
1426 if (!reo)
1427 return E_INVALIDARG;
1428
1429 if (reo->cbStruct < sizeof(*reo)) return STG_E_INVALIDPARAMETER;
1430
1431 ME_InsertOLEFromCursor(This->editor, reo, 0);
1432 ME_CommitUndo(This->editor);
1433 ME_UpdateRepaint(This->editor, FALSE);
1434 return S_OK;
1435 }
1436
1437 static HRESULT WINAPI IRichEditOle_fnSaveCompleted(IRichEditOle *me, LONG iob,
1438 LPSTORAGE lpstg)
1439 {
1440 IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1441 FIXME("stub %p\n",This);
1442 return E_NOTIMPL;
1443 }
1444
1445 static HRESULT WINAPI
1446 IRichEditOle_fnSetDvaspect(IRichEditOle *me, LONG iob, DWORD dvaspect)
1447 {
1448 IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1449 FIXME("stub %p\n",This);
1450 return E_NOTIMPL;
1451 }
1452
1453 static HRESULT WINAPI IRichEditOle_fnSetHostNames(IRichEditOle *me,
1454 LPCSTR lpstrContainerApp, LPCSTR lpstrContainerObj)
1455 {
1456 IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1457 FIXME("stub %p %s %s\n",This, lpstrContainerApp, lpstrContainerObj);
1458 return E_NOTIMPL;
1459 }
1460
1461 static HRESULT WINAPI
1462 IRichEditOle_fnSetLinkAvailable(IRichEditOle *me, LONG iob, BOOL fAvailable)
1463 {
1464 IRichEditOleImpl *This = impl_from_IRichEditOle(me);
1465 FIXME("stub %p\n",This);
1466 return E_NOTIMPL;
1467 }
1468
1469 static const IRichEditOleVtbl revt = {
1470 IRichEditOle_fnQueryInterface,
1471 IRichEditOle_fnAddRef,
1472 IRichEditOle_fnRelease,
1473 IRichEditOle_fnGetClientSite,
1474 IRichEditOle_fnGetObjectCount,
1475 IRichEditOle_fnGetLinkCount,
1476 IRichEditOle_fnGetObject,
1477 IRichEditOle_fnInsertObject,
1478 IRichEditOle_fnConvertObject,
1479 IRichEditOle_fnActivateAs,
1480 IRichEditOle_fnSetHostNames,
1481 IRichEditOle_fnSetLinkAvailable,
1482 IRichEditOle_fnSetDvaspect,
1483 IRichEditOle_fnHandsOffStorage,
1484 IRichEditOle_fnSaveCompleted,
1485 IRichEditOle_fnInPlaceDeactivate,
1486 IRichEditOle_fnContextSensitiveHelp,
1487 IRichEditOle_fnGetClipboardData,
1488 IRichEditOle_fnImportDataObject
1489 };
1490
1491 /* ITextRange interface */
1492 static HRESULT WINAPI ITextRange_fnQueryInterface(ITextRange *me, REFIID riid, void **ppvObj)
1493 {
1494 ITextRangeImpl *This = impl_from_ITextRange(me);
1495
1496 *ppvObj = NULL;
1497 if (IsEqualGUID(riid, &IID_IUnknown)
1498 || IsEqualGUID(riid, &IID_IDispatch)
1499 || IsEqualGUID(riid, &IID_ITextRange))
1500 {
1501 *ppvObj = me;
1502 ITextRange_AddRef(me);
1503 return S_OK;
1504 }
1505 else if (IsEqualGUID(riid, &IID_Igetrichole))
1506 {
1507 *ppvObj = This->child.reole;
1508 return S_OK;
1509 }
1510
1511 return E_NOINTERFACE;
1512 }
1513
1514 static ULONG WINAPI ITextRange_fnAddRef(ITextRange *me)
1515 {
1516 ITextRangeImpl *This = impl_from_ITextRange(me);
1517 return InterlockedIncrement(&This->ref);
1518 }
1519
1520 static ULONG WINAPI ITextRange_fnRelease(ITextRange *me)
1521 {
1522 ITextRangeImpl *This = impl_from_ITextRange(me);
1523 ULONG ref = InterlockedDecrement(&This->ref);
1524
1525 TRACE ("%p ref=%u\n", This, ref);
1526 if (ref == 0)
1527 {
1528 if (This->child.reole)
1529 {
1530 list_remove(&This->child.entry);
1531 This->child.reole = NULL;
1532 }
1533 heap_free(This);
1534 }
1535 return ref;
1536 }
1537
1538 static HRESULT WINAPI ITextRange_fnGetTypeInfoCount(ITextRange *me, UINT *pctinfo)
1539 {
1540 ITextRangeImpl *This = impl_from_ITextRange(me);
1541 TRACE("(%p)->(%p)\n", This, pctinfo);
1542 *pctinfo = 1;
1543 return S_OK;
1544 }
1545
1546 static HRESULT WINAPI ITextRange_fnGetTypeInfo(ITextRange *me, UINT iTInfo, LCID lcid,
1547 ITypeInfo **ppTInfo)
1548 {
1549 ITextRangeImpl *This = impl_from_ITextRange(me);
1550 HRESULT hr;
1551
1552 TRACE("(%p)->(%u,%d,%p)\n", This, iTInfo, lcid, ppTInfo);
1553
1554 hr = get_typeinfo(ITextRange_tid, ppTInfo);
1555 if (SUCCEEDED(hr))
1556 ITypeInfo_AddRef(*ppTInfo);
1557 return hr;
1558 }
1559
1560 static HRESULT WINAPI ITextRange_fnGetIDsOfNames(ITextRange *me, REFIID riid, LPOLESTR *rgszNames,
1561 UINT cNames, LCID lcid, DISPID *rgDispId)
1562 {
1563 ITextRangeImpl *This = impl_from_ITextRange(me);
1564 ITypeInfo *ti;
1565 HRESULT hr;
1566
1567 TRACE("(%p)->(%s, %p, %u, %d, %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid,
1568 rgDispId);
1569
1570 hr = get_typeinfo(ITextRange_tid, &ti);
1571 if (SUCCEEDED(hr))
1572 hr = ITypeInfo_GetIDsOfNames(ti, rgszNames, cNames, rgDispId);
1573 return hr;
1574 }
1575
1576 static HRESULT WINAPI ITextRange_fnInvoke(ITextRange *me, DISPID dispIdMember, REFIID riid,
1577 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1578 VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
1579 UINT *puArgErr)
1580 {
1581 ITextRangeImpl *This = impl_from_ITextRange(me);
1582 ITypeInfo *ti;
1583 HRESULT hr;
1584
1585 TRACE("(%p)->(%d, %s, %d, %u, %p, %p, %p, %p)\n", This, dispIdMember, debugstr_guid(riid),
1586 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1587
1588 hr = get_typeinfo(ITextRange_tid, &ti);
1589 if (SUCCEEDED(hr))
1590 hr = ITypeInfo_Invoke(ti, me, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1591 return hr;
1592 }
1593
1594 static HRESULT WINAPI ITextRange_fnGetText(ITextRange *me, BSTR *str)
1595 {
1596 ITextRangeImpl *This = impl_from_ITextRange(me);
1597 ME_TextEditor *editor;
1598 ME_Cursor start, end;
1599 int length;
1600 BOOL bEOP;
1601
1602 TRACE("(%p)->(%p)\n", This, str);
1603
1604 if (!This->child.reole)
1605 return CO_E_RELEASED;
1606
1607 if (!str)
1608 return E_INVALIDARG;
1609
1610 /* return early for degenerate range */
1611 if (This->start == This->end) {
1612 *str = NULL;
1613 return S_OK;
1614 }
1615
1616 editor = This->child.reole->editor;
1617 ME_CursorFromCharOfs(editor, This->start, &start);
1618 ME_CursorFromCharOfs(editor, This->end, &end);
1619
1620 length = This->end - This->start;
1621 *str = SysAllocStringLen(NULL, length);
1622 if (!*str)
1623 return E_OUTOFMEMORY;
1624
1625 bEOP = (end.pRun->next->type == diTextEnd && This->end > ME_GetTextLength(editor));
1626 ME_GetTextW(editor, *str, length, &start, length, FALSE, bEOP);
1627 return S_OK;
1628 }
1629
1630 static HRESULT WINAPI ITextRange_fnSetText(ITextRange *me, BSTR str)
1631 {
1632 ITextRangeImpl *This = impl_from_ITextRange(me);
1633 ME_TextEditor *editor;
1634 ME_Cursor cursor;
1635 ME_Style *style;
1636 int len;
1637
1638 TRACE("(%p)->(%s)\n", This, debugstr_w(str));
1639
1640 if (!This->child.reole)
1641 return CO_E_RELEASED;
1642
1643 editor = This->child.reole->editor;
1644
1645 /* delete only where's something to delete */
1646 if (This->start != This->end) {
1647 ME_CursorFromCharOfs(editor, This->start, &cursor);
1648 ME_InternalDeleteText(editor, &cursor, This->end - This->start, FALSE);
1649 }
1650
1651 if (!str || !*str) {
1652 /* will update this range as well */
1653 textranges_update_ranges(This->child.reole, This->start, This->end, RANGE_UPDATE_DELETE);
1654 return S_OK;
1655 }
1656
1657 /* it's safer not to rely on stored BSTR length */
1658 len = strlenW(str);
1659 cursor = editor->pCursors[0];
1660 ME_CursorFromCharOfs(editor, This->start, &editor->pCursors[0]);
1661 style = ME_GetInsertStyle(editor, 0);
1662 ME_InsertTextFromCursor(editor, 0, str, len, style);
1663 ME_ReleaseStyle(style);
1664 editor->pCursors[0] = cursor;
1665
1666 if (len < This->end - This->start)
1667 textranges_update_ranges(This->child.reole, This->start + len, This->end, RANGE_UPDATE_DELETE);
1668 else
1669 This->end = len - This->start;
1670
1671 return S_OK;
1672 }
1673
1674 static HRESULT range_GetChar(ME_TextEditor *editor, ME_Cursor *cursor, LONG *pch)
1675 {
1676 WCHAR wch[2];
1677
1678 ME_GetTextW(editor, wch, 1, cursor, 1, FALSE, cursor->pRun->next->type == diTextEnd);
1679 *pch = wch[0];
1680
1681 return S_OK;
1682 }
1683
1684 static HRESULT WINAPI ITextRange_fnGetChar(ITextRange *me, LONG *pch)
1685 {
1686 ITextRangeImpl *This = impl_from_ITextRange(me);
1687 ME_TextEditor *editor;
1688 ME_Cursor cursor;
1689
1690 TRACE("(%p)->(%p)\n", This, pch);
1691
1692 if (!This->child.reole)
1693 return CO_E_RELEASED;
1694
1695 if (!pch)
1696 return E_INVALIDARG;
1697
1698 editor = This->child.reole->editor;
1699 ME_CursorFromCharOfs(editor, This->start, &cursor);
1700 return range_GetChar(editor, &cursor, pch);
1701 }
1702
1703 static HRESULT WINAPI ITextRange_fnSetChar(ITextRange *me, LONG ch)
1704 {
1705 ITextRangeImpl *This = impl_from_ITextRange(me);
1706
1707 FIXME("(%p)->(%x): stub\n", This, ch);
1708
1709 if (!This->child.reole)
1710 return CO_E_RELEASED;
1711
1712 return E_NOTIMPL;
1713 }
1714
1715 static HRESULT CreateITextRange(IRichEditOleImpl *reOle, LONG start, LONG end, ITextRange** ppRange);
1716
1717 static HRESULT WINAPI ITextRange_fnGetDuplicate(ITextRange *me, ITextRange **ppRange)
1718 {
1719 ITextRangeImpl *This = impl_from_ITextRange(me);
1720
1721 TRACE("(%p)->(%p)\n", This, ppRange);
1722
1723 if (!This->child.reole)
1724 return CO_E_RELEASED;
1725
1726 if (!ppRange)
1727 return E_INVALIDARG;
1728
1729 return CreateITextRange(This->child.reole, This->start, This->end, ppRange);
1730 }
1731
1732 static HRESULT WINAPI ITextRange_fnGetFormattedText(ITextRange *me, ITextRange **range)
1733 {
1734 ITextRangeImpl *This = impl_from_ITextRange(me);
1735
1736 FIXME("(%p)->(%p): stub\n", This, range);
1737
1738 if (!This->child.reole)
1739 return CO_E_RELEASED;
1740
1741 return E_NOTIMPL;
1742 }
1743
1744 static HRESULT WINAPI ITextRange_fnSetFormattedText(ITextRange *me, ITextRange *range)
1745 {
1746 ITextRangeImpl *This = impl_from_ITextRange(me);
1747
1748 FIXME("(%p)->(%p): stub\n", This, range);
1749
1750 if (!This->child.reole)
1751 return CO_E_RELEASED;
1752
1753 return E_NOTIMPL;
1754 }
1755
1756 static HRESULT WINAPI ITextRange_fnGetStart(ITextRange *me, LONG *start)
1757 {
1758 ITextRangeImpl *This = impl_from_ITextRange(me);
1759
1760 TRACE("(%p)->(%p)\n", This, start);
1761
1762 if (!This->child.reole)
1763 return CO_E_RELEASED;
1764
1765 if (!start)
1766 return E_INVALIDARG;
1767
1768 *start = This->start;
1769 return S_OK;
1770 }
1771
1772 static HRESULT textrange_setstart(const IRichEditOleImpl *reole, LONG value, LONG *start, LONG *end)
1773 {
1774 int len;
1775
1776 if (value < 0)
1777 value = 0;
1778
1779 if (value == *start)
1780 return S_FALSE;
1781
1782 if (value <= *end) {
1783 *start = value;
1784 return S_OK;
1785 }
1786
1787 len = ME_GetTextLength(reole->editor);
1788 *start = *end = value > len ? len : value;
1789 return S_OK;
1790 }
1791
1792 static HRESULT WINAPI ITextRange_fnSetStart(ITextRange *me, LONG value)
1793 {
1794 ITextRangeImpl *This = impl_from_ITextRange(me);
1795
1796 TRACE("(%p)->(%d)\n", This, value);
1797
1798 if (!This->child.reole)
1799 return CO_E_RELEASED;
1800
1801 return textrange_setstart(This->child.reole, value, &This->start, &This->end);
1802 }
1803
1804 static HRESULT WINAPI ITextRange_fnGetEnd(ITextRange *me, LONG *end)
1805 {
1806 ITextRangeImpl *This = impl_from_ITextRange(me);
1807
1808 TRACE("(%p)->(%p)\n", This, end);
1809
1810 if (!This->child.reole)
1811 return CO_E_RELEASED;
1812
1813 if (!end)
1814 return E_INVALIDARG;
1815
1816 *end = This->end;
1817 return S_OK;
1818 }
1819
1820 static HRESULT textrange_setend(const IRichEditOleImpl *reole, LONG value, LONG *start, LONG *end)
1821 {
1822 int len;
1823
1824 if (value == *end)
1825 return S_FALSE;
1826
1827 if (value < *start) {
1828 *start = *end = max(0, value);
1829 return S_OK;
1830 }
1831
1832 len = ME_GetTextLength(reole->editor);
1833 *end = value > len ? len + 1 : value;
1834 return S_OK;
1835 }
1836
1837 static HRESULT WINAPI ITextRange_fnSetEnd(ITextRange *me, LONG value)
1838 {
1839 ITextRangeImpl *This = impl_from_ITextRange(me);
1840
1841 TRACE("(%p)->(%d)\n", This, value);
1842
1843 if (!This->child.reole)
1844 return CO_E_RELEASED;
1845
1846 return textrange_setend(This->child.reole, value, &This->start, &This->end);
1847 }
1848
1849 static HRESULT WINAPI ITextRange_fnGetFont(ITextRange *me, ITextFont **font)
1850 {
1851 ITextRangeImpl *This = impl_from_ITextRange(me);
1852
1853 TRACE("(%p)->(%p)\n", This, font);
1854
1855 if (!This->child.reole)
1856 return CO_E_RELEASED;
1857
1858 if (!font)
1859 return E_INVALIDARG;
1860
1861 return create_textfont(me, NULL, font);
1862 }
1863
1864 static HRESULT WINAPI ITextRange_fnSetFont(ITextRange *me, ITextFont *font)
1865 {
1866 ITextRangeImpl *This = impl_from_ITextRange(me);
1867
1868 TRACE("(%p)->(%p)\n", This, font);
1869
1870 if (!font)
1871 return E_INVALIDARG;
1872
1873 if (!This->child.reole)
1874 return CO_E_RELEASED;
1875
1876 textrange_set_font(me, font);
1877 return S_OK;
1878 }
1879
1880 static HRESULT WINAPI ITextRange_fnGetPara(ITextRange *me, ITextPara **para)
1881 {
1882 ITextRangeImpl *This = impl_from_ITextRange(me);
1883
1884 TRACE("(%p)->(%p)\n", This, para);
1885
1886 if (!This->child.reole)
1887 return CO_E_RELEASED;
1888
1889 if (!para)
1890 return E_INVALIDARG;
1891
1892 return create_textpara(me, para);
1893 }
1894
1895 static HRESULT WINAPI ITextRange_fnSetPara(ITextRange *me, ITextPara *para)
1896 {
1897 ITextRangeImpl *This = impl_from_ITextRange(me);
1898
1899 FIXME("(%p)->(%p): stub\n", This, para);
1900
1901 if (!This->child.reole)
1902 return CO_E_RELEASED;
1903
1904 return E_NOTIMPL;
1905 }
1906
1907 static HRESULT WINAPI ITextRange_fnGetStoryLength(ITextRange *me, LONG *length)
1908 {
1909 ITextRangeImpl *This = impl_from_ITextRange(me);
1910
1911 TRACE("(%p)->(%p)\n", This, length);
1912
1913 if (!This->child.reole)
1914 return CO_E_RELEASED;
1915
1916 return textrange_get_storylength(This->child.reole->editor, length);
1917 }
1918
1919 static HRESULT WINAPI ITextRange_fnGetStoryType(ITextRange *me, LONG *value)
1920 {
1921 ITextRangeImpl *This = impl_from_ITextRange(me);
1922
1923 TRACE("(%p)->(%p)\n", This, value);
1924
1925 if (!This->child.reole)
1926 return CO_E_RELEASED;
1927
1928 if (!value)
1929 return E_INVALIDARG;
1930
1931 *value = tomUnknownStory;
1932 return S_OK;
1933 }
1934
1935 static HRESULT range_Collapse(LONG bStart, LONG *start, LONG *end)
1936 {
1937 if (*end == *start)
1938 return S_FALSE;
1939
1940 if (bStart == tomEnd)
1941 *start = *end;
1942 else
1943 *end = *start;
1944 return S_OK;
1945 }
1946
1947 static HRESULT WINAPI ITextRange_fnCollapse(ITextRange *me, LONG bStart)
1948 {
1949 ITextRangeImpl *This = impl_from_ITextRange(me);
1950
1951 TRACE("(%p)->(%d)\n", This, bStart);
1952
1953 if (!This->child.reole)
1954 return CO_E_RELEASED;
1955
1956 return range_Collapse(bStart, &This->start, &This->end);
1957 }
1958
1959 static HRESULT WINAPI ITextRange_fnExpand(ITextRange *me, LONG unit, LONG *delta)
1960 {
1961 ITextRangeImpl *This = impl_from_ITextRange(me);
1962
1963 TRACE("(%p)->(%d %p)\n", This, unit, delta);
1964
1965 if (!This->child.reole)
1966 return CO_E_RELEASED;
1967
1968 return textrange_expand(me, unit, delta);
1969 }
1970
1971 static HRESULT WINAPI ITextRange_fnGetIndex(ITextRange *me, LONG unit, LONG *index)
1972 {
1973 ITextRangeImpl *This = impl_from_ITextRange(me);
1974
1975 FIXME("(%p)->(%d %p): stub\n", This, unit, index);
1976
1977 if (!This->child.reole)
1978 return CO_E_RELEASED;
1979
1980 return E_NOTIMPL;
1981 }
1982
1983 static HRESULT WINAPI ITextRange_fnSetIndex(ITextRange *me, LONG unit, LONG index,
1984 LONG extend)
1985 {
1986 ITextRangeImpl *This = impl_from_ITextRange(me);
1987
1988 FIXME("(%p)->(%d %d %d): stub\n", This, unit, index, extend);
1989
1990 if (!This->child.reole)
1991 return CO_E_RELEASED;
1992
1993 return E_NOTIMPL;
1994 }
1995
1996 static void cp2range(ME_TextEditor *editor, LONG *cp1, LONG *cp2)
1997 {
1998 int len = ME_GetTextLength(editor) + 1;
1999 *cp1 = max(*cp1, 0);
2000 *cp2 = max(*cp2, 0);
2001 *cp1 = min(*cp1, len);
2002 *cp2 = min(*cp2, len);
2003 if (*cp1 > *cp2)
2004 {
2005 int tmp = *cp1;
2006 *cp1 = *cp2;
2007 *cp2 = tmp;
2008 }
2009 if (*cp1 == len)
2010 *cp1 = *cp2 = len - 1;
2011 }
2012
2013 static HRESULT WINAPI ITextRange_fnSetRange(ITextRange *me, LONG anchor, LONG active)
2014 {
2015 ITextRangeImpl *This = impl_from_ITextRange(me);
2016
2017 FIXME("(%p)->(%d %d): stub\n", This, anchor, active);
2018
2019 if (!This->child.reole)
2020 return CO_E_RELEASED;
2021
2022 cp2range(This->child.reole->editor, &anchor, &active);
2023 if (anchor == This->start && active == This->end)
2024 return S_FALSE;
2025
2026 This->start = anchor;
2027 This->end = active;
2028 return S_OK;
2029 }
2030
2031 static HRESULT textrange_inrange(LONG start, LONG end, ITextRange *range, LONG *ret)
2032 {
2033 LONG from, to, v;
2034
2035 if (!ret)
2036 ret = &v;
2037
2038 if (FAILED(ITextRange_GetStart(range, &from)) || FAILED(ITextRange_GetEnd(range, &to))) {
2039 *ret = tomFalse;
2040 }
2041 else
2042 *ret = (start >= from && end <= to) ? tomTrue : tomFalse;
2043 return *ret == tomTrue ? S_OK : S_FALSE;
2044 }
2045
2046 static HRESULT WINAPI ITextRange_fnInRange(ITextRange *me, ITextRange *range, LONG *ret)
2047 {
2048 ITextRangeImpl *This = impl_from_ITextRange(me);
2049
2050 TRACE("(%p)->(%p %p)\n", This, range, ret);
2051
2052 if (ret)
2053 *ret = tomFalse;
2054
2055 if (!This->child.reole)
2056 return CO_E_RELEASED;
2057
2058 if (!range)
2059 return S_FALSE;
2060
2061 return textrange_inrange(This->start, This->end, range, ret);
2062 }
2063
2064 static HRESULT WINAPI ITextRange_fnInStory(ITextRange *me, ITextRange *pRange, LONG *ret)
2065 {
2066 ITextRangeImpl *This = impl_from_ITextRange(me);
2067
2068 FIXME("(%p)->(%p): stub\n", This, ret);
2069
2070 if (!This->child.reole)
2071 return CO_E_RELEASED;
2072
2073 return E_NOTIMPL;
2074 }
2075
2076 static HRESULT textrange_isequal(LONG start, LONG end, ITextRange *range, LONG *ret)
2077 {
2078 LONG from, to, v;
2079
2080 if (!ret)
2081 ret = &v;
2082
2083 if (FAILED(ITextRange_GetStart(range, &from)) || FAILED(ITextRange_GetEnd(range, &to))) {
2084 *ret = tomFalse;
2085 }
2086 else
2087 *ret = (start == from && end == to) ? tomTrue : tomFalse;
2088 return *ret == tomTrue ? S_OK : S_FALSE;
2089 }
2090
2091 static HRESULT WINAPI ITextRange_fnIsEqual(ITextRange *me, ITextRange *range, LONG *ret)
2092 {
2093 ITextRangeImpl *This = impl_from_ITextRange(me);
2094
2095 TRACE("(%p)->(%p %p)\n", This, range, ret);
2096
2097 if (ret)
2098 *ret = tomFalse;
2099
2100 if (!This->child.reole)
2101 return CO_E_RELEASED;
2102
2103 if (!range)
2104 return S_FALSE;
2105
2106 return textrange_isequal(This->start, This->end, range, ret);
2107 }
2108
2109 static HRESULT WINAPI ITextRange_fnSelect(ITextRange *me)
2110 {
2111 ITextRangeImpl *This = impl_from_ITextRange(me);
2112
2113 TRACE("(%p)\n", This);
2114
2115 if (!This->child.reole)
2116 return CO_E_RELEASED;
2117
2118 ME_SetSelection(This->child.reole->editor, This->start, This->end);
2119 return S_OK;
2120 }
2121
2122 static HRESULT WINAPI ITextRange_fnStartOf(ITextRange *me, LONG unit, LONG extend,
2123 LONG *delta)
2124 {
2125 ITextRangeImpl *This = impl_from_ITextRange(me);
2126
2127 FIXME("(%p)->(%d %d %p): stub\n", This, unit, extend, delta);
2128
2129 if (!This->child.reole)
2130 return CO_E_RELEASED;
2131
2132 return E_NOTIMPL;
2133 }
2134
2135 static HRESULT WINAPI ITextRange_fnEndOf(ITextRange *me, LONG unit, LONG extend,
2136 LONG *delta)
2137 {
2138 ITextRangeImpl *This = impl_from_ITextRange(me);
2139
2140 FIXME("(%p)->(%d %d %p): stub\n", This, unit, extend, delta);
2141
2142 if (!This->child.reole)
2143 return CO_E_RELEASED;
2144
2145 return E_NOTIMPL;
2146 }
2147
2148 static HRESULT WINAPI ITextRange_fnMove(ITextRange *me, LONG unit, LONG count, LONG *delta)
2149 {
2150 ITextRangeImpl *This = impl_from_ITextRange(me);
2151
2152 FIXME("(%p)->(%d %d %p): stub\n", This, unit, count, delta);
2153
2154 if (!This->child.reole)
2155 return CO_E_RELEASED;
2156
2157 return E_NOTIMPL;
2158 }
2159
2160 static HRESULT WINAPI ITextRange_fnMoveStart(ITextRange *me, LONG unit, LONG count,
2161 LONG *delta)
2162 {
2163 ITextRangeImpl *This = impl_from_ITextRange(me);
2164
2165 FIXME("(%p)->(%d %d %p): stub\n", This, unit, count, delta);
2166
2167 if (!This->child.reole)
2168 return CO_E_RELEASED;
2169
2170 return E_NOTIMPL;
2171 }
2172
2173 static HRESULT WINAPI ITextRange_fnMoveEnd(ITextRange *me, LONG unit, LONG count,
2174 LONG *delta)
2175 {
2176 ITextRangeImpl *This = impl_from_ITextRange(me);
2177
2178 FIXME("(%p)->(%d %d %p): stub\n", This, unit, count, delta);
2179
2180 if (!This->child.reole)
2181 return CO_E_RELEASED;
2182
2183 return E_NOTIMPL;
2184 }
2185
2186 static HRESULT WINAPI ITextRange_fnMoveWhile(ITextRange *me, VARIANT *charset, LONG count,
2187 LONG *delta)
2188 {
2189 ITextRangeImpl *This = impl_from_ITextRange(me);
2190
2191 FIXME("(%p)->(%s %d %p): stub\n", This, debugstr_variant(charset), count, delta);
2192
2193 if (!This->child.reole)
2194 return CO_E_RELEASED;
2195
2196 return E_NOTIMPL;
2197 }
2198
2199 static HRESULT WINAPI ITextRange_fnMoveStartWhile(ITextRange *me, VARIANT *charset, LONG count,
2200 LONG *delta)
2201 {
2202 ITextRangeImpl *This = impl_from_ITextRange(me);
2203
2204 FIXME("(%p)->(%s %d %p): stub\n", This, debugstr_variant(charset), count, delta);
2205
2206 if (!This->child.reole)
2207 return CO_E_RELEASED;
2208
2209 return E_NOTIMPL;
2210 }
2211
2212 static HRESULT WINAPI ITextRange_fnMoveEndWhile(ITextRange *me, VARIANT *charset, LONG count,
2213 LONG *delta)
2214 {
2215 ITextRangeImpl *This = impl_from_ITextRange(me);
2216
2217 FIXME("(%p)->(%s %d %p): stub\n", This, debugstr_variant(charset), count, delta);
2218
2219 if (!This->child.reole)
2220 return CO_E_RELEASED;
2221
2222 return E_NOTIMPL;
2223 }
2224
2225 static HRESULT WINAPI ITextRange_fnMoveUntil(ITextRange *me, VARIANT *charset, LONG count,
2226 LONG *delta)
2227 {
2228 ITextRangeImpl *This = impl_from_ITextRange(me);
2229
2230 FIXME("(%p)->(%s %d %p): stub\n", This, debugstr_variant(charset), count, delta);
2231
2232 if (!This->child.reole)
2233 return CO_E_RELEASED;
2234
2235 return E_NOTIMPL;
2236 }
2237
2238 static HRESULT WINAPI ITextRange_fnMoveStartUntil(ITextRange *me, VARIANT *charset, LONG count,
2239 LONG *delta)
2240 {
2241 ITextRangeImpl *This = impl_from_ITextRange(me);
2242
2243 FIXME("(%p)->(%s %d %p): stub\n", This, debugstr_variant(charset), count, delta);
2244
2245 if (!This->child.reole)
2246 return CO_E_RELEASED;
2247
2248 return E_NOTIMPL;
2249 }
2250
2251 static HRESULT WINAPI ITextRange_fnMoveEndUntil(ITextRange *me, VARIANT *charset, LONG count,
2252 LONG *delta)
2253 {
2254 ITextRangeImpl *This = impl_from_ITextRange(me);
2255
2256 FIXME("(%p)->(%s %d %p): stub\n", This, debugstr_variant(charset), count, delta);
2257
2258 if (!This->child.reole)
2259 return CO_E_RELEASED;
2260
2261 return E_NOTIMPL;
2262 }
2263
2264 static HRESULT WINAPI ITextRange_fnFindText(ITextRange *me, BSTR text, LONG count, LONG flags,
2265 LONG *length)
2266 {
2267 ITextRangeImpl *This = impl_from_ITextRange(me);
2268
2269 FIXME("(%p)->(%s %d %x %p): stub\n", This, debugstr_w(text), count, flags, length);
2270
2271 if (!This->child.reole)
2272 return CO_E_RELEASED;
2273
2274 return E_NOTIMPL;
2275 }
2276
2277 static HRESULT WINAPI ITextRange_fnFindTextStart(ITextRange *me, BSTR text, LONG count,
2278 LONG flags, LONG *length)
2279 {
2280 ITextRangeImpl *This = impl_from_ITextRange(me);
2281
2282 FIXME("(%p)->(%s %d %x %p): stub\n", This, debugstr_w(text), count, flags, length);
2283
2284 if (!This->child.reole)
2285 return CO_E_RELEASED;
2286
2287 return E_NOTIMPL;
2288 }
2289
2290 static HRESULT WINAPI ITextRange_fnFindTextEnd(ITextRange *me, BSTR text, LONG count,
2291 LONG flags, LONG *length)
2292 {
2293 ITextRangeImpl *This = impl_from_ITextRange(me);
2294
2295 FIXME("(%p)->(%s %d %x %p): stub\n", This, debugstr_w(text), count, flags, length);
2296
2297 if (!This->child.reole)
2298 return CO_E_RELEASED;
2299
2300 return E_NOTIMPL;
2301 }
2302
2303 static HRESULT WINAPI ITextRange_fnDelete(ITextRange *me, LONG unit, LONG count, LONG *delta)
2304 {
2305 ITextRangeImpl *This = impl_from_ITextRange(me);
2306
2307 FIXME("(%p)->(%d %d %p): stub\n", This, unit, count, delta);
2308
2309 if (!This->child.reole)
2310 return CO_E_RELEASED;
2311
2312 return E_NOTIMPL;
2313 }
2314
2315 static HRESULT WINAPI ITextRange_fnCut(ITextRange *me, VARIANT *v)
2316 {
2317 ITextRangeImpl *This = impl_from_ITextRange(me);
2318
2319 FIXME("(%p)->(%p): stub\n", This, v);
2320
2321 if (!This->child.reole)
2322 return CO_E_RELEASED;
2323
2324 return E_NOTIMPL;
2325 }
2326
2327 static HRESULT WINAPI ITextRange_fnCopy(ITextRange *me, VARIANT *v)
2328 {
2329 ITextRangeImpl *This = impl_from_ITextRange(me);
2330
2331 FIXME("(%p)->(%p): stub\n", This, v);
2332
2333 if (!This->child.reole)
2334 return CO_E_RELEASED;
2335
2336 return E_NOTIMPL;
2337 }
2338
2339 static HRESULT WINAPI ITextRange_fnPaste(ITextRange *me, VARIANT *v, LONG format)
2340 {
2341 ITextRangeImpl *This = impl_from_ITextRange(me);
2342
2343 FIXME("(%p)->(%s %x): stub\n", This, debugstr_variant(v), format);
2344
2345 if (!This->child.reole)
2346 return CO_E_RELEASED;
2347
2348 return E_NOTIMPL;
2349 }
2350
2351 static HRESULT WINAPI ITextRange_fnCanPaste(ITextRange *me, VARIANT *v, LONG format, LONG *ret)
2352 {
2353 ITextRangeImpl *This = impl_from_ITextRange(me);
2354
2355 FIXME("(%p)->(%s %x %p): stub\n", This, debugstr_variant(v), format, ret);
2356
2357 if (!This->child.reole)
2358 return CO_E_RELEASED;
2359
2360 return E_NOTIMPL;
2361 }
2362
2363 static HRESULT WINAPI ITextRange_fnCanEdit(ITextRange *me, LONG *ret)
2364 {
2365 ITextRangeImpl *This = impl_from_ITextRange(me);
2366
2367 FIXME("(%p)->(%p): stub\n", This, ret);
2368
2369 if (!This->child.reole)
2370 return CO_E_RELEASED;
2371
2372 return E_NOTIMPL;
2373 }
2374
2375 static HRESULT WINAPI ITextRange_fnChangeCase(ITextRange *me, LONG type)
2376 {
2377 ITextRangeImpl *This = impl_from_ITextRange(me);
2378
2379 FIXME("(%p)->(%d): stub\n", This, type);
2380
2381 if (!This->child.reole)
2382 return CO_E_RELEASED;
2383
2384 return E_NOTIMPL;
2385 }
2386
2387 static HRESULT WINAPI ITextRange_fnGetPoint(ITextRange *me, LONG type, LONG *cx, LONG *cy)
2388 {
2389 ITextRangeImpl *This = impl_from_ITextRange(me);
2390
2391 FIXME("(%p)->(%d %p %p): stub\n", This, type, cx, cy);
2392
2393 if (!This->child.reole)
2394 return CO_E_RELEASED;
2395
2396 return E_NOTIMPL;
2397 }
2398
2399 static HRESULT WINAPI ITextRange_fnSetPoint(ITextRange *me, LONG x, LONG y, LONG type,
2400 LONG extend)
2401 {
2402 ITextRangeImpl *This = impl_from_ITextRange(me);
2403
2404 FIXME("(%p)->(%d %d %d %d): stub\n", This, x, y, type, extend);
2405
2406 if (!This->child.reole)
2407 return CO_E_RELEASED;
2408
2409 return E_NOTIMPL;
2410 }
2411
2412 static HRESULT WINAPI ITextRange_fnScrollIntoView(ITextRange *me, LONG value)
2413 {
2414 ITextRangeImpl *This = impl_from_ITextRange(me);
2415 ME_TextEditor *editor;
2416 ME_Cursor cursor;
2417 int x, y, height;
2418
2419 TRACE("(%p)->(%d)\n", This, value);
2420
2421 if (!This->child.reole)
2422 return CO_E_RELEASED;
2423
2424 editor = This->child.reole->editor;
2425
2426 switch (value)
2427 {
2428 case tomStart:
2429 ME_CursorFromCharOfs(editor, This->start, &cursor);
2430 ME_GetCursorCoordinates(editor, &cursor, &x, &y, &height);
2431 break;
2432 default:
2433 FIXME("bStart value %d not handled\n", value);
2434 return E_NOTIMPL;
2435 }
2436 ME_ScrollAbs(editor, x, y);
2437 return S_OK;
2438 }
2439
2440 static HRESULT WINAPI ITextRange_fnGetEmbeddedObject(ITextRange *me, IUnknown **ppv)
2441 {
2442 ITextRangeImpl *This = impl_from_ITextRange(me);
2443
2444 FIXME("(%p)->(%p): stub\n", This, ppv);
2445
2446 if (!This->child.reole)
2447 return CO_E_RELEASED;
2448
2449 return E_NOTIMPL;
2450 }
2451
2452 static const ITextRangeVtbl trvt = {
2453 ITextRange_fnQueryInterface,
2454 ITextRange_fnAddRef,
2455 ITextRange_fnRelease,
2456 ITextRange_fnGetTypeInfoCount,
2457 ITextRange_fnGetTypeInfo,
2458 ITextRange_fnGetIDsOfNames,
2459 ITextRange_fnInvoke,
2460 ITextRange_fnGetText,
2461 ITextRange_fnSetText,
2462 ITextRange_fnGetChar,
2463 ITextRange_fnSetChar,
2464 ITextRange_fnGetDuplicate,
2465 ITextRange_fnGetFormattedText,
2466 ITextRange_fnSetFormattedText,
2467 ITextRange_fnGetStart,
2468 ITextRange_fnSetStart,
2469 ITextRange_fnGetEnd,
2470 ITextRange_fnSetEnd,
2471 ITextRange_fnGetFont,
2472 ITextRange_fnSetFont,
2473 ITextRange_fnGetPara,
2474 ITextRange_fnSetPara,
2475 ITextRange_fnGetStoryLength,
2476 ITextRange_fnGetStoryType,
2477 ITextRange_fnCollapse,
2478 ITextRange_fnExpand,
2479 ITextRange_fnGetIndex,
2480 ITextRange_fnSetIndex,
2481 ITextRange_fnSetRange,
2482 ITextRange_fnInRange,
2483 ITextRange_fnInStory,
2484 ITextRange_fnIsEqual,
2485 ITextRange_fnSelect,
2486 ITextRange_fnStartOf,
2487 ITextRange_fnEndOf,
2488 ITextRange_fnMove,
2489 ITextRange_fnMoveStart,
2490 ITextRange_fnMoveEnd,
2491 ITextRange_fnMoveWhile,
2492 ITextRange_fnMoveStartWhile,
2493 ITextRange_fnMoveEndWhile,
2494 ITextRange_fnMoveUntil,
2495 ITextRange_fnMoveStartUntil,
2496 ITextRange_fnMoveEndUntil,
2497 ITextRange_fnFindText,
2498 ITextRange_fnFindTextStart,
2499 ITextRange_fnFindTextEnd,
2500 ITextRange_fnDelete,
2501 ITextRange_fnCut,
2502 ITextRange_fnCopy,
2503 ITextRange_fnPaste,
2504 ITextRange_fnCanPaste,
2505 ITextRange_fnCanEdit,
2506 ITextRange_fnChangeCase,
2507 ITextRange_fnGetPoint,
2508 ITextRange_fnSetPoint,
2509 ITextRange_fnScrollIntoView,
2510 ITextRange_fnGetEmbeddedObject
2511 };
2512
2513 /* ITextFont */
2514 static HRESULT WINAPI TextFont_QueryInterface(ITextFont *iface, REFIID riid, void **ppv)
2515 {
2516 ITextFontImpl *This = impl_from_ITextFont(iface);
2517
2518 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
2519
2520 if (IsEqualIID(riid, &IID_ITextFont) ||
2521 IsEqualIID(riid, &IID_IDispatch) ||
2522 IsEqualIID(riid, &IID_IUnknown))
2523 {
2524 *ppv = iface;
2525 ITextFont_AddRef(iface);
2526 return S_OK;
2527 }
2528
2529 *ppv = NULL;
2530 return E_NOINTERFACE;
2531 }
2532
2533 static ULONG WINAPI TextFont_AddRef(ITextFont *iface)
2534 {
2535 ITextFontImpl *This = impl_from_ITextFont(iface);
2536 ULONG ref = InterlockedIncrement(&This->ref);
2537 TRACE("(%p)->(%u)\n", This, ref);
2538 return ref;
2539 }
2540
2541 static ULONG WINAPI TextFont_Release(ITextFont *iface)
2542 {
2543 ITextFontImpl *This = impl_from_ITextFont(iface);
2544 ULONG ref = InterlockedDecrement(&This->ref);
2545
2546 TRACE("(%p)->(%u)\n", This, ref);
2547
2548 if (!ref)
2549 {
2550 if (This->range)
2551 ITextRange_Release(This->range);
2552 SysFreeString(This->props[FONT_NAME].str);
2553 heap_free(This);
2554 }
2555
2556 return ref;
2557 }
2558
2559 static HRESULT WINAPI TextFont_GetTypeInfoCount(ITextFont *iface, UINT *pctinfo)
2560 {
2561 ITextFontImpl *This = impl_from_ITextFont(iface);
2562 TRACE("(%p)->(%p)\n", This, pctinfo);
2563 *pctinfo = 1;
2564 return S_OK;
2565 }
2566
2567 static HRESULT WINAPI TextFont_GetTypeInfo(ITextFont *iface, UINT iTInfo, LCID lcid,
2568 ITypeInfo **ppTInfo)
2569 {
2570 ITextFontImpl *This = impl_from_ITextFont(iface);
2571 HRESULT hr;
2572
2573 TRACE("(%p)->(%u,%d,%p)\n", This, iTInfo, lcid, ppTInfo);
2574
2575 hr = get_typeinfo(ITextFont_tid, ppTInfo);
2576 if (SUCCEEDED(hr))
2577 ITypeInfo_AddRef(*ppTInfo);
2578 return hr;
2579 }
2580
2581 static HRESULT WINAPI TextFont_GetIDsOfNames(ITextFont *iface, REFIID riid,
2582 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
2583 {
2584 ITextFontImpl *This = impl_from_ITextFont(iface);
2585 ITypeInfo *ti;
2586 HRESULT hr;
2587
2588 TRACE("(%p)->(%s, %p, %u, %d, %p)\n", This, debugstr_guid(riid),
2589 rgszNames, cNames, lcid, rgDispId);
2590
2591 hr = get_typeinfo(ITextFont_tid, &ti);
2592 if (SUCCEEDED(hr))
2593 hr = ITypeInfo_GetIDsOfNames(ti, rgszNames, cNames, rgDispId);
2594 return hr;
2595 }
2596
2597 static HRESULT WINAPI TextFont_Invoke(
2598 ITextFont *iface,
2599 DISPID dispIdMember,
2600 REFIID riid,
2601 LCID lcid,
2602 WORD wFlags,
2603 DISPPARAMS *pDispParams,
2604 VARIANT *pVarResult,
2605 EXCEPINFO *pExcepInfo,
2606 UINT *puArgErr)
2607 {
2608 ITextFontImpl *This = impl_from_ITextFont(iface);
2609 ITypeInfo *ti;
2610 HRESULT hr;
2611
2612 TRACE("(%p)->(%d, %s, %d, %u, %p, %p, %p, %p)\n", This, dispIdMember, debugstr_guid(riid),
2613 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2614
2615 hr = get_typeinfo(ITextFont_tid, &ti);
2616 if (SUCCEEDED(hr))
2617 hr = ITypeInfo_Invoke(ti, iface, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2618 return hr;
2619 }
2620
2621 static HRESULT WINAPI TextFont_GetDuplicate(ITextFont *iface, ITextFont **ret)
2622 {
2623 ITextFontImpl *This = impl_from_ITextFont(iface);
2624
2625 TRACE("(%p)->(%p)\n", This, ret);
2626
2627 if (!ret)
2628 return E_INVALIDARG;
2629
2630 *ret = NULL;
2631 if (This->range && !get_range_reole(This->range))
2632 return CO_E_RELEASED;
2633
2634 return create_textfont(NULL, This, ret);
2635 }
2636
2637 static HRESULT WINAPI TextFont_SetDuplicate(ITextFont *iface, ITextFont *pFont)
2638 {
2639 ITextFontImpl *This = impl_from_ITextFont(iface);
2640 FIXME("(%p)->(%p): stub\n", This, pFont);
2641
2642 if (This->range && !get_range_reole(This->range))
2643 return CO_E_RELEASED;
2644
2645 return E_NOTIMPL;
2646 }
2647
2648 static HRESULT WINAPI TextFont_CanChange(ITextFont *iface, LONG *ret)
2649 {
2650 ITextFontImpl *This = impl_from_ITextFont(iface);
2651 FIXME("(%p)->(%p): stub\n", This, ret);
2652
2653 if (This->range && !get_range_reole(This->range))
2654 return CO_E_RELEASED;
2655
2656 return E_NOTIMPL;
2657 }
2658
2659 static HRESULT WINAPI TextFont_IsEqual(ITextFont *iface, ITextFont *font, LONG *ret)
2660 {
2661 ITextFontImpl *This = impl_from_ITextFont(iface);
2662 FIXME("(%p)->(%p %p): stub\n", This, font, ret);
2663
2664 if (This->range && !get_range_reole(This->range))
2665 return CO_E_RELEASED;
2666
2667 return E_NOTIMPL;
2668 }
2669
2670 static void textfont_reset_to_default(ITextFontImpl *font)
2671 {
2672 enum textfont_prop_id id;
2673
2674 for (id = FONT_PROPID_FIRST; id < FONT_PROPID_LAST; id++) {
2675 switch (id)
2676 {
2677 case FONT_ALLCAPS:
2678 case FONT_ANIMATION:
2679 case FONT_BOLD:
2680 case FONT_EMBOSS:
2681 case FONT_HIDDEN:
2682 case FONT_ENGRAVE:
2683 case FONT_ITALIC:
2684 case FONT_OUTLINE:
2685 case FONT_PROTECTED:
2686 case FONT_SHADOW:
2687 case FONT_SMALLCAPS:
2688 case FONT_STRIKETHROUGH:
2689 case FONT_SUBSCRIPT:
2690 case FONT_SUPERSCRIPT:
2691 case FONT_UNDERLINE:
2692 font->props[id].l = tomFalse;
2693 break;
2694 case FONT_BACKCOLOR:
2695 case FONT_FORECOLOR:
2696 font->props[id].l = tomAutoColor;
2697 break;
2698 case FONT_KERNING:
2699 case FONT_POSITION:
2700 case FONT_SIZE:
2701 case FONT_SPACING:
2702 font->props[id].f = 0.0;
2703 break;
2704 case FONT_LANGID:
2705 font->props[id].l = GetSystemDefaultLCID();
2706 break;
2707 case FONT_NAME: {
2708 static const WCHAR sysW[] = {'S','y','s','t','e','m',0};
2709 SysFreeString(font->props[id].str);
2710 font->props[id].str = SysAllocString(sysW);
2711 break;
2712 }
2713 case FONT_WEIGHT:
2714 font->props[id].l = FW_NORMAL;
2715 break;
2716 default:
2717 FIXME("font property %d not handled\n", id);
2718 }
2719 }
2720 }
2721
2722 static void textfont_reset_to_undefined(ITextFontImpl *font)
2723 {
2724 enum textfont_prop_id id;
2725
2726 for (id = FONT_PROPID_FIRST; id < FONT_PROPID_LAST; id++) {
2727 switch (id)
2728 {
2729 case FONT_ALLCAPS:
2730 case FONT_ANIMATION:
2731 case FONT_BOLD:
2732 case FONT_EMBOSS:
2733 case FONT_HIDDEN:
2734 case FONT_ENGRAVE:
2735 case FONT_ITALIC:
2736 case FONT_OUTLINE:
2737 case FONT_PROTECTED:
2738 case FONT_SHADOW:
2739 case FONT_SMALLCAPS:
2740 case FONT_STRIKETHROUGH:
2741 case FONT_SUBSCRIPT:
2742 case FONT_SUPERSCRIPT:
2743 case FONT_UNDERLINE:
2744 case FONT_BACKCOLOR:
2745 case FONT_FORECOLOR:
2746 case FONT_LANGID:
2747 case FONT_WEIGHT:
2748 font->props[id].l = tomUndefined;
2749 break;
2750 case FONT_KERNING:
2751 case FONT_POSITION:
2752 case FONT_SIZE:
2753 case FONT_SPACING:
2754 font->props[id].f = tomUndefined;
2755 break;
2756 case FONT_NAME:
2757 break;
2758 default:
2759 FIXME("font property %d not handled\n", id);
2760 }
2761 }
2762 }
2763
2764 static void textfont_apply_range_props(ITextFontImpl *font)
2765 {
2766 enum textfont_prop_id propid;
2767 for (propid = FONT_PROPID_FIRST; propid < FONT_PROPID_LAST; propid++)
2768 set_textfont_prop(font, propid, &font->props[propid]);
2769 }
2770
2771 static HRESULT WINAPI TextFont_Reset(ITextFont *iface, LONG value)
2772 {
2773 ITextFontImpl *This = impl_from_ITextFont(iface);
2774
2775 TRACE("(%p)->(%d)\n", This, value);
2776
2777 /* If font is attached to a range, released or not, we can't
2778 reset to undefined */
2779 if (This->range) {
2780 if (!get_range_reole(This->range))
2781 return CO_E_RELEASED;
2782
2783 switch (value)
2784 {
2785 case tomUndefined:
2786 return E_INVALIDARG;
2787 case tomCacheParms:
2788 textfont_cache_range_props(This);
2789 This->get_cache_enabled = TRUE;
2790 break;
2791 case tomTrackParms:
2792 This->get_cache_enabled = FALSE;
2793 break;
2794 case tomApplyLater:
2795 This->set_cache_enabled = TRUE;
2796 break;
2797 case tomApplyNow:
2798 This->set_cache_enabled = FALSE;
2799 textfont_apply_range_props(This);
2800 break;
2801 case tomUsePoints:
2802 case tomUseTwips:
2803 return E_INVALIDARG;
2804 default:
2805 FIXME("reset mode %d not supported\n", value);
2806 }
2807
2808 return S_OK;
2809 }
2810 else {
2811 switch (value)
2812 {
2813 /* reset to global defaults */
2814 case tomDefault:
2815 textfont_reset_to_default(This);
2816 return S_OK;
2817 /* all properties are set to tomUndefined, font name is retained */
2818 case tomUndefined:
2819 textfont_reset_to_undefined(This);
2820 return S_OK;
2821 case tomApplyNow:
2822 case tomApplyLater:
2823 case tomTrackParms:
2824 case tomCacheParms:
2825 return S_OK;
2826 case tomUsePoints:
2827 case tomUseTwips:
2828 return E_INVALIDARG;
2829 }
2830 }
2831
2832 FIXME("reset mode %d not supported\n", value);
2833 return E_NOTIMPL;
2834 }
2835
2836 static HRESULT WINAPI TextFont_GetStyle(ITextFont *iface, LONG *value)
2837 {
2838 ITextFontImpl *This = impl_from_ITextFont(iface);
2839 FIXME("(%p)->(%p): stub\n", This, value);
2840
2841 if (This->range && !get_range_reole(This->range))
2842 return CO_E_RELEASED;
2843
2844 return E_NOTIMPL;
2845 }
2846
2847 static HRESULT WINAPI TextFont_SetStyle(ITextFont *iface, LONG value)
2848 {
2849 ITextFontImpl *This = impl_from_ITextFont(iface);
2850 FIXME("(%p)->(%d): stub\n", This, value);
2851
2852 if (This->range && !get_range_reole(This->range))
2853 return CO_E_RELEASED;
2854
2855 return E_NOTIMPL;
2856 }
2857
2858 static HRESULT WINAPI TextFont_GetAllCaps(ITextFont *iface, LONG *value)
2859 {
2860 ITextFontImpl *This = impl_from_ITextFont(iface);
2861 TRACE("(%p)->(%p)\n", This, value);
2862 return get_textfont_propl(This, FONT_ALLCAPS, value);
2863 }
2864
2865 static HRESULT WINAPI TextFont_SetAllCaps(ITextFont *iface, LONG value)
2866 {
2867 ITextFontImpl *This = impl_from_ITextFont(iface);
2868 TRACE("(%p)->(%d)\n", This, value);
2869 return set_textfont_propd(This, FONT_ALLCAPS, value);
2870 }
2871
2872 static HRESULT WINAPI TextFont_GetAnimation(ITextFont *iface, LONG *value)
2873 {
2874 ITextFontImpl *This = impl_from_ITextFont(iface);
2875 TRACE("(%p)->(%p)\n", This, value);
2876 return get_textfont_propl(This, FONT_ANIMATION, value);
2877 }
2878
2879 static HRESULT WINAPI TextFont_SetAnimation(ITextFont *iface, LONG value)
2880 {
2881 ITextFontImpl *This = impl_from_ITextFont(iface);
2882
2883 TRACE("(%p)->(%d)\n", This, value);
2884
2885 if (value < tomNoAnimation || value > tomAnimationMax)
2886 return E_INVALIDARG;
2887
2888 return set_textfont_propl(This, FONT_ANIMATION, value);
2889 }
2890
2891 static HRESULT WINAPI TextFont_GetBackColor(ITextFont *iface, LONG *value)
2892 {
2893 ITextFontImpl *This = impl_from_ITextFont(iface);
2894 TRACE("(%p)->(%p)\n", This, value);
2895 return get_textfont_propl(This, FONT_BACKCOLOR, value);
2896 }
2897
2898 static HRESULT WINAPI TextFont_SetBackColor(ITextFont *iface, LONG value)
2899 {
2900 ITextFontImpl *This = impl_from_ITextFont(iface);
2901 TRACE("(%p)->(%d)\n", This, value);
2902 return set_textfont_propl(This, FONT_BACKCOLOR, value);
2903 }
2904
2905 static HRESULT WINAPI TextFont_GetBold(ITextFont *iface, LONG *value)
2906 {
2907 ITextFontImpl *This = impl_from_ITextFont(iface);
2908 TRACE("(%p)->(%p)\n", This, value);
2909 return get_textfont_propl(This, FONT_BOLD, value);
2910 }
2911
2912 static HRESULT WINAPI TextFont_SetBold(ITextFont *iface, LONG value)
2913 {
2914 ITextFontImpl *This = impl_from_ITextFont(iface);
2915 TRACE("(%p)->(%d)\n", This, value);
2916 return set_textfont_propd(This, FONT_BOLD, value);
2917 }
2918
2919 static HRESULT WINAPI TextFont_GetEmboss(ITextFont *iface, LONG *value)
2920 {
2921 ITextFontImpl *This = impl_from_ITextFont(iface);
2922 TRACE("(%p)->(%p)\n", This, value);
2923 return get_textfont_propl(This, FONT_EMBOSS, value);
2924 }
2925
2926 static HRESULT WINAPI TextFont_SetEmboss(ITextFont *iface, LONG value)
2927 {
2928 ITextFontImpl *This = impl_from_ITextFont(iface);
2929 TRACE("(%p)->(%d)\n", This, value);
2930 return set_textfont_propd(This, FONT_EMBOSS, value);
2931 }
2932
2933 static HRESULT WINAPI TextFont_GetForeColor(ITextFont *iface, LONG *value)
2934 {
2935 ITextFontImpl *This = impl_from_ITextFont(iface);
2936 TRACE("(%p)->(%p)\n", This, value);
2937 return get_textfont_propl(This, FONT_FORECOLOR, value);
2938 }
2939
2940 static HRESULT WINAPI TextFont_SetForeColor(ITextFont *iface, LONG value)
2941 {
2942 ITextFontImpl *This = impl_from_ITextFont(iface);
2943 TRACE("(%p)->(%d)\n", This, value);
2944 return set_textfont_propl(This, FONT_FORECOLOR, value);
2945 }
2946
2947 static HRESULT WINAPI TextFont_GetHidden(ITextFont *iface, LONG *value)
2948 {
2949 ITextFontImpl *This = impl_from_ITextFont(iface);
2950 TRACE("(%p)->(%p)\n", This, value);
2951 return get_textfont_propl(This, FONT_HIDDEN, value);
2952 }
2953
2954 static HRESULT WINAPI TextFont_SetHidden(ITextFont *iface, LONG value)
2955 {
2956 ITextFontImpl *This = impl_from_ITextFont(iface);
2957 TRACE("(%p)->(%d)\n", This, value);
2958 return set_textfont_propd(This, FONT_HIDDEN, value);
2959 }
2960
2961 static HRESULT WINAPI TextFont_GetEngrave(ITextFont *iface, LONG *value)
2962 {
2963 ITextFontImpl *This = impl_from_ITextFont(iface);
2964 TRACE("(%p)->(%p)\n", This, value);
2965 return get_textfont_propl(This, FONT_ENGRAVE, value);
2966 }
2967
2968 static HRESULT WINAPI TextFont_SetEngrave(ITextFont *iface, LONG value)
2969 {
2970 ITextFontImpl *This = impl_from_ITextFont(iface);
2971 TRACE("(%p)->(%d)\n", This, value);
2972 return set_textfont_propd(This, FONT_ENGRAVE, value);
2973 }
2974
2975 static HRESULT WINAPI TextFont_GetItalic(ITextFont *iface, LONG *value)
2976 {
2977 ITextFontImpl *This = impl_from_ITextFont(iface);
2978 TRACE("(%p)->(%p)\n", This, value);
2979 return get_textfont_propl(This, FONT_ITALIC, value);
2980 }
2981
2982 static HRESULT WINAPI TextFont_SetItalic(ITextFont *iface, LONG value)
2983 {
2984 ITextFontImpl *This = impl_from_ITextFont(iface);
2985 TRACE("(%p)->(%d)\n", This, value);
2986 return set_textfont_propd(This, FONT_ITALIC, value);
2987 }
2988
2989 static HRESULT WINAPI TextFont_GetKerning(ITextFont *iface, FLOAT *value)
2990 {
2991 ITextFontImpl *This = impl_from_ITextFont(iface);
2992 TRACE("(%p)->(%p)\n", This, value);
2993 return get_textfont_propf(This, FONT_KERNING, value);
2994 }
2995
2996 static HRESULT WINAPI TextFont_SetKerning(ITextFont *iface, FLOAT value)
2997 {
2998 ITextFontImpl *This = impl_from_ITextFont(iface);
2999 TRACE("(%p)->(%.2f)\n", This, value);
3000 return set_textfont_propf(This, FONT_KERNING, value);
3001 }
3002
3003 static HRESULT WINAPI TextFont_GetLanguageID(ITextFont *iface, LONG *value)
3004 {
3005 ITextFontImpl *This = impl_from_ITextFont(iface);
3006 TRACE("(%p)->(%p)\n", This, value);
3007 return get_textfont_propl(This, FONT_LANGID, value);
3008 }
3009
3010 static HRESULT WINAPI TextFont_SetLanguageID(ITextFont *iface, LONG value)
3011 {
3012 ITextFontImpl *This = impl_from_ITextFont(iface);
3013 TRACE("(%p)->(%d)\n", This, value);
3014 return set_textfont_propl(This, FONT_LANGID, value);
3015 }
3016
3017 static HRESULT WINAPI TextFont_GetName(ITextFont *iface, BSTR *value)
3018 {
3019 ITextFontImpl *This = impl_from_ITextFont(iface);
3020
3021 TRACE("(%p)->(%p)\n", This, value);
3022
3023 if (!value)
3024 return E_INVALIDARG;
3025
3026 *value = NULL;
3027
3028 if (!This->range) {
3029 if (This->props[FONT_NAME].str)
3030 *value = SysAllocString(This->props[FONT_NAME].str);
3031 else
3032 *value = SysAllocStringLen(NULL, 0);
3033 return *value ? S_OK : E_OUTOFMEMORY;
3034 }
3035
3036 return textfont_getname_from_range(This->range, value);
3037 }
3038
3039 static HRESULT WINAPI TextFont_SetName(ITextFont *iface, BSTR value)
3040 {
3041 ITextFontImpl *This = impl_from_ITextFont(iface);
3042 textfont_prop_val v;
3043
3044 TRACE("(%p)->(%s)\n", This, debugstr_w(value));
3045
3046 v.str = value;
3047 return set_textfont_prop(This, FONT_NAME, &v);
3048 }
3049
3050 static HRESULT WINAPI TextFont_GetOutline(ITextFont *iface, LONG *value)
3051 {
3052 ITextFontImpl *This = impl_from_ITextFont(iface);
3053 TRACE("(%p)->(%p)\n", This, value);
3054 return get_textfont_propl(This, FONT_OUTLINE, value);
3055 }
3056
3057 static HRESULT WINAPI TextFont_SetOutline(ITextFont *iface, LONG value)
3058 {
3059 ITextFontImpl *This = impl_from_ITextFont(iface);
3060 TRACE("(%p)->(%d)\n", This, value);
3061 return set_textfont_propd(This, FONT_OUTLINE, value);
3062 }
3063
3064 static HRESULT WINAPI TextFont_GetPosition(ITextFont *iface, FLOAT *value)
3065 {
3066 ITextFontImpl *This = impl_from_ITextFont(iface);
3067 TRACE("(%p)->(%p)\n", This, value);
3068 return get_textfont_propf(This, FONT_POSITION, value);
3069 }
3070
3071 static HRESULT WINAPI TextFont_SetPosition(ITextFont *iface, FLOAT value)
3072 {
3073 ITextFontImpl *This = impl_from_ITextFont(iface);
3074 TRACE("(%p)->(%.2f)\n", This, value);
3075 return set_textfont_propf(This, FONT_POSITION, value);
3076 }
3077
3078 static HRESULT WINAPI TextFont_GetProtected(ITextFont *iface, LONG *value)
3079 {
3080 ITextFontImpl *This = impl_from_ITextFont(iface);
3081 TRACE("(%p)->(%p)\n", This, value);
3082 return get_textfont_propl(This, FONT_PROTECTED, value);
3083 }
3084
3085 static HRESULT WINAPI TextFont_SetProtected(ITextFont *iface, LONG value)
3086 {
3087 ITextFontImpl *This = impl_from_ITextFont(iface);
3088 TRACE("(%p)->(%d)\n", This, value);
3089 return set_textfont_propd(This, FONT_PROTECTED, value);
3090 }
3091
3092 static HRESULT WINAPI TextFont_GetShadow(ITextFont *iface, LONG *value)
3093 {
3094 ITextFontImpl *This = impl_from_ITextFont(iface);
3095 TRACE("(%p)->(%p)\n", This, value);
3096 return get_textfont_propl(This, FONT_SHADOW, value);
3097 }
3098
3099 static HRESULT WINAPI TextFont_SetShadow(ITextFont *iface, LONG value)
3100 {
3101 ITextFontImpl *This = impl_from_ITextFont(iface);
3102 TRACE("(%p)->(%d)\n", This, value);
3103 return set_textfont_propd(This, FONT_SHADOW, value);
3104 }
3105
3106 static HRESULT WINAPI TextFont_GetSize(ITextFont *iface, FLOAT *value)
3107 {
3108 ITextFontImpl *This = impl_from_ITextFont(iface);
3109 TRACE("(%p)->(%p)\n", This, value);
3110 return get_textfont_propf(This, FONT_SIZE, value);
3111 }
3112
3113 static HRESULT WINAPI TextFont_SetSize(ITextFont *iface, FLOAT value)
3114 {
3115 ITextFontImpl *This = impl_from_ITextFont(iface);
3116 TRACE("(%p)->(%.2f)\n", This, value);
3117 return set_textfont_propf(This, FONT_SIZE, value);
3118 }
3119
3120 static HRESULT WINAPI TextFont_GetSmallCaps(ITextFont *iface, LONG *value)
3121 {
3122 ITextFontImpl *This = impl_from_ITextFont(iface);
3123 TRACE("(%p)->(%p)\n", This, value);
3124 return get_textfont_propl(This, FONT_SMALLCAPS, value);
3125 }
3126
3127 static HRESULT WINAPI TextFont_SetSmallCaps(ITextFont *iface, LONG value)
3128 {
3129 ITextFontImpl *This = impl_from_ITextFont(iface);
3130 TRACE("(%p)->(%d)\n", This, value);
3131 return set_textfont_propd(This, FONT_SMALLCAPS, value);
3132 }
3133
3134 static HRESULT WINAPI TextFont_GetSpacing(ITextFont *iface, FLOAT *value)
3135 {
3136 ITextFontImpl *This = impl_from_ITextFont(iface);
3137 TRACE("(%p)->(%p)\n", This, value);
3138 return get_textfont_propf(This, FONT_SPACING, value);
3139 }
3140
3141 static HRESULT WINAPI TextFont_SetSpacing(ITextFont *iface, FLOAT value)
3142 {
3143 ITextFontImpl *This = impl_from_ITextFont(iface);
3144 TRACE("(%p)->(%.2f)\n", This, value);
3145 return set_textfont_propf(This, FONT_SPACING, value);
3146 }
3147
3148 static HRESULT WINAPI TextFont_GetStrikeThrough(ITextFont *iface, LONG *value)
3149 {
3150 ITextFontImpl *This = impl_from_ITextFont(iface);
3151 TRACE("(%p)->(%p)\n", This, value);
3152 return get_textfont_propl(This, FONT_STRIKETHROUGH, value);
3153 }
3154
3155 static HRESULT WINAPI TextFont_SetStrikeThrough(ITextFont *iface, LONG value)
3156 {
3157 ITextFontImpl *This = impl_from_ITextFont(iface);
3158 TRACE("(%p)->(%d)\n", This, value);
3159 return set_textfont_propd(This, FONT_STRIKETHROUGH, value);
3160 }
3161
3162 static HRESULT WINAPI TextFont_GetSubscript(ITextFont *iface, LONG *value)
3163 {
3164 ITextFontImpl *This = impl_from_ITextFont(iface);
3165 TRACE("(%p)->(%p)\n", This, value);
3166 return get_textfont_propl(This, FONT_SUBSCRIPT, value);
3167 }
3168
3169 static HRESULT WINAPI TextFont_SetSubscript(ITextFont *iface, LONG value)
3170 {
3171 ITextFontImpl *This = impl_from_ITextFont(iface);
3172 TRACE("(%p)->(%d)\n", This, value);
3173 return set_textfont_propd(This, FONT_SUBSCRIPT, value);
3174 }
3175
3176 static HRESULT WINAPI TextFont_GetSuperscript(ITextFont *iface, LONG *value)
3177 {
3178 ITextFontImpl *This = impl_from_ITextFont(iface);
3179 TRACE("(%p)->(%p)\n", This, value);
3180 return get_textfont_propl(This, FONT_SUPERSCRIPT, value);
3181 }
3182
3183 static HRESULT WINAPI TextFont_SetSuperscript(ITextFont *iface, LONG value)
3184 {
3185 ITextFontImpl *This = impl_from_ITextFont(iface);
3186 TRACE("(%p)->(%d)\n", This, value);
3187 return set_textfont_propd(This, FONT_SUPERSCRIPT, value);
3188 }
3189
3190 static HRESULT WINAPI TextFont_GetUnderline(ITextFont *iface, LONG *value)
3191 {
3192 ITextFontImpl *This = impl_from_ITextFont(iface);
3193 TRACE("(%p)->(%p)\n", This, value);
3194 return get_textfont_propl(This, FONT_UNDERLINE, value);
3195 }
3196
3197 static HRESULT WINAPI TextFont_SetUnderline(ITextFont *iface, LONG value)
3198 {
3199 ITextFontImpl *This = impl_from_ITextFont(iface);
3200 TRACE("(%p)->(%d)\n", This, value);
3201 return set_textfont_propd(This, FONT_UNDERLINE, value);
3202 }
3203
3204 static HRESULT WINAPI TextFont_GetWeight(ITextFont *iface, LONG *value)
3205 {
3206 ITextFontImpl *This = impl_from_ITextFont(iface);
3207 TRACE("(%p)->(%p)\n", This, value);
3208 return get_textfont_propl(This, FONT_WEIGHT, value);
3209 }
3210
3211 static HRESULT WINAPI TextFont_SetWeight(ITextFont *iface, LONG value)
3212 {
3213 ITextFontImpl *This = impl_from_ITextFont(iface);
3214 TRACE("(%p)->(%d)\n", This, value);
3215 return set_textfont_propl(This, FONT_WEIGHT, value);
3216 }
3217
3218 static ITextFontVtbl textfontvtbl = {
3219 TextFont_QueryInterface,
3220 TextFont_AddRef,
3221 TextFont_Release,
3222 TextFont_GetTypeInfoCount,
3223 TextFont_GetTypeInfo,
3224 TextFont_GetIDsOfNames,
3225 TextFont_Invoke,
3226 TextFont_GetDuplicate,
3227 TextFont_SetDuplicate,
3228 TextFont_CanChange,
3229 TextFont_IsEqual,
3230 TextFont_Reset,
3231 TextFont_GetStyle,
3232 TextFont_SetStyle,
3233 TextFont_GetAllCaps,
3234 TextFont_SetAllCaps,
3235 TextFont_GetAnimation,
3236 TextFont_SetAnimation,
3237 TextFont_GetBackColor,
3238 TextFont_SetBackColor,
3239 TextFont_GetBold,
3240 TextFont_SetBold,
3241 TextFont_GetEmboss,
3242 TextFont_SetEmboss,
3243 TextFont_GetForeColor,
3244 TextFont_SetForeColor,
3245 TextFont_GetHidden,
3246 TextFont_SetHidden,
3247 TextFont_GetEngrave,
3248 TextFont_SetEngrave,
3249 TextFont_GetItalic,
3250 TextFont_SetItalic,
3251 TextFont_GetKerning,
3252 TextFont_SetKerning,
3253 TextFont_GetLanguageID,
3254 TextFont_SetLanguageID,
3255 TextFont_GetName,
3256 TextFont_SetName,
3257 TextFont_GetOutline,
3258 TextFont_SetOutline,
3259 TextFont_GetPosition,
3260 TextFont_SetPosition,
3261 TextFont_GetProtected,
3262 TextFont_SetProtected,
3263 TextFont_GetShadow,
3264 TextFont_SetShadow,
3265 TextFont_GetSize,
3266 TextFont_SetSize,
3267 TextFont_GetSmallCaps,
3268 TextFont_SetSmallCaps,
3269 TextFont_GetSpacing,
3270 TextFont_SetSpacing,
3271 TextFont_GetStrikeThrough,
3272 TextFont_SetStrikeThrough,
3273 TextFont_GetSubscript,
3274 TextFont_SetSubscript,
3275 TextFont_GetSuperscript,
3276 TextFont_SetSuperscript,
3277 TextFont_GetUnderline,
3278 TextFont_SetUnderline,
3279 TextFont_GetWeight,
3280 TextFont_SetWeight
3281 };
3282
3283 static HRESULT create_textfont(ITextRange *range, const ITextFontImpl *src, ITextFont **ret)
3284 {
3285 ITextFontImpl *font;
3286
3287 *ret = NULL;
3288 font = heap_alloc(sizeof(*font));
3289 if (!font)
3290 return E_OUTOFMEMORY;
3291
3292 font->ITextFont_iface.lpVtbl = &textfontvtbl;
3293 font->ref = 1;
3294
3295 if (src) {
3296 font->range = NULL;
3297 font->get_cache_enabled = TRUE;
3298 font->set_cache_enabled = TRUE;
3299 memcpy(&font->props, &src->props, sizeof(font->props));
3300 if (font->props[FONT_NAME].str)
3301 font->props[FONT_NAME].str = SysAllocString(font->props[FONT_NAME].str);
3302 }
3303 else {
3304 font->range = range;
3305 ITextRange_AddRef(range);
3306
3307 /* cache current properties */
3308 font->get_cache_enabled = FALSE;
3309 font->set_cache_enabled = FALSE;
3310 textfont_cache_range_props(font);
3311 }
3312
3313 *ret = &font->ITextFont_iface;
3314 return S_OK;
3315 }
3316
3317 /* ITextPara */
3318 static HRESULT WINAPI TextPara_QueryInterface(ITextPara *iface, REFIID riid, void **ppv)
3319 {
3320 ITextParaImpl *This = impl_from_ITextPara(iface);
3321
3322 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
3323
3324 if (IsEqualIID(riid, &IID_ITextPara) ||
3325 IsEqualIID(riid, &IID_IDispatch) ||
3326 IsEqualIID(riid, &IID_IUnknown))
3327 {
3328 *ppv = iface;
3329 ITextPara_AddRef(iface);
3330 return S_OK;
3331 }
3332
3333 *ppv = NULL;
3334 return E_NOINTERFACE;
3335 }
3336
3337 static ULONG WINAPI TextPara_AddRef(ITextPara *iface)
3338 {
3339 ITextParaImpl *This = impl_from_ITextPara(iface);
3340 ULONG ref = InterlockedIncrement(&This->ref);
3341 TRACE("(%p)->(%u)\n", This, ref);
3342 return ref;
3343 }
3344
3345 static ULONG WINAPI TextPara_Release(ITextPara *iface)
3346 {
3347 ITextParaImpl *This = impl_from_ITextPara(iface);
3348 ULONG ref = InterlockedDecrement(&This->ref);
3349
3350 TRACE("(%p)->(%u)\n", This, ref);
3351
3352 if (!ref)
3353 {
3354 ITextRange_Release(This->range);
3355 heap_free(This);
3356 }
3357
3358 return ref;
3359 }
3360
3361 static IRichEditOleImpl *para_get_reole(ITextParaImpl *This)
3362 {
3363 if (This->range)
3364 {
3365 ITextRangeImpl *rng = impl_from_ITextRange(This->range);
3366 return rng->child.reole;
3367 }
3368 return NULL;
3369 }
3370
3371 static HRESULT WINAPI TextPara_GetTypeInfoCount(ITextPara *iface, UINT *pctinfo)
3372 {
3373 ITextParaImpl *This = impl_from_ITextPara(iface);
3374 TRACE("(%p)->(%p)\n", This, pctinfo);
3375 *pctinfo = 1;
3376 return S_OK;
3377 }
3378
3379 static HRESULT WINAPI TextPara_GetTypeInfo(ITextPara *iface, UINT iTInfo, LCID lcid,
3380 ITypeInfo **ppTInfo)
3381 {
3382 ITextParaImpl *This = impl_from_ITextPara(iface);
3383 HRESULT hr;
3384
3385 TRACE("(%p)->(%u,%d,%p)\n", This, iTInfo, lcid, ppTInfo);
3386
3387 hr = get_typeinfo(ITextPara_tid, ppTInfo);
3388 if (SUCCEEDED(hr))
3389 ITypeInfo_AddRef(*ppTInfo);
3390 return hr;
3391 }
3392
3393 static HRESULT WINAPI TextPara_GetIDsOfNames(ITextPara *iface, REFIID riid,
3394 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
3395 {
3396 ITextParaImpl *This = impl_from_ITextPara(iface);
3397 ITypeInfo *ti;
3398 HRESULT hr;
3399
3400 TRACE("(%p)->(%s, %p, %u, %d, %p)\n", This, debugstr_guid(riid), rgszNames,
3401 cNames, lcid, rgDispId);
3402
3403 hr = get_typeinfo(ITextPara_tid, &ti);
3404 if (SUCCEEDED(hr))
3405 hr = ITypeInfo_GetIDsOfNames(ti, rgszNames, cNames, rgDispId);
3406 return hr;
3407 }
3408
3409 static HRESULT WINAPI TextPara_Invoke(
3410 ITextPara *iface,
3411 DISPID dispIdMember,
3412 REFIID riid,
3413 LCID lcid,
3414 WORD wFlags,
3415 DISPPARAMS *pDispParams,
3416 VARIANT *pVarResult,
3417 EXCEPINFO *pExcepInfo,
3418 UINT *puArgErr)
3419 {
3420 ITextParaImpl *This = impl_from_ITextPara(iface);
3421 ITypeInfo *ti;
3422 HRESULT hr;
3423
3424 TRACE("(%p)->(%d, %s, %d, %u, %p, %p, %p, %p)\n", This, dispIdMember,
3425 debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult,
3426 pExcepInfo, puArgErr);
3427
3428 hr = get_typeinfo(ITextPara_tid, &ti);
3429 if (SUCCEEDED(hr))
3430 hr = ITypeInfo_Invoke(ti, iface, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
3431 return hr;
3432 }
3433
3434 static HRESULT WINAPI TextPara_GetDuplicate(ITextPara *iface, ITextPara **ret)
3435 {
3436 ITextParaImpl *This = impl_from_ITextPara(iface);
3437 FIXME("(%p)->(%p)\n", This, ret);
3438
3439 if (!para_get_reole(This))
3440 return CO_E_RELEASED;
3441
3442 return E_NOTIMPL;
3443 }
3444
3445 static HRESULT WINAPI TextPara_SetDuplicate(ITextPara *iface, ITextPara *para)
3446 {
3447 ITextParaImpl *This = impl_from_ITextPara(iface);
3448 FIXME("(%p)->(%p)\n", This, para);
3449
3450 if (!para_get_reole(This))
3451 return CO_E_RELEASED;
3452
3453 return E_NOTIMPL;
3454 }
3455
3456 static HRESULT WINAPI TextPara_CanChange(ITextPara *iface, LONG *ret)
3457 {
3458 ITextParaImpl *This = impl_from_ITextPara(iface);
3459 FIXME("(%p)->(%p)\n", This, ret);
3460
3461 if (!para_get_reole(This))
3462 return CO_E_RELEASED;
3463
3464 return E_NOTIMPL;
3465 }
3466
3467 static HRESULT WINAPI TextPara_IsEqual(ITextPara *iface, ITextPara *para, LONG *ret)
3468 {
3469 ITextParaImpl *This = impl_from_ITextPara(iface);
3470 FIXME("(%p)->(%p %p)\n", This, para, ret);
3471
3472 if (!para_get_reole(This))
3473 return CO_E_RELEASED;
3474
3475 return E_NOTIMPL;
3476 }
3477
3478 static HRESULT WINAPI TextPara_Reset(ITextPara *iface, LONG value)
3479 {
3480 ITextParaImpl *This = impl_from_ITextPara(iface);
3481 FIXME("(%p)->(%d)\n", This, value);
3482
3483 if (!para_get_reole(This))
3484 return CO_E_RELEASED;
3485
3486 return E_NOTIMPL;
3487 }
3488
3489 static HRESULT WINAPI TextPara_GetStyle(ITextPara *iface, LONG *value)
3490 {
3491 ITextParaImpl *This = impl_from_ITextPara(iface);
3492 FIXME("(%p)->(%p)\n", This, value);
3493
3494 if (!para_get_reole(This))
3495 return CO_E_RELEASED;
3496
3497 return E_NOTIMPL;
3498 }
3499
3500 static HRESULT WINAPI TextPara_SetStyle(ITextPara *iface, LONG value)
3501 {
3502 ITextParaImpl *This = impl_from_ITextPara(iface);
3503 FIXME("(%p)->(%d)\n", This, value);
3504
3505 if (!para_get_reole(This))
3506 return CO_E_RELEASED;
3507
3508 return E_NOTIMPL;
3509 }
3510
3511 static HRESULT WINAPI TextPara_GetAlignment(ITextPara *iface, LONG *value)
3512 {
3513 ITextParaImpl *This = impl_from_ITextPara(iface);
3514 static int once;
3515
3516 if (!once++) FIXME("(%p)->(%p)\n", This, value);
3517
3518 if (!para_get_reole(This))
3519 return CO_E_RELEASED;
3520
3521 return E_NOTIMPL;
3522 }
3523
3524 static HRESULT WINAPI TextPara_SetAlignment(ITextPara *iface, LONG value)
3525 {
3526 ITextParaImpl *This = impl_from_ITextPara(iface);
3527 FIXME("(%p)->(%d)\n", This, value);
3528
3529 if (!para_get_reole(This))
3530 return CO_E_RELEASED;
3531
3532 return E_NOTIMPL;
3533 }
3534
3535 static HRESULT WINAPI TextPara_GetHyphenation(ITextPara *iface, LONG *value)
3536 {
3537 ITextParaImpl *This = impl_from_ITextPara(iface);
3538 FIXME("(%p)->(%p)\n", This, value);
3539
3540 if (!para_get_reole(This))
3541 return CO_E_RELEASED;
3542
3543 return E_NOTIMPL;
3544 }
3545
3546 static HRESULT WINAPI TextPara_SetHyphenation(ITextPara *iface, LONG value)
3547 {
3548 ITextParaImpl *This = impl_from_ITextPara(iface);
3549 FIXME("(%p)->(%d)\n", This, value);
3550
3551 if (!para_get_reole(This))
3552 return CO_E_RELEASED;
3553
3554 return E_NOTIMPL;
3555 }
3556
3557 static HRESULT WINAPI TextPara_GetFirstLineIndent(ITextPara *iface, FLOAT *value)
3558 {
3559 ITextParaImpl *This = impl_from_ITextPara(iface);
3560 FIXME("(%p)->(%p)\n", This, value);
3561
3562 if (!para_get_reole(This))
3563 return CO_E_RELEASED;
3564
3565 return E_NOTIMPL;
3566 }
3567
3568 static HRESULT WINAPI TextPara_GetKeepTogether(ITextPara *iface, LONG *value)
3569 {
3570 ITextParaImpl *This = impl_from_ITextPara(iface);
3571 FIXME("(%p)->(%p)\n", This, value);
3572
3573 if (!para_get_reole(This))
3574 return CO_E_RELEASED;
3575
3576 return E_NOTIMPL;
3577 }
3578
3579 static HRESULT WINAPI TextPara_SetKeepTogether(ITextPara *iface, LONG value)
3580 {
3581 ITextParaImpl *This = impl_from_ITextPara(iface);
3582 FIXME("(%p)->(%d)\n", This, value);
3583
3584 if (!para_get_reole(This))
3585 return CO_E_RELEASED;
3586
3587 return E_NOTIMPL;
3588 }
3589
3590 static HRESULT WINAPI TextPara_GetKeepWithNext(ITextPara *iface, LONG *value)
3591 {
3592 ITextParaImpl *This = impl_from_ITextPara(iface);
3593 FIXME("(%p)->(%p)\n", This, value);
3594
3595 if (!para_get_reole(This))
3596 return CO_E_RELEASED;
3597
3598 return E_NOTIMPL;
3599 }
3600
3601 static HRESULT WINAPI TextPara_SetKeepWithNext(ITextPara *iface, LONG value)
3602 {
3603 ITextParaImpl *This = impl_from_ITextPara(iface);
3604 FIXME("(%p)->(%d)\n", This, value);
3605
3606 if (!para_get_reole(This))
3607 return CO_E_RELEASED;
3608
3609 return E_NOTIMPL;
3610 }
3611
3612 static HRESULT WINAPI TextPara_GetLeftIndent(ITextPara *iface, FLOAT *value)
3613 {
3614 ITextParaImpl *This = impl_from_ITextPara(iface);
3615 FIXME("(%p)->(%p)\n", This, value);
3616
3617 if (!para_get_reole(This))
3618 return CO_E_RELEASED;
3619
3620 return E_NOTIMPL;
3621 }
3622
3623 static HRESULT WINAPI TextPara_GetLineSpacing(ITextPara *iface, FLOAT *value)
3624 {
3625 ITextParaImpl *This = impl_from_ITextPara(iface);
3626 FIXME("(%p)->(%p)\n", This, value);
3627
3628 if (!para_get_reole(This))
3629 return CO_E_RELEASED;
3630
3631 return E_NOTIMPL;
3632 }
3633
3634 static HRESULT WINAPI TextPara_GetLineSpacingRule(ITextPara *iface, LONG *value)
3635 {
3636 ITextParaImpl *This = impl_from_ITextPara(iface);
3637 FIXME("(%p)->(%p)\n", This, value);
3638
3639 if (!para_get_reole(This))
3640 return CO_E_RELEASED;
3641
3642 return E_NOTIMPL;
3643 }
3644
3645 static HRESULT WINAPI TextPara_GetListAlignment(ITextPara *iface, LONG *value)
3646 {
3647 ITextParaImpl *This = impl_from_ITextPara(iface);
3648 FIXME("(%p)->(%p)\n", This, value);
3649
3650 if (!para_get_reole(This))
3651 return CO_E_RELEASED;
3652
3653 return E_NOTIMPL;
3654 }
3655
3656 static HRESULT WINAPI TextPara_SetListAlignment(ITextPara *iface, LONG value)
3657 {
3658 ITextParaImpl *This = impl_from_ITextPara(iface);
3659 FIXME("(%p)->(%d)\n", This, value);
3660
3661 if (!para_get_reole(This))
3662 return CO_E_RELEASED;
3663
3664 return E_NOTIMPL;
3665 }
3666
3667 static HRESULT WINAPI TextPara_GetListLevelIndex(ITextPara *iface, LONG *value)
3668 {
3669 ITextParaImpl *This = impl_from_ITextPara(iface);
3670 FIXME("(%p)->(%p)\n", This, value);
3671
3672 if (!para_get_reole(This))
3673 return CO_E_RELEASED;
3674
3675 return E_NOTIMPL;
3676 }
3677
3678 static HRESULT WINAPI TextPara_SetListLevelIndex(ITextPara *iface, LONG value)
3679 {
3680 ITextParaImpl *This = impl_from_ITextPara(iface);
3681 FIXME("(%p)->(%d)\n", This, value);
3682
3683 if (!para_get_reole(This))
3684 return CO_E_RELEASED;
3685
3686 return E_NOTIMPL;
3687 }
3688
3689 static HRESULT WINAPI TextPara_GetListStart(ITextPara *iface, LONG *value)
3690 {
3691 ITextParaImpl *This = impl_from_ITextPara(iface);
3692 FIXME("(%p)->(%p)\n", This, value);
3693
3694 if (!para_get_reole(This))
3695 return CO_E_RELEASED;
3696
3697 return E_NOTIMPL;
3698 }
3699
3700 static HRESULT WINAPI TextPara_SetListStart(ITextPara *iface, LONG value)
3701 {
3702 ITextParaImpl *This = impl_from_ITextPara(iface);
3703 FIXME("(%p)->(%d)\n", This, value);
3704
3705 if (!para_get_reole(This))
3706 return CO_E_RELEASED;
3707
3708 return E_NOTIMPL;
3709 }
3710
3711 static HRESULT WINAPI TextPara_GetListTab(ITextPara *iface, FLOAT *value)
3712 {
3713 ITextParaImpl *This = impl_from_ITextPara(iface);
3714 FIXME("(%p)->(%p)\n", This, value);
3715
3716 if (!para_get_reole(This))
3717 return CO_E_RELEASED;
3718
3719 return E_NOTIMPL;
3720 }
3721
3722 static HRESULT WINAPI TextPara_SetListTab(ITextPara *iface, FLOAT value)
3723 {
3724 ITextParaImpl *This = impl_from_ITextPara(iface);
3725 FIXME("(%p)->(%.2f)\n", This, value);
3726
3727 if (!para_get_reole(This))
3728 return CO_E_RELEASED;
3729
3730 return E_NOTIMPL;
3731 }
3732
3733 static HRESULT WINAPI TextPara_GetListType(ITextPara *iface, LONG *value)
3734 {
3735 ITextParaImpl *This = impl_from_ITextPara(iface);
3736 FIXME("(%p)->(%p)\n", This, value);
3737
3738 if (!para_get_reole(This))
3739 return CO_E_RELEASED;
3740
3741 return E_NOTIMPL;
3742 }
3743
3744 static HRESULT WINAPI TextPara_SetListType(ITextPara *iface, LONG value)
3745 {
3746 ITextParaImpl *This = impl_from_ITextPara(iface);
3747 FIXME("(%p)->(%d)\n", This, value);
3748
3749 if (!para_get_reole(This))
3750 return CO_E_RELEASED;
3751
3752 return E_NOTIMPL;
3753 }
3754
3755