nss: upgrade to release 3.73
[LibreOffice.git] / sw / source / core / edit / edsect.cxx
blob662293a8d5c8601118fc49656ea90c911fc8efc5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <editsh.hxx>
21 #include <doc.hxx>
22 #include <IDocumentUndoRedo.hxx>
23 #include <IDocumentContentOperations.hxx>
24 #include <pam.hxx>
25 #include <docary.hxx>
26 #include <swundo.hxx>
27 #include <section.hxx>
28 #include <sectfrm.hxx>
29 #include <cntfrm.hxx>
30 #include <tabfrm.hxx>
31 #include <rootfrm.hxx>
33 SwSection const*
34 SwEditShell::InsertSection(
35 SwSectionData & rNewData, SfxItemSet const*const pAttr)
37 const SwSection* pRet = nullptr;
38 if( !IsTableMode() )
40 StartAllAction();
41 GetDoc()->GetIDocumentUndoRedo().StartUndo( SwUndoId::INSSECTION, nullptr );
43 for(const SwPaM& rPaM : GetCursor()->GetRingContainer())
45 SwSection const*const pNew =
46 GetDoc()->InsertSwSection( rPaM, rNewData, nullptr, pAttr );
47 if( !pRet )
48 pRet = pNew;
51 GetDoc()->GetIDocumentUndoRedo().EndUndo( SwUndoId::INSSECTION, nullptr );
52 EndAllAction();
54 return pRet;
57 bool SwEditShell::IsInsRegionAvailable() const
59 if( IsTableMode() )
60 return false;
61 SwPaM* pCursor = GetCursor();
62 if( pCursor->GetNext() != pCursor )
63 return false;
64 if( pCursor->HasMark() )
65 return 0 != SwDoc::IsInsRegionAvailable( *pCursor );
67 return true;
70 const SwSection* SwEditShell::GetCurrSection() const
72 if( IsTableMode() )
73 return nullptr;
75 return SwDoc::GetCurrSection( *GetCursor()->GetPoint() );
78 /** Deliver the responsible area of the columns.
80 * In footnotes it may not be the area within the footnote.
82 SwSection* SwEditShell::GetAnySection( bool bOutOfTab, const Point* pPt )
84 SwFrame *pFrame;
85 if ( pPt )
87 SwPosition aPos( *GetCursor()->GetPoint() );
88 Point aPt( *pPt );
89 GetLayout()->GetModelPositionForViewPoint( &aPos, aPt );
90 SwContentNode *pNd = aPos.nNode.GetNode().GetContentNode();
91 std::pair<Point, bool> const tmp(*pPt, true);
92 pFrame = pNd->getLayoutFrame(GetLayout(), nullptr, &tmp);
94 else
95 pFrame = GetCurrFrame( false );
97 if( bOutOfTab && pFrame )
98 pFrame = pFrame->FindTabFrame();
99 if( pFrame && pFrame->IsInSct() )
101 SwSectionFrame* pSect = pFrame->FindSctFrame();
102 OSL_ENSURE( pSect, "GetAnySection: Where's my Sect?" );
103 if( pSect->IsInFootnote() && pSect->GetUpper()->IsInSct() )
105 pSect = pSect->GetUpper()->FindSctFrame();
106 OSL_ENSURE( pSect, "GetAnySection: Where's my SectFrame?" );
108 return pSect->GetSection();
110 return nullptr;
113 size_t SwEditShell::GetSectionFormatCount() const
115 return GetDoc()->GetSections().size();
118 bool SwEditShell::IsAnySectionInDoc() const
120 const SwSectionFormats& rFormats = GetDoc()->GetSections();
122 for( const SwSectionFormat* pFormat : rFormats )
124 SectionType eTmpType;
125 if( pFormat->IsInNodesArr() &&
126 ( (eTmpType = pFormat->GetSection()->GetType()) != SectionType::ToxContent
127 && SectionType::ToxHeader != eTmpType ) )
129 return true;
132 return false;
135 size_t SwEditShell::GetSectionFormatPos( const SwSectionFormat& rFormat ) const
137 SwSectionFormat* pFormat = const_cast<SwSectionFormat*>(&rFormat);
138 return GetDoc()->GetSections().GetPos( pFormat );
141 const SwSectionFormat& SwEditShell::GetSectionFormat(size_t nFormat) const
143 return *GetDoc()->GetSections()[ nFormat ];
146 void SwEditShell::DelSectionFormat(size_t nFormat)
148 StartAllAction();
149 GetDoc()->DelSectionFormat( GetDoc()->GetSections()[ nFormat ] );
150 // Call the AttrChangeNotify on the UI page.
151 CallChgLnk();
152 EndAllAction();
155 void SwEditShell::UpdateSection(size_t const nSect,
156 SwSectionData & rNewData, SfxItemSet const*const pAttr)
158 StartAllAction();
159 GetDoc()->UpdateSection( nSect, rNewData, pAttr );
160 // Call the AttrChangeNotify on the UI page.
161 CallChgLnk();
162 EndAllAction();
165 OUString SwEditShell::GetUniqueSectionName( const OUString* pChkStr ) const
167 return GetDoc()->GetUniqueSectionName( pChkStr );
170 void SwEditShell::SetSectionAttr( const SfxItemSet& rSet,
171 SwSectionFormat* pSectFormat )
173 if( pSectFormat )
174 SetSectionAttr_( *pSectFormat, rSet );
175 else
177 // for all section in the selection
179 for(SwPaM& rPaM : GetCursor()->GetRingContainer())
181 const SwPosition* pStt = rPaM.Start(),
182 * pEnd = rPaM.End();
184 SwSectionNode* pSttSectNd = pStt->nNode.GetNode().FindSectionNode(),
185 * pEndSectNd = pEnd->nNode.GetNode().FindSectionNode();
187 if( pSttSectNd || pEndSectNd )
189 if( pSttSectNd )
190 SetSectionAttr_( *pSttSectNd->GetSection().GetFormat(),
191 rSet );
192 if( pEndSectNd && pSttSectNd != pEndSectNd )
193 SetSectionAttr_( *pEndSectNd->GetSection().GetFormat(),
194 rSet );
196 if( pSttSectNd && pEndSectNd )
198 SwNodeIndex aSIdx( pStt->nNode );
199 SwNodeIndex aEIdx( pEnd->nNode );
200 if( pSttSectNd->EndOfSectionIndex() <
201 pEndSectNd->GetIndex() )
203 aSIdx = pSttSectNd->EndOfSectionIndex() + 1;
204 aEIdx = *pEndSectNd;
207 while( aSIdx < aEIdx )
209 if( nullptr != (pSttSectNd = aSIdx.GetNode().GetSectionNode())
210 || ( aSIdx.GetNode().IsEndNode() &&
211 nullptr != ( pSttSectNd = aSIdx.GetNode().
212 StartOfSectionNode()->GetSectionNode())) )
213 SetSectionAttr_( *pSttSectNd->GetSection().GetFormat(),
214 rSet );
215 ++aSIdx;
224 void SwEditShell::SetSectionAttr_( SwSectionFormat& rSectFormat,
225 const SfxItemSet& rSet )
227 StartAllAction();
228 if(SfxItemState::SET == rSet.GetItemState(RES_CNTNT, false))
230 SfxItemSet aSet(rSet);
231 aSet.ClearItem(RES_CNTNT);
232 GetDoc()->SetAttr( aSet, rSectFormat );
234 else
235 GetDoc()->SetAttr( rSet, rSectFormat );
237 // Call the AttrChangeNotify on the UI page.
238 CallChgLnk();
239 EndAllAction();
242 /** Search inside the cursor selection for full selected sections.
244 * @return If any part of section in the selection return 0, if more than one return the count.
246 sal_uInt16 SwEditShell::GetFullSelectedSectionCount() const
248 sal_uInt16 nRet = 0;
249 for(SwPaM& rPaM : GetCursor()->GetRingContainer())
252 const SwPosition* pStt = rPaM.Start(),
253 * pEnd = rPaM.End();
254 const SwContentNode* pCNd;
255 // check the selection, if Start at Node begin and End at Node end
256 if( pStt->nContent.GetIndex() ||
257 ( nullptr == ( pCNd = pEnd->nNode.GetNode().GetContentNode() )) ||
258 pCNd->Len() != pEnd->nContent.GetIndex() )
260 nRet = 0;
261 break;
264 // !!!
265 // what about table at start or end ?
266 // There is no selection possible!
267 // What about only a table inside the section ?
268 // There is only a table selection possible!
270 SwNodeIndex aSIdx( pStt->nNode, -1 ), aEIdx( pEnd->nNode, +1 );
271 if( !aSIdx.GetNode().IsSectionNode() ||
272 !aEIdx.GetNode().IsEndNode() ||
273 !aEIdx.GetNode().StartOfSectionNode()->IsSectionNode() )
275 nRet = 0;
276 break;
279 ++nRet;
280 if( &aSIdx.GetNode() != aEIdx.GetNode().StartOfSectionNode() )
281 ++nRet;
284 return nRet;
287 /** Find the suitable node for a special insert (alt-enter).
289 * This should enable inserting text before/after sections and tables.
291 * A node is found if:
292 * 1) the innermost table/section is not in a write-protected area
293 * 2) pCurrentPos is at or just before an end node
294 * (or at or just after a start node)
295 * 3) there are only start/end nodes between pCurrentPos and the innermost
296 * table/section
298 * If a suitable node is found, an SwNode* is returned; else it is NULL.
300 static const SwNode* lcl_SpecialInsertNode(const SwPosition* pCurrentPos)
302 const SwNode* pReturn = nullptr;
304 // the current position
305 OSL_ENSURE( pCurrentPos != nullptr, "Strange, we have no position!" );
306 const SwNode& rCurrentNode = pCurrentPos->nNode.GetNode();
308 // find innermost section or table. At the end of this scope,
309 // pInnermostNode contains the section/table before/after which we should
310 // insert our empty paragraph, or it will be NULL if none is found.
311 const SwNode* pInnermostNode = nullptr;
313 const SwNode* pTableNode = rCurrentNode.FindTableNode();
314 const SwNode* pSectionNode = rCurrentNode.FindSectionNode();
316 // find the table/section which is close
317 if( pTableNode == nullptr )
318 pInnermostNode = pSectionNode;
319 else if ( pSectionNode == nullptr )
320 pInnermostNode = pTableNode;
321 else
323 // compare and choose the larger one
324 pInnermostNode =
325 ( pSectionNode->GetIndex() > pTableNode->GetIndex() )
326 ? pSectionNode : pTableNode;
330 // The previous version had a check to skip empty read-only sections. Those
331 // shouldn't occur, so we only need to check whether our pInnermostNode is
332 // inside a protected area.
334 // Now, pInnermostNode is NULL or the innermost section or table node.
335 if( (pInnermostNode != nullptr) && !pInnermostNode->IsProtect() )
337 OSL_ENSURE( pInnermostNode->IsTableNode() ||
338 pInnermostNode->IsSectionNode(), "wrong node found" );
339 OSL_ENSURE( ( pInnermostNode->GetIndex() <= rCurrentNode.GetIndex() )&&
340 ( pInnermostNode->EndOfSectionNode()->GetIndex() >=
341 rCurrentNode.GetIndex() ), "wrong node found" );
343 // we now need to find the possible start/end positions
345 // we found a start if
346 // - we're at or just before a start node
347 // - there are only start nodes between the current and pInnermostNode
348 SwNodeIndex aBegin( pCurrentPos->nNode );
349 if( rCurrentNode.IsContentNode() &&
350 (pCurrentPos->nContent.GetIndex() == 0))
351 --aBegin;
352 while( (aBegin != pInnermostNode->GetIndex()) &&
353 aBegin.GetNode().IsStartNode() )
354 --aBegin;
355 bool bStart = ( aBegin == pInnermostNode->GetIndex() );
357 // we found an end if
358 // - we're at or just before an end node
359 // - there are only end nodes between the current node and
360 // pInnermostNode's end node
361 SwNodeIndex aEnd( pCurrentPos->nNode );
362 if( rCurrentNode.IsContentNode() &&
363 ( pCurrentPos->nContent.GetIndex() ==
364 rCurrentNode.GetContentNode()->Len() ) )
365 ++aEnd;
366 while( (aEnd != pInnermostNode->EndOfSectionNode()->GetIndex()) &&
367 aEnd.GetNode().IsEndNode() )
368 ++aEnd;
369 bool bEnd = ( aEnd == pInnermostNode->EndOfSectionNode()->GetIndex() );
371 // evaluate result: if both start + end, end is preferred
372 if( bEnd )
373 pReturn = pInnermostNode->EndOfSectionNode();
374 else if ( bStart )
375 pReturn = pInnermostNode;
378 OSL_ENSURE( ( pReturn == nullptr ) || pReturn->IsStartNode() ||
379 pReturn->IsEndNode(),
380 "SpecialInsertNode failed" );
381 return pReturn;
384 /** a node can be special-inserted (alt-Enter) whenever lcl_SpecialInsertNode
385 finds a suitable position
387 bool SwEditShell::CanSpecialInsert() const
389 return nullptr != lcl_SpecialInsertNode( GetCursor()->GetPoint() );
392 /** check whether a node can be special-inserted (alt-Enter), and do so. Return
393 whether insertion was possible.
395 void SwEditShell::DoSpecialInsert()
397 // get current node
398 SwPosition* pCursorPos = GetCursor()->GetPoint();
399 const SwNode* pInsertNode = lcl_SpecialInsertNode( pCursorPos );
400 if( pInsertNode == nullptr )
401 return;
403 StartAllAction();
405 // adjust insert position to insert before start nodes and after end
406 // nodes
407 SwNodeIndex aInsertIndex( *pInsertNode,
408 pInsertNode->IsStartNode() ? -1 : 0 );
409 SwPosition aInsertPos( aInsertIndex );
411 // insert a new text node, and set the cursor
412 GetDoc()->getIDocumentContentOperations().AppendTextNode( aInsertPos );
413 *pCursorPos = aInsertPos;
415 // call AttrChangeNotify for the UI
416 CallChgLnk();
418 EndAllAction();
421 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */