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