sw/qa/extras/rtfexport/data/tdf116358.rtf      |  116 +++++++++++++++++++++++++
 sw/qa/extras/rtfexport/rtfexport4.cxx          |   30 ++++++
 sw/rtfexport_setup.mk                          |    1 
 tools/CppunitTest_tools_test.mk                |    1 
 tools/qa/cppunit/test_Wildcard.cxx             |   46 +++++++++
 tools/source/fsys/wldcrd.cxx                   |   77 +++++++++-------
 writerfilter/source/dmapper/SettingsTable.cxx  |    6 -
 writerfilter/source/filter/WriterFilter.cxx    |    1 
 writerfilter/source/rtftok/rtfdispatchflag.cxx |    3 
 9 files changed, 241 insertions(+), 40 deletions(-)

New commits:
commit 8bbe35a88da6c7f1803cb99783bea4be074c7635
Author:     Vasily Melenchuk <vasily.melenc...@cib.de>
AuthorDate: Wed Mar 30 13:09:19 2022 +0300
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Wed Apr 6 13:28:32 2022 +0200

    tdf#116358: rtf import: "keep with next" also affects table rows
    
    Like in DOCX for RTF there is exactly same behavior for paragraphs
    inside cells. They do affect table breaking over the pages.
    
    So:
    1) Enable "TableRowKeep" doc setting for RTF documents.
    2) Do not ignore \keepn token for paragraphs in tables.
    
    Change-Id: I11e45ca9114c792b8cdbeb77dd51359717129651
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132305
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132355

diff --git a/sw/qa/extras/rtfexport/data/tdf116358.rtf 
b/sw/qa/extras/rtfexport/data/tdf116358.rtf
new file mode 100644
index 000000000000..09a9b3f8ead8
--- /dev/null
+++ b/sw/qa/extras/rtfexport/data/tdf116358.rtf
@@ -0,0 +1,116 @@
+{\rtf1\ansi\deff3\adeflang1025
+{\fonttbl{\f0\froman\fprq2\fcharset0 Times New 
Roman;}{\f1\froman\fprq2\fcharset2 Symbol;}{\f2\fswiss\fprq2\fcharset0 
Arial;}{\f3\froman\fprq2\fcharset204 Liberation Serif{\*\falt Times New 
Roman};}{\f4\froman\fprq2\fcharset204 Times New 
Roman;}{\f5\froman\fprq2\fcharset204 Liberation Sans{\*\falt 
Arial};}{\f6\fnil\fprq2\fcharset204 Microsoft 
YaHei;}{\f7\fnil\fprq2\fcharset204 0;}{\f8\fnil\fprq2\fcharset204 Times New 
Roman;}{\f9\fnil\fprq2\fcharset204 Lucida Sans;}}
+{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}
+{\stylesheet{\s0\snext0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052
 Normal;}
+{\s15\sbasedon0\snext16\rtlch\af9\afs28\alang1081 
\ltrch\lang2057\langfe2052\hich\af5\loch\ql\widctlpar\hyphpar0\sb240\sa120\keepn\ltrpar\cf0\f5\fs28\lang2057\kerning1\dbch\af6\langfe2052
 Heading;}
+{\s16\sbasedon0\snext16\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\sl276\slmult1\ql\widctlpar\hyphpar0\sb0\sa140\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052
 Text Body;}
+{\s17\sbasedon16\snext17\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\sl276\slmult1\ql\widctlpar\hyphpar0\sb0\sa140\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052
 List;}
+{\s18\sbasedon0\snext18\rtlch\af9\afs24\alang1081\ai 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\sb120\sa120\ltrpar\cf0\f3\fs24\lang2057\i\kerning1\dbch\af7\langfe2052
 Caption;}
+{\s19\sbasedon0\snext19\rtlch\af9\afs24\alang255 
\ltrch\lang255\langfe255\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang255\kerning1\dbch\af7\langfe255
 Index;}
+{\s20\sbasedon0\snext20\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\nowidctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052
 Table Contents;}
+}{\*\generator LibreOfficeDev/7.4.0.0.alpha0$Windows_X86_64 
LibreOffice_project/1e1cab9d5a0728c13209aeed95b6802175799a0a}{\info{\creatim\yr2022\mo3\dy30\hr9\min3}{\revtim\yr2022\mo3\dy30\hr9\min11}{\printim\yr0\mo0\dy0\hr0\min0}}{\*\userprops}\deftab709
+\hyphauto1\viewscale100
+{\*\pgdsctbl
+{\pgdsc0\pgdscuse451\pgwsxn11906\pghsxn16838\marglsxn1134\margrsxn1134\margtsxn1134\margbsxn1134\pgdscnxt0
 Default Page Style;}}
+\formshade\paperh16838\paperw11906\margl1134\margr1134\margt1134\margb1134\sectd\sbknone\pgndec\sftnnar\saftnnrlc\sectunlocked1\pgwsxn11906\pghsxn16838\marglsxn1134\margrsxn1134\margtsxn1134\margbsxn1134\ftnbj\ftnstart1\ftnrstcont\ftnnar\aenddoc\aftnrstcont\aftnstart1\aftnnrlc
+{\*\ftnsep\chftnsep}\pgndec\pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052{\loch
+A}
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par \pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch
+
+\par 
\trowd\trql\trleft-15\ltrrow\trpaddft3\trpaddt0\trpaddfl3\trpaddl0\trpaddfb3\trpaddb0\trpaddfr3\trpaddr0\clbrdrt\brdrs\brdrw10\brdrcf1\clpadfl3\clpadl55\clbrdrl\brdrs\brdrw10\brdrcf1\clpadft3\clpadt55\clbrdrb\brdrs\brdrw10\brdrcf1\clpadfb3\clpadb55\clbrdrr\brdrs\brdrw10\brdrcf1\clpadfr3\clpadr55\cellx9623\pard\plain
 \s20\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\nowidctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch\keepn\intbl\nowidctlpar\rtlch\af8\afs24
 \ltrch\hich\af4\loch\cf1\fs24\f4\dbch\af8\loch
+\cell\row\pard\trowd\trql\trleft-15\ltrrow\trpaddft3\trpaddt0\trpaddfl3\trpaddl0\trpaddfb3\trpaddb0\trpaddfr3\trpaddr0\clpadfl3\clpadl55\clbrdrl\brdrs\brdrw10\brdrcf1\clpadft3\clpadt55\clbrdrb\brdrs\brdrw10\brdrcf1\clpadfb3\clpadb55\clbrdrr\brdrs\brdrw10\brdrcf1\clpadfr3\clpadr55\cellx9623\pard\plain
 \s20\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\nowidctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch\keepn\intbl\nowidctlpar\rtlch\af8\afs24
 \ltrch\hich\af4\loch\cf1\fs24\f4\dbch\af8\loch
+\cell\row\pard\pard\plain \s0\rtlch\af9\afs24\alang1081 
\ltrch\lang2057\langfe2052\hich\af3\loch\ql\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang2057\kerning1\dbch\af7\langfe2052\loch\nowidctlpar{\loch
+b}
+\par }
\ No newline at end of file
diff --git a/sw/qa/extras/rtfexport/rtfexport4.cxx 
b/sw/qa/extras/rtfexport/rtfexport4.cxx
index e487c2c7213d..7edad225267d 100644
--- a/sw/qa/extras/rtfexport/rtfexport4.cxx
+++ b/sw/qa/extras/rtfexport/rtfexport4.cxx
@@ -26,6 +26,7 @@
 #include <fmtanchr.hxx>
 #include <frameformats.hxx>
 #include <formatlinebreak.hxx>
+#include <wrtsh.hxx>
 
 using namespace css;
 
@@ -403,6 +404,35 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf126309)
         
static_cast<style::ParagraphAdjust>(getProperty<sal_Int16>(getParagraph(1), 
"ParaAdjust")));
 }
 
+DECLARE_RTFEXPORT_TEST(testTdf116358, "tdf116358.rtf")
+{
+    SwXTextDocument* pTextDoc = 
dynamic_cast<SwXTextDocument*>(mxComponent.get());
+    CPPUNIT_ASSERT(pTextDoc);
+    SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell();
+    CPPUNIT_ASSERT(pWrtShell);
+
+    // Insert a paragraph break
+    pWrtShell->SplitNode(false);
+
+    // Entire table should go to page 2, no remains on first page
+    xmlDocUniquePtr pDump = parseLayoutDump();
+    {
+        xmlXPathObjectPtr pXmlObj = getXPathNode(pDump, 
"/root/page[1]/body/tab");
+        xmlNodeSetPtr pXmlNodes = pXmlObj->nodesetval;
+        sal_Int32 tablesOnPage = xmlXPathNodeSetGetLength(pXmlNodes);
+        xmlXPathFreeObject(pXmlObj);
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(0), tablesOnPage);
+    }
+
+    {
+        xmlXPathObjectPtr pXmlObj = getXPathNode(pDump, 
"/root/page[2]/body/tab");
+        xmlNodeSetPtr pXmlNodes = pXmlObj->nodesetval;
+        sal_Int32 tablesOnPage = xmlXPathNodeSetGetLength(pXmlNodes);
+        xmlXPathFreeObject(pXmlObj);
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(1), tablesOnPage);
+    }
+}
+
 CPPUNIT_TEST_FIXTURE(Test, testGutterLeft)
 {
     load(mpTestDocumentPath, "gutter-left.rtf");
diff --git a/sw/rtfexport_setup.mk b/sw/rtfexport_setup.mk
index 40bbfb62321a..3ea61755d467 100644
--- a/sw/rtfexport_setup.mk
+++ b/sw/rtfexport_setup.mk
@@ -45,6 +45,7 @@ $(eval $(call gb_CppunitTest_use_externals,sw_rtfexport$(1),\
 $(eval $(call gb_CppunitTest_set_include,sw_rtfexport$(1),\
     -I$(SRCDIR)/sw/inc \
     -I$(SRCDIR)/sw/source/core/inc \
+    -I$(SRCDIR)/sw/source/uibase/inc \
     -I$(SRCDIR)/sw/qa/inc \
     $$(INCLUDE) \
 ))
diff --git a/writerfilter/source/dmapper/SettingsTable.cxx 
b/writerfilter/source/dmapper/SettingsTable.cxx
index 732b96ff96db..3e6afe7b5fa1 100644
--- a/writerfilter/source/dmapper/SettingsTable.cxx
+++ b/writerfilter/source/dmapper/SettingsTable.cxx
@@ -539,11 +539,13 @@ static bool lcl_isDefault(const 
uno::Reference<beans::XPropertyState>& xProperty
 void SettingsTable::ApplyProperties(uno::Reference<text::XTextDocument> const& 
xDoc)
 {
     uno::Reference< beans::XPropertySet> xDocProps( xDoc, uno::UNO_QUERY );
+    uno::Reference<lang::XMultiServiceFactory> xTextFactory(xDoc, 
uno::UNO_QUERY_THROW);
+    uno::Reference<beans::XPropertySet> 
xDocumentSettings(xTextFactory->createInstance("com.sun.star.document.Settings"),
 uno::UNO_QUERY_THROW);
+
+    xDocumentSettings->setPropertyValue("TableRowKeep", uno::makeAny(true));
 
     if (GetWordCompatibilityMode() <= 14)
     {
-        uno::Reference<lang::XMultiServiceFactory> xTextFactory(xDoc, 
uno::UNO_QUERY_THROW);
-        uno::Reference<beans::XPropertySet> 
xDocumentSettings(xTextFactory->createInstance("com.sun.star.document.Settings"),
 uno::UNO_QUERY_THROW);
         xDocumentSettings->setPropertyValue("MsWordCompMinLineHeightByFly", 
uno::makeAny(true));
         xDocumentSettings->setPropertyValue("TabOverMargin", 
uno::makeAny(true));
     }
diff --git a/writerfilter/source/filter/WriterFilter.cxx 
b/writerfilter/source/filter/WriterFilter.cxx
index f62dff1fe19a..945a00f95258 100644
--- a/writerfilter/source/filter/WriterFilter.cxx
+++ b/writerfilter/source/filter/WriterFilter.cxx
@@ -314,7 +314,6 @@ void WriterFilter::setTargetDocument(const 
uno::Reference<lang::XComponent>& xDo
     xSettings->setPropertyValue("UseFormerObjectPositioning", 
uno::makeAny(false));
     xSettings->setPropertyValue("ConsiderTextWrapOnObjPos", 
uno::makeAny(true));
     xSettings->setPropertyValue("UseFormerTextWrapping", uno::makeAny(false));
-    xSettings->setPropertyValue("TableRowKeep", uno::makeAny(true));
     xSettings->setPropertyValue("IgnoreTabsAndBlanksForLineCalculation", 
uno::makeAny(true));
     xSettings->setPropertyValue("InvertBorderSpacing", uno::makeAny(true));
     xSettings->setPropertyValue("CollapseEmptyCellPara", uno::makeAny(true));
diff --git a/writerfilter/source/rtftok/rtfdispatchflag.cxx 
b/writerfilter/source/rtftok/rtfdispatchflag.cxx
index 83c5a0966259..3aee1e1dda75 100644
--- a/writerfilter/source/rtftok/rtfdispatchflag.cxx
+++ b/writerfilter/source/rtftok/rtfdispatchflag.cxx
@@ -421,8 +421,7 @@ RTFError RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword)
                 nParam = NS_ooxml::LN_CT_PPrBase_keepLines;
             break;
         case RTFKeyword::KEEPN:
-            if (m_aStates.top().getCurrentBuffer() != 
&m_aTableBufferStack.back())
-                nParam = NS_ooxml::LN_CT_PPrBase_keepNext;
+            nParam = NS_ooxml::LN_CT_PPrBase_keepNext;
             break;
         case RTFKeyword::INTBL:
         {
commit 1d116089e32f2ac0d95e1d78d292f4f272f978dd
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Wed Mar 30 22:41:49 2022 +0300
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Wed Apr 6 13:27:43 2022 +0200

    tdf#148253: fix matching algorithm
    
    Using 'flag' as a "continue the loop" marker allowed to continue
    processing wildcard after its last character - not crashing because
    it was a subview of a larger string with separators, but failing
    the match.
    
    Change-Id: I308058b68c59d5719f3c8b5f5656998a95a9ba09
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132336
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    (cherry picked from commit 50add7c97e75d604287218f49c9283aab052fdf0)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132374
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/tools/CppunitTest_tools_test.mk b/tools/CppunitTest_tools_test.mk
index 096b3ddb1835..be47c09ab191 100644
--- a/tools/CppunitTest_tools_test.mk
+++ b/tools/CppunitTest_tools_test.mk
@@ -37,6 +37,7 @@ $(eval $(call 
gb_CppunitTest_add_exception_objects,tools_test, \
     tools/qa/cppunit/test_cpu_runtime_detection_AVX2 \
     tools/qa/cppunit/test_cpu_runtime_detection_SSE2 \
     tools/qa/cppunit/test_cpu_runtime_detection_SSSE3 \
+    tools/qa/cppunit/test_Wildcard \
 ))
 
 $(eval $(call gb_CppunitTest_add_exception_objects,tools_test,\
diff --git a/tools/qa/cppunit/test_Wildcard.cxx 
b/tools/qa/cppunit/test_Wildcard.cxx
new file mode 100644
index 000000000000..1760ca6932db
--- /dev/null
+++ b/tools/qa/cppunit/test_Wildcard.cxx
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <sal/types.h>
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <tools/wldcrd.hxx>
+
+namespace
+{
+class Test : public CppUnit::TestFixture
+{
+public:
+    void test_Wildcard();
+
+    CPPUNIT_TEST_SUITE(Test);
+    CPPUNIT_TEST(test_Wildcard);
+    CPPUNIT_TEST_SUITE_END();
+};
+
+void Test::test_Wildcard()
+{
+    WildCard wildcard(u"*.html;*??a;*\\*abc;*\\?xyz", ';'); // tdf#148253
+    CPPUNIT_ASSERT(wildcard.Matches(u"foo.html"));
+    CPPUNIT_ASSERT(wildcard.Matches(u"foo.ht.html")); // test stepping back 
after partial match
+    CPPUNIT_ASSERT(wildcard.Matches(u"foo.html.html")); // test stepping back 
after full match
+    CPPUNIT_ASSERT(wildcard.Matches(u"??aa")); // test stepping back with 
question marks
+    CPPUNIT_ASSERT(wildcard.Matches(u"111*abc")); // test escaped asterisk
+    CPPUNIT_ASSERT(!wildcard.Matches(u"111-abc")); // test escaped asterisk
+    CPPUNIT_ASSERT(wildcard.Matches(u"111?xyz")); // test escaped question mark
+    CPPUNIT_ASSERT(!wildcard.Matches(u"111-xyz")); // test escaped question 
mark
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Test);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/tools/source/fsys/wldcrd.cxx b/tools/source/fsys/wldcrd.cxx
index a9867c00ba51..e8769a00e047 100644
--- a/tools/source/fsys/wldcrd.cxx
+++ b/tools/source/fsys/wldcrd.cxx
@@ -27,67 +27,74 @@
  */
 bool WildCard::ImpMatch( std::u16string_view aWild, std::u16string_view aStr )
 {
-    int    pos=0;
-    int    flag=0;
+    const sal_Unicode* pPosAfterAsterisk = nullptr;
     const sal_Unicode* pWild = aWild.data();
     const sal_Unicode* pWildEnd = aWild.data() + aWild.size();
     const sal_Unicode* pStr = aStr.data();
     const sal_Unicode* pStrEnd = aStr.data() + aStr.size();
 
-    while ( pWild != pWildEnd || flag )
+    while (pWild != pWildEnd)
     {
         switch (*pWild)
         {
             case '?':
                 if ( pStr == pStrEnd )
                     return false;
-                break;
-
-            default:
-                if ( (*pWild == '\\') && (pWild + 1 != pWildEnd) && 
((*(pWild+1)=='?') || (*(pWild+1) == '*')) )
+                break; // Match -> proceed to the next character
+            case '\\': // Escaping '?' and '*'; don't we need to escape '\\'?
+                if ((pWild + 1 != pWildEnd) && ((*(pWild + 1) == '?') || 
(*(pWild + 1) == '*')))
                     pWild++;
-                if ( *pWild != *pStr )
-                    if ( !pos )
-                        return false;
-                    else
-                        pWild += pos;
-                else
-                    break;
-                // WARNING/TODO: may cause execution of next case in some
-                // circumstances!
+                [[fallthrough]];
+            default: // No wildcard, literal match
+                if (pStr == pStrEnd)
+                    return false;
+                if (*pWild == *pStr)
+                    break; // Match -> proceed to the next character
+                if (!pPosAfterAsterisk)
+                    return false;
+                pWild = pPosAfterAsterisk;
                 [[fallthrough]];
             case '*':
                 while ( pWild != pWildEnd && *pWild == '*' )
                     pWild++;
                 if ( pWild == pWildEnd )
                     return true;
-                flag = 1;
-                pos  = 0;
+                // Consider strange things like "**?*?*"
+                while (*pWild == '?')
+                {
+                    if (pStr == pStrEnd)
+                        return false;
+                    pWild++;
+                    pStr++;
+                    while (pWild != pWildEnd && *pWild == '*')
+                        pWild++;
+                    if (pWild == pWildEnd)
+                        return true;
+                }
+                // At this point, we are past wildcards, and a literal match 
must follow
                 if ( pStr == pStrEnd )
                     return false;
-                while ( pStr != pStrEnd && *pStr != *pWild )
+                pPosAfterAsterisk = pWild;
+                if ((*pWild == '\\') && (pWild + 1 != pWildEnd) && ((*(pWild + 
1) == '?') || (*(pWild + 1) == '*')))
+                    pWild++;
+                while (*pStr != *pWild)
                 {
-                    if ( *pWild == '?' ) {
-                        pWild++;
-                        while ( pWild != pWildEnd && *pWild == '*' )
-                            pWild++;
-                    }
                     pStr++;
                     if ( pStr == pStrEnd )
-                        return pWild == pWildEnd;
+                        return false;
                 }
-                break;
+                break; // Match -> proceed to the next character
         }
-        if ( pWild != pWildEnd )
-            pWild++;
-        if ( pStr != pStrEnd )
-            pStr++;
-        else
-            flag = 0;
-        if ( flag )
-            pos--;
+        // We arrive here when the current characters in pWild and pStr match
+        assert(pWild != pWildEnd);
+        pWild++;
+        assert(pStr != pStrEnd);
+        pStr++;
+        if (pWild == pWildEnd && pPosAfterAsterisk && pStr != pStrEnd)
+            pWild = pPosAfterAsterisk; // Try again on the rest of pStr
     }
-    return ( pStr == pStrEnd ) && ( pWild == pWildEnd );
+    assert(pWild == pWildEnd);
+    return pStr == pStrEnd;
 }
 
 bool WildCard::Matches( std::u16string_view rString ) const

Reply via email to