Huw Davies : riched20: Implement parsing of the paragraph numbering destination.
Alexandre Julliard
julliard at winehq.org
Fri Oct 7 14:46:47 CDT 2016
Module: wine
Branch: master
Commit: 880b45ffb011a191c8b535cb346f88c220d74db7
URL: http://source.winehq.org/git/wine.git/?a=commit;h=880b45ffb011a191c8b535cb346f88c220d74db7
Author: Huw Davies <huw at 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 at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at 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.
More information about the wine-cvs
mailing list