summaryrefslogtreecommitdiff
path: root/sw/source/core/edit/edsect.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/edit/edsect.cxx')
-rw-r--r--sw/source/core/edit/edsect.cxx455
1 files changed, 455 insertions, 0 deletions
diff --git a/sw/source/core/edit/edsect.cxx b/sw/source/core/edit/edsect.cxx
new file mode 100644
index 000000000000..898e80a95f56
--- /dev/null
+++ b/sw/source/core/edit/edsect.cxx
@@ -0,0 +1,455 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <editsh.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <pam.hxx>
+#include <docary.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <section.hxx>
+#include <edimp.hxx>
+#include <sectfrm.hxx> // SwSectionFrm
+#include <cntfrm.hxx> // SwCntntFrm
+#include <tabfrm.hxx> // SwTabFrm
+#include <rootfrm.hxx> // SwRootFrm
+
+
+SwSection const*
+SwEditShell::InsertSection(
+ SwSectionData & rNewData, SfxItemSet const*const pAttr)
+{
+ const SwSection* pRet = 0;
+ if( !IsTableMode() )
+ {
+ StartAllAction();
+ GetDoc()->GetIDocumentUndoRedo().StartUndo( UNDO_INSSECTION, NULL );
+
+ FOREACHPAM_START(this)
+ SwSection const*const pNew =
+ GetDoc()->InsertSwSection( *PCURCRSR, rNewData, 0, pAttr );
+ if( !pRet )
+ pRet = pNew;
+ FOREACHPAM_END()
+
+ GetDoc()->GetIDocumentUndoRedo().EndUndo( UNDO_INSSECTION, NULL );
+ EndAllAction();
+ }
+ return pRet;
+}
+
+
+sal_Bool SwEditShell::IsInsRegionAvailable() const
+{
+ if( IsTableMode() )
+ return sal_False;
+ SwPaM* pCrsr = GetCrsr();
+ if( pCrsr->GetNext() != pCrsr )
+ return sal_False;
+ if( pCrsr->HasMark() )
+ return 0 != GetDoc()->IsInsRegionAvailable( *pCrsr );
+
+ return sal_True;
+}
+
+
+const SwSection* SwEditShell::GetCurrSection() const
+{
+ if( IsTableMode() )
+ return 0;
+
+ return GetDoc()->GetCurrSection( *GetCrsr()->GetPoint() );
+}
+
+/*-----------------17.03.99 11:53-------------------
+ * SwEditShell::GetAnySection liefert den fuer Spalten
+ * zustaendigen Bereich, bei Fussnoten kann es nicht der
+ * Bereich innerhalb der Fussnote sein.
+ * --------------------------------------------------*/
+
+const SwSection* SwEditShell::GetAnySection( sal_Bool bOutOfTab, const Point* pPt ) const
+{
+ SwFrm *pFrm;
+ if ( pPt )
+ {
+ SwPosition aPos( *GetCrsr()->GetPoint() );
+ Point aPt( *pPt );
+ GetLayout()->GetCrsrOfst( &aPos, aPt );
+ SwCntntNode *pNd = aPos.nNode.GetNode().GetCntntNode();
+ pFrm = pNd->GetFrm( pPt );
+ }
+ else
+ pFrm = GetCurrFrm( sal_False );
+
+ if( bOutOfTab && pFrm )
+ pFrm = pFrm->FindTabFrm();
+ if( pFrm && pFrm->IsInSct() )
+ {
+ SwSectionFrm* pSect = pFrm->FindSctFrm();
+ ASSERT( pSect, "GetAnySection: Where's my Sect?" );
+ if( pSect->IsInFtn() && pSect->GetUpper()->IsInSct() )
+ {
+ pSect = pSect->GetUpper()->FindSctFrm();
+ ASSERT( pSect, "GetAnySection: Where's my SectFrm?" );
+ }
+ return pSect->GetSection();
+ }
+ return NULL;
+}
+
+sal_uInt16 SwEditShell::GetSectionFmtCount() const
+{
+ return GetDoc()->GetSections().Count();
+}
+
+
+sal_Bool SwEditShell::IsAnySectionInDoc( sal_Bool bChkReadOnly, sal_Bool bChkHidden, sal_Bool bChkTOX ) const
+{
+ const SwSectionFmts& rFmts = GetDoc()->GetSections();
+ sal_uInt16 nCnt = rFmts.Count();
+ sal_uInt16 n;
+
+ for( n = 0; n < nCnt; ++n )
+ {
+ SectionType eTmpType;
+ const SwSectionFmt* pFmt = rFmts[ n ];
+ if( pFmt->IsInNodesArr() &&
+ (bChkTOX ||
+ ( (eTmpType = pFmt->GetSection()->GetType()) != TOX_CONTENT_SECTION
+ && TOX_HEADER_SECTION != eTmpType ) ) )
+ {
+ const SwSection& rSect = *rFmts[ n ]->GetSection();
+ if( (!bChkReadOnly && !bChkHidden ) ||
+ (bChkReadOnly && rSect.IsProtectFlag() ) ||
+ (bChkHidden && rSect.IsHiddenFlag() ) )
+ break;
+ }
+ }
+ return n != nCnt;
+}
+
+sal_uInt16 SwEditShell::GetSectionFmtPos( const SwSectionFmt& rFmt ) const
+{
+ SwSectionFmt* pFmt = (SwSectionFmt*)&rFmt;
+ return GetDoc()->GetSections().GetPos( pFmt );
+}
+
+const SwSectionFmt& SwEditShell::GetSectionFmt( sal_uInt16 nFmt ) const
+{
+ return *GetDoc()->GetSections()[ nFmt ];
+}
+
+
+void SwEditShell::DelSectionFmt( sal_uInt16 nFmt )
+{
+ StartAllAction();
+ GetDoc()->DelSectionFmt( GetDoc()->GetSections()[ nFmt ] );
+ // rufe das AttrChangeNotify auf der UI-Seite.
+ CallChgLnk();
+ EndAllAction();
+}
+
+
+void SwEditShell::UpdateSection(sal_uInt16 const nSect,
+ SwSectionData & rNewData, SfxItemSet const*const pAttr)
+{
+ StartAllAction();
+ GetDoc()->UpdateSection( nSect, rNewData, pAttr );
+ // rufe das AttrChangeNotify auf der UI-Seite.
+ CallChgLnk();
+ EndAllAction();
+}
+
+String SwEditShell::GetUniqueSectionName( const String* pChkStr ) const
+{
+ return GetDoc()->GetUniqueSectionName( pChkStr );
+}
+
+void SwEditShell::SetSectionAttr( const SfxItemSet& rSet,
+ SwSectionFmt* pSectFmt )
+{
+ if( pSectFmt )
+ _SetSectionAttr( *pSectFmt, rSet );
+ else
+ {
+ // for all section in the selection
+
+ FOREACHPAM_START(this)
+
+ const SwPosition* pStt = PCURCRSR->Start(),
+ * pEnd = PCURCRSR->End();
+
+ const SwSectionNode* pSttSectNd = pStt->nNode.GetNode().FindSectionNode(),
+ * pEndSectNd = pEnd->nNode.GetNode().FindSectionNode();
+
+ if( pSttSectNd || pEndSectNd )
+ {
+ if( pSttSectNd )
+ _SetSectionAttr( *pSttSectNd->GetSection().GetFmt(),
+ rSet );
+ if( pEndSectNd && pSttSectNd != pEndSectNd )
+ _SetSectionAttr( *pEndSectNd->GetSection().GetFmt(),
+ 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( 0 != (pSttSectNd = aSIdx.GetNode().GetSectionNode())
+ || ( aSIdx.GetNode().IsEndNode() &&
+ 0 != ( pSttSectNd = aSIdx.GetNode().
+ StartOfSectionNode()->GetSectionNode())) )
+ _SetSectionAttr( *pSttSectNd->GetSection().GetFmt(),
+ rSet );
+ aSIdx++;
+ }
+ }
+ }
+
+ FOREACHPAM_END()
+ }
+}
+
+void SwEditShell::_SetSectionAttr( SwSectionFmt& rSectFmt,
+ const SfxItemSet& rSet )
+{
+ StartAllAction();
+ if(SFX_ITEM_SET == rSet.GetItemState(RES_CNTNT, sal_False))
+ {
+ SfxItemSet aSet(rSet);
+ aSet.ClearItem(RES_CNTNT);
+ GetDoc()->SetAttr( aSet, rSectFmt );
+ }
+ else
+ GetDoc()->SetAttr( rSet, rSectFmt );
+
+ // rufe das AttrChangeNotify auf der UI-Seite.
+ CallChgLnk();
+ EndAllAction();
+}
+
+// search inside the cursor selection for full selected sections.
+// if any part of section in the selection return 0.
+// if more than one in the selection return the count
+sal_uInt16 SwEditShell::GetFullSelectedSectionCount() const
+{
+ sal_uInt16 nRet = 0;
+ FOREACHPAM_START(this)
+
+ const SwPosition* pStt = PCURCRSR->Start(),
+ * pEnd = PCURCRSR->End();
+ const SwCntntNode* pCNd;
+ // check the selection, if Start at Node begin and End at Node end
+ if( pStt->nContent.GetIndex() ||
+ ( 0 == ( pCNd = pEnd->nNode.GetNode().GetCntntNode() )) ||
+ 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;
+
+ FOREACHPAM_END()
+ 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.
+ */
+const SwNode* lcl_SpecialInsertNode(const SwPosition* pCurrentPos)
+{
+ const SwNode* pReturn = NULL;
+
+ // the current position
+ // const SwPosition* pCurrentPos = GetCrsr()->GetPoint();
+ DBG_ASSERT( pCurrentPos != NULL, "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 = NULL;
+ {
+ const SwNode* pTableNode = rCurrentNode.FindTableNode();
+ const SwNode* pSectionNode = rCurrentNode.FindSectionNode();
+
+ // find the table/section which is close
+ if( pTableNode == NULL )
+ pInnermostNode = pSectionNode;
+ else if ( pSectionNode == NULL )
+ 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 != NULL) && !pInnermostNode->IsProtect() )
+ {
+ DBG_ASSERT( pInnermostNode->IsTableNode() ||
+ pInnermostNode->IsSectionNode(), "wrong node found" );
+ DBG_ASSERT( ( 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.IsCntntNode() &&
+ (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.IsCntntNode() &&
+ ( pCurrentPos->nContent.GetIndex() ==
+ rCurrentNode.GetCntntNode()->Len() ) )
+ aEnd++;
+ while( (aEnd != pInnermostNode->EndOfSectionNode()->GetIndex()) &&
+ aEnd.GetNode().IsEndNode() )
+ aEnd++;
+ bool bEnd = ( aEnd == pInnermostNode->EndOfSectionNode()->GetIndex() );
+
+ // evalutate result: if both start + end, end is preferred
+ if( bEnd )
+ pReturn = pInnermostNode->EndOfSectionNode();
+ else if ( bStart )
+ pReturn = pInnermostNode;
+ // else pReturn = NULL;
+ }
+ // else: pReturn = NULL
+
+
+ DBG_ASSERT( ( pReturn == NULL ) || 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 NULL != lcl_SpecialInsertNode( GetCrsr()->GetPoint() );
+}
+
+
+/** check whether a node cen be special-inserted (alt-Enter), and do so. Return
+ whether insertion was possible.
+ */
+bool SwEditShell::DoSpecialInsert()
+{
+ bool bRet = false;
+
+ // get current node
+ SwPosition* pCursorPos = GetCrsr()->GetPoint();
+ const SwNode* pInsertNode = lcl_SpecialInsertNode( pCursorPos );
+ if( pInsertNode != NULL )
+ {
+ 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
+ bRet = GetDoc()->AppendTxtNode( aInsertPos );
+ *pCursorPos = aInsertPos;
+
+ // call AttrChangeNotify for the UI
+ CallChgLnk();
+
+ EndAllAction();
+ }
+
+ return bRet;
+}
+