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