update dev300-m58
[ooovba.git] / sw / source / core / edit / edsect.cxx
blobfbf0d38ff5ea49461db2147259cd4446509d1f2a
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: edsect.cxx,v $
10 * $Revision: 1.12 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <doc.hxx>
36 #include <editsh.hxx>
37 #include <pam.hxx>
38 #include <docary.hxx>
39 #include <swundo.hxx> // fuer die UndoIds
40 #include <section.hxx>
41 #include <edimp.hxx>
42 #include <sectfrm.hxx> // SwSectionFrm
43 #include <cntfrm.hxx> // SwCntntFrm
44 #include <tabfrm.hxx> // SwTabFrm
45 #include <rootfrm.hxx> // SwRootFrm
48 // SS fuer Bereiche
49 const SwSection* SwEditShell::InsertSection( const SwSection& rNew,
50 const SfxItemSet* pAttr )
52 const SwSection* pRet = 0;
53 if( !IsTableMode() )
55 StartAllAction();
56 GetDoc()->StartUndo( UNDO_INSSECTION, NULL );
58 FOREACHPAM_START(this)
59 const SwSection* pNew = GetDoc()->Insert( *PCURCRSR,
60 rNew, pAttr );
61 if( !pRet )
62 pRet = pNew;
63 FOREACHPAM_END()
65 // Undo-Klammerung hier beenden
66 GetDoc()->EndUndo( UNDO_INSSECTION, NULL );
67 EndAllAction();
69 return pRet;
73 BOOL SwEditShell::IsInsRegionAvailable() const
75 if( IsTableMode() )
76 return FALSE;
77 SwPaM* pCrsr = GetCrsr();
78 if( pCrsr->GetNext() != pCrsr )
79 return FALSE;
80 if( pCrsr->HasMark() )
81 return 0 != GetDoc()->IsInsRegionAvailable( *pCrsr );
83 return TRUE;
87 const SwSection* SwEditShell::GetCurrSection() const
89 if( IsTableMode() )
90 return 0;
92 return GetDoc()->GetCurrSection( *GetCrsr()->GetPoint() );
95 /*-----------------17.03.99 11:53-------------------
96 * SwEditShell::GetAnySection liefert den fuer Spalten
97 * zustaendigen Bereich, bei Fussnoten kann es nicht der
98 * Bereich innerhalb der Fussnote sein.
99 * --------------------------------------------------*/
101 const SwSection* SwEditShell::GetAnySection( BOOL bOutOfTab, const Point* pPt ) const
103 SwFrm *pFrm;
104 if ( pPt )
106 SwPosition aPos( *GetCrsr()->GetPoint() );
107 Point aPt( *pPt );
108 GetLayout()->GetCrsrOfst( &aPos, aPt );
109 SwCntntNode *pNd = aPos.nNode.GetNode().GetCntntNode();
110 pFrm = pNd->GetFrm( pPt );
112 else
113 pFrm = GetCurrFrm( FALSE );
115 if( bOutOfTab && pFrm )
116 pFrm = pFrm->FindTabFrm();
117 if( pFrm && pFrm->IsInSct() )
119 SwSectionFrm* pSect = pFrm->FindSctFrm();
120 ASSERT( pSect, "GetAnySection: Where's my Sect?" );
121 if( pSect->IsInFtn() && pSect->GetUpper()->IsInSct() )
123 pSect = pSect->GetUpper()->FindSctFrm();
124 ASSERT( pSect, "GetAnySection: Where's my SectFrm?" );
126 return pSect->GetSection();
128 return NULL;
131 USHORT SwEditShell::GetSectionFmtCount() const
133 return GetDoc()->GetSections().Count();
137 BOOL SwEditShell::IsAnySectionInDoc( BOOL bChkReadOnly, BOOL bChkHidden, BOOL bChkTOX ) const
139 const SwSectionFmts& rFmts = GetDoc()->GetSections();
140 USHORT nCnt = rFmts.Count();
141 USHORT n;
143 for( n = 0; n < nCnt; ++n )
145 SectionType eTmpType;
146 const SwSectionFmt* pFmt = rFmts[ n ];
147 if( pFmt->IsInNodesArr() &&
148 (bChkTOX ||
149 (eTmpType = pFmt->GetSection()->GetType()) != TOX_CONTENT_SECTION
150 && TOX_HEADER_SECTION != eTmpType ))
152 const SwSection& rSect = *rFmts[ n ]->GetSection();
153 if( (!bChkReadOnly && !bChkHidden ) ||
154 (bChkReadOnly && rSect.IsProtectFlag() ) ||
155 (bChkHidden && rSect.IsHiddenFlag() ) )
156 break;
159 return n != nCnt;
162 USHORT SwEditShell::GetSectionFmtPos( const SwSectionFmt& rFmt ) const
164 SwSectionFmt* pFmt = (SwSectionFmt*)&rFmt;
165 return GetDoc()->GetSections().GetPos( pFmt );
168 const SwSectionFmt& SwEditShell::GetSectionFmt( USHORT nFmt ) const
170 return *GetDoc()->GetSections()[ nFmt ];
174 void SwEditShell::DelSectionFmt( USHORT nFmt )
176 StartAllAction();
177 GetDoc()->DelSectionFmt( GetDoc()->GetSections()[ nFmt ] );
178 // rufe das AttrChangeNotify auf der UI-Seite.
179 CallChgLnk();
180 EndAllAction();
184 void SwEditShell::ChgSection( USHORT nSect, const SwSection& rSect,
185 const SfxItemSet* pAttr )
187 StartAllAction();
188 GetDoc()->ChgSection( nSect, rSect, pAttr );
189 // rufe das AttrChangeNotify auf der UI-Seite.
190 CallChgLnk();
191 EndAllAction();
194 String SwEditShell::GetUniqueSectionName( const String* pChkStr ) const
196 return GetDoc()->GetUniqueSectionName( pChkStr );
199 void SwEditShell::SetSectionAttr( const SfxItemSet& rSet,
200 SwSectionFmt* pSectFmt )
202 if( pSectFmt )
203 _SetSectionAttr( *pSectFmt, rSet );
204 else
206 // for all section in the selection
208 FOREACHPAM_START(this)
210 const SwPosition* pStt = PCURCRSR->Start(),
211 * pEnd = PCURCRSR->End();
213 const SwSectionNode* pSttSectNd = pStt->nNode.GetNode().FindSectionNode(),
214 * pEndSectNd = pEnd->nNode.GetNode().FindSectionNode();
216 if( pSttSectNd || pEndSectNd )
218 if( pSttSectNd )
219 _SetSectionAttr( *pSttSectNd->GetSection().GetFmt(),
220 rSet );
221 if( pEndSectNd && pSttSectNd != pEndSectNd )
222 _SetSectionAttr( *pEndSectNd->GetSection().GetFmt(),
223 rSet );
225 if( pSttSectNd && pEndSectNd )
227 SwNodeIndex aSIdx( pStt->nNode );
228 SwNodeIndex aEIdx( pEnd->nNode );
229 if( pSttSectNd->EndOfSectionIndex() <
230 pEndSectNd->GetIndex() )
232 aSIdx = pSttSectNd->EndOfSectionIndex() + 1;
233 aEIdx = *pEndSectNd;
236 while( aSIdx < aEIdx )
238 if( 0 != (pSttSectNd = aSIdx.GetNode().GetSectionNode())
239 || ( aSIdx.GetNode().IsEndNode() &&
240 0 != ( pSttSectNd = aSIdx.GetNode().
241 StartOfSectionNode()->GetSectionNode())) )
242 _SetSectionAttr( *pSttSectNd->GetSection().GetFmt(),
243 rSet );
244 aSIdx++;
249 FOREACHPAM_END()
253 void SwEditShell::_SetSectionAttr( SwSectionFmt& rSectFmt,
254 const SfxItemSet& rSet )
256 StartAllAction();
257 if(SFX_ITEM_SET == rSet.GetItemState(RES_CNTNT, FALSE))
259 SfxItemSet aSet(rSet);
260 aSet.ClearItem(RES_CNTNT);
261 GetDoc()->SetAttr( aSet, rSectFmt );
263 else
264 GetDoc()->SetAttr( rSet, rSectFmt );
266 // rufe das AttrChangeNotify auf der UI-Seite.
267 CallChgLnk();
268 EndAllAction();
271 // search inside the cursor selection for full selected sections.
272 // if any part of section in the selection return 0.
273 // if more than one in the selection return the count
274 USHORT SwEditShell::GetFullSelectedSectionCount() const
276 USHORT nRet = 0;
277 FOREACHPAM_START(this)
279 const SwPosition* pStt = PCURCRSR->Start(),
280 * pEnd = PCURCRSR->End();
281 const SwCntntNode* pCNd;
282 // check the selection, if Start at Node begin and End at Node end
283 if( pStt->nContent.GetIndex() ||
284 ( 0 == ( pCNd = pEnd->nNode.GetNode().GetCntntNode() )) ||
285 pCNd->Len() != pEnd->nContent.GetIndex() )
287 nRet = 0;
288 break;
291 // !!!!!!!!!!!!!!!!!!!!!!!!!!
292 // what about table at start or end ?
293 // There is no selection possible!
294 // What about only a table inside the section ?
295 // There is only a table selection possible!
297 SwNodeIndex aSIdx( pStt->nNode, -1 ), aEIdx( pEnd->nNode, +1 );
298 if( !aSIdx.GetNode().IsSectionNode() ||
299 !aEIdx.GetNode().IsEndNode() ||
300 !aEIdx.GetNode().StartOfSectionNode()->IsSectionNode() )
302 nRet = 0;
303 break;
306 ++nRet;
307 if( &aSIdx.GetNode() != aEIdx.GetNode().StartOfSectionNode() )
308 ++nRet;
310 FOREACHPAM_END()
311 return nRet;
316 * Find the suitable node for a special insert (alt-enter).
317 * This should enable inserting text before/after sections and tables.
319 * A node is found if:
320 * 1) the innermost table/section is not in a write-protected area
321 * 2) pCurrentPos is at or just before an end node
322 * (or at or just after a start node)
323 * 3) there are only start/end nodes between pCurrentPos and the innermost
324 * table/section
326 * If a suitable node is found, an SwNode* is returned; else it is NULL.
328 const SwNode* lcl_SpecialInsertNode(const SwPosition* pCurrentPos)
330 const SwNode* pReturn = NULL;
332 // the current position
333 // const SwPosition* pCurrentPos = GetCrsr()->GetPoint();
334 DBG_ASSERT( pCurrentPos != NULL, "Strange, we have no position!" );
335 const SwNode& rCurrentNode = pCurrentPos->nNode.GetNode();
338 // find innermost section or table. At the end of this scope,
339 // pInntermostNode contain the section/table before/after which we should
340 // insert our empty paragraph, or it will be NULL if none is found.
341 const SwNode* pInnermostNode = NULL;
343 const SwNode* pTableNode = rCurrentNode.FindTableNode();
344 const SwNode* pSectionNode = rCurrentNode.FindSectionNode();
346 // find the table/section which is close
347 if( pTableNode == NULL )
348 pInnermostNode = pSectionNode;
349 else if ( pSectionNode == NULL )
350 pInnermostNode = pTableNode;
351 else
353 // compare and choose the larger one
354 pInnermostNode =
355 ( pSectionNode->GetIndex() > pTableNode->GetIndex() )
356 ? pSectionNode : pTableNode;
360 // The previous version had a check to skip empty read-only sections. Those
361 // shouldn't occur, so we only need to check whether our pInnermostNode is
362 // inside a protected area.
364 // Now, pInnermostNode is NULL or the innermost section or table node.
365 if( (pInnermostNode != NULL) && !pInnermostNode->IsProtect() )
367 DBG_ASSERT( pInnermostNode->IsTableNode() ||
368 pInnermostNode->IsSectionNode(), "wrong node found" );
369 DBG_ASSERT( ( pInnermostNode->GetIndex() <= rCurrentNode.GetIndex() )&&
370 ( pInnermostNode->EndOfSectionNode()->GetIndex() >=
371 rCurrentNode.GetIndex() ), "wrong node found" );
373 // we now need to find the possible start/end positions
375 // we found a start if
376 // - we're at or just before a start node
377 // - there are only start nodes between the current and pInnermostNode
378 SwNodeIndex aBegin( pCurrentPos->nNode );
379 if( rCurrentNode.IsCntntNode() &&
380 (pCurrentPos->nContent.GetIndex() == 0))
381 aBegin--;
382 while( (aBegin != pInnermostNode->GetIndex()) &&
383 aBegin.GetNode().IsStartNode() )
384 aBegin--;
385 bool bStart = ( aBegin == pInnermostNode->GetIndex() );
387 // we found an end if
388 // - we're at or just before an end node
389 // - there are only end nodes between the current node and
390 // pInnermostNode's end node
391 SwNodeIndex aEnd( pCurrentPos->nNode );
392 if( rCurrentNode.IsCntntNode() &&
393 ( pCurrentPos->nContent.GetIndex() ==
394 rCurrentNode.GetCntntNode()->Len() ) )
395 aEnd++;
396 while( (aEnd != pInnermostNode->EndOfSectionNode()->GetIndex()) &&
397 aEnd.GetNode().IsEndNode() )
398 aEnd++;
399 bool bEnd = ( aEnd == pInnermostNode->EndOfSectionNode()->GetIndex() );
401 // evalutate result: if both start + end, end is preferred
402 if( bEnd )
403 pReturn = pInnermostNode->EndOfSectionNode();
404 else if ( bStart )
405 pReturn = pInnermostNode;
406 // else pReturn = NULL;
408 // else: pReturn = NULL
411 DBG_ASSERT( ( pReturn == NULL ) || pReturn->IsStartNode() ||
412 pReturn->IsEndNode(),
413 "SpecialInsertNode failed" );
414 return pReturn;
418 /** a node can be special-inserted (alt-Enter) whenever lcl_SpecialInsertNode
419 finds a suitable position
421 bool SwEditShell::CanSpecialInsert() const
423 return NULL != lcl_SpecialInsertNode( GetCrsr()->GetPoint() );
427 /** check whether a node cen be special-inserted (alt-Enter), and do so. Return
428 whether insertion was possible.
430 bool SwEditShell::DoSpecialInsert()
432 bool bRet = false;
434 // get current node
435 SwPosition* pCursorPos = GetCrsr()->GetPoint();
436 const SwNode* pInsertNode = lcl_SpecialInsertNode( pCursorPos );
437 if( pInsertNode != NULL )
439 StartAllAction();
441 // adjust insert position to insert before start nodes and after end
442 // nodes
443 SwNodeIndex aInsertIndex( *pInsertNode,
444 pInsertNode->IsStartNode() ? -1 : 0 );
445 SwPosition aInsertPos( aInsertIndex );
447 // insert a new text node, and set the cursor
448 bRet = GetDoc()->AppendTxtNode( aInsertPos );
449 *pCursorPos = aInsertPos;
451 // call AttrChangeNotify for the UI
452 CallChgLnk();
454 EndAllAction();
457 return bRet;