diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c index 24121a70273..7b87dfc62b7 100644 --- a/dlls/riched20/editor.c +++ b/dlls/riched20/editor.c @@ -544,11 +544,6 @@ void ME_RTFCharAttrHook(RTF_Info *info) the same tags mean different things in different contexts */ void ME_RTFParAttrHook(RTF_Info *info) { - PARAFORMAT2 fmt; - fmt.cbSize = sizeof(fmt); - fmt.dwMask = 0; - fmt.wEffects = 0; - switch(info->rtfMinor) { case rtfParDef: /* restores default paragraph attributes */ @@ -556,18 +551,18 @@ void ME_RTFParAttrHook(RTF_Info *info) info->borderType = RTFBorderParaLeft; else /* v1.0 - 3.0 */ info->borderType = RTFBorderParaTop; - fmt.dwMask = PFM_ALIGNMENT | PFM_BORDER | PFM_LINESPACING | PFM_TABSTOPS | + info->fmt.dwMask = PFM_ALIGNMENT | PFM_BORDER | PFM_LINESPACING | PFM_TABSTOPS | PFM_OFFSET | PFM_RIGHTINDENT | PFM_SPACEAFTER | PFM_SPACEBEFORE | PFM_STARTINDENT; /* TODO: numbering, shading */ - fmt.wAlignment = PFA_LEFT; - fmt.cTabCount = 0; - fmt.dxOffset = fmt.dxStartIndent = fmt.dxRightIndent = 0; - fmt.wBorderWidth = fmt.wBorders = 0; - fmt.wBorderSpace = 0; - fmt.bLineSpacingRule = 0; - fmt.dySpaceBefore = fmt.dySpaceAfter = 0; - fmt.dyLineSpacing = 0; + info->fmt.wAlignment = PFA_LEFT; + info->fmt.cTabCount = 0; + info->fmt.dxOffset = info->fmt.dxStartIndent = info->fmt.dxRightIndent = 0; + info->fmt.wBorderWidth = info->fmt.wBorders = 0; + info->fmt.wBorderSpace = 0; + info->fmt.bLineSpacingRule = 0; + info->fmt.dySpaceBefore = info->fmt.dySpaceAfter = 0; + info->fmt.dyLineSpacing = 0; if (!info->editor->bEmulateVersion10) /* v4.1 */ { if (info->tableDef && info->tableDef->tableRowStart && @@ -591,8 +586,8 @@ void ME_RTFParAttrHook(RTF_Info *info) } } } else { /* v1.0 - v3.0 */ - fmt.dwMask |= PFM_TABLE; - fmt.wEffects &= ~PFE_TABLE; + info->fmt.dwMask |= PFM_TABLE; + info->fmt.wEffects &= ~PFE_TABLE; } break; case rtfNestLevel: @@ -660,197 +655,168 @@ void ME_RTFParAttrHook(RTF_Info *info) } return; } else { /* v1.0 - v3.0 */ - fmt.dwMask |= PFM_TABLE; - fmt.wEffects |= PFE_TABLE; + info->fmt.dwMask |= PFM_TABLE; + info->fmt.wEffects |= PFE_TABLE; } break; } case rtfFirstIndent: - ME_GetSelectionParaFormat(info->editor, &fmt); - fmt.dwMask = PFM_STARTINDENT | PFM_OFFSET; - fmt.dxStartIndent += fmt.dxOffset + info->rtfParam; - fmt.dxOffset = -info->rtfParam; - break; case rtfLeftIndent: - ME_GetSelectionParaFormat(info->editor, &fmt); - fmt.dwMask = PFM_STARTINDENT; - fmt.dxStartIndent = info->rtfParam - fmt.dxOffset; + if ((info->fmt.dwMask & (PFM_STARTINDENT | PFM_OFFSET)) != (PFM_STARTINDENT | PFM_OFFSET)) + { + PARAFORMAT2 fmt; + fmt.cbSize = sizeof(fmt); + ME_GetSelectionParaFormat(info->editor, &fmt); + info->fmt.dwMask |= PFM_STARTINDENT | PFM_OFFSET; + info->fmt.dxStartIndent = fmt.dxStartIndent; + info->fmt.dxOffset = fmt.dxOffset; + } + if (info->rtfMinor == rtfFirstIndent) + { + info->fmt.dxStartIndent += info->fmt.dxOffset + info->rtfParam; + info->fmt.dxOffset = -info->rtfParam; + } + else + info->fmt.dxStartIndent = info->rtfParam - info->fmt.dxOffset; break; case rtfRightIndent: - fmt.dwMask = PFM_RIGHTINDENT; - fmt.dxRightIndent = info->rtfParam; + info->fmt.dwMask |= PFM_RIGHTINDENT; + info->fmt.dxRightIndent = info->rtfParam; break; case rtfQuadLeft: case rtfQuadJust: - fmt.dwMask = PFM_ALIGNMENT; - fmt.wAlignment = PFA_LEFT; + info->fmt.dwMask |= PFM_ALIGNMENT; + info->fmt.wAlignment = PFA_LEFT; break; case rtfQuadRight: - fmt.dwMask = PFM_ALIGNMENT; - fmt.wAlignment = PFA_RIGHT; + info->fmt.dwMask |= PFM_ALIGNMENT; + info->fmt.wAlignment = PFA_RIGHT; break; case rtfQuadCenter: - fmt.dwMask = PFM_ALIGNMENT; - fmt.wAlignment = PFA_CENTER; + info->fmt.dwMask |= PFM_ALIGNMENT; + info->fmt.wAlignment = PFA_CENTER; break; case rtfTabPos: - ME_GetSelectionParaFormat(info->editor, &fmt); - if (!(fmt.dwMask & PFM_TABSTOPS)) + if (!(info->fmt.dwMask & PFM_TABSTOPS)) { - fmt.cTabCount = 0; + PARAFORMAT2 fmt; + fmt.cbSize = sizeof(fmt); + ME_GetSelectionParaFormat(info->editor, &fmt); + memcpy(info->fmt.rgxTabs, fmt.rgxTabs, + fmt.cTabCount * sizeof(fmt.rgxTabs[0])); + info->fmt.cTabCount = fmt.cTabCount; + info->fmt.dwMask |= PFM_TABSTOPS; } - if (fmt.cTabCount < MAX_TAB_STOPS && info->rtfParam < 0x1000000) - fmt.rgxTabs[fmt.cTabCount++] = info->rtfParam; - fmt.dwMask = PFM_TABSTOPS; + if (info->fmt.cTabCount < MAX_TAB_STOPS && info->rtfParam < 0x1000000) + info->fmt.rgxTabs[info->fmt.cTabCount++] = info->rtfParam; break; case rtfKeep: - fmt.dwMask = PFM_KEEP; - fmt.wEffects = PFE_KEEP; + info->fmt.dwMask |= PFM_KEEP; + info->fmt.wEffects |= PFE_KEEP; break; case rtfNoWidowControl: - fmt.dwMask = PFM_NOWIDOWCONTROL; - fmt.wEffects = PFE_NOWIDOWCONTROL; + info->fmt.dwMask |= PFM_NOWIDOWCONTROL; + info->fmt.wEffects |= PFE_NOWIDOWCONTROL; break; case rtfKeepNext: - fmt.dwMask = PFM_KEEPNEXT; - fmt.wEffects = PFE_KEEPNEXT; + info->fmt.dwMask |= PFM_KEEPNEXT; + info->fmt.wEffects |= PFE_KEEPNEXT; break; case rtfSpaceAfter: - fmt.dwMask = PFM_SPACEAFTER; - fmt.dySpaceAfter = info->rtfParam; + info->fmt.dwMask |= PFM_SPACEAFTER; + info->fmt.dySpaceAfter = info->rtfParam; break; case rtfSpaceBefore: - fmt.dwMask = PFM_SPACEBEFORE; - fmt.dySpaceBefore = info->rtfParam; + info->fmt.dwMask |= PFM_SPACEBEFORE; + info->fmt.dySpaceBefore = info->rtfParam; break; case rtfSpaceBetween: - fmt.dwMask = PFM_LINESPACING; + info->fmt.dwMask |= PFM_LINESPACING; if ((int)info->rtfParam > 0) { - fmt.dyLineSpacing = info->rtfParam; - fmt.bLineSpacingRule = 3; + info->fmt.dyLineSpacing = info->rtfParam; + info->fmt.bLineSpacingRule = 3; } else { - fmt.dyLineSpacing = info->rtfParam; - fmt.bLineSpacingRule = 4; + info->fmt.dyLineSpacing = info->rtfParam; + info->fmt.bLineSpacingRule = 4; } break; case rtfSpaceMultiply: - fmt.dwMask = PFM_LINESPACING; - fmt.dyLineSpacing = info->rtfParam * 20; - fmt.bLineSpacingRule = 5; + info->fmt.dwMask |= PFM_LINESPACING; + info->fmt.dyLineSpacing = info->rtfParam * 20; + info->fmt.bLineSpacingRule = 5; break; case rtfParBullet: - fmt.dwMask = PFM_NUMBERING; - fmt.wNumbering = PFN_BULLET; + info->fmt.dwMask |= PFM_NUMBERING; + info->fmt.wNumbering = PFN_BULLET; break; case rtfParSimple: - fmt.dwMask = PFM_NUMBERING; - fmt.wNumbering = 2; /* FIXME: MSDN says it's not used ?? */ + info->fmt.dwMask |= PFM_NUMBERING; + info->fmt.wNumbering = 2; /* FIXME: MSDN says it's not used ?? */ break; case rtfParNumDecimal: - fmt.dwMask = PFM_NUMBERING; - fmt.wNumbering = 2; /* FIXME: MSDN says it's not used ?? */ + info->fmt.dwMask |= PFM_NUMBERING; + info->fmt.wNumbering = 2; /* FIXME: MSDN says it's not used ?? */ break; case rtfParNumIndent: - fmt.dwMask = PFM_NUMBERINGTAB; - fmt.wNumberingTab = info->rtfParam; + info->fmt.dwMask |= PFM_NUMBERINGTAB; + info->fmt.wNumberingTab = info->rtfParam; break; case rtfParNumStartAt: - fmt.dwMask = PFM_NUMBERINGSTART; - fmt.wNumberingStart = info->rtfParam; + info->fmt.dwMask |= PFM_NUMBERINGSTART; + info->fmt.wNumberingStart = info->rtfParam; break; case rtfBorderLeft: info->borderType = RTFBorderParaLeft; - ME_GetSelectionParaFormat(info->editor, &fmt); - if (!(fmt.dwMask & PFM_BORDER)) - { - fmt.wBorderSpace = 0; - fmt.wBorderWidth = 1; - fmt.wBorders = 0; - } - fmt.wBorders |= 1; - fmt.dwMask = PFM_BORDER; + info->fmt.wBorders |= 1; + info->fmt.dwMask |= PFM_BORDER; break; case rtfBorderRight: info->borderType = RTFBorderParaRight; - ME_GetSelectionParaFormat(info->editor, &fmt); - if (!(fmt.dwMask & PFM_BORDER)) - { - fmt.wBorderSpace = 0; - fmt.wBorderWidth = 1; - fmt.wBorders = 0; - } - fmt.wBorders |= 2; - fmt.dwMask = PFM_BORDER; + info->fmt.wBorders |= 2; + info->fmt.dwMask |= PFM_BORDER; break; case rtfBorderTop: info->borderType = RTFBorderParaTop; - ME_GetSelectionParaFormat(info->editor, &fmt); - if (!(fmt.dwMask & PFM_BORDER)) - { - fmt.wBorderSpace = 0; - fmt.wBorderWidth = 1; - fmt.wBorders = 0; - } - fmt.wBorders |= 4; - fmt.dwMask = PFM_BORDER; + info->fmt.wBorders |= 4; + info->fmt.dwMask |= PFM_BORDER; break; case rtfBorderBottom: info->borderType = RTFBorderParaBottom; - ME_GetSelectionParaFormat(info->editor, &fmt); - if (!(fmt.dwMask & PFM_BORDER)) - { - fmt.wBorderSpace = 0; - fmt.wBorderWidth = 1; - fmt.wBorders = 0; - } - fmt.wBorders |= 8; - fmt.dwMask = PFM_BORDER; + info->fmt.wBorders |= 8; + info->fmt.dwMask |= PFM_BORDER; break; case rtfBorderSingle: - ME_GetSelectionParaFormat(info->editor, &fmt); - /* we assume that borders have been created before (RTF spec) */ - fmt.wBorders &= ~0x700; - fmt.wBorders |= 1 << 8; - fmt.dwMask = PFM_BORDER; + info->fmt.wBorders &= ~0x700; + info->fmt.wBorders |= 1 << 8; + info->fmt.dwMask |= PFM_BORDER; break; case rtfBorderThick: - ME_GetSelectionParaFormat(info->editor, &fmt); - /* we assume that borders have been created before (RTF spec) */ - fmt.wBorders &= ~0x700; - fmt.wBorders |= 2 << 8; - fmt.dwMask = PFM_BORDER; + info->fmt.wBorders &= ~0x700; + info->fmt.wBorders |= 2 << 8; + info->fmt.dwMask |= PFM_BORDER; break; case rtfBorderShadow: - ME_GetSelectionParaFormat(info->editor, &fmt); - /* we assume that borders have been created before (RTF spec) */ - fmt.wBorders &= ~0x700; - fmt.wBorders |= 10 << 8; - fmt.dwMask = PFM_BORDER; + info->fmt.wBorders &= ~0x700; + info->fmt.wBorders |= 10 << 8; + info->fmt.dwMask |= PFM_BORDER; break; case rtfBorderDouble: - ME_GetSelectionParaFormat(info->editor, &fmt); - /* we assume that borders have been created before (RTF spec) */ - fmt.wBorders &= ~0x700; - fmt.wBorders |= 7 << 8; - fmt.dwMask = PFM_BORDER; + info->fmt.wBorders &= ~0x700; + info->fmt.wBorders |= 7 << 8; + info->fmt.dwMask |= PFM_BORDER; break; case rtfBorderDot: - ME_GetSelectionParaFormat(info->editor, &fmt); - /* we assume that borders have been created before (RTF spec) */ - fmt.wBorders &= ~0x700; - fmt.wBorders |= 11 << 8; - fmt.dwMask = PFM_BORDER; + info->fmt.wBorders &= ~0x700; + info->fmt.wBorders |= 11 << 8; + info->fmt.dwMask |= PFM_BORDER; break; case rtfBorderWidth: { int borderSide = info->borderType & RTFBorderSideMask; RTFTable *tableDef = info->tableDef; - ME_GetSelectionParaFormat(info->editor, &fmt); - /* we assume that borders have been created before (RTF spec) */ - fmt.wBorderWidth |= ((info->rtfParam / 15) & 7) << 8; if ((info->borderType & RTFBorderTypeMask) == RTFBorderTypeCell) { RTFBorder *border; @@ -860,14 +826,13 @@ void ME_RTFParAttrHook(RTF_Info *info) border->width = info->rtfParam; break; } - fmt.dwMask = PFM_BORDER; + info->fmt.wBorderWidth = info->rtfParam; + info->fmt.dwMask |= PFM_BORDER; break; } case rtfBorderSpace: - ME_GetSelectionParaFormat(info->editor, &fmt); - /* we assume that borders have been created before (RTF spec) */ - fmt.wBorderSpace = info->rtfParam; - fmt.dwMask = PFM_BORDER; + info->fmt.wBorderSpace = info->rtfParam; + info->fmt.dwMask |= PFM_BORDER; break; case rtfBorderColor: { @@ -894,19 +859,14 @@ void ME_RTFParAttrHook(RTF_Info *info) break; } case rtfRTLPar: - fmt.dwMask = PFM_RTLPARA; - fmt.wEffects = PFE_RTLPARA; + info->fmt.dwMask |= PFM_RTLPARA; + info->fmt.wEffects |= PFE_RTLPARA; break; case rtfLTRPar: - fmt.dwMask = PFM_RTLPARA; - fmt.wEffects = 0; + info->fmt.dwMask = PFM_RTLPARA; + info->fmt.wEffects &= ~PFE_RTLPARA; break; } - if (fmt.dwMask) { - RTFFlushOutputBuffer(info); - /* FIXME too slow ? how come ?*/ - ME_SetSelectionParaFormat(info->editor, &fmt); - } } void ME_RTFTblAttrHook(RTF_Info *info) diff --git a/dlls/riched20/reader.c b/dlls/riched20/reader.c index 0972911d9bb..27d0182b09d 100644 --- a/dlls/riched20/reader.c +++ b/dlls/riched20/reader.c @@ -269,6 +269,9 @@ void RTFInit(RTF_Info *info) info->nestingLevel = 0; info->canInheritInTbl = FALSE; info->borderType = 0; + + memset(&info->fmt, 0, sizeof(info->fmt)); + info->fmt.cbSize = sizeof(info->fmt); } /* @@ -2516,6 +2519,10 @@ static void SpecialChar (RTF_Info *info) case rtfPage: case rtfSect: case rtfPar: + RTFFlushOutputBuffer(info); + ME_SetSelectionParaFormat(info->editor, &info->fmt); + memset(&info->fmt, 0, sizeof(info->fmt)); + info->fmt.cbSize = sizeof(info->fmt); RTFPutUnicodeChar (info, '\r'); if (info->editor->bEmulateVersion10) RTFPutUnicodeChar (info, '\n'); break; diff --git a/dlls/riched20/rtf.h b/dlls/riched20/rtf.h index 335d098f6e8..cc53c615ab0 100644 --- a/dlls/riched20/rtf.h +++ b/dlls/riched20/rtf.h @@ -1181,6 +1181,8 @@ struct _RTF_Info { int nestingLevel; BOOL canInheritInTbl; int borderType; /* value corresponds to the RTFBorder constants. */ + + PARAFORMAT2 fmt; /* Accumulated para fmt for current paragraph. */ }; diff --git a/dlls/riched20/tests/editor.c b/dlls/riched20/tests/editor.c index 6e0585a68fe..98b31cef9b4 100644 --- a/dlls/riched20/tests/editor.c +++ b/dlls/riched20/tests/editor.c @@ -5404,9 +5404,10 @@ static void test_EM_STREAMIN(void) EDITSTREAM es; char buffer[1024] = {0}, tmp[16]; CHARRANGE range; + PARAFORMAT2 fmt; - const char * streamText0 = "{\\rtf1 TestSomeText}"; - const char * streamText0a = "{\\rtf1 TestSomeText\\par}"; + const char * streamText0 = "{\\rtf1\\fi100\\li200\\rtlpar\\qr TestSomeText}"; + const char * streamText0a = "{\\rtf1\\fi100\\li200\\rtlpar\\qr TestSomeText\\par}"; const char * streamText0b = "{\\rtf1 TestSomeText\\par\\par}"; const char * ptr; @@ -5463,6 +5464,17 @@ static void test_EM_STREAMIN(void) ok (result == 0, "EM_STREAMIN: Test 0 set wrong text: Result: %s\n",buffer); ok(es.dwError == 0, "EM_STREAMIN: Test 0 set error %d, expected %d\n", es.dwError, 0); + /* Show that para fmts are ignored */ + range.cpMin = 2; + range.cpMax = 2; + result = SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&range); + memset(&fmt, 0xcc, sizeof(fmt)); + fmt.cbSize = sizeof(fmt); + result = SendMessageA(hwndRichEdit, EM_GETPARAFORMAT, 0, (LPARAM)&fmt); + ok(fmt.dxStartIndent == 0, "got %d\n", fmt.dxStartIndent); + ok(fmt.dxOffset == 0, "got %d\n", fmt.dxOffset); + ok(fmt.wAlignment == PFA_LEFT, "got %d\n", fmt.wAlignment); + ok((fmt.wEffects & PFE_RTLPARA) == 0, "got %x\n", fmt.wEffects); /* Native richedit 2.0 ignores last \par */ ptr = streamText0a; @@ -5479,6 +5491,17 @@ static void test_EM_STREAMIN(void) ok (result == 0, "EM_STREAMIN: Test 0-a set wrong text: Result: %s\n",buffer); ok(es.dwError == 0, "EM_STREAMIN: Test 0-a set error %d, expected %d\n", es.dwError, 0); + /* This time para fmts are processed */ + range.cpMin = 2; + range.cpMax = 2; + result = SendMessageA(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM)&range); + memset(&fmt, 0xcc, sizeof(fmt)); + fmt.cbSize = sizeof(fmt); + result = SendMessageA(hwndRichEdit, EM_GETPARAFORMAT, 0, (LPARAM)&fmt); + ok(fmt.dxStartIndent == 300, "got %d\n", fmt.dxStartIndent); + ok(fmt.dxOffset == -100, "got %d\n", fmt.dxOffset); + ok(fmt.wAlignment == PFA_RIGHT, "got %d\n", fmt.wAlignment); + ok((fmt.wEffects & PFE_RTLPARA) == PFE_RTLPARA, "got %x\n", fmt.wEffects); /* Native richedit 2.0 ignores last \par, next-to-last \par appears */ es.dwCookie = (DWORD_PTR)&streamText0b;