From: Rose Hellsing <rose@pinkro.se> riched20 previously ignored \pntext instuctions in RTF, which caused errornous Paragraph numbers to appear in some Applications. It now properly captures the \pntext content and properly applies numbering when it's missing. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=59392 --- dlls/riched20/editor.c | 56 ++++++++++++++++++++++++++++++++++++++++++ dlls/riched20/reader.c | 31 +++++++++++++++++++++++ dlls/riched20/rtf.h | 1 + 3 files changed, 88 insertions(+) diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c index e704508f2a5..72d25d3946d 100644 --- a/dlls/riched20/editor.c +++ b/dlls/riched20/editor.c @@ -1513,6 +1513,61 @@ static void ME_RTFReadParnumGroup( RTF_Info *info ) RTFRouteToken( info ); /* feed "}" back to router */ } +static void ME_RTFReadPntextGroup( RTF_Info *info ) +{ + int level = 1; + WCHAR buf[256]; + int buf_len = 0; + + ME_DestroyString( info->pntext ); + info->pntext = NULL; + + for (;;) + { + RTFGetToken( info ); + + if (info->rtfClass == rtfEOF) + return; + + if (RTFCheckCM( info, rtfGroup, rtfBeginGroup )) + { + level++; + continue; + } + + if (RTFCheckCM( info, rtfGroup, rtfEndGroup )) + { + level--; + if (level == 0) break; + continue; + } + + if (buf_len >= ARRAY_SIZE(buf) - 1) + continue; + + if (info->rtfClass == rtfText) + { + buf[buf_len++] = (WCHAR)(unsigned char)info->rtfMajor; + } + else if (info->rtfClass == rtfControl && info->rtfMajor == rtfSpecialChar) + { + switch (info->rtfMinor) + { + case rtfTab: buf[buf_len++] = '\t'; break; + case rtfBullet: buf[buf_len++] = 0x2022; break; + case rtfNoBrkSpace: buf[buf_len++] = 0x00A0; break; + case rtfNoBrkHyphen:buf[buf_len++] = 0x2011; break; + case rtfOptDest: + default: break; + } + } + } + + info->pntext = ME_MakeStringN( buf, buf_len ); + + RTFRouteToken( info ); +} + static void ME_RTFReadHook(RTF_Info *info) { switch(info->rtfClass) @@ -1670,6 +1725,7 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre RTFSetDestinationCallback(&parser, rtfPict, ME_RTFReadPictGroup); RTFSetDestinationCallback(&parser, rtfObject, ME_RTFReadObjectGroup); RTFSetDestinationCallback(&parser, rtfParNumbering, ME_RTFReadParnumGroup); + RTFSetDestinationCallback(&parser, rtfParNumText, ME_RTFReadPntextGroup); if (!parser.editor->bEmulateVersion10) /* v4.1 */ { RTFSetDestinationCallback(&parser, rtfNoNestTables, RTFSkipGroup); diff --git a/dlls/riched20/reader.c b/dlls/riched20/reader.c index 95360d8b9d4..402335d4b68 100644 --- a/dlls/riched20/reader.c +++ b/dlls/riched20/reader.c @@ -150,6 +150,7 @@ RTFDestroy(RTF_Info *info) } RTFDestroyAttrs(info); free(info->cpOutputBuffer); + ME_DestroyString( info->pntext ); while (info->tableDef) { RTFTable *tableDef = info->tableDef; @@ -252,6 +253,7 @@ void RTFInit(RTF_Info *info) info->nestingLevel = 0; info->canInheritInTbl = FALSE; info->borderType = 0; + info->pntext = NULL; memset(&info->fmt, 0, sizeof(info->fmt)); info->fmt.cbSize = sizeof(info->fmt); @@ -2498,13 +2500,42 @@ static void SpecialChar (RTF_Info *info) case rtfPage: case rtfSect: case rtfPar: + { + ME_Paragraph *para; RTFFlushOutputBuffer(info); + if ((info->fmt.dwMask & PFM_NUMBERING) && !info->pntext) + info->fmt.wNumbering = 0; + + if (info->pntext && info->pntext->nLen && + info->pntext->szData[info->pntext->nLen - 1] == '\t') + { + info->pntext->szData[--info->pntext->nLen] = 0; + if ((info->fmt.dwMask & PFM_NUMBERINGTAB) && + info->fmt.wNumberingTab == 0) + info->fmt.wNumberingTab = lDefaultTab; + } + editor_set_selection_para_fmt( info->editor, &info->fmt ); + para = info->editor->pCursors[0].para; memset(&info->fmt, 0, sizeof(info->fmt)); info->fmt.cbSize = sizeof(info->fmt); RTFPutUnicodeChar (info, '\r'); if (info->editor->bEmulateVersion10) RTFPutUnicodeChar (info, '\n'); + + if (info->pntext) + { + if (info->pntext->nLen && para->fmt.wNumbering) + { + para_num_clear( ¶->para_num ); + para->para_num.text = info->pntext; + info->pntext = NULL; + para_mark_rewrap( info->editor, para ); + } + ME_DestroyString( info->pntext ); + info->pntext = NULL; + } break; + } case rtfNoBrkSpace: RTFPutUnicodeChar (info, 0x00A0); break; diff --git a/dlls/riched20/rtf.h b/dlls/riched20/rtf.h index f2d446ac5d3..69deb28ea0c 100644 --- a/dlls/riched20/rtf.h +++ b/dlls/riched20/rtf.h @@ -1175,6 +1175,7 @@ struct _RTF_Info { int borderType; /* value corresponds to the RTFBorder constants. */ PARAFORMAT2 fmt; /* Accumulated para fmt for current paragraph. */ + ME_String *pntext; /* Explicit paragraph number text from \pntext destination. */ }; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10952