Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <editsh.hxx>
31 : : #include <doc.hxx>
32 : : #include <IDocumentUndoRedo.hxx>
33 : : #include <pam.hxx>
34 : : #include <docary.hxx>
35 : : #include <swundo.hxx> // fuer die UndoIds
36 : : #include <section.hxx>
37 : : #include <edimp.hxx>
38 : : #include <sectfrm.hxx> // SwSectionFrm
39 : : #include <cntfrm.hxx> // SwCntntFrm
40 : : #include <tabfrm.hxx> // SwTabFrm
41 : : #include <rootfrm.hxx> // SwRootFrm
42 : :
43 : :
44 : : SwSection const*
45 : 0 : SwEditShell::InsertSection(
46 : : SwSectionData & rNewData, SfxItemSet const*const pAttr)
47 : : {
48 : 0 : const SwSection* pRet = 0;
49 [ # # ]: 0 : if( !IsTableMode() )
50 : : {
51 : 0 : StartAllAction();
52 : 0 : GetDoc()->GetIDocumentUndoRedo().StartUndo( UNDO_INSSECTION, NULL );
53 : :
54 [ # # ]: 0 : FOREACHPAM_START(this)
55 : : SwSection const*const pNew =
56 : 0 : GetDoc()->InsertSwSection( *PCURCRSR, rNewData, 0, pAttr );
57 [ # # ]: 0 : if( !pRet )
58 : 0 : pRet = pNew;
59 : 0 : FOREACHPAM_END()
60 : :
61 : 0 : GetDoc()->GetIDocumentUndoRedo().EndUndo( UNDO_INSSECTION, NULL );
62 : 0 : EndAllAction();
63 : : }
64 : 0 : return pRet;
65 : : }
66 : :
67 : :
68 : 0 : sal_Bool SwEditShell::IsInsRegionAvailable() const
69 : : {
70 [ # # ]: 0 : if( IsTableMode() )
71 : 0 : return sal_False;
72 : 0 : SwPaM* pCrsr = GetCrsr();
73 [ # # ]: 0 : if( pCrsr->GetNext() != pCrsr )
74 : 0 : return sal_False;
75 [ # # ]: 0 : if( pCrsr->HasMark() )
76 : 0 : return 0 != GetDoc()->IsInsRegionAvailable( *pCrsr );
77 : :
78 : 0 : return sal_True;
79 : : }
80 : :
81 : :
82 : 1357 : const SwSection* SwEditShell::GetCurrSection() const
83 : : {
84 [ - + ]: 1357 : if( IsTableMode() )
85 : 0 : return 0;
86 : :
87 : 1357 : return GetDoc()->GetCurrSection( *GetCrsr()->GetPoint() );
88 : : }
89 : :
90 : : /*--------------------------------------------------
91 : : * SwEditShell::GetAnySection liefert den fuer Spalten
92 : : * zustaendigen Bereich, bei Fussnoten kann es nicht der
93 : : * Bereich innerhalb der Fussnote sein.
94 : : * --------------------------------------------------*/
95 : :
96 : 0 : const SwSection* SwEditShell::GetAnySection( sal_Bool bOutOfTab, const Point* pPt ) const
97 : : {
98 : : SwFrm *pFrm;
99 [ # # ]: 0 : if ( pPt )
100 : : {
101 [ # # ][ # # ]: 0 : SwPosition aPos( *GetCrsr()->GetPoint() );
102 : 0 : Point aPt( *pPt );
103 [ # # ][ # # ]: 0 : GetLayout()->GetCrsrOfst( &aPos, aPt );
104 : 0 : SwCntntNode *pNd = aPos.nNode.GetNode().GetCntntNode();
105 [ # # ][ # # ]: 0 : pFrm = pNd->getLayoutFrm( GetLayout(), pPt );
[ # # ]
106 : : }
107 : : else
108 : 0 : pFrm = GetCurrFrm( sal_False );
109 : :
110 [ # # ][ # # ]: 0 : if( bOutOfTab && pFrm )
111 : 0 : pFrm = pFrm->FindTabFrm();
112 [ # # ][ # # ]: 0 : if( pFrm && pFrm->IsInSct() )
[ # # ]
113 : : {
114 : 0 : SwSectionFrm* pSect = pFrm->FindSctFrm();
115 : : OSL_ENSURE( pSect, "GetAnySection: Where's my Sect?" );
116 [ # # ][ # # ]: 0 : if( pSect->IsInFtn() && pSect->GetUpper()->IsInSct() )
[ # # ]
117 : : {
118 : 0 : pSect = pSect->GetUpper()->FindSctFrm();
119 : : OSL_ENSURE( pSect, "GetAnySection: Where's my SectFrm?" );
120 : : }
121 : 0 : return pSect->GetSection();
122 : : }
123 : 0 : return NULL;
124 : : }
125 : :
126 : 0 : sal_uInt16 SwEditShell::GetSectionFmtCount() const
127 : : {
128 : 0 : return GetDoc()->GetSections().size();
129 : : }
130 : :
131 : :
132 : 4 : sal_Bool SwEditShell::IsAnySectionInDoc( sal_Bool bChkReadOnly, sal_Bool bChkHidden, sal_Bool bChkTOX ) const
133 : : {
134 : 4 : const SwSectionFmts& rFmts = GetDoc()->GetSections();
135 : 4 : sal_uInt16 nCnt = rFmts.size();
136 : : sal_uInt16 n;
137 : :
138 [ - + ]: 4 : for( n = 0; n < nCnt; ++n )
139 : : {
140 : : SectionType eTmpType;
141 : 0 : const SwSectionFmt* pFmt = rFmts[ n ];
142 [ # # # # ]: 0 : if( pFmt->IsInNodesArr() &&
[ # # ][ # # ]
[ # # ]
143 : : (bChkTOX ||
144 : 0 : ( (eTmpType = pFmt->GetSection()->GetType()) != TOX_CONTENT_SECTION
145 : : && TOX_HEADER_SECTION != eTmpType ) ) )
146 : : {
147 : 0 : const SwSection& rSect = *rFmts[ n ]->GetSection();
148 [ # # ]: 0 : if( (!bChkReadOnly && !bChkHidden ) ||
[ # # # # ]
[ # # # # ]
[ # # ][ # # ]
149 : 0 : (bChkReadOnly && rSect.IsProtectFlag() ) ||
150 : 0 : (bChkHidden && rSect.IsHiddenFlag() ) )
151 : 0 : break;
152 : : }
153 : : }
154 : 4 : return n != nCnt;
155 : : }
156 : :
157 : 0 : sal_uInt16 SwEditShell::GetSectionFmtPos( const SwSectionFmt& rFmt ) const
158 : : {
159 : 0 : SwSectionFmt* pFmt = (SwSectionFmt*)&rFmt;
160 : 0 : return GetDoc()->GetSections().GetPos( pFmt );
161 : : }
162 : :
163 : 0 : const SwSectionFmt& SwEditShell::GetSectionFmt( sal_uInt16 nFmt ) const
164 : : {
165 : 0 : return *GetDoc()->GetSections()[ nFmt ];
166 : : }
167 : :
168 : :
169 : 0 : void SwEditShell::DelSectionFmt( sal_uInt16 nFmt )
170 : : {
171 : 0 : StartAllAction();
172 : 0 : GetDoc()->DelSectionFmt( GetDoc()->GetSections()[ nFmt ] );
173 : : // rufe das AttrChangeNotify auf der UI-Seite.
174 : 0 : CallChgLnk();
175 : 0 : EndAllAction();
176 : 0 : }
177 : :
178 : :
179 : 0 : void SwEditShell::UpdateSection(sal_uInt16 const nSect,
180 : : SwSectionData & rNewData, SfxItemSet const*const pAttr)
181 : : {
182 : 0 : StartAllAction();
183 : 0 : GetDoc()->UpdateSection( nSect, rNewData, pAttr );
184 : : // rufe das AttrChangeNotify auf der UI-Seite.
185 : 0 : CallChgLnk();
186 : 0 : EndAllAction();
187 : 0 : }
188 : :
189 : 0 : String SwEditShell::GetUniqueSectionName( const String* pChkStr ) const
190 : : {
191 : 0 : return GetDoc()->GetUniqueSectionName( pChkStr );
192 : : }
193 : :
194 : 0 : void SwEditShell::SetSectionAttr( const SfxItemSet& rSet,
195 : : SwSectionFmt* pSectFmt )
196 : : {
197 [ # # ]: 0 : if( pSectFmt )
198 : 0 : _SetSectionAttr( *pSectFmt, rSet );
199 : : else
200 : : {
201 : : // for all section in the selection
202 : :
203 [ # # ]: 0 : FOREACHPAM_START(this)
204 : :
205 : 0 : const SwPosition* pStt = PCURCRSR->Start(),
206 : 0 : * pEnd = PCURCRSR->End();
207 : :
208 : 0 : const SwSectionNode* pSttSectNd = pStt->nNode.GetNode().FindSectionNode(),
209 : 0 : * pEndSectNd = pEnd->nNode.GetNode().FindSectionNode();
210 : :
211 [ # # ][ # # ]: 0 : if( pSttSectNd || pEndSectNd )
212 : : {
213 [ # # ]: 0 : if( pSttSectNd )
214 : 0 : _SetSectionAttr( *pSttSectNd->GetSection().GetFmt(),
215 : 0 : rSet );
216 [ # # ][ # # ]: 0 : if( pEndSectNd && pSttSectNd != pEndSectNd )
217 : 0 : _SetSectionAttr( *pEndSectNd->GetSection().GetFmt(),
218 : 0 : rSet );
219 : :
220 [ # # ][ # # ]: 0 : if( pSttSectNd && pEndSectNd )
221 : : {
222 [ # # ]: 0 : SwNodeIndex aSIdx( pStt->nNode );
223 [ # # ]: 0 : SwNodeIndex aEIdx( pEnd->nNode );
224 [ # # ]: 0 : if( pSttSectNd->EndOfSectionIndex() <
225 : 0 : pEndSectNd->GetIndex() )
226 : : {
227 [ # # ]: 0 : aSIdx = pSttSectNd->EndOfSectionIndex() + 1;
228 [ # # ]: 0 : aEIdx = *pEndSectNd;
229 : : }
230 : :
231 [ # # ]: 0 : while( aSIdx < aEIdx )
232 : : {
233 [ # # # # : 0 : if( 0 != (pSttSectNd = aSIdx.GetNode().GetSectionNode())
# # ][ # # ]
234 : 0 : || ( aSIdx.GetNode().IsEndNode() &&
235 : 0 : 0 != ( pSttSectNd = aSIdx.GetNode().
236 : 0 : StartOfSectionNode()->GetSectionNode())) )
237 : 0 : _SetSectionAttr( *pSttSectNd->GetSection().GetFmt(),
238 [ # # ]: 0 : rSet );
239 [ # # ]: 0 : aSIdx++;
240 [ # # ][ # # ]: 0 : }
241 : : }
242 : : }
243 : :
244 : 0 : FOREACHPAM_END()
245 : : }
246 : 0 : }
247 : :
248 : 0 : void SwEditShell::_SetSectionAttr( SwSectionFmt& rSectFmt,
249 : : const SfxItemSet& rSet )
250 : : {
251 : 0 : StartAllAction();
252 [ # # ]: 0 : if(SFX_ITEM_SET == rSet.GetItemState(RES_CNTNT, sal_False))
253 : : {
254 [ # # ]: 0 : SfxItemSet aSet(rSet);
255 [ # # ]: 0 : aSet.ClearItem(RES_CNTNT);
256 [ # # ][ # # ]: 0 : GetDoc()->SetAttr( aSet, rSectFmt );
257 : : }
258 : : else
259 : 0 : GetDoc()->SetAttr( rSet, rSectFmt );
260 : :
261 : : // rufe das AttrChangeNotify auf der UI-Seite.
262 : 0 : CallChgLnk();
263 : 0 : EndAllAction();
264 : 0 : }
265 : :
266 : : // search inside the cursor selection for full selected sections.
267 : : // if any part of section in the selection return 0.
268 : : // if more than one in the selection return the count
269 : 0 : sal_uInt16 SwEditShell::GetFullSelectedSectionCount() const
270 : : {
271 : 0 : sal_uInt16 nRet = 0;
272 [ # # ]: 0 : FOREACHPAM_START(this)
273 : :
274 [ # # ]: 0 : const SwPosition* pStt = PCURCRSR->Start(),
275 [ # # ]: 0 : * pEnd = PCURCRSR->End();
276 : : const SwCntntNode* pCNd;
277 : : // check the selection, if Start at Node begin and End at Node end
278 [ # # # # : 0 : if( pStt->nContent.GetIndex() ||
# # ][ # # ]
279 : 0 : ( 0 == ( pCNd = pEnd->nNode.GetNode().GetCntntNode() )) ||
280 [ # # ]: 0 : pCNd->Len() != pEnd->nContent.GetIndex() )
281 : : {
282 : 0 : nRet = 0;
283 : : break;
284 : : }
285 : :
286 : : // !!!!!!!!!!!!!!!!!!!!!!!!!!
287 : : // what about table at start or end ?
288 : : // There is no selection possible!
289 : : // What about only a table inside the section ?
290 : : // There is only a table selection possible!
291 : :
292 [ # # ][ # # ]: 0 : SwNodeIndex aSIdx( pStt->nNode, -1 ), aEIdx( pEnd->nNode, +1 );
293 [ # # # # : 0 : if( !aSIdx.GetNode().IsSectionNode() ||
# # ][ # # ]
294 : 0 : !aEIdx.GetNode().IsEndNode() ||
295 : 0 : !aEIdx.GetNode().StartOfSectionNode()->IsSectionNode() )
296 : : {
297 : 0 : nRet = 0;
298 : : break;
299 : : }
300 : :
301 : 0 : ++nRet;
302 [ # # ]: 0 : if( &aSIdx.GetNode() != aEIdx.GetNode().StartOfSectionNode() )
303 [ # # ][ # # ]: 0 : ++nRet;
[ # # ][ # # ]
304 : :
305 : 0 : FOREACHPAM_END()
306 : 0 : return nRet;
307 : : }
308 : :
309 : :
310 : : /**
311 : : * Find the suitable node for a special insert (alt-enter).
312 : : * This should enable inserting text before/after sections and tables.
313 : : *
314 : : * A node is found if:
315 : : * 1) the innermost table/section is not in a write-protected area
316 : : * 2) pCurrentPos is at or just before an end node
317 : : * (or at or just after a start node)
318 : : * 3) there are only start/end nodes between pCurrentPos and the innermost
319 : : * table/section
320 : : *
321 : : * If a suitable node is found, an SwNode* is returned; else it is NULL.
322 : : */
323 : 0 : const SwNode* lcl_SpecialInsertNode(const SwPosition* pCurrentPos)
324 : : {
325 : 0 : const SwNode* pReturn = NULL;
326 : :
327 : : // the current position
328 : : // const SwPosition* pCurrentPos = GetCrsr()->GetPoint();
329 : : OSL_ENSURE( pCurrentPos != NULL, "Strange, we have no position!" );
330 : 0 : const SwNode& rCurrentNode = pCurrentPos->nNode.GetNode();
331 : :
332 : :
333 : : // find innermost section or table. At the end of this scope,
334 : : // pInntermostNode contain the section/table before/after which we should
335 : : // insert our empty paragraph, or it will be NULL if none is found.
336 : 0 : const SwNode* pInnermostNode = NULL;
337 : : {
338 : 0 : const SwNode* pTableNode = rCurrentNode.FindTableNode();
339 : 0 : const SwNode* pSectionNode = rCurrentNode.FindSectionNode();
340 : :
341 : : // find the table/section which is close
342 [ # # ]: 0 : if( pTableNode == NULL )
343 : 0 : pInnermostNode = pSectionNode;
344 [ # # ]: 0 : else if ( pSectionNode == NULL )
345 : 0 : pInnermostNode = pTableNode;
346 : : else
347 : : {
348 : : // compare and choose the larger one
349 : : pInnermostNode =
350 : 0 : ( pSectionNode->GetIndex() > pTableNode->GetIndex() )
351 [ # # ]: 0 : ? pSectionNode : pTableNode;
352 : : }
353 : : }
354 : :
355 : : // The previous version had a check to skip empty read-only sections. Those
356 : : // shouldn't occur, so we only need to check whether our pInnermostNode is
357 : : // inside a protected area.
358 : :
359 : : // Now, pInnermostNode is NULL or the innermost section or table node.
360 [ # # ][ # # ]: 0 : if( (pInnermostNode != NULL) && !pInnermostNode->IsProtect() )
[ # # ]
361 : : {
362 : : OSL_ENSURE( pInnermostNode->IsTableNode() ||
363 : : pInnermostNode->IsSectionNode(), "wrong node found" );
364 : : OSL_ENSURE( ( pInnermostNode->GetIndex() <= rCurrentNode.GetIndex() )&&
365 : : ( pInnermostNode->EndOfSectionNode()->GetIndex() >=
366 : : rCurrentNode.GetIndex() ), "wrong node found" );
367 : :
368 : : // we now need to find the possible start/end positions
369 : :
370 : : // we found a start if
371 : : // - we're at or just before a start node
372 : : // - there are only start nodes between the current and pInnermostNode
373 [ # # ]: 0 : SwNodeIndex aBegin( pCurrentPos->nNode );
374 [ # # # # ]: 0 : if( rCurrentNode.IsCntntNode() &&
[ # # ]
375 : 0 : (pCurrentPos->nContent.GetIndex() == 0))
376 [ # # ]: 0 : aBegin--;
377 [ # # # # ]: 0 : while( (aBegin != pInnermostNode->GetIndex()) &&
[ # # ]
378 : 0 : aBegin.GetNode().IsStartNode() )
379 [ # # ]: 0 : aBegin--;
380 : 0 : bool bStart = ( aBegin == pInnermostNode->GetIndex() );
381 : :
382 : : // we found an end if
383 : : // - we're at or just before an end node
384 : : // - there are only end nodes between the current node and
385 : : // pInnermostNode's end node
386 [ # # ]: 0 : SwNodeIndex aEnd( pCurrentPos->nNode );
387 [ # # ][ # # ]: 0 : if( rCurrentNode.IsCntntNode() &&
[ # # ]
388 : 0 : ( pCurrentPos->nContent.GetIndex() ==
389 [ # # ]: 0 : rCurrentNode.GetCntntNode()->Len() ) )
390 [ # # ]: 0 : aEnd++;
391 [ # # # # ]: 0 : while( (aEnd != pInnermostNode->EndOfSectionNode()->GetIndex()) &&
[ # # ]
392 : 0 : aEnd.GetNode().IsEndNode() )
393 [ # # ]: 0 : aEnd++;
394 : 0 : bool bEnd = ( aEnd == pInnermostNode->EndOfSectionNode()->GetIndex() );
395 : :
396 : : // evalutate result: if both start + end, end is preferred
397 [ # # ]: 0 : if( bEnd )
398 : 0 : pReturn = pInnermostNode->EndOfSectionNode();
399 [ # # ]: 0 : else if ( bStart )
400 [ # # ][ # # ]: 0 : pReturn = pInnermostNode;
401 : : }
402 : :
403 : :
404 : : OSL_ENSURE( ( pReturn == NULL ) || pReturn->IsStartNode() ||
405 : : pReturn->IsEndNode(),
406 : : "SpecialInsertNode failed" );
407 : 0 : return pReturn;
408 : : }
409 : :
410 : :
411 : : /** a node can be special-inserted (alt-Enter) whenever lcl_SpecialInsertNode
412 : : finds a suitable position
413 : : */
414 : 0 : bool SwEditShell::CanSpecialInsert() const
415 : : {
416 : 0 : return NULL != lcl_SpecialInsertNode( GetCrsr()->GetPoint() );
417 : : }
418 : :
419 : :
420 : : /** check whether a node cen be special-inserted (alt-Enter), and do so. Return
421 : : whether insertion was possible.
422 : : */
423 : 0 : bool SwEditShell::DoSpecialInsert()
424 : : {
425 : 0 : bool bRet = false;
426 : :
427 : : // get current node
428 : 0 : SwPosition* pCursorPos = GetCrsr()->GetPoint();
429 : 0 : const SwNode* pInsertNode = lcl_SpecialInsertNode( pCursorPos );
430 [ # # ]: 0 : if( pInsertNode != NULL )
431 : : {
432 [ # # ]: 0 : StartAllAction();
433 : :
434 : : // adjust insert position to insert before start nodes and after end
435 : : // nodes
436 : : SwNodeIndex aInsertIndex( *pInsertNode,
437 [ # # ][ # # ]: 0 : pInsertNode->IsStartNode() ? -1 : 0 );
438 [ # # ]: 0 : SwPosition aInsertPos( aInsertIndex );
439 : :
440 : : // insert a new text node, and set the cursor
441 [ # # ]: 0 : bRet = GetDoc()->AppendTxtNode( aInsertPos );
442 [ # # ]: 0 : *pCursorPos = aInsertPos;
443 : :
444 : : // call AttrChangeNotify for the UI
445 [ # # ]: 0 : CallChgLnk();
446 : :
447 [ # # ][ # # ]: 0 : EndAllAction();
[ # # ]
448 : : }
449 : :
450 : 0 : return bRet;
451 : : }
452 : :
453 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|