summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVasily Melenchuk <vasily.melenchuk@cib.de>2020-04-13 11:06:29 +0300
committerThorsten Behrens <Thorsten.Behrens@CIB.de>2020-05-05 22:22:37 +0200
commit10e99b6ad18a8575351e1a9a6b129b6a6e1f0586 (patch)
treeea0c3b4d6528911535c7339fb921810272ecf1b8
parent76beaebdb4e45149576e3946895d77bd3054fe50 (diff)
tdf#116883: sw: support for lists level format string
Multilevel lists are more flexible in case of DOCX. There is supported custom format for any level in DOCX unlike in LO and ODT where we are limited only with prefix and suffix for hardcoded list levels separated by dot. At the same time DOCX can have lists not only "1.2.3.4", but "1/2/3/4" or even "1!2>3)4" and such format can vary on each list level. Here is basic implementation for list format as a core feature for all documents and old way (prefix-suffix + ".") is left as fallback. Practically its usage is currently implemented only in DOCX import/export. Some RTF/OOXML unittests were redesigned: since we are not creating prefix/suffix for these formats conditions should be checked in a different way. Change-Id: I1ec58bcc5874d4fa19aee6a1f42bf1671d853b14 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/92106 Tested-by: Jenkins Reviewed-by: Thorsten Behrens <Thorsten.Behrens@CIB.de> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/93125 Tested-by: Jenkins Reviewed-by: Thorsten Behrens <Thorsten.Behrens@CIB.de> Change-Id: Ia8f066913a2565559d81f3caabeba24b29c09052 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/93456
-rw-r--r--editeng/source/items/numitem.cxx8
-rw-r--r--include/editeng/numitem.hxx3
-rw-r--r--sw/inc/unoprnms.hxx1
-rw-r--r--sw/qa/extras/ooxmlexport/data/tdf116883.docxbin0 -> 10422 bytes
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport.cxx5
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport10.cxx22
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport12.cxx44
-rw-r--r--sw/qa/extras/rtfexport/rtfexport.cxx8
-rw-r--r--sw/qa/extras/rtfimport/rtfimport.cxx156
-rw-r--r--sw/source/core/doc/number.cxx116
-rw-r--r--sw/source/core/unocore/unosett.cxx15
-rw-r--r--sw/source/filter/ww8/wrtw8num.cxx8
-rw-r--r--writerfilter/source/dmapper/NumberingManager.cxx73
-rw-r--r--writerfilter/source/dmapper/NumberingManager.hxx5
-rw-r--r--writerfilter/source/dmapper/PropertyIds.cxx1
-rw-r--r--writerfilter/source/dmapper/PropertyIds.hxx1
16 files changed, 235 insertions, 231 deletions
diff --git a/editeng/source/items/numitem.cxx b/editeng/source/items/numitem.cxx
index 67cf0373cc37..6182ec5189b1 100644
--- a/editeng/source/items/numitem.cxx
+++ b/editeng/source/items/numitem.cxx
@@ -344,9 +344,10 @@ SvxNumberFormat& SvxNumberFormat::operator=( const SvxNumberFormat& rFormat )
mnListtabPos = rFormat.mnListtabPos;
mnFirstLineIndent = rFormat.mnFirstLineIndent;
mnIndentAt = rFormat.mnIndentAt;
- eVertOrient = rFormat.eVertOrient ;
- sPrefix = rFormat.sPrefix ;
- sSuffix = rFormat.sSuffix ;
+ eVertOrient = rFormat.eVertOrient;
+ sPrefix = rFormat.sPrefix;
+ sSuffix = rFormat.sSuffix;
+ sListFormat = rFormat.sListFormat;
aGraphicSize = rFormat.aGraphicSize ;
nBulletColor = rFormat.nBulletColor ;
nBulletRelSize = rFormat.nBulletRelSize;
@@ -381,6 +382,7 @@ bool SvxNumberFormat::operator==( const SvxNumberFormat& rFormat) const
eVertOrient != rFormat.eVertOrient ||
sPrefix != rFormat.sPrefix ||
sSuffix != rFormat.sSuffix ||
+ sListFormat != rFormat.sListFormat ||
aGraphicSize != rFormat.aGraphicSize ||
nBulletColor != rFormat.nBulletColor ||
nBulletRelSize != rFormat.nBulletRelSize ||
diff --git a/include/editeng/numitem.hxx b/include/editeng/numitem.hxx
index 699f82928069..52cb14858c1f 100644
--- a/include/editeng/numitem.hxx
+++ b/include/editeng/numitem.hxx
@@ -102,6 +102,7 @@ public:
private:
OUString sPrefix;
OUString sSuffix;
+ OUString sListFormat; // Format string ">%1.%2<" can be used instead of prefix/suffix
SvxAdjust eNumAdjust;
@@ -166,6 +167,8 @@ public:
const OUString& GetPrefix() const { return sPrefix;}
void SetSuffix(const OUString& rSet) { sSuffix = rSet;}
const OUString& GetSuffix() const { return sSuffix;}
+ void SetListFormat(const OUString& rSet) { sListFormat = rSet; }
+ const OUString& GetListFormat() const { return sListFormat; }
void SetCharFormatName(const OUString& rSet){ sCharStyleName = rSet; }
virtual OUString GetCharFormatName()const;
diff --git a/sw/inc/unoprnms.hxx b/sw/inc/unoprnms.hxx
index d324be62bf0a..91780b6530bd 100644
--- a/sw/inc/unoprnms.hxx
+++ b/sw/inc/unoprnms.hxx
@@ -77,6 +77,7 @@
#define UNO_NAME_ANCHOR_CHAR_STYLE_NAME "AnchorCharStyleName"
#define UNO_NAME_SUFFIX "Suffix"
#define UNO_NAME_PREFIX "Prefix"
+#define UNO_NAME_LIST_FORMAT "ListFormat"
#define UNO_NAME_PARENT_NUMBERING "ParentNumbering"
#define UNO_NAME_CHAR_FONT_NAME "CharFontName"
#define UNO_NAME_CHAR_FONT_STYLE_NAME "CharFontStyleName"
diff --git a/sw/qa/extras/ooxmlexport/data/tdf116883.docx b/sw/qa/extras/ooxmlexport/data/tdf116883.docx
new file mode 100644
index 000000000000..52a9c42218fa
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/tdf116883.docx
Binary files differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
index e144e6178129..d4a453a27580 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
@@ -780,7 +780,10 @@ DECLARE_OOXMLEXPORT_TEST(testNumOverrideLvltext, "num-override-lvltext.docx")
{
uno::Reference<container::XIndexAccess> xRules = getProperty< uno::Reference<container::XIndexAccess> >(getStyles("NumberingStyles")->getByName("WWNum1"), "NumberingRules");
// This was 1, i.e. the numbering on the second level was "1", not "1.1".
- CPPUNIT_ASSERT_EQUAL(sal_Int16(2), comphelper::SequenceAsHashMap(xRules->getByIndex(1))["ParentNumbering"].get<sal_Int16>());
+ // Check the praragraph properties, not the list ones, since they can differ due to overrides
+ uno::Reference<beans::XPropertySet> xPara(getParagraph(1), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(1), getProperty<sal_Int16>(xPara, "NumberingLevel"));
+ CPPUNIT_ASSERT_EQUAL(OUString("1.1"), getProperty<OUString>(xPara, "ListLabelString"));
// The paragraph marker's red font color was inherited by the number portion, this was ff0000.
CPPUNIT_ASSERT_EQUAL(OUString("ffffffff"), parseDump("//Special[@nType='PortionType::Number']/SwFont", "color"));
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx
index 835947da9dfb..92d7d63aa80d 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx
@@ -853,25 +853,11 @@ DECLARE_OOXMLEXPORT_TEST(testTdf65955_2, "tdf65955_2.odt")
DECLARE_OOXMLEXPORT_TEST(testChtOutlineNumberingOoxml, "chtoutline.docx")
{
- const sal_Unicode aExpectedPrefix[2] = { 0x7b2c, 0x0020 };
- const sal_Unicode aExpectedSuffix[2] = { 0x0020, 0x7ae0 };
- uno::Reference< text::XChapterNumberingSupplier > xChapterNumberingSupplier(mxComponent, uno::UNO_QUERY);
- uno::Reference< container::XIndexAccess> xLevels(xChapterNumberingSupplier->getChapterNumberingRules());
- uno::Sequence<beans::PropertyValue> aProps;
- xLevels->getByIndex(0) >>= aProps; // 1st level
-
- OUString aSuffix,aPrefix;
- for (int i = 0; i < aProps.getLength(); ++i)
- {
- const beans::PropertyValue& rProp = aProps[i];
+ const sal_Unicode aExpectedNumbering[] = { 0x7b2c, ' ', '1', ' ', 0x7ae0 };
- if (rProp.Name == "Suffix")
- aSuffix = rProp.Value.get<OUString>();
- if (rProp.Name == "Prefix")
- aPrefix = rProp.Value.get<OUString>();
- }
- CPPUNIT_ASSERT_EQUAL(OUString(aExpectedPrefix,SAL_N_ELEMENTS(aExpectedPrefix)), aPrefix);
- CPPUNIT_ASSERT_EQUAL(OUString(aExpectedSuffix,SAL_N_ELEMENTS(aExpectedSuffix)), aSuffix);
+ uno::Reference<beans::XPropertySet> xPara(getParagraph(1), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString(aExpectedNumbering,SAL_N_ELEMENTS(aExpectedNumbering)),
+ getProperty<OUString>(xPara, "ListLabelString"));
}
DECLARE_OOXMLEXPORT_TEST(mathtype, "mathtype.docx")
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx
index 908faf14e22a..f51804eebd1c 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx
@@ -995,6 +995,50 @@ DECLARE_OOXMLEXPORT_TEST(testTdf122594, "tdf122594.docx")
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(3), nCheck);
}
+DECLARE_OOXMLEXPORT_TEST(testTdf116883, "tdf116883.docx")
+{
+ {
+ uno::Reference<beans::XPropertySet> xPara(getParagraph(1), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("1>1>"), getProperty<OUString>(xPara, "ListLabelString"));
+ }
+ {
+ uno::Reference<beans::XPropertySet> xPara(getParagraph(2), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("1>2>"), getProperty<OUString>(xPara, "ListLabelString"));
+ }
+ {
+ uno::Reference<beans::XPropertySet> xPara(getParagraph(3), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("1>2>1>1>"), getProperty<OUString>(xPara, "ListLabelString"));
+ }
+ {
+ uno::Reference<beans::XPropertySet> xPara(getParagraph(4), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("1>2>2>"), getProperty<OUString>(xPara, "ListLabelString"));
+ }
+ {
+ uno::Reference<beans::XPropertySet> xPara(getParagraph(5), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("1>2>3>"), getProperty<OUString>(xPara, "ListLabelString"));
+ }
+ {
+ uno::Reference<beans::XPropertySet> xPara(getParagraph(6), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("1>1)"), getProperty<OUString>(xPara, "ListLabelString"));
+ }
+ {
+ uno::Reference<beans::XPropertySet> xPara(getParagraph(7), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("1>2)"), getProperty<OUString>(xPara, "ListLabelString"));
+ }
+ {
+ uno::Reference<beans::XPropertySet> xPara(getParagraph(8), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("1>2>1<1)"), getProperty<OUString>(xPara, "ListLabelString"));
+ }
+ {
+ uno::Reference<beans::XPropertySet> xPara(getParagraph(9), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("1>2.2)"), getProperty<OUString>(xPara, "ListLabelString"));
+ }
+ {
+ uno::Reference<beans::XPropertySet> xPara(getParagraph(10), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString("1>2.3)"), getProperty<OUString>(xPara, "ListLabelString"));
+ }
+}
+
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/extras/rtfexport/rtfexport.cxx b/sw/qa/extras/rtfexport/rtfexport.cxx
index cf2cb780bb12..535374da8863 100644
--- a/sw/qa/extras/rtfexport/rtfexport.cxx
+++ b/sw/qa/extras/rtfexport/rtfexport.cxx
@@ -659,16 +659,16 @@ DECLARE_RTFEXPORT_TEST(testFdo66682, "fdo66682.rtf")
uno::Sequence<beans::PropertyValue> aProps;
xLevels->getByIndex(0) >>= aProps; // 1st level
- OUString aSuffix;
+ OUString aListFormat;
for (int i = 0; i < aProps.getLength(); ++i)
{
const beans::PropertyValue& rProp = aProps[i];
- if (rProp.Name == "Suffix")
- aSuffix = rProp.Value.get<OUString>();
+ if (rProp.Name == "ListFormat")
+ aListFormat = rProp.Value.get<OUString>();
}
// Suffix was '\0' instead of ' '.
- CPPUNIT_ASSERT_EQUAL(OUString(" "), aSuffix);
+ CPPUNIT_ASSERT_EQUAL(OUString(" %1 "), aListFormat);
}
DECLARE_RTFEXPORT_TEST(testParaShadow, "para-shadow.rtf")
diff --git a/sw/qa/extras/rtfimport/rtfimport.cxx b/sw/qa/extras/rtfimport/rtfimport.cxx
index a652b354dbe7..3fe90033be59 100644
--- a/sw/qa/extras/rtfimport/rtfimport.cxx
+++ b/sw/qa/extras/rtfimport/rtfimport.cxx
@@ -141,21 +141,52 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf108943)
CPPUNIT_TEST_FIXTURE(Test, testFdo46662)
{
load(mpTestDocumentPath, "fdo46662.rtf");
- uno::Reference<beans::XPropertySet> xPropertySet(
- getStyles("NumberingStyles")->getByName("WWNum3"), uno::UNO_QUERY);
- uno::Reference<container::XIndexAccess> xLevels(
- xPropertySet->getPropertyValue("NumberingRules"), uno::UNO_QUERY);
- uno::Sequence<beans::PropertyValue> aProps;
- xLevels->getByIndex(1) >>= aProps; // 2nd level
- for (int i = 0; i < aProps.getLength(); ++i)
+ OUString listStyle;
+
{
- const beans::PropertyValue& rProp = aProps[i];
+ uno::Reference<beans::XPropertySet> xPara(getParagraph(1), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(0),
+ getProperty<sal_Int16>(xPara, "NumberingLevel"));
+ CPPUNIT_ASSERT(xPara->getPropertyValue("NumberingStyleName") >>= listStyle);
+ CPPUNIT_ASSERT(listStyle.startsWith("WWNum"));
+ CPPUNIT_ASSERT_EQUAL(OUString("1"), getProperty<OUString>(xPara, "ListLabelString"));
+ }
+
+ {
+ uno::Reference<beans::XPropertySet> xPara(getParagraph(2), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(1),
+ getProperty<sal_Int16>(xPara, "NumberingLevel"));
+ CPPUNIT_ASSERT(xPara->getPropertyValue("NumberingStyleName") >>= listStyle);
+ CPPUNIT_ASSERT(listStyle.startsWith("WWNum"));
+ CPPUNIT_ASSERT_EQUAL(OUString("1.1"), getProperty<OUString>(xPara, "ListLabelString"));
+ }
+
+ {
+ uno::Reference<beans::XPropertySet> xPara(getParagraph(3), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(2),
+ getProperty<sal_Int16>(xPara, "NumberingLevel"));
+ CPPUNIT_ASSERT(xPara->getPropertyValue("NumberingStyleName") >>= listStyle);
+ CPPUNIT_ASSERT(listStyle.startsWith("WWNum"));
+ CPPUNIT_ASSERT_EQUAL(OUString("1.1.1"), getProperty<OUString>(xPara, "ListLabelString"));
+ }
+
+ {
+ uno::Reference<beans::XPropertySet> xPara(getParagraph(4), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(3),
+ getProperty<sal_Int16>(xPara, "NumberingLevel"));
+ CPPUNIT_ASSERT(xPara->getPropertyValue("NumberingStyleName") >>= listStyle);
+ CPPUNIT_ASSERT(listStyle.startsWith("WWNum"));
+ CPPUNIT_ASSERT_EQUAL(OUString("1.1.1.1"), getProperty<OUString>(xPara, "ListLabelString"));
+ }
- if (rProp.Name == "ParentNumbering")
- CPPUNIT_ASSERT_EQUAL(sal_Int16(2), rProp.Value.get<sal_Int16>());
- else if (rProp.Name == "Suffix")
- CPPUNIT_ASSERT_EQUAL(sal_Int32(0), rProp.Value.get<OUString>().getLength());
+ {
+ 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(xPara->getPropertyValue("NumberingStyleName") >>= listStyle);
+ CPPUNIT_ASSERT(listStyle.startsWith("WWNum"));
+ CPPUNIT_ASSERT_EQUAL(OUString("2"), getProperty<OUString>(xPara, "ListLabelString"));
}
}
@@ -1037,25 +1068,12 @@ CPPUNIT_TEST_FIXTURE(Test, testCp950listleveltext1)
{
load(mpTestDocumentPath, "cp950listleveltext1.rtf");
// suffix with Chinese only ( most common case generated by MSO2010 TC)
- const sal_Unicode aExpectedSuffix[1]
- = { 0x3001 }; // This is a dot that is generally used as suffix of Chinese list number
- uno::Reference<beans::XPropertySet> xPropertySet(
- getStyles("NumberingStyles")->getByName("WWNum3"), uno::UNO_QUERY);
- uno::Reference<container::XIndexAccess> xLevels(
- xPropertySet->getPropertyValue("NumberingRules"), uno::UNO_QUERY);
- uno::Sequence<beans::PropertyValue> aProps;
- xLevels->getByIndex(0) >>= aProps; // 1st level
-
- OUString aSuffix;
- for (int i = 0; i < aProps.getLength(); ++i)
- {
- const beans::PropertyValue& rProp = aProps[i];
+ // This is a dot that is generally used as suffix of Chinese list number
+ const sal_Unicode aExpectedNumbering[] = { 0x4e00, 0x3001 };
- if (rProp.Name == "Suffix")
- aSuffix = rProp.Value.get<OUString>();
- }
- // Suffix was '\0' instead of ' '.
- CPPUNIT_ASSERT_EQUAL(OUString(aExpectedSuffix, SAL_N_ELEMENTS(aExpectedSuffix)), aSuffix);
+ uno::Reference<beans::XPropertySet> xPara(getParagraph(1), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString(aExpectedNumbering, SAL_N_ELEMENTS(aExpectedNumbering)),
+ getProperty<OUString>(xPara, "ListLabelString"));
}
// This testcase illustrate leveltext with multibyte strings coded in cp950 ( BIG5 ).
@@ -1063,85 +1081,35 @@ CPPUNIT_TEST_FIXTURE(Test, testCp950listleveltext2)
{
load(mpTestDocumentPath, "cp950listleveltext2.rtf");
// Prefix and suffix with Chinese only ( tweaked from default in MSO2010 TC)
- const sal_Unicode aExpectedPrefix[2] = { 0x524d, 0x7f6e };
- const sal_Unicode aExpectedSuffix[3] = { 0x3001, 0x5f8c, 0x7f6e };
+ const sal_Unicode aExpectedNumbering[] = { 0x524d, 0x7f6e, 0x7532, 0x3001, 0x5f8c, 0x7f6e };
- uno::Reference<beans::XPropertySet> xPropertySet(
- getStyles("NumberingStyles")->getByName("WWNum1"), uno::UNO_QUERY);
- uno::Reference<container::XIndexAccess> xLevels(
- xPropertySet->getPropertyValue("NumberingRules"), uno::UNO_QUERY);
- uno::Sequence<beans::PropertyValue> aProps;
- xLevels->getByIndex(0) >>= aProps; // 1st level
-
- OUString aSuffix, aPrefix;
- for (int i = 0; i < aProps.getLength(); ++i)
- {
- const beans::PropertyValue& rProp = aProps[i];
-
- if (rProp.Name == "Suffix")
- aSuffix = rProp.Value.get<OUString>();
- if (rProp.Name == "Prefix")
- aPrefix = rProp.Value.get<OUString>();
- }
- // Suffix was '\0' instead of ' '.
- CPPUNIT_ASSERT_EQUAL(OUString(aExpectedPrefix, SAL_N_ELEMENTS(aExpectedPrefix)), aPrefix);
- CPPUNIT_ASSERT_EQUAL(OUString(aExpectedSuffix, SAL_N_ELEMENTS(aExpectedSuffix)), aSuffix);
+ uno::Reference<beans::XPropertySet> xPara(getParagraph(1), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString(aExpectedNumbering, SAL_N_ELEMENTS(aExpectedNumbering)),
+ getProperty<OUString>(xPara, "ListLabelString"));
}
// This testcase illustrate leveltext with multibyte strings coded in cp950 ( BIG5 )
CPPUNIT_TEST_FIXTURE(Test, testCp950listleveltext3)
{
load(mpTestDocumentPath, "cp950listleveltext3.rtf");
- // Prefix and suffix that mix Chinese and English ( tweaked from default in MSO2010 TC)
- const sal_Unicode aExpectedPrefix[4] = { 0x524d, 0x0061, 0x7f6e, 0x0062 };
- const sal_Unicode aExpectedSuffix[6] = { 0x3001, 0x0063, 0x5f8c, 0x0064, 0x7f6e, 0x0065 };
+ // Numbering is a mix Chinese and English ( tweaked from default in MSO2010 TC)
+ const sal_Unicode aExpectedNumbering[] = { 0x524d, 0x0061, 0x7f6e, 0x0062, 0x7532, 0x3001,
+ 0x0063, 0x5f8c, 0x0064, 0x7f6e, 0x0065 };
- uno::Reference<beans::XPropertySet> xPropertySet(
- getStyles("NumberingStyles")->getByName("WWNum1"), uno::UNO_QUERY);
- uno::Reference<container::XIndexAccess> xLevels(
- xPropertySet->getPropertyValue("NumberingRules"), uno::UNO_QUERY);
- uno::Sequence<beans::PropertyValue> aProps;
- xLevels->getByIndex(0) >>= aProps; // 1st level
-
- OUString aSuffix, aPrefix;
- for (int i = 0; i < aProps.getLength(); ++i)
- {
- const beans::PropertyValue& rProp = aProps[i];
-
- if (rProp.Name == "Suffix")
- aSuffix = rProp.Value.get<OUString>();
- if (rProp.Name == "Prefix")
- aPrefix = rProp.Value.get<OUString>();
- }
- // Suffix was '\0' instead of ' '.
- CPPUNIT_ASSERT_EQUAL(OUString(aExpectedPrefix, SAL_N_ELEMENTS(aExpectedPrefix)), aPrefix);
- CPPUNIT_ASSERT_EQUAL(OUString(aExpectedSuffix, SAL_N_ELEMENTS(aExpectedSuffix)), aSuffix);
+ uno::Reference<beans::XPropertySet> xPara(getParagraph(1), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString(aExpectedNumbering, SAL_N_ELEMENTS(aExpectedNumbering)),
+ getProperty<OUString>(xPara, "ListLabelString"));
}
CPPUNIT_TEST_FIXTURE(Test, testChtOutlineNumberingRtf)
{
load(mpTestDocumentPath, "chtoutline.rtf");
- const sal_Unicode aExpectedPrefix[2] = { 0x7b2c, 0x0020 };
- const sal_Unicode aExpectedSuffix[2] = { 0x0020, 0x7ae0 };
- uno::Reference<text::XChapterNumberingSupplier> xChapterNumberingSupplier(mxComponent,
- uno::UNO_QUERY);
- uno::Reference<container::XIndexAccess> xLevels(
- xChapterNumberingSupplier->getChapterNumberingRules());
- uno::Sequence<beans::PropertyValue> aProps;
- xLevels->getByIndex(0) >>= aProps; // 1st level
- OUString aSuffix, aPrefix;
- for (int i = 0; i < aProps.getLength(); ++i)
- {
- const beans::PropertyValue& rProp = aProps[i];
+ const sal_Unicode aExpectedNumbering[] = { 0x7b2c, ' ', '1', ' ', 0x7ae0 };
- if (rProp.Name == "Suffix")
- aSuffix = rProp.Value.get<OUString>();
- if (rProp.Name == "Prefix")
- aPrefix = rProp.Value.get<OUString>();
- }
- CPPUNIT_ASSERT_EQUAL(OUString(aExpectedPrefix, SAL_N_ELEMENTS(aExpectedPrefix)), aPrefix);
- CPPUNIT_ASSERT_EQUAL(OUString(aExpectedSuffix, SAL_N_ELEMENTS(aExpectedSuffix)), aSuffix);
+ uno::Reference<beans::XPropertySet> xPara(getParagraph(1), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(OUString(aExpectedNumbering, SAL_N_ELEMENTS(aExpectedNumbering)),
+ getProperty<OUString>(xPara, "ListLabelString"));
}
CPPUNIT_TEST_FIXTURE(Test, testTdf90046)
diff --git a/sw/source/core/doc/number.cxx b/sw/source/core/doc/number.cxx
index f57933440278..df3dcf76bfff 100644
--- a/sw/source/core/doc/number.cxx
+++ b/sw/source/core/doc/number.cxx
@@ -639,64 +639,94 @@ OUString SwNumRule::MakeNumString( const SwNumberTree::tNumberVector & rNumVecto
const SwNumFormat& rMyNFormat = Get( static_cast<sal_uInt16>(nLevel) );
{
- SwNumberTree::tNumberVector::size_type i = nLevel;
+ css::lang::Locale aLocale( LanguageTag::convertToLocale(nLang));
- if( !IsContinusNum() &&
- // - do not include upper levels, if level isn't numbered.
- rMyNFormat.GetNumberingType() != SVX_NUM_NUMBER_NONE &&
- rMyNFormat.GetIncludeUpperLevels() ) // Just the own level?
+ OUString sLevelFormat = rMyNFormat.GetListFormat();
+ if (!sLevelFormat.isEmpty())
{
- sal_uInt8 n = rMyNFormat.GetIncludeUpperLevels();
- if( 1 < n )
+ // In this case we are ignoring GetIncludeUpperLevels: we put all
+ // level nubers requested by level format
+ for (SwNumberTree::tNumberVector::size_type i=0; i <= nLevel; ++i)
{
- if( i+1 >= n )
- i -= n - 1;
+ OUString sReplacement;
+ if (rNumVector[i])
+ {
+ if (bOnlyArabic)
+ sReplacement = OUString::number(rNumVector[i]);
+ else
+ sReplacement = Get(i).GetNumStr(rNumVector[i], aLocale);
+ }
else
- i = 0;
+ sReplacement = "0"; // all 0 level are a 0
+
+ OUString sFind("%" + OUString::number(i + 1));
+ sal_Int32 nPosition = sLevelFormat.indexOf(sFind);
+ if (nPosition >= 0)
+ sLevelFormat = sLevelFormat.replaceAt(nPosition, sFind.getLength(), sReplacement);
}
+ aStr = sLevelFormat;
}
-
- css::lang::Locale aLocale( LanguageTag::convertToLocale(nLang));
-
- for( ; i <= nLevel; ++i )
+ else
{
- const SwNumFormat& rNFormat = Get( i );
- if( SVX_NUM_NUMBER_NONE == rNFormat.GetNumberingType() )
+ // Fallback case: level format is not defined
+ // So use old way with levels joining by dot "."
+ SwNumberTree::tNumberVector::size_type i = nLevel;
+
+ if (!IsContinusNum() &&
+ // - do not include upper levels, if level isn't numbered.
+ rMyNFormat.GetNumberingType() != SVX_NUM_NUMBER_NONE &&
+ rMyNFormat.GetIncludeUpperLevels()) // Just the own level?
{
- // Should 1.1.1 --> 2. NoNum --> 1..1 or 1.1 ??
- // if( i != rNum.nMyLevel )
- // aStr += ".";
- continue;
+ sal_uInt8 n = rMyNFormat.GetIncludeUpperLevels();
+ if (1 < n)
+ {
+ if (i + 1 >= n)
+ i -= n - 1;
+ else
+ i = 0;
+ }
}
- if( rNumVector[ i ] )
+ for (; i <= nLevel; ++i)
{
- if( bOnlyArabic )
- aStr.append(OUString::number( rNumVector[ i ] ));
+ const SwNumFormat& rNFormat = Get(i);
+ if (SVX_NUM_NUMBER_NONE == rNFormat.GetNumberingType())
+ {
+ // Should 1.1.1 --> 2. NoNum --> 1..1 or 1.1 ??
+ // if( i != rNum.nMyLevel )
+ // aStr += ".";
+ continue;
+ }
+
+ if (rNumVector[i])
+ {
+ if (bOnlyArabic)
+ aStr.append(OUString::number(rNumVector[i]));
+ else
+ aStr.append(rNFormat.GetNumStr(rNumVector[i], aLocale));
+ }
else
- aStr.append(rNFormat.GetNumStr( rNumVector[ i ], aLocale ));
+ aStr.append("0"); // all 0 level are a 0
+ if (i != nLevel && !aStr.isEmpty())
+ aStr.append(".");
}
- else
- aStr.append("0"); // all 0 level are a 0
- if( i != nLevel && !aStr.isEmpty() )
- aStr.append(".");
- }
- // The type doesn't have any number, so don't append
- // the post-/prefix string
- if( bInclStrings && !bOnlyArabic &&
- SVX_NUM_CHAR_SPECIAL != rMyNFormat.GetNumberingType() &&
- SVX_NUM_BITMAP != rMyNFormat.GetNumberingType() )
- {
- const OUString& sPrefix = rMyNFormat.GetPrefix();
- const OUString& sSuffix = rMyNFormat.GetSuffix();
-
- aStr.insert(0, sPrefix);
- aStr.append(sSuffix);
- if ( pExtremities )
+ // The type doesn't have any number, so don't append
+ // the post-/prefix string
+ if (bInclStrings && !bOnlyArabic &&
+ SVX_NUM_CHAR_SPECIAL != rMyNFormat.GetNumberingType() &&
+ SVX_NUM_BITMAP != rMyNFormat.GetNumberingType())
{
- pExtremities->nPrefixChars = sPrefix.getLength();
- pExtremities->nSuffixChars = sSuffix.getLength();
+ const OUString& sPrefix = rMyNFormat.GetPrefix();
+ const OUString& sSuffix = rMyNFormat.GetSuffix();
+
+ aStr.insert(0, sPrefix);
+ aStr.append(sSuffix);
+ if (pExtremities)
+ {
+ pExtremities->nPrefixChars = sPrefix.getLength();
+ pExtremities->nSuffixChars = sSuffix.getLength();
+ }
}
}
}
diff --git a/sw/source/core/unocore/unosett.cxx b/sw/source/core/unocore/unosett.cxx
index c41d13dea3a8..2b3b08e59b9e 100644
--- a/sw/source/core/unocore/unosett.cxx
+++ b/sw/source/core/unocore/unosett.cxx
@@ -1342,6 +1342,10 @@ uno::Sequence<beans::PropertyValue> SwXNumberingRules::GetPropertiesForNumFormat
aUString = rFormat.GetSuffix();
aPropertyValues.push_back(comphelper::makePropertyValue("Suffix", aUString));
+ //listformat
+ aUString = rFormat.GetListFormat();
+ aPropertyValues.push_back(comphelper::makePropertyValue("ListFormat", aUString));
+
//char style name
aUString.clear();
@@ -1581,7 +1585,9 @@ void SwXNumberingRules::SetPropertiesToNumFormat(
// these two are accepted but ignored for some reason
UNO_NAME_BULLET_REL_SIZE, // 25
UNO_NAME_BULLET_COLOR, // 26
- UNO_NAME_GRAPHIC_URL // 27
+ UNO_NAME_GRAPHIC_URL, // 27
+
+ UNO_NAME_LIST_FORMAT // 28
};
enum {
@@ -2035,6 +2041,13 @@ void SwXNumberingRules::SetPropertiesToNumFormat(
bWrongArg = true;
}
break;
+ case 28: //"ListFormat",
+ {
+ OUString uTmp;
+ pProp->Value >>= uTmp;
+ aFormat.SetListFormat(uTmp);
+ }
+ break;
}
}
if(!bWrongArg && (pSetBrush || pSetSize || pSetVOrient))
diff --git a/sw/source/filter/ww8/wrtw8num.cxx b/sw/source/filter/ww8/wrtw8num.cxx
index e665a253ca3e..afe0204a48cd 100644
--- a/sw/source/filter/ww8/wrtw8num.cxx
+++ b/sw/source/filter/ww8/wrtw8num.cxx
@@ -489,7 +489,13 @@ void MSWordExportBase::NumberingLevel(
const vcl::Font* pBulletFont=nullptr;
rtl_TextEncoding eChrSet=0;
FontFamily eFamily=FAMILY_DECORATIVE;
- if (SVX_NUM_CHAR_SPECIAL == rFormat.GetNumberingType() ||
+
+ if (!rRule.Get(nLvl).GetListFormat().isEmpty())
+ {
+ // We have stored list format, use it
+ sNumStr = rRule.Get(nLvl).GetListFormat();
+ }
+ else if (SVX_NUM_CHAR_SPECIAL == rFormat.GetNumberingType() ||
SVX_NUM_BITMAP == rFormat.GetNumberingType())
{
sNumStr = OUString(rFormat.GetBulletChar());
diff --git a/writerfilter/source/dmapper/NumberingManager.cxx b/writerfilter/source/dmapper/NumberingManager.cxx
index 32dead60a100..eab1ac81ecc7 100644
--- a/writerfilter/source/dmapper/NumberingManager.cxx
+++ b/writerfilter/source/dmapper/NumberingManager.cxx
@@ -42,6 +42,7 @@
#include <tools/diagnose_ex.h>
#include <comphelper/sequence.hxx>
#include <comphelper/propertyvalue.hxx>
+#include <comphelper/string.hxx>
using namespace com::sun::star;
@@ -149,55 +150,6 @@ void ListLevel::SetParaStyle( const tools::SvRef< StyleSheetEntry >& pStyle )
&& styleId[ RTL_CONSTASCII_LENGTH( "Heading " ) ] <= '9' );
}
-sal_Int16 ListLevel::GetParentNumbering( const OUString& sText, sal_Int16 nLevel,
- OUString& rPrefix, OUString& rSuffix )
-{
- sal_Int16 nParentNumbering = 1;
-
- //now parse the text to find %n from %1 to %nLevel+1
- //everything before the first % and the last %x is prefix and suffix
- OUString sLevelText( sText );
- sal_Int32 nCurrentIndex = 0;
- sal_Int32 nFound = sLevelText.indexOf( '%', nCurrentIndex );
- if( nFound > 0 )
- {
- rPrefix = sLevelText.copy( 0, nFound );
- sLevelText = sLevelText.copy( nFound );
- }
- sal_Int32 nMinLevel = nLevel;
- //now the text should either be empty or start with %
- nFound = sLevelText.getLength( ) > 1 ? 0 : -1;
- while( nFound >= 0 )
- {
- if( sLevelText.getLength() > 1 )
- {
- sal_Unicode cLevel = sLevelText[1];
- if( cLevel >= '1' && cLevel <= '9' )
- {
- if( cLevel - '1' < nMinLevel )
- nMinLevel = cLevel - '1';
- //remove first char - next char is removed later
- sLevelText = sLevelText.copy( 1 );
- }
- }
- //remove old '%' or number
- sLevelText = sLevelText.copy( 1 );
- nCurrentIndex = 0;
- nFound = sLevelText.indexOf( '%', nCurrentIndex );
- //remove the text before the next %
- if(nFound > 0)
- sLevelText = sLevelText.copy( nFound -1 );
- }
- if( nMinLevel < nLevel )
- {
- nParentNumbering = sal_Int16( nLevel - nMinLevel + 1);
- }
-
- rSuffix = sLevelText;
-
- return nParentNumbering;
-}
-
uno::Sequence<beans::PropertyValue> ListLevel::GetProperties(bool bDefaults)
{
uno::Sequence<beans::PropertyValue> aLevelProps = GetLevelProperties(bDefaults);
@@ -588,19 +540,11 @@ void ListDef::CreateNumberingRules( DomainMapper& rDMapper,
if (pLevel.get() && !pLevel->GetBulletChar().isEmpty())
sText = pLevel->GetBulletChar( );
- OUString sPrefix;
- OUString sSuffix;
- OUString& rPrefix = sPrefix;
- OUString& rSuffix = sSuffix;
- sal_Int16 nParentNum = ListLevel::GetParentNumbering(
- sText, nLevel, rPrefix, rSuffix );
-
- aLvlProps.push_back(comphelper::makePropertyValue(getPropertyName(PROP_PREFIX), rPrefix));
-
if (sText.isEmpty())
{
// Empty <w:lvlText>? Then put a Unicode "zero width space" as a suffix, so LabelFollowedBy is still shown, as in Word.
// With empty suffix, Writer does not show LabelFollowedBy, either.
+ OUString sSuffix;
auto it = std::find_if(aLvlProps.begin(), aLvlProps.end(), [](const beans::PropertyValue& rValue) { return rValue.Name == "NumberingType"; });
if (it != aLvlProps.end())
{
@@ -617,12 +561,19 @@ void ListDef::CreateNumberingRules( DomainMapper& rDMapper,
}
if (bLabelFollowedBy && nNumberFormat == style::NumberingType::NUMBER_NONE)
- rSuffix = OUString(u'\x200B');
+ sSuffix = OUString(u'\x200B');
}
+ aLvlProps.push_back(comphelper::makePropertyValue(getPropertyName(PROP_SUFFIX), sSuffix));
}
+ else
+ {
+ aLvlProps.push_back(comphelper::makePropertyValue(getPropertyName(PROP_LIST_FORMAT), sText));
- aLvlProps.push_back(comphelper::makePropertyValue(getPropertyName(PROP_SUFFIX), rSuffix));
- aLvlProps.push_back(comphelper::makePropertyValue(getPropertyName(PROP_PARENT_NUMBERING), nParentNum));
+ // 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(sText, '%');
+ aLvlProps.push_back(comphelper::makePropertyValue(getPropertyName(PROP_PARENT_NUMBERING), nParentNum));
+ }
aLvlProps.push_back(comphelper::makePropertyValue(getPropertyName(PROP_POSITION_AND_SPACE_MODE), sal_Int16(text::PositionAndSpaceMode::LABEL_ALIGNMENT)));
diff --git a/writerfilter/source/dmapper/NumberingManager.hxx b/writerfilter/source/dmapper/NumberingManager.hxx
index c0e68d9327a5..3949c3bf7dcd 100644
--- a/writerfilter/source/dmapper/NumberingManager.hxx
+++ b/writerfilter/source/dmapper/NumberingManager.hxx
@@ -86,11 +86,6 @@ public:
bool HasValues() const;
// UNO mapping functions
-
- // rPrefix and rSuffix are out parameters
- static sal_Int16 GetParentNumbering( const OUString& sText, sal_Int16 nLevel,
- OUString& rPrefix, OUString& rSuffix );
-
css::uno::Sequence<css::beans::PropertyValue> GetProperties(bool bDefaults);
css::uno::Sequence<css::beans::PropertyValue> GetCharStyleProperties();
diff --git a/writerfilter/source/dmapper/PropertyIds.cxx b/writerfilter/source/dmapper/PropertyIds.cxx
index 0d5740e9fa83..6fecf7fe2be4 100644
--- a/writerfilter/source/dmapper/PropertyIds.cxx
+++ b/writerfilter/source/dmapper/PropertyIds.cxx
@@ -207,6 +207,7 @@ OUString getPropertyName( PropertyIds eId )
case PROP_LEVEL_FOLLOW : sName = "LabelFollowedBy"; break;
case PROP_LEVEL_PARAGRAPH_STYLES : sName = "LevelParagraphStyles"; break;
case PROP_LEVEL_FORMAT : sName = "LevelFormat"; break;
+ case PROP_LIST_FORMAT : sName = "ListFormat"; break;
case PROP_TOKEN_TYPE : sName = "TokenType"; break;
case PROP_TOKEN_HYPERLINK_START : sName = "TokenHyperlinkStart"; break;
case PROP_TOKEN_HYPERLINK_END : sName = "TokenHyperlinkEnd"; break;
diff --git a/writerfilter/source/dmapper/PropertyIds.hxx b/writerfilter/source/dmapper/PropertyIds.hxx
index a1a0c8f851a1..d511fd737238 100644
--- a/writerfilter/source/dmapper/PropertyIds.hxx
+++ b/writerfilter/source/dmapper/PropertyIds.hxx
@@ -205,6 +205,7 @@ enum PropertyIds
,PROP_LEVEL_FORMAT
,PROP_LEVEL_PARAGRAPH_STYLES
,PROP_LISTTAB_STOP_POSITION
+ ,PROP_LIST_FORMAT
,PROP_MACRO_NAME
,PROP_NAME
,PROP_NUMBERING_LEVEL