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 <huw@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Huw Davies 2016-10-14 10:05:03 +01:00 committed by Alexandre Julliard
parent 3ac78b763b
commit aa57db38dd
7 changed files with 124 additions and 75 deletions

View File

@ -427,11 +427,12 @@ void ME_RTFCharAttrHook(RTF_Info *info)
{ {
case rtfPlain: case rtfPlain:
/* FIXME add more flags once they're implemented */ /* 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.dwEffects = CFE_AUTOCOLOR | CFE_AUTOBACKCOLOR;
fmt.yHeight = 12*20; /* 12pt */ fmt.yHeight = 12*20; /* 12pt */
fmt.wWeight = FW_NORMAL; fmt.wWeight = FW_NORMAL;
fmt.bUnderlineType = CFU_UNDERLINENONE; fmt.bUnderlineType = CFU_UNDERLINE;
break; break;
case rtfBold: case rtfBold:
fmt.dwMask = CFM_BOLD | CFM_WEIGHT; fmt.dwMask = CFM_BOLD | CFM_WEIGHT;
@ -443,24 +444,28 @@ void ME_RTFCharAttrHook(RTF_Info *info)
fmt.dwEffects = info->rtfParam ? fmt.dwMask : 0; fmt.dwEffects = info->rtfParam ? fmt.dwMask : 0;
break; break;
case rtfUnderline: case rtfUnderline:
fmt.dwMask = CFM_UNDERLINETYPE; fmt.dwMask = CFM_UNDERLINETYPE | CFM_UNDERLINE;
fmt.bUnderlineType = info->rtfParam ? CFU_CF1UNDERLINE : CFU_UNDERLINENONE; fmt.bUnderlineType = CFU_UNDERLINE;
fmt.dwEffects = info->rtfParam ? CFE_UNDERLINE : 0;
break; break;
case rtfDotUnderline: case rtfDotUnderline:
fmt.dwMask = CFM_UNDERLINETYPE; fmt.dwMask = CFM_UNDERLINETYPE | CFM_UNDERLINE;
fmt.bUnderlineType = info->rtfParam ? CFU_UNDERLINEDOTTED : CFU_UNDERLINENONE; fmt.bUnderlineType = CFU_UNDERLINEDOTTED;
fmt.dwEffects = info->rtfParam ? CFE_UNDERLINE : 0;
break; break;
case rtfDbUnderline: case rtfDbUnderline:
fmt.dwMask = CFM_UNDERLINETYPE; fmt.dwMask = CFM_UNDERLINETYPE | CFM_UNDERLINE;
fmt.bUnderlineType = info->rtfParam ? CFU_UNDERLINEDOUBLE : CFU_UNDERLINENONE; fmt.bUnderlineType = CFU_UNDERLINEDOUBLE;
fmt.dwEffects = info->rtfParam ? CFE_UNDERLINE : 0;
break; break;
case rtfWordUnderline: case rtfWordUnderline:
fmt.dwMask = CFM_UNDERLINETYPE; fmt.dwMask = CFM_UNDERLINETYPE | CFM_UNDERLINE;
fmt.bUnderlineType = info->rtfParam ? CFU_UNDERLINEWORD : CFU_UNDERLINENONE; fmt.bUnderlineType = CFU_UNDERLINEWORD;
fmt.dwEffects = info->rtfParam ? CFE_UNDERLINE : 0;
break; break;
case rtfNoUnderline: case rtfNoUnderline:
fmt.dwMask = CFM_UNDERLINETYPE; fmt.dwMask = CFM_UNDERLINE;
fmt.bUnderlineType = CFU_UNDERLINENONE; fmt.dwEffects = 0;
break; break;
case rtfStrikeThru: case rtfStrikeThru:
fmt.dwMask = CFM_STRIKEOUT; fmt.dwMask = CFM_STRIKEOUT;

View File

@ -220,7 +220,7 @@ static void get_underline_pen( ME_Style *style, COLORREF color, HPEN *pen )
{ {
*pen = NULL; *pen = NULL;
/* Choose the pen type for underlining the text. */ /* Choose the pen type for underlining the text. */
if (style->fmt.dwMask & CFM_UNDERLINETYPE) if (style->fmt.dwEffects & CFE_UNDERLINE)
{ {
switch (style->fmt.bUnderlineType) switch (style->fmt.bUnderlineType)
{ {

View File

@ -66,7 +66,8 @@ void ME_MakeFirstParagraph(ME_TextEditor *editor)
if (lf.lfWeight > FW_NORMAL) cf.dwEffects |= CFE_BOLD; if (lf.lfWeight > FW_NORMAL) cf.dwEffects |= CFE_BOLD;
cf.wWeight = lf.lfWeight; cf.wWeight = lf.lfWeight;
if (lf.lfItalic) cf.dwEffects |= CFE_ITALIC; 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; if (lf.lfStrikeOut) cf.dwEffects |= CFE_STRIKEOUT;
cf.bPitchAndFamily = lf.lfPitchAndFamily; cf.bPitchAndFamily = lf.lfPitchAndFamily;
cf.bCharSet = lf.lfCharSet; cf.bCharSet = lf.lfCharSet;

View File

@ -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) static void ME_GetRunCharFormat(ME_TextEditor *editor, ME_DisplayItem *run, CHARFORMAT2W *pFmt)
{ {
ME_CopyCharFormat(pFmt, &run->member.run.style->fmt); 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;
}
} }
/****************************************************************************** /******************************************************************************

View File

@ -79,20 +79,6 @@ static CHARFORMAT2W *ME_ToCFAny(CHARFORMAT2W *to, CHARFORMAT2W *from)
CHARFORMATA *t = (CHARFORMATA *)to; CHARFORMATA *t = (CHARFORMATA *)to;
CopyMemory(t, from, FIELD_OFFSET(CHARFORMATA, szFaceName)); CopyMemory(t, from, FIELD_OFFSET(CHARFORMATA, szFaceName));
WideCharToMultiByte(CP_ACP, 0, from->szFaceName, -1, t->szFaceName, sizeof(t->szFaceName), NULL, NULL); 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 */ t->cbSize = sizeof(*t); /* it was overwritten by CopyMemory */
return to; return to;
} }
@ -100,20 +86,6 @@ static CHARFORMAT2W *ME_ToCFAny(CHARFORMAT2W *to, CHARFORMAT2W *from)
{ {
CHARFORMATW *t = (CHARFORMATW *)to; CHARFORMATW *t = (CHARFORMATW *)to;
CopyMemory(t, from, sizeof(*t)); 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 */ t->cbSize = sizeof(*t); /* it was overwritten by CopyMemory */
return to; 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_SPACING, sSpacing);
COPY_STYLE_ITEM(CFM_STYLE, sStyle); COPY_STYLE_ITEM(CFM_STYLE, sStyle);
COPY_STYLE_ITEM(CFM_UNDERLINETYPE, bUnderlineType);
COPY_STYLE_ITEM(CFM_WEIGHT, wWeight); COPY_STYLE_ITEM(CFM_WEIGHT, wWeight);
/* FIXME: this is not documented this way, but that's the more logical */ /* FIXME: this is not documented this way, but that's the more logical */
COPY_STYLE_ITEM(CFM_FACE, bPitchAndFamily); COPY_STYLE_ITEM(CFM_FACE, bPitchAndFamily);
@ -210,12 +181,18 @@ ME_Style *ME_ApplyStyle(ME_TextEditor *editor, ME_Style *sSrc, CHARFORMAT2W *mod
else else
fmt.dwEffects &= ~CFE_AUTOCOLOR; 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.dwMask |= CFM_UNDERLINE;
fmt.bUnderlineType = (mod->dwEffects & CFM_UNDERLINE) ? if (mod->bUnderlineType == CFU_UNDERLINENONE)
CFU_CF1UNDERLINE : CFU_UNDERLINENONE; fmt.dwEffects &= ~CFE_UNDERLINE;
else
fmt.dwEffects |= CFE_UNDERLINE;
} }
if (mod->dwMask & CFM_BOLD && !(mod->dwMask & CFM_WEIGHT)) if (mod->dwMask & CFM_BOLD && !(mod->dwMask & CFM_WEIGHT))
{ {
fmt.wWeight = (mod->dwEffects & CFE_BOLD) ? FW_BOLD : FW_NORMAL; 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; lf->lfWeight = s->fmt.wWeight;
if (s->fmt.dwEffects & s->fmt.dwMask & CFM_ITALIC) if (s->fmt.dwEffects & s->fmt.dwMask & CFM_ITALIC)
lf->lfItalic = 1; lf->lfItalic = 1;
if (s->fmt.dwEffects & s->fmt.dwMask & (CFM_UNDERLINE | CFE_LINK)) if ((s->fmt.dwEffects & s->fmt.dwMask & (CFM_UNDERLINE | CFE_LINK)) &&
lf->lfUnderline = 1; s->fmt.bUnderlineType == CFU_CF1UNDERLINE)
if (s->fmt.dwMask & CFM_UNDERLINETYPE && s->fmt.bUnderlineType == CFU_CF1UNDERLINE)
lf->lfUnderline = 1; lf->lfUnderline = 1;
if (s->fmt.dwEffects & s->fmt.dwMask & CFM_STRIKEOUT) if (s->fmt.dwEffects & s->fmt.dwMask & CFM_STRIKEOUT)
lf->lfStrikeOut = 1; lf->lfStrikeOut = 1;
@ -352,14 +328,13 @@ void ME_CharFormatFromLogFont(HDC hDC, const LOGFONTW *lf, CHARFORMAT2W *fmt)
ry = GetDeviceCaps(hDC, LOGPIXELSY); ry = GetDeviceCaps(hDC, LOGPIXELSY);
lstrcpyW(fmt->szFaceName, lf->lfFaceName); lstrcpyW(fmt->szFaceName, lf->lfFaceName);
fmt->dwEffects = 0; 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->wWeight = lf->lfWeight;
fmt->yHeight = -lf->lfHeight*1440/ry; fmt->yHeight = -lf->lfHeight*1440/ry;
if (lf->lfWeight > FW_NORMAL) fmt->dwEffects |= CFM_BOLD; if (lf->lfWeight > FW_NORMAL) fmt->dwEffects |= CFM_BOLD;
if (lf->lfItalic) fmt->dwEffects |= CFM_ITALIC; if (lf->lfItalic) fmt->dwEffects |= CFM_ITALIC;
if (lf->lfUnderline) fmt->dwEffects |= CFM_UNDERLINE; if (lf->lfUnderline) fmt->dwEffects |= CFM_UNDERLINE;
/* notice that if a logfont was created with underline due to CFM_LINK, this fmt->bUnderlineType = CFU_UNDERLINE;
would add an erroneous CFM_UNDERLINE. This isn't currently ever a problem. */
if (lf->lfStrikeOut) fmt->dwEffects |= CFM_STRIKEOUT; if (lf->lfStrikeOut) fmt->dwEffects |= CFM_STRIKEOUT;
fmt->bPitchAndFamily = lf->lfPitchAndFamily; fmt->bPitchAndFamily = lf->lfPitchAndFamily;
fmt->bCharSet = lf->lfCharSet; fmt->bCharSet = lf->lfCharSet;

View File

@ -1256,6 +1256,85 @@ static void test_EM_SETCHARFORMAT(void)
SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cfW); SendMessageA(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cfW);
ok(cfW.sSpacing == 10, "got %d\n", cfW.sSpacing); 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); DestroyWindow(hwndRichEdit);
} }

View File

@ -787,29 +787,28 @@ ME_StreamOutRTFCharProps(ME_OutStream *pStream, CHARFORMAT2W *fmt)
else if (fmt->dwEffects & CFE_SUPERSCRIPT) else if (fmt->dwEffects & CFE_SUPERSCRIPT)
strcat(props, "\\super"); strcat(props, "\\super");
} }
if (fmt->dwMask & CFM_UNDERLINE || fmt->dwMask & CFM_UNDERLINETYPE) { if (fmt->dwEffects & CFE_UNDERLINE)
if (fmt->dwMask & CFM_UNDERLINETYPE) {
switch (fmt->bUnderlineType) { switch (fmt->bUnderlineType)
case CFU_CF1UNDERLINE: {
case CFU_UNDERLINE: case CFU_UNDERLINE:
strcat(props, "\\ul"); strcat(props, "\\ul");
break; break;
case CFU_UNDERLINEDOTTED: case CFU_UNDERLINEDOTTED:
strcat(props, "\\uld"); strcat(props, "\\uld");
break; break;
case CFU_UNDERLINEDOUBLE: case CFU_UNDERLINEDOUBLE:
strcat(props, "\\uldb"); strcat(props, "\\uldb");
break; break;
case CFU_UNDERLINEWORD: case CFU_UNDERLINEWORD:
strcat(props, "\\ulw"); strcat(props, "\\ulw");
break; break;
case CFU_UNDERLINENONE: case CFU_CF1UNDERLINE:
default: case CFU_UNDERLINENONE:
default:
strcat(props, "\\ulnone"); strcat(props, "\\ulnone");
break; break;
} }
else if (fmt->dwEffects & CFE_UNDERLINE)
strcat(props, "\\ul");
} }
/* FIXME: How to emit CFM_WEIGHT? */ /* FIXME: How to emit CFM_WEIGHT? */