[Libreoffice-commits] core.git: 2 commits - filter/source include/filter sw/CppunitTest_sw_ooxmlexport.mk sw/qa sw/source writerfilter/source

Miklos Vajna vmiklos at suse.cz
Mon Aug 26 04:11:38 PDT 2013


 filter/source/msfilter/util.cxx                   |   19 +++++++++++++
 include/filter/msfilter/util.hxx                  |    7 ++++
 sw/CppunitTest_sw_ooxmlexport.mk                  |    1 
 sw/qa/extras/ooxmlexport/ooxmlexport.cxx          |   14 +++++++++
 sw/source/filter/ww8/docxattributeoutput.cxx      |   31 ++++++++++++++++++++++
 sw/source/filter/ww8/docxattributeoutput.hxx      |    7 ++++
 writerfilter/source/dmapper/DomainMapper_Impl.cxx |   28 ++-----------------
 7 files changed, 83 insertions(+), 24 deletions(-)

New commits:
commit e9275c08acc2f4f1c925f78b56a1089515cd9a37
Author: Miklos Vajna <vmiklos at suse.cz>
Date:   Mon Aug 26 11:35:48 2013 +0200

    bnc#834035 DOCX export: fix hyperlinks of illustration index
    
    We used to export raw Writer bookmarks, but that's not valid in OOXML.
    Instead, it has normal bookmarks around the sequence fields, so use them
    if they are available.
    
    Change-Id: I0ef2ff7967c2802b53752c9505ef6db4cc2b8265

diff --git a/sw/CppunitTest_sw_ooxmlexport.mk b/sw/CppunitTest_sw_ooxmlexport.mk
index e96961f..2e90bec 100644
--- a/sw/CppunitTest_sw_ooxmlexport.mk
+++ b/sw/CppunitTest_sw_ooxmlexport.mk
@@ -76,6 +76,7 @@ $(eval $(call gb_CppunitTest_use_components,sw_ooxmlexport,\
     ucb/source/ucp/file/ucpfile1 \
     unotools/util/utl \
     unoxml/source/service/unoxml \
+	uui/util/uui \
     writerfilter/util/writerfilter \
     xmloff/util/xo \
 ))
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
index d5cb1cb..e4347dd 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx
@@ -112,6 +112,7 @@ public:
     void testFdo44689_start_page_7();
     void testFdo67737();
     void testTransparentShadow();
+    void testBnc834035();
 
     CPPUNIT_TEST_SUITE(Test);
 #if !defined(MACOSX) && !defined(WNT)
@@ -200,6 +201,7 @@ void Test::run()
         {"fdo44689_start_page_7.docx", &Test::testFdo44689_start_page_7},
         {"fdo67737.docx", &Test::testFdo67737},
         {"transparent-shadow.docx", &Test::testTransparentShadow},
+        {"bnc834035.odt", &Test::testBnc834035},
     };
     // Don't test the first import of these, for some reason those tests fail
     const char* aBlacklist[] = {
@@ -1233,6 +1235,18 @@ void Test::testTransparentShadow()
     CPPUNIT_ASSERT_EQUAL(sal_Int32(0x7f808080), aShadow.Color);
 }
 
+void Test::testBnc834035()
+{
+    // This is tricky, when saving manually, there are 2 hyperlinks, here only
+    // one, no idea why. That one still shows that we're not using bookmarks, though.
+
+    // Illustration index had wrong hyperlinks: anchor was using Writer's
+    // <seqname>!<index>|sequence syntax, not a bookmark name.
+    xmlDocPtr pXmlDoc = parseExport();
+    // This was Figure!1|sequence.
+    assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:hyperlink", "anchor", "_Toc363553908");
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(Test);
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index 5fa9713..2cf7058 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -706,6 +706,7 @@ void DocxAttributeOutput::DoWriteBookmarks()
             FSNS( XML_w, XML_id ), OString::number( nId ).getStr(  ),
             FSNS( XML_w, XML_name ), rName.getStr(),
             FSEND );
+        m_sLastOpenedMark = rName;
     }
     m_rMarksStart.clear();
 
@@ -835,6 +836,12 @@ void DocxAttributeOutput::StartField_Impl( FieldInfos& rInfos, bool bWriteRun )
 
 void DocxAttributeOutput::DoWriteCmd( String& rCmd )
 {
+    OUString sCmd = OUString(rCmd).trim();
+    if (sCmd.startsWith("SEQ"))
+    {
+        OUString sSeqName = msfilter::util::findQuotedText(sCmd, "SEQ ", '\\').trim();
+        m_aSeqMarksNames[sSeqName].push_back(m_sLastOpenedMark);
+    }
     // Write the Field command
     m_pSerializer->startElementNS( XML_w, XML_instrText, FSEND );
     m_pSerializer->writeEscaped( OUString( rCmd ) );
@@ -1309,8 +1316,32 @@ bool DocxAttributeOutput::StartURL( const String& rUrl, const String& rTarget )
             m_pHyperlinkAttrList->add( FSNS( XML_r, XML_id), sId.getStr());
         }
         else
+        {
+            // Is this a link to a sequence? Then try to replace that with a
+            // normal bookmark, as Word won't understand our special
+            // <seqname>!<index>|sequence syntax.
+            if (sMark.endsWith("|sequence"))
+            {
+                sal_Int32 nPos = sMark.indexOf('!');
+                if (nPos != -1)
+                {
+                    // Extract <seqname>, the field instruction text has the name quoted.
+                    OUString aSequenceName = OUString('"') + sMark.copy(0, nPos) + OUString('"');
+                    // Extract <index>.
+                    sal_uInt32 nIndex = sMark.copy(nPos + 1, sMark.getLength() - nPos - sizeof("|sequence")).toInt32();
+                    std::map<OUString, std::vector<OString> >::iterator it = m_aSeqMarksNames.find(aSequenceName);
+                    if (it != m_aSeqMarksNames.end())
+                    {
+                        std::vector<OString>& rNames = it->second;
+                        if (rNames.size() > nIndex)
+                            // We know the bookmark name for this sequence and this index, do the replacement.
+                            sMark = OStringToOUString(rNames[nIndex], RTL_TEXTENCODING_UTF8);
+                    }
+                }
+            }
             m_pHyperlinkAttrList->add( FSNS( XML_w, XML_anchor ),
                     OUStringToOString( sMark, RTL_TEXTENCODING_UTF8 ).getStr( ) );
+        }
 
         OUString sTarget( rTarget );
         if ( !sTarget.isEmpty() )
diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx
index a6c4532..5e297aa 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -649,6 +649,13 @@ private:
     /// Maps of the bookmarks ids
     std::map<OString, sal_uInt16> m_rOpenedMarksIds;
 
+    /// Name of the last opened bookmark.
+    OString m_sLastOpenedMark;
+
+    /// If there are bookmarks around sequence fields, this map contains the
+    /// names of these bookmarks for each sequence.
+    std::map<OUString, std::vector<OString> > m_aSeqMarksNames;
+
     /// The current table helper
     SwWriteTable *m_pTableWrt;
 
commit 750f0ebf97d19d1cf305dabe72d52ad6e90adf70
Author: Miklos Vajna <vmiklos at suse.cz>
Date:   Mon Aug 26 11:05:04 2013 +0200

    Introduce msfilter::util::findQuotedText()
    
    This was in writerfilter, but we'll need it soon in sw as well, so move
    it down to msfilter.
    
    Change-Id: I8efe02b6bbe8f391d9e14857ed58dbae184d5632

diff --git a/filter/source/msfilter/util.cxx b/filter/source/msfilter/util.cxx
index 9501a40..f50ec54 100644
--- a/filter/source/msfilter/util.cxx
+++ b/filter/source/msfilter/util.cxx
@@ -427,6 +427,25 @@ const ApiPaperSize& PaperSizeConv::getApiSizeForMSPaperSizeIndex( sal_Int32 nMSO
     return spPaperSizeTable[ nMSOPaperIndex ];
 }
 
+OUString findQuotedText( const OUString& rCommand,
+                const sal_Char* cStartQuote, const sal_Unicode uEndQuote )
+{
+    OUString sRet;
+    OUString sStartQuote( OUString::createFromAscii(cStartQuote) );
+    sal_Int32 nStartIndex = rCommand.indexOf( sStartQuote );
+    if( nStartIndex >= 0 )
+    {
+        sal_Int32 nStartLength = sStartQuote.getLength();
+        sal_Int32 nEndIndex = rCommand.indexOf( uEndQuote, nStartIndex + nStartLength);
+        if( nEndIndex > nStartIndex )
+        {
+            sRet = rCommand.copy( nStartIndex + nStartLength, nEndIndex - nStartIndex - nStartLength);
+        }
+    }
+    return sRet;
+
+}
+
 }
 }
 
diff --git a/include/filter/msfilter/util.hxx b/include/filter/msfilter/util.hxx
index e134199..38cdf56 100644
--- a/include/filter/msfilter/util.hxx
+++ b/include/filter/msfilter/util.hxx
@@ -88,6 +88,13 @@ public:
     static sal_Int32 getMSPaperSizeIndex( const com::sun::star::awt::Size& rSize );
     static const ApiPaperSize& getApiSizeForMSPaperSizeIndex( sal_Int32 nMSOPaperIndex );
 };
+
+/**
+ * Finds the quoted text in a field instruction text.
+ *
+ * Example: SEQ "Figure" \someoption -> "Figure"
+ */
+MSFILTER_DLLPUBLIC OUString findQuotedText( const OUString& rCommand, const sal_Char* cStartQuote, const sal_Unicode uEndQuote );
 }
 }
 
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 6f2a31e..7725b86 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -71,6 +71,7 @@
 #include <vcl/svapp.hxx>
 #include <vcl/outdev.hxx>
 #include <officecfg/Office/Common.hxx>
+#include <filter/msfilter/util.hxx>
 
 using namespace ::com::sun::star;
 using namespace ::rtl;
@@ -1822,33 +1823,12 @@ void DomainMapper_Impl::PopShapeContext()
     }
 }
 
-
-OUString lcl_FindQuotedText( const OUString& rCommand,
-                const sal_Char* cStartQuote, const sal_Unicode uEndQuote )
-{
-    OUString sRet;
-    OUString sStartQuote( OUString::createFromAscii(cStartQuote) );
-    sal_Int32 nStartIndex = rCommand.indexOf( sStartQuote );
-    if( nStartIndex >= 0 )
-    {
-        sal_Int32 nStartLength = sStartQuote.getLength();
-        sal_Int32 nEndIndex = rCommand.indexOf( uEndQuote, nStartIndex + nStartLength);
-        if( nEndIndex > nStartIndex )
-        {
-            sRet = rCommand.copy( nStartIndex + nStartLength, nEndIndex - nStartIndex - nStartLength);
-        }
-    }
-    return sRet;
-
-}
-
-
 sal_Int16 lcl_ParseNumberingType( const OUString& rCommand )
 {
     sal_Int16 nRet = style::NumberingType::PAGE_DESCRIPTOR;
 
     //  The command looks like: " PAGE \* Arabic "
-    OUString sNumber = lcl_FindQuotedText(rCommand, "\\* ", ' ');
+    OUString sNumber = msfilter::util::findQuotedText(rCommand, "\\* ", ' ');
 
     if( !sNumber.isEmpty() )
     {
@@ -1943,7 +1923,7 @@ style::NumberingType::
 OUString lcl_ParseFormat( const OUString& rCommand )
 {
     //  The command looks like: " DATE \@ "dd MMMM yyyy"
-    return lcl_FindQuotedText(rCommand, "\\@ \"", '\"');
+    return msfilter::util::findQuotedText(rCommand, "\\@ \"", '\"');
 }
 /*-------------------------------------------------------------------------
 extract a parameter (with or without quotes) between the command and the following backslash
@@ -3238,7 +3218,7 @@ void DomainMapper_Impl::CloseFieldCommand()
                         // command looks like: " SEQ Table \* ARABIC "
                         OUString sCmd(pContext->GetCommand());
                         // find the sequence name, e.g. "SEQ"
-                        OUString sSeqName = lcl_FindQuotedText(sCmd, "SEQ ", '\\');
+                        OUString sSeqName = msfilter::util::findQuotedText(sCmd, "SEQ ", '\\');
                         sSeqName = sSeqName.trim();
 
                         // create a sequence field master using the sequence name


More information about the Libreoffice-commits mailing list