summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVasily Melenchuk <vasily.melenchuk@cib.de>2020-05-19 10:24:35 +0300
committerThorsten Behrens <Thorsten.Behrens@CIB.de>2020-06-17 11:19:35 +0200
commit7e605bc3ff0cfea76be4683f0170d821fcae7203 (patch)
tree2750d6daee2d016aaad49361dd700e9ad2751152
parente52263a8d3e61eae82b6345010162427fc5ed7ad (diff)
tdf#120394: doc import: use list format string
Since introducion of list level format string there is no need in complex parsing of doc level string and convering it to prefix-number-suffix format. We can just replace there special chars by %n placeholders (used in docx and now in LO) and this should be enough. Change-Id: I4e947939c4d4f393ee7e16c851cf22567d352ac3 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/94475 Tested-by: Jenkins Reviewed-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>
-rw-r--r--sw/qa/extras/ww8export/data/tdf120394.docbin0 -> 30208 bytes
-rw-r--r--sw/qa/extras/ww8export/ww8export3.cxx30
-rw-r--r--sw/source/filter/ww8/ww8par.hxx3
-rw-r--r--sw/source/filter/ww8/ww8par3.cxx157
4 files changed, 63 insertions, 127 deletions
diff --git a/sw/qa/extras/ww8export/data/tdf120394.doc b/sw/qa/extras/ww8export/data/tdf120394.doc
new file mode 100644
index 000000000000..2ee9058a59ef
--- /dev/null
+++ b/sw/qa/extras/ww8export/data/tdf120394.doc
Binary files differ
diff --git a/sw/qa/extras/ww8export/ww8export3.cxx b/sw/qa/extras/ww8export/ww8export3.cxx
index 96547e30133a..f998ffe1d85a 100644
--- a/sw/qa/extras/ww8export/ww8export3.cxx
+++ b/sw/qa/extras/ww8export/ww8export3.cxx
@@ -561,6 +561,36 @@ DECLARE_WW8EXPORT_TEST(testPresetDash, "tdf127166_prstDash_Word97.doc")
}
}
+DECLARE_WW8EXPORT_TEST(testTdf120394, "tdf120394.doc")
+{
+ CPPUNIT_ASSERT_EQUAL(1, getPages());
+ {
+ uno::Reference<beans::XPropertySet> xPara(getParagraph(1), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(2), getProperty<sal_Int16>(xPara, "NumberingLevel"));
+ CPPUNIT_ASSERT_EQUAL(OUString("1.1.1"), getProperty<OUString>(xPara, "ListLabelString"));
+ }
+ {
+ uno::Reference<beans::XPropertySet> xPara(getParagraph(5), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(0), getProperty<sal_Int16>(xPara, "NumberingLevel"));
+ CPPUNIT_ASSERT_EQUAL(OUString(CHAR_ZWSP), getProperty<OUString>(xPara, "ListLabelString"));
+ }
+ {
+ uno::Reference<beans::XPropertySet> xPara(getParagraph(8), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(2), getProperty<sal_Int16>(xPara, "NumberingLevel"));
+ CPPUNIT_ASSERT_EQUAL(OUString(CHAR_ZWSP), getProperty<OUString>(xPara, "ListLabelString"));
+ }
+ {
+ uno::Reference<beans::XPropertySet> xPara(getParagraph(9), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(2), getProperty<sal_Int16>(xPara, "NumberingLevel"));
+ CPPUNIT_ASSERT_EQUAL(OUString("1.1.2"), getProperty<OUString>(xPara, "ListLabelString"));
+ }
+ {
+ uno::Reference<beans::XPropertySet> xPara(getParagraph(10), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(2), getProperty<sal_Int16>(xPara, "NumberingLevel"));
+ CPPUNIT_ASSERT_EQUAL(OUString(CHAR_ZWSP), getProperty<OUString>(xPara, "ListLabelString"));
+ }
+}
+
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/ww8par.hxx b/sw/source/filter/ww8/ww8par.hxx
index 679c56a01ad5..810b692ee6aa 100644
--- a/sw/source/filter/ww8/ww8par.hxx
+++ b/sw/source/filter/ww8/ww8par.hxx
@@ -176,8 +176,7 @@ private:
//the rParaSprms returns back the original word paragraph indent
//sprms which are attached to this numbering level
bool ReadLVL(SwNumFormat& rNumFormat, std::unique_ptr<SfxItemSet>& rpItemSet, sal_uInt16 nLevelStyle,
- bool bSetStartNo, std::deque<bool> &rNotReallyThere, sal_uInt16 nLevel,
- ww::bytes &rParaSprms);
+ bool bSetStartNo, sal_uInt16 nLevel, ww::bytes &rParaSprms);
// character attributes from GrpprlChpx
typedef std::unique_ptr<SfxItemSet> WW8aISet[nMaxLevel];
diff --git a/sw/source/filter/ww8/ww8par3.cxx b/sw/source/filter/ww8/ww8par3.cxx
index d35adc6ca42e..02c02ecc459d 100644
--- a/sw/source/filter/ww8/ww8par3.cxx
+++ b/sw/source/filter/ww8/ww8par3.cxx
@@ -70,6 +70,7 @@
#include <unotools/fltrcfg.hxx>
#include <rtl/character.hxx>
#include <xmloff/odffields.hxx>
+#include <comphelper/string.hxx>
using namespace com::sun::star;
using namespace sw::util;
@@ -489,18 +490,6 @@ WW8LSTInfo* WW8ListManager::GetLSTByListId( sal_uInt32 nIdLst ) const
return aResult->get();
}
-static void lcl_CopyGreaterEight(OUString &rDest, OUString const &rSrc,
- sal_Int32 nStart, sal_Int32 nLen = SAL_MAX_INT32)
-{
- const sal_Int32 nMaxLen = std::min(rSrc.getLength(), nLen);
- for( sal_Int32 nI = nStart; nI < nMaxLen; ++nI)
- {
- sal_Unicode nChar = rSrc[nI];
- if (nChar > WW8ListManager::nMaxLevel)
- rDest += OUStringChar(nChar);
- }
-}
-
static OUString sanitizeString(const OUString& rString)
{
sal_Int32 i=0;
@@ -628,20 +617,15 @@ SvxNumType WW8ListManager::GetSvxNumTypeFromMSONFC(sal_uInt16 nNFC)
}
bool WW8ListManager::ReadLVL(SwNumFormat& rNumFormat, std::unique_ptr<SfxItemSet>& rpItemSet,
- sal_uInt16 nLevelStyle, bool bSetStartNo,
- std::deque<bool> &rNotReallyThere, sal_uInt16 nLevel,
- ww::bytes &rParaSprms)
+ sal_uInt16 nLevelStyle, bool bSetStartNo, sal_uInt16 /*nLevel*/, ww::bytes &rParaSprms)
{
sal_uInt8 aBits1(0);
- sal_uInt16 nStartNo(0); // Start-No. for Writer
SvxNumType nType(SVX_NUM_ARABIC);
SvxAdjust eAdj; // Alignment (Left/right/centered)
sal_Unicode cBullet(0x2190); // default safe bullet
sal_Unicode cGrfBulletCP(USHRT_MAX);
- OUString sPrefix;
- OUString sPostfix;
WW8LVL aLVL = {};
// 1. read LVLF
@@ -839,9 +823,6 @@ bool WW8ListManager::ReadLVL(SwNumFormat& rNumFormat, std::unique_ptr<SfxItemSet
// 5. convert read values into Writer syntax
- if( 0 <= aLVL.nStartAt )
- nStartNo = static_cast<sal_uInt16>(aLVL.nStartAt);
-
nType = GetSvxNumTypeFromMSONFC(aLVL.nNFC);
//For i120928,type info
if (bIsPicBullet)
@@ -849,68 +830,6 @@ bool WW8ListManager::ReadLVL(SwNumFormat& rNumFormat, std::unique_ptr<SfxItemSet
nType = SVX_NUM_BITMAP;
}
- //If a number level is not going to be used, then record this fact
- if (SVX_NUM_NUMBER_NONE == nType)
- rNotReallyThere[nLevel] = true;
-
- /*
- If a number level was not used (i.e. is in NotReallyThere), and that
- number level appears at one of the positions in the display string of the
- list, then it effectively is not there at all. So remove that level entry
- from a copy of the aOfsNumsXCH.
- */
- std::vector<sal_uInt8> aOfsNumsXCH;
- aOfsNumsXCH.reserve(nMaxLevel);
-
- for(sal_uInt8 nLevelB = 0; nLevelB < nMaxLevel; ++nLevelB)
- aOfsNumsXCH.push_back(aLVL.aOfsNumsXCH[nLevelB]);
-
- // nLevelB is an index in the aOfsNumsXCH array.
- for(sal_uInt16 nLevelB = 0; nLevelB <= nLevel; ++nLevelB)
- {
- // nPos is a one-based character offset to a level placeholder in
- // sNumString.
- sal_uInt8 nPos = aOfsNumsXCH[nLevelB];
- if (nPos && nPos < sNumString.getLength())
- {
- // nPosValue is the actual numbering level.
- sal_Unicode nPosValue = sNumString[nPos-1];
- if (nPosValue < nMaxLevel)
- {
- if (rNotReallyThere[nPosValue])
- aOfsNumsXCH[nLevelB] = 0;
- }
- }
- }
- auto aIter = std::remove(aOfsNumsXCH.begin(), aOfsNumsXCH.end(), 0);
- auto aEnd = aOfsNumsXCH.end();
- // #i60633# - suppress access on <aOfsNumsXCH.end()>
- if ( aIter != aEnd )
- {
- // Somehow the first removed vector element, at which <aIter>
- // points to, isn't reset to zero.
- // Investigation is needed to clarify why. It seems that only
- // special arrays are handled correctly by this code.
- ++aIter;
- while (aIter != aEnd)
- {
- (*aIter) = 0;
- ++aIter;
- }
- }
-
- sal_uInt8 nUpperLevel = 0; // current displaydepth for Writer
- for(sal_uInt8 nLevelB = 0; nLevelB < nMaxLevel; ++nLevelB)
- {
- if (!nUpperLevel && !aOfsNumsXCH[nLevelB])
- nUpperLevel = nLevelB;
- }
-
- // If the terminating char was not NULL, all indices of the list are
- // filled, so the levels have to be displayed.
- if (!nUpperLevel)
- nUpperLevel = nMaxLevel;
-
if (style::NumberingType::CHAR_SPECIAL == nType)
{
cBullet = !sNumString.isEmpty() ? sNumString[0] : 0x2190;
@@ -922,35 +841,6 @@ bool WW8ListManager::ReadLVL(SwNumFormat& rNumFormat, std::unique_ptr<SfxItemSet
{
cGrfBulletCP = nWitchPicIsBullet; // This is a bullet picture ID
}
- else
- {
- /*
- #i173#
- Our aOfsNumsXCH seems generally to be an array that contains the
- offset into sNumString of locations where the numbers should be
- filled in, so if the first "fill in a number" slot is greater than
- 1 there is a "prefix" before the number
- */
- //First number appears at
- sal_uInt8 nOneBasedFirstNoIndex = aOfsNumsXCH[0];
- const sal_Int32 nFirstNoIndex =
- nOneBasedFirstNoIndex > 0 ? nOneBasedFirstNoIndex -1 : SAL_MAX_INT32;
- lcl_CopyGreaterEight(sPrefix, sNumString, 0, nFirstNoIndex);
-
- //Next number appears at
- assert(nUpperLevel > 0);
- sal_uInt8 nOneBasedNextNoIndex = aOfsNumsXCH[nUpperLevel-1];
- const sal_Int32 nNextNoIndex =
- nOneBasedNextNoIndex > 0 ? nOneBasedNextNoIndex : SAL_MAX_INT32;
- if (sNumString.getLength() > nNextNoIndex)
- lcl_CopyGreaterEight(sPostfix, sNumString, nNextNoIndex);
-
- /*
- We use lcl_CopyGreaterEight because once if we have removed unused
- number indexes from the aOfsNumsXCH then placeholders remain in
- sNumString which must not be copied into the final numbering strings
- */
- }
switch( aLVL.nAlign )
{
@@ -976,8 +866,8 @@ bool WW8ListManager::ReadLVL(SwNumFormat& rNumFormat, std::unique_ptr<SfxItemSet
}
// 6. Configure NumFormat
- if( bSetStartNo )
- rNumFormat.SetStart( nStartNo );
+ if( bSetStartNo && 0 <= aLVL.nStartAt)
+ rNumFormat.SetStart(static_cast<sal_uInt16>(aLVL.nStartAt));
rNumFormat.SetNumberingType( nType );
rNumFormat.SetNumAdjust( eAdj );
@@ -995,12 +885,32 @@ bool WW8ListManager::ReadLVL(SwNumFormat& rNumFormat, std::unique_ptr<SfxItemSet
}
else
{
- // reminder: Garnix is default Prefix
- if( !sPrefix.isEmpty() )
- rNumFormat.SetPrefix( sPrefix );
- // reminder: Point is default Postfix
- rNumFormat.SetSuffix( sPostfix );
- rNumFormat.SetIncludeUpperLevels( nUpperLevel );
+ // Replace symbols at aOfsNumsXCH offsets to %1, %2 as supported by DOCX and LO
+ OUString sListFormat = sNumString;
+ if (sListFormat.getLength())
+ {
+ sal_uInt32 nExtraOffset = 0;
+ for (sal_uInt8 nLevelB = 0; nLevelB < nMaxLevel; ++nLevelB)
+ {
+ OUString sReplacement("%" + OUString::number(nLevelB + 1));
+ if (aLVL.aOfsNumsXCH[nLevelB])
+ {
+ if (aLVL.aOfsNumsXCH[nLevelB] <= sNumString.getLength())
+ sListFormat = sListFormat.replaceAt(aLVL.aOfsNumsXCH[nLevelB] + nExtraOffset - 1, 1, sReplacement);
+ else
+ SAL_WARN("sw.ww8", "List level reference is beyond the border. Ignored.");
+ }
+ // We need also update an offset, since we are replacing one symbol by at least two
+ nExtraOffset += sReplacement.getLength() - 1;
+ }
+ }
+
+ rNumFormat.SetListFormat(sListFormat);
+
+ // Total count of replacement holders is determining amount of required parent numbering to include
+ // TODO: not sure how "%" symbol is escaped. This is not supported yet
+ sal_Int16 nParentNum = comphelper::string::getTokenCount(sListFormat, '%');
+ rNumFormat.SetIncludeUpperLevels(nParentNum);
}
// #i89181#
@@ -1298,15 +1208,13 @@ WW8ListManager::WW8ListManager(SvStream& rSt_, SwWW8ImplReader& rReader_)
// 1.2.1 read specific LVL(s) for this aLST
sal_uInt16 nLvlCount = static_cast< sal_uInt16 >(pListInfo->bSimpleList ? nMinLevel : nMaxLevel);
- std::deque<bool> aNotReallyThere;
- aNotReallyThere.resize(nMaxLevel);
pListInfo->maParaSprms.resize(nMaxLevel);
for (sal_uInt16 nLevel = 0; nLevel < nLvlCount; ++nLevel)
{
SwNumFormat aNumFormat( rMyNumRule.Get( nLevel ) );
// read LVLF
bLVLOk = ReadLVL( aNumFormat, aItemSet[nLevel],
- pListInfo->aIdSty[nLevel], true, aNotReallyThere, nLevel,
+ pListInfo->aIdSty[nLevel], true, nLevel,
pListInfo->maParaSprms[nLevel]);
if( !bLVLOk )
break;
@@ -1449,7 +1357,6 @@ WW8ListManager::WW8ListManager(SvStream& rSt_, SwWW8ImplReader& rReader_)
while (nTest == 0xFFFFFFFF);
rSt.SeekRel(-4);
- std::deque<bool> aNotReallyThere(WW8ListManager::nMaxLevel);
for (sal_uInt8 nLevel = 0; nLevel < rLFOInfo.nLfoLvl; ++nLevel)
{
WW8LFOLVL aLFOLVL;
@@ -1487,7 +1394,7 @@ WW8ListManager::WW8ListManager(SvStream& rSt_, SwWW8ImplReader& rReader_)
bLVLOk = nLevel < rLFOInfo.maParaSprms.size() &&
ReadLVL(aNumFormat, aItemSet[nLevel],
pParentListInfo->aIdSty[nLevel],
- aLFOLVL.bStartAt, aNotReallyThere, nLevel,
+ aLFOLVL.bStartAt, nLevel,
rLFOInfo.maParaSprms[nLevel]);
if (!bLVLOk)