Line data Source code
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>
23 : #include <IDocumentContentOperations.hxx>
24 : #include <pam.hxx>
25 : #include <docary.hxx>
26 : #include <swundo.hxx>
27 : #include <section.hxx>
28 : #include <edimp.hxx>
29 : #include <sectfrm.hxx>
30 : #include <cntfrm.hxx>
31 : #include <tabfrm.hxx>
32 : #include <rootfrm.hxx>
33 :
34 : SwSection const*
35 1 : SwEditShell::InsertSection(
36 : SwSectionData & rNewData, SfxItemSet const*const pAttr)
37 : {
38 1 : const SwSection* pRet = 0;
39 1 : if( !IsTableMode() )
40 : {
41 1 : StartAllAction();
42 1 : GetDoc()->GetIDocumentUndoRedo().StartUndo( UNDO_INSSECTION, NULL );
43 :
44 2 : for(SwPaM& rPaM : GetCrsr()->GetRingContainer())
45 : {
46 : SwSection const*const pNew =
47 1 : GetDoc()->InsertSwSection( rPaM, rNewData, 0, pAttr );
48 1 : if( !pRet )
49 1 : pRet = pNew;
50 : }
51 :
52 1 : GetDoc()->GetIDocumentUndoRedo().EndUndo( UNDO_INSSECTION, NULL );
53 1 : EndAllAction();
54 : }
55 1 : return pRet;
56 : }
57 :
58 0 : bool SwEditShell::IsInsRegionAvailable() const
59 : {
60 0 : if( IsTableMode() )
61 0 : return false;
62 0 : SwPaM* pCrsr = GetCrsr();
63 0 : if( pCrsr->GetNext() != pCrsr )
64 0 : return false;
65 0 : if( pCrsr->HasMark() )
66 0 : return 0 != SwDoc::IsInsRegionAvailable( *pCrsr );
67 :
68 0 : return true;
69 : }
70 :
71 5560 : const SwSection* SwEditShell::GetCurrSection() const
72 : {
73 5560 : if( IsTableMode() )
74 2 : return 0;
75 :
76 5558 : return SwDoc::GetCurrSection( *GetCrsr()->GetPoint() );
77 : }
78 :
79 : /** Deliver the responsible area of the columns.
80 : *
81 : * In footnotes it may not be the area within the footnote.
82 : */
83 0 : SwSection* SwEditShell::GetAnySection( bool bOutOfTab, const Point* pPt )
84 : {
85 : SwFrm *pFrm;
86 0 : if ( pPt )
87 : {
88 0 : SwPosition aPos( *GetCrsr()->GetPoint() );
89 0 : Point aPt( *pPt );
90 0 : GetLayout()->GetCrsrOfst( &aPos, aPt );
91 0 : SwContentNode *pNd = aPos.nNode.GetNode().GetContentNode();
92 0 : pFrm = pNd->getLayoutFrm( GetLayout(), pPt );
93 : }
94 : else
95 0 : pFrm = GetCurrFrm( false );
96 :
97 0 : if( bOutOfTab && pFrm )
98 0 : pFrm = pFrm->FindTabFrm();
99 0 : if( pFrm && pFrm->IsInSct() )
100 : {
101 0 : SwSectionFrm* pSect = pFrm->FindSctFrm();
102 : OSL_ENSURE( pSect, "GetAnySection: Where's my Sect?" );
103 0 : if( pSect->IsInFootnote() && pSect->GetUpper()->IsInSct() )
104 : {
105 0 : pSect = pSect->GetUpper()->FindSctFrm();
106 : OSL_ENSURE( pSect, "GetAnySection: Where's my SectFrm?" );
107 : }
108 0 : return pSect->GetSection();
109 : }
110 0 : return NULL;
111 : }
112 :
113 40 : size_t SwEditShell::GetSectionFormatCount() const
114 : {
115 40 : return GetDoc()->GetSections().size();
116 : }
117 :
118 1 : bool SwEditShell::IsAnySectionInDoc( bool bChkReadOnly, bool bChkHidden, bool bChkTOX ) const
119 : {
120 1 : const SwSectionFormats& rFormats = GetDoc()->GetSections();
121 :
122 1 : for( const SwSectionFormat* pFormat : rFormats )
123 : {
124 : SectionType eTmpType;
125 0 : if( pFormat->IsInNodesArr() &&
126 0 : (bChkTOX ||
127 0 : ( (eTmpType = pFormat->GetSection()->GetType()) != TOX_CONTENT_SECTION
128 0 : && TOX_HEADER_SECTION != eTmpType ) ) )
129 : {
130 0 : const SwSection& rSect = *pFormat->GetSection();
131 0 : if( (!bChkReadOnly && !bChkHidden ) ||
132 0 : (bChkReadOnly && rSect.IsProtectFlag() ) ||
133 0 : (bChkHidden && rSect.IsHiddenFlag() ) )
134 0 : return true;
135 : }
136 : }
137 1 : return false;
138 : }
139 :
140 0 : size_t SwEditShell::GetSectionFormatPos( const SwSectionFormat& rFormat ) const
141 : {
142 0 : SwSectionFormat* pFormat = const_cast<SwSectionFormat*>(&rFormat);
143 0 : return GetDoc()->GetSections().GetPos( pFormat );
144 : }
145 :
146 0 : const SwSectionFormat& SwEditShell::GetSectionFormat(size_t nFormat) const
147 : {
148 0 : return *GetDoc()->GetSections()[ nFormat ];
149 : }
150 :
151 0 : void SwEditShell::DelSectionFormat(size_t nFormat)
152 : {
153 0 : StartAllAction();
154 0 : GetDoc()->DelSectionFormat( GetDoc()->GetSections()[ nFormat ] );
155 : // Call the AttrChangeNotify on the UI page.
156 0 : CallChgLnk();
157 0 : EndAllAction();
158 0 : }
159 :
160 0 : void SwEditShell::UpdateSection(size_t const nSect,
161 : SwSectionData & rNewData, SfxItemSet const*const pAttr)
162 : {
163 0 : StartAllAction();
164 0 : GetDoc()->UpdateSection( nSect, rNewData, pAttr );
165 : // Call the AttrChangeNotify on the UI page.
166 0 : CallChgLnk();
167 0 : EndAllAction();
168 0 : }
169 :
170 1 : OUString SwEditShell::GetUniqueSectionName( const OUString* pChkStr ) const
171 : {
172 1 : return GetDoc()->GetUniqueSectionName( pChkStr );
173 : }
174 :
175 0 : void SwEditShell::SetSectionAttr( const SfxItemSet& rSet,
176 : SwSectionFormat* pSectFormat )
177 : {
178 0 : if( pSectFormat )
179 0 : _SetSectionAttr( *pSectFormat, rSet );
180 : else
181 : {
182 : // for all section in the selection
183 :
184 0 : for(SwPaM& rPaM : GetCrsr()->GetRingContainer())
185 : {
186 0 : const SwPosition* pStt = rPaM.Start(),
187 0 : * pEnd = rPaM.End();
188 :
189 0 : SwSectionNode* pSttSectNd = pStt->nNode.GetNode().FindSectionNode(),
190 0 : * pEndSectNd = pEnd->nNode.GetNode().FindSectionNode();
191 :
192 0 : if( pSttSectNd || pEndSectNd )
193 : {
194 0 : if( pSttSectNd )
195 0 : _SetSectionAttr( *pSttSectNd->GetSection().GetFormat(),
196 0 : rSet );
197 0 : if( pEndSectNd && pSttSectNd != pEndSectNd )
198 0 : _SetSectionAttr( *pEndSectNd->GetSection().GetFormat(),
199 0 : rSet );
200 :
201 0 : if( pSttSectNd && pEndSectNd )
202 : {
203 0 : SwNodeIndex aSIdx( pStt->nNode );
204 0 : SwNodeIndex aEIdx( pEnd->nNode );
205 0 : if( pSttSectNd->EndOfSectionIndex() <
206 0 : pEndSectNd->GetIndex() )
207 : {
208 0 : aSIdx = pSttSectNd->EndOfSectionIndex() + 1;
209 0 : aEIdx = *pEndSectNd;
210 : }
211 :
212 0 : while( aSIdx < aEIdx )
213 : {
214 0 : if( 0 != (pSttSectNd = aSIdx.GetNode().GetSectionNode())
215 0 : || ( aSIdx.GetNode().IsEndNode() &&
216 0 : 0 != ( pSttSectNd = aSIdx.GetNode().
217 0 : StartOfSectionNode()->GetSectionNode())) )
218 0 : _SetSectionAttr( *pSttSectNd->GetSection().GetFormat(),
219 0 : rSet );
220 0 : ++aSIdx;
221 0 : }
222 : }
223 : }
224 :
225 : }
226 : }
227 0 : }
228 :
229 0 : void SwEditShell::_SetSectionAttr( SwSectionFormat& rSectFormat,
230 : const SfxItemSet& rSet )
231 : {
232 0 : StartAllAction();
233 0 : if(SfxItemState::SET == rSet.GetItemState(RES_CNTNT, false))
234 : {
235 0 : SfxItemSet aSet(rSet);
236 0 : aSet.ClearItem(RES_CNTNT);
237 0 : GetDoc()->SetAttr( aSet, rSectFormat );
238 : }
239 : else
240 0 : GetDoc()->SetAttr( rSet, rSectFormat );
241 :
242 : // Call the AttrChangeNotify on the UI page.
243 0 : CallChgLnk();
244 0 : EndAllAction();
245 0 : }
246 :
247 : /** Search inside the cursor selection for full selected sections.
248 : *
249 : * @return If any part of section in the selection return 0, if more than one return the count.
250 : */
251 0 : sal_uInt16 SwEditShell::GetFullSelectedSectionCount() const
252 : {
253 0 : sal_uInt16 nRet = 0;
254 0 : for(SwPaM& rPaM : GetCrsr()->GetRingContainer())
255 : {
256 :
257 0 : const SwPosition* pStt = rPaM.Start(),
258 0 : * pEnd = rPaM.End();
259 : const SwContentNode* pCNd;
260 : // check the selection, if Start at Node begin and End at Node end
261 0 : if( pStt->nContent.GetIndex() ||
262 0 : ( 0 == ( pCNd = pEnd->nNode.GetNode().GetContentNode() )) ||
263 0 : pCNd->Len() != pEnd->nContent.GetIndex() )
264 : {
265 0 : nRet = 0;
266 0 : break;
267 : }
268 :
269 : // !!!
270 : // what about table at start or end ?
271 : // There is no selection possible!
272 : // What about only a table inside the section ?
273 : // There is only a table selection possible!
274 :
275 0 : SwNodeIndex aSIdx( pStt->nNode, -1 ), aEIdx( pEnd->nNode, +1 );
276 0 : if( !aSIdx.GetNode().IsSectionNode() ||
277 0 : !aEIdx.GetNode().IsEndNode() ||
278 0 : !aEIdx.GetNode().StartOfSectionNode()->IsSectionNode() )
279 : {
280 0 : nRet = 0;
281 0 : break;
282 : }
283 :
284 0 : ++nRet;
285 0 : if( &aSIdx.GetNode() != aEIdx.GetNode().StartOfSectionNode() )
286 0 : ++nRet;
287 :
288 0 : }
289 0 : return nRet;
290 : }
291 :
292 : /** Find the suitable node for a special insert (alt-enter).
293 : *
294 : * This should enable inserting text before/after sections and tables.
295 : *
296 : * A node is found if:
297 : * 1) the innermost table/section is not in a write-protected area
298 : * 2) pCurrentPos is at or just before an end node
299 : * (or at or just after a start node)
300 : * 3) there are only start/end nodes between pCurrentPos and the innermost
301 : * table/section
302 : *
303 : * If a suitable node is found, an SwNode* is returned; else it is NULL.
304 : */
305 0 : static const SwNode* lcl_SpecialInsertNode(const SwPosition* pCurrentPos)
306 : {
307 0 : const SwNode* pReturn = NULL;
308 :
309 : // the current position
310 : OSL_ENSURE( pCurrentPos != NULL, "Strange, we have no position!" );
311 0 : const SwNode& rCurrentNode = pCurrentPos->nNode.GetNode();
312 :
313 : // find innermost section or table. At the end of this scope,
314 : // pInntermostNode contain the section/table before/after which we should
315 : // insert our empty paragraph, or it will be NULL if none is found.
316 0 : const SwNode* pInnermostNode = NULL;
317 : {
318 0 : const SwNode* pTableNode = rCurrentNode.FindTableNode();
319 0 : const SwNode* pSectionNode = rCurrentNode.FindSectionNode();
320 :
321 : // find the table/section which is close
322 0 : if( pTableNode == NULL )
323 0 : pInnermostNode = pSectionNode;
324 0 : else if ( pSectionNode == NULL )
325 0 : pInnermostNode = pTableNode;
326 : else
327 : {
328 : // compare and choose the larger one
329 : pInnermostNode =
330 0 : ( pSectionNode->GetIndex() > pTableNode->GetIndex() )
331 0 : ? pSectionNode : pTableNode;
332 : }
333 : }
334 :
335 : // The previous version had a check to skip empty read-only sections. Those
336 : // shouldn't occur, so we only need to check whether our pInnermostNode is
337 : // inside a protected area.
338 :
339 : // Now, pInnermostNode is NULL or the innermost section or table node.
340 0 : if( (pInnermostNode != NULL) && !pInnermostNode->IsProtect() )
341 : {
342 : OSL_ENSURE( pInnermostNode->IsTableNode() ||
343 : pInnermostNode->IsSectionNode(), "wrong node found" );
344 : OSL_ENSURE( ( pInnermostNode->GetIndex() <= rCurrentNode.GetIndex() )&&
345 : ( pInnermostNode->EndOfSectionNode()->GetIndex() >=
346 : rCurrentNode.GetIndex() ), "wrong node found" );
347 :
348 : // we now need to find the possible start/end positions
349 :
350 : // we found a start if
351 : // - we're at or just before a start node
352 : // - there are only start nodes between the current and pInnermostNode
353 0 : SwNodeIndex aBegin( pCurrentPos->nNode );
354 0 : if( rCurrentNode.IsContentNode() &&
355 0 : (pCurrentPos->nContent.GetIndex() == 0))
356 0 : --aBegin;
357 0 : while( (aBegin != pInnermostNode->GetIndex()) &&
358 0 : aBegin.GetNode().IsStartNode() )
359 0 : --aBegin;
360 0 : bool bStart = ( aBegin == pInnermostNode->GetIndex() );
361 :
362 : // we found an end if
363 : // - we're at or just before an end node
364 : // - there are only end nodes between the current node and
365 : // pInnermostNode's end node
366 0 : SwNodeIndex aEnd( pCurrentPos->nNode );
367 0 : if( rCurrentNode.IsContentNode() &&
368 0 : ( pCurrentPos->nContent.GetIndex() ==
369 0 : rCurrentNode.GetContentNode()->Len() ) )
370 0 : ++aEnd;
371 0 : while( (aEnd != pInnermostNode->EndOfSectionNode()->GetIndex()) &&
372 0 : aEnd.GetNode().IsEndNode() )
373 0 : ++aEnd;
374 0 : bool bEnd = ( aEnd == pInnermostNode->EndOfSectionNode()->GetIndex() );
375 :
376 : // evalutate result: if both start + end, end is preferred
377 0 : if( bEnd )
378 0 : pReturn = pInnermostNode->EndOfSectionNode();
379 0 : else if ( bStart )
380 0 : pReturn = pInnermostNode;
381 : }
382 :
383 : OSL_ENSURE( ( pReturn == NULL ) || pReturn->IsStartNode() ||
384 : pReturn->IsEndNode(),
385 : "SpecialInsertNode failed" );
386 0 : return pReturn;
387 : }
388 :
389 : /** a node can be special-inserted (alt-Enter) whenever lcl_SpecialInsertNode
390 : finds a suitable position
391 : */
392 0 : bool SwEditShell::CanSpecialInsert() const
393 : {
394 0 : return NULL != lcl_SpecialInsertNode( GetCrsr()->GetPoint() );
395 : }
396 :
397 : /** check whether a node can be special-inserted (alt-Enter), and do so. Return
398 : whether insertion was possible.
399 : */
400 0 : bool SwEditShell::DoSpecialInsert()
401 : {
402 0 : bool bRet = false;
403 :
404 : // get current node
405 0 : SwPosition* pCursorPos = GetCrsr()->GetPoint();
406 0 : const SwNode* pInsertNode = lcl_SpecialInsertNode( pCursorPos );
407 0 : if( pInsertNode != NULL )
408 : {
409 0 : StartAllAction();
410 :
411 : // adjust insert position to insert before start nodes and after end
412 : // nodes
413 : SwNodeIndex aInsertIndex( *pInsertNode,
414 0 : pInsertNode->IsStartNode() ? -1 : 0 );
415 0 : SwPosition aInsertPos( aInsertIndex );
416 :
417 : // insert a new text node, and set the cursor
418 0 : bRet = GetDoc()->getIDocumentContentOperations().AppendTextNode( aInsertPos );
419 0 : *pCursorPos = aInsertPos;
420 :
421 : // call AttrChangeNotify for the UI
422 0 : CallChgLnk();
423 :
424 0 : EndAllAction();
425 : }
426 :
427 0 : return bRet;
428 177 : }
429 :
430 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|