[PATCH 2/6] riched20: Fix the interaction between CFE_UNDERLINE and bUnderlineType.

Huw Davies huw at codeweavers.com
Fri Oct 14 04:05:03 CDT 2016


The effect specifies whether underlining is turned on, while bUnderlineType
indicates the type of underlining.

Signed-off-by: Huw Davies <huw at codeweavers.com>
---
 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 8b94ccf..1ce444e 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 b76f533..41b3896 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 f050b2e..3f54fea 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 496f0f9..098c4f8 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 0d2c16a..1a944cbb 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 8d7d209..bfc61ea 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 77f50e3..8ecc1601 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? */
   
-- 
2.8.2




More information about the wine-patches mailing list