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 : : #include "pam.hxx"
30 : : #include "swtable.hxx"
31 : : #include "frame.hxx"
32 : : #include "rootfrm.hxx"
33 : : #include "pagefrm.hxx"
34 : : #include "flyfrm.hxx"
35 : : #include "viewsh.hxx"
36 : : #include "doc.hxx"
37 : : #include "viewimp.hxx"
38 : : #include "viewopt.hxx"
39 : : #include "dflyobj.hxx"
40 : : #include "frmtool.hxx"
41 : : #include "dcontact.hxx"
42 : : #include <editeng/brkitem.hxx>
43 : : #include <editeng/keepitem.hxx>
44 : : #include <fmtsrnd.hxx>
45 : : #include <fmtanchr.hxx>
46 : : #include <fmtpdsc.hxx>
47 : : #include <editeng/ulspitem.hxx>
48 : : #include <tgrditem.hxx>
49 : : #include <txtftn.hxx>
50 : : #include <fmtftn.hxx>
51 : : #include <editeng/pgrditem.hxx>
52 : : #include <paratr.hxx>
53 : : #include "ftnfrm.hxx"
54 : : #include "txtfrm.hxx"
55 : : #include "tabfrm.hxx"
56 : : #include "pagedesc.hxx"
57 : : #include "layact.hxx"
58 : : #include "fmtornt.hxx"
59 : : #include "flyfrms.hxx"
60 : : #include "sectfrm.hxx"
61 : : #include "section.hxx"
62 : : #include "dbg_lay.hxx"
63 : : #include "lineinfo.hxx"
64 : : #include <fmtclbl.hxx>
65 : : #include <sortedobjs.hxx>
66 : : #include <layouter.hxx>
67 : : #include <fmtfollowtextflow.hxx>
68 : : #include <switerator.hxx>
69 : :
70 : : sal_Bool SwFlowFrm::bMoveBwdJump = sal_False;
71 : :
72 : :
73 : : /*************************************************************************
74 : : |*
75 : : |* SwFlowFrm::SwFlowFrm()
76 : : |*
77 : : |*************************************************************************/
78 : :
79 : :
80 : 6167 : SwFlowFrm::SwFlowFrm( SwFrm &rFrm ) :
81 : : rThis( rFrm ),
82 : : m_pFollow( 0 ),
83 : : m_pPrecede( 0 ),
84 : : bLockJoin( false ),
85 : : bUndersized( false ),
86 : 6167 : bFlyLock( false )
87 : 6167 : {}
88 : :
89 : 5879 : SwFlowFrm::~SwFlowFrm()
90 : : {
91 [ + + ]: 5879 : if (m_pFollow)
92 : : {
93 : 19 : m_pFollow->m_pPrecede = 0;
94 : : }
95 [ - + ]: 5879 : if (m_pPrecede)
96 : : {
97 : 0 : m_pPrecede->m_pFollow = 0;
98 : : }
99 [ - + ]: 5879 : }
100 : :
101 : 575 : void SwFlowFrm::SetFollow(SwFlowFrm *const pFollow)
102 : : {
103 [ + + ]: 575 : if (m_pFollow)
104 : : {
105 : : assert(this == m_pFollow->m_pPrecede);
106 : 97 : m_pFollow->m_pPrecede = 0;
107 : : }
108 : 575 : m_pFollow = pFollow;
109 [ + + ]: 575 : if (m_pFollow != NULL)
110 : : {
111 [ + + ]: 118 : if (m_pFollow->m_pPrecede) // re-chaining pFollow?
112 : : {
113 : : assert(m_pFollow == m_pFollow->m_pPrecede->m_pFollow);
114 : 2 : m_pFollow->m_pPrecede->m_pFollow = 0;
115 : : }
116 : 118 : m_pFollow->m_pPrecede = this;
117 : : }
118 : 575 : }
119 : :
120 : : /*************************************************************************
121 : : |*
122 : : |* SwFlowFrm::IsFollowLocked()
123 : : |* return sal_True if any follow has the JoinLocked flag
124 : : |*
125 : : |*************************************************************************/
126 : :
127 : 299 : sal_Bool SwFlowFrm::HasLockedFollow() const
128 : : {
129 : 299 : const SwFlowFrm* pFrm = GetFollow();
130 [ - + ]: 299 : while( pFrm )
131 : : {
132 [ # # ]: 0 : if( pFrm->IsJoinLocked() )
133 : 0 : return sal_True;
134 : 0 : pFrm = pFrm->GetFollow();
135 : : }
136 : 299 : return sal_False;
137 : : }
138 : :
139 : : /*************************************************************************
140 : : |*
141 : : |* SwFlowFrm::IsKeepFwdMoveAllowed()
142 : : |*
143 : : |*************************************************************************/
144 : :
145 : :
146 : 0 : sal_Bool SwFlowFrm::IsKeepFwdMoveAllowed()
147 : : {
148 : : // If all the predecessors up to the first of the chain have
149 : : // the 'keep' attribute set, and the first of the chain's
150 : : // IsFwdMoveAllowed returns sal_False, then we're not allowed to move.
151 : 0 : SwFrm *pFrm = &rThis;
152 [ # # ]: 0 : if ( !pFrm->IsInFtn() )
153 [ # # ]: 0 : do
154 [ # # ]: 0 : { if ( pFrm->GetAttrSet()->GetKeep().GetValue() )
155 : 0 : pFrm = pFrm->GetIndPrev();
156 : : else
157 : 0 : return sal_True;
158 : : } while ( pFrm );
159 : :
160 : : //See IsFwdMoveAllowed()
161 : 0 : sal_Bool bRet = sal_False;
162 [ # # ][ # # ]: 0 : if ( pFrm && pFrm->GetIndPrev() )
[ # # ]
163 : 0 : bRet = sal_True;
164 : 0 : return bRet;
165 : : }
166 : :
167 : : /*************************************************************************
168 : : |*
169 : : |* SwFlowFrm::CheckKeep()
170 : : |*
171 : : |*************************************************************************/
172 : :
173 : :
174 : 1302 : void SwFlowFrm::CheckKeep()
175 : : {
176 : : // Kick off the "last" predecessor with a 'keep' attribute, because
177 : : // it's possible for the whole troop to move back.
178 : 1302 : SwFrm *pPre = rThis.GetIndPrev();
179 [ + + ]: 1302 : if( pPre->IsSctFrm() )
180 : : {
181 : 56 : SwFrm *pLast = ((SwSectionFrm*)pPre)->FindLastCntnt();
182 [ + - ][ + - ]: 56 : if( pLast && pLast->FindSctFrm() == pPre )
[ + - ]
183 : 56 : pPre = pLast;
184 : : else
185 : 1302 : return;
186 : : }
187 : : SwFrm* pTmp;
188 : : sal_Bool bKeep;
189 [ + + ][ + + ]: 1415 : while ( sal_True == (bKeep = pPre->GetAttrSet()->GetKeep().GetValue()) &&
[ + + ]
190 : : 0 != ( pTmp = pPre->GetIndPrev() ) )
191 : : {
192 [ - + ]: 113 : if( pTmp->IsSctFrm() )
193 : : {
194 : 0 : SwFrm *pLast = ((SwSectionFrm*)pTmp)->FindLastCntnt();
195 [ # # ][ # # ]: 0 : if( pLast && pLast->FindSctFrm() == pTmp )
[ # # ]
196 : 0 : pTmp = pLast;
197 : : else
198 : 0 : break;
199 : : }
200 : 113 : pPre = pTmp;
201 : : }
202 [ + + ]: 1302 : if ( bKeep )
203 : 52 : pPre->InvalidatePos();
204 : : }
205 : :
206 : : /*************************************************************************
207 : : |*
208 : : |* SwFlowFrm::IsKeep()
209 : : |*
210 : : |*************************************************************************/
211 : :
212 : 23778 : sal_Bool SwFlowFrm::IsKeep( const SwAttrSet& rAttrs, bool bCheckIfLastRowShouldKeep ) const
213 : : {
214 : : // 1. The keep attribute is ignored inside footnotes
215 : : // 2. For compatibility reasons, the keep attribute is
216 : : // ignored for frames inside table cells
217 : : // 3. If bBreakCheck is set to true, this function only checks
218 : : // if there are any break after attributes set at rAttrs
219 : : // or break before attributes set for the next content (or next table)
220 : : sal_Bool bKeep = bCheckIfLastRowShouldKeep ||
221 : 23718 : ( !rThis.IsInFtn() &&
222 : 30434 : ( !rThis.IsInTab() || rThis.IsTabFrm() ) &&
223 [ + + + + : 77930 : rAttrs.GetKeep().GetValue() );
+ + + + ]
[ + + ]
224 : :
225 : : OSL_ENSURE( !bCheckIfLastRowShouldKeep || rThis.IsTabFrm(),
226 : : "IsKeep with bCheckIfLastRowShouldKeep should only be used for tabfrms" );
227 : :
228 : : // Ignore keep attribute if there are break situations:
229 [ + + ]: 23778 : if ( bKeep )
230 : : {
231 [ + + ]: 212 : switch ( rAttrs.GetBreak().GetBreak() )
232 : : {
233 : : case SVX_BREAK_COLUMN_AFTER:
234 : : case SVX_BREAK_COLUMN_BOTH:
235 : : case SVX_BREAK_PAGE_AFTER:
236 : : case SVX_BREAK_PAGE_BOTH:
237 : : {
238 : 23 : bKeep = sal_False;
239 : : }
240 : 212 : default: break;
241 : : }
242 [ + + ]: 212 : if ( bKeep )
243 : : {
244 : : SwFrm *pNxt;
245 [ + + ]: 189 : if( 0 != (pNxt = rThis.FindNextCnt()) &&
[ - + # # ]
[ + + ]
246 : 0 : (!m_pFollow || pNxt != m_pFollow->GetFrm()))
247 : : {
248 : : // #135914#
249 : : // The last row of a table only keeps with the next content
250 : : // it they are in the same section:
251 [ + + ]: 168 : if ( bCheckIfLastRowShouldKeep )
252 : : {
253 : 60 : const SwSection* pThisSection = 0;
254 : 60 : const SwSection* pNextSection = 0;
255 : 60 : const SwSectionFrm* pThisSectionFrm = rThis.FindSctFrm();
256 : 60 : const SwSectionFrm* pNextSectionFrm = pNxt->FindSctFrm();
257 : :
258 [ - + ]: 60 : if ( pThisSectionFrm )
259 : 0 : pThisSection = pThisSectionFrm->GetSection();
260 : :
261 [ - + ]: 60 : if ( pNextSectionFrm )
262 : 0 : pNextSection = pNextSectionFrm->GetSection();
263 : :
264 [ - + ]: 60 : if ( pThisSection != pNextSection )
265 : 0 : bKeep = sal_False;
266 : : }
267 : :
268 [ + - ]: 168 : if ( bKeep )
269 : : {
270 : 168 : const SwAttrSet* pSet = NULL;
271 : :
272 [ - + ]: 168 : if ( pNxt->IsInTab() )
273 : : {
274 : 0 : SwTabFrm* pTab = pNxt->FindTabFrm();
275 [ # # ][ # # ]: 0 : if ( ! rThis.IsInTab() || rThis.FindTabFrm() != pTab )
[ # # ]
276 : 0 : pSet = &pTab->GetFmt()->GetAttrSet();
277 : : }
278 : :
279 [ + - ]: 168 : if ( ! pSet )
280 : 168 : pSet = pNxt->GetAttrSet();
281 : :
282 : : OSL_ENSURE( pSet, "No AttrSet to check keep attribute" );
283 : :
284 [ - + ]: 168 : if ( pSet->GetPageDesc().GetPageDesc() )
285 : 0 : bKeep = sal_False;
286 [ - + ]: 168 : else switch ( pSet->GetBreak().GetBreak() )
287 : : {
288 : : case SVX_BREAK_COLUMN_BEFORE:
289 : : case SVX_BREAK_COLUMN_BOTH:
290 : : case SVX_BREAK_PAGE_BEFORE:
291 : : case SVX_BREAK_PAGE_BOTH:
292 : 0 : bKeep = sal_False;
293 : 168 : default: break;
294 : : }
295 : : }
296 : : }
297 : : }
298 : : }
299 : 23778 : return bKeep;
300 : : }
301 : :
302 : : /*************************************************************************
303 : : |*
304 : : |* SwFlowFrm::BwdMoveNecessary()
305 : : |*
306 : : |*************************************************************************/
307 : :
308 : :
309 : 180 : sal_uInt8 SwFlowFrm::BwdMoveNecessary( const SwPageFrm *pPage, const SwRect &rRect )
310 : : {
311 : : // The return value helps deciding whether we need to flow back (3),
312 : : // or whether we can use the good old WouldFit (0, 1), or if
313 : : // it's reasonable to relocate and test-format (2).
314 : : //
315 : : // Bit 1 in this case means that there are objects anchored to myself,
316 : : // bit 2 means that I have to evade other objects.
317 : :
318 : : // If a SurroundObj that desires to be wrapped around overlaps with the
319 : : // Rect, it's required to flow (because we can't guess the relationships).
320 : : // However it's possible for a test formatting to happen.
321 : : // If the SurroundObj is a Fly and I'm a Lower, or the Fly is a Lower of
322 : : // mine, then it doesn't matter.
323 : : // If the SurroundObj is anchored in a character bound Fly, and I'm not
324 : : // a Lower of that character bound Fly myself, then the Fly doesn't matter.
325 : :
326 : : // #32639# If the object is anchored with me, i can ignore it, because
327 : : // it's likely that it will follow me with the flow. A test formatting is
328 : : // not allowed in that case, however!
329 : 180 : sal_uInt8 nRet = 0;
330 : 180 : SwFlowFrm *pTmp = this;
331 [ - + ][ - + ]: 180 : do
[ + - ]
332 : : { // If there are objects hanging either on me or on a follow, we can't
333 : : // do a test formatting, because paragraph bound objects wouldn't
334 : : // be properly considered, and character bound objects shouldn't
335 : : // be test formatted at all.
336 [ - + ]: 180 : if( pTmp->GetFrm()->GetDrawObjs() )
337 : 0 : nRet = 1;
338 : 180 : pTmp = pTmp->GetFollow();
339 : : } while ( !nRet && pTmp );
340 [ + + ]: 180 : if ( pPage->GetSortedObjs() )
341 : : {
342 : : // #i28701# - new type <SwSortedObjs>
343 : 20 : const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
344 : 20 : sal_uLong nIndex = ULONG_MAX;
345 [ + - ][ + + ]: 80 : for ( sal_uInt16 i = 0; nRet < 3 && i < rObjs.Count(); ++i )
[ + + ]
346 : : {
347 : : // #i28701# - consider changed type of
348 : : // <SwSortedObjs> entries.
349 [ + - ]: 60 : SwAnchoredObject* pObj = rObjs[i];
350 [ + - ]: 60 : const SwFrmFmt& rFmt = pObj->GetFrmFmt();
351 [ + - ]: 60 : const SwRect aRect( pObj->GetObjRect() );
352 [ + - ]: 60 : if ( aRect.IsOver( rRect ) &&
[ - + # # ]
[ - + ]
353 [ # # ]: 0 : rFmt.GetSurround().GetSurround() != SURROUND_THROUGHT )
354 : : {
355 [ # # ][ # # ]: 0 : if( rThis.IsLayoutFrm() && //Fly Lower of This?
[ # # ]
356 [ # # ][ # # ]: 0 : Is_Lower_Of( &rThis, pObj->GetDrawObj() ) )
357 : 0 : continue;
358 [ # # ][ # # ]: 0 : if( pObj->ISA(SwFlyFrm) )
[ # # ]
359 : : {
360 [ # # ]: 0 : const SwFlyFrm *pFly = static_cast<const SwFlyFrm*>(pObj);
361 [ # # ][ # # ]: 0 : if ( pFly->IsAnLower( &rThis ) )//This Lower of Fly?
362 : 0 : continue;
363 : : }
364 : :
365 [ # # ]: 0 : const SwFrm* pAnchor = pObj->GetAnchorFrm();
366 [ # # ]: 0 : if ( pAnchor == &rThis )
367 : : {
368 : 0 : nRet |= 1;
369 : 0 : continue;
370 : : }
371 : :
372 : : // Don't do this if the object is anchored behind me in the text
373 : : // flow, because then I wouldn't evade it.
374 [ # # ][ # # ]: 0 : if ( ::IsFrmInSameKontext( pAnchor, &rThis ) )
375 : : {
376 [ # # ][ # # ]: 0 : if ( rFmt.GetAnchor().GetAnchorId() == FLY_AT_PARA )
377 : : {
378 : : // The index of the other one can be retrieved using the anchor attribute.
379 [ # # ][ # # ]: 0 : sal_uLong nTmpIndex = rFmt.GetAnchor().GetCntntAnchor()->nNode.GetIndex();
380 : : // Now we're going to check whether the current paragraph before
381 : : // the anchor of the displacing object sits in the text. If this
382 : : // is the case, we don't try to evade it.
383 : : // The index is being determined via SwFmtAnchor, because it's
384 : : // getting quite expensive otherwise.
385 [ # # ]: 0 : if( ULONG_MAX == nIndex )
386 : : {
387 : : const SwNode *pNode;
388 [ # # ]: 0 : if ( rThis.IsCntntFrm() )
389 [ # # ]: 0 : pNode = ((SwCntntFrm&)rThis).GetNode();
390 [ # # ]: 0 : else if( rThis.IsSctFrm() )
391 : : pNode = ((SwSectionFmt*)((SwSectionFrm&)rThis).
392 [ # # ][ # # ]: 0 : GetFmt())->GetSectionNode();
393 : : else
394 : : {
395 : : OSL_ENSURE( rThis.IsTabFrm(), "new FowFrm?" );
396 : : pNode = ((SwTabFrm&)rThis).GetTable()->
397 [ # # ][ # # ]: 0 : GetTabSortBoxes()[0]->GetSttNd()->FindTableNode();
398 : : }
399 : 0 : nIndex = pNode->GetIndex();
400 : : }
401 [ # # ]: 0 : if( nIndex < nTmpIndex )
402 : 0 : continue;
403 : : }
404 : : }
405 : : else
406 : 0 : continue;
407 : :
408 : 60 : nRet |= 2;
409 : : }
410 : : }
411 : : }
412 : 180 : return nRet;
413 : : }
414 : :
415 : : /*************************************************************************
416 : : |*
417 : : |* SwFlowFrm::CutTree(), PasteTree(), MoveSubTree()
418 : : |*
419 : : |* Description A specialized form of Cut() and Paste(), which
420 : : |* relocates a whole chain (this and the following, in particular).
421 : : |* During this process, only the minimum operations and notifications
422 : : |* are done.
423 : : |*
424 : : |*************************************************************************/
425 : :
426 : :
427 : 172 : SwLayoutFrm *SwFlowFrm::CutTree( SwFrm *pStart )
428 : : {
429 : : // Cut the Start and all the neighbours; they are chained together and
430 : : // a handle to the first one is returned. Residuals are invalidated
431 : : // as appropriate.
432 : :
433 : 172 : SwLayoutFrm *pLay = pStart->GetUpper();
434 [ - + ]: 172 : if ( pLay->IsInFtn() )
435 : 0 : pLay = pLay->FindFtnFrm();
436 : :
437 : : // #i58846#
438 : : // <pPrepare( PREP_QUOVADIS )> only for frames in footnotes
439 [ - + ]: 172 : if( pStart->IsInFtn() )
440 : : {
441 : 0 : SwFrm* pTmp = pStart->GetIndPrev();
442 [ # # ]: 0 : if( pTmp )
443 : 0 : pTmp->Prepare( PREP_QUOVADIS );
444 : : }
445 : :
446 : : // Just cut quickly and take care that we don't cause problems with the
447 : : // left-behinds. The pointers of the chain being cut can point who-knows where.
448 [ + + ]: 172 : if ( pStart == pStart->GetUpper()->Lower() )
449 : 76 : pStart->GetUpper()->pLower = 0;
450 [ + + ]: 172 : if ( pStart->GetPrev() )
451 : : {
452 : 96 : pStart->GetPrev()->pNext = 0;
453 : 96 : pStart->pPrev = 0;
454 : : }
455 : :
456 [ - + ]: 172 : if ( pLay->IsFtnFrm() )
457 : : {
458 [ # # ]: 0 : if ( !pLay->Lower() && !pLay->IsColLocked() &&
[ # # # # ]
[ # # ]
459 : 0 : !((SwFtnFrm*)pLay)->IsBackMoveLocked() )
460 : : {
461 : 0 : pLay->Cut();
462 [ # # ]: 0 : delete pLay;
463 : : }
464 : : else
465 : : {
466 : 0 : sal_Bool bUnlock = !((SwFtnFrm*)pLay)->IsBackMoveLocked();
467 : 0 : ((SwFtnFrm*)pLay)->LockBackMove();
468 : 0 : pLay->InvalidateSize();
469 : 0 : pLay->Calc();
470 : 0 : SwCntntFrm *pCnt = pLay->ContainsCntnt();
471 [ # # ][ # # ]: 0 : while ( pCnt && pLay->IsAnLower( pCnt ) )
[ # # ]
472 : : {
473 : : // It's possible for the CntFrm to be locked, and we don't want
474 : : // to end up in an endless page migration, so we're not even
475 : : // going to call Calc!
476 : : OSL_ENSURE( pCnt->IsTxtFrm(), "The Graphic has landed." );
477 [ # # # # ]: 0 : if ( ((SwTxtFrm*)pCnt)->IsLocked() ||
[ # # ]
478 : 0 : ((SwTxtFrm*)pCnt)->GetFollow() == pStart )
479 : 0 : break;
480 : 0 : pCnt->Calc();
481 : 0 : pCnt = pCnt->GetNextCntntFrm();
482 : : }
483 [ # # ]: 0 : if( bUnlock )
484 : 0 : ((SwFtnFrm*)pLay)->UnlockBackMove();
485 : : }
486 : 0 : pLay = 0;
487 : : }
488 : 172 : return pLay;
489 : : }
490 : :
491 : :
492 : :
493 : 172 : sal_Bool SwFlowFrm::PasteTree( SwFrm *pStart, SwLayoutFrm *pParent, SwFrm *pSibling,
494 : : SwFrm *pOldParent )
495 : : {
496 : : //returns sal_True if there's a LayoutFrm in the chain.
497 : 172 : sal_Bool bRet = sal_False;
498 : :
499 : : // The chain beginning with pStart is inserted before pSibling
500 : : // under the parent. We take care to invalidate as required.
501 : :
502 : : // I'm receiving a finished chain. We need to update the pointers for
503 : : // the beginning of the chain, then all the uppers and finally the end.
504 : : // On the way there, we invalidate as required.
505 [ + + ]: 172 : if ( pSibling )
506 : : {
507 [ - + ]: 61 : if ( 0 != (pStart->pPrev = pSibling->GetPrev()) )
508 : 0 : pStart->GetPrev()->pNext = pStart;
509 : : else
510 : 61 : pParent->pLower = pStart;
511 : 61 : pSibling->_InvalidatePos();
512 : 61 : pSibling->_InvalidatePrt();
513 : : }
514 : : else
515 : : {
516 [ + + ]: 111 : if ( 0 == (pStart->pPrev = pParent->Lower()) )
517 : 109 : pParent->pLower = pStart;
518 : : else
519 : : //Modified for #i100782#,04/03/2009
520 : : //If the pParent has more than 1 child nodes, former design will
521 : : //ignore them directly without any collection work. It will make some
522 : : //dangling pointers. This lead the crash...
523 : : //The new design will find the last child of pParent in loop way, and
524 : : //add the pStart after the last child.
525 : : // pParent->Lower()->pNext = pStart;
526 : : {
527 : 2 : SwFrm* pTemp = pParent->pLower;
528 [ + - ]: 2 : while (pTemp)
529 : : {
530 [ - + ]: 2 : if (pTemp->pNext)
531 : 0 : pTemp = pTemp->pNext;
532 : : else
533 : : {
534 : 2 : pStart->pPrev = pTemp;
535 : 2 : pTemp->pNext = pStart;
536 : 2 : break;
537 : : }
538 : : }
539 : : }
540 : : //End modification for #i100782#,04/03/2009
541 : :
542 : : // #i27145#
543 [ + + ]: 111 : if ( pParent->IsSctFrm() )
544 : : {
545 : : // We have no sibling because pParent is a section frame and
546 : : // has just been created to contain some content. The printing
547 : : // area of the frame behind pParent has to be invalidated, so
548 : : // that the correct distance between pParent and the next frame
549 : : // can be calculated.
550 : 3 : pParent->InvalidateNextPrtArea();
551 : : }
552 : : }
553 : 172 : SwFrm *pFloat = pStart;
554 : 172 : SwFrm *pLst = 0;
555 [ - + ][ # # ]: 172 : SWRECTFN( pParent )
[ # # ][ - + ]
556 : 172 : SwTwips nGrowVal = 0;
557 [ + + ]: 242 : do
558 : 242 : { pFloat->pUpper = pParent;
559 : 242 : pFloat->_InvalidateAll();
560 : 242 : pFloat->CheckDirChange();
561 : :
562 : : // I'm a friend of the TxtFrm and thus am allowed to do many things.
563 : : // The CacheIdx idea seems to be a bit risky!
564 [ + + ]: 242 : if ( pFloat->IsTxtFrm() )
565 : : {
566 [ + + ]: 212 : if ( ((SwTxtFrm*)pFloat)->GetCacheIdx() != USHRT_MAX )
567 : 39 : ((SwTxtFrm*)pFloat)->Init(); // I'm his friend.
568 : : }
569 : : else
570 : 30 : bRet = sal_True;
571 : :
572 [ + - ]: 242 : nGrowVal += (pFloat->Frm().*fnRect->fnGetHeight)();
573 [ + + ]: 242 : if ( pFloat->GetNext() )
574 : 70 : pFloat = pFloat->GetNext();
575 : : else
576 : : {
577 : 172 : pLst = pFloat;
578 : 172 : pFloat = 0;
579 : : }
580 : : } while ( pFloat );
581 : :
582 [ + + ]: 172 : if ( pSibling )
583 : : {
584 : 61 : pLst->pNext = pSibling;
585 : 61 : pSibling->pPrev = pLst;
586 [ - + ]: 61 : if( pSibling->IsInFtn() )
587 : : {
588 [ # # ]: 0 : if( pSibling->IsSctFrm() )
589 : 0 : pSibling = ((SwSectionFrm*)pSibling)->ContainsAny();
590 [ # # ]: 0 : if( pSibling )
591 : 0 : pSibling->Prepare( PREP_ERGOSUM );
592 : : }
593 : : }
594 [ + + ]: 172 : if ( nGrowVal )
595 : : {
596 [ + - ][ + + ]: 115 : if ( pOldParent && pOldParent->IsBodyFrm() ) // For variable page height while browsing
[ + + ]
597 : 112 : pOldParent->Shrink( nGrowVal );
598 : 115 : pParent->Grow( nGrowVal );
599 : : }
600 : :
601 [ - + ]: 172 : if ( pParent->IsFtnFrm() )
602 : 0 : ((SwFtnFrm*)pParent)->InvalidateNxtFtnCnts( pParent->FindPageFrm() );
603 : 172 : return bRet;
604 : : }
605 : :
606 : :
607 : :
608 : 172 : void SwFlowFrm::MoveSubTree( SwLayoutFrm* pParent, SwFrm* pSibling )
609 : : {
610 : : OSL_ENSURE( pParent, "No parent given." );
611 : : OSL_ENSURE( rThis.GetUpper(), "Where are we coming from?" );
612 : :
613 : : // Be economical with notifications if an action is running.
614 : 172 : ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
615 [ + - ]: 172 : const SwViewImp *pImp = pSh ? pSh->Imp() : 0;
616 [ + - ][ + - ]: 172 : const sal_Bool bComplete = pImp && pImp->IsAction() && pImp->GetLayAction().IsComplete();
[ + + ]
617 : :
618 [ + + ]: 172 : if ( !bComplete )
619 : : {
620 : 99 : SwFrm *pPre = rThis.GetIndPrev();
621 [ + - ]: 99 : if ( pPre )
622 : : {
623 : 99 : pPre->SetRetouche();
624 : : // #115759# - follow-up of #i26250#
625 : : // invalidate printing area of previous frame, if it's in a table
626 [ - + ]: 99 : if ( pPre->GetUpper()->IsInTab() )
627 : : {
628 : 0 : pPre->_InvalidatePrt();
629 : : }
630 : 99 : pPre->InvalidatePage();
631 : : }
632 : : else
633 : 0 : { rThis.GetUpper()->SetCompletePaint();
634 : 0 : rThis.GetUpper()->InvalidatePage();
635 : : }
636 : : }
637 : :
638 : 172 : SwPageFrm *pOldPage = rThis.FindPageFrm();
639 : :
640 : 172 : SwLayoutFrm *pOldParent = CutTree( &rThis );
641 : 172 : const sal_Bool bInvaLay = PasteTree( &rThis, pParent, pSibling, pOldParent );
642 : :
643 : : // If, by cutting & pasting, an empty SectionFrm came into existence, it should
644 : : // disappear automatically.
645 : : SwSectionFrm *pSct;
646 : : // #126020# - adjust check for empty section
647 : : // #130797# - correct fix #126020#
648 [ + + + - ]: 350 : if ( pOldParent && !pOldParent->Lower() &&
[ + + + - ]
[ + + ][ + - ]
649 : 76 : ( pOldParent->IsInSct() &&
650 : 76 : !(pSct = pOldParent->FindSctFrm())->ContainsCntnt() &&
651 : 26 : !pSct->ContainsAny( true ) ) )
652 : : {
653 : 26 : pSct->DelEmpty( sal_False );
654 : : }
655 : :
656 : : // If we're in a column section, we'd rather not call Calc "from below"
657 [ + + - + : 263 : if( !rThis.IsInSct() &&
# # # # ]
[ + + ]
658 : 91 : ( !rThis.IsInTab() || ( rThis.IsTabFrm() && !rThis.GetUpper()->IsInTab() ) ) )
659 : 91 : rThis.GetUpper()->Calc();
660 [ + + ]: 81 : else if( rThis.GetUpper()->IsSctFrm() )
661 : : {
662 : 3 : SwSectionFrm* pTmpSct = (SwSectionFrm*)rThis.GetUpper();
663 : 3 : sal_Bool bOld = pTmpSct->IsCntntLocked();
664 : 3 : pTmpSct->SetCntntLock( sal_True );
665 : 3 : pTmpSct->Calc();
666 [ + - ]: 3 : if( !bOld )
667 : 3 : pTmpSct->SetCntntLock( sal_False );
668 : : }
669 : 172 : SwPageFrm *pPage = rThis.FindPageFrm();
670 : :
671 [ + + ]: 172 : if ( pOldPage != pPage )
672 : : {
673 : 116 : rThis.InvalidatePage( pPage );
674 [ + + ]: 116 : if ( rThis.IsLayoutFrm() )
675 : : {
676 : 2 : SwCntntFrm *pCnt = ((SwLayoutFrm*)&rThis)->ContainsCntnt();
677 [ + - ]: 2 : if ( pCnt )
678 : 2 : pCnt->InvalidatePage( pPage );
679 : : }
680 [ + - ]: 114 : else if ( pSh && pSh->GetDoc()->GetLineNumberInfo().IsRestartEachPage()
[ - + # # ]
[ - + ]
681 : 0 : && pPage->FindFirstBodyCntnt() == &rThis )
682 : : {
683 : 0 : rThis._InvalidateLineNum();
684 : : }
685 : : }
686 [ + + ][ + + ]: 172 : if ( bInvaLay || (pSibling && pSibling->IsLayoutFrm()) )
[ - + ][ + + ]
687 : 2 : rThis.GetUpper()->InvalidatePage( pPage );
688 : 172 : }
689 : :
690 : : /*************************************************************************
691 : : |*
692 : : |* SwFlowFrm::IsAnFollow()
693 : : |*
694 : : |*************************************************************************/
695 : :
696 : :
697 : 621 : sal_Bool SwFlowFrm::IsAnFollow( const SwFlowFrm *pAssumed ) const
698 : : {
699 : 621 : const SwFlowFrm *pFoll = this;
700 [ - + ]: 619 : do
701 [ + + ]: 621 : { if ( pAssumed == pFoll )
702 : 2 : return sal_True;
703 : 619 : pFoll = pFoll->GetFollow();
704 : : } while ( pFoll );
705 : 621 : return sal_False;
706 : : }
707 : :
708 : :
709 : : /*************************************************************************
710 : : |*
711 : : |* SwFlowFrm::FindMaster()
712 : : |*
713 : : |*************************************************************************/
714 : :
715 : 39861 : SwTxtFrm* SwCntntFrm::FindMaster() const
716 : : {
717 : : OSL_ENSURE( IsFollow(), "SwCntntFrm::FindMaster(): !IsFollow" );
718 : :
719 : 39861 : const SwCntntFrm* pPrec = GetPrecede();
720 : :
721 [ + - ][ + - ]: 39861 : if ( pPrec && pPrec->HasFollow() && pPrec->GetFollow() == this )
[ + - ][ + - ]
722 : : {
723 : : OSL_ENSURE( pPrec->IsTxtFrm(), "NoTxtFrm with follow found" );
724 : 39861 : return ( SwTxtFrm* )pPrec;
725 : : }
726 : :
727 : : OSL_FAIL( "Follow ist lost in Space." );
728 : 39861 : return 0;
729 : : }
730 : :
731 : 42 : SwSectionFrm* SwSectionFrm::FindMaster() const
732 : : {
733 : : OSL_ENSURE( IsFollow(), "SwSectionFrm::FindMaster(): !IsFollow" );
734 : :
735 [ + - ]: 42 : SwIterator<SwSectionFrm,SwFmt> aIter( *pSection->GetFmt() );
736 [ + - ]: 42 : SwSectionFrm* pSect = aIter.First();
737 [ + - ]: 140 : while ( pSect )
738 : : {
739 [ + + ]: 140 : if( pSect->GetFollow() == this )
740 : 42 : return pSect;
741 [ + - ]: 98 : pSect = aIter.Next();
742 : : }
743 : :
744 : : OSL_FAIL( "Follow ist lost in Space." );
745 [ + - ]: 42 : return 0;
746 : : }
747 : :
748 : 0 : SwTabFrm* SwTabFrm::FindMaster( bool bFirstMaster ) const
749 : : {
750 : : OSL_ENSURE( IsFollow(), "SwTabFrm::FindMaster(): !IsFollow" );
751 : :
752 [ # # ]: 0 : SwIterator<SwTabFrm,SwFmt> aIter( *GetTable()->GetFrmFmt() );
753 [ # # ]: 0 : SwTabFrm* pTab = aIter.First();
754 [ # # ]: 0 : while ( pTab )
755 : : {
756 [ # # ]: 0 : if ( bFirstMaster )
757 : : {
758 : : //
759 : : // Optimization. This makes code like this obsolete:
760 : : // while ( pTab->IsFollow() )
761 : : // pTab = pTab->FindMaster();
762 : : //
763 [ # # ]: 0 : if ( !pTab->IsFollow() )
764 : : {
765 : 0 : SwTabFrm* pNxt = pTab;
766 [ # # ]: 0 : while ( pNxt )
767 : : {
768 [ # # ]: 0 : if ( pNxt->GetFollow() == this )
769 : 0 : return pTab;
770 : 0 : pNxt = pNxt->GetFollow();
771 : : }
772 : : }
773 : : }
774 : : else
775 : : {
776 [ # # ]: 0 : if ( pTab->GetFollow() == this )
777 : 0 : return pTab;
778 : : }
779 : :
780 [ # # ]: 0 : pTab = aIter.Next();
781 : : }
782 : :
783 : : OSL_FAIL( "Follow ist lost in Space." );
784 [ # # ]: 0 : return 0;
785 : : }
786 : :
787 : : /*************************************************************************
788 : : |*
789 : : |* SwFrm::GetLeaf()
790 : : |*
791 : : |* Description Returns the next/previous Layout leaf that's NOT below
792 : : |* this (or even is this itself). Also, that leaf must be in the same
793 : : |* text flow as the pAnch origin frm (Body, Ftn)
794 : : |*
795 : : |*************************************************************************/
796 : :
797 : :
798 : 0 : const SwLayoutFrm *SwFrm::GetLeaf( MakePageType eMakePage, sal_Bool bFwd,
799 : : const SwFrm *pAnch ) const
800 : : {
801 : : // No flow, no joy...
802 [ # # ][ # # ]: 0 : if ( !(IsInDocBody() || IsInFtn() || IsInFly()) )
[ # # ][ # # ]
803 : 0 : return 0;
804 : :
805 : 0 : const SwFrm *pLeaf = this;
806 : 0 : sal_Bool bFound = sal_False;
807 : :
808 [ # # ][ # # ]: 0 : do
[ # # ]
809 : 0 : { pLeaf = ((SwFrm*)pLeaf)->GetLeaf( eMakePage, bFwd );
810 : :
811 [ # # ][ # # : 0 : if ( pLeaf &&
# # # # ]
812 : 0 : (!IsLayoutFrm() || !((SwLayoutFrm*)this)->IsAnLower( pLeaf )))
813 : : {
814 [ # # # # ]: 0 : if ( pAnch->IsInDocBody() == pLeaf->IsInDocBody() &&
[ # # ]
815 : 0 : pAnch->IsInFtn() == pLeaf->IsInFtn() )
816 : : {
817 : 0 : bFound = sal_True;
818 : : }
819 : : }
820 : : } while ( !bFound && pLeaf );
821 : :
822 : 0 : return (const SwLayoutFrm*)pLeaf;
823 : : }
824 : :
825 : : /*************************************************************************
826 : : |*
827 : : |* SwFrm::GetLeaf()
828 : : |*
829 : : |* Description calls Get[Next|Prev]Leaf
830 : : |*
831 : : |*************************************************************************/
832 : :
833 : :
834 : 12791 : SwLayoutFrm *SwFrm::GetLeaf( MakePageType eMakePage, sal_Bool bFwd )
835 : : {
836 [ + + ]: 12791 : if ( IsInFtn() )
837 [ - + ]: 37 : return bFwd ? GetNextFtnLeaf( eMakePage ) : GetPrevFtnLeaf( eMakePage );
838 : :
839 : : // #i53323#
840 : : // A frame could be inside a table AND inside a section.
841 : : // Thus, it has to be determined, which is the first parent.
842 : 12754 : bool bInTab( IsInTab() );
843 : 12754 : bool bInSct( IsInSct() );
844 [ - + ][ + + ]: 12754 : if ( bInTab && bInSct )
845 : : {
846 : 0 : const SwFrm* pUpperFrm( GetUpper() );
847 [ # # ]: 0 : while ( pUpperFrm )
848 : : {
849 [ # # ]: 0 : if ( pUpperFrm->IsTabFrm() )
850 : : {
851 : : // the table is the first.
852 : 0 : bInSct = false;
853 : 0 : break;
854 : : }
855 [ # # ]: 0 : else if ( pUpperFrm->IsSctFrm() )
856 : : {
857 : : // the section is the first.
858 : 0 : bInTab = false;
859 : 0 : break;
860 : : }
861 : :
862 : 0 : pUpperFrm = pUpperFrm->GetUpper();
863 : : }
864 : : }
865 : :
866 [ + + ][ + - ]: 12754 : if ( bInTab && ( !IsTabFrm() || GetUpper()->IsCellFrm() ) ) // TABLE IN TABLE
[ - + ][ - + ]
867 [ # # ]: 0 : return bFwd ? GetNextCellLeaf( eMakePage ) : GetPrevCellLeaf( eMakePage );
868 : :
869 [ + + ]: 12754 : if ( bInSct )
870 [ + + ]: 361 : return bFwd ? GetNextSctLeaf( eMakePage ) : GetPrevSctLeaf( eMakePage );
871 : :
872 [ + + ]: 12791 : return bFwd ? GetNextLeaf( eMakePage ) : GetPrevLeaf( eMakePage );
873 : : }
874 : :
875 : :
876 : :
877 : 117 : sal_Bool SwFrm::WrongPageDesc( SwPageFrm* pNew )
878 : : {
879 : : // Now it's getting a bit complicated:
880 : : //
881 : : // Maybe i'm bringing a Pagedesc myself; in that case,
882 : : // the pagedesc of the next page needs to correspond.
883 : : // Otherwise, I'll have to dig a bit deeper to see where
884 : : // the following Pagedesc is coming from.
885 : : // If the following page itself tells me that it's pagedesc
886 : : // is wrong, I can happily exchange it.
887 : : // If the page however thinks that it's pagedesc is correct,
888 : : // this doesn't mean it's useful to me:
889 : : // If the first BodyCntnt asks for a PageDesc or a PageBreak,
890 : : // I'll have to insert a new page - except the desired page is
891 : : // the correct one.
892 : : // If I inserted a new page, the problems only get started:
893 : : // because then it's likely for the next page to have been
894 : : // wrong and having been swapped because of that.
895 : : // This in turn means that I have a new (and correct) page,
896 : : // but the conditions to swap still apply.
897 : : // Way out of the situation: Try to preliminarily insert a
898 : : // new page once (empty pages are already inserted by InsertPage()
899 : : // if required)
900 : 117 : const SwFmtPageDesc &rFmtDesc = GetAttrSet()->GetPageDesc();
901 : :
902 : : //My Pagedesc doesn't count if I'm a follow!
903 : 117 : SwPageDesc *pDesc = 0;
904 : 117 : sal_uInt16 nTmp = 0;
905 : 117 : SwFlowFrm *pFlow = SwFlowFrm::CastFlowFrm( this );
906 [ + + ][ + + ]: 117 : if ( !pFlow || !pFlow->IsFollow() )
[ + - ]
907 : : {
908 : 54 : pDesc = (SwPageDesc*)rFmtDesc.GetPageDesc();
909 [ - + ]: 54 : if( pDesc )
910 : : {
911 [ # # ]: 0 : if( !pDesc->GetRightFmt() )
912 : 0 : nTmp = 2;
913 [ # # ]: 0 : else if( !pDesc->GetLeftFmt() )
914 : 0 : nTmp = 1;
915 [ # # ]: 0 : else if( rFmtDesc.GetNumOffset() )
916 : 0 : nTmp = rFmtDesc.GetNumOffset();
917 : : }
918 : : }
919 : :
920 : : // Does the Cntnt bring a Pagedesc or do we need the
921 : : // virtual page number of the new layout leaf?
922 : : // PageDesc isn't allowed with Follows
923 : : const sal_Bool bOdd = nTmp ? ( nTmp % 2 ? sal_True : sal_False )
924 [ - + ]: 117 : : pNew->OnRightPage();
925 [ + - ]: 117 : if ( !pDesc )
926 : 117 : pDesc = pNew->FindPageDesc();
927 : :
928 : 117 : bool bFirst = pNew->OnFirstPage();
929 : :
930 [ + + ]: 117 : const SwFlowFrm *pNewFlow = pNew->FindFirstBodyCntnt();
931 : : // Did we find ourselves?
932 [ - + ]: 117 : if( pNewFlow == pFlow )
933 : 0 : pNewFlow = NULL;
934 [ + + ][ - + ]: 117 : if ( pNewFlow && pNewFlow->GetFrm()->IsInTab() )
[ - + ]
935 [ # # ]: 0 : pNewFlow = pNewFlow->GetFrm()->FindTabFrm();
936 : 88 : const SwPageDesc *pNewDesc= ( pNewFlow && !pNewFlow->IsFollow() )
937 [ + + + + ]: 205 : ? pNewFlow->GetFrm()->GetAttrSet()->GetPageDesc().GetPageDesc():0;
938 : :
939 : 117 : return ( pNew->GetPageDesc() != pDesc || // own desc ?
940 : 117 : pNew->GetFmt() != (bFirst ? pDesc->GetFirstFmt() : (bOdd ? pDesc->GetRightFmt() : pDesc->GetLeftFmt())) ||
941 [ + + ][ + - ]: 234 : ( pNewDesc && pNewDesc == pDesc ) );
[ + + ][ + - ]
[ + - + + ]
942 : : }
943 : :
944 : :
945 : : /*************************************************************************
946 : : |*
947 : : |* SwFrm::GetNextLeaf()
948 : : |*
949 : : |* Description Returns the next layout leaf in which we can move
950 : : |* the frame.
951 : : |*
952 : : |*************************************************************************/
953 : :
954 : 91 : SwLayoutFrm *SwFrm::GetNextLeaf( MakePageType eMakePage )
955 : : {
956 : : OSL_ENSURE( !IsInFtn(), "GetNextLeaf(), don't call me for Ftn." );
957 : : OSL_ENSURE( !IsInSct(), "GetNextLeaf(), don't call me for Sections." );
958 : :
959 : 91 : const sal_Bool bBody = IsInDocBody(); // If I'm coming from the DocBody,
960 : : // I want to end up in the body.
961 : :
962 : : // It doesn't make sense to insert pages, as we only want to search the
963 : : // chain.
964 [ - + ]: 91 : if( IsInFly() )
965 : 0 : eMakePage = MAKEPAGE_NONE;
966 : :
967 : : // For tables, we just take the big leap. A simple GetNext would
968 : : // iterate through the first cells and, in turn, all other cells.
969 : 91 : SwLayoutFrm *pLayLeaf = 0;
970 [ - + ]: 91 : if ( IsTabFrm() )
971 : : {
972 : 0 : SwCntntFrm* pTmp = ((SwTabFrm*)this)->FindLastCntnt();
973 [ # # ]: 0 : if ( pTmp )
974 : 0 : pLayLeaf = pTmp->GetUpper();
975 : : }
976 [ + - ]: 91 : if ( !pLayLeaf )
977 : 91 : pLayLeaf = GetNextLayoutLeaf();
978 : :
979 : 91 : SwLayoutFrm *pOldLayLeaf = 0; // Make sure that we don't have to
980 : : // start searching from top when we
981 : : // have a freshly created page.
982 : 91 : sal_Bool bNewPg = sal_False; // Only insert a new page once.
983 : :
984 : 22 : while ( sal_True )
985 : : {
986 [ + + ]: 113 : if ( pLayLeaf )
987 : : {
988 : : // There's yet another LayoutFrm. Let's see if it's ready to host
989 : : // me as well.
990 : : // It only needs to be of the same kind like my starting point
991 : : // (DocBody or Footnote respectively)
992 [ - + ]: 91 : if ( pLayLeaf->FindPageFrm()->IsFtnPage() )
993 : : { // If I ended up at the end note pages, we're done.
994 : 0 : pLayLeaf = 0;
995 : 0 : continue;
996 : : }
997 [ + - ][ + - ]: 182 : if ( (bBody && !pLayLeaf->IsInDocBody()) || pLayLeaf->IsInTab()
[ + - - + ]
[ - + ]
998 : 91 : || pLayLeaf->IsInSct() )
999 : : {
1000 : : // They don't want me! Try again
1001 : 0 : pOldLayLeaf = pLayLeaf;
1002 : 0 : pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
1003 : 0 : continue;
1004 : : }
1005 : :
1006 : : // I'm wanted, therefore I'm done. However, it may still be that,
1007 : : // during a page break, the page type isn't the desired one. In that
1008 : : // case we have to insert a page of the correct type.
1009 : :
1010 [ - + ][ # # ]: 91 : if( !IsFlowFrm() && ( eMakePage == MAKEPAGE_NONE ||
[ # # ][ # # ]
[ - + ]
1011 : : eMakePage==MAKEPAGE_APPEND || eMakePage==MAKEPAGE_NOSECTION ) )
1012 : 0 : return pLayLeaf;
1013 : :
1014 : 91 : SwPageFrm *pNew = pLayLeaf->FindPageFrm();
1015 : 91 : const ViewShell *pSh = getRootFrm()->GetCurrShell();
1016 : : // #111704# The pagedesc check does not make sense for frames in fly frames
1017 [ + - ][ + - ]: 176 : if ( pNew != FindPageFrm() && !bNewPg && !IsInFly() &&
[ + - ][ + + ]
[ + + ]
1018 : : // #i46683#
1019 : : // Do not consider page descriptions in browse mode (since
1020 : : // MoveBwd ignored them)
1021 [ + - ]: 85 : !(pSh && pSh->GetViewOptions()->getBrowseMode() ) )
1022 : : {
1023 [ - + ]: 85 : if( WrongPageDesc( pNew ) )
1024 : : {
1025 : 0 : SwFtnContFrm *pCont = pNew->FindFtnCont();
1026 [ # # ]: 0 : if( pCont )
1027 : : {
1028 : : // If the reference of the first footnote of this page
1029 : : // lies before the page, we'd rather not insert a new page.
1030 : : // (Bug #55620#)
1031 : 0 : SwFtnFrm *pFtn = (SwFtnFrm*)pCont->Lower();
1032 [ # # ][ # # ]: 0 : if( pFtn && pFtn->GetRef() )
[ # # ]
1033 : : {
1034 : 0 : const sal_uInt16 nRefNum = pNew->GetPhyPageNum();
1035 [ # # ]: 0 : if( pFtn->GetRef()->GetPhyPageNum() < nRefNum )
1036 : 0 : break;
1037 : : }
1038 : : }
1039 : : //Gotcha! The following page is wrong, therefore we need to
1040 : : //insert a new one.
1041 [ # # ]: 0 : if ( eMakePage == MAKEPAGE_INSERT )
1042 : : {
1043 : 0 : bNewPg = sal_True;
1044 : :
1045 : : SwPageFrm *pPg = pOldLayLeaf ?
1046 [ # # ]: 0 : pOldLayLeaf->FindPageFrm() : 0;
1047 [ # # ][ # # ]: 0 : if ( pPg && pPg->IsEmptyPage() )
[ # # ]
1048 : : // Don't insert behind. Insert before the EmptyPage.
1049 : 0 : pPg = (SwPageFrm*)pPg->GetPrev();
1050 : :
1051 [ # # ][ # # ]: 0 : if ( !pPg || pPg == pNew )
1052 : 0 : pPg = FindPageFrm();
1053 : :
1054 : 0 : InsertPage( pPg, sal_False );
1055 : 0 : pLayLeaf = GetNextLayoutLeaf();
1056 : 0 : pOldLayLeaf = 0;
1057 : 0 : continue;
1058 : : }
1059 : : else
1060 : 0 : pLayLeaf = 0;
1061 : : }
1062 : : }
1063 : 91 : break;
1064 : : }
1065 : : else
1066 : : {
1067 : : // There's no other matching LayoutFrm, so we have to insert
1068 : : // a new page.
1069 [ + - ][ + - ]: 22 : if ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT )
1070 : : {
1071 : : InsertPage(
1072 : 0 : pOldLayLeaf ? pOldLayLeaf->FindPageFrm() : FindPageFrm(),
1073 [ - + ]: 22 : sal_False );
1074 : :
1075 : : // And again from the start.
1076 [ + - ]: 22 : pLayLeaf = pOldLayLeaf ? pOldLayLeaf : GetNextLayoutLeaf();
1077 : : }
1078 : : else
1079 : 0 : break;
1080 : : }
1081 : : }
1082 : 91 : return pLayLeaf;
1083 : : }
1084 : :
1085 : : /*************************************************************************
1086 : : |*
1087 : : |* SwFrm::GetPrevLeaf()
1088 : : |*
1089 : : |* Beschreibung Returns the previous layout leaf where we can move
1090 : : |* the frame.
1091 : : |*
1092 : : |*************************************************************************/
1093 : :
1094 : :
1095 : 12302 : SwLayoutFrm *SwFrm::GetPrevLeaf( MakePageType )
1096 : : {
1097 : : OSL_ENSURE( !IsInFtn(), "GetPrevLeaf(), don't call me for Ftn." );
1098 : :
1099 : 12302 : const sal_Bool bBody = IsInDocBody(); // If I'm coming from the DocBody,
1100 : : // I want to end up in the body.
1101 : 12302 : const sal_Bool bFly = IsInFly();
1102 : :
1103 : 12302 : SwLayoutFrm *pLayLeaf = GetPrevLayoutLeaf();
1104 : 12302 : SwLayoutFrm *pPrevLeaf = 0;
1105 : :
1106 [ + + ]: 12417 : while ( pLayLeaf )
1107 : : {
1108 [ + - + + ]: 4142 : if ( pLayLeaf->IsInTab() || // Never go into tables.
[ + + ]
1109 : 2071 : pLayLeaf->IsInSct() ) // Same goes for sections!
1110 : 56 : pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1111 [ + - ][ + + ]: 2015 : else if ( bBody && pLayLeaf->IsInDocBody() )
[ + + ]
1112 : : {
1113 [ + + ]: 1958 : if ( pLayLeaf->Lower() )
1114 : 1956 : break;
1115 : 2 : pPrevLeaf = pLayLeaf;
1116 : 2 : pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1117 [ + - ]: 2 : if ( pLayLeaf )
1118 : 2 : SwFlowFrm::SetMoveBwdJump( sal_True );
1119 : : }
1120 [ - + ]: 57 : else if ( bFly )
1121 : 0 : break; //Cntnts in Flys should accept any layout leaf.
1122 : : else
1123 : 57 : pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1124 : : }
1125 [ + + ]: 12302 : return pLayLeaf ? pLayLeaf : pPrevLeaf;
1126 : : }
1127 : :
1128 : : /*************************************************************************
1129 : : |*
1130 : : |* SwFlowFrm::IsPrevObjMove()
1131 : : |*
1132 : : |*************************************************************************/
1133 : :
1134 : :
1135 : 8094 : sal_Bool SwFlowFrm::IsPrevObjMove() const
1136 : : {
1137 : : //sal_True The FlowFrm must respect the a border of the predecessor, also needs
1138 : : // to insert a break if required.
1139 : :
1140 : : //!!!!!!!!!!!Hack!!!!!!!!!!!
1141 : 8094 : const ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
1142 [ - + ][ - + ]: 8094 : if( pSh && pSh->GetViewOptions()->getBrowseMode() )
[ + - ]
1143 : 0 : return sal_False;
1144 : :
1145 : 8094 : SwFrm *pPre = rThis.FindPrev();
1146 : :
1147 [ + + ][ + + ]: 8094 : if ( pPre && pPre->GetDrawObjs() )
[ + - ]
1148 : : {
1149 : : OSL_ENSURE( SwFlowFrm::CastFlowFrm( pPre ), "new flowfrm?" );
1150 [ - + ]: 437 : if( SwFlowFrm::CastFlowFrm( pPre )->IsAnFollow( this ) )
1151 : 0 : return sal_False;
1152 : 437 : SwLayoutFrm* pPreUp = pPre->GetUpper();
1153 : : // If the upper is a SectionFrm, or a column of a SectionFrm, we're
1154 : : // allowed to protrude out of it. However, we need to respect the
1155 : : // Upper of the SectionFrm.
1156 [ - + ]: 437 : if( pPreUp->IsInSct() )
1157 : : {
1158 [ # # ]: 0 : if( pPreUp->IsSctFrm() )
1159 : 0 : pPreUp = pPreUp->GetUpper();
1160 [ # # # # ]: 0 : else if( pPreUp->IsColBodyFrm() &&
[ # # ]
1161 : 0 : pPreUp->GetUpper()->GetUpper()->IsSctFrm() )
1162 : 0 : pPreUp = pPreUp->GetUpper()->GetUpper()->GetUpper();
1163 : : }
1164 : : // #i26945# - re-factoring
1165 : : // use <GetVertPosOrientFrm()> to determine, if object has followed the
1166 : : // text flow to the next layout frame
1167 [ + + ]: 874 : for ( sal_uInt16 i = 0; i < pPre->GetDrawObjs()->Count(); ++i )
1168 : : {
1169 : : // #i28701# - consider changed type of
1170 : : // <SwSortedObjs> entries.
1171 : 437 : const SwAnchoredObject* pObj = (*pPre->GetDrawObjs())[i];
1172 : : // OD 2004-01-20 #110582# - do not consider hidden objects
1173 : : // #i26945# - do not consider object, which
1174 : : // doesn't follow the text flow.
1175 [ + - - + ]: 1748 : if ( pObj->GetFrmFmt().GetDoc()->IsVisibleLayerId(
[ - + ][ + - ]
1176 [ + - ][ + - ]: 874 : pObj->GetDrawObj()->GetLayer() ) &&
[ + - ][ # # ]
[ + - ]
1177 [ + - ][ + - ]: 437 : pObj->GetFrmFmt().GetFollowTextFlow().GetValue() )
1178 : : {
1179 : 0 : const SwLayoutFrm* pVertPosOrientFrm = pObj->GetVertPosOrientFrm();
1180 [ # # # # ]: 0 : if ( pVertPosOrientFrm &&
[ # # ][ # # ]
1181 : : pPreUp != pVertPosOrientFrm &&
1182 : 0 : !pPreUp->IsAnLower( pVertPosOrientFrm ) )
1183 : : {
1184 : 0 : return sal_True;
1185 : : }
1186 : : }
1187 : : }
1188 : : }
1189 : 8094 : return sal_False;
1190 : : }
1191 : :
1192 : : /*************************************************************************
1193 : : |*
1194 : : |* sal_Bool SwFlowFrm::IsPageBreak()
1195 : : |*
1196 : : |* Description If there's a hard page break before the Frm AND there's a
1197 : : |* predecessor on the same page, sal_True is returned (we need to create a
1198 : : |* new PageBreak). Otherwise, returns sal_False.
1199 : : |* If bAct is set to sal_True, this function returns sal_True if
1200 : : |* there's a PageBreak.
1201 : : |* Of course, we don't evaluate the hard page break for follows.
1202 : : |* The page break is in it's own FrmFmt (BEFORE) or in the FrmFmt of the
1203 : : |* predecessor (AFTER). If there's no predecessor on the page, we don't
1204 : : |* need to think further.
1205 : : |* Also, a page break (or the need for one) is also present if
1206 : : |* the FrmFmt contains a PageDesc.
1207 : : |* The implementation works only on CntntFrms! - the definition
1208 : : |* of the predecessor is not clear for LayoutFrms.
1209 : : |*
1210 : : |*************************************************************************/
1211 : :
1212 : :
1213 : 39479 : sal_Bool SwFlowFrm::IsPageBreak( sal_Bool bAct ) const
1214 : : {
1215 [ + + ][ + + : 78713 : if ( !IsFollow() && rThis.IsInDocBody() &&
+ + + - +
- ][ + + ]
1216 : 39234 : ( !rThis.IsInTab() || ( rThis.IsTabFrm() && !rThis.GetUpper()->IsInTab() ) ) ) // i66968
1217 : : {
1218 : 34440 : const ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
1219 [ + + ][ + + ]: 34440 : if( pSh && pSh->GetViewOptions()->getBrowseMode() )
[ + - ]
1220 : 208 : return sal_False;
1221 : 34232 : const SwAttrSet *pSet = rThis.GetAttrSet();
1222 : :
1223 : : // Determine predecessor
1224 : 34232 : const SwFrm *pPrev = rThis.FindPrev();
1225 [ + + ][ + - : 50886 : while ( pPrev && ( !pPrev->IsInDocBody() ||
+ + - + ]
[ - + ]
1226 : 16654 : ( pPrev->IsTxtFrm() && ((SwTxtFrm*)pPrev)->IsHiddenNow() ) ) )
1227 : 0 : pPrev = pPrev->FindPrev();
1228 : :
1229 [ + + ]: 34232 : if ( pPrev )
1230 : : {
1231 : : OSL_ENSURE( pPrev->IsInDocBody(), "IsPageBreak: Not in DocBody?" );
1232 [ + + ]: 8537 : if ( bAct )
1233 [ + + ]: 535 : { if ( rThis.FindPageFrm() == pPrev->FindPageFrm() )
1234 : 140 : return sal_False;
1235 : : }
1236 : : else
1237 [ + + ]: 8002 : { if ( rThis.FindPageFrm() != pPrev->FindPageFrm() )
1238 : 16 : return sal_False;
1239 : : }
1240 : :
1241 : 8381 : const SvxBreak eBreak = pSet->GetBreak().GetBreak();
1242 [ - + ][ + + ]: 8381 : if ( eBreak == SVX_BREAK_PAGE_BEFORE || eBreak == SVX_BREAK_PAGE_BOTH )
1243 : 54 : return sal_True;
1244 : : else
1245 : : {
1246 : 8327 : const SvxBreak &ePrB = pPrev->GetAttrSet()->GetBreak().GetBreak();
1247 [ + - + + ]: 16654 : if ( ePrB == SVX_BREAK_PAGE_AFTER ||
[ + + ][ + - ]
1248 : : ePrB == SVX_BREAK_PAGE_BOTH ||
1249 : 8327 : pSet->GetPageDesc().GetPageDesc() )
1250 : 99 : return sal_True;
1251 : : }
1252 : : }
1253 : : }
1254 : 39479 : return sal_False;
1255 : : }
1256 : :
1257 : : /*************************************************************************
1258 : : |*
1259 : : |* sal_Bool SwFlowFrm::IsColBreak()
1260 : : |*
1261 : : |* If there's a hard column break before the Frm AND there is
1262 : : |* a predecessor in the same column, we return sal_True (we need to create
1263 : : |* a ColBreak). Otherwise, we return sal_False.
1264 : : |* If bAct is set to sal_True, we return sal_True if there's a ColBreak.
1265 : : |* Of course, we don't evaluate the hard column break for follows.
1266 : : |*
1267 : : |* The column break is in it's own FrmFmt (BEFORE) or in the FrmFmt of the
1268 : : |* predecessor (AFTER). If there's no predecessor in the column, we don't
1269 : : |* need to think further.
1270 : : |* The implementation works only on CntntFrms! - the definition
1271 : : |* of the predecessor is not clear for LayoutFrms.
1272 : : |*
1273 : : |*************************************************************************/
1274 : :
1275 : 20769 : sal_Bool SwFlowFrm::IsColBreak( sal_Bool bAct ) const
1276 : : {
1277 [ + + ][ + + ]: 20769 : if ( !IsFollow() && (rThis.IsMoveable() || bAct) )
[ + - ][ + + ]
1278 : : {
1279 : 18859 : const SwFrm *pCol = rThis.FindColFrm();
1280 [ + + ]: 18859 : if ( pCol )
1281 : : {
1282 : : // Determine predecessor
1283 : 579 : const SwFrm *pPrev = rThis.FindPrev();
1284 [ + + ][ - + ]: 1495 : while( pPrev && ( ( !pPrev->IsInDocBody() && !rThis.IsInFly() ) ||
[ # # + -
- + ][ - + ]
1285 : 916 : ( pPrev->IsTxtFrm() && ((SwTxtFrm*)pPrev)->IsHiddenNow() ) ) )
1286 : 0 : pPrev = pPrev->FindPrev();
1287 : :
1288 [ + + ]: 579 : if ( pPrev )
1289 : : {
1290 [ + + ]: 458 : if ( bAct )
1291 [ - + ]: 238 : { if ( pCol == pPrev->FindColFrm() )
1292 : 0 : return sal_False;
1293 : : }
1294 : : else
1295 [ + + ]: 220 : { if ( pCol != pPrev->FindColFrm() )
1296 : 184 : return sal_False;
1297 : : }
1298 : :
1299 : 274 : const SvxBreak eBreak = rThis.GetAttrSet()->GetBreak().GetBreak();
1300 [ - + ][ + + ]: 274 : if ( eBreak == SVX_BREAK_COLUMN_BEFORE ||
1301 : : eBreak == SVX_BREAK_COLUMN_BOTH )
1302 : 18 : return sal_True;
1303 : : else
1304 : : {
1305 : 256 : const SvxBreak &ePrB = pPrev->GetAttrSet()->GetBreak().GetBreak();
1306 [ - + ][ + - ]: 256 : if ( ePrB == SVX_BREAK_COLUMN_AFTER ||
1307 : : ePrB == SVX_BREAK_COLUMN_BOTH )
1308 : 0 : return sal_True;
1309 : : }
1310 : : }
1311 : : }
1312 : : }
1313 : 20769 : return sal_False;
1314 : : }
1315 : :
1316 : 13964 : sal_Bool SwFlowFrm::HasParaSpaceAtPages( sal_Bool bSct ) const
1317 : : {
1318 [ + + ]: 13964 : if( rThis.IsInSct() )
1319 : : {
1320 : 528 : const SwFrm* pTmp = rThis.GetUpper();
1321 [ + - ]: 1248 : while( pTmp )
1322 : : {
1323 [ + + ][ + - : 4988 : if( pTmp->IsCellFrm() || pTmp->IsFlyFrm() ||
+ - + - +
+ + - ]
[ + + ]
1324 : 2488 : pTmp->IsFooterFrm() || pTmp->IsHeaderFrm() ||
1325 : 1252 : ( pTmp->IsFtnFrm() && !((SwFtnFrm*)pTmp)->GetMaster() ) )
1326 : 12 : return sal_True;
1327 [ + + ]: 1236 : if( pTmp->IsPageFrm() )
1328 [ + + ][ - + ]: 77 : return ( pTmp->GetPrev() && !IsPageBreak(sal_True) ) ? sal_False : sal_True;
1329 [ + + ][ + + ]: 1159 : if( pTmp->IsColumnFrm() && pTmp->GetPrev() )
[ + + ]
1330 : 50 : return IsColBreak( sal_True );
1331 [ + + ][ + + ]: 1109 : if( pTmp->IsSctFrm() && ( !bSct || pTmp->GetPrev() ) )
[ - + ][ + + ]
1332 : 389 : return sal_False;
1333 : 720 : pTmp = pTmp->GetUpper();
1334 : : }
1335 : : OSL_FAIL( "HasParaSpaceAtPages: Where's my page?" );
1336 : 0 : return sal_False;
1337 : : }
1338 [ + + ][ + + ]: 24592 : if( !rThis.IsInDocBody() || ( rThis.IsInTab() && !rThis.IsTabFrm()) ||
[ + + + +
+ + + + ]
[ + + ]
1339 : 11156 : IsPageBreak( sal_True ) || ( rThis.FindColFrm() && IsColBreak( sal_True ) ) )
1340 : 7912 : return sal_True;
1341 : 5524 : const SwFrm* pTmp = rThis.FindColFrm();
1342 [ + + ]: 5524 : if( pTmp )
1343 : : {
1344 [ - + ]: 12 : if( pTmp->GetPrev() )
1345 : 0 : return sal_False;
1346 : : }
1347 : : else
1348 : 5512 : pTmp = &rThis;
1349 : 5524 : pTmp = pTmp->FindPageFrm();
1350 [ + + ][ + - ]: 13964 : return pTmp && !pTmp->GetPrev();
1351 : : }
1352 : :
1353 : : /** helper method to determine previous frame for calculation of the
1354 : : upper space
1355 : :
1356 : : OD 2004-03-10 #i11860#
1357 : :
1358 : : @author OD
1359 : : */
1360 : 20070 : const SwFrm* SwFlowFrm::_GetPrevFrmForUpperSpaceCalc( const SwFrm* _pProposedPrevFrm ) const
1361 : : {
1362 : : const SwFrm* pPrevFrm = _pProposedPrevFrm
1363 : : ? _pProposedPrevFrm
1364 [ + + ]: 20070 : : rThis.GetPrev();
1365 : :
1366 : : // Skip hidden paragraphs and empty sections
1367 [ + + + + : 35187 : while ( pPrevFrm &&
+ - + + +
+ ][ + + ]
1368 : 5157 : ( ( pPrevFrm->IsTxtFrm() &&
1369 : 4465 : static_cast<const SwTxtFrm*>(pPrevFrm)->IsHiddenNow() ) ||
1370 : 5157 : ( pPrevFrm->IsSctFrm() &&
1371 : 282 : !static_cast<const SwSectionFrm*>(pPrevFrm)->GetSection() ) ) )
1372 : : {
1373 : 56 : pPrevFrm = pPrevFrm->GetPrev();
1374 : : }
1375 : :
1376 : : // Special case: no direct previous frame is found but frame is in footnote
1377 : : // Search for a previous frame in previous footnote,
1378 : : // if frame isn't in a section, which is also in the footnote
1379 [ + + ][ + + : 20414 : if ( !pPrevFrm && rThis.IsInFtn() &&
+ + + + -
+ ][ + + ]
1380 : 172 : ( rThis.IsSctFrm() ||
1381 : 172 : !rThis.IsInSct() || !rThis.FindSctFrm()->IsInFtn() ) )
1382 : : {
1383 : : const SwFtnFrm* pPrevFtnFrm =
1384 : 164 : static_cast<const SwFtnFrm*>(rThis.FindFtnFrm()->GetPrev());
1385 [ + + ]: 164 : if ( pPrevFtnFrm )
1386 : : {
1387 : 34 : pPrevFrm = pPrevFtnFrm->GetLastLower();
1388 : :
1389 : : // Skip hidden paragraphs and empty sections
1390 [ + - + - : 136 : while ( pPrevFrm &&
+ - - + #
# ][ - + ]
1391 : 34 : ( ( pPrevFrm->IsTxtFrm() &&
1392 : 34 : static_cast<const SwTxtFrm*>(pPrevFrm)->IsHiddenNow() ) ||
1393 : 34 : ( pPrevFrm->IsSctFrm() &&
1394 : 0 : !static_cast<const SwSectionFrm*>(pPrevFrm)->GetSection() ) ) )
1395 : : {
1396 : 0 : pPrevFrm = pPrevFrm->GetPrev();
1397 : : }
1398 : : }
1399 : : }
1400 : : // Special case: found previous frame is a section
1401 : : // Search for the last content in the section
1402 [ + + ][ + + ]: 20070 : if( pPrevFrm && pPrevFrm->IsSctFrm() )
[ + + ]
1403 : : {
1404 : : const SwSectionFrm* pPrevSectFrm =
1405 : 226 : static_cast<const SwSectionFrm*>(pPrevFrm);
1406 : 226 : pPrevFrm = pPrevSectFrm->FindLastCntnt();
1407 : : // If the last content is in a table _inside_ the section,
1408 : : // take the table herself.
1409 : : // OD 2004-02-18 #106629# - correction:
1410 : : // Check directly, if table is inside table, instead of indirectly
1411 : : // by checking, if section isn't inside a table
1412 [ + + ][ + + ]: 226 : if ( pPrevFrm && pPrevFrm->IsInTab() )
[ + - ]
1413 : : {
1414 : 8 : const SwTabFrm* pTableFrm = pPrevFrm->FindTabFrm();
1415 [ - + ]: 8 : if ( pPrevSectFrm->IsAnLower( pTableFrm ) )
1416 : : {
1417 : 0 : pPrevFrm = pTableFrm;
1418 : : }
1419 : : }
1420 : : // OD 2004-02-18 #106629# correction: skip hidden text frames
1421 [ + - + - : 678 : while ( pPrevFrm &&
- + ][ - + ]
1422 : 226 : pPrevFrm->IsTxtFrm() &&
1423 : 226 : static_cast<const SwTxtFrm*>(pPrevFrm)->IsHiddenNow() )
1424 : : {
1425 : 0 : pPrevFrm = pPrevFrm->GetPrev();
1426 : : }
1427 : : }
1428 : :
1429 : 20070 : return pPrevFrm;
1430 : : }
1431 : :
1432 : : /// Compare styles attached to these text frames.
1433 : 12 : bool lcl_IdenticalStyles(const SwFrm* pPrevFrm, const SwFrm* pFrm)
1434 : : {
1435 : 12 : SwTxtFmtColl *pPrevFmtColl = 0;
1436 [ + - ][ + - ]: 12 : if (pPrevFrm && pPrevFrm->IsTxtFrm())
[ + - ]
1437 : : {
1438 : 12 : SwTxtFrm *pTxtFrm = ( SwTxtFrm * ) pPrevFrm;
1439 [ - + ]: 12 : pPrevFmtColl = dynamic_cast<SwTxtFmtColl*>(pTxtFrm->GetTxtNode()->GetFmtColl());
1440 : : }
1441 : :
1442 : 12 : bool bIdenticalStyles = false;
1443 [ + - ][ + - ]: 12 : if (pFrm && pFrm->IsTxtFrm())
[ + - ]
1444 : : {
1445 : 12 : SwTxtFrm *pTxtFrm = ( SwTxtFrm * ) pFrm;
1446 [ - + ]: 12 : SwTxtFmtColl *pFmtColl = dynamic_cast<SwTxtFmtColl*>(pTxtFrm->GetTxtNode()->GetFmtColl());
1447 : 12 : bIdenticalStyles = pPrevFmtColl == pFmtColl;
1448 : : }
1449 : 12 : return bIdenticalStyles;
1450 : : }
1451 : :
1452 : 18 : bool lcl_getContextualSpacing(const SwFrm* pPrevFrm)
1453 : : {
1454 : : bool bRet;
1455 [ + - ]: 18 : SwBorderAttrAccess *pAccess = new SwBorderAttrAccess( SwFrm::GetCache(), pPrevFrm );
1456 : 18 : const SwBorderAttrs *pAttrs = pAccess->Get();
1457 : :
1458 : 18 : bRet = pAttrs->GetULSpace().GetContext();
1459 : :
1460 [ + - ]: 18 : delete pAccess;
1461 : 18 : return bRet;
1462 : : }
1463 : :
1464 : : // OD 2004-03-12 #i11860# - add 3rd parameter <_bConsiderGrid>
1465 : 18253 : SwTwips SwFlowFrm::CalcUpperSpace( const SwBorderAttrs *pAttrs,
1466 : : const SwFrm* pPr,
1467 : : const bool _bConsiderGrid ) const
1468 : : {
1469 : : // OD 2004-03-10 #i11860# - use new method <GetPrevFrmForUpperSpaceCalc(..)>
1470 : 18253 : const SwFrm* pPrevFrm = _GetPrevFrmForUpperSpaceCalc( pPr );
1471 : :
1472 : : SwBorderAttrAccess *pAccess;
1473 : : SwFrm* pOwn;
1474 [ + + ]: 18253 : if( !pAttrs )
1475 : : {
1476 [ + + ]: 2043 : if( rThis.IsSctFrm() )
1477 : : {
1478 : 192 : SwSectionFrm* pFoll = &((SwSectionFrm&)rThis);
1479 [ + + ][ + + ]: 208 : do
[ + + ]
1480 : 208 : pOwn = pFoll->ContainsAny();
1481 : : while( !pOwn && 0 != ( pFoll = pFoll->GetFollow() ) );
1482 [ + + ]: 192 : if( !pOwn )
1483 : 14 : return 0;
1484 : : }
1485 : : else
1486 : 1851 : pOwn = &rThis;
1487 [ + - ]: 2029 : pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), pOwn );
1488 : 2029 : pAttrs = pAccess->Get();
1489 : : }
1490 : : else
1491 : : {
1492 : 16210 : pAccess = NULL;
1493 : 16210 : pOwn = &rThis;
1494 : : }
1495 : 18239 : SwTwips nUpper = 0;
1496 : : // OD 06.01.2004 #i11859#
1497 : : {
1498 : 18239 : const IDocumentSettingAccess* pIDSA = rThis.GetUpper()->GetFmt()->getIDocumentSettingAccess();
1499 : 18239 : const bool bUseFormerLineSpacing = pIDSA->get(IDocumentSettingAccess::OLD_LINE_SPACING);
1500 [ + + ]: 18239 : if( pPrevFrm )
1501 : : {
1502 : : // OD 2004-03-10 #i11860# - use new method to determine needed spacing
1503 : : // values of found previous frame and use these values.
1504 : 4247 : SwTwips nPrevLowerSpace = 0;
1505 : 4247 : SwTwips nPrevLineSpacing = 0;
1506 : : // #i102458#
1507 : 4247 : bool bPrevLineSpacingPorportional = false;
1508 : : GetSpacingValuesOfFrm( (*pPrevFrm),
1509 : : nPrevLowerSpace, nPrevLineSpacing,
1510 [ + - ]: 4247 : bPrevLineSpacingPorportional );
1511 [ + - ][ + + ]: 4247 : if( pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX) )
1512 : : {
1513 : 2831 : nUpper = nPrevLowerSpace + pAttrs->GetULSpace().GetUpper();
1514 : 2831 : SwTwips nAdd = nPrevLineSpacing;
1515 : : // OD 07.01.2004 #i11859# - consideration of the line spacing
1516 : : // for the upper spacing of a text frame
1517 [ - + ]: 2831 : if ( bUseFormerLineSpacing )
1518 : : {
1519 : : // former consideration
1520 [ # # ]: 0 : if ( pOwn->IsTxtFrm() )
1521 : : {
1522 [ # # ]: 0 : nAdd = Max( nAdd, static_cast<SwTxtFrm&>(rThis).GetLineSpace() );
1523 : : }
1524 : 0 : nUpper += nAdd;
1525 : : }
1526 : : else
1527 : : {
1528 : : // new consideration:
1529 : : // Only the proportional line spacing of the previous
1530 : : // text frame is considered for the upper spacing and
1531 : : // the line spacing values are add up instead of
1532 : : // building its maximum.
1533 [ + + ]: 2831 : if ( pOwn->IsTxtFrm() )
1534 : : {
1535 : : // #i102458#
1536 : : // Correction:
1537 : : // A proportional line spacing of the previous text frame
1538 : : // is added up to a own leading line spacing.
1539 : : // Otherwise, the maximum of the leading line spacing
1540 : : // of the previous text frame and the own leading line
1541 : : // spacing is built.
1542 [ - + ]: 2811 : if ( bPrevLineSpacingPorportional )
1543 : : {
1544 [ # # ]: 0 : nAdd += static_cast<SwTxtFrm&>(rThis).GetLineSpace( true );
1545 : : }
1546 : : else
1547 : : {
1548 [ + - ]: 2811 : nAdd = Max( nAdd, static_cast<SwTxtFrm&>(rThis).GetLineSpace( true ) );
1549 : : }
1550 : : }
1551 : 2831 : nUpper += nAdd;
1552 : : }
1553 : : }
1554 : : else
1555 : : {
1556 : : nUpper = Max( static_cast<long>(nPrevLowerSpace),
1557 : 1416 : static_cast<long>(pAttrs->GetULSpace().GetUpper()) );
1558 : : // OD 07.01.2004 #i11859# - consideration of the line spacing
1559 : : // for the upper spacing of a text frame
1560 [ - + ]: 1416 : if ( bUseFormerLineSpacing )
1561 : : {
1562 : : // former consideration
1563 [ # # ]: 0 : if ( pOwn->IsTxtFrm() )
1564 [ # # ]: 0 : nUpper = Max( nUpper, ((SwTxtFrm*)pOwn)->GetLineSpace() );
1565 [ # # ]: 0 : if ( nPrevLineSpacing != 0 )
1566 : : {
1567 : 0 : nUpper = Max( nUpper, nPrevLineSpacing );
1568 : : }
1569 : : }
1570 : : else
1571 : : {
1572 : : // new consideration:
1573 : : // Only the proportional line spacing of the previous
1574 : : // text frame is considered for the upper spacing and
1575 : : // the line spacing values are add up and added to
1576 : : // the paragraph spacing instead of building the
1577 : : // maximum of the line spacings and the paragraph spacing.
1578 : 1416 : SwTwips nAdd = nPrevLineSpacing;
1579 [ + + ]: 1416 : if ( pOwn->IsTxtFrm() )
1580 : : {
1581 : : // #i102458#
1582 : : // Correction:
1583 : : // A proportional line spacing of the previous text frame
1584 : : // is added up to a own leading line spacing.
1585 : : // Otherwise, the maximum of the leading line spacing
1586 : : // of the previous text frame and the own leading line
1587 : : // spacing is built.
1588 [ + + ]: 1239 : if ( bPrevLineSpacingPorportional )
1589 : : {
1590 [ + - ]: 318 : nAdd += static_cast<SwTxtFrm&>(rThis).GetLineSpace( true );
1591 : : }
1592 : : else
1593 : : {
1594 [ + - ]: 921 : nAdd = Max( nAdd, static_cast<SwTxtFrm&>(rThis).GetLineSpace( true ) );
1595 : : }
1596 : : }
1597 : 4247 : nUpper += nAdd;
1598 : : }
1599 : : }
1600 : : }
1601 [ + + + + ]: 27956 : else if ( pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX_AT_PAGES) &&
[ + + ]
1602 : 13964 : CastFlowFrm( pOwn )->HasParaSpaceAtPages( rThis.IsSctFrm() ) )
1603 : : {
1604 : 13279 : nUpper = pAttrs->GetULSpace().GetUpper();
1605 : : }
1606 : : }
1607 : :
1608 : : // OD 2004-02-26 #i25029# - pass previous frame <pPrevFrm>
1609 : : // to method <GetTopLine(..)>, if parameter <pPr> is set.
1610 : : // Note: parameter <pPr> is set, if method is called from <SwTxtFrm::WouldFit(..)>
1611 [ + + ]: 18239 : nUpper += pAttrs->GetTopLine( rThis, (pPr ? pPrevFrm : 0L) );
1612 : :
1613 : : // OD 2004-03-12 #i11860# - consider value of new parameter <_bConsiderGrid>
1614 : : // and use new method <GetUpperSpaceAmountConsideredForPageGrid(..)>
1615 : :
1616 : : //consider grid in square page mode
1617 [ + + ][ + + ]: 18239 : if ( _bConsiderGrid && rThis.GetUpper()->GetFmt()->GetDoc()->IsSquaredPageMode() )
[ + + ]
1618 : : {
1619 : 15450 : nUpper += _GetUpperSpaceAmountConsideredForPageGrid( nUpper );
1620 : : }
1621 : :
1622 : 18239 : bool bContextualSpacing = pAttrs->GetULSpace().GetContext();
1623 [ + + ]: 18239 : delete pAccess;
1624 : :
1625 [ + + ][ + - ]: 18251 : if (bContextualSpacing && pPrevFrm && lcl_getContextualSpacing(pPrevFrm)
[ + + + - ]
[ + + ]
1626 : 12 : && lcl_IdenticalStyles(pPrevFrm, &rThis))
1627 : : {
1628 : 12 : return 0;
1629 : : }
1630 : : else
1631 : 18253 : return nUpper;
1632 : : }
1633 : :
1634 : : /** method to detemine the upper space amount, which is considered for
1635 : : the page grid
1636 : :
1637 : : OD 2004-03-12 #i11860#
1638 : : Precondition: Position of frame is valid.
1639 : :
1640 : : @author OD
1641 : : */
1642 : 17267 : SwTwips SwFlowFrm::_GetUpperSpaceAmountConsideredForPageGrid(
1643 : : const SwTwips _nUpperSpaceWithoutGrid ) const
1644 : : {
1645 : 17267 : SwTwips nUpperSpaceAmountConsideredForPageGrid = 0;
1646 : :
1647 [ + + ][ + - ]: 17267 : if ( rThis.IsInDocBody() && rThis.GetAttrSet()->GetParaGrid().GetValue() )
[ + + ]
1648 : : {
1649 : 15628 : const SwPageFrm* pPageFrm = rThis.FindPageFrm();
1650 [ - + ][ # # ]: 15628 : GETGRID( pPageFrm )
[ - + ][ + - ]
1651 [ - + ]: 15628 : if( pGrid )
1652 : : {
1653 : 0 : const SwFrm* pBodyFrm = pPageFrm->FindBodyCont();
1654 [ # # ]: 0 : if ( pBodyFrm )
1655 : : {
1656 : : const long nGridLineHeight =
1657 : 0 : pGrid->GetBaseHeight() + pGrid->GetRubyHeight();
1658 : :
1659 [ # # ][ # # ]: 0 : SWRECTFN( (&rThis) )
[ # # ][ # # ]
1660 [ # # ]: 0 : const SwTwips nBodyPrtTop = (pBodyFrm->*fnRect->fnGetPrtTop)();
1661 : : const SwTwips nProposedPrtTop =
1662 : 0 : (*fnRect->fnYInc)( (rThis.Frm().*fnRect->fnGetTop)(),
1663 [ # # ]: 0 : _nUpperSpaceWithoutGrid );
1664 : :
1665 : : const SwTwips nSpaceAbovePrtTop =
1666 : 0 : (*fnRect->fnYDiff)( nProposedPrtTop, nBodyPrtTop );
1667 : : const SwTwips nSpaceOfCompleteLinesAbove =
1668 : 0 : nGridLineHeight * ( nSpaceAbovePrtTop / nGridLineHeight );
1669 : : SwTwips nNewPrtTop =
1670 : 0 : (*fnRect->fnYInc)( nBodyPrtTop, nSpaceOfCompleteLinesAbove );
1671 [ # # ]: 0 : if ( (*fnRect->fnYDiff)( nProposedPrtTop, nNewPrtTop ) > 0 )
1672 : : {
1673 : 0 : nNewPrtTop = (*fnRect->fnYInc)( nNewPrtTop, nGridLineHeight );
1674 : : }
1675 : :
1676 : : const SwTwips nNewUpperSpace =
1677 : : (*fnRect->fnYDiff)( nNewPrtTop,
1678 [ # # ]: 0 : (rThis.Frm().*fnRect->fnGetTop)() );
1679 : :
1680 : : nUpperSpaceAmountConsideredForPageGrid =
1681 : 0 : nNewUpperSpace - _nUpperSpaceWithoutGrid;
1682 : :
1683 : : OSL_ENSURE( nUpperSpaceAmountConsideredForPageGrid >= 0,
1684 : : "<SwFlowFrm::GetUpperSpaceAmountConsideredForPageGrid(..)> - negative space considered for page grid!" );
1685 : : }
1686 : : }
1687 : : }
1688 : 17267 : return nUpperSpaceAmountConsideredForPageGrid;
1689 : : }
1690 : :
1691 : : /** method to determent the upper space amount, which is considered for
1692 : : the previous frame
1693 : :
1694 : : OD 2004-03-11 #i11860#
1695 : :
1696 : : @author OD
1697 : : */
1698 : 1817 : SwTwips SwFlowFrm::_GetUpperSpaceAmountConsideredForPrevFrm() const
1699 : : {
1700 : 1817 : SwTwips nUpperSpaceAmountOfPrevFrm = 0;
1701 : :
1702 : 1817 : const SwFrm* pPrevFrm = _GetPrevFrmForUpperSpaceCalc();
1703 [ + + ]: 1817 : if ( pPrevFrm )
1704 : : {
1705 : 888 : SwTwips nPrevLowerSpace = 0;
1706 : 888 : SwTwips nPrevLineSpacing = 0;
1707 : : // #i102458#
1708 : 888 : bool bDummy = false;
1709 [ + - ]: 888 : GetSpacingValuesOfFrm( (*pPrevFrm), nPrevLowerSpace, nPrevLineSpacing, bDummy );
1710 [ + - ][ - + ]: 888 : if ( nPrevLowerSpace > 0 || nPrevLineSpacing > 0 )
1711 : : {
1712 [ # # ][ # # ]: 0 : const IDocumentSettingAccess* pIDSA = rThis.GetUpper()->GetFmt()->getIDocumentSettingAccess();
1713 [ # # ][ # # ]: 0 : if ( pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX) ||
[ # # ][ # # ]
1714 [ # # ]: 0 : !pIDSA->get(IDocumentSettingAccess::OLD_LINE_SPACING) )
1715 : : {
1716 : 0 : nUpperSpaceAmountOfPrevFrm = nPrevLowerSpace + nPrevLineSpacing;
1717 : : }
1718 : : else
1719 : : {
1720 : 888 : nUpperSpaceAmountOfPrevFrm = Max( nPrevLowerSpace, nPrevLineSpacing );
1721 : : }
1722 : : }
1723 : : }
1724 : :
1725 : 1817 : return nUpperSpaceAmountOfPrevFrm;
1726 : : }
1727 : :
1728 : : /** method to determine the upper space amount, which is considered for
1729 : : the previous frame and the page grid, if option 'Use former object
1730 : : positioning' is OFF
1731 : :
1732 : : OD 2004-03-18 #i11860#
1733 : :
1734 : : @author OD
1735 : : */
1736 : 1817 : SwTwips SwFlowFrm::GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() const
1737 : : {
1738 : 1817 : SwTwips nUpperSpaceAmountConsideredForPrevFrmAndPageGrid = 0;
1739 : :
1740 [ + - ]: 1817 : if ( !rThis.GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::USE_FORMER_OBJECT_POS) )
1741 : : {
1742 : : nUpperSpaceAmountConsideredForPrevFrmAndPageGrid =
1743 : 1817 : _GetUpperSpaceAmountConsideredForPrevFrm() +
1744 : 1817 : _GetUpperSpaceAmountConsideredForPageGrid( CalcUpperSpace( 0L, 0L, false ) );
1745 : : }
1746 : :
1747 : 1817 : return nUpperSpaceAmountConsideredForPrevFrmAndPageGrid;
1748 : : }
1749 : :
1750 : : /** calculation of lower space
1751 : :
1752 : : OD 2004-03-02 #106629#
1753 : :
1754 : : @author OD
1755 : : */
1756 : 15451 : SwTwips SwFlowFrm::CalcLowerSpace( const SwBorderAttrs* _pAttrs ) const
1757 : : {
1758 : 15451 : SwTwips nLowerSpace = 0;
1759 : :
1760 : 15451 : SwBorderAttrAccess* pAttrAccess = 0L;
1761 [ - + ]: 15451 : if ( !_pAttrs )
1762 : : {
1763 [ # # ]: 0 : pAttrAccess = new SwBorderAttrAccess( SwFrm::GetCache(), &rThis );
1764 : 0 : _pAttrs = pAttrAccess->Get();
1765 : : }
1766 : :
1767 : 15451 : sal_Bool bCommonBorder = sal_True;
1768 [ + + ][ + + ]: 15451 : if ( rThis.IsInSct() && rThis.GetUpper()->IsColBodyFrm() )
[ + + ]
1769 : : {
1770 : 278 : const SwSectionFrm* pSectFrm = rThis.FindSctFrm();
1771 : 278 : bCommonBorder = pSectFrm->GetFmt()->GetBalancedColumns().GetValue();
1772 : : }
1773 : : nLowerSpace = bCommonBorder ?
1774 : 15197 : _pAttrs->GetBottomLine( rThis ) :
1775 [ + + ]: 30648 : _pAttrs->CalcBottomLine();
1776 : :
1777 : : // #i26250#
1778 : : // - correct consideration of table frames
1779 : : // - use new method <CalcAddLowerSpaceAsLastInTableCell(..)>
1780 [ - + ][ # # : 44094 : if ( ( ( rThis.IsTabFrm() && rThis.GetUpper()->IsInTab() ) ||
+ + + - +
+ ][ + + ]
1781 : : // #115759# - no lower spacing, if frame has a follow
1782 : 22047 : ( rThis.IsInTab() && !GetFollow() ) ) &&
1783 : 6596 : !rThis.GetIndNext() )
1784 : : {
1785 : 6571 : nLowerSpace += CalcAddLowerSpaceAsLastInTableCell( _pAttrs );
1786 : : }
1787 : :
1788 [ - + ]: 15451 : delete pAttrAccess;
1789 : :
1790 : 15451 : return nLowerSpace;
1791 : : }
1792 : :
1793 : : /** calculation of the additional space to be considered, if flow frame
1794 : : is the last inside a table cell
1795 : :
1796 : : OD 2004-07-16 #i26250#
1797 : :
1798 : : @author OD
1799 : : */
1800 : 6571 : SwTwips SwFlowFrm::CalcAddLowerSpaceAsLastInTableCell(
1801 : : const SwBorderAttrs* _pAttrs ) const
1802 : : {
1803 : 6571 : SwTwips nAdditionalLowerSpace = 0;
1804 : :
1805 [ + - ]: 6571 : if ( rThis.GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS) )
1806 : : {
1807 : 6571 : const SwFrm* pFrm = &rThis;
1808 [ - + ]: 6571 : if ( pFrm->IsSctFrm() )
1809 : : {
1810 : 0 : const SwSectionFrm* pSectFrm = static_cast<const SwSectionFrm*>(pFrm);
1811 : 0 : pFrm = pSectFrm->FindLastCntnt();
1812 [ # # ][ # # ]: 0 : if ( pFrm && pFrm->IsInTab() )
[ # # ]
1813 : : {
1814 : 0 : const SwTabFrm* pTableFrm = pFrm->FindTabFrm();
1815 [ # # ]: 0 : if ( pSectFrm->IsAnLower( pTableFrm ) )
1816 : : {
1817 : 0 : pFrm = pTableFrm;
1818 : : }
1819 : : }
1820 : : }
1821 : :
1822 : 6571 : SwBorderAttrAccess* pAttrAccess = 0L;
1823 [ + - ][ - + ]: 6571 : if ( !_pAttrs || pFrm != &rThis )
1824 : : {
1825 [ # # ]: 0 : pAttrAccess = new SwBorderAttrAccess( SwFrm::GetCache(), pFrm );
1826 : 0 : _pAttrs = pAttrAccess->Get();
1827 : : }
1828 : :
1829 : 6571 : nAdditionalLowerSpace += _pAttrs->GetULSpace().GetLower();
1830 : :
1831 [ - + ]: 6571 : delete pAttrAccess;
1832 : : }
1833 : :
1834 : 6571 : return nAdditionalLowerSpace;
1835 : : }
1836 : :
1837 : : /*************************************************************************
1838 : : |*
1839 : : |* sal_Bool SwFlowFrm::CheckMoveFwd()
1840 : : |*
1841 : : |* Description Moves the Frm forward if it seems necessary regarding
1842 : : |* the current conditions and attributes.
1843 : : |*
1844 : : |*************************************************************************/
1845 : :
1846 : :
1847 : 20767 : sal_Bool SwFlowFrm::CheckMoveFwd( bool& rbMakePage, sal_Bool bKeep, sal_Bool )
1848 : : {
1849 : 20767 : const SwFrm* pNxt = rThis.GetIndNext();
1850 : :
1851 [ + + + + : 21063 : if ( bKeep && //!bMovedBwd &&
- + ]
[ - + # # ]
[ - + ][ + + ]
1852 : 296 : ( !pNxt || ( pNxt->IsTxtFrm() && ((SwTxtFrm*)pNxt)->IsEmptyMaster() ) ) &&
1853 : 0 : ( 0 != (pNxt = rThis.FindNext()) ) && IsKeepFwdMoveAllowed() )
1854 : : {
1855 [ # # ]: 0 : if( pNxt->IsSctFrm() )
1856 : : { // Don't get fooled by empty SectionFrms
1857 : 0 : const SwFrm* pTmp = NULL;
1858 [ # # ]: 0 : while( pNxt && pNxt->IsSctFrm() &&
[ # # # # ]
[ # # ][ # # ]
1859 : 0 : ( !((SwSectionFrm*)pNxt)->GetSection() ||
1860 : 0 : 0 == ( pTmp = ((SwSectionFrm*)pNxt)->ContainsAny() ) ) )
1861 : : {
1862 : 0 : pNxt = pNxt->FindNext();
1863 : 0 : pTmp = NULL;
1864 : : }
1865 [ # # ]: 0 : if( pTmp )
1866 : 0 : pNxt = pTmp; // the content of the next notempty sectionfrm
1867 : : }
1868 [ # # ][ # # ]: 0 : if( pNxt && pNxt->GetValidPosFlag() )
[ # # ]
1869 : : {
1870 : 0 : sal_Bool bMove = sal_False;
1871 : 0 : const SwSectionFrm *pSct = rThis.FindSctFrm();
1872 [ # # ][ # # ]: 0 : if( pSct && !pSct->GetValidSizeFlag() )
[ # # ]
1873 : : {
1874 : 0 : const SwSectionFrm* pNxtSct = pNxt->FindSctFrm();
1875 [ # # ][ # # ]: 0 : if( pNxtSct && pSct->IsAnFollow( pNxtSct ) )
[ # # ][ # # ]
1876 : 0 : bMove = sal_True;
1877 : : }
1878 : : else
1879 : 0 : bMove = sal_True;
1880 [ # # ]: 0 : if( bMove )
1881 : : {
1882 : : //Keep together with the following frame
1883 : 0 : MoveFwd( rbMakePage, sal_False );
1884 : 0 : return sal_True;
1885 : : }
1886 : : }
1887 : : }
1888 : :
1889 : 20767 : sal_Bool bMovedFwd = sal_False;
1890 : :
1891 [ + + ]: 20767 : if ( rThis.GetIndPrev() )
1892 : : {
1893 [ - + ]: 8034 : if ( IsPrevObjMove() ) // Should we care about objects of the Prev?
1894 : : {
1895 : 0 : bMovedFwd = sal_True;
1896 [ # # ]: 0 : if ( !MoveFwd( rbMakePage, sal_False ) )
1897 : 0 : rbMakePage = false;
1898 : : }
1899 : : else
1900 : : {
1901 [ - + ]: 8034 : if ( IsPageBreak( sal_False ) )
1902 : : {
1903 [ # # ]: 0 : while ( MoveFwd( rbMakePage, sal_True ) )
1904 : : /* do nothing */;
1905 : 0 : rbMakePage = false;
1906 : 0 : bMovedFwd = sal_True;
1907 : : }
1908 [ + + ]: 8034 : else if ( IsColBreak ( sal_False ) )
1909 : : {
1910 : 6 : const SwPageFrm *pPage = rThis.FindPageFrm();
1911 : 6 : SwFrm *pCol = rThis.FindColFrm();
1912 [ - + ]: 6 : do
1913 : 6 : { MoveFwd( rbMakePage, sal_False );
1914 : 6 : SwFrm *pTmp = rThis.FindColFrm();
1915 [ + - ]: 6 : if( pTmp != pCol )
1916 : : {
1917 : 6 : bMovedFwd = sal_True;
1918 : 6 : pCol = pTmp;
1919 : : }
1920 : : else
1921 : 0 : break;
1922 : 6 : } while ( IsColBreak( sal_False ) );
1923 [ - + ]: 6 : if ( pPage != rThis.FindPageFrm() )
1924 : 0 : rbMakePage = false;
1925 : : }
1926 : : }
1927 : : }
1928 : 20767 : return bMovedFwd;
1929 : : }
1930 : :
1931 : : /*************************************************************************
1932 : : |*
1933 : : |* sal_Bool SwFlowFrm::MoveFwd()
1934 : : |*
1935 : : |* Description Return value tells us whether the Frm has changed
1936 : : |* the page.
1937 : : |*
1938 : : |*************************************************************************/
1939 : :
1940 : :
1941 : 222 : sal_Bool SwFlowFrm::MoveFwd( sal_Bool bMakePage, sal_Bool bPageBreak, sal_Bool bMoveAlways )
1942 : : {
1943 : : //!!!!MoveFtnCntFwd might need to be updated as well.
1944 : 222 : SwFtnBossFrm *pOldBoss = rThis.FindFtnBossFrm();
1945 [ - + ]: 222 : if ( rThis.IsInFtn() )
1946 : 0 : return ((SwCntntFrm&)rThis).MoveFtnCntFwd( bMakePage, pOldBoss );
1947 : :
1948 [ + + ][ + - ]: 222 : if( !IsFwdMoveAllowed() && !bMoveAlways )
[ + + ]
1949 : : {
1950 : 52 : sal_Bool bNoFwd = sal_True;
1951 [ - + ]: 52 : if( rThis.IsInSct() )
1952 : : {
1953 : 0 : SwFtnBossFrm* pBoss = rThis.FindFtnBossFrm();
1954 : 0 : bNoFwd = !pBoss->IsInSct() || ( !pBoss->Lower()->GetNext() &&
1955 [ # # ]: 0 : !pBoss->GetPrev() );
[ # # # # ]
1956 : : }
1957 : :
1958 : : // Allow the MoveFwd even if we do not have an IndPrev in these cases:
1959 [ - + # # : 52 : if ( rThis.IsInTab() &&
# # # # #
# ][ - + ]
1960 : 0 : ( !rThis.IsTabFrm() ||
1961 : 0 : ( rThis.GetUpper()->IsInTab() &&
1962 : 0 : rThis.GetUpper()->FindTabFrm()->IsFwdMoveAllowed() ) ) &&
1963 : 0 : 0 != const_cast<SwFrm&>(rThis).GetNextCellLeaf( MAKEPAGE_NONE ) )
1964 : : {
1965 : 0 : bNoFwd = sal_False;
1966 : : }
1967 : :
1968 [ + - ]: 52 : if( bNoFwd )
1969 : : {
1970 : : // It's allowed to move PageBreaks if the Frm isn't the first
1971 : : // one on the page.
1972 [ + - ]: 52 : if ( !bPageBreak )
1973 : 52 : return sal_False;
1974 : :
1975 : 0 : const SwFrm *pCol = rThis.FindColFrm();
1976 [ # # ][ # # ]: 0 : if ( !pCol || !pCol->GetPrev() )
[ # # ]
1977 : 0 : return sal_False;
1978 : : }
1979 : : }
1980 : :
1981 : 170 : sal_Bool bSamePage = sal_True;
1982 : : SwLayoutFrm *pNewUpper =
1983 [ + - ]: 170 : rThis.GetLeaf( bMakePage ? MAKEPAGE_INSERT : MAKEPAGE_NONE, sal_True );
1984 : :
1985 [ + - ]: 170 : if ( pNewUpper )
1986 : : {
1987 : : PROTOCOL_ENTER( &rThis, PROT_MOVE_FWD, 0, 0 );
1988 : 170 : SwPageFrm *pOldPage = pOldBoss->FindPageFrm();
1989 : : // We move ourself and all the direct successors before the
1990 : : // first CntntFrm below the new Upper.
1991 : :
1992 : : // If our NewUpper lies in a SectionFrm, we need to make sure
1993 : : // that it won't destroy itself in Calc.
1994 : 170 : SwSectionFrm* pSect = pNewUpper->FindSctFrm();
1995 : 170 : sal_Bool bUnlock = sal_False;
1996 [ + + ]: 170 : if( pSect )
1997 : : {
1998 : : // If we only switch column within our SectionFrm, we better don't
1999 : : // call Calc, as this would format the SectionFrm, which in turn would
2000 : : // call us again, etc.
2001 [ + + ]: 79 : if( pSect != rThis.FindSctFrm() )
2002 : : {
2003 : 29 : bUnlock = !pSect->IsColLocked();
2004 : 29 : pSect->ColLock();
2005 : 29 : pNewUpper->Calc();
2006 [ + - ]: 29 : if( bUnlock )
2007 : 29 : pSect->ColUnlock();
2008 : : }
2009 : : }
2010 : : // Do not calculate split cell frames.
2011 [ - + ][ # # ]: 91 : else if ( !pNewUpper->IsCellFrm() || ((SwLayoutFrm*)pNewUpper)->Lower() )
[ + - ]
2012 : 91 : pNewUpper->Calc();
2013 : :
2014 : 170 : SwFtnBossFrm *pNewBoss = pNewUpper->FindFtnBossFrm();
2015 : 170 : sal_Bool bBossChg = pNewBoss != pOldBoss;
2016 : 170 : pNewBoss = pNewBoss->FindFtnBossFrm( sal_True );
2017 : 170 : pOldBoss = pOldBoss->FindFtnBossFrm( sal_True );
2018 : 170 : SwPageFrm* pNewPage = pOldPage;
2019 : :
2020 : : // First, we move the footnotes.
2021 : 170 : sal_Bool bFtnMoved = sal_False;
2022 : :
2023 : : // #i26831#
2024 : : // If pSect has just been created, the printing area of pSect has
2025 : : // been calculated based on the first content of its follow.
2026 : : // In this case we prefer to call a SimpleFormat for this new
2027 : : // section after we inserted the contents. Otherwise the section
2028 : : // frame will invalidate its lowers, if its printing area changes
2029 : : // in SwSectionFrm::Format, which can cause loops.
2030 : 79 : const bool bForceSimpleFormat = pSect && pSect->HasFollow() &&
2031 [ # # ]: 249 : !pSect->ContainsAny();
[ + + - + ]
2032 : :
2033 [ + - ]: 170 : if ( pNewBoss != pOldBoss )
2034 : : {
2035 [ + - ]: 170 : pNewPage = pNewBoss->FindPageFrm();
2036 : 170 : bSamePage = pNewPage == pOldPage;
2037 : : // Set deadline, so the footnotes don't think up
2038 : : // silly things...
2039 [ + - ][ - + ]: 170 : SWRECTFN( pOldBoss )
[ # # ][ # # ]
[ - + ]
2040 : : SwSaveFtnHeight aHeight( pOldBoss,
2041 [ + - ][ + - ]: 170 : (pOldBoss->Frm().*fnRect->fnGetBottom)() );
[ + - ]
2042 : 170 : SwCntntFrm* pStart = rThis.IsCntntFrm() ?
2043 [ # # ][ + - ]: 170 : (SwCntntFrm*)&rThis : ((SwLayoutFrm&)rThis).ContainsCntnt();
2044 : : OSL_ENSURE( pStart || ( rThis.IsTabFrm() && !((SwTabFrm&)rThis).Lower() ),
2045 : : "MoveFwd: Missing Content" );
2046 : 170 : SwLayoutFrm* pBody = pStart ? ( pStart->IsTxtFrm() ?
2047 [ + - + - ]: 340 : (SwLayoutFrm*)((SwTxtFrm*)pStart)->FindBodyFrm() : 0 ) : 0;
[ + - ]
2048 [ + - ]: 170 : if( pBody )
2049 : : bFtnMoved = pBody->MoveLowerFtns( pStart, pOldBoss, pNewBoss,
2050 [ + - ][ + - ]: 170 : sal_False);
2051 : : }
2052 : : // It's possible when dealing with SectionFrms that we have been moved
2053 : : // by pNewUpper->Calc(), for instance into the pNewUpper.
2054 : : // MoveSubTree or PasteTree respectively is not prepared to handle such a
2055 : : // situation.
2056 [ + - ]: 170 : if( pNewUpper != rThis.GetUpper() )
2057 : : {
2058 : : // #i27145#
2059 : 170 : SwSectionFrm* pOldSct = 0;
2060 [ + + ]: 170 : if ( rThis.GetUpper()->IsSctFrm() )
2061 : : {
2062 : 3 : pOldSct = static_cast<SwSectionFrm*>(rThis.GetUpper());
2063 : : }
2064 : :
2065 : 170 : MoveSubTree( pNewUpper, pNewUpper->Lower() );
2066 : :
2067 : : // #i27145#
2068 [ + - ][ + + ]: 170 : if ( pOldSct && pOldSct->GetSection() )
[ + + ]
2069 : : {
2070 : : // Prevent loops by setting the new height at
2071 : : // the section frame if footnotes have been moved.
2072 : : // Otherwise the call of SwLayNotify::~SwLayNotify() for
2073 : : // the (invalid) section frame will invalidate the first
2074 : : // lower of its follow, because it grows due to the removed
2075 : : // footnotes.
2076 : : // Note: If pOldSct has become empty during MoveSubTree, it
2077 : : // has already been scheduled for removal. No SimpleFormat
2078 : : // for these.
2079 : 3 : pOldSct->SimpleFormat();
2080 : : }
2081 : :
2082 : : // #i26831#
2083 [ - + ]: 170 : if ( bForceSimpleFormat )
2084 : : {
2085 : 0 : pSect->SimpleFormat();
2086 : : }
2087 : :
2088 [ - + ][ # # ]: 170 : if ( bFtnMoved && !bSamePage )
2089 : : {
2090 : 0 : pOldPage->UpdateFtnNum();
2091 : 0 : pNewPage->UpdateFtnNum();
2092 : : }
2093 : :
2094 [ + - ]: 170 : if( bBossChg )
2095 : : {
2096 : 170 : rThis.Prepare( PREP_BOSS_CHGD, 0, sal_False );
2097 [ + + ]: 170 : if( !bSamePage )
2098 : : {
2099 : 114 : ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
2100 [ + - ][ + - ]: 114 : if ( pSh && !pSh->Imp()->IsUpdateExpFlds() )
[ + - ]
2101 : 114 : pSh->GetDoc()->SetNewFldLst(true); // Will be done by CalcLayout() later on!
2102 : :
2103 : 114 : pNewPage->InvalidateSpelling();
2104 : 114 : pNewPage->InvalidateSmartTags(); // SMARTTAGS
2105 : 114 : pNewPage->InvalidateAutoCompleteWords();
2106 : 114 : pNewPage->InvalidateWordCount();
2107 : : }
2108 : : }
2109 : : }
2110 : : // OD 30.10.2002 #97265# - no <CheckPageDesc(..)> in online layout
2111 : 170 : const ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
2112 : :
2113 [ + - ][ + - ]: 170 : if ( !( pSh && pSh->GetViewOptions()->getBrowseMode() ) )
[ + - ]
2114 : : {
2115 : : // #i106452#
2116 : : // check page description not only in situation with sections.
2117 [ + + + - : 398 : if ( !bSamePage &&
- + ][ - + ]
2118 : 114 : ( rThis.GetAttrSet()->GetPageDesc().GetPageDesc() ||
2119 : 114 : pOldPage->GetPageDesc()->GetFollow() != pNewPage->GetPageDesc() ) )
2120 : : {
2121 : 0 : SwFrm::CheckPageDescs( pNewPage, sal_False );
2122 : : }
2123 : : }
2124 : : }
2125 : 222 : return bSamePage;
2126 : : }
2127 : :
2128 : :
2129 : : /*************************************************************************
2130 : : |*
2131 : : |* sal_Bool SwFlowFrm::MoveBwd()
2132 : : |*
2133 : : |* Description Return value tells whether the Frm should change the page.
2134 : : |* This should be called by derived classes.
2135 : : |* The actual moving must be implemented in the subclasses.
2136 : : |*
2137 : : |*************************************************************************/
2138 : :
2139 : 12901 : sal_Bool SwFlowFrm::MoveBwd( sal_Bool &rbReformat )
2140 : : {
2141 : 12901 : SwFlowFrm::SetMoveBwdJump( sal_False );
2142 : :
2143 : 12901 : SwFtnFrm* pFtn = rThis.FindFtnFrm();
2144 [ + + ][ + + ]: 12901 : if ( pFtn && pFtn->IsBackMoveLocked() )
[ + + ]
2145 : 55 : return sal_False;
2146 : :
2147 : : // #115759# - text frames, which are directly inside
2148 : : // tables aren't allowed to move backward.
2149 [ + + ][ - + ]: 12846 : if ( rThis.IsTxtFrm() && rThis.IsInTab() )
[ - + ]
2150 : : {
2151 : 0 : const SwLayoutFrm* pUpperFrm = rThis.GetUpper();
2152 [ # # ]: 0 : while ( pUpperFrm )
2153 : : {
2154 [ # # ]: 0 : if ( pUpperFrm->IsTabFrm() )
2155 : : {
2156 : 0 : return sal_False;
2157 : : }
2158 [ # # ][ # # ]: 0 : else if ( pUpperFrm->IsColumnFrm() && pUpperFrm->IsInSct() )
[ # # ]
2159 : : {
2160 : 0 : break;
2161 : : }
2162 : 0 : pUpperFrm = pUpperFrm->GetUpper();
2163 : : }
2164 : : }
2165 : :
2166 : 12846 : SwFtnBossFrm * pOldBoss = rThis.FindFtnBossFrm();
2167 : 12846 : SwPageFrm * const pOldPage = pOldBoss->FindPageFrm();
2168 : 12846 : SwLayoutFrm *pNewUpper = 0;
2169 : 12846 : sal_Bool bCheckPageDescs = sal_False;
2170 : 12846 : bool bCheckPageDescOfNextPage = false;
2171 : :
2172 [ + + ]: 12846 : if ( pFtn )
2173 : : {
2174 : : // If the footnote already sits on the same page/column as the reference,
2175 : : // we can't flow back. The breaks don't need to be checked for footnotes.
2176 : :
2177 : : // #i37084# FindLastCntnt does not necessarily
2178 : : // have to have a result != 0
2179 : 199 : SwFrm* pRef = 0;
2180 : 199 : const bool bEndnote = pFtn->GetAttr()->GetFtn().IsEndNote();
2181 [ - + ][ - + ]: 199 : if( bEndnote && pFtn->IsInSct() )
[ + + ]
2182 : : {
2183 : 0 : SwSectionFrm* pSect = pFtn->FindSctFrm();
2184 [ # # ]: 0 : if( pSect->IsEndnAtEnd() )
2185 : 0 : pRef = pSect->FindLastCntnt( FINDMODE_LASTCNT );
2186 : : }
2187 [ + - ]: 199 : if( !pRef )
2188 : 199 : pRef = pFtn->GetRef();
2189 : :
2190 : : OSL_ENSURE( pRef, "MoveBwd: Endnote for an empty section?" );
2191 : :
2192 [ + + ]: 199 : if( !bEndnote )
2193 : 166 : pOldBoss = pOldBoss->FindFtnBossFrm( sal_True );
2194 : 199 : SwFtnBossFrm *pRefBoss = pRef->FindFtnBossFrm( !bEndnote );
2195 [ + + + - ]: 232 : if ( pOldBoss != pRefBoss &&
[ + + ][ + + ]
2196 : : // OD 08.11.2002 #104840# - use <SwLayoutFrm::IsBefore(..)>
2197 : 37 : ( !bEndnote ||
2198 : 33 : pRefBoss->IsBefore( pOldBoss ) )
2199 : : )
2200 : 37 : pNewUpper = rThis.GetLeaf( MAKEPAGE_FTN, sal_False );
2201 : : }
2202 [ + + ]: 12647 : else if ( IsPageBreak( sal_True ) ) // Do we have to respect a PageBreak?
2203 : : {
2204 : : // If the previous page doesn't have an Frm in the body,
2205 : : // flowing back makes sense despite the PageBreak (otherwise,
2206 : : // we'd get an empty page).
2207 : : // Of course we need to overlook empty pages!
2208 : 63 : const SwFrm *pFlow = &rThis;
2209 [ - + ][ + - : 189 : do
+ - - + ]
2210 : : {
2211 : 63 : pFlow = pFlow->FindPrev();
2212 : : } while ( pFlow &&
2213 : 63 : ( pFlow->FindPageFrm() == pOldPage ||
2214 : 63 : !pFlow->IsInDocBody() ) );
2215 [ + - ]: 63 : if ( pFlow )
2216 : : {
2217 : 63 : long nDiff = pOldPage->GetPhyPageNum() - pFlow->GetPhyPageNum();
2218 [ - + ]: 63 : if ( nDiff > 1 )
2219 : : {
2220 [ # # ]: 0 : if ( ((SwPageFrm*)pOldPage->GetPrev())->IsEmptyPage() )
2221 : 0 : nDiff -= 1;
2222 [ # # ]: 0 : if ( nDiff > 1 )
2223 : : {
2224 : 0 : pNewUpper = rThis.GetLeaf( MAKEPAGE_NONE, sal_False );
2225 : : // #i53139#
2226 : : // Now <pNewUpper> is a previous layout frame, which contains
2227 : : // content. But the new upper layout frame has to be the next one.
2228 : : // Thus, hack for issue i14206 no longer needed, but fix for issue 114442
2229 : : // #136024# - correct fix for i53139
2230 : : // Check for wrong page description before using next new upper.
2231 : : // #i66051# - further correction of fix for i53139
2232 : : // Check for correct type of new next upper layout frame
2233 : : // #136538# - another correction of fix for i53139
2234 : : // Assumption, that in all cases <pNewUpper> is a previous
2235 : : // layout frame, which contains content, is wrong.
2236 : : // #136538# - another correction of fix for i53139
2237 : : // Beside type check, check also, if proposed new next upper
2238 : : // frame is inside the same frame types.
2239 : : // #i73194# - and yet another correction
2240 : : // of fix for i53139:
2241 : : // Assure that the new next upper layout frame doesn't
2242 : : // equal the current one.
2243 : : // E.g.: content is on page 3, on page 2 is only a 'ghost'
2244 : : // section and on page 1 is normal content. Method <FindPrev(..)>
2245 : : // will find the last content of page 1, but <GetLeaf(..)>
2246 : : // returns new upper on page 2.
2247 [ # # ]: 0 : if ( pNewUpper->Lower() )
2248 : : {
2249 : 0 : SwLayoutFrm* pNewNextUpper = pNewUpper->GetLeaf( MAKEPAGE_NONE, sal_True );
2250 [ # # ][ # # : 0 : if ( pNewNextUpper &&
# # # # #
# # # # #
# # # # ]
2251 : 0 : pNewNextUpper != rThis.GetUpper() &&
2252 : 0 : pNewNextUpper->GetType() == pNewUpper->GetType() &&
2253 : 0 : pNewNextUpper->IsInDocBody() == pNewUpper->IsInDocBody() &&
2254 : 0 : pNewNextUpper->IsInFtn() == pNewUpper->IsInFtn() &&
2255 : 0 : pNewNextUpper->IsInTab() == pNewUpper->IsInTab() &&
2256 : 0 : pNewNextUpper->IsInSct() == pNewUpper->IsInSct() &&
2257 : 0 : !rThis.WrongPageDesc( pNewNextUpper->FindPageFrm() ) )
2258 : : {
2259 : 0 : pNewUpper = pNewNextUpper;
2260 : 0 : bCheckPageDescOfNextPage = true;
2261 : : }
2262 : : }
2263 : :
2264 : 0 : bCheckPageDescs = sal_True;
2265 : : }
2266 : : }
2267 : : }
2268 : : }
2269 [ - + ]: 12584 : else if ( IsColBreak( sal_True ) )
2270 : : {
2271 : : // If the previous column doesn't contain a CntntFrm, flowing back
2272 : : // makes sense despite the ColumnBreak, as otherwise we'd get
2273 : : // an empty column.
2274 [ # # ]: 0 : if( rThis.IsInSct() )
2275 : : {
2276 : 0 : pNewUpper = rThis.GetLeaf( MAKEPAGE_NONE, sal_False );
2277 [ # # # # : 0 : if( pNewUpper && !SwFlowFrm::IsMoveBwdJump() &&
# # # # #
# ][ # # ]
[ # # ]
2278 : 0 : ( pNewUpper->ContainsCntnt() ||
2279 : 0 : ( ( !pNewUpper->IsColBodyFrm() ||
2280 : 0 : !pNewUpper->GetUpper()->GetPrev() ) &&
2281 : 0 : !pNewUpper->FindSctFrm()->GetPrev() ) ) )
2282 : : {
2283 : 0 : pNewUpper = 0;
2284 : : }
2285 : : // #i53139#
2286 : : // #i69409# - check <pNewUpper>
2287 : : // #i71065# - check <SwFlowFrm::IsMoveBwdJump()>
2288 [ # # ][ # # ]: 0 : else if ( pNewUpper && !SwFlowFrm::IsMoveBwdJump() )
[ # # ]
2289 : : {
2290 : : // Now <pNewUpper> is a previous layout frame, which
2291 : : // contains content. But the new upper layout frame
2292 : : // has to be the next one.
2293 : : // #136024# - correct fix for i53139
2294 : : // Check for wrong page description before using next new upper.
2295 : : // #i66051# - further correction of fix for i53139
2296 : : // Check for correct type of new next upper layout frame
2297 : : // #136538# - another correction of fix for i53139
2298 : : // Beside type check, check also, if proposed new next upper
2299 : : // frame is inside the same frame types.
2300 : 0 : SwLayoutFrm* pNewNextUpper = pNewUpper->GetLeaf( MAKEPAGE_NOSECTION, sal_True );
2301 [ # # ][ # # : 0 : if ( pNewNextUpper &&
# # # # #
# # # # #
# # ]
2302 : 0 : pNewNextUpper->GetType() == pNewUpper->GetType() &&
2303 : 0 : pNewNextUpper->IsInDocBody() == pNewUpper->IsInDocBody() &&
2304 : 0 : pNewNextUpper->IsInFtn() == pNewUpper->IsInFtn() &&
2305 : 0 : pNewNextUpper->IsInTab() == pNewUpper->IsInTab() &&
2306 : 0 : pNewNextUpper->IsInSct() == pNewUpper->IsInSct() &&
2307 : 0 : !rThis.WrongPageDesc( pNewNextUpper->FindPageFrm() ) )
2308 : : {
2309 : 0 : pNewUpper = pNewNextUpper;
2310 : : }
2311 : : }
2312 : : }
2313 : : else
2314 : : {
2315 : 0 : const SwFrm *pCol = rThis.FindColFrm();
2316 : 0 : sal_Bool bGoOn = sal_True;
2317 : 0 : sal_Bool bJump = sal_False;
2318 [ # # ]: 0 : do
2319 : : {
2320 [ # # ]: 0 : if ( pCol->GetPrev() )
2321 : 0 : pCol = pCol->GetPrev();
2322 : : else
2323 : : {
2324 : 0 : bGoOn = sal_False;
2325 : 0 : pCol = rThis.GetLeaf( MAKEPAGE_NONE, sal_False );
2326 : : }
2327 [ # # ]: 0 : if ( pCol )
2328 : : {
2329 : : // ColumnFrms now with BodyFrm
2330 : 0 : SwLayoutFrm* pColBody = pCol->IsColumnFrm() ?
2331 : : (SwLayoutFrm*)((SwLayoutFrm*)pCol)->Lower() :
2332 [ # # ]: 0 : (SwLayoutFrm*)pCol;
2333 [ # # ]: 0 : if ( pColBody->ContainsCntnt() )
2334 : : {
2335 : 0 : bGoOn = sal_False; // We have content here! we accept this
2336 : : // only if GetLeaf() has set the MoveBwdJump.
2337 [ # # ]: 0 : if( SwFlowFrm::IsMoveBwdJump() )
2338 : : {
2339 : 0 : pNewUpper = pColBody;
2340 : : // #i53139#
2341 : : // Now <pNewUpper> is a previous layout frame, which
2342 : : // contains content. But the new upper layout frame
2343 : : // has to be the next one.
2344 : : // #136024# - correct fix for i53139
2345 : : // Check for wrong page description before using next new upper.
2346 : : // #i66051# - further correction of fix for i53139
2347 : : // Check for correct type of new next upper layout frame
2348 : : // #136538# - another correction of fix for i53139
2349 : : // Beside type check, check also, if proposed new next upper
2350 : : // frame is inside the same frame types.
2351 : : // #i71065#
2352 : : // Check that the proposed new next upper layout
2353 : : // frame isn't the current one.
2354 : 0 : SwLayoutFrm* pNewNextUpper = pNewUpper->GetLeaf( MAKEPAGE_NONE, sal_True );
2355 [ # # ][ # # : 0 : if ( pNewNextUpper &&
# # # # #
# # # # #
# # # # ]
2356 : 0 : pNewNextUpper != rThis.GetUpper() &&
2357 : 0 : pNewNextUpper->GetType() == pNewUpper->GetType() &&
2358 : 0 : pNewNextUpper->IsInDocBody() == pNewUpper->IsInDocBody() &&
2359 : 0 : pNewNextUpper->IsInFtn() == pNewUpper->IsInFtn() &&
2360 : 0 : pNewNextUpper->IsInTab() == pNewUpper->IsInTab() &&
2361 : 0 : pNewNextUpper->IsInSct() == pNewUpper->IsInSct() &&
2362 : 0 : !rThis.WrongPageDesc( pNewNextUpper->FindPageFrm() ) )
2363 : : {
2364 : 0 : pNewUpper = pNewNextUpper;
2365 : : }
2366 : : }
2367 : : }
2368 : : else
2369 : : {
2370 [ # # ]: 0 : if( pNewUpper ) // We already had an empty column, in other
2371 : 0 : bJump = sal_True; // words we skipped one.
2372 : 0 : pNewUpper = pColBody; // this empty column could be considered,
2373 : : // but we continue searching nevertheless.
2374 : : }
2375 : : }
2376 : : } while( bGoOn );
2377 [ # # ]: 0 : if( bJump )
2378 : 0 : SwFlowFrm::SetMoveBwdJump( sal_True );
2379 : : }
2380 : : }
2381 : : else // No breaks - we can flow back.
2382 : 12584 : pNewUpper = rThis.GetLeaf( MAKEPAGE_NONE, sal_False );
2383 : :
2384 : : // #i27801# - no move backward of 'master' text frame,
2385 : : // if - due to its object positioning - it isn't allowed to be on the new page frame
2386 : : // #i44049# - add another condition for not moving backward
2387 : : // If one of its objects has restarted the layout process, moving backward
2388 : : // isn't sensible either.
2389 : : // #i47697# - refine condition made for issue i44049
2390 : : // - allow move backward as long as the anchored object is only temporarily
2391 : : // positions considering its wrapping style.
2392 [ + + + - : 16842 : if ( pNewUpper &&
+ + ][ + + ]
2393 : 3996 : rThis.IsTxtFrm() && !IsFollow() )
2394 : : {
2395 : 88 : sal_uInt32 nToPageNum( 0L );
2396 : : const bool bMoveFwdByObjPos = SwLayouter::FrmMovedFwdByObjPos(
2397 [ + - ]: 88 : *(pOldPage->GetFmt()->GetDoc()),
2398 : : static_cast<SwTxtFrm&>(rThis),
2399 [ + - ]: 88 : nToPageNum );
2400 [ - + # # ]: 88 : if ( bMoveFwdByObjPos &&
[ - + ]
2401 [ # # ]: 0 : pNewUpper->FindPageFrm()->GetPhyPageNum() < nToPageNum )
2402 : : {
2403 : 0 : pNewUpper = 0;
2404 : : }
2405 : : // #i44049# - check, if one of its anchored objects
2406 : : // has restarted the layout process.
2407 [ - + ]: 88 : else if ( rThis.GetDrawObjs() )
2408 : : {
2409 : 0 : sal_uInt32 i = 0;
2410 [ # # ][ # # ]: 88 : for ( ; i < rThis.GetDrawObjs()->Count(); ++i )
2411 : : {
2412 [ # # ]: 0 : SwAnchoredObject* pAnchoredObj = (*rThis.GetDrawObjs())[i];
2413 : : // #i47697# - refine condition - see above
2414 [ # # ][ # # ]: 0 : if ( pAnchoredObj->RestartLayoutProcess() &&
[ # # ][ # # ]
2415 [ # # ]: 0 : !pAnchoredObj->IsTmpConsiderWrapInfluence() )
2416 : : {
2417 : 0 : pNewUpper = 0;
2418 : 0 : break;
2419 : : }
2420 : : }
2421 : : }
2422 : : }
2423 : :
2424 : : // With Follows, it's only allowed to flow back if there's no neighbor
2425 : : // in the new environment (because that would be the Master).
2426 : : // (6677) If however we skipped empty pages, we still have to move.
2427 [ + + ][ + + ]: 12846 : if ( pNewUpper && IsFollow() && pNewUpper->Lower() )
[ + - ][ + + ]
2428 : : {
2429 : : // #i79774#
2430 : : // neglect empty sections in proposed new upper frame
2431 : 1910 : bool bProposedNewUpperContainsOnlyEmptySections( true );
2432 : : {
2433 : 1910 : const SwFrm* pLower( pNewUpper->Lower() );
2434 [ + - ]: 1910 : while ( pLower )
2435 : : {
2436 [ - + # # ]: 1910 : if ( pLower->IsSctFrm() &&
[ - + ]
2437 [ # # ]: 0 : !dynamic_cast<const SwSectionFrm*>(pLower)->GetSection() )
2438 : : {
2439 : 0 : pLower = pLower->GetNext();
2440 : 0 : continue;
2441 : : }
2442 : : else
2443 : : {
2444 : 1910 : bProposedNewUpperContainsOnlyEmptySections = false;
2445 : 1910 : break;
2446 : : }
2447 : : }
2448 : : }
2449 [ + - ]: 1910 : if ( !bProposedNewUpperContainsOnlyEmptySections )
2450 : : {
2451 [ - + ]: 1910 : if ( SwFlowFrm::IsMoveBwdJump() )
2452 : : {
2453 : : // Don't move after the Master, but into the next empty page.
2454 : 0 : SwFrm *pFrm = pNewUpper->Lower();
2455 [ # # ]: 0 : while ( pFrm->GetNext() )
2456 : 0 : pFrm = pFrm->GetNext();
2457 : 0 : pNewUpper = pFrm->GetLeaf( MAKEPAGE_INSERT, sal_True );
2458 [ # # ]: 0 : if( pNewUpper == rThis.GetUpper() ) // Did we end up in the same place?
2459 : 0 : pNewUpper = NULL; // If so, moving is not needed.
2460 : : }
2461 : : else
2462 : 1910 : pNewUpper = 0;
2463 : : }
2464 : : }
2465 [ + + ][ + + ]: 12846 : if ( pNewUpper && !ShouldBwdMoved( pNewUpper, sal_True, rbReformat ) )
[ + + ]
2466 : : {
2467 [ - + ]: 14 : if( !pNewUpper->Lower() )
2468 : : {
2469 [ # # ]: 0 : if( pNewUpper->IsFtnContFrm() )
2470 : : {
2471 : 0 : pNewUpper->Cut();
2472 [ # # ]: 0 : delete pNewUpper;
2473 : : }
2474 : : else
2475 : : {
2476 : 0 : SwSectionFrm* pSectFrm = pNewUpper->FindSctFrm();
2477 : : // #126020# - adjust check for empty section
2478 : : // #130797# - correct fix #126020#
2479 [ # # # # : 0 : if ( pSectFrm && !pSectFrm->IsColLocked() &&
# # ][ # # ]
[ # # ]
2480 : 0 : !pSectFrm->ContainsCntnt() && !pSectFrm->ContainsAny( true ) )
2481 : : {
2482 : 0 : pSectFrm->DelEmpty( sal_True );
2483 [ # # ]: 0 : delete pSectFrm;
2484 : 0 : rThis.bValidPos = sal_True;
2485 : : }
2486 : : }
2487 : : }
2488 : 14 : pNewUpper = 0;
2489 : : }
2490 : :
2491 : : // OD 2004-05-26 #i21478# - don't move backward, if flow frame wants to
2492 : : // keep with next frame and next frame is locked.
2493 : : // #i38232# - If next frame is a table, do *not* check,
2494 : : // if it's locked.
2495 [ + + ][ + - : 12934 : if ( pNewUpper && !IsFollow() &&
+ + + - ]
[ + + ]
2496 : 88 : rThis.GetAttrSet()->GetKeep().GetValue() && rThis.GetIndNext() )
2497 : : {
2498 : 14 : SwFrm* pIndNext = rThis.GetIndNext();
2499 : : // #i38232#
2500 [ + - ]: 14 : if ( !pIndNext->IsTabFrm() )
2501 : : {
2502 : : // get first content of section, while empty sections are skipped
2503 [ + - ][ + + ]: 28 : while ( pIndNext && pIndNext->IsSctFrm() )
[ + + ]
2504 : : {
2505 [ + - ]: 14 : if( static_cast<SwSectionFrm*>(pIndNext)->GetSection() )
2506 : : {
2507 : 14 : SwFrm* pTmp = static_cast<SwSectionFrm*>(pIndNext)->ContainsAny();
2508 [ - + ]: 14 : if ( pTmp )
2509 : : {
2510 : 0 : pIndNext = pTmp;
2511 : 0 : break;
2512 : : }
2513 : : }
2514 : 14 : pIndNext = pIndNext->GetIndNext();
2515 : : }
2516 : : OSL_ENSURE( !pIndNext || pIndNext->ISA(SwTxtFrm),
2517 : : "<SwFlowFrm::MovedBwd(..)> - incorrect next found." );
2518 [ + - ]: 28 : if ( pIndNext && pIndNext->IsFlowFrm() &&
[ + - - + ]
[ - + ]
2519 : 14 : SwFlowFrm::CastFlowFrm(pIndNext)->IsJoinLocked() )
2520 : : {
2521 : 0 : pNewUpper = 0L;
2522 : : }
2523 : : }
2524 : : }
2525 : :
2526 : : // #i65250#
2527 : : // layout loop control for flowing content again and again moving
2528 : : // backward under the same layout condition.
2529 [ + + ][ + - : 12994 : if ( pNewUpper && !IsFollow() &&
+ - - + ]
[ - + ]
2530 : 74 : pNewUpper != rThis.GetUpper() &&
2531 : 74 : SwLayouter::MoveBwdSuppressed( *(pOldPage->GetFmt()->GetDoc()),
2532 : 74 : *this, *pNewUpper ) )
2533 : : {
2534 : : SwLayoutFrm* pNextNewUpper = pNewUpper->GetLeaf(
2535 : 0 : ( !rThis.IsSctFrm() && rThis.IsInSct() )
2536 : : ? MAKEPAGE_NOSECTION
2537 : : : MAKEPAGE_NONE,
2538 [ # # # # ]: 0 : sal_True );
2539 : : // #i73194# - make code robust
2540 : : OSL_ENSURE( pNextNewUpper, "<SwFlowFrm::MoveBwd(..)> - missing next new upper" );
2541 [ # # ][ # # : 0 : if ( pNextNewUpper &&
# # # # ]
2542 : 0 : ( pNextNewUpper == rThis.GetUpper() ||
2543 : 0 : pNextNewUpper->GetType() != rThis.GetUpper()->GetType() ) )
2544 : : {
2545 : 0 : pNewUpper = 0L;
2546 : : OSL_FAIL( "<SwFlowFrm::MoveBwd(..)> - layout loop control for layout action <Move Backward> applied!" );
2547 : : }
2548 : : }
2549 : :
2550 : : OSL_ENSURE( pNewUpper != rThis.GetUpper(),
2551 : : "<SwFlowFrm::MoveBwd(..)> - moving backward to the current upper frame!? -> Please inform OD." );
2552 [ + + ]: 12846 : if ( pNewUpper )
2553 : : {
2554 : : PROTOCOL_ENTER( &rThis, PROT_MOVE_BWD, 0, 0 );
2555 [ - + ]: 74 : if ( pNewUpper->IsFtnContFrm() )
2556 : : {
2557 : : //Kann sein, dass ich einen Container bekam.
2558 : 0 : SwFtnFrm *pOld = rThis.FindFtnFrm();
2559 : 0 : SwFtnFrm *pNew = new SwFtnFrm( pOld->GetFmt(), pOld,
2560 [ # # ]: 0 : pOld->GetRef(), pOld->GetAttr() );
2561 [ # # ]: 0 : if ( pOld->GetMaster() )
2562 : : {
2563 : 0 : pNew->SetMaster( pOld->GetMaster() );
2564 : 0 : pOld->GetMaster()->SetFollow( pNew );
2565 : : }
2566 : 0 : pNew->SetFollow( pOld );
2567 : 0 : pOld->SetMaster( pNew );
2568 : 0 : pNew->Paste( pNewUpper );
2569 : 0 : pNewUpper = pNew;
2570 : : }
2571 [ - + ][ # # ]: 74 : if( pNewUpper->IsFtnFrm() && rThis.IsInSct() )
[ - + ]
2572 : : {
2573 : 0 : SwSectionFrm* pSct = rThis.FindSctFrm();
2574 : : // If we're in a section of a footnote, we may need to create
2575 : : // a SwSectionFrm in the new upper
2576 [ # # ]: 0 : if( pSct->IsInFtn() )
2577 : : {
2578 : 0 : SwFrm* pTmp = pNewUpper->Lower();
2579 [ # # ]: 0 : if( pTmp )
2580 : : {
2581 [ # # ]: 0 : while( pTmp->GetNext() )
2582 : 0 : pTmp = pTmp->GetNext();
2583 [ # # # # ]: 0 : if( !pTmp->IsSctFrm() ||
[ # # ]
2584 : 0 : ((SwSectionFrm*)pTmp)->GetFollow() != pSct )
2585 : 0 : pTmp = NULL;
2586 : : }
2587 [ # # ]: 0 : if( pTmp )
2588 : 0 : pNewUpper = (SwSectionFrm*)pTmp;
2589 : : else
2590 : : {
2591 [ # # ]: 0 : pSct = new SwSectionFrm( *pSct, sal_True );
2592 : 0 : pSct->Paste( pNewUpper );
2593 : 0 : pSct->Init();
2594 : 0 : pNewUpper = pSct;
2595 : 0 : pSct->SimpleFormat();
2596 : : }
2597 : : }
2598 : : }
2599 : 74 : sal_Bool bUnlock = sal_False;
2600 : 74 : sal_Bool bFollow = sal_False;
2601 : : // Lock section. Otherwise, it could get destroyed if the only Cntnt
2602 : : // moves e.g. from the second into the first column.
2603 : 74 : SwSectionFrm* pSect = pNewUpper->FindSctFrm();
2604 [ + + ]: 74 : if( pSect )
2605 : : {
2606 : 42 : bUnlock = !pSect->IsColLocked();
2607 : 42 : pSect->ColLock();
2608 : 42 : bFollow = pSect->HasFollow();
2609 : : }
2610 : 74 : pNewUpper->Calc();
2611 : 74 : rThis.Cut();
2612 : : //
2613 : : // optimization: format section, if its size is invalidated and if it's
2614 : : // the new parent of moved backward frame.
2615 : 74 : bool bFormatSect( false );
2616 [ + + ]: 74 : if( bUnlock )
2617 : : {
2618 : 16 : pSect->ColUnlock();
2619 [ + + ]: 16 : if( pSect->HasFollow() != bFollow )
2620 : : {
2621 : 14 : pSect->InvalidateSize();
2622 : : // - optimization
2623 [ + - ]: 14 : if ( pSect == pNewUpper )
2624 : 14 : bFormatSect = true;
2625 : : }
2626 : : }
2627 : :
2628 : 74 : rThis.Paste( pNewUpper );
2629 : : // - optimization
2630 [ + + ]: 74 : if ( bFormatSect )
2631 : 14 : pSect->Calc();
2632 : :
2633 : 74 : SwPageFrm *pNewPage = rThis.FindPageFrm();
2634 [ + - ]: 74 : if( pNewPage != pOldPage )
2635 : : {
2636 : 74 : rThis.Prepare( PREP_BOSS_CHGD, (const void*)pOldPage, sal_False );
2637 : 74 : ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
2638 [ + - ][ + - ]: 74 : if ( pSh && !pSh->Imp()->IsUpdateExpFlds() )
[ + - ]
2639 : 74 : pSh->GetDoc()->SetNewFldLst(true); // Will be done by CalcLayout() later on
2640 : :
2641 : 74 : pNewPage->InvalidateSpelling();
2642 : 74 : pNewPage->InvalidateSmartTags(); // SMARTTAGS
2643 : 74 : pNewPage->InvalidateAutoCompleteWords();
2644 : 74 : pNewPage->InvalidateWordCount();
2645 : :
2646 : : // OD 30.10.2002 #97265# - no <CheckPageDesc(..)> in online layout
2647 [ + - ][ + - ]: 74 : if ( !( pSh && pSh->GetViewOptions()->getBrowseMode() ) )
[ + - ]
2648 : : {
2649 [ - + ][ # # ]: 74 : if ( bCheckPageDescs && pNewPage->GetNext() )
[ - + ]
2650 : : {
2651 : : SwPageFrm* pStartPage = bCheckPageDescOfNextPage ?
2652 : : pNewPage :
2653 [ # # ]: 0 : (SwPageFrm*)pNewPage->GetNext();
2654 : 0 : SwFrm::CheckPageDescs( pStartPage, sal_False);
2655 : : }
2656 [ - + ]: 74 : else if ( rThis.GetAttrSet()->GetPageDesc().GetPageDesc() )
2657 : : {
2658 : : // First page could get empty for example by disabling
2659 : : // a section
2660 : 0 : SwFrm::CheckPageDescs( (SwPageFrm*)pNewPage, sal_False);
2661 : : }
2662 : : }
2663 : : }
2664 : : }
2665 : 12901 : return pNewUpper != 0;
2666 : : }
2667 : :
2668 : : /*************************************************************************
2669 : : |*
2670 : : |* SwFlowFrm::CastFlowFrm
2671 : : |*
2672 : : |*************************************************************************/
2673 : :
2674 : 591892 : SwFlowFrm *SwFlowFrm::CastFlowFrm( SwFrm *pFrm )
2675 : : {
2676 [ + + ]: 591892 : if ( pFrm->IsCntntFrm() )
2677 [ + - ]: 589896 : return (SwCntntFrm*)pFrm;
2678 [ + + ]: 1996 : if ( pFrm->IsTabFrm() )
2679 [ + - ]: 1756 : return (SwTabFrm*)pFrm;
2680 [ + - ]: 240 : if ( pFrm->IsSctFrm() )
2681 [ + - ]: 240 : return (SwSectionFrm*)pFrm;
2682 : 591892 : return 0;
2683 : : }
2684 : :
2685 : 163 : const SwFlowFrm *SwFlowFrm::CastFlowFrm( const SwFrm *pFrm )
2686 : : {
2687 [ + + ]: 163 : if ( pFrm->IsCntntFrm() )
2688 [ + - ]: 131 : return (SwCntntFrm*)pFrm;
2689 [ + - ]: 32 : if ( pFrm->IsTabFrm() )
2690 [ + - ]: 32 : return (SwTabFrm*)pFrm;
2691 [ # # ]: 0 : if ( pFrm->IsSctFrm() )
2692 [ # # ]: 0 : return (SwSectionFrm*)pFrm;
2693 : 163 : return 0;
2694 : : }
2695 : :
2696 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|