diff options
-rw-r--r-- | sw/inc/IDocumentMarkAccess.hxx | 2 | ||||
-rw-r--r-- | sw/qa/uibase/uno/uno.cxx | 33 | ||||
-rw-r--r-- | sw/source/core/doc/docbm.cxx | 23 | ||||
-rw-r--r-- | sw/source/core/inc/MarkManager.hxx | 1 | ||||
-rw-r--r-- | sw/source/uibase/uno/loktxdoc.cxx | 44 |
5 files changed, 101 insertions, 2 deletions
diff --git a/sw/inc/IDocumentMarkAccess.hxx b/sw/inc/IDocumentMarkAccess.hxx index 93690fb2b305..20f876d16495 100644 --- a/sw/inc/IDocumentMarkAccess.hxx +++ b/sw/inc/IDocumentMarkAccess.hxx @@ -313,6 +313,8 @@ class IDocumentMarkAccess */ virtual const_iterator_t findFirstBookmarkStartsAfter(const SwPosition& rPos) const =0; + /// Get the innermost bookmark that contains rPos. + virtual sw::mark::IMark* getBookmarkFor(const SwPosition& rPos) const = 0; // Fieldmarks /** returns a STL-like random access iterator to the begin of the sequence of fieldmarks. diff --git a/sw/qa/uibase/uno/uno.cxx b/sw/qa/uibase/uno/uno.cxx index 4b21bca0bb0c..d2be66457b81 100644 --- a/sw/qa/uibase/uno/uno.cxx +++ b/sw/qa/uibase/uno/uno.cxx @@ -442,6 +442,39 @@ CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, testGetSections) CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aTree.get_child("sections").count("")); } +CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, testGetBookmark) +{ + // Given a document with a bookmark: + createSwDoc(); + uno::Sequence<css::beans::PropertyValue> aArgs = { + comphelper::makePropertyValue("Bookmark", uno::Any(OUString("ZOTERO_BREF_1"))), + comphelper::makePropertyValue("BookmarkText", uno::Any(OUString("<p>aaa</p><p>bbb</p>"))), + }; + dispatchCommand(mxComponent, ".uno:InsertBookmark", aArgs); + + // When stepping into the bookmark with the cursor and getting the command value for + // .uno:Bookmark: + SwDoc* pDoc = getSwDoc(); + SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell(); + pWrtShell->SttEndDoc(/*bStt=*/false); + pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false); + tools::JsonWriter aJsonWriter; + std::string_view aCommand(".uno:Bookmark?namePrefix=ZOTERO_BREF_"); + auto pXTextDocument = dynamic_cast<SwXTextDocument*>(mxComponent.get()); + pXTextDocument->getCommandValues(aJsonWriter, aCommand); + + // Then make sure we find the inserted bookmark: + std::unique_ptr<char[], o3tl::free_delete> pJSON(aJsonWriter.extractData()); + std::stringstream aStream(pJSON.get()); + boost::property_tree::ptree aTree; + boost::property_tree::read_json(aStream, aTree); + boost::property_tree::ptree aBookmark = aTree.get_child("bookmark"); + // Without the accompanying fix in place, this test would have failed with: + // - No such node (bookmark) + // i.e. the returned JSON was an empty object. + CPPUNIT_ASSERT_EQUAL(std::string("ZOTERO_BREF_1"), aBookmark.get<std::string>("name")); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/doc/docbm.cxx b/sw/source/core/doc/docbm.cxx index 8e4d2ef72e95..7152c2a2314a 100644 --- a/sw/source/core/doc/docbm.cxx +++ b/sw/source/core/doc/docbm.cxx @@ -1437,6 +1437,29 @@ namespace sw::mark return dynamic_cast<IFieldmark*>(pFieldmark); } + IMark* MarkManager::getBookmarkFor(const SwPosition& rPos) const + { + auto it = std::find_if(m_vBookmarks.begin(), m_vBookmarks.end(), + [&rPos](const sw::mark::MarkBase* pMark) + { return pMark->IsCoveringPosition(rPos); }); + if (it == m_vBookmarks.end()) + { + return nullptr; + } + sw::mark::IMark* pBookmark = *it; + for (; it != m_vBookmarks.end() && (*it)->GetMarkStart() <= rPos; ++it) + { + // Find the innermost bookmark. + if (rPos < (*it)->GetMarkEnd() + && (pBookmark->GetMarkStart() < (*it)->GetMarkStart() + || (*it)->GetMarkEnd() < pBookmark->GetMarkEnd())) + { + pBookmark = *it; + } + } + return pBookmark; + } + void MarkManager::deleteFieldmarkAt(const SwPosition& rPos) { auto const pFieldmark = dynamic_cast<Fieldmark*>(getFieldmarkAt(rPos)); diff --git a/sw/source/core/inc/MarkManager.hxx b/sw/source/core/inc/MarkManager.hxx index d362036b5464..1599996ae055 100644 --- a/sw/source/core/inc/MarkManager.hxx +++ b/sw/source/core/inc/MarkManager.hxx @@ -88,6 +88,7 @@ namespace sw::mark { virtual sal_Int32 getBookmarksCount() const override; virtual const_iterator_t findBookmark(const OUString& rName) const override; virtual const_iterator_t findFirstBookmarkStartsAfter(const SwPosition& rPos) const override; + virtual ::sw::mark::IMark* getBookmarkFor(const SwPosition& rPos) const override; // Fieldmarks virtual const_iterator_t getFieldmarksBegin() const override; diff --git a/sw/source/uibase/uno/loktxdoc.cxx b/sw/source/uibase/uno/loktxdoc.cxx index a2f5b3cdd131..44b72d4f1eae 100644 --- a/sw/source/uibase/uno/loktxdoc.cxx +++ b/sw/source/uibase/uno/loktxdoc.cxx @@ -230,6 +230,41 @@ void GetBookmarks(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell, } } +/// Implements getCommandValues(".uno:Bookmark"). +/// +/// Parameters: +/// +/// - namePrefix: bookmark name prefix to not return all bookmarks +void GetBookmark(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell, + const std::map<OUString, OUString>& rArguments) +{ + OUString aNamePrefix; + { + auto it = rArguments.find("namePrefix"); + if (it != rArguments.end()) + { + aNamePrefix = it->second; + } + } + + IDocumentMarkAccess& rIDMA = *pDocShell->GetDoc()->getIDocumentMarkAccess(); + SwWrtShell* pWrtShell = pDocShell->GetWrtShell(); + SwPosition& rCursor = *pWrtShell->GetCursor()->GetPoint(); + sw::mark::IMark* pBookmark = rIDMA.getBookmarkFor(rCursor); + tools::ScopedJsonWriterNode aBookmark = rJsonWriter.startNode("bookmark"); + if (!pBookmark) + { + return; + } + + if (!pBookmark->GetName().startsWith(aNamePrefix)) + { + return; + } + + rJsonWriter.put("name", pBookmark->GetName()); +} + /// Implements getCommandValues(".uno:Fields"). /// /// Parameters: @@ -326,8 +361,8 @@ void GetSections(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell, bool SwXTextDocument::supportsCommand(std::u16string_view rCommand) { static const std::initializer_list<std::u16string_view> vForward - = { u"TextFormFields", u"TextFormField", u"SetDocumentProperties", - u"Bookmarks", u"Fields", u"Sections" }; + = { u"TextFormFields", u"TextFormField", u"SetDocumentProperties", u"Bookmarks", u"Fields", + u"Sections", u"Bookmark" }; return std::find(vForward.begin(), vForward.end(), rCommand) != vForward.end(); } @@ -342,6 +377,7 @@ void SwXTextDocument::getCommandValues(tools::JsonWriter& rJsonWriter, std::stri static constexpr OStringLiteral aBookmarks(".uno:Bookmarks"); static constexpr OStringLiteral aFields(".uno:Fields"); static constexpr OStringLiteral aSections(".uno:Sections"); + static constexpr OStringLiteral aBookmark(".uno:Bookmark"); INetURLObject aParser(OUString::fromUtf8(rCommand)); OUString aArguments = aParser.GetParam(); @@ -389,6 +425,10 @@ void SwXTextDocument::getCommandValues(tools::JsonWriter& rJsonWriter, std::stri { GetSections(rJsonWriter, m_pDocShell, aMap); } + else if (o3tl::starts_with(rCommand, aBookmark)) + { + GetBookmark(rJsonWriter, m_pDocShell, aMap); + } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |