diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
commit | 940b4d1848e8c70ab7642901a68594e8016caffc (patch) | |
tree | eb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /sw/source/core/edit/edsect.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.tar.xz libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.zip |
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sw/source/core/edit/edsect.cxx')
-rw-r--r-- | sw/source/core/edit/edsect.cxx | 421 |
1 files changed, 421 insertions, 0 deletions
diff --git a/sw/source/core/edit/edsect.cxx b/sw/source/core/edit/edsect.cxx new file mode 100644 index 000000000..ba765eee4 --- /dev/null +++ b/sw/source/core/edit/edsect.cxx @@ -0,0 +1,421 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <editsh.hxx> +#include <doc.hxx> +#include <IDocumentUndoRedo.hxx> +#include <IDocumentContentOperations.hxx> +#include <pam.hxx> +#include <docary.hxx> +#include <swundo.hxx> +#include <section.hxx> +#include <sectfrm.hxx> +#include <cntfrm.hxx> +#include <tabfrm.hxx> +#include <rootfrm.hxx> + +SwSection const* +SwEditShell::InsertSection( + SwSectionData & rNewData, SfxItemSet const*const pAttr) +{ + const SwSection* pRet = nullptr; + if( !IsTableMode() ) + { + StartAllAction(); + GetDoc()->GetIDocumentUndoRedo().StartUndo( SwUndoId::INSSECTION, nullptr ); + + for(const SwPaM& rPaM : GetCursor()->GetRingContainer()) + { + SwSection const*const pNew = + GetDoc()->InsertSwSection( rPaM, rNewData, nullptr, pAttr ); + if( !pRet ) + pRet = pNew; + } + + GetDoc()->GetIDocumentUndoRedo().EndUndo( SwUndoId::INSSECTION, nullptr ); + EndAllAction(); + } + return pRet; +} + +bool SwEditShell::IsInsRegionAvailable() const +{ + if( IsTableMode() ) + return false; + SwPaM* pCursor = GetCursor(); + if( pCursor->GetNext() != pCursor ) + return false; + if( pCursor->HasMark() ) + return 0 != SwDoc::IsInsRegionAvailable( *pCursor ); + + return true; +} + +const SwSection* SwEditShell::GetCurrSection() const +{ + if( IsTableMode() ) + return nullptr; + + return SwDoc::GetCurrSection( *GetCursor()->GetPoint() ); +} + +/** Deliver the responsible area of the columns. + * + * In footnotes it may not be the area within the footnote. + */ +SwSection* SwEditShell::GetAnySection( bool bOutOfTab, const Point* pPt ) +{ + SwFrame *pFrame; + if ( pPt ) + { + SwPosition aPos( *GetCursor()->GetPoint() ); + Point aPt( *pPt ); + GetLayout()->GetModelPositionForViewPoint( &aPos, aPt ); + SwContentNode *pNd = aPos.nNode.GetNode().GetContentNode(); + std::pair<Point, bool> const tmp(*pPt, true); + pFrame = pNd->getLayoutFrame(GetLayout(), nullptr, &tmp); + } + else + pFrame = GetCurrFrame( false ); + + if( bOutOfTab && pFrame ) + pFrame = pFrame->FindTabFrame(); + if( pFrame && pFrame->IsInSct() ) + { + SwSectionFrame* pSect = pFrame->FindSctFrame(); + OSL_ENSURE( pSect, "GetAnySection: Where's my Sect?" ); + if( pSect->IsInFootnote() && pSect->GetUpper()->IsInSct() ) + { + pSect = pSect->GetUpper()->FindSctFrame(); + OSL_ENSURE( pSect, "GetAnySection: Where's my SectFrame?" ); + } + return pSect->GetSection(); + } + return nullptr; +} + +size_t SwEditShell::GetSectionFormatCount() const +{ + return GetDoc()->GetSections().size(); +} + +bool SwEditShell::IsAnySectionInDoc() const +{ + const SwSectionFormats& rFormats = GetDoc()->GetSections(); + + for( const SwSectionFormat* pFormat : rFormats ) + { + SectionType eTmpType; + if( pFormat->IsInNodesArr() && + ( (eTmpType = pFormat->GetSection()->GetType()) != SectionType::ToxContent + && SectionType::ToxHeader != eTmpType ) ) + { + return true; + } + } + return false; +} + +size_t SwEditShell::GetSectionFormatPos( const SwSectionFormat& rFormat ) const +{ + SwSectionFormat* pFormat = const_cast<SwSectionFormat*>(&rFormat); + return GetDoc()->GetSections().GetPos( pFormat ); +} + +const SwSectionFormat& SwEditShell::GetSectionFormat(size_t nFormat) const +{ + return *GetDoc()->GetSections()[ nFormat ]; +} + +void SwEditShell::DelSectionFormat(size_t nFormat) +{ + StartAllAction(); + GetDoc()->DelSectionFormat( GetDoc()->GetSections()[ nFormat ] ); + // Call the AttrChangeNotify on the UI page. + CallChgLnk(); + EndAllAction(); +} + +void SwEditShell::UpdateSection(size_t const nSect, + SwSectionData & rNewData, SfxItemSet const*const pAttr) +{ + StartAllAction(); + GetDoc()->UpdateSection( nSect, rNewData, pAttr ); + // Call the AttrChangeNotify on the UI page. + CallChgLnk(); + EndAllAction(); +} + +OUString SwEditShell::GetUniqueSectionName( const OUString* pChkStr ) const +{ + return GetDoc()->GetUniqueSectionName( pChkStr ); +} + +void SwEditShell::SetSectionAttr( const SfxItemSet& rSet, + SwSectionFormat* pSectFormat ) +{ + if( pSectFormat ) + SetSectionAttr_( *pSectFormat, rSet ); + else + { + // for all section in the selection + + for(SwPaM& rPaM : GetCursor()->GetRingContainer()) + { + const SwPosition* pStt = rPaM.Start(), + * pEnd = rPaM.End(); + + SwSectionNode* pSttSectNd = pStt->nNode.GetNode().FindSectionNode(), + * pEndSectNd = pEnd->nNode.GetNode().FindSectionNode(); + + if( pSttSectNd || pEndSectNd ) + { + if( pSttSectNd ) + SetSectionAttr_( *pSttSectNd->GetSection().GetFormat(), + rSet ); + if( pEndSectNd && pSttSectNd != pEndSectNd ) + SetSectionAttr_( *pEndSectNd->GetSection().GetFormat(), + rSet ); + + if( pSttSectNd && pEndSectNd ) + { + SwNodeIndex aSIdx( pStt->nNode ); + SwNodeIndex aEIdx( pEnd->nNode ); + if( pSttSectNd->EndOfSectionIndex() < + pEndSectNd->GetIndex() ) + { + aSIdx = pSttSectNd->EndOfSectionIndex() + 1; + aEIdx = *pEndSectNd; + } + + while( aSIdx < aEIdx ) + { + if( nullptr != (pSttSectNd = aSIdx.GetNode().GetSectionNode()) + || ( aSIdx.GetNode().IsEndNode() && + nullptr != ( pSttSectNd = aSIdx.GetNode(). + StartOfSectionNode()->GetSectionNode())) ) + SetSectionAttr_( *pSttSectNd->GetSection().GetFormat(), + rSet ); + ++aSIdx; + } + } + } + + } + } +} + +void SwEditShell::SetSectionAttr_( SwSectionFormat& rSectFormat, + const SfxItemSet& rSet ) +{ + StartAllAction(); + if(SfxItemState::SET == rSet.GetItemState(RES_CNTNT, false)) + { + SfxItemSet aSet(rSet); + aSet.ClearItem(RES_CNTNT); + GetDoc()->SetAttr( aSet, rSectFormat ); + } + else + GetDoc()->SetAttr( rSet, rSectFormat ); + + // Call the AttrChangeNotify on the UI page. + CallChgLnk(); + EndAllAction(); +} + +/** Search inside the cursor selection for full selected sections. + * + * @return If any part of section in the selection return 0, if more than one return the count. + */ +sal_uInt16 SwEditShell::GetFullSelectedSectionCount() const +{ + sal_uInt16 nRet = 0; + for(SwPaM& rPaM : GetCursor()->GetRingContainer()) + { + + const SwPosition* pStt = rPaM.Start(), + * pEnd = rPaM.End(); + const SwContentNode* pCNd; + // check the selection, if Start at Node begin and End at Node end + if( pStt->nContent.GetIndex() || + ( nullptr == ( pCNd = pEnd->nNode.GetNode().GetContentNode() )) || + pCNd->Len() != pEnd->nContent.GetIndex() ) + { + nRet = 0; + break; + } + +// !!! +// what about table at start or end ? +// There is no selection possible! +// What about only a table inside the section ? +// There is only a table selection possible! + + SwNodeIndex aSIdx( pStt->nNode, -1 ), aEIdx( pEnd->nNode, +1 ); + if( !aSIdx.GetNode().IsSectionNode() || + !aEIdx.GetNode().IsEndNode() || + !aEIdx.GetNode().StartOfSectionNode()->IsSectionNode() ) + { + nRet = 0; + break; + } + + ++nRet; + if( &aSIdx.GetNode() != aEIdx.GetNode().StartOfSectionNode() ) + ++nRet; + + } + return nRet; +} + +/** Find the suitable node for a special insert (alt-enter). + * + * This should enable inserting text before/after sections and tables. + * + * A node is found if: + * 1) the innermost table/section is not in a write-protected area + * 2) pCurrentPos is at or just before an end node + * (or at or just after a start node) + * 3) there are only start/end nodes between pCurrentPos and the innermost + * table/section + * + * If a suitable node is found, an SwNode* is returned; else it is NULL. + */ +static const SwNode* lcl_SpecialInsertNode(const SwPosition* pCurrentPos) +{ + const SwNode* pReturn = nullptr; + + // the current position + OSL_ENSURE( pCurrentPos != nullptr, "Strange, we have no position!" ); + const SwNode& rCurrentNode = pCurrentPos->nNode.GetNode(); + + // find innermost section or table. At the end of this scope, + // pInntermostNode contain the section/table before/after which we should + // insert our empty paragraph, or it will be NULL if none is found. + const SwNode* pInnermostNode = nullptr; + { + const SwNode* pTableNode = rCurrentNode.FindTableNode(); + const SwNode* pSectionNode = rCurrentNode.FindSectionNode(); + + // find the table/section which is close + if( pTableNode == nullptr ) + pInnermostNode = pSectionNode; + else if ( pSectionNode == nullptr ) + pInnermostNode = pTableNode; + else + { + // compare and choose the larger one + pInnermostNode = + ( pSectionNode->GetIndex() > pTableNode->GetIndex() ) + ? pSectionNode : pTableNode; + } + } + + // The previous version had a check to skip empty read-only sections. Those + // shouldn't occur, so we only need to check whether our pInnermostNode is + // inside a protected area. + + // Now, pInnermostNode is NULL or the innermost section or table node. + if( (pInnermostNode != nullptr) && !pInnermostNode->IsProtect() ) + { + OSL_ENSURE( pInnermostNode->IsTableNode() || + pInnermostNode->IsSectionNode(), "wrong node found" ); + OSL_ENSURE( ( pInnermostNode->GetIndex() <= rCurrentNode.GetIndex() )&& + ( pInnermostNode->EndOfSectionNode()->GetIndex() >= + rCurrentNode.GetIndex() ), "wrong node found" ); + + // we now need to find the possible start/end positions + + // we found a start if + // - we're at or just before a start node + // - there are only start nodes between the current and pInnermostNode + SwNodeIndex aBegin( pCurrentPos->nNode ); + if( rCurrentNode.IsContentNode() && + (pCurrentPos->nContent.GetIndex() == 0)) + --aBegin; + while( (aBegin != pInnermostNode->GetIndex()) && + aBegin.GetNode().IsStartNode() ) + --aBegin; + bool bStart = ( aBegin == pInnermostNode->GetIndex() ); + + // we found an end if + // - we're at or just before an end node + // - there are only end nodes between the current node and + // pInnermostNode's end node + SwNodeIndex aEnd( pCurrentPos->nNode ); + if( rCurrentNode.IsContentNode() && + ( pCurrentPos->nContent.GetIndex() == + rCurrentNode.GetContentNode()->Len() ) ) + ++aEnd; + while( (aEnd != pInnermostNode->EndOfSectionNode()->GetIndex()) && + aEnd.GetNode().IsEndNode() ) + ++aEnd; + bool bEnd = ( aEnd == pInnermostNode->EndOfSectionNode()->GetIndex() ); + + // evaluate result: if both start + end, end is preferred + if( bEnd ) + pReturn = pInnermostNode->EndOfSectionNode(); + else if ( bStart ) + pReturn = pInnermostNode; + } + + OSL_ENSURE( ( pReturn == nullptr ) || pReturn->IsStartNode() || + pReturn->IsEndNode(), + "SpecialInsertNode failed" ); + return pReturn; +} + +/** a node can be special-inserted (alt-Enter) whenever lcl_SpecialInsertNode + finds a suitable position +*/ +bool SwEditShell::CanSpecialInsert() const +{ + return nullptr != lcl_SpecialInsertNode( GetCursor()->GetPoint() ); +} + +/** check whether a node can be special-inserted (alt-Enter), and do so. Return + whether insertion was possible. + */ +void SwEditShell::DoSpecialInsert() +{ + // get current node + SwPosition* pCursorPos = GetCursor()->GetPoint(); + const SwNode* pInsertNode = lcl_SpecialInsertNode( pCursorPos ); + if( pInsertNode != nullptr ) + { + StartAllAction(); + + // adjust insert position to insert before start nodes and after end + // nodes + SwNodeIndex aInsertIndex( *pInsertNode, + pInsertNode->IsStartNode() ? -1 : 0 ); + SwPosition aInsertPos( aInsertIndex ); + + // insert a new text node, and set the cursor + GetDoc()->getIDocumentContentOperations().AppendTextNode( aInsertPos ); + *pCursorPos = aInsertPos; + + // call AttrChangeNotify for the UI + CallChgLnk(); + + EndAllAction(); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |