LibreOffice Module sw (master) 1
edsect.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <editsh.hxx>
21#include <doc.hxx>
22#include <IDocumentUndoRedo.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>
32#include <osl/diagnose.h>
33
34SwSection const*
36 SwSectionData & rNewData, SfxItemSet const*const pAttr)
37{
38 const SwSection* pRet = nullptr;
39 if( !IsTableMode() )
40 {
42 GetDoc()->GetIDocumentUndoRedo().StartUndo( SwUndoId::INSSECTION, nullptr );
43
44 for(const SwPaM& rPaM : GetCursor()->GetRingContainer())
45 {
46 SwSection const*const pNew =
47 GetDoc()->InsertSwSection( rPaM, rNewData, nullptr, pAttr );
48 if( !pRet )
49 pRet = pNew;
50 }
51
52 GetDoc()->GetIDocumentUndoRedo().EndUndo( SwUndoId::INSSECTION, nullptr );
54 }
55 return pRet;
56}
57
59{
60 if( IsTableMode() )
61 return false;
62 SwPaM* pCursor = GetCursor();
63 if( pCursor->GetNext() != pCursor )
64 return false;
65 if( pCursor->HasMark() )
66 return 0 != SwDoc::IsInsRegionAvailable( *pCursor );
67
68 return true;
69}
70
72{
73 if( IsTableMode() )
74 return nullptr;
75
76 return SwDoc::GetCurrSection( *GetCursor()->GetPoint() );
77}
78
83SwSection* SwEditShell::GetAnySection( bool bOutOfTab, const Point* pPt )
84{
85 SwFrame *pFrame;
86 if ( pPt )
87 {
88 SwPosition aPos( *GetCursor()->GetPoint() );
89 Point aPt( *pPt );
91 SwContentNode *pNd = aPos.GetNode().GetContentNode();
92 std::pair<Point, bool> const tmp(*pPt, true);
93 pFrame = pNd->getLayoutFrame(GetLayout(), nullptr, &tmp);
94 }
95 else
96 pFrame = GetCurrFrame( false );
97
98 if( bOutOfTab && pFrame )
99 pFrame = pFrame->FindTabFrame();
100 if( pFrame && pFrame->IsInSct() )
101 {
102 SwSectionFrame* pSect = pFrame->FindSctFrame();
103 OSL_ENSURE( pSect, "GetAnySection: Where's my Sect?" );
104 if( pSect->IsInFootnote() && pSect->GetUpper()->IsInSct() )
105 {
106 pSect = pSect->GetUpper()->FindSctFrame();
107 OSL_ENSURE( pSect, "GetAnySection: Where's my SectFrame?" );
108 }
109 return pSect->GetSection();
110 }
111 return nullptr;
112}
113
115{
116 return GetDoc()->GetSections().size();
117}
118
120{
121 const SwSectionFormats& rFormats = GetDoc()->GetSections();
122
123 for( const SwSectionFormat* pFormat : rFormats )
124 {
125 SectionType eTmpType;
126 if( pFormat->IsInNodesArr() &&
127 ( (eTmpType = pFormat->GetSection()->GetType()) != SectionType::ToxContent
128 && SectionType::ToxHeader != eTmpType ) )
129 {
130 return true;
131 }
132 }
133 return false;
134}
135
137{
138 SwSectionFormat* pFormat = const_cast<SwSectionFormat*>(&rFormat);
139 return GetDoc()->GetSections().GetPos( pFormat );
140}
141
143{
144 return *GetDoc()->GetSections()[ nFormat ];
145}
146
148{
150 GetDoc()->DelSectionFormat( GetDoc()->GetSections()[ nFormat ] );
151 // Call the AttrChangeNotify on the UI page.
152 CallChgLnk();
153 EndAllAction();
154}
155
156void SwEditShell::UpdateSection(size_t const nSect,
157 SwSectionData & rNewData, SfxItemSet const*const pAttr)
158{
160 GetDoc()->UpdateSection( nSect, rNewData, pAttr );
161 // Call the AttrChangeNotify on the UI page.
162 CallChgLnk();
163 EndAllAction();
164}
165
166OUString SwEditShell::GetUniqueSectionName( const OUString* pChkStr ) const
167{
168 return GetDoc()->GetUniqueSectionName( pChkStr );
169}
170
172 SwSectionFormat* pSectFormat )
173{
174 if( pSectFormat )
175 SetSectionAttr_( *pSectFormat, rSet );
176 else
177 {
178 // for all section in the selection
179
180 for(SwPaM& rPaM : GetCursor()->GetRingContainer())
181 {
182 auto [pStt, pEnd] = rPaM.StartEnd(); // SwPosition*
183
184 SwSectionNode* pSttSectNd = pStt->GetNode().FindSectionNode(),
185 * pEndSectNd = pEnd->GetNode().FindSectionNode();
186
187 if( pSttSectNd || pEndSectNd )
188 {
189 if( pSttSectNd )
190 SetSectionAttr_( *pSttSectNd->GetSection().GetFormat(),
191 rSet );
192 if( pEndSectNd && pSttSectNd != pEndSectNd )
193 SetSectionAttr_( *pEndSectNd->GetSection().GetFormat(),
194 rSet );
195
196 if( pSttSectNd && pEndSectNd )
197 {
198 SwNodeIndex aSIdx( pStt->GetNode() );
199 SwNodeIndex aEIdx( pEnd->GetNode() );
200 if( pSttSectNd->EndOfSectionIndex() <
201 pEndSectNd->GetIndex() )
202 {
203 aSIdx = pSttSectNd->EndOfSectionIndex() + 1;
204 aEIdx = *pEndSectNd;
205 }
206
207 while( aSIdx < aEIdx )
208 {
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;
216 }
217 }
218 }
219
220 }
221 }
222}
223
225 const SfxItemSet& rSet )
226{
228 if(SfxItemState::SET == rSet.GetItemState(RES_CNTNT, false))
229 {
230 SfxItemSet aSet(rSet);
231 aSet.ClearItem(RES_CNTNT);
232 GetDoc()->SetAttr( aSet, rSectFormat );
233 }
234 else
235 GetDoc()->SetAttr( rSet, rSectFormat );
236
237 // Call the AttrChangeNotify on the UI page.
238 CallChgLnk();
239 EndAllAction();
240}
241
247{
248 sal_uInt16 nRet = 0;
249 for(SwPaM& rPaM : GetCursor()->GetRingContainer())
250 {
251
252 auto [pStt, pEnd] = rPaM.StartEnd(); // SwPosition*
253 const SwContentNode* pCNd;
254 // check the selection, if Start at Node begin and End at Node end
255 if( pStt->GetContentIndex() ||
256 ( nullptr == ( pCNd = pEnd->GetNode().GetContentNode() )) ||
257 pCNd->Len() != pEnd->GetContentIndex() )
258 {
259 nRet = 0;
260 break;
261 }
262
263// !!!
264// what about table at start or end ?
265// There is no selection possible!
266// What about only a table inside the section ?
267// There is only a table selection possible!
268
269 SwNodeIndex aSIdx( pStt->GetNode(), -1 ), aEIdx( pEnd->GetNode(), +1 );
270 if( !aSIdx.GetNode().IsSectionNode() ||
271 !aEIdx.GetNode().IsEndNode() ||
273 {
274 nRet = 0;
275 break;
276 }
277
278 ++nRet;
279 if( &aSIdx.GetNode() != aEIdx.GetNode().StartOfSectionNode() )
280 ++nRet;
281
282 }
283 return nRet;
284}
285
299static const SwNode* lcl_SpecialInsertNode(const SwPosition* pCurrentPos)
300{
301 const SwNode* pReturn = nullptr;
302
303 // the current position
304 OSL_ENSURE( pCurrentPos != nullptr, "Strange, we have no position!" );
305 const SwNode& rCurrentNode = pCurrentPos->GetNode();
306
307 // find innermost section or table. At the end of this scope,
308 // pInnermostNode contains the section/table before/after which we should
309 // insert our empty paragraph, or it will be NULL if none is found.
310 const SwNode* pInnermostNode = nullptr;
311 {
312 const SwNode* pTableNode = rCurrentNode.FindTableNode();
313 const SwNode* pSectionNode = rCurrentNode.FindSectionNode();
314
315 // find the table/section which is close
316 if( pTableNode == nullptr )
317 pInnermostNode = pSectionNode;
318 else if ( pSectionNode == nullptr )
319 pInnermostNode = pTableNode;
320 else
321 {
322 // compare and choose the larger one
323 pInnermostNode =
324 ( pSectionNode->GetIndex() > pTableNode->GetIndex() )
325 ? pSectionNode : pTableNode;
326 }
327 }
328
329 // The previous version had a check to skip empty read-only sections. Those
330 // shouldn't occur, so we only need to check whether our pInnermostNode is
331 // inside a protected area.
332
333 // Now, pInnermostNode is NULL or the innermost section or table node.
334 if( (pInnermostNode != nullptr) && !pInnermostNode->IsProtect() )
335 {
336 OSL_ENSURE( pInnermostNode->IsTableNode() ||
337 pInnermostNode->IsSectionNode(), "wrong node found" );
338 OSL_ENSURE( ( pInnermostNode->GetIndex() <= rCurrentNode.GetIndex() )&&
339 ( pInnermostNode->EndOfSectionNode()->GetIndex() >=
340 rCurrentNode.GetIndex() ), "wrong node found" );
341
342 // we now need to find the possible start/end positions
343
344 // we found a start if
345 // - we're at or just before a start node
346 // - there are only start nodes between the current and pInnermostNode
347 SwNodeIndex aBegin( pCurrentPos->GetNode() );
348 if( rCurrentNode.IsContentNode() &&
349 (pCurrentPos->GetContentIndex() == 0))
350 --aBegin;
351 while( (aBegin != pInnermostNode->GetIndex()) &&
352 aBegin.GetNode().IsStartNode() )
353 --aBegin;
354 bool bStart = ( aBegin == pInnermostNode->GetIndex() );
355
356 // we found an end if
357 // - we're at or just before an end node
358 // - there are only end nodes between the current node and
359 // pInnermostNode's end node
360 SwNodeIndex aEnd( pCurrentPos->GetNode() );
361 if( rCurrentNode.IsContentNode() &&
362 ( pCurrentPos->GetContentIndex() ==
363 rCurrentNode.GetContentNode()->Len() ) )
364 ++aEnd;
365 while( (aEnd != pInnermostNode->EndOfSectionNode()->GetIndex()) &&
366 aEnd.GetNode().IsEndNode() )
367 ++aEnd;
368 bool bEnd = ( aEnd == pInnermostNode->EndOfSectionNode()->GetIndex() );
369
370 // evaluate result: if both start + end, end is preferred
371 if( bEnd )
372 pReturn = pInnermostNode->EndOfSectionNode();
373 else if ( bStart )
374 pReturn = pInnermostNode;
375 }
376
377 OSL_ENSURE( ( pReturn == nullptr ) || pReturn->IsStartNode() ||
378 pReturn->IsEndNode(),
379 "SpecialInsertNode failed" );
380 return pReturn;
381}
382
387{
388 return nullptr != lcl_SpecialInsertNode( GetCursor()->GetPoint() );
389}
390
395{
396 // get current node
397 SwPosition* pCursorPos = GetCursor()->GetPoint();
398 const SwNode* pInsertNode = lcl_SpecialInsertNode( pCursorPos );
399 if( pInsertNode == nullptr )
400 return;
401
403
404 // adjust insert position to insert before start nodes and after end
405 // nodes
406 SwNodeIndex aInsertIndex( *pInsertNode,
407 SwNodeOffset(pInsertNode->IsStartNode() ? -1 : 0) );
408 SwPosition aInsertPos( aInsertIndex );
409
410 // insert a new text node, and set the cursor
412 *pCursorPos = aInsertPos;
413
414 // call AttrChangeNotify for the UI
415 CallChgLnk();
416
417 EndAllAction();
418}
419
420/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual bool AppendTextNode(SwPosition &rPos)=0
sal_uInt16 ClearItem(sal_uInt16 nWhich=0)
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
SwContentFrame * getLayoutFrame(const SwRootFrame *, const SwPosition *pPos=nullptr, std::pair< Point, bool > const *pViewPosAndCalcFrame=nullptr) const
Definition: node.cxx:1223
virtual sal_Int32 Len() const
Definition: node.cxx:1256
SwCursor * GetCursor(bool bMakeTableCursor=true) const
Return pointer to the current shell cursor.
Definition: crsrsh.cxx:194
SwContentFrame * GetCurrFrame(const bool bCalcFrame=true) const
Get current frame in which the cursor is positioned.
Definition: crsrsh.cxx:2771
void CallChgLnk()
Definition: crsrsh.cxx:2847
bool IsTableMode() const
Definition: crsrsh.hxx:668
SwSectionFormats & GetSections()
Definition: doc.hxx:1356
static SwSection * GetCurrSection(const SwPosition &rPos)
Definition: ndsect.cxx:492
static sal_uInt16 IsInsRegionAvailable(const SwPaM &rRange, const SwNode **ppSttNd=nullptr)
Definition: ndsect.cxx:380
SwSection * InsertSwSection(SwPaM const &rRange, SwSectionData &, std::tuple< SwTOXBase const *, sw::RedlineMode, sw::FieldmarkMode, sw::ParagraphBreakMode > const *pTOXBase, SfxItemSet const *const pAttr, bool const bUpdate=true)
Definition: ndsect.cxx:148
void SetAttr(const SfxPoolItem &, SwFormat &)
Set attribute in given format.1y If Undo is enabled, the old values is added to the Undo history.
Definition: docfmt.cxx:458
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:329
IDocumentUndoRedo & GetIDocumentUndoRedo()
Definition: doc.cxx:158
void DelSectionFormat(SwSectionFormat *pFormat, bool bDelNodes=false)
Definition: ndsect.cxx:507
OUString GetUniqueSectionName(const OUString *pChkStr=nullptr) const
Definition: ndsect.cxx:1393
void UpdateSection(size_t const nSect, SwSectionData &, SfxItemSet const *const =nullptr, bool const bPreventLinkUpdate=false)
Definition: ndsect.cxx:594
void StartAllAction()
For all views of this document.
Definition: edws.cxx:86
size_t GetSectionFormatCount() const
Definition: edsect.cxx:114
void DoSpecialInsert()
Special insert: Insert a new text node just before or after a section or table, if the cursor is posi...
Definition: edsect.cxx:394
SwSection const * InsertSection(SwSectionData &rNewData, SfxItemSet const *const =nullptr)
Definition: edsect.cxx:35
sal_uInt16 GetFullSelectedSectionCount() const
Search inside the cursor selection for full selected sections.
Definition: edsect.cxx:246
const SwSection * GetCurrSection() const
Definition: edsect.cxx:71
void UpdateSection(size_t const nSect, SwSectionData &, SfxItemSet const *const =nullptr)
Definition: edsect.cxx:156
void SetSectionAttr(const SfxItemSet &rSet, SwSectionFormat *pSectFormat=nullptr)
Set attributes.
Definition: edsect.cxx:171
bool CanSpecialInsert() const
a node can be special-inserted (alt-Enter) whenever lcl_SpecialInsertNode finds a suitable position
Definition: edsect.cxx:386
OUString GetUniqueSectionName(const OUString *pChkStr=nullptr) const
Definition: edsect.cxx:166
bool IsAnySectionInDoc() const
Definition: edsect.cxx:119
bool IsInsRegionAvailable() const
Definition: edsect.cxx:58
SwSection * GetAnySection(bool bOutOfTab=false, const Point *pPt=nullptr)
Deliver the responsible area of the columns.
Definition: edsect.cxx:83
const SwSectionFormat & GetSectionFormat(size_t nFormat) const
Definition: edsect.cxx:142
size_t GetSectionFormatPos(const SwSectionFormat &) const
Definition: edsect.cxx:136
void DelSectionFormat(size_t nFormat)
Definition: edsect.cxx:147
void EndAllAction()
Definition: edws.cxx:97
SAL_DLLPRIVATE void SetSectionAttr_(SwSectionFormat &rSectFormat, const SfxItemSet &rSet)
Definition: edsect.cxx:224
size_t GetPos(const SwFormat *p) const
Definition: docary.hxx:162
Base class of the Writer layout elements.
Definition: frame.hxx:315
SwSectionFrame * FindSctFrame()
Definition: frame.hxx:1121
SwTabFrame * FindTabFrame()
Definition: frame.hxx:1105
bool IsInFootnote() const
Definition: frame.hxx:955
SwLayoutFrame * GetUpper()
Definition: frame.hxx:684
bool IsInSct() const
Definition: frame.hxx:973
Marks a node in the document model.
Definition: ndindex.hxx:31
SwNode & GetNode() const
Definition: ndindex.hxx:123
Base class of the Writer document model elements.
Definition: node.hxx:98
SwSectionNode * GetSectionNode()
Definition: node.hxx:658
SwNodeOffset GetIndex() const
Definition: node.hxx:312
bool IsProtect() const
Is node in something that is protected (range, frame, table cells ... including anchor in case of fra...
Definition: node.cxx:449
bool IsContentNode() const
Definition: node.hxx:188
bool IsEndNode() const
Definition: node.hxx:189
bool IsStartNode() const
Definition: node.hxx:187
bool IsSectionNode() const
Definition: node.hxx:192
bool IsTableNode() const
Definition: node.hxx:191
SwTableNode * FindTableNode()
Search table node, in which it is.
Definition: node.cxx:380
SwSectionNode * FindSectionNode()
Search section node, in which it is.
Definition: ndsect.cxx:968
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:153
SwNodeOffset EndOfSectionIndex() const
Definition: node.hxx:691
SwContentNode * GetContentNode()
Definition: node.hxx:666
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:695
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:188
SwPaM * GetNext()
Definition: pam.hxx:314
const SwPosition * GetPoint() const
Definition: pam.hxx:253
bool HasMark() const
A PaM marks a selection if Point and Mark are distinct positions.
Definition: pam.hxx:251
virtual bool GetModelPositionForViewPoint(SwPosition *, Point &, SwCursorMoveState *=nullptr, bool bTestBackground=false) const override
Primary passes the call to the first page.
Definition: trvlfrm.cxx:425
Array of Undo-history.
Definition: docary.hxx:193
SwSection * GetSection()
Definition: sectfrm.hxx:97
A section node represents the start of a section on the UI, i.e.
Definition: node.hxx:575
const SwSection & GetSection() const
Definition: node.hxx:590
SwSectionFormat * GetFormat()
Definition: section.hxx:341
size_t size() const
Definition: docary.hxx:88
SwRootFrame * GetLayout() const
Definition: viewsh.cxx:2163
SwDoc * GetDoc() const
Definition: viewsh.hxx:308
ring_container GetRingContainer()
Definition: ring.hxx:240
static const SwNode * lcl_SpecialInsertNode(const SwPosition *pCurrentPos)
Find the suitable node for a special insert (alt-enter).
Definition: edsect.cxx:299
constexpr TypedWhichId< SwFormatContent > RES_CNTNT(101)
o3tl::strong_int< sal_Int32, struct Tag_SwNodeOffset > SwNodeOffset
Definition: nodeoffset.hxx:16
SectionType
Definition: section.hxx:46
static SfxItemSet & rSet
Marks a position in the document model.
Definition: pam.hxx:38
SwNode & GetNode() const
Definition: pam.hxx:81
sal_Int32 GetContentIndex() const
Definition: pam.hxx:85