diff --git a/dlls/riched20/richole.c b/dlls/riched20/richole.c index e35f56167fc..5b8cad5d3f9 100644 --- a/dlls/riched20/richole.c +++ b/dlls/riched20/richole.c @@ -421,6 +421,11 @@ static inline FLOAT twips_to_points(LONG value) return value * 72.0 / 1440; } +static inline FLOAT points_to_twips(FLOAT value) +{ + return value * 1440 / 72.0; +} + static HRESULT get_textfont_prop_for_pos(const IRichEditOleImpl *reole, int pos, enum textfont_prop_id propid, textfont_prop_val *value) { @@ -502,6 +507,166 @@ static inline const IRichEditOleImpl *get_range_reole(ITextRange *range) return reole; } +static void textrange_set_font(ITextRange *range, ITextFont *font) +{ + CHARFORMAT2W fmt; + LONG value; + BSTR str; + FLOAT f; + +#define CHARFORMAT_SET_B_FIELD(mask, value) \ + if (value != tomUndefined) { \ + fmt.dwMask |= CFM_##mask; \ + if (value == tomTrue) fmt.dwEffects |= CFE_##mask; \ + } \ + + /* fill format data from font */ + memset(&fmt, 0, sizeof(fmt)); + fmt.cbSize = sizeof(fmt); + + value = tomUndefined; + ITextFont_GetAllCaps(font, &value); + CHARFORMAT_SET_B_FIELD(ALLCAPS, value); + + value = tomUndefined; + ITextFont_GetBold(font, &value); + CHARFORMAT_SET_B_FIELD(BOLD, value); + + value = tomUndefined; + ITextFont_GetEmboss(font, &value); + CHARFORMAT_SET_B_FIELD(EMBOSS, value); + + value = tomUndefined; + ITextFont_GetHidden(font, &value); + CHARFORMAT_SET_B_FIELD(HIDDEN, value); + + value = tomUndefined; + ITextFont_GetEngrave(font, &value); + CHARFORMAT_SET_B_FIELD(IMPRINT, value); + + value = tomUndefined; + ITextFont_GetItalic(font, &value); + CHARFORMAT_SET_B_FIELD(ITALIC, value); + + value = tomUndefined; + ITextFont_GetOutline(font, &value); + CHARFORMAT_SET_B_FIELD(OUTLINE, value); + + value = tomUndefined; + ITextFont_GetProtected(font, &value); + CHARFORMAT_SET_B_FIELD(PROTECTED, value); + + value = tomUndefined; + ITextFont_GetShadow(font, &value); + CHARFORMAT_SET_B_FIELD(SHADOW, value); + + value = tomUndefined; + ITextFont_GetSmallCaps(font, &value); + CHARFORMAT_SET_B_FIELD(SMALLCAPS, value); + + value = tomUndefined; + ITextFont_GetStrikeThrough(font, &value); + CHARFORMAT_SET_B_FIELD(STRIKEOUT, value); + + value = tomUndefined; + ITextFont_GetSubscript(font, &value); + CHARFORMAT_SET_B_FIELD(SUBSCRIPT, value); + + value = tomUndefined; + ITextFont_GetSuperscript(font, &value); + CHARFORMAT_SET_B_FIELD(SUPERSCRIPT, value); + + value = tomUndefined; + ITextFont_GetUnderline(font, &value); + CHARFORMAT_SET_B_FIELD(UNDERLINE, value); + +#undef CHARFORMAT_SET_B_FIELD + + value = tomUndefined; + ITextFont_GetAnimation(font, &value); + if (value != tomUndefined) { + fmt.dwMask |= CFM_ANIMATION; + fmt.bAnimation = value; + } + + value = tomUndefined; + ITextFont_GetBackColor(font, &value); + if (value != tomUndefined) { + fmt.dwMask |= CFM_BACKCOLOR; + if (value == tomAutoColor) + fmt.dwEffects |= CFE_AUTOBACKCOLOR; + else + fmt.crBackColor = value; + } + + value = tomUndefined; + ITextFont_GetForeColor(font, &value); + if (value != tomUndefined) { + fmt.dwMask |= CFM_COLOR; + if (value == tomAutoColor) + fmt.dwEffects |= CFE_AUTOCOLOR; + else + fmt.crTextColor = value; + } + + value = tomUndefined; + ITextFont_GetKerning(font, &f); + if (f != tomUndefined) { + fmt.dwMask |= CFM_KERNING; + fmt.wKerning = points_to_twips(f); + } + + value = tomUndefined; + ITextFont_GetLanguageID(font, &value); + if (value != tomUndefined) { + fmt.dwMask |= CFM_LCID; + fmt.lcid = value; + } + + if (ITextFont_GetName(font, &str) == S_OK) { + fmt.dwMask |= CFM_FACE; + lstrcpynW(fmt.szFaceName, str, sizeof(fmt.szFaceName)/sizeof(WCHAR)); + SysFreeString(str); + } + + ITextFont_GetPosition(font, &f); + if (f != tomUndefined) { + fmt.dwMask |= CFM_OFFSET; + fmt.yOffset = points_to_twips(f); + } + + ITextFont_GetSize(font, &f); + if (f != tomUndefined) { + fmt.dwMask |= CFM_SIZE; + fmt.yHeight = points_to_twips(f); + } + + ITextFont_GetSpacing(font, &f); + if (f != tomUndefined) { + fmt.dwMask |= CFM_SPACING; + fmt.sSpacing = f; + } + + ITextFont_GetWeight(font, &value); + if (value != tomUndefined) { + fmt.dwMask |= CFM_WEIGHT; + fmt.wWeight = value; + } + + if (fmt.dwMask) { + const IRichEditOleImpl *reole = get_range_reole(range); + ME_Cursor from, to; + LONG start, end; + + ITextRange_GetStart(range, &start); + ITextRange_GetEnd(range, &end); + + ME_CursorFromCharOfs(reole->editor, start, &from); + ME_CursorFromCharOfs(reole->editor, end, &to); + ME_SetCharFormat(reole->editor, &from, &to, &fmt); + } +} + static HRESULT get_textfont_prop(const ITextFontImpl *font, enum textfont_prop_id propid, textfont_prop_val *value) { const IRichEditOleImpl *reole; @@ -1638,14 +1803,20 @@ static HRESULT WINAPI ITextRange_fnGetFont(ITextRange *me, ITextFont **font) return create_textfont(me, NULL, font); } -static HRESULT WINAPI ITextRange_fnSetFont(ITextRange *me, ITextFont *pFont) +static HRESULT WINAPI ITextRange_fnSetFont(ITextRange *me, ITextFont *font) { ITextRangeImpl *This = impl_from_ITextRange(me); + + TRACE("(%p)->(%p)\n", This, font); + + if (!font) + return E_INVALIDARG; + if (!This->reOle) return CO_E_RELEASED; - FIXME("not implemented %p\n", This); - return E_NOTIMPL; + textrange_set_font(me, font); + return S_OK; } static HRESULT WINAPI ITextRange_fnGetPara(ITextRange *me, ITextPara **para) @@ -4086,14 +4257,20 @@ static HRESULT WINAPI ITextSelection_fnGetFont(ITextSelection *me, ITextFont **f return create_textfont((ITextRange*)me, NULL, font); } -static HRESULT WINAPI ITextSelection_fnSetFont(ITextSelection *me, ITextFont *pFont) +static HRESULT WINAPI ITextSelection_fnSetFont(ITextSelection *me, ITextFont *font) { ITextSelectionImpl *This = impl_from_ITextSelection(me); + + TRACE("(%p)->(%p)\n", This, font); + + if (!font) + return E_INVALIDARG; + if (!This->reOle) return CO_E_RELEASED; - FIXME("not implemented\n"); - return E_NOTIMPL; + textrange_set_font((ITextRange*)me, font); + return S_OK; } static HRESULT WINAPI ITextSelection_fnGetPara(ITextSelection *me, ITextPara **para) diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c index 35fd59c91b9..09ab9394745 100644 --- a/dlls/riched20/tests/richole.c +++ b/dlls/riched20/tests/richole.c @@ -2923,6 +2923,93 @@ static void test_GetStoryType(void) ITextSelection_Release(selection); } +static void test_SetFont(void) +{ + static const CHAR test_text1[] = "TestSomeText"; + IRichEditOle *reOle = NULL; + ITextDocument *doc = NULL; + ITextSelection *selection; + ITextRange *range, *range2; + ITextFont *font, *font2; + LONG value; + HRESULT hr; + HWND hwnd; + + create_interfaces(&hwnd, &reOle, &doc, &selection); + SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1); + SendMessageA(hwnd, EM_SETSEL, 1, 2); + + hr = ITextDocument_Range(doc, 0, 4, &range); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = ITextDocument_Range(doc, 5, 2, &range2); + ok(hr == S_OK, "got 0x%08x\n", hr); + + EXPECT_REF(range, 1); + hr = ITextRange_GetFont(range, &font); + ok(hr == S_OK, "got 0x%08x\n", hr); + EXPECT_REF(range, 2); + + EXPECT_REF(range2, 1); + hr = ITextRange_GetFont(range2, &font2); + ok(hr == S_OK, "got 0x%08x\n", hr); + EXPECT_REF(range2, 2); + + hr = ITextRange_SetFont(range, NULL); + ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); + + /* setting same font, no-op */ + EXPECT_REF(range, 2); + hr = ITextRange_SetFont(range, font); + ok(hr == S_OK, "got 0x%08x\n", hr); + EXPECT_REF(range, 2); + + EXPECT_REF(range2, 2); + EXPECT_REF(range, 2); + hr = ITextRange_SetFont(range, font2); + ok(hr == S_OK, "got 0x%08x\n", hr); + EXPECT_REF(range2, 2); + EXPECT_REF(range, 2); + + /* originaly range 0-4 is non-italic */ + value = tomTrue; + hr = ITextFont_GetItalic(font, &value); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(value == tomFalse, "got %d\n", value); + + /* set range 5-2 to italic, then set this font to range 0-4 */ + hr = ITextFont_SetItalic(font2, tomTrue); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = ITextRange_SetFont(range, font2); + ok(hr == S_OK, "got 0x%08x\n", hr); + + value = tomFalse; + hr = ITextFont_GetItalic(font, &value); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(value == tomTrue, "got %d\n", value); + + release_interfaces(&hwnd, &reOle, &doc, NULL); + + hr = ITextRange_SetFont(range, NULL); + ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); + + hr = ITextRange_SetFont(range, font); + ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr); + + hr = ITextSelection_SetFont(selection, NULL); + ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); + + hr = ITextSelection_SetFont(selection, font); + ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr); + + ITextFont_Release(font); + ITextFont_Release(font2); + ITextRange_Release(range); + ITextRange_Release(range2); + ITextSelection_Release(selection); +} + START_TEST(richole) { /* Must explicitly LoadLibrary(). The test has no references to functions in @@ -2954,4 +3041,5 @@ START_TEST(richole) test_ITextRange_IsEqual(); test_Select(); test_GetStoryType(); + test_SetFont(); }