sw/qa/extras/ooxmlexport/data/custom-styles-TOC-semicolon.docx |binary
 sw/qa/extras/ooxmlexport/ooxmlexport17.cxx                     |   24 ++++++++
 sw/source/filter/ww8/ww8atr.cxx                                |   27 
++++++++--
 writerfilter/source/dmapper/DomainMapper_Impl.cxx              |    7 +-
 4 files changed, 51 insertions(+), 7 deletions(-)

New commits:
commit 5b8de6f5e19b4b85e9d13d86aa71ee6b7adae5f3
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Wed Jan 18 11:56:30 2023 +0100
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Thu Jan 19 12:43:48 2023 +0000

    tdf#153082 writerfilter,sw: import/export locale-dependent TOC ...
    
    ... \t style name separators.
    
    OOXML says in 17.16.5.68 TOC:
    
      \t field-argument
      Uses paragraphs formatted with styles other than the built-in
      heading styles. text in this switch's field-argument specifies those
      styles as a set of comma-separated doublets, with each doublet
      being a comma-separated set of style name and table of content
      level.
    
    The reality is documented in Word online help:
    
https://support.microsoft.com/en-us/office/field-codes-toc-table-of-contents-field-1f538bc4-60e6-4854-9f64-67754d78d05c?ui=en-US&rs=en-US&ad=US
    
      Note: Syntax shown here uses a comma (,) between the Style and Level
      parameters. A semicolon (;) is also valid, depending on which
      character is specified as the list separator in your operating
      system's regional and language settings. Because of language-specific
      dependencies, we recommend not using the \t switch in templates or
      documents that are intended for users across multiple language
      configurations.
    
    It's easy enough to recognize both ',' and ';' as separators on import,
    and unlikely that anybody would use these characters inside a style
    name; for export, both can't be written and a decision must be made.
    
    So do the same thing on export as Word does, assuming most document
    exchange is between users in the same locale; currently only for "de"
    locales but more can be added.
    
    Interestingly WW8 used to write ';' before 2009 when CWS hb32bugs01
    changed it to ','.
    
    Change-Id: I2dcfdd009f448f6fae37cbd28929d0bbe504acf9
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145744
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 7b62d09090e5172e26141694fb97bc27562a81ce)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145722
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/sw/qa/extras/ooxmlexport/data/custom-styles-TOC-semicolon.docx 
b/sw/qa/extras/ooxmlexport/data/custom-styles-TOC-semicolon.docx
new file mode 100644
index 000000000000..bef835c9bb46
Binary files /dev/null and 
b/sw/qa/extras/ooxmlexport/data/custom-styles-TOC-semicolon.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
index b216e14d22fe..0e000bff9641 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
@@ -702,6 +702,30 @@ DECLARE_OOXMLEXPORT_TEST(testTdf148361, "tdf148361.docx")
     CPPUNIT_ASSERT_EQUAL(OUString("[Type text]"), aActual);
 }
 
+DECLARE_OOXMLEXPORT_TEST(testTdf153082_semicolon, 
"custom-styles-TOC-semicolon.docx")
+{
+    uno::Reference<text::XDocumentIndexesSupplier> xIndexSupplier(mxComponent, 
uno::UNO_QUERY);
+    uno::Reference<container::XIndexAccess> xIndexes = 
xIndexSupplier->getDocumentIndexes();
+    uno::Reference<text::XDocumentIndex> xTOC(xIndexes->getByIndex(0), 
uno::UNO_QUERY);
+    // check styles
+    uno::Reference<container::XIndexAccess> xParaStyles =
+        getProperty<uno::Reference<container::XIndexAccess>>(xTOC, 
"LevelParagraphStyles");
+    uno::Sequence<OUString> styles;
+    xParaStyles->getByIndex(0) >>= styles;
+    CPPUNIT_ASSERT_EQUAL(uno::Sequence<OUString>{}, styles);
+    xParaStyles->getByIndex(1) >>= styles;
+    CPPUNIT_ASSERT_EQUAL(uno::Sequence<OUString>{}, styles);
+    xParaStyles->getByIndex(2) >>= styles;
+    // the first one is built-in Word style that was localised DE "Intensives 
Zitat" in the file
+    CPPUNIT_ASSERT_EQUAL((uno::Sequence<OUString>{"Intense Quote", "Custom1", 
"_MyStyle0"}), styles);
+    xTOC->update();
+    OUString const tocContent(xTOC->getAnchor()->getString());
+    CPPUNIT_ASSERT(tocContent.startsWith("Table of Contents"));
+    CPPUNIT_ASSERT(tocContent.indexOf("Lorem ipsum dolor sit amet, 
consectetuer adipiscing elit.") != -1);
+    CPPUNIT_ASSERT(tocContent.indexOf("Fusce posuere, magna sed pulvinar 
ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis 
urna.") != -1);
+    CPPUNIT_ASSERT(tocContent.indexOf("Proin pharetra nonummy pede. Mauris et 
orci.") != -1);
+}
+
 DECLARE_OOXMLEXPORT_TEST(testTdf153082_comma, "custom-styles-TOC-comma.docx")
 {
     uno::Reference<text::XDocumentIndexesSupplier> xIndexSupplier(mxComponent, 
uno::UNO_QUERY);
diff --git a/sw/source/filter/ww8/ww8atr.cxx b/sw/source/filter/ww8/ww8atr.cxx
index d0bed9c5c5bf..301b46e86319 100644
--- a/sw/source/filter/ww8/ww8atr.cxx
+++ b/sw/source/filter/ww8/ww8atr.cxx
@@ -138,6 +138,7 @@
 #include "ww8par.hxx"
 #include "ww8attributeoutput.hxx"
 #include "fields.hxx"
+#include <i18nlangtag/mslangid.hxx>
 #include <i18nlangtag/languagetag.hxx>
 #include <unotools/fltrcfg.hxx>
 
@@ -2252,6 +2253,21 @@ void 
AttributeOutputBase::GenerateBookmarksForSequenceField(const SwTextNode& rN
     }
 }
 
+static auto GetSeparatorForLocale() -> OUString
+{
+    switch (sal_uInt16(MsLangId::getSystemLanguage()))
+    {
+        case sal_uInt16(LANGUAGE_GERMAN):
+        case sal_uInt16(LANGUAGE_GERMAN_AUSTRIAN):
+        case sal_uInt16(LANGUAGE_GERMAN_LIECHTENSTEIN):
+        case sal_uInt16(LANGUAGE_GERMAN_LUXEMBOURG):
+        case sal_uInt16(LANGUAGE_GERMAN_SWISS):
+            return ";";
+        default:
+            return ",";
+    }
+}
+
 void AttributeOutputBase::StartTOX( const SwSection& rSect )
 {
     if ( const SwTOXBase* pTOX = rSect.GetTOXBase() )
@@ -2361,6 +2377,9 @@ void AttributeOutputBase::StartTOX( const SwSection& 
rSect )
                     sStr = FieldString(eCode);
 
                     OUString sTOption;
+                    // tdf#153082 Word's separator interpretation in DOCX
+                    // fields varies by system locale.
+                    auto const tsep(GetSeparatorForLocale());
                     sal_uInt16 n, nTOXLvl = pTOX->GetLevel();
                     if( !nTOXLvl )
                         ++nTOXLvl;
@@ -2462,8 +2481,8 @@ void AttributeOutputBase::StartTOX( const SwSection& 
rSect )
                                 if (nTestLvl < nTOXLvl && nTestLvl >= 
nMaxMSAutoEvaluate)
                                 {
                                     if (!sTOption.isEmpty())
-                                        sTOption += ",";
-                                    sTOption += pColl->GetName() + "," + 
OUString::number( nTestLvl + 1 );
+                                        sTOption += tsep;
+                                    sTOption += pColl->GetName() + tsep + 
OUString::number(nTestLvl + 1);
                                 }
                             }
                         }
@@ -2483,7 +2502,7 @@ void AttributeOutputBase::StartTOX( const SwSection& 
rSect )
                             if( !rStyles.isEmpty() )
                             {
                                 sal_Int32 nPos = 0;
-                                const OUString sLvl{ "," + OUString::number( n 
+ 1 ) };
+                                const OUString sLvl{tsep + OUString::number(n 
+ 1)};
                                 do {
                                     const OUString sStyle( rStyles.getToken( 
0, TOX_STYLE_DELIMITER, nPos ));
                                     if( !sStyle.isEmpty() )
@@ -2494,7 +2513,7 @@ void AttributeOutputBase::StartTOX( const SwSection& 
rSect )
                                             if 
(!pColl->IsAssignedToListLevelOfOutlineStyle() || 
pColl->GetAssignedOutlineStyleLevel() < nTOXLvl)
                                             {
                                                 if( !sTOption.isEmpty() )
-                                                    sTOption += ",";
+                                                    sTOption += tsep;
                                                 sTOption += sStyle + sLvl;
                                             }
                                         }
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx 
b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 3f33280f5a22..21ee55444ca6 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -6255,13 +6255,14 @@ void DomainMapper_Impl::handleToc
             TOCStyleMap aMap;
             sal_Int32 nLevel;
             sal_Int32 nPosition = 0;
+            auto const tsep(sTemplate.indexOf(',') != -1 ? ',' : ';');
             while( nPosition >= 0)
             {
-                OUString sStyleName = sTemplate.getToken( 0, ',', nPosition );
+                OUString sStyleName = sTemplate.getToken(0, tsep, nPosition);
                                 //empty tokens should be skipped
                 while( sStyleName.isEmpty() && nPosition > 0 )
-                    sStyleName = sTemplate.getToken( 0, ',', nPosition );
-                nLevel = o3tl::toInt32(o3tl::getToken(sTemplate, 0, ',', 
nPosition ));
+                    sStyleName = sTemplate.getToken(0, tsep, nPosition);
+                nLevel = o3tl::toInt32(o3tl::getToken(sTemplate, 0, tsep, 
nPosition ));
                 if( !nLevel )
                     nLevel = 1;
                 if( !sStyleName.isEmpty() )

Reply via email to