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