[Libreoffice-commits] core.git: sw/inc sw/qa sw/source

Michael Stahl (via logerrit) logerrit at kemper.freedesktop.org
Tue Feb 2 17:17:32 UTC 2021


 sw/inc/ToxTextGenerator.hxx              |    5 -
 sw/inc/swtypes.hxx                       |    2 
 sw/qa/extras/uiwriter/data3/udindex3.odt |binary
 sw/qa/extras/uiwriter/uiwriter3.cxx      |  125 +++++++++++++++++++++++++++++++
 sw/source/core/doc/doctxm.cxx            |   10 --
 sw/source/core/inc/txmsrt.hxx            |    7 -
 sw/source/core/tox/ToxTextGenerator.cxx  |   16 +++
 sw/source/core/tox/txmsrt.cxx            |   44 ++++++++--
 sw/source/uibase/uiview/view2.cxx        |   81 ++++++++++++++++++++
 9 files changed, 269 insertions(+), 21 deletions(-)

New commits:
commit 7685c0746cf0db6f51c6a7a488f4a960f8eab3c9
Author:     Michael Stahl <michael.stahl at allotropia.de>
AuthorDate: Thu Jan 28 19:59:35 2021 +0100
Commit:     Michael Stahl <michael.stahl at allotropia.de>
CommitDate: Tue Feb 2 18:16:43 2021 +0100

    tdf#121842 sw: add hyperlinks to toxmarks in ToC/User-Defined Index
    
    The toxmark is identified by the type of index, the name of the index
    type (only for user-defined; there is only one ToC type), the text
    (either text:string-value or text content of the toxmark),
    and a counter to distinguish marks with the same text.
    
    Both text and type name can contain arbitrary characters so use U+0019
    control character as separator.
    
    Links look like: #1%19text%19Utypename|toxmark
    
    Change-Id: I5aeec727e2cd3a02d676cf3ea4c302bf7c77d319
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/110091
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.stahl at allotropia.de>

diff --git a/sw/inc/ToxTextGenerator.hxx b/sw/inc/ToxTextGenerator.hxx
index 675835573266..d3a7e9177db0 100644
--- a/sw/inc/ToxTextGenerator.hxx
+++ b/sw/inc/ToxTextGenerator.hxx
@@ -27,6 +27,7 @@
 
 #include <memory>
 #include <vector>
+#include <unordered_map>
 
 class SfxItemSet;
 class SwAttrPool;
@@ -67,7 +68,9 @@ public:
      * process @p numberOfEntriesToProcess entries.
      */
     void
-    GenerateText(SwDoc *doc, const std::vector<std::unique_ptr<SwTOXSortTabBase>>& entries,
+    GenerateText(SwDoc *doc,
+        std::unordered_map<OUString, int> & rMarkURLs,
+        const std::vector<std::unique_ptr<SwTOXSortTabBase>>& entries,
         sal_uInt16 indexOfEntryToProcess, sal_uInt16 numberOfEntriesToProcess,
         SwRootFrame const* pLayout);
 
diff --git a/sw/inc/swtypes.hxx b/sw/inc/swtypes.hxx
index 24e9c248b167..c45ce1a5a216 100644
--- a/sw/inc/swtypes.hxx
+++ b/sw/inc/swtypes.hxx
@@ -129,6 +129,8 @@ SW_DLLPUBLIC Size GetGraphicSizeTwip( const Graphic&, vcl::RenderContext* pOutDe
 const sal_Unicode cMarkSeparator = '|';
 // Sequences names for jumps are <name of sequence>!<no>
 const char cSequenceMarkSeparator = '!';
+/// separator for toxmarks: #<no>%19<text>%19<type><typename>|toxmark
+sal_Unicode const toxMarkSeparator = '\u0019';
 
 #define DB_DELIM u'\x00ff'        // Database <-> table separator.
 
diff --git a/sw/qa/extras/uiwriter/data3/udindex3.odt b/sw/qa/extras/uiwriter/data3/udindex3.odt
new file mode 100644
index 000000000000..e6c7736b91e4
Binary files /dev/null and b/sw/qa/extras/uiwriter/data3/udindex3.odt differ
diff --git a/sw/qa/extras/uiwriter/uiwriter3.cxx b/sw/qa/extras/uiwriter/uiwriter3.cxx
index f6b67313889f..87f2cc338038 100644
--- a/sw/qa/extras/uiwriter/uiwriter3.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter3.cxx
@@ -28,6 +28,8 @@
 #include <tools/json_writer.hxx>
 #include <unotools/streamwrap.hxx>
 
+#include <fmtinfmt.hxx>
+#include <view.hxx>
 #include <wrtsh.hxx>
 #include <unotxdoc.hxx>
 #include <docsh.hxx>
@@ -656,6 +658,129 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf124722)
     CPPUNIT_ASSERT_EQUAL(22, getPages());
 }
 
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testToxmarkLinks)
+{
+    load(DATA_DIRECTORY, "udindex3.odt");
+
+    SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
+    CPPUNIT_ASSERT(pTextDoc);
+    SwWrtShell& rWrtShell(*pTextDoc->GetDocShell()->GetWrtShell());
+    SwView& rView(*pTextDoc->GetDocShell()->GetView());
+
+    // update indexes
+    for (auto i = rWrtShell.GetTOXCount(); 0 < i;)
+    {
+        --i;
+        rWrtShell.UpdateTableOf(*rWrtShell.GetTOX(i));
+    }
+
+    // click on the links...
+    {
+        OUString const tmp("Table of Contents");
+        rWrtShell.GotoNextTOXBase(&tmp);
+    }
+
+    { // ToC toxmark
+        rWrtShell.Down(false);
+        SfxItemSet aSet(rWrtShell.GetAttrPool(),
+                        svl::Items<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT>{});
+        rWrtShell.GetCurAttr(aSet);
+        CPPUNIT_ASSERT(aSet.HasItem(RES_TXTATR_INETFMT));
+        rWrtShell.Push();
+        OUString const url(aSet.GetItem<SwFormatINetFormat>(RES_TXTATR_INETFMT)->GetValue());
+        CPPUNIT_ASSERT_EQUAL(OUString("#1%19the%20tocmark%19C%7Ctoxmark"), url);
+        rView.JumpToSwMark(url.copy(1)); // SfxApplication::OpenDocExec_Impl eats the "#"
+        CPPUNIT_ASSERT_EQUAL(OUString(OUStringChar(CH_TXTATR_INWORD) + "tocmark"),
+                             rWrtShell.GetCursor()->GetNode().GetTextNode()->GetText());
+        rWrtShell.Pop(SwCursorShell::PopMode::DeleteCurrent);
+    }
+
+    { // ToC heading
+        rWrtShell.Down(false);
+        SfxItemSet aSet(rWrtShell.GetAttrPool(),
+                        svl::Items<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT>{});
+        rWrtShell.GetCurAttr(aSet);
+        CPPUNIT_ASSERT(aSet.HasItem(RES_TXTATR_INETFMT));
+        rWrtShell.Push();
+        OUString const url(aSet.GetItem<SwFormatINetFormat>(RES_TXTATR_INETFMT)->GetValue());
+        CPPUNIT_ASSERT_EQUAL(OUString("#__RefHeading___Toc105_706348105"), url);
+        rView.JumpToSwMark(url.copy(1));
+        CPPUNIT_ASSERT_EQUAL(OUString("foo"),
+                             rWrtShell.GetCursor()->GetNode().GetTextNode()->GetText());
+        rWrtShell.Pop(SwCursorShell::PopMode::DeleteCurrent);
+    }
+
+    {
+        OUString const tmp("User-Defined1");
+        rWrtShell.GotoNextTOXBase(&tmp);
+    }
+
+    { // UD1 toxmark 1
+        rWrtShell.Down(false);
+        SfxItemSet aSet(rWrtShell.GetAttrPool(),
+                        svl::Items<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT>{});
+        rWrtShell.GetCurAttr(aSet);
+        CPPUNIT_ASSERT(aSet.HasItem(RES_TXTATR_INETFMT));
+        rWrtShell.Push();
+        OUString const url(aSet.GetItem<SwFormatINetFormat>(RES_TXTATR_INETFMT)->GetValue());
+        CPPUNIT_ASSERT_EQUAL(OUString("#1%19the%20udmark%19UUser-Defined%7Ctoxmark"), url);
+        rView.JumpToSwMark(url.copy(1));
+        CPPUNIT_ASSERT_EQUAL(OUString(OUStringChar(CH_TXTATR_INWORD) + "udmark the first"),
+                             rWrtShell.GetCursor()->GetNode().GetTextNode()->GetText());
+        rWrtShell.Pop(SwCursorShell::PopMode::DeleteCurrent);
+    }
+
+    { // UD1 toxmark 2 (with same text)
+        rWrtShell.Down(false);
+        SfxItemSet aSet(rWrtShell.GetAttrPool(),
+                        svl::Items<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT>{});
+        rWrtShell.GetCurAttr(aSet);
+        CPPUNIT_ASSERT(aSet.HasItem(RES_TXTATR_INETFMT));
+        rWrtShell.Push();
+        OUString const url(aSet.GetItem<SwFormatINetFormat>(RES_TXTATR_INETFMT)->GetValue());
+        CPPUNIT_ASSERT_EQUAL(OUString("#2%19the%20udmark%19UUser-Defined%7Ctoxmark"), url);
+        rView.JumpToSwMark(url.copy(1));
+        CPPUNIT_ASSERT_EQUAL(OUString(OUStringChar(CH_TXTATR_INWORD) + "udmark the 2nd"),
+                             rWrtShell.GetCursor()->GetNode().GetTextNode()->GetText());
+        rWrtShell.Pop(SwCursorShell::PopMode::DeleteCurrent);
+    }
+
+    { // UD heading
+        rWrtShell.Down(false);
+        SfxItemSet aSet(rWrtShell.GetAttrPool(),
+                        svl::Items<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT>{});
+        rWrtShell.GetCurAttr(aSet);
+        CPPUNIT_ASSERT(aSet.HasItem(RES_TXTATR_INETFMT));
+        rWrtShell.Push();
+        OUString const url(aSet.GetItem<SwFormatINetFormat>(RES_TXTATR_INETFMT)->GetValue());
+        CPPUNIT_ASSERT_EQUAL(OUString("#__RefHeading___Toc105_706348105"), url);
+        rView.JumpToSwMark(url.copy(1));
+        CPPUNIT_ASSERT_EQUAL(OUString("foo"),
+                             rWrtShell.GetCursor()->GetNode().GetTextNode()->GetText());
+        rWrtShell.Pop(SwCursorShell::PopMode::DeleteCurrent);
+    }
+
+    {
+        OUString const tmp("NewUD!|1");
+        rWrtShell.GotoNextTOXBase(&tmp);
+    }
+
+    { // UD2 toxmark, with same text as those in other UD
+        rWrtShell.Down(false);
+        SfxItemSet aSet(rWrtShell.GetAttrPool(),
+                        svl::Items<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT>{});
+        rWrtShell.GetCurAttr(aSet);
+        CPPUNIT_ASSERT(aSet.HasItem(RES_TXTATR_INETFMT));
+        rWrtShell.Push();
+        OUString const url(aSet.GetItem<SwFormatINetFormat>(RES_TXTATR_INETFMT)->GetValue());
+        CPPUNIT_ASSERT_EQUAL(OUString("#1%19the%20udmark%19UNewUD!%7C%7Ctoxmark"), url);
+        rView.JumpToSwMark(url.copy(1));
+        CPPUNIT_ASSERT_EQUAL(OUString("the udmark"),
+                             rWrtShell.GetCursor()->GetNode().GetTextNode()->GetText());
+        rWrtShell.Pop(SwCursorShell::PopMode::DeleteCurrent);
+    }
+}
+
 CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf125261)
 {
     load(DATA_DIRECTORY, "tdf125261.odt");
diff --git a/sw/source/core/doc/doctxm.cxx b/sw/source/core/doc/doctxm.cxx
index d367ce54a482..d8e7d30e80e1 100644
--- a/sw/source/core/doc/doctxm.cxx
+++ b/sw/source/core/doc/doctxm.cxx
@@ -229,11 +229,8 @@ const SwTOXMark& SwDoc::GotoTOXMark( const SwTOXMark& rCurTOXMark,
                                     SwTOXSearch eDir, bool bInReadOnly )
 {
     const SwTextTOXMark* pMark = rCurTOXMark.GetTextTOXMark();
-    OSL_ENSURE(pMark, "pMark==0 invalid TextTOXMark");
 
-    const SwTextNode *pTOXSrc = pMark->GetpTextNd();
-
-    CompareNodeContent aAbsIdx( pTOXSrc->GetIndex(), pMark->GetStart() );
+    CompareNodeContent aAbsIdx(pMark ? pMark->GetpTextNd()->GetIndex() : 0, pMark ? pMark->GetStart() : 0);
     CompareNodeContent aPrevPos( 0, 0 );
     CompareNodeContent aNextPos( ULONG_MAX, SAL_MAX_INT32 );
     CompareNodeContent aMax( 0, 0 );
@@ -256,7 +253,7 @@ const SwTOXMark& SwDoc::GotoTOXMark( const SwTOXMark& rCurTOXMark,
         if (!pMark)
             continue;
 
-        pTOXSrc = pMark->GetpTextNd();
+        SwTextNode const*const pTOXSrc = pMark->GetpTextNd();
         if (!pTOXSrc)
             continue;
 
@@ -982,6 +979,7 @@ void SwTOXBaseSection::Update(const SfxItemSet* pAttr,
 
     // Sort the List of all TOC Marks and TOC Sections
     std::vector<SwTextFormatColl*> aCollArr( GetTOXForm().GetFormMax(), nullptr );
+    std::unordered_map<OUString, int> markURLs;
     SwNodeIndex aInsPos( *pFirstEmptyNd, 1 );
     for( size_t nCnt = 0; nCnt < m_aSortArr.size(); ++nCnt )
     {
@@ -1034,7 +1032,7 @@ void SwTOXBaseSection::Update(const SfxItemSet* pAttr,
                                 sw::DefaultToxTabStopTokenHandler::TABSTOPS_RELATIVE_TO_INDENT :
                                 sw::DefaultToxTabStopTokenHandler::TABSTOPS_RELATIVE_TO_PAGE);
         sw::ToxTextGenerator ttgn(GetTOXForm(), tabStopTokenHandler);
-        ttgn.GenerateText(GetFormat()->GetDoc(), m_aSortArr, nCnt, nRange, pLayout);
+        ttgn.GenerateText(GetFormat()->GetDoc(), markURLs, m_aSortArr, nCnt, nRange, pLayout);
         nCnt += nRange - 1;
     }
 
diff --git a/sw/source/core/inc/txmsrt.hxx b/sw/source/core/inc/txmsrt.hxx
index dd8cc50412f0..c4c91b734a00 100644
--- a/sw/source/core/inc/txmsrt.hxx
+++ b/sw/source/core/inc/txmsrt.hxx
@@ -148,7 +148,7 @@ struct SwTOXSortTabBase
     virtual bool    equivalent( const SwTOXSortTabBase& );
     virtual bool    sort_lt( const SwTOXSortTabBase& );
 
-    virtual OUString  GetURL() const;
+    virtual std::pair<OUString, bool> GetURL(SwRootFrame const*const pLayout) const;
 
     virtual bool IsFullPara() const;
 
@@ -251,7 +251,7 @@ struct SwTOXPara final : public SwTOXSortTabBase
             sal_uInt16 nAuthField, SwRootFrame const* pLayout) const override;
     virtual sal_uInt16  GetLevel() const override;
 
-    virtual OUString  GetURL() const override;
+    virtual std::pair<OUString, bool> GetURL(SwRootFrame const*const pLayout) const override;
     virtual bool IsFullPara() const override;
 private:
     virtual TextAndReading GetText_Impl(SwRootFrame const* pLayout) const override;
@@ -271,7 +271,8 @@ struct SwTOXTable final : public SwTOXSortTabBase
 
     virtual sal_uInt16  GetLevel() const override;
 
-    virtual OUString  GetURL() const override;
+    virtual std::pair<OUString, bool> GetURL(SwRootFrame const*const pLayout) const override;
+
 private:
     virtual TextAndReading GetText_Impl(SwRootFrame const* pLayout) const override;
 
diff --git a/sw/source/core/tox/ToxTextGenerator.cxx b/sw/source/core/tox/ToxTextGenerator.cxx
index ba76ecdaaa62..d836ec60f238 100644
--- a/sw/source/core/tox/ToxTextGenerator.cxx
+++ b/sw/source/core/tox/ToxTextGenerator.cxx
@@ -164,7 +164,9 @@ ToxTextGenerator::GenerateTextForChapterToken(const SwFormToken& chapterToken, c
 // Add parameter <_TOXSectNdIdx> and <_pDefaultPageDesc> in order to control,
 // which page description is used, no appropriate one is found.
 void
-ToxTextGenerator::GenerateText(SwDoc* pDoc, const std::vector<std::unique_ptr<SwTOXSortTabBase>> &entries,
+ToxTextGenerator::GenerateText(SwDoc* pDoc,
+        std::unordered_map<OUString, int> & rMarkURLs,
+        const std::vector<std::unique_ptr<SwTOXSortTabBase>> &entries,
         sal_uInt16 indexOfEntryToProcess, sal_uInt16 numberOfEntriesToProcess,
         SwRootFrame const*const pLayout)
 {
@@ -239,7 +241,17 @@ ToxTextGenerator::GenerateText(SwDoc* pDoc, const std::vector<std::unique_ptr<Sw
                 break;
 
             case TOKEN_LINK_END:
-                mLinkProcessor->CloseLink(rText.getLength(), rBase.GetURL());
+                {
+                    auto [url, isMark] = rBase.GetURL(pLayout);
+                    if (isMark)
+                    {
+                        auto [iter, _] = rMarkURLs.emplace(url, 0);
+                        (void) _; // sigh... ignore it more explicitly
+                        ++iter->second;
+                        url = "#" + OUString::number(iter->second) + url;
+                    }
+                    mLinkProcessor->CloseLink(rText.getLength(), url);
+                }
                 break;
 
             case TOKEN_AUTHORITY:
diff --git a/sw/source/core/tox/txmsrt.cxx b/sw/source/core/tox/txmsrt.cxx
index 7aefd76721a9..f626f09afc40 100644
--- a/sw/source/core/tox/txmsrt.cxx
+++ b/sw/source/core/tox/txmsrt.cxx
@@ -19,6 +19,7 @@
 
 #include <unotools/charclass.hxx>
 #include <osl/diagnose.h>
+#include <rtl/uri.hxx>
 #include <txtfld.hxx>
 #include <doc.hxx>
 #include <IDocumentLayoutAccess.hxx>
@@ -179,9 +180,34 @@ SwTOXSortTabBase::SwTOXSortTabBase( TOXSortType nTyp, const SwContentNode* pNd,
     }
 }
 
-OUString SwTOXSortTabBase::GetURL() const
+std::pair<OUString, bool> SwTOXSortTabBase::GetURL(SwRootFrame const*const pLayout) const
 {
-    return OUString();
+    OUString typeName;
+    SwTOXType const& rType(*pTextMark->GetTOXMark().GetTOXType());
+    switch (rType.GetType())
+    {
+        case TOX_INDEX:
+            typeName = "A";
+            break;
+        case TOX_CONTENT:
+            typeName = "C";
+            break;
+        case TOX_USER:
+            typeName = "U" + rType.GetTypeName();
+            break;
+        default:
+            assert(false); // other tox can't have toxmarks as source
+            break;
+    }
+    OUString const decodedUrl( // counter will be added by caller!
+          OUStringChar(toxMarkSeparator) + pTextMark->GetTOXMark().GetText(pLayout)
+        + OUStringChar(toxMarkSeparator) + typeName
+        + OUStringChar(cMarkSeparator) + "toxmark" );
+
+    OUString const uri(rtl::Uri::encode(decodedUrl, rtl_UriCharClassUricNoSlash,
+        rtl_UriEncodeIgnoreEscapes, RTL_TEXTENCODING_UTF8));
+
+    return std::make_pair(uri, true);
 }
 
 bool SwTOXSortTabBase::IsFullPara() const
@@ -645,7 +671,7 @@ sal_uInt16 SwTOXPara::GetLevel() const
     return nRet;
 }
 
-OUString SwTOXPara::GetURL() const
+std::pair<OUString, bool> SwTOXPara::GetURL(SwRootFrame const*const) const
 {
     OUString aText;
     const SwContentNode* pNd = aTOXSources[0].pNd;
@@ -696,7 +722,7 @@ OUString SwTOXPara::GetURL() const
         break;
     default: break;
     }
-    return aText;
+    return std::make_pair(aText, false);
 }
 
 bool SwTOXPara::IsFullPara() const
@@ -741,21 +767,21 @@ sal_uInt16 SwTOXTable::GetLevel() const
     return nLevel;
 }
 
-OUString SwTOXTable::GetURL() const
+std::pair<OUString, bool> SwTOXTable::GetURL(SwRootFrame const*const) const
 {
     const SwNode* pNd = aTOXSources[0].pNd;
     if (!pNd)
-        return OUString();
+        return std::make_pair(OUString(), false);
 
     pNd = pNd->FindTableNode();
     if (!pNd)
-        return OUString();
+        return std::make_pair(OUString(), false);
 
     const OUString sName = static_cast<const SwTableNode*>(pNd)->GetTable().GetFrameFormat()->GetName();
     if ( sName.isEmpty() )
-        return OUString();
+        return std::make_pair(OUString(), false);
 
-    return "#" + sName + OUStringChar(cMarkSeparator) + "table";
+    return std::make_pair("#" + sName + OUStringChar(cMarkSeparator) + "table", false);
 }
 
 SwTOXAuthority::SwTOXAuthority( const SwContentNode& rNd,
diff --git a/sw/source/uibase/uiview/view2.cxx b/sw/source/uibase/uiview/view2.cxx
index 8b7e4667aae3..e76fc2f30e41 100644
--- a/sw/source/uibase/uiview/view2.cxx
+++ b/sw/source/uibase/uiview/view2.cxx
@@ -2022,6 +2022,83 @@ void SwView::EditLinkDlg()
     pDlg->Execute();
 }
 
+static auto JumpToTOXMark(SwWrtShell & rSh, OUString const& rName) -> bool
+{
+    sal_Int32 const first(rName.indexOf(toxMarkSeparator));
+    if (first == -1)
+    {
+        SAL_WARN("sw.ui", "JumpToTOXMark: missing separator");
+        return false;
+    }
+    sal_Int32 const counter(rName.copy(0, first).toInt32());
+    if (counter <= 0)
+    {
+        SAL_WARN("sw.ui", "JumpToTOXMark: invalid counter");
+        return false;
+    }
+    sal_Int32 const second(rName.indexOf(toxMarkSeparator, first + 1));
+    if (second == -1)
+    {
+        SAL_WARN("sw.ui", "JumpToTOXMark: missing separator");
+        return false;
+    }
+    OUString const entry(rName.copy(first + 1, second - (first + 1)));
+    if (rName.getLength() < second + 2)
+    {
+        SAL_WARN("sw.ui", "JumpToTOXMark: invalid tox");
+        return false;
+    }
+    sal_uInt16 const indexType(rName[second + 1]);
+    OUString const indexName(rName.copy(second + 2));
+    SwTOXType const* pType(nullptr);
+    switch (indexType)
+    {
+        case 'A':
+            pType = rSh.GetTOXType(TOX_INDEX, 0);
+            assert(pType);
+            break;
+        case 'C':
+            pType = rSh.GetTOXType(TOX_CONTENT, 0);
+            assert(pType);
+            break;
+        case 'U':
+            for (auto i = rSh.GetTOXTypeCount(TOX_USER); 0 < i; )
+            {
+                --i;
+                auto const pTmp(rSh.GetTOXType(TOX_USER, i));
+                if (pTmp->GetTypeName() == indexName)
+                {
+                    pType = pTmp;
+                    break;
+                }
+            }
+            break;
+    }
+    if (!pType)
+    {
+        SAL_WARN("sw.ui", "JumpToTOXMark: tox doesn't exist");
+        return false;
+    }
+    // type and alt text are the search keys
+    SwTOXMark tmp(pType);
+    tmp.SetAlternativeText(entry);
+    SwTOXMark const* pMark(&tmp);
+    // hack: check first if one exists
+    if (&tmp != &rSh.GetDoc()->GotoTOXMark(tmp, TOX_SAME_NXT, rSh.IsReadOnlyAvailable()))
+    {
+        for (sal_Int32 i = 0; i < counter; ++i)
+        {
+            pMark = &rSh.GotoTOXMark(*pMark, TOX_SAME_NXT);
+        }
+        return true;
+    }
+    else
+    {
+        SAL_WARN("sw.ui", "JumpToTOXMark: tox mark doesn't exist");
+        return false;
+    }
+}
+
 bool SwView::JumpToSwMark( const OUString& rMark )
 {
     bool bRet = false;
@@ -2092,6 +2169,10 @@ bool SwView::JumpToSwMark( const OUString& rMark )
                     bRet = m_pWrtShell->GotoRefMark(sName, REF_SEQUENCEFLD, nSeqNo);
                 }
             }
+            else if (sCmp == "toxmark")
+            {
+                bRet = JumpToTOXMark(*m_pWrtShell, sName);
+            }
             else if( sCmp == "text" )
             {
                 // normal text search


More information about the Libreoffice-commits mailing list