[Libreoffice-commits] core.git: 2 commits - i18npool/source officecfg/registry sc/qa sc/source

Tor Lillqvist (via logerrit) logerrit at kemper.freedesktop.org
Wed May 6 21:48:06 UTC 2020


 i18npool/source/collator/collator_unicode.cxx            |   26 ++-
 officecfg/registry/schema/org/openoffice/Office/Calc.xcs |   17 +
 sc/qa/unit/data/ods/tdf79998.ods                         |binary
 sc/qa/unit/filters-test.cxx                              |   20 ++
 sc/source/filter/excel/xestream.cxx                      |  129 +++++++++++++++
 sc/source/filter/inc/xestream.hxx                        |    5 
 6 files changed, 193 insertions(+), 4 deletions(-)

New commits:
commit df283b12a95d80a82aa2c2c9b8d32888a4d4039e
Author:     Tor Lillqvist <tml at collabora.com>
AuthorDate: Tue May 5 19:18:56 2020 +0300
Commit:     Tor Lillqvist <tml at collabora.com>
CommitDate: Wed May 6 23:47:39 2020 +0200

    Throw exceptions with useful messages
    
    Change-Id: Ic8e09d31db97c0cf2e1aaf006c96481d12deb2d8
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/93506
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Tor Lillqvist <tml at collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/93592
    Tested-by: Jenkins

diff --git a/i18npool/source/collator/collator_unicode.cxx b/i18npool/source/collator/collator_unicode.cxx
index 609ef0f20351..673f5c35d3c7 100644
--- a/i18npool/source/collator/collator_unicode.cxx
+++ b/i18npool/source/collator/collator_unicode.cxx
@@ -19,6 +19,8 @@
 
 #include <config_locales.h>
 
+#include <sal/log.hxx>
+
 #include <lrl_include.hxx>
 
 #include <rtl/ustrbuf.hxx>
@@ -141,7 +143,11 @@ Collator_Unicode::loadCollatorAlgorithm(const OUString& rAlgorithm, const lang::
         OUString rule = LocaleDataImpl::get()->getCollatorRuleByAlgorithm(rLocale, rAlgorithm);
         if (!rule.isEmpty()) {
             collator.reset( new icu::RuleBasedCollator(reinterpret_cast<const UChar *>(rule.getStr()), status) );
-            if (! U_SUCCESS(status)) throw RuntimeException();
+            if (! U_SUCCESS(status)) {
+                OUString message = "icu::RuleBasedCollator ctor failed: " + OUString::createFromAscii(u_errorName(status));
+                SAL_WARN("i18npool", message);
+                throw RuntimeException(message);
+            }
         }
         if (!collator && OUString(LOCAL_RULE_LANGS).indexOf(rLocale.Language) >= 0) {
             const sal_uInt8* (*func)() = nullptr;
@@ -359,10 +365,18 @@ Collator_Unicode::loadCollatorAlgorithm(const OUString& rAlgorithm, const lang::
                 uca_base.reset( static_cast<icu::RuleBasedCollator*>(icu::Collator::createInstance(
                             icu::Locale::getRoot(), status)) );
 #endif
-                if (! U_SUCCESS(status)) throw RuntimeException();
+                if (! U_SUCCESS(status)) {
+                    OUString message = "icu::Collator::createInstance() failed: " + OUString::createFromAscii(u_errorName(status));
+                    SAL_WARN("i18npool", message);
+                    throw RuntimeException(message);
+                }
                 collator.reset( new icu::RuleBasedCollator(
                         reinterpret_cast<const uint8_t*>(ruleImage), ruleImageSize, uca_base.get(), status) );
-                if (! U_SUCCESS(status)) throw RuntimeException();
+                if (! U_SUCCESS(status)) {
+                    OUString message = "icu::RuleBasedCollator ctor failed: " + OUString::createFromAscii(u_errorName(status));
+                    SAL_WARN("i18npool", message);
+                    throw RuntimeException(message);
+                }
             }
         }
         if (!collator) {
@@ -383,7 +397,11 @@ Collator_Unicode::loadCollatorAlgorithm(const OUString& rAlgorithm, const lang::
 
             // load ICU collator
             collator.reset( static_cast<icu::RuleBasedCollator*>( icu::Collator::createInstance(icuLocale, status) ) );
-            if (! U_SUCCESS(status)) throw RuntimeException();
+            if (! U_SUCCESS(status)) {
+                OUString message = "icu::Collator::createInstance() failed: " + OUString::createFromAscii(u_errorName(status));
+                SAL_WARN("i18npool", message);
+                throw RuntimeException(message);
+            }
         }
     }
 
commit 6b75874386b7b1ec44f7acc49cd3556a56108ed8
Author:     Serge Krot <Serge.Krot at cib.de>
AuthorDate: Thu Apr 16 15:42:33 2020 +0200
Commit:     Eike Rathke <erack at redhat.com>
CommitDate: Wed May 6 23:47:31 2020 +0200

    tdf#79998 FILESAVE: XLSX export with long sheet names (length > 31 characters)
    
    Change-Id: If18e3b751486144f3477b6e0c2615751f57e5565
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/92372
    Tested-by: Jenkins
    Reviewed-by: Eike Rathke <erack at redhat.com>

diff --git a/officecfg/registry/schema/org/openoffice/Office/Calc.xcs b/officecfg/registry/schema/org/openoffice/Office/Calc.xcs
index 8cd789e9a9ad..0762279bf3db 100644
--- a/officecfg/registry/schema/org/openoffice/Office/Calc.xcs
+++ b/officecfg/registry/schema/org/openoffice/Office/Calc.xcs
@@ -1830,6 +1830,23 @@
           </prop>
         </group>
       </group>
+      <group oor:name="Export">
+        <info>
+          <desc>Contains settings for export filters.</desc>
+        </info>
+        <group oor:name="MS_Excel">
+          <info>
+            <desc>Contains settings for MS Excel export.</desc>
+          </info>
+          <prop oor:name="TruncateLongSheetNames" oor:type="xs:boolean" oor:nillable="false">
+            <info>
+              <desc>Indicates whether sheet names should be truncated to 31 characters.</desc>
+              <label>Truncate long sheet names</label>
+            </info>
+            <value>true</value>
+          </prop>
+        </group>
+      </group>
     </group>
     <group oor:name="Print">
       <info>
diff --git a/sc/qa/unit/data/ods/tdf79998.ods b/sc/qa/unit/data/ods/tdf79998.ods
new file mode 100644
index 000000000000..201cca140585
Binary files /dev/null and b/sc/qa/unit/data/ods/tdf79998.ods differ
diff --git a/sc/qa/unit/filters-test.cxx b/sc/qa/unit/filters-test.cxx
index dc097180cbbd..43c3483bb281 100644
--- a/sc/qa/unit/filters-test.cxx
+++ b/sc/qa/unit/filters-test.cxx
@@ -70,6 +70,7 @@ public:
     void testSharedFormulaXLSX();
     void testSharedFormulaRefUpdateXLSX();
     void testSheetNamesXLSX();
+    void testTdf79998();
     void testLegacyCellAnchoredRotatedShape();
     void testEnhancedProtectionXLS();
     void testEnhancedProtectionXLSX();
@@ -96,6 +97,7 @@ public:
     CPPUNIT_TEST(testSharedFormulaXLSX);
     CPPUNIT_TEST(testSharedFormulaRefUpdateXLSX);
     CPPUNIT_TEST(testSheetNamesXLSX);
+    CPPUNIT_TEST(testTdf79998);
     CPPUNIT_TEST(testLegacyCellAnchoredRotatedShape);
     CPPUNIT_TEST(testEnhancedProtectionXLS);
     CPPUNIT_TEST(testEnhancedProtectionXLSX);
@@ -468,6 +470,24 @@ void ScFiltersTest::testSheetNamesXLSX()
     xDocSh->DoClose();
 }
 
+// FILESAVE: XLSX export with long sheet names (length > 31 characters)
+void ScFiltersTest::testTdf79998()
+{
+    // check: original document has tab name > 31 characters
+    ScDocShellRef xDocSh = loadDoc("tdf79998.", FORMAT_ODS);
+    ScDocument& rDoc1 = xDocSh->GetDocument();
+    const std::vector<OUString> aTabNames1 = rDoc1.GetAllTableNames();
+    CPPUNIT_ASSERT_EQUAL(OUString("Utilities (FX Kurse, Kreditkarten etc)"), aTabNames1[1]);
+
+    // check: saved XLSX document has truncated tab name
+    xDocSh = saveAndReload( &(*xDocSh), FORMAT_XLSX);
+    ScDocument& rDoc2 = xDocSh->GetDocument();
+    const std::vector<OUString> aTabNames2 = rDoc2.GetAllTableNames();
+    CPPUNIT_ASSERT_EQUAL(OUString("Utilities (FX Kurse, Kreditkart"), aTabNames2[1]);
+
+    xDocSh->DoClose();
+}
+
 static void impl_testLegacyCellAnchoredRotatedShape( ScDocument& rDoc, const tools::Rectangle& aRect, const ScDrawObjData& aAnchor, long TOLERANCE = 30 /* 30 hmm */ )
 {
     ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
diff --git a/sc/source/filter/excel/xestream.cxx b/sc/source/filter/excel/xestream.cxx
index 51b11ebaf029..b3f96aa46b5c 100644
--- a/sc/source/filter/excel/xestream.cxx
+++ b/sc/source/filter/excel/xestream.cxx
@@ -32,6 +32,7 @@
 #include <tools/urlobj.hxx>
 #include <vcl/svapp.hxx>
 #include <vcl/settings.hxx>
+#include <officecfg/Office/Calc.hxx>
 
 #include <docuno.hxx>
 #include <xestream.hxx>
@@ -49,6 +50,7 @@
 #include <globstr.hrc>
 #include <scresid.hxx>
 #include <root.hxx>
+#include <sfx2/app.hxx>
 
 #include <docsh.hxx>
 #include <viewdata.hxx>
@@ -1002,6 +1004,13 @@ bool XclExpXmlStream::exportDocument()
     ScDocument& rDoc = pShell->GetDocument();
     ScRefreshTimerProtector aProt(rDoc.GetRefreshTimerControlAddress());
 
+    const bool bValidateTabNames = officecfg::Office::Calc::Filter::Export::MS_Excel::TruncateLongSheetNames::get();
+    std::vector<OUString> aOriginalTabNames;
+    if (bValidateTabNames)
+    {
+        validateTabNames(aOriginalTabNames);
+    }
+
     uno::Reference<task::XStatusIndicator> xStatusIndicator = getStatusIndicator();
 
     if (xStatusIndicator.is())
@@ -1103,6 +1112,11 @@ bool XclExpXmlStream::exportDocument()
 
     commitStorage();
 
+    if (bValidateTabNames)
+    {
+        restoreTabNames(aOriginalTabNames);
+    }
+
     if (xStatusIndicator.is())
         xStatusIndicator->end();
     mpRoot = nullptr;
@@ -1119,4 +1133,119 @@ OUString XclExpXmlStream::getImplementationName()
     return "TODO";
 }
 
+void XclExpXmlStream::validateTabNames(std::vector<OUString>& aOriginalTabNames)
+{
+    const int MAX_TAB_NAME_LENGTH = 31;
+
+    ScDocShell* pShell = getDocShell();
+    ScDocument& rDoc = pShell->GetDocument();
+
+    // get original names
+    aOriginalTabNames.resize(rDoc.GetTableCount());
+    for (SCTAB nTab=0; nTab < rDoc.GetTableCount(); nTab++)
+    {
+        rDoc.GetName(nTab, aOriginalTabNames[nTab]);
+    }
+
+    // new tab names
+    std::vector<OUString> aNewTabNames;
+    aNewTabNames.reserve(rDoc.GetTableCount());
+
+    // check and rename
+    for (SCTAB nTab=0; nTab < rDoc.GetTableCount(); nTab++)
+    {
+        const OUString& rOriginalName = aOriginalTabNames[nTab];
+        if (rOriginalName.getLength() > MAX_TAB_NAME_LENGTH)
+        {
+            OUString aNewName;
+
+            // let's try just truncate "<first 31 chars>"
+            if (aNewName.isEmpty())
+            {
+                aNewName = rOriginalName.copy(0, MAX_TAB_NAME_LENGTH);
+                if (aNewTabNames.end() != std::find(aNewTabNames.begin(), aNewTabNames.end(), aNewName) ||
+                    aOriginalTabNames.end() != std::find(aOriginalTabNames.begin(), aOriginalTabNames.end(), aNewName))
+                {
+                    // was found => let's use another tab name
+                    aNewName.clear();
+                }
+            }
+
+            // let's try "<first N chars>-XXX" template
+            for (int digits=1; digits<10 && aNewName.isEmpty(); digits++)
+            {
+                const int rangeStart = pow(10, digits - 1);
+                const int rangeEnd = pow(10, digits);
+
+                for (int i=rangeStart; i<rangeEnd && aNewName.isEmpty(); i++)
+                {
+                    aNewName = rOriginalName.copy(0, MAX_TAB_NAME_LENGTH - 1 - digits).concat("-").concat(OUString::number(i));
+                    if (aNewTabNames.end() != std::find(aNewTabNames.begin(), aNewTabNames.end(), aNewName) ||
+                        aOriginalTabNames.end() != std::find(aOriginalTabNames.begin(), aOriginalTabNames.end(), aNewName))
+                    {
+                        // was found => let's use another tab name
+                        aNewName.clear();
+                    }
+                }
+            }
+
+            if (!aNewName.isEmpty())
+            {
+                // new name was created => rename
+                renameTab(nTab, aNewName);
+                aNewTabNames.push_back(aNewName);
+            }
+            else
+            {
+                // default: do not rename
+                aNewTabNames.push_back(rOriginalName);
+            }
+        }
+        else
+        {
+            // default: do not rename
+            aNewTabNames.push_back(rOriginalName);
+        }
+    }
+}
+
+void XclExpXmlStream::restoreTabNames(const std::vector<OUString>& aOriginalTabNames)
+{
+    ScDocShell* pShell = getDocShell();
+    ScDocument& rDoc = pShell->GetDocument();
+
+    for (SCTAB nTab=0; nTab < rDoc.GetTableCount(); nTab++)
+    {
+        const OUString& rOriginalName = aOriginalTabNames[nTab];
+
+        OUString rModifiedName;
+        rDoc.GetName(nTab, rModifiedName);
+
+        if (rOriginalName != rModifiedName)
+        {
+            renameTab(nTab, rOriginalName);
+        }
+    }
+}
+
+void XclExpXmlStream::renameTab(SCTAB aTab, OUString aNewName)
+{
+    ScDocShell* pShell = getDocShell();
+    ScDocument& rDoc = pShell->GetDocument();
+
+    bool bAutoCalcShellDisabled = rDoc.IsAutoCalcShellDisabled();
+    bool bIdleEnabled = rDoc.IsIdleEnabled();
+
+    rDoc.SetAutoCalcShellDisabled( true );
+    rDoc.EnableIdle(false);
+
+    if (rDoc.RenameTab(aTab, aNewName))
+    {
+        SfxGetpApp()->Broadcast(SfxHint(SfxHintId::ScTablesChanged));
+    }
+
+    rDoc.SetAutoCalcShellDisabled( bAutoCalcShellDisabled );
+    rDoc.EnableIdle(bIdleEnabled);
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/inc/xestream.hxx b/sc/source/filter/inc/xestream.hxx
index 3aaebd7ce776..5701039418ab 100644
--- a/sc/source/filter/inc/xestream.hxx
+++ b/sc/source/filter/inc/xestream.hxx
@@ -29,6 +29,7 @@
 #include <tools/stream.hxx>
 #include <formula/errorcodes.hxx>
 #include "ftools.hxx"
+#include <types.hxx>
 
 #include <filter/msfilter/mscodec.hxx>
 #include <vector>
@@ -338,6 +339,10 @@ private:
             WriteAttribute(nAttr, OUString(sVal, strlen(sVal), RTL_TEXTENCODING_UTF8));
     }
 
+    void validateTabNames(std::vector<OUString>& aOriginalTabNames);
+    void restoreTabNames(const std::vector<OUString>& aOriginalTabNames);
+    void renameTab(SCTAB aTab, OUString aNewName);
+
     typedef std::map< OUString,
         std::pair< OUString,
             sax_fastparser::FSHelperPtr > >     XclExpXmlPathToStateMap;


More information about the Libreoffice-commits mailing list