diff options
Diffstat (limited to 'sw/source/core/crsr')
27 files changed, 4783 insertions, 2876 deletions
diff --git a/sw/source/core/crsr/DateFormFieldButton.cxx b/sw/source/core/crsr/DateFormFieldButton.cxx index 5a1bb75f7733..b16845a63318 100644 --- a/sw/source/core/crsr/DateFormFieldButton.cxx +++ b/sw/source/core/crsr/DateFormFieldButton.cxx @@ -9,9 +9,9 @@ #include <DateFormFieldButton.hxx> #include <edtwin.hxx> -#include <bookmrk.hxx> +#include <bookmark.hxx> #include <tools/date.hxx> -#include <svl/zforlist.hxx> +#include <svl/numformat.hxx> #include <vcl/svapp.hxx> IMPL_LINK(DateFormFieldButton, ImplSelectHdl, weld::Calendar&, rCalendar, void) @@ -37,8 +37,8 @@ DateFormFieldButton::~DateFormFieldButton() { disposeOnce(); } void DateFormFieldButton::LaunchPopup() { - m_xFieldPopupBuilder.reset( - Application::CreateBuilder(GetFrameWeld(), "modules/swriter/ui/calendar.ui")); + m_xFieldPopupBuilder + = Application::CreateBuilder(GetFrameWeld(), "modules/swriter/ui/calendar.ui"); m_xFieldPopup = m_xFieldPopupBuilder->weld_popover("Calendar"); m_xCalendar = m_xFieldPopupBuilder->weld_calendar("date"); if (m_pDateFieldmark) diff --git a/sw/source/core/crsr/DropDownFormFieldButton.cxx b/sw/source/core/crsr/DropDownFormFieldButton.cxx index 4dd968e7ee62..2198fcf80982 100644 --- a/sw/source/core/crsr/DropDownFormFieldButton.cxx +++ b/sw/source/core/crsr/DropDownFormFieldButton.cxx @@ -9,7 +9,7 @@ #include <DropDownFormFieldButton.hxx> #include <edtwin.hxx> -#include <bookmrk.hxx> +#include <bookmark.hxx> #include <vcl/settings.hxx> #include <vcl/svapp.hxx> #include <xmloff/odffields.hxx> @@ -33,7 +33,7 @@ void DropDownFormFieldButton::InitDropdown() if (pListEntries != pParameters->end()) { pListEntries->second >>= vListEntries; - for (OUString const& i : std::as_const(vListEntries)) + for (OUString const& i : vListEntries) m_xTreeView->append_text(i); } @@ -98,8 +98,8 @@ DropDownFormFieldButton::~DropDownFormFieldButton() { disposeOnce(); } void DropDownFormFieldButton::LaunchPopup() { - m_xFieldPopupBuilder.reset( - Application::CreateBuilder(GetFrameWeld(), "modules/swriter/ui/formdropdown.ui")); + m_xFieldPopupBuilder + = Application::CreateBuilder(GetFrameWeld(), "modules/swriter/ui/formdropdown.ui"); m_xFieldPopup = m_xFieldPopupBuilder->weld_popover("FormDropDown"); m_xTreeView = m_xFieldPopupBuilder->weld_tree_view("list"); InitDropdown(); diff --git a/sw/source/core/crsr/FormFieldButton.cxx b/sw/source/core/crsr/FormFieldButton.cxx index 0f13494b648e..319dcdb9c0dd 100644 --- a/sw/source/core/crsr/FormFieldButton.cxx +++ b/sw/source/core/crsr/FormFieldButton.cxx @@ -10,7 +10,7 @@ #include <DropDownFormFieldButton.hxx> #include <edtwin.hxx> #include <basegfx/color/bcolortools.hxx> -#include <bookmrk.hxx> +#include <bookmark.hxx> #include <vcl/weldutils.hxx> #include <vcl/event.hxx> @@ -121,7 +121,7 @@ void FormFieldButton::Paint(vcl::RenderContext& rRenderContext, const tools::Rec Point aButtonPos(aFrameRect.TopLeft()); aButtonPos.AdjustX(aFrameRect.GetSize().getWidth() - 1); Size aButtonSize(aFrameRect.GetSize()); - aButtonSize.setWidth(GetSizePixel().getWidth() - aFrameRect.getWidth() - nPadding); + aButtonSize.setWidth(GetSizePixel().getWidth() - aFrameRect.getOpenWidth() - nPadding); const tools::Rectangle aButtonRect(tools::Rectangle(aButtonPos, aButtonSize)); // Background & border diff --git a/sw/source/core/crsr/annotationmark.cxx b/sw/source/core/crsr/annotationmark.cxx index ce7c03675e14..28e0bcf85b24 100644 --- a/sw/source/core/crsr/annotationmark.cxx +++ b/sw/source/core/crsr/annotationmark.cxx @@ -51,10 +51,10 @@ namespace sw::mark void AnnotationMark::InitDoc(SwDoc& io_rDoc, sw::mark::InsertMode const, SwPosition const*const) { - SwTextNode *pTextNode = GetMarkEnd().nNode.GetNode().GetTextNode(); + SwTextNode *pTextNode = GetMarkEnd().GetNode().GetTextNode(); assert(pTextNode); SwTextField *const pTextField = pTextNode->GetFieldTextAttrAt( - GetMarkEnd().nContent.GetIndex()-1, true); + GetMarkEnd().GetContentIndex()-1, ::sw::GetTextAttrMode::Default); assert(pTextField != nullptr); auto pPostItField = dynamic_cast<const SwPostItField*>(pTextField->GetFormatField().GetField()); diff --git a/sw/source/core/crsr/bookmrk.cxx b/sw/source/core/crsr/bookmark.cxx index 3a22f54180c5..60aee0b19197 100644 --- a/sw/source/core/crsr/bookmrk.cxx +++ b/sw/source/core/crsr/bookmark.cxx @@ -18,7 +18,7 @@ */ #include <memory> -#include <bookmrk.hxx> +#include <bookmark.hxx> #include <IDocumentUndoRedo.hxx> #include <IDocumentLinksAdministration.hxx> #include <IDocumentState.hxx> @@ -30,11 +30,14 @@ #include <sfx2/viewsh.hxx> #include <UndoBookmark.hxx> #include <unobookmark.hxx> +#include <utility> #include <xmloff/odffields.hxx> #include <libxml/xmlwriter.h> #include <comphelper/random.hxx> +#include <comphelper/sequence.hxx> #include <comphelper/anytostring.hxx> #include <sal/log.hxx> +#include <svl/numformat.hxx> #include <svl/zforlist.hxx> #include <edtwin.hxx> #include <DateFormFieldButton.hxx> @@ -45,6 +48,7 @@ #include <LibreOfficeKit/LibreOfficeKitEnums.h> #include <rtl/strbuf.hxx> #include <strings.hrc> +#include <tools/json_writer.hxx> using namespace ::sw::mark; using namespace ::com::sun::star; @@ -57,23 +61,23 @@ namespace sw::mark { SwPosition const& rStartPos(rMark.GetMarkStart()); SwPosition const& rEndPos(rMark.GetMarkEnd()); - SwNodes const& rNodes(rStartPos.nNode.GetNodes()); - sal_uLong const nStartNode(rStartPos.nNode.GetIndex()); - sal_uLong const nEndNode(rEndPos.nNode.GetIndex()); + SwNodes const& rNodes(rStartPos.GetNodes()); + SwNodeOffset const nStartNode(rStartPos.GetNodeIndex()); + SwNodeOffset const nEndNode(rEndPos.GetNodeIndex()); int nFields(0); std::optional<SwPosition> ret; - for (sal_uLong n = nEndNode; nStartNode <= n; --n) + for (SwNodeOffset n = nEndNode; nStartNode <= n; --n) { SwNode *const pNode(rNodes[n]); if (pNode->IsTextNode()) { SwTextNode & rTextNode(*pNode->GetTextNode()); sal_Int32 const nStart(n == nStartNode - ? rStartPos.nContent.GetIndex() + 1 + ? rStartPos.GetContentIndex() + 1 : 0); sal_Int32 const nEnd(n == nEndNode // subtract 1 to ignore the end char - ? rEndPos.nContent.GetIndex() - 1 + ? rEndPos.GetContentIndex() - 1 : rTextNode.Len()); for (sal_Int32 i = nEnd; nStart < i; --i) { @@ -93,7 +97,7 @@ namespace sw::mark if (nFields == 0) { assert(!ret); // one per field - ret = SwPosition(rTextNode, i - 1); + ret.emplace(rTextNode, i - 1); #ifndef DBG_UTIL return *ret; #endif @@ -110,7 +114,8 @@ namespace sw::mark } else { - assert(pNode->IsNoTextNode() || pNode->IsSectionNode()); + assert(pNode->IsNoTextNode() || pNode->IsSectionNode() + || (pNode->IsEndNode() && pNode->StartOfSectionNode()->IsSectionNode())); } } assert(ret); // must have found it @@ -123,20 +128,20 @@ namespace void lcl_FixPosition(SwPosition& rPos) { // make sure the position has 1) the proper node, and 2) a proper index - SwTextNode* pTextNode = rPos.nNode.GetNode().GetTextNode(); - if(pTextNode == nullptr && rPos.nContent.GetIndex() > 0) + SwTextNode* pTextNode = rPos.GetNode().GetTextNode(); + if(pTextNode == nullptr && rPos.GetContentIndex() > 0) { SAL_INFO( "sw.core", - "illegal position: " << rPos.nContent.GetIndex() + "illegal position: " << rPos.GetContentIndex() << " without proper TextNode"); rPos.nContent.Assign(nullptr, 0); } - else if(pTextNode != nullptr && rPos.nContent.GetIndex() > pTextNode->Len()) + else if(pTextNode != nullptr && rPos.GetContentIndex() > pTextNode->Len()) { SAL_INFO( "sw.core", - "illegal position: " << rPos.nContent.GetIndex() + "illegal position: " << rPos.GetContentIndex() << " is beyond " << pTextNode->Len()); rPos.nContent.Assign(pTextNode, pTextNode->Len()); } @@ -149,12 +154,16 @@ namespace if (aEndMark != CH_TXT_ATR_FORMELEMENT) { SwPosition const& rStart(rField.GetMarkStart()); - assert(rStart.nNode.GetNode().GetTextNode()->GetText()[rStart.nContent.GetIndex()] == aStartMark); (void) rStart; (void) aStartMark; + assert(rStart.GetNode().GetTextNode()->GetText()[rStart.GetContentIndex()] == aStartMark); (void) rStart; (void) aStartMark; SwPosition const sepPos(sw::mark::FindFieldSep(rField)); - assert(sepPos.nNode.GetNode().GetTextNode()->GetText()[sepPos.nContent.GetIndex()] == CH_TXT_ATR_FIELDSEP); (void) sepPos; + assert(sepPos.GetNode().GetTextNode()->GetText()[sepPos.GetContentIndex()] == CH_TXT_ATR_FIELDSEP); (void) sepPos; + } + else + { // must be m_pPos1 < m_pPos2 because of asymmetric SplitNode update + assert(rField.GetMarkPos().GetContentIndex() + 1 == rField.GetOtherMarkPos().GetContentIndex()); } SwPosition const& rEnd(rField.GetMarkEnd()); - assert(rEnd.nNode.GetNode().GetTextNode()->GetText()[rEnd.nContent.GetIndex() - 1] == aEndMark); (void) rEnd; + assert(rEnd.GetNode().GetTextNode()->GetText()[rEnd.GetContentIndex() - 1] == aEndMark); (void) rEnd; } void lcl_SetFieldMarks(Fieldmark& rField, @@ -178,7 +187,7 @@ namespace { SwPaM aStartPaM(start); io_rDoc.getIDocumentContentOperations().InsertString(aStartPaM, startChar); - start.nContent -= startChar.getLength(); // restore, it was moved by InsertString + start.AdjustContent( -startChar.getLength() ); // restore, it was moved by InsertString // do not manipulate via reference directly but call SetMarkStartPos // which works even if start and end pos were the same rField.SetMarkStartPos( start ); @@ -191,7 +200,7 @@ namespace io_rDoc.getIDocumentContentOperations().InsertString(aStartPaM, OUString(CH_TXT_ATR_FIELDSEP)); if (!pSepPos || rEnd < *pSepPos) { // rEnd is not moved automatically if it's same as insert pos - ++rEnd.nContent; + rEnd.AdjustContent(1); } } assert(pSepPos == nullptr || (start < *pSepPos && *pSepPos <= rEnd)); @@ -206,7 +215,14 @@ namespace { SwPaM aEndPaM(rEnd); io_rDoc.getIDocumentContentOperations().InsertString(aEndPaM, OUString(aEndMark)); - ++rEnd.nContent; + if (aEndMark != CH_TXT_ATR_FORMELEMENT) + { + rEnd.AdjustContent(1); // InsertString didn't move non-empty mark + } + else + { // InsertString moved the mark's end, not its start + assert(rField.GetMarkPos().GetContentIndex() + 1 == rField.GetOtherMarkPos().GetContentIndex()); + } } lcl_AssertFieldMarksSet(rField, aStartMark, aEndMark); @@ -221,7 +237,7 @@ namespace io_rDoc.GetIDocumentUndoRedo().StartUndo(SwUndoId::UI_REPLACE, nullptr); const SwPosition& rStart = rField.GetMarkStart(); - SwTextNode const*const pStartTextNode = rStart.nNode.GetNode().GetTextNode(); + SwTextNode const*const pStartTextNode = rStart.GetNode().GetTextNode(); assert(pStartTextNode); if (aEndMark != CH_TXT_ATR_FORMELEMENT) { @@ -233,11 +249,11 @@ namespace } const SwPosition& rEnd = rField.GetMarkEnd(); - SwTextNode *const pEndTextNode = rEnd.nNode.GetNode().GetTextNode(); + SwTextNode *const pEndTextNode = rEnd.GetNode().GetTextNode(); assert(pEndTextNode); const sal_Int32 nEndPos = (rEnd == rStart) - ? rEnd.nContent.GetIndex() - : rEnd.nContent.GetIndex() - 1; + ? rEnd.GetContentIndex() + : rEnd.GetContentIndex() - 1; assert(pEndTextNode->GetText()[nEndPos] == aEndMark); SwPosition const aEnd(*pEndTextNode, nEndPos); io_rDoc.GetDocumentContentOperationsManager().DeleteDummyChar(aEnd, aEndMark); @@ -247,27 +263,30 @@ namespace auto InvalidatePosition(SwPosition const& rPos) -> void { - SwUpdateAttr const aHint(rPos.nContent.GetIndex(), rPos.nContent.GetIndex(), 0); - rPos.nNode.GetNode().GetTextNode()->CallSwClientNotify(sw::LegacyModifyHint(&aHint, &aHint)); + SwUpdateAttr const aHint(rPos.GetContentIndex(), rPos.GetContentIndex(), 0); + rPos.GetNode().GetTextNode()->CallSwClientNotify(sw::LegacyModifyHint(&aHint, &aHint)); } } namespace sw::mark { MarkBase::MarkBase(const SwPaM& aPaM, - const OUString& rName) - : m_pPos1(new SwPosition(*(aPaM.GetPoint()))) - , m_aName(rName) + OUString aName) + : m_oPos1(*aPaM.GetPoint()) + , m_aName(std::move(aName)) { - m_pPos1->nContent.SetMark(this); - lcl_FixPosition(*m_pPos1); + m_oPos1->SetMark(this); + lcl_FixPosition(*m_oPos1); if (aPaM.HasMark() && (*aPaM.GetMark() != *aPaM.GetPoint())) { MarkBase::SetOtherMarkPos(*(aPaM.GetMark())); - lcl_FixPosition(*m_pPos2); + lcl_FixPosition(*m_oPos2); } } + void MarkBase::SetXBookmark(rtl::Reference<SwXBookmark> const& xBkmk) + { m_wXBookmark = xBkmk.get(); } + // For fieldmarks, the CH_TXT_ATR_FIELDSTART and CH_TXT_ATR_FIELDEND // themselves are part of the covered range. This is guaranteed by // TextFieldmark::InitDoc/lcl_AssureFieldMarksSet. @@ -278,21 +297,21 @@ namespace sw::mark void MarkBase::SetMarkPos(const SwPosition& rNewPos) { - std::make_unique<SwPosition>(rNewPos).swap(m_pPos1); - m_pPos1->nContent.SetMark(this); + m_oPos1.emplace(rNewPos); + m_oPos1->SetMark(this); } void MarkBase::SetOtherMarkPos(const SwPosition& rNewPos) { - std::make_unique<SwPosition>(rNewPos).swap(m_pPos2); - m_pPos2->nContent.SetMark(this); + m_oPos2.emplace(rNewPos); + m_oPos2->SetMark(this); } OUString MarkBase::ToString( ) const { return "Mark: ( Name, [ Node1, Index1 ] ): ( " + m_aName + ", [ " - + OUString::number( GetMarkPos().nNode.GetIndex( ) ) + ", " - + OUString::number( GetMarkPos().nContent.GetIndex( ) ) + " ] )"; + + OUString::number( sal_Int32(GetMarkPos().GetNodeIndex()) ) + ", " + + OUString::number( GetMarkPos().GetContentIndex( ) ) + " ] )"; } void MarkBase::dumpAsXml(xmlTextWriterPtr pWriter) const @@ -342,10 +361,12 @@ namespace sw::mark void MarkBase::SwClientNotify(const SwModify&, const SfxHint& rHint) { CallSwClientNotify(rHint); - auto pLegacy = dynamic_cast<const sw::LegacyModifyHint*>(&rHint); - if(pLegacy && RES_REMOVE_UNO_OBJECT == pLegacy->GetWhich()) + if (rHint.GetId() != SfxHintId::SwLegacyModify) + return; + auto pLegacy = static_cast<const sw::LegacyModifyHint*>(&rHint); + if(RES_REMOVE_UNO_OBJECT == pLegacy->GetWhich()) { // invalidate cached uno object - SetXBookmark(uno::Reference<text::XTextContent>(nullptr)); + SetXBookmark(nullptr); } } @@ -393,13 +414,33 @@ namespace sw::mark const vcl::KeyCode& rCode, const OUString& rName) : DdeBookmark(aPaM) - , ::sfx2::Metadatable() , m_aCode(rCode) , m_bHidden(false) { m_aName = rName; } + void Bookmark::sendLOKDeleteCallback() + { + if (!comphelper::LibreOfficeKit::isActive() || GetMarkPos().GetDoc().IsClipBoard()) + return; + + SfxViewShell* pViewShell = SfxViewShell::Current(); + if (!pViewShell) + return; + + OUString fieldCommand = GetName(); + tools::JsonWriter aJson; + aJson.put("commandName", ".uno:DeleteBookmark"); + aJson.put("success", true); + { + auto result = aJson.startNode("result"); + aJson.put("DeleteBookmark", fieldCommand); + } + + pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_UNO_COMMAND_RESULT, aJson.finishAndGetAsOString()); + } + void Bookmark::InitDoc(SwDoc& io_rDoc, sw::mark::InsertMode const, SwPosition const*const) { @@ -449,7 +490,8 @@ namespace sw::mark if (m_sHideCondition != rHideCondition) { m_sHideCondition = rHideCondition; - InvalidateFrames(); + // don't eval condition here yet - probably only needed for + // UI editing condition and that doesn't exist yet } } @@ -473,14 +515,14 @@ namespace sw::mark bool Bookmark::IsInContent() const { SwDoc& rDoc( GetMarkPos().GetDoc() ); - return !rDoc.IsInHeaderFooter( GetMarkPos().nNode ); + return !rDoc.IsInHeaderFooter( GetMarkPos().GetNode() ); } uno::Reference< rdf::XMetadatable > Bookmark::MakeUnoObject() { SwDoc& rDoc( GetMarkPos().GetDoc() ); const uno::Reference< rdf::XMetadatable> xMeta( - SwXBookmark::CreateXBookmark(rDoc, this), uno::UNO_QUERY); + SwXBookmark::CreateXBookmark(rDoc, this) ); return xMeta; } @@ -499,21 +541,13 @@ namespace sw::mark return SetOtherMarkPos( rNewStartPos ); } - void Fieldmark::SetMarkEndPos( const SwPosition& rNewEndPos ) - { - if ( GetMarkPos( ) <= GetOtherMarkPos( ) ) - return SetOtherMarkPos( rNewEndPos ); - else - return SetMarkPos( rNewEndPos ); - } - OUString Fieldmark::ToString( ) const { return "Fieldmark: ( Name, Type, [ Nd1, Id1 ], [ Nd2, Id2 ] ): ( " + m_aName + ", " - + m_aFieldname + ", [ " + OUString::number( GetMarkPos().nNode.GetIndex( ) ) - + ", " + OUString::number( GetMarkPos( ).nContent.GetIndex( ) ) + " ], [" - + OUString::number( GetOtherMarkPos().nNode.GetIndex( ) ) + ", " - + OUString::number( GetOtherMarkPos( ).nContent.GetIndex( ) ) + " ] ) "; + + m_aFieldname + ", [ " + OUString::number( sal_Int32(GetMarkPos().GetNodeIndex( )) ) + + ", " + OUString::number( GetMarkPos( ).GetContentIndex( ) ) + " ], [" + + OUString::number( sal_Int32(GetOtherMarkPos().GetNodeIndex( )) ) + ", " + + OUString::number( GetOtherMarkPos( ).GetContentIndex( ) ) + " ] ) "; } void Fieldmark::Invalidate( ) @@ -544,14 +578,38 @@ namespace sw::mark TextFieldmark::TextFieldmark(const SwPaM& rPaM, const OUString& rName) : Fieldmark(rPaM) + , m_pDocumentContentOperationsManager(nullptr) { if ( !rName.isEmpty() ) m_aName = rName; } + TextFieldmark::~TextFieldmark() + { + if (!comphelper::LibreOfficeKit::isActive() || GetMarkPos().GetDoc().IsClipBoard()) + return; + + SfxViewShell* pViewShell = SfxViewShell::Current(); + if (!pViewShell) + return; + + OUString fieldCommand; + (*GetParameters())[ODF_CODE_PARAM] >>= fieldCommand; + tools::JsonWriter aJson; + aJson.put("commandName", ".uno:DeleteTextFormField"); + aJson.put("success", true); + { + auto result = aJson.startNode("result"); + aJson.put("DeleteTextFormField", fieldCommand); + } + + pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_UNO_COMMAND_RESULT, aJson.finishAndGetAsOString()); + } + void TextFieldmark::InitDoc(SwDoc& io_rDoc, sw::mark::InsertMode const eMode, SwPosition const*const pSepPos) { + m_pDocumentContentOperationsManager = &io_rDoc.GetDocumentContentOperationsManager(); if (eMode == sw::mark::InsertMode::New) { lcl_SetFieldMarks(*this, io_rDoc, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FIELDEND, pSepPos); @@ -576,6 +634,45 @@ namespace sw::mark sw::UpdateFramesForRemoveDeleteRedline(rDoc, tmp); } + OUString TextFieldmark::GetContent() const + { + const SwTextNode& rTextNode = *GetMarkEnd().GetNode().GetTextNode(); + SwPosition const sepPos(sw::mark::FindFieldSep(*this)); + const sal_Int32 nStart(sepPos.GetContentIndex()); + const sal_Int32 nEnd(GetMarkEnd().GetContentIndex()); + + OUString sContent; + const sal_Int32 nLen = rTextNode.GetText().getLength(); + if (nStart + 1 < nLen && nEnd <= nLen && nEnd > nStart + 2) + sContent = rTextNode.GetText().copy(nStart + 1, nEnd - nStart - 2); + + return sContent; + } + + void TextFieldmark::ReplaceContent(const OUString& sNewContent) + { + if (!m_pDocumentContentOperationsManager) + return; + + SwPosition const sepPos(sw::mark::FindFieldSep(*this)); + const sal_Int32 nStart(sepPos.GetContentIndex()); + const sal_Int32 nEnd(GetMarkEnd().GetContentIndex()); + + const sal_Int32 nLen = GetMarkEnd().GetNode().GetTextNode()->GetText().getLength(); + if (nStart + 1 < nLen && nEnd <= nLen && nEnd > nStart + 2) + { + SwPaM aFieldPam(GetMarkStart().GetNode(), nStart + 1, + GetMarkStart().GetNode(), nEnd - 1); + m_pDocumentContentOperationsManager->ReplaceRange(aFieldPam, sNewContent, false); + } + else + { + SwPaM aFieldStartPam(GetMarkStart().GetNode(), nStart + 1); + m_pDocumentContentOperationsManager->InsertString(aFieldStartPam, sNewContent); + } + Invalidate(); + } + NonTextFieldmark::NonTextFieldmark(const SwPaM& rPaM) : Fieldmark(rPaM) { } @@ -587,12 +684,6 @@ namespace sw::mark if (eMode == sw::mark::InsertMode::New) { lcl_SetFieldMarks(*this, io_rDoc, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FORMELEMENT, pSepPos); - - // For some reason the end mark is moved from 1 by the Insert: - // we don't want this for checkboxes - SwPosition aNewEndPos = GetMarkEnd(); - aNewEndPos.nContent--; - SetMarkEndPos( aNewEndPos ); } else { @@ -613,15 +704,18 @@ namespace sw::mark } - CheckboxFieldmark::CheckboxFieldmark(const SwPaM& rPaM) + CheckboxFieldmark::CheckboxFieldmark(const SwPaM& rPaM, const OUString& rName) : NonTextFieldmark(rPaM) - { } + { + if (!rName.isEmpty()) + m_aName = rName; + } void CheckboxFieldmark::SetChecked(bool checked) { if ( IsChecked() != checked ) { - (*GetParameters())[OUString(ODF_FORMCHECKBOX_RESULT)] <<= checked; + (*GetParameters())[ODF_FORMCHECKBOX_RESULT] <<= checked; // mark document as modified SwDoc& rDoc( GetMarkPos().GetDoc() ); rDoc.getIDocumentState().SetModified(); @@ -631,12 +725,23 @@ namespace sw::mark bool CheckboxFieldmark::IsChecked() const { bool bResult = false; - parameter_map_t::const_iterator pResult = GetParameters()->find(OUString(ODF_FORMCHECKBOX_RESULT)); + parameter_map_t::const_iterator pResult = GetParameters()->find(ODF_FORMCHECKBOX_RESULT); if(pResult != GetParameters()->end()) pResult->second >>= bResult; return bResult; } + OUString CheckboxFieldmark::GetContent() const + { + return IsChecked() ? "1" : "0"; + } + + void CheckboxFieldmark::ReplaceContent(const OUString& sNewContent) + { + SetChecked(sNewContent.toBoolean()); + Invalidate(); + } + FieldmarkWithDropDownButton::FieldmarkWithDropDownButton(const SwPaM& rPaM) : NonTextFieldmark(rPaM) , m_pButton(nullptr) @@ -654,9 +759,20 @@ namespace sw::mark m_pButton.disposeAndClear(); } - DropDownFieldmark::DropDownFieldmark(const SwPaM& rPaM) + void FieldmarkWithDropDownButton::LaunchPopup() + { + if (!m_pButton) + return; + + m_pButton->Invalidate(); + m_pButton->LaunchPopup(); + } + + DropDownFieldmark::DropDownFieldmark(const SwPaM& rPaM, const OUString& rName) : FieldmarkWithDropDownButton(rPaM) { + if (!rName.isEmpty()) + m_aName = rName; } DropDownFieldmark::~DropDownFieldmark() @@ -679,6 +795,183 @@ namespace sw::mark FieldmarkWithDropDownButton::RemoveButton(); } + /** GetContent + * @param pIndex The zero-based index to retrieve + * [in] if pIndex is null or negative, return the listbox's chosen result, + * else return the indicated entry (or last entry for invalid choice). + * [out] the index of the returned result or -1 if error + */ + OUString DropDownFieldmark::GetContent(sal_Int32* pIndex) const + { + sal_Int32 nIndex = pIndex ? *pIndex : -1; + auto rParameters = *GetParameters(); + if (nIndex < 0) + rParameters[ODF_FORMDROPDOWN_RESULT] >>= nIndex; + + uno::Sequence<OUString> aSeq; + rParameters[ODF_FORMDROPDOWN_LISTENTRY] >>= aSeq; + nIndex = std::min(nIndex, aSeq.getLength() - 1); + + if (nIndex < 0) + { + if (pIndex) + *pIndex = -1; + return OUString(); + } + + if (pIndex) + *pIndex = nIndex; + + return aSeq[nIndex]; + } + + OUString DropDownFieldmark::GetContent() const + { + return GetContent(nullptr); + } + + /** AddContent : INSERTS a new choice + * @param rText: The choice to add to the list choices. + * + * @param pIndex [optional] + * [in] If pIndex is null or invalid, append to the end of the list. + * [out] Modified to point to the position of the choice if it already exists. + */ + void DropDownFieldmark::AddContent(const OUString& rText, sal_Int32* pIndex) + { + uno::Sequence<OUString> aSeq; + sw::mark::IFieldmark::parameter_map_t* pParameters = GetParameters(); + (*pParameters)[ODF_FORMDROPDOWN_LISTENTRY] >>= aSeq; + + // no duplicates: if it already exists, modify the given index to point to it + const sal_Int32 nCurrentTextPos = comphelper::findValue(aSeq, rText); + if (nCurrentTextPos != -1) + { + if (pIndex) + *pIndex = nCurrentTextPos; + return; + } + + const sal_Int32 nLen = aSeq.getLength(); + const sal_Int32 nNewPos = pIndex && *pIndex > -1 ? std::min(*pIndex, nLen) : nLen; + + // need to shift list result index up if adding new entry before it + sal_Int32 nResultIndex = -1; + (*pParameters)[ODF_FORMDROPDOWN_RESULT] >>= nResultIndex; + if (nNewPos <= nResultIndex) + (*pParameters)[ODF_FORMDROPDOWN_RESULT] <<= nResultIndex + 1; + + auto aList = comphelper::sequenceToContainer<std::vector<OUString>>(aSeq); + if (nNewPos < nLen) + aList.insert(aList.begin() + nNewPos, rText); + else + { + if (pIndex) + *pIndex = nLen; + aList.push_back(rText); + } + + (*pParameters)[ODF_FORMDROPDOWN_LISTENTRY] <<= comphelper::containerToSequence(aList); + Invalidate(); + } + + /** + * ReplaceContent : changes the list result index or renames the existing choices + * @param pText + * [in] If pIndex is null, change the list result index to this provided choice + * (but do nothing if pText is an invalid choice) + * else rename that entry. + * + * @param pIndex + * [in] If pText is null, change the list result index to this provided Index + * (or the last position if it is an invalid choice) + * else rename this entry (doing nothing for invalid indexes). + * [out] If pIndex is invalid, it is modified to use the last position. + * + * This function allows duplicate entries - which is also allowed in MS Word. + */ + void DropDownFieldmark::ReplaceContent(const OUString* pText, sal_Int32* pIndex) + { + if (!pIndex && !pText) + return; + + uno::Sequence<OUString> aSeq; + sw::mark::IFieldmark::parameter_map_t* pParameters = GetParameters(); + (*pParameters)[ODF_FORMDROPDOWN_LISTENTRY] >>= aSeq; + const sal_Int32 nLen = aSeq.getLength(); + + if (!pText) + { + if (*pIndex < 0 || *pIndex >= nLen) + *pIndex = nLen - 1; + + // select pIndex as the new value for the list box + (*pParameters)[ODF_FORMDROPDOWN_RESULT] <<= *pIndex; + Invalidate(); + return; + } + + if (!pIndex) + { + const sal_Int32 nNewPos = comphelper::findValue(aSeq, *pText); + if (nNewPos != -1) + { + (*pParameters)[ODF_FORMDROPDOWN_RESULT] <<= nNewPos; + Invalidate(); + } + return; + } + + if (*pIndex > -1 && *pIndex < nLen) + { + auto aList = comphelper::sequenceToContainer<std::vector<OUString>>(aSeq); + aList[*pIndex] = *pText; + (*pParameters)[ODF_FORMDROPDOWN_LISTENTRY] <<= comphelper::containerToSequence(aList); + Invalidate(); + } + } + + void DropDownFieldmark::ReplaceContent(const OUString& rNewContent) + { + ReplaceContent(&rNewContent, nullptr); + } + + /** + * Remove everything if the given index is negative, else remove the given index (if valid). + * If deleting the currently selected choice, reset the selection to the first choice. + */ + void DropDownFieldmark::DelContent(sal_Int32 nDelIndex) + { + sw::mark::IFieldmark::parameter_map_t* pParameters = GetParameters(); + uno::Sequence<OUString> aSeq; + if (nDelIndex < 0) + { + pParameters->erase(ODF_FORMDROPDOWN_RESULT); + (*pParameters)[ODF_FORMDROPDOWN_LISTENTRY] <<= aSeq; + Invalidate(); + return; + } + + (*pParameters)[ODF_FORMDROPDOWN_LISTENTRY] >>= aSeq; + if (nDelIndex >= aSeq.getLength()) + return; + + // If deleting the current choice, select the first entry instead + // else need to shift list result index down if deleting an entry before it + sal_Int32 nResultIndex = -1; + (*pParameters)[ODF_FORMDROPDOWN_RESULT] >>= nResultIndex; + if (nDelIndex == nResultIndex) + nResultIndex = 0; + else if (nDelIndex < nResultIndex) + --nResultIndex; + + comphelper::removeElementAt(aSeq, nDelIndex); + if (nResultIndex != -1) + (*pParameters)[ODF_FORMDROPDOWN_RESULT] <<= nResultIndex; + (*pParameters)[ODF_FORMDROPDOWN_LISTENTRY] <<= aSeq; + Invalidate(); + } + void DropDownFieldmark::SetPortionPaintArea(const SwRect& rPortionPaintArea) { m_aPortionPaintArea = rPortionPaintArea; @@ -689,7 +982,7 @@ namespace sw::mark } } - void DropDownFieldmark::SendLOKShowMessage(SfxViewShell* pViewShell) + void DropDownFieldmark::SendLOKShowMessage(const SfxViewShell* pViewShell) { if (!comphelper::LibreOfficeKit::isActive()) return; @@ -714,7 +1007,7 @@ namespace sw::mark if (pListEntriesIter != pParameters->end()) { pListEntriesIter->second >>= vListEntries; - for (const OUString& sItem : std::as_const(vListEntries)) + for (const OUString& sItem : vListEntries) sPayload.append("\"" + OUStringToOString(sItem, RTL_TEXTENCODING_UTF8) + "\", "); sPayload.setLength(sPayload.getLength() - 2); } @@ -731,13 +1024,13 @@ namespace sw::mark // Placeholder text sPayload.append("\"placeholderText\": \"" + OUStringToOString(SwResId(STR_DROP_DOWN_EMPTY_LIST), RTL_TEXTENCODING_UTF8) + "\"}}"); - pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_FORM_FIELD_BUTTON, sPayload.toString().getStr()); + pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_FORM_FIELD_BUTTON, sPayload.toString()); } - void DropDownFieldmark::SendLOKHideMessage(SfxViewShell* pViewShell) + void DropDownFieldmark::SendLOKHideMessage(const SfxViewShell* pViewShell) { - OString sPayload = "{\"action\": \"hide\", \"type\": \"drop-down\"}"; - pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_FORM_FIELD_BUTTON, sPayload.getStr()); + pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_FORM_FIELD_BUTTON, + "{\"action\": \"hide\", \"type\": \"drop-down\"}"_ostr); } DateFieldmark::DateFieldmark(const SwPaM& rPaM) @@ -824,10 +1117,10 @@ namespace sw::mark OUString DateFieldmark::GetContent() const { - const SwTextNode* const pTextNode = GetMarkEnd().nNode.GetNode().GetTextNode(); + const SwTextNode* const pTextNode = GetMarkEnd().GetNode().GetTextNode(); SwPosition const sepPos(sw::mark::FindFieldSep(*this)); - const sal_Int32 nStart(sepPos.nContent.GetIndex()); - const sal_Int32 nEnd (GetMarkEnd().nContent.GetIndex()); + const sal_Int32 nStart(sepPos.GetContentIndex()); + const sal_Int32 nEnd (GetMarkEnd().GetContentIndex()); OUString sContent; if(nStart + 1 < pTextNode->GetText().getLength() && nEnd <= pTextNode->GetText().getLength() && @@ -841,21 +1134,21 @@ namespace sw::mark if(!m_pDocumentContentOperationsManager) return; - const SwTextNode* const pTextNode = GetMarkEnd().nNode.GetNode().GetTextNode(); + const SwTextNode* const pTextNode = GetMarkEnd().GetNode().GetTextNode(); SwPosition const sepPos(sw::mark::FindFieldSep(*this)); - const sal_Int32 nStart(sepPos.nContent.GetIndex()); - const sal_Int32 nEnd (GetMarkEnd().nContent.GetIndex()); + const sal_Int32 nStart(sepPos.GetContentIndex()); + const sal_Int32 nEnd (GetMarkEnd().GetContentIndex()); if(nStart + 1 < pTextNode->GetText().getLength() && nEnd <= pTextNode->GetText().getLength() && nEnd > nStart + 2) { - SwPaM aFieldPam(GetMarkStart().nNode, nStart + 1, - GetMarkStart().nNode, nEnd - 1); + SwPaM aFieldPam(GetMarkStart().GetNode(), nStart + 1, + GetMarkStart().GetNode(), nEnd - 1); m_pDocumentContentOperationsManager->ReplaceRange(aFieldPam, sNewContent, false); } else { - SwPaM aFieldStartPam(GetMarkStart().nNode, nStart + 1); + SwPaM aFieldStartPam(GetMarkStart().GetNode(), nStart + 1); m_pDocumentContentOperationsManager->InsertString(aFieldStartPam, sNewContent); } diff --git a/sw/source/core/crsr/callnk.cxx b/sw/source/core/crsr/callnk.cxx index 955622409af8..e3f08add1e30 100644 --- a/sw/source/core/crsr/callnk.cxx +++ b/sw/source/core/crsr/callnk.cxx @@ -31,15 +31,16 @@ #include <ndtxt.hxx> #include <flyfrm.hxx> #include <breakit.hxx> +#include <UndoTable.hxx> SwCallLink::SwCallLink( SwCursorShell & rSh ) : m_rShell( rSh ) { // remember SPoint-values of current cursor SwPaM* pCursor = m_rShell.IsTableMode() ? m_rShell.GetTableCrs() : m_rShell.GetCursor(); - SwNode& rNd = pCursor->GetPoint()->nNode.GetNode(); + SwNode& rNd = pCursor->GetPoint()->GetNode(); m_nNode = rNd.GetIndex(); - m_nContent = pCursor->GetPoint()->nContent.GetIndex(); + m_nContent = pCursor->GetPoint()->GetContentIndex(); m_nNodeType = rNd.GetNodeType(); m_bHasSelection = ( *pCursor->GetPoint() != *pCursor->GetMark() ); @@ -60,24 +61,36 @@ SwCallLink::SwCallLink( SwCursorShell & rSh ) } } -static void lcl_notifyRow(const SwContentNode* pNode, SwCursorShell & rShell) +namespace sw { + +/** + An empty paragraph inside a table with a nested table preceding it + should be hidden, unless the cursor is positioned in the paragraph. + + If the cursor is now (or was previously) inside such a paragraph, + send a size change notification on the row frame to force reformatting. + */ +void NotifyTableCollapsedParagraph(const SwContentNode *const pNode, SwCursorShell *const pShell) { if ( !pNode ) return; - SwFrame *const pMyFrame = pNode->getLayoutFrame( rShell.GetLayout() ); + SwFrame *const pMyFrame = pNode->getLayoutFrame(pShell ? pShell->GetLayout() : nullptr); if ( !pMyFrame ) return; - // We need to emulated a change of the row height in order - // to have the complete row redrawn + // important: only invalidate layout if something is actually hidden or + // shown! Otherwise performance is going to suffer with "difficult" tables. + if (!pMyFrame->IsCollapse()) + return; + SwRowFrame *const pRow = pMyFrame->FindRowFrame(); if ( !pRow ) return; const SwTableLine* pLine = pRow->GetTabLine( ); - if (rShell.IsTableMode() || (rShell.StartsWithTable() && rShell.ExtendedSelectedAll())) + if (pShell && (pShell->IsTableMode() || (pShell->StartsWith_() != SwCursorShell::StartsWith::None && pShell->ExtendedSelectedAll()))) { // If we have a table selection, then avoid the notification: it's not necessary (the text // cursor needs no updating) and the notification may kill the selection overlay, leading to @@ -86,11 +99,14 @@ static void lcl_notifyRow(const SwContentNode* pNode, SwCursorShell & rShell) return; } + // notify a change in frame size to force reformatting of the row const SwFormatFrameSize aSize = pLine->GetFrameFormat()->GetFrameSize(); pRow->OnFrameSize(aSize); } -SwCallLink::~SwCallLink() COVERITY_NOEXCEPT_FALSE +} // namespace sw + +void SwCallLink::ImplDestroy() { if( m_nNodeType == SwNodeType::NONE || !m_rShell.m_bCallChgLnk ) // see ctor return ; @@ -98,23 +114,25 @@ SwCallLink::~SwCallLink() COVERITY_NOEXCEPT_FALSE // If travelling over Nodes check formats and register them anew at the // new Node. SwPaM* pCurrentCursor = m_rShell.IsTableMode() ? m_rShell.GetTableCrs() : m_rShell.GetCursor(); - SwContentNode * pCNd = pCurrentCursor->GetContentNode(); + SwContentNode * pCNd = pCurrentCursor->GetPointContentNode(); if( !pCNd ) return; - lcl_notifyRow(pCNd, m_rShell); - - const SwDoc *pDoc=m_rShell.GetDoc(); - const SwContentNode *pNode = nullptr; - if ( pDoc && m_nNode < pDoc->GetNodes( ).Count( ) ) + if (pCNd->GetIndex() != m_nNode) // only if moved to different node { - pNode = pDoc->GetNodes()[m_nNode]->GetContentNode(); + ::sw::NotifyTableCollapsedParagraph(pCNd, &m_rShell); + + const SwDoc *pDoc=m_rShell.GetDoc(); + if (sal_Int32(m_nNode) < sal_Int32(pDoc->GetNodes().Count())) + { + const SwContentNode *const pNode = pDoc->GetNodes()[m_nNode]->GetContentNode(); + ::sw::NotifyTableCollapsedParagraph(pNode, &m_rShell); + } } - lcl_notifyRow(pNode, m_rShell); - sal_Int32 nCmp, nCurrentContent = pCurrentCursor->GetPoint()->nContent.GetIndex(); + sal_Int32 nCmp, nCurrentContent = pCurrentCursor->GetPoint()->GetContentIndex(); SwNodeType nNdWhich = pCNd->GetNodeType(); - sal_uLong nCurrentNode = pCurrentCursor->GetPoint()->nNode.GetIndex(); + SwNodeOffset nCurrentNode = pCurrentCursor->GetPoint()->GetNodeIndex(); // Register the Shell as dependent at the current Node. By doing this all // attribute changes can be signaled over the link. @@ -221,6 +239,11 @@ SwCallLink::~SwCallLink() COVERITY_NOEXCEPT_FALSE m_rShell.GetFlyMacroLnk().Call( pFlyFrame->GetFormat() ); } +SwCallLink::~SwCallLink() +{ + suppress_fun_call_w_exception(ImplDestroy()); +} + tools::Long SwCallLink::getLayoutFrame(const SwRootFrame* pRoot, SwTextNode const & rNd, sal_Int32 nCntPos, bool /*bCalcFrame*/) { diff --git a/sw/source/core/crsr/callnk.hxx b/sw/source/core/crsr/callnk.hxx index ca47821c147f..3614816749ad 100644 --- a/sw/source/core/crsr/callnk.hxx +++ b/sw/source/core/crsr/callnk.hxx @@ -21,8 +21,8 @@ #define INCLUDED_SW_SOURCE_CORE_CRSR_CALLNK_HXX #include <tools/long.hxx> -#include <tools/solar.h> #include <ndtyp.hxx> +#include <nodeoffset.hxx> class SwCursorShell; class SwTextNode; @@ -32,16 +32,18 @@ class SwCallLink { public: SwCursorShell & m_rShell; - sal_uLong m_nNode; + SwNodeOffset m_nNode; + tools::Long m_nLeftFramePos; sal_Int32 m_nContent; SwNodeType m_nNodeType; - tools::Long m_nLeftFramePos; bool m_bHasSelection; explicit SwCallLink( SwCursorShell & rSh ); - ~SwCallLink() COVERITY_NOEXCEPT_FALSE; + ~SwCallLink(); static tools::Long getLayoutFrame( const SwRootFrame*, SwTextNode const & rNd, sal_Int32 nCntPos, bool bCalcFrame ); +private: + void ImplDestroy(); }; #endif // INCLUDED_SW_SOURCE_CORE_CRSR_CALLNK_HXX diff --git a/sw/source/core/crsr/contentcontrolbutton.cxx b/sw/source/core/crsr/contentcontrolbutton.cxx new file mode 100644 index 000000000000..0d805cb492c3 --- /dev/null +++ b/sw/source/core/crsr/contentcontrolbutton.cxx @@ -0,0 +1,179 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <contentcontrolbutton.hxx> + +#include <utility> +#include <vcl/weldutils.hxx> +#include <vcl/event.hxx> +#include <vcl/decoview.hxx> + +#include <edtwin.hxx> +#include <dview.hxx> + +SwContentControlButton::SwContentControlButton(SwEditWin* pEditWin, + std::shared_ptr<SwContentControl> pContentControl) + : Control(pEditWin, WB_DIALOGCONTROL) + , m_pContentControl(std::move(pContentControl)) +{ + assert(GetParent()); + assert(dynamic_cast<SwEditWin*>(GetParent())); + + SetBackground(); + EnableChildTransparentMode(); + SetParentClipMode(ParentClipMode::NoClip); + SetPaintTransparent(true); +} + +SwContentControlButton::~SwContentControlButton() { disposeOnce(); } + +void SwContentControlButton::LaunchPopup() +{ + m_xPopup->connect_closed(LINK(this, SwContentControlButton, PopupModeEndHdl)); + + tools::Rectangle aRect(Point(0, 0), GetSizePixel()); + weld::Window* pParent = weld::GetPopupParent(*this, aRect); + m_xPopup->popup_at_rect(pParent, aRect); +} + +void SwContentControlButton::DestroyPopup() +{ + m_xPopup.reset(); + m_xPopupBuilder.reset(); +} + +void SwContentControlButton::dispose() +{ + DestroyPopup(); + Control::dispose(); +} + +void SwContentControlButton::CalcPosAndSize(const SwRect& rPortionPaintArea) +{ + assert(GetParent()); + + Point aBoxPos = GetParent()->LogicToPixel(rPortionPaintArea.Pos()); + Size aBoxSize = GetParent()->LogicToPixel(rPortionPaintArea.SSize()); + + // First calculate the size of the frame around the content control's last portion + int nPadding = aBoxSize.Height() / 4; + aBoxPos.AdjustX(-nPadding / 2); + aBoxPos.AdjustY(-1); + aBoxSize.AdjustWidth(nPadding); + aBoxSize.AdjustHeight(2); + + m_aFramePixel = tools::Rectangle(aBoxPos, aBoxSize); + + // Then extend the size with the button area + if (m_bRTL) + { + aBoxPos.AdjustX(-GetParent()->LogicToPixel(rPortionPaintArea.SSize()).Height()); + } + aBoxSize.AdjustWidth(GetParent()->LogicToPixel(rPortionPaintArea.SSize()).Height()); + + if (aBoxPos != GetPosPixel() || aBoxSize != GetSizePixel()) + { + SetPosSizePixel(aBoxPos, aBoxSize); + Invalidate(); + } +} + +void SwContentControlButton::MouseButtonDown(const MouseEvent&) { StartPopup(); } + +void SwContentControlButton::StartPopup() +{ + if (m_xPopup) // tdf#152257 already launched, don't relaunch + return; + LaunchPopup(); + Invalidate(); +} + +IMPL_LINK_NOARG(SwContentControlButton, PopupModeEndHdl, weld::Popover&, void) +{ + DestroyPopup(); + Show(false); + Invalidate(); +} + +void SwContentControlButton::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&) +{ + SetMapMode(MapMode(MapUnit::MapPixel)); + + Color aLineColor = COL_BLACK; + Color aFillColor = aLineColor; + aFillColor.IncreaseLuminance(255 * (m_xPopup ? 0.5 : 0.75)); + + // Calc the frame around the content control's last portion + int nPadding = 1; + Point aPos(nPadding, nPadding); + Size aSize(m_aFramePixel.GetSize().Width() - nPadding, + m_aFramePixel.GetSize().Height() - nPadding); + const tools::Rectangle aFrameRect(tools::Rectangle(aPos, aSize)); + + // Draw the button next to the frame + Point aButtonPos(aFrameRect.TopLeft()); + if (m_bRTL) + { + aButtonPos.AdjustX(nPadding * 2); + } + else + { + aButtonPos.AdjustX(aFrameRect.GetSize().getWidth() - nPadding * 2); + } + Size aButtonSize(aFrameRect.GetSize()); + aButtonSize.setWidth(GetSizePixel().getWidth() - aFrameRect.getOpenWidth() - nPadding); + const tools::Rectangle aButtonRect(tools::Rectangle(aButtonPos, aButtonSize)); + + // Background & border + rRenderContext.SetLineColor(aLineColor); + rRenderContext.SetFillColor(aFillColor); + rRenderContext.DrawRect(aButtonRect); + + // the arrowhead + DecorationView aDecoView(&rRenderContext); + tools::Rectangle aSymbolRect(aButtonRect); + // 20% distance to the left and right button border + const tools::Long nBorderDistanceLeftAndRight = aSymbolRect.GetWidth() / 4; + aSymbolRect.AdjustLeft(nBorderDistanceLeftAndRight); + aSymbolRect.AdjustRight(-nBorderDistanceLeftAndRight); + // 20% distance to the top and bottom button border + const tools::Long nBorderDistanceTopAndBottom = aSymbolRect.GetHeight() / 4; + aSymbolRect.AdjustTop(nBorderDistanceTopAndBottom); + aSymbolRect.AdjustBottom(-nBorderDistanceTopAndBottom); + AntialiasingFlags eAntialiasing = rRenderContext.GetAntialiasing(); + if (SwDrawView::IsAntiAliasing()) + { + rRenderContext.SetAntialiasing(eAntialiasing | AntialiasingFlags::Enable); + } + aDecoView.DrawSymbol(aSymbolRect, SymbolType::SPIN_DOWN, GetTextColor(), DrawSymbolFlags::NONE); + if (SwDrawView::IsAntiAliasing()) + { + rRenderContext.SetAntialiasing(eAntialiasing); + } +} + +WindowHitTest SwContentControlButton::ImplHitTest(const Point& rFramePos) +{ + // We need to check whether the position hits the button (the frame should be mouse transparent) + WindowHitTest aResult = Control::ImplHitTest(rFramePos); + if (aResult != WindowHitTest::Inside) + return aResult; + else + { + if (m_bRTL) + { + return rFramePos.X() <= m_aFramePixel.Left() ? WindowHitTest::Inside + : WindowHitTest::Transparent; + } + return rFramePos.X() >= m_aFramePixel.Right() ? WindowHitTest::Inside + : WindowHitTest::Transparent; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/crsr/crbm.cxx b/sw/source/core/crsr/crbm.cxx index 1b60a3f7e290..15b1bba2b1b6 100644 --- a/sw/source/core/crsr/crbm.cxx +++ b/sw/source/core/crsr/crbm.cxx @@ -26,14 +26,12 @@ #include <IDocumentMarkAccess.hxx> #include <IDocumentSettingAccess.hxx> -using namespace std; - namespace { struct CursorStateHelper { explicit CursorStateHelper(SwCursorShell const & rShell) - : m_pCursor(rShell.GetSwCursor()) + : m_pCursor(rShell.GetCursor()) , m_aSaveState(*m_pCursor) { } @@ -130,9 +128,14 @@ bool IsMarkHidden(SwRootFrame const& rLayout, ::sw::mark::IMark const& rMark) { return false; } - SwTextNode const& rNode(*rMark.GetMarkPos().nNode.GetNode().GetTextNode()); + SwNode const& rNode(rMark.GetMarkPos().GetNode()); + SwTextNode const*const pTextNode(rNode.GetTextNode()); + if (pTextNode == nullptr) + { // UNO_BOOKMARK may point to table node + return rNode.GetRedlineMergeFlag() == SwNode::Merge::Hidden; + } SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>( - rNode.getLayoutFrame(&rLayout))); + pTextNode->getLayoutFrame(&rLayout))); if (!pFrame) { return true; @@ -140,21 +143,21 @@ bool IsMarkHidden(SwRootFrame const& rLayout, ::sw::mark::IMark const& rMark) if (rMark.IsExpanded()) { SwTextFrame const*const pOtherFrame(static_cast<SwTextFrame const*>( - rMark.GetOtherMarkPos().nNode.GetNode().GetTextNode()->getLayoutFrame(&rLayout))); + rMark.GetOtherMarkPos().GetNode().GetTextNode()->getLayoutFrame(&rLayout))); return pFrame == pOtherFrame && pFrame->MapModelToViewPos(rMark.GetMarkPos()) == pFrame->MapModelToViewPos(rMark.GetOtherMarkPos()); } else { - if (rMark.GetMarkPos().nContent.GetIndex() == rNode.Len()) + if (rMark.GetMarkPos().GetContentIndex() == pTextNode->Len()) { // at end of node: never deleted (except if node deleted) - return rNode.GetRedlineMergeFlag() == SwNode::Merge::Hidden; + return pTextNode->GetRedlineMergeFlag() == SwNode::Merge::Hidden; } else { // check character following mark pos return pFrame->MapModelToViewPos(rMark.GetMarkPos()) - == pFrame->MapModelToView(&rNode, rMark.GetMarkPos().nContent.GetIndex() + 1); + == pFrame->MapModelToView(pTextNode, rMark.GetMarkPos().GetContentIndex() + 1); } } } @@ -283,31 +286,34 @@ bool SwCursorShell::IsFormProtected() ::sw::mark::IFieldmark* SwCursorShell::GetCurrentFieldmark() { // TODO: Refactor - SwPosition pos(*GetCursor()->GetPoint()); - return getIDocumentMarkAccess()->getFieldmarkFor(pos); + SwPosition pos(*GetCursor()->Start()); + return getIDocumentMarkAccess()->getInnerFieldmarkFor(pos); } -::sw::mark::IFieldmark* SwCursorShell::GetFieldmarkAfter() +sw::mark::IFieldmark* SwCursorShell::GetFieldmarkAfter() { SwPosition pos(*GetCursor()->GetPoint()); - return getIDocumentMarkAccess()->getFieldmarkAfter(pos); + return getIDocumentMarkAccess()->getFieldmarkAfter(pos, /*bLoop*/true); } -::sw::mark::IFieldmark* SwCursorShell::GetFieldmarkBefore() +sw::mark::IFieldmark* SwCursorShell::GetFieldmarkBefore() { SwPosition pos(*GetCursor()->GetPoint()); - return getIDocumentMarkAccess()->getFieldmarkBefore(pos); + return getIDocumentMarkAccess()->getFieldmarkBefore(pos, /*bLoop*/true); } -bool SwCursorShell::GotoFieldmark(::sw::mark::IFieldmark const * const pMark) +bool SwCursorShell::GotoFieldmark(::sw::mark::IFieldmark const * const pMark, bool completeSelection) { if(pMark==nullptr) return false; // watch Cursor-Moves CursorStateHelper aCursorSt(*this); aCursorSt.SetCursorToMark(pMark); - ++aCursorSt.m_pCursor->GetPoint()->nContent; - --aCursorSt.m_pCursor->GetMark()->nContent; + if (!completeSelection || aCursorSt.m_pCursor->HasReadonlySel(false, false)) + { + aCursorSt.m_pCursor->GetPoint()->AdjustContent(+1); + aCursorSt.m_pCursor->GetMark()->AdjustContent(-1); + } if(aCursorSt.RollbackIfIllegal()) return false; diff --git a/sw/source/core/crsr/crossrefbookmark.cxx b/sw/source/core/crsr/crossrefbookmark.cxx index 55b77bf4ccb3..8b61f709eb02 100644 --- a/sw/source/core/crsr/crossrefbookmark.cxx +++ b/sw/source/core/crsr/crossrefbookmark.cxx @@ -24,10 +24,11 @@ #include <IDocumentMarkAccess.hxx> #include <crossrefbookmark.hxx> #include <ndtxt.hxx> +#include <o3tl/string_view.hxx> namespace { - constexpr OUStringLiteral CrossRefNumItemBookmark_NamePrefix = u"__RefNumPara__"; + constexpr OUString CrossRefNumItemBookmark_NamePrefix = u"__RefNumPara__"_ustr; } namespace sw::mark @@ -45,15 +46,15 @@ namespace sw::mark "- creation of cross-reference bookmark with an illegal PaM that does not expand over exactly one whole paragraph."); if(rName.isEmpty()) m_aName = MarkBase::GenerateNewName(rPrefix); - assert(!m_pPos2); + assert(!m_oPos2); } void CrossRefBookmark::SetMarkPos(const SwPosition& rNewPos) { - assert(rNewPos.nNode.GetNode().GetTextNode() && + assert(rNewPos.GetNode().GetTextNode() && "<sw::mark::CrossRefBookmark::SetMarkPos(..)>" " - new bookmark position for cross-reference bookmark doesn't mark text node"); - assert(rNewPos.nContent.GetIndex() == 0 && + assert(rNewPos.GetContentIndex() == 0 && "<sw::mark::CrossRefBookmark::SetMarkPos(..)>" " - new bookmark position for cross-reference bookmark doesn't mark start of text node"); MarkBase::SetMarkPos(rNewPos); @@ -70,12 +71,12 @@ namespace sw::mark CrossRefHeadingBookmark::CrossRefHeadingBookmark(const SwPaM& rPaM, const vcl::KeyCode& rCode, const OUString& rName) - : CrossRefBookmark(rPaM, rCode, rName, OUString(IDocumentMarkAccess::GetCrossRefHeadingBookmarkNamePrefix()+"_Toc")) + : CrossRefBookmark(rPaM, rCode, rName, Concat2View(IDocumentMarkAccess::GetCrossRefHeadingBookmarkNamePrefix()+"_Toc")) { } - bool CrossRefHeadingBookmark::IsLegalName(const OUString& rName) + bool CrossRefHeadingBookmark::IsLegalName(std::u16string_view rName) { - return rName.match(IDocumentMarkAccess::GetCrossRefHeadingBookmarkNamePrefix()); + return o3tl::starts_with(rName, IDocumentMarkAccess::GetCrossRefHeadingBookmarkNamePrefix()); } CrossRefNumItemBookmark::CrossRefNumItemBookmark(const SwPaM& rPaM, @@ -84,9 +85,9 @@ namespace sw::mark : CrossRefBookmark(rPaM, rCode, rName, CrossRefNumItemBookmark_NamePrefix) { } - bool CrossRefNumItemBookmark::IsLegalName(const OUString& rName) + bool CrossRefNumItemBookmark::IsLegalName(std::u16string_view rName) { - return rName.match(CrossRefNumItemBookmark_NamePrefix); + return o3tl::starts_with(rName, CrossRefNumItemBookmark_NamePrefix); } } diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx index a7d4d2474613..58aa478d4d43 100644 --- a/sw/source/core/crsr/crsrsh.cxx +++ b/sw/source/core/crsr/crsrsh.cxx @@ -17,7 +17,8 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#include <memory> +#include <config_wasm_strip.h> + #include <com/sun/star/text/XTextRange.hpp> #include <hintids.hxx> @@ -54,7 +55,8 @@ #include <unotextrange.hxx> #include <vcl/svapp.hxx> #include <vcl/settings.hxx> -#include <IGrammarContact.hxx> +#include <GrammarContact.hxx> +#include <OnlineAccessibilityCheck.hxx> #include <comphelper/flagguard.hxx> #include <strings.hrc> #include <IDocumentLayoutAccess.hxx> @@ -72,11 +74,12 @@ #include <tabcol.hxx> #include <wrtsh.hxx> #include <undobj.hxx> -#include <boost/property_tree/json_parser.hpp> +#include <view.hxx> #include <hints.hxx> +#include <tools/json_writer.hxx> +#include <redline.hxx> using namespace com::sun::star; -using namespace util; /** * Check if pCurrentCursor points into already existing ranges and delete those. @@ -84,8 +87,7 @@ using namespace util; */ static void CheckRange( SwCursor* pCurrentCursor ) { - const SwPosition *pStt = pCurrentCursor->Start(), - *pEnd = pCurrentCursor->GetPoint() == pStt ? pCurrentCursor->GetMark() : pCurrentCursor->GetPoint(); + auto [pStt, pEnd] = pCurrentCursor->StartEnd(); // SwPosition* SwPaM *pTmpDel = nullptr, *pTmp = pCurrentCursor->GetNext(); @@ -93,9 +95,7 @@ static void CheckRange( SwCursor* pCurrentCursor ) // Search the complete ring while( pTmp != pCurrentCursor ) { - const SwPosition *pTmpStt = pTmp->Start(), - *pTmpEnd = pTmp->GetPoint() == pTmpStt ? - pTmp->GetMark() : pTmp->GetPoint(); + auto [pTmpStt, pTmpEnd] = pTmp->StartEnd(); // SwPosition* if( *pStt <= *pTmpStt ) { if( *pEnd > *pTmpStt || @@ -169,7 +169,7 @@ void SwCursorShell::DestroyCursor() * Simply returns the current shell cursor if there is no selection * (HasSelection()). */ -SwPaM & SwCursorShell::CreateNewShellCursor() +SwCursor & SwCursorShell::CreateNewShellCursor() { if (HasSelection()) { @@ -182,29 +182,29 @@ SwPaM & SwCursorShell::CreateNewShellCursor() * Return the current shell cursor * @return - returns current `SwPaM` shell cursor */ -SwPaM & SwCursorShell::GetCurrentShellCursor() +SwCursor & SwCursorShell::GetCurrentShellCursor() { return *GetCursor(); } /** * Return pointer to the current shell cursor - * @return - returns pointer to current `SwPaM` shell cursor + * @return - returns pointer to current `SwCursor` shell cursor */ -SwPaM* SwCursorShell::GetCursor( bool bMakeTableCursor ) const +SwCursor* SwCursorShell::GetCursor( bool bMakeTableCursor ) const { if( m_pTableCursor ) { if( bMakeTableCursor && m_pTableCursor->IsCursorMovedUpdate() ) { //don't re-create 'parked' cursors - if( m_pTableCursor->GetPoint()->nNode.GetIndex() && - m_pTableCursor->GetMark()->nNode.GetIndex() ) + if( m_pTableCursor->GetPoint()->GetNodeIndex() && + m_pTableCursor->GetMark()->GetNodeIndex() ) { - const SwContentNode* pCNd = m_pTableCursor->GetContentNode(); + const SwContentNode* pCNd = m_pTableCursor->GetPointContentNode(); if( pCNd && pCNd->getLayoutFrame( GetLayout() ) ) { - pCNd = m_pTableCursor->GetContentNode(false); + pCNd = m_pTableCursor->GetMarkContentNode(); if( pCNd && pCNd->getLayoutFrame( GetLayout() ) ) { SwShellTableCursor* pTC = m_pTableCursor; @@ -228,9 +228,9 @@ void SwCursorShell::StartAction() if( !ActionPend() ) { // save for update of the ribbon bar - const SwNode& rNd = m_pCurrentCursor->GetPoint()->nNode.GetNode(); + const SwNode& rNd = m_pCurrentCursor->GetPoint()->GetNode(); m_nCurrentNode = rNd.GetIndex(); - m_nCurrentContent = m_pCurrentCursor->GetPoint()->nContent.GetIndex(); + m_nCurrentContent = m_pCurrentCursor->GetPoint()->GetContentIndex(); m_nCurrentNdTyp = rNd.GetNodeType(); if( rNd.IsTextNode() ) m_nLeftFramePos = SwCallLink::getLayoutFrame( GetLayout(), *rNd.GetTextNode(), m_nCurrentContent, true ); @@ -242,11 +242,11 @@ void SwCursorShell::StartAction() void SwCursorShell::EndAction( const bool bIdleEnd ) { - comphelper::FlagRestorationGuard g(mbSelectAll, StartsWithTable() && ExtendedSelectedAll()); + comphelper::FlagRestorationGuard g(mbSelectAll, StartsWith_() != StartsWith::None && ExtendedSelectedAll()); bool bVis = m_bSVCursorVis; // Idle-formatting? - if( bIdleEnd && Imp()->GetRegion() ) + if( bIdleEnd && Imp()->HasPaintRegion() ) { m_pCurrentCursor->Hide(); } @@ -320,7 +320,7 @@ void SwCursorShell::EndCursorMove( const bool bIdleEnd ) #endif } -bool SwCursorShell::LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode, +bool SwCursorShell::LeftRight( bool bLeft, sal_uInt16 nCnt, SwCursorSkipMode nMode, bool bVisualAllowed ) { if( IsTableMode() ) @@ -346,13 +346,13 @@ bool SwCursorShell::LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode, // 2. CASE: Cursor is at beginning of numbered paragraph. A move // to the left will simply set the bInFrontOfLabel flag: else if (bLeft - && pShellCursor->GetPoint()->nNode.GetNode().IsTextNode() + && pShellCursor->GetPoint()->GetNode().IsTextNode() && static_cast<SwTextFrame const*>( - pShellCursor->GetPoint()->nNode.GetNode().GetTextNode()->getLayoutFrame(GetLayout()) + pShellCursor->GetPoint()->GetNode().GetTextNode()->getLayoutFrame(GetLayout()) )->MapModelToViewPos(*pShellCursor->GetPoint()) == TextFrameIndex(0) && !pShellCursor->IsInFrontOfLabel() && !pShellCursor->HasMark() - && nullptr != (pTextNd = sw::GetParaPropsNode(*GetLayout(), pShellCursor->GetPoint()->nNode)) + && nullptr != (pTextNd = sw::GetParaPropsNode(*GetLayout(), pShellCursor->GetPoint()->GetNode())) && pTextNd->HasVisibleNumberingOrBullet()) { SetInFrontOfLabel( true ); @@ -391,12 +391,18 @@ void SwCursorShell::MarkListLevel( const OUString& sListId, if (sListId == m_sMarkedListId && nListLevel == m_nMarkedListLevel) return; - if ( !m_sMarkedListId.isEmpty() ) - mxDoc->MarkListLevel( m_sMarkedListId, m_nMarkedListLevel, false ); - - if ( !sListId.isEmpty() ) + // Writer redraws the "marked" list with the field shading, if there + // is no field shading then the marked list would be redrawn for no + // visually identifiable reason, so skip the mark if field shadings + // are disabled. + const bool bVisuallyMarked(GetViewOptions()->IsFieldShadings()); + if (bVisuallyMarked) { - mxDoc->MarkListLevel( sListId, nListLevel, true ); + if ( !m_sMarkedListId.isEmpty() ) + mxDoc->MarkListLevel( m_sMarkedListId, m_nMarkedListLevel, false ); + + if ( !sListId.isEmpty() ) + mxDoc->MarkListLevel( sListId, nListLevel, true ); } m_sMarkedListId = sListId; @@ -406,7 +412,7 @@ void SwCursorShell::MarkListLevel( const OUString& sListId, void SwCursorShell::UpdateMarkedListLevel() { SwTextNode const*const pTextNd = sw::GetParaPropsNode(*GetLayout(), - GetCursor_()->GetPoint()->nNode); + GetCursor_()->GetPoint()->GetNode()); if ( !pTextNd ) return; @@ -523,7 +529,7 @@ bool SwCursorShell::UpDown( bool bUp, sal_uInt16 nCnt ) if( !bTableMode ) eUpdateMode = static_cast<CursorFlag>(eUpdateMode | SwCursorShell::UPDOWN | SwCursorShell::CHKRANGE); - UpdateCursor( static_cast<sal_uInt16>(eUpdateMode) ); + UpdateCursor( o3tl::narrowing<sal_uInt16>(eUpdateMode) ); } } return bRet; @@ -547,8 +553,8 @@ bool SwCursorShell::LRMargin( bool bLeft, bool bAPI) if ( bLeft && !bTableMode && bRet && bWasAtLM && !GetCursor_()->HasMark() ) { - const SwTextNode * pTextNd = GetCursor_()->GetNode().GetTextNode(); - assert(sw::GetParaPropsNode(*GetLayout(), GetCursor_()->GetPoint()->nNode) == pTextNd); + const SwTextNode * pTextNd = GetCursor_()->GetPointNode().GetTextNode(); + assert(sw::GetParaPropsNode(*GetLayout(), GetCursor_()->GetPoint()->GetNode()) == pTextNd); if ( pTextNd && pTextNd->HasVisibleNumberingOrBullet() ) SetInFrontOfLabel( true ); } @@ -591,43 +597,331 @@ bool SwCursorShell::SttEndDoc( bool bStt ) return bRet; } +const SwTableNode* SwCursorShell::IsCursorInTable() const +{ + if (m_pTableCursor && m_pTableCursor->GetSelectedBoxesCount()) + { // find the table that has the selected boxes + return m_pTableCursor->GetSelectedBoxes()[0]->GetSttNd()->FindTableNode(); + } + return m_pCurrentCursor->GetPointNode().FindTableNode(); +} + +// fun cases to consider: +// * outermost table +// - into para => SA/ESA +// - into prev/next table => continue... +// - no prev/next => done +// * inner table +// - into containing cell => SA/ESA +// - into prev/next of containing cell +// + into para +// + into table nested in prev/next cell +// - out of table -> as above +// => iterate in one direction until a node is reached that is a parent or a sibling of a parent of the current table +// - parent reached => SA/ESA depending +// - not in parent but in *prev/next* sibling of outer cell => TrySelectOuterTable +// - not in parent but in *prev/next* sibling of outer table => TrySelectOuterTable +// => select-all cannot select a sequence of table with no para at same level; only 1 table +// - no parent, no prev/next => TrySelectOuterTable + +bool SwCursorShell::MoveOutOfTable() +{ + SwPosition const point(*getShellCursor(false)->GetPoint()); + SwPosition const mark(*getShellCursor(false)->GetMark()); + + for (auto const fnMove : {&fnMoveBackward, &fnMoveForward}) + { + Push(); + SwCursor *const pCursor(getShellCursor(false)); + + pCursor->Normalize(fnMove == &fnMoveBackward); + pCursor->DeleteMark(); + SwTableNode const*const pTable(pCursor->GetPoint()->GetNode().FindTableNode()); + assert(pTable); + while (MovePara(GoInContent, *fnMove)) + { + SwStartNode const*const pBox(pCursor->GetPoint()->GetNode().FindTableBoxStartNode()); + if (!pBox) + { + Pop(SwCursorShell::PopMode::DeleteStack); + return true; // moved to paragraph at top-level of text + } + if (pBox->GetIndex() < pTable->GetIndex() + && pTable->EndOfSectionIndex() < pBox->EndOfSectionIndex()) + { + Pop(SwCursorShell::PopMode::DeleteStack); + return true; // pBox contains start position (pTable) + } + } + + Pop(SwCursorShell::PopMode::DeleteCurrent); + // FIXME: Pop doesn't restore original cursor if nested tables + *getShellCursor(false)->GetPoint() = point; + getShellCursor(false)->SetMark(); + *getShellCursor(false)->GetMark() = mark; + } + return false; +} + +bool SwCursorShell::TrySelectOuterTable() +{ + assert(m_pTableCursor); + SwTableNode const& rInnerTable(*m_pTableCursor->GetPoint()->GetNode().FindTableNode()); + SwNodes const& rNodes(rInnerTable.GetNodes()); + SwTableNode const*const pOuterTable(rInnerTable.GetNodes()[rInnerTable.GetIndex()-1]->FindTableNode()); + if (!pOuterTable) + { + return false; + } + + // manually select boxes of pOuterTable + SwNodeIndex firstCell(*pOuterTable, +1); + SwNodeIndex lastCell(*rNodes[pOuterTable->EndOfSectionIndex()-1]->StartOfSectionNode()); + SwSelBoxes aNew; + pOuterTable->GetTable().CreateSelection(&firstCell.GetNode(), &lastCell.GetNode(), + aNew, SwTable::SEARCH_NONE, false); + // set table cursor to 1st / last content which may be in inner table + SwContentNode* const pStart = SwNodes::GoNext(&firstCell); + assert(pStart); // must at least find the previous point node + lastCell = *lastCell.GetNode().EndOfSectionNode(); + SwContentNode *const pEnd = SwNodes::GoPrevious(&lastCell); + assert(pEnd); // must at least find the previous point node + delete m_pTableCursor; + m_pTableCursor = new SwShellTableCursor(*this, SwPosition(*pStart, 0), Point(), + SwPosition(*pEnd, 0), Point()); + m_pTableCursor->ActualizeSelection( aNew ); + m_pTableCursor->IsCursorMovedUpdate(); // clear this so GetCursor() doesn't recreate our SwSelBoxes + + // this will update m_pCurrentCursor based on m_pTableCursor + UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY); + + return true; +} + +/// find XText start node +static SwStartNode const* FindTextStart(SwPosition const& rPos) +{ + SwStartNode const* pStartNode(rPos.GetNode().StartOfSectionNode()); + while (pStartNode && (pStartNode->IsSectionNode() || pStartNode->IsTableNode())) + { + pStartNode = pStartNode->StartOfSectionNode(); + } + return pStartNode; +} + +static SwStartNode const* FindParentText(SwShellCursor const& rCursor) +{ + // find closest section containing both start and end - ignore Sections + SwStartNode const* pStartNode(FindTextStart(*rCursor.Start())); + SwEndNode const* pEndNode(FindTextStart(*rCursor.End())->EndOfSectionNode()); + while (pStartNode->EndOfSectionNode()->GetIndex() < pEndNode->GetIndex()) + { + pStartNode = pStartNode->StartOfSectionNode(); + } + while (pStartNode->GetIndex() < pEndNode->StartOfSectionNode()->GetIndex()) + { + pEndNode = pEndNode->StartOfSectionNode()->StartOfSectionNode()->EndOfSectionNode(); + } + assert(pStartNode->EndOfSectionNode() == pEndNode); + + return (pStartNode->IsSectionNode() || pStartNode->IsTableNode()) + ? FindTextStart(SwPosition(*pStartNode)) + : pStartNode; +} + +bool SwCursorShell::MoveStartText() +{ + SwPosition const old(*m_pCurrentCursor->GetPoint()); + SwStartNode const*const pStartNode(FindParentText(*getShellCursor(false))); + assert(pStartNode); + SwTableNode const*const pTable(pStartNode->FindTableNode()); + m_pCurrentCursor->GetPoint()->Assign(*pStartNode); + SwNodes::GoNext(m_pCurrentCursor->GetPoint()); + while (m_pCurrentCursor->GetPoint()->GetNode().FindTableNode() != pTable + && (!pTable || pTable->GetIndex() < m_pCurrentCursor->GetPoint()->GetNode().FindTableNode()->GetIndex()) + && MoveOutOfTable()); + UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY); + return old != *m_pCurrentCursor->GetPoint(); +} + +// select all inside the current XText, with table or hidden para at start/end void SwCursorShell::ExtendedSelectAll(bool bFootnotes) { + // find common ancestor node of both ends of cursor + SwStartNode const*const pStartNode(FindParentText(*getShellCursor(false))); + assert(pStartNode); + if (IsTableMode()) + { // convert m_pTableCursor to m_pCurrentCursor after determining pStartNode + TableCursorToCursor(); + } SwNodes& rNodes = GetDoc()->GetNodes(); + m_pCurrentCursor->Normalize(true); SwPosition* pPos = m_pCurrentCursor->GetPoint(); - pPos->nNode = bFootnotes ? rNodes.GetEndOfPostIts() : rNodes.GetEndOfAutotext(); - pPos->nContent.Assign( rNodes.GoNext( &pPos->nNode ), 0 ); + pPos->Assign(bFootnotes ? rNodes.GetEndOfPostIts() : static_cast<SwNode const&>(*pStartNode)); + SwNodes::GoNext(pPos); pPos = m_pCurrentCursor->GetMark(); - pPos->nNode = rNodes.GetEndOfContent(); - SwContentNode* pCNd = SwNodes::GoPrevious( &pPos->nNode ); - pPos->nContent.Assign( pCNd, pCNd ? pCNd->Len() : 0 ); + pPos->Assign(bFootnotes ? rNodes.GetEndOfContent() : static_cast<SwNode const&>(*pStartNode->EndOfSectionNode())); + SwContentNode* pCNd = SwNodes::GoPrevious( pPos ); + if (pCNd) + pPos->AssignEndIndex(*pCNd); } -bool SwCursorShell::ExtendedSelectedAll() +static typename SwCursorShell::StartsWith StartsWith(SwStartNode const& rStart) { + for (auto i = rStart.GetIndex() + 1; i < rStart.EndOfSectionIndex(); ++i) + { + SwNode const& rNode(*rStart.GetNodes()[i]); + switch (rNode.GetNodeType()) + { + case SwNodeType::Section: + if (rNode.GetSectionNode()->GetSection().IsHidden()) + return SwCursorShell::StartsWith::HiddenSection; + continue; + case SwNodeType::Table: + return SwCursorShell::StartsWith::Table; + case SwNodeType::Text: + if (rNode.GetTextNode()->IsHidden()) + { + return SwCursorShell::StartsWith::HiddenPara; + } + return SwCursorShell::StartsWith::None; + default: + return SwCursorShell::StartsWith::None; + } + } + return SwCursorShell::StartsWith::None; +} + +static typename SwCursorShell::StartsWith EndsWith(SwStartNode const& rStart) +{ + for (auto i = rStart.EndOfSectionIndex() - 1; rStart.GetIndex() < i; --i) + { + SwNode const& rNode(*rStart.GetNodes()[i]); + switch (rNode.GetNodeType()) + { + case SwNodeType::End: + if (auto pStartNode = rNode.StartOfSectionNode(); pStartNode->IsTableNode()) + { + return SwCursorShell::StartsWith::Table; + } + else if (pStartNode->IsSectionNode()) + { + if (pStartNode->GetSectionNode()->GetSection().IsHidden()) + return SwCursorShell::StartsWith::HiddenSection; + } + //TODO buggy SwUndoRedline in testTdf137503? assert(rNode.StartOfSectionNode()->IsSectionNode()); + break; + case SwNodeType::Text: + if (rNode.GetTextNode()->IsHidden()) + { + return SwCursorShell::StartsWith::HiddenPara; + } + return SwCursorShell::StartsWith::None; + default: + return SwCursorShell::StartsWith::None; + } + } + return SwCursorShell::StartsWith::None; +} + +// return the node that is the start of the extended selection (to include table +// or section start nodes; looks like extending for end nodes is not required) +::std::optional<::std::pair<SwNode const*, ::std::vector<SwTableNode*>>> +SwCursorShell::ExtendedSelectedAll() const +{ + if (m_pTableCursor) + { + return {}; + } + SwNodes& rNodes = GetDoc()->GetNodes(); - SwNodeIndex nNode = rNodes.GetEndOfAutotext(); - SwContentNode* pStart = rNodes.GoNext(&nNode); + SwShellCursor const*const pShellCursor = getShellCursor(false); + SwStartNode const* pStartNode(FindParentText(*pShellCursor)); + + SwNodeIndex nNode(*pStartNode); + SwContentNode* pStart = SwNodes::GoNext(&nNode); if (!pStart) - return false; + { + return {}; + } - nNode = rNodes.GetEndOfContent(); + nNode = *pStartNode->EndOfSectionNode(); SwContentNode* pEnd = SwNodes::GoPrevious(&nNode); if (!pEnd) - return false; + { + return {}; + } SwPosition aStart(*pStart, 0); SwPosition aEnd(*pEnd, pEnd->Len()); - SwShellCursor* pShellCursor = getShellCursor(false); - return aStart == *pShellCursor->Start() && aEnd == *pShellCursor->End(); + if (!(aStart == *pShellCursor->Start() && aEnd == *pShellCursor->End())) + { + return {}; + } + + auto const ends(::EndsWith(*pStartNode)); + if (::StartsWith(*pStartNode) == StartsWith::None + && ends == StartsWith::None) + { + return {}; // "ordinary" selection will work + } + + ::std::vector<SwTableNode*> tablesAtEnd; + if (ends == StartsWith::Table) + { + SwNode * pLastNode(rNodes[pStartNode->EndOfSectionIndex() - 1]); + while (pLastNode->IsEndNode()) + { + SwNode *const pNode(pLastNode->StartOfSectionNode()); + if (pNode->IsTableNode()) + { + tablesAtEnd.push_back(pNode->GetTableNode()); + pLastNode = rNodes[pNode->GetIndex() - 1]; + } + else if (pNode->IsSectionNode()) + { + pLastNode = rNodes[pLastNode->GetIndex() - 1]; + } + } + assert(!tablesAtEnd.empty()); + } + + // tdf#133990 ensure directly containing section is included in SwUndoDelete + while (pStartNode->IsSectionNode() + && pStartNode->GetIndex() == pStartNode->StartOfSectionNode()->GetIndex() + 1 + && pStartNode->EndOfSectionNode()->GetIndex() + 1 == pStartNode->StartOfSectionNode()->EndOfSectionNode()->GetIndex()) + { + pStartNode = pStartNode->StartOfSectionNode(); + } + + // pStartNode is the node that fully contains the selection - the first + // node of the selection is the first node inside pStartNode + return ::std::make_pair(rNodes[pStartNode->GetIndex() + 1], tablesAtEnd); } -bool SwCursorShell::StartsWithTable() +typename SwCursorShell::StartsWith SwCursorShell::StartsWith_() { - SwNodes& rNodes = GetDoc()->GetNodes(); - SwNodeIndex nNode(rNodes.GetEndOfExtras()); - SwContentNode* pContentNode = rNodes.GoNext(&nNode); - return pContentNode->FindTableNode(); + SwShellCursor const*const pShellCursor = getShellCursor(false); + // first, check if this is invalid; ExtendedSelectAll(true) may result in + // a) an ordinary selection that is valid + // b) a selection that is extended + // c) a selection that is invalid and will cause FindParentText to loop + SwNode const& rEndOfExtras(GetDoc()->GetNodes().GetEndOfExtras()); + if (pShellCursor->Start()->nNode.GetIndex() <= rEndOfExtras.GetIndex() + && rEndOfExtras.GetIndex() < pShellCursor->End()->nNode.GetIndex()) + { + return StartsWith::None; // *very* extended, no ExtendedSelectedAll handling! + } + SwStartNode const*const pStartNode(FindParentText(*pShellCursor)); + if (auto const ret = ::StartsWith(*pStartNode); ret != StartsWith::None) + { + return ret; + } + if (auto const ret = ::EndsWith(*pStartNode); ret != StartsWith::None) + { + return ret; + } + return StartsWith::None; } bool SwCursorShell::MovePage( SwWhichPage fnWhichPage, SwPosPage fnPosPage ) @@ -643,7 +937,7 @@ bool SwCursorShell::MovePage( SwWhichPage fnWhichPage, SwPosPage fnPosPage ) SwCursorSaveState aSaveState( *m_pCurrentCursor ); Point& rPt = m_pCurrentCursor->GetPtPos(); std::pair<Point, bool> tmp(rPt, false); - SwContentFrame * pFrame = m_pCurrentCursor->GetContentNode()-> + SwContentFrame * pFrame = m_pCurrentCursor->GetPointContentNode()-> getLayoutFrame(GetLayout(), m_pCurrentCursor->GetPoint(), &tmp); if( pFrame && GetFrameInPage( pFrame, fnWhichPage, fnPosPage, m_pCurrentCursor ) && !m_pCurrentCursor->IsSelOvr( SwCursorSelOverFlags::Toggle | @@ -656,21 +950,21 @@ bool SwCursorShell::MovePage( SwWhichPage fnWhichPage, SwPosPage fnPosPage ) return bRet; } -bool SwCursorShell::isInHiddenTextFrame(SwShellCursor* pShellCursor) +bool SwCursorShell::isInHiddenFrame(SwShellCursor* pShellCursor) { - SwContentNode *pCNode = pShellCursor->GetContentNode(); + SwContentNode *pCNode = pShellCursor->GetPointContentNode(); std::pair<Point, bool> tmp(pShellCursor->GetPtPos(), false); SwContentFrame *const pFrame = pCNode ? pCNode->getLayoutFrame(GetLayout(), pShellCursor->GetPoint(), &tmp) : nullptr; - return !pFrame || (pFrame->IsTextFrame() && static_cast<SwTextFrame*>(pFrame)->IsHiddenNow()); + return !pFrame || pFrame->IsHiddenNow(); } // sw_redlinehide: this should work for all cases: GoCurrPara, GoNextPara, GoPrevPara static bool IsAtStartOrEndOfFrame(SwCursorShell const*const pShell, SwShellCursor const*const pShellCursor, SwMoveFnCollection const& fnPosPara) { - SwContentNode *const pCNode = pShellCursor->GetContentNode(); + SwContentNode *const pCNode = pShellCursor->GetPointContentNode(); assert(pCNode); // surely can't have moved otherwise? std::pair<Point, bool> tmp(pShellCursor->GetPtPos(), false); SwContentFrame const*const pFrame = pCNode->getLayoutFrame( @@ -704,7 +998,7 @@ bool SwCursorShell::MovePara(SwWhichPara fnWhichPara, SwMoveFnCollection const & //which is what SwCursorShell::UpdateCursorPos will reset //the position to if we pass it a position in an //invisible hidden paragraph field - while (isInHiddenTextFrame(pTmpCursor) + while (isInHiddenFrame(pTmpCursor) || !IsAtStartOrEndOfFrame(this, pTmpCursor, fnPosPara)) { if (!pTmpCursor->MovePara(fnWhichPara, fnPosPara)) @@ -730,10 +1024,10 @@ bool SwCursorShell::MoveSection( SwWhichSection fnWhichSect, // position cursor -static SwFrame* lcl_IsInHeaderFooter( const SwNodeIndex& rIdx, Point& rPt ) +static SwFrame* lcl_IsInHeaderFooter( SwNode& rNd, Point& rPt ) { SwFrame* pFrame = nullptr; - SwContentNode* pCNd = rIdx.GetNode().GetContentNode(); + SwContentNode* pCNd = rNd.GetContentNode(); if( pCNd ) { std::pair<Point, bool> tmp(rPt, false); @@ -751,13 +1045,13 @@ static SwFrame* lcl_IsInHeaderFooter( const SwNodeIndex& rIdx, Point& rPt ) bool SwCursorShell::IsInHeaderFooter( bool* pbInHeader ) const { Point aPt; - SwFrame* pFrame = ::lcl_IsInHeaderFooter( m_pCurrentCursor->GetPoint()->nNode, aPt ); + SwFrame* pFrame = ::lcl_IsInHeaderFooter( m_pCurrentCursor->GetPoint()->GetNode(), aPt ); if( pFrame && pbInHeader ) *pbInHeader = pFrame->IsHeaderFrame(); return nullptr != pFrame; } -int SwCursorShell::SetCursor( const Point &rLPt, bool bOnlyText, bool bBlock ) +int SwCursorShell::SetCursor(const Point& rLPt, bool bOnlyText, bool bBlock, bool bFieldInfo) { CurrShell aCurr( this ); @@ -768,8 +1062,10 @@ int SwCursorShell::SetCursor( const Point &rLPt, bool bOnlyText, bool bBlock ) SwCursorMoveState aTmpState( IsTableMode() ? CursorMoveState::TableSel : bOnlyText ? CursorMoveState::SetOnlyText : CursorMoveState::NONE ); aTmpState.m_bSetInReadOnly = IsReadOnlyAvailable(); + aTmpState.m_bFieldInfo = bFieldInfo; // always set cursor at field-start if point is over field + aTmpState.m_bPosMatchesBounds = bFieldInfo; // always set cursor at character-start if over char - SwTextNode const*const pTextNd = sw::GetParaPropsNode(*GetLayout(), pCursor->GetPoint()->nNode); + SwTextNode const*const pTextNd = sw::GetParaPropsNode(*GetLayout(), pCursor->GetPoint()->GetNode()); if ( pTextNd && !IsTableMode() && // #i37515# No bInFrontOfLabel during selection @@ -795,9 +1091,9 @@ int SwCursorShell::SetCursor( const Point &rLPt, bool bOnlyText, bool bBlock ) if( CursorMoveState::RightMargin == aTmpState.m_eState ) m_eMvState = CursorMoveState::RightMargin; // is the new position in header or footer? - SwFrame* pFrame = lcl_IsInHeaderFooter( aPos.nNode, aPt ); - if( IsTableMode() && !pFrame && aPos.nNode.GetNode().StartOfSectionNode() == - pCursor->GetPoint()->nNode.GetNode().StartOfSectionNode() ) + SwFrame* pFrame = lcl_IsInHeaderFooter( aPos.GetNode(), aPt ); + if( IsTableMode() && !pFrame && aPos.GetNode().StartOfSectionNode() == + pCursor->GetPoint()->GetNode().StartOfSectionNode() ) // same table column and not in header/footer -> back return bRet; @@ -817,17 +1113,17 @@ int SwCursorShell::SetCursor( const Point &rLPt, bool bOnlyText, bool bBlock ) { if( pFrame ) { - if( pFrame->getFrameArea().IsInside( rCurrentCursorPt )) + if( pFrame->getFrameArea().Contains( rCurrentCursorPt )) return bRet; } - else if( aPos.nNode.GetNode().IsContentNode() ) + else if( aPos.GetNode().IsContentNode() ) { // in the same frame? std::pair<Point, bool> tmp(m_aCharRect.Pos(), false); - SwFrame* pOld = static_cast<SwContentNode&>(aPos.nNode.GetNode()).getLayoutFrame( + SwFrame* pOld = static_cast<SwContentNode&>(aPos.GetNode()).getLayoutFrame( GetLayout(), nullptr, &tmp); tmp.first = aPt; - SwFrame* pNew = static_cast<SwContentNode&>(aPos.nNode.GetNode()).getLayoutFrame( + SwFrame* pNew = static_cast<SwContentNode&>(aPos.GetNode()).getLayoutFrame( GetLayout(), nullptr, &tmp); if( pNew == pOld ) return bRet; @@ -837,8 +1133,8 @@ int SwCursorShell::SetCursor( const Point &rLPt, bool bOnlyText, bool bBlock ) else { // SSelection over not allowed sections or if in header/footer -> different - if( !CheckNodesRange( aPos.nNode, pCursor->GetMark()->nNode, true ) - || ( pFrame && !pFrame->getFrameArea().IsInside( pCursor->GetMkPos() ) )) + if( !CheckNodesRange( aPos.GetNode(), pCursor->GetMark()->GetNode(), true ) + || ( pFrame && !pFrame->getFrameArea().Contains( pCursor->GetMkPos() ) )) return bRet; // is at same position but not in header/footer @@ -995,7 +1291,7 @@ bool SwCursorShell::TestCurrPam( // check if the SPoint is in a table selection if( m_pTableCursor ) - return m_pTableCursor->IsInside( rPt ); + return m_pTableCursor->Contains( rPt ); SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed // search position <rPt> in document @@ -1004,6 +1300,7 @@ bool SwCursorShell::TestCurrPam( SwCursorMoveState aTmpState( CursorMoveState::NONE ); aTmpState.m_bSetInReadOnly = IsReadOnlyAvailable(); + aTmpState.m_bPosMatchesBounds = true; // treat last half of character same as first half if ( !GetLayout()->GetModelPositionForViewPoint( &aPtPos, aPt, &aTmpState ) && bTstHit ) return false; @@ -1054,7 +1351,7 @@ int SwCursorShell::CompareCursorStackMkCurrPt() const { int nRet = 0; const SwPosition *pFirst = nullptr, *pSecond = nullptr; - const SwPaM *pCur = GetCursor(), *pStack = m_pStackCursor; + const SwCursor *pCur = GetCursor(), *pStack = m_pStackCursor; // cursor on stack is needed if we compare against stack if( pStack ) { @@ -1078,14 +1375,14 @@ bool SwCursorShell::IsSelOnePara() const { return false; } - if (m_pCurrentCursor->GetPoint()->nNode == m_pCurrentCursor->GetMark()->nNode) + if (m_pCurrentCursor->GetPoint()->GetNode() == m_pCurrentCursor->GetMark()->GetNode()) { return true; } if (GetLayout()->HasMergedParas()) { SwContentFrame const*const pFrame(GetCurrFrame(false)); - auto const n(m_pCurrentCursor->GetMark()->nNode.GetIndex()); + auto const n(m_pCurrentCursor->GetMark()->GetNodeIndex()); return FrameContainsNode(*pFrame, n); } return false; @@ -1095,7 +1392,7 @@ bool SwCursorShell::IsSttPara() const { if (GetLayout()->HasMergedParas()) { - SwTextNode const*const pNode(m_pCurrentCursor->GetPoint()->nNode.GetNode().GetTextNode()); + SwTextNode const*const pNode(m_pCurrentCursor->GetPoint()->GetNode().GetTextNode()); if (pNode) { SwTextFrame const*const pFrame(static_cast<SwTextFrame*>( @@ -1107,14 +1404,14 @@ bool SwCursorShell::IsSttPara() const } } } - return m_pCurrentCursor->GetPoint()->nContent == 0; + return m_pCurrentCursor->GetPoint()->GetContentIndex() == 0; } bool SwCursorShell::IsEndPara() const { if (GetLayout()->HasMergedParas()) { - SwTextNode const*const pNode(m_pCurrentCursor->GetPoint()->nNode.GetNode().GetTextNode()); + SwTextNode const*const pNode(m_pCurrentCursor->GetPoint()->GetNode().GetTextNode()); if (pNode) { SwTextFrame const*const pFrame(static_cast<SwTextFrame*>( @@ -1126,7 +1423,7 @@ bool SwCursorShell::IsEndPara() const } } } - return m_pCurrentCursor->GetPoint()->nContent == m_pCurrentCursor->GetContentNode()->Len(); + return m_pCurrentCursor->GetPoint()->GetContentIndex() == m_pCurrentCursor->GetPointContentNode()->Len(); } bool SwCursorShell::IsEndOfTable() const @@ -1144,15 +1441,29 @@ bool SwCursorShell::IsEndOfTable() const SwNodeIndex const lastNode(*pEndTableNode, -2); SAL_WARN_IF(!lastNode.GetNode().GetTextNode(), "sw.core", "text node expected"); - return (lastNode == m_pCurrentCursor->GetPoint()->nNode); + return (lastNode == m_pCurrentCursor->GetPoint()->GetNode()); } bool SwCursorShell::IsCursorInFootnote() const { - SwStartNodeType aStartNodeType = m_pCurrentCursor->GetNode().StartOfSectionNode()->GetStartNodeType(); + SwStartNodeType aStartNodeType = m_pCurrentCursor->GetPointNode().StartOfSectionNode()->GetStartNodeType(); return aStartNodeType == SwStartNodeType::SwFootnoteStartNode; } +Point SwCursorShell::GetCursorPagePos() const +{ + Point aRet(-1, -1); + if (SwFrame *pFrame = GetCurrFrame()) + { + if (SwPageFrame* pCurrentPage = pFrame->FindPageFrame()) + { + const Point& rDocPos = GetCursorDocPos(); + aRet = rDocPos - pCurrentPage->getFrameArea().TopLeft(); + } + } + return aRet; +} + bool SwCursorShell::IsInFrontOfLabel() const { return m_pCurrentCursor->IsInFrontOfLabel(); @@ -1301,14 +1612,14 @@ OUString SwCursorShell::getPageRectangles() OUStringBuffer aBuf; for (const SwFrame* pFrame = pLayout->GetLower(); pFrame; pFrame = pFrame->GetNext()) { - aBuf.append(pFrame->getFrameArea().Left()); - aBuf.append(", "); - aBuf.append(pFrame->getFrameArea().Top()); - aBuf.append(", "); - aBuf.append(pFrame->getFrameArea().Width()); - aBuf.append(", "); - aBuf.append(pFrame->getFrameArea().Height()); - aBuf.append("; "); + aBuf.append(OUString::number(pFrame->getFrameArea().Left()) + + ", " + + OUString::number(pFrame->getFrameArea().Top()) + + ", " + + OUString::number(pFrame->getFrameArea().Width()) + + ", " + + OUString::number(pFrame->getFrameArea().Height()) + + "; "); } if (!aBuf.isEmpty()) aBuf.setLength( aBuf.getLength() - 2); // remove the last "; " @@ -1390,7 +1701,7 @@ bool SwCursorShell::GoPrevCursor() return true; } -bool SwCursorShell::GoNextPrevCursorSetSearchLabel(const bool bNext) +void SwCursorShell::GoNextPrevCursorSetSearchLabel(const bool bNext) { SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty ); @@ -1398,15 +1709,18 @@ bool SwCursorShell::GoNextPrevCursorSetSearchLabel(const bool bNext) { if( !m_pCurrentCursor->HasMark() ) SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound ); - return false; + return; } - return bNext ? GoNextCursor() : GoPrevCursor(); + if (bNext) + GoNextCursor(); + else + GoPrevCursor(); } void SwCursorShell::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle &rRect) { - comphelper::FlagRestorationGuard g(mbSelectAll, StartsWithTable() && ExtendedSelectedAll()); + comphelper::FlagRestorationGuard g(mbSelectAll, StartsWith_() != StartsWith::None && ExtendedSelectedAll()); CurrShell aCurr( this ); // always switch off all cursors when painting @@ -1414,7 +1728,7 @@ void SwCursorShell::Paint(vcl::RenderContext& rRenderContext, const tools::Recta bool bVis = false; // if a cursor is visible then hide the SV cursor - if( m_pVisibleCursor->IsVisible() && !aRect.IsOver( m_aCharRect ) ) + if( m_pVisibleCursor->IsVisible() && !aRect.Overlaps( m_aCharRect ) ) { bVis = true; m_pVisibleCursor->Hide(); @@ -1480,8 +1794,8 @@ void SwCursorShell::VisPortChgd( const SwRect & rRect ) /** Set the cursor back into content. - This should only be called if the cursor was move somewhere else (e.g. when - deleting a border). The new position is calculated from its current position + This should only be called if the cursor was moved (e.g. when deleting a + text frame). The new position is calculated from its current position in the layout. */ void SwCursorShell::UpdateCursorPos() @@ -1491,35 +1805,54 @@ void SwCursorShell::UpdateCursorPos() SwShellCursor* pShellCursor = getShellCursor( true ); Size aOldSz( GetDocSize() ); - if( isInHiddenTextFrame(pShellCursor) ) + if (isInHiddenFrame(pShellCursor) && !ExtendedSelectedAll()) { - SwCursorMoveState aTmpState( CursorMoveState::NONE ); + SwCursorMoveState aTmpState(CursorMoveState::SetOnlyText); aTmpState.m_bSetInReadOnly = IsReadOnlyAvailable(); GetLayout()->GetModelPositionForViewPoint( pShellCursor->GetPoint(), pShellCursor->GetPtPos(), &aTmpState ); pShellCursor->DeleteMark(); + // kde45196-1.html: try to get to a non-hidden paragraph, there must + // be one in the document body + while (isInHiddenFrame(pShellCursor)) + { + if (!pShellCursor->MovePara(GoNextPara, fnParaStart)) + { + break; + } + } + while (isInHiddenFrame(pShellCursor)) + { + if (!pShellCursor->MovePara(GoPrevPara, fnParaStart)) + { + break; + } + } } - IGrammarContact *pGrammarContact = GetDoc() ? GetDoc()->getGrammarContact() : nullptr; - if( pGrammarContact ) - pGrammarContact->updateCursorPosition( *m_pCurrentCursor->GetPoint() ); + auto* pDoc = GetDoc(); + if (pDoc) + { + pDoc->getGrammarContact()->updateCursorPosition(*m_pCurrentCursor->GetPoint()); + pDoc->getOnlineAccessibilityCheck()->update(*m_pCurrentCursor->GetPoint()); + } + --mnStartAction; if( aOldSz != GetDocSize() ) SizeChgNotify(); } // #i65475# - if Point/Mark in hidden sections, move them out -static bool lcl_CheckHiddenSection( SwNodeIndex& rIdx ) +static bool lcl_CheckHiddenSection( SwPosition& rPos ) { bool bOk = true; - const SwSectionNode* pSectNd = rIdx.GetNode().FindSectionNode(); + const SwSectionNode* pSectNd = rPos.GetNode().FindSectionNode(); if( pSectNd && pSectNd->GetSection().IsHiddenFlag() ) { - SwNodeIndex aTmp( *pSectNd ); const SwNode* pFrameNd = - rIdx.GetNodes().FindPrvNxtFrameNode( aTmp, pSectNd->EndOfSectionNode() ); + rPos.GetNodes().FindPrvNxtFrameNode( *pSectNd, pSectNd->EndOfSectionNode() ); bOk = pFrameNd != nullptr; SAL_WARN_IF(!bOk, "sw.core", "found no Node with Frames"); - rIdx = aTmp; + rPos.Assign( *(bOk ? pFrameNd : pSectNd) ); } return bOk; } @@ -1527,11 +1860,11 @@ static bool lcl_CheckHiddenSection( SwNodeIndex& rIdx ) /// Try to set the cursor to the next visible content node. static void lcl_CheckHiddenPara( SwPosition& rPos ) { - SwNodeIndex aTmp( rPos.nNode ); + SwNodeIndex aTmp( rPos.GetNode() ); SwTextNode* pTextNd = aTmp.GetNode().GetTextNode(); while( pTextNd && pTextNd->HasHiddenCharAttribute( true ) ) { - SwContentNode* pContent = aTmp.GetNodes().GoNext( &aTmp ); + SwContentNode* pContent = SwNodes::GoNext(&aTmp); if ( pContent && pContent->IsTextNode() ) pTextNd = pContent->GetTextNode(); else @@ -1539,9 +1872,10 @@ static void lcl_CheckHiddenPara( SwPosition& rPos ) } if ( pTextNd ) - rPos = SwPosition( aTmp, SwIndex( pTextNd, 0 ) ); + rPos.Assign( *pTextNd, 0 ); } +#if !ENABLE_WASM_STRIP_ACCESSIBILITY namespace { // #i27301# - helper class that notifies the accessibility about invalid text @@ -1563,6 +1897,7 @@ class SwNotifyAccAboutInvalidTextSelections }; } +#endif void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool bIdleEnd ) { @@ -1576,7 +1911,9 @@ void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool bIdleEnd ) return; // if not then no update } +#if !ENABLE_WASM_STRIP_ACCESSIBILITY SwNotifyAccAboutInvalidTextSelections aInvalidateTextSelections( *this ); +#endif if ( m_bIgnoreReadonly ) { @@ -1594,10 +1931,10 @@ void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool bIdleEnd ) // then the table mode is active (also if it is already active: m_pTableCursor) SwPaM* pTstCursor = getShellCursor( true ); if( pTstCursor->HasMark() && !m_pBlockCursor && - mxDoc->IsIdxInTable( pTstCursor->GetPoint()->nNode ) && + SwDoc::IsInTable( pTstCursor->GetPoint()->GetNode() ) && ( m_pTableCursor || - pTstCursor->GetNode().StartOfSectionNode() != - pTstCursor->GetNode( false ).StartOfSectionNode() ) && !mbSelectAll) + pTstCursor->GetPointNode().StartOfSectionNode() != + pTstCursor->GetMarkNode().StartOfSectionNode() ) && !mbSelectAll) { SwShellCursor* pITmpCursor = getShellCursor( true ); Point aTmpPt( pITmpCursor->GetPtPos() ); @@ -1605,8 +1942,8 @@ void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool bIdleEnd ) SwPosition* pPos = pITmpCursor->GetPoint(); // Bug 65475 (1999) - if Point/Mark in hidden sections, move them out - lcl_CheckHiddenSection( pPos->nNode ); - lcl_CheckHiddenSection( pITmpCursor->GetMark()->nNode ); + lcl_CheckHiddenSection( *pPos ); + lcl_CheckHiddenSection( *pITmpCursor->GetMark() ); // Move cursor out of hidden paragraphs if ( !GetViewOptions()->IsShowHiddenChar() ) @@ -1616,7 +1953,7 @@ void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool bIdleEnd ) } std::pair<Point, bool> const tmp(aTmpPt, false); - SwContentFrame *pTableFrame = pPos->nNode.GetNode().GetContentNode()-> + SwContentFrame *pTableFrame = pPos->GetNode().GetContentNode()-> getLayoutFrame( GetLayout(), pPos, &tmp); OSL_ENSURE( pTableFrame, "Table Cursor not in Content ??" ); @@ -1634,7 +1971,7 @@ void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool bIdleEnd ) if ( !bInRepeatedHeadline ) { std::pair<Point, bool> const tmp1(aTmpMk, false); - SwContentFrame* pMarkTableFrame = pITmpCursor->GetContentNode( false )-> + SwContentFrame* pMarkTableFrame = pITmpCursor->GetMarkContentNode()-> getLayoutFrame(GetLayout(), pITmpCursor->GetMark(), &tmp1); OSL_ENSURE( pMarkTableFrame, "Table Cursor not in Content ??" ); @@ -1656,22 +1993,27 @@ void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool bIdleEnd ) { pTableFrame = nullptr; - SwMoveFnCollection const & fnPosSect = *pPos < *pITmpCursor->GetMark() - ? fnSectionStart - : fnSectionEnd; - // then only select inside the Box if( m_pTableCursor ) { + SwMoveFnCollection const & fnPosSect = *pPos < *pITmpCursor->GetMark() + ? fnSectionStart + : fnSectionEnd; + m_pCurrentCursor->SetMark(); *m_pCurrentCursor->GetMark() = *m_pTableCursor->GetMark(); m_pCurrentCursor->GetMkPos() = m_pTableCursor->GetMkPos(); m_pTableCursor->DeleteMark(); m_pTableCursor->SwSelPaintRects::Hide(); - } - *m_pCurrentCursor->GetPoint() = *m_pCurrentCursor->GetMark(); - GoCurrSection( *m_pCurrentCursor, fnPosSect ); + *m_pCurrentCursor->GetPoint() = *m_pCurrentCursor->GetMark(); + GoCurrSection( *m_pCurrentCursor, fnPosSect ); + } + else + { + eFlags &= SwCursorShell::UPDOWN; + *m_pCurrentCursor->GetPoint() = *m_pCurrentCursor->GetMark(); + } } } @@ -1744,8 +2086,10 @@ void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool bIdleEnd ) m_pVisibleCursor->Show(); // show again } m_eMvState = CursorMoveState::NONE; // state for cursor travelling - GetModelPositionForViewPoint - if (Imp()->IsAccessible()) +#if !ENABLE_WASM_STRIP_ACCESSIBILITY + if (Imp()->IsAccessible() && m_bSendAccessibleCursorEvents) Imp()->InvalidateAccessibleCursorPosition( pTableFrame ); +#endif return; } } @@ -1768,7 +2112,7 @@ void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool bIdleEnd ) { SwShellCursor* pShellCursor = getShellCursor( true ); bool bChgState = true; - const SwSectionNode* pSectNd = pShellCursor->GetNode().FindSectionNode(); + const SwSectionNode* pSectNd = pShellCursor->GetPointNode().FindSectionNode(); if( pSectNd && ( pSectNd->GetSection().IsHiddenFlag() || ( !IsReadOnlyAvailable() && pSectNd->GetSection().IsProtectFlag() && @@ -1821,14 +2165,14 @@ void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool bIdleEnd ) bool bPointIsStart = ( rCmp.Start() == rCmp.GetPoint() ); // move point; forward if it's the start, backwards if it's the end - if( ! rCmp.GetPoint()->nNode.GetNode().IsContentNode() ) + if( ! rCmp.GetPoint()->GetNode().IsContentNode() ) rCmp.Move( bPointIsStart ? fnMoveForward : fnMoveBackward, GoInContent ); // move mark (if exists); forward if it's the start, else backwards if( rCmp.HasMark() ) { - if( ! rCmp.GetMark()->nNode.GetNode().IsContentNode() ) + if( ! rCmp.GetMark()->GetNode().IsContentNode() ) { rCmp.Exchange(); rCmp.Move( !bPointIsStart ? fnMoveForward : fnMoveBackward, @@ -1849,17 +2193,25 @@ void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool bIdleEnd ) do { bAgainst = false; std::pair<Point, bool> const tmp1(pShellCursor->GetPtPos(), false); - pFrame = pShellCursor->GetContentNode()->getLayoutFrame(GetLayout(), + pFrame = pShellCursor->GetPointContentNode()->getLayoutFrame(GetLayout(), pShellCursor->GetPoint(), &tmp1); // if the Frame doesn't exist anymore, the complete Layout has to be // created, because there used to be a Frame here! if ( !pFrame ) { + // skip, if it is a hidden deleted cell without frame + if ( GetLayout()->IsHideRedlines() ) + { + const SwStartNode* pNd = pShellCursor->GetPointNode().FindTableBoxStartNode(); + if ( pNd && pNd->GetTableBox()->GetRedlineType() == RedlineType::Delete ) + return; + } + do { CalcLayout(); std::pair<Point, bool> const tmp(pShellCursor->GetPtPos(), false); - pFrame = pShellCursor->GetContentNode()->getLayoutFrame( + pFrame = pShellCursor->GetPointContentNode()->getLayoutFrame( GetLayout(), pShellCursor->GetPoint(), &tmp); } while( !pFrame ); } @@ -2016,8 +2368,10 @@ void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool bIdleEnd ) m_eMvState = CursorMoveState::NONE; // state for cursor travelling - GetModelPositionForViewPoint - if (Imp()->IsAccessible()) +#if !ENABLE_WASM_STRIP_ACCESSIBILITY + if (Imp()->IsAccessible() && m_bSendAccessibleCursorEvents) Imp()->InvalidateAccessibleCursorPosition( pFrame ); +#endif // switch from blinking cursor to read-only-text-selection cursor const sal_uInt64 nBlinkTime = GetOut()->GetSettings().GetStyleSettings(). @@ -2048,76 +2402,74 @@ void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool bIdleEnd ) void SwCursorShell::sendLOKCursorUpdates() { - SwWrtShell* pShell = GetDoc()->GetDocShell()->GetWrtShell(); - if (!pShell) + SwView* pView = static_cast<SwView*>(GetSfxViewShell()); + if (!pView || !pView->GetWrtShellPtr()) return; + SwWrtShell* pShell = &pView->GetWrtShell(); + SwFrame* pCurrentFrame = GetCurrFrame(); SelectionType eType = pShell->GetSelectionType(); - boost::property_tree::ptree aRootTree; + tools::JsonWriter aJsonWriter; if (pCurrentFrame && (eType & SelectionType::Table) && pCurrentFrame->IsInTab()) { const SwRect& rPageRect = pShell->GetAnyCurRect(CurRectType::Page, nullptr); - boost::property_tree::ptree aTableColumns; { + auto columnsNode = aJsonWriter.startNode("columns"); SwTabCols aTabCols; pShell->GetTabCols(aTabCols); const int nColumnOffset = aTabCols.GetLeftMin() + rPageRect.Left(); - aTableColumns.put("left", aTabCols.GetLeft()); - aTableColumns.put("right", aTabCols.GetRight()); - aTableColumns.put("tableOffset", nColumnOffset); + aJsonWriter.put("left", aTabCols.GetLeft()); + aJsonWriter.put("right", aTabCols.GetRight()); + aJsonWriter.put("tableOffset", static_cast<sal_Int64>(nColumnOffset)); - boost::property_tree::ptree aEntries; - for (size_t i = 0; i < aTabCols.Count(); ++i) { - auto const & rEntry = aTabCols.GetEntry(i); - boost::property_tree::ptree aTableColumnEntry; - aTableColumnEntry.put("position", rEntry.nPos); - aTableColumnEntry.put("min", rEntry.nMin); - aTableColumnEntry.put("max", rEntry.nMax); - aTableColumnEntry.put("hidden", rEntry.bHidden); - aEntries.push_back(std::make_pair("", aTableColumnEntry)); + auto entriesNode = aJsonWriter.startArray("entries"); + for (size_t i = 0; i < aTabCols.Count(); ++i) + { + auto entryNode = aJsonWriter.startStruct(); + auto const & rEntry = aTabCols.GetEntry(i); + aJsonWriter.put("position", rEntry.nPos); + aJsonWriter.put("min", rEntry.nMin); + aJsonWriter.put("max", rEntry.nMax); + aJsonWriter.put("hidden", rEntry.bHidden); + } } - aTableColumns.push_back(std::make_pair("entries", aEntries)); } - boost::property_tree::ptree aTableRows; { + auto rowsNode = aJsonWriter.startNode("rows"); SwTabCols aTabRows; pShell->GetTabRows(aTabRows); const int nRowOffset = aTabRows.GetLeftMin() + rPageRect.Top(); - aTableRows.put("left", aTabRows.GetLeft()); - aTableRows.put("right", aTabRows.GetRight()); - aTableRows.put("tableOffset", nRowOffset); + aJsonWriter.put("left", aTabRows.GetLeft()); + aJsonWriter.put("right", aTabRows.GetRight()); + aJsonWriter.put("tableOffset", static_cast<sal_Int64>(nRowOffset)); - boost::property_tree::ptree aEntries; - for (size_t i = 0; i < aTabRows.Count(); ++i) { - auto const & rEntry = aTabRows.GetEntry(i); - boost::property_tree::ptree aTableRowEntry; - aTableRowEntry.put("position", rEntry.nPos); - aTableRowEntry.put("min", rEntry.nMin); - aTableRowEntry.put("max", rEntry.nMax); - aTableRowEntry.put("hidden", rEntry.bHidden); - aEntries.push_back(std::make_pair("", aTableRowEntry)); + auto entriesNode = aJsonWriter.startArray("entries"); + for (size_t i = 0; i < aTabRows.Count(); ++i) + { + auto entryNode = aJsonWriter.startStruct(); + auto const & rEntry = aTabRows.GetEntry(i); + aJsonWriter.put("position", rEntry.nPos); + aJsonWriter.put("min", rEntry.nMin); + aJsonWriter.put("max", rEntry.nMax); + aJsonWriter.put("hidden", rEntry.bHidden); + } } - aTableRows.push_back(std::make_pair("entries", aEntries)); } - - aRootTree.add_child("columns", aTableColumns); - aRootTree.add_child("rows", aTableRows); } - std::stringstream aStream; - boost::property_tree::write_json(aStream, aRootTree); - GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_TABLE_SELECTED, aStream.str().c_str()); + OString pChar = aJsonWriter.finishAndGetAsOString(); + GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_TABLE_SELECTED, pChar); } void SwCursorShell::RefreshBlockCursor() @@ -2126,7 +2478,7 @@ void SwCursorShell::RefreshBlockCursor() SwShellCursor &rBlock = m_pBlockCursor->getShellCursor(); Point aPt = rBlock.GetPtPos(); std::pair<Point, bool> const tmp(aPt, false); - SwContentFrame* pFrame = rBlock.GetContentNode()->getLayoutFrame( + SwContentFrame* pFrame = rBlock.GetPointContentNode()->getLayoutFrame( GetLayout(), rBlock.GetPoint(), &tmp); Point aMk; if( m_pBlockCursor->getEndPoint() && m_pBlockCursor->getStartPoint() ) @@ -2258,7 +2610,16 @@ void SwCursorShell::Push() */ bool SwCursorShell::Pop(PopMode const eDelete) { - SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed + std::optional<SwCallLink> aLink(std::in_place, *this); // watch Cursor-Moves; call Link if needed + return Pop(eDelete, aLink); +} + +bool SwCursorShell::Pop(PopMode const eDelete, + [[maybe_unused]] std::optional<SwCallLink>& roLink) +{ + // parameter exists only to be deleted before return + assert(roLink); + comphelper::ScopeGuard aGuard( [&]() { roLink.reset(); } ); // are there any left? if (nullptr == m_pStackCursor) @@ -2279,7 +2640,7 @@ bool SwCursorShell::Pop(PopMode const eDelete) if (PopMode::DeleteCurrent == eDelete) { - SwCursorSaveState aSaveState( *m_pCurrentCursor ); + ::std::optional<SwCursorSaveState> oSaveState( *m_pCurrentCursor ); // If the visible SSelection was not changed const Point& rPoint = pOldStack->GetPtPos(); @@ -2307,6 +2668,7 @@ bool SwCursorShell::Pop(PopMode const eDelete) !m_pCurrentCursor->IsSelOvr( SwCursorSelOverFlags::Toggle | SwCursorSelOverFlags::ChangePos ) ) { + oSaveState.reset(); // prevent UAF UpdateCursor(); // update current cursor if (m_pTableCursor) { // tdf#106929 ensure m_pCurrentCursor ring is recreated from table @@ -2333,8 +2695,8 @@ void SwCursorShell::Combine() SwCursorSaveState aSaveState(*m_pStackCursor); // stack cursor & current cursor in same Section? assert(!m_pStackCursor->HasMark() || - CheckNodesRange(m_pStackCursor->GetMark()->nNode, - m_pCurrentCursor->GetPoint()->nNode, true)); + CheckNodesRange(m_pStackCursor->GetMark()->GetNode(), + m_pCurrentCursor->GetPoint()->GetNode(), true)); *m_pStackCursor->GetPoint() = *m_pCurrentCursor->GetPoint(); m_pStackCursor->GetPtPos() = m_pCurrentCursor->GetPtPos(); @@ -2389,13 +2751,16 @@ void SwCursorShell::ShowCursor() if( m_bBasicHideCursor ) return; + comphelper::FlagRestorationGuard g(mbSelectAll, StartsWith_() != StartsWith::None && ExtendedSelectedAll()); + m_bSVCursorVis = true; m_pCurrentCursor->SetShowTextInputFieldOverlay( true ); + m_pCurrentCursor->SetShowContentControlOverlay(true); if (comphelper::LibreOfficeKit::isActive()) { const OString aPayload = OString::boolean(m_bSVCursorVis); - GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_CURSOR_VISIBLE, aPayload.getStr()); + GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_CURSOR_VISIBLE, aPayload); SfxLokHelper::notifyOtherViews(GetSfxViewShell(), LOK_CALLBACK_VIEW_CURSOR_VISIBLE, "visible", aPayload); } @@ -2411,12 +2776,13 @@ void SwCursorShell::HideCursor() // possibly reverse selected areas!! CurrShell aCurr( this ); m_pCurrentCursor->SetShowTextInputFieldOverlay( false ); + m_pCurrentCursor->SetShowContentControlOverlay(false); m_pVisibleCursor->Hide(); if (comphelper::LibreOfficeKit::isActive()) { OString aPayload = OString::boolean(m_bSVCursorVis); - GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_CURSOR_VISIBLE, aPayload.getStr()); + GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_CURSOR_VISIBLE, aPayload); SfxLokHelper::notifyOtherViews(GetSfxViewShell(), LOK_CALLBACK_VIEW_CURSOR_VISIBLE, "visible", aPayload); } } @@ -2430,12 +2796,12 @@ void SwCursorShell::ShellLoseFocus() void SwCursorShell::ShellGetFocus() { - comphelper::FlagRestorationGuard g(mbSelectAll, StartsWithTable() && ExtendedSelectedAll()); + comphelper::FlagRestorationGuard g(mbSelectAll, StartsWith_() != StartsWith::None && ExtendedSelectedAll()); m_bHasFocus = true; if( !m_bBasicHideCursor && VisArea().Width() ) { - UpdateCursor( static_cast<sal_uInt16>( SwCursorShell::CHKRANGE ) ); + UpdateCursor( o3tl::narrowing<sal_uInt16>( SwCursorShell::CHKRANGE ) ); ShowCursors( m_bSVCursorVis ); } } @@ -2445,7 +2811,7 @@ SwContentFrame *SwCursorShell::GetCurrFrame( const bool bCalcFrame ) const { CurrShell aCurr( const_cast<SwCursorShell*>(this) ); SwContentFrame *pRet = nullptr; - SwContentNode *pNd = m_pCurrentCursor->GetContentNode(); + SwContentNode *pNd = m_pCurrentCursor->GetPointContentNode(); if ( pNd ) { if ( bCalcFrame ) @@ -2481,29 +2847,25 @@ void SwCursorShell::SwClientNotify(const SwModify&, const SfxHint& rHint) m_aGrfArrivedLnk.Call(*this); return; } - auto pLegacy = dynamic_cast<const sw::LegacyModifyHint*>(&rHint); - if(!pLegacy) + if (rHint.GetId() != SfxHintId::SwLegacyModify) return; + auto pLegacy = static_cast<const sw::LegacyModifyHint*>(&rHint); auto nWhich = pLegacy->GetWhich(); if(!nWhich) - nWhich = sal::static_int_cast<sal_uInt16>(RES_MSG_BEGIN); + nWhich = RES_OBJECTDYING; if( m_bCallChgLnk && - ( nWhich < RES_MSG_BEGIN || nWhich >= RES_MSG_END || - nWhich == RES_FMT_CHG || nWhich == RES_UPDATE_ATTR || - nWhich == RES_ATTRSET_CHG )) + ( !isFormatMessage(nWhich) + || nWhich == RES_FMT_CHG + || nWhich == RES_UPDATE_ATTR + || nWhich == RES_ATTRSET_CHG )) // messages are not forwarded // #i6681#: RES_UPDATE_ATTR is implicitly unset in // SwTextNode::Insert(SwTextHint*, sal_uInt16); we react here and thus do // not need to send the expensive RES_FMT_CHG in Insert. CallChgLnk(); - switch(nWhich) + if( nWhich == RES_OBJECTDYING ) { - case RES_OBJECTDYING: - EndListeningAll(); - break; - case RES_GRAPHIC_SWAPIN: - if(m_aGrfArrivedLnk.IsSet()) - m_aGrfArrivedLnk.Call(*this); + EndListeningAll(); } } @@ -2542,14 +2904,14 @@ OUString SwCursorShell::GetSelText() const if (GetLayout()->HasMergedParas()) { SwContentFrame const*const pFrame(GetCurrFrame(false)); - if (FrameContainsNode(*pFrame, m_pCurrentCursor->GetMark()->nNode.GetIndex())) + if (pFrame && FrameContainsNode(*pFrame, m_pCurrentCursor->GetMark()->GetNodeIndex())) { OUStringBuffer buf; SwPosition const*const pStart(m_pCurrentCursor->Start()); SwPosition const*const pEnd(m_pCurrentCursor->End()); - for (sal_uLong i = pStart->nNode.GetIndex(); i <= pEnd->nNode.GetIndex(); ++i) + for (SwNodeOffset i = pStart->GetNodeIndex(); i <= pEnd->GetNodeIndex(); ++i) { - SwNode const& rNode(*pStart->nNode.GetNodes()[i]); + SwNode const& rNode(*pStart->GetNodes()[i]); assert(!rNode.IsEndNode()); if (rNode.IsStartNode()) { @@ -2557,11 +2919,11 @@ OUString SwCursorShell::GetSelText() const } else if (rNode.IsTextNode()) { - sal_Int32 const nStart(i == pStart->nNode.GetIndex() - ? pStart->nContent.GetIndex() + sal_Int32 const nStart(i == pStart->GetNodeIndex() + ? pStart->GetContentIndex() : 0); - sal_Int32 const nEnd(i == pEnd->nNode.GetIndex() - ? pEnd->nContent.GetIndex() + sal_Int32 const nEnd(i == pEnd->GetNodeIndex() + ? pEnd->GetContentIndex() : rNode.GetTextNode()->Len()); buf.append(rNode.GetTextNode()->GetExpandText( GetLayout(), @@ -2573,21 +2935,22 @@ OUString SwCursorShell::GetSelText() const aText = buf.makeStringAndClear(); } } - else if( m_pCurrentCursor->GetPoint()->nNode.GetIndex() == - m_pCurrentCursor->GetMark()->nNode.GetIndex() ) + else if( m_pCurrentCursor->GetPoint()->GetNodeIndex() == + m_pCurrentCursor->GetMark()->GetNodeIndex() ) { - SwTextNode* pTextNd = m_pCurrentCursor->GetNode().GetTextNode(); + SwTextNode* pTextNd = m_pCurrentCursor->GetPointNode().GetTextNode(); if( pTextNd ) { - const sal_Int32 nStt = m_pCurrentCursor->Start()->nContent.GetIndex(); + const sal_Int32 nStt = m_pCurrentCursor->Start()->GetContentIndex(); aText = pTextNd->GetExpandText(GetLayout(), nStt, - m_pCurrentCursor->End()->nContent.GetIndex() - nStt ); + m_pCurrentCursor->End()->GetContentIndex() - nStt ); } } return aText; } /** get the nth character of the current SSelection + in the same paragraph as the start/end. @param bEnd Start counting from the end? From start otherwise. @param nOffset position of the character @@ -2599,12 +2962,18 @@ sal_Unicode SwCursorShell::GetChar( bool bEnd, tools::Long nOffset ) const SwPosition* pPos = !m_pCurrentCursor->HasMark() ? m_pCurrentCursor->GetPoint() : bEnd ? m_pCurrentCursor->End() : m_pCurrentCursor->Start(); - SwTextNode* pTextNd = pPos->nNode.GetNode().GetTextNode(); + SwTextNode* pTextNd = pPos->GetNode().GetTextNode(); if( !pTextNd ) return 0; - const sal_Int32 nPos = pPos->nContent.GetIndex(); - const OUString& rStr = pTextNd->GetText(); + SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(pTextNd->getLayoutFrame(GetLayout()))); + if (!pFrame) + { + return 0; + } + + const sal_Int32 nPos(sal_Int32(pFrame->MapModelToViewPos(*pPos))); + const OUString& rStr(pFrame->GetText()); sal_Unicode cCh = 0; if (((nPos+nOffset) >= 0 ) && (nPos+nOffset) < rStr.getLength()) @@ -2624,10 +2993,10 @@ bool SwCursorShell::ExtendSelection( bool bEnd, sal_Int32 nCount ) return false; // no selection SwPosition* pPos = bEnd ? m_pCurrentCursor->End() : m_pCurrentCursor->Start(); - SwTextNode* pTextNd = pPos->nNode.GetNode().GetTextNode(); + SwTextNode* pTextNd = pPos->GetNode().GetTextNode(); assert(pTextNd); - sal_Int32 nPos = pPos->nContent.GetIndex(); + sal_Int32 nPos = pPos->GetContentIndex(); if( bEnd ) { if ((nPos + nCount) <= pTextNd->GetText().getLength()) @@ -2642,7 +3011,7 @@ bool SwCursorShell::ExtendSelection( bool bEnd, sal_Int32 nCount ) SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed - pPos->nContent = nPos; + pPos->SetContent(nPos) ; UpdateCursor(); return true; @@ -2667,7 +3036,7 @@ bool SwCursorShell::SetVisibleCursor( const Point &rPt ) SetInFrontOfLabel( false ); // #i27615# // show only in TextNodes - SwTextNode* pTextNd = aPos.nNode.GetNode().GetTextNode(); + SwTextNode* pTextNd = aPos.GetNode().GetTextNode(); if( !pTextNd ) return false; @@ -2722,7 +3091,7 @@ bool SwCursorShell::IsOverReadOnlyPos( const Point& rPt ) const SwPaM aPam( *m_pCurrentCursor->GetPoint() ); GetLayout()->GetModelPositionForViewPoint( aPam.GetPoint(), aPt ); // form view - return aPam.HasReadonlySel( GetViewOptions()->IsFormView() ); + return aPam.HasReadonlySel(GetViewOptions()->IsFormView(), false); } /** Get the number of elements in the ring of cursors @@ -2746,14 +3115,14 @@ sal_uInt16 SwCursorShell::GetCursorCnt( bool bAll ) const bool SwCursorShell::IsStartOfDoc() const { - if( m_pCurrentCursor->GetPoint()->nContent.GetIndex() ) + if( m_pCurrentCursor->GetPoint()->GetContentIndex() ) return false; // after EndOfIcons comes the content selection (EndNd+StNd+ContentNd) SwNodeIndex aIdx( GetDoc()->GetNodes().GetEndOfExtras(), 2 ); if( !aIdx.GetNode().IsContentNode() ) - GetDoc()->GetNodes().GoNext( &aIdx ); - return aIdx == m_pCurrentCursor->GetPoint()->nNode; + SwNodes::GoNext(&aIdx); + return aIdx == m_pCurrentCursor->GetPoint()->GetNode(); } bool SwCursorShell::IsEndOfDoc() const @@ -2763,8 +3132,8 @@ bool SwCursorShell::IsEndOfDoc() const if( !pCNd ) pCNd = SwNodes::GoPrevious( &aIdx ); - return aIdx == m_pCurrentCursor->GetPoint()->nNode && - pCNd->Len() == m_pCurrentCursor->GetPoint()->nContent.GetIndex(); + return aIdx == m_pCurrentCursor->GetPoint()->GetNode() && pCNd && + pCNd->Len() == m_pCurrentCursor->GetPoint()->GetContentIndex(); } /** Invalidate cursors @@ -2793,8 +3162,7 @@ bool SwCursorShell::ParkTableCursor() void SwCursorShell::ParkPams( SwPaM* pDelRg, SwShellCursor** ppDelRing ) { - const SwPosition *pStt = pDelRg->Start(), - *pEnd = pDelRg->GetPoint() == pStt ? pDelRg->GetMark() : pDelRg->GetPoint(); + auto [pStt, pEnd] = pDelRg->StartEnd(); // SwPosition* SwPaM *pTmpDel = nullptr, *pTmp = *ppDelRing; @@ -2805,9 +3173,7 @@ void SwCursorShell::ParkPams( SwPaM* pDelRg, SwShellCursor** ppDelRing ) if (!pTmp) break; - const SwPosition *pTmpStt = pTmp->Start(), - *pTmpEnd = pTmp->GetPoint() == pTmpStt ? - pTmp->GetMark() : pTmp->GetPoint(); + auto [pTmpStt, pTmpEnd] = pTmp->StartEnd(); // SwPosition* // If a SPoint or GetMark are in a cursor area then cancel the old area. // During comparison keep in mind that End() is outside the area. if( *pStt <= *pTmpStt ) @@ -2847,8 +3213,7 @@ void SwCursorShell::ParkPams( SwPaM* pDelRg, SwShellCursor** ppDelRing ) } else { - pTmpDel->GetPoint()->nContent.Assign(nullptr, 0); - pTmpDel->GetPoint()->nNode = 0; + pTmpDel->GetPoint()->Assign(SwNodeOffset(0)); pTmpDel->DeleteMark(); } pTmpDel = nullptr; @@ -2866,12 +3231,12 @@ void SwCursorShell::ParkPams( SwPaM* pDelRg, SwShellCursor** ppDelRing ) @param rIdx ??? */ -void SwCursorShell::ParkCursor( const SwNodeIndex &rIdx ) +void SwCursorShell::ParkCursor( const SwNode &rIdx ) { - SwNode *pNode = &rIdx.GetNode(); + const SwNode *pNode = &rIdx; // create a new PaM - std::unique_ptr<SwPaM> pNew( new SwPaM( *GetCursor()->GetPoint() ) ); + SwPaM aNew( *GetCursor()->GetPoint() ); if( pNode->GetStartNode() ) { pNode = pNode->StartOfSectionNode(); @@ -2879,18 +3244,18 @@ void SwCursorShell::ParkCursor( const SwNodeIndex &rIdx ) { // the given node is in a table, thus park cursor to table node // (outside of the table) - pNew->GetPoint()->nNode = *pNode->StartOfSectionNode(); + aNew.GetPoint()->Assign( *pNode->StartOfSectionNode() ); } else // Also on the start node itself. Then we need to request the start // node always via its end node! (StartOfSelection of StartNode is // the parent) - pNew->GetPoint()->nNode = *pNode->EndOfSectionNode()->StartOfSectionNode(); + aNew.GetPoint()->Assign( *pNode->EndOfSectionNode()->StartOfSectionNode() ); } else - pNew->GetPoint()->nNode = *pNode->StartOfSectionNode(); - pNew->SetMark(); - pNew->GetPoint()->nNode = *pNode->EndOfSectionNode(); + aNew.GetPoint()->Assign( *pNode->StartOfSectionNode() ); + aNew.SetMark(); + aNew.GetPoint()->Assign(*pNode->EndOfSectionNode()); // take care of all shells for(SwViewShell& rTmp : GetRingContainer()) @@ -2898,21 +3263,20 @@ void SwCursorShell::ParkCursor( const SwNodeIndex &rIdx ) if( auto pSh = dynamic_cast<SwCursorShell *>(&rTmp)) { if (pSh->m_pStackCursor) - pSh->ParkPams(pNew.get(), &pSh->m_pStackCursor); + pSh->ParkPams(&aNew, &pSh->m_pStackCursor); - pSh->ParkPams( pNew.get(), &pSh->m_pCurrentCursor ); + pSh->ParkPams( &aNew, &pSh->m_pCurrentCursor ); if( pSh->m_pTableCursor ) { // set table cursor always to 0 and the current one always to // the beginning of the table SwPaM* pTCursor = pSh->GetTableCrs(); - SwNode* pTableNd = pTCursor->GetPoint()->nNode.GetNode().FindTableNode(); + SwNode* pTableNd = pTCursor->GetPoint()->GetNode().FindTableNode(); if ( pTableNd ) { - pTCursor->GetPoint()->nContent.Assign(nullptr, 0); - pTCursor->GetPoint()->nNode = 0; + pTCursor->GetPoint()->Assign(SwNodeOffset(0)); pTCursor->DeleteMark(); - pSh->m_pCurrentCursor->GetPoint()->nNode = *pTableNd; + pSh->m_pCurrentCursor->GetPoint()->Assign( *pTableNd ); } } } @@ -2940,18 +3304,18 @@ SwCursorShell::SwCursorShell( SwCursorShell& rShell, vcl::Window *pInitWin ) , m_nCursorMove( 0 ) , m_eMvState( CursorMoveState::NONE ) , m_eEnhancedTableSel(SwTable::SEARCH_NONE) - , m_sMarkedListId() , m_nMarkedListLevel( 0 ) , m_oldColFrame(nullptr) { CurrShell aCurr( this ); // only keep the position of the current cursor of the copy shell m_pCurrentCursor = new SwShellCursor( *this, *(rShell.m_pCurrentCursor->GetPoint()) ); - m_pCurrentCursor->GetContentNode()->Add( this ); + m_pCurrentCursor->GetPointContentNode()->Add( this ); m_bAllProtect = m_bVisPortChgd = m_bChgCallFlag = m_bInCMvVisportChgd = m_bGCAttr = m_bIgnoreReadonly = m_bSelTableCells = m_bBasicHideCursor = m_bOverwriteCursor = false; + m_bSendAccessibleCursorEvents = true; m_bCallChgLnk = m_bHasFocus = m_bAutoUpdateCells = true; m_bSVCursorVis = true; m_bSetCursorInReadOnly = true; @@ -2977,7 +3341,6 @@ SwCursorShell::SwCursorShell( SwDoc& rDoc, vcl::Window *pInitWin, , m_nCursorMove( 0 ) , m_eMvState( CursorMoveState::NONE ) // state for crsr-travelling - GetModelPositionForViewPoint , m_eEnhancedTableSel(SwTable::SEARCH_NONE) - , m_sMarkedListId() , m_nMarkedListLevel( 0 ) , m_oldColFrame(nullptr) { @@ -2986,9 +3349,9 @@ SwCursorShell::SwCursorShell( SwDoc& rDoc, vcl::Window *pInitWin, SwNodes& rNds = rDoc.GetNodes(); SwNodeIndex aNodeIdx( *rNds.GetEndOfContent().StartOfSectionNode() ); - SwContentNode* pCNd = rNds.GoNext( &aNodeIdx ); // go to the first ContentNode + SwContentNode* pCNd = SwNodes::GoNext(&aNodeIdx); // go to the first ContentNode - m_pCurrentCursor = new SwShellCursor( *this, SwPosition( aNodeIdx, SwIndex( pCNd, 0 ))); + m_pCurrentCursor = new SwShellCursor( *this, SwPosition( aNodeIdx, pCNd, 0 ) ); // Register shell as dependent at current node. As a result all attribute // changes can be forwarded via the Link. @@ -2997,6 +3360,7 @@ SwCursorShell::SwCursorShell( SwDoc& rDoc, vcl::Window *pInitWin, m_bAllProtect = m_bVisPortChgd = m_bChgCallFlag = m_bInCMvVisportChgd = m_bGCAttr = m_bIgnoreReadonly = m_bSelTableCells = m_bBasicHideCursor = m_bOverwriteCursor = false; + m_bSendAccessibleCursorEvents = true; m_bCallChgLnk = m_bHasFocus = m_bAutoUpdateCells = true; m_bSVCursorVis = true; m_bSetCursorInReadOnly = true; @@ -3057,8 +3421,8 @@ bool SwCursorShell::ShouldWait() const return true; SwPaM* pPam = GetCursor(); - return pPam->Start()->nNode.GetIndex() + 10 < - pPam->End()->nNode.GetIndex(); + return pPam->Start()->GetNodeIndex() + SwNodeOffset(10) < + pPam->End()->GetNodeIndex(); } size_t SwCursorShell::UpdateTableSelBoxes() @@ -3120,14 +3484,14 @@ bool SwCursorShell::FindValidContentNode( bool bOnlyText ) GetDoc()->GetDocShell()->IsReadOnlyUI() ) return true; - if( m_pCurrentCursor->HasMark() ) + if( m_pCurrentCursor->HasMark() && !mbSelectAll ) ClearMark(); // first check for frames - SwNodeIndex& rNdIdx = m_pCurrentCursor->GetPoint()->nNode; - sal_uLong nNdIdx = rNdIdx.GetIndex(); // keep backup + SwPosition& rNdPos = *m_pCurrentCursor->GetPoint(); + SwNodeOffset nNdIdx = rNdPos.GetNodeIndex(); // keep backup SwNodes& rNds = mxDoc->GetNodes(); - SwContentNode* pCNd = rNdIdx.GetNode().GetContentNode(); + SwContentNode* pCNd = rNdPos.GetNode().GetContentNode(); const SwContentFrame * pFrame; if (pCNd && nullptr != (pFrame = pCNd->getLayoutFrame(GetLayout(), m_pCurrentCursor->GetPoint())) && @@ -3137,19 +3501,19 @@ bool SwCursorShell::FindValidContentNode( bool bOnlyText ) // skip protected frame SwPaM aPam( *m_pCurrentCursor->GetPoint() ); aPam.SetMark(); - aPam.GetMark()->nNode = rNds.GetEndOfContent(); - aPam.GetPoint()->nNode = *pCNd->EndOfSectionNode(); + aPam.GetMark()->Assign( rNds.GetEndOfContent() ); + aPam.GetPoint()->Assign( *pCNd->EndOfSectionNode() ); bool bFirst = false; if( nullptr == (pCNd = ::GetNode( aPam, bFirst, fnMoveForward ))) { - aPam.GetMark()->nNode = *rNds.GetEndOfPostIts().StartOfSectionNode(); + aPam.GetMark()->Assign( *rNds.GetEndOfPostIts().StartOfSectionNode() ); pCNd = ::GetNode( aPam, bFirst, fnMoveBackward ); } if( !pCNd ) // should *never* happen { - rNdIdx = nNdIdx; // back to old node + rNdPos.Assign(nNdIdx); // back to old node return false; } *m_pCurrentCursor->GetPoint() = *aPam.GetPoint(); @@ -3157,48 +3521,47 @@ bool SwCursorShell::FindValidContentNode( bool bOnlyText ) else if( bOnlyText && pCNd && pCNd->IsNoTextNode() ) { // set to beginning of document - rNdIdx = mxDoc->GetNodes().GetEndOfExtras(); - m_pCurrentCursor->GetPoint()->nContent.Assign( mxDoc->GetNodes().GoNext( - &rNdIdx ), 0 ); - nNdIdx = rNdIdx.GetIndex(); + rNdPos.Assign( mxDoc->GetNodes().GetEndOfExtras() ); + SwNodes::GoNext(&rNdPos); + nNdIdx = rNdPos.GetNodeIndex(); } bool bOk = true; // #i9059# cursor may not stand in protected cells // (unless cursor in protected areas is OK.) - const SwTableNode* pTableNode = rNdIdx.GetNode().FindTableNode(); + const SwTableNode* pTableNode = rNdPos.GetNode().FindTableNode(); if( !IsReadOnlyAvailable() && - pTableNode != nullptr && rNdIdx.GetNode().IsProtect() ) + pTableNode != nullptr && rNdPos.GetNode().IsProtect() ) { // we're in a table, and we're in a protected area, so we're // probably in a protected cell. // move forward into non-protected area. - SwPaM aPam( rNdIdx.GetNode(), 0 ); - while( aPam.GetNode().IsProtect() && + SwPaM aPam( rNdPos.GetNode(), 0 ); + while( aPam.GetPointNode().IsProtect() && aPam.Move( fnMoveForward, GoInContent ) ) ; // nothing to do in the loop; the aPam.Move does the moving! // didn't work? then go backwards! - if( aPam.GetNode().IsProtect() ) + if( aPam.GetPointNode().IsProtect() ) { - SwPaM aTmpPaM( rNdIdx.GetNode(), 0 ); + SwPaM aTmpPaM( rNdPos.GetNode(), 0 ); aPam = aTmpPaM; - while( aPam.GetNode().IsProtect() && + while( aPam.GetPointNode().IsProtect() && aPam.Move( fnMoveBackward, GoInContent ) ) ; // nothing to do in the loop; the aPam.Move does the moving! } // if we're successful, set the new position - if( ! aPam.GetNode().IsProtect() ) + if( ! aPam.GetPointNode().IsProtect() ) { *m_pCurrentCursor->GetPoint() = *aPam.GetPoint(); } } // in a protected frame - const SwSectionNode* pSectNd = rNdIdx.GetNode().FindSectionNode(); + const SwSectionNode* pSectNd = rNdPos.GetNode().FindSectionNode(); if( pSectNd && ( pSectNd->GetSection().IsHiddenFlag() || ( !IsReadOnlyAvailable() && pSectNd->GetSection().IsProtectFlag() )) ) @@ -3213,10 +3576,10 @@ bool SwCursorShell::FindValidContentNode( bool bOnlyText ) for (;;) { if (bGoNextSection) - pCNd = rNds.GoNextSection( &rNdIdx, + pCNd = SwNodes::GoNextSection( &rNdPos, true, !IsReadOnlyAvailable() ); else - pCNd = SwNodes::GoPrevSection( &rNdIdx, + pCNd = SwNodes::GoPrevSection( &rNdPos, true, !IsReadOnlyAvailable() ); if ( pCNd == nullptr) break; // moved inside a table -> check if it is protected @@ -3245,7 +3608,7 @@ bool SwCursorShell::FindValidContentNode( bool bOnlyText ) } } - if( bOk && rNdIdx.GetIndex() < rNds.GetEndOfExtras().GetIndex() ) + if( bOk && rNdPos.GetNodeIndex() < rNds.GetEndOfExtras().GetIndex() ) { // also check for Fly - might be protected as well pFrame = pCNd->getLayoutFrame(GetLayout(), nullptr, nullptr); @@ -3264,19 +3627,19 @@ bool SwCursorShell::FindValidContentNode( bool bOnlyText ) { if( !nLoopCnt ) bGoNextSection = false; - rNdIdx = nNdIdx; + rNdPos.Assign( nNdIdx ); } } } if( bOk ) { - pCNd = rNdIdx.GetNode().GetContentNode(); - const sal_Int32 nContent = rNdIdx.GetIndex() < nNdIdx ? pCNd->Len() : 0; - m_pCurrentCursor->GetPoint()->nContent.Assign( pCNd, nContent ); + pCNd = rNdPos.GetNode().GetContentNode(); + const sal_Int32 nContent = rNdPos.GetNodeIndex() < nNdIdx ? pCNd->Len() : 0; + m_pCurrentCursor->GetPoint()->SetContent( nContent ); } else { - pCNd = rNdIdx.GetNode().GetContentNode(); + pCNd = rNdPos.GetNode().GetContentNode(); // if cursor in hidden frame, always move it if (!pCNd || !pCNd->getLayoutFrame(GetLayout(), nullptr, nullptr)) { @@ -3342,32 +3705,15 @@ void SwCursorShell::SetReadOnlyAvailable( bool bFlag ) } } -bool SwCursorShell::HasReadonlySel() const +bool SwCursorShell::HasReadonlySel(bool const isReplace) const { + // Treat selections that span over start or end of paragraph of an outline node + // with folded outline content as read-only. if (GetViewOptions()->IsShowOutlineContentVisibilityButton()) { - // Treat selections that span over start or end of paragraph of an outline node - // with folded outline content as read-only. SwWrtShell* pWrtSh = GetDoc()->GetDocShell()->GetWrtShell(); - if (pWrtSh) - { - for(SwPaM& rPaM : GetCursor()->GetRingContainer()) - { - rPaM.Normalize(); - SwNodeIndex aPointIdx(rPaM.GetPoint()->nNode.GetNode()); - SwNodeIndex aMarkIdx(rPaM.GetMark()->nNode.GetNode()); - if (aPointIdx == aMarkIdx) - continue; - // If any nodes in PaM are folded outline content nodes, then set read-only. - SwOutlineNodes::size_type nPos; - for (SwNodeIndex aIdx = aPointIdx; aIdx <= aMarkIdx; aIdx++) - { - if (GetDoc()->GetNodes().GetOutLineNds().Seek_Entry(&(aIdx.GetNode()), &nPos) && - !pWrtSh->GetAttrOutlineContentVisible(nPos)) - return true; - } - } - } + if (pWrtSh && pWrtSh->HasFoldedOutlineContentSelected()) + return true; } bool bRet = false; // If protected area is to be ignored, then selections are never read-only. @@ -3377,14 +3723,15 @@ bool SwCursorShell::HasReadonlySel() const { if ( m_pTableCursor != nullptr ) { + // TODO: handling when a table cell (cells) is selected bRet = m_pTableCursor->HasReadOnlyBoxSel() - || m_pTableCursor->HasReadonlySel( GetViewOptions()->IsFormView() ); + || m_pTableCursor->HasReadonlySel(GetViewOptions()->IsFormView(), isReplace); } else { for(const SwPaM& rCursor : m_pCurrentCursor->GetRingContainer()) { - if( rCursor.HasReadonlySel( GetViewOptions()->IsFormView() ) ) + if (rCursor.HasReadonlySel(GetViewOptions()->IsFormView(), isReplace)) { bRet = true; break; @@ -3395,22 +3742,50 @@ bool SwCursorShell::HasReadonlySel() const return bRet; } -bool SwCursorShell::IsSelFullPara() const +bool SwCursorShell::HasHiddenSections() const { + // Treat selections that span over start or end of paragraph of an outline node + // with folded outline content as read-only. + if (GetViewOptions()->IsShowOutlineContentVisibilityButton()) + { + SwWrtShell* pWrtSh = GetDoc()->GetDocShell()->GetWrtShell(); + if (pWrtSh && pWrtSh->HasFoldedOutlineContentSelected()) + return true; + } bool bRet = false; - if( m_pCurrentCursor->GetPoint()->nNode.GetIndex() == - m_pCurrentCursor->GetMark()->nNode.GetIndex() && !m_pCurrentCursor->IsMultiSelection() ) + if ( m_pTableCursor != nullptr ) { - sal_Int32 nStt = m_pCurrentCursor->GetPoint()->nContent.GetIndex(); - sal_Int32 nEnd = m_pCurrentCursor->GetMark()->nContent.GetIndex(); - if( nStt > nEnd ) + bRet = m_pTableCursor->HasHiddenBoxSel() + || m_pTableCursor->HasHiddenSections(); + } + else + { + for(const SwPaM& rCursor : m_pCurrentCursor->GetRingContainer()) { - sal_Int32 nTmp = nStt; - nStt = nEnd; - nEnd = nTmp; + if (rCursor.HasHiddenSections()) + { + bRet = true; + break; + } } - const SwContentNode* pCNd = m_pCurrentCursor->GetContentNode(); + } + + return bRet; +} + +bool SwCursorShell::IsSelFullPara() const +{ + bool bRet = false; + + if( m_pCurrentCursor->GetPoint()->GetNodeIndex() == + m_pCurrentCursor->GetMark()->GetNodeIndex() && !m_pCurrentCursor->IsMultiSelection() ) + { + sal_Int32 nStt = m_pCurrentCursor->GetPoint()->GetContentIndex(); + sal_Int32 nEnd = m_pCurrentCursor->GetMark()->GetContentIndex(); + if( nStt > nEnd ) + std::swap( nStt, nEnd ); + const SwContentNode* pCNd = m_pCurrentCursor->GetPointContentNode(); bRet = pCNd && !nStt && nEnd == pCNd->Len(); } return bRet; @@ -3446,18 +3821,18 @@ bool SwCursorShell::IsInRightToLeftText() const return SvxFrameDirection::Vertical_LR_TB == nDir || SvxFrameDirection::Horizontal_RL_TB == nDir; } -/// If the current cursor position is inside a hidden range, the hidden range -/// is selected. -bool SwCursorShell::SelectHiddenRange() +/// If the current cursor position is inside a hidden range true is returned. If bSelect is +/// true, the hidden range is selected. If bSelect is false, the hidden range is not selected. +bool SwCursorShell::IsInHiddenRange(const bool bSelect) { bool bRet = false; if ( !GetViewOptions()->IsShowHiddenChar() && !m_pCurrentCursor->HasMark() ) { SwPosition& rPt = *m_pCurrentCursor->GetPoint(); - const SwTextNode* pNode = rPt.nNode.GetNode().GetTextNode(); + const SwTextNode* pNode = rPt.GetNode().GetTextNode(); if ( pNode ) { - const sal_Int32 nPos = rPt.nContent.GetIndex(); + const sal_Int32 nPos = rPt.GetContentIndex(); // check if nPos is in hidden range sal_Int32 nHiddenStart; @@ -3465,9 +3840,12 @@ bool SwCursorShell::SelectHiddenRange() SwScriptInfo::GetBoundsOfHiddenRange( *pNode, nPos, nHiddenStart, nHiddenEnd ); if ( COMPLETE_STRING != nHiddenStart ) { - // make selection: - m_pCurrentCursor->SetMark(); - m_pCurrentCursor->GetMark()->nContent = nHiddenEnd; + if (bSelect) + { + // make selection: + m_pCurrentCursor->SetMark(); + m_pCurrentCursor->GetMark()->SetContent(nHiddenEnd); + } bRet = true; } } @@ -3476,7 +3854,7 @@ bool SwCursorShell::SelectHiddenRange() return bRet; } -sal_uLong SwCursorShell::Find_Text( const i18nutil::SearchOptions2& rSearchOpt, +sal_Int32 SwCursorShell::Find_Text( const i18nutil::SearchOptions2& rSearchOpt, bool bSearchInNotes, SwDocPositions eStart, SwDocPositions eEnd, bool& bCancel, @@ -3488,14 +3866,14 @@ sal_uLong SwCursorShell::Find_Text( const i18nutil::SearchOptions2& rSearchOpt, delete m_pTableCursor; m_pTableCursor = nullptr; SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed - sal_uLong nRet = m_pCurrentCursor->Find_Text(rSearchOpt, bSearchInNotes, eStart, eEnd, + sal_Int32 nRet = m_pCurrentCursor->Find_Text(rSearchOpt, bSearchInNotes, eStart, eEnd, bCancel, eRng, bReplace, GetLayout()); if( nRet || bCancel ) UpdateCursor(); return nRet; } -sal_uLong SwCursorShell::FindFormat( const SwTextFormatColl& rFormatColl, +sal_Int32 SwCursorShell::FindFormat( const SwTextFormatColl& rFormatColl, SwDocPositions eStart, SwDocPositions eEnd, bool& bCancel, FindRanges eRng, @@ -3506,14 +3884,14 @@ sal_uLong SwCursorShell::FindFormat( const SwTextFormatColl& rFormatColl, delete m_pTableCursor; m_pTableCursor = nullptr; SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed - sal_uLong nRet = m_pCurrentCursor->FindFormat(rFormatColl, eStart, eEnd, bCancel, eRng, + sal_Int32 nRet = m_pCurrentCursor->FindFormat(rFormatColl, eStart, eEnd, bCancel, eRng, pReplFormat ); if( nRet ) UpdateCursor(); return nRet; } -sal_uLong SwCursorShell::FindAttrs( const SfxItemSet& rSet, +sal_Int32 SwCursorShell::FindAttrs( const SfxItemSet& rSet, bool bNoCollections, SwDocPositions eStart, SwDocPositions eEnd, bool& bCancel, @@ -3526,7 +3904,7 @@ sal_uLong SwCursorShell::FindAttrs( const SfxItemSet& rSet, delete m_pTableCursor; m_pTableCursor = nullptr; SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed - sal_uLong nRet = m_pCurrentCursor->FindAttrs(rSet, bNoCollections, eStart, eEnd, + sal_Int32 nRet = m_pCurrentCursor->FindAttrs(rSet, bNoCollections, eStart, eEnd, bCancel, eRng, pSearchOpt, rReplSet, GetLayout()); if( nRet ) UpdateCursor(); @@ -3536,7 +3914,7 @@ sal_uLong SwCursorShell::FindAttrs( const SfxItemSet& rSet, void SwCursorShell::SetSelection( const SwPaM& rCursor ) { StartAction(); - SwPaM* pCursor = GetCursor(); + SwCursor* pCursor = GetCursor(); *pCursor->GetPoint() = *rCursor.GetPoint(); if(rCursor.GetNext() != &rCursor) { @@ -3579,10 +3957,10 @@ static const SwStartNode* lcl_NodeContext( const SwNode& rNode ) @param aPos the position to check. */ -bool sw_PosOk(const SwPosition & aPos) +static bool sw_PosOk(const SwPosition & aPos) { - return nullptr != aPos.nNode.GetNode().GetContentNode() && - aPos.nContent.GetIdxReg(); + return nullptr != aPos.GetNode().GetContentNode() && + aPos.GetContentNode(); } /** @@ -3624,21 +4002,35 @@ void SwCursorShell::ClearUpCursors() pStartCursor->DeleteMark(); bChanged = true; } + if (pStartCursor->GetPoint()->GetNode().IsTableNode()) + { + // tdf#106959: When cursor points to start of a table, the proper content + // node is the first one inside the table, not the previous one + SwNodeIndex aIdx(pStartCursor->GetPoint()->GetNode()); + if (SwNode* pNode = SwNodes::GoNext(&aIdx)) + { + SwPaM aTmpPam(*pNode); + *pStartCursor = aTmpPam; + bChanged = true; + } + } if( !sw_PosOk( *pStartCursor->GetPoint() ) ) { SwNodes & aNodes = GetDoc()->GetNodes(); - const SwNode* pStart = lcl_NodeContext( pStartCursor->GetPoint()->nNode.GetNode() ); - SwNodeIndex aIdx( pStartCursor->GetPoint()->nNode ); + const SwNode* pStart = lcl_NodeContext( pStartCursor->GetPoint()->GetNode() ); + SwNodeIndex aIdx( pStartCursor->GetPoint()->GetNode() ); SwNode * pNode = SwNodes::GoPrevious(&aIdx); if( pNode == nullptr || lcl_NodeContext( *pNode ) != pStart ) - aNodes.GoNext( &aIdx ); - if( pNode == nullptr || lcl_NodeContext( *pNode ) != pStart ) { - // If the start entry of the ring is invalid replace it with a - // cursor pointing to the beginning of the first content node in the - // document. - aIdx = *(aNodes.GetEndOfContent().StartOfSectionNode()); - pNode = aNodes.GoNext( &aIdx ); + pNode = SwNodes::GoNext(&aIdx); + if( pNode == nullptr || lcl_NodeContext( *pNode ) != pStart ) + { + // If the start entry of the ring is invalid replace it with a + // cursor pointing to the beginning of the first content node in the + // document. + aIdx = *(aNodes.GetEndOfContent().StartOfSectionNode()); + pNode = SwNodes::GoNext(&aIdx); + } } bool bFound = (pNode != nullptr); @@ -3703,6 +4095,7 @@ static void lcl_FillRecognizerData( std::vector< OUString >& rSmartTagTypes, if ( pArea ) { rSmartTagTypes.push_back( pArea->maType ); + aStringKeyMaps.push_back( pArea->mxPropertyBag ); } } } @@ -3717,14 +4110,11 @@ static void lcl_FillTextRange( uno::Reference<text::XTextRange>& rRange, SwTextNode& rNode, sal_Int32 nBegin, sal_Int32 nLen ) { // create SwPosition for nStartIndex - SwIndex aIndex( &rNode, nBegin ); - SwPosition aStartPos( rNode, aIndex ); - + SwPosition aStartPos( rNode, nBegin ); // create SwPosition for nEndIndex - SwPosition aEndPos( aStartPos ); - aEndPos.nContent = nBegin + nLen; + SwPosition aEndPos( rNode, nBegin + nLen ); - const uno::Reference<text::XTextRange> xRange = + const rtl::Reference<SwXTextRange> xRange = SwXTextRange::CreateXTextRange(rNode.GetDoc(), aStartPos, &aEndPos); rRange = xRange; @@ -3738,8 +4128,8 @@ void SwCursorShell::GetSmartTagTerm( std::vector< OUString >& rSmartTagTypes, return; SwPaM* pCursor = GetCursor(); - SwPosition aPos( *pCursor->GetPoint() ); - SwTextNode *pNode = aPos.nNode.GetNode().GetTextNode(); + SwPosition aPos(*pCursor->Start()); + SwTextNode *pNode = aPos.GetNode().GetTextNode(); if ( !pNode || pNode->IsInProtectSect() ) return; @@ -3747,7 +4137,7 @@ void SwCursorShell::GetSmartTagTerm( std::vector< OUString >& rSmartTagTypes, if ( !pSmartTagList ) return; - sal_Int32 nCurrent = aPos.nContent.GetIndex(); + sal_Int32 nCurrent = aPos.GetContentIndex(); sal_Int32 nBegin = nCurrent; sal_Int32 nLen = 1; @@ -3773,6 +4163,7 @@ void SwCursorShell::GetSmartTagRect( const Point& rPt, SwRect& rSelectRect ) SwPosition aPos( *pCursor->GetPoint() ); Point aPt( rPt ); SwCursorMoveState eTmpState( CursorMoveState::SetOnlyText ); + eTmpState.m_bPosMatchesBounds = true; // treat last half of character same as first half SwSpecialPos aSpecialPos; eTmpState.m_pSpecialPos = &aSpecialPos; SwTextNode *pNode; @@ -3780,7 +4171,7 @@ void SwCursorShell::GetSmartTagRect( const Point& rPt, SwRect& rSelectRect ) if( !GetLayout()->GetModelPositionForViewPoint( &aPos, aPt, &eTmpState ) ) return; - pNode = aPos.nNode.GetNode().GetTextNode(); + pNode = aPos.GetNode().GetTextNode(); if( !pNode ) return; pSmartTagList = pNode->GetSmartTags(); @@ -3789,7 +4180,7 @@ void SwCursorShell::GetSmartTagRect( const Point& rPt, SwRect& rSelectRect ) if( pNode->IsInProtectSect() ) return; - sal_Int32 nBegin = aPos.nContent.GetIndex(); + sal_Int32 nBegin = aPos.GetContentIndex(); sal_Int32 nLen = 1; if (!pSmartTagList->InWrongWord(nBegin, nLen) || pNode->IsSymbolAt(nBegin)) @@ -3801,9 +4192,9 @@ void SwCursorShell::GetSmartTagRect( const Point& rPt, SwRect& rSelectRect ) //save the start and end positions of the line and the starting point Push(); LeftMargin(); - const sal_Int32 nLineStart = GetCursor()->GetPoint()->nContent.GetIndex(); + const sal_Int32 nLineStart = GetCursor()->GetPoint()->GetContentIndex(); RightMargin(); - const sal_Int32 nLineEnd = GetCursor()->GetPoint()->nContent.GetIndex(); + const sal_Int32 nLineEnd = GetCursor()->GetPoint()->GetContentIndex(); Pop(PopMode::DeleteCurrent); // make sure the selection build later from the data below does not @@ -3819,7 +4210,7 @@ void SwCursorShell::GetSmartTagRect( const Point& rPt, SwRect& rSelectRect ) while (pChar && *pChar-- == CH_TXTATR_INWORD) ++nRight; - aPos.nContent = nBegin + nLeft; + aPos.SetContent( nBegin + nLeft ); pCursor = GetCursor(); *pCursor->GetPoint() = aPos; pCursor->SetMark(); @@ -3831,18 +4222,18 @@ void SwCursorShell::GetSmartTagRect( const Point& rPt, SwRect& rSelectRect ) const sal_Int32 nWordEnd = std::min(nBegin + nLen - nLeft - nRight, nLineEnd); Push(); pCursor->DeleteMark(); - SwIndex& rContent = GetCursor()->GetPoint()->nContent; - rContent = nWordStart; + SwPosition& rPos = *GetCursor()->GetPoint(); + rPos.SetContent( nWordStart ); SwRect aStartRect; SwCursorMoveState aState; aState.m_bRealWidth = true; - SwContentNode* pContentNode = pCursor->GetContentNode(); + SwContentNode* pContentNode = pCursor->GetPointContentNode(); std::pair<Point, bool> const tmp(rPt, false); SwContentFrame *pContentFrame = pContentNode->getLayoutFrame( GetLayout(), pCursor->GetPoint(), &tmp); pContentFrame->GetCharRect( aStartRect, *pCursor->GetPoint(), &aState ); - rContent = nWordEnd - 1; + rPos.SetContent( nWordEnd - 1 ); SwRect aEndRect; pContentFrame->GetCharRect( aEndRect, *pCursor->GetPoint(),&aState ); rSelectRect = aStartRect.Union( aEndRect ); diff --git a/sw/source/core/crsr/crstrvl.cxx b/sw/source/core/crsr/crstrvl.cxx index 58bf0b4f9626..2abfb959a46d 100644 --- a/sw/source/core/crsr/crstrvl.cxx +++ b/sw/source/core/crsr/crstrvl.cxx @@ -74,6 +74,7 @@ #include <frameformats.hxx> #include <docsh.hxx> #include <wrtsh.hxx> +#include <textcontentcontrol.hxx> using namespace ::com::sun::star; @@ -88,7 +89,7 @@ void SwCursorShell::MoveCursorToNum() // SRectangle's height Point aPt( m_pCurrentCursor->GetPtPos() ); std::pair<Point, bool> const tmp(aPt, true); - SwContentFrame * pFrame = m_pCurrentCursor->GetContentNode()->getLayoutFrame( + SwContentFrame * pFrame = m_pCurrentCursor->GetPointContentNode()->getLayoutFrame( GetLayout(), m_pCurrentCursor->GetPoint(), &tmp); pFrame->GetCharRect( m_aCharRect, *m_pCurrentCursor->GetPoint() ); pFrame->Calc(GetOut()); @@ -137,21 +138,21 @@ bool SwCursorShell::GotoHeaderText() while( pFrame && !pFrame->IsContentFrame() ) pFrame = pFrame->GetLower(); - if( pFrame ) - { - CurrShell aCurr( this ); - // get header frame - SwCallLink aLk( *this ); // watch Cursor-Moves - SwCursor *pTmpCursor = getShellCursor( true ); - SwCursorSaveState aSaveState( *pTmpCursor ); - pFrame->Calc(GetOut()); - Point aPt( pFrame->getFrameArea().Pos() + pFrame->getFramePrintArea().Pos() ); - pFrame->GetModelPositionForViewPoint( pTmpCursor->GetPoint(), aPt ); - if( !pTmpCursor->IsSelOvr() ) - UpdateCursor(); - else - pFrame = nullptr; - } + if( !pFrame ) + return false; + + CurrShell aCurr( this ); + // get header frame + SwCallLink aLk( *this ); // watch Cursor-Moves + SwCursor *pTmpCursor = getShellCursor( true ); + SwCursorSaveState aSaveState( *pTmpCursor ); + pFrame->Calc(GetOut()); + Point aPt( pFrame->getFrameArea().Pos() + pFrame->getFramePrintArea().Pos() ); + pFrame->GetModelPositionForViewPoint( pTmpCursor->GetPoint(), aPt ); + if( !pTmpCursor->IsSelOvr() ) + UpdateCursor(); + else + pFrame = nullptr; return nullptr != pFrame; } @@ -159,42 +160,37 @@ bool SwCursorShell::GotoHeaderText() bool SwCursorShell::GotoFooterText() { const SwPageFrame* pFrame = GetCurrFrame()->FindPageFrame(); - if( pFrame ) - { - const SwFrame* pLower = pFrame->GetLastLower(); + if( !pFrame ) + return false; - while( pLower && !pLower->IsFooterFrame() ) - pLower = pLower->GetLower(); - // found footer, search 1. content frame - while( pLower && !pLower->IsContentFrame() ) - pLower = pLower->GetLower(); + const SwFrame* pLower = pFrame->GetLastLower(); - if( pLower ) - { - SwCursor *pTmpCursor = getShellCursor( true ); - CurrShell aCurr( this ); - // get position in footer - SwCallLink aLk( *this ); // watch Cursor-Moves - SwCursorSaveState aSaveState( *pTmpCursor ); - pLower->Calc(GetOut()); - Point aPt( pLower->getFrameArea().Pos() + pLower->getFramePrintArea().Pos() ); - pLower->GetModelPositionForViewPoint( pTmpCursor->GetPoint(), aPt ); - if( !pTmpCursor->IsSelOvr() ) - UpdateCursor(); - else - pFrame = nullptr; - } - else - pFrame = nullptr; - } + while( pLower && !pLower->IsFooterFrame() ) + pLower = pLower->GetLower(); + // found footer, search 1. content frame + while( pLower && !pLower->IsContentFrame() ) + pLower = pLower->GetLower(); + + if( !pLower ) + return false; + + SwCursor *pTmpCursor = getShellCursor( true ); + CurrShell aCurr( this ); + // get position in footer + SwCallLink aLk( *this ); // watch Cursor-Moves + SwCursorSaveState aSaveState( *pTmpCursor ); + pLower->Calc(GetOut()); + Point aPt( pLower->getFrameArea().Pos() + pLower->getFramePrintArea().Pos() ); + pLower->GetModelPositionForViewPoint( pTmpCursor->GetPoint(), aPt ); + if( !pTmpCursor->IsSelOvr() ) + UpdateCursor(); else pFrame = nullptr; return nullptr != pFrame; } -bool SwCursorShell::SetCursorInHdFt( size_t nDescNo, bool bInHeader ) +bool SwCursorShell::SetCursorInHdFt(size_t nDescNo, bool bInHeader, bool bEven, bool bFirst) { - bool bRet = false; SwDoc *pMyDoc = GetDoc(); const SwPageDesc* pDesc = nullptr; @@ -213,61 +209,62 @@ bool SwCursorShell::SetCursorInHdFt( size_t nDescNo, bool bInHeader ) if (nDescNo < pMyDoc->GetPageDescCnt()) pDesc = &pMyDoc->GetPageDesc( nDescNo ); - if( pDesc ) + if( !pDesc ) + return false; + + // check if the attribute exists + const SwFormatContent* pCnt = nullptr; + if( bInHeader ) { - // check if the attribute exists - const SwFormatContent* pCnt = nullptr; - if( bInHeader ) - { - // mirrored pages? ignore for now - const SwFormatHeader& rHd = pDesc->GetMaster().GetHeader(); - if( rHd.GetHeaderFormat() ) - pCnt = &rHd.GetHeaderFormat()->GetContent(); - } - else - { - const SwFormatFooter& rFt = pDesc->GetMaster().GetFooter(); - if( rFt.GetFooterFormat() ) - pCnt = &rFt.GetFooterFormat()->GetContent(); - } + const SwFormatHeader& rHd + = bEven ? bFirst ? pDesc->GetFirstLeft().GetHeader() : pDesc->GetLeft().GetHeader() + : bFirst ? pDesc->GetFirstMaster().GetHeader() : pDesc->GetMaster().GetHeader(); + if( rHd.GetHeaderFormat() ) + pCnt = &rHd.GetHeaderFormat()->GetContent(); + } + else + { + const SwFormatFooter& rFt + = bEven ? bFirst ? pDesc->GetFirstLeft().GetFooter() : pDesc->GetLeft().GetFooter() + : bFirst ? pDesc->GetFirstMaster().GetFooter() : pDesc->GetMaster().GetFooter(); + if( rFt.GetFooterFormat() ) + pCnt = &rFt.GetFooterFormat()->GetContent(); + } - if( pCnt && pCnt->GetContentIdx() ) - { - SwNodeIndex aIdx( *pCnt->GetContentIdx(), 1 ); - SwContentNode* pCNd = aIdx.GetNode().GetContentNode(); - if( !pCNd ) - pCNd = pMyDoc->GetNodes().GoNext( &aIdx ); + if( !pCnt || !pCnt->GetContentIdx() ) + return false; - Point aPt( m_pCurrentCursor->GetPtPos() ); + SwNodeIndex aIdx( *pCnt->GetContentIdx(), 1 ); + SwContentNode* pCNd = aIdx.GetNode().GetContentNode(); + if( !pCNd ) + pCNd = SwNodes::GoNext(&aIdx); - std::pair<Point, bool> const tmp(aPt, false); - if (pCNd && nullptr != pCNd->getLayoutFrame(GetLayout(), nullptr, &tmp)) - { - // then we can set the cursor in here - SwCallLink aLk( *this ); // watch Cursor-Moves - SwCursorSaveState aSaveState( *m_pCurrentCursor ); + Point aPt( m_pCurrentCursor->GetPtPos() ); - ClearMark(); + std::pair<Point, bool> const tmp(aPt, false); + if (!pCNd || nullptr == pCNd->getLayoutFrame(GetLayout(), nullptr, &tmp)) + return false; - SwPosition& rPos = *m_pCurrentCursor->GetPoint(); - rPos.nNode = *pCNd; - rPos.nContent.Assign( pCNd, 0 ); + // then we can set the cursor in here + SwCallLink aLk( *this ); // watch Cursor-Moves + SwCursorSaveState aSaveState( *m_pCurrentCursor ); - bRet = !m_pCurrentCursor->IsSelOvr(); - if( bRet ) - UpdateCursor( SwCursorShell::SCROLLWIN | SwCursorShell::CHKRANGE | - SwCursorShell::READONLY ); - } - } - } - return bRet; + ClearMark(); + + SwPosition& rPos = *m_pCurrentCursor->GetPoint(); + rPos.Assign( *pCNd ); + + if (m_pCurrentCursor->IsSelOvr()) + return false; + + UpdateCursor( SwCursorShell::SCROLLWIN | SwCursorShell::CHKRANGE | + SwCursorShell::READONLY ); + return true; } /// jump to the next index bool SwCursorShell::GotoNextTOXBase( const OUString* pName ) { - bool bRet = false; - const SwSectionFormats& rFormats = GetDoc()->GetSections(); SwContentNode* pFnd = nullptr; for( SwSectionFormats::size_type n = rFormats.size(); n; ) @@ -278,7 +275,7 @@ bool SwCursorShell::GotoNextTOXBase( const OUString* pName ) SwSectionNode const*const pSectNd( pSect->GetFormat()->GetSectionNode()); if ( pSectNd - && m_pCurrentCursor->GetPoint()->nNode < pSectNd->GetIndex() + && m_pCurrentCursor->GetPoint()->GetNode() < *pSectNd && (!pFnd || pFnd->GetIndex() > pSectNd->GetIndex()) && (!pName || *pName == static_cast<SwTOXBaseSection const*>(pSect)->GetTOXName())) @@ -286,7 +283,7 @@ bool SwCursorShell::GotoNextTOXBase( const OUString* pName ) SwNodeIndex aIdx(*pSectNd, 1); SwContentNode* pCNd = aIdx.GetNode().GetContentNode(); if (!pCNd) - pCNd = GetDoc()->GetNodes().GoNext( &aIdx ); + pCNd = SwNodes::GoNext(&aIdx); if (pCNd && pCNd->EndOfSectionIndex() <= pSectNd->EndOfSectionIndex()) { @@ -301,24 +298,20 @@ bool SwCursorShell::GotoNextTOXBase( const OUString* pName ) } } } - if( pFnd ) - { - SwCallLink aLk( *this ); // watch Cursor-Moves - SwCursorSaveState aSaveState( *m_pCurrentCursor ); - m_pCurrentCursor->GetPoint()->nNode = *pFnd; - m_pCurrentCursor->GetPoint()->nContent.Assign( pFnd, 0 ); - bRet = !m_pCurrentCursor->IsSelOvr(); - if( bRet ) - UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY); - } + if( !pFnd ) + return false; + SwCallLink aLk( *this ); // watch Cursor-Moves + SwCursorSaveState aSaveState( *m_pCurrentCursor ); + m_pCurrentCursor->GetPoint()->Assign( *pFnd ); + bool bRet = !m_pCurrentCursor->IsSelOvr(); + if( bRet ) + UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY); return bRet; } /// jump to previous index bool SwCursorShell::GotoPrevTOXBase( const OUString* pName ) { - bool bRet = false; - const SwSectionFormats& rFormats = GetDoc()->GetSections(); SwContentNode* pFnd = nullptr; for( SwSectionFormats::size_type n = rFormats.size(); n; ) @@ -329,15 +322,15 @@ bool SwCursorShell::GotoPrevTOXBase( const OUString* pName ) SwSectionNode const*const pSectNd( pSect->GetFormat()->GetSectionNode()); if ( pSectNd - && m_pCurrentCursor->GetPoint()->nNode > pSectNd->EndOfSectionIndex() - && (!pFnd || pFnd->GetIndex() < pSectNd->GetIndex()) + && m_pCurrentCursor->GetPoint()->GetNode() > *pSectNd->EndOfSectionNode() + && (!pFnd || *pFnd < *pSectNd) && (!pName || *pName == static_cast<SwTOXBaseSection const*>(pSect)->GetTOXName())) { SwNodeIndex aIdx(*pSectNd, 1); SwContentNode* pCNd = aIdx.GetNode().GetContentNode(); if (!pCNd) - pCNd = GetDoc()->GetNodes().GoNext( &aIdx ); + pCNd = SwNodes::GoNext(&aIdx); if (pCNd && pCNd->EndOfSectionIndex() <= pSectNd->EndOfSectionIndex()) { @@ -353,16 +346,15 @@ bool SwCursorShell::GotoPrevTOXBase( const OUString* pName ) } } - if( pFnd ) - { - SwCallLink aLk( *this ); // watch Cursor-Moves - SwCursorSaveState aSaveState( *m_pCurrentCursor ); - m_pCurrentCursor->GetPoint()->nNode = *pFnd; - m_pCurrentCursor->GetPoint()->nContent.Assign( pFnd, 0 ); - bRet = !m_pCurrentCursor->IsSelOvr(); - if( bRet ) - UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY); - } + if( !pFnd ) + return false; + + SwCallLink aLk( *this ); // watch Cursor-Moves + SwCursorSaveState aSaveState( *m_pCurrentCursor ); + m_pCurrentCursor->GetPoint()->Assign(*pFnd); + bool bRet = !m_pCurrentCursor->IsSelOvr(); + if( bRet ) + UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY); return bRet; } @@ -375,7 +367,9 @@ void SwCursorShell::GotoTOXMarkBase() return; // Take the 1. and get the index type. Ask it for the actual index. const SwTOXType* pType = aMarks[0]->GetTOXType(); - auto pContentFrame = pType->FindContentFrame(*GetDoc(), *GetLayout(), IsReadOnlyAvailable()); + auto pContentFrame = pType->FindContentFrame(*GetLayout()); + if(!pContentFrame) + return; SwCallLink aLk(*this); // watch Cursor-Moves SwCursorSaveState aSaveState(*m_pCurrentCursor); assert(pContentFrame->IsTextFrame()); @@ -400,11 +394,11 @@ bool SwCursorShell::GotoNxtPrvTableFormula( bool bNext, bool bOnlyErrors ) Point aPt; SwPosition aFndPos( GetDoc()->GetNodes().GetEndOfContent() ); if( !bNext ) - aFndPos.nNode = 0; + aFndPos.Assign(SwNodeOffset(0)); SetGetExpField aFndGEF( aFndPos ), aCurGEF( rPos ); { - const SwNode* pSttNd = rPos.nNode.GetNode().FindTableBoxStartNode(); + const SwNode* pSttNd = rPos.GetNode().FindTableBoxStartNode(); if( pSttNd ) { const SwTableBox* pTBox = pSttNd->FindTableNode()->GetTable(). @@ -414,93 +408,91 @@ bool SwCursorShell::GotoNxtPrvTableFormula( bool bNext, bool bOnlyErrors ) } } - if( rPos.nNode < GetDoc()->GetNodes().GetEndOfExtras() ) + if( rPos.GetNode() < GetDoc()->GetNodes().GetEndOfExtras() ) { // also at collection use only the first frame std::pair<Point, bool> const tmp(aPt, false); - aCurGEF.SetBodyPos( *rPos.nNode.GetNode().GetContentNode()->getLayoutFrame( GetLayout(), + aCurGEF.SetBodyPos( *rPos.GetNode().GetContentNode()->getLayoutFrame( GetLayout(), &rPos, &tmp) ); } - { - sal_uInt32 nMaxItems = GetDoc()->GetAttrPool().GetItemCount2( RES_BOXATR_FORMULA ); - if( nMaxItems > 0 ) - { - sal_uInt8 nMaxDo = 2; - do { - for (const SfxPoolItem* pItem : GetDoc()->GetAttrPool().GetItemSurrogates(RES_BOXATR_FORMULA)) + ItemSurrogates aSurrogates; + GetDoc()->GetAttrPool().GetItemSurrogates(aSurrogates, RES_BOXATR_FORMULA); + const sal_uInt32 nMaxItems(aSurrogates.size()); + if( nMaxItems > 0 ) + { + sal_uInt8 nMaxDo = 2; + do { + for (const SfxPoolItem* pItem : aSurrogates) + { + const SwTableBox* pTBox; + auto pFormulaItem = dynamic_cast<const SwTableBoxFormula*>(pItem); + if( !pFormulaItem ) + continue; + pTBox = pFormulaItem->GetTableBox(); + if( pTBox && + pTBox->GetSttNd() && + pTBox->GetSttNd()->GetNodes().IsDocNodes() && + ( !bOnlyErrors || + !pFormulaItem->HasValidBoxes() ) ) { - const SwTableBox* pTBox; - auto pFormulaItem = dynamic_cast<const SwTableBoxFormula*>(pItem); - if( !pFormulaItem ) - continue; - pTBox = pFormulaItem->GetTableBox(); - if( pTBox && - pTBox->GetSttNd() && - pTBox->GetSttNd()->GetNodes().IsDocNodes() && - ( !bOnlyErrors || - !pFormulaItem->HasValidBoxes() ) ) + SwNodeIndex aIdx( *pTBox->GetSttNd() ); + const SwContentNode* pCNd = SwNodes::GoNext(&aIdx); + std::pair<Point, bool> const tmp(aPt, false); + if (pCNd) { - SwNodeIndex aIdx( *pTBox->GetSttNd() ); - const SwContentNode* pCNd = GetDoc()->GetNodes().GoNext( &aIdx ); - std::pair<Point, bool> const tmp(aPt, false); - if (pCNd) + const SwContentFrame* pCFrame = pCNd->getLayoutFrame(GetLayout(), nullptr, &tmp); + if (pCFrame && (IsReadOnlyAvailable() || !pCFrame->IsProtected() )) { - const SwContentFrame* pCFrame = pCNd->getLayoutFrame(GetLayout(), nullptr, &tmp); - if (pCFrame && (IsReadOnlyAvailable() || !pCFrame->IsProtected() )) - { - SetGetExpField aCmp( *pTBox ); - aCmp.SetBodyPos( *pCFrame ); + SetGetExpField aCmp( *pTBox ); + aCmp.SetBodyPos( *pCFrame ); - if( bNext ? ( aCurGEF < aCmp && aCmp < aFndGEF ) - : ( aCmp < aCurGEF && aFndGEF < aCmp )) - { - aFndGEF = aCmp; - bFnd = true; - } + if( bNext ? ( aCurGEF < aCmp && aCmp < aFndGEF ) + : ( aCmp < aCurGEF && aFndGEF < aCmp )) + { + aFndGEF = aCmp; + bFnd = true; } } } } - if( !bFnd ) + } + if( !bFnd ) + { + if( bNext ) { - if( bNext ) - { - rPos.nNode = 0; - rPos.nContent = 0; - aCurGEF = SetGetExpField( rPos ); - SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::EndWrapped ); - } - else - { - aCurGEF = SetGetExpField( SwPosition( GetDoc()->GetNodes().GetEndOfContent() ) ); - SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::StartWrapped ); - } + rPos.Assign(SwNodeOffset(0), 0); + aCurGEF = SetGetExpField( rPos ); + SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::EndWrapped ); } - } while( !bFnd && --nMaxDo ); - } + else + { + aCurGEF = SetGetExpField( SwPosition( GetDoc()->GetNodes().GetEndOfContent() ) ); + SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::StartWrapped ); + } + } + } while( !bFnd && --nMaxDo ); } - if( bFnd ) - { - CurrShell aCurr( this ); - SwCallLink aLk( *this ); // watch Cursor-Moves - SwCursorSaveState aSaveState( *m_pCurrentCursor ); - - aFndGEF.GetPosOfContent( rPos ); - m_pCurrentCursor->DeleteMark(); - - bFnd = !m_pCurrentCursor->IsSelOvr(); - if( bFnd ) - UpdateCursor( SwCursorShell::SCROLLWIN | SwCursorShell::CHKRANGE | - SwCursorShell::READONLY ); - } - else + if( !bFnd ) { - rPos = aOldPos; + rPos = std::move(aOldPos); SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound ); + return false; } + CurrShell aCurr( this ); + SwCallLink aLk( *this ); // watch Cursor-Moves + SwCursorSaveState aSaveState( *m_pCurrentCursor ); + + aFndGEF.GetPosOfContent( rPos ); + m_pCurrentCursor->DeleteMark(); + + bFnd = !m_pCurrentCursor->IsSelOvr(); + if( bFnd ) + UpdateCursor( SwCursorShell::SCROLLWIN | SwCursorShell::CHKRANGE | + SwCursorShell::READONLY ); + return bFnd; } @@ -518,86 +510,81 @@ bool SwCursorShell::GotoNxtPrvTOXMark( bool bNext ) Point aPt; SwPosition aFndPos( GetDoc()->GetNodes().GetEndOfContent() ); if( !bNext ) - aFndPos.nNode = 0; + aFndPos.Assign(SwNodeOffset(0)); SetGetExpField aFndGEF( aFndPos ), aCurGEF( rPos ); - if( rPos.nNode.GetIndex() < GetDoc()->GetNodes().GetEndOfExtras().GetIndex() ) + if( rPos.GetNodeIndex() < GetDoc()->GetNodes().GetEndOfExtras().GetIndex() ) { // also at collection use only the first frame std::pair<Point, bool> const tmp(aPt, false); - aCurGEF.SetBodyPos( *rPos.nNode.GetNode(). + aCurGEF.SetBodyPos( *rPos.GetNode(). GetContentNode()->getLayoutFrame(GetLayout(), &rPos, &tmp)); } + const SwTextNode* pTextNd; + const SwTextTOXMark* pTextTOX; + ItemSurrogates aSurrogates; + GetDoc()->GetAttrPool().GetItemSurrogates(aSurrogates, RES_TXTATR_TOXMARK); + const sal_uInt32 nMaxItems(aSurrogates.size()); + if( nMaxItems == 0 ) { - const SwTextNode* pTextNd; - const SwTextTOXMark* pTextTOX; - sal_uInt32 nMaxItems = GetDoc()->GetAttrPool().GetItemCount2( RES_TXTATR_TOXMARK ); + SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound ); + return false; + } - if( nMaxItems > 0 ) + do { + for (const SfxPoolItem* pItem : aSurrogates) { - do { - for (const SfxPoolItem* pItem : GetDoc()->GetAttrPool().GetItemSurrogates(RES_TXTATR_TOXMARK)) - { - auto pToxMarkItem = dynamic_cast<const SwTOXMark*>(pItem); - if( !pToxMarkItem ) - continue; - pTextTOX = pToxMarkItem->GetTextTOXMark(); - if( !pTextTOX ) - continue; - pTextNd = &pTextTOX->GetTextNode(); - if( !pTextNd->GetNodes().IsDocNodes() ) - continue; - std::pair<Point, bool> const tmp(aPt, false); - const SwContentFrame* pCFrame = pTextNd->getLayoutFrame(GetLayout(), nullptr, &tmp); - if( pCFrame && ( IsReadOnlyAvailable() || !pCFrame->IsProtected() )) - { - SwNodeIndex aNdIndex( *pTextNd ); // UNIX needs this object - SetGetExpField aCmp( aNdIndex, *pTextTOX ); - aCmp.SetBodyPos( *pCFrame ); + auto pToxMarkItem = dynamic_cast<const SwTOXMark*>(pItem); + if( !pToxMarkItem ) + continue; + pTextTOX = pToxMarkItem->GetTextTOXMark(); + if( !pTextTOX ) + continue; + pTextNd = &pTextTOX->GetTextNode(); + if( !pTextNd->GetNodes().IsDocNodes() ) + continue; + std::pair<Point, bool> const tmp(aPt, false); + const SwContentFrame* pCFrame = pTextNd->getLayoutFrame(GetLayout(), nullptr, &tmp); + if( pCFrame && ( IsReadOnlyAvailable() || !pCFrame->IsProtected() )) + { + SetGetExpField aCmp( *pTextNd, *pTextTOX ); + aCmp.SetBodyPos( *pCFrame ); - if( bNext ? ( aCurGEF < aCmp && aCmp < aFndGEF ) - : ( aCmp < aCurGEF && aFndGEF < aCmp )) - { - aFndGEF = aCmp; - bFnd = true; - } - } - } - if( !bFnd ) + if( bNext ? ( aCurGEF < aCmp && aCmp < aFndGEF ) + : ( aCmp < aCurGEF && aFndGEF < aCmp )) { - if ( bNext ) - { - rPos.nNode = 0; - rPos.nContent = 0; - aCurGEF = SetGetExpField( rPos ); - SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::EndWrapped ); - } - else - { - aCurGEF = SetGetExpField( SwPosition( GetDoc()->GetNodes().GetEndOfContent() ) ); - SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::StartWrapped ); - } + aFndGEF = aCmp; + bFnd = true; } - } while ( !bFnd ); + } } - else - SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound ); - } + if( !bFnd ) + { + if ( bNext ) + { + rPos.Assign(SwNodeOffset(0), 0); + aCurGEF = SetGetExpField( rPos ); + SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::EndWrapped ); + } + else + { + aCurGEF = SetGetExpField( SwPosition( GetDoc()->GetNodes().GetEndOfContent() ) ); + SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::StartWrapped ); + } + } + } while ( !bFnd ); - if( bFnd ) - { - CurrShell aCurr( this ); - SwCallLink aLk( *this ); // watch Cursor-Moves - SwCursorSaveState aSaveState( *m_pCurrentCursor ); + CurrShell aCurr( this ); + SwCallLink aLk( *this ); // watch Cursor-Moves + SwCursorSaveState aSaveState( *m_pCurrentCursor ); - aFndGEF.GetPosOfContent( rPos ); + aFndGEF.GetPosOfContent( rPos ); - bFnd = !m_pCurrentCursor->IsSelOvr(); - if( bFnd ) - UpdateCursor( SwCursorShell::SCROLLWIN | SwCursorShell::CHKRANGE | - SwCursorShell::READONLY ); - } + bFnd = !m_pCurrentCursor->IsSelOvr(); + if( bFnd ) + UpdateCursor( SwCursorShell::SCROLLWIN | SwCursorShell::CHKRANGE | + SwCursorShell::READONLY ); return bFnd; } @@ -613,9 +600,9 @@ const SwTOXMark& SwCursorShell::GotoTOXMark( const SwTOXMark& rStart, IsReadOnlyAvailable() ); // set position SwPosition& rPos = *GetCursor()->GetPoint(); - rPos.nNode = rNewMark.GetTextTOXMark()->GetTextNode(); - rPos.nContent.Assign( rPos.nNode.GetNode().GetContentNode(), - rNewMark.GetTextTOXMark()->GetStart() ); + rPos.Assign(rNewMark.GetTextTOXMark()->GetTextNode(), + rNewMark.GetTextTOXMark()->GetStart() ); + GetCursor()->DeleteMark(); // tdf#158783 prevent UpdateCursor resetting point if( !m_pCurrentCursor->IsSelOvr() ) UpdateCursor( SwCursorShell::SCROLLWIN | SwCursorShell::CHKRANGE | @@ -651,7 +638,7 @@ static void lcl_MakeFieldLst( if ( pCFrame != nullptr && ( bInReadOnly || !pCFrame->IsProtected() ) ) { - std::unique_ptr<SetGetExpField> pNew(new SetGetExpField( SwNodeIndex( rTextNode ), pTextField )); + std::unique_ptr<SetGetExpField> pNew(new SetGetExpField( rTextNode, pTextField )); pNew->SetBodyPos( *pCFrame ); rLst.insert( std::move(pNew) ); } @@ -665,29 +652,27 @@ lcl_FindField(bool & o_rFound, SetGetExpFields const& rSrtLst, SwTextField const *const pTextField, SwPosition const& rPos, sal_Int32 const nContentOffset) { - std::unique_ptr<SetGetExpField> pSrch; - std::unique_ptr<SwIndex> pIndex; + std::optional<SetGetExpField> oSrch; if (-1 == nContentOffset) { - pSrch.reset(new SetGetExpField(rPos.nNode, pTextField, &rPos.nContent)); + oSrch.emplace(rPos.GetNode(), pTextField, rPos.GetContentIndex()); } else { - pIndex.reset(new SwIndex(rPos.nNode.GetNode().GetContentNode(), nContentOffset)); - pSrch.reset(new SetGetExpField(rPos.nNode, pTextField, pIndex.get())); + oSrch.emplace(rPos.GetNode(), pTextField, nContentOffset); } - if (rPos.nNode.GetIndex() < pTextNode->GetNodes().GetEndOfExtras().GetIndex()) + if (rPos.GetNodeIndex() < pTextNode->GetNodes().GetEndOfExtras().GetIndex()) { // also at collection use only the first frame Point aPt; std::pair<Point, bool> const tmp(aPt, false); - pSrch->SetBodyPos(*pTextNode->getLayoutFrame(pLayout, &rPos, &tmp)); + oSrch->SetBodyPos(*pTextNode->getLayoutFrame(pLayout, &rPos, &tmp)); } - SetGetExpFields::const_iterator it = rSrtLst.lower_bound(pSrch.get()); + SetGetExpFields::const_iterator it = rSrtLst.lower_bound(&*oSrch); - o_rFound = (it != rSrtLst.end()) && (**it == *pSrch); + o_rFound = (it != rSrtLst.end()) && (**it == *oSrch); return it; } @@ -752,21 +737,28 @@ bool SwCursorShell::MoveFieldType( // field const SwPosition& rPos = *pCursor->GetPoint(); - SwTextNode* pTNd = rPos.nNode.GetNode().GetTextNode(); + SwTextNode* pTNd = rPos.GetNode().GetTextNode(); OSL_ENSURE( pTNd, "No ContentNode" ); - SwTextField * pTextField = pTNd->GetFieldTextAttrAt( rPos.nContent.GetIndex(), true ); + SwTextField * pTextField = pTNd->GetFieldTextAttrAt(rPos.GetContentIndex(), ::sw::GetTextAttrMode::Default); const bool bDelField = ( pTextField == nullptr ); sal_Int32 nContentOffset = -1; if( bDelField ) { // create dummy for the search - SwFormatField* pFormatField = new SwFormatField( SwDateTimeField( - static_cast<SwDateTimeFieldType*>(mxDoc->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::DateTime ) ) ) ); - - pTextField = new SwTextField( *pFormatField, rPos.nContent.GetIndex(), - mxDoc->IsClipBoard() ); + // NOTE: with SfxPoolItemHolder in SwTextAttr the + // SwFormatField will just be managed by it, when + // wanted and handing over bPassingOwnership==true + pTextField = new SwTextField ( + SfxPoolItemHolder( + mxDoc->GetAttrPool(), + new SwFormatField( + SwDateTimeField( + static_cast<SwDateTimeFieldType*>(mxDoc->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::DateTime )))), + true), // bPassingOwnership + rPos.GetContentIndex(), + mxDoc->IsClipBoard() ); pTextField->ChgTextNode( pTNd ); } else @@ -774,7 +766,7 @@ bool SwCursorShell::MoveFieldType( // the cursor might be anywhere inside the input field, // but we will be searching for the field start if (pTextField->Which() == RES_TXTATR_INPUTFIELD - && rPos.nContent.GetIndex() != pTextField->GetStart()) + && rPos.GetContentIndex() != pTextField->GetStart()) nContentOffset = pTextField->GetStart(); } bool isSrch; @@ -783,9 +775,9 @@ bool SwCursorShell::MoveFieldType( if( bDelField ) { - auto const pFormat(static_cast<SwFormatField*>(&pTextField->GetAttr())); + // with using SfxPoolItemHolder in SwTextAttr there is no need anymore + // to cleanup the contained SwFormatField self delete pTextField; - delete pFormat; } if( it != aSrtLst.end() && isSrch ) // found @@ -831,42 +823,227 @@ bool SwCursorShell::MoveFieldType( return bRet; } -bool SwCursorShell::GotoFormatField( const SwFormatField& rField ) +bool SwCursorShell::GotoFootnoteAnchor(const SwTextFootnote& rTextFootnote) { + if (SwWrtShell* pWrtSh = dynamic_cast<SwWrtShell*>(this)) + pWrtSh->addCurrentPosition(); + bool bRet = false; - SwTextField const*const pTextField(rField.GetTextField()); - if (pTextField - && (!GetLayout()->IsHideRedlines() - || !sw::IsFieldDeletedInModel( - GetDoc()->getIDocumentRedlineAccess(), *pTextField))) - { - CurrShell aCurr( this ); - SwCallLink aLk( *this ); // watch Cursor-Moves + SwCursor* pCursor = getShellCursor(true); + + CurrShell aCurr(this); + SwCallLink aLk(*this); // watch Cursor-Moves + SwCursorSaveState aSaveState(*pCursor); + + pCursor->GetPoint()->Assign(rTextFootnote.GetTextNode(), + rTextFootnote.GetStart()); + bRet = !pCursor->IsSelOvr(); + if (bRet) + UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY); + return bRet; +} + +bool SwCursorShell::GotoFormatContentControl(const SwFormatContentControl& rContentControl) +{ + std::shared_ptr<SwContentControl> pContentControl = rContentControl.GetContentControl(); + const SwTextContentControl* pTextContentControl = pContentControl->GetTextAttr(); + if (!pTextContentControl) + return false; - SwCursor* pCursor = getShellCursor( true ); - SwCursorSaveState aSaveState( *pCursor ); + CurrShell aCurr(this); + SwCallLink aLink(*this); - SwTextNode* pTNd = pTextField->GetpTextNode(); - pCursor->GetPoint()->nNode = *pTNd; - pCursor->GetPoint()->nContent.Assign( pTNd, pTextField->GetStart() ); + SwCursor* pCursor = getShellCursor(true); + SwCursorSaveState aSaveState(*pCursor); + SwTextNode* pTextNode = pContentControl->GetTextNode(); + // Don't select the text attribute itself at the start. + sal_Int32 nStart = pTextContentControl->GetStart() + 1; + pCursor->GetPoint()->Assign(*pTextNode, nStart); + + bool bRet = true; + // select contents for certain controls or conditions + if (pContentControl->GetShowingPlaceHolder() || pContentControl->GetCheckbox() + || pContentControl->GetSelectedListItem() || pContentControl->GetSelectedDate()) + { + pCursor->SetMark(); + // Don't select the CH_TXTATR_BREAKWORD itself at the end. + sal_Int32 nEnd = *pTextContentControl->End() - 1; + pCursor->GetMark()->Assign(*pTextNode, nEnd); bRet = !pCursor->IsSelOvr(); - if( bRet ) - UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY); } + else + ClearMark(); + + if (bRet) + { + UpdateCursor(SwCursorShell::SCROLLWIN | SwCursorShell::CHKRANGE + | SwCursorShell::READONLY); + } + + return bRet; +} + +/** + * Go to the next (or previous) form control, based first on tabIndex and then paragraph position, + * where a tabIndex of 1 is first, 0 is last, and -1 is excluded. + */ +void SwCursorShell::GotoFormControl(bool bNext) +{ + // (note: this only applies to modern content controls and legacy fieldmarks, + // since activeX richText controls aren't exposed to SW keystrokes) + + struct FormControlSort + { + bool operator()(std::pair<const SwPosition&, sal_uInt32> rLHS, + std::pair<const SwPosition&, sal_uInt32> rRHS) const + { + assert(rLHS.second && rRHS.second && "tabIndex zero must be changed to SAL_MAX_UINT32"); + //first compare tabIndexes where 1 has the priority. + if (rLHS.second < rRHS.second) + return true; + if (rLHS.second > rRHS.second) + return false; + + // when tabIndexes are equal (and they usually are) then sort by paragraph position + return rLHS.first < rRHS.first; + } + }; + std::map<std::pair<SwPosition, sal_uInt32>, + std::pair<SwTextContentControl*, sw::mark::IFieldmark*>, FormControlSort> aFormMap; + + // add all of the eligible modern Content Controls into a sorted map + SwContentControlManager& rManager = GetDoc()->GetContentControlManager(); + for (size_t i = 0; i < rManager.GetCount(); ++i) + { + SwTextContentControl* pTCC = rManager.UnsortedGet(i); + if (!pTCC || !pTCC->GetTextNode()) + continue; + auto pCC = pTCC->GetContentControl().GetContentControl(); + + // -1 indicates the control should not participate in keyboard tab navigation + if (pCC && pCC->GetTabIndex() == SAL_MAX_UINT32) + continue; + + const SwPosition nPos(*pTCC->GetTextNode(), pTCC->GetStart()); + + // since 0 is the lowest priority (1 is the highest), and -1 has already been excluded, + // use SAL_MAX_UINT32 as zero's tabIndex so that automatic sorting is correct. + sal_uInt32 nTabIndex = pCC && pCC->GetTabIndex() ? pCC->GetTabIndex() : SAL_MAX_UINT32; + + const std::pair<SwTextContentControl*, sw::mark::IFieldmark*> pFormControl(pTCC, nullptr); + aFormMap[std::make_pair(nPos, nTabIndex)] = pFormControl; + } + + if (aFormMap.begin() == aFormMap.end()) + { + // only legacy fields exist. Avoid reprocessing everything and use legacy code path. + GotoFieldmark(bNext ? GetFieldmarkAfter() : GetFieldmarkBefore()); + return; + } + + // add all of the legacy form field controls into the sorted map + IDocumentMarkAccess* pMarkAccess = GetDoc()->getIDocumentMarkAccess(); + for (auto it = pMarkAccess->getFieldmarksBegin(); it != pMarkAccess->getFieldmarksEnd(); ++it) + { + auto pFieldMark = dynamic_cast<sw::mark::IFieldmark*>(*it); + assert(pFieldMark); + // legacy form fields do not have (functional) tabIndexes - use lowest priority for them + aFormMap[std::make_pair((*it)->GetMarkStart(), SAL_MAX_UINT32)] = + std::pair<SwTextContentControl*, sw::mark::IFieldmark*>(nullptr, pFieldMark); + } + + if (aFormMap.begin() == aFormMap.end()) + return; + + // Identify the current location in the document, and the current tab index priority + + // A content control could contain a Fieldmark, so check for legacy fieldmarks first + sw::mark::IFieldmark* pFieldMark = GetCurrentFieldmark(); + SwTextContentControl* pTCC = !pFieldMark ? CursorInsideContentControl() : nullptr; + + auto pCC = pTCC ? pTCC->GetContentControl().GetContentControl() : nullptr; + const sal_Int32 nCurTabIndex = pCC && pCC->GetTabIndex() ? pCC->GetTabIndex() : SAL_MAX_UINT32; + + SwPosition nCurPos(*GetCursor()->GetPoint()); + if (pFieldMark) + nCurPos = pFieldMark->GetMarkStart(); + else if (pTCC && pTCC->GetTextNode()) + nCurPos = SwPosition(*pTCC->GetTextNode(), pTCC->GetStart()); + + // Find the previous (or next) tab control and navigate to it + const std::pair<SwPosition, sal_uInt32> nOldPos(nCurPos, nCurTabIndex); + + // lower_bound acts like find, and returns a pointer to nFindPos if it exists, + // otherwise it will point to the previous entry. + auto aNewPos = aFormMap.lower_bound(nOldPos); + if (bNext && aNewPos != aFormMap.end()) + ++aNewPos; + else if (!bNext && aNewPos != aFormMap.end() && aNewPos->first == nOldPos) + { + // Found the current position - need to return previous + if (aNewPos == aFormMap.begin()) + aNewPos = aFormMap.end(); // prepare to loop around + else + --aNewPos; + } + + if (aNewPos == aFormMap.end()) + { + // Loop around to the other side + if (bNext) + aNewPos = aFormMap.begin(); + else + --aNewPos; + } + + // the entry contains a pointer to either a Content Control (first) or Fieldmark (second) + if (aNewPos->second.first) + { + auto& rFCC = static_cast<SwFormatContentControl&>(aNewPos->second.first->GetAttr()); + GotoFormatContentControl(rFCC); + } + else + { + assert(aNewPos->second.second); + GotoFieldmark(aNewPos->second.second); + } +} + +bool SwCursorShell::GotoFormatField( const SwFormatField& rField ) +{ + SwTextField const*const pTextField(rField.GetTextField()); + if (!pTextField + || (GetLayout()->IsHideRedlines() + && sw::IsFieldDeletedInModel( + GetDoc()->getIDocumentRedlineAccess(), *pTextField))) + return false; + + CurrShell aCurr( this ); + SwCallLink aLk( *this ); // watch Cursor-Moves + + SwCursor* pCursor = getShellCursor( true ); + SwCursorSaveState aSaveState( *pCursor ); + + SwTextNode* pTNd = pTextField->GetpTextNode(); + pCursor->GetPoint()->Assign(*pTNd, pTextField->GetStart() ); + + bool bRet = !pCursor->IsSelOvr(); + if( bRet ) + UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY); return bRet; } SwTextField * SwCursorShell::GetTextFieldAtPos( const SwPosition* pPos, - const bool bIncludeInputFieldAtStart ) + ::sw::GetTextAttrMode const eMode) { SwTextField* pTextField = nullptr; - SwTextNode * const pNode = pPos->nNode.GetNode().GetTextNode(); + SwTextNode * const pNode = pPos->GetNode().GetTextNode(); if ( pNode != nullptr ) { - pTextField = pNode->GetFieldTextAttrAt( pPos->nContent.GetIndex(), bIncludeInputFieldAtStart ); + pTextField = pNode->GetFieldTextAttrAt(pPos->GetContentIndex(), eMode); } return pTextField; @@ -874,22 +1051,21 @@ SwTextField * SwCursorShell::GetTextFieldAtPos( SwTextField* SwCursorShell::GetTextFieldAtCursor( const SwPaM* pCursor, - const bool bIncludeInputFieldAtStart ) + ::sw::GetTextAttrMode const eMode) { - SwTextField* pFieldAtCursor = nullptr; + SwTextField* pTextField = GetTextFieldAtPos(pCursor->Start(), eMode); + if ( !pTextField + || pCursor->Start()->GetNode() != pCursor->End()->GetNode() ) + return nullptr; - SwTextField* pTextField = GetTextFieldAtPos( pCursor->Start(), bIncludeInputFieldAtStart ); - if ( pTextField != nullptr - && pCursor->Start()->nNode == pCursor->End()->nNode ) + SwTextField* pFieldAtCursor = nullptr; + const sal_Int32 nTextFieldLength = + pTextField->End() != nullptr + ? *(pTextField->End()) - pTextField->GetStart() + : 1; + if ( ( pCursor->End()->GetContentIndex() - pCursor->Start()->GetContentIndex() ) <= nTextFieldLength ) { - const sal_Int32 nTextFieldLength = - pTextField->End() != nullptr - ? *(pTextField->End()) - pTextField->GetStart() - : 1; - if ( ( pCursor->End()->nContent.GetIndex() - pCursor->Start()->nContent.GetIndex() ) <= nTextFieldLength ) - { - pFieldAtCursor = pTextField; - } + pFieldAtCursor = pTextField; } return pFieldAtCursor; @@ -899,7 +1075,8 @@ SwField* SwCursorShell::GetFieldAtCursor( const SwPaM *const pCursor, const bool bIncludeInputFieldAtStart) { - SwTextField *const pField(GetTextFieldAtCursor(pCursor, bIncludeInputFieldAtStart)); + SwTextField *const pField(GetTextFieldAtCursor(pCursor, + bIncludeInputFieldAtStart ? ::sw::GetTextAttrMode::Default : ::sw::GetTextAttrMode::Expand)); return pField ? const_cast<SwField*>(pField->GetFormatField().GetField()) : nullptr; @@ -930,15 +1107,36 @@ bool SwCursorShell::CursorInsideInputField() const { for(SwPaM& rCursor : GetCursor()->GetRingContainer()) { - if (dynamic_cast<const SwTextInputField*>(GetTextFieldAtCursor(&rCursor, true))) + if (dynamic_cast<const SwTextInputField*>(GetTextFieldAtCursor(&rCursor, ::sw::GetTextAttrMode::Parent))) return true; } return false; } +SwTextContentControl* SwCursorShell::CursorInsideContentControl() const +{ + for (SwPaM& rCursor : GetCursor()->GetRingContainer()) + { + const SwPosition* pStart = rCursor.Start(); + SwTextNode* pTextNode = pStart->GetNode().GetTextNode(); + if (!pTextNode) + { + continue; + } + + sal_Int32 nIndex = pStart->GetContentIndex(); + if (SwTextAttr* pAttr = pTextNode->GetTextAttrAt(nIndex, RES_TXTATR_CONTENTCONTROL, ::sw::GetTextAttrMode::Parent)) + { + return static_txtattr_cast<SwTextContentControl*>(pAttr); + } + } + + return nullptr; +} + bool SwCursorShell::PosInsideInputField( const SwPosition& rPos ) { - return dynamic_cast<const SwTextInputField*>(GetTextFieldAtPos( &rPos, false )) != nullptr; + return dynamic_cast<const SwTextInputField*>(GetTextFieldAtPos(&rPos, ::sw::GetTextAttrMode::Parent)) != nullptr; } bool SwCursorShell::DocPtInsideInputField( const Point& rDocPt ) const @@ -954,7 +1152,7 @@ bool SwCursorShell::DocPtInsideInputField( const Point& rDocPt ) const sal_Int32 SwCursorShell::StartOfInputFieldAtPos( const SwPosition& rPos ) { - const SwTextInputField* pTextInputField = dynamic_cast<const SwTextInputField*>(GetTextFieldAtPos( &rPos, true )); + const SwTextInputField* pTextInputField = dynamic_cast<const SwTextInputField*>(GetTextFieldAtPos(&rPos, ::sw::GetTextAttrMode::Default)); assert(pTextInputField != nullptr && "<SwEditShell::StartOfInputFieldAtPos(..)> - no Input Field at given position"); return pTextInputField->GetStart(); @@ -962,7 +1160,7 @@ sal_Int32 SwCursorShell::StartOfInputFieldAtPos( const SwPosition& rPos ) sal_Int32 SwCursorShell::EndOfInputFieldAtPos( const SwPosition& rPos ) { - const SwTextInputField* pTextInputField = dynamic_cast<const SwTextInputField*>(GetTextFieldAtPos( &rPos, true )); + const SwTextInputField* pTextInputField = dynamic_cast<const SwTextInputField*>(GetTextFieldAtPos(&rPos, ::sw::GetTextAttrMode::Default)); assert(pTextInputField != nullptr && "<SwEditShell::EndOfInputFieldAtPos(..)> - no Input Field at given position"); return *(pTextInputField->End()); @@ -978,8 +1176,7 @@ void SwCursorShell::GotoOutline( SwOutlineNodes::size_type nIdx ) const SwNodes& rNds = GetDoc()->GetNodes(); SwTextNode* pTextNd = rNds.GetOutLineNds()[ nIdx ]->GetTextNode(); - pCursor->GetPoint()->nNode = *pTextNd; - pCursor->GetPoint()->nContent.Assign( pTextNd, 0 ); + pCursor->GetPoint()->Assign(*pTextNd); if( !pCursor->IsSelOvr() ) UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY); @@ -1015,7 +1212,7 @@ bool SwCursorShell::GotoNextOutline() } SwCursor* pCursor = getShellCursor( true ); - SwNode* pNd = &(pCursor->GetNode()); + SwNode* pNd = &(pCursor->GetPointNode()); SwOutlineNodes::size_type nPos; bool bUseFirst = !rNds.GetOutLineNds().Seek_Entry( pNd, &nPos ); SwOutlineNodes::size_type const nStartPos(nPos); @@ -1060,8 +1257,7 @@ bool SwCursorShell::GotoNextOutline() CurrShell aCurr( this ); SwCallLink aLk( *this ); // watch Cursor-Moves SwCursorSaveState aSaveState( *pCursor ); - pCursor->GetPoint()->nNode = *pNd; - pCursor->GetPoint()->nContent.Assign( pNd->GetTextNode(), 0 ); + pCursor->GetPoint()->Assign(*pNd); bool bRet = !pCursor->IsSelOvr(); if( bRet ) @@ -1081,9 +1277,8 @@ bool SwCursorShell::GotoPrevOutline() } SwCursor* pCursor = getShellCursor( true ); - SwNode* pNd = &(pCursor->GetNode()); + SwNode* pNd = &(pCursor->GetPointNode()); SwOutlineNodes::size_type nPos; - bool bRet = false; (void)rNds.GetOutLineNds().Seek_Entry(pNd, &nPos); SwOutlineNodes::size_type const nStartPos(nPos); @@ -1107,30 +1302,28 @@ bool SwCursorShell::GotoPrevOutline() } while (!sw::IsParaPropsNode(*GetLayout(), *pNd->GetTextNode())); - if (pNd) + if (!pNd) { - if (nStartPos < nPos) - { - SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::StartWrapped ); - } - else - { - SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty ); - } - CurrShell aCurr( this ); - SwCallLink aLk( *this ); // watch Cursor-Moves - SwCursorSaveState aSaveState( *pCursor ); - pCursor->GetPoint()->nNode = *pNd; - pCursor->GetPoint()->nContent.Assign( pNd->GetTextNode(), 0 ); + SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound ); + return false; + } - bRet = !pCursor->IsSelOvr(); - if( bRet ) - UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY); + if (nStartPos < nPos) + { + SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::StartWrapped ); } else { - SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound ); + SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty ); } + CurrShell aCurr( this ); + SwCallLink aLk( *this ); // watch Cursor-Moves + SwCursorSaveState aSaveState( *pCursor ); + pCursor->GetPoint()->Assign(*pNd); + + bool bRet = !pCursor->IsSelOvr(); + if( bRet ) + UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY); return bRet; } @@ -1140,7 +1333,7 @@ SwOutlineNodes::size_type SwCursorShell::GetOutlinePos(sal_uInt8 nLevel, SwPaM* SwPaM* pCursor = pPaM ? pPaM : getShellCursor(true); const SwNodes& rNds = GetDoc()->GetNodes(); - SwNode* pNd = &(pCursor->GetNode()); + SwNode* pNd = &(pCursor->GetPointNode()); SwOutlineNodes::size_type nPos; if( rNds.GetOutLineNds().Seek_Entry( pNd, &nPos )) nPos++; // is at correct position; take next for while @@ -1153,7 +1346,7 @@ SwOutlineNodes::size_type SwCursorShell::GetOutlinePos(sal_uInt8 nLevel, SwPaM* && pNd->GetTextNode()->GetAttrOutlineLevel()-1 <= nLevel) { if (pNd->GetIndex() < rNds.GetEndOfExtras().GetIndex() - && pCursor->GetNode().GetIndex() > rNds.GetEndOfExtras().GetIndex()) + && pCursor->GetPointNode().GetIndex() > rNds.GetEndOfExtras().GetIndex()) { // node found in extras but cursor position is not in extras return SwOutlineNodes::npos; @@ -1164,13 +1357,13 @@ SwOutlineNodes::size_type SwCursorShell::GetOutlinePos(sal_uInt8 nLevel, SwPaM* return SwOutlineNodes::npos; // no more left } -bool SwCursorShell::MakeOutlineSel(SwOutlineNodes::size_type nSttPos, SwOutlineNodes::size_type nEndPos, +void SwCursorShell::MakeOutlineSel(SwOutlineNodes::size_type nSttPos, SwOutlineNodes::size_type nEndPos, bool bWithChildren , bool bKillPams) { const SwNodes& rNds = GetDoc()->GetNodes(); const SwOutlineNodes& rOutlNds = rNds.GetOutLineNds(); if( rOutlNds.empty() ) - return false; + return; CurrShell aCurr( this ); SwCallLink aLk( *this ); // watch Cursor-Moves @@ -1208,42 +1401,44 @@ bool SwCursorShell::MakeOutlineSel(SwOutlineNodes::size_type nSttPos, SwOutlineN SwCursorSaveState aSaveState( *m_pCurrentCursor ); // set end to the end of the previous content node - m_pCurrentCursor->GetPoint()->nNode = *pSttNd; - m_pCurrentCursor->GetPoint()->nContent.Assign( pSttNd->GetContentNode(), 0 ); + m_pCurrentCursor->GetPoint()->Assign(*pSttNd); m_pCurrentCursor->SetMark(); - m_pCurrentCursor->GetPoint()->nNode = *pEndNd; + m_pCurrentCursor->GetPoint()->Assign(*pEndNd); m_pCurrentCursor->Move( fnMoveBackward, GoInNode ); // end of predecessor // and everything is already selected bool bRet = !m_pCurrentCursor->IsSelOvr(); if( bRet ) UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY); - return bRet; } /// jump to reference marker bool SwCursorShell::GotoRefMark( const OUString& rRefMark, sal_uInt16 nSubType, - sal_uInt16 nSeqNo ) + sal_uInt16 nSeqNo, sal_uInt16 nFlags ) { CurrShell aCurr( this ); SwCallLink aLk( *this ); // watch Cursor-Moves SwCursorSaveState aSaveState( *m_pCurrentCursor ); sal_Int32 nPos = -1; - SwTextNode* pTextNd = SwGetRefFieldType::FindAnchor( GetDoc(), rRefMark, - nSubType, nSeqNo, &nPos, nullptr, GetLayout()); - if( pTextNd && pTextNd->GetNodes().IsDocNodes() ) - { - m_pCurrentCursor->GetPoint()->nNode = *pTextNd; - m_pCurrentCursor->GetPoint()->nContent.Assign( pTextNd, nPos ); - if( !m_pCurrentCursor->IsSelOvr() ) - { - UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY); - return true; - } - } - return false; + SwPaM* pCursor = GetCursor(); + SwPosition* pPos = pCursor->GetPoint(); + SwTextNode* pRefTextNd = pPos->GetNode().GetTextNode(); + SwContentFrame* pRefFrame = GetCurrFrame(); + + SwTextNode* pTextNd = SwGetRefFieldType::FindAnchor(GetDoc(), rRefMark, + nSubType, nSeqNo, nFlags, &nPos, nullptr, GetLayout(), pRefTextNd, pRefFrame); + if( !pTextNd || !pTextNd->GetNodes().IsDocNodes() ) + return false; + + m_pCurrentCursor->GetPoint()->Assign(*pTextNd, nPos ); + + if( m_pCurrentCursor->IsSelOvr() ) + return false; + + UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY); + return true; } bool SwCursorShell::IsPageAtPos( const Point &rPt ) const @@ -1261,418 +1456,394 @@ bool SwCursorShell::GetContentAtPos( const Point& rPt, CurrShell aCurr( this ); bool bRet = false; - if( !IsTableMode() ) + if( IsTableMode() ) { - Point aPt( rPt ); - SwPosition aPos( *m_pCurrentCursor->GetPoint() ); + rContentAtPos.eContentAtPos = IsAttrAtPos::NONE; + rContentAtPos.aFnd.pField = nullptr; + return false; + } - SwTextNode* pTextNd; - SwCursorMoveState aTmpState; - aTmpState.m_bFieldInfo = true; - aTmpState.m_bExactOnly = !( IsAttrAtPos::Outline & rContentAtPos.eContentAtPos ); - aTmpState.m_bContentCheck = bool(IsAttrAtPos::ContentCheck & rContentAtPos.eContentAtPos); - aTmpState.m_bSetInReadOnly = IsReadOnlyAvailable(); + Point aPt( rPt ); + SwPosition aPos( *m_pCurrentCursor->GetPoint() ); - SwSpecialPos aSpecialPos; - aTmpState.m_pSpecialPos = ( IsAttrAtPos::SmartTag & rContentAtPos.eContentAtPos ) ? - &aSpecialPos : nullptr; + SwTextNode* pTextNd; + SwCursorMoveState aTmpState; + aTmpState.m_bFieldInfo = true; + aTmpState.m_bExactOnly = !( IsAttrAtPos::Outline & rContentAtPos.eContentAtPos ); + aTmpState.m_bContentCheck = bool(IsAttrAtPos::ContentCheck & rContentAtPos.eContentAtPos); + aTmpState.m_bSetInReadOnly = IsReadOnlyAvailable(); + aTmpState.m_bPosMatchesBounds = true; // treat last half of character same as first half - const bool bCursorFoundExact = GetLayout()->GetModelPositionForViewPoint( &aPos, aPt, &aTmpState ); - pTextNd = aPos.nNode.GetNode().GetTextNode(); + SwSpecialPos aSpecialPos; + aTmpState.m_pSpecialPos = ( IsAttrAtPos::SmartTag & rContentAtPos.eContentAtPos ) ? + &aSpecialPos : nullptr; - const SwNodes& rNds = GetDoc()->GetNodes(); - if( pTextNd - && IsAttrAtPos::Outline & rContentAtPos.eContentAtPos - && !rNds.GetOutLineNds().empty() ) + const bool bCursorFoundExact = GetLayout()->GetModelPositionForViewPoint( &aPos, aPt, &aTmpState ); + pTextNd = aPos.GetNode().GetTextNode(); + + const SwNodes& rNds = GetDoc()->GetNodes(); + if( pTextNd + && IsAttrAtPos::Outline & rContentAtPos.eContentAtPos + && !rNds.GetOutLineNds().empty() ) + { + // only for nodes in outline nodes + SwOutlineNodes::size_type nPos = 0; + bool bFoundOutline = rNds.GetOutLineNds().Seek_Entry(pTextNd, &nPos); + if (!bFoundOutline && nPos && (IsAttrAtPos::AllowContaining & rContentAtPos.eContentAtPos)) { - // only for nodes in outline nodes - SwOutlineNodes::size_type nPos; - if(rNds.GetOutLineNds().Seek_Entry(pTextNd, &nPos)) - { - rContentAtPos.eContentAtPos = IsAttrAtPos::Outline; - rContentAtPos.sStr = sw::GetExpandTextMerged(GetLayout(), *pTextNd, true, false, ExpandMode::ExpandFootnote); - rContentAtPos.aFnd.pNode = pTextNd; - bRet = true; - } + // nPos points to the first found outline node not before pTextNd, or to end(); + // when bFoundOutline is false, and nPos is not 0, it means that there were + // outline nodes before pTextNd, and nPos-1 points to the last of those. + pTextNd = rNds.GetOutLineNds()[nPos - 1]->GetTextNode(); + bFoundOutline = true; } - else if ( IsAttrAtPos::ContentCheck & rContentAtPos.eContentAtPos - && bCursorFoundExact ) + if (bFoundOutline) { + rContentAtPos.eContentAtPos = IsAttrAtPos::Outline; + rContentAtPos.sStr = sw::GetExpandTextMerged(GetLayout(), *pTextNd, true, false, ExpandMode::ExpandFootnote); + rContentAtPos.aFnd.pNode = pTextNd; bRet = true; } - else if( pTextNd - && IsAttrAtPos::NumLabel & rContentAtPos.eContentAtPos) - { - bRet = aTmpState.m_bInNumPortion; - rContentAtPos.aFnd.pNode = sw::GetParaPropsNode(*GetLayout(), aPos.nNode); + } + else if ( IsAttrAtPos::ContentCheck & rContentAtPos.eContentAtPos + && bCursorFoundExact ) + { + bRet = true; + } + else if( pTextNd + && IsAttrAtPos::NumLabel & rContentAtPos.eContentAtPos) + { + bRet = aTmpState.m_bInNumPortion; + rContentAtPos.aFnd.pNode = sw::GetParaPropsNode(*GetLayout(), aPos.GetNode()); - Size aSizeLogic(aTmpState.m_nInNumPortionOffset, 0); - Size aSizePixel = GetWin()->LogicToPixel(aSizeLogic); - rContentAtPos.nDist = aSizePixel.Width(); - } - else if( bCursorFoundExact && pTextNd ) + Size aSizeLogic(aTmpState.m_nInNumPortionOffset, 0); + Size aSizePixel = GetWin()->LogicToPixel(aSizeLogic); + rContentAtPos.nDist = aSizePixel.Width(); + } + else if( bCursorFoundExact && pTextNd ) + { + SwContentFrame *pFrame(nullptr); + if( !aTmpState.m_bPosCorr ) { - SwContentFrame *pFrame(nullptr); - if( !aTmpState.m_bPosCorr ) + SwTextAttr* pTextAttr; + if ( IsAttrAtPos::SmartTag & rContentAtPos.eContentAtPos + && !aTmpState.m_bFootnoteNoInfo ) { - SwTextAttr* pTextAttr; - if ( IsAttrAtPos::SmartTag & rContentAtPos.eContentAtPos - && !aTmpState.m_bFootnoteNoInfo ) - { - const SwWrongList* pSmartTagList = pTextNd->GetSmartTags(); - sal_Int32 nCurrent = aPos.nContent.GetIndex(); - const sal_Int32 nBegin = nCurrent; - sal_Int32 nLen = 1; + const SwWrongList* pSmartTagList = pTextNd->GetSmartTags(); + sal_Int32 nCurrent = aPos.GetContentIndex(); + const sal_Int32 nBegin = nCurrent; + sal_Int32 nLen = 1; - if (pSmartTagList && pSmartTagList->InWrongWord(nCurrent, nLen) && !pTextNd->IsSymbolAt(nBegin)) + if (pSmartTagList && pSmartTagList->InWrongWord(nCurrent, nLen) && !pTextNd->IsSymbolAt(nBegin)) + { + const sal_uInt16 nIndex = pSmartTagList->GetWrongPos( nBegin ); + const SwWrongList* pSubList = pSmartTagList->SubList( nIndex ); + if ( pSubList ) { - const sal_uInt16 nIndex = pSmartTagList->GetWrongPos( nBegin ); - const SwWrongList* pSubList = pSmartTagList->SubList( nIndex ); - if ( pSubList ) - { - nCurrent = aTmpState.m_pSpecialPos->nCharOfst; + nCurrent = aTmpState.m_pSpecialPos->nCharOfst; - if ( pSubList->InWrongWord( nCurrent, nLen ) ) - bRet = true; - } - else + if ( pSubList->InWrongWord( nCurrent, nLen ) ) bRet = true; - - if( bRet && bSetCursor ) - { - SwCursorSaveState aSaveState( *m_pCurrentCursor ); - SwCallLink aLk( *this ); // watch Cursor-Moves - m_pCurrentCursor->DeleteMark(); - *m_pCurrentCursor->GetPoint() = aPos; - if( m_pCurrentCursor->IsSelOvr( SwCursorSelOverFlags::CheckNodeSection | SwCursorSelOverFlags::Toggle) ) - bRet = false; - else - UpdateCursor(); - } - if( bRet ) - { - rContentAtPos.eContentAtPos = IsAttrAtPos::SmartTag; - - std::pair<Point, bool> tmp(aPt, true); - if (pFieldRect) - { - pFrame = pTextNd->getLayoutFrame(GetLayout(), nullptr, &tmp); - if (pFrame) - pFrame->GetCharRect( *pFieldRect, aPos, &aTmpState ); - } - } } - } + else + bRet = true; - if ( !bRet - && ( IsAttrAtPos::Field | IsAttrAtPos::ClickField ) & rContentAtPos.eContentAtPos - && !aTmpState.m_bFootnoteNoInfo ) - { - pTextAttr = pTextNd->GetFieldTextAttrAt( aPos.nContent.GetIndex() ); - const SwField* pField = pTextAttr != nullptr - ? pTextAttr->GetFormatField().GetField() - : nullptr; - if ( IsAttrAtPos::ClickField & rContentAtPos.eContentAtPos - && pField && !pField->HasClickHdl() ) + if( bRet && bSetCursor ) { - pField = nullptr; + SwCursorSaveState aSaveState( *m_pCurrentCursor ); + SwCallLink aLk( *this ); // watch Cursor-Moves + m_pCurrentCursor->DeleteMark(); + *m_pCurrentCursor->GetPoint() = aPos; + if( m_pCurrentCursor->IsSelOvr( SwCursorSelOverFlags::CheckNodeSection | SwCursorSelOverFlags::Toggle) ) + bRet = false; + else + UpdateCursor(); } - - if ( pField ) + if( bRet ) { + rContentAtPos.eContentAtPos = IsAttrAtPos::SmartTag; + + std::pair<Point, bool> tmp(aPt, true); if (pFieldRect) { - std::pair<Point, bool> tmp(aPt, true); pFrame = pTextNd->getLayoutFrame(GetLayout(), nullptr, &tmp); if (pFrame) - { - //tdf#116397 now that we looking for the bounds of the field drop the SmartTag - //index within field setting so we don't the bounds of the char within the field - SwSpecialPos* pSpecialPos = aTmpState.m_pSpecialPos; - aTmpState.m_pSpecialPos = nullptr; pFrame->GetCharRect( *pFieldRect, aPos, &aTmpState ); - aTmpState.m_pSpecialPos = pSpecialPos; - } } - - if( bSetCursor ) - { - SwCallLink aLk( *this ); // watch Cursor-Moves - SwCursorSaveState aSaveState( *m_pCurrentCursor ); - m_pCurrentCursor->DeleteMark(); - *m_pCurrentCursor->GetPoint() = aPos; - if( m_pCurrentCursor->IsSelOvr() ) - { - // allow click fields in protected sections - // only placeholder is not possible - if( IsAttrAtPos::Field & rContentAtPos.eContentAtPos - || SwFieldIds::JumpEdit == pField->Which() ) - pField = nullptr; - } - else - UpdateCursor(); - } - else if( SwFieldIds::Table == pField->Which() && - static_cast<const SwTableField*>(pField)->IsIntrnlName() ) - { - // create from internal (for CORE) the external - // (for UI) formula - const SwTableNode* pTableNd = pTextNd->FindTableNode(); - if( pTableNd ) // is in a table - const_cast<SwTableField*>(static_cast<const SwTableField*>(pField))->PtrToBoxNm( &pTableNd->GetTable() ); - } - } - - if( pField ) - { - rContentAtPos.aFnd.pField = pField; - rContentAtPos.pFndTextAttr = pTextAttr; - rContentAtPos.eContentAtPos = IsAttrAtPos::Field; - bRet = true; } } + } - if( !bRet && IsAttrAtPos::FormControl & rContentAtPos.eContentAtPos ) + if ( !bRet + && ( IsAttrAtPos::Field | IsAttrAtPos::ClickField ) & rContentAtPos.eContentAtPos + && !aTmpState.m_bFootnoteNoInfo ) + { + pTextAttr = pTextNd->GetFieldTextAttrAt( aPos.GetContentIndex() ); + const SwField* pField = pTextAttr != nullptr + ? pTextAttr->GetFormatField().GetField() + : nullptr; + if ( IsAttrAtPos::ClickField & rContentAtPos.eContentAtPos + && pField && !pField->HasClickHdl() ) { - IDocumentMarkAccess* pMarksAccess = GetDoc()->getIDocumentMarkAccess( ); - sw::mark::IFieldmark* pFieldBookmark = pMarksAccess->getFieldmarkFor( aPos ); - if (bCursorFoundExact && pFieldBookmark) - { - rContentAtPos.eContentAtPos = IsAttrAtPos::FormControl; - rContentAtPos.aFnd.pFieldmark = pFieldBookmark; - bRet=true; - } + pField = nullptr; } - if( !bRet && IsAttrAtPos::Ftn & rContentAtPos.eContentAtPos ) + if ( pField ) { - if( aTmpState.m_bFootnoteNoInfo ) + if (pFieldRect) { - // over the footnote's char - bRet = true; - if( bSetCursor ) + std::pair<Point, bool> tmp(aPt, true); + pFrame = pTextNd->getLayoutFrame(GetLayout(), nullptr, &tmp); + if (pFrame) { - *m_pCurrentCursor->GetPoint() = aPos; - if( !GotoFootnoteAnchor() ) - bRet = false; + //tdf#116397 now that we looking for the bounds of the field drop the SmartTag + //index within field setting so we don't the bounds of the char within the field + SwSpecialPos* pSpecialPos = aTmpState.m_pSpecialPos; + aTmpState.m_pSpecialPos = nullptr; + pFrame->GetCharRect( *pFieldRect, aPos, &aTmpState ); + aTmpState.m_pSpecialPos = pSpecialPos; } - if( bRet ) - rContentAtPos.eContentAtPos = IsAttrAtPos::Ftn; } - else if ( nullptr != ( pTextAttr = pTextNd->GetTextAttrForCharAt( - aPos.nContent.GetIndex(), RES_TXTATR_FTN )) ) + + if( bSetCursor ) { - bRet = true; - if( bSetCursor ) + SwCallLink aLk( *this ); // watch Cursor-Moves + SwCursorSaveState aSaveState( *m_pCurrentCursor ); + m_pCurrentCursor->DeleteMark(); + *m_pCurrentCursor->GetPoint() = aPos; + if( m_pCurrentCursor->IsSelOvr() ) { - SwCallLink aLk( *this ); // watch Cursor-Moves - SwCursorSaveState aSaveState( *m_pCurrentCursor ); - m_pCurrentCursor->GetPoint()->nNode = *static_cast<SwTextFootnote*>(pTextAttr)->GetStartNode(); - SwContentNode* pCNd = GetDoc()->GetNodes().GoNextSection( - &m_pCurrentCursor->GetPoint()->nNode, - true, !IsReadOnlyAvailable() ); - - if( pCNd ) - { - m_pCurrentCursor->GetPoint()->nContent.Assign( pCNd, 0 ); - if( m_pCurrentCursor->IsSelOvr( SwCursorSelOverFlags::CheckNodeSection | - SwCursorSelOverFlags::Toggle )) - bRet = false; - else - UpdateCursor(); - } - else - bRet = false; + // allow click fields in protected sections + // only placeholder is not possible + if( IsAttrAtPos::Field & rContentAtPos.eContentAtPos + || SwFieldIds::JumpEdit == pField->Which() ) + pField = nullptr; } + else + UpdateCursor(); + } + else if( SwFieldIds::Table == pField->Which() && + static_cast<const SwTableField*>(pField)->IsIntrnlName() ) + { + // create from internal (for CORE) the external + // (for UI) formula + const SwTableNode* pTableNd = pTextNd->FindTableNode(); + if( pTableNd ) // is in a table + const_cast<SwTableField*>(static_cast<const SwTableField*>(pField))->PtrToBoxNm( &pTableNd->GetTable() ); + } + } - if( bRet ) - { - rContentAtPos.eContentAtPos = IsAttrAtPos::Ftn; - rContentAtPos.pFndTextAttr = pTextAttr; - rContentAtPos.aFnd.pAttr = &pTextAttr->GetAttr(); + if( pField ) + { + rContentAtPos.aFnd.pField = pField; + rContentAtPos.pFndTextAttr = pTextAttr; + rContentAtPos.eContentAtPos = IsAttrAtPos::Field; + bRet = true; + } + } - if (pFieldRect) - { - std::pair<Point, bool> tmp(aPt, true); - pFrame = pTextNd->getLayoutFrame(GetLayout(), nullptr, &tmp); - if (pFrame) - pFrame->GetCharRect( *pFieldRect, aPos, &aTmpState ); - } - } - } + if( !bRet && IsAttrAtPos::FormControl & rContentAtPos.eContentAtPos ) + { + IDocumentMarkAccess* pMarksAccess = GetDoc()->getIDocumentMarkAccess( ); + sw::mark::IFieldmark* pFieldBookmark = pMarksAccess->getInnerFieldmarkFor(aPos); + if (bCursorFoundExact && pFieldBookmark) + { + rContentAtPos.eContentAtPos = IsAttrAtPos::FormControl; + rContentAtPos.aFnd.pFieldmark = pFieldBookmark; + bRet=true; } + } - if( !bRet - && ( IsAttrAtPos::ToxMark | IsAttrAtPos::RefMark ) & rContentAtPos.eContentAtPos - && !aTmpState.m_bFootnoteNoInfo ) + if (!bRet && rContentAtPos.eContentAtPos & IsAttrAtPos::ContentControl) + { + SwTextAttr* pAttr = pTextNd->GetTextAttrAt( + aPos.GetContentIndex(), RES_TXTATR_CONTENTCONTROL, ::sw::GetTextAttrMode::Parent); + if (pAttr) { - pTextAttr = nullptr; - if( IsAttrAtPos::ToxMark & rContentAtPos.eContentAtPos ) - { - std::vector<SwTextAttr *> const marks( - pTextNd->GetTextAttrsAt( - aPos.nContent.GetIndex(), RES_TXTATR_TOXMARK)); - if (!marks.empty()) - { // hmm... can only return 1 here - pTextAttr = *marks.begin(); - } - } + rContentAtPos.eContentAtPos = IsAttrAtPos::ContentControl; + rContentAtPos.pFndTextAttr = pAttr; + bRet = true; + } + } - if( !pTextAttr && - IsAttrAtPos::RefMark & rContentAtPos.eContentAtPos ) + if( !bRet && IsAttrAtPos::Ftn & rContentAtPos.eContentAtPos ) + { + if( aTmpState.m_bFootnoteNoInfo ) + { + // over the footnote's char + bRet = true; + if( bSetCursor ) { - std::vector<SwTextAttr *> const marks( - pTextNd->GetTextAttrsAt( - aPos.nContent.GetIndex(), RES_TXTATR_REFMARK)); - if (!marks.empty()) - { // hmm... can only return 1 here - pTextAttr = *marks.begin(); - } + *m_pCurrentCursor->GetPoint() = aPos; + if( !GotoFootnoteAnchor() ) + bRet = false; } - - if( pTextAttr ) + if( bRet ) + rContentAtPos.eContentAtPos = IsAttrAtPos::Ftn; + } + else if ( nullptr != ( pTextAttr = pTextNd->GetTextAttrForCharAt( + aPos.GetContentIndex(), RES_TXTATR_FTN )) ) + { + bRet = true; + if( bSetCursor ) { - bRet = true; - if( bSetCursor ) + if (SwWrtShell* pWrtSh = dynamic_cast<SwWrtShell*>(this)) + pWrtSh->addCurrentPosition(); + + SwCallLink aLk( *this ); // watch Cursor-Moves + SwCursorSaveState aSaveState( *m_pCurrentCursor ); + m_pCurrentCursor->GetPoint()->Assign( *static_cast<SwTextFootnote*>(pTextAttr)->GetStartNode() ); + SwContentNode* pCNd = SwNodes::GoNextSection( + m_pCurrentCursor->GetPoint(), + true, !IsReadOnlyAvailable() ); + + if( pCNd ) { - SwCallLink aLk( *this ); // watch Cursor-Moves - SwCursorSaveState aSaveState( *m_pCurrentCursor ); - m_pCurrentCursor->DeleteMark(); - *m_pCurrentCursor->GetPoint() = aPos; - if( m_pCurrentCursor->IsSelOvr( SwCursorSelOverFlags::CheckNodeSection | SwCursorSelOverFlags::Toggle ) ) + if( m_pCurrentCursor->IsSelOvr( SwCursorSelOverFlags::CheckNodeSection | + SwCursorSelOverFlags::Toggle )) bRet = false; else UpdateCursor(); } + else + bRet = false; + } - if( bRet ) - { - const sal_Int32* pEnd = pTextAttr->GetEnd(); - if( pEnd ) - rContentAtPos.sStr = - pTextNd->GetExpandText(GetLayout(), pTextAttr->GetStart(), *pEnd - pTextAttr->GetStart()); - else if( RES_TXTATR_TOXMARK == pTextAttr->Which()) - rContentAtPos.sStr = - pTextAttr->GetTOXMark().GetAlternativeText(); - - rContentAtPos.eContentAtPos = - RES_TXTATR_TOXMARK == pTextAttr->Which() - ? IsAttrAtPos::ToxMark - : IsAttrAtPos::RefMark; - rContentAtPos.pFndTextAttr = pTextAttr; - rContentAtPos.aFnd.pAttr = &pTextAttr->GetAttr(); + if( bRet ) + { + rContentAtPos.eContentAtPos = IsAttrAtPos::Ftn; + rContentAtPos.pFndTextAttr = pTextAttr; + rContentAtPos.aFnd.pAttr = &pTextAttr->GetAttr(); + if (pFieldRect) + { std::pair<Point, bool> tmp(aPt, true); - if (pFieldRect) - { - pFrame = pTextNd->getLayoutFrame(GetLayout(), nullptr, &tmp); - if (pFrame) - pFrame->GetCharRect( *pFieldRect, aPos, &aTmpState ); - } + pFrame = pTextNd->getLayoutFrame(GetLayout(), nullptr, &tmp); + if (pFrame) + pFrame->GetCharRect( *pFieldRect, aPos, &aTmpState ); } } } + } - if ( !bRet - && IsAttrAtPos::InetAttr & rContentAtPos.eContentAtPos - && !aTmpState.m_bFootnoteNoInfo ) + if( !bRet + && ( IsAttrAtPos::ToxMark | IsAttrAtPos::RefMark ) & rContentAtPos.eContentAtPos + && !aTmpState.m_bFootnoteNoInfo ) + { + pTextAttr = nullptr; + if( IsAttrAtPos::ToxMark & rContentAtPos.eContentAtPos ) { - sal_Int32 index = aPos.nContent.GetIndex(); - pTextAttr = pTextNd->GetTextAttrAt(index, RES_TXTATR_INETFMT); + std::vector<SwTextAttr *> const marks( + pTextNd->GetTextAttrsAt( + aPos.GetContentIndex(), RES_TXTATR_TOXMARK)); + if (!marks.empty()) + { // hmm... can only return 1 here + pTextAttr = *marks.begin(); + } + } - if(!pTextAttr && index > 0) - pTextAttr = pTextNd->GetTextAttrAt(index - 1, RES_TXTATR_INETFMT); - // "detect" only INetAttrs with URLs - if( pTextAttr && !pTextAttr->GetINetFormat().GetValue().isEmpty() ) - { - bRet = true; - if( bSetCursor ) - { - SwCursorSaveState aSaveState( *m_pCurrentCursor ); - SwCallLink aLk( *this ); // watch Cursor-Moves - m_pCurrentCursor->DeleteMark(); - *m_pCurrentCursor->GetPoint() = aPos; - if( m_pCurrentCursor->IsSelOvr( SwCursorSelOverFlags::CheckNodeSection | - SwCursorSelOverFlags::Toggle) ) - bRet = false; - else - UpdateCursor(); - } - if( bRet ) - { - const sal_Int32 nSt = pTextAttr->GetStart(); - const sal_Int32 nEnd = *pTextAttr->End(); + if( !pTextAttr && + IsAttrAtPos::RefMark & rContentAtPos.eContentAtPos ) + { + std::vector<SwTextAttr *> const marks( + pTextNd->GetTextAttrsAt( + aPos.GetContentIndex(), RES_TXTATR_REFMARK)); + if (!marks.empty()) + { // hmm... can only return 1 here + pTextAttr = *marks.begin(); + } + } - rContentAtPos.sStr = pTextNd->GetExpandText(GetLayout(), nSt, nEnd-nSt); + if( pTextAttr ) + { + bRet = true; + if( bSetCursor ) + { + SwCallLink aLk( *this ); // watch Cursor-Moves + SwCursorSaveState aSaveState( *m_pCurrentCursor ); + m_pCurrentCursor->DeleteMark(); + *m_pCurrentCursor->GetPoint() = aPos; + if( m_pCurrentCursor->IsSelOvr( SwCursorSelOverFlags::CheckNodeSection | SwCursorSelOverFlags::Toggle ) ) + bRet = false; + else + UpdateCursor(); + } - rContentAtPos.aFnd.pAttr = &pTextAttr->GetAttr(); - rContentAtPos.eContentAtPos = IsAttrAtPos::InetAttr; - rContentAtPos.pFndTextAttr = pTextAttr; + if( bRet ) + { + const sal_Int32* pEnd = pTextAttr->GetEnd(); + if( pEnd ) + rContentAtPos.sStr = + pTextNd->GetExpandText(GetLayout(), pTextAttr->GetStart(), *pEnd - pTextAttr->GetStart()); + else if( RES_TXTATR_TOXMARK == pTextAttr->Which()) + rContentAtPos.sStr = + pTextAttr->GetTOXMark().GetAlternativeText(); + + rContentAtPos.eContentAtPos = + RES_TXTATR_TOXMARK == pTextAttr->Which() + ? IsAttrAtPos::ToxMark + : IsAttrAtPos::RefMark; + rContentAtPos.pFndTextAttr = pTextAttr; + rContentAtPos.aFnd.pAttr = &pTextAttr->GetAttr(); - if (pFieldRect) - { - std::pair<Point, bool> tmp(aPt, true); - pFrame = pTextNd->getLayoutFrame(GetLayout(), nullptr, &tmp); - if (pFrame) - { - //get bounding box of range - SwRect aStart; - SwPosition aStartPos(*pTextNd, nSt); - pFrame->GetCharRect(aStart, aStartPos, &aTmpState); - SwRect aEnd; - SwPosition aEndPos(*pTextNd, nEnd); - pFrame->GetCharRect(aEnd, aEndPos, &aTmpState); - if (aStart.Top() != aEnd.Top() || aStart.Bottom() != aEnd.Bottom()) - { - aStart.Left(pFrame->getFrameArea().Left()); - aEnd.Right(pFrame->getFrameArea().Right()); - } - *pFieldRect = aStart.Union(aEnd); - } - } + std::pair<Point, bool> tmp(aPt, true); + if (pFieldRect) + { + pFrame = pTextNd->getLayoutFrame(GetLayout(), nullptr, &tmp); + if (pFrame) + pFrame->GetCharRect( *pFieldRect, aPos, &aTmpState ); } } } + } - if( !bRet && IsAttrAtPos::Redline & rContentAtPos.eContentAtPos ) - { - const SwRangeRedline* pRedl = GetDoc()->getIDocumentRedlineAccess().GetRedline(aPos, nullptr); + if ( !bRet + && IsAttrAtPos::InetAttr & rContentAtPos.eContentAtPos + && !aTmpState.m_bFootnoteNoInfo ) + { + sal_Int32 index = aPos.GetContentIndex(); + pTextAttr = pTextNd->GetTextAttrAt(index, RES_TXTATR_INETFMT); - if( pRedl ) + // "detect" only INetAttrs with URLs + if( pTextAttr && !pTextAttr->GetINetFormat().GetValue().isEmpty() ) + { + bRet = true; + if( bSetCursor ) { - rContentAtPos.aFnd.pRedl = pRedl; - rContentAtPos.eContentAtPos = IsAttrAtPos::Redline; - rContentAtPos.pFndTextAttr = nullptr; - bRet = true; + SwCursorSaveState aSaveState( *m_pCurrentCursor ); + SwCallLink aLk( *this ); // watch Cursor-Moves + m_pCurrentCursor->DeleteMark(); + *m_pCurrentCursor->GetPoint() = aPos; + if( m_pCurrentCursor->IsSelOvr( SwCursorSelOverFlags::CheckNodeSection | + SwCursorSelOverFlags::Toggle) ) + bRet = false; + else + UpdateCursor(); + } + if( bRet ) + { + const sal_Int32 nSt = pTextAttr->GetStart(); + const sal_Int32 nEnd = *pTextAttr->End(); + + rContentAtPos.sStr = pTextNd->GetExpandText(GetLayout(), nSt, nEnd-nSt); + + rContentAtPos.aFnd.pAttr = &pTextAttr->GetAttr(); + rContentAtPos.eContentAtPos = IsAttrAtPos::InetAttr; + rContentAtPos.pFndTextAttr = pTextAttr; if (pFieldRect) { std::pair<Point, bool> tmp(aPt, true); pFrame = pTextNd->getLayoutFrame(GetLayout(), nullptr, &tmp); - if( pFrame ) + if (pFrame) { - // not sure if this should be limited to one - // paragraph, or mark the entire redline; let's - // leave it limited to one for now... - sal_Int32 nStart; - sal_Int32 nEnd; - pRedl->CalcStartEnd(pTextNd->GetIndex(), nStart, nEnd); - if (nStart == COMPLETE_STRING) - { - // consistency: found pRedl, so there must be - // something in pTextNd - assert(nEnd != COMPLETE_STRING); - nStart = 0; - } - if (nEnd == COMPLETE_STRING) - { - nEnd = pTextNd->Len(); - } //get bounding box of range SwRect aStart; - pFrame->GetCharRect(aStart, SwPosition(*pTextNd, nStart), &aTmpState); + SwPosition aStartPos(*pTextNd, nSt); + pFrame->GetCharRect(aStart, aStartPos, &aTmpState); SwRect aEnd; - pFrame->GetCharRect(aEnd, SwPosition(*pTextNd, nEnd), &aTmpState); + SwPosition aEndPos(*pTextNd, nEnd); + pFrame->GetCharRect(aEnd, aEndPos, &aTmpState); if (aStart.Top() != aEnd.Top() || aStart.Bottom() != aEnd.Bottom()) { aStart.Left(pFrame->getFrameArea().Left()); @@ -1685,169 +1856,260 @@ bool SwCursorShell::GetContentAtPos( const Point& rPt, } } - if( !bRet - && ( IsAttrAtPos::TableBoxFml & rContentAtPos.eContentAtPos -#ifdef DBG_UTIL - || IsAttrAtPos::TableBoxValue & rContentAtPos.eContentAtPos -#endif - ) ) + if( !bRet && IsAttrAtPos::Redline & rContentAtPos.eContentAtPos ) { - const SwTableNode* pTableNd; - const SwTableBox* pBox; - const SwStartNode* pSttNd = pTextNd->FindTableBoxStartNode(); - const SfxPoolItem* pItem; - if( pSttNd && nullptr != ( pTableNd = pTextNd->FindTableNode()) && - nullptr != ( pBox = pTableNd->GetTable().GetTableBox( - pSttNd->GetIndex() )) && -#ifdef DBG_UTIL - ( SfxItemState::SET == pBox->GetFrameFormat()->GetItemState( - RES_BOXATR_FORMULA, false, &pItem ) || - SfxItemState::SET == pBox->GetFrameFormat()->GetItemState( - RES_BOXATR_VALUE, false, &pItem )) -#else - SfxItemState::SET == pBox->GetFrameFormat()->GetItemState( - RES_BOXATR_FORMULA, false, &pItem ) -#endif - ) + const SwRangeRedline* pRedl = GetDoc()->getIDocumentRedlineAccess().GetRedline(aPos, nullptr); + + if( pRedl ) { - std::pair<Point, bool> tmp(aPt, true); - SwFrame* pF = pTextNd->getLayoutFrame(GetLayout(), nullptr, &tmp); - if( pF ) + rContentAtPos.aFnd.pRedl = pRedl; + rContentAtPos.eContentAtPos = IsAttrAtPos::Redline; + rContentAtPos.pFndTextAttr = nullptr; + bRet = true; + + if (pFieldRect) { - // then the CellFrame - pFrame = static_cast<SwContentFrame*>(pF); - while( pF && !pF->IsCellFrame() ) - pF = pF->GetUpper(); + std::pair<Point, bool> tmp(aPt, true); + pFrame = pTextNd->getLayoutFrame(GetLayout(), nullptr, &tmp); + if( pFrame ) + { + // not sure if this should be limited to one + // paragraph, or mark the entire redline; let's + // leave it limited to one for now... + sal_Int32 nStart; + sal_Int32 nEnd; + pRedl->CalcStartEnd(pTextNd->GetIndex(), nStart, nEnd); + if (nStart == COMPLETE_STRING) + { + // consistency: found pRedl, so there must be + // something in pTextNd + assert(nEnd != COMPLETE_STRING); + nStart = 0; + } + if (nEnd == COMPLETE_STRING) + { + nEnd = pTextNd->Len(); + } + //get bounding box of range + SwRect aStart; + pFrame->GetCharRect(aStart, SwPosition(*pTextNd, nStart), &aTmpState); + SwRect aEnd; + pFrame->GetCharRect(aEnd, SwPosition(*pTextNd, nEnd), &aTmpState); + if (aStart.Top() != aEnd.Top() || aStart.Bottom() != aEnd.Bottom()) + { + aStart.Left(pFrame->getFrameArea().Left()); + aEnd.Right(pFrame->getFrameArea().Right()); + } + *pFieldRect = aStart.Union(aEnd); + } } + } + } + } - if( aTmpState.m_bPosCorr ) + if( !bRet && ( ( IsAttrAtPos::TableRedline & rContentAtPos.eContentAtPos ) || + ( IsAttrAtPos::TableColRedline & rContentAtPos.eContentAtPos ) ) ) + { + const SwTableNode* pTableNd; + const SwTableBox* pBox; + const SwTableLine* pTableLine; + const SwStartNode* pSttNd = pTextNd->FindTableBoxStartNode(); + if( pSttNd && nullptr != ( pTableNd = pTextNd->FindTableNode()) && + nullptr != ( pBox = pTableNd->GetTable().GetTableBox( + pSttNd->GetIndex() )) && + nullptr != ( pTableLine = pBox->GetUpper() ) && + ( RedlineType::None != pBox->GetRedlineType() || + RedlineType::None != pTableLine->GetRedlineType() ) ) + { + const SwRedlineTable& aRedlineTable = GetDoc()->getIDocumentRedlineAccess().GetRedlineTable(); + if ( RedlineType::None != pTableLine->GetRedlineType() ) + { + SwRedlineTable::size_type nPos = 0; + nPos = pTableLine->UpdateTextChangesOnly(nPos); + if ( nPos != SwRedlineTable::npos ) { - if( pF && !pF->getFrameArea().IsInside( aPt )) - pF = nullptr; + rContentAtPos.aFnd.pRedl = aRedlineTable[nPos]; + rContentAtPos.eContentAtPos = IsAttrAtPos::TableRedline; + bRet = true; } - else if( !pF ) - pF = pFrame; - - if( pF ) // only then it is valid + } + else + { + SwRedlineTable::size_type n = 0; + SwNodeIndex aIdx( *pSttNd, 1 ); + const SwPosition aBoxStart(aIdx); + const SwRangeRedline* pFnd = aRedlineTable.FindAtPosition( aBoxStart, n, /*next=*/true ); + if( pFnd && RedlineType::Delete == pFnd->GetType() ) { - // create from internal (for CORE) the external - // (for UI) formula - rContentAtPos.eContentAtPos = IsAttrAtPos::TableBoxFml; + rContentAtPos.aFnd.pRedl = aRedlineTable[n]; + rContentAtPos.eContentAtPos = IsAttrAtPos::TableColRedline; + bRet = true; + } + } + } + } + + if( !bRet + && ( IsAttrAtPos::TableBoxFml & rContentAtPos.eContentAtPos #ifdef DBG_UTIL - if( RES_BOXATR_VALUE == pItem->Which() ) - rContentAtPos.eContentAtPos = IsAttrAtPos::TableBoxValue; - else + || IsAttrAtPos::TableBoxValue & rContentAtPos.eContentAtPos +#endif + ) ) + { + const SwTableNode* pTableNd; + const SwTableBox* pBox; + const SwStartNode* pSttNd = pTextNd->FindTableBoxStartNode(); + const SwTableBoxFormula* pItem; +#ifdef DBG_UTIL + const SwTableBoxValue* pItem2 = nullptr; +#endif + if( pSttNd && nullptr != ( pTableNd = pTextNd->FindTableNode()) && + nullptr != ( pBox = pTableNd->GetTable().GetTableBox( + pSttNd->GetIndex() )) && +#ifdef DBG_UTIL + ( (pItem = pBox->GetFrameFormat()->GetItemIfSet( RES_BOXATR_FORMULA, false )) || + (pItem2 = pBox->GetFrameFormat()->GetItemIfSet( RES_BOXATR_VALUE, false )) ) +#else + (pItem = pBox->GetFrameFormat()->GetItemIfSet( RES_BOXATR_FORMULA, false )) #endif - const_cast<SwTableBoxFormula&>(pItem->StaticWhichCast(RES_BOXATR_FORMULA)).PtrToBoxNm( &pTableNd->GetTable() ); + ) + { + std::pair<Point, bool> tmp(aPt, true); + SwFrame* pF = pTextNd->getLayoutFrame(GetLayout(), nullptr, &tmp); + if( pF ) + { + // then the CellFrame + pFrame = static_cast<SwContentFrame*>(pF); + while( pF && !pF->IsCellFrame() ) + pF = pF->GetUpper(); + } - bRet = true; - if( bSetCursor ) - { - SwCallLink aLk( *this ); // watch Cursor-Moves - SwCursorSaveState aSaveState( *m_pCurrentCursor ); - *m_pCurrentCursor->GetPoint() = aPos; - if( m_pCurrentCursor->IsSelOvr( SwCursorSelOverFlags::CheckNodeSection | - SwCursorSelOverFlags::Toggle) ) - bRet = false; - else - UpdateCursor(); - } + if( aTmpState.m_bPosCorr ) + { + if( pF && !pF->getFrameArea().Contains( aPt )) + pF = nullptr; + } + else if( !pF ) + pF = pFrame; + + if( pF ) // only then it is valid + { + // create from internal (for CORE) the external + // (for UI) formula + rContentAtPos.eContentAtPos = IsAttrAtPos::TableBoxFml; +#ifdef DBG_UTIL + if( pItem2 ) + rContentAtPos.eContentAtPos = IsAttrAtPos::TableBoxValue; + else +#endif + const_cast<SwTableBoxFormula&>(*pItem).PtrToBoxNm( &pTableNd->GetTable() ); - if( bRet ) + bRet = true; + if( bSetCursor ) + { + SwCallLink aLk( *this ); // watch Cursor-Moves + SwCursorSaveState aSaveState( *m_pCurrentCursor ); + *m_pCurrentCursor->GetPoint() = aPos; + if( m_pCurrentCursor->IsSelOvr( SwCursorSelOverFlags::CheckNodeSection | + SwCursorSelOverFlags::Toggle) ) + bRet = false; + else + UpdateCursor(); + } + + if( bRet ) + { + if( pFieldRect ) { - if( pFieldRect ) - { - *pFieldRect = pF->getFramePrintArea(); - *pFieldRect += pF->getFrameArea().Pos(); - } - rContentAtPos.pFndTextAttr = nullptr; - rContentAtPos.aFnd.pAttr = pItem; + *pFieldRect = pF->getFramePrintArea(); + *pFieldRect += pF->getFrameArea().Pos(); } + rContentAtPos.pFndTextAttr = nullptr; + rContentAtPos.aFnd.pAttr = pItem; } } } + } #ifdef DBG_UTIL - if( !bRet && IsAttrAtPos::CurrAttrs & rContentAtPos.eContentAtPos ) + if( !bRet && IsAttrAtPos::CurrAttrs & rContentAtPos.eContentAtPos ) + { + const sal_Int32 n = aPos.GetContentIndex(); + SfxItemSetFixed<POOLATTR_BEGIN, POOLATTR_END - 1> aSet( GetDoc()->GetAttrPool() ); + if( pTextNd->GetpSwpHints() ) { - const sal_Int32 n = aPos.nContent.GetIndex(); - SfxItemSet aSet( GetDoc()->GetAttrPool(), svl::Items<POOLATTR_BEGIN, - POOLATTR_END - 1>{} ); - if( pTextNd->GetpSwpHints() ) + for( size_t i = 0; i < pTextNd->GetSwpHints().Count(); ++i ) { - for( size_t i = 0; i < pTextNd->GetSwpHints().Count(); ++i ) - { - const SwTextAttr* pHt = pTextNd->GetSwpHints().Get(i); - const sal_Int32 nAttrStart = pHt->GetStart(); - if( nAttrStart > n ) // over the section - break; - - if( nullptr != pHt->End() && ( - ( nAttrStart < n && - ( pHt->DontExpand() ? n < *pHt->End() - : n <= *pHt->End() )) || - ( n == nAttrStart && - ( nAttrStart == *pHt->End() || !n ))) ) - { - aSet.Put( pHt->GetAttr() ); - } - } - if( pTextNd->HasSwAttrSet() && - pTextNd->GetpSwAttrSet()->Count() ) + const SwTextAttr* pHt = pTextNd->GetSwpHints().Get(i); + const sal_Int32 nAttrStart = pHt->GetStart(); + if( nAttrStart > n ) // over the section + break; + + if( nullptr != pHt->End() && ( + ( nAttrStart < n && + ( pHt->DontExpand() ? n < *pHt->End() + : n <= *pHt->End() )) || + ( n == nAttrStart && + ( nAttrStart == *pHt->End() || !n ))) ) { - SfxItemSet aFormatSet( pTextNd->GetSwAttrSet() ); - // remove all from format set that are also in TextSet - aFormatSet.Differentiate( aSet ); - // now merge all together - aSet.Put( aFormatSet ); + aSet.Put( pHt->GetAttr() ); } } - else - pTextNd->SwContentNode::GetAttr( aSet ); - - rContentAtPos.sStr = "Pos: ("; - rContentAtPos.sStr += OUString::number( aPos.nNode.GetIndex()); - rContentAtPos.sStr += ":"; - rContentAtPos.sStr += OUString::number( aPos.nContent.GetIndex()); - rContentAtPos.sStr += ")"; - rContentAtPos.sStr += "\nParagraph Style: "; - rContentAtPos.sStr += pTextNd->GetFormatColl()->GetName(); - if( pTextNd->GetCondFormatColl() ) + if( pTextNd->HasSwAttrSet() && + pTextNd->GetpSwAttrSet()->Count() ) { - rContentAtPos.sStr += "\nConditional Style: " + pTextNd->GetCondFormatColl()->GetName(); + SfxItemSet aFormatSet( pTextNd->GetSwAttrSet() ); + // remove all from format set that are also in TextSet + aFormatSet.Differentiate( aSet ); + // now merge all together + aSet.Put( aFormatSet ); } + } + else + pTextNd->SwContentNode::GetAttr( aSet ); + + rContentAtPos.sStr = "Pos: ("; + rContentAtPos.sStr += OUString::number( sal_Int32(aPos.GetNodeIndex())); + rContentAtPos.sStr += ":"; + rContentAtPos.sStr += OUString::number( aPos.GetContentIndex()); + rContentAtPos.sStr += ")"; + rContentAtPos.sStr += "\nParagraph Style: "; + rContentAtPos.sStr += pTextNd->GetFormatColl()->GetName(); + if( pTextNd->GetCondFormatColl() ) + { + rContentAtPos.sStr += "\nConditional Style: " + pTextNd->GetCondFormatColl()->GetName(); + } - if( aSet.Count() ) + if( aSet.Count() ) + { + OUStringBuffer sAttrs; + SfxItemIter aIter( aSet ); + const SfxPoolItem* pItem = aIter.GetCurItem(); + const IntlWrapper aInt(SvtSysLocale().GetUILanguageTag()); + do { - OUStringBuffer sAttrs; - SfxItemIter aIter( aSet ); - const SfxPoolItem* pItem = aIter.GetCurItem(); - const IntlWrapper aInt(SvtSysLocale().GetUILanguageTag()); - do + if( !IsInvalidItem( pItem )) { - if( !IsInvalidItem( pItem )) - { - OUString aStr; - GetDoc()->GetAttrPool().GetPresentation(*pItem, - MapUnit::MapCM, aStr, aInt); - if (!sAttrs.isEmpty()) - sAttrs.append(", "); - sAttrs.append(aStr); - } - pItem = aIter.NextItem(); - } while (pItem); - if (!sAttrs.isEmpty()) - { - if( !rContentAtPos.sStr.isEmpty() ) - rContentAtPos.sStr += "\n"; - rContentAtPos.sStr += "Attr: " + sAttrs.toString(); + OUString aStr; + GetDoc()->GetAttrPool().GetPresentation(*pItem, + MapUnit::MapCM, aStr, aInt); + if (!sAttrs.isEmpty()) + sAttrs.append(", "); + sAttrs.append(aStr); } + pItem = aIter.NextItem(); + } while (pItem); + if (!sAttrs.isEmpty()) + { + if( !rContentAtPos.sStr.isEmpty() ) + rContentAtPos.sStr += "\n"; + rContentAtPos.sStr += "Attr: " + sAttrs; } - bRet = true; - rContentAtPos.eContentAtPos = IsAttrAtPos::CurrAttrs; } -#endif + bRet = true; + rContentAtPos.eContentAtPos = IsAttrAtPos::CurrAttrs; } +#endif } if( !bRet ) @@ -1861,21 +2123,20 @@ bool SwCursorShell::GetContentAtPos( const Point& rPt, // #i90516# const SwPostItField* SwCursorShell::GetPostItFieldAtCursor() const { - const SwPostItField* pPostItField = nullptr; + if ( IsTableMode() ) + return nullptr; + + const SwPosition* pCursorPos = GetCursor_()->GetPoint(); + const SwTextNode* pTextNd = pCursorPos->GetNode().GetTextNode(); + if ( !pTextNd ) + return nullptr; - if ( !IsTableMode() ) + const SwPostItField* pPostItField = nullptr; + SwTextAttr* pTextAttr = pTextNd->GetFieldTextAttrAt( pCursorPos->GetContentIndex() ); + const SwField* pField = pTextAttr != nullptr ? pTextAttr->GetFormatField().GetField() : nullptr; + if ( pField && pField->Which()== SwFieldIds::Postit ) { - const SwPosition* pCursorPos = GetCursor_()->GetPoint(); - const SwTextNode* pTextNd = pCursorPos->nNode.GetNode().GetTextNode(); - if ( pTextNd ) - { - SwTextAttr* pTextAttr = pTextNd->GetFieldTextAttrAt( pCursorPos->nContent.GetIndex() ); - const SwField* pField = pTextAttr != nullptr ? pTextAttr->GetFormatField().GetField() : nullptr; - if ( pField && pField->Which()== SwFieldIds::Postit ) - { - pPostItField = static_cast<const SwPostItField*>(pField); - } - } + pPostItField = static_cast<const SwPostItField*>(pField); } return pPostItField; @@ -1918,39 +2179,39 @@ bool SwContentAtPos::IsInProtectSect() const bool SwContentAtPos::IsInRTLText()const { - bool bRet = false; const SwTextNode* pNd = nullptr; - if (pFndTextAttr && (eContentAtPos == IsAttrAtPos::Ftn)) - { - const SwTextFootnote* pTextFootnote = static_cast<const SwTextFootnote*>(pFndTextAttr); - if(pTextFootnote->GetStartNode()) - { - SwStartNode* pSttNd = pTextFootnote->GetStartNode()->GetNode().GetStartNode(); - SwPaM aTemp( *pSttNd ); - aTemp.Move(fnMoveForward, GoInNode); - SwContentNode* pContentNode = aTemp.GetContentNode(); - if(pContentNode && pContentNode->IsTextNode()) - pNd = pContentNode->GetTextNode(); - } - } - if(pNd) + if (!pFndTextAttr || (eContentAtPos != IsAttrAtPos::Ftn)) + return false; + + const SwTextFootnote* pTextFootnote = static_cast<const SwTextFootnote*>(pFndTextAttr); + if(!pTextFootnote->GetStartNode()) + return false; + + SwStartNode* pSttNd = pTextFootnote->GetStartNode()->GetNode().GetStartNode(); + SwPaM aTemp( *pSttNd ); + aTemp.Move(fnMoveForward, GoInNode); + SwContentNode* pContentNode = aTemp.GetPointContentNode(); + if(pContentNode && pContentNode->IsTextNode()) + pNd = pContentNode->GetTextNode(); + if(!pNd) + return false; + + bool bRet = false; + SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(*pNd); + SwTextFrame* pTmpFrame = aIter.First(); + while( pTmpFrame ) { - SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(*pNd); - SwTextFrame* pTmpFrame = aIter.First(); - while( pTmpFrame ) + if ( !pTmpFrame->IsFollow()) { - if ( !pTmpFrame->IsFollow()) - { - bRet = pTmpFrame->IsRightToLeft(); - break; - } - pTmpFrame = aIter.Next(); + bRet = pTmpFrame->IsRightToLeft(); + break; } + pTmpFrame = aIter.Next(); } return bRet; } -bool SwCursorShell::SelectText( const sal_Int32 nStart, +bool SwCursorShell::SelectTextModel( const sal_Int32 nStart, const sal_Int32 nEnd ) { CurrShell aCurr( this ); @@ -1960,10 +2221,11 @@ bool SwCursorShell::SelectText( const sal_Int32 nStart, SwCursorSaveState aSaveState( *m_pCurrentCursor ); SwPosition& rPos = *m_pCurrentCursor->GetPoint(); + assert(nEnd <= rPos.GetNode().GetTextNode()->Len()); m_pCurrentCursor->DeleteMark(); - rPos.nContent = nStart; + rPos.SetContent(nStart); m_pCurrentCursor->SetMark(); - rPos.nContent = nEnd; + rPos.SetContent(nEnd); if( !m_pCurrentCursor->IsSelOvr() ) { @@ -1974,53 +2236,86 @@ bool SwCursorShell::SelectText( const sal_Int32 nStart, return bRet; } +TextFrameIndex SwCursorShell::GetCursorPointAsViewIndex() const +{ + SwPosition const*const pPos(GetCursor()->GetPoint()); + SwTextNode const*const pTextNode(pPos->GetNode().GetTextNode()); + assert(pTextNode); + SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(pTextNode->getLayoutFrame(GetLayout()))); + assert(pFrame); + return pFrame->MapModelToViewPos(*pPos); +} + +bool SwCursorShell::SelectTextView(TextFrameIndex const nStart, + TextFrameIndex const nEnd) +{ + CurrShell aCurr( this ); + bool bRet = false; + + SwCallLink aLk( *this ); + SwCursorSaveState aSaveState( *m_pCurrentCursor ); + + SwPosition& rPos = *m_pCurrentCursor->GetPoint(); + m_pCurrentCursor->DeleteMark(); + // indexes must correspond to cursor point! + SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(m_pCurrentCursor->GetPoint()->GetNode().GetTextNode()->getLayoutFrame(GetLayout()))); + assert(pFrame); + rPos = pFrame->MapViewToModelPos(nStart); + m_pCurrentCursor->SetMark(); + rPos = pFrame->MapViewToModelPos(nEnd); + + if (!m_pCurrentCursor->IsSelOvr()) + { + UpdateCursor(); + bRet = true; + } + + return bRet; +} + bool SwCursorShell::SelectTextAttr( sal_uInt16 nWhich, bool bExpand, const SwTextAttr* pTextAttr ) { CurrShell aCurr( this ); - bool bRet = false; - if( !IsTableMode() ) - { - if( !pTextAttr ) - { - SwPosition& rPos = *m_pCurrentCursor->GetPoint(); - SwTextNode* pTextNd = rPos.nNode.GetNode().GetTextNode(); - pTextAttr = pTextNd - ? pTextNd->GetTextAttrAt(rPos.nContent.GetIndex(), - nWhich, - bExpand ? SwTextNode::EXPAND : SwTextNode::DEFAULT) - : nullptr; - } + if( IsTableMode() ) + return false; - if( pTextAttr ) - { - const sal_Int32* pEnd = pTextAttr->End(); - bRet = SelectText( pTextAttr->GetStart(), ( pEnd ? *pEnd : pTextAttr->GetStart() + 1 ) ); - } + if( !pTextAttr ) + { + SwPosition& rPos = *m_pCurrentCursor->GetPoint(); + SwTextNode* pTextNd = rPos.GetNode().GetTextNode(); + pTextAttr = pTextNd + ? pTextNd->GetTextAttrAt(rPos.GetContentIndex(), + nWhich, + bExpand ? ::sw::GetTextAttrMode::Expand : ::sw::GetTextAttrMode::Default) + : nullptr; } + if( !pTextAttr ) + return false; + + const sal_Int32* pEnd = pTextAttr->End(); + sal_Int32 const nEnd(pEnd ? *pEnd : pTextAttr->GetStart() + 1); + assert(nEnd <= m_pCurrentCursor->GetPoint()->GetNode().GetTextNode()->Len()); + bool bRet = SelectTextModel(pTextAttr->GetStart(), nEnd); return bRet; } bool SwCursorShell::GotoINetAttr( const SwTextINetFormat& rAttr ) { - bool bRet = false; - if( rAttr.GetpTextNode() ) - { - SwCursor* pCursor = getShellCursor( true ); + if( !rAttr.GetpTextNode() ) + return false; + SwCursor* pCursor = getShellCursor( true ); - CurrShell aCurr( this ); - SwCallLink aLk( *this ); // watch Cursor-Moves - SwCursorSaveState aSaveState( *pCursor ); + CurrShell aCurr( this ); + SwCallLink aLk( *this ); // watch Cursor-Moves + SwCursorSaveState aSaveState( *pCursor ); - pCursor->GetPoint()->nNode = *rAttr.GetpTextNode(); - pCursor->GetPoint()->nContent.Assign( const_cast<SwTextNode*>(rAttr.GetpTextNode()), - rAttr.GetStart() ); - bRet = !pCursor->IsSelOvr(); - if( bRet ) - UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY); - } + pCursor->GetPoint()->Assign(*rAttr.GetpTextNode(), rAttr.GetStart() ); + bool bRet = !pCursor->IsSelOvr(); + if( bRet ) + UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY); return bRet; } @@ -2034,25 +2329,25 @@ bool SwCursorShell::GetShadowCursorPos( const Point& rPt, SwFillMode eFillMode, { CurrShell aCurr( this ); - bool bRet = false; - if (!IsTableMode() && !HasSelection() - && GetDoc()->GetIDocumentUndoRedo().DoesUndo()) - { - Point aPt( rPt ); - SwPosition aPos( *m_pCurrentCursor->GetPoint() ); + if (IsTableMode() || HasSelection() + || !GetDoc()->GetIDocumentUndoRedo().DoesUndo()) + return false; - SwFillCursorPos aFPos( eFillMode ); - SwCursorMoveState aTmpState( &aFPos ); + Point aPt( rPt ); + SwPosition aPos( *m_pCurrentCursor->GetPoint() ); - if( GetLayout()->GetModelPositionForViewPoint( &aPos, aPt, &aTmpState ) && - !aPos.nNode.GetNode().IsProtect()) - { - // start position in protected section? - rRect = aFPos.aCursor; - rOrient = aFPos.eOrient; - bRet = true; - } + SwFillCursorPos aFPos( eFillMode ); + SwCursorMoveState aTmpState( &aFPos ); + + bool bRet = false; + if( GetLayout()->GetModelPositionForViewPoint( &aPos, aPt, &aTmpState ) && + !aPos.GetNode().IsProtect()) + { + // start position in protected section? + rRect = aFPos.aCursor; + rOrient = aFPos.eOrient; + bRet = true; } return bRet; } @@ -2060,199 +2355,196 @@ bool SwCursorShell::GetShadowCursorPos( const Point& rPt, SwFillMode eFillMode, bool SwCursorShell::SetShadowCursorPos( const Point& rPt, SwFillMode eFillMode ) { CurrShell aCurr( this ); - bool bRet = false; - if (!IsTableMode() && !HasSelection() - && GetDoc()->GetIDocumentUndoRedo().DoesUndo()) + if (IsTableMode() || HasSelection() + || !GetDoc()->GetIDocumentUndoRedo().DoesUndo()) + return false; + + Point aPt( rPt ); + SwPosition aPos( *m_pCurrentCursor->GetPoint() ); + + SwFillCursorPos aFPos( eFillMode ); + SwCursorMoveState aTmpState( &aFPos ); + + if( !GetLayout()->GetModelPositionForViewPoint( &aPos, aPt, &aTmpState ) ) + return false; + + SwCallLink aLk( *this ); // watch Cursor-Moves + StartAction(); + + SwContentNode* pCNd = aPos.GetNode().GetContentNode(); + SwUndoId nUndoId = SwUndoId::INS_FROM_SHADOWCRSR; + // If only the paragraph attributes "Adjust" or "LRSpace" are set, + // then the following should not delete those again. + if( 0 == aFPos.nParaCnt + aFPos.nColumnCnt && + ( SwFillMode::Indent == aFPos.eMode || + ( text::HoriOrientation::NONE != aFPos.eOrient && + 0 == aFPos.nTabCnt + aFPos.nSpaceCnt )) && + pCNd && pCNd->Len() ) + nUndoId = SwUndoId::EMPTY; + + GetDoc()->GetIDocumentUndoRedo().StartUndo( nUndoId, nullptr ); + + SwTextFormatColl* pNextFormat = nullptr; + SwTextNode* pTNd = pCNd ? pCNd->GetTextNode() : nullptr; + if( pTNd ) + pNextFormat = &pTNd->GetTextColl()->GetNextTextFormatColl(); + + const SwSectionNode* pSectNd = pCNd ? pCNd->FindSectionNode() : nullptr; + if( pSectNd && aFPos.nParaCnt ) + { + SwNodeIndex aEnd( aPos.GetNode(), 1 ); + while( aEnd.GetNode().IsEndNode() && + &aEnd.GetNode() != + pSectNd->EndOfSectionNode() ) + ++aEnd; + + if( aEnd.GetNode().IsEndNode() && + pCNd->Len() == aPos.GetContentIndex() ) + aPos.Assign( *pSectNd->EndOfSectionNode() ); + } + + for( sal_uInt16 n = 0; n < aFPos.nParaCnt + aFPos.nColumnCnt; ++n ) { - Point aPt( rPt ); - SwPosition aPos( *m_pCurrentCursor->GetPoint() ); + GetDoc()->getIDocumentContentOperations().AppendTextNode( aPos ); + if( !n && pNextFormat ) + { + *m_pCurrentCursor->GetPoint() = aPos; + GetDoc()->SetTextFormatColl( *m_pCurrentCursor, pNextFormat, false ); + } + if( n < aFPos.nColumnCnt ) + { + *m_pCurrentCursor->GetPoint() = aPos; + GetDoc()->getIDocumentContentOperations().InsertPoolItem( *m_pCurrentCursor, + SvxFormatBreakItem( SvxBreak::ColumnBefore, RES_BREAK ) ); + } + } - SwFillCursorPos aFPos( eFillMode ); - SwCursorMoveState aTmpState( &aFPos ); + *m_pCurrentCursor->GetPoint() = aPos; + switch( aFPos.eMode ) + { + case SwFillMode::Indent: + if( nullptr != (pCNd = aPos.GetNode().GetContentNode() )) + { + assert(pCNd->IsTextNode()); // ??? + SfxItemSetFixed< + RES_PARATR_ADJUST, RES_PARATR_ADJUST, + RES_MARGIN_FIRSTLINE, RES_MARGIN_TEXTLEFT> aSet(GetDoc()->GetAttrPool()); + SvxFirstLineIndentItem firstLine(pCNd->GetAttr(RES_MARGIN_FIRSTLINE)); + SvxTextLeftMarginItem leftMargin(pCNd->GetAttr(RES_MARGIN_TEXTLEFT)); + firstLine.SetTextFirstLineOffset(0); + leftMargin.SetTextLeft(aFPos.nTabCnt); + aSet.Put(firstLine); + aSet.Put(leftMargin); + + const SvxAdjustItem& rAdj = pCNd->GetAttr(RES_PARATR_ADJUST); + if( SvxAdjust::Left != rAdj.GetAdjust() ) + aSet.Put( SvxAdjustItem( SvxAdjust::Left, RES_PARATR_ADJUST ) ); + + GetDoc()->getIDocumentContentOperations().InsertItemSet( *m_pCurrentCursor, aSet ); + } + else { + OSL_ENSURE( false, "No ContentNode" ); + } + break; - if( GetLayout()->GetModelPositionForViewPoint( &aPos, aPt, &aTmpState ) ) + case SwFillMode::Tab: + case SwFillMode::TabSpace: + case SwFillMode::Space: { - SwCallLink aLk( *this ); // watch Cursor-Moves - StartAction(); - - SwContentNode* pCNd = aPos.nNode.GetNode().GetContentNode(); - SwUndoId nUndoId = SwUndoId::INS_FROM_SHADOWCRSR; - // If only the paragraph attributes "Adjust" or "LRSpace" are set, - // then the following should not delete those again. - if( 0 == aFPos.nParaCnt + aFPos.nColumnCnt && - ( SwFillMode::Indent == aFPos.eMode || - ( text::HoriOrientation::NONE != aFPos.eOrient && - 0 == aFPos.nTabCnt + aFPos.nSpaceCnt )) && - pCNd && pCNd->Len() ) - nUndoId = SwUndoId::EMPTY; - - GetDoc()->GetIDocumentUndoRedo().StartUndo( nUndoId, nullptr ); - - SwTextFormatColl* pNextFormat = nullptr; - SwTextNode* pTNd = pCNd ? pCNd->GetTextNode() : nullptr; - if( pTNd ) - pNextFormat = &pTNd->GetTextColl()->GetNextTextFormatColl(); - - const SwSectionNode* pSectNd = pCNd ? pCNd->FindSectionNode() : nullptr; - if( pSectNd && aFPos.nParaCnt ) + OUStringBuffer sInsert; + if (aFPos.eMode == SwFillMode::Space) { - SwNodeIndex aEnd( aPos.nNode, 1 ); - while( aEnd.GetNode().IsEndNode() && - &aEnd.GetNode() != - pSectNd->EndOfSectionNode() ) - ++aEnd; - - if( aEnd.GetNode().IsEndNode() && - pCNd->Len() == aPos.nContent.GetIndex() ) - aPos.nNode = *pSectNd->EndOfSectionNode(); + comphelper::string::padToLength(sInsert, sInsert.getLength() + aFPos.nSpaceOnlyCnt, ' '); } - - for( sal_uInt16 n = 0; n < aFPos.nParaCnt + aFPos.nColumnCnt; ++n ) + else { - GetDoc()->getIDocumentContentOperations().AppendTextNode( aPos ); - if( !n && pNextFormat ) - { - *m_pCurrentCursor->GetPoint() = aPos; - GetDoc()->SetTextFormatColl( *m_pCurrentCursor, pNextFormat, false ); - } - if( n < aFPos.nColumnCnt ) - { - *m_pCurrentCursor->GetPoint() = aPos; - GetDoc()->getIDocumentContentOperations().InsertPoolItem( *m_pCurrentCursor, - SvxFormatBreakItem( SvxBreak::ColumnBefore, RES_BREAK ) ); - } + if (aFPos.nTabCnt) + comphelper::string::padToLength(sInsert, aFPos.nTabCnt, '\t'); + if (aFPos.nSpaceCnt) + comphelper::string::padToLength(sInsert, sInsert.getLength() + aFPos.nSpaceCnt, ' '); } - - *m_pCurrentCursor->GetPoint() = aPos; - switch( aFPos.eMode ) + if (!sInsert.isEmpty()) + GetDoc()->getIDocumentContentOperations().InsertString( *m_pCurrentCursor, sInsert.makeStringAndClear()); + } + [[fallthrough]]; // still need to set orientation + case SwFillMode::Margin: + if( text::HoriOrientation::NONE != aFPos.eOrient ) + { + SvxAdjustItem aAdj( SvxAdjust::Left, RES_PARATR_ADJUST ); + switch( aFPos.eOrient ) { - case SwFillMode::Indent: - if( nullptr != (pCNd = aPos.nNode.GetNode().GetContentNode() )) - { - SfxItemSet aSet( - GetDoc()->GetAttrPool(), - svl::Items< - RES_PARATR_ADJUST, RES_PARATR_ADJUST, - RES_LR_SPACE, RES_LR_SPACE>{}); - SvxLRSpaceItem aLR(pCNd->GetAttr(RES_LR_SPACE).StaticWhichCast(RES_LR_SPACE)); - aLR.SetTextLeft( aFPos.nTabCnt ); - aLR.SetTextFirstLineOffset( 0 ); - aSet.Put( aLR ); - - const SvxAdjustItem& rAdj = pCNd->GetAttr(RES_PARATR_ADJUST).StaticWhichCast(RES_PARATR_ADJUST); - if( SvxAdjust::Left != rAdj.GetAdjust() ) - aSet.Put( SvxAdjustItem( SvxAdjust::Left, RES_PARATR_ADJUST ) ); - - GetDoc()->getIDocumentContentOperations().InsertItemSet( *m_pCurrentCursor, aSet ); - } - else { - OSL_ENSURE( false, "No ContentNode" ); - } + case text::HoriOrientation::CENTER: + aAdj.SetAdjust( SvxAdjust::Center ); break; - - case SwFillMode::Tab: - case SwFillMode::TabSpace: - case SwFillMode::Space: - { - OUStringBuffer sInsert; - if (aFPos.eMode == SwFillMode::Space) - { - comphelper::string::padToLength(sInsert, sInsert.getLength() + aFPos.nSpaceOnlyCnt, ' '); - } - else - { - if (aFPos.nTabCnt) - comphelper::string::padToLength(sInsert, aFPos.nTabCnt, '\t'); - if (aFPos.nSpaceCnt) - comphelper::string::padToLength(sInsert, sInsert.getLength() + aFPos.nSpaceCnt, ' '); - } - if (!sInsert.isEmpty()) - GetDoc()->getIDocumentContentOperations().InsertString( *m_pCurrentCursor, sInsert.makeStringAndClear()); - } - [[fallthrough]]; // still need to set orientation - case SwFillMode::Margin: - if( text::HoriOrientation::NONE != aFPos.eOrient ) - { - SvxAdjustItem aAdj( SvxAdjust::Left, RES_PARATR_ADJUST ); - switch( aFPos.eOrient ) - { - case text::HoriOrientation::CENTER: - aAdj.SetAdjust( SvxAdjust::Center ); - break; - case text::HoriOrientation::RIGHT: - aAdj.SetAdjust( SvxAdjust::Right ); - break; - default: - break; - } - GetDoc()->getIDocumentContentOperations().InsertPoolItem( *m_pCurrentCursor, aAdj ); - } + case text::HoriOrientation::RIGHT: + aAdj.SetAdjust( SvxAdjust::Right ); + break; + default: break; } - - GetDoc()->GetIDocumentUndoRedo().EndUndo( nUndoId, nullptr ); - EndAction(); - - bRet = true; + GetDoc()->getIDocumentContentOperations().InsertPoolItem( *m_pCurrentCursor, aAdj ); } + break; } - return bRet; + + GetDoc()->GetIDocumentUndoRedo().EndUndo( nUndoId, nullptr ); + EndAction(); + + return true; } const SwRangeRedline* SwCursorShell::SelNextRedline() { - const SwRangeRedline* pFnd = nullptr; - if( !IsTableMode() ) - { - CurrShell aCurr( this ); - SwCallLink aLk( *this ); // watch Cursor-Moves - SwCursorSaveState aSaveState( *m_pCurrentCursor ); + if( IsTableMode() ) + return nullptr; - // ensure point is at the end so alternating SelNext/SelPrev works - NormalizePam(false); - pFnd = GetDoc()->getIDocumentRedlineAccess().SelNextRedline( *m_pCurrentCursor ); + CurrShell aCurr( this ); + SwCallLink aLk( *this ); // watch Cursor-Moves + SwCursorSaveState aSaveState( *m_pCurrentCursor ); - // at the end of the document, go to the start of the document, and try again - if ( !pFnd ) - { - GetDoc()->GetDocShell()->GetWrtShell()->StartOfSection(); - pFnd = GetDoc()->getIDocumentRedlineAccess().SelNextRedline( *m_pCurrentCursor ); - } + // ensure point is at the end so alternating SelNext/SelPrev works + NormalizePam(false); + const SwRangeRedline* pFnd = GetDoc()->getIDocumentRedlineAccess().SelNextRedline( *m_pCurrentCursor ); - if( pFnd && !m_pCurrentCursor->IsInProtectTable() && !m_pCurrentCursor->IsSelOvr() ) - UpdateCursor( SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY); - else - pFnd = nullptr; + // at the end of the document, go to the start of the document, and try again + if ( !pFnd ) + { + GetDoc()->GetDocShell()->GetWrtShell()->StartOfSection(); + pFnd = GetDoc()->getIDocumentRedlineAccess().SelNextRedline( *m_pCurrentCursor ); } + + if( pFnd && !m_pCurrentCursor->IsInProtectTable() && !m_pCurrentCursor->IsSelOvr() ) + UpdateCursor( SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY); + else + pFnd = nullptr; return pFnd; } const SwRangeRedline* SwCursorShell::SelPrevRedline() { - const SwRangeRedline* pFnd = nullptr; - if( !IsTableMode() ) - { - CurrShell aCurr( this ); - SwCallLink aLk( *this ); // watch Cursor-Moves - SwCursorSaveState aSaveState( *m_pCurrentCursor ); + if( IsTableMode() ) + return nullptr; - // ensure point is at the start so alternating SelNext/SelPrev works - NormalizePam(true); - pFnd = GetDoc()->getIDocumentRedlineAccess().SelPrevRedline( *m_pCurrentCursor ); + CurrShell aCurr( this ); + SwCallLink aLk( *this ); // watch Cursor-Moves + SwCursorSaveState aSaveState( *m_pCurrentCursor ); - // at the start of the document, go to the end of the document, and try again - if ( !pFnd ) - { - GetDoc()->GetDocShell()->GetWrtShell()->EndOfSection(); - pFnd = GetDoc()->getIDocumentRedlineAccess().SelPrevRedline( *m_pCurrentCursor ); - } + // ensure point is at the start so alternating SelNext/SelPrev works + NormalizePam(true); + const SwRangeRedline* pFnd = GetDoc()->getIDocumentRedlineAccess().SelPrevRedline( *m_pCurrentCursor ); - if( pFnd && !m_pCurrentCursor->IsInProtectTable() && !m_pCurrentCursor->IsSelOvr() ) - UpdateCursor( SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY); - else - pFnd = nullptr; + // at the start of the document, go to the end of the document, and try again + if ( !pFnd ) + { + GetDoc()->GetDocShell()->GetWrtShell()->EndOfSection(); + pFnd = GetDoc()->getIDocumentRedlineAccess().SelPrevRedline( *m_pCurrentCursor ); } + + if( pFnd && !m_pCurrentCursor->IsInProtectTable() && !m_pCurrentCursor->IsSelOvr() ) + UpdateCursor( SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY); + else + pFnd = nullptr; return pFnd; } @@ -2263,68 +2555,68 @@ const SwRangeRedline* SwCursorShell::GotoRedline_( SwRedlineTable::size_type nAr SwCursorSaveState aSaveState( *m_pCurrentCursor ); pFnd = GetDoc()->getIDocumentRedlineAccess().GetRedlineTable()[ nArrPos ]; - if( pFnd ) + if( !pFnd ) + return nullptr; + + *m_pCurrentCursor->GetPoint() = *pFnd->Start(); + + SwPosition* pPtPos = m_pCurrentCursor->GetPoint(); + if( !pPtPos->GetNode().IsContentNode() ) { - *m_pCurrentCursor->GetPoint() = *pFnd->Start(); + SwContentNode* pCNd = SwNodes::GoNextSection(pPtPos, + true, IsReadOnlyAvailable() ); + if( pCNd ) + { + if( pPtPos->GetNode() <= pFnd->End()->GetNode() ) + pPtPos->SetContent( 0 ); + else + pFnd = nullptr; + } + } - SwNodeIndex* pIdx = &m_pCurrentCursor->GetPoint()->nNode; - if( !pIdx->GetNode().IsContentNode() ) + if( pFnd && bSelect ) + { + m_pCurrentCursor->SetMark(); + if( RedlineType::FmtColl == pFnd->GetType() ) { - SwContentNode* pCNd = GetDoc()->GetNodes().GoNextSection( pIdx, - true, IsReadOnlyAvailable() ); + SwContentNode* pCNd = pPtPos->GetNode().GetContentNode(); + m_pCurrentCursor->GetPoint()->SetContent( pCNd->Len() ); + m_pCurrentCursor->GetMark()->Assign( *pCNd, 0 ); + } + else + *m_pCurrentCursor->GetPoint() = *pFnd->End(); + + pPtPos = m_pCurrentCursor->GetPoint(); + if( !pPtPos->GetNode().IsContentNode() ) + { + SwContentNode* pCNd = SwNodes::GoPrevSection( pPtPos, + true, IsReadOnlyAvailable() ); if( pCNd ) { - if( *pIdx <= pFnd->End()->nNode ) - m_pCurrentCursor->GetPoint()->nContent.Assign( pCNd, 0 ); + if( pPtPos->GetNode() >= m_pCurrentCursor->GetMark()->GetNode() ) + pPtPos->SetContent( pCNd->Len() ); else pFnd = nullptr; } } + } - if( pFnd && bSelect ) - { - m_pCurrentCursor->SetMark(); - if( RedlineType::FmtColl == pFnd->GetType() ) - { - SwContentNode* pCNd = pIdx->GetNode().GetContentNode(); - m_pCurrentCursor->GetPoint()->nContent.Assign( pCNd, pCNd->Len() ); - m_pCurrentCursor->GetMark()->nContent.Assign( pCNd, 0 ); - } - else - *m_pCurrentCursor->GetPoint() = *pFnd->End(); - - pIdx = &m_pCurrentCursor->GetPoint()->nNode; - if( !pIdx->GetNode().IsContentNode() ) - { - SwContentNode* pCNd = SwNodes::GoPrevSection( pIdx, - true, IsReadOnlyAvailable() ); - if( pCNd ) - { - if( *pIdx >= m_pCurrentCursor->GetMark()->nNode ) - m_pCurrentCursor->GetPoint()->nContent.Assign( pCNd, pCNd->Len() ); - else - pFnd = nullptr; - } - } - } + if( !pFnd ) + { + m_pCurrentCursor->DeleteMark(); + m_pCurrentCursor->RestoreSavePos(); + } + else if( bSelect && *m_pCurrentCursor->GetMark() == *m_pCurrentCursor->GetPoint() ) + m_pCurrentCursor->DeleteMark(); - if( !pFnd ) - { - m_pCurrentCursor->DeleteMark(); - m_pCurrentCursor->RestoreSavePos(); - } - else if( bSelect && *m_pCurrentCursor->GetMark() == *m_pCurrentCursor->GetPoint() ) + if( pFnd && !m_pCurrentCursor->IsInProtectTable() && !m_pCurrentCursor->IsSelOvr() ) + UpdateCursor( SwCursorShell::SCROLLWIN | SwCursorShell::CHKRANGE + | SwCursorShell::READONLY ); + else + { + pFnd = nullptr; + if( bSelect ) m_pCurrentCursor->DeleteMark(); - - if( pFnd && !m_pCurrentCursor->IsInProtectTable() && !m_pCurrentCursor->IsSelOvr() ) - UpdateCursor( SwCursorShell::SCROLLWIN | SwCursorShell::CHKRANGE - | SwCursorShell::READONLY ); - else - { - pFnd = nullptr; - if( bSelect ) - m_pCurrentCursor->DeleteMark(); - } } return pFnd; } @@ -2332,109 +2624,109 @@ const SwRangeRedline* SwCursorShell::GotoRedline_( SwRedlineTable::size_type nAr const SwRangeRedline* SwCursorShell::GotoRedline( SwRedlineTable::size_type nArrPos, bool bSelect ) { const SwRangeRedline* pFnd = nullptr; - if( !IsTableMode() ) - { - CurrShell aCurr( this ); + if( IsTableMode() ) + return nullptr; - const SwRedlineTable& rTable = GetDoc()->getIDocumentRedlineAccess().GetRedlineTable(); - const SwRangeRedline* pTmp = rTable[ nArrPos ]; - sal_uInt16 nSeqNo = pTmp->GetSeqNo(); - if( nSeqNo && bSelect ) - { - bool bCheck = false; - int nLoopCnt = 2; - SwRedlineTable::size_type nArrSavPos = nArrPos; + CurrShell aCurr( this ); - do { - pTmp = GotoRedline_( nArrPos, true ); + const SwRedlineTable& rTable = GetDoc()->getIDocumentRedlineAccess().GetRedlineTable(); + const SwRangeRedline* pTmp = rTable[ nArrPos ]; + sal_uInt16 nSeqNo = pTmp->GetSeqNo(); + if( !nSeqNo || !bSelect ) + { + pFnd = GotoRedline_( nArrPos, bSelect ); + return pFnd; + } - if( !pFnd ) - pFnd = pTmp; + bool bCheck = false; + int nLoopCnt = 2; + SwRedlineTable::size_type nArrSavPos = nArrPos; - if( pTmp && bCheck ) - { - // Check for overlaps. These can happen when FormatColl- - // Redlines were stretched over a whole paragraph - SwPaM* pCur = m_pCurrentCursor; - SwPaM* pNextPam = pCur->GetNext(); - SwPosition* pCStt = pCur->Start(), *pCEnd = pCur->End(); - while( pCur != pNextPam ) - { - const SwPosition *pNStt = pNextPam->Start(), - *pNEnd = pNextPam->End(); + do { + pTmp = GotoRedline_( nArrPos, true ); - bool bDel = true; - switch( ::ComparePosition( *pCStt, *pCEnd, - *pNStt, *pNEnd )) - { - case SwComparePosition::Inside: // Pos1 is completely in Pos2 - if( !pCur->HasMark() ) - { - pCur->SetMark(); - *pCur->GetMark() = *pNStt; - } - else - *pCStt = *pNStt; - *pCEnd = *pNEnd; - break; - - case SwComparePosition::Outside: // Pos2 is completely in Pos1 - case SwComparePosition::Equal: // Pos1 has same size as Pos2 - break; - - case SwComparePosition::OverlapBefore: // Pos1 overlaps Pos2 at beginning - if( !pCur->HasMark() ) - pCur->SetMark(); - *pCEnd = *pNEnd; - break; - case SwComparePosition::OverlapBehind: // Pos1 overlaps Pos2 at end - if( !pCur->HasMark() ) - { - pCur->SetMark(); - *pCur->GetMark() = *pNStt; - } - else - *pCStt = *pNStt; - break; + if( !pFnd ) + pFnd = pTmp; - default: - bDel = false; - } + if( pTmp && bCheck ) + { + // Check for overlaps. These can happen when FormatColl- + // Redlines were stretched over a whole paragraph + SwPaM* pCur = m_pCurrentCursor; + SwPaM* pNextPam = pCur->GetNext(); + auto [pCStt, pCEnd] = pCur->StartEnd(); // SwPosition* + while( pCur != pNextPam ) + { + auto [pNStt, pNEnd] = pNextPam->StartEnd(); // SwPosition* - if( bDel ) - { - // not needed anymore - SwPaM* pPrevPam = pNextPam->GetPrev(); - delete pNextPam; - pNextPam = pPrevPam; - } - pNextPam = pNextPam->GetNext(); + bool bDel = true; + switch( ::ComparePosition( *pCStt, *pCEnd, + *pNStt, *pNEnd )) + { + case SwComparePosition::Inside: // Pos1 is completely in Pos2 + if( !pCur->HasMark() ) + { + pCur->SetMark(); + *pCur->GetMark() = *pNStt; + } + else + *pCStt = *pNStt; + *pCEnd = *pNEnd; + break; + + case SwComparePosition::Outside: // Pos2 is completely in Pos1 + case SwComparePosition::Equal: // Pos1 has same size as Pos2 + break; + + case SwComparePosition::OverlapBefore: // Pos1 overlaps Pos2 at beginning + if( !pCur->HasMark() ) + pCur->SetMark(); + *pCEnd = *pNEnd; + break; + case SwComparePosition::OverlapBehind: // Pos1 overlaps Pos2 at end + if( !pCur->HasMark() ) + { + pCur->SetMark(); + *pCur->GetMark() = *pNStt; } + else + *pCStt = *pNStt; + break; + + default: + bDel = false; } - SwRedlineTable::size_type nFndPos = 2 == nLoopCnt - ? rTable.FindNextOfSeqNo( nArrPos ) - : rTable.FindPrevOfSeqNo( nArrPos ); - if( SwRedlineTable::npos != nFndPos || - ( 0 != ( --nLoopCnt ) && SwRedlineTable::npos != ( - nFndPos = rTable.FindPrevOfSeqNo( nArrSavPos ))) ) + if( bDel ) { - if( pTmp ) - { - // create new cursor - CreateCursor(); - bCheck = true; - } - nArrPos = nFndPos; + // not needed anymore + SwPaM* pPrevPam = pNextPam->GetPrev(); + delete pNextPam; + pNextPam = pPrevPam; } - else - nLoopCnt = 0; + pNextPam = pNextPam->GetNext(); + } + } - } while( nLoopCnt ); + SwRedlineTable::size_type nFndPos = 2 == nLoopCnt + ? rTable.FindNextOfSeqNo( nArrPos ) + : rTable.FindPrevOfSeqNo( nArrPos ); + if( SwRedlineTable::npos != nFndPos || + ( 0 != ( --nLoopCnt ) && SwRedlineTable::npos != ( + nFndPos = rTable.FindPrevOfSeqNo( nArrSavPos ))) ) + { + if( pTmp ) + { + // create new cursor + CreateCursor(); + bCheck = true; + } + nArrPos = nFndPos; } else - pFnd = GotoRedline_( nArrPos, bSelect ); - } + nLoopCnt = 0; + + } while( nLoopCnt ); return pFnd; } @@ -2443,7 +2735,7 @@ bool SwCursorShell::SelectNxtPrvHyperlink( bool bNext ) SwNodes& rNds = GetDoc()->GetNodes(); const SwNode* pBodyEndNd = &rNds.GetEndOfContent(); const SwNode* pBodySttNd = pBodyEndNd->StartOfSectionNode(); - sal_uLong nBodySttNdIdx = pBodySttNd->GetIndex(); + SwNodeOffset nBodySttNdIdx = pBodySttNd->GetIndex(); Point aPt; SetGetExpField aCmpPos( SwPosition( bNext ? *pBodyEndNd : *pBodySttNd ) ); @@ -2474,8 +2766,7 @@ bool SwCursorShell::SelectNxtPrvHyperlink( bool bNext ) if( pTextNd && pTextNd->GetNodes().IsDocNodes() ) { SwTextINetFormat& rAttr = *pFnd; - SwPosition aTmpPos( *pTextNd ); - SetGetExpField aPos( aTmpPos.nNode, rAttr ); + SetGetExpField aPos( *pTextNd, rAttr ); if (pTextNd->GetIndex() < nBodySttNdIdx) { std::pair<Point, bool> tmp(aPt, true); @@ -2507,10 +2798,9 @@ bool SwCursorShell::SelectNxtPrvHyperlink( bool bNext ) // then check all the Flys with a URL or image map { - const SwFrameFormats* pFormats = GetDoc()->GetSpzFrameFormats(); - for( SwFrameFormats::size_type n = 0, nEnd = pFormats->size(); n < nEnd; ++n ) + for(sw::SpzFrameFormat* pSpz: *GetDoc()->GetSpzFrameFormats()) { - SwFlyFrameFormat* pFormat = static_cast<SwFlyFrameFormat*>((*pFormats)[ n ]); + auto pFormat = static_cast<SwFlyFrameFormat*>(pSpz); const SwFormatURL& rURLItem = pFormat->GetURL(); if( rURLItem.GetMap() || !rURLItem.GetURL().isEmpty() ) { @@ -2531,51 +2821,51 @@ bool SwCursorShell::SelectNxtPrvHyperlink( bool bNext ) } // found any URL ? - bool bRet = false; const SwTextINetFormat* pFndAttr = aCmpPos.GetINetFormat(); const SwFlyFrameFormat* pFndFormat = aCmpPos.GetFlyFormat(); - if( pFndAttr || pFndFormat ) - { - CurrShell aCurr( this ); - SwCallLink aLk( *this ); + if( !pFndAttr && !pFndFormat ) + return false; - // found a text attribute ? - if( pFndAttr ) - { - SwCursorSaveState aSaveState( *m_pCurrentCursor ); + CurrShell aCurr( this ); + SwCallLink aLk( *this ); - aCmpPos.GetPosOfContent( *m_pCurrentCursor->GetPoint() ); - m_pCurrentCursor->DeleteMark(); - m_pCurrentCursor->SetMark(); - m_pCurrentCursor->GetPoint()->nContent = *pFndAttr->End(); + bool bRet = false; + // found a text attribute ? + if( pFndAttr ) + { + SwCursorSaveState aSaveState( *m_pCurrentCursor ); - if( !m_pCurrentCursor->IsInProtectTable() && !m_pCurrentCursor->IsSelOvr() ) - { - UpdateCursor( SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE| - SwCursorShell::READONLY ); - bRet = true; - } + aCmpPos.GetPosOfContent( *m_pCurrentCursor->GetPoint() ); + m_pCurrentCursor->DeleteMark(); + m_pCurrentCursor->SetMark(); + m_pCurrentCursor->GetPoint()->SetContent( *pFndAttr->End() ); + + if( !m_pCurrentCursor->IsInProtectTable() && !m_pCurrentCursor->IsSelOvr() ) + { + UpdateCursor( SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE| + SwCursorShell::READONLY ); + bRet = true; } - // found a draw object ? - else if( RES_DRAWFRMFMT == pFndFormat->Which() ) + } + // found a draw object ? + else if( RES_DRAWFRMFMT == pFndFormat->Which() ) + { + const SdrObject* pSObj = pFndFormat->FindSdrObject(); + if (pSObj) { - const SdrObject* pSObj = pFndFormat->FindSdrObject(); - if (pSObj) - { - static_cast<SwFEShell*>(this)->SelectObj( pSObj->GetCurrentBoundRect().Center() ); - MakeSelVisible(); - bRet = true; - } + static_cast<SwFEShell*>(this)->SelectObj( pSObj->GetCurrentBoundRect().Center() ); + MakeSelVisible(); + bRet = true; } - else // then is it a fly + } + else // then is it a fly + { + SwFlyFrame* pFly = pFndFormat->GetFrame(&aPt); + if( pFly ) { - SwFlyFrame* pFly = pFndFormat->GetFrame(&aPt); - if( pFly ) - { - static_cast<SwFEShell*>(this)->SelectFlyFrame( *pFly ); - MakeSelVisible(); - bRet = true; - } + static_cast<SwFEShell*>(this)->SelectFlyFrame( *pFly ); + MakeSelVisible(); + bRet = true; } } return bRet; diff --git a/sw/source/core/crsr/datecontentcontrolbutton.cxx b/sw/source/core/crsr/datecontentcontrolbutton.cxx new file mode 100644 index 000000000000..9de971b6f9f6 --- /dev/null +++ b/sw/source/core/crsr/datecontentcontrolbutton.cxx @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <datecontentcontrolbutton.hxx> + +#include <svl/numformat.hxx> +#include <tools/date.hxx> +#include <vcl/svapp.hxx> + +#include <edtwin.hxx> +#include <formatcontentcontrol.hxx> +#include <view.hxx> +#include <wrtsh.hxx> + +IMPL_LINK(SwDateContentControlButton, SelectHandler, weld::Calendar&, rCalendar, void) +{ + const Date& rNullDate = m_pNumberFormatter->GetNullDate(); + double fDate = rCalendar.get_date() - rNullDate; + m_xPopup->popdown(); + m_pContentControl->SetSelectedDate(fDate); + SwView& rView = static_cast<SwEditWin*>(GetParent())->GetView(); + SwWrtShell& rWrtShell = rView.GetWrtShell(); + rWrtShell.GotoContentControl(*m_pContentControl->GetFormatContentControl()); +} + +SwDateContentControlButton::SwDateContentControlButton( + SwEditWin* pEditWin, const std::shared_ptr<SwContentControl>& pContentControl, + SvNumberFormatter* pNumberFormatter) + : SwContentControlButton(pEditWin, pContentControl) + , m_pNumberFormatter(pNumberFormatter) +{ +} + +SwDateContentControlButton::~SwDateContentControlButton() { disposeOnce(); } + +void SwDateContentControlButton::LaunchPopup() +{ + m_xPopupBuilder = Application::CreateBuilder(GetFrameWeld(), + "modules/swriter/ui/contentcontrolcalendar.ui"); + m_xPopup = m_xPopupBuilder->weld_popover("Calendar"); + m_xCalendar = m_xPopupBuilder->weld_calendar("date"); + + // Read the doc model. + if (m_pContentControl) + { + const Date& rNullDate = m_pNumberFormatter->GetNullDate(); + double fCurrentDate = m_pContentControl->GetCurrentDateValue(); + if (fCurrentDate != 0) + { + m_xCalendar->set_date(rNullDate + sal_Int32(fCurrentDate)); + } + } + + m_xCalendar->connect_activated(LINK(this, SwDateContentControlButton, SelectHandler)); + SwContentControlButton::LaunchPopup(); + m_xCalendar->grab_focus(); +} + +void SwDateContentControlButton::DestroyPopup() +{ + m_xCalendar.reset(); + SwContentControlButton::DestroyPopup(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/crsr/dropdowncontentcontrolbutton.cxx b/sw/source/core/crsr/dropdowncontentcontrolbutton.cxx new file mode 100644 index 000000000000..ba47c33f2607 --- /dev/null +++ b/sw/source/core/crsr/dropdowncontentcontrolbutton.cxx @@ -0,0 +1,96 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <dropdowncontentcontrolbutton.hxx> + +#include <vcl/settings.hxx> +#include <vcl/svapp.hxx> + +#include <edtwin.hxx> +#include <view.hxx> +#include <strings.hrc> +#include <formatcontentcontrol.hxx> +#include <wrtsh.hxx> + +void SwDropDownContentControlButton::InitDropdown() +{ + std::vector<SwContentControlListItem> aListItems = m_pContentControl->GetListItems(); + + for (const auto& rListItem : aListItems) + { + m_xTreeView->append_text(rListItem.ToString()); + } + + if (aListItems.empty()) + { + m_xTreeView->append_text(SwResId(STR_DROP_DOWN_EMPTY_LIST)); + } + + int nHeight = m_xTreeView->get_height_rows( + std::min<int>(Application::GetSettings().GetStyleSettings().GetListBoxMaximumLineCount(), + m_xTreeView->n_children())); + m_xTreeView->set_size_request(-1, nHeight); + Size aSize(m_xTreeView->get_preferred_size()); + aSize.AdjustWidth(4); + aSize.AdjustHeight(4); + tools::Long nMinListWidth = GetSizePixel().Width(); + aSize.setWidth(std::max(aSize.Width(), nMinListWidth)); + m_xTreeView->set_size_request(aSize.Width(), aSize.Height()); + m_xTreeView->set_direction(m_bRTL); +} + +IMPL_LINK(SwDropDownContentControlButton, ListBoxHandler, weld::TreeView&, rBox, bool) +{ + OUString sSelection = rBox.get_selected_text(); + if (sSelection == SwResId(STR_DROP_DOWN_EMPTY_LIST)) + { + m_xPopup->popdown(); + return true; + } + + sal_Int32 nSelection = rBox.get_selected_index(); + m_xPopup->popdown(); + if (nSelection >= 0) + { + SwView& rView = static_cast<SwEditWin*>(GetParent())->GetView(); + SwWrtShell& rWrtShell = rView.GetWrtShell(); + m_pContentControl->SetSelectedListItem(nSelection); + rWrtShell.GotoContentControl(*m_pContentControl->GetFormatContentControl()); + } + + return true; +} + +SwDropDownContentControlButton::SwDropDownContentControlButton( + SwEditWin* pEditWin, const std::shared_ptr<SwContentControl>& pContentControl) + : SwContentControlButton(pEditWin, pContentControl) +{ +} + +SwDropDownContentControlButton::~SwDropDownContentControlButton() { disposeOnce(); } + +void SwDropDownContentControlButton::LaunchPopup() +{ + m_xPopupBuilder = Application::CreateBuilder(GetFrameWeld(), + "modules/swriter/ui/contentcontroldropdown.ui"); + m_xPopup = m_xPopupBuilder->weld_popover("ContentControlDropDown"); + m_xTreeView = m_xPopupBuilder->weld_tree_view("list"); + InitDropdown(); + m_xTreeView->connect_row_activated(LINK(this, SwDropDownContentControlButton, ListBoxHandler)); + SwContentControlButton::LaunchPopup(); + m_xTreeView->grab_focus(); +} + +void SwDropDownContentControlButton::DestroyPopup() +{ + m_xTreeView.reset(); + SwContentControlButton::DestroyPopup(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/crsr/findattr.cxx b/sw/source/core/crsr/findattr.cxx index 09f78df324e8..7c4932f745d0 100644 --- a/sw/source/core/crsr/findattr.cxx +++ b/sw/source/core/crsr/findattr.cxx @@ -104,22 +104,21 @@ static void lcl_SetAttrPam( SwPaM& rPam, sal_Int32 nStart, const sal_Int32* pEnd { sal_Int32 nContentPos; if( bSaveMark ) - nContentPos = rPam.GetMark()->nContent.GetIndex(); + nContentPos = rPam.GetMark()->GetContentIndex(); else - nContentPos = rPam.GetPoint()->nContent.GetIndex(); - bool bTstEnd = rPam.GetPoint()->nNode == rPam.GetMark()->nNode; + nContentPos = rPam.GetPoint()->GetContentIndex(); + bool bTstEnd = rPam.GetPoint()->GetNode() == rPam.GetMark()->GetNode(); - SwContentNode* pCNd = rPam.GetContentNode(); - rPam.GetPoint()->nContent.Assign( pCNd, nStart ); + rPam.GetPoint()->SetContent( nStart ); rPam.SetMark(); // Point == GetMark // Point points to end of search area or end of attribute if( pEnd ) { if( bTstEnd && *pEnd > nContentPos ) - rPam.GetPoint()->nContent = nContentPos; + rPam.GetPoint()->SetContent(nContentPos); else - rPam.GetPoint()->nContent = *pEnd; + rPam.GetPoint()->SetContent(*pEnd); } } @@ -146,7 +145,7 @@ static bool lcl_SearchAttr( const SwTextNode& rTextNd, SwPaM& rPam, const SwTextAttr *pTextHt = nullptr; bool bForward = &fnMove == &fnMoveForward; size_t nPos = bForward ? 0 : rTextNd.GetSwpHints().Count(); - sal_Int32 nContentPos = rPam.GetPoint()->nContent.GetIndex(); + sal_Int32 nContentPos = rPam.GetPoint()->GetContentIndex(); while( nullptr != ( pTextHt=(*fnMove.fnGetHint)(rTextNd.GetSwpHints(),nPos,nContentPos))) if (pTextHt->Which() == rCmpItem.Which()) @@ -214,7 +213,7 @@ SwAttrCheckArr::SwAttrCheckArr( const SfxItemSet& rSet, bool bFwd, , m_nNodeEnd(0) , m_nFound(0) , m_nStackCount(0) - , m_aComapeSet( *rSet.GetPool(), svl::Items<RES_CHRATR_BEGIN, RES_TXTATR_END-1>{} ) + , m_aComapeSet( *rSet.GetPool(), svl::Items<RES_CHRATR_BEGIN, RES_TXTATR_END-1> ) , m_bNoColls(bNoCollections) , m_bForward(bFwd) { @@ -222,8 +221,8 @@ SwAttrCheckArr::SwAttrCheckArr( const SfxItemSet& rSet, bool bFwd, // determine area of Fnd/Stack array (Min/Max) SfxItemIter aIter( m_aComapeSet ); - m_nArrStart = m_aComapeSet.GetWhichByPos( aIter.GetFirstPos() ); - m_nArrLen = m_aComapeSet.GetWhichByPos( aIter.GetLastPos() ) - m_nArrStart+1; + m_nArrStart = m_aComapeSet.GetWhichByOffset( aIter.GetFirstPos() ); + m_nArrLen = m_aComapeSet.GetWhichByOffset( aIter.GetLastPos() ) - m_nArrStart+1; char* pFndChar = new char[ m_nArrLen * sizeof(SwSrchChrAttr) ]; char* pStackChar = new char[ m_nArrLen * sizeof(SwSrchChrAttr) ]; @@ -247,16 +246,16 @@ void SwAttrCheckArr::SetNewSet( const SwTextNode& rTextNd, const SwPaM& rPam ) if( m_bForward ) { - m_nNodeStart = rPam.GetPoint()->nContent.GetIndex(); - m_nNodeEnd = rPam.GetPoint()->nNode == rPam.GetMark()->nNode - ? rPam.GetMark()->nContent.GetIndex() + m_nNodeStart = rPam.GetPoint()->GetContentIndex(); + m_nNodeEnd = rPam.GetPoint()->GetNode() == rPam.GetMark()->GetNode() + ? rPam.GetMark()->GetContentIndex() : rTextNd.GetText().getLength(); } else { - m_nNodeEnd = rPam.GetPoint()->nContent.GetIndex(); - m_nNodeStart = rPam.GetPoint()->nNode == rPam.GetMark()->nNode - ? rPam.GetMark()->nContent.GetIndex() + m_nNodeEnd = rPam.GetPoint()->GetContentIndex(); + m_nNodeStart = rPam.GetPoint()->GetNode() == rPam.GetMark()->GetNode() + ? rPam.GetMark()->GetContentIndex() : 0; } @@ -274,12 +273,12 @@ void SwAttrCheckArr::SetNewSet( const SwTextNode& rTextNd, const SwPaM& rPam ) { if( IsInvalidItem( pItem ) ) { - nWhich = m_aComapeSet.GetWhichByPos( aIter.GetCurPos() ); + nWhich = m_aComapeSet.GetWhichByOffset( aIter.GetCurPos() ); if( RES_TXTATR_END <= nWhich ) break; // end of text attributes if( SfxItemState::SET == rSet.GetItemState( nWhich, !m_bNoColls, &pFndItem ) - && !CmpAttr( *pFndItem, rSet.GetPool()->GetDefaultItem( nWhich ) )) + && !CmpAttr( *pFndItem, rSet.GetPool()->GetUserOrPoolDefaultItem( nWhich ) )) { m_pFindArr[ nWhich - m_nArrStart ] = SwSrchChrAttr( *pFndItem, m_nNodeStart, m_nNodeEnd ); @@ -332,7 +331,7 @@ bool SwAttrCheckArr::SetAttrFwd( const SwTextAttr& rAttr ) const SfxPoolItem* pItem; // here we explicitly also search in character templates sal_uInt16 nWhch = rAttr.Which(); - std::unique_ptr<SfxWhichIter> pIter; + std::optional<SfxWhichIter> oIter; const SfxPoolItem* pTmpItem = nullptr; const SfxItemSet* pSet = nullptr; if( RES_TXTATR_CHARFMT == nWhch || RES_TXTATR_AUTOFMT == nWhch ) @@ -343,11 +342,11 @@ bool SwAttrCheckArr::SetAttrFwd( const SwTextAttr& rAttr ) pSet = CharFormat::GetItemSet( rAttr.GetAttr() ); if ( pSet ) { - pIter.reset(new SfxWhichIter( *pSet )); - nWhch = pIter->FirstWhich(); + oIter.emplace( *pSet ); + nWhch = oIter->FirstWhich(); while( nWhch && - SfxItemState::SET != pSet->GetItemState( nWhch, true, &pTmpItem ) ) - nWhch = pIter->NextWhich(); + SfxItemState::SET != oIter->GetItemState( true, &pTmpItem ) ) + nWhch = oIter->NextWhich(); if( !nWhch ) pTmpItem = nullptr; } @@ -358,7 +357,7 @@ bool SwAttrCheckArr::SetAttrFwd( const SwTextAttr& rAttr ) while( pTmpItem ) { SfxItemState eState = m_aComapeSet.GetItemState( nWhch, false, &pItem ); - if( SfxItemState::DONTCARE == eState || SfxItemState::SET == eState ) + if( SfxItemState::INVALID == eState || SfxItemState::SET == eState ) { sal_uInt16 n; SwSrchChrAttr* pCmp; @@ -410,10 +409,10 @@ bool SwAttrCheckArr::SetAttrFwd( const SwTextAttr& rAttr ) bool bContinue = false; - if( SfxItemState::DONTCARE == eState ) + if( SfxItemState::INVALID == eState ) { // Will the attribute become valid? - if( !CmpAttr( m_aComapeSet.GetPool()->GetDefaultItem( nWhch ), + if( !CmpAttr( m_aComapeSet.GetPool()->GetUserOrPoolDefaultItem( nWhch ), *pTmpItem )) { // search attribute and extend if needed @@ -462,20 +461,20 @@ bool SwAttrCheckArr::SetAttrFwd( const SwTextAttr& rAttr ) } } } - if( pIter ) + if( oIter ) { - assert(pSet && "otherwise no pIter"); - nWhch = pIter->NextWhich(); + assert(pSet && "otherwise no oIter"); + nWhch = oIter->NextWhich(); while( nWhch && - SfxItemState::SET != pSet->GetItemState( nWhch, true, &pTmpItem ) ) - nWhch = pIter->NextWhich(); + SfxItemState::SET != oIter->GetItemState( true, &pTmpItem ) ) + nWhch = oIter->NextWhich(); if( !nWhch ) break; } else break; } - pIter.reset(); + oIter.reset(); return Found(); } @@ -492,7 +491,7 @@ bool SwAttrCheckArr::SetAttrBwd( const SwTextAttr& rAttr ) const SfxPoolItem* pItem; // here we explicitly also search in character templates sal_uInt16 nWhch = rAttr.Which(); - std::unique_ptr<SfxWhichIter> pIter; + std::optional<SfxWhichIter> oIter; const SfxPoolItem* pTmpItem = nullptr; const SfxItemSet* pSet = nullptr; if( RES_TXTATR_CHARFMT == nWhch || RES_TXTATR_AUTOFMT == nWhch ) @@ -503,11 +502,11 @@ bool SwAttrCheckArr::SetAttrBwd( const SwTextAttr& rAttr ) pSet = CharFormat::GetItemSet( rAttr.GetAttr() ); if ( pSet ) { - pIter.reset( new SfxWhichIter( *pSet ) ); - nWhch = pIter->FirstWhich(); + oIter.emplace( *pSet ); + nWhch = oIter->FirstWhich(); while( nWhch && - SfxItemState::SET != pSet->GetItemState( nWhch, true, &pTmpItem ) ) - nWhch = pIter->NextWhich(); + SfxItemState::SET != oIter->GetItemState( true, &pTmpItem ) ) + nWhch = oIter->NextWhich(); if( !nWhch ) pTmpItem = nullptr; } @@ -518,7 +517,7 @@ bool SwAttrCheckArr::SetAttrBwd( const SwTextAttr& rAttr ) while( pTmpItem ) { SfxItemState eState = m_aComapeSet.GetItemState( nWhch, false, &pItem ); - if( SfxItemState::DONTCARE == eState || SfxItemState::SET == eState ) + if( SfxItemState::INVALID == eState || SfxItemState::SET == eState ) { sal_uInt16 n; SwSrchChrAttr* pCmp; @@ -568,10 +567,10 @@ bool SwAttrCheckArr::SetAttrBwd( const SwTextAttr& rAttr ) } bool bContinue = false; - if( SfxItemState::DONTCARE == eState ) + if( SfxItemState::INVALID == eState ) { // Will the attribute become valid? - if( !CmpAttr( m_aComapeSet.GetPool()->GetDefaultItem( nWhch ), + if( !CmpAttr( m_aComapeSet.GetPool()->GetUserOrPoolDefaultItem( nWhch ), *pTmpItem ) ) { // search attribute and extend if needed @@ -620,20 +619,20 @@ bool SwAttrCheckArr::SetAttrBwd( const SwTextAttr& rAttr ) } } } - if( pIter ) + if( oIter ) { - assert(pSet && "otherwise no pIter"); - nWhch = pIter->NextWhich(); + assert(pSet && "otherwise no oIter"); + nWhch = oIter->NextWhich(); while( nWhch && - SfxItemState::SET != pSet->GetItemState( nWhch, true, &pTmpItem ) ) - nWhch = pIter->NextWhich(); + SfxItemState::SET != oIter->GetItemState( true, &pTmpItem ) ) + nWhch = oIter->NextWhich(); if( !nWhch ) break; } else break; } - pIter.reset(); + oIter.reset(); return Found(); } @@ -888,9 +887,9 @@ static bool lcl_Search( const SwContentNode& rCNd, const SfxItemSet& rCmpSet, bo { if( IsInvalidItem( pItem )) { - nWhich = rCmpSet.GetWhichByPos( aIter.GetCurPos() ); + nWhich = rCmpSet.GetWhichByOffset( aIter.GetCurPos() ); if( SfxItemState::SET != rNdSet.GetItemState( nWhich, !bNoColls, &pNdItem ) - || CmpAttr( *pNdItem, rNdSet.GetPool()->GetDefaultItem( nWhich ) )) + || CmpAttr( *pNdItem, rNdSet.GetPool()->GetUserOrPoolDefaultItem( nWhich ) )) return false; } else @@ -918,7 +917,8 @@ bool FindAttrImpl(SwPaM & rSearchPam, bool bCharAttr = isCHRATR(nWhich) || isTXTATR(nWhich); assert(isTXTATR(nWhich)); // sw_redlinehide: only works for non-formatting hints such as needed in UpdateFields; use FindAttrsImpl for others - std::unique_ptr<SwPaM> pPam(sw::MakeRegion(fnMove, rRegion)); + std::optional<SwPaM> oPam; + sw::MakeRegion(fnMove, rRegion, oPam); bool bFound = false; bool bFirst = true; @@ -927,18 +927,18 @@ bool FindAttrImpl(SwPaM & rSearchPam, // if at beginning/end then move it out of the node if( bSrchForward - ? pPam->GetPoint()->nContent.GetIndex() == pPam->GetContentNode()->Len() - : !pPam->GetPoint()->nContent.GetIndex() ) + ? oPam->GetPoint()->GetContentIndex() == oPam->GetPointContentNode()->Len() + : !oPam->GetPoint()->GetContentIndex() ) { - if( !(*fnMove.fnNds)( &pPam->GetPoint()->nNode, false )) + if( !(*fnMove.fnPos)( oPam->GetPoint(), false )) { return false; } - SwContentNode *pNd = pPam->GetContentNode(); - pPam->GetPoint()->nContent.Assign( pNd, bSrchForward ? 0 : pNd->Len() ); + SwContentNode *pNd = oPam->GetPointContentNode(); + oPam->GetPoint()->SetContent( bSrchForward ? 0 : pNd->Len() ); } - while (nullptr != (pNode = ::GetNode(*pPam, bFirst, fnMove, bInReadOnly, pLayout))) + while (nullptr != (pNode = ::GetNode(*oPam, bFirst, fnMove, bInReadOnly, pLayout))) { if( bCharAttr ) { @@ -960,9 +960,9 @@ bool FindAttrImpl(SwPaM & rSearchPam, pAttr = iter.NextAttr(&pAttrNode); } while (pAttr - && (pAttrNode->GetIndex() < pPam->GetPoint()->nNode.GetIndex() - || (pAttrNode->GetIndex() == pPam->GetPoint()->nNode.GetIndex() - && pAttr->GetStart() < pPam->GetPoint()->nContent.GetIndex()) + && (pAttrNode->GetIndex() < oPam->GetPoint()->GetNodeIndex() + || (pAttrNode->GetIndex() == oPam->GetPoint()->GetNodeIndex() + && pAttr->GetStart() < oPam->GetPoint()->GetContentIndex()) || pAttr->Which() != nWhich)); } else @@ -973,22 +973,22 @@ bool FindAttrImpl(SwPaM & rSearchPam, pAttr = iter.PrevAttr(&pAttrNode); } while (pAttr - && (pPam->GetPoint()->nNode.GetIndex() < pAttrNode->GetIndex() - || (pPam->GetPoint()->nNode.GetIndex() == pAttrNode->GetIndex() - && pPam->GetPoint()->nContent.GetIndex() <= pAttr->GetStart()) + && (oPam->GetPoint()->GetNodeIndex() < pAttrNode->GetIndex() + || (oPam->GetPoint()->GetNodeIndex() == pAttrNode->GetIndex() + && oPam->GetPoint()->GetContentIndex() <= pAttr->GetStart()) || pAttr->Which() != nWhich)); } if (pAttr) { assert(pAttrNode); - pPam->GetPoint()->nNode = *pAttrNode; - lcl_SetAttrPam(*pPam, pAttr->GetStart(), pAttr->End(), bSrchForward); + oPam->GetPoint()->Assign(*pAttrNode); + lcl_SetAttrPam(*oPam, pAttr->GetStart(), pAttr->End(), bSrchForward); bFound = true; break; } } else if (!pLayout && pNode->GetTextNode()->HasHints() && - lcl_SearchAttr(*pNode->GetTextNode(), *pPam, rAttr, fnMove)) + lcl_SearchAttr(*pNode->GetTextNode(), *oPam, rAttr, fnMove)) { bFound = true; } @@ -996,8 +996,8 @@ bool FindAttrImpl(SwPaM & rSearchPam, { // set to the values of the attribute rSearchPam.SetMark(); - *rSearchPam.GetPoint() = *pPam->GetPoint(); - *rSearchPam.GetMark() = *pPam->GetMark(); + *rSearchPam.GetPoint() = *oPam->GetPoint(); + *rSearchPam.GetMark() = *oPam->GetMark(); break; } else if (isTXTATR(nWhich)) @@ -1021,7 +1021,7 @@ bool FindAttrImpl(SwPaM & rSearchPam, // always: incl. start and incl. end *rSearchPam.GetPoint() = *pPam->GetPoint(); rSearchPam.SetMark(); - pNode->MakeEndIndex( &rSearchPam.GetPoint()->nContent ); + rSearchPam.GetPoint()->SetContent(pNode->Len()); bFound = true; break; } @@ -1044,7 +1044,8 @@ static bool FindAttrsImpl(SwPaM & rSearchPam, const SwPaM & rRegion, bool bInReadOnly, bool bMoveFirst, SwRootFrame const*const pLayout) { - std::unique_ptr<SwPaM> pPam(sw::MakeRegion(fnMove, rRegion)); + std::optional<SwPaM> oPam; + sw::MakeRegion(fnMove, rRegion, oPam); bool bFound = false; bool bFirst = true; @@ -1054,8 +1055,7 @@ static bool FindAttrsImpl(SwPaM & rSearchPam, // check which text/char attributes are searched SwAttrCheckArr aCmpArr( rSet, bSrchForward, bNoColls ); - SfxItemSet aOtherSet( rSearchPam.GetDoc().GetAttrPool(), - svl::Items<RES_PARATR_BEGIN, RES_GRFATR_END-1>{} ); + SfxItemSetFixed<RES_PARATR_BEGIN, RES_GRFATR_END-1> aOtherSet( rSearchPam.GetDoc().GetAttrPool() ); aOtherSet.Put( rSet, false ); // got all invalid items FnSearchAttr fnSearch = bSrchForward @@ -1065,18 +1065,18 @@ static bool FindAttrsImpl(SwPaM & rSearchPam, // if at beginning/end then move it out of the node if( bMoveFirst && ( bSrchForward - ? pPam->GetPoint()->nContent.GetIndex() == pPam->GetContentNode()->Len() - : !pPam->GetPoint()->nContent.GetIndex() ) ) + ? oPam->GetPoint()->GetContentIndex() == oPam->GetPointContentNode()->Len() + : !oPam->GetPoint()->GetContentIndex() ) ) { - if( !(*fnMove.fnNds)( &pPam->GetPoint()->nNode, false )) + if( !(*fnMove.fnPos)( oPam->GetPoint(), false )) { return false; } - SwContentNode *pNd = pPam->GetContentNode(); - pPam->GetPoint()->nContent.Assign( pNd, bSrchForward ? 0 : pNd->Len() ); + SwContentNode *pNd = oPam->GetPointContentNode(); + oPam->GetPoint()->SetContent( bSrchForward ? 0 : pNd->Len() ); } - while (nullptr != (pNode = ::GetNode(*pPam, bFirst, fnMove, bInReadOnly, pLayout))) + while (nullptr != (pNode = ::GetNode(*oPam, bFirst, fnMove, bInReadOnly, pLayout))) { SwTextFrame const*const pFrame(pLayout && pNode->IsTextNode() ? static_cast<SwTextFrame const*>(pNode->getLayoutFrame(pLayout)) @@ -1101,20 +1101,20 @@ static bool FindAttrsImpl(SwPaM & rSearchPam, sw::MergedPara const*const pMergedPara(pFrame ? pFrame->GetMergedPara() : nullptr); if (pMergedPara) { - SwPosition const& rStart(*pPam->Start()); - SwPosition const& rEnd(*pPam->End()); + SwPosition const& rStart(*oPam->Start()); + SwPosition const& rEnd(*oPam->End()); // no extents? fall back to searching index 0 of propsnode // to find its node items if (pMergedPara->extents.empty()) { - if (rStart.nNode.GetIndex() <= rPropsNode.GetIndex() - && rPropsNode.GetIndex() <= rEnd.nNode.GetIndex()) + if (rStart.GetNodeIndex() <= rPropsNode.GetIndex() + && rPropsNode.GetIndex() <= rEnd.GetNodeIndex()) { SwPaM tmp(rPropsNode, 0, rPropsNode, 0); bFound = (*fnSearch)(*pNode->GetTextNode(), aCmpArr, tmp); if (bFound) { - *pPam = tmp; + *oPam = tmp; } } } @@ -1128,20 +1128,20 @@ static bool FindAttrsImpl(SwPaM & rSearchPam, auto const rExtent(pMergedPara->extents[bSrchForward ? i : pMergedPara->extents.size() - i - 1]); - if (rExtent.pNode->GetIndex() < rStart.nNode.GetIndex() - || rEnd.nNode.GetIndex() < rExtent.pNode->GetIndex()) + if (rExtent.pNode->GetIndex() < rStart.GetNodeIndex() + || rEnd.GetNodeIndex() < rExtent.pNode->GetIndex()) { continue; } - sal_Int32 const nStart(rExtent.pNode == &rStart.nNode.GetNode() - ? rStart.nContent.GetIndex() + sal_Int32 const nStart(rExtent.pNode == &rStart.GetNode() + ? rStart.GetContentIndex() : 0); if (rExtent.nEnd <= nStart) { continue; } - sal_Int32 const nEnd(rExtent.pNode == &rEnd.nNode.GetNode() - ? rEnd.nContent.GetIndex() + sal_Int32 const nEnd(rExtent.pNode == &rEnd.GetNode() + ? rEnd.GetContentIndex() : rExtent.pNode->Len()); if (nEnd < rExtent.nStart || (nStart != nEnd && nEnd == rExtent.nStart)) @@ -1154,7 +1154,7 @@ static bool FindAttrsImpl(SwPaM & rSearchPam, bFound = (*fnSearch)(*rExtent.pNode, aCmpArr, tmp); if (bFound) { - *pPam = tmp; + *oPam = tmp; break; } } @@ -1162,14 +1162,14 @@ static bool FindAttrsImpl(SwPaM & rSearchPam, } else { - bFound = (*fnSearch)(*pNode->GetTextNode(), aCmpArr, *pPam); + bFound = (*fnSearch)(*pNode->GetTextNode(), aCmpArr, *oPam); } if (bFound) { // set to the values of the attribute rSearchPam.SetMark(); - *rSearchPam.GetPoint() = *pPam->GetPoint(); - *rSearchPam.GetMark() = *pPam->GetMark(); + *rSearchPam.GetPoint() = *oPam->GetPoint(); + *rSearchPam.GetMark() = *oPam->GetMark(); break; } continue; // text attribute @@ -1193,22 +1193,22 @@ static bool FindAttrsImpl(SwPaM & rSearchPam, // BACKWARD: SPoint at the beginning, GetMark at the end of the node if (pFrame) { - *rSearchPam.GetPoint() = *pPam->GetPoint(); + *rSearchPam.GetPoint() = *oPam->GetPoint(); rSearchPam.SetMark(); *rSearchPam.GetMark() = pFrame->MapViewToModelPos( TextFrameIndex(bSrchForward ? pFrame->GetText().getLength() : 0)); } else { - *rSearchPam.GetPoint() = *pPam->GetPoint(); + *rSearchPam.GetPoint() = *oPam->GetPoint(); rSearchPam.SetMark(); if (bSrchForward) { - pNode->MakeEndIndex( &rSearchPam.GetPoint()->nContent ); + rSearchPam.GetPoint()->SetContent(pNode->Len()); } else { - pNode->MakeStartIndex( &rSearchPam.GetPoint()->nContent ); + rSearchPam.GetPoint()->SetContent(0); } } bFound = true; @@ -1328,8 +1328,8 @@ int SwFindParaAttr::DoFind(SwPaM & rCursor, SwMoveFnCollection const & fnMove, { const bool bRegExp( SearchAlgorithms2::REGEXP == pSearchOpt->AlgorithmType2); - SwIndex& rSttCntIdx = rCursor.Start()->nContent; - const sal_Int32 nSttCnt = rSttCntIdx.GetIndex(); + SwPosition& rSttCntPos = *rCursor.Start(); + const sal_Int32 nSttCnt = rSttCntPos.GetContentIndex(); // add to shell-cursor-ring so that the regions will be moved eventually SwPaM* pPrevRing(nullptr); @@ -1359,7 +1359,7 @@ int SwFindParaAttr::DoFind(SwPaM & rCursor, SwMoveFnCollection const & fnMove, p->MoveTo(const_cast<SwPaM*>(&rRegion)); } while( p != pPrevRing ); } - rSttCntIdx = nSttCnt; + rSttCntPos.SetContent(nSttCnt); } if( bReplaceAttr ) @@ -1384,7 +1384,7 @@ int SwFindParaAttr::DoFind(SwPaM & rCursor, SwMoveFnCollection const & fnMove, // reset all that are not set with pool defaults if( !IsInvalidItem( pItem ) && SfxItemState::SET != pReplSet->GetItemState( pItem->Which(), false )) - aSet.Put( pPool->GetDefaultItem( pItem->Which() )); + aSet.Put( pPool->GetUserOrPoolDefaultItem( pItem->Which() )); pItem = aIter.NextItem(); } while (pItem); @@ -1406,7 +1406,7 @@ bool SwFindParaAttr::IsReplaceMode() const } /// search for attributes -sal_uLong SwCursor::FindAttrs( const SfxItemSet& rSet, bool bNoCollections, +sal_Int32 SwCursor::FindAttrs( const SfxItemSet& rSet, bool bNoCollections, SwDocPositions nStart, SwDocPositions nEnd, bool& bCancel, FindRanges eFndRngs, const i18nutil::SearchOptions2* pSearchOpt, @@ -1430,7 +1430,7 @@ sal_uLong SwCursor::FindAttrs( const SfxItemSet& rSet, bool bNoCollections, SwFindParaAttr aSwFindParaAttr( rSet, bNoCollections, pSearchOpt, pReplSet, *this, pLayout ); - sal_uLong nRet = FindAll( aSwFindParaAttr, nStart, nEnd, eFndRngs, bCancel ); + sal_Int32 nRet = FindAll( aSwFindParaAttr, nStart, nEnd, eFndRngs, bCancel ); rDoc.SetOle2Link( aLnk ); if( nRet && bReplace ) rDoc.getIDocumentState().SetModified(); diff --git a/sw/source/core/crsr/findcoll.cxx b/sw/source/core/crsr/findcoll.cxx index ad43b7afec44..31a64aa3313f 100644 --- a/sw/source/core/crsr/findcoll.cxx +++ b/sw/source/core/crsr/findcoll.cxx @@ -72,7 +72,7 @@ bool SwFindParaFormatColl::IsReplaceMode() const } /// search for Format-Collections -sal_uLong SwCursor::FindFormat( const SwTextFormatColl& rFormatColl, SwDocPositions nStart, +sal_Int32 SwCursor::FindFormat( const SwTextFormatColl& rFormatColl, SwDocPositions nStart, SwDocPositions nEnd, bool& bCancel, FindRanges eFndRngs, const SwTextFormatColl* pReplFormatColl, SwRootFrame const*const pLayout) @@ -97,7 +97,7 @@ sal_uLong SwCursor::FindFormat( const SwTextFormatColl& rFormatColl, SwDocPositi SwFindParaFormatColl aSwFindParaFormatColl(rFormatColl, pReplFormatColl, pLayout); - sal_uLong nRet = FindAll( aSwFindParaFormatColl, nStart, nEnd, eFndRngs, bCancel ); + sal_Int32 nRet = FindAll( aSwFindParaFormatColl, nStart, nEnd, eFndRngs, bCancel ); rDoc.SetOle2Link( aLnk ); if( nRet && pReplFormatColl ) diff --git a/sw/source/core/crsr/findfmt.cxx b/sw/source/core/crsr/findfmt.cxx index a04850284433..ba8ab8382804 100644 --- a/sw/source/core/crsr/findfmt.cxx +++ b/sw/source/core/crsr/findfmt.cxx @@ -32,24 +32,25 @@ bool FindFormatImpl(SwPaM & rSearchPam, { bool bFound = false; const bool bSrchForward = &fnMove == &fnMoveForward; - std::unique_ptr<SwPaM> pPam(MakeRegion( fnMove, rRegion )); + std::optional<SwPaM> oPam; + MakeRegion( fnMove, rRegion, oPam ); // if at beginning/end then move it out of the node if( bSrchForward - ? pPam->GetPoint()->nContent.GetIndex() == pPam->GetContentNode()->Len() - : !pPam->GetPoint()->nContent.GetIndex() ) + ? oPam->GetPoint()->GetContentIndex() == oPam->GetPointContentNode()->Len() + : !oPam->GetPoint()->GetContentIndex() ) { - if( !(*fnMove.fnNds)( &pPam->GetPoint()->nNode, false )) + if( !(*fnMove.fnPos)( oPam->GetPoint(), false )) { return false; } - SwContentNode *pNd = pPam->GetPoint()->nNode.GetNode().GetContentNode(); - pPam->GetPoint()->nContent.Assign( pNd, bSrchForward ? 0 : pNd->Len() ); + SwContentNode *pNd = oPam->GetPoint()->GetNode().GetContentNode(); + oPam->GetPoint()->SetContent( bSrchForward ? 0 : pNd->Len() ); } bool bFirst = true; SwContentNode* pNode; - while (nullptr != (pNode = ::GetNode(*pPam, bFirst, fnMove, bInReadOnly, pLayout))) + while (nullptr != (pNode = ::GetNode(*oPam, bFirst, fnMove, bInReadOnly, pLayout))) { SwTextFrame const*const pFrame(pLayout && pNode->IsTextNode() ? static_cast<SwTextFrame const*>(pNode->getLayoutFrame(pLayout)) @@ -68,17 +69,17 @@ bool FindFormatImpl(SwPaM & rSearchPam, // always: incl. start and incl. end if (pFrame) { - *rSearchPam.GetPoint() = *pPam->GetPoint(); + *rSearchPam.GetPoint() = *oPam->GetPoint(); rSearchPam.SetMark(); *rSearchPam.GetMark() = pFrame->MapViewToModelPos( TextFrameIndex(bSrchForward ? pFrame->GetText().getLength() : 0)); } else { - *rSearchPam.GetPoint() = *pPam->GetPoint(); + *rSearchPam.GetPoint() = *oPam->GetPoint(); rSearchPam.SetMark(); - pNode->MakeEndIndex( &rSearchPam.GetPoint()->nContent ); - rSearchPam.GetMark()->nContent = 0; + rSearchPam.GetPoint()->SetContent(pNode->Len()); + rSearchPam.GetMark()->SetContent(0); } // if backward search, switch point and mark diff --git a/sw/source/core/crsr/findtxt.cxx b/sw/source/core/crsr/findtxt.cxx index ccb3a650c86f..07a19bde59b7 100644 --- a/sw/source/core/crsr/findtxt.cxx +++ b/sw/source/core/crsr/findtxt.cxx @@ -153,11 +153,7 @@ public: { if (pFrame) { -#if BOOST_VERSION < 105600 - m_oMergedIter.reset(*pFrame); -#else m_oMergedIter.emplace(*pFrame); -#endif } } @@ -275,7 +271,6 @@ lcl_CleanStr(const SwTextNode& rNd, switch (pNextHint->Which()) { case RES_TXTATR_FLYCNT: - case RES_TXTATR_FTN: case RES_TXTATR_FIELD: case RES_TXTATR_REFMARK: case RES_TXTATR_TOXMARK: @@ -366,7 +361,7 @@ static bool DoSearch(SwPaM & rSearchPam, bool bSrchForward, bool bRegSearch, bool bChkEmptyPara, bool bChkParaEnd, AmbiguousIndex & nStart, AmbiguousIndex & nEnd, AmbiguousIndex nTextLen, SwTextNode const* pNode, SwTextFrame const* pTextFrame, - SwRootFrame const* pLayout, SwPaM* pPam); + SwRootFrame const* pLayout, SwPaM& rPam); namespace sw { @@ -381,10 +376,10 @@ bool FindTextImpl(SwPaM & rSearchPam, if( rSearchOpt.searchString.isEmpty() ) return false; - std::unique_ptr<SwPaM> pPam = sw::MakeRegion(fnMove, rRegion); + std::optional<SwPaM> oPam; + sw::MakeRegion(fnMove, rRegion, oPam); const bool bSrchForward = &fnMove == &fnMoveForward; - SwNodeIndex& rNdIdx = pPam->GetPoint()->nNode; - SwIndex& rContentIdx = pPam->GetPoint()->nContent; + SwPosition& rPtPos = *oPam->GetPoint(); // If bFound is true then the string was found and is between nStart and nEnd bool bFound = false; @@ -406,325 +401,317 @@ bool FindTextImpl(SwPaM & rSearchPam, } // LanguageType eLastLang = 0; - while (nullptr != (pNode = ::GetNode(*pPam, bFirst, fnMove, bInReadOnly, pLayout))) + while (nullptr != (pNode = ::GetNode(*oPam, bFirst, fnMove, bInReadOnly, pLayout))) { - if( pNode->IsTextNode() ) + if (!pNode->IsTextNode()) + continue; + + const SwTextNode& rTextNode = *pNode->GetTextNode(); + SwTextFrame const* const pFrame( + pLayout ? static_cast<SwTextFrame const*>(rTextNode.getLayoutFrame(pLayout)) : nullptr); + assert(!pLayout || pFrame); + AmbiguousIndex nTextLen; + if (pLayout) + { + nTextLen.SetFrameIndex(TextFrameIndex(pFrame->GetText().getLength())); + } + else + { + nTextLen.SetModelIndex(rTextNode.GetText().getLength()); + } + AmbiguousIndex nEnd; + if (pLayout ? FrameContainsNode(*pFrame, oPam->GetMark()->GetNodeIndex()) + : rPtPos.GetNode() == oPam->GetMark()->GetNode()) { - SwTextNode& rTextNode = *pNode->GetTextNode(); - SwTextFrame const*const pFrame(pLayout - ? static_cast<SwTextFrame const*>(rTextNode.getLayoutFrame(pLayout)) - : nullptr); - assert(!pLayout || pFrame); - AmbiguousIndex nTextLen; if (pLayout) { - nTextLen.SetFrameIndex(TextFrameIndex(pFrame->GetText().getLength())); + nEnd.SetFrameIndex(pFrame->MapModelToViewPos(*oPam->GetMark())); } else { - nTextLen.SetModelIndex(rTextNode.GetText().getLength()); + nEnd.SetModelIndex(oPam->GetMark()->GetContentIndex()); + } + } + else + { + if (bSrchForward) + { + nEnd = nTextLen; } - AmbiguousIndex nEnd; - if (pLayout - ? FrameContainsNode(*pFrame, pPam->GetMark()->nNode.GetIndex()) - : rNdIdx == pPam->GetMark()->nNode) + else { if (pLayout) { - nEnd.SetFrameIndex(pFrame->MapModelToViewPos(*pPam->GetMark())); + nEnd.SetFrameIndex(TextFrameIndex(0)); } else { - nEnd.SetModelIndex(pPam->GetMark()->nContent.GetIndex()); + nEnd.SetModelIndex(0); } } - else + } + AmbiguousIndex nStart; + if (pLayout) + { + nStart.SetFrameIndex(pFrame->MapModelToViewPos(*oPam->GetPoint())); + } + else + { + nStart.SetModelIndex(rPtPos.GetContentIndex()); + } + + /* #i80135# */ + // if there are SwPostItFields inside our current node text, we + // split the text into separate pieces and search for text inside + // the pieces as well as inside the fields + MaybeMergedIter iter(pLayout ? pFrame : nullptr, pLayout ? nullptr : &rTextNode); + + // count PostItFields by looping over all fields + std::vector<std::pair<SwTextAttr const*, AmbiguousIndex>> postits; + if (bSearchInNotes) + { + if (!bSrchForward) { - if (bSrchForward) - { - nEnd = nTextLen; - } - else + std::swap(nStart, nEnd); + } + + SwTextNode const* pTemp(nullptr); + while (SwTextAttr const* const pTextAttr = iter.NextAttr(pTemp)) + { + if (pTextAttr->Which() == RES_TXTATR_ANNOTATION) { + AmbiguousIndex aPos; + aPos.SetModelIndex(pTextAttr->GetStart()); if (pLayout) { - nEnd.SetFrameIndex(TextFrameIndex(0)); + aPos.SetFrameIndex(pFrame->MapModelToView(pTemp, aPos.GetModelIndex())); } - else + if ((nStart <= aPos) && (aPos <= nEnd)) { - nEnd.SetModelIndex(0); + postits.emplace_back(pTextAttr, aPos); } } } - AmbiguousIndex nStart; - if (pLayout) - { - nStart.SetFrameIndex(pFrame->MapModelToViewPos(*pPam->GetPoint())); - } - else + + if (!bSrchForward) { - nStart.SetModelIndex(rContentIdx.GetIndex()); + std::swap(nStart, nEnd); } + } - /* #i80135# */ - // if there are SwPostItFields inside our current node text, we - // split the text into separate pieces and search for text inside - // the pieces as well as inside the fields - MaybeMergedIter iter(pLayout ? pFrame : nullptr, pLayout ? nullptr : &rTextNode); + SwDocShell* const pDocShell = pNode->GetDoc().GetDocShell(); + SwWrtShell* const pWrtShell = pDocShell ? pDocShell->GetWrtShell() : nullptr; + SwPostItMgr* const pPostItMgr = pWrtShell ? pWrtShell->GetPostItMgr() : nullptr; - // count PostItFields by looping over all fields - std::vector<std::pair<SwTextAttr const*, AmbiguousIndex>> postits; - if (bSearchInNotes) + // If there is an active text edit, then search there. + bool bEndedTextEdit = false; + SdrView* pSdrView = pWrtShell ? pWrtShell->GetDrawView() : nullptr; + if (pSdrView) + { + // If the edited object is not anchored to this node, then ignore it. + SdrObject* pObject = pSdrView->GetTextEditObject(); + if (pObject) { - if (!bSrchForward) + if (SwFrameFormat* pFrameFormat = FindFrameFormat(pObject)) { - std::swap(nStart, nEnd); + const SwNode* pAnchorNode = pFrameFormat->GetAnchor().GetAnchorNode(); + if (!pAnchorNode + || (pLayout ? !FrameContainsNode(*pFrame, pAnchorNode->GetIndex()) + : pAnchorNode->GetIndex() != pNode->GetIndex())) + pObject = nullptr; } + } - SwTextNode const* pTemp(nullptr); - while (SwTextAttr const*const pTextAttr = iter.NextAttr(pTemp)) + if (pObject) + { + sal_uInt16 nResult + = pSdrView->GetTextEditOutlinerView()->StartSearchAndReplace(*xSearchItem); + if (!nResult) { - if ( pTextAttr->Which()==RES_TXTATR_ANNOTATION ) - { - AmbiguousIndex aPos; - aPos.SetModelIndex(pTextAttr->GetStart()); - if (pLayout) - { - aPos.SetFrameIndex(pFrame->MapModelToView(pTemp, aPos.GetModelIndex())); - } - if ((nStart <= aPos) && (aPos <= nEnd)) - { - postits.emplace_back(pTextAttr, aPos); - } - } + // If not found, end the text edit. + pSdrView->SdrEndTextEdit(); + const Point aPoint(pSdrView->GetAllMarkedRect().TopLeft()); + pSdrView->UnmarkAll(); + pWrtShell->CallSetCursor(&aPoint, true); + pWrtShell->Edit(); + bEndedTextEdit = true; } - - if (!bSrchForward) + else { - std::swap(nStart, nEnd); + bFound = true; + break; } - } + } - SwDocShell *const pDocShell = pNode->GetDoc().GetDocShell(); - SwWrtShell *const pWrtShell = pDocShell ? pDocShell->GetWrtShell() : nullptr; - SwPostItMgr *const pPostItMgr = pWrtShell ? pWrtShell->GetPostItMgr() : nullptr; - - // If there is an active text edit, then search there. - bool bEndedTextEdit = false; - SdrView* pSdrView = pWrtShell ? pWrtShell->GetDrawView() : nullptr; - if (pSdrView) + if (comphelper::LibreOfficeKit::isActive()) + { + // Writer and editeng selections are not supported in parallel. + SvxSearchItem* pSearchItem = SwView::GetSearchItem(); + // If we just finished search in shape text, don't attempt to do that again. + if (!bEndedTextEdit + && !(pSearchItem && pSearchItem->GetCommand() == SvxSearchCmd::FIND_ALL)) { - // If the edited object is not anchored to this node, then ignore it. - SdrObject* pObject = pSdrView->GetTextEditObject(); - if (pObject) + // If there are any shapes anchored to this node, search there. + SwPaM aPaM(pNode->GetDoc().GetNodes().GetEndOfContent()); + if (pLayout) { - if (SwFrameFormat* pFrameFormat = FindFrameFormat(pObject)) - { - const SwPosition* pPosition = pFrameFormat->GetAnchor().GetContentAnchor(); - if (!pPosition || (pLayout - ? !FrameContainsNode(*pFrame, pPosition->nNode.GetIndex()) - : pPosition->nNode.GetIndex() != pNode->GetIndex())) - pObject = nullptr; - } + *aPaM.GetPoint() = pFrame->MapViewToModelPos(nStart.GetFrameIndex()); } - - if (pObject) + else { - sal_uInt16 nResult = pSdrView->GetTextEditOutlinerView()->StartSearchAndReplace(*xSearchItem); - if (!nResult) - { - // If not found, end the text edit. - pSdrView->SdrEndTextEdit(); - const Point aPoint(pSdrView->GetAllMarkedRect().TopLeft()); - pSdrView->UnmarkAll(); - pWrtShell->CallSetCursor(&aPoint, true); - pWrtShell->Edit(); - bEndedTextEdit = true; - } - else - { - bFound = true; - break; - } + aPaM.GetPoint()->Assign(rTextNode, nStart.GetModelIndex()); } - } - - if (comphelper::LibreOfficeKit::isActive()) - { - // Writer and editeng selections are not supported in parallel. - SvxSearchItem* pSearchItem = SwView::GetSearchItem(); - // If we just finished search in shape text, don't attempt to do that again. - if (!bEndedTextEdit && !(pSearchItem && pSearchItem->GetCommand() == SvxSearchCmd::FIND_ALL)) + aPaM.SetMark(); + if (pLayout) { - // If there are any shapes anchored to this node, search there. - SwPaM aPaM(pNode->GetDoc().GetNodes().GetEndOfContent()); - if (pLayout) - { - *aPaM.GetPoint() = pFrame->MapViewToModelPos(nStart.GetFrameIndex()); - } - else - { - aPaM.GetPoint()->nNode = rTextNode; - aPaM.GetPoint()->nContent.Assign( - aPaM.GetPoint()->nNode.GetNode().GetTextNode(), - nStart.GetModelIndex()); - } - aPaM.SetMark(); - if (pLayout) - { - aPaM.GetMark()->nNode = (pFrame->GetMergedPara() - ? *pFrame->GetMergedPara()->pLastNode - : rTextNode) - .GetIndex() + 1; - } - else - { - aPaM.GetMark()->nNode = rTextNode.GetIndex() + 1; - } - aPaM.GetMark()->nContent.Assign(aPaM.GetMark()->nNode.GetNode().GetTextNode(), 0); - if (pNode->GetDoc().getIDocumentDrawModelAccess().Search(aPaM, *xSearchItem) && pSdrView) + aPaM.GetMark()->Assign( + (pFrame->GetMergedPara() ? *pFrame->GetMergedPara()->pLastNode : rTextNode) + .GetIndex() + + 1); + } + else + { + aPaM.GetMark()->Assign(rTextNode.GetIndex() + 1); + } + if (pNode->GetDoc().getIDocumentDrawModelAccess().Search(aPaM, *xSearchItem) + && pSdrView) + { + if (SdrObject* pObject = pSdrView->GetTextEditObject()) { - if (SdrObject* pObject = pSdrView->GetTextEditObject()) + if (SwFrameFormat* pFrameFormat = FindFrameFormat(pObject)) { - if (SwFrameFormat* pFrameFormat = FindFrameFormat(pObject)) + const SwNode* pAnchorNode = pFrameFormat->GetAnchor().GetAnchorNode(); + if (pAnchorNode) { - const SwPosition* pPosition = pFrameFormat->GetAnchor().GetContentAnchor(); - if (pPosition) - { - // Set search position to the shape's anchor point. - *rSearchPam.GetPoint() = *pPosition; - rSearchPam.GetPoint()->nContent.Assign(pPosition->nNode.GetNode().GetContentNode(), 0); - rSearchPam.SetMark(); - bFound = true; - break; - } + // Set search position to the shape's anchor point. + rSearchPam.GetPoint()->Assign(*pAnchorNode); + rSearchPam.SetMark(); + bFound = true; + break; } } } } } + } - // do we need to finish a note? - if (pPostItMgr && pPostItMgr->HasActiveSidebarWin()) + // do we need to finish a note? + if (pPostItMgr && pPostItMgr->HasActiveSidebarWin()) + { + if (bSearchInNotes) { - if (bSearchInNotes) + if (!postits.empty()) { - if (!postits.empty()) + if (bSrchForward) { - if (bSrchForward) - { - postits.erase(postits.begin()); - } - else - { - postits.pop_back(); // hope that's the right one? - } + postits.erase(postits.begin()); } - //search inside, finish and put focus back into the doc - if (pPostItMgr->FinishSearchReplace(rSearchOpt,bSrchForward)) + else { - bFound = true ; - break; + postits.pop_back(); // hope that's the right one? } } - else + //search inside, finish and put focus back into the doc + if (pPostItMgr->FinishSearchReplace(rSearchOpt, bSrchForward)) { - pPostItMgr->SetActiveSidebarWin(nullptr); + bFound = true; + break; } } - - if (!postits.empty()) + else { - // now we have to split - AmbiguousIndex nStartInside; - AmbiguousIndex nEndInside; - sal_Int32 aLoop = bSrchForward ? 0 : postits.size(); + pPostItMgr->SetActiveSidebarWin(nullptr); + } + } - while ((0 <= aLoop) && (o3tl::make_unsigned(aLoop) <= postits.size())) + if (!postits.empty()) + { + // now we have to split + AmbiguousIndex nStartInside; + AmbiguousIndex nEndInside; + sal_Int32 aLoop = bSrchForward ? 0 : postits.size(); + + while ((0 <= aLoop) && (o3tl::make_unsigned(aLoop) <= postits.size())) + { + if (bSrchForward) { - if (bSrchForward) + if (aLoop == 0) { - if (aLoop == 0) - { - nStartInside = nStart; - } - else if (pLayout) - { - nStartInside.SetFrameIndex(postits[aLoop - 1].second.GetFrameIndex() + TextFrameIndex(1)); - } - else - { - nStartInside.SetModelIndex(postits[aLoop - 1].second.GetModelIndex() + 1); - } - nEndInside = static_cast<size_t>(aLoop) == postits.size() - ? nEnd - : postits[aLoop].second; - nTextLen = nEndInside - nStartInside; + nStartInside = nStart; + } + else if (pLayout) + { + nStartInside.SetFrameIndex(postits[aLoop - 1].second.GetFrameIndex() + + TextFrameIndex(1)); } else { - nStartInside = static_cast<size_t>(aLoop) == postits.size() - ? nStart - : postits[aLoop].second; - if (aLoop == 0) - { - nEndInside = nEnd; - } - else if (pLayout) - { - nEndInside.SetFrameIndex(postits[aLoop - 1].second.GetFrameIndex() + TextFrameIndex(1)); - } - else - { - nEndInside.SetModelIndex(postits[aLoop - 1].second.GetModelIndex() + 1); - } - nTextLen = nStartInside - nEndInside; + nStartInside.SetModelIndex(postits[aLoop - 1].second.GetModelIndex() + 1); + } + nEndInside = static_cast<size_t>(aLoop) == postits.size() + ? nEnd + : postits[aLoop].second; + nTextLen = nEndInside - nStartInside; + } + else + { + nStartInside = static_cast<size_t>(aLoop) == postits.size() + ? nStart + : postits[aLoop].second; + if (aLoop == 0) + { + nEndInside = nEnd; + } + else if (pLayout) + { + nEndInside.SetFrameIndex(postits[aLoop - 1].second.GetFrameIndex() + + TextFrameIndex(1)); } - // search inside the text between a note - bFound = DoSearch( rSearchPam, - rSearchOpt, rSText, fnMove, bSrchForward, - bRegSearch, bChkEmptyPara, bChkParaEnd, - nStartInside, nEndInside, nTextLen, - pNode->GetTextNode(), pFrame, pLayout, - pPam.get() ); - if ( bFound ) - break; else { - // we should now be right in front of a note, search inside - if (bSrchForward - ? (static_cast<size_t>(aLoop) != postits.size()) - : (aLoop != 0)) + nEndInside.SetModelIndex(postits[aLoop - 1].second.GetModelIndex() + 1); + } + nTextLen = nStartInside - nEndInside; + } + // search inside the text between a note + bFound = DoSearch(rSearchPam, rSearchOpt, rSText, fnMove, bSrchForward, bRegSearch, + bChkEmptyPara, bChkParaEnd, nStartInside, nEndInside, nTextLen, + pNode->GetTextNode(), pFrame, pLayout, *oPam); + if (bFound) + break; + else + { + // we should now be right in front of a note, search inside + if (bSrchForward ? (static_cast<size_t>(aLoop) != postits.size()) + : (aLoop != 0)) + { + const SwTextAttr* const pTextAttr + = bSrchForward ? postits[aLoop].first : postits[aLoop - 1].first; + if (pPostItMgr + && pPostItMgr->SearchReplace( + static_txtattr_cast<SwTextField const*>(pTextAttr) + ->GetFormatField(), + rSearchOpt, bSrchForward)) { - const SwTextAttr *const pTextAttr = bSrchForward - ? postits[aLoop].first - : postits[aLoop - 1].first; - if (pPostItMgr && pPostItMgr->SearchReplace( - static_txtattr_cast<SwTextField const*>(pTextAttr)->GetFormatField(),rSearchOpt,bSrchForward)) - { - bFound = true ; - break; - } + bFound = true; + break; } } - aLoop = bSrchForward ? aLoop+1 : aLoop-1; } + aLoop = bSrchForward ? aLoop + 1 : aLoop - 1; } - else - { - // if there is no SwPostItField inside or searching inside notes - // is disabled, we search the whole length just like before - bFound = DoSearch( rSearchPam, - rSearchOpt, rSText, fnMove, bSrchForward, - bRegSearch, bChkEmptyPara, bChkParaEnd, - nStart, nEnd, nTextLen, - pNode->GetTextNode(), pFrame, pLayout, - pPam.get() ); - } - if (bFound) - break; } + else + { + // if there is no SwPostItField inside or searching inside notes + // is disabled, we search the whole length just like before + bFound = DoSearch(rSearchPam, rSearchOpt, rSText, fnMove, bSrchForward, bRegSearch, + bChkEmptyPara, bChkParaEnd, nStart, nEnd, nTextLen, + pNode->GetTextNode(), pFrame, pLayout, *oPam); + } + if (bFound) + break; } return bFound; } @@ -737,10 +724,28 @@ bool DoSearch(SwPaM & rSearchPam, bool bChkEmptyPara, bool bChkParaEnd, AmbiguousIndex & nStart, AmbiguousIndex & nEnd, AmbiguousIndex const nTextLen, SwTextNode const*const pNode, SwTextFrame const*const pFrame, - SwRootFrame const*const pLayout, SwPaM* pPam) + SwRootFrame const*const pLayout, SwPaM& rPam) { + if (bRegSearch && rSearchOpt.searchString.endsWith("$")) + { + bool bAlwaysSearchingForEndOfPara = true; + sal_Int32 nIndex = 0; + while ((nIndex = rSearchOpt.searchString.indexOf("|", nIndex)) != -1) + { + if (!nIndex || rSearchOpt.searchString[nIndex - 1] != '$') + { + bAlwaysSearchingForEndOfPara = false; + break; + } + ++nIndex; + } + // when searching for something at the end of the paragraph, the para end must be in range + const AmbiguousIndex& rParaEnd = bSrchForward ? nEnd : nStart; + if (bAlwaysSearchingForEndOfPara && nTextLen.GetAnyIndex() != rParaEnd.GetAnyIndex()) + return false; + } + bool bFound = false; - SwNodeIndex& rNdIdx = pPam->GetPoint()->nNode; OUString sCleanStr; std::vector<AmbiguousIndex> aFltArr; LanguageType eLastLang = LANGUAGE_SYSTEM; @@ -755,6 +760,7 @@ bool DoSearch(SwPaM & rSearchPam, if ( -1 != rSearchOpt.searchString.indexOf("\\xAD") || -1 != rSearchOpt.searchString.indexOf("\\x{00AD}") || -1 != rSearchOpt.searchString.indexOf("\\u00AD") + || -1 != rSearchOpt.searchString.indexOf("\\u00ad") || -1 != rSearchOpt.searchString.indexOf("\\U000000AD") || -1 != rSearchOpt.searchString.indexOf("\\N{SOFT HYPHEN}")) { @@ -812,7 +818,7 @@ bool DoSearch(SwPaM & rSearchPam, { const lang::Locale aLocale( g_pBreakIt->GetLocale( eCurrLang ) ); - rSText.SetLocale( utl::TextSearch::UpgradeToSearchOptions2( rSearchOpt), aLocale ); + rSText.SetLocale(rSearchOpt, aLocale); eLastLang = eCurrLang; } } @@ -827,7 +833,7 @@ bool DoSearch(SwPaM & rSearchPam, nStart = nProxyStart; nEnd = nProxyEnd; // set section correctly - *rSearchPam.GetPoint() = *pPam->GetPoint(); + *rSearchPam.GetPoint() = *rPam.GetPoint(); rSearchPam.SetMark(); // adjust start and end @@ -860,8 +866,8 @@ bool DoSearch(SwPaM & rSearchPam, } else { - rSearchPam.GetMark()->nContent = nStart.GetModelIndex(); - rSearchPam.GetPoint()->nContent = nEnd.GetModelIndex(); + rSearchPam.GetMark()->SetContent( nStart.GetModelIndex() ); + rSearchPam.GetPoint()->SetContent( nEnd.GetModelIndex() ); } // if backward search, switch point and mark @@ -881,39 +887,43 @@ bool DoSearch(SwPaM & rSearchPam, if ( bFound ) return true; - else if ((bChkEmptyPara && !nStart.GetAnyIndex() && !nTextLen.GetAnyIndex()) - || bChkParaEnd) + + if (!bChkEmptyPara && !bChkParaEnd) + return false; + + if (bChkEmptyPara && bSrchForward && nTextLen.GetAnyIndex()) + return false; // the length is not zero - there is content here + + // move to the end (or start) of the paragraph + *rSearchPam.GetPoint() = *rPam.GetPoint(); + if (pLayout) { - *rSearchPam.GetPoint() = *pPam->GetPoint(); - if (pLayout) - { - *rSearchPam.GetPoint() = pFrame->MapViewToModelPos( - bChkParaEnd ? nTextLen.GetFrameIndex() : TextFrameIndex(0)); - } - else - { - rSearchPam.GetPoint()->nContent = bChkParaEnd ? nTextLen.GetModelIndex() : 0; - } - rSearchPam.SetMark(); - const SwNode *const pSttNd = bSrchForward - ? &rSearchPam.GetPoint()->nNode.GetNode() // end of the frame - : &rNdIdx.GetNode(); // keep the bug as-is for now... - /* FIXME: this condition does not work for !bSrchForward backward - * search, it probably never did. (pSttNd != &rNdIdx.GetNode()) - * is never true in this case. */ - if( (bSrchForward || pSttNd != &rNdIdx.GetNode()) && - rSearchPam.Move(fnMoveForward, GoInContent) && - (!bSrchForward || pSttNd != &rSearchPam.GetPoint()->nNode.GetNode()) && - 1 == std::abs(static_cast<int>(rSearchPam.GetPoint()->nNode.GetIndex() - - rSearchPam.GetMark()->nNode.GetIndex()))) - { - // if backward search, switch point and mark - if( !bSrchForward ) - rSearchPam.Exchange(); - return true; - } + *rSearchPam.GetPoint() = pFrame->MapViewToModelPos( + bSrchForward ? nTextLen.GetFrameIndex() : TextFrameIndex(0)); } - return bFound; + else + { + rSearchPam.GetPoint()->SetContent(bSrchForward ? nTextLen.GetModelIndex() : 0); + } + rSearchPam.SetMark(); + + if (!rSearchPam.Move(fnMove, GoInContent)) + return false; // at start or end of the document + + // selection must not be outside of the search area + if (!rPam.ContainsPosition(*rSearchPam.GetPoint())) + return false; + + if (SwNodeOffset(1) == abs(rSearchPam.GetPoint()->GetNodeIndex() - + rSearchPam.GetMark()->GetNodeIndex())) + { + if (bChkEmptyPara && !bSrchForward && rSearchPam.GetPoint()->GetContentIndex()) + return false; // the length is not zero - there is content here + + return true; + } + + return false; } namespace { @@ -933,7 +943,7 @@ struct SwFindParaText : public SwFindParas : m_rSearchOpt( rOpt ) , m_rCursor( rCursor ) , m_pLayout(pLayout) - , m_aSText( utl::TextSearch::UpgradeToSearchOptions2(rOpt) ) + , m_aSText(rOpt) , m_bReplace( bRepl ) , m_bSearchInNotes( bSearchInNotes ) {} @@ -962,8 +972,7 @@ int SwFindParaText::DoFind(SwPaM & rCursor, SwMoveFnCollection const & fnMove, { // use replace method in SwDoc const bool bRegExp(SearchAlgorithms2::REGEXP == m_rSearchOpt.AlgorithmType2); - SwIndex& rSttCntIdx = rCursor.Start()->nContent; - const sal_Int32 nSttCnt = rSttCntIdx.GetIndex(); + const sal_Int32 nSttCnt = rCursor.Start()->GetContentIndex(); // add to shell-cursor-ring so that the regions will be moved eventually SwPaM* pPrev(nullptr); if( bRegExp ) @@ -1000,7 +1009,7 @@ int SwFindParaText::DoFind(SwPaM & rCursor, SwMoveFnCollection const & fnMove, assert(bRet); // if join failed, next node must be SwTextNode } else - rCursor.Start()->nContent = nSttCnt; + rCursor.Start()->SetContent(nSttCnt); return FIND_NO_RING; } return bFnd ? FIND_FOUND : FIND_NOT_FOUND; @@ -1011,7 +1020,7 @@ bool SwFindParaText::IsReplaceMode() const return m_bReplace; } -sal_uLong SwCursor::Find_Text( const i18nutil::SearchOptions2& rSearchOpt, bool bSearchInNotes, +sal_Int32 SwCursor::Find_Text( const i18nutil::SearchOptions2& rSearchOpt, bool bSearchInNotes, SwDocPositions nStart, SwDocPositions nEnd, bool& bCancel, FindRanges eFndRngs, bool bReplace, SwRootFrame const*const pLayout) @@ -1031,7 +1040,7 @@ sal_uLong SwCursor::Find_Text( const i18nutil::SearchOptions2& rSearchOpt, bool if( bSearchSel ) eFndRngs = static_cast<FindRanges>(eFndRngs | FindRanges::InSel); SwFindParaText aSwFindParaText(rSearchOpt, bSearchInNotes, bReplace, *this, pLayout); - sal_uLong nRet = FindAll( aSwFindParaText, nStart, nEnd, eFndRngs, bCancel ); + sal_Int32 nRet = FindAll( aSwFindParaText, nStart, nEnd, eFndRngs, bCancel ); rDoc.SetOle2Link( aLnk ); if( nRet && bReplace ) rDoc.getIDocumentState().SetModified(); @@ -1069,7 +1078,7 @@ bool ReplaceImpl( else { assert(!ranges.empty()); - assert(ranges.front()->GetPoint()->nNode == ranges.front()->GetMark()->nNode); + assert(ranges.front()->GetPoint()->GetNode() == ranges.front()->GetMark()->GetNode()); bReplaced = rIDCO.ReplaceRange(*ranges.front(), rReplacement, bRegExp); for (auto it = ranges.begin() + 1; it != ranges.end(); ++it) { @@ -1122,8 +1131,8 @@ std::optional<OUString> ReplaceBackReferences(const i18nutil::SearchOptions2& rS if( pPam && pPam->HasMark() && SearchAlgorithms2::REGEXP == rSearchOpt.AlgorithmType2 ) { - SwContentNode const*const pTextNode = pPam->GetContentNode(); - SwContentNode const*const pMarkTextNode = pPam->GetContentNode(false); + SwContentNode const*const pTextNode = pPam->GetPointContentNode(); + SwContentNode const*const pMarkTextNode = pPam->GetMarkContentNode(); if (!pTextNode || !pTextNode->IsTextNode() || !pMarkTextNode || !pMarkTextNode->IsTextNode()) { @@ -1134,28 +1143,23 @@ std::optional<OUString> ReplaceBackReferences(const i18nutil::SearchOptions2& rS : nullptr); const bool bParaEnd = rSearchOpt.searchString == "$" || rSearchOpt.searchString == "^$" || rSearchOpt.searchString == "$^"; if (bParaEnd || (pLayout - ? sw::FrameContainsNode(*pFrame, pPam->GetMark()->nNode.GetIndex()) + ? sw::FrameContainsNode(*pFrame, pPam->GetMark()->GetNodeIndex()) : pTextNode == pMarkTextNode)) { - utl::TextSearch aSText( utl::TextSearch::UpgradeToSearchOptions2( rSearchOpt) ); + utl::TextSearch aSText(rSearchOpt); SearchResult aResult; OUString aReplaceStr( rSearchOpt.replaceString ); if (bParaEnd) { - OUString const aStr("\\n"); + static constexpr OUString aStr(u"\\n"_ustr); aResult.subRegExpressions = 1; - aResult.startOffset.realloc(1); - aResult.endOffset.realloc(1); - aResult.startOffset[0] = 0; - aResult.endOffset[0] = aStr.getLength(); - aSText.ReplaceBackReferences( aReplaceStr, aStr, aResult ); + aResult.startOffset = { 0 }; + aResult.endOffset = { aStr.getLength() }; + utl::TextSearch::ReplaceBackReferences( aReplaceStr, aStr, aResult ); xRet = aReplaceStr; } else { - OUString const aStr(pLayout - ? pFrame->GetText() - : pTextNode->GetTextNode()->GetText()); AmbiguousIndex nStart; AmbiguousIndex nEnd; if (pLayout) @@ -1165,12 +1169,15 @@ std::optional<OUString> ReplaceBackReferences(const i18nutil::SearchOptions2& rS } else { - nStart.SetModelIndex(pPam->Start()->nContent.GetIndex()); - nEnd.SetModelIndex(pPam->End()->nContent.GetIndex()); + nStart.SetModelIndex(pPam->Start()->GetContentIndex()); + nEnd.SetModelIndex(pPam->End()->GetContentIndex()); } + std::vector<AmbiguousIndex> aFltArr; + OUString const aStr = lcl_CleanStr(*pTextNode->GetTextNode(), pFrame, pLayout, + nStart, nEnd, aFltArr, false, false); if (aSText.SearchForward(aStr, &nStart.GetAnyIndex(), &nEnd.GetAnyIndex(), &aResult)) { - aSText.ReplaceBackReferences( aReplaceStr, aStr, aResult ); + utl::TextSearch::ReplaceBackReferences( aReplaceStr, aStr, aResult ); xRet = aReplaceStr; } } diff --git a/sw/source/core/crsr/overlayrangesoutline.cxx b/sw/source/core/crsr/overlayrangesoutline.cxx index 1ec83370e544..265509a055ab 100644 --- a/sw/source/core/crsr/overlayrangesoutline.cxx +++ b/sw/source/core/crsr/overlayrangesoutline.cxx @@ -60,10 +60,10 @@ namespace sw::overlay if( nCount ) { const basegfx::BColor aRGBColor(getBaseColor().getBColor()); - const basegfx::B2DPolyPolygon aPolyPolygon(impCombineRangesToPolyPolygon(getRanges())); + basegfx::B2DPolyPolygon aPolyPolygon(impCombineRangesToPolyPolygon(getRanges())); const drawinglayer::primitive2d::Primitive2DReference aOutline( new drawinglayer::primitive2d::PolyPolygonHairlinePrimitive2D( - aPolyPolygon, + std::move(aPolyPolygon), aRGBColor)); aRetval.resize(1); @@ -75,9 +75,9 @@ namespace sw::overlay OverlayRangesOutline::OverlayRangesOutline( const Color& rColor, - const std::vector< basegfx::B2DRange >& rRanges ) + std::vector< basegfx::B2DRange >&& rRanges ) : sdr::overlay::OverlayObject(rColor) - , maRanges(rRanges) + , maRanges(std::move(rRanges)) { // no AA for highlight overlays allowAntiAliase(false); @@ -91,11 +91,11 @@ namespace sw::overlay } } - void OverlayRangesOutline::setRanges(const std::vector< basegfx::B2DRange >& rNew) + void OverlayRangesOutline::setRanges(std::vector< basegfx::B2DRange >&& rNew) { if(rNew != maRanges) { - maRanges = rNew; + maRanges = std::move(rNew); objectChange(); } } diff --git a/sw/source/core/crsr/overlayrangesoutline.hxx b/sw/source/core/crsr/overlayrangesoutline.hxx index ff1fd71b447b..2eb053c72132 100644 --- a/sw/source/core/crsr/overlayrangesoutline.hxx +++ b/sw/source/core/crsr/overlayrangesoutline.hxx @@ -37,7 +37,7 @@ namespace sw::overlay public: OverlayRangesOutline( const Color& rColor, - const std::vector< basegfx::B2DRange >& rRanges ); + std::vector< basegfx::B2DRange >&& rRanges ); virtual ~OverlayRangesOutline() override; @@ -48,7 +48,7 @@ namespace sw::overlay } // data write access - void setRanges(const std::vector< basegfx::B2DRange >& rNew); + void setRanges(std::vector< basegfx::B2DRange >&& rNew); }; } // end of namespace sw::overlay diff --git a/sw/source/core/crsr/pam.cxx b/sw/source/core/crsr/pam.cxx index f6e55168315a..6fc9c6f5d6b7 100644 --- a/sw/source/core/crsr/pam.cxx +++ b/sw/source/core/crsr/pam.cxx @@ -19,11 +19,10 @@ #include <sal/config.h> -#include <string_view> - #include <tools/gen.hxx> #include <editeng/protitem.hxx> #include <officecfg/Office/Common.hxx> +#include <unotools/configmgr.hxx> #include <cntfrm.hxx> #include <pagefrm.hxx> @@ -47,10 +46,12 @@ #include <hints.hxx> #include <txatbase.hxx> #include <osl/diagnose.h> +#include <utility> #include <xmloff/odffields.hxx> #include <rtl/ustrbuf.hxx> #include <editsh.hxx> +#include <textcontentcontrol.hxx> // for the dump "MSC-" compiler static sal_Int32 GetSttOrEnd( bool bCondition, const SwContentNode& rNd ) @@ -58,36 +59,75 @@ static sal_Int32 GetSttOrEnd( bool bCondition, const SwContentNode& rNd ) return bCondition ? 0 : rNd.Len(); } -SwPosition::SwPosition( const SwNodeIndex & rNodeIndex, const SwIndex & rContent ) +SwPosition::SwPosition( const SwNodeIndex & rNodeIndex, const SwContentIndex & rContent ) : nNode( rNodeIndex ), nContent( rContent ) { + assert((!rNodeIndex.GetNode().GetContentNode() || rNodeIndex.GetNode().GetContentNode() == rContent.GetContentNode()) + && "parameters point to different nodes"); +} + +SwPosition::SwPosition( const SwNode & rNode, const SwContentIndex & rContent ) + : nNode( rNode ), nContent( rContent ) +{ + assert((!rNode.GetContentNode() || rNode.GetContentNode() == rContent.GetContentNode()) + && "parameters point to different nodes"); } -SwPosition::SwPosition( const SwNodeIndex & rNodeIndex ) - : nNode( rNodeIndex ), nContent( nNode.GetNode().GetContentNode() ) +SwPosition::SwPosition( const SwNodeIndex & rNodeIndex, const SwContentNode* pContentNode, sal_Int32 nContentOffset ) + : nNode( rNodeIndex ), nContent( pContentNode, nContentOffset ) { + assert((!pContentNode || pContentNode == &rNodeIndex.GetNode()) && + "parameters point to different nodes"); } -SwPosition::SwPosition( const SwNode& rNode ) - : nNode( rNode ), nContent( nNode.GetNode().GetContentNode() ) +SwPosition::SwPosition( const SwNode & rNode, const SwContentNode* pContentNode, sal_Int32 nContentOffset ) + : nNode( rNode ), nContent( pContentNode, nContentOffset ) { + assert((!pContentNode || pContentNode == &rNode) && + "parameters point to different nodes"); } -SwPosition::SwPosition( SwContentNode & rNode, const sal_Int32 nOffset ) - : nNode( rNode ), nContent( &rNode, nOffset ) +SwPosition::SwPosition( const SwNodeIndex & rNodeIndex, SwNodeOffset nDiff, const SwContentNode* pContentNode, sal_Int32 nContentOffset ) + : nNode( rNodeIndex, nDiff ), nContent( pContentNode, nContentOffset ) +{ + assert((!pContentNode || pContentNode == &rNodeIndex.GetNode()) && + "parameters point to different nodes"); +} + +SwPosition::SwPosition( const SwNodeIndex & rNodeIndex, SwNodeOffset nDiff ) + : nNode( rNodeIndex, nDiff ), nContent( GetNode().GetContentNode() ) +{ +} + +SwPosition::SwPosition( const SwNode& rNode, SwNodeOffset nDiff ) + : nNode( rNode, nDiff ), nContent( GetNode().GetContentNode() ) +{ +} + +SwPosition::SwPosition( SwNodes& rNodes, SwNodeOffset nIndex ) + : nNode( rNodes, nIndex ), nContent( GetNode().GetContentNode() ) +{ +} + +SwPosition::SwPosition( const SwContentNode & rNode, const sal_Int32 nContentOffset ) + : nNode( rNode ), nContent( &rNode, nContentOffset ) +{ +} + +SwPosition::SwPosition( const SwContentIndex & rContentIndex, short nDiff ) + : nNode( *rContentIndex.GetContentNode() ), nContent( rContentIndex, nDiff ) { } bool SwPosition::operator<(const SwPosition &rPos) const { - if( nNode < rPos.nNode ) - return true; + // cheaper to check for == first if( nNode == rPos.nNode ) { - // note that positions with text node but no SwIndex registered are + // note that positions with text node but no SwContentIndex registered are // created for text frames anchored at para (see SwXFrame::getAnchor()) - SwIndexReg const*const pThisReg(nContent.GetIdxReg()); - SwIndexReg const*const pOtherReg(rPos.nContent.GetIdxReg()); + SwContentNode const*const pThisReg(GetContentNode()); + SwContentNode const*const pOtherReg(rPos.GetContentNode()); if (pThisReg && pOtherReg) { return (nContent < rPos.nContent); @@ -97,19 +137,18 @@ bool SwPosition::operator<(const SwPosition &rPos) const return pOtherReg != nullptr; } } - return false; + return nNode < rPos.nNode; } bool SwPosition::operator>(const SwPosition &rPos) const { - if(nNode > rPos.nNode ) - return true; + // cheaper to check for == first if( nNode == rPos.nNode ) { - // note that positions with text node but no SwIndex registered are + // note that positions with text node but no SwContentIndex registered are // created for text frames anchored at para (see SwXFrame::getAnchor()) - SwIndexReg const*const pThisReg(nContent.GetIdxReg()); - SwIndexReg const*const pOtherReg(rPos.nContent.GetIdxReg()); + SwContentNode const*const pThisReg(GetContentNode()); + SwContentNode const*const pOtherReg(rPos.GetContentNode()); if (pThisReg && pOtherReg) { return (nContent > rPos.nContent); @@ -119,19 +158,18 @@ bool SwPosition::operator>(const SwPosition &rPos) const return pThisReg != nullptr; } } - return false; + return nNode > rPos.nNode; } bool SwPosition::operator<=(const SwPosition &rPos) const { - if(nNode < rPos.nNode ) - return true; + // cheaper to check for == first if( nNode == rPos.nNode ) { - // note that positions with text node but no SwIndex registered are + // note that positions with text node but no SwContentIndex registered are // created for text frames anchored at para (see SwXFrame::getAnchor()) - SwIndexReg const*const pThisReg(nContent.GetIdxReg()); - SwIndexReg const*const pOtherReg(rPos.nContent.GetIdxReg()); + SwContentNode const*const pThisReg(GetContentNode()); + SwContentNode const*const pOtherReg(rPos.GetContentNode()); if (pThisReg && pOtherReg) { return (nContent <= rPos.nContent); @@ -141,19 +179,18 @@ bool SwPosition::operator<=(const SwPosition &rPos) const return pThisReg == nullptr; } } - return false; + return nNode < rPos.nNode; } bool SwPosition::operator>=(const SwPosition &rPos) const { - if(nNode > rPos.nNode ) - return true; + // cheaper to check for == first if( nNode == rPos.nNode ) { - // note that positions with text node but no SwIndex registered are + // note that positions with text node but no SwContentIndex registered are // created for text frames anchored at para (see SwXFrame::getAnchor()) - SwIndexReg const*const pThisReg(nContent.GetIdxReg()); - SwIndexReg const*const pOtherReg(rPos.nContent.GetIdxReg()); + SwContentNode const*const pThisReg(GetContentNode()); + SwContentNode const*const pOtherReg(rPos.GetContentNode()); if (pThisReg && pOtherReg) { return (nContent >= rPos.nContent); @@ -163,7 +200,7 @@ bool SwPosition::operator>=(const SwPosition &rPos) const return pOtherReg == nullptr; } } - return false; + return nNode > rPos.nNode; } bool SwPosition::operator==(const SwPosition &rPos) const @@ -180,20 +217,73 @@ bool SwPosition::operator!=(const SwPosition &rPos) const SwDoc& SwPosition::GetDoc() const { - return nNode.GetNode().GetDoc(); + return GetNode().GetDoc(); } void SwPosition::dumpAsXml(xmlTextWriterPtr pWriter) const { (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwPosition")); - (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("nNode"), BAD_CAST(OString::number(nNode.GetIndex()).getStr())); - (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("nContent"), BAD_CAST(OString::number(nContent.GetIndex()).getStr())); + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("nNode"), BAD_CAST(OString::number(sal_Int32(GetNodeIndex())).getStr())); + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("nContent"), BAD_CAST(OString::number(GetContentIndex()).getStr())); (void)xmlTextWriterEndElement(pWriter); } +void SwPosition::Assign( const SwNode& rNd, SwNodeOffset nDelta, sal_Int32 nContentOffset ) +{ + nNode.Assign(rNd, nDelta); + assert((nNode.GetNode().GetContentNode() || nContentOffset == 0) && "setting contentoffset, but node is not SwContentNode"); + nContent.Assign(nNode.GetNode().GetContentNode(), nContentOffset); +} +void SwPosition::Assign( SwNodeOffset nNodeOffset, sal_Int32 nContentOffset ) +{ + nNode = nNodeOffset; + nContent.Assign(nNode.GetNode().GetContentNode(), nContentOffset); +} +void SwPosition::Assign( const SwContentNode& rNode, sal_Int32 nContentOffset ) +{ + nNode = rNode; + nContent.Assign(&rNode, nContentOffset); +} +void SwPosition::Assign( const SwNode& rNd, sal_Int32 nContentOffset ) +{ + nNode.Assign(rNd); + nContent.Assign(rNd.GetContentNode(), nContentOffset); +} +void SwPosition::Assign( const SwNodeIndex& rNdIdx, sal_Int32 nContentOffset ) +{ + nNode = rNdIdx; + nContent.Assign(nNode.GetNode().GetContentNode(), nContentOffset); +} +void SwPosition::Adjust( SwNodeOffset nDelta ) +{ + nNode += nDelta; + nContent.Assign(nNode.GetNode().GetContentNode(), 0); +} +void SwPosition::AdjustContent( sal_Int32 nDelta ) +{ + assert(nNode.GetNode().GetContentNode() && "only valid to call this if we point to an SwContentNode"); + nContent += nDelta; +} +void SwPosition::SetContent( sal_Int32 nContentIndex ) +{ + assert(nNode.GetNode().GetContentNode() && "only valid to call this if we point to an SwContentNode"); + nContent = nContentIndex; +} +void SwPosition::AssignStartIndex( const SwContentNode& rNd ) +{ + nNode = rNd; + nContent.Assign(&rNd, 0); +} +void SwPosition::AssignEndIndex( const SwContentNode& rNd ) +{ + nNode = rNd; + nContent.Assign(&rNd, rNd.Len()); +} + + std::ostream &operator <<(std::ostream& s, const SwPosition& position) { - return s << "SwPosition (node " << position.nNode.GetIndex() << ", offset " << position.nContent.GetIndex() << ")"; + return s << "SwPosition (node " << position.GetNodeIndex() << ", offset " << position.GetContentIndex() << ")"; } namespace { @@ -202,9 +292,9 @@ enum CHKSECTION { Chk_Both, Chk_One, Chk_None }; } -static CHKSECTION lcl_TstIdx( sal_uLong nSttIdx, sal_uLong nEndIdx, const SwNode& rEndNd ) +static CHKSECTION lcl_TstIdx( SwNodeOffset nSttIdx, SwNodeOffset nEndIdx, const SwNode& rEndNd ) { - sal_uLong nStt = rEndNd.StartOfSectionIndex(), nEnd = rEndNd.GetIndex(); + SwNodeOffset nStt = rEndNd.StartOfSectionIndex(), nEnd = rEndNd.GetIndex(); CHKSECTION eSec = nStt < nSttIdx && nEnd >= nSttIdx ? Chk_One : Chk_None; if( nStt < nEndIdx && nEnd >= nEndIdx ) return( eSec == Chk_One ? Chk_Both : Chk_One ); @@ -212,7 +302,7 @@ static CHKSECTION lcl_TstIdx( sal_uLong nSttIdx, sal_uLong nEndIdx, const SwNode } static bool lcl_ChkOneRange( CHKSECTION eSec, bool bChkSections, - const SwNode& rBaseEnd, sal_uLong nStt, sal_uLong nEnd ) + const SwNode& rBaseEnd, SwNodeOffset nStt, SwNodeOffset nEnd ) { if( eSec != Chk_Both ) return false; @@ -241,7 +331,7 @@ static bool lcl_ChkOneRange( CHKSECTION eSec, bool bChkSections, pNd = pTmp; } - sal_uLong nSttIdx = pNd->GetIndex(), nEndIdx = pNd->EndOfSectionIndex(); + SwNodeOffset nSttIdx = pNd->GetIndex(), nEndIdx = pNd->EndOfSectionIndex(); return nSttIdx <= nStt && nStt <= nEndIdx && nSttIdx <= nEnd && nEnd <= nEndIdx; } @@ -256,11 +346,11 @@ static bool lcl_ChkOneRange( CHKSECTION eSec, bool bChkSections, * * @return <true> if valid range */ -bool CheckNodesRange( const SwNodeIndex& rStt, - const SwNodeIndex& rEnd, bool bChkSection ) +bool CheckNodesRange( const SwNode& rStt, + const SwNode& rEnd, bool bChkSection ) { const SwNodes& rNds = rStt.GetNodes(); - sal_uLong nStt = rStt.GetIndex(), nEnd = rEnd.GetIndex(); + SwNodeOffset nStt = rStt.GetIndex(), nEnd = rEnd.GetIndex(); CHKSECTION eSec = lcl_TstIdx( nStt, nEnd, rNds.GetEndOfContent() ); if( Chk_None != eSec ) return eSec == Chk_Both; @@ -288,14 +378,14 @@ bool CheckNodesRange( const SwNodeIndex& rStt, return false; // somewhere in between => error } -bool GoNext(SwNode* pNd, SwIndex * pIdx, sal_uInt16 nMode ) +bool GoNext(SwNode* pNd, SwContentIndex * pIdx, SwCursorSkipMode nMode ) { if( pNd->IsContentNode() ) return static_cast<SwContentNode*>(pNd)->GoNext( pIdx, nMode ); return false; } -bool GoPrevious( SwNode* pNd, SwIndex * pIdx, sal_uInt16 nMode ) +bool GoPrevious( SwNode* pNd, SwContentIndex * pIdx, SwCursorSkipMode nMode ) { if( pNd->IsContentNode() ) return static_cast<SwContentNode*>(pNd)->GoPrevious( pIdx, nMode ); @@ -305,11 +395,11 @@ bool GoPrevious( SwNode* pNd, SwIndex * pIdx, sal_uInt16 nMode ) SwContentNode* GoNextNds( SwNodeIndex* pIdx, bool bChk ) { SwNodeIndex aIdx( *pIdx ); - SwContentNode* pNd = aIdx.GetNodes().GoNext( &aIdx ); + SwContentNode* pNd = SwNodes::GoNext(&aIdx); if( pNd ) { - if( bChk && 1 != aIdx.GetIndex() - pIdx->GetIndex() && - !CheckNodesRange( *pIdx, aIdx, true ) ) + if( bChk && SwNodeOffset(1) != aIdx.GetIndex() - pIdx->GetIndex() && + !CheckNodesRange( pIdx->GetNode(), aIdx.GetNode(), true ) ) pNd = nullptr; else *pIdx = aIdx; @@ -323,8 +413,8 @@ SwContentNode* GoPreviousNds( SwNodeIndex * pIdx, bool bChk ) SwContentNode* pNd = SwNodes::GoPrevious( &aIdx ); if( pNd ) { - if( bChk && 1 != pIdx->GetIndex() - aIdx.GetIndex() && - !CheckNodesRange( *pIdx, aIdx, true ) ) + if( bChk && SwNodeOffset(1) != pIdx->GetIndex() - aIdx.GetIndex() && + !CheckNodesRange( pIdx->GetNode(), aIdx.GetNode(), true ) ) pNd = nullptr; else *pIdx = aIdx; @@ -332,10 +422,40 @@ SwContentNode* GoPreviousNds( SwNodeIndex * pIdx, bool bChk ) return pNd; } +SwContentNode* GoNextPos( SwPosition* pIdx, bool bChk ) +{ + SwNodeIndex aIdx( pIdx->GetNode() ); + SwContentNode* pNd = SwNodes::GoNext(&aIdx); + if( pNd ) + { + if( bChk && SwNodeOffset(1) != aIdx.GetIndex() - pIdx->GetNodeIndex() && + !CheckNodesRange( pIdx->GetNode(), aIdx.GetNode(), true ) ) + pNd = nullptr; + else + pIdx->Assign(aIdx); + } + return pNd; +} + +SwContentNode* GoPreviousPos( SwPosition * pIdx, bool bChk ) +{ + SwNodeIndex aIdx( pIdx->GetNode() ); + SwContentNode* pNd = SwNodes::GoPrevious( &aIdx ); + if( pNd ) + { + if( bChk && SwNodeOffset(1) != pIdx->GetNodeIndex() - aIdx.GetIndex() && + !CheckNodesRange( pIdx->GetNode(), aIdx.GetNode(), true ) ) + pNd = nullptr; + else + pIdx->Assign(aIdx); + } + return pNd; +} + SwPaM::SwPaM( const SwPosition& rPos, SwPaM* pRing ) : Ring( pRing ) , m_Bound1( rPos ) - , m_Bound2( rPos.nNode.GetNode().GetNodes() ) // default initialize + , m_Bound2( rPos.GetNode().GetNodes() ) // default initialize , m_pPoint( &m_Bound1 ) , m_pMark( m_pPoint ) , m_bIsInFrontOfLabel( false ) @@ -353,7 +473,7 @@ SwPaM::SwPaM( const SwPosition& rMark, const SwPosition& rPoint, SwPaM* pRing ) } SwPaM::SwPaM( const SwNodeIndex& rMark, const SwNodeIndex& rPoint, - tools::Long nMarkOffset, tools::Long nPointOffset, SwPaM* pRing ) + SwNodeOffset nMarkOffset, SwNodeOffset nPointOffset, SwPaM* pRing ) : Ring( pRing ) , m_Bound1( rMark ) , m_Bound2( rPoint ) @@ -369,12 +489,12 @@ SwPaM::SwPaM( const SwNodeIndex& rMark, const SwNodeIndex& rPoint, { m_pPoint->nNode += nPointOffset; } - m_Bound1.nContent.Assign( m_Bound1.nNode.GetNode().GetContentNode(), 0 ); - m_Bound2.nContent.Assign( m_Bound2.nNode.GetNode().GetContentNode(), 0 ); + m_Bound1.nContent.Assign( m_Bound1.GetNode().GetContentNode(), 0 ); + m_Bound2.nContent.Assign( m_Bound2.GetNode().GetContentNode(), 0 ); } SwPaM::SwPaM( const SwNode& rMark, const SwNode& rPoint, - tools::Long nMarkOffset, tools::Long nPointOffset, SwPaM* pRing ) + SwNodeOffset nMarkOffset, SwNodeOffset nPointOffset, SwPaM* pRing ) : Ring( pRing ) , m_Bound1( rMark ) , m_Bound2( rPoint ) @@ -390,8 +510,8 @@ SwPaM::SwPaM( const SwNode& rMark, const SwNode& rPoint, { m_pPoint->nNode += nPointOffset; } - m_Bound1.nContent.Assign( m_Bound1.nNode.GetNode().GetContentNode(), 0 ); - m_Bound2.nContent.Assign( m_Bound2.nNode.GetNode().GetContentNode(), 0 ); + m_Bound1.nContent.Assign( m_Bound1.GetNode().GetContentNode(), 0 ); + m_Bound2.nContent.Assign( m_Bound2.GetNode().GetContentNode(), 0 ); } SwPaM::SwPaM( const SwNodeIndex& rMark, sal_Int32 nMarkContent, @@ -416,21 +536,56 @@ SwPaM::SwPaM( const SwNode& rMark, sal_Int32 nMarkContent, , m_pMark( &m_Bound1 ) , m_bIsInFrontOfLabel( false ) { - m_pPoint->nContent.Assign( m_pPoint->nNode.GetNode().GetContentNode(), + m_pPoint->nContent.Assign( m_pPoint->GetNode().GetContentNode(), nPointContent); - m_pMark ->nContent.Assign( m_pMark ->nNode.GetNode().GetContentNode(), + m_pMark ->nContent.Assign( m_pMark ->GetNode().GetContentNode(), + nMarkContent ); +} + +SwPaM::SwPaM( const SwNode& rMark, SwNodeOffset nMarkOffset, sal_Int32 nMarkContent, + const SwNode& rPoint, SwNodeOffset nPointOffset, sal_Int32 nPointContent, SwPaM* pRing ) + : Ring( pRing ) + , m_Bound1( rMark ) + , m_Bound2( rPoint ) + , m_pPoint( &m_Bound2 ) + , m_pMark( &m_Bound1 ) + , m_bIsInFrontOfLabel( false ) +{ + if ( nMarkOffset ) + { + m_pMark->nNode += nMarkOffset; + } + if ( nPointOffset ) + { + m_pPoint->nNode += nPointOffset; + } + m_pPoint->nContent.Assign( m_pPoint->GetNode().GetContentNode(), + nPointContent); + m_pMark ->nContent.Assign( m_pMark ->GetNode().GetContentNode(), nMarkContent ); } SwPaM::SwPaM( const SwNode& rNode, sal_Int32 nContent, SwPaM* pRing ) : Ring( pRing ) , m_Bound1( rNode ) - , m_Bound2( m_Bound1.nNode.GetNode().GetNodes() ) // default initialize + , m_Bound2( m_Bound1.GetNode().GetNodes() ) // default initialize + , m_pPoint( &m_Bound1 ) + , m_pMark( &m_Bound1 ) + , m_bIsInFrontOfLabel( false ) +{ + m_pPoint->nContent.Assign( m_pPoint->GetNode().GetContentNode(), + nContent ); +} + +SwPaM::SwPaM( const SwNode& rNode, SwNodeOffset nNdOffset, sal_Int32 nContent, SwPaM* pRing ) + : Ring( pRing ) + , m_Bound1( rNode, nNdOffset ) + , m_Bound2( m_Bound1.GetNode().GetNodes() ) // default initialize , m_pPoint( &m_Bound1 ) , m_pMark( &m_Bound1 ) , m_bIsInFrontOfLabel( false ) { - m_pPoint->nContent.Assign( m_pPoint->nNode.GetNode().GetContentNode(), + m_pPoint->nContent.Assign( m_pPoint->GetNode().GetContentNode(), nContent ); } @@ -445,6 +600,16 @@ SwPaM::SwPaM( const SwNodeIndex& rNodeIdx, sal_Int32 nContent, SwPaM* pRing ) m_pPoint->nContent.Assign( rNodeIdx.GetNode().GetContentNode(), nContent ); } +SwPaM::SwPaM( SwNodes& rNodes, SwNodeOffset nNdOffset, SwPaM* pRing ) + : Ring( pRing ) + , m_Bound1( rNodes, nNdOffset ) + , m_Bound2( rNodes ) // default initialize + , m_pPoint( &m_Bound1 ) + , m_pMark( &m_Bound1 ) + , m_bIsInFrontOfLabel( false ) +{ +} + SwPaM::~SwPaM() {} SwPaM::SwPaM(SwPaM const& rPam, SwPaM *const pRing) @@ -488,18 +653,6 @@ void SwPaM::SetMark() (*m_pMark) = *m_pPoint; } -#ifdef DBG_UTIL -void SwPaM::Exchange() -{ - if (m_pPoint != m_pMark) - { - SwPosition *pTmp = m_pPoint; - m_pPoint = m_pMark; - m_pMark = pTmp; - } -} -#endif - /// movement of cursor bool SwPaM::Move( SwMoveFnCollection const & fnMove, SwGoInDoc fnGo ) { @@ -518,22 +671,17 @@ namespace sw { @param fnMove Contains information if beginning or end of document. @param pOrigRg The given region. - - @return Newly created range, in Ring with parameter pOrigRg. + @param rPam returns newly created range, in Ring with parameter pOrigRg. */ -std::unique_ptr<SwPaM> MakeRegion(SwMoveFnCollection const & fnMove, - const SwPaM & rOrigRg) +void MakeRegion(SwMoveFnCollection const & fnMove, + const SwPaM & rOrigRg, std::optional<SwPaM>& rPam) { - std::unique_ptr<SwPaM> pPam; - { - pPam.reset(new SwPaM(rOrigRg, const_cast<SwPaM*>(&rOrigRg))); // given search range - // make sure that SPoint is on the "real" start position - // FORWARD: SPoint always smaller than GetMark - // BACKWARD: SPoint always bigger than GetMark - if( (pPam->GetMark()->*fnMove.fnCmpOp)( *pPam->GetPoint() ) ) - pPam->Exchange(); - } - return pPam; + rPam.emplace(rOrigRg, const_cast<SwPaM*>(&rOrigRg)); // given search range + // make sure that SPoint is on the "real" start position + // FORWARD: SPoint always smaller than GetMark + // BACKWARD: SPoint always bigger than GetMark + if( (rPam->GetMark()->*fnMove.fnCmpOp)( *rPam->GetPoint() ) ) + rPam->Exchange(); } } // namespace sw @@ -562,7 +710,7 @@ sal_uInt16 SwPaM::GetPageNum( bool bAtPoint, const Point* pLayPos ) tmp.first = *pLayPos; tmp.second = false; } - if( nullptr != ( pNd = pPos->nNode.GetNode().GetContentNode() ) && + if( nullptr != ( pNd = pPos->GetNode().GetContentNode() ) && nullptr != (pCFrame = pNd->getLayoutFrame(pNd->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(), pPos, pLayPos ? &tmp : nullptr)) && nullptr != ( pPg = pCFrame->FindPageFrame() )) return pPg->GetPhyPageNum(); @@ -595,11 +743,11 @@ static const SwFrame* lcl_FindEditInReadonlyFrame( const SwFrame& rFrame ) } /// is in protected section or selection surrounds something protected -bool SwPaM::HasReadonlySel( bool bFormView ) const +bool SwPaM::HasReadonlySel(bool bFormView, bool const isReplace) const { bool bRet = false; - const SwContentNode* pNd = GetPoint()->nNode.GetNode().GetContentNode(); + const SwContentNode* pNd = GetPoint()->GetNode().GetContentNode(); const SwContentFrame *pFrame = nullptr; if ( pNd != nullptr ) { @@ -645,7 +793,7 @@ bool SwPaM::HasReadonlySel( bool bFormView ) const && HasMark() && GetPoint()->nNode != GetMark()->nNode ) { - pNd = GetMark()->nNode.GetNode().GetContentNode(); + pNd = GetMark()->GetNode().GetContentNode(); pFrame = nullptr; if ( pNd != nullptr ) { @@ -687,19 +835,15 @@ bool SwPaM::HasReadonlySel( bool bFormView ) const // check for protected section inside the selection if( !bRet ) { - sal_uLong nSttIdx = GetMark()->nNode.GetIndex(), - nEndIdx = GetPoint()->nNode.GetIndex(); - if( nEndIdx <= nSttIdx ) - { - sal_uLong nTmp = nSttIdx; - nSttIdx = nEndIdx; - nEndIdx = nTmp; - } + SwNodeOffset nSttIdx = GetMark()->GetNodeIndex(), + nEndIdx = GetPoint()->GetNodeIndex(); + if( nEndIdx < nSttIdx ) + std::swap( nSttIdx, nEndIdx ); // If a protected section should be between nodes, then the // selection needs to contain already x nodes. // (TextNd, SectNd, TextNd, EndNd, TextNd ) - if( nSttIdx + 3 < nEndIdx ) + if( nSttIdx + SwNodeOffset(3) < nEndIdx ) { const SwSectionFormats& rFormats = GetDoc().GetSections(); for( SwSectionFormats::size_type n = rFormats.size(); n; ) @@ -709,7 +853,7 @@ bool SwPaM::HasReadonlySel( bool bFormView ) const { const SwFormatContent& rContent = pFormat->GetContent(false); OSL_ENSURE( rContent.GetContentIdx(), "where is the SectionNode?" ); - sal_uLong nIdx = rContent.GetContentIdx()->GetIndex(); + SwNodeOffset nIdx = rContent.GetContentIdx()->GetIndex(); if( nSttIdx <= nIdx && nEndIdx >= nIdx && rContent.GetContentIdx()->GetNode().GetNodes().IsDocNodes() ) { @@ -725,13 +869,13 @@ bool SwPaM::HasReadonlySel( bool bFormView ) const const SwDoc& rDoc = GetDoc(); // Legacy text/combo/checkbox: never return read-only when inside these form fields. const IDocumentMarkAccess* pMarksAccess = rDoc.getIDocumentMarkAccess(); - sw::mark::IFieldmark* pA = GetPoint() ? pMarksAccess->getFieldmarkFor( *GetPoint( ) ) : nullptr; - sw::mark::IFieldmark* pB = GetMark() ? pMarksAccess->getFieldmarkFor( *GetMark( ) ) : pA; + sw::mark::IFieldmark* pA = GetPoint() ? pMarksAccess->getInnerFieldmarkFor(*GetPoint()) : nullptr; + sw::mark::IFieldmark* pB = GetMark() ? pMarksAccess->getInnerFieldmarkFor(*GetMark()) : pA; // prevent the user from accidentally deleting the field itself when modifying the text. const bool bAtStartA = (pA != nullptr) && (pA->GetMarkStart() == *GetPoint()); const bool bAtStartB = (pB != nullptr) && (pB->GetMarkStart() == *GetMark()); - if (officecfg::Office::Common::Filter::Microsoft::Import::ForceImportWWFieldsAsGenericFields::get(comphelper::getProcessComponentContext())) + if (officecfg::Office::Common::Filter::Microsoft::Import::ForceImportWWFieldsAsGenericFields::get()) { ; // allow editing all fields in generic mode } @@ -762,19 +906,27 @@ bool SwPaM::HasReadonlySel( bool bFormView ) const { // Allow editing when the cursor/selection is fully inside of a legacy form field. bRet = !( pA != nullptr && !bAtStartA && !bAtStartB && pA == pB ); + + if (bRet) + { + // Also allow editing inside content controls in general, similar to form fields. + // Specific types will be disabled below. + if (const SwEditShell* pEditShell = rDoc.GetEditShell()) + bRet = !pEditShell->CursorInsideContentControl(); + } } if (!bRet) { // Paragraph Signatures and Classification fields are read-only. - if (rDoc.GetEditShell()) - bRet = rDoc.GetEditShell()->IsCursorInParagraphMetadataField(); + if (const SwEditShell* pEditShell = rDoc.GetEditShell()) + bRet = pEditShell->IsCursorInParagraphMetadataField(); } if (!bRet && rDoc.getIDocumentSettingAccess().get(DocumentSettingId::PROTECT_BOOKMARKS)) { - if (rDoc.getIDocumentMarkAccess()->isBookmarkDeleted(*this)) + if (rDoc.getIDocumentMarkAccess()->isBookmarkDeleted(*this, isReplace)) { return true; } @@ -784,7 +936,7 @@ bool SwPaM::HasReadonlySel( bool bFormView ) const { SwPosition const& rStart(*Start()); SwPosition const& rEnd(*End()); - for (SwNodeIndex n = rStart.nNode; n <= rEnd.nNode; ++n) + for (SwNodeIndex n(rStart.GetNode()); n <= rEnd.GetNode(); ++n) { if (SwTextNode const*const pNode = n.GetNode().GetTextNode()) { @@ -793,11 +945,11 @@ bool SwPaM::HasReadonlySel( bool bFormView ) const for (size_t i = 0; i < pHints->Count(); ++i) { SwTextAttr const*const pHint(pHints->Get(i)); - if (n == rStart.nNode && pHint->GetStart() < rStart.nContent.GetIndex()) + if (n == rStart.GetNode() && pHint->GetStart() < rStart.GetContentIndex()) { continue; // before selection } - if (n == rEnd.nNode && rEnd.nContent.GetIndex() <= pHint->GetStart()) + if (n == rEnd.GetNode() && rEnd.GetContentIndex() <= pHint->GetStart()) { break; // after selection } @@ -813,6 +965,74 @@ bool SwPaM::HasReadonlySel( bool bFormView ) const } } + if (!bRet) + { + // See if we're inside a read-only content control. + const SwPosition* pStart = Start(); + SwTextNode* pTextNode = pStart->GetNode().GetTextNode(); + if (pTextNode) + { + sal_Int32 nIndex = pStart->GetContentIndex(); + SwTextAttr* pAttr + = pTextNode->GetTextAttrAt(nIndex, RES_TXTATR_CONTENTCONTROL, ::sw::GetTextAttrMode::Parent); + auto pTextContentControl = static_txtattr_cast<SwTextContentControl*>(pAttr); + if (pTextContentControl) + { + const SwFormatContentControl& rFormatContentControl + = pTextContentControl->GetContentControl(); + std::shared_ptr<SwContentControl> pContentControl + = rFormatContentControl.GetContentControl(); + if (pContentControl && !pContentControl->GetReadWrite()) + { + switch (pContentControl->GetType()) + { + case SwContentControlType::CHECKBOX: + case SwContentControlType::PICTURE: + case SwContentControlType::DROP_DOWN_LIST: + bRet = true; + break; + default: + break; + } + } + } + } + } + + return bRet; +} + +bool SwPaM::HasHiddenSections() const +{ + bool bRet = false; + + if (HasMark() && GetPoint()->nNode != GetMark()->nNode) + { + // check for hidden section inside the selection + SwNodeOffset nSttIdx = Start()->GetNodeIndex(), nEndIdx = End()->GetNodeIndex(); + + if (nSttIdx + SwNodeOffset(3) < nEndIdx) + { + const SwSectionFormats& rFormats = GetDoc().GetSections(); + for (SwSectionFormats::size_type n = rFormats.size(); n;) + { + const SwSectionFormat* pFormat = rFormats[--n]; + if (pFormat->GetSection()->IsHidden()) + { + const SwFormatContent& rContent = pFormat->GetContent(false); + OSL_ENSURE(rContent.GetContentIdx(), "where is the SectionNode?"); + SwNodeOffset nIdx = rContent.GetContentIdx()->GetIndex(); + if (nSttIdx <= nIdx && nEndIdx >= nIdx + && rContent.GetContentIdx()->GetNode().GetNodes().IsDocNodes()) + { + bRet = true; + break; + } + } + } + } + } + return bRet; } @@ -832,7 +1052,7 @@ SwContentNode* GetNode( SwPaM & rPam, bool& rbFirst, SwMoveFnCollection const & if( rbFirst ) { rbFirst = false; - pNd = rPam.GetContentNode(); + pNd = rPam.GetPointContentNode(); if( pNd ) { SwContentFrame const*const pFrame(pNd->getLayoutFrame(pLayout)); @@ -840,15 +1060,15 @@ SwContentNode* GetNode( SwPaM & rPam, bool& rbFirst, SwMoveFnCollection const & ( nullptr == pFrame || ( !bInReadOnly && pFrame->IsProtected() ) || - (pFrame->IsTextFrame() && static_cast<SwTextFrame const*>(pFrame)->IsHiddenNow()) + pFrame->IsHiddenNow() ) || ( !bInReadOnly && pNd->FindSectionNode() && pNd->FindSectionNode()->GetSection().IsProtect() ) ) - { - pNd = nullptr; - } + { + pNd = nullptr; + } } } @@ -856,23 +1076,23 @@ SwContentNode* GetNode( SwPaM & rPam, bool& rbFirst, SwMoveFnCollection const & { SwPosition aPos( *rPam.GetPoint() ); bool bSrchForward = &fnMove == &fnMoveForward; - SwNodes& rNodes = aPos.nNode.GetNodes(); // go to next/previous ContentNode while( true ) { - if (i_pLayout && aPos.nNode.GetNode().IsTextNode()) + if (i_pLayout && aPos.GetNode().IsTextNode()) { - auto const fal(sw::GetFirstAndLastNode(*pLayout, aPos.nNode)); - aPos.nNode = bSrchForward ? *fal.second : *fal.first; + auto const fal(sw::GetFirstAndLastNode(*pLayout, aPos.GetNode())); + aPos.Assign( bSrchForward ? *fal.second : *fal.first ); } pNd = bSrchForward - ? rNodes.GoNextSection( &aPos.nNode, true, !bInReadOnly ) - : SwNodes::GoPrevSection( &aPos.nNode, true, !bInReadOnly ); + ? SwNodes::GoNextSection( &aPos, true, !bInReadOnly ) + : SwNodes::GoPrevSection( &aPos, true, !bInReadOnly ); if( pNd ) { - aPos.nContent.Assign( pNd, ::GetSttOrEnd( bSrchForward,*pNd )); + if (!bSrchForward) + aPos.AssignEndIndex( *pNd ); // is the position still in the area if( (aPos.*fnMove.fnCmpOp)( *rPam.GetMark() ) ) { @@ -880,8 +1100,7 @@ SwContentNode* GetNode( SwPaM & rPam, bool& rbFirst, SwMoveFnCollection const & SwContentFrame const*const pFrame(pNd->getLayoutFrame(pLayout)); if (nullptr == pFrame || ( !bInReadOnly && pFrame->IsProtected() ) || - ( pFrame->IsTextFrame() && - static_cast<SwTextFrame const*>(pFrame)->IsHiddenNow())) + pFrame->IsHiddenNow()) { pNd = nullptr; continue; @@ -901,49 +1120,61 @@ SwContentNode* GetNode( SwPaM & rPam, bool& rbFirst, SwMoveFnCollection const & void GoStartDoc( SwPosition * pPos ) { - SwNodes& rNodes = pPos->nNode.GetNodes(); - pPos->nNode = *rNodes.GetEndOfContent().StartOfSectionNode(); + SwNodes& rNodes = pPos->GetNodes(); + pPos->Assign( *rNodes.GetEndOfContent().StartOfSectionNode() ); // we always need to find a ContentNode! - SwContentNode* pCNd = rNodes.GoNext( &pPos->nNode ); - if( pCNd ) - pCNd->MakeStartIndex( &pPos->nContent ); + SwNodes::GoNext(pPos); } void GoEndDoc( SwPosition * pPos ) { - SwNodes& rNodes = pPos->nNode.GetNodes(); - pPos->nNode = rNodes.GetEndOfContent(); - SwContentNode* pCNd = GoPreviousNds( &pPos->nNode, true ); + SwNodes& rNodes = pPos->GetNodes(); + pPos->Assign( rNodes.GetEndOfContent() ); + SwContentNode* pCNd = GoPreviousPos( pPos, true ); if( pCNd ) - pCNd->MakeEndIndex( &pPos->nContent ); + pPos->AssignEndIndex(*pCNd); } void GoStartSection( SwPosition * pPos ) { // jump to section's beginning - SwNodes& rNodes = pPos->nNode.GetNodes(); - sal_uInt16 nLevel = SwNodes::GetSectionLevel( pPos->nNode ); - if( pPos->nNode < rNodes.GetEndOfContent().StartOfSectionIndex() ) + SwNodes& rNodes = pPos->GetNodes(); + sal_uInt16 nLevel = SwNodes::GetSectionLevel( pPos->GetNode() ); + if( pPos->GetNode() < *rNodes.GetEndOfContent().StartOfSectionNode() ) nLevel--; do { SwNodes::GoStartOfSection( &pPos->nNode ); } while( nLevel-- ); // already on a ContentNode - pPos->nNode.GetNode().GetContentNode()->MakeStartIndex( &pPos->nContent ); + pPos->AssignStartIndex(*pPos->GetNode().GetContentNode()); +} + +void GoStartOfSection( SwPosition * pPos ) +{ + // jump to section's beginning + SwNodes::GoStartOfSection( &pPos->nNode ); + pPos->nContent.Assign(pPos->GetNode().GetContentNode(), 0); } /// go to the end of the current base section void GoEndSection( SwPosition * pPos ) { // jump to section's beginning/end - SwNodes& rNodes = pPos->nNode.GetNodes(); - sal_uInt16 nLevel = SwNodes::GetSectionLevel( pPos->nNode ); - if( pPos->nNode < rNodes.GetEndOfContent().StartOfSectionIndex() ) + SwNodes& rNodes = pPos->GetNodes(); + sal_uInt16 nLevel = SwNodes::GetSectionLevel( pPos->GetNode() ); + if( pPos->GetNode() < *rNodes.GetEndOfContent().StartOfSectionNode() ) nLevel--; do { SwNodes::GoEndOfSection( &pPos->nNode ); } while( nLevel-- ); // now on an EndNode, thus to the previous ContentNode - if( GoPreviousNds( &pPos->nNode, true ) ) - pPos->nNode.GetNode().GetContentNode()->MakeEndIndex( &pPos->nContent ); + if( SwContentNode* pCNd = GoPreviousNds( &pPos->nNode, true ) ) + pPos->AssignEndIndex(*pCNd); +} + +void GoEndOfSection( SwPosition * pPos ) +{ + SwNodes::GoEndOfSection( &pPos->nNode ); + SwContentNode* pCNd = pPos->nNode.GetNode().GetContentNode(); + pPos->nContent.Assign(pCNd, pCNd ? pCNd->Len() : 0); } bool GoInDoc( SwPaM & rPam, SwMoveFnCollection const & fnMove ) @@ -960,41 +1191,41 @@ bool GoInSection( SwPaM & rPam, SwMoveFnCollection const & fnMove ) bool GoInNode( SwPaM & rPam, SwMoveFnCollection const & fnMove ) { - SwContentNode *pNd = (*fnMove.fnNds)( &rPam.GetPoint()->nNode, true ); + SwContentNode *pNd = (*fnMove.fnPos)( rPam.GetPoint(), true ); if( pNd ) - rPam.GetPoint()->nContent.Assign( pNd, + rPam.GetPoint()->SetContent( ::GetSttOrEnd( &fnMove == &fnMoveForward, *pNd ) ); return pNd; } bool GoInContent( SwPaM & rPam, SwMoveFnCollection const & fnMove ) { - if( (*fnMove.fnNd)( &rPam.GetPoint()->nNode.GetNode(), - &rPam.GetPoint()->nContent, CRSR_SKIP_CHARS )) + if( (*fnMove.fnNd)( &rPam.GetPoint()->GetNode(), + &rPam.GetPoint()->nContent, SwCursorSkipMode::Chars )) return true; return GoInNode( rPam, fnMove ); } bool GoInContentCells( SwPaM & rPam, SwMoveFnCollection const & fnMove ) { - if( (*fnMove.fnNd)( &rPam.GetPoint()->nNode.GetNode(), - &rPam.GetPoint()->nContent, CRSR_SKIP_CELLS )) + if( (*fnMove.fnNd)( &rPam.GetPoint()->GetNode(), + &rPam.GetPoint()->nContent, SwCursorSkipMode::Cells )) return true; return GoInNode( rPam, fnMove ); } bool GoInContentSkipHidden( SwPaM & rPam, SwMoveFnCollection const & fnMove ) { - if( (*fnMove.fnNd)( &rPam.GetPoint()->nNode.GetNode(), - &rPam.GetPoint()->nContent, CRSR_SKIP_CHARS | CRSR_SKIP_HIDDEN ) ) + if( (*fnMove.fnNd)( &rPam.GetPoint()->GetNode(), + &rPam.GetPoint()->nContent, SwCursorSkipMode::Chars | SwCursorSkipMode::Hidden ) ) return true; return GoInNode( rPam, fnMove ); } bool GoInContentCellsSkipHidden( SwPaM & rPam, SwMoveFnCollection const & fnMove ) { - if( (*fnMove.fnNd)( &rPam.GetPoint()->nNode.GetNode(), - &rPam.GetPoint()->nContent, CRSR_SKIP_CELLS | CRSR_SKIP_HIDDEN ) ) + if( (*fnMove.fnNd)( &rPam.GetPoint()->GetNode(), + &rPam.GetPoint()->nContent, SwCursorSkipMode::Cells | SwCursorSkipMode::Hidden ) ) return true; return GoInNode( rPam, fnMove ); } @@ -1005,9 +1236,8 @@ bool GoPrevPara( SwPaM & rPam, SwMoveFnCollection const & aPosPara ) { // always on a ContentNode SwPosition& rPos = *rPam.GetPoint(); - SwContentNode * pNd = rPos.nNode.GetNode().GetContentNode(); - rPos.nContent.Assign( pNd, - ::GetSttOrEnd( &aPosPara == &fnMoveForward, *pNd ) ); + SwContentNode * pNd = rPos.GetNode().GetContentNode(); + rPos.SetContent( ::GetSttOrEnd( &aPosPara == &fnMoveForward, *pNd ) ); return true; } return false; @@ -1016,26 +1246,25 @@ bool GoPrevPara( SwPaM & rPam, SwMoveFnCollection const & aPosPara ) bool GoCurrPara( SwPaM & rPam, SwMoveFnCollection const & aPosPara ) { SwPosition& rPos = *rPam.GetPoint(); - SwContentNode * pNd = rPos.nNode.GetNode().GetContentNode(); + SwContentNode * pNd = rPos.GetNode().GetContentNode(); if( pNd ) { - const sal_Int32 nOld = rPos.nContent.GetIndex(); + const sal_Int32 nOld = rPos.GetContentIndex(); const sal_Int32 nNew = &aPosPara == &fnMoveForward ? 0 : pNd->Len(); // if already at beginning/end then to the next/previous if( nOld != nNew ) { - rPos.nContent.Assign( pNd, nNew ); + rPos.SetContent( nNew ); return true; } } // move node to next/previous ContentNode if( ( &aPosPara==&fnParaStart && nullptr != ( pNd = - GoPreviousNds( &rPos.nNode, true ))) || + GoPreviousPos( &rPos, true ))) || ( &aPosPara==&fnParaEnd && nullptr != ( pNd = - GoNextNds( &rPos.nNode, true ))) ) + GoNextPos( &rPos, true ))) ) { - rPos.nContent.Assign( pNd, - ::GetSttOrEnd( &aPosPara == &fnMoveForward, *pNd )); + rPos.SetContent( ::GetSttOrEnd( &aPosPara == &fnMoveForward, *pNd )); return true; } return false; @@ -1047,9 +1276,8 @@ bool GoNextPara( SwPaM & rPam, SwMoveFnCollection const & aPosPara ) { // always on a ContentNode SwPosition& rPos = *rPam.GetPoint(); - SwContentNode * pNd = rPos.nNode.GetNode().GetContentNode(); - rPos.nContent.Assign( pNd, - ::GetSttOrEnd( &aPosPara == &fnMoveForward, *pNd ) ); + SwContentNode * pNd = rPos.GetNode().GetContentNode(); + rPos.SetContent( ::GetSttOrEnd( &aPosPara == &fnMoveForward, *pNd ) ); return true; } return false; @@ -1059,17 +1287,16 @@ bool GoCurrSection( SwPaM & rPam, SwMoveFnCollection const & fnMove ) { SwPosition& rPos = *rPam.GetPoint(); SwPosition aSavePos( rPos ); // position for comparison - (fnMove.fnSection)( &rPos.nNode ); + (fnMove.fnSection)( &rPos ); SwContentNode *pNd; - if( nullptr == ( pNd = rPos.nNode.GetNode().GetContentNode()) && - nullptr == ( pNd = (*fnMove.fnNds)( &rPos.nNode, true )) ) + if( nullptr == ( pNd = rPos.GetNode().GetContentNode()) && + nullptr == ( pNd = (*fnMove.fnPos)( &rPos, true )) ) { rPos = aSavePos; // do not change cursor return false; } - rPos.nContent.Assign( pNd, - ::GetSttOrEnd( &fnMove == &fnMoveForward, *pNd ) ); + rPos.SetContent( ::GetSttOrEnd( &fnMove == &fnMoveForward, *pNd ) ); return aSavePos != rPos; } @@ -1096,14 +1323,14 @@ OUString SwPaM::GetText() const } const OUString& aTmpStr = pTextNode->GetText(); - if (bIsStartNode || bIsEndNode) + if (!aTmpStr.isEmpty() && (bIsStartNode || bIsEndNode)) { // Handle corner cases of start/end node(s) const sal_Int32 nStart = bIsStartNode - ? Start()->nContent.GetIndex() + ? Start()->GetContentIndex() : 0; const sal_Int32 nEnd = bIsEndNode - ? End()->nContent.GetIndex() + ? End()->GetContentIndex() : aTmpStr.getLength(); aResult.append(aTmpStr.subView(nStart, nEnd-nStart)); @@ -1128,18 +1355,18 @@ OUString SwPaM::GetText() const void SwPaM::InvalidatePaM() { - for (SwNodeIndex index = Start()->nNode; index <= End()->nNode; ++index) + for (SwNodeIndex index(Start()->GetNode()); index <= End()->GetNode(); ++index) { if (SwTextNode *const pTextNode = index.GetNode().GetTextNode()) { // pretend that the PaM marks changed formatting to reformat... sal_Int32 const nStart( - index == Start()->nNode ? Start()->nContent.GetIndex() : 0); + index == Start()->nNode ? Start()->GetContentIndex() : 0); // this should work even for length of 0 SwUpdateAttr const aHint( nStart, index == End()->nNode - ? End()->nContent.GetIndex() - nStart + ? End()->GetContentIndex() - nStart : pTextNode->Len() - nStart, 0); pTextNode->TriggerNodeUpdate(sw::LegacyModifyHint(&aHint, &aHint)); diff --git a/sw/source/core/crsr/paminit.cxx b/sw/source/core/crsr/paminit.cxx index 367be6e02e37..a415aee2c21c 100644 --- a/sw/source/core/crsr/paminit.cxx +++ b/sw/source/core/crsr/paminit.cxx @@ -24,23 +24,25 @@ const SwMoveFnCollection aFwrd = { /* fnNd */ &GoNext, /* fnNds */ &GoNextNds, + /* fnPos */ &GoNextPos, /* fnDoc */ &GoEndDoc, /* fnSections */ &GoEndSection, /* fnCmpOp */ &SwPosition::operator<, /* fnGetHint */ &GetFrwrdTextHint, /* fnSearch */ &utl::TextSearch::SearchForward, - /* fnSection */ &SwNodes::GoStartOfSection + /* fnSection */ &GoStartOfSection }; const SwMoveFnCollection aBwrd = { /* fnNd */ &GoPrevious, /* fnNds */ &GoPreviousNds, + /* fnPos */ &GoPreviousPos, /* fnDoc */ &GoStartDoc, /* fnSections */ &GoStartSection, /* fnCmpOp */ &SwPosition::operator>, /* fnGetHint */ &GetBkwrdTextHint, /* fnSearch */ &utl::TextSearch::SearchBackward, - /* fnSection */ &SwNodes::GoEndOfSection + /* fnSection */ &GoEndOfSection }; SwMoveFnCollection const & fnParaStart = aFwrd; diff --git a/sw/source/core/crsr/swcrsr.cxx b/sw/source/core/crsr/swcrsr.cxx index 69388177ab28..63b107f823d8 100644 --- a/sw/source/core/crsr/swcrsr.cxx +++ b/sw/source/core/crsr/swcrsr.cxx @@ -29,7 +29,7 @@ #include <swtblfmt.hxx> #include <swcrsr.hxx> #include <unocrsr.hxx> -#include <bookmrk.hxx> +#include <bookmark.hxx> #include <doc.hxx> #include <IDocumentUndoRedo.hxx> #include <IDocumentRedlineAccess.hxx> @@ -76,34 +76,30 @@ struct PercentHdl { bBack = (nStt > nEnd); if( bBack ) - { - sal_uLong n = nStt; nStt = nEnd; nEnd = n; - } + std::swap( nStt, nEnd ); ::StartProgress( STR_STATSTR_SEARCH, nStt, nEnd ); } explicit PercentHdl( const SwPaM& rPam ) : pDSh( rPam.GetDoc().GetDocShell() ) { - sal_uLong nStt, nEnd; - if( rPam.GetPoint()->nNode == rPam.GetMark()->nNode ) + sal_Int32 nStt, nEnd; + if( rPam.GetPoint()->GetNode() == rPam.GetMark()->GetNode() ) { bNodeIdx = false; - nStt = rPam.GetMark()->nContent.GetIndex(); - nEnd = rPam.GetPoint()->nContent.GetIndex(); + nStt = rPam.GetMark()->GetContentIndex(); + nEnd = rPam.GetPoint()->GetContentIndex(); } else { bNodeIdx = true; - nStt = rPam.GetMark()->nNode.GetIndex(); - nEnd = rPam.GetPoint()->nNode.GetIndex(); + nStt = sal_Int32(rPam.GetMark()->GetNodeIndex()); + nEnd = sal_Int32(rPam.GetPoint()->GetNodeIndex()); } nActPos = nStt; bBack = (nStt > nEnd ); if( bBack ) - { - sal_uLong n = nStt; nStt = nEnd; nEnd = n; - } + std::swap( nStt, nEnd ); ::StartProgress( STR_STATSTR_SEARCH, nStt, nEnd, pDSh ); } @@ -114,11 +110,11 @@ struct PercentHdl void NextPos( SwPosition const & rPos ) const { - sal_uLong nPos; + sal_Int32 nPos; if( bNodeIdx ) - nPos = rPos.nNode.GetIndex(); + nPos = sal_Int32(rPos.GetNodeIndex()); else - nPos = rPos.nContent.GetIndex(); + nPos = rPos.GetContentIndex(); ::SetProgressState( bBack ? nActPos - nPos : nPos, pDSh ); } }; @@ -184,7 +180,7 @@ void SwCursor::RestoreState() /// determine if point is outside of the node-array's content area bool SwCursor::IsNoContent() const { - return GetPoint()->nNode.GetIndex() < + return GetPoint()->GetNodeIndex() < GetDoc().GetNodes().GetEndOfExtras().GetIndex(); } @@ -202,10 +198,10 @@ bool SwTableCursor::IsSelOvrCheck(SwCursorSelOverFlags eFlags) && HasMark() ) { SwNodeIndex aOldPos( rNds, GetSavePos()->nNode ); - if( !CheckNodesRange( aOldPos, GetPoint()->nNode, true )) + if( !CheckNodesRange( aOldPos.GetNode(), GetPoint()->GetNode(), true )) { - GetPoint()->nNode = aOldPos; - GetPoint()->nContent.Assign( GetContentNode(), GetSavePos()->nContent ); + GetPoint()->Assign( aOldPos ); + GetPoint()->SetContent( GetSavePos()->nContent ); return true; } } @@ -216,14 +212,14 @@ namespace { const SwTextAttr* InputFieldAtPos(SwPosition const *pPos) { - SwTextNode* pTextNd = pPos->nNode.GetNode().GetTextNode(); + SwTextNode* pTextNd = pPos->GetNode().GetTextNode(); if (!pTextNd) return nullptr; - return pTextNd->GetTextAttrAt(pPos->nContent.GetIndex(), RES_TXTATR_INPUTFIELD, SwTextNode::PARENT); + return pTextNd->GetTextAttrAt(pPos->GetContentIndex(), RES_TXTATR_INPUTFIELD, ::sw::GetTextAttrMode::Parent); } } -bool SwCursor::IsSelOvr( SwCursorSelOverFlags eFlags ) +bool SwCursor::IsSelOvr(SwCursorSelOverFlags const eFlags) { SwDoc& rDoc = GetDoc(); SwNodes& rNds = rDoc.GetNodes(); @@ -236,13 +232,13 @@ bool SwCursor::IsSelOvr( SwCursorSelOverFlags eFlags ) return true; } - if (m_vSavePos.back().nNode != GetPoint()->nNode.GetIndex() && + if (m_vSavePos.back().nNode != GetPoint()->GetNodeIndex() && // (1997) in UI-ReadOnly everything is allowed ( !rDoc.GetDocShell() || !rDoc.GetDocShell()->IsReadOnlyUI() )) { // check new sections - SwNodeIndex& rPtIdx = GetPoint()->nNode; - const SwSectionNode* pSectNd = rPtIdx.GetNode().FindSectionNode(); + SwPosition& rPtPos = *GetPoint(); + const SwSectionNode* pSectNd = rPtPos.GetNode().FindSectionNode(); if( pSectNd && ((bSkipOverHiddenSections && pSectNd->GetSection().IsHiddenFlag() ) || (bSkipOverProtectSections && pSectNd->GetSection().IsProtectFlag() ))) @@ -255,44 +251,44 @@ bool SwCursor::IsSelOvr( SwCursorSelOverFlags eFlags ) } // set cursor to new position: - SwNodeIndex aIdx( rPtIdx ); + SwNodeIndex aIdx( rPtPos.GetNode() ); sal_Int32 nContentPos = m_vSavePos.back().nContent; - bool bGoNxt = m_vSavePos.back().nNode < rPtIdx.GetIndex(); + bool bGoNxt = m_vSavePos.back().nNode < rPtPos.GetNodeIndex(); SwContentNode* pCNd = bGoNxt - ? rNds.GoNextSection( &rPtIdx, bSkipOverHiddenSections, bSkipOverProtectSections) - : SwNodes::GoPrevSection( &rPtIdx, bSkipOverHiddenSections, bSkipOverProtectSections); + ? SwNodes::GoNextSection( &rPtPos, bSkipOverHiddenSections, bSkipOverProtectSections) + : SwNodes::GoPrevSection( &rPtPos, bSkipOverHiddenSections, bSkipOverProtectSections); if( !pCNd && ( SwCursorSelOverFlags::EnableRevDirection & eFlags )) { bGoNxt = !bGoNxt; - pCNd = bGoNxt ? rNds.GoNextSection( &rPtIdx, bSkipOverHiddenSections, bSkipOverProtectSections) - : SwNodes::GoPrevSection( &rPtIdx, bSkipOverHiddenSections, bSkipOverProtectSections); + pCNd = bGoNxt ? SwNodes::GoNextSection( &rPtPos, bSkipOverHiddenSections, bSkipOverProtectSections) + : SwNodes::GoPrevSection( &rPtPos, bSkipOverHiddenSections, bSkipOverProtectSections); } bool bIsValidPos = nullptr != pCNd; const bool bValidNodesRange = bIsValidPos && - ::CheckNodesRange( rPtIdx, aIdx, true ); + ::CheckNodesRange( rPtPos.GetNode(), aIdx.GetNode(), true ); if( !bValidNodesRange ) { - rPtIdx = m_vSavePos.back().nNode; - pCNd = rPtIdx.GetNode().GetContentNode(); + rPtPos.Assign( m_vSavePos.back().nNode ); + pCNd = rPtPos.GetNode().GetContentNode(); if( !pCNd ) { bIsValidPos = false; nContentPos = 0; - rPtIdx = aIdx; - pCNd = rPtIdx.GetNode().GetContentNode(); + rPtPos.Assign( aIdx ); + pCNd = rPtPos.GetNode().GetContentNode(); if( !pCNd ) { // then to the beginning of the document - rPtIdx = rNds.GetEndOfExtras(); - pCNd = rNds.GoNext( &rPtIdx ); + rPtPos.Assign( rNds.GetEndOfExtras() ); + pCNd = SwNodes::GoNext(&rPtPos); } } } // register ContentIndex: const sal_Int32 nTmpPos = bIsValidPos ? (bGoNxt ? 0 : pCNd->Len()) : nContentPos; - GetPoint()->nContent.Assign( pCNd, nTmpPos ); + GetPoint()->SetContent( nTmpPos ); if( !bIsValidPos || !bValidNodesRange || IsInProtectTable( true ) ) return true; @@ -301,14 +297,10 @@ bool SwCursor::IsSelOvr( SwCursorSelOverFlags eFlags ) // is there a protected section in the section? if( HasMark() && bSkipOverProtectSections) { - sal_uLong nSttIdx = GetMark()->nNode.GetIndex(), - nEndIdx = GetPoint()->nNode.GetIndex(); + SwNodeOffset nSttIdx = GetMark()->GetNodeIndex(), + nEndIdx = GetPoint()->GetNodeIndex(); if( nEndIdx <= nSttIdx ) - { - sal_uLong nTmp = nSttIdx; - nSttIdx = nEndIdx; - nEndIdx = nTmp; - } + std::swap( nSttIdx, nEndIdx ); const SwSectionFormats& rFormats = rDoc.GetSections(); for( SwSectionFormats::size_type n = 0; n < rFormats.size(); ++n ) @@ -319,7 +311,7 @@ bool SwCursor::IsSelOvr( SwCursorSelOverFlags eFlags ) { const SwFormatContent& rContent = pFormat->GetContent(false); OSL_ENSURE( rContent.GetContentIdx(), "No SectionNode?" ); - sal_uLong nIdx = rContent.GetContentIdx()->GetIndex(); + SwNodeOffset nIdx = rContent.GetContentIdx()->GetIndex(); if( nSttIdx <= nIdx && nEndIdx >= nIdx ) { // if it is no linked section then we cannot select it @@ -335,7 +327,7 @@ bool SwCursor::IsSelOvr( SwCursorSelOverFlags eFlags ) } } - const SwNode* pNd = &GetPoint()->nNode.GetNode(); + const SwNode* pNd = &GetPoint()->GetNode(); if( pNd->IsContentNode() && !dynamic_cast<SwUnoCursor*>(this) ) { const SwContentFrame* pFrame = static_cast<const SwContentNode*>(pNd)->getLayoutFrame( rDoc.getIDocumentLayoutAccess().GetCurrentLayout() ); @@ -345,11 +337,11 @@ bool SwCursor::IsSelOvr( SwCursorSelOverFlags eFlags ) && !InputFieldAtPos(GetPoint()) ) //unless it's a (vertical) input field { // skip to the next/prev valid paragraph with a layout - SwNodeIndex& rPtIdx = GetPoint()->nNode; - bool bGoNxt = m_vSavePos.back().nNode < rPtIdx.GetIndex(); + SwPosition& rPtPos = *GetPoint(); + bool bGoNxt = m_vSavePos.back().nNode < rPtPos.GetNodeIndex(); for (;;) { - pFrame = bGoNxt ? pFrame->GetNextContentFrame() : pFrame->GetPrevContentFrame(); + pFrame = bGoNxt ? pFrame->FindNextCnt(true) : pFrame->FindPrevCnt(); if (!pFrame || 0 != pFrame->getFrameArea().Height() ) break; } @@ -362,8 +354,7 @@ bool SwCursor::IsSelOvr( SwCursorSelOverFlags eFlags ) pFrame = static_cast<const SwContentNode*>(pNd)->getLayoutFrame( rDoc.getIDocumentLayoutAccess().GetCurrentLayout() ); while ( pFrame && 0 == pFrame->getFrameArea().Height() ) { - pFrame = bGoNxt ? pFrame->GetNextContentFrame() - : pFrame->GetPrevContentFrame(); + pFrame = bGoNxt ? pFrame->FindNextCnt(true) : pFrame->FindPrevCnt(); } } @@ -383,15 +374,15 @@ bool SwCursor::IsSelOvr( SwCursorSelOverFlags eFlags ) assert(pCNd); // set this ContentNode as new position - rPtIdx = *pCNd; + rPtPos.Assign( *pCNd ); // assign corresponding ContentIndex const sal_Int32 nTmpPos = bGoNxt ? 0 : pCNd->Len(); - GetPoint()->nContent.Assign( pCNd, nTmpPos ); + GetPoint()->SetContent( nTmpPos ); } - if (rPtIdx.GetIndex() == m_vSavePos.back().nNode - && GetPoint()->nContent.GetIndex() == m_vSavePos.back().nContent) + if (rPtPos.GetNodeIndex() == m_vSavePos.back().nNode + && GetPoint()->GetContentIndex() == m_vSavePos.back().nContent) { // new position equals saved one // --> trigger restore of saved pos by setting <pFrame> to NULL - see below @@ -409,9 +400,16 @@ bool SwCursor::IsSelOvr( SwCursorSelOverFlags eFlags ) if( !pFrame ) { - DeleteMark(); - RestoreSavePos(); - return true; // we need a frame + assert(!m_vSavePos.empty()); + SwContentNode const*const pSaveNode(rNds[m_vSavePos.back().nNode]->GetContentNode()); + // if the old position already didn't have a frame, allow moving + // anyway, hope the caller can handle that + if (pSaveNode && pSaveNode->getLayoutFrame(rDoc.getIDocumentLayoutAccess().GetCurrentLayout())) + { + DeleteMark(); + RestoreSavePos(); + return true; // we need a frame + } } } @@ -427,14 +425,14 @@ bool SwCursor::IsSelOvr( SwCursorSelOverFlags eFlags ) return false; // check for invalid sections - if( !::CheckNodesRange( GetMark()->nNode, GetPoint()->nNode, true )) + if( !::CheckNodesRange( GetMark()->GetNode(), GetPoint()->GetNode(), true )) { DeleteMark(); RestoreSavePos(); return true; // we need a frame } - pNd = &GetMark()->nNode.GetNode(); + pNd = &GetMark()->GetNode(); if( pNd->IsContentNode() && !static_cast<const SwContentNode*>(pNd)->getLayoutFrame( rDoc.getIDocumentLayoutAccess().GetCurrentLayout() ) && !dynamic_cast<SwUnoCursor*>(this) ) @@ -451,39 +449,37 @@ bool SwCursor::IsSelOvr( SwCursorSelOverFlags eFlags ) if ( pInputFieldTextAttrAtPoint != pInputFieldTextAttrAtMark ) { - const sal_uLong nRefNodeIdx = + const SwNodeOffset nRefNodeIdx = ( SwCursorSelOverFlags::Toggle & eFlags ) ? m_vSavePos.back().nNode - : GetMark()->nNode.GetIndex(); + : GetMark()->GetNodeIndex(); const sal_Int32 nRefContentIdx = ( SwCursorSelOverFlags::Toggle & eFlags ) ? m_vSavePos.back().nContent - : GetMark()->nContent.GetIndex(); + : GetMark()->GetContentIndex(); const bool bIsForwardSelection = - nRefNodeIdx < GetPoint()->nNode.GetIndex() - || ( nRefNodeIdx == GetPoint()->nNode.GetIndex() - && nRefContentIdx < GetPoint()->nContent.GetIndex() ); + nRefNodeIdx < GetPoint()->GetNodeIndex() + || ( nRefNodeIdx == GetPoint()->GetNodeIndex() + && nRefContentIdx < GetPoint()->GetContentIndex() ); if ( pInputFieldTextAttrAtPoint != nullptr ) { const sal_Int32 nNewPointPos = bIsForwardSelection ? *(pInputFieldTextAttrAtPoint->End()) : pInputFieldTextAttrAtPoint->GetStart(); - SwTextNode* pTextNdAtPoint = GetPoint()->nNode.GetNode().GetTextNode(); - GetPoint()->nContent.Assign( pTextNdAtPoint, nNewPointPos ); + GetPoint()->SetContent( nNewPointPos ); } if ( pInputFieldTextAttrAtMark != nullptr ) { const sal_Int32 nNewMarkPos = bIsForwardSelection ? pInputFieldTextAttrAtMark->GetStart() : *(pInputFieldTextAttrAtMark->End()); - SwTextNode* pTextNdAtMark = GetMark()->nNode.GetNode().GetTextNode(); - GetMark()->nContent.Assign( pTextNdAtMark, nNewMarkPos ); + GetMark()->SetContent( nNewMarkPos ); } } } - const SwTableNode* pPtNd = GetPoint()->nNode.GetNode().FindTableNode(); - const SwTableNode* pMrkNd = GetMark()->nNode.GetNode().FindTableNode(); + const SwTableNode* pPtNd = GetPoint()->GetNode().FindTableNode(); + const SwTableNode* pMrkNd = GetMark()->GetNode().FindTableNode(); // both in no or in same table node if( ( !pMrkNd && !pPtNd ) || pPtNd == pMrkNd ) return false; @@ -501,26 +497,26 @@ bool SwCursor::IsSelOvr( SwCursorSelOverFlags eFlags ) // Only Point in Table then go behind/in front of table if (SwCursorSelOverFlags::ChangePos & eFlags) { - bool bSelTop = GetPoint()->nNode.GetIndex() < + bool bSelTop = GetPoint()->GetNodeIndex() < ((SwCursorSelOverFlags::Toggle & eFlags) - ? m_vSavePos.back().nNode : GetMark()->nNode.GetIndex()); + ? m_vSavePos.back().nNode : GetMark()->GetNodeIndex()); do { // loop for table after table - sal_uLong nSEIdx = pPtNd->EndOfSectionIndex(); - sal_uLong nSttEndTable = nSEIdx + 1; + SwNodeOffset nSEIdx = pPtNd->EndOfSectionIndex(); + SwNodeOffset nSttEndTable = nSEIdx + 1; if( bSelTop ) nSttEndTable = rNds[ nSEIdx ]->StartOfSectionIndex() - 1; - GetPoint()->nNode = nSttEndTable; - const SwNode* pMyNd = &(GetNode()); + GetPoint()->Assign( nSttEndTable ); + const SwNode* pMyNd = &(GetPointNode()); if( pMyNd->IsSectionNode() || ( pMyNd->IsEndNode() && pMyNd->StartOfSectionNode()->IsSectionNode() ) ) { pMyNd = bSelTop - ? SwNodes::GoPrevSection( &GetPoint()->nNode,true,false ) - : rNds.GoNextSection( &GetPoint()->nNode,true,false ); + ? SwNodes::GoPrevSection( GetPoint(),true,false ) + : SwNodes::GoNextSection( GetPoint(),true,false ); /* #i12312# Handle failure of Go{Prev|Next}Section */ if ( nullptr == pMyNd) @@ -533,8 +529,8 @@ bool SwCursor::IsSelOvr( SwCursorSelOverFlags eFlags ) // we permit these if( pMyNd->IsContentNode() && - ::CheckNodesRange( GetMark()->nNode, - GetPoint()->nNode, true )) + ::CheckNodesRange( GetMark()->GetNode(), + GetPoint()->GetNode(), true )) { // table in table const SwTableNode* pOuterTableNd = pMyNd->FindTableNode(); @@ -543,7 +539,7 @@ bool SwCursor::IsSelOvr( SwCursorSelOverFlags eFlags ) else { SwContentNode* pCNd = const_cast<SwContentNode*>(static_cast<const SwContentNode*>(pMyNd)); - GetPoint()->nContent.Assign( pCNd, bSelTop ? pCNd->Len() : 0 ); + GetPoint()->SetContent( bSelTop ? pCNd->Len() : 0 ); return false; } } @@ -567,7 +563,7 @@ bool SwCursor::IsSelOvr( SwCursorSelOverFlags eFlags ) bool SwCursor::IsInProtectTable( bool bMove, bool bChgCursor ) { - SwContentNode* pCNd = GetContentNode(); + SwContentNode* pCNd = GetPointContentNode(); if( !pCNd ) return false; @@ -577,7 +573,7 @@ bool SwCursor::IsInProtectTable( bool bMove, bool bChgCursor ) return false; // Current position == last save position? - if (m_vSavePos.back().nNode == GetPoint()->nNode.GetIndex()) + if (m_vSavePos.back().nNode == GetPoint()->GetNodeIndex()) return false; // Check for covered cell: @@ -612,12 +608,12 @@ bool SwCursor::IsInProtectTable( bool bMove, bool bChgCursor ) } // We are in a protected table cell. Traverse top to bottom? - if (m_vSavePos.back().nNode < GetPoint()->nNode.GetIndex()) + if (m_vSavePos.back().nNode < GetPoint()->GetNodeIndex()) { // search next valid box // if there is another StartNode after the EndNode of a cell then // there is another cell - SwNodeIndex aCellStt( *GetNode().FindTableBoxStartNode()->EndOfSectionNode(), 1 ); + SwNodeIndex aCellStt( *GetPointNode().FindTableBoxStartNode()->EndOfSectionNode(), 1 ); bool bProt = true; GoNextCell: for (;;) { @@ -626,7 +622,7 @@ GoNextCell: ++aCellStt; pCNd = aCellStt.GetNode().GetContentNode(); if( !pCNd ) - pCNd = aCellStt.GetNodes().GoNext( &aCellStt ); + pCNd = SwNodes::GoNext(&aCellStt); bProt = pCNd->IsProtect(); if( !bProt ) break; @@ -636,11 +632,11 @@ GoNextCell: SetNextCursor: if( !bProt ) // found free cell { - GetPoint()->nNode = aCellStt; - SwContentNode* pTmpCNd = GetContentNode(); + GetPoint()->Assign( aCellStt ); + SwContentNode* pTmpCNd = GetPointContentNode(); if( pTmpCNd ) { - GetPoint()->nContent.Assign( pTmpCNd, 0 ); + GetPoint()->SetContent( 0 ); return false; } return IsSelOvr( SwCursorSelOverFlags::Toggle | @@ -656,8 +652,11 @@ SetNextCursor: RestoreSavePos(); return true; } - else if( pNd->IsTableNode() && aCellStt++ ) + else if( pNd->IsTableNode() ) + { + ++aCellStt; goto GoNextCell; + } bProt = false; // index is now on a content node goto SetNextCursor; @@ -667,7 +666,7 @@ SetNextCursor: { // if there is another EndNode in front of the StartNode than there // exists a previous cell - SwNodeIndex aCellStt( *GetNode().FindTableBoxStartNode(), -1 ); + SwNodeIndex aCellStt( *GetPointNode().FindTableBoxStartNode(), -1 ); SwNode* pNd; bool bProt = true; GoPrevCell: @@ -678,7 +677,7 @@ GoPrevCell: aCellStt.Assign( *pNd->StartOfSectionNode(), +1 ); pCNd = aCellStt.GetNode().GetContentNode(); if( !pCNd ) - pCNd = pNd->GetNodes().GoNext( &aCellStt ); + pCNd = SwNodes::GoNext(&aCellStt); bProt = pCNd->IsProtect(); if( !bProt ) break; @@ -688,11 +687,11 @@ GoPrevCell: SetPrevCursor: if( !bProt ) // found free cell { - GetPoint()->nNode = aCellStt; - SwContentNode* pTmpCNd = GetContentNode(); + GetPoint()->Assign( aCellStt ); + SwContentNode* pTmpCNd = GetPointContentNode(); if( pTmpCNd ) { - GetPoint()->nContent.Assign( pTmpCNd, 0 ); + GetPoint()->SetContent( 0 ); return false; } return IsSelOvr( SwCursorSelOverFlags::Toggle | @@ -708,8 +707,11 @@ SetPrevCursor: RestoreSavePos(); return true; } - else if( pNd->StartOfSectionNode()->IsTableNode() && aCellStt-- ) + else if( pNd->StartOfSectionNode()->IsTableNode() ) + { + --aCellStt; goto GoPrevCell; + } bProt = false; // index is now on a content node goto SetPrevCursor; @@ -721,7 +723,7 @@ bool SwCursor::IsAtValidPos( bool bPoint ) const { const SwDoc& rDoc = GetDoc(); const SwPosition* pPos = bPoint ? GetPoint() : GetMark(); - const SwNode* pNd = &pPos->nNode.GetNode(); + const SwNode* pNd = &pPos->GetNode(); if( pNd->IsContentNode() && !static_cast<const SwContentNode*>(pNd)->getLayoutFrame( rDoc.getIDocumentLayoutAccess().GetCurrentLayout() ) && !dynamic_cast<const SwUnoCursor*>(this) ) @@ -760,7 +762,7 @@ SwMoveFnCollection const & SwCursor::MakeFindRange( SwDocPositions nStart, ? fnMoveForward : fnMoveBackward; } -static sal_uLong lcl_FindSelection( SwFindParas& rParas, SwCursor* pCurrentCursor, +static sal_Int32 lcl_FindSelection( SwFindParas& rParas, SwCursor* pCurrentCursor, SwMoveFnCollection const & fnMove, SwCursor*& pFndRing, SwPaM& aRegion, FindRanges eFndRngs, bool bInReadOnly, bool& bCancel ) @@ -768,7 +770,7 @@ static sal_uLong lcl_FindSelection( SwFindParas& rParas, SwCursor* pCurrentCurso SwDoc& rDoc = pCurrentCursor->GetDoc(); bool const bDoesUndo = rDoc.GetIDocumentUndoRedo().DoesUndo(); int nFndRet = 0; - sal_uLong nFound = 0; + sal_Int32 nFound = 0; const bool bSrchBkwrd = &fnMove == &fnMoveBackward; SwPaM *pTmpCursor = pCurrentCursor, *pSaveCursor = pCurrentCursor; std::unique_ptr<SvxSearchItem> xSearchItem; @@ -892,28 +894,27 @@ static bool lcl_MakeSelFwrd( const SwNode& rSttNd, const SwNode& rEndNd, if( rSttNd.GetIndex() + 1 == rEndNd.GetIndex() ) return false; - SwNodes& rNds = rPam.GetDoc().GetNodes(); rPam.DeleteMark(); SwContentNode* pCNd; if( !bFirst ) { - rPam.GetPoint()->nNode = rSttNd; - pCNd = rNds.GoNext( &rPam.GetPoint()->nNode ); + rPam.GetPoint()->Assign(rSttNd); + pCNd = SwNodes::GoNext(rPam.GetPoint()); if( !pCNd ) return false; - pCNd->MakeStartIndex( &rPam.GetPoint()->nContent ); + rPam.GetPoint()->AssignStartIndex(*pCNd); } - else if( rSttNd.GetIndex() > rPam.GetPoint()->nNode.GetIndex() || - rPam.GetPoint()->nNode.GetIndex() >= rEndNd.GetIndex() ) + else if( rSttNd.GetIndex() > rPam.GetPoint()->GetNodeIndex() || + rPam.GetPoint()->GetNodeIndex() >= rEndNd.GetIndex() ) // not in this section return false; rPam.SetMark(); - rPam.GetPoint()->nNode = rEndNd; - pCNd = SwNodes::GoPrevious( &rPam.GetPoint()->nNode ); + rPam.GetPoint()->Assign(rEndNd); + pCNd = SwNodes::GoPrevious(rPam.GetPoint(), true); if( !pCNd ) return false; - pCNd->MakeEndIndex( &rPam.GetPoint()->nContent ); + rPam.GetPoint()->AssignEndIndex(*pCNd); return *rPam.GetMark() < *rPam.GetPoint(); } @@ -924,34 +925,33 @@ static bool lcl_MakeSelBkwrd( const SwNode& rSttNd, const SwNode& rEndNd, if( rEndNd.GetIndex() + 1 == rSttNd.GetIndex() ) return false; - SwNodes& rNds = rPam.GetDoc().GetNodes(); rPam.DeleteMark(); SwContentNode* pCNd; if( !bFirst ) { - rPam.GetPoint()->nNode = rSttNd; - pCNd = SwNodes::GoPrevious( &rPam.GetPoint()->nNode ); + rPam.GetPoint()->Assign(rSttNd); + pCNd = SwNodes::GoPrevious(rPam.GetPoint(), true); if( !pCNd ) return false; - pCNd->MakeEndIndex( &rPam.GetPoint()->nContent ); + rPam.GetPoint()->AssignEndIndex(*pCNd); } - else if( rEndNd.GetIndex() > rPam.GetPoint()->nNode.GetIndex() || - rPam.GetPoint()->nNode.GetIndex() >= rSttNd.GetIndex() ) + else if( rEndNd.GetIndex() > rPam.GetPoint()->GetNodeIndex() || + rPam.GetPoint()->GetNodeIndex() >= rSttNd.GetIndex() ) return false; // not in this section rPam.SetMark(); - rPam.GetPoint()->nNode = rEndNd; - pCNd = rNds.GoNext( &rPam.GetPoint()->nNode ); + rPam.GetPoint()->Assign(rEndNd); + pCNd = SwNodes::GoNext(rPam.GetPoint()); if( !pCNd ) return false; - pCNd->MakeStartIndex( &rPam.GetPoint()->nContent ); + rPam.GetPoint()->SetContent(0); return *rPam.GetPoint() < *rPam.GetMark(); } // this method "searches" for all use cases because in SwFindParas is always the // correct parameters and respective search method -sal_uLong SwCursor::FindAll( SwFindParas& rParas, +sal_Int32 SwCursor::FindAll( SwFindParas& rParas, SwDocPositions nStart, SwDocPositions nEnd, FindRanges eFndRngs, bool& bCancel ) { @@ -962,7 +962,7 @@ sal_uLong SwCursor::FindAll( SwFindParas& rParas, SwPaM aRegion( *GetPoint() ); SwMoveFnCollection const & fnMove = MakeFindRange( nStart, nEnd, &aRegion ); - sal_uLong nFound = 0; + sal_Int32 nFound = 0; const bool bMvBkwrd = &fnMove == &fnMoveBackward; bool bInReadOnly = IsReadOnlyAvailable(); std::unique_ptr<SvxSearchItem> xSearchItem; @@ -1003,11 +1003,11 @@ sal_uLong SwCursor::FindAll( SwFindParas& rParas, ? lcl_MakeSelBkwrd( rNds.GetEndOfExtras(), *rNds.GetEndOfPostIts().StartOfSectionNode(), *this, rNds.GetEndOfExtras().GetIndex() >= - GetPoint()->nNode.GetIndex() ) + GetPoint()->GetNodeIndex() ) : lcl_MakeSelFwrd( *rNds.GetEndOfPostIts().StartOfSectionNode(), rNds.GetEndOfExtras(), *this, rNds.GetEndOfExtras().GetIndex() >= - GetPoint()->nNode.GetIndex() )) + GetPoint()->GetNodeIndex() )) { nFound = lcl_FindSelection( rParas, this, fnMove, pFndRing, aRegion, eFndRngs, bInReadOnly, bCancel ); @@ -1096,7 +1096,7 @@ sal_uLong SwCursor::FindAll( SwFindParas& rParas, nFound = rParas.DoFind(*this, fnMove, aRegion, bInReadOnly, xSearchItem) ? 1 : 0; if (0 != nFound && bMarkPos) - *GetMark() = aMarkPos; + *GetMark() = std::move(aMarkPos); } if( nFound && SwCursor::IsSelOvr( SwCursorSelOverFlags::Toggle ) ) @@ -1113,30 +1113,30 @@ void SwCursor::FillFindPos( SwDocPositions ePos, SwPosition& rPos ) const switch( ePos ) { case SwDocPositions::Start: - rPos.nNode = *rNds.GetEndOfContent().StartOfSectionNode(); - pCNd = rNds.GoNext( &rPos.nNode ); + rPos.Assign(*rNds.GetEndOfContent().StartOfSectionNode()); + pCNd = SwNodes::GoNext(&rPos); break; case SwDocPositions::End: - rPos.nNode = rNds.GetEndOfContent(); - pCNd = SwNodes::GoPrevious( &rPos.nNode ); + rPos.Assign(rNds.GetEndOfContent()); + pCNd = SwNodes::GoPrevious( &rPos ); bIsStart = false; break; case SwDocPositions::OtherStart: - rPos.nNode = *rNds[ sal_uLong(0) ]; - pCNd = rNds.GoNext( &rPos.nNode ); + rPos.Assign( *rNds[ SwNodeOffset(0) ] ); + pCNd = SwNodes::GoNext(&rPos); break; case SwDocPositions::OtherEnd: - rPos.nNode = *rNds.GetEndOfContent().StartOfSectionNode(); - pCNd = SwNodes::GoPrevious( &rPos.nNode ); + rPos.Assign( *rNds.GetEndOfContent().StartOfSectionNode() ); + pCNd = SwNodes::GoPrevious( &rPos ); bIsStart = false; break; default: rPos = *GetPoint(); } - if( pCNd ) + if( pCNd && !bIsStart ) { - rPos.nContent.Assign( pCNd, bIsStart ? 0 : pCNd->Len() ); + rPos.AssignEndIndex( *pCNd ); } } @@ -1212,10 +1212,10 @@ bool SwCursor::SelectWord( SwViewShell const * pViewShell, const Point* pPt ) bool SwCursor::IsStartWordWT(sal_Int16 nWordType, SwRootFrame const*const pLayout) const { bool bRet = false; - SwTextNode* pTextNd = GetNode().GetTextNode(); + SwTextNode* pTextNd = GetPointNode().GetTextNode(); if (pTextNd) { - sal_Int32 nPtPos = GetPoint()->nContent.GetIndex(); + sal_Int32 nPtPos = GetPoint()->GetContentIndex(); HideWrapper w(pLayout, pTextNd, nPtPos); @@ -1230,10 +1230,10 @@ bool SwCursor::IsStartWordWT(sal_Int16 nWordType, SwRootFrame const*const pLayou bool SwCursor::IsEndWordWT(sal_Int16 nWordType, SwRootFrame const*const pLayout) const { bool bRet = false; - SwTextNode* pTextNd = GetNode().GetTextNode(); + SwTextNode* pTextNd = GetPointNode().GetTextNode(); if (pTextNd) { - sal_Int32 nPtPos = GetPoint()->nContent.GetIndex(); + sal_Int32 nPtPos = GetPoint()->GetContentIndex(); HideWrapper w(pLayout, pTextNd, nPtPos); @@ -1249,10 +1249,10 @@ bool SwCursor::IsEndWordWT(sal_Int16 nWordType, SwRootFrame const*const pLayout) bool SwCursor::IsInWordWT(sal_Int16 nWordType, SwRootFrame const*const pLayout) const { bool bRet = false; - SwTextNode* pTextNd = GetNode().GetTextNode(); + SwTextNode* pTextNd = GetPointNode().GetTextNode(); if (pTextNd) { - sal_Int32 nPtPos = GetPoint()->nContent.GetIndex(); + sal_Int32 nPtPos = GetPoint()->GetContentIndex(); { HideWrapper w(pLayout, pTextNd, nPtPos); @@ -1280,8 +1280,8 @@ bool SwCursor::IsInWordWT(sal_Int16 nWordType, SwRootFrame const*const pLayout) bool SwCursor::IsStartEndSentence(bool bEnd, SwRootFrame const*const pLayout) const { bool bRet = bEnd ? - GetContentNode() && GetPoint()->nContent == GetContentNode()->Len() : - GetPoint()->nContent.GetIndex() == 0; + GetPointContentNode() && GetPoint()->GetContentIndex() == GetPointContentNode()->Len() : + GetPoint()->GetContentIndex() == 0; if ((pLayout != nullptr && pLayout->HasMergedParas()) || !bRet) { @@ -1296,11 +1296,11 @@ bool SwCursor::IsStartEndSentence(bool bEnd, SwRootFrame const*const pLayout) co bool SwCursor::GoStartWordWT(sal_Int16 nWordType, SwRootFrame const*const pLayout) { bool bRet = false; - SwTextNode* pTextNd = GetNode().GetTextNode(); + SwTextNode* pTextNd = GetPointNode().GetTextNode(); if (pTextNd) { SwCursorSaveState aSave( *this ); - sal_Int32 nPtPos = GetPoint()->nContent.GetIndex(); + sal_Int32 nPtPos = GetPoint()->GetContentIndex(); { HideWrapper w(pLayout, pTextNd, nPtPos); @@ -1314,7 +1314,7 @@ bool SwCursor::GoStartWordWT(sal_Int16 nWordType, SwRootFrame const*const pLayou if (nPtPos < pTextNd->GetText().getLength() && nPtPos >= 0) { - *GetPoint() = SwPosition(*pTextNd, nPtPos); + GetPoint()->Assign(*pTextNd, nPtPos); if( !IsSelOvr() ) bRet = true; } @@ -1325,11 +1325,11 @@ bool SwCursor::GoStartWordWT(sal_Int16 nWordType, SwRootFrame const*const pLayou bool SwCursor::GoEndWordWT(sal_Int16 nWordType, SwRootFrame const*const pLayout) { bool bRet = false; - SwTextNode* pTextNd = GetNode().GetTextNode(); + SwTextNode* pTextNd = GetPointNode().GetTextNode(); if (pTextNd) { SwCursorSaveState aSave( *this ); - sal_Int32 nPtPos = GetPoint()->nContent.GetIndex(); + sal_Int32 nPtPos = GetPoint()->GetContentIndex(); { HideWrapper w(pLayout, pTextNd, nPtPos); @@ -1342,9 +1342,9 @@ bool SwCursor::GoEndWordWT(sal_Int16 nWordType, SwRootFrame const*const pLayout) } if (nPtPos <= pTextNd->GetText().getLength() && nPtPos >= 0 && - GetPoint()->nContent.GetIndex() != nPtPos ) + GetPoint()->GetContentIndex() != nPtPos ) { - *GetPoint() = SwPosition(*pTextNd, nPtPos); + GetPoint()->Assign(*pTextNd, nPtPos); if( !IsSelOvr() ) bRet = true; } @@ -1355,11 +1355,11 @@ bool SwCursor::GoEndWordWT(sal_Int16 nWordType, SwRootFrame const*const pLayout) bool SwCursor::GoNextWordWT(sal_Int16 nWordType, SwRootFrame const*const pLayout) { bool bRet = false; - SwTextNode* pTextNd = GetNode().GetTextNode(); + SwTextNode* pTextNd = GetPointNode().GetTextNode(); if (pTextNd) { SwCursorSaveState aSave( *this ); - sal_Int32 nPtPos = GetPoint()->nContent.GetIndex(); + sal_Int32 nPtPos = GetPoint()->GetContentIndex(); { HideWrapper w(pLayout, pTextNd, nPtPos); @@ -1372,7 +1372,7 @@ bool SwCursor::GoNextWordWT(sal_Int16 nWordType, SwRootFrame const*const pLayout if (nPtPos <= pTextNd->GetText().getLength() && nPtPos >= 0) { - *GetPoint() = SwPosition(*pTextNd, nPtPos); + GetPoint()->Assign(*pTextNd, nPtPos); if( !IsSelOvr() ) bRet = true; } @@ -1383,11 +1383,11 @@ bool SwCursor::GoNextWordWT(sal_Int16 nWordType, SwRootFrame const*const pLayout bool SwCursor::GoPrevWordWT(sal_Int16 nWordType, SwRootFrame const*const pLayout) { bool bRet = false; - SwTextNode* pTextNd = GetNode().GetTextNode(); + SwTextNode* pTextNd = GetPointNode().GetTextNode(); if (pTextNd) { SwCursorSaveState aSave( *this ); - sal_Int32 nPtPos = GetPoint()->nContent.GetIndex(); + sal_Int32 nPtPos = GetPoint()->GetContentIndex(); { HideWrapper w(pLayout, pTextNd, nPtPos); @@ -1407,7 +1407,7 @@ bool SwCursor::GoPrevWordWT(sal_Int16 nWordType, SwRootFrame const*const pLayout if (nPtPos < pTextNd->GetText().getLength() && nPtPos >= 0) { - *GetPoint() = SwPosition(*pTextNd, nPtPos); + GetPoint()->Assign(*pTextNd, nPtPos); if( !IsSelOvr() ) bRet = true; } @@ -1429,32 +1429,31 @@ bool SwCursor::SelectWordWT( SwViewShell const * pViewShell, sal_Int16 nWordType pLayout->GetModelPositionForViewPoint( GetPoint(), aPt ); } - SwTextNode* pTextNd = GetNode().GetTextNode(); + SwTextNode* pTextNd = GetPointNode().GetTextNode(); if (pTextNd) { // Should we select the whole fieldmark? const IDocumentMarkAccess* pMarksAccess = GetDoc().getIDocumentMarkAccess( ); - sw::mark::IFieldmark const*const pMark(pMarksAccess->getFieldmarkFor(*GetPoint())); + sw::mark::IFieldmark const*const pMark(pMarksAccess->getInnerFieldmarkFor(*GetPoint())); if (pMark && (IDocumentMarkAccess::GetType(*pMark) == IDocumentMarkAccess::MarkType::TEXT_FIELDMARK || IDocumentMarkAccess::GetType(*pMark) == IDocumentMarkAccess::MarkType::DATE_FIELDMARK)) { *GetPoint() = sw::mark::FindFieldSep(*pMark); - ++GetPoint()->nContent; // Don't select the separator + GetPoint()->AdjustContent(+1); // Don't select the separator const SwPosition& rEnd = pMark->GetMarkEnd(); assert(pMark->GetMarkEnd() != *GetPoint()); SetMark(); - GetMark()->nNode = rEnd.nNode; - GetMark()->nContent = rEnd.nContent; - --GetMark()->nContent; // Don't select the end delimiter + *GetMark() = rEnd; + GetMark()->AdjustContent(-1); // Don't select the end delimiter bRet = true; } else { bool bForward = true; - sal_Int32 nPtPos = GetPoint()->nContent.GetIndex(); + sal_Int32 nPtPos = GetPoint()->GetContentIndex(); HideWrapper w(pViewShell->GetLayout(), pTextNd, nPtPos); @@ -1490,22 +1489,22 @@ bool SwCursor::SelectWordWT( SwViewShell const * pViewShell, sal_Int16 nWordType if( aBndry.startPos != aBndry.endPos ) { - *GetPoint() = SwPosition(*pEndNode, nEndIndex); + GetPoint()->Assign(*pEndNode, nEndIndex); if( !IsSelOvr() ) { SetMark(); - *GetMark() = SwPosition(*pStartNode, nStartIndex); + GetMark()->Assign(*pStartNode, nStartIndex); if (sw::mark::IMark* pAnnotationMark = pMarksAccess->getAnnotationMarkFor(*GetPoint())) { // An annotation mark covers the selected word. Check // if it covers only the word: in that case we select // the comment anchor as well. - bool bStartMatch = GetMark()->nNode == pAnnotationMark->GetMarkStart().nNode && - GetMark()->nContent == pAnnotationMark->GetMarkStart().nContent; - bool bEndMatch = GetPoint()->nNode == pAnnotationMark->GetMarkEnd().nNode && - GetPoint()->nContent.GetIndex() + 1 == pAnnotationMark->GetMarkEnd().nContent.GetIndex(); + bool bStartMatch = GetMark()->GetNode() == pAnnotationMark->GetMarkStart().GetNode() && + GetMark()->GetContentIndex() == pAnnotationMark->GetMarkStart().GetContentIndex(); + bool bEndMatch = GetPoint()->GetNode() == pAnnotationMark->GetMarkEnd().GetNode() && + GetPoint()->GetContentIndex() + 1 == pAnnotationMark->GetMarkEnd().GetContentIndex(); if (bStartMatch && bEndMatch) - ++GetPoint()->nContent; + GetPoint()->AdjustContent(+1); } if( !IsSelOvr() ) bRet = true; @@ -1537,7 +1536,7 @@ static OUString lcl_MaskDeletedRedlines( const SwTextNode* pTextNd ) for ( ; nAct < rDoc.getIDocumentRedlineAccess().GetRedlineTable().size(); nAct++ ) { const SwRangeRedline* pRed = rDoc.getIDocumentRedlineAccess().GetRedlineTable()[ nAct ]; - if ( pRed->Start()->nNode > pTextNd->GetIndex() ) + if ( pRed->Start()->GetNode() > *pTextNd ) break; if( RedlineType::Delete == pRed->GetType() ) @@ -1546,7 +1545,7 @@ static OUString lcl_MaskDeletedRedlines( const SwTextNode* pTextNd ) pRed->CalcStartEnd( pTextNd->GetIndex(), nStart, nEnd ); while ( nStart < nEnd && nStart < sNodeText.getLength() ) - sNodeText = sNodeText.replaceAt( nStart++, 1, OUString(CH_TXTATR_INWORD) ); + sNodeText = sNodeText.replaceAt( nStart++, 1, rtl::OUStringChar(CH_TXTATR_INWORD) ); } } } @@ -1558,13 +1557,13 @@ static OUString lcl_MaskDeletedRedlines( const SwTextNode* pTextNd ) bool SwCursor::GoSentence(SentenceMoveType eMoveType, SwRootFrame const*const pLayout) { bool bRet = false; - SwTextNode* pTextNd = GetNode().GetTextNode(); + SwTextNode* pTextNd = GetPointNode().GetTextNode(); if (pTextNd) { OUString const sNodeText(lcl_MaskDeletedRedlines(pTextNd)); SwCursorSaveState aSave( *this ); - sal_Int32 nPtPos = GetPoint()->nContent.GetIndex(); + sal_Int32 nPtPos = GetPoint()->GetContentIndex(); { HideWrapper w(pLayout, pTextNd, nPtPos, &sNodeText); @@ -1618,7 +1617,7 @@ bool SwCursor::GoSentence(SentenceMoveType eMoveType, SwRootFrame const*const pL // character in the text thus <= ...Len if (nPtPos <= pTextNd->GetText().getLength() && nPtPos >= 0) { - *GetPoint() = SwPosition(*pTextNd, nPtPos); + GetPoint()->Assign(*pTextNd, nPtPos); if( !IsSelOvr() ) bRet = true; } @@ -1626,58 +1625,51 @@ bool SwCursor::GoSentence(SentenceMoveType eMoveType, SwRootFrame const*const pL return bRet; } -bool SwCursor::ExpandToSentenceBorders(SwRootFrame const*const pLayout) +void SwCursor::ExpandToSentenceBorders(SwRootFrame const*const pLayout) { - bool bRes = false; - SwTextNode* pStartNd = Start()->nNode.GetNode().GetTextNode(); - SwTextNode* pEndNd = End()->nNode.GetNode().GetTextNode(); - if (pStartNd && pEndNd) - { - if (!HasMark()) - SetMark(); + SwTextNode* pStartNd = Start()->GetNode().GetTextNode(); + SwTextNode* pEndNd = End()->GetNode().GetTextNode(); + if (!pStartNd || !pEndNd) + return; - OUString sStartText( lcl_MaskDeletedRedlines( pStartNd ) ); - OUString sEndText( pStartNd == pEndNd? sStartText : lcl_MaskDeletedRedlines( pEndNd ) ); + if (!HasMark()) + SetMark(); - SwCursorSaveState aSave( *this ); - sal_Int32 nStartPos = Start()->nContent.GetIndex(); - sal_Int32 nEndPos = End()->nContent.GetIndex(); + OUString sStartText( lcl_MaskDeletedRedlines( pStartNd ) ); + OUString sEndText( pStartNd == pEndNd? sStartText : lcl_MaskDeletedRedlines( pEndNd ) ); - { - HideWrapper w(pLayout, pStartNd, nStartPos, &sStartText); + SwCursorSaveState aSave( *this ); + sal_Int32 nStartPos = Start()->GetContentIndex(); + sal_Int32 nEndPos = End()->GetContentIndex(); - w.m_nPtIndex = g_pBreakIt->GetBreakIter()->beginOfSentence( - *w.m_pText, w.m_nPtIndex, - g_pBreakIt->GetLocale( pStartNd->GetLang( nStartPos ) ) ); - } - { - HideWrapper w(pLayout, pEndNd, nEndPos, &sEndText); + { + HideWrapper w(pLayout, pStartNd, nStartPos, &sStartText); - w.m_nPtIndex = g_pBreakIt->GetBreakIter()->endOfSentence( - *w.m_pText, w.m_nPtIndex, - g_pBreakIt->GetLocale( pEndNd->GetLang( nEndPos ) ) ); - } + w.m_nPtIndex = g_pBreakIt->GetBreakIter()->beginOfSentence( + *w.m_pText, w.m_nPtIndex, + g_pBreakIt->GetLocale( pStartNd->GetLang( nStartPos ) ) ); + } + { + HideWrapper w(pLayout, pEndNd, nEndPos, &sEndText); - // it is allowed to place the PaM just behind the last - // character in the text thus <= ...Len - bool bChanged = false; - if (nStartPos <= pStartNd->GetText().getLength() && nStartPos >= 0) - { - *GetMark() = SwPosition(*pStartNd, nStartPos); - bChanged = true; - } - if (nEndPos <= pEndNd->GetText().getLength() && nEndPos >= 0) - { - *GetPoint() = SwPosition(*pEndNd, nEndPos); - bChanged = true; - } - if (bChanged && !IsSelOvr()) - bRes = true; + w.m_nPtIndex = g_pBreakIt->GetBreakIter()->endOfSentence( + *w.m_pText, w.m_nPtIndex, + g_pBreakIt->GetLocale( pEndNd->GetLang( nEndPos ) ) ); + } + + // it is allowed to place the PaM just behind the last + // character in the text thus <= ...Len + if (nStartPos <= pStartNd->GetText().getLength() && nStartPos >= 0) + { + GetMark()->Assign(*pStartNd, nStartPos); + } + if (nEndPos <= pEndNd->GetText().getLength() && nEndPos >= 0) + { + GetPoint()->Assign(*pEndNd, nEndPos); } - return bRes; } -bool SwTableCursor::LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 /*nMode*/, +bool SwTableCursor::LeftRight( bool bLeft, sal_uInt16 nCnt, SwCursorSkipMode /*nMode*/, bool /*bVisualAllowed*/, bool /*bSkipHidden*/, bool /*bInsertCursor*/, SwRootFrame const*, bool /*isFieldNames*/) { @@ -1692,18 +1684,15 @@ SwCursor::DoSetBidiLevelLeftRight( { // calculate cursor bidi level const SwContentFrame* pSttFrame = nullptr; - SwNode& rNode = GetPoint()->nNode.GetNode(); + SwNode& rNode = GetPoint()->GetNode(); if( rNode.IsTextNode() ) { const SwTextNode& rTNd = *rNode.GetTextNode(); - SwIndex& rIdx = GetPoint()->nContent; - sal_Int32 nPos = rIdx.GetIndex(); + sal_Int32 nPos = GetPoint()->GetContentIndex(); - const SvtCTLOptions& rCTLOptions = SW_MOD()->GetCTLOptions(); - if ( bVisualAllowed && rCTLOptions.IsCTLFontEnabled() && - SvtCTLOptions::MOVEMENT_VISUAL == - rCTLOptions.GetCTLCursorMovement() ) + if ( bVisualAllowed && SvtCTLOptions::IsCTLFontEnabled() && + SvtCTLOptions::MOVEMENT_VISUAL == SvtCTLOptions::GetCTLCursorMovement() ) { // for visual cursor travelling (used in bidi layout) // we first have to convert the logic to a visual position @@ -1743,12 +1732,12 @@ SwCursor::DoSetBidiLevelLeftRight( return pSttFrame; } -bool SwCursor::LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode, +bool SwCursor::LeftRight( bool bLeft, sal_uInt16 nCnt, SwCursorSkipMode nMode, bool bVisualAllowed,bool bSkipHidden, bool bInsertCursor, SwRootFrame const*const pLayout, bool isFieldNames) { // calculate cursor bidi level - SwNode& rNode = GetPoint()->nNode.GetNode(); + SwNode& rNode = GetPoint()->GetNode(); const SwContentFrame* pSttFrame = // may side-effect bLeft! DoSetBidiLevelLeftRight(bLeft, bVisualAllowed, bInsertCursor); @@ -1758,9 +1747,9 @@ bool SwCursor::LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode, SwGoInDoc fnGo; if ( bSkipHidden ) - fnGo = CRSR_SKIP_CELLS == nMode ? GoInContentCellsSkipHidden : GoInContentSkipHidden; + fnGo = SwCursorSkipMode::Cells == nMode ? GoInContentCellsSkipHidden : GoInContentSkipHidden; else - fnGo = CRSR_SKIP_CELLS == nMode ? GoInContentCells : GoInContent; + fnGo = SwCursorSkipMode::Cells == nMode ? GoInContentCells : GoInContent; SwTextFrame const* pFrame(nullptr); if (pLayout) @@ -1777,7 +1766,7 @@ bool SwCursor::LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode, while( nCnt ) { - SwNodeIndex aOldNodeIdx( GetPoint()->nNode ); + SwNodeIndex aOldNodeIdx( GetPoint()->GetNode() ); TextFrameIndex beforeIndex(-1); if (pFrame) @@ -1787,10 +1776,10 @@ bool SwCursor::LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode, if (!bLeft && pLayout && pLayout->GetFieldmarkMode() == sw::FieldmarkMode::ShowResult) { - SwTextNode const*const pNode(GetPoint()->nNode.GetNode().GetTextNode()); + SwTextNode const*const pNode(GetPoint()->GetNode().GetTextNode()); assert(pNode); - if (pNode->Len() != GetPoint()->nContent.GetIndex() - && pNode->GetText()[GetPoint()->nContent.GetIndex()] == CH_TXT_ATR_FIELDSTART) + if (pNode->Len() != GetPoint()->GetContentIndex() + && pNode->GetText()[GetPoint()->GetContentIndex()] == CH_TXT_ATR_FIELDSTART) { IDocumentMarkAccess const& rIDMA(*GetDoc().getIDocumentMarkAccess()); sw::mark::IFieldmark const*const pMark(rIDMA.getFieldmarkAt(*GetPoint())); @@ -1801,23 +1790,25 @@ bool SwCursor::LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode, if ( !Move( fnMove, fnGo ) ) { - SwEditShell* rSh = GetDoc().GetEditShell(); - if (rSh && rSh->GetViewOptions() && - rSh->GetViewOptions()->IsShowOutlineContentVisibilityButton()) + const SwEditShell* pSh = GetDoc().GetEditShell(); + const SwViewOption* pViewOptions = pSh ? pSh->GetViewOptions() : nullptr; + if (pViewOptions && pViewOptions->IsShowOutlineContentVisibilityButton()) + { // Fixes crash that occurs in documents with outline content folded at the end of // the document. When the cursor is at the end of the visible document and // right arrow key is pressed Move fails after moving the cursor to the // end of the document model, which doesn't have a node frame and causes - // wierd numbers to be displayed in the statusbar page number count. Left + // weird numbers to be displayed in the statusbar page number count. Left // arrow, when in this state, causes a crash without RestoredSavePos() added here. RestoreSavePos(); + } break; } if (pFrame) { SwTextFrame const* pNewFrame(static_cast<SwTextFrame const*>( - GetPoint()->nNode.GetNode().GetContentNode()->getLayoutFrame(pLayout))); + GetPoint()->GetNode().GetContentNode()->getLayoutFrame(pLayout))); if (pNewFrame) { while (pNewFrame->GetPrecede()) @@ -1843,10 +1834,10 @@ bool SwCursor::LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode, if (bLeft && pLayout && pLayout->GetFieldmarkMode() == sw::FieldmarkMode::ShowCommand) { - SwTextNode const*const pNode(GetPoint()->nNode.GetNode().GetTextNode()); + SwTextNode const*const pNode(GetPoint()->GetNode().GetTextNode()); assert(pNode); - if (pNode->Len() != GetPoint()->nContent.GetIndex() - && pNode->GetText()[GetPoint()->nContent.GetIndex()] == CH_TXT_ATR_FIELDEND) + if (pNode->Len() != GetPoint()->GetContentIndex() + && pNode->GetText()[GetPoint()->GetContentIndex()] == CH_TXT_ATR_FIELDEND) { IDocumentMarkAccess const& rIDMA(*GetDoc().getIDocumentMarkAccess()); sw::mark::IFieldmark const*const pMark(rIDMA.getFieldmarkAt(*GetPoint())); @@ -1857,10 +1848,10 @@ bool SwCursor::LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode, if (isFieldNames) { - SwTextNode const*const pNode(GetPoint()->nNode.GetNode().GetTextNode()); + SwTextNode const*const pNode(GetPoint()->GetNode().GetTextNode()); assert(pNode); SwTextAttr const*const pInputField(pNode->GetTextAttrAt( - GetPoint()->nContent.GetIndex(), RES_TXTATR_INPUTFIELD, SwTextNode::PARENT)); + GetPoint()->GetContentIndex(), RES_TXTATR_INPUTFIELD, ::sw::GetTextAttrMode::Parent)); if (pInputField) { continue; // skip over input fields @@ -1875,7 +1866,7 @@ bool SwCursor::LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode, { const SwNode* pOldTabBoxSttNode = aOldNodeIdx.GetNode().FindTableBoxStartNode(); const SwTableNode* pOldTabSttNode = pOldTabBoxSttNode ? pOldTabBoxSttNode->FindTableNode() : nullptr; - const SwNode* pNewTabBoxSttNode = GetPoint()->nNode.GetNode().FindTableBoxStartNode(); + const SwNode* pNewTabBoxSttNode = GetPoint()->GetNode().FindTableBoxStartNode(); const SwTableNode* pNewTabSttNode = pNewTabBoxSttNode ? pNewTabBoxSttNode->FindTableNode() : nullptr; const bool bCellChanged = pOldTabSttNode && pNewTabSttNode && @@ -1891,16 +1882,16 @@ bool SwCursor::LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode, { pTableBox = & pTableBox->FindEndOfRowSpan( pOldTabSttNode->GetTable(), - static_cast<sal_uInt16>(pTableBox->getRowSpan() + m_nRowSpanOffset)); - SwNodeIndex& rPtIdx = GetPoint()->nNode; + o3tl::narrowing<sal_uInt16>(pTableBox->getRowSpan() + m_nRowSpanOffset)); + SwPosition& rPtPos = *GetPoint(); SwNodeIndex aNewIdx( *pTableBox->GetSttNd() ); - rPtIdx = aNewIdx; + rPtPos.Assign( aNewIdx ); - GetDoc().GetNodes().GoNextSection( &rPtIdx, false, false ); - SwContentNode* pContentNode = GetContentNode(); + SwNodes::GoNextSection(&rPtPos, false, false); + SwContentNode* pContentNode = GetPointContentNode(); if ( pContentNode ) { - GetPoint()->nContent.Assign( pContentNode, bLeft ? pContentNode->Len() : 0 ); + GetPoint()->SetContent( bLeft ? pContentNode->Len() : 0 ); // Redo the move: if ( !Move( fnMove, fnGo ) ) @@ -1913,7 +1904,7 @@ bool SwCursor::LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode, // Check if I'm inside a covered cell. Correct cursor if necessary and // store covered cell: - const SwNode* pTableBoxStartNode = GetPoint()->nNode.GetNode().FindTableBoxStartNode(); + const SwNode* pTableBoxStartNode = GetPoint()->GetNode().FindTableBoxStartNode(); if ( pTableBoxStartNode ) { const SwTableBox* pTableBox = pTableBoxStartNode->GetTableBox(); @@ -1925,15 +1916,15 @@ bool SwCursor::LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode, // Move cursor to non-covered cell: const SwTableNode* pTableNd = pTableBoxStartNode->FindTableNode(); pTableBox = & pTableBox->FindStartOfRowSpan( pTableNd->GetTable() ); - SwNodeIndex& rPtIdx = GetPoint()->nNode; + SwPosition& rPtPos = *GetPoint(); SwNodeIndex aNewIdx( *pTableBox->GetSttNd() ); - rPtIdx = aNewIdx; + rPtPos.Assign( aNewIdx ); - GetDoc().GetNodes().GoNextSection( &rPtIdx, false, false ); - SwContentNode* pContentNode = GetContentNode(); + SwNodes::GoNextSection(&rPtPos, false, false); + SwContentNode* pContentNode = GetPointContentNode(); if ( pContentNode ) { - GetPoint()->nContent.Assign( pContentNode, bLeft ? pContentNode->Len() : 0 ); + GetPoint()->SetContent( bLeft ? pContentNode->Len() : 0 ); } } } @@ -1943,7 +1934,7 @@ bool SwCursor::LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode, // here come some special rules for visual cursor travelling if ( pSttFrame ) { - SwNode& rTmpNode = GetPoint()->nNode.GetNode(); + SwNode& rTmpNode = GetPoint()->GetNode(); if ( &rTmpNode != &rNode && rTmpNode.IsTextNode() ) { Point aPt; @@ -1972,7 +1963,7 @@ bool SwCursor::LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode, // calculate cursor bidi level: extracted from UpDown() void SwCursor::DoSetBidiLevelUpDown() { - SwNode& rNode = GetPoint()->nNode.GetNode(); + SwNode& rNode = GetPoint()->GetNode(); if ( !rNode.IsTextNode() ) return; @@ -1982,8 +1973,7 @@ void SwCursor::DoSetBidiLevelUpDown() if ( !pSI ) return; - SwIndex& rIdx = GetPoint()->nContent; - const sal_Int32 nPos = rIdx.GetIndex(); + const sal_Int32 nPos = GetPoint()->GetContentIndex(); if (!(nPos && nPos < rNode.GetTextNode()->GetText().getLength())) return; @@ -2010,8 +2000,8 @@ bool SwCursor::UpDown( bool bUp, sal_uInt16 nCnt, // If the point/mark of the table cursor in the same box then set cursor to // beginning of the box - if( pTableCursor && GetNode().StartOfSectionNode() == - GetNode( false ).StartOfSectionNode() ) + if( pTableCursor && GetPointNode().StartOfSectionNode() == + GetMarkNode().StartOfSectionNode() ) { if ( End() != GetPoint() ) Exchange(); @@ -2023,7 +2013,7 @@ bool SwCursor::UpDown( bool bUp, sal_uInt16 nCnt, if( pPt ) aPt = *pPt; std::pair<Point, bool> const temp(aPt, true); - SwContentFrame* pFrame = GetContentNode()->getLayoutFrame(&rLayout, GetPoint(), &temp); + SwContentFrame* pFrame = GetPointContentNode()->getLayoutFrame(&rLayout, GetPoint(), &temp); if( pFrame ) { @@ -2051,26 +2041,26 @@ bool SwCursor::UpDown( bool bUp, sal_uInt16 nCnt, // than one paragraph. If we want to go down, we have to set the // point to the last frame in the table box. This is only necessary // if we do not already have a table selection - const SwStartNode* pTableNd = GetNode().FindTableBoxStartNode(); + const SwStartNode* pTableNd = GetPointNode().FindTableBoxStartNode(); OSL_ENSURE( pTableNd, "pTableCursor without SwTableNode?" ); if ( pTableNd ) // safety first { const SwNode* pEndNd = pTableNd->EndOfSectionNode(); - GetPoint()->nNode = *pEndNd; + GetPoint()->Assign( *pEndNd ); pTableCursor->Move( fnMoveBackward, GoInNode ); std::pair<Point, bool> const tmp(aPt, true); - pFrame = GetContentNode()->getLayoutFrame(&rLayout, GetPoint(), &tmp); + pFrame = GetPointContentNode()->getLayoutFrame(&rLayout, GetPoint(), &tmp); } } while( nCnt && (bUp ? pFrame->UnitUp( this, nUpDownX, bInReadOnly ) : pFrame->UnitDown( this, nUpDownX, bInReadOnly ) ) && - CheckNodesRange( aOldPos.nNode, GetPoint()->nNode, bChkRange )) + CheckNodesRange( aOldPos.GetNode(), GetPoint()->GetNode(), bChkRange )) { std::pair<Point, bool> const tmp(aPt, true); - pFrame = GetContentNode()->getLayoutFrame(&rLayout, GetPoint(), &tmp); + pFrame = GetPointContentNode()->getLayoutFrame(&rLayout, GetPoint(), &tmp); --nCnt; } @@ -2083,7 +2073,7 @@ bool SwCursor::UpDown( bool bUp, sal_uInt16 nCnt, // try to position the cursor at half of the char-rect's height DisableCallbackAction a(rLayout); std::pair<Point, bool> const tmp(aPt, true); - pFrame = GetContentNode()->getLayoutFrame(&rLayout, GetPoint(), &tmp); + pFrame = GetPointContentNode()->getLayoutFrame(&rLayout, GetPoint(), &tmp); SwCursorMoveState eTmpState( CursorMoveState::UpDown ); eTmpState.m_bSetInReadOnly = bInReadOnly; SwRect aTmpRect; @@ -2104,24 +2094,27 @@ bool SwCursor::UpDown( bool bUp, sal_uInt16 nCnt, } bRet = !IsSelOvr( SwCursorSelOverFlags::Toggle | SwCursorSelOverFlags::ChangePos ); } - else + else if (!pFrame->IsInFootnote()) // tdf#150457 Jump to the begin/end + // of the first/last line only if the + // cursor is not inside a footnote { sal_Int32 nOffset = 0; // Jump to beginning or end of line when the cursor at first or last line. if(!bUp) { - SwTextNode* pTextNd = GetPoint()->nNode.GetNode().GetTextNode(); + SwTextNode* pTextNd = GetPoint()->GetNode().GetTextNode(); if (pTextNd) nOffset = pTextNd->GetText().getLength(); } - const SwPosition aPos(*GetContentNode(), nOffset); + const SwPosition aPos(*GetPointContentNode(), nOffset); //if cursor has already been at start or end of file, //Update cursor to change nUpDownX. - if ( aOldPos.nContent.GetIndex() == nOffset ) + if ( aOldPos.GetContentIndex() == nOffset ) { - GetDoc().GetEditShell()->UpdateCursor(); + if (SwEditShell* pSh = GetDoc().GetEditShell()) + pSh->UpdateCursor(); bRet = false; } else{ @@ -2130,6 +2123,8 @@ bool SwCursor::UpDown( bool bUp, sal_uInt16 nCnt, } } + else + *GetPoint() = aOldPos; DoSetBidiLevelUpDown(); // calculate cursor bidi level } @@ -2140,7 +2135,7 @@ bool SwCursor::LeftRightMargin(SwRootFrame const& rLayout, bool bLeft, bool bAPI { Point aPt; std::pair<Point, bool> const tmp(aPt, true); - SwContentFrame const*const pFrame = GetContentNode()->getLayoutFrame( + SwContentFrame const*const pFrame = GetPointContentNode()->getLayoutFrame( &rLayout, GetPoint(), &tmp); // calculate cursor bidi level @@ -2158,13 +2153,13 @@ bool SwCursor::IsAtLeftRightMargin(SwRootFrame const& rLayout, bool bLeft, bool bool bRet = false; Point aPt; std::pair<Point, bool> const tmp(aPt, true); - SwContentFrame const*const pFrame = GetContentNode()->getLayoutFrame( + SwContentFrame const*const pFrame = GetPointContentNode()->getLayoutFrame( &rLayout, GetPoint(), &tmp); if( pFrame ) { SwPaM aPam( *GetPoint() ); - if( !bLeft && aPam.GetPoint()->nContent.GetIndex() ) - --aPam.GetPoint()->nContent; + if( !bLeft && aPam.GetPoint()->GetContentIndex() ) + aPam.GetPoint()->AdjustContent(-1); bRet = (bLeft ? pFrame->LeftMargin( &aPam ) : pFrame->RightMargin( &aPam, bAPI )) && (!pFrame->IsTextFrame() @@ -2191,18 +2186,18 @@ bool SwCursor::SttEndDoc( bool bStt ) bool SwCursor::GoPrevNextCell( bool bNext, sal_uInt16 nCnt ) { - const SwTableNode* pTableNd = GetPoint()->nNode.GetNode().FindTableNode(); + const SwTableNode* pTableNd = GetPoint()->GetNode().FindTableNode(); if( !pTableNd ) return false; // If there is another EndNode in front of the cell's StartNode then there // exists a previous cell SwCursorSaveState aSave( *this ); - SwNodeIndex& rPtIdx = GetPoint()->nNode; + SwPosition& rPtPos = *GetPoint(); while( nCnt-- ) { - const SwNode* pTableBoxStartNode = rPtIdx.GetNode().FindTableBoxStartNode(); + const SwNode* pTableBoxStartNode = rPtPos.GetNode().FindTableBoxStartNode(); const SwTableBox* pTableBox = pTableBoxStartNode->GetTableBox(); // Check if we have to move the cursor to a covered cell before @@ -2212,10 +2207,9 @@ bool SwCursor::GoPrevNextCell( bool bNext, sal_uInt16 nCnt ) if ( pTableBox && pTableBox->getRowSpan() > 1 ) { pTableBox = & pTableBox->FindEndOfRowSpan( pTableNd->GetTable(), - static_cast<sal_uInt16>(pTableBox->getRowSpan() + m_nRowSpanOffset)); - SwNodeIndex aNewIdx( *pTableBox->GetSttNd() ); - rPtIdx = aNewIdx; - pTableBoxStartNode = rPtIdx.GetNode().FindTableBoxStartNode(); + o3tl::narrowing<sal_uInt16>(pTableBox->getRowSpan() + m_nRowSpanOffset)); + rPtPos.Assign( *pTableBox->GetSttNd() ); + pTableBoxStartNode = rPtPos.GetNode().FindTableBoxStartNode(); } m_nRowSpanOffset = 0; } @@ -2230,26 +2224,25 @@ bool SwCursor::GoPrevNextCell( bool bNext, sal_uInt16 nCnt ) return false; if (bNext) - rPtIdx = aCellIdx; + rPtPos.Assign( aCellIdx ); else - rPtIdx.Assign(*aCellIdx.GetNode().StartOfSectionNode()); + rPtPos.Assign(*aCellIdx.GetNode().StartOfSectionNode()); - pTableBoxStartNode = rPtIdx.GetNode().FindTableBoxStartNode(); + pTableBoxStartNode = rPtPos.GetNode().FindTableBoxStartNode(); pTableBox = pTableBoxStartNode->GetTableBox(); if ( pTableBox && pTableBox->getRowSpan() < 1 ) { m_nRowSpanOffset = pTableBox->getRowSpan(); // move cursor to non-covered cell: pTableBox = & pTableBox->FindStartOfRowSpan( pTableNd->GetTable() ); - SwNodeIndex aNewIdx( *pTableBox->GetSttNd() ); - rPtIdx = aNewIdx; + rPtPos.Assign( *pTableBox->GetSttNd() ); } } - ++rPtIdx; - if( !rPtIdx.GetNode().IsContentNode() ) - GetDoc().GetNodes().GoNextSection( &rPtIdx, true, false ); - GetPoint()->nContent.Assign( GetContentNode(), 0 ); + rPtPos.Adjust(SwNodeOffset(1)); + if( !rPtPos.GetNode().IsContentNode() ) + SwNodes::GoNextSection(&rPtPos, true, false); + GetPoint()->SetContent( 0 ); return !IsInProtectTable( true ); } @@ -2269,8 +2262,8 @@ bool SwCursor::GotoTable( const OUString& rName ) { // a table in a normal nodes array SwCursorSaveState aSave( *this ); - GetPoint()->nNode = *pTmpTable->GetTabSortBoxes()[ 0 ]-> - GetSttNd()->FindTableNode(); + GetPoint()->Assign( *pTmpTable->GetTabSortBoxes()[ 0 ]-> + GetSttNd()->FindTableNode() ); Move( fnMoveForward, GoInContent ); bRet = !IsSelOvr(); } @@ -2281,7 +2274,7 @@ bool SwCursor::GotoTable( const OUString& rName ) bool SwCursor::GotoTableBox( const OUString& rName ) { bool bRet = false; - const SwTableNode* pTableNd = GetPoint()->nNode.GetNode().FindTableNode(); + const SwTableNode* pTableNd = GetPoint()->GetNode().FindTableNode(); if( pTableNd ) { // retrieve box by name @@ -2291,7 +2284,7 @@ bool SwCursor::GotoTableBox( const OUString& rName ) IsReadOnlyAvailable() ) ) { SwCursorSaveState aSave( *this ); - GetPoint()->nNode = *pTableBox->GetSttNd(); + GetPoint()->Assign( *pTableBox->GetSttNd() ); Move( fnMoveForward, GoInContent ); bRet = !IsSelOvr(); } @@ -2302,7 +2295,7 @@ bool SwCursor::GotoTableBox( const OUString& rName ) bool SwCursor::MovePara(SwWhichPara fnWhichPara, SwMoveFnCollection const & fnPosPara ) { // for optimization test something before - const SwNode* pNd = &GetPoint()->nNode.GetNode(); + const SwNode* pNd = &GetPoint()->GetNode(); bool bShortCut = false; if ( fnWhichPara == GoCurrPara ) { @@ -2314,7 +2307,7 @@ bool SwCursor::MovePara(SwWhichPara fnWhichPara, SwMoveFnCollection const & fnPo if ( pContentNd ) { const sal_Int32 nSttEnd = &fnPosPara == &fnMoveForward ? 0 : pContentNd->Len(); - if ( GetPoint()->nContent.GetIndex() != nSttEnd ) + if ( GetPoint()->GetContentIndex() != nSttEnd ) bShortCut = true; } } @@ -2322,7 +2315,7 @@ bool SwCursor::MovePara(SwWhichPara fnWhichPara, SwMoveFnCollection const & fnPo { if ( pNd->IsTextNode() && pNd->GetNodes()[ pNd->GetIndex() + - (fnWhichPara == GoNextPara ? 1 : -1 ) ]->IsTextNode() ) + SwNodeOffset(fnWhichPara == GoNextPara ? 1 : -1 ) ]->IsTextNode() ) bShortCut = true; } @@ -2352,27 +2345,27 @@ void SwCursor::RestoreSavePos() { // This method is not supposed to be used in cases when nodes may be // deleted; detect such cases, but do not crash (example: fdo#40831). - sal_uLong uNodeCount = GetPoint()->nNode.GetNodes().Count(); + SwNodeOffset uNodeCount(GetPoint()->GetNodes().Count()); OSL_ENSURE(m_vSavePos.empty() || m_vSavePos.back().nNode < uNodeCount, "SwCursor::RestoreSavePos: invalid node: " "probably something was deleted; consider using SwUnoCursor instead"); if (m_vSavePos.empty() || m_vSavePos.back().nNode >= uNodeCount) return; - GetPoint()->nNode = m_vSavePos.back().nNode; + GetPoint()->Assign( m_vSavePos.back().nNode ); sal_Int32 nIdx = 0; - if ( GetContentNode() ) + if ( GetPointContentNode() ) { - if (m_vSavePos.back().nContent <= GetContentNode()->Len()) + if (m_vSavePos.back().nContent <= GetPointContentNode()->Len()) nIdx = m_vSavePos.back().nContent; else { - nIdx = GetContentNode()->Len(); + nIdx = GetPointContentNode()->Len(); OSL_FAIL("SwCursor::RestoreSavePos: invalid content index"); } } - GetPoint()->nContent.Assign( GetContentNode(), nIdx ); + GetPoint()->SetContent( nIdx ); } SwTableCursor::SwTableCursor( const SwPosition &rPos ) @@ -2380,8 +2373,8 @@ SwTableCursor::SwTableCursor( const SwPosition &rPos ) { m_bParked = false; m_bChanged = false; - m_nTablePtNd = 0; - m_nTableMkNd = 0; + m_nTablePtNd = SwNodeOffset(0); + m_nTableMkNd = SwNodeOffset(0); m_nTablePtCnt = 0; m_nTableMkCnt = 0; } @@ -2392,7 +2385,7 @@ static bool lcl_SeekEntry(const SwSelBoxes& rTmp, SwStartNode const*const pSrch, size_t & o_rFndPos) { - sal_uLong nIdx = pSrch->GetIndex(); + SwNodeOffset nIdx = pSrch->GetIndex(); size_t nO = rTmp.size(); if( nO > 0 ) @@ -2441,13 +2434,13 @@ SwCursor* SwTableCursor::MakeBoxSels( SwCursor* pCurrentCursor ) // compare old and new ones SwNodes& rNds = pCurrentCursor->GetDoc().GetNodes(); const SwStartNode* pSttNd; - SwPaM* pCur = pCurrentCursor; + SwCursor* pCur = pCurrentCursor; do { size_t nPos; bool bDel = false; - pSttNd = pCur->GetPoint()->nNode.GetNode().FindTableBoxStartNode(); + pSttNd = pCur->GetPoint()->GetNode().FindTableBoxStartNode(); if( !pCur->HasMark() || !pSttNd || - pSttNd != pCur->GetMark()->nNode.GetNode().FindTableBoxStartNode() ) + pSttNd != pCur->GetMark()->GetNode().FindTableBoxStartNode() ) bDel = true; else if( lcl_SeekEntry( aTmp, pSttNd, nPos )) @@ -2455,12 +2448,12 @@ SwCursor* SwTableCursor::MakeBoxSels( SwCursor* pCurrentCursor ) SwNodeIndex aIdx( *pSttNd, 1 ); const SwNode* pNd = &aIdx.GetNode(); if( !pNd->IsContentNode() ) - pNd = rNds.GoNextSection( &aIdx, true, false ); + pNd = SwNodes::GoNextSection(&aIdx, true, false); SwPosition* pPos = pCur->GetMark(); - if( pNd != &pPos->nNode.GetNode() ) - pPos->nNode = *pNd; - pPos->nContent.Assign( const_cast<SwContentNode*>(static_cast<const SwContentNode*>(pNd)), 0 ); + if( pNd != &pPos->GetNode() ) + pPos->Assign( *pNd ); + pPos->SetContent( 0 ); aIdx.Assign( *pSttNd->EndOfSectionNode(), - 1 ); pNd = &aIdx.GetNode(); @@ -2468,9 +2461,9 @@ SwCursor* SwTableCursor::MakeBoxSels( SwCursor* pCurrentCursor ) pNd = SwNodes::GoPrevSection( &aIdx, true, false ); pPos = pCur->GetPoint(); - if (pNd && pNd != &pPos->nNode.GetNode()) - pPos->nNode = *pNd; - pPos->nContent.Assign(const_cast<SwContentNode*>(static_cast<const SwContentNode*>(pNd)), pNd ? static_cast<const SwContentNode*>(pNd)->Len() : 0); + if (pNd && pNd != &pPos->GetNode()) + pPos->Assign( *pNd ); + pPos->SetContent( pNd ? static_cast<const SwContentNode*>(pNd)->Len() : 0); aTmp.erase( aTmp.begin() + nPos ); } @@ -2480,7 +2473,9 @@ SwCursor* SwTableCursor::MakeBoxSels( SwCursor* pCurrentCursor ) pCur = pCur->GetNext(); if( bDel ) { - SwPaM* pDel = pCur->GetPrev(); + SwCursor* pDel = pCur->GetPrev(); + if (pDel == dynamic_cast<SwShellCursor*>(pCurrentCursor)) + pCurrentCursor = pDel->GetPrev(); if( pDel == pCurrentCursor ) pCurrentCursor->DeleteMark(); @@ -2498,22 +2493,21 @@ SwCursor* SwTableCursor::MakeBoxSels( SwCursor* pCurrentCursor ) break; SwNode* pNd = &aIdx.GetNode(); if( !pNd->IsContentNode() ) - pNd = rNds.GoNextSection( &aIdx, true, false ); + pNd = SwNodes::GoNextSection(&aIdx, true, false); SwPaM *const pNew = (!pCurrentCursor->IsMultiSelection() && !pCurrentCursor->HasMark()) ? pCurrentCursor : pCurrentCursor->Create( pCurrentCursor ); - pNew->GetPoint()->nNode = *pNd; - pNew->GetPoint()->nContent.Assign( static_cast<SwContentNode*>(pNd), 0 ); + pNew->GetPoint()->Assign( *pNd ); pNew->SetMark(); SwPosition* pPos = pNew->GetPoint(); - pPos->nNode.Assign( *pSttNd->EndOfSectionNode(), - 1 ); - pNd = &pPos->nNode.GetNode(); + pPos->Assign( *pSttNd->EndOfSectionNode(), - 1 ); + pNd = &pPos->GetNode(); if( !pNd->IsContentNode() ) - pNd = SwNodes::GoPrevSection( &pPos->nNode, true, false ); - - pPos->nContent.Assign(static_cast<SwContentNode*>(pNd), pNd ? static_cast<SwContentNode*>(pNd)->Len() : 0); + pNd = SwNodes::GoPrevSection( pPos, true, false ); + if (pNd) + pPos->AssignEndIndex(*static_cast<SwContentNode*>(pNd)); } } return pCurrentCursor; @@ -2535,8 +2529,8 @@ void SwTableCursor::DeleteBox(size_t const nPos) bool SwTableCursor::NewTableSelection() { bool bRet = false; - const SwNode *pStart = GetNode().FindTableBoxStartNode(); - const SwNode *pEnd = GetNode(false).FindTableBoxStartNode(); + const SwNode *pStart = GetPointNode().FindTableBoxStartNode(); + const SwNode *pEnd = GetMarkNode().FindTableBoxStartNode(); if( pStart && pEnd ) { const SwTableNode *pTableNode = pStart->FindTableNode(); @@ -2593,10 +2587,10 @@ bool SwTableCursor::IsCursorMovedUpdate() if( !IsCursorMoved() ) return false; - m_nTableMkNd = GetMark()->nNode.GetIndex(); - m_nTablePtNd = GetPoint()->nNode.GetIndex(); - m_nTableMkCnt = GetMark()->nContent.GetIndex(); - m_nTablePtCnt = GetPoint()->nContent.GetIndex(); + m_nTableMkNd = GetMark()->GetNodeIndex(); + m_nTablePtNd = GetPoint()->GetNodeIndex(); + m_nTableMkCnt = GetMark()->GetContentIndex(); + m_nTablePtCnt = GetPoint()->GetContentIndex(); return true; } @@ -2604,17 +2598,15 @@ bool SwTableCursor::IsCursorMovedUpdate() void SwTableCursor::ParkCursor() { // de-register index from text node - SwNode* pNd = &GetPoint()->nNode.GetNode(); + SwNode* pNd = &GetPoint()->GetNode(); if( !pNd->IsStartNode() ) pNd = pNd->StartOfSectionNode(); - GetPoint()->nNode = *pNd; - GetPoint()->nContent.Assign( nullptr, 0 ); + GetPoint()->Assign(*pNd); - pNd = &GetMark()->nNode.GetNode(); + pNd = &GetMark()->GetNode(); if( !pNd->IsStartNode() ) pNd = pNd->StartOfSectionNode(); - GetMark()->nNode = *pNd; - GetMark()->nContent.Assign( nullptr, 0 ); + GetMark()->Assign(*pNd); m_bChanged = true; m_bParked = true; @@ -2634,4 +2626,18 @@ bool SwTableCursor::HasReadOnlyBoxSel() const return bRet; } +bool SwTableCursor::HasHiddenBoxSel() const +{ + bool bRet = false; + for (size_t n = m_SelectedBoxes.size(); n; ) + { + if (m_SelectedBoxes[--n]->GetFrameFormat()->IsHidden()) + { + bRet = true; + break; + } + } + return bRet; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/crsr/trvlfnfl.cxx b/sw/source/core/crsr/trvlfnfl.cxx index c93faffff95b..098bad4b3435 100644 --- a/sw/source/core/crsr/trvlfnfl.cxx +++ b/sw/source/core/crsr/trvlfnfl.cxx @@ -30,6 +30,7 @@ #include <viscrs.hxx> #include "callnk.hxx" #include <svx/srchdlg.hxx> +#include <wrtsh.hxx> bool SwCursorShell::CallCursorShellFN( FNCursorShell fnCursor ) { @@ -43,6 +44,10 @@ bool SwCursorShell::CallCursorShellFN( FNCursorShell fnCursor ) bool SwCursorShell::CallCursorFN( FNCursor fnCursor ) { + // for footnote anchor<->text recency + if (SwWrtShell* pWrtSh = dynamic_cast<SwWrtShell*>(this)) + pWrtSh->addCurrentPosition(); + SwCallLink aLk( *this ); // watch Cursor-Moves SwCursor* pCursor = getShellCursor( true ); bool bRet = (pCursor->*fnCursor)(); @@ -56,23 +61,22 @@ bool SwCursor::GotoFootnoteText() { // jump from content to footnote bool bRet = false; - SwTextNode* pTextNd = GetPoint()->nNode.GetNode().GetTextNode(); + SwTextNode* pTextNd = GetPoint()->GetNode().GetTextNode(); SwTextAttr *const pFootnote( pTextNd ? pTextNd->GetTextAttrForCharAt( - GetPoint()->nContent.GetIndex(), RES_TXTATR_FTN) + GetPoint()->GetContentIndex(), RES_TXTATR_FTN) : nullptr); if (pFootnote) { SwCursorSaveState aSaveState( *this ); - GetPoint()->nNode = *static_cast<SwTextFootnote*>(pFootnote)->GetStartNode(); + GetPoint()->Assign( *static_cast<SwTextFootnote*>(pFootnote)->GetStartNode() ); - SwContentNode* pCNd = GetDoc().GetNodes().GoNextSection( - &GetPoint()->nNode, + SwContentNode* pCNd = SwNodes::GoNextSection( + GetPoint(), true, !IsReadOnlyAvailable() ); if( pCNd ) { - GetPoint()->nContent.Assign( pCNd, 0 ); bRet = !IsSelOvr( SwCursorSelOverFlags::CheckNodeSection | SwCursorSelOverFlags::Toggle ); } @@ -86,7 +90,7 @@ bool SwCursorShell::GotoFootnoteText() if( !bRet ) { SwTextNode* pTextNd = GetCursor_() ? - GetCursor_()->GetPoint()->nNode.GetNode().GetTextNode() : nullptr; + GetCursor_()->GetPoint()->GetNode().GetTextNode() : nullptr; if( pTextNd ) { std::pair<Point, bool> const tmp(GetCursor_()->GetSttPos(), true); @@ -134,7 +138,7 @@ bool SwCursorShell::GotoFootnoteText() bool SwCursor::GotoFootnoteAnchor() { // jump from footnote to anchor - const SwNode* pSttNd = GetNode().FindFootnoteStartNode(); + const SwNode* pSttNd = GetPointNode().FindFootnoteStartNode(); if( pSttNd ) { // search in all footnotes in document for this StartIndex @@ -148,8 +152,7 @@ bool SwCursor::GotoFootnoteAnchor() SwCursorSaveState aSaveState( *this ); SwTextNode& rTNd = const_cast<SwTextNode&>(pTextFootnote->GetTextNode()); - GetPoint()->nNode = rTNd; - GetPoint()->nContent.Assign( &rTNd, pTextFootnote->GetStart() ); + GetPoint()->Assign( rTNd, pTextFootnote->GetStart() ); return !IsSelOvr( SwCursorSelOverFlags::CheckNodeSection | SwCursorSelOverFlags::Toggle ); @@ -161,6 +164,9 @@ bool SwCursor::GotoFootnoteAnchor() bool SwCursorShell::GotoFootnoteAnchor() { + if (SwWrtShell* pWrtSh = dynamic_cast<SwWrtShell*>(this)) + pWrtSh->addCurrentPosition(); + // jump from footnote to anchor SwCallLink aLk( *this ); // watch Cursor-Moves bool bRet = m_pCurrentCursor->GotoFootnoteAnchor(); @@ -174,15 +180,15 @@ bool SwCursorShell::GotoFootnoteAnchor() return bRet; } -static bool CmpLE( const SwTextFootnote& rFootnote, sal_uLong nNd, sal_Int32 nCnt ) +static bool CmpLE( const SwTextFootnote& rFootnote, SwNodeOffset nNd, sal_Int32 nCnt ) { - const sal_uLong nTNd = rFootnote.GetTextNode().GetIndex(); + const SwNodeOffset nTNd = rFootnote.GetTextNode().GetIndex(); return nTNd < nNd || ( nTNd == nNd && rFootnote.GetStart() <= nCnt ); } -static bool CmpL( const SwTextFootnote& rFootnote, sal_uLong nNd, sal_Int32 nCnt ) +static bool CmpL( const SwTextFootnote& rFootnote, SwNodeOffset nNd, sal_Int32 nCnt ) { - const sal_uLong nTNd = rFootnote.GetTextNode().GetIndex(); + const SwNodeOffset nTNd = rFootnote.GetTextNode().GetIndex(); return nTNd < nNd || ( nTNd == nNd && rFootnote.GetStart() < nCnt ); } @@ -198,13 +204,13 @@ bool SwCursor::GotoNextFootnoteAnchor() return false; } - if( rFootnoteArr.SeekEntry( GetPoint()->nNode, &nPos )) + if( rFootnoteArr.SeekEntry( GetPoint()->GetNode(), &nPos )) { // there is a footnote with this index, so search also for the next one if( nPos < rFootnoteArr.size() ) { - sal_uLong nNdPos = GetPoint()->nNode.GetIndex(); - const sal_Int32 nCntPos = GetPoint()->nContent.GetIndex(); + SwNodeOffset nNdPos = GetPoint()->GetNodeIndex(); + const sal_Int32 nCntPos = GetPoint()->GetContentIndex(); pTextFootnote = rFootnoteArr[ nPos ]; // search forwards @@ -252,8 +258,7 @@ bool SwCursor::GotoNextFootnoteAnchor() SwCursorSaveState aSaveState( *this ); SwTextNode& rTNd = const_cast<SwTextNode&>(pTextFootnote->GetTextNode()); - GetPoint()->nNode = rTNd; - GetPoint()->nContent.Assign( &rTNd, pTextFootnote->GetStart() ); + GetPoint()->Assign( rTNd, pTextFootnote->GetStart() ); bRet = !IsSelOvr(); } return bRet; @@ -271,11 +276,11 @@ bool SwCursor::GotoPrevFootnoteAnchor() return false; } - if( rFootnoteArr.SeekEntry( GetPoint()->nNode, &nPos ) ) + if( rFootnoteArr.SeekEntry( GetPoint()->GetNode(), &nPos ) ) { // there is a footnote with this index, so search also for the next one - sal_uLong nNdPos = GetPoint()->nNode.GetIndex(); - const sal_Int32 nCntPos = GetPoint()->nContent.GetIndex(); + SwNodeOffset nNdPos = GetPoint()->GetNodeIndex(); + const sal_Int32 nCntPos = GetPoint()->GetContentIndex(); pTextFootnote = rFootnoteArr[ nPos ]; // search forwards @@ -323,8 +328,7 @@ bool SwCursor::GotoPrevFootnoteAnchor() SwCursorSaveState aSaveState( *this ); SwTextNode& rTNd = const_cast<SwTextNode&>(pTextFootnote->GetTextNode()); - GetPoint()->nNode = rTNd; - GetPoint()->nContent.Assign( &rTNd, pTextFootnote->GetStart() ); + GetPoint()->Assign( rTNd, pTextFootnote->GetStart() ); bRet = !IsSelOvr(); } return bRet; @@ -357,7 +361,7 @@ void SwCursorShell::GotoFlyAnchor() // jump in BodyFrame closest to FlyFrame SwRect aTmpRect( m_aCharRect ); - if( !pFrame->getFrameArea().IsInside( aTmpRect )) + if( !pFrame->getFrameArea().Contains( aTmpRect )) aTmpRect = pFrame->getFrameArea(); Point aPt( aTmpRect.Left(), aTmpRect.Top() + ( aTmpRect.Bottom() - aTmpRect.Top() ) / 2 ); diff --git a/sw/source/core/crsr/trvlreg.cxx b/sw/source/core/crsr/trvlreg.cxx index 07d9061672aa..1bcc4e81ea33 100644 --- a/sw/source/core/crsr/trvlreg.cxx +++ b/sw/source/core/crsr/trvlreg.cxx @@ -32,13 +32,13 @@ bool GotoPrevRegion( SwPaM& rCurrentCursor, SwMoveFnCollection const & fnPosRegi bool bInReadOnly ) { SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty ); - SwNodeIndex aIdx( rCurrentCursor.GetPoint()->nNode ); + SwNodeIndex aIdx( rCurrentCursor.GetPoint()->GetNode() ); SwSectionNode* pNd = aIdx.GetNode().FindSectionNode(); if( pNd ) - aIdx.Assign( *pNd, - 1 ); + aIdx.Assign( *pNd, -1 ); SwNodeIndex aOldIdx = aIdx; - sal_uLong nLastNd = rCurrentCursor.GetDoc().GetNodes().Count() - 1; + SwNodeOffset nLastNd(rCurrentCursor.GetDoc().GetNodes().Count() - 1); do { while( aIdx.GetIndex() ) { @@ -73,14 +73,13 @@ bool GotoPrevRegion( SwPaM& rCurrentCursor, SwMoveFnCollection const & fnPosRegi else if( &fnPosRegion == &fnMoveForward ) { aIdx = *pNd; - SwContentNode* pCNd = pNd->GetNodes().GoNextSection( &aIdx, - true, !bInReadOnly ); + SwContentNode* pCNd = SwNodes::GoNextSection(&aIdx, true, !bInReadOnly); if( !pCNd ) { --aIdx; continue; } - rCurrentCursor.GetPoint()->nContent.Assign( pCNd, 0 ); + rCurrentCursor.GetPoint()->SetContent( 0 ); } else { @@ -92,9 +91,9 @@ bool GotoPrevRegion( SwPaM& rCurrentCursor, SwMoveFnCollection const & fnPosRegi aIdx.Assign( *pNd, - 1 ); continue; } - rCurrentCursor.GetPoint()->nContent.Assign( pCNd, pCNd->Len() ); + rCurrentCursor.GetPoint()->SetContent( pCNd->Len() ); } - rCurrentCursor.GetPoint()->nNode = aIdx; + rCurrentCursor.GetPoint()->Assign( aIdx ); return true; } } while( true ); @@ -107,13 +106,13 @@ bool GotoNextRegion( SwPaM& rCurrentCursor, SwMoveFnCollection const & fnPosRegi bool bInReadOnly ) { SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty ); - SwNodeIndex aIdx( rCurrentCursor.GetPoint()->nNode ); + SwNodeIndex aIdx( rCurrentCursor.GetPoint()->GetNode() ); SwSectionNode* pNd = aIdx.GetNode().FindSectionNode(); if( pNd ) aIdx.Assign( *pNd->EndOfSectionNode(), - 1 ); SwNodeIndex aOldIdx = aIdx; - sal_uLong nEndCount = aIdx.GetNode().GetNodes().Count()-1; + SwNodeOffset nEndCount = aIdx.GetNode().GetNodes().Count() - 1; do { while( aIdx.GetIndex() < nEndCount ) { @@ -131,7 +130,7 @@ bool GotoNextRegion( SwPaM& rCurrentCursor, SwMoveFnCollection const & fnPosRegi if ( aIdx.GetIndex() == nEndCount ) { SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::EndWrapped ); - aIdx = 0; + aIdx = SwNodeOffset(0); continue; } @@ -148,14 +147,13 @@ bool GotoNextRegion( SwPaM& rCurrentCursor, SwMoveFnCollection const & fnPosRegi else if( &fnPosRegion == &fnMoveForward ) { aIdx = *pNd; - SwContentNode* pCNd = pNd->GetNodes().GoNextSection( &aIdx, - true, !bInReadOnly ); + SwContentNode* pCNd = SwNodes::GoNextSection(&aIdx, true, !bInReadOnly); if( !pCNd ) { aIdx.Assign( *pNd->EndOfSectionNode(), +1 ); continue; } - rCurrentCursor.GetPoint()->nContent.Assign( pCNd, 0 ); + rCurrentCursor.GetPoint()->SetContent( 0 ); } else { @@ -167,9 +165,9 @@ bool GotoNextRegion( SwPaM& rCurrentCursor, SwMoveFnCollection const & fnPosRegi ++aIdx; continue; } - rCurrentCursor.GetPoint()->nContent.Assign( pCNd, pCNd->Len() ); + rCurrentCursor.GetPoint()->SetContent( pCNd->Len() ); } - rCurrentCursor.GetPoint()->nNode = aIdx; + rCurrentCursor.GetPoint()->Assign( aIdx ); return true; } } while( true ); @@ -181,13 +179,13 @@ bool GotoNextRegion( SwPaM& rCurrentCursor, SwMoveFnCollection const & fnPosRegi bool GotoCurrRegionAndSkip( SwPaM& rCurrentCursor, SwMoveFnCollection const & fnPosRegion, bool bInReadOnly ) { - SwNode& rCurrNd = rCurrentCursor.GetNode(); + SwNode& rCurrNd = rCurrentCursor.GetPointNode(); SwSectionNode* pNd = rCurrNd.FindSectionNode(); if( !pNd ) return false; SwPosition* pPos = rCurrentCursor.GetPoint(); - const sal_Int32 nCurrCnt = pPos->nContent.GetIndex(); + const sal_Int32 nCurrCnt = pPos->GetContentIndex(); bool bMoveBackward = &fnPosRegion == &fnMoveBackward; do { @@ -198,21 +196,21 @@ bool GotoCurrRegionAndSkip( SwPaM& rCurrentCursor, SwMoveFnCollection const & fn pCNd = SwNodes::GoPrevSection( &aIdx, true, !bInReadOnly ); if( !pCNd ) return false; - pPos->nNode = aIdx; + pPos->Assign( aIdx ); } else { SwNodeIndex aIdx( *pNd ); - pCNd = pNd->GetNodes().GoNextSection( &aIdx, true, !bInReadOnly ); + pCNd = SwNodes::GoNextSection(&aIdx, true, !bInReadOnly); if( !pCNd ) return false; - pPos->nNode = aIdx; + pPos->Assign( aIdx ); } - pPos->nContent.Assign( pCNd, bMoveBackward ? pCNd->Len() : 0 ); + pPos->SetContent( bMoveBackward ? pCNd->Len() : 0 ); - if( &pPos->nNode.GetNode() != &rCurrNd || - pPos->nContent.GetIndex() != nCurrCnt ) + if( &pPos->GetNode() != &rCurrNd || + pPos->GetContentIndex() != nCurrCnt ) // there was a change return true; @@ -229,8 +227,8 @@ bool SwCursor::MoveRegion( SwWhichRegion fnWhichRegion, SwMoveFnCollection const return !dynamic_cast<SwTableCursor*>(this) && (*fnWhichRegion)( *this, fnPosRegion, IsReadOnlyAvailable() ) && !IsSelOvr() && - (GetPoint()->nNode.GetIndex() != m_vSavePos.back().nNode || - GetPoint()->nContent.GetIndex() != m_vSavePos.back().nContent); + (GetPoint()->GetNodeIndex() != m_vSavePos.back().nNode || + GetPoint()->GetContentIndex() != m_vSavePos.back().nContent); } bool SwCursorShell::MoveRegion( SwWhichRegion fnWhichRegion, SwMoveFnCollection const & fnPosRegion ) @@ -258,7 +256,7 @@ bool SwCursor::GotoRegion( std::u16string_view rName ) // area in normal nodes array SwCursorSaveState aSaveState( *this ); - GetPoint()->nNode = *pIdx; + GetPoint()->Assign( *pIdx ); Move( fnMoveForward, GoInContent ); bRet = !IsSelOvr(); } diff --git a/sw/source/core/crsr/trvltbl.cxx b/sw/source/core/crsr/trvltbl.cxx index 5f26c9f23788..b16b40122a26 100644 --- a/sw/source/core/crsr/trvltbl.cxx +++ b/sw/source/core/crsr/trvltbl.cxx @@ -49,7 +49,7 @@ bool SwCursorShell::GoNextCell( bool bAppendLine ) // Check if we have to move the cursor to a covered cell before // proceeding: - const SwNode* pTableBoxStartNode = pCursor->GetNode().FindTableBoxStartNode(); + const SwNode* pTableBoxStartNode = pCursor->GetPointNode().FindTableBoxStartNode(); const SwTableBox* pTableBox = nullptr; if ( pCursor->GetCursorRowSpanOffset() ) @@ -61,7 +61,7 @@ bool SwCursorShell::GoNextCell( bool bAppendLine ) pTableNd = IsCursorInTable(); assert (pTableNd); pTableBox = & pTableBox->FindEndOfRowSpan( pTableNd->GetTable(), - static_cast<sal_uInt16>(pTableBox->getRowSpan() + pCursor->GetCursorRowSpanOffset() ) ); + o3tl::narrowing<sal_uInt16>(pTableBox->getRowSpan() + pCursor->GetCursorRowSpanOffset() ) ); pTableBoxStartNode = pTableBox->GetSttNd(); } } @@ -79,7 +79,7 @@ bool SwCursorShell::GoNextCell( bool bAppendLine ) // if there is no list anymore then create new one if ( !pTableBox ) pTableBox = pTableNd->GetTable().GetTableBox( - pCursor->GetPoint()->nNode.GetNode(). + pCursor->GetPoint()->GetNode(). StartOfSectionIndex() ); OSL_ENSURE( pTableBox, "Box is not in this table" ); @@ -128,7 +128,7 @@ bool SwCursorShell::SelTableRowOrCol( bool bRow, bool bRowSimple ) { // check if the current cursor's SPoint/Mark are in a table SwFrame *pFrame = GetCurrFrame(); - if( !pFrame->IsInTab() ) + if( !pFrame || !pFrame->IsInTab() ) return false; const SwTabFrame* pTabFrame = pFrame->FindTabFrame(); @@ -176,7 +176,7 @@ bool SwCursorShell::SelTableRowOrCol( bool bRow, bool bRowSimple ) { const SwShellCursor *pCursor = GetCursor_(); const SwFrame* pStartFrame = pFrame; - const SwContentNode *pCNd = pCursor->GetContentNode( false ); + const SwContentNode *pCNd = pCursor->GetMarkContentNode(); std::pair<Point, bool> const tmp(pCursor->GetMkPos(), true); const SwFrame* pEndFrame = pCNd ? pCNd->getLayoutFrame(GetLayout(), nullptr, &tmp) @@ -233,10 +233,10 @@ bool SwCursorShell::SelTableRowOrCol( bool bRow, bool bRowSimple ) m_pTableCursor->DeleteMark(); // set start and end of a column - m_pTableCursor->GetPoint()->nNode = *pEnd->GetSttNd(); - m_pTableCursor->Move( fnMoveForward, GoInContent ); + m_pTableCursor->GetPoint()->Assign( *pEnd->GetSttNd()->EndOfSectionNode() ); + m_pTableCursor->Move( fnMoveBackward, GoInContent ); m_pTableCursor->SetMark(); - m_pTableCursor->GetPoint()->nNode = *pStt->GetSttNd()->EndOfSectionNode(); + m_pTableCursor->GetPoint()->Assign( *pStt->GetSttNd()->EndOfSectionNode() ); m_pTableCursor->Move( fnMoveBackward, GoInContent ); // set PtPos 'close' to the reference table, otherwise we might get problems @@ -271,13 +271,13 @@ bool SwCursorShell::SelTable() } m_pTableCursor->DeleteMark(); - m_pTableCursor->GetPoint()->nNode = *pTableNd; + m_pTableCursor->GetPoint()->Assign( *pTableNd ); m_pTableCursor->Move( fnMoveForward, GoInContent ); m_pTableCursor->SetMark(); // set MkPos 'close' to the master table, otherwise we might get problems // with the repeated headlines check in UpdateCursor(): m_pTableCursor->GetMkPos() = pMasterTabFrame->IsVertical() ? pMasterTabFrame->getFrameArea().TopRight() : pMasterTabFrame->getFrameArea().TopLeft(); - m_pTableCursor->GetPoint()->nNode = *pTableNd->EndOfSectionNode(); + m_pTableCursor->GetPoint()->Assign( *pTableNd->EndOfSectionNode() ); m_pTableCursor->Move( fnMoveBackward, GoInContent ); UpdateCursor(); return true; @@ -290,7 +290,7 @@ bool SwCursorShell::SelTableBox() // search for start node of our table box. If not found, exit really const SwStartNode* pStartNode = - m_pCurrentCursor->GetPoint()->nNode.GetNode().FindTableBoxStartNode(); + m_pCurrentCursor->GetPoint()->GetNode().FindTableBoxStartNode(); #if OSL_DEBUG_LEVEL > 0 // the old code checks whether we're in a table by asking the @@ -316,12 +316,12 @@ bool SwCursorShell::SelTableBox() // select the complete box with our shiny new m_pTableCursor // 1. delete mark, and move point to first content node in box m_pTableCursor->DeleteMark(); - *(m_pTableCursor->GetPoint()) = SwPosition( *pStartNode ); + m_pTableCursor->GetPoint()->Assign( *pStartNode ); m_pTableCursor->Move( fnMoveForward, GoInNode ); // 2. set mark, and move point to last content node in box m_pTableCursor->SetMark(); - *(m_pTableCursor->GetPoint()) = SwPosition( *(pStartNode->EndOfSectionNode()) ); + m_pTableCursor->GetPoint()->Assign( *(pStartNode->EndOfSectionNode()) ); m_pTableCursor->Move( fnMoveBackward, GoInNode ); // 3. exchange @@ -359,12 +359,11 @@ static bool lcl_FindNextCell( SwNodeIndex& rIdx, bool bInReadOnly ) const SwNode* pTableEndNode = pTableNd->EndOfSectionNode(); - SwNodes& rNds = aTmp.GetNode().GetNodes(); SwContentNode* pCNd = aTmp.GetNode().GetContentNode(); // no content node => go to next content node if( !pCNd ) - pCNd = rNds.GoNext( &aTmp ); + pCNd = SwNodes::GoNext(&aTmp); // robust if ( !pCNd ) @@ -395,7 +394,7 @@ static bool lcl_FindNextCell( SwNodeIndex& rIdx, bool bInReadOnly ) // ok, get the next content node: pCNd = aTmp.GetNode().GetContentNode(); if( nullptr == pCNd ) - pCNd = rNds.GoNext( &aTmp ); + pCNd = SwNodes::GoNext(&aTmp); // robust: if ( !pCNd ) @@ -471,7 +470,7 @@ static bool lcl_FindPrevCell( SwNodeIndex& rIdx, bool bInReadOnly ) rIdx = *pCNd; return true; // ok, not protected } - aTmp.Assign( *pCNd->StartOfSectionNode(), - 1 ); + aTmp.Assign( *pCNd->StartOfSectionNode(), -1 ); } } rIdx = *pCNd; @@ -483,7 +482,7 @@ bool GotoPrevTable( SwPaM& rCurrentCursor, SwMoveFnCollection const & fnPosTable { SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty ); - SwNodeIndex aIdx( rCurrentCursor.GetPoint()->nNode ); + SwNodeIndex aIdx( rCurrentCursor.GetPoint()->GetNode() ); SwTableNode* pTableNd = aIdx.GetNode().FindTableNode(); if( pTableNd ) @@ -497,11 +496,11 @@ bool GotoPrevTable( SwPaM& rCurrentCursor, SwMoveFnCollection const & fnPosTable --aTmpIdx; if( pInnerTableNd == pTableNd ) - aIdx.Assign( *pTableNd, - 1 ); + aIdx.Assign( *pTableNd, -1 ); } SwNodeIndex aOldIdx = aIdx; - sal_uLong nLastNd = rCurrentCursor.GetDoc().GetNodes().Count() - 1; + SwNodeOffset nLastNd(rCurrentCursor.GetDoc().GetNodes().Count() - 1); do { while( aIdx.GetIndex() && nullptr == ( pTableNd = aIdx.GetNode().StartOfSectionNode()->GetTableNode()) ) @@ -546,8 +545,7 @@ bool GotoPrevTable( SwPaM& rCurrentCursor, SwMoveFnCollection const & fnPosTable SwTextNode* pTextNode = aIdx.GetNode().GetTextNode(); if ( pTextNode ) { - rCurrentCursor.GetPoint()->nNode = *pTextNode; - rCurrentCursor.GetPoint()->nContent.Assign( pTextNode, &fnPosTable == &fnMoveBackward ? + rCurrentCursor.GetPoint()->Assign(*pTextNode, &fnPosTable == &fnMoveBackward ? pTextNode->Len() : 0 ); } @@ -563,14 +561,14 @@ bool GotoNextTable( SwPaM& rCurrentCursor, SwMoveFnCollection const & fnPosTable { SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty ); - SwNodeIndex aIdx( rCurrentCursor.GetPoint()->nNode ); + SwNodeIndex aIdx( rCurrentCursor.GetPoint()->GetNode() ); SwTableNode* pTableNd = aIdx.GetNode().FindTableNode(); if( pTableNd ) aIdx.Assign( *pTableNd->EndOfSectionNode(), 1 ); SwNodeIndex aOldIdx = aIdx; - sal_uLong nLastNd = rCurrentCursor.GetDoc().GetNodes().Count() - 1; + SwNodeOffset nLastNd(rCurrentCursor.GetDoc().GetNodes().Count() - 1); do { while( aIdx.GetIndex() < nLastNd && nullptr == ( pTableNd = aIdx.GetNode().GetTableNode()) ) @@ -586,7 +584,7 @@ bool GotoNextTable( SwPaM& rCurrentCursor, SwMoveFnCollection const & fnPosTable if ( aIdx.GetIndex() == nLastNd ) { SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::EndWrapped ); - aIdx = 0; + aIdx = SwNodeOffset(0); continue; } @@ -616,8 +614,7 @@ bool GotoNextTable( SwPaM& rCurrentCursor, SwMoveFnCollection const & fnPosTable SwTextNode* pTextNode = aIdx.GetNode().GetTextNode(); if ( pTextNode ) { - rCurrentCursor.GetPoint()->nNode = *pTextNode; - rCurrentCursor.GetPoint()->nContent.Assign( pTextNode, &fnPosTable == &fnMoveBackward ? + rCurrentCursor.GetPoint()->Assign(*pTextNode, &fnPosTable == &fnMoveBackward ? pTextNode->Len() : 0 ); } @@ -633,7 +630,7 @@ bool GotoNextTable( SwPaM& rCurrentCursor, SwMoveFnCollection const & fnPosTable bool GotoCurrTable( SwPaM& rCurrentCursor, SwMoveFnCollection const & fnPosTable, bool bInReadOnly ) { - SwTableNode* pTableNd = rCurrentCursor.GetPoint()->nNode.GetNode().FindTableNode(); + SwTableNode* pTableNd = rCurrentCursor.GetPoint()->GetNode().FindTableNode(); if( !pTableNd ) return false; @@ -655,8 +652,7 @@ bool GotoCurrTable( SwPaM& rCurrentCursor, SwMoveFnCollection const & fnPosTable if ( pTextNode ) { - rCurrentCursor.GetPoint()->nNode = *pTextNode; - rCurrentCursor.GetPoint()->nContent.Assign( pTextNode, &fnPosTable == &fnMoveBackward ? + rCurrentCursor.GetPoint()->Assign(*pTextNode, &fnPosTable == &fnMoveBackward ? pTextNode->Len() : 0 ); } @@ -686,7 +682,7 @@ bool SwCursorShell::MoveTable( SwWhichTable fnWhichTable, SwMoveFnCollection con SwShellCursor* pCursor = m_pTableCursor ? m_pTableCursor : m_pCurrentCursor; bool bCheckPos; bool bRet; - sal_uLong nPtNd = 0; + SwNodeOffset nPtNd(0); sal_Int32 nPtCnt = 0; if ( !m_pTableCursor && m_pCurrentCursor->HasMark() ) @@ -702,8 +698,8 @@ bool SwCursorShell::MoveTable( SwWhichTable fnWhichTable, SwMoveFnCollection con else { bCheckPos = true; - nPtNd = pCursor->GetPoint()->nNode.GetIndex(); - nPtCnt = pCursor->GetPoint()->nContent.GetIndex(); + nPtNd = pCursor->GetPoint()->GetNodeIndex(); + nPtCnt = pCursor->GetPoint()->GetContentIndex(); } bRet = pCursor->MoveTable( fnWhichTable, fnPosTable ); @@ -716,8 +712,8 @@ bool SwCursorShell::MoveTable( SwWhichTable fnWhichTable, SwMoveFnCollection con UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY); if( bCheckPos && - pCursor->GetPoint()->nNode.GetIndex() == nPtNd && - pCursor->GetPoint()->nContent.GetIndex() == nPtCnt ) + pCursor->GetPoint()->GetNodeIndex() == nPtNd && + pCursor->GetPoint()->GetContentIndex() == nPtCnt ) bRet = false; } return bRet; @@ -729,7 +725,7 @@ bool SwCursorShell::IsTableComplexForChart() // Here we may trigger table formatting so we better do that inside an action StartAction(); - const SwTableNode* pTNd = m_pCurrentCursor->GetPoint()->nNode.GetNode().FindTableNode(); + const SwTableNode* pTNd = m_pCurrentCursor->GetPoint()->GetNode().FindTableNode(); if( pTNd ) { // in a table; check if table or section is balanced @@ -751,7 +747,7 @@ OUString SwCursorShell::GetBoxNms() const if( IsTableMode() ) { - SwContentNode *pCNd = m_pTableCursor->Start()->nNode.GetNode().GetContentNode(); + SwContentNode *pCNd = m_pTableCursor->Start()->GetNode().GetContentNode(); pFrame = pCNd ? pCNd->getLayoutFrame( GetLayout() ) : nullptr; if( !pFrame ) return sNm; @@ -776,7 +772,7 @@ OUString SwCursorShell::GetBoxNms() const pPos = GetCursor()->GetPoint(); } - SwContentNode* pCNd = pPos->nNode.GetNode().GetContentNode(); + SwContentNode* pCNd = pPos->GetNode().GetContentNode(); pFrame = pCNd ? pCNd->getLayoutFrame( GetLayout() ) : nullptr; if( pFrame ) @@ -823,13 +819,13 @@ bool SwCursorShell::CheckTableBoxContent( const SwPosition* pPos ) } else { - pSttNd = pPos->nNode.GetNode().FindSttNodeByType( SwTableBoxStartNode ); + pSttNd = pPos->GetNode().FindSttNodeByType( SwTableBoxStartNode ); if( pSttNd) pChkBox = pSttNd->FindTableNode()->GetTable().GetTableBox( pSttNd->GetIndex() ); } // box has more than one paragraph - if( pChkBox && pSttNd->GetIndex() + 2 != pSttNd->EndOfSectionIndex() ) + if( pChkBox && pSttNd->GetIndex() + SwNodeOffset(2) != pSttNd->EndOfSectionIndex() ) pChkBox = nullptr; // destroy pointer before next action starts @@ -839,7 +835,7 @@ bool SwCursorShell::CheckTableBoxContent( const SwPosition* pPos ) // cursor not anymore in this section? if( pChkBox && !pPos && ( m_pCurrentCursor->HasMark() || m_pCurrentCursor->GetNext() != m_pCurrentCursor || - pSttNd->GetIndex() + 1 == m_pCurrentCursor->GetPoint()->nNode.GetIndex() )) + pSttNd->GetIndex() + 1 == m_pCurrentCursor->GetPoint()->GetNodeIndex() )) pChkBox = nullptr; // Did the content of a box change at all? This is important if e.g. Undo @@ -875,7 +871,7 @@ void SwCursorShell::SaveTableBoxContent( const SwPosition* pPos ) if( !pPos ) pPos = m_pCurrentCursor->GetPoint(); - SwStartNode* pSttNd = pPos->nNode.GetNode().FindSttNodeByType( SwTableBoxStartNode ); + SwStartNode* pSttNd = pPos->GetNode().FindSttNodeByType( SwTableBoxStartNode ); bool bCheckBox = false; if( pSttNd && m_pBoxIdx ) diff --git a/sw/source/core/crsr/viscrs.cxx b/sw/source/core/crsr/viscrs.cxx index 4777b767deb3..0a0f5f186d93 100644 --- a/sw/source/core/crsr/viscrs.cxx +++ b/sw/source/core/crsr/viscrs.cxx @@ -56,9 +56,15 @@ #include <PostItMgr.hxx> #include <SwGrammarMarkUp.hxx> #include <docsh.hxx> - +#include <svtools/optionsdrawinglayer.hxx> +#include <o3tl/string_view.hxx> +#include <tools/json_writer.hxx> #include <cellfrm.hxx> #include <wrtsh.hxx> +#include <textcontentcontrol.hxx> +#include <dropdowncontentcontrolbutton.hxx> +#include <datecontentcontrolbutton.hxx> +#include <FrameControlsManager.hxx> // Here static members are defined. They will get changed on alteration of the // MapMode. This is done so that on ShowCursor the same size does not have to be @@ -94,7 +100,7 @@ void SwVisibleCursor::Show() m_bIsVisible = true; // display at all? - if( m_pCursorShell->VisArea().IsOver( m_pCursorShell->m_aCharRect ) || comphelper::LibreOfficeKit::isActive() ) + if( m_pCursorShell->VisArea().Overlaps( m_pCursorShell->m_aCharRect ) || comphelper::LibreOfficeKit::isActive() ) SetPosAndShow(nullptr); } } @@ -122,7 +128,7 @@ OString buildHyperlinkJSON(const OUString& sText, const OUString& sLink) std::stringstream aStream; boost::property_tree::write_json(aStream, aTree, false); - return OString(aStream.str().c_str()).trim(); + return OString(o3tl::trim(aStream.str())); } } @@ -155,7 +161,7 @@ void SwVisibleCursor::SetPosAndShow(SfxViewShell const * pViewShell) if ( pTmpCursor && !m_pCursorShell->IsOverwriteCursor() ) { - SwNode& rNode = pTmpCursor->GetPoint()->nNode.GetNode(); + SwNode& rNode = pTmpCursor->GetPoint()->GetNode(); if( rNode.IsTextNode() ) { const SwTextNode& rTNd = *rNode.GetTextNode(); @@ -222,15 +228,67 @@ void SwVisibleCursor::SetPosAndShow(SfxViewShell const * pViewShell) { m_nPageLastTime = nPage; OString aPayload = OString::number(nPage - 1); - m_pCursorShell->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_SET_PART, aPayload.getStr()); + m_pCursorShell->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_SET_PART, aPayload); } + // This may get called often, so instead of sending data on each update, just notify + // that there's been an update, and the other side will pull the data using + // getLOKPayload() when it decides to. + m_aLastLOKRect = aRect; + if (pViewShell) + { + if (pViewShell == m_pCursorShell->GetSfxViewShell()) + { + SfxLokHelper::notifyUpdatePerViewId(pViewShell, LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR); + } + else + { + SfxLokHelper::notifyUpdatePerViewId(pViewShell, m_pCursorShell->GetSfxViewShell(), pViewShell, + LOK_CALLBACK_INVALIDATE_VIEW_CURSOR); + } + } + else + { + SfxLokHelper::notifyUpdatePerViewId(m_pCursorShell->GetSfxViewShell(), SfxViewShell::Current(), + m_pCursorShell->GetSfxViewShell(), LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR); + SfxLokHelper::notifyOtherViewsUpdatePerViewId(m_pCursorShell->GetSfxViewShell(), LOK_CALLBACK_INVALIDATE_VIEW_CURSOR); + } + } + + if ( m_pCursorShell->IsCursorReadonly() && !m_pCursorShell->GetViewOptions()->IsSelectionInReadonly() ) + return; + + if ( m_pCursorShell->GetDrawView() ) + const_cast<SwDrawView*>(static_cast<const SwDrawView*>(m_pCursorShell->GetDrawView()))->SetAnimationEnabled( + !m_pCursorShell->IsSelection() ); + + sal_uInt16 nStyle = m_bIsDragCursor ? CURSOR_SHADOW : 0; + if( nStyle != m_aTextCursor.GetStyle() ) + { + m_aTextCursor.SetStyle( nStyle ); + m_aTextCursor.SetWindow( m_bIsDragCursor ? m_pCursorShell->GetWin() : nullptr ); + } + + m_aTextCursor.Show(); +} + +std::optional<OString> SwVisibleCursor::getLOKPayload(int nType, int nViewId) const +{ + assert(nType == LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR || nType == LOK_CALLBACK_INVALIDATE_VIEW_CURSOR); + if (comphelper::LibreOfficeKit::isActive()) + { + SwRect aRect = m_aLastLOKRect; + // notify about the cursor position & size tools::Rectangle aSVRect(aRect.Pos().getX(), aRect.Pos().getY(), aRect.Pos().getX() + aRect.SSize().Width(), aRect.Pos().getY() + aRect.SSize().Height()); OString sRect = aSVRect.toString(); + if(nType == LOK_CALLBACK_INVALIDATE_VIEW_CURSOR) + return SfxLokHelper::makePayloadJSON(m_pCursorShell->GetSfxViewShell(), nViewId, "rectangle", sRect); + // is cursor at a misspelled word ? bool bIsWrong = false; + SwView* pView = dynamic_cast<SwView*>(m_pCursorShell->GetSfxViewShell()); if (pView && pView->GetWrtShellPtr()) { const SwViewOption* pVOpt = pView->GetWrtShell().GetViewOptions(); @@ -242,19 +300,18 @@ void SwVisibleCursor::SetPosAndShow(SfxViewShell const * pViewShell) SwCursorMoveState eTmpState(CursorMoveState::SetOnlyText); SwTextNode *pNode = nullptr; if (m_pCursorShell->GetLayout()->GetModelPositionForViewPoint(&aPos, aPt, &eTmpState)) - pNode = aPos.nNode.GetNode().GetTextNode(); + pNode = aPos.GetNode().GetTextNode(); if (pNode && !pNode->IsInProtectSect()) { - sal_Int32 nBegin = aPos.nContent.GetIndex(); + sal_Int32 nBegin = aPos.GetContentIndex(); sal_Int32 nLen = 1; - SwWrongList *pWrong = nullptr; - pWrong = pNode->GetWrong(); + SwWrongList *pWrong = pNode->GetWrong(); if (!pWrong) pWrong = pNode->GetGrammarCheck(); if (pWrong) bIsWrong = pWrong->InWrongWord(nBegin,nLen) && !pNode->IsSymbolAt(nBegin); - } + } } } @@ -273,9 +330,8 @@ void SwVisibleCursor::SetPosAndShow(SfxViewShell const * pViewShell) if (pShell) { - SfxItemSet aSet(m_pCursorShell->GetSfxViewShell()->GetPool(), - svl::Items<RES_TXTATR_INETFMT, - RES_TXTATR_INETFMT>{}); + SfxItemSetFixed<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT> + aSet(m_pCursorShell->GetSfxViewShell()->GetPool()); pShell->GetCurAttr(aSet); if(SfxItemState::SET <= aSet.GetItemState( RES_TXTATR_INETFMT )) { @@ -285,37 +341,10 @@ void SwVisibleCursor::SetPosAndShow(SfxViewShell const * pViewShell) } } - if (pViewShell) - { - if (pViewShell == m_pCursorShell->GetSfxViewShell()) - { - SfxLokHelper::notifyVisCursorInvalidation(pViewShell, sRect, bIsWrong, sHyperlink); - } - else - SfxLokHelper::notifyOtherView(m_pCursorShell->GetSfxViewShell(), pViewShell, LOK_CALLBACK_INVALIDATE_VIEW_CURSOR, "rectangle", sRect); - } - else - { - SfxLokHelper::notifyVisCursorInvalidation(m_pCursorShell->GetSfxViewShell(), sRect, bIsWrong, sHyperlink); - SfxLokHelper::notifyOtherViews(m_pCursorShell->GetSfxViewShell(), LOK_CALLBACK_INVALIDATE_VIEW_CURSOR, "rectangle", sRect); - } + return SfxLokHelper::makeVisCursorInvalidation(nViewId, sRect, bIsWrong, sHyperlink); } - - if ( m_pCursorShell->IsCursorReadonly() && !m_pCursorShell->GetViewOptions()->IsSelectionInReadonly() ) - return; - - if ( m_pCursorShell->GetDrawView() ) - const_cast<SwDrawView*>(static_cast<const SwDrawView*>(m_pCursorShell->GetDrawView()))->SetAnimationEnabled( - !m_pCursorShell->IsSelection() ); - - sal_uInt16 nStyle = m_bIsDragCursor ? CURSOR_SHADOW : 0; - if( nStyle != m_aTextCursor.GetStyle() ) - { - m_aTextCursor.SetStyle( nStyle ); - m_aTextCursor.SetWindow( m_bIsDragCursor ? m_pCursorShell->GetWin() : nullptr ); - } - - m_aTextCursor.Show(); + else + abort(); } const vcl::Cursor& SwVisibleCursor::GetTextCursor() const @@ -324,10 +353,10 @@ const vcl::Cursor& SwVisibleCursor::GetTextCursor() const } SwSelPaintRects::SwSelPaintRects( const SwCursorShell& rCSh ) - : SwRects() - , m_pCursorShell( &rCSh ) + : m_pCursorShell( &rCSh ) #if HAVE_FEATURE_DESKTOP , m_bShowTextInputFieldOverlay(true) + , m_bShowContentControlOverlay(true) #endif { } @@ -335,6 +364,7 @@ SwSelPaintRects::SwSelPaintRects( const SwCursorShell& rCSh ) SwSelPaintRects::~SwSelPaintRects() { Hide(); + m_pContentControlButton.disposeAndClear(); } void SwSelPaintRects::swapContent(SwSelPaintRects& rSwap) @@ -346,6 +376,8 @@ void SwSelPaintRects::swapContent(SwSelPaintRects& rSwap) std::swap(m_pCursorOverlay, rSwap.m_pCursorOverlay); std::swap(m_bShowTextInputFieldOverlay, rSwap.m_bShowTextInputFieldOverlay); std::swap(m_pTextInputFieldOverlay, rSwap.m_pTextInputFieldOverlay); + std::swap(m_bShowContentControlOverlay, rSwap.m_bShowContentControlOverlay); + std::swap(m_pContentControlOverlay, rSwap.m_pContentControlOverlay); #endif } @@ -354,6 +386,7 @@ void SwSelPaintRects::Hide() #if HAVE_FEATURE_DESKTOP m_pCursorOverlay.reset(); m_pTextInputFieldOverlay.reset(); + m_pContentControlOverlay.reset(); #endif SwRects::clear(); @@ -369,7 +402,7 @@ void SwSelPaintRects::Hide() */ static SwRect lcl_getLayoutRect(const Point& rPoint, const SwPosition& rPosition) { - const SwContentNode* pNode = rPosition.nNode.GetNode().GetContentNode(); + const SwContentNode* pNode = rPosition.GetNode().GetContentNode(); std::pair<Point, bool> const tmp(rPoint, true); const SwContentFrame* pFrame = pNode->getLayoutFrame( pNode->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(), @@ -415,7 +448,7 @@ void SwSelPaintRects::Show(std::vector<OString>* pSelectionRectangles) { if(!aNewRanges.empty()) { - static_cast<sdr::overlay::OverlaySelection*>(m_pCursorOverlay.get())->setRanges(aNewRanges); + m_pCursorOverlay->setRanges(std::move(aNewRanges)); } else { @@ -430,14 +463,13 @@ void SwSelPaintRects::Show(std::vector<OString>* pSelectionRectangles) if (xTargetOverlay.is()) { // get the system's highlight color - const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer; - const Color aHighlight(aSvtOptionsDrawinglayer.getHilightColor()); + const Color aHighlight(SvtOptionsDrawinglayer::getHilightColor()); // create correct selection m_pCursorOverlay.reset( new sdr::overlay::OverlaySelection( sdr::overlay::OverlayType::Transparent, aHighlight, - aNewRanges, + std::move(aNewRanges), true) ); xTargetOverlay->add(*m_pCursorOverlay); @@ -445,6 +477,7 @@ void SwSelPaintRects::Show(std::vector<OString>* pSelectionRectangles) } HighlightInputField(); + HighlightContentControl(); #endif // Tiled editing does not expose the draw and writer cursor, it just @@ -457,25 +490,14 @@ void SwSelPaintRects::Show(std::vector<OString>* pSelectionRectangles) // If pSelectionRectangles is set, we're just collecting the text selections -> don't emit start/end. if (!empty() && !pSelectionRectangles) { - // The selection may be a complex polygon, emit the logical - // start/end cursor rectangle of the selection as separate - // events, if there is a real selection. - // This can be used to easily show selection handles on the - // client side. SwRect aStartRect; SwRect aEndRect; FillStartEnd(aStartRect, aEndRect); if (aStartRect.HasArea()) - { - OString sRect = aStartRect.SVRect().toString(); - GetShell()->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION_START, sRect.getStr()); - } + SfxLokHelper::notifyUpdate(GetShell()->GetSfxViewShell(), LOK_CALLBACK_TEXT_SELECTION_START); if (aEndRect.HasArea()) - { - OString sRect = aEndRect.SVRect().toString(); - GetShell()->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION_END, sRect.getStr()); - } + SfxLokHelper::notifyUpdate(GetShell()->GetSfxViewShell(), LOK_CALLBACK_TEXT_SELECTION_END); } std::vector<OString> aRect; @@ -488,13 +510,68 @@ void SwSelPaintRects::Show(std::vector<OString>* pSelectionRectangles) OString sRect = comphelper::string::join("; ", aRect); if (!pSelectionRectangles) { - GetShell()->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION, sRect.getStr()); - SfxLokHelper::notifyOtherViews(GetShell()->GetSfxViewShell(), LOK_CALLBACK_TEXT_VIEW_SELECTION, "selection", sRect); + SfxLokHelper::notifyUpdate(GetShell()->GetSfxViewShell(),LOK_CALLBACK_TEXT_SELECTION); + SfxLokHelper::notifyOtherViewsUpdatePerViewId(GetShell()->GetSfxViewShell(), LOK_CALLBACK_TEXT_VIEW_SELECTION); } else pSelectionRectangles->push_back(sRect); } +std::optional<OString> SwSelPaintRects::getLOKPayload(int nType, int nViewId) const +{ + switch( nType ) + { + case LOK_CALLBACK_TEXT_SELECTION_START: + case LOK_CALLBACK_TEXT_SELECTION_END: + { + // The selection may be a complex polygon, emit the logical + // start/end cursor rectangle of the selection as separate + // events, if there is a real selection. + // This can be used to easily show selection handles on the + // client side. + SwRect aStartRect; + SwRect aEndRect; + FillStartEnd(aStartRect, aEndRect); + + // no selection rect + if (!size()) + return {}; + + if( nType == LOK_CALLBACK_TEXT_SELECTION_START ) + { + if (aStartRect.HasArea()) + return aStartRect.SVRect().toString(); + return {}; + } + else // LOK_CALLBACK_TEXT_SELECTION_END + { + if (aEndRect.HasArea()) + return aEndRect.SVRect().toString(); + return {}; + } + } + break; + case LOK_CALLBACK_TEXT_SELECTION: + case LOK_CALLBACK_TEXT_VIEW_SELECTION: + { + std::vector<OString> aRect; + aRect.reserve(size()); + for (size_type i = 0; i < size(); ++i) + { + const SwRect& rRect = (*this)[i]; + aRect.push_back(rRect.SVRect().toString()); + } + OString sRect = comphelper::string::join("; ", aRect); + if( nType == LOK_CALLBACK_TEXT_SELECTION ) + return sRect; + else // LOK_CALLBACK_TEXT_VIEW_SELECTION + return SfxLokHelper::makePayloadJSON(GetShell()->GetSfxViewShell(), nViewId, "selection", sRect); + } + break; + } + abort(); +} + void SwSelPaintRects::HighlightInputField() { std::vector< basegfx::B2DRange > aInputFieldRanges; @@ -502,18 +579,17 @@ void SwSelPaintRects::HighlightInputField() if (m_bShowTextInputFieldOverlay) { SwTextInputField* pCurTextInputFieldAtCursor = - dynamic_cast<SwTextInputField*>(SwCursorShell::GetTextFieldAtPos( GetShell()->GetCursor()->Start(), false )); + dynamic_cast<SwTextInputField*>(SwCursorShell::GetTextFieldAtPos( GetShell()->GetCursor()->Start(), ::sw::GetTextAttrMode::Expand)); if ( pCurTextInputFieldAtCursor != nullptr ) { SwTextNode* pTextNode = pCurTextInputFieldAtCursor->GetpTextNode(); std::unique_ptr<SwShellCursor> pCursorForInputTextField( new SwShellCursor( *GetShell(), SwPosition( *pTextNode, pCurTextInputFieldAtCursor->GetStart() ) ) ); pCursorForInputTextField->SetMark(); - pCursorForInputTextField->GetMark()->nNode = *pTextNode; - pCursorForInputTextField->GetMark()->nContent.Assign( pTextNode, *(pCurTextInputFieldAtCursor->End()) ); + pCursorForInputTextField->GetMark()->Assign(*pTextNode, *(pCurTextInputFieldAtCursor->End()) ); pCursorForInputTextField->FillRects(); - SwRects* pRects = static_cast<SwRects*>(pCursorForInputTextField.get()); + SwRects* pRects = pCursorForInputTextField.get(); for (const SwRect & rNextRect : *pRects) { const tools::Rectangle aPntRect(rNextRect.SVRect()); @@ -529,7 +605,7 @@ void SwSelPaintRects::HighlightInputField() { if (m_pTextInputFieldOverlay != nullptr) { - m_pTextInputFieldOverlay->setRanges( aInputFieldRanges ); + m_pTextInputFieldOverlay->setRanges( std::move(aInputFieldRanges) ); } else { @@ -540,12 +616,11 @@ void SwSelPaintRects::HighlightInputField() if (xTargetOverlay.is()) { // use system's highlight color with decreased luminance as highlight color - const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer; - Color aHighlight(aSvtOptionsDrawinglayer.getHilightColor()); + Color aHighlight(SvtOptionsDrawinglayer::getHilightColor()); aHighlight.DecreaseLuminance( 128 ); m_pTextInputFieldOverlay.reset( new sw::overlay::OverlayRangesOutline( - aHighlight, aInputFieldRanges ) ); + aHighlight, std::move(aInputFieldRanges) ) ); xTargetOverlay->add( *m_pTextInputFieldOverlay ); } } @@ -556,6 +631,218 @@ void SwSelPaintRects::HighlightInputField() } } +void SwSelPaintRects::HighlightContentControl() +{ + std::vector<basegfx::B2DRange> aContentControlRanges; + std::vector<OString> aLOKRectangles; + SwRect aFirstPortionPaintArea; + SwRect aLastPortionPaintArea; + bool bRTL = false; + std::shared_ptr<SwContentControl> pContentControl; + + if (m_bShowContentControlOverlay) + { + const SwPosition* pStart = GetShell()->GetCursor()->Start(); + SwTextNode* pTextNode = pStart->GetNode().GetTextNode(); + SwTextContentControl* pCurContentControlAtCursor = nullptr; + if (pTextNode) + { + // GetTextAttrMode::Parent because this way we highlight when the user will type inside the + // content control, not outside of it. + SwTextAttr* pAttr = pTextNode->GetTextAttrAt( + pStart->GetContentIndex(), RES_TXTATR_CONTENTCONTROL, ::sw::GetTextAttrMode::Parent); + if (pAttr) + { + pCurContentControlAtCursor = static_txtattr_cast<SwTextContentControl*>(pAttr); + } + } + if (pCurContentControlAtCursor) + { + auto pCursorForContentControl = std::make_unique<SwShellCursor>( + *GetShell(), SwPosition(*pTextNode, pCurContentControlAtCursor->GetStart())); + pCursorForContentControl->SetMark(); + pCursorForContentControl->GetMark()->Assign( + *pTextNode, *(pCurContentControlAtCursor->End())); + + pCursorForContentControl->FillRects(); + SwRects* pRects = pCursorForContentControl.get(); + for (const auto& rRect : *pRects) + { + tools::Rectangle aRect(rRect.SVRect()); + + aContentControlRanges.emplace_back(aRect.Left(), aRect.Top(), aRect.Right() + 1, + aRect.Bottom() + 1); + if (comphelper::LibreOfficeKit::isActive()) + { + aLOKRectangles.push_back(aRect.toString()); + } + } + + if (!pRects->empty()) + { + aFirstPortionPaintArea = (*pRects)[0]; + aLastPortionPaintArea = (*pRects)[pRects->size() - 1]; + } + pContentControl = pCurContentControlAtCursor->GetContentControl().GetContentControl(); + + // The layout knows if the text node is RTL (either set directly, or inherited from the + // environment). + SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aFrames(*pTextNode); + SwTextFrame* pFrame = aFrames.First(); + if (pFrame) + { + bRTL = pFrame->IsRightToLeft(); + } + } + } + + auto pWrtShell = dynamic_cast<const SwWrtShell*>(GetShell()); + if (!aContentControlRanges.empty()) + { + if (comphelper::LibreOfficeKit::isActive()) + { + OString aPayload = comphelper::string::join("; ", aLOKRectangles); + tools::JsonWriter aJson; + aJson.put("action", "show"); + aJson.put("rectangles", aPayload); + + if (pContentControl && (pContentControl->GetComboBox() || pContentControl->GetDropDown())) + { + auto aItems = aJson.startArray("items"); + for (const auto& rItem : pContentControl->GetListItems()) + { + aJson.putSimpleValue(rItem.ToString()); + } + } + + if (pContentControl && pContentControl->GetDate()) + { + aJson.put("date", "true"); + } + + if (pContentControl && !pContentControl->GetAlias().isEmpty()) + { + aJson.put("alias", pContentControl->GetAlias()); + } + + OString pJson(aJson.finishAndGetAsOString()); + GetShell()->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_CONTENT_CONTROL, pJson); + } + if (m_pContentControlOverlay) + { + m_pContentControlOverlay->setRanges(std::move(aContentControlRanges)); + } + else + { + SdrView* pView = const_cast<SdrView*>(GetShell()->GetDrawView()); + SdrPaintWindow* pCandidate = pView->GetPaintWindow(0); + const rtl::Reference<sdr::overlay::OverlayManager>& xTargetOverlay + = pCandidate->GetOverlayManager(); + + if (xTargetOverlay.is()) + { + // Use the system's highlight color with decreased luminance as highlight color. + Color aHighlight(SvtOptionsDrawinglayer::getHilightColor()); + aHighlight.DecreaseLuminance(128); + + m_pContentControlOverlay.reset(new sw::overlay::OverlayRangesOutline( + aHighlight, std::move(aContentControlRanges))); + xTargetOverlay->add(*m_pContentControlOverlay); + } + } + + if (pContentControl && (pContentControl->GetComboBox() || pContentControl->GetDropDown())) + { + if (pWrtShell) + { + auto& rEditWin = const_cast<SwEditWin&>(pWrtShell->GetView().GetEditWin()); + if (m_pContentControlButton + && m_pContentControlButton->GetContentControl() != pContentControl) + { + m_pContentControlButton.disposeAndClear(); + } + if (!m_pContentControlButton) + { + m_pContentControlButton = VclPtr<SwDropDownContentControlButton>::Create( + &rEditWin, pContentControl); + } + m_pContentControlButton->SetRTL(bRTL); + if (bRTL) + { + m_pContentControlButton->CalcPosAndSize(aFirstPortionPaintArea); + } + else + { + m_pContentControlButton->CalcPosAndSize(aLastPortionPaintArea); + } + m_pContentControlButton->Show(); + } + } + if (pContentControl && pContentControl->GetDate()) + { + if (pWrtShell) + { + auto& rEditWin = const_cast<SwEditWin&>(pWrtShell->GetView().GetEditWin()); + if (m_pContentControlButton + && m_pContentControlButton->GetContentControl() != pContentControl) + { + m_pContentControlButton.disposeAndClear(); + } + if (!m_pContentControlButton) + { + m_pContentControlButton = VclPtr<SwDateContentControlButton>::Create( + &rEditWin, pContentControl, pWrtShell->GetDoc()->GetNumberFormatter()); + } + m_pContentControlButton->CalcPosAndSize(aLastPortionPaintArea); + m_pContentControlButton->Show(); + } + } + + if (pWrtShell) + { + auto& rEditWin = const_cast<SwEditWin&>(pWrtShell->GetView().GetEditWin()); + SwFrameControlsManager& rMngr = rEditWin.GetFrameControlsManager(); + if (pContentControl && !pContentControl->GetAlias().isEmpty()) + { + Point aTopLeftPixel = rEditWin.LogicToPixel(aFirstPortionPaintArea.TopLeft()); + rMngr.SetContentControlAliasButton(pContentControl.get(), aTopLeftPixel); + } + else + { + rMngr.HideControls(FrameControlType::ContentControl); + } + } + } + else + { + if (comphelper::LibreOfficeKit::isActive() && m_pContentControlOverlay) + { + tools::JsonWriter aJson; + aJson.put("action", "hide"); + OString pJson(aJson.finishAndGetAsOString()); + GetShell()->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_CONTENT_CONTROL, pJson); + } + m_pContentControlOverlay.reset(); + + if (m_pContentControlButton) + { + m_pContentControlButton.disposeAndClear(); + } + + if (pWrtShell) + { + auto& rEditWin = const_cast<SwEditWin&>(pWrtShell->GetView().GetEditWin()); + SwFrameControlsManager& rMngr = rEditWin.GetFrameControlsManager(); + rMngr.HideControls(FrameControlType::ContentControl); + } + } +} + +const VclPtr<SwContentControlButton>& SwSelPaintRects::GetContentControlButton() const +{ + return m_pContentControlButton; +} + void SwSelPaintRects::Invalidate( const SwRect& rRect ) { size_type nSz = size(); @@ -592,7 +879,7 @@ void SwSelPaintRects::Invalidate( const SwRect& rRect ) void SwSelPaintRects::Get1PixelInLogic( const SwViewShell& rSh, tools::Long* pX, tools::Long* pY ) { - const OutputDevice* pOut = rSh.GetWin(); + const OutputDevice* pOut = rSh.GetWin()->GetOutDev(); if ( ! pOut ) pOut = rSh.GetOut(); @@ -662,12 +949,14 @@ void SwShellCursor::FillRects() { // calculate the new rectangles if( HasMark() && - GetPoint()->nNode.GetNode().IsContentNode() && - GetPoint()->nNode.GetNode().GetContentNode()->getLayoutFrame( GetShell()->GetLayout() ) && - (GetMark()->nNode == GetPoint()->nNode || - (GetMark()->nNode.GetNode().IsContentNode() && - GetMark()->nNode.GetNode().GetContentNode()->getLayoutFrame( GetShell()->GetLayout() ) ) )) - GetShell()->GetLayout()->CalcFrameRects( *this ); + GetPoint()->GetNode().IsContentNode() && + GetPoint()->GetNode().GetContentNode()->getLayoutFrame( GetShell()->GetLayout() ) && + (GetMark()->GetNode() == GetPoint()->GetNode() || + (GetMark()->GetNode().IsContentNode() && + GetMark()->GetNode().GetContentNode()->getLayoutFrame( GetShell()->GetLayout() ) ) )) + { + GetShell()->GetLayout()->CalcFrameRects(*this, *this); + } } void SwShellCursor::Show(SfxViewShell const * pViewShell) @@ -699,7 +988,7 @@ void SwShellCursor::Show(SfxViewShell const * pViewShell) } else { - GetShell()->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION, sRect.getStr()); + GetShell()->GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION, sRect); SfxLokHelper::notifyOtherViews(GetShell()->GetSfxViewShell(), LOK_CALLBACK_TEXT_VIEW_SELECTION, "selection", sRect); } } @@ -780,6 +1069,33 @@ void SwShellCursor::SaveTableBoxContent( const SwPosition* pPos ) bool SwShellCursor::UpDown( bool bUp, sal_uInt16 nCnt ) { + // tdf#124603 trigger pending spell checking of the node + if ( nCnt == 1 ) + { + SwTextNode* pNode = GetPoint()->GetNode().GetTextNode(); + if( pNode && sw::WrongState::PENDING == pNode->GetWrongDirty() ) + { + SwWrtShell* pShell = pNode->GetDoc().GetDocShell()->GetWrtShell(); + if ( pShell && !pShell->IsSelection() && !pShell->IsSelFrameMode() ) + { + const SwViewOption* pVOpt = pShell->GetViewOptions(); + if ( pVOpt && pVOpt->IsOnlineSpell() ) + { + const bool bOldViewLock = pShell->IsViewLocked(); + pShell->LockView( true ); + + SwTextFrame* pFrame( + static_cast<SwTextFrame*>(pNode->getLayoutFrame(GetShell()->GetLayout()))); + SwRect aRepaint(pFrame->AutoSpell_(*pNode, 0)); + if (aRepaint.HasArea()) + pShell->InvalidateWindows(aRepaint); + + pShell->LockView( bOldViewLock ); + } + } + } + } + return SwCursor::UpDown( bUp, nCnt, &GetPtPos(), GetShell()->GetUpDownX(), *GetShell()->GetLayout()); @@ -836,14 +1152,13 @@ void SwShellTableCursor::SaveTableBoxContent( const SwPosition* pPos ) void SwShellTableCursor::FillRects() { // Calculate the new rectangles. If the cursor is still "parked" do nothing - if (m_SelectedBoxes.empty() || m_bParked || !GetPoint()->nNode.GetIndex()) + if (m_SelectedBoxes.empty() || m_bParked || !GetPoint()->GetNodeIndex()) return; bool bStart = true; - SwRegionRects aReg( GetShell()->VisArea() ); - if (comphelper::LibreOfficeKit::isActive()) - aReg = GetShell()->getIDocumentLayoutAccess().GetCurrentLayout()->getFrameArea(); - SwNodes& rNds = GetDoc().GetNodes(); + SwRegionRects aReg( comphelper::LibreOfficeKit::isActive() + ? GetShell()->getIDocumentLayoutAccess().GetCurrentLayout()->getFrameArea() + : GetShell()->VisArea() ); SwFrame* pEndFrame = nullptr; for (size_t n = 0; n < m_SelectedBoxes.size(); ++n) { @@ -851,7 +1166,7 @@ void SwShellTableCursor::FillRects() const SwTableNode* pSelTableNd = pSttNd->FindTableNode(); SwNodeIndex aIdx( *pSttNd ); - SwContentNode* pCNd = rNds.GoNextSection( &aIdx, true, false ); + SwContentNode* pCNd = SwNodes::GoNextSection(&aIdx, true, false); // table in table // (see also lcl_FindTopLevelTable in unoobj2.cxx for a different @@ -860,7 +1175,7 @@ void SwShellTableCursor::FillRects() while ( pSelTableNd != pCurTableNd && pCurTableNd ) { aIdx = pCurTableNd->EndOfSectionIndex(); - pCNd = rNds.GoNextSection( &aIdx, true, false ); + pCNd = SwNodes::GoNextSection(&aIdx, true, false); pCurTableNd = pCNd->FindTableNode(); } @@ -876,7 +1191,7 @@ void SwShellTableCursor::FillRects() while ( pFrame ) { - if( aReg.GetOrigin().IsOver( pFrame->getFrameArea() ) ) + if( aReg.GetOrigin().Overlaps( pFrame->getFrameArea() ) ) { aReg -= pFrame->getFrameArea(); if (bStart) @@ -903,17 +1218,16 @@ void SwShellTableCursor::FillStartEnd(SwRect& rStart, SwRect& rEnd) const } // Check if the SPoint is within the Table-SSelection. -bool SwShellTableCursor::IsInside( const Point& rPt ) const +bool SwShellTableCursor::Contains( const Point& rPt ) const { // Calculate the new rectangles. If the cursor is still "parked" do nothing - if (m_SelectedBoxes.empty() || m_bParked || !GetPoint()->nNode.GetIndex()) + if (m_SelectedBoxes.empty() || m_bParked || !GetPoint()->GetNodeIndex()) return false; - SwNodes& rNds = GetDoc().GetNodes(); for (size_t n = 0; n < m_SelectedBoxes.size(); ++n) { SwNodeIndex aIdx( *m_SelectedBoxes[n]->GetSttNd() ); - SwContentNode* pCNd = rNds.GoNextSection( &aIdx, true, false ); + SwContentNode* pCNd = SwNodes::GoNextSection(&aIdx, true, false); if( !pCNd ) continue; @@ -922,12 +1236,12 @@ bool SwShellTableCursor::IsInside( const Point& rPt ) const while( pFrame && !pFrame->IsCellFrame() ) pFrame = pFrame->GetUpper(); OSL_ENSURE( pFrame, "Node not in a table" ); - if( pFrame && pFrame->getFrameArea().IsInside( rPt ) ) + if( pFrame && pFrame->getFrameArea().Contains( rPt ) ) return true; for ( SwCellFrame* pCellFrame = static_cast<SwCellFrame*>(pFrame); pCellFrame; pCellFrame = pCellFrame->GetFollowCell() ) { - if( pCellFrame->getFrameArea().IsInside( rPt ) ) + if( pCellFrame->getFrameArea().Contains( rPt ) ) return true; } } |