From aa57db38dd9cf7afb903e39b64b7274b9e175a33 Mon Sep 17 00:00:00 2001 From: Huw Davies Date: Fri, 14 Oct 2016 10:05:03 +0100 Subject: [PATCH] riched20: Fix the interaction between CFE_UNDERLINE and bUnderlineType. The effect specifies whether underlining is turned on, while bUnderlineType indicates the type of underlining. Signed-off-by: Huw Davies Signed-off-by: Alexandre Julliard --- dlls/riched20/editor.c | 29 +++++++------ dlls/riched20/paint.c | 2 +- dlls/riched20/para.c | 3 +- dlls/riched20/run.c | 10 ----- dlls/riched20/style.c | 53 +++++++----------------- dlls/riched20/tests/editor.c | 79 ++++++++++++++++++++++++++++++++++++ dlls/riched20/writer.c | 23 +++++------ 7 files changed, 124 insertions(+), 75 deletions(-) diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c index 8b94ccf4fa..1ce444e604 100644 --- a/dlls/riched20/editor.c +++ b/dlls/riched20/editor.c @@ -427,11 +427,12 @@ void ME_RTFCharAttrHook(RTF_Info *info) { case rtfPlain: /* FIXME add more flags once they're implemented */ - fmt.dwMask = CFM_BOLD | CFM_ITALIC | CFM_UNDERLINETYPE | CFM_STRIKEOUT | CFM_COLOR | CFM_BACKCOLOR | CFM_SIZE | CFM_WEIGHT; + fmt.dwMask = CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE | CFM_UNDERLINETYPE | CFM_STRIKEOUT | + CFM_COLOR | CFM_BACKCOLOR | CFM_SIZE | CFM_WEIGHT; fmt.dwEffects = CFE_AUTOCOLOR | CFE_AUTOBACKCOLOR; fmt.yHeight = 12*20; /* 12pt */ fmt.wWeight = FW_NORMAL; - fmt.bUnderlineType = CFU_UNDERLINENONE; + fmt.bUnderlineType = CFU_UNDERLINE; break; case rtfBold: fmt.dwMask = CFM_BOLD | CFM_WEIGHT; @@ -443,24 +444,28 @@ void ME_RTFCharAttrHook(RTF_Info *info) fmt.dwEffects = info->rtfParam ? fmt.dwMask : 0; break; case rtfUnderline: - fmt.dwMask = CFM_UNDERLINETYPE; - fmt.bUnderlineType = info->rtfParam ? CFU_CF1UNDERLINE : CFU_UNDERLINENONE; + fmt.dwMask = CFM_UNDERLINETYPE | CFM_UNDERLINE; + fmt.bUnderlineType = CFU_UNDERLINE; + fmt.dwEffects = info->rtfParam ? CFE_UNDERLINE : 0; break; case rtfDotUnderline: - fmt.dwMask = CFM_UNDERLINETYPE; - fmt.bUnderlineType = info->rtfParam ? CFU_UNDERLINEDOTTED : CFU_UNDERLINENONE; + fmt.dwMask = CFM_UNDERLINETYPE | CFM_UNDERLINE; + fmt.bUnderlineType = CFU_UNDERLINEDOTTED; + fmt.dwEffects = info->rtfParam ? CFE_UNDERLINE : 0; break; case rtfDbUnderline: - fmt.dwMask = CFM_UNDERLINETYPE; - fmt.bUnderlineType = info->rtfParam ? CFU_UNDERLINEDOUBLE : CFU_UNDERLINENONE; + fmt.dwMask = CFM_UNDERLINETYPE | CFM_UNDERLINE; + fmt.bUnderlineType = CFU_UNDERLINEDOUBLE; + fmt.dwEffects = info->rtfParam ? CFE_UNDERLINE : 0; break; case rtfWordUnderline: - fmt.dwMask = CFM_UNDERLINETYPE; - fmt.bUnderlineType = info->rtfParam ? CFU_UNDERLINEWORD : CFU_UNDERLINENONE; + fmt.dwMask = CFM_UNDERLINETYPE | CFM_UNDERLINE; + fmt.bUnderlineType = CFU_UNDERLINEWORD; + fmt.dwEffects = info->rtfParam ? CFE_UNDERLINE : 0; break; case rtfNoUnderline: - fmt.dwMask = CFM_UNDERLINETYPE; - fmt.bUnderlineType = CFU_UNDERLINENONE; + fmt.dwMask = CFM_UNDERLINE; + fmt.dwEffects = 0; break; case rtfStrikeThru: fmt.dwMask = CFM_STRIKEOUT; diff --git a/dlls/riched20/paint.c b/dlls/riched20/paint.c index b76f5335c1..41b38969c0 100644 --- a/dlls/riched20/paint.c +++ b/dlls/riched20/paint.c @@ -220,7 +220,7 @@ static void get_underline_pen( ME_Style *style, COLORREF color, HPEN *pen ) { *pen = NULL; /* Choose the pen type for underlining the text. */ - if (style->fmt.dwMask & CFM_UNDERLINETYPE) + if (style->fmt.dwEffects & CFE_UNDERLINE) { switch (style->fmt.bUnderlineType) { diff --git a/dlls/riched20/para.c b/dlls/riched20/para.c index f050b2ef74..3f54fea5c2 100644 --- a/dlls/riched20/para.c +++ b/dlls/riched20/para.c @@ -66,7 +66,8 @@ void ME_MakeFirstParagraph(ME_TextEditor *editor) if (lf.lfWeight > FW_NORMAL) cf.dwEffects |= CFE_BOLD; cf.wWeight = lf.lfWeight; if (lf.lfItalic) cf.dwEffects |= CFE_ITALIC; - cf.bUnderlineType = (lf.lfUnderline) ? CFU_CF1UNDERLINE : CFU_UNDERLINENONE; + if (lf.lfUnderline) cf.dwEffects |= CFE_UNDERLINE; + cf.bUnderlineType = CFU_UNDERLINE; if (lf.lfStrikeOut) cf.dwEffects |= CFE_STRIKEOUT; cf.bPitchAndFamily = lf.lfPitchAndFamily; cf.bCharSet = lf.lfCharSet; diff --git a/dlls/riched20/run.c b/dlls/riched20/run.c index 496f0f9795..098c4f8b4d 100644 --- a/dlls/riched20/run.c +++ b/dlls/riched20/run.c @@ -773,16 +773,6 @@ void ME_SetCharFormat(ME_TextEditor *editor, ME_Cursor *start, ME_Cursor *end, C static void ME_GetRunCharFormat(ME_TextEditor *editor, ME_DisplayItem *run, CHARFORMAT2W *pFmt) { ME_CopyCharFormat(pFmt, &run->member.run.style->fmt); - if ((pFmt->dwMask & CFM_UNDERLINETYPE) && (pFmt->bUnderlineType == CFU_CF1UNDERLINE)) - { - pFmt->dwMask |= CFM_UNDERLINE; - pFmt->dwEffects |= CFE_UNDERLINE; - } - if ((pFmt->dwMask & CFM_UNDERLINETYPE) && (pFmt->bUnderlineType == CFU_UNDERLINENONE)) - { - pFmt->dwMask |= CFM_UNDERLINE; - pFmt->dwEffects &= ~CFE_UNDERLINE; - } } /****************************************************************************** diff --git a/dlls/riched20/style.c b/dlls/riched20/style.c index 0d2c16a19b..1a944cbb79 100644 --- a/dlls/riched20/style.c +++ b/dlls/riched20/style.c @@ -79,20 +79,6 @@ static CHARFORMAT2W *ME_ToCFAny(CHARFORMAT2W *to, CHARFORMAT2W *from) CHARFORMATA *t = (CHARFORMATA *)to; CopyMemory(t, from, FIELD_OFFSET(CHARFORMATA, szFaceName)); WideCharToMultiByte(CP_ACP, 0, from->szFaceName, -1, t->szFaceName, sizeof(t->szFaceName), NULL, NULL); - if (from->dwMask & CFM_UNDERLINETYPE) - { - switch (from->bUnderlineType) - { - case CFU_CF1UNDERLINE: - to->dwMask |= CFM_UNDERLINE; - to->dwEffects |= CFE_UNDERLINE; - break; - case CFU_UNDERLINENONE: - to->dwMask |= CFM_UNDERLINE; - to->dwEffects &= ~CFE_UNDERLINE; - break; - } - } t->cbSize = sizeof(*t); /* it was overwritten by CopyMemory */ return to; } @@ -100,20 +86,6 @@ static CHARFORMAT2W *ME_ToCFAny(CHARFORMAT2W *to, CHARFORMAT2W *from) { CHARFORMATW *t = (CHARFORMATW *)to; CopyMemory(t, from, sizeof(*t)); - if (from->dwMask & CFM_UNDERLINETYPE) - { - switch (from->bUnderlineType) - { - case CFU_CF1UNDERLINE: - to->dwMask |= CFM_UNDERLINE; - to->dwEffects |= CFE_UNDERLINE; - break; - case CFU_UNDERLINENONE: - to->dwMask |= CFM_UNDERLINE; - to->dwEffects &= ~CFE_UNDERLINE; - break; - } - } t->cbSize = sizeof(*t); /* it was overwritten by CopyMemory */ return to; } @@ -195,7 +167,6 @@ ME_Style *ME_ApplyStyle(ME_TextEditor *editor, ME_Style *sSrc, CHARFORMAT2W *mod } COPY_STYLE_ITEM(CFM_SPACING, sSpacing); COPY_STYLE_ITEM(CFM_STYLE, sStyle); - COPY_STYLE_ITEM(CFM_UNDERLINETYPE, bUnderlineType); COPY_STYLE_ITEM(CFM_WEIGHT, wWeight); /* FIXME: this is not documented this way, but that's the more logical */ COPY_STYLE_ITEM(CFM_FACE, bPitchAndFamily); @@ -210,12 +181,18 @@ ME_Style *ME_ApplyStyle(ME_TextEditor *editor, ME_Style *sSrc, CHARFORMAT2W *mod else fmt.dwEffects &= ~CFE_AUTOCOLOR; } - if (mod->dwMask & CFM_UNDERLINE) + + COPY_STYLE_ITEM(CFM_UNDERLINETYPE, bUnderlineType); + /* If the CFM_UNDERLINE effect is not specified set it appropiately */ + if ((mod->dwMask & CFM_UNDERLINETYPE) && !(mod->dwMask & CFM_UNDERLINE)) { - fmt.dwMask |= CFM_UNDERLINETYPE; - fmt.bUnderlineType = (mod->dwEffects & CFM_UNDERLINE) ? - CFU_CF1UNDERLINE : CFU_UNDERLINENONE; + fmt.dwMask |= CFM_UNDERLINE; + if (mod->bUnderlineType == CFU_UNDERLINENONE) + fmt.dwEffects &= ~CFE_UNDERLINE; + else + fmt.dwEffects |= CFE_UNDERLINE; } + if (mod->dwMask & CFM_BOLD && !(mod->dwMask & CFM_WEIGHT)) { fmt.wWeight = (mod->dwEffects & CFE_BOLD) ? FW_BOLD : FW_NORMAL; @@ -329,9 +306,8 @@ ME_LogFontFromStyle(ME_Context* c, LOGFONTW *lf, const ME_Style *s) lf->lfWeight = s->fmt.wWeight; if (s->fmt.dwEffects & s->fmt.dwMask & CFM_ITALIC) lf->lfItalic = 1; - if (s->fmt.dwEffects & s->fmt.dwMask & (CFM_UNDERLINE | CFE_LINK)) - lf->lfUnderline = 1; - if (s->fmt.dwMask & CFM_UNDERLINETYPE && s->fmt.bUnderlineType == CFU_CF1UNDERLINE) + if ((s->fmt.dwEffects & s->fmt.dwMask & (CFM_UNDERLINE | CFE_LINK)) && + s->fmt.bUnderlineType == CFU_CF1UNDERLINE) lf->lfUnderline = 1; if (s->fmt.dwEffects & s->fmt.dwMask & CFM_STRIKEOUT) lf->lfStrikeOut = 1; @@ -352,14 +328,13 @@ void ME_CharFormatFromLogFont(HDC hDC, const LOGFONTW *lf, CHARFORMAT2W *fmt) ry = GetDeviceCaps(hDC, LOGPIXELSY); lstrcpyW(fmt->szFaceName, lf->lfFaceName); fmt->dwEffects = 0; - fmt->dwMask = CFM_WEIGHT|CFM_BOLD|CFM_ITALIC|CFM_UNDERLINE|CFM_STRIKEOUT|CFM_SIZE|CFM_FACE|CFM_CHARSET; + fmt->dwMask = CFM_WEIGHT|CFM_BOLD|CFM_ITALIC|CFM_UNDERLINE|CFM_UNDERLINETYPE|CFM_STRIKEOUT|CFM_SIZE|CFM_FACE|CFM_CHARSET; fmt->wWeight = lf->lfWeight; fmt->yHeight = -lf->lfHeight*1440/ry; if (lf->lfWeight > FW_NORMAL) fmt->dwEffects |= CFM_BOLD; if (lf->lfItalic) fmt->dwEffects |= CFM_ITALIC; if (lf->lfUnderline) fmt->dwEffects |= CFM_UNDERLINE; - /* notice that if a logfont was created with underline due to CFM_LINK, this - would add an erroneous CFM_UNDERLINE. This isn't currently ever a problem. */ + fmt->bUnderlineType = CFU_UNDERLINE; if (lf->lfStrikeOut) fmt->dwEffects |= CFM_STRIKEOUT; fmt->bPitchAndFamily = lf->lfPitchAndFamily; fmt->bCharSet = lf->lfCharSet; diff --git a/dlls/riched20/tests/editor.c b/dlls/riched20/tests/editor.c index 8d7d209017..bfc61ea37e 100644 --- a/dlls/riched20/tests/editor.c +++ b/dlls/riched20/tests/editor.c @@ -1256,6 +1256,85 @@ static void test_EM_SETCHARFORMAT(void) SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cfW); ok(cfW.sSpacing == 10, "got %d\n", cfW.sSpacing); + /* test CFE_UNDERLINE and bUnderlineType interaction */ + /* clear bold, italic */ + SendMessageA(hwndRichEdit, EM_SETSEL, 0, -1); + memset(&cf2, 0, sizeof(CHARFORMAT2A)); + cf2.cbSize = sizeof(CHARFORMAT2A); + cf2.dwMask = CFM_BOLD | CFM_ITALIC; + cf2.dwEffects = 0; + SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2); + + /* check CFE_UNDERLINE is clear and bUnderlineType is CFU_UNDERLINE */ + memset(&cf2, 0, sizeof(CHARFORMAT2A)); + cf2.cbSize = sizeof(CHARFORMAT2A); + SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2); + ok((cf2.dwMask & (CFM_UNDERLINE | CFM_UNDERLINETYPE)) == (CFM_UNDERLINE | CFM_UNDERLINETYPE), + "got %08x\n", cf2.dwMask); + ok(!(cf2.dwEffects & CFE_UNDERLINE), "got %08x\n", cf2.dwEffects); + ok(cf2.bUnderlineType == CFU_UNDERLINE, "got %x\n", cf2.bUnderlineType); + + /* simply touching bUnderlineType will toggle CFE_UNDERLINE */ + cf2.dwMask = CFM_UNDERLINETYPE; + cf2.bUnderlineType = CFU_UNDERLINE; + SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2); + memset(&cf2, 0, sizeof(CHARFORMAT2A)); + cf2.cbSize = sizeof(CHARFORMAT2A); + SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2); + ok((cf2.dwMask & (CFM_UNDERLINE | CFM_UNDERLINETYPE)) == (CFM_UNDERLINE | CFM_UNDERLINETYPE), + "got %08x\n", cf2.dwMask); + ok(cf2.dwEffects & CFE_UNDERLINE, "got %08x\n", cf2.dwEffects); + ok(cf2.bUnderlineType == CFU_UNDERLINE, "got %x\n", cf2.bUnderlineType); + + /* setting bUnderline to CFU_UNDERLINENONE clears CFE_UNDERLINE */ + cf2.dwMask = CFM_UNDERLINETYPE; + cf2.bUnderlineType = CFU_UNDERLINENONE; + SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2); + memset(&cf2, 0, sizeof(CHARFORMAT2A)); + cf2.cbSize = sizeof(CHARFORMAT2A); + SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2); + ok((cf2.dwMask & (CFM_UNDERLINE | CFM_UNDERLINETYPE)) == (CFM_UNDERLINE | CFM_UNDERLINETYPE), + "got %08x\n", cf2.dwMask); + ok(!(cf2.dwEffects & CFE_UNDERLINE), "got %08x\n", cf2.dwEffects); + ok(cf2.bUnderlineType == CFU_UNDERLINENONE, "got %x\n", cf2.bUnderlineType); + + /* another underline type also sets CFE_UNDERLINE */ + cf2.dwMask = CFM_UNDERLINETYPE; + cf2.bUnderlineType = CFU_UNDERLINEDOUBLE; + SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2); + memset(&cf2, 0, sizeof(CHARFORMAT2A)); + cf2.cbSize = sizeof(CHARFORMAT2A); + SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2); + ok((cf2.dwMask & (CFM_UNDERLINE | CFM_UNDERLINETYPE)) == (CFM_UNDERLINE | CFM_UNDERLINETYPE), + "got %08x\n", cf2.dwMask); + ok(cf2.dwEffects & CFE_UNDERLINE, "got %08x\n", cf2.dwEffects); + ok(cf2.bUnderlineType == CFU_UNDERLINEDOUBLE, "got %x\n", cf2.bUnderlineType); + + /* However explicitly clearing CFE_UNDERLINE results in it remaining cleared */ + cf2.dwMask = CFM_UNDERLINETYPE | CFM_UNDERLINE; + cf2.bUnderlineType = CFU_UNDERLINEDOUBLE; + cf2.dwEffects = 0; + SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2); + memset(&cf2, 0, sizeof(CHARFORMAT2A)); + cf2.cbSize = sizeof(CHARFORMAT2A); + SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2); + ok((cf2.dwMask & (CFM_UNDERLINE | CFM_UNDERLINETYPE)) == (CFM_UNDERLINE | CFM_UNDERLINETYPE), + "got %08x\n", cf2.dwMask); + ok(!(cf2.dwEffects & CFE_UNDERLINE), "got %08x\n", cf2.dwEffects); + ok(cf2.bUnderlineType == CFU_UNDERLINEDOUBLE, "got %x\n", cf2.bUnderlineType); + + /* And turing it back on again by just setting CFE_UNDERLINE */ + cf2.dwMask = CFM_UNDERLINE; + cf2.dwEffects = CFE_UNDERLINE; + SendMessageA(hwndRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2); + memset(&cf2, 0, sizeof(CHARFORMAT2A)); + cf2.cbSize = sizeof(CHARFORMAT2A); + SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2); + ok((cf2.dwMask & (CFM_UNDERLINE | CFM_UNDERLINETYPE)) == (CFM_UNDERLINE | CFM_UNDERLINETYPE), + "got %08x\n", cf2.dwMask); + ok(cf2.dwEffects & CFE_UNDERLINE, "got %08x\n", cf2.dwEffects); + ok(cf2.bUnderlineType == CFU_UNDERLINEDOUBLE, "got %x\n", cf2.bUnderlineType); + DestroyWindow(hwndRichEdit); } diff --git a/dlls/riched20/writer.c b/dlls/riched20/writer.c index 77f50e32e4..8ecc160152 100644 --- a/dlls/riched20/writer.c +++ b/dlls/riched20/writer.c @@ -787,29 +787,28 @@ ME_StreamOutRTFCharProps(ME_OutStream *pStream, CHARFORMAT2W *fmt) else if (fmt->dwEffects & CFE_SUPERSCRIPT) strcat(props, "\\super"); } - if (fmt->dwMask & CFM_UNDERLINE || fmt->dwMask & CFM_UNDERLINETYPE) { - if (fmt->dwMask & CFM_UNDERLINETYPE) - switch (fmt->bUnderlineType) { - case CFU_CF1UNDERLINE: - case CFU_UNDERLINE: + if (fmt->dwEffects & CFE_UNDERLINE) + { + switch (fmt->bUnderlineType) + { + case CFU_UNDERLINE: strcat(props, "\\ul"); break; - case CFU_UNDERLINEDOTTED: + case CFU_UNDERLINEDOTTED: strcat(props, "\\uld"); break; - case CFU_UNDERLINEDOUBLE: + case CFU_UNDERLINEDOUBLE: strcat(props, "\\uldb"); break; - case CFU_UNDERLINEWORD: + case CFU_UNDERLINEWORD: strcat(props, "\\ulw"); break; - case CFU_UNDERLINENONE: - default: + case CFU_CF1UNDERLINE: + case CFU_UNDERLINENONE: + default: strcat(props, "\\ulnone"); break; } - else if (fmt->dwEffects & CFE_UNDERLINE) - strcat(props, "\\ul"); } /* FIXME: How to emit CFM_WEIGHT? */