Module: wine Branch: master Commit: 880b45ffb011a191c8b535cb346f88c220d74db7 URL: http://source.winehq.org/git/wine.git/?a=commit;h=880b45ffb011a191c8b535cb34...
Author: Huw Davies huw@codeweavers.com Date: Fri Oct 7 10:49:32 2016 +0100
riched20: Implement parsing of the paragraph numbering destination.
Signed-off-by: Huw Davies huw@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/riched20/editor.c | 117 ++++++++++++++++++++++++++++++++++++++----- dlls/riched20/reader.c | 4 +- dlls/riched20/tests/editor.c | 69 +++++++++++++++++++++++++ 3 files changed, 176 insertions(+), 14 deletions(-)
diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c index da9425e..162daa8 100644 --- a/dlls/riched20/editor.c +++ b/dlls/riched20/editor.c @@ -763,18 +763,6 @@ void ME_RTFParAttrHook(RTF_Info *info) info->fmt.dwMask |= PFM_NUMBERING; info->fmt.wNumbering = 2; /* FIXME: MSDN says it's not used ?? */ break; - case rtfParNumDecimal: - info->fmt.dwMask |= PFM_NUMBERING; - info->fmt.wNumbering = 2; /* FIXME: MSDN says it's not used ?? */ - break; - case rtfParNumIndent: - info->fmt.dwMask |= PFM_NUMBERINGTAB; - info->fmt.wNumberingTab = info->rtfParam; - break; - case rtfParNumStartAt: - info->fmt.dwMask |= PFM_NUMBERINGSTART; - info->fmt.wNumberingStart = info->rtfParam; - break; case rtfBorderLeft: info->borderType = RTFBorderParaLeft; info->fmt.wBorders |= 1; @@ -1432,6 +1420,110 @@ static void ME_RTFReadObjectGroup(RTF_Info *info) RTFRouteToken(info); /* feed "}" back to router */ }
+static void ME_RTFReadParnumGroup( RTF_Info *info ) +{ + int level = 1, type = -1; + WORD indent = 0, start = 1; + WCHAR txt_before = 0, txt_after = 0; + + for (;;) + { + RTFGetToken( info ); + + if (RTFCheckCMM( info, rtfControl, rtfDestination, rtfParNumTextBefore ) || + RTFCheckCMM( info, rtfControl, rtfDestination, rtfParNumTextAfter )) + { + int loc = info->rtfMinor; + + RTFGetToken( info ); + if (info->rtfClass == rtfText) + { + if (loc == rtfParNumTextBefore) + txt_before = info->rtfMajor; + else + txt_after = info->rtfMajor; + continue; + } + /* falling through to catch EOFs and group level changes */ + } + + if (info->rtfClass == rtfEOF) + return; + + if (RTFCheckCM( info, rtfGroup, rtfEndGroup )) + { + if (--level == 0) break; + continue; + } + + if (RTFCheckCM( info, rtfGroup, rtfBeginGroup )) + { + level++; + continue; + } + + /* Ignore non para-attr */ + if (!RTFCheckCM( info, rtfControl, rtfParAttr )) + continue; + + switch (info->rtfMinor) + { + case rtfParLevel: /* Para level is ignored */ + case rtfParSimple: + break; + case rtfParBullet: + type = PFN_BULLET; + break; + + case rtfParNumDecimal: + type = PFN_ARABIC; + break; + case rtfParNumULetter: + type = PFN_UCLETTER; + break; + case rtfParNumURoman: + type = PFN_UCROMAN; + break; + case rtfParNumLLetter: + type = PFN_LCLETTER; + break; + case rtfParNumLRoman: + type = PFN_LCROMAN; + break; + + case rtfParNumIndent: + indent = info->rtfParam; + break; + case rtfParNumStartAt: + start = info->rtfParam; + break; + } + } + + if (type != -1) + { + info->fmt.dwMask |= (PFM_NUMBERING | PFM_NUMBERINGSTART | PFM_NUMBERINGSTYLE | PFM_NUMBERINGTAB); + info->fmt.wNumbering = type; + info->fmt.wNumberingStart = start; + info->fmt.wNumberingStyle = PFNS_PAREN; + if (type != PFN_BULLET) + { + if (txt_before == 0 && txt_after == 0) + info->fmt.wNumberingStyle = PFNS_PLAIN; + else if (txt_after == '.') + info->fmt.wNumberingStyle = PFNS_PERIOD; + else if (txt_before == '(' && txt_after == ')') + info->fmt.wNumberingStyle = PFNS_PARENS; + } + info->fmt.wNumberingTab = indent; + } + + TRACE("type %d indent %d start %d txt before %04x txt after %04x\n", + type, indent, start, txt_before, txt_after); + + RTFRouteToken( info ); /* feed "}" back to router */ +} + static void ME_RTFReadHook(RTF_Info *info) { switch(info->rtfClass) @@ -1581,6 +1673,7 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre RTFSetDestinationCallback(&parser, rtfShpPict, ME_RTFReadShpPictGroup); RTFSetDestinationCallback(&parser, rtfPict, ME_RTFReadPictGroup); RTFSetDestinationCallback(&parser, rtfObject, ME_RTFReadObjectGroup); + RTFSetDestinationCallback(&parser, rtfParNumbering, ME_RTFReadParnumGroup); if (!parser.editor->bEmulateVersion10) /* v4.1 */ { RTFSetDestinationCallback(&parser, rtfNoNestTables, RTFSkipGroup); diff --git a/dlls/riched20/reader.c b/dlls/riched20/reader.c index 2e5dafd..a05b7fc 100644 --- a/dlls/riched20/reader.c +++ b/dlls/riched20/reader.c @@ -1774,8 +1774,8 @@ static RTFKey rtfKey[] = { rtfDestination, rtfFooterFirst, "footerf", 0 }, { rtfDestination, rtfParNumText, "pntext", 0 }, { rtfDestination, rtfParNumbering, "pn", 0 }, - { rtfDestination, rtfParNumTextAfter, "pntexta", 0 }, - { rtfDestination, rtfParNumTextBefore, "pntextb", 0 }, + { rtfDestination, rtfParNumTextAfter, "pntxta", 0 }, + { rtfDestination, rtfParNumTextBefore, "pntxtb", 0 }, { rtfDestination, rtfBookmarkStart, "bkmkstart", 0 }, { rtfDestination, rtfBookmarkEnd, "bkmkend", 0 }, { rtfDestination, rtfPict, "pict", 0 }, diff --git a/dlls/riched20/tests/editor.c b/dlls/riched20/tests/editor.c index ad51e64..d694d28 100644 --- a/dlls/riched20/tests/editor.c +++ b/dlls/riched20/tests/editor.c @@ -8414,6 +8414,74 @@ static void test_eop_char_fmt(void) DestroyWindow( edit ); }
+static void test_para_numbering(void) +{ + HWND edit = new_richeditW( NULL ); + const char *numbers = "{\rtf1{\fonttbl{\f0\fswiss\fprq2\fcharset0 Arial;}{\f1\fnil\fcharset2 Symbol;}}" + "\pard{\pntext\f0 3.\tab}{\*\pn\pnlvlbody\pnfs32\pnf0\pnindent1000\pnstart2\pndec{\pntxta.}}" + "\fs20\fi200\li360\f0 First\par" + "{\pntext\f0 4.\tab}\f0 Second\par" + "{\pntext\f0 6.\tab}\f0 Third\par}"; + const WCHAR expect_numbers_txt[] = {'F','i','r','s','t','\r','S','e','c','o','n','d','\r','T','h','i','r','d',0}; + EDITSTREAM es; + WCHAR buf[80]; + LRESULT result; + PARAFORMAT2 fmt, fmt2; + GETTEXTEX get_text; + CHARFORMAT2W cf; + + get_text.cb = sizeof(buf); + get_text.flags = GT_RAWTEXT; + get_text.codepage = 1200; + get_text.lpDefaultChar = NULL; + get_text.lpUsedDefChar = NULL; + + es.dwCookie = (DWORD_PTR)&numbers; + es.dwError = 0; + es.pfnCallback = test_EM_STREAMIN_esCallback; + result = SendMessageA( edit, EM_STREAMIN, SF_RTF, (LPARAM)&es ); + ok( result == lstrlenW( expect_numbers_txt ), "got %ld\n", result ); + + result = SendMessageW( edit, EM_GETTEXTEX, (WPARAM)&get_text, (LPARAM)buf ); + ok( result == lstrlenW( expect_numbers_txt ), "got %ld\n", result ); + ok( !lstrcmpW( buf, expect_numbers_txt ), "got %s\n", wine_dbgstr_w(buf) ); + + SendMessageW( edit, EM_SETSEL, 1, 1 ); + memset( &fmt, 0, sizeof(fmt) ); + fmt.cbSize = sizeof(fmt); + fmt.dwMask = PFM_ALL2; + SendMessageW( edit, EM_GETPARAFORMAT, 0, (LPARAM)&fmt ); + ok( fmt.wNumbering == PFN_ARABIC, "got %d\n", fmt.wNumbering ); + ok( fmt.wNumberingStart == 2, "got %d\n", fmt.wNumberingStart ); + ok( fmt.wNumberingStyle == PFNS_PERIOD, "got %04x\n", fmt.wNumberingStyle ); + ok( fmt.wNumberingTab == 1000, "got %d\n", fmt.wNumberingTab ); + ok( fmt.dxStartIndent == 560, "got %d\n", fmt.dxStartIndent ); + ok( fmt.dxOffset == -200, "got %d\n", fmt.dxOffset ); + + /* Second para should have identical fmt */ + SendMessageW( edit, EM_SETSEL, 10, 10 ); + memset( &fmt2, 0, sizeof(fmt2) ); + fmt2.cbSize = sizeof(fmt2); + fmt2.dwMask = PFM_ALL2; + SendMessageW( edit, EM_GETPARAFORMAT, 0, (LPARAM)&fmt2 ); + ok( !memcmp( &fmt, &fmt2, sizeof(fmt) ), "format mismatch\n" ); + + /* Check the eop heights - this determines the label height */ + SendMessageW( edit, EM_SETSEL, 12, 13 ); + cf.cbSize = sizeof(cf); + cf.dwMask = CFM_SIZE; + SendMessageW( edit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf ); + ok( cf.yHeight == 200, "got %d\n", cf.yHeight ); + + SendMessageW( edit, EM_SETSEL, 18, 19 ); + cf.cbSize = sizeof(cf); + cf.dwMask = CFM_SIZE; + SendMessageW( edit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf ); + ok( cf.yHeight == 200, "got %d\n", cf.yHeight ); + + DestroyWindow( edit ); +} + START_TEST( editor ) { BOOL ret; @@ -8486,6 +8554,7 @@ START_TEST( editor ) test_rtf_specials(); test_background(); test_eop_char_fmt(); + test_para_numbering();
/* Set the environment variable WINETEST_RICHED20 to keep windows * responsive and open for 30 seconds. This is useful for debugging.