1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: edsect.cxx,v $
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"
39 #include <swundo.hxx> // fuer die UndoIds
40 #include <section.hxx>
42 #include <sectfrm.hxx> // SwSectionFrm
43 #include <cntfrm.hxx> // SwCntntFrm
44 #include <tabfrm.hxx> // SwTabFrm
45 #include <rootfrm.hxx> // SwRootFrm
49 const SwSection
* SwEditShell::InsertSection( const SwSection
& rNew
,
50 const SfxItemSet
* pAttr
)
52 const SwSection
* pRet
= 0;
56 GetDoc()->StartUndo( UNDO_INSSECTION
, NULL
);
58 FOREACHPAM_START(this)
59 const SwSection
* pNew
= GetDoc()->Insert( *PCURCRSR
,
65 // Undo-Klammerung hier beenden
66 GetDoc()->EndUndo( UNDO_INSSECTION
, NULL
);
73 BOOL
SwEditShell::IsInsRegionAvailable() const
77 SwPaM
* pCrsr
= GetCrsr();
78 if( pCrsr
->GetNext() != pCrsr
)
80 if( pCrsr
->HasMark() )
81 return 0 != GetDoc()->IsInsRegionAvailable( *pCrsr
);
87 const SwSection
* SwEditShell::GetCurrSection() const
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
106 SwPosition
aPos( *GetCrsr()->GetPoint() );
108 GetLayout()->GetCrsrOfst( &aPos
, aPt
);
109 SwCntntNode
*pNd
= aPos
.nNode
.GetNode().GetCntntNode();
110 pFrm
= pNd
->GetFrm( pPt
);
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();
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();
143 for( n
= 0; n
< nCnt
; ++n
)
145 SectionType eTmpType
;
146 const SwSectionFmt
* pFmt
= rFmts
[ n
];
147 if( pFmt
->IsInNodesArr() &&
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() ) )
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
)
177 GetDoc()->DelSectionFmt( GetDoc()->GetSections()[ nFmt
] );
178 // rufe das AttrChangeNotify auf der UI-Seite.
184 void SwEditShell::ChgSection( USHORT nSect
, const SwSection
& rSect
,
185 const SfxItemSet
* pAttr
)
188 GetDoc()->ChgSection( nSect
, rSect
, pAttr
);
189 // rufe das AttrChangeNotify auf der UI-Seite.
194 String
SwEditShell::GetUniqueSectionName( const String
* pChkStr
) const
196 return GetDoc()->GetUniqueSectionName( pChkStr
);
199 void SwEditShell::SetSectionAttr( const SfxItemSet
& rSet
,
200 SwSectionFmt
* pSectFmt
)
203 _SetSectionAttr( *pSectFmt
, rSet
);
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
)
219 _SetSectionAttr( *pSttSectNd
->GetSection().GetFmt(),
221 if( pEndSectNd
&& pSttSectNd
!= pEndSectNd
)
222 _SetSectionAttr( *pEndSectNd
->GetSection().GetFmt(),
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;
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(),
253 void SwEditShell::_SetSectionAttr( SwSectionFmt
& rSectFmt
,
254 const SfxItemSet
& rSet
)
257 if(SFX_ITEM_SET
== rSet
.GetItemState(RES_CNTNT
, FALSE
))
259 SfxItemSet
aSet(rSet
);
260 aSet
.ClearItem(RES_CNTNT
);
261 GetDoc()->SetAttr( aSet
, rSectFmt
);
264 GetDoc()->SetAttr( rSet
, rSectFmt
);
266 // rufe das AttrChangeNotify auf der UI-Seite.
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
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() )
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() )
307 if( &aSIdx
.GetNode() != aEIdx
.GetNode().StartOfSectionNode() )
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
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
;
353 // compare and choose the larger one
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))
382 while( (aBegin
!= pInnermostNode
->GetIndex()) &&
383 aBegin
.GetNode().IsStartNode() )
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() ) )
396 while( (aEnd
!= pInnermostNode
->EndOfSectionNode()->GetIndex()) &&
397 aEnd
.GetNode().IsEndNode() )
399 bool bEnd
= ( aEnd
== pInnermostNode
->EndOfSectionNode()->GetIndex() );
401 // evalutate result: if both start + end, end is preferred
403 pReturn
= pInnermostNode
->EndOfSectionNode();
405 pReturn
= pInnermostNode
;
406 // else pReturn = NULL;
408 // else: pReturn = NULL
411 DBG_ASSERT( ( pReturn
== NULL
) || pReturn
->IsStartNode() ||
412 pReturn
->IsEndNode(),
413 "SpecialInsertNode failed" );
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()
435 SwPosition
* pCursorPos
= GetCrsr()->GetPoint();
436 const SwNode
* pInsertNode
= lcl_SpecialInsertNode( pCursorPos
);
437 if( pInsertNode
!= NULL
)
441 // adjust insert position to insert before start nodes and after end
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