1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 #include "pam.hxx"
27 #include "swtable.hxx"
28 #include "frame.hxx"
29 #include "rootfrm.hxx"
30 #include "pagefrm.hxx"
31 #include "flyfrm.hxx"
32 #include "viewsh.hxx"
33 #include "doc.hxx"
34 #include "viewimp.hxx"
35 #include "viewopt.hxx"
36 #include "dflyobj.hxx"
37 #include "frmtool.hxx"
38 #include "dcontact.hxx"
39 #include <editeng/brkitem.hxx>
40 #include <editeng/keepitem.hxx>
41 #include <fmtsrnd.hxx>
42 #include <fmtanchr.hxx>
43 #include <fmtpdsc.hxx>
44 #include <editeng/ulspitem.hxx>
45 #include <tgrditem.hxx>
46 #include <txtftn.hxx>
47 #include <fmtftn.hxx>
48 #include <editeng/pgrditem.hxx>
49 #include <paratr.hxx>
50 #include "ftnfrm.hxx"
51 #include "txtfrm.hxx"
52 #include "tabfrm.hxx"
53 #include "pagedesc.hxx"
54 #include "layact.hxx"
55 #include "fmtornt.hxx"
56 #include "flyfrms.hxx"
57 #include "sectfrm.hxx"
58 #include "section.hxx"
59 #include "dbg_lay.hxx"
60 #include "lineinfo.hxx"
61 #include <fmtclbl.hxx>
62 #include <sortedobjs.hxx>
63 #include <layouter.hxx>
64 #include <fmtfollowtextflow.hxx>
65 #include <switerator.hxx>
66
67 sal_Bool SwFlowFrm::bMoveBwdJump = sal_False;
68
69
70 /*************************************************************************
71 |*
72 |* SwFlowFrm::SwFlowFrm()
73 |*
74 |* Ersterstellung MA 26. Apr. 95
75 |* Letzte Aenderung MA 26. Apr. 95
76 |*
77 |*************************************************************************/
78
79
SwFlowFrm(SwFrm & rFrm)80 SwFlowFrm::SwFlowFrm( SwFrm &rFrm ) :
81 rThis( rFrm ),
82 pFollow( 0 )
83 {
84 bLockJoin = bIsFollow = bCntntLock = bOwnFtnNum =
85 bFtnLock = bFlyLock = sal_False;
86 }
87
88
89 /*************************************************************************
90 |*
91 |* SwFlowFrm::IsFollowLocked()
92 |* return sal_True if any follow has the JoinLocked flag
93 |*
94 |*************************************************************************/
95
HasLockedFollow() const96 sal_Bool SwFlowFrm::HasLockedFollow() const
97 {
98 const SwFlowFrm* pFrm = GetFollow();
99 while( pFrm )
100 {
101 if( pFrm->IsJoinLocked() )
102 return sal_True;
103 pFrm = pFrm->GetFollow();
104 }
105 return sal_False;
106 }
107
108 /*************************************************************************
109 |*
110 |* SwFlowFrm::IsKeepFwdMoveAllowed()
111 |*
112 |* Ersterstellung MA 20. Jul. 94
113 |* Letzte Aenderung MA 16. May. 95
114 |*
115 |*************************************************************************/
116
117
IsKeepFwdMoveAllowed()118 sal_Bool SwFlowFrm::IsKeepFwdMoveAllowed()
119 {
120 //Wenn der Vorgaenger das KeepAttribut traegt und auch dessen
121 //Vorgaenger usw. bis zum ersten der Kette und fuer diesen das
122 //IsFwdMoveAllowed ein sal_False liefert, so ist das Moven eben nicht erlaubt.
123 SwFrm *pFrm = &rThis;
124 if ( !pFrm->IsInFtn() )
125 do
126 { if ( pFrm->GetAttrSet()->GetKeep().GetValue() )
127 pFrm = pFrm->GetIndPrev();
128 else
129 return sal_True;
130 } while ( pFrm );
131
132 //Siehe IsFwdMoveAllowed()
133 sal_Bool bRet = sal_False;
134 if ( pFrm && pFrm->GetIndPrev() )
135 bRet = sal_True;
136 return bRet;
137 }
138
139 /*************************************************************************
140 |*
141 |* SwFlowFrm::CheckKeep()
142 |*
143 |* Beschreibung
144 |* Ersterstellung MA 20. Jun. 95
145 |* Letzte Aenderung MA 09. Apr. 97
146 |*
147 |*************************************************************************/
148
149
CheckKeep()150 void SwFlowFrm::CheckKeep()
151 {
152 //Den 'letzten' Vorgaenger mit KeepAttribut anstossen, denn
153 //die ganze Truppe koennte zuruckrutschen.
154 SwFrm *pPre = rThis.GetIndPrev();
155 if( pPre->IsSctFrm() )
156 {
157 SwFrm *pLast = ((SwSectionFrm*)pPre)->FindLastCntnt();
158 if( pLast && pLast->FindSctFrm() == pPre )
159 pPre = pLast;
160 else
161 return;
162 }
163 SwFrm* pTmp;
164 sal_Bool bKeep;
165 while ( sal_True == (bKeep = pPre->GetAttrSet()->GetKeep().GetValue()) &&
166 0 != ( pTmp = pPre->GetIndPrev() ) )
167 {
168 if( pTmp->IsSctFrm() )
169 {
170 SwFrm *pLast = ((SwSectionFrm*)pTmp)->FindLastCntnt();
171 if( pLast && pLast->FindSctFrm() == pTmp )
172 pTmp = pLast;
173 else
174 break;
175 }
176 pPre = pTmp;
177 }
178 if ( bKeep )
179 pPre->InvalidatePos();
180 }
181
182 /*************************************************************************
183 |*
184 |* SwFlowFrm::IsKeep()
185 |*
186 |* Ersterstellung MA 09. Apr. 97
187 |* Letzte Aenderung MA 09. Apr. 97
188 |*
189 |*************************************************************************/
190
IsKeep(const SwAttrSet & rAttrs,bool bCheckIfLastRowShouldKeep) const191 sal_Bool SwFlowFrm::IsKeep( const SwAttrSet& rAttrs, bool bCheckIfLastRowShouldKeep ) const
192 {
193 // 1. The keep attribute is ignored inside footnotes
194 // 2. For compatibility reasons, the keep attribute is
195 // ignored for frames inside table cells
196 // 3. If bBreakCheck is set to true, this function only checks
197 // if there are any break after attributes set at rAttrs
198 // or break before attributes set for the next content (or next table)
199 sal_Bool bKeep = bCheckIfLastRowShouldKeep ||
200 ( !rThis.IsInFtn() &&
201 ( !rThis.IsInTab() || rThis.IsTabFrm() ) &&
202 rAttrs.GetKeep().GetValue() );
203
204 ASSERT( !bCheckIfLastRowShouldKeep || rThis.IsTabFrm(),
205 "IsKeep with bCheckIfLastRowShouldKeep should only be used for tabfrms" )
206
207 // Ignore keep attribute if there are break situations:
208 if ( bKeep )
209 {
210 switch ( rAttrs.GetBreak().GetBreak() )
211 {
212 case SVX_BREAK_COLUMN_AFTER:
213 case SVX_BREAK_COLUMN_BOTH:
214 case SVX_BREAK_PAGE_AFTER:
215 case SVX_BREAK_PAGE_BOTH:
216 {
217 bKeep = sal_False;
218 }
219 default: break;
220 }
221 if ( bKeep )
222 {
223 SwFrm *pNxt;
224 if( 0 != (pNxt = rThis.FindNextCnt()) &&
225 (!pFollow || pNxt != pFollow->GetFrm()))
226 {
227 // --> FME 2006-05-15 #135914#
228 // The last row of a table only keeps with the next content
229 // it they are in the same section:
230 if ( bCheckIfLastRowShouldKeep )
231 {
232 const SwSection* pThisSection = 0;
233 const SwSection* pNextSection = 0;
234 const SwSectionFrm* pThisSectionFrm = rThis.FindSctFrm();
235 const SwSectionFrm* pNextSectionFrm = pNxt->FindSctFrm();
236
237 if ( pThisSectionFrm )
238 pThisSection = pThisSectionFrm->GetSection();
239
240 if ( pNextSectionFrm )
241 pNextSection = pNextSectionFrm->GetSection();
242
243 if ( pThisSection != pNextSection )
244 bKeep = sal_False;
245 }
246 // <--
247
248 if ( bKeep )
249 {
250 const SwAttrSet* pSet = NULL;
251
252 if ( pNxt->IsInTab() )
253 {
254 SwTabFrm* pTab = pNxt->FindTabFrm();
255 if ( ! rThis.IsInTab() || rThis.FindTabFrm() != pTab )
256 pSet = &pTab->GetFmt()->GetAttrSet();
257 }
258
259 if ( ! pSet )
260 pSet = pNxt->GetAttrSet();
261
262 ASSERT( pSet, "No AttrSet to check keep attribute" )
263
264 if ( pSet->GetPageDesc().GetPageDesc() )
265 bKeep = sal_False;
266 else switch ( pSet->GetBreak().GetBreak() )
267 {
268 case SVX_BREAK_COLUMN_BEFORE:
269 case SVX_BREAK_COLUMN_BOTH:
270 case SVX_BREAK_PAGE_BEFORE:
271 case SVX_BREAK_PAGE_BOTH:
272 bKeep = sal_False;
273 default: break;
274 }
275 }
276 }
277 }
278 }
279 return bKeep;
280 }
281
282 /*************************************************************************
283 |*
284 |* SwFlowFrm::BwdMoveNecessary()
285 |*
286 |* Ersterstellung MA 20. Jul. 94
287 |* Letzte Aenderung MA 02. May. 96
288 |*
289 |*************************************************************************/
290
291
BwdMoveNecessary(const SwPageFrm * pPage,const SwRect & rRect)292 sal_uInt8 SwFlowFrm::BwdMoveNecessary( const SwPageFrm *pPage, const SwRect &rRect )
293 {
294 // Der return-Wert entscheidet mit,
295 // ob auf Zurueckgeflossen werden muss, (3)
296 // ob das gute alte WouldFit gerufen werden kann (0, 1)
297 // oder ob ein Umhaengen und eine Probeformatierung sinnvoll ist (2)
298 // dabei bedeutet Bit 1, dass Objekte an mir selbst verankert sind
299 // und Bit 2, dass ich anderen Objekten ausweichen muss.
300
301 //Wenn ein SurroundObj, dass einen Umfluss wuenscht mit dem Rect ueberlappt
302 //ist der Fluss notwendig (weil die Verhaeltnisse nicht geschaetzt werden
303 //koennen), es kann allerdings ggf. eine TestFormatierung stattfinden.
304 //Wenn das SurroundObj ein Fly ist und ich selbst ein Lower bin oder der Fly
305 //Lower von mir ist, so spielt er keine Rolle.
306 //Wenn das SurroundObj in einem zeichengebunden Fly verankert ist, und ich
307 //selbst nicht Lower dieses Zeichengebundenen Flys bin, so spielt der Fly
308 //keine Rolle.
309 //#32639# Wenn das Objekt bei mir verankert ist kann ich es
310 //vernachlaessigen, weil es hoechstwahrscheinlich (!?) mitfliesst,
311 //eine TestFormatierung ist dann allerdings nicht erlaubt!
312 sal_uInt8 nRet = 0;
313 SwFlowFrm *pTmp = this;
314 do
315 { // Wenn an uns oder einem Follow Objekte haengen, so
316 // kann keine ProbeFormatierung stattfinden, da absatzgebundene
317 // nicht richtig beruecksichtigt wuerden und zeichengebundene sollten
318 // gar nicht zur Probe formatiert werden.
319 if( pTmp->GetFrm()->GetDrawObjs() )
320 nRet = 1;
321 pTmp = pTmp->GetFollow();
322 } while ( !nRet && pTmp );
323 if ( pPage->GetSortedObjs() )
324 {
325 // --> OD 2004-07-01 #i28701# - new type <SwSortedObjs>
326 const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
327 sal_uLong nIndex = ULONG_MAX;
328 for ( sal_uInt16 i = 0; nRet < 3 && i < rObjs.Count(); ++i )
329 {
330 // --> OD 2004-07-01 #i28701# - consider changed type of
331 // <SwSortedObjs> entries.
332 SwAnchoredObject* pObj = rObjs[i];
333 const SwFrmFmt& rFmt = pObj->GetFrmFmt();
334 const SwRect aRect( pObj->GetObjRect() );
335 if ( aRect.IsOver( rRect ) &&
336 rFmt.GetSurround().GetSurround() != SURROUND_THROUGHT )
337 {
338 if( rThis.IsLayoutFrm() && //Fly Lower von This?
339 Is_Lower_Of( &rThis, pObj->GetDrawObj() ) )
340 continue;
341 if( pObj->ISA(SwFlyFrm) )
342 {
343 const SwFlyFrm *pFly = static_cast<const SwFlyFrm*>(pObj);
344 if ( pFly->IsAnLower( &rThis ) )//This Lower vom Fly?
345 continue;
346 }
347
348 const SwFrm* pAnchor = pObj->GetAnchorFrm();
349 if ( pAnchor == &rThis )
350 {
351 nRet |= 1;
352 continue;
353 }
354
355 //Nicht wenn das Objekt im Textfluss hinter mir verankert ist,
356 //denn dann weiche ich ihm nicht aus.
357 if ( ::IsFrmInSameKontext( pAnchor, &rThis ) )
358 {
359 if ( rFmt.GetAnchor().GetAnchorId() == FLY_AT_PARA )
360 {
361 // Den Index des anderen erhalten wir immer ueber das Ankerattr.
362 sal_uLong nTmpIndex = rFmt.GetAnchor().GetCntntAnchor()->nNode.GetIndex();
363 // Jetzt wird noch ueberprueft, ob der aktuelle Absatz vor dem
364 // Anker des verdraengenden Objekts im Text steht, dann wird
365 // nicht ausgewichen.
366 // Der Index wird moeglichst ueber einen SwFmtAnchor ermittelt,
367 // da sonst recht teuer.
368 if( ULONG_MAX == nIndex )
369 {
370 const SwNode *pNode;
371 if ( rThis.IsCntntFrm() )
372 pNode = ((SwCntntFrm&)rThis).GetNode();
373 else if( rThis.IsSctFrm() )
374 pNode = ((SwSectionFmt*)((SwSectionFrm&)rThis).
375 GetFmt())->GetSectionNode();
376 else
377 {
378 ASSERT( rThis.IsTabFrm(), "new FowFrm?" );
379 pNode = ((SwTabFrm&)rThis).GetTable()->
380 GetTabSortBoxes()[0]->GetSttNd()->FindTableNode();
381 }
382 nIndex = pNode->GetIndex();
383 }
384 if( nIndex < nTmpIndex )
385 continue;
386 }
387 }
388 else
389 continue;
390
391 nRet |= 2;
392 }
393 }
394 }
395 return nRet;
396 }
397
398 /*************************************************************************
399 |*
400 |* SwFlowFrm::CutTree(), PasteTree(), MoveSubTree()
401 |*
402 |* Beschreibung Eine Spezialisierte Form des Cut() und Paste(), die
403 |* eine ganze Kette umhaengt (naehmlich this und folgende). Dabei werden
404 |* nur minimale Operationen und Benachrichtigungen ausgefuehrt.
405 |* Ersterstellung MA 18. Mar. 93
406 |* Letzte Aenderung MA 18. May. 95
407 |*
408 |*************************************************************************/
409
410
CutTree(SwFrm * pStart)411 SwLayoutFrm *SwFlowFrm::CutTree( SwFrm *pStart )
412 {
413 //Der Start und alle Nachbarn werden ausgeschnitten, sie werden aneinander-
414 //gereiht und ein Henkel auf den ersten wird zurueckgeliefert.
415 //Zurueckbleibende werden geeignet invalidiert.
416
417 SwLayoutFrm *pLay = pStart->GetUpper();
418 if ( pLay->IsInFtn() )
419 pLay = pLay->FindFtnFrm();
420
421 // --> OD 2006-05-08 #i58846#
422 // <pPrepare( PREP_QUOVADIS )> only for frames in footnotes
423 if( pStart->IsInFtn() )
424 {
425 SwFrm* pTmp = pStart->GetIndPrev();
426 if( pTmp )
427 pTmp->Prepare( PREP_QUOVADIS );
428 }
429 // <--
430
431 //Nur fix auschneiden und zwar so, dass klare Verhaeltnisse bei den
432 //Verlassenen herrschen. Die Pointer der ausgeschnittenen Kette zeigen
433 //noch wer weiss wo hin.
434 if ( pStart == pStart->GetUpper()->Lower() )
435 pStart->GetUpper()->pLower = 0;
436 if ( pStart->GetPrev() )
437 {
438 pStart->GetPrev()->pNext = 0;
439 pStart->pPrev = 0;
440 }
441
442 if ( pLay->IsFtnFrm() )
443 {
444 if ( !pLay->Lower() && !pLay->IsColLocked() &&
445 !((SwFtnFrm*)pLay)->IsBackMoveLocked() )
446 {
447 pLay->Cut();
448 delete pLay;
449 }
450 else
451 {
452 sal_Bool bUnlock = !((SwFtnFrm*)pLay)->IsBackMoveLocked();
453 ((SwFtnFrm*)pLay)->LockBackMove();
454 pLay->InvalidateSize();
455 pLay->Calc();
456 SwCntntFrm *pCnt = pLay->ContainsCntnt();
457 while ( pCnt && pLay->IsAnLower( pCnt ) )
458 {
459 //Kann sein, dass der CntFrm gelockt ist, wir wollen hier nicht
460 //in eine endlose Seitenwanderung hineinlaufen und rufen das
461 //Calc garnicht erst!
462 ASSERT( pCnt->IsTxtFrm(), "Die Graphic ist gelandet." );
463 if ( ((SwTxtFrm*)pCnt)->IsLocked() ||
464 ((SwTxtFrm*)pCnt)->GetFollow() == pStart )
465 break;
466 pCnt->Calc();
467 pCnt = pCnt->GetNextCntntFrm();
468 }
469 if( bUnlock )
470 ((SwFtnFrm*)pLay)->UnlockBackMove();
471 }
472 pLay = 0;
473 }
474 return pLay;
475 }
476
477
478
PasteTree(SwFrm * pStart,SwLayoutFrm * pParent,SwFrm * pSibling,SwFrm * pOldParent)479 sal_Bool SwFlowFrm::PasteTree( SwFrm *pStart, SwLayoutFrm *pParent, SwFrm *pSibling,
480 SwFrm *pOldParent )
481 {
482 //returnt sal_True wenn in der Kette ein LayoutFrm steht.
483 sal_Bool bRet = sal_False;
484
485 //Die mit pStart beginnende Kette wird vor den Sibling unter den Parent
486 //gehaengt. Fuer geeignete Invalidierung wird ebenfalls gesorgt.
487
488 //Ich bekomme eine fertige Kette. Der Anfang der Kette muss verpointert
489 //werden, dann alle Upper fuer die Kette und schliesslich dass Ende.
490 //Unterwegs werden alle geeignet invalidiert.
491 if ( pSibling )
492 {
493 if ( 0 != (pStart->pPrev = pSibling->GetPrev()) )
494 pStart->GetPrev()->pNext = pStart;
495 else
496 pParent->pLower = pStart;
497 pSibling->_InvalidatePos();
498 pSibling->_InvalidatePrt();
499 }
500 else
501 {
502 if ( 0 == (pStart->pPrev = pParent->Lower()) )
503 pParent->pLower = pStart;
504 else
505 //Modified for #i100782#,04/03/2009
506 //If the pParent has more than 1 child nodes, former design will
507 //ignore them directly without any collection work. It will make some
508 //dangling pointers. This lead the crash...
509 //The new design will find the last child of pParent in loop way, and
510 //add the pStart after the last child.
511 // pParent->Lower()->pNext = pStart;
512 {
513 SwFrm* pTemp = pParent->pLower;
514 while (pTemp)
515 {
516 if (pTemp->pNext)
517 pTemp = pTemp->pNext;
518 else
519 {
520 pStart->pPrev = pTemp;
521 pTemp->pNext = pStart;
522 break;
523 }
524 }
525 }
526 //End modification for #i100782#,04/03/2009
527
528 // #i27145#
529 if ( pParent->IsSctFrm() )
530 {
531 // We have no sibling because pParent is a section frame and
532 // has just been created to contain some content. The printing
533 // area of the frame behind pParent has to be invalidated, so
534 // that the correct distance between pParent and the next frame
535 // can be calculated.
536 pParent->InvalidateNextPrtArea();
537 }
538 }
539 SwFrm *pFloat = pStart;
540 SwFrm *pLst = 0;
541 SWRECTFN( pParent )
542 SwTwips nGrowVal = 0;
543 do
544 { pFloat->pUpper = pParent;
545 pFloat->_InvalidateAll();
546 pFloat->CheckDirChange();
547
548 //Ich bin Freund des TxtFrm und darf deshalb so einiges. Das mit
549 //dem CacheIdx scheint etwas riskant!
550 if ( pFloat->IsTxtFrm() )
551 {
552 if ( ((SwTxtFrm*)pFloat)->GetCacheIdx() != USHRT_MAX )
553 ((SwTxtFrm*)pFloat)->Init(); //Ich bin sein Freund.
554 }
555 else
556 bRet = sal_True;
557
558 nGrowVal += (pFloat->Frm().*fnRect->fnGetHeight)();
559 if ( pFloat->GetNext() )
560 pFloat = pFloat->GetNext();
561 else
562 {
563 pLst = pFloat;
564 pFloat = 0;
565 }
566 } while ( pFloat );
567
568 if ( pSibling )
569 {
570 pLst->pNext = pSibling;
571 pSibling->pPrev = pLst;
572 if( pSibling->IsInFtn() )
573 {
574 if( pSibling->IsSctFrm() )
575 pSibling = ((SwSectionFrm*)pSibling)->ContainsAny();
576 if( pSibling )
577 pSibling->Prepare( PREP_ERGOSUM );
578 }
579 }
580 if ( nGrowVal )
581 {
582 if ( pOldParent && pOldParent->IsBodyFrm() ) //Fuer variable Seitenhoehe beim Browsen
583 pOldParent->Shrink( nGrowVal );
584 pParent->Grow( nGrowVal );
585 }
586
587 if ( pParent->IsFtnFrm() )
588 ((SwFtnFrm*)pParent)->InvalidateNxtFtnCnts( pParent->FindPageFrm() );
589 return bRet;
590 }
591
592
593
MoveSubTree(SwLayoutFrm * pParent,SwFrm * pSibling)594 void SwFlowFrm::MoveSubTree( SwLayoutFrm* pParent, SwFrm* pSibling )
595 {
596 ASSERT( pParent, "Kein Parent uebergeben." );
597 ASSERT( rThis.GetUpper(), "Wo kommen wir denn her?" );
598
599 //Sparsamer benachrichtigen wenn eine Action laeuft.
600 ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
601 const SwViewImp *pImp = pSh ? pSh->Imp() : 0;
602 const sal_Bool bComplete = pImp && pImp->IsAction() && pImp->GetLayAction().IsComplete();
603
604 if ( !bComplete )
605 {
606 SwFrm *pPre = rThis.GetIndPrev();
607 if ( pPre )
608 {
609 pPre->SetRetouche();
610 // --> OD 2004-11-23 #115759# - follow-up of #i26250#
611 // invalidate printing area of previous frame, if it's in a table
612 if ( pPre->GetUpper()->IsInTab() )
613 {
614 pPre->_InvalidatePrt();
615 }
616 // <--
617 pPre->InvalidatePage();
618 }
619 else
620 { rThis.GetUpper()->SetCompletePaint();
621 rThis.GetUpper()->InvalidatePage();
622 }
623 }
624
625 SwPageFrm *pOldPage = rThis.FindPageFrm();
626
627 SwLayoutFrm *pOldParent = CutTree( &rThis );
628 const sal_Bool bInvaLay = PasteTree( &rThis, pParent, pSibling, pOldParent );
629
630 // Wenn durch das Cut&Paste ein leerer SectionFrm entstanden ist, sollte
631 // dieser automatisch verschwinden.
632 SwSectionFrm *pSct;
633 // --> OD 2006-01-04 #126020# - adjust check for empty section
634 // --> OD 2006-02-01 #130797# - correct fix #126020#
635 if ( pOldParent && !pOldParent->Lower() &&
636 ( pOldParent->IsInSct() &&
637 !(pSct = pOldParent->FindSctFrm())->ContainsCntnt() &&
638 !pSct->ContainsAny( true ) ) )
639 // <--
640 {
641 pSct->DelEmpty( sal_False );
642 }
643
644 // In einem spaltigen Bereich rufen wir lieber kein Calc "von unten"
645 if( !rThis.IsInSct() &&
646 ( !rThis.IsInTab() || ( rThis.IsTabFrm() && !rThis.GetUpper()->IsInTab() ) ) )
647 rThis.GetUpper()->Calc();
648 else if( rThis.GetUpper()->IsSctFrm() )
649 {
650 SwSectionFrm* pTmpSct = (SwSectionFrm*)rThis.GetUpper();
651 sal_Bool bOld = pTmpSct->IsCntntLocked();
652 pTmpSct->SetCntntLock( sal_True );
653 pTmpSct->Calc();
654 if( !bOld )
655 pTmpSct->SetCntntLock( sal_False );
656 }
657 SwPageFrm *pPage = rThis.FindPageFrm();
658
659 if ( pOldPage != pPage )
660 {
661 rThis.InvalidatePage( pPage );
662 if ( rThis.IsLayoutFrm() )
663 {
664 SwCntntFrm *pCnt = ((SwLayoutFrm*)&rThis)->ContainsCntnt();
665 if ( pCnt )
666 pCnt->InvalidatePage( pPage );
667 }
668 else if ( pSh && pSh->GetDoc()->GetLineNumberInfo().IsRestartEachPage()
669 && pPage->FindFirstBodyCntnt() == &rThis )
670 {
671 rThis._InvalidateLineNum();
672 }
673 }
674 if ( bInvaLay || (pSibling && pSibling->IsLayoutFrm()) )
675 rThis.GetUpper()->InvalidatePage( pPage );
676 }
677
678 /*************************************************************************
679 |*
680 |* SwFlowFrm::IsAnFollow()
681 |*
682 |* Ersterstellung MA 26. Apr. 95
683 |* Letzte Aenderung MA 26. Apr. 95
684 |*
685 |*************************************************************************/
686
687
IsAnFollow(const SwFlowFrm * pAssumed) const688 sal_Bool SwFlowFrm::IsAnFollow( const SwFlowFrm *pAssumed ) const
689 {
690 const SwFlowFrm *pFoll = this;
691 do
692 { if ( pAssumed == pFoll )
693 return sal_True;
694 pFoll = pFoll->GetFollow();
695 } while ( pFoll );
696 return sal_False;
697 }
698
699
700 /*************************************************************************
701 |*
702 |* SwFlowFrm::FindMaster()
703 |*
704 |* Ersterstellung MA 26. Apr. 95
705 |* Letzte Aenderung MA 26. Apr. 95
706 |*
707 |*************************************************************************/
708
FindMaster() const709 SwTxtFrm* SwCntntFrm::FindMaster() const
710 {
711 ASSERT( IsFollow(), "SwCntntFrm::FindMaster(): !IsFollow" );
712
713 const SwCntntFrm* pCnt = GetPrevCntntFrm();
714
715 while ( pCnt )
716 {
717 if ( pCnt->HasFollow() && pCnt->GetFollow() == this )
718 {
719 ASSERT( pCnt->IsTxtFrm(), "NoTxtFrm with follow found" )
720 return (SwTxtFrm*)pCnt;
721 }
722 pCnt = pCnt->GetPrevCntntFrm();
723 }
724
725 ASSERT( sal_False, "Follow ist lost in Space." );
726 return 0;
727 }
728
FindMaster() const729 SwSectionFrm* SwSectionFrm::FindMaster() const
730 {
731 ASSERT( IsFollow(), "SwSectionFrm::FindMaster(): !IsFollow" );
732
733 SwIterator<SwSectionFrm,SwFmt> aIter( *pSection->GetFmt() );
734 SwSectionFrm* pSect = aIter.First();
735 while ( pSect )
736 {
737 if( pSect->GetFollow() == this )
738 return pSect;
739 pSect = aIter.Next();
740 }
741
742 ASSERT( sal_False, "Follow ist lost in Space." );
743 return 0;
744 }
745
FindMaster(bool bFirstMaster) const746 SwTabFrm* SwTabFrm::FindMaster( bool bFirstMaster ) const
747 {
748 ASSERT( IsFollow(), "SwTabFrm::FindMaster(): !IsFollow" );
749
750 SwIterator<SwTabFrm,SwFmt> aIter( *GetTable()->GetFrmFmt() );
751 SwTabFrm* pTab = aIter.First();
752 while ( pTab )
753 {
754 if ( bFirstMaster )
755 {
756 //
757 // Optimization. This makes code like this obsolete:
758 // while ( pTab->IsFollow() )
759 // pTab = pTab->FindMaster();
760 //
761 if ( !pTab->IsFollow() )
762 {
763 SwTabFrm* pNxt = pTab;
764 while ( pNxt )
765 {
766 if ( pNxt->GetFollow() == this )
767 return pTab;
768 pNxt = pNxt->GetFollow();
769 }
770 }
771 }
772 else
773 {
774 if ( pTab->GetFollow() == this )
775 return pTab;
776 }
777
778 pTab = aIter.Next();
779 }
780
781 ASSERT( sal_False, "Follow ist lost in Space." );
782 return 0;
783 }
784
785 /*************************************************************************
786 |*
787 |* SwFrm::GetLeaf()
788 |*
789 |* Beschreibung Liefert das naechste/vorhergehende LayoutBlatt,
790 |* das _nicht_ unterhalb von this liegt (oder gar this selbst ist).
791 |* Ausserdem muss dieses LayoutBlatt im gleichen Textfluss wie
792 |* pAnch Ausgangsfrm liegen (Body, Ftn)
793 |* Ersterstellung MA 25. Nov. 92
794 |* Letzte Aenderung MA 25. Apr. 95
795 |*
796 |*************************************************************************/
797
798
GetLeaf(MakePageType eMakePage,sal_Bool bFwd,const SwFrm * pAnch) const799 const SwLayoutFrm *SwFrm::GetLeaf( MakePageType eMakePage, sal_Bool bFwd,
800 const SwFrm *pAnch ) const
801 {
802 //Ohne Fluss kein genuss...
803 if ( !(IsInDocBody() || IsInFtn() || IsInFly()) )
804 return 0;
805
806 const SwFrm *pLeaf = this;
807 sal_Bool bFound = sal_False;
808
809 do
810 { pLeaf = ((SwFrm*)pLeaf)->GetLeaf( eMakePage, bFwd );
811
812 if ( pLeaf &&
813 (!IsLayoutFrm() || !((SwLayoutFrm*)this)->IsAnLower( pLeaf )))
814 {
815 if ( pAnch->IsInDocBody() == pLeaf->IsInDocBody() &&
816 pAnch->IsInFtn() == pLeaf->IsInFtn() )
817 {
818 bFound = sal_True;
819 }
820 }
821 } while ( !bFound && pLeaf );
822
823 return (const SwLayoutFrm*)pLeaf;
824 }
825
826 /*************************************************************************
827 |*
828 |* SwFrm::GetLeaf()
829 |*
830 |* Beschreibung Ruft Get[Next|Prev]Leaf
831 |*
832 |* Ersterstellung MA 20. Mar. 93
833 |* Letzte Aenderung MA 25. Apr. 95
834 |*
835 |*************************************************************************/
836
837
GetLeaf(MakePageType eMakePage,sal_Bool bFwd)838 SwLayoutFrm *SwFrm::GetLeaf( MakePageType eMakePage, sal_Bool bFwd )
839 {
840 if ( IsInFtn() )
841 return bFwd ? GetNextFtnLeaf( eMakePage ) : GetPrevFtnLeaf( eMakePage );
842
843 // --> OD 2005-08-16 #i53323#
844 // A frame could be inside a table AND inside a section.
845 // Thus, it has to be determined, which is the first parent.
846 bool bInTab( IsInTab() );
847 bool bInSct( IsInSct() );
848 if ( bInTab && bInSct )
849 {
850 const SwFrm* pUpperFrm( GetUpper() );
851 while ( pUpperFrm )
852 {
853 if ( pUpperFrm->IsTabFrm() )
854 {
855 // the table is the first.
856 bInSct = false;
857 break;
858 }
859 else if ( pUpperFrm->IsSctFrm() )
860 {
861 // the section is the first.
862 bInTab = false;
863 break;
864 }
865
866 pUpperFrm = pUpperFrm->GetUpper();
867 }
868 }
869
870 if ( bInTab && ( !IsTabFrm() || GetUpper()->IsCellFrm() ) ) // TABLE IN TABLE
871 return bFwd ? GetNextCellLeaf( eMakePage ) : GetPrevCellLeaf( eMakePage );
872
873 if ( bInSct )
874 return bFwd ? GetNextSctLeaf( eMakePage ) : GetPrevSctLeaf( eMakePage );
875 // <--
876
877 return bFwd ? GetNextLeaf( eMakePage ) : GetPrevLeaf( eMakePage );
878 }
879
880
881
WrongPageDesc(SwPageFrm * pNew)882 sal_Bool SwFrm::WrongPageDesc( SwPageFrm* pNew )
883 {
884 //Jetzt wirds leider etwas kompliziert:
885 //Ich bringe ich evtl. selbst
886 //einen Pagedesc mit; der der Folgeseite muss dann damit
887 //uebereinstimmen.
888 //Anderfalls muss ich mir etwas genauer ansehen wo der
889 //Folgepagedesc herkam.
890 //Wenn die Folgeseite selbst schon sagt, dass ihr
891 //Pagedesc nicht stimmt so kann ich das Teil bedenkenlos
892 //auswechseln.
893 //Wenn die Seite meint, dass ihr Pagedesc stimmt, so heisst
894 //das leider noch immer nicht, dass ich damit etwas anfangen
895 //kann: Wenn der erste BodyCntnt einen PageDesc oder einen
896 //PageBreak wuenscht, so muss ich ebenfalls eine neue
897 //Seite einfuegen; es sein denn die gewuenschte Seite ist
898 //die richtige.
899 //Wenn ich einen neue Seite eingefuegt habe, so fangen die
900 //Probleme leider erst an, denn wahrscheinlich wird die dann
901 //folgende Seite verkehrt gewesen und ausgewechselt worden
902 //sein. Das hat zur Folge, dass ich zwar eine neue (und
903 //jetzt richtige) Seite habe, die Bedingungen zum auswechseln
904 //aber leider noch immer stimmen.
905 //Ausweg: Vorlaeufiger Versuch, nur einmal eine neue Seite
906 //einsetzen (Leerseiten werden noetigenfalls bereits von
907 //InsertPage() eingefuegt.
908 const SwFmtPageDesc &rFmtDesc = GetAttrSet()->GetPageDesc();
909
910 //Mein Pagedesc zaehlt nicht, wenn ich ein Follow bin!
911 SwPageDesc *pDesc = 0;
912 sal_uInt16 nTmp = 0;
913 SwFlowFrm *pFlow = SwFlowFrm::CastFlowFrm( this );
914 if ( !pFlow || !pFlow->IsFollow() )
915 {
916 pDesc = (SwPageDesc*)rFmtDesc.GetPageDesc();
917 if( pDesc )
918 {
919 if( !pDesc->GetRightFmt() )
920 nTmp = 2;
921 else if( !pDesc->GetLeftFmt() )
922 nTmp = 1;
923 else if( rFmtDesc.GetNumOffset() )
924 nTmp = rFmtDesc.GetNumOffset();
925 }
926 }
927
928 //Bringt der Cntnt einen Pagedesc mit oder muss zaehlt die
929 //virtuelle Seitennummer des neuen Layoutleafs?
930 // Bei Follows zaehlt der PageDesc nicht
931 const sal_Bool bOdd = nTmp ? ( nTmp % 2 ? sal_True : sal_False )
932 : pNew->OnRightPage();
933 if ( !pDesc )
934 pDesc = pNew->FindPageDesc();
935 const SwFlowFrm *pNewFlow = pNew->FindFirstBodyCntnt();
936 // Haben wir uns selbst gefunden?
937 if( pNewFlow == pFlow )
938 pNewFlow = NULL;
939 if ( pNewFlow && pNewFlow->GetFrm()->IsInTab() )
940 pNewFlow = pNewFlow->GetFrm()->FindTabFrm();
941 const SwPageDesc *pNewDesc= ( pNewFlow && !pNewFlow->IsFollow() )
942 ? pNewFlow->GetFrm()->GetAttrSet()->GetPageDesc().GetPageDesc():0;
943
944 return ( pNew->GetPageDesc() != pDesc || // own desc ?
945 pNew->GetFmt() != (bOdd ? pDesc->GetRightFmt() : pDesc->GetLeftFmt()) ||
946 ( pNewDesc && pNewDesc == pDesc ) );
947 }
948
949
950 /*************************************************************************
951 |*
952 |* SwFrm::GetNextLeaf()
953 |*
954 |* Beschreibung Liefert das naechste LayoutBlatt in den das
955 |* Frame gemoved werden kann.
956 |*
957 |* Ersterstellung MA 16. Nov. 92
958 |* Letzte Aenderung MA 05. Dec. 96
959 |*
960 |*************************************************************************/
961
GetNextLeaf(MakePageType eMakePage)962 SwLayoutFrm *SwFrm::GetNextLeaf( MakePageType eMakePage )
963 {
964 ASSERT( !IsInFtn(), "GetNextLeaf(), don't call me for Ftn." );
965 ASSERT( !IsInSct(), "GetNextLeaf(), don't call me for Sections." );
966
967 const sal_Bool bBody = IsInDocBody(); //Wenn ich aus dem DocBody komme
968 //Will ich auch im Body landen.
969
970 // Bei Flys macht es keinen Sinn, Seiten einzufuegen, wir wollen lediglich
971 // die Verkettung absuchen.
972 if( IsInFly() )
973 eMakePage = MAKEPAGE_NONE;
974
975 //Bei Tabellen gleich den grossen Sprung wagen, ein einfaches GetNext...
976 //wuerde die erste Zellen und in der Folge alle weiteren Zellen nacheinander
977 //abklappern....
978 SwLayoutFrm *pLayLeaf = 0;
979 if ( IsTabFrm() )
980 {
981 SwCntntFrm* pTmp = ((SwTabFrm*)this)->FindLastCntnt();
982 if ( pTmp )
983 pLayLeaf = pTmp->GetUpper();
984 }
985 if ( !pLayLeaf )
986 pLayLeaf = GetNextLayoutLeaf();
987
988 SwLayoutFrm *pOldLayLeaf = 0; //Damit bei neu erzeugten Seiten
989 //nicht wieder vom Anfang gesucht
990 //wird.
991 sal_Bool bNewPg = sal_False; //nur einmal eine neue Seite einfuegen.
992
993 while ( sal_True )
994 {
995 if ( pLayLeaf )
996 {
997 //Es gibt noch einen weiteren LayoutFrm, mal sehen,
998 //ob er bereit ist mich aufzunehmen.
999 //Dazu braucht er nur von der gleichen Art wie mein Ausgangspunkt
1000 //sein (DocBody bzw. Footnote.)
1001 if ( pLayLeaf->FindPageFrm()->IsFtnPage() )
1002 { //Wenn ich bei den Endnotenseiten angelangt bin hat sichs.
1003 pLayLeaf = 0;
1004 continue;
1005 }
1006 if ( (bBody && !pLayLeaf->IsInDocBody()) || pLayLeaf->IsInTab()
1007 || pLayLeaf->IsInSct() )
1008 {
1009 //Er will mich nicht; neuer Versuch, neues Glueck
1010 pOldLayLeaf = pLayLeaf;
1011 pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
1012 continue;
1013 }
1014 //Er will mich, also ist er der gesuchte und ich bin fertig.
1015 //Bei einem Seitenwechsel kann es allerdings noch sein, dass
1016 //Der Seitentyp nicht der gewuenschte ist, in diesem Fall muessen
1017 //wir eine Seite des richtigen Typs einfuegen.
1018
1019 if( !IsFlowFrm() && ( eMakePage == MAKEPAGE_NONE ||
1020 eMakePage==MAKEPAGE_APPEND || eMakePage==MAKEPAGE_NOSECTION ) )
1021 return pLayLeaf;
1022
1023 SwPageFrm *pNew = pLayLeaf->FindPageFrm();
1024 const ViewShell *pSh = getRootFrm()->GetCurrShell();
1025 // #111704# The pagedesc check does not make sense for frames in fly frames
1026 if ( pNew != FindPageFrm() && !bNewPg && !IsInFly() &&
1027 // --> FME 2005-05-10 #i46683#
1028 // Do not consider page descriptions in browse mode (since
1029 // MoveBwd ignored them)
1030 !(pSh && pSh->GetViewOptions()->getBrowseMode() ) )
1031 // <--
1032 {
1033 if( WrongPageDesc( pNew ) )
1034 {
1035 SwFtnContFrm *pCont = pNew->FindFtnCont();
1036 if( pCont )
1037 {
1038 // Falls die Referenz der ersten Fussnote dieser Seite
1039 // vor der Seite liegt, fuegen wir lieber keine neue Seite
1040 // ein (Bug #55620#)
1041 SwFtnFrm *pFtn = (SwFtnFrm*)pCont->Lower();
1042 if( pFtn && pFtn->GetRef() )
1043 {
1044 const sal_uInt16 nRefNum = pNew->GetPhyPageNum();
1045 if( pFtn->GetRef()->GetPhyPageNum() < nRefNum )
1046 break;
1047 }
1048 }
1049 //Erwischt, die folgende Seite ist verkehrt, also
1050 //muss eine neue eingefuegt werden.
1051 if ( eMakePage == MAKEPAGE_INSERT )
1052 {
1053 bNewPg = sal_True;
1054
1055 SwPageFrm *pPg = pOldLayLeaf ?
1056 pOldLayLeaf->FindPageFrm() : 0;
1057 if ( pPg && pPg->IsEmptyPage() )
1058 //Nicht hinter, sondern vor der EmptyPage einfuegen.
1059 pPg = (SwPageFrm*)pPg->GetPrev();
1060
1061 if ( !pPg || pPg == pNew )
1062 pPg = FindPageFrm();
1063
1064 InsertPage( pPg, sal_False );
1065 pLayLeaf = GetNextLayoutLeaf();
1066 pOldLayLeaf = 0;
1067 continue;
1068 }
1069 else
1070 pLayLeaf = 0;
1071 }
1072 }
1073 break;
1074 }
1075 else
1076 {
1077 //Es gibt keinen passenden weiteren LayoutFrm, also muss eine
1078 //neue Seite her.
1079 if ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT )
1080 {
1081 InsertPage(
1082 pOldLayLeaf ? pOldLayLeaf->FindPageFrm() : FindPageFrm(),
1083 sal_False );
1084
1085 //und nochmal das ganze
1086 pLayLeaf = pOldLayLeaf ? pOldLayLeaf : GetNextLayoutLeaf();
1087 }
1088 else
1089 break;
1090 }
1091 }
1092 return pLayLeaf;
1093 }
1094
1095 /*************************************************************************
1096 |*
1097 |* SwFrm::GetPrevLeaf()
1098 |*
1099 |* Beschreibung Liefert das vorhergehende LayoutBlatt in das der
1100 |* Frame gemoved werden kann.
1101 |* Ersterstellung MA 16. Nov. 92
1102 |* Letzte Aenderung MA 25. Apr. 95
1103 |*
1104 |*************************************************************************/
1105
1106
GetPrevLeaf(MakePageType)1107 SwLayoutFrm *SwFrm::GetPrevLeaf( MakePageType )
1108 {
1109 ASSERT( !IsInFtn(), "GetPrevLeaf(), don't call me for Ftn." );
1110
1111 const sal_Bool bBody = IsInDocBody(); //Wenn ich aus dem DocBody komme
1112 //will ich auch im Body landen.
1113 const sal_Bool bFly = IsInFly();
1114
1115 SwLayoutFrm *pLayLeaf = GetPrevLayoutLeaf();
1116 SwLayoutFrm *pPrevLeaf = 0;
1117
1118 while ( pLayLeaf )
1119 {
1120 if ( pLayLeaf->IsInTab() || //In Tabellen geht's niemals hinein.
1121 pLayLeaf->IsInSct() ) //In Bereiche natuerlich auch nicht!
1122 pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1123 else if ( bBody && pLayLeaf->IsInDocBody() )
1124 {
1125 if ( pLayLeaf->Lower() )
1126 break;
1127 pPrevLeaf = pLayLeaf;
1128 pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1129 if ( pLayLeaf )
1130 SwFlowFrm::SetMoveBwdJump( sal_True );
1131 }
1132 else if ( bFly )
1133 break; //Cntnts in Flys sollte jedes Layout-Blatt recht sein.
1134 else
1135 pLayLeaf = pLayLeaf->GetPrevLayoutLeaf();
1136 }
1137 return pLayLeaf ? pLayLeaf : pPrevLeaf;
1138 }
1139
1140 /*************************************************************************
1141 |*
1142 |* SwFlowFrm::IsPrevObjMove()
1143 |*
1144 |* Ersterstellung MA 20. Feb. 96
1145 |* Letzte Aenderung MA 22. Feb. 96
1146 |*
1147 |*************************************************************************/
1148
1149
IsPrevObjMove() const1150 sal_Bool SwFlowFrm::IsPrevObjMove() const
1151 {
1152 //sal_True der FlowFrm soll auf einen Rahmen des Vorgaengers Ruecksicht nehmen
1153 // und fuer diesen ggf. Umbrechen.
1154
1155 //!!!!!!!!!!!Hack!!!!!!!!!!!
1156 const ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
1157 if( pSh && pSh->GetViewOptions()->getBrowseMode() )
1158 return sal_False;
1159
1160 SwFrm *pPre = rThis.FindPrev();
1161
1162 if ( pPre && pPre->GetDrawObjs() )
1163 {
1164 ASSERT( SwFlowFrm::CastFlowFrm( pPre ), "new flowfrm?" );
1165 if( SwFlowFrm::CastFlowFrm( pPre )->IsAnFollow( this ) )
1166 return sal_False;
1167 SwLayoutFrm* pPreUp = pPre->GetUpper();
1168 // Wenn der Upper ein SectionFrm oder die Spalte eines SectionFrms ist,
1169 // duerfen wir aus diesem durchaus heraushaengen,
1170 // es muss stattdessen der Upper des SectionFrms beruecksichtigt werden.
1171 if( pPreUp->IsInSct() )
1172 {
1173 if( pPreUp->IsSctFrm() )
1174 pPreUp = pPreUp->GetUpper();
1175 else if( pPreUp->IsColBodyFrm() &&
1176 pPreUp->GetUpper()->GetUpper()->IsSctFrm() )
1177 pPreUp = pPreUp->GetUpper()->GetUpper()->GetUpper();
1178 }
1179 // --> OD 2004-10-15 #i26945# - re-factoring:
1180 // use <GetVertPosOrientFrm()> to determine, if object has followed the
1181 // text flow to the next layout frame
1182 for ( sal_uInt16 i = 0; i < pPre->GetDrawObjs()->Count(); ++i )
1183 {
1184 // --> OD 2004-07-01 #i28701# - consider changed type of
1185 // <SwSortedObjs> entries.
1186 const SwAnchoredObject* pObj = (*pPre->GetDrawObjs())[i];
1187 // OD 2004-01-20 #110582# - do not consider hidden objects
1188 // --> OD 2004-10-15 #i26945# - do not consider object, which
1189 // doesn't follow the text flow.
1190 if ( pObj->GetFrmFmt().GetDoc()->IsVisibleLayerId(
1191 pObj->GetDrawObj()->GetLayer() ) &&
1192 pObj->GetFrmFmt().GetFollowTextFlow().GetValue() )
1193 // <--
1194 {
1195 const SwLayoutFrm* pVertPosOrientFrm = pObj->GetVertPosOrientFrm();
1196 if ( pVertPosOrientFrm &&
1197 pPreUp != pVertPosOrientFrm &&
1198 !pPreUp->IsAnLower( pVertPosOrientFrm ) )
1199 {
1200 return sal_True;
1201 }
1202 }
1203 }
1204 // <--
1205 }
1206 return sal_False;
1207 }
1208
1209 /*************************************************************************
1210 |*
1211 |* sal_Bool SwFlowFrm::IsPageBreak()
1212 |*
1213 |* Beschreibung Wenn vor dem Frm ein harter Seitenumbruch steht UND
1214 |* es einen Vorgaenger auf der gleichen Seite gibt, wird sal_True
1215 |* zurueckgeliefert (es muss ein PageBreak erzeugt werden) sal_False sonst.
1216 |* Wenn in bAct sal_True uebergeben wird, gibt die Funktion dann sal_True
1217 |* zurueck, wenn ein PageBreak besteht.
1218 |* Fuer Follows wird der harte Seitenumbruch natuerlich nicht
1219 |* ausgewertet.
1220 |* Der Seitenumbruch steht im eigenen FrmFmt (BEFORE) oder im FrmFmt
1221 |* des Vorgaengers (AFTER). Wenn es keinen Vorgaenger auf der Seite
1222 |* gibt ist jede weitere Ueberlegung ueberfluessig.
1223 |* Ein Seitenumbruch (oder der Bedarf) liegt auch dann vor, wenn
1224 |* im FrmFmt ein PageDesc angegeben wird.
1225 |* Die Implementierung arbeitet zuaechst nur auf CntntFrms!
1226 |* -->Fuer LayoutFrms ist die Definition des Vorgaengers unklar.
1227 |* Ersterstellung MA ??
1228 |* Letzte Aenderung MA 21. Mar. 95
1229 |*
1230 |*************************************************************************/
1231
1232
IsPageBreak(sal_Bool bAct) const1233 sal_Bool SwFlowFrm::IsPageBreak( sal_Bool bAct ) const
1234 {
1235 if ( !IsFollow() && rThis.IsInDocBody() &&
1236 ( !rThis.IsInTab() || ( rThis.IsTabFrm() && !rThis.GetUpper()->IsInTab() ) ) ) // i66968
1237 {
1238 const ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
1239 if( pSh && pSh->GetViewOptions()->getBrowseMode() )
1240 return sal_False;
1241 const SwAttrSet *pSet = rThis.GetAttrSet();
1242
1243 //Vorgaenger ermitteln
1244 const SwFrm *pPrev = rThis.FindPrev();
1245 while ( pPrev && ( !pPrev->IsInDocBody() ||
1246 ( pPrev->IsTxtFrm() && ((SwTxtFrm*)pPrev)->IsHiddenNow() ) ) )
1247 pPrev = pPrev->FindPrev();
1248
1249 if ( pPrev )
1250 {
1251 ASSERT( pPrev->IsInDocBody(), "IsPageBreak: Not in DocBody?" );
1252 if ( bAct )
1253 { if ( rThis.FindPageFrm() == pPrev->FindPageFrm() )
1254 return sal_False;
1255 }
1256 else
1257 { if ( rThis.FindPageFrm() != pPrev->FindPageFrm() )
1258 return sal_False;
1259 }
1260
1261 const SvxBreak eBreak = pSet->GetBreak().GetBreak();
1262 if ( eBreak == SVX_BREAK_PAGE_BEFORE || eBreak == SVX_BREAK_PAGE_BOTH )
1263 return sal_True;
1264 else
1265 {
1266 const SvxBreak &ePrB = pPrev->GetAttrSet()->GetBreak().GetBreak();
1267 if ( ePrB == SVX_BREAK_PAGE_AFTER ||
1268 ePrB == SVX_BREAK_PAGE_BOTH ||
1269 pSet->GetPageDesc().GetPageDesc() )
1270 return sal_True;
1271 }
1272 }
1273 }
1274 return sal_False;
1275 }
1276
1277 /*************************************************************************
1278 |*
1279 |* sal_Bool SwFlowFrm::IsColBreak()
1280 |*
1281 |* Beschreibung Wenn vor dem Frm ein harter Spaltenumbruch steht UND
1282 |* es einen Vorgaenger in der gleichen Spalte gibt, wird sal_True
1283 |* zurueckgeliefert (es muss ein PageBreak erzeugt werden) sal_False sonst.
1284 |* Wenn in bAct sal_True uebergeben wird, gibt die Funktion dann sal_True
1285 |* zurueck, wenn ein ColBreak besteht.
1286 |* Fuer Follows wird der harte Spaltenumbruch natuerlich nicht
1287 |* ausgewertet.
1288 |* Der Spaltenumbruch steht im eigenen FrmFmt (BEFORE) oder im FrmFmt
1289 |* des Vorgaengers (AFTER). Wenn es keinen Vorgaenger in der Spalte
1290 |* gibt ist jede weitere Ueberlegung ueberfluessig.
1291 |* Die Implementierung arbeitet zuaechst nur auf CntntFrms!
1292 |* -->Fuer LayoutFrms ist die Definition des Vorgaengers unklar.
1293 |* Ersterstellung MA 11. Jun. 93
1294 |* Letzte Aenderung MA 21. Mar. 95
1295 |*
1296 |*************************************************************************/
1297
IsColBreak(sal_Bool bAct) const1298 sal_Bool SwFlowFrm::IsColBreak( sal_Bool bAct ) const
1299 {
1300 if ( !IsFollow() && (rThis.IsMoveable() || bAct) )
1301 {
1302 const SwFrm *pCol = rThis.FindColFrm();
1303 if ( pCol )
1304 {
1305 //Vorgaenger ermitteln
1306 const SwFrm *pPrev = rThis.FindPrev();
1307 while( pPrev && ( ( !pPrev->IsInDocBody() && !rThis.IsInFly() ) ||
1308 ( pPrev->IsTxtFrm() && ((SwTxtFrm*)pPrev)->IsHiddenNow() ) ) )
1309 pPrev = pPrev->FindPrev();
1310
1311 if ( pPrev )
1312 {
1313 if ( bAct )
1314 { if ( pCol == pPrev->FindColFrm() )
1315 return sal_False;
1316 }
1317 else
1318 { if ( pCol != pPrev->FindColFrm() )
1319 return sal_False;
1320 }
1321
1322 const SvxBreak eBreak = rThis.GetAttrSet()->GetBreak().GetBreak();
1323 if ( eBreak == SVX_BREAK_COLUMN_BEFORE ||
1324 eBreak == SVX_BREAK_COLUMN_BOTH )
1325 return sal_True;
1326 else
1327 {
1328 const SvxBreak &ePrB = pPrev->GetAttrSet()->GetBreak().GetBreak();
1329 if ( ePrB == SVX_BREAK_COLUMN_AFTER ||
1330 ePrB == SVX_BREAK_COLUMN_BOTH )
1331 return sal_True;
1332 }
1333 }
1334 }
1335 }
1336 return sal_False;
1337 }
1338
HasParaSpaceAtPages(sal_Bool bSct) const1339 sal_Bool SwFlowFrm::HasParaSpaceAtPages( sal_Bool bSct ) const
1340 {
1341 if( rThis.IsInSct() )
1342 {
1343 const SwFrm* pTmp = rThis.GetUpper();
1344 while( pTmp )
1345 {
1346 if( pTmp->IsCellFrm() || pTmp->IsFlyFrm() ||
1347 pTmp->IsFooterFrm() || pTmp->IsHeaderFrm() ||
1348 ( pTmp->IsFtnFrm() && !((SwFtnFrm*)pTmp)->GetMaster() ) )
1349 return sal_True;
1350 if( pTmp->IsPageFrm() )
1351 return ( pTmp->GetPrev() && !IsPageBreak(sal_True) ) ? sal_False : sal_True;
1352 if( pTmp->IsColumnFrm() && pTmp->GetPrev() )
1353 return IsColBreak( sal_True );
1354 if( pTmp->IsSctFrm() && ( !bSct || pTmp->GetPrev() ) )
1355 return sal_False;
1356 pTmp = pTmp->GetUpper();
1357 }
1358 ASSERT( sal_False, "HasParaSpaceAtPages: Where's my page?" );
1359 return sal_False;
1360 }
1361 if( !rThis.IsInDocBody() || ( rThis.IsInTab() && !rThis.IsTabFrm()) ||
1362 IsPageBreak( sal_True ) || ( rThis.FindColFrm() && IsColBreak( sal_True ) ) )
1363 return sal_True;
1364 const SwFrm* pTmp = rThis.FindColFrm();
1365 if( pTmp )
1366 {
1367 if( pTmp->GetPrev() )
1368 return sal_False;
1369 }
1370 else
1371 pTmp = &rThis;
1372 pTmp = pTmp->FindPageFrm();
1373 return pTmp && !pTmp->GetPrev();
1374 }
1375
1376 /** helper method to determine previous frame for calculation of the
1377 upper space
1378
1379 OD 2004-03-10 #i11860#
1380
1381 @author OD
1382 */
_GetPrevFrmForUpperSpaceCalc(const SwFrm * _pProposedPrevFrm) const1383 const SwFrm* SwFlowFrm::_GetPrevFrmForUpperSpaceCalc( const SwFrm* _pProposedPrevFrm ) const
1384 {
1385 const SwFrm* pPrevFrm = _pProposedPrevFrm
1386 ? _pProposedPrevFrm
1387 : rThis.GetPrev();
1388
1389 // Skip hidden paragraphs and empty sections
1390 while ( pPrevFrm &&
1391 ( ( pPrevFrm->IsTxtFrm() &&
1392 static_cast<const SwTxtFrm*>(pPrevFrm)->IsHiddenNow() ) ||
1393 ( pPrevFrm->IsSctFrm() &&
1394 !static_cast<const SwSectionFrm*>(pPrevFrm)->GetSection() ) ) )
1395 {
1396 pPrevFrm = pPrevFrm->GetPrev();
1397 }
1398
1399 // Special case: no direct previous frame is found but frame is in footnote
1400 // Search for a previous frame in previous footnote,
1401 // if frame isn't in a section, which is also in the footnote
1402 if ( !pPrevFrm && rThis.IsInFtn() &&
1403 ( rThis.IsSctFrm() ||
1404 !rThis.IsInSct() || !rThis.FindSctFrm()->IsInFtn() ) )
1405 {
1406 const SwFtnFrm* pPrevFtnFrm =
1407 static_cast<const SwFtnFrm*>(rThis.FindFtnFrm()->GetPrev());
1408 if ( pPrevFtnFrm )
1409 {
1410 pPrevFrm = pPrevFtnFrm->GetLastLower();
1411
1412 // Skip hidden paragraphs and empty sections
1413 while ( pPrevFrm &&
1414 ( ( pPrevFrm->IsTxtFrm() &&
1415 static_cast<const SwTxtFrm*>(pPrevFrm)->IsHiddenNow() ) ||
1416 ( pPrevFrm->IsSctFrm() &&
1417 !static_cast<const SwSectionFrm*>(pPrevFrm)->GetSection() ) ) )
1418 {
1419 pPrevFrm = pPrevFrm->GetPrev();
1420 }
1421 }
1422 }
1423 // Special case: found previous frame is a section
1424 // Search for the last content in the section
1425 if( pPrevFrm && pPrevFrm->IsSctFrm() )
1426 {
1427 const SwSectionFrm* pPrevSectFrm =
1428 static_cast<const SwSectionFrm*>(pPrevFrm);
1429 pPrevFrm = pPrevSectFrm->FindLastCntnt();
1430 // If the last content is in a table _inside_ the section,
1431 // take the table herself.
1432 // OD 2004-02-18 #106629# - correction:
1433 // Check directly, if table is inside table, instead of indirectly
1434 // by checking, if section isn't inside a table
1435 if ( pPrevFrm && pPrevFrm->IsInTab() )
1436 {
1437 const SwTabFrm* pTableFrm = pPrevFrm->FindTabFrm();
1438 if ( pPrevSectFrm->IsAnLower( pTableFrm ) )
1439 {
1440 pPrevFrm = pTableFrm;
1441 }
1442 }
1443 // OD 2004-02-18 #106629# correction: skip hidden text frames
1444 while ( pPrevFrm &&
1445 pPrevFrm->IsTxtFrm() &&
1446 static_cast<const SwTxtFrm*>(pPrevFrm)->IsHiddenNow() )
1447 {
1448 pPrevFrm = pPrevFrm->GetPrev();
1449 }
1450 }
1451
1452 return pPrevFrm;
1453 }
1454
1455 // OD 2004-03-12 #i11860# - add 3rd parameter <_bConsiderGrid>
CalcUpperSpace(const SwBorderAttrs * pAttrs,const SwFrm * pPr,const bool _bConsiderGrid) const1456 SwTwips SwFlowFrm::CalcUpperSpace( const SwBorderAttrs *pAttrs,
1457 const SwFrm* pPr,
1458 const bool _bConsiderGrid ) const
1459 {
1460 // OD 2004-03-10 #i11860# - use new method <GetPrevFrmForUpperSpaceCalc(..)>
1461 const SwFrm* pPrevFrm = _GetPrevFrmForUpperSpaceCalc( pPr );
1462
1463 SwBorderAttrAccess *pAccess;
1464 SwFrm* pOwn;
1465 if( !pAttrs )
1466 {
1467 if( rThis.IsSctFrm() )
1468 {
1469 SwSectionFrm* pFoll = &((SwSectionFrm&)rThis);
1470 do
1471 pOwn = pFoll->ContainsAny();
1472 while( !pOwn && 0 != ( pFoll = pFoll->GetFollow() ) );
1473 if( !pOwn )
1474 return 0;
1475 }
1476 else
1477 pOwn = &rThis;
1478 pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), pOwn );
1479 pAttrs = pAccess->Get();
1480 }
1481 else
1482 {
1483 pAccess = NULL;
1484 pOwn = &rThis;
1485 }
1486 SwTwips nUpper = 0;
1487 // OD 06.01.2004 #i11859#
1488 {
1489 const IDocumentSettingAccess* pIDSA = rThis.GetUpper()->GetFmt()->getIDocumentSettingAccess();
1490 const bool bUseFormerLineSpacing = pIDSA->get(IDocumentSettingAccess::OLD_LINE_SPACING);
1491 if( pPrevFrm )
1492 {
1493 // OD 2004-03-10 #i11860# - use new method to determine needed spacing
1494 // values of found previous frame and use these values.
1495 SwTwips nPrevLowerSpace = 0;
1496 SwTwips nPrevLineSpacing = 0;
1497 // --> OD 2009-08-28 #i102458#
1498 bool bPrevLineSpacingPorportional = false;
1499 GetSpacingValuesOfFrm( (*pPrevFrm),
1500 nPrevLowerSpace, nPrevLineSpacing,
1501 bPrevLineSpacingPorportional );
1502 // <--
1503 if( pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX) )
1504 {
1505 nUpper = nPrevLowerSpace + pAttrs->GetULSpace().GetUpper();
1506 SwTwips nAdd = nPrevLineSpacing;
1507 // OD 07.01.2004 #i11859# - consideration of the line spacing
1508 // for the upper spacing of a text frame
1509 if ( bUseFormerLineSpacing )
1510 {
1511 // former consideration
1512 if ( pOwn->IsTxtFrm() )
1513 {
1514 nAdd = Max( nAdd, static_cast<SwTxtFrm&>(rThis).GetLineSpace() );
1515 }
1516 nUpper += nAdd;
1517 }
1518 else
1519 {
1520 // new consideration:
1521 // Only the proportional line spacing of the previous
1522 // text frame is considered for the upper spacing and
1523 // the line spacing values are add up instead of
1524 // building its maximum.
1525 if ( pOwn->IsTxtFrm() )
1526 {
1527 // --> OD 2009-08-28 #i102458#
1528 // Correction:
1529 // A proportional line spacing of the previous text frame
1530 // is added up to a own leading line spacing.
1531 // Otherwise, the maximum of the leading line spacing
1532 // of the previous text frame and the own leading line
1533 // spacing is built.
1534 if ( bPrevLineSpacingPorportional )
1535 {
1536 nAdd += static_cast<SwTxtFrm&>(rThis).GetLineSpace( true );
1537 }
1538 else
1539 {
1540 nAdd = Max( nAdd, static_cast<SwTxtFrm&>(rThis).GetLineSpace( true ) );
1541 }
1542 // <--
1543 }
1544 nUpper += nAdd;
1545 }
1546 }
1547 else
1548 {
1549 nUpper = Max( static_cast<long>(nPrevLowerSpace),
1550 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 if ( bUseFormerLineSpacing )
1554 {
1555 // former consideration
1556 if ( pOwn->IsTxtFrm() )
1557 nUpper = Max( nUpper, ((SwTxtFrm*)pOwn)->GetLineSpace() );
1558 if ( nPrevLineSpacing != 0 )
1559 {
1560 nUpper = 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 SwTwips nAdd = nPrevLineSpacing;
1572 if ( pOwn->IsTxtFrm() )
1573 {
1574 // --> OD 2009-08-28 #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 if ( bPrevLineSpacingPorportional )
1582 {
1583 nAdd += static_cast<SwTxtFrm&>(rThis).GetLineSpace( true );
1584 }
1585 else
1586 {
1587 nAdd = Max( nAdd, static_cast<SwTxtFrm&>(rThis).GetLineSpace( true ) );
1588 }
1589 // <--
1590 }
1591 nUpper += nAdd;
1592 }
1593 }
1594 }
1595 else if ( pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX_AT_PAGES) &&
1596 CastFlowFrm( pOwn )->HasParaSpaceAtPages( rThis.IsSctFrm() ) )
1597 {
1598 nUpper = pAttrs->GetULSpace().GetUpper();
1599 }
1600 }
1601
1602 // OD 2004-02-26 #i25029# - pass previous frame <pPrevFrm>
1603 // to method <GetTopLine(..)>, if parameter <pPr> is set.
1604 // Note: parameter <pPr> is set, if method is called from <SwTxtFrm::WouldFit(..)>
1605 nUpper += pAttrs->GetTopLine( rThis, (pPr ? pPrevFrm : 0L) );
1606
1607 // OD 2004-03-12 #i11860# - consider value of new parameter <_bConsiderGrid>
1608 // and use new method <GetUpperSpaceAmountConsideredForPageGrid(..)>
1609
1610 //consider grid in square page mode
1611 if ( _bConsiderGrid && rThis.GetUpper()->GetFmt()->GetDoc()->IsSquaredPageMode() )
1612 {
1613 nUpper += _GetUpperSpaceAmountConsideredForPageGrid( nUpper );
1614 }
1615
1616 delete pAccess;
1617 return nUpper;
1618 }
1619
1620 /** method to detemine the upper space amount, which is considered for
1621 the page grid
1622
1623 OD 2004-03-12 #i11860#
1624 Precondition: Position of frame is valid.
1625
1626 @author OD
1627 */
_GetUpperSpaceAmountConsideredForPageGrid(const SwTwips _nUpperSpaceWithoutGrid) const1628 SwTwips SwFlowFrm::_GetUpperSpaceAmountConsideredForPageGrid(
1629 const SwTwips _nUpperSpaceWithoutGrid ) const
1630 {
1631 SwTwips nUpperSpaceAmountConsideredForPageGrid = 0;
1632
1633 if ( rThis.IsInDocBody() && rThis.GetAttrSet()->GetParaGrid().GetValue() )
1634 {
1635 const SwPageFrm* pPageFrm = rThis.FindPageFrm();
1636 GETGRID( pPageFrm )
1637 if( pGrid )
1638 {
1639 const SwFrm* pBodyFrm = pPageFrm->FindBodyCont();
1640 if ( pBodyFrm )
1641 {
1642 const long nGridLineHeight =
1643 pGrid->GetBaseHeight() + pGrid->GetRubyHeight();
1644
1645 SWRECTFN( (&rThis) )
1646 const SwTwips nBodyPrtTop = (pBodyFrm->*fnRect->fnGetPrtTop)();
1647 const SwTwips nProposedPrtTop =
1648 (*fnRect->fnYInc)( (rThis.Frm().*fnRect->fnGetTop)(),
1649 _nUpperSpaceWithoutGrid );
1650
1651 const SwTwips nSpaceAbovePrtTop =
1652 (*fnRect->fnYDiff)( nProposedPrtTop, nBodyPrtTop );
1653 const SwTwips nSpaceOfCompleteLinesAbove =
1654 nGridLineHeight * ( nSpaceAbovePrtTop / nGridLineHeight );
1655 SwTwips nNewPrtTop =
1656 (*fnRect->fnYInc)( nBodyPrtTop, nSpaceOfCompleteLinesAbove );
1657 if ( (*fnRect->fnYDiff)( nProposedPrtTop, nNewPrtTop ) > 0 )
1658 {
1659 nNewPrtTop = (*fnRect->fnYInc)( nNewPrtTop, nGridLineHeight );
1660 }
1661
1662 const SwTwips nNewUpperSpace =
1663 (*fnRect->fnYDiff)( nNewPrtTop,
1664 (rThis.Frm().*fnRect->fnGetTop)() );
1665
1666 nUpperSpaceAmountConsideredForPageGrid =
1667 nNewUpperSpace - _nUpperSpaceWithoutGrid;
1668
1669 ASSERT( nUpperSpaceAmountConsideredForPageGrid >= 0,
1670 "<SwFlowFrm::GetUpperSpaceAmountConsideredForPageGrid(..)> - negative space considered for page grid!" );
1671 }
1672 }
1673 }
1674 return nUpperSpaceAmountConsideredForPageGrid;
1675 }
1676
1677 /** method to determent the upper space amount, which is considered for
1678 the previous frame
1679
1680 OD 2004-03-11 #i11860#
1681
1682 @author OD
1683 */
_GetUpperSpaceAmountConsideredForPrevFrm() const1684 SwTwips SwFlowFrm::_GetUpperSpaceAmountConsideredForPrevFrm() const
1685 {
1686 SwTwips nUpperSpaceAmountOfPrevFrm = 0;
1687
1688 const SwFrm* pPrevFrm = _GetPrevFrmForUpperSpaceCalc();
1689 if ( pPrevFrm )
1690 {
1691 SwTwips nPrevLowerSpace = 0;
1692 SwTwips nPrevLineSpacing = 0;
1693 // --> OD 2009-08-28 #i102458#
1694 bool bDummy = false;
1695 GetSpacingValuesOfFrm( (*pPrevFrm), nPrevLowerSpace, nPrevLineSpacing, bDummy );
1696 // <--
1697 if ( nPrevLowerSpace > 0 || nPrevLineSpacing > 0 )
1698 {
1699 const IDocumentSettingAccess* pIDSA = rThis.GetUpper()->GetFmt()->getIDocumentSettingAccess();
1700 if ( pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX) ||
1701 !pIDSA->get(IDocumentSettingAccess::OLD_LINE_SPACING) )
1702 {
1703 nUpperSpaceAmountOfPrevFrm = nPrevLowerSpace + nPrevLineSpacing;
1704 }
1705 else
1706 {
1707 nUpperSpaceAmountOfPrevFrm = Max( nPrevLowerSpace, nPrevLineSpacing );
1708 }
1709 }
1710 }
1711
1712 return nUpperSpaceAmountOfPrevFrm;
1713 }
1714
1715 /** method to determine the upper space amount, which is considered for
1716 the previous frame and the page grid, if option 'Use former object
1717 positioning' is OFF
1718
1719 OD 2004-03-18 #i11860#
1720
1721 @author OD
1722 */
GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() const1723 SwTwips SwFlowFrm::GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() const
1724 {
1725 SwTwips nUpperSpaceAmountConsideredForPrevFrmAndPageGrid = 0;
1726
1727 if ( !rThis.GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::USE_FORMER_OBJECT_POS) )
1728 {
1729 nUpperSpaceAmountConsideredForPrevFrmAndPageGrid =
1730 _GetUpperSpaceAmountConsideredForPrevFrm() +
1731 ( rThis.GetUpper()->GetFmt()->GetDoc()->IsSquaredPageMode()
1732 ? _GetUpperSpaceAmountConsideredForPageGrid( CalcUpperSpace( 0, 0, false ) )
1733 : 0 );
1734 }
1735
1736 return nUpperSpaceAmountConsideredForPrevFrmAndPageGrid;
1737 }
1738
1739 /** calculation of lower space
1740
1741 OD 2004-03-02 #106629#
1742
1743 @author OD
1744 */
CalcLowerSpace(const SwBorderAttrs * _pAttrs) const1745 SwTwips SwFlowFrm::CalcLowerSpace( const SwBorderAttrs* _pAttrs ) const
1746 {
1747 SwTwips nLowerSpace = 0;
1748
1749 SwBorderAttrAccess* pAttrAccess = 0L;
1750 if ( !_pAttrs )
1751 {
1752 pAttrAccess = new SwBorderAttrAccess( SwFrm::GetCache(), &rThis );
1753 _pAttrs = pAttrAccess->Get();
1754 }
1755
1756 sal_Bool bCommonBorder = sal_True;
1757 if ( rThis.IsInSct() && rThis.GetUpper()->IsColBodyFrm() )
1758 {
1759 const SwSectionFrm* pSectFrm = rThis.FindSctFrm();
1760 bCommonBorder = pSectFrm->GetFmt()->GetBalancedColumns().GetValue();
1761 }
1762 nLowerSpace = bCommonBorder ?
1763 _pAttrs->GetBottomLine( rThis ) :
1764 _pAttrs->CalcBottomLine();
1765
1766 // --> OD 2004-07-16 #i26250#
1767 // - correct consideration of table frames
1768 // - use new method <CalcAddLowerSpaceAsLastInTableCell(..)>
1769 if ( ( ( rThis.IsTabFrm() && rThis.GetUpper()->IsInTab() ) ||
1770 // --> OD 2004-11-16 #115759# - no lower spacing, if frame has a follow
1771 ( rThis.IsInTab() && !GetFollow() ) ) &&
1772 // <--
1773 !rThis.GetIndNext() )
1774 {
1775 nLowerSpace += CalcAddLowerSpaceAsLastInTableCell( _pAttrs );
1776 }
1777 // <--
1778
1779 delete pAttrAccess;
1780
1781 return nLowerSpace;
1782 }
1783
1784 /** calculation of the additional space to be considered, if flow frame
1785 is the last inside a table cell
1786
1787 OD 2004-07-16 #i26250#
1788
1789 @author OD
1790 */
CalcAddLowerSpaceAsLastInTableCell(const SwBorderAttrs * _pAttrs) const1791 SwTwips SwFlowFrm::CalcAddLowerSpaceAsLastInTableCell(
1792 const SwBorderAttrs* _pAttrs ) const
1793 {
1794 SwTwips nAdditionalLowerSpace = 0;
1795
1796 if ( rThis.GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS) )
1797 {
1798 const SwFrm* pFrm = &rThis;
1799 if ( pFrm->IsSctFrm() )
1800 {
1801 const SwSectionFrm* pSectFrm = static_cast<const SwSectionFrm*>(pFrm);
1802 pFrm = pSectFrm->FindLastCntnt();
1803 if ( pFrm && pFrm->IsInTab() )
1804 {
1805 const SwTabFrm* pTableFrm = pFrm->FindTabFrm();
1806 if ( pSectFrm->IsAnLower( pTableFrm ) )
1807 {
1808 pFrm = pTableFrm;
1809 }
1810 }
1811 }
1812
1813 SwBorderAttrAccess* pAttrAccess = 0L;
1814 if ( !_pAttrs || pFrm != &rThis )
1815 {
1816 pAttrAccess = new SwBorderAttrAccess( SwFrm::GetCache(), pFrm );
1817 _pAttrs = pAttrAccess->Get();
1818 }
1819
1820 nAdditionalLowerSpace += _pAttrs->GetULSpace().GetLower();
1821
1822 delete pAttrAccess;
1823 }
1824
1825 return nAdditionalLowerSpace;
1826 }
1827
1828 /*************************************************************************
1829 |*
1830 |* sal_Bool SwFlowFrm::CheckMoveFwd()
1831 |*
1832 |* Beschreibung Moved den Frm vorwaerts wenn es durch die aktuellen
1833 |* Bedingungen und Attribute notwendig erscheint.
1834 |* Ersterstellung MA 05. Dec. 96
1835 |* Letzte Aenderung MA 09. Mar. 98
1836 |*
1837 |*************************************************************************/
1838
1839
CheckMoveFwd(sal_Bool & rbMakePage,sal_Bool bKeep,sal_Bool)1840 sal_Bool SwFlowFrm::CheckMoveFwd( sal_Bool &rbMakePage, sal_Bool bKeep, sal_Bool )
1841 {
1842 const SwFrm* pNxt = rThis.GetIndNext();
1843
1844 if ( bKeep && //!bMovedBwd &&
1845 ( !pNxt || ( pNxt->IsTxtFrm() && ((SwTxtFrm*)pNxt)->IsEmptyMaster() ) ) &&
1846 ( 0 != (pNxt = rThis.FindNext()) ) && IsKeepFwdMoveAllowed() )
1847 {
1848 if( pNxt->IsSctFrm() )
1849 { // Nicht auf leere SectionFrms hereinfallen
1850 const SwFrm* pTmp = NULL;
1851 while( pNxt && pNxt->IsSctFrm() &&
1852 ( !((SwSectionFrm*)pNxt)->GetSection() ||
1853 0 == ( pTmp = ((SwSectionFrm*)pNxt)->ContainsAny() ) ) )
1854 {
1855 pNxt = pNxt->FindNext();
1856 pTmp = NULL;
1857 }
1858 if( pTmp )
1859 pNxt = pTmp; // the content of the next notempty sectionfrm
1860 }
1861 if( pNxt && pNxt->GetValidPosFlag() )
1862 {
1863 sal_Bool bMove = sal_False;
1864 const SwSectionFrm *pSct = rThis.FindSctFrm();
1865 if( pSct && !pSct->GetValidSizeFlag() )
1866 {
1867 const SwSectionFrm* pNxtSct = pNxt->FindSctFrm();
1868 if( pNxtSct && pSct->IsAnFollow( pNxtSct ) )
1869 bMove = sal_True;
1870 }
1871 else
1872 bMove = sal_True;
1873 if( bMove )
1874 {
1875 //Keep together with the following frame
1876 MoveFwd( rbMakePage, sal_False );
1877 return sal_True;
1878 }
1879 }
1880 }
1881
1882 sal_Bool bMovedFwd = sal_False;
1883
1884 if ( rThis.GetIndPrev() )
1885 {
1886 if ( IsPrevObjMove() ) //Auf Objekte des Prev Ruecksicht nehmen?
1887 {
1888 bMovedFwd = sal_True;
1889 if ( !MoveFwd( rbMakePage, sal_False ) )
1890 rbMakePage = sal_False;
1891 }
1892 else
1893 {
1894 if ( IsPageBreak( sal_False ) )
1895 {
1896 while ( MoveFwd( rbMakePage, sal_True ) )
1897 /* do nothing */;
1898 rbMakePage = sal_False;
1899 bMovedFwd = sal_True;
1900 }
1901 else if ( IsColBreak ( sal_False ) )
1902 {
1903 const SwPageFrm *pPage = rThis.FindPageFrm();
1904 SwFrm *pCol = rThis.FindColFrm();
1905 do
1906 { MoveFwd( rbMakePage, sal_False );
1907 SwFrm *pTmp = rThis.FindColFrm();
1908 if( pTmp != pCol )
1909 {
1910 bMovedFwd = sal_True;
1911 pCol = pTmp;
1912 }
1913 else
1914 break;
1915 } while ( IsColBreak( sal_False ) );
1916 if ( pPage != rThis.FindPageFrm() )
1917 rbMakePage = sal_False;
1918 }
1919 }
1920 }
1921 return bMovedFwd;
1922 }
1923
1924 /*************************************************************************
1925 |*
1926 |* sal_Bool SwFlowFrm::MoveFwd()
1927 |*
1928 |* Beschreibung Returnwert sagt, ob der Frm die Seite gewechselt hat.
1929 |* Ersterstellung MA 05. Dec. 96
1930 |* Letzte Aenderung MA 05. Dec. 96
1931 |*
1932 |*************************************************************************/
1933
1934
MoveFwd(sal_Bool bMakePage,sal_Bool bPageBreak,sal_Bool bMoveAlways)1935 sal_Bool SwFlowFrm::MoveFwd( sal_Bool bMakePage, sal_Bool bPageBreak, sal_Bool bMoveAlways )
1936 {
1937 //!!!!MoveFtnCntFwd muss ggf. mitgepflegt werden.
1938 SwFtnBossFrm *pOldBoss = rThis.FindFtnBossFrm();
1939 if ( rThis.IsInFtn() )
1940 return ((SwCntntFrm&)rThis).MoveFtnCntFwd( bMakePage, pOldBoss );
1941
1942 if( !IsFwdMoveAllowed() && !bMoveAlways )
1943 {
1944 sal_Bool bNoFwd = sal_True;
1945 if( rThis.IsInSct() )
1946 {
1947 SwFtnBossFrm* pBoss = rThis.FindFtnBossFrm();
1948 bNoFwd = !pBoss->IsInSct() || ( !pBoss->Lower()->GetNext() &&
1949 !pBoss->GetPrev() );
1950 }
1951
1952 // Allow the MoveFwd even if we do not have an IndPrev in these cases:
1953 if ( rThis.IsInTab() &&
1954 ( !rThis.IsTabFrm() ||
1955 ( rThis.GetUpper()->IsInTab() &&
1956 rThis.GetUpper()->FindTabFrm()->IsFwdMoveAllowed() ) ) &&
1957 0 != const_cast<SwFrm&>(rThis).GetNextCellLeaf( MAKEPAGE_NONE ) )
1958 /*
1959 &&
1960 // NEW TABLES
1961 // Have a look at our main competitor: We don't move inside row span cells:
1962 ( !rThis.GetUpper()->IsCellFrm() || !rThis.GetUpper()->IsLeaveUpperAllowed() ) )*/
1963 {
1964 bNoFwd = sal_False;
1965 }
1966
1967 if( bNoFwd )
1968 {
1969 //Fuer PageBreak ist das Moven erlaubt, wenn der Frm nicht
1970 //bereits der erste der Seite ist.
1971 if ( !bPageBreak )
1972 return sal_False;
1973
1974 const SwFrm *pCol = rThis.FindColFrm();
1975 if ( !pCol || !pCol->GetPrev() )
1976 return sal_False;
1977 }
1978 }
1979
1980 sal_Bool bSamePage = sal_True;
1981 SwLayoutFrm *pNewUpper =
1982 rThis.GetLeaf( bMakePage ? MAKEPAGE_INSERT : MAKEPAGE_NONE, sal_True );
1983
1984 if ( pNewUpper )
1985 {
1986 PROTOCOL_ENTER( &rThis, PROT_MOVE_FWD, 0, 0 );
1987 SwPageFrm *pOldPage = pOldBoss->FindPageFrm();
1988 //Wir moven uns und alle direkten Nachfolger vor den ersten
1989 //CntntFrm unterhalb des neuen Uppers.
1990
1991 // Wenn unser NewUpper in einem SectionFrm liegt, muessen wir
1992 // verhindern, dass sich dieser im Calc selbst zerstoert
1993 SwSectionFrm* pSect = pNewUpper->FindSctFrm();
1994 sal_Bool bUnlock = sal_False;
1995 if( pSect )
1996 {
1997 // Wenn wir nur innerhalb unseres SectionFrms die Spalte wechseln,
1998 // rufen wir lieber kein Calc, sonst wird noch der SectionFrm
1999 // formatiert, der wiederum uns ruft etc.
2000 if( pSect != rThis.FindSctFrm() )
2001 {
2002 bUnlock = !pSect->IsColLocked();
2003 pSect->ColLock();
2004 pNewUpper->Calc();
2005 if( bUnlock )
2006 pSect->ColUnlock();
2007 }
2008 }
2009 // Do not calculate split cell frames.
2010 else if ( !pNewUpper->IsCellFrm() || ((SwLayoutFrm*)pNewUpper)->Lower() )
2011 pNewUpper->Calc();
2012
2013 SwFtnBossFrm *pNewBoss = pNewUpper->FindFtnBossFrm();
2014 sal_Bool bBossChg = pNewBoss != pOldBoss;
2015 pNewBoss = pNewBoss->FindFtnBossFrm( sal_True );
2016 pOldBoss = pOldBoss->FindFtnBossFrm( sal_True );
2017 SwPageFrm* pNewPage = pOldPage;
2018
2019 // First, we move the footnotes.
2020 sal_Bool bFtnMoved = sal_False;
2021
2022 // --> FME 2004-07-15 #i26831#
2023 // If pSect has just been created, the printing area of pSect has
2024 // been calculated based on the first content of its follow.
2025 // In this case we prefer to call a SimpleFormat for this new
2026 // section after we inserted the contents. Otherwise the section
2027 // frame will invalidate its lowers, if its printing area changes
2028 // in SwSectionFrm::Format, which can cause loops.
2029 const bool bForceSimpleFormat = pSect && pSect->HasFollow() &&
2030 !pSect->ContainsAny();
2031 // <--
2032
2033 if ( pNewBoss != pOldBoss )
2034 {
2035 pNewPage = pNewBoss->FindPageFrm();
2036 bSamePage = pNewPage == pOldPage;
2037 //Damit die Fussnoten nicht auf dumme Gedanken kommen
2038 //setzen wir hier die Deadline.
2039 SWRECTFN( pOldBoss )
2040 SwSaveFtnHeight aHeight( pOldBoss,
2041 (pOldBoss->Frm().*fnRect->fnGetBottom)() );
2042 SwCntntFrm* pStart = rThis.IsCntntFrm() ?
2043 (SwCntntFrm*)&rThis : ((SwLayoutFrm&)rThis).ContainsCntnt();
2044 ASSERT( pStart || ( rThis.IsTabFrm() && !((SwTabFrm&)rThis).Lower() ),
2045 "MoveFwd: Missing Content" );
2046 SwLayoutFrm* pBody = pStart ? ( pStart->IsTxtFrm() ?
2047 (SwLayoutFrm*)((SwTxtFrm*)pStart)->FindBodyFrm() : 0 ) : 0;
2048 if( pBody )
2049 bFtnMoved = pBody->MoveLowerFtns( pStart, pOldBoss, pNewBoss,
2050 sal_False);
2051 }
2052 // Bei SectionFrms ist es moeglich, dass wir selbst durch pNewUpper->Calc()
2053 // bewegt wurden, z. B. in den pNewUpper.
2054 // MoveSubTree bzw. PasteTree ist auf so etwas nicht vorbereitet.
2055 if( pNewUpper != rThis.GetUpper() )
2056 {
2057 // --> FME 2004-04-19 #i27145#
2058 SwSectionFrm* pOldSct = 0;
2059 if ( rThis.GetUpper()->IsSctFrm() )
2060 {
2061 pOldSct = static_cast<SwSectionFrm*>(rThis.GetUpper());
2062 }
2063 // <--
2064
2065 MoveSubTree( pNewUpper, pNewUpper->Lower() );
2066
2067 // --> FME 2004-04-19 #i27145#
2068 if ( pOldSct && pOldSct->GetSection() )
2069 {
2070 // Prevent loops by setting the new height at
2071 // the section frame if footnotes have been moved.
2072 // Otherwise the call of SwLayNotify::~SwLayNotify() for
2073 // the (invalid) section frame will invalidate the first
2074 // lower of its follow, because it grows due to the removed
2075 // footnotes.
2076 // Note: If pOldSct has become empty during MoveSubTree, it
2077 // has already been scheduled for removal. No SimpleFormat
2078 // for these.
2079 pOldSct->SimpleFormat();
2080 }
2081 // <--
2082
2083 // --> FME 2004-07-15 #i26831#
2084 if ( bForceSimpleFormat )
2085 {
2086 pSect->SimpleFormat();
2087 }
2088 // <--
2089
2090 if ( bFtnMoved && !bSamePage )
2091 {
2092 pOldPage->UpdateFtnNum();
2093 pNewPage->UpdateFtnNum();
2094 }
2095
2096 if( bBossChg )
2097 {
2098 rThis.Prepare( PREP_BOSS_CHGD, 0, sal_False );
2099 if( !bSamePage )
2100 {
2101 ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
2102 if ( pSh && !pSh->Imp()->IsUpdateExpFlds() )
2103 pSh->GetDoc()->SetNewFldLst(true); //Wird von CalcLayout() hinterher erledigt!
2104
2105 pNewPage->InvalidateSpelling();
2106 pNewPage->InvalidateSmartTags(); // SMARTTAGS
2107 pNewPage->InvalidateAutoCompleteWords();
2108 pNewPage->InvalidateWordCount();
2109 }
2110 }
2111 }
2112 // OD 30.10.2002 #97265# - no <CheckPageDesc(..)> in online layout
2113 const ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
2114
2115 if ( !( pSh && pSh->GetViewOptions()->getBrowseMode() ) )
2116 {
2117 // --> OD 2009-12-31 #i106452#
2118 // check page description not only in situation with sections.
2119 if ( !bSamePage &&
2120 ( rThis.GetAttrSet()->GetPageDesc().GetPageDesc() ||
2121 pOldPage->GetPageDesc()->GetFollow() != pNewPage->GetPageDesc() ) )
2122 {
2123 SwFrm::CheckPageDescs( pNewPage, sal_False );
2124 }
2125 // <--
2126 }
2127 }
2128 return bSamePage;
2129 }
2130
2131
2132 /*************************************************************************
2133 |*
2134 |* sal_Bool SwFlowFrm::MoveBwd()
2135 |*
2136 |* Beschreibung Returnwert sagt, ob der Frm die Seite wechseln soll.
2137 |* Sollte von abgeleiteten Klassen gerufen werden.
2138 |* Das moven selbst muessen die abgeleiteten uebernehmen.
2139 |* Ersterstellung MA 05. Dec. 96
2140 |* Letzte Aenderung MA 05. Dec. 96
2141 |*
2142 |*************************************************************************/
2143
MoveBwd(sal_Bool & rbReformat)2144 sal_Bool SwFlowFrm::MoveBwd( sal_Bool &rbReformat )
2145 {
2146 SwFlowFrm::SetMoveBwdJump( sal_False );
2147
2148 SwFtnFrm* pFtn = rThis.FindFtnFrm();
2149 if ( pFtn && pFtn->IsBackMoveLocked() )
2150 return sal_False;
2151
2152 // --> OD 2004-11-29 #115759# - text frames, which are directly inside
2153 // tables aren't allowed to move backward.
2154 if ( rThis.IsTxtFrm() && rThis.IsInTab() )
2155 {
2156 const SwLayoutFrm* pUpperFrm = rThis.GetUpper();
2157 while ( pUpperFrm )
2158 {
2159 if ( pUpperFrm->IsTabFrm() )
2160 {
2161 return sal_False;
2162 }
2163 else if ( pUpperFrm->IsColumnFrm() && pUpperFrm->IsInSct() )
2164 {
2165 break;
2166 }
2167 pUpperFrm = pUpperFrm->GetUpper();
2168 }
2169 }
2170 // <--
2171
2172 SwFtnBossFrm * pOldBoss = rThis.FindFtnBossFrm();
2173 SwPageFrm * const pOldPage = pOldBoss->FindPageFrm();
2174 SwLayoutFrm *pNewUpper = 0;
2175 sal_Bool bCheckPageDescs = sal_False;
2176 bool bCheckPageDescOfNextPage = false;
2177
2178 if ( pFtn )
2179 {
2180 //Wenn die Fussnote bereits auf der gleichen Seite/Spalte wie die Referenz
2181 //steht, ist nix mit zurueckfliessen. Die breaks brauche fuer die
2182 //Fussnoten nicht geprueft zu werden.
2183
2184 // --> FME 2004-11-15 #i37084# FindLastCntnt does not necessarily
2185 // have to have a result != 0
2186 SwFrm* pRef = 0;
2187 const bool bEndnote = pFtn->GetAttr()->GetFtn().IsEndNote();
2188 if( bEndnote && pFtn->IsInSct() )
2189 {
2190 SwSectionFrm* pSect = pFtn->FindSctFrm();
2191 if( pSect->IsEndnAtEnd() )
2192 pRef = pSect->FindLastCntnt( FINDMODE_LASTCNT );
2193 }
2194 if( !pRef )
2195 pRef = pFtn->GetRef();
2196 // <--
2197
2198 ASSERT( pRef, "MoveBwd: Endnote for an empty section?" );
2199
2200 if( !bEndnote )
2201 pOldBoss = pOldBoss->FindFtnBossFrm( sal_True );
2202 SwFtnBossFrm *pRefBoss = pRef->FindFtnBossFrm( !bEndnote );
2203 if ( pOldBoss != pRefBoss &&
2204 // OD 08.11.2002 #104840# - use <SwLayoutFrm::IsBefore(..)>
2205 ( !bEndnote ||
2206 pRefBoss->IsBefore( pOldBoss ) )
2207 )
2208 pNewUpper = rThis.GetLeaf( MAKEPAGE_FTN, sal_False );
2209 }
2210 else if ( IsPageBreak( sal_True ) ) //PageBreak zu beachten?
2211 {
2212 //Wenn auf der vorhergehenden Seite kein Frm im Body steht,
2213 //so ist das Zurueckfliessen trotz Pagebreak sinnvoll
2214 //(sonst: leere Seite).
2215 //Natuerlich muessen Leereseiten geflissentlich uebersehen werden!
2216 const SwFrm *pFlow = &rThis;
2217 do
2218 {
2219 pFlow = pFlow->FindPrev();
2220 } while ( pFlow &&
2221 ( pFlow->FindPageFrm() == pOldPage ||
2222 !pFlow->IsInDocBody() ) );
2223 if ( pFlow )
2224 {
2225 long nDiff = pOldPage->GetPhyPageNum() - pFlow->GetPhyPageNum();
2226 if ( nDiff > 1 )
2227 {
2228 if ( ((SwPageFrm*)pOldPage->GetPrev())->IsEmptyPage() )
2229 nDiff -= 1;
2230 if ( nDiff > 1 )
2231 {
2232 pNewUpper = rThis.GetLeaf( MAKEPAGE_NONE, sal_False );
2233 // --> OD 2006-05-08 #i53139#
2234 // Now <pNewUpper> is a previous layout frame, which contains
2235 // content. But the new upper layout frame has to be the next one.
2236 // Thus, hack for issue i14206 no longer needed, but fix for issue 114442
2237 // --> OD 2006-05-17 #136024# - correct fix for i53139:
2238 // Check for wrong page description before using next new upper.
2239 // --> OD 2006-06-06 #i66051# - further correction of fix for i53139
2240 // Check for correct type of new next upper layout frame
2241 // --> OD 2006-06-08 #136538# - another correction of fix for i53139
2242 // Assumption, that in all cases <pNewUpper> is a previous
2243 // layout frame, which contains content, is wrong.
2244 // --> OD 2006-07-05 #136538# - another correction of fix for i53139
2245 // Beside type check, check also, if proposed new next upper
2246 // frame is inside the same frame types.
2247 // --> OD 2007-01-10 #i73194# - and yet another correction
2248 // of fix for i53139:
2249 // Assure that the new next upper layout frame doesn't
2250 // equal the current one.
2251 // E.g.: content is on page 3, on page 2 is only a 'ghost'
2252 // section and on page 1 is normal content. Method <FindPrev(..)>
2253 // will find the last content of page 1, but <GetLeaf(..)>
2254 // returns new upper on page 2.
2255 if ( pNewUpper->Lower() )
2256 {
2257 SwLayoutFrm* pNewNextUpper = pNewUpper->GetLeaf( MAKEPAGE_NONE, sal_True );
2258 if ( pNewNextUpper &&
2259 pNewNextUpper != rThis.GetUpper() &&
2260 pNewNextUpper->GetType() == pNewUpper->GetType() &&
2261 pNewNextUpper->IsInDocBody() == pNewUpper->IsInDocBody() &&
2262 pNewNextUpper->IsInFtn() == pNewUpper->IsInFtn() &&
2263 pNewNextUpper->IsInTab() == pNewUpper->IsInTab() &&
2264 pNewNextUpper->IsInSct() == pNewUpper->IsInSct() &&
2265 !rThis.WrongPageDesc( pNewNextUpper->FindPageFrm() ) )
2266 {
2267 pNewUpper = pNewNextUpper;
2268 bCheckPageDescOfNextPage = true;
2269 }
2270 }
2271 // <--
2272
2273 bCheckPageDescs = sal_True;
2274 }
2275 }
2276 }
2277 }
2278 else if ( IsColBreak( sal_True ) )
2279 {
2280 //Wenn in der vorhergehenden Spalte kein CntntFrm steht, so ist
2281 //das Zurueckfliessen trotz ColumnBreak sinnvoll
2282 //(sonst: leere Spalte).
2283 if( rThis.IsInSct() )
2284 {
2285 pNewUpper = rThis.GetLeaf( MAKEPAGE_NONE, sal_False );
2286 if( pNewUpper && !SwFlowFrm::IsMoveBwdJump() &&
2287 ( pNewUpper->ContainsCntnt() ||
2288 ( ( !pNewUpper->IsColBodyFrm() ||
2289 !pNewUpper->GetUpper()->GetPrev() ) &&
2290 !pNewUpper->FindSctFrm()->GetPrev() ) ) )
2291 {
2292 pNewUpper = 0;
2293 }
2294 // --> OD 2006-05-08 #i53139#
2295 // --> OD 2006-09-11 #i69409# - check <pNewUpper>
2296 // --> OD 2006-11-02 #i71065# - check <SwFlowFrm::IsMoveBwdJump()>
2297 else if ( pNewUpper && !SwFlowFrm::IsMoveBwdJump() )
2298 // <--
2299 {
2300 // Now <pNewUpper> is a previous layout frame, which
2301 // contains content. But the new upper layout frame
2302 // has to be the next one.
2303 // --> OD 2006-05-17 #136024# - correct fix for i53139
2304 // Check for wrong page description before using next new upper.
2305 // --> OD 2006-06-06 #i66051# - further correction of fix for i53139
2306 // Check for correct type of new next upper layout frame
2307 // --> OD 2006-07-05 #136538# - another correction of fix for i53139
2308 // Beside type check, check also, if proposed new next upper
2309 // frame is inside the same frame types.
2310 SwLayoutFrm* pNewNextUpper = pNewUpper->GetLeaf( MAKEPAGE_NOSECTION, sal_True );
2311 if ( pNewNextUpper &&
2312 pNewNextUpper->GetType() == pNewUpper->GetType() &&
2313 pNewNextUpper->IsInDocBody() == pNewUpper->IsInDocBody() &&
2314 pNewNextUpper->IsInFtn() == pNewUpper->IsInFtn() &&
2315 pNewNextUpper->IsInTab() == pNewUpper->IsInTab() &&
2316 pNewNextUpper->IsInSct() == pNewUpper->IsInSct() &&
2317 !rThis.WrongPageDesc( pNewNextUpper->FindPageFrm() ) )
2318 {
2319 pNewUpper = pNewNextUpper;
2320 }
2321 }
2322 // <--
2323 }
2324 else
2325 {
2326 const SwFrm *pCol = rThis.FindColFrm();
2327 sal_Bool bGoOn = sal_True;
2328 sal_Bool bJump = sal_False;
2329 do
2330 {
2331 if ( pCol->GetPrev() )
2332 pCol = pCol->GetPrev();
2333 else
2334 {
2335 bGoOn = sal_False;
2336 pCol = rThis.GetLeaf( MAKEPAGE_NONE, sal_False );
2337 }
2338 if ( pCol )
2339 {
2340 // ColumnFrms jetzt mit BodyFrm
2341 SwLayoutFrm* pColBody = pCol->IsColumnFrm() ?
2342 (SwLayoutFrm*)((SwLayoutFrm*)pCol)->Lower() :
2343 (SwLayoutFrm*)pCol;
2344 if ( pColBody->ContainsCntnt() )
2345 {
2346 bGoOn = sal_False; // Hier gibt's Inhalt, wir akzeptieren diese
2347 // nur, wenn GetLeaf() das MoveBwdJump-Flag gesetzt hat.
2348 if( SwFlowFrm::IsMoveBwdJump() )
2349 {
2350 pNewUpper = pColBody;
2351 // --> OD 2006-05-08 #i53139#
2352 // Now <pNewUpper> is a previous layout frame, which
2353 // contains content. But the new upper layout frame
2354 // has to be the next one.
2355 // --> OD 2006-05-17 #136024# - correct fix for i53139
2356 // Check for wrong page description before using next new upper.
2357 // --> OD 2006-06-06 #i66051# - further correction of fix for i53139
2358 // Check for correct type of new next upper layout frame
2359 // --> OD 2006-07-05 #136538# - another correction of fix for i53139
2360 // Beside type check, check also, if proposed new next upper
2361 // frame is inside the same frame types.
2362 // --> OD 2006-11-02 #i71065#
2363 // Check that the proposed new next upper layout
2364 // frame isn't the current one.
2365 SwLayoutFrm* pNewNextUpper = pNewUpper->GetLeaf( MAKEPAGE_NONE, sal_True );
2366 if ( pNewNextUpper &&
2367 pNewNextUpper != rThis.GetUpper() &&
2368 pNewNextUpper->GetType() == pNewUpper->GetType() &&
2369 pNewNextUpper->IsInDocBody() == pNewUpper->IsInDocBody() &&
2370 pNewNextUpper->IsInFtn() == pNewUpper->IsInFtn() &&
2371 pNewNextUpper->IsInTab() == pNewUpper->IsInTab() &&
2372 pNewNextUpper->IsInSct() == pNewUpper->IsInSct() &&
2373 !rThis.WrongPageDesc( pNewNextUpper->FindPageFrm() ) )
2374 {
2375 pNewUpper = pNewNextUpper;
2376 }
2377 // <--
2378 }
2379 }
2380 else
2381 {
2382 if( pNewUpper ) // Wir hatten schon eine leere Spalte, haben
2383 bJump = sal_True; // also eine uebersprungen
2384 pNewUpper = pColBody; // Diese leere Spalte kommt in Frage,
2385 // trotzdem weitersuchen
2386 }
2387 }
2388 } while( bGoOn );
2389 if( bJump )
2390 SwFlowFrm::SetMoveBwdJump( sal_True );
2391 }
2392 }
2393 else //Keine Breaks also kann ich zurueckfliessen
2394 pNewUpper = rThis.GetLeaf( MAKEPAGE_NONE, sal_False );
2395
2396 // --> OD 2004-06-23 #i27801# - no move backward of 'master' text frame,
2397 // if - due to its object positioning - it isn't allowed to be on the new page frame
2398 // --> OD 2005-03-07 #i44049# - add another condition for not moving backward:
2399 // If one of its objects has restarted the layout process, moving backward
2400 // isn't sensible either.
2401 // --> OD 2005-04-19 #i47697# - refine condition made for issue i44049:
2402 // - allow move backward as long as the anchored object is only temporarily
2403 // positions considering its wrapping style.
2404 if ( pNewUpper &&
2405 rThis.IsTxtFrm() && !IsFollow() )
2406 {
2407 sal_uInt32 nToPageNum( 0L );
2408 const bool bMoveFwdByObjPos = SwLayouter::FrmMovedFwdByObjPos(
2409 *(pOldPage->GetFmt()->GetDoc()),
2410 static_cast<SwTxtFrm&>(rThis),
2411 nToPageNum );
2412 if ( bMoveFwdByObjPos &&
2413 pNewUpper->FindPageFrm()->GetPhyPageNum() < nToPageNum )
2414 {
2415 pNewUpper = 0;
2416 }
2417 // --> OD 2005-03-07 #i44049# - check, if one of its anchored objects
2418 // has restarted the layout process.
2419 else if ( rThis.GetDrawObjs() )
2420 {
2421 sal_uInt32 i = 0;
2422 for ( ; i < rThis.GetDrawObjs()->Count(); ++i )
2423 {
2424 SwAnchoredObject* pAnchoredObj = (*rThis.GetDrawObjs())[i];
2425 // --> OD 2005-04-19 #i47697# - refine condition - see above
2426 if ( pAnchoredObj->RestartLayoutProcess() &&
2427 !pAnchoredObj->IsTmpConsiderWrapInfluence() )
2428 // <--
2429 {
2430 pNewUpper = 0;
2431 break;
2432 }
2433 }
2434 }
2435 // <--
2436 }
2437 // <--
2438
2439 //Fuer Follows ist das zurueckfliessen nur dann erlaubt wenn in der
2440 //neuen Umgebung kein Nachbar existiert (denn dieses waere der Master).
2441 //(6677)Wenn allerdings leere Blaetter uebersprungen wurden wird doch gemoved.
2442 if ( pNewUpper && IsFollow() && pNewUpper->Lower() )
2443 {
2444 // --> OD 2007-09-05 #i79774#, #b6596954#
2445 // neglect empty sections in proposed new upper frame
2446 bool bProposedNewUpperContainsOnlyEmptySections( true );
2447 {
2448 const SwFrm* pLower( pNewUpper->Lower() );
2449 while ( pLower )
2450 {
2451 if ( pLower->IsSctFrm() &&
2452 !dynamic_cast<const SwSectionFrm*>(pLower)->GetSection() )
2453 {
2454 pLower = pLower->GetNext();
2455 continue;
2456 }
2457 else
2458 {
2459 bProposedNewUpperContainsOnlyEmptySections = false;
2460 break;
2461 }
2462 }
2463 }
2464 if ( !bProposedNewUpperContainsOnlyEmptySections )
2465 {
2466 if ( SwFlowFrm::IsMoveBwdJump() )
2467 {
2468 //Nicht hinter den Master sondern in das naechstfolgende leere
2469 //Blatt moven.
2470 SwFrm *pFrm = pNewUpper->Lower();
2471 while ( pFrm->GetNext() )
2472 pFrm = pFrm->GetNext();
2473 pNewUpper = pFrm->GetLeaf( MAKEPAGE_INSERT, sal_True );
2474 if( pNewUpper == rThis.GetUpper() ) //Landen wir wieder an der gleichen Stelle?
2475 pNewUpper = NULL; //dann eruebrigt sich das Moven
2476 }
2477 else
2478 pNewUpper = 0;
2479 }
2480 // <--
2481 }
2482 if ( pNewUpper && !ShouldBwdMoved( pNewUpper, sal_True, rbReformat ) )
2483 {
2484 if( !pNewUpper->Lower() )
2485 {
2486 if( pNewUpper->IsFtnContFrm() )
2487 {
2488 pNewUpper->Cut();
2489 delete pNewUpper;
2490 }
2491 else
2492 {
2493 SwSectionFrm* pSectFrm = pNewUpper->FindSctFrm();
2494 // --> OD 2006-01-04 #126020# - adjust check for empty section
2495 // --> OD 2006-02-01 #130797# - correct fix #126020#
2496 if ( pSectFrm && !pSectFrm->IsColLocked() &&
2497 !pSectFrm->ContainsCntnt() && !pSectFrm->ContainsAny( true ) )
2498 // <--
2499 {
2500 pSectFrm->DelEmpty( sal_True );
2501 delete pSectFrm;
2502 rThis.bValidPos = sal_True;
2503 }
2504 }
2505 }
2506 pNewUpper = 0;
2507 }
2508
2509 // OD 2004-05-26 #i21478# - don't move backward, if flow frame wants to
2510 // keep with next frame and next frame is locked.
2511 // --> OD 2004-12-08 #i38232# - If next frame is a table, do *not* check,
2512 // if it's locked.
2513 if ( pNewUpper && !IsFollow() &&
2514 rThis.GetAttrSet()->GetKeep().GetValue() && rThis.GetIndNext() )
2515 {
2516 SwFrm* pIndNext = rThis.GetIndNext();
2517 // --> OD 2004-12-08 #i38232#
2518 if ( !pIndNext->IsTabFrm() )
2519 {
2520 // get first content of section, while empty sections are skipped
2521 while ( pIndNext && pIndNext->IsSctFrm() )
2522 {
2523 if( static_cast<SwSectionFrm*>(pIndNext)->GetSection() )
2524 {
2525 SwFrm* pTmp = static_cast<SwSectionFrm*>(pIndNext)->ContainsAny();
2526 if ( pTmp )
2527 {
2528 pIndNext = pTmp;
2529 break;
2530 }
2531 }
2532 pIndNext = pIndNext->GetIndNext();
2533 }
2534 ASSERT( !pIndNext || pIndNext->ISA(SwTxtFrm),
2535 "<SwFlowFrm::MovedBwd(..)> - incorrect next found." );
2536 if ( pIndNext && pIndNext->IsFlowFrm() &&
2537 SwFlowFrm::CastFlowFrm(pIndNext)->IsJoinLocked() )
2538 {
2539 pNewUpper = 0L;
2540 }
2541 }
2542 // <--
2543 }
2544
2545 // --> OD 2006-05-10 #i65250#
2546 // layout loop control for flowing content again and again moving
2547 // backward under the same layout condition.
2548 if ( pNewUpper && !IsFollow() &&
2549 pNewUpper != rThis.GetUpper() &&
2550 SwLayouter::MoveBwdSuppressed( *(pOldPage->GetFmt()->GetDoc()),
2551 *this, *pNewUpper ) )
2552 {
2553 SwLayoutFrm* pNextNewUpper = pNewUpper->GetLeaf(
2554 ( !rThis.IsSctFrm() && rThis.IsInSct() )
2555 ? MAKEPAGE_NOSECTION
2556 : MAKEPAGE_NONE,
2557 sal_True );
2558 // --> OD 2007-01-10 #i73194# - make code robust
2559 ASSERT( pNextNewUpper, "<SwFlowFrm::MoveBwd(..)> - missing next new upper" );
2560 if ( pNextNewUpper &&
2561 ( pNextNewUpper == rThis.GetUpper() ||
2562 pNextNewUpper->GetType() != rThis.GetUpper()->GetType() ) )
2563 // <--
2564 {
2565 pNewUpper = 0L;
2566 #if OSL_DEBUG_LEVEL > 1
2567 ASSERT( false,
2568 "<SwFlowFrm::MoveBwd(..)> - layout loop control for layout action <Move Backward> applied!" );
2569 #endif
2570 }
2571 }
2572 // <--
2573
2574 ASSERT( pNewUpper != rThis.GetUpper(),
2575 "<SwFlowFrm::MoveBwd(..)> - moving backward to the current upper frame!? -> Please inform OD." );
2576 if ( pNewUpper )
2577 {
2578 PROTOCOL_ENTER( &rThis, PROT_MOVE_BWD, 0, 0 );
2579 if ( pNewUpper->IsFtnContFrm() )
2580 {
2581 //Kann sein, dass ich einen Container bekam.
2582 SwFtnFrm *pOld = rThis.FindFtnFrm();
2583 SwFtnFrm *pNew = new SwFtnFrm( pOld->GetFmt(), pOld,
2584 pOld->GetRef(), pOld->GetAttr() );
2585 if ( pOld->GetMaster() )
2586 {
2587 pNew->SetMaster( pOld->GetMaster() );
2588 pOld->GetMaster()->SetFollow( pNew );
2589 }
2590 pNew->SetFollow( pOld );
2591 pOld->SetMaster( pNew );
2592 pNew->Paste( pNewUpper );
2593 pNewUpper = pNew;
2594 }
2595 if( pNewUpper->IsFtnFrm() && rThis.IsInSct() )
2596 {
2597 SwSectionFrm* pSct = rThis.FindSctFrm();
2598 //Wenn wir in einem Bereich in einer Fussnote stecken, muss im
2599 //neuen Upper ggf. ein SwSectionFrm angelegt werden
2600 if( pSct->IsInFtn() )
2601 {
2602 SwFrm* pTmp = pNewUpper->Lower();
2603 if( pTmp )
2604 {
2605 while( pTmp->GetNext() )
2606 pTmp = pTmp->GetNext();
2607 if( !pTmp->IsSctFrm() ||
2608 ((SwSectionFrm*)pTmp)->GetFollow() != pSct )
2609 pTmp = NULL;
2610 }
2611 if( pTmp )
2612 pNewUpper = (SwSectionFrm*)pTmp;
2613 else
2614 {
2615 pSct = new SwSectionFrm( *pSct, sal_True );
2616 pSct->Paste( pNewUpper );
2617 pSct->Init();
2618 pNewUpper = pSct;
2619 pSct->SimpleFormat();
2620 }
2621 }
2622 }
2623 sal_Bool bUnlock = sal_False;
2624 sal_Bool bFollow = sal_False;
2625 //Section locken, sonst kann sie bei Fluss des einzigen Cntnt etwa
2626 //von zweiter in die erste Spalte zerstoert werden.
2627 SwSectionFrm* pSect = pNewUpper->FindSctFrm();
2628 if( pSect )
2629 {
2630 bUnlock = !pSect->IsColLocked();
2631 pSect->ColLock();
2632 bFollow = pSect->HasFollow();
2633 }
2634 pNewUpper->Calc();
2635 rThis.Cut();
2636 // --> OD 2005-02-23 #b6229852#
2637 // optimization: format section, if its size is invalidated and if it's
2638 // the new parent of moved backward frame.
2639 bool bFormatSect( false );
2640 // <--
2641 if( bUnlock )
2642 {
2643 pSect->ColUnlock();
2644 if( pSect->HasFollow() != bFollow )
2645 {
2646 pSect->InvalidateSize();
2647 // --> OD 2005-02-23 #b6229852# - optimization
2648 if ( pSect == pNewUpper )
2649 bFormatSect = true;
2650 // <--
2651 }
2652 }
2653
2654 rThis.Paste( pNewUpper );
2655 // --> OD 2005-02-23 #b6229852# - optimization
2656 if ( bFormatSect )
2657 pSect->Calc();
2658 // <--
2659
2660 SwPageFrm *pNewPage = rThis.FindPageFrm();
2661 if( pNewPage != pOldPage )
2662 {
2663 rThis.Prepare( PREP_BOSS_CHGD, (const void*)pOldPage, sal_False );
2664 ViewShell *pSh = rThis.getRootFrm()->GetCurrShell();
2665 if ( pSh && !pSh->Imp()->IsUpdateExpFlds() )
2666 pSh->GetDoc()->SetNewFldLst(true); //Wird von CalcLayout() hinterher eledigt!
2667
2668 pNewPage->InvalidateSpelling();
2669 pNewPage->InvalidateSmartTags(); // SMARTTAGS
2670 pNewPage->InvalidateAutoCompleteWords();
2671 pNewPage->InvalidateWordCount();
2672
2673 // OD 30.10.2002 #97265# - no <CheckPageDesc(..)> in online layout
2674 if ( !( pSh && pSh->GetViewOptions()->getBrowseMode() ) )
2675 {
2676 if ( bCheckPageDescs && pNewPage->GetNext() )
2677 {
2678 SwPageFrm* pStartPage = bCheckPageDescOfNextPage ?
2679 pNewPage :
2680 (SwPageFrm*)pNewPage->GetNext();
2681 SwFrm::CheckPageDescs( pStartPage, sal_False);
2682 }
2683 else if ( rThis.GetAttrSet()->GetPageDesc().GetPageDesc() )
2684 {
2685 //Erste Seite wird etwa durch Ausblenden eines Bereiches leer
2686 SwFrm::CheckPageDescs( (SwPageFrm*)pNewPage, sal_False);
2687 }
2688 }
2689 }
2690 }
2691 return pNewUpper != 0;
2692 }
2693
2694 /*************************************************************************
2695 |*
2696 |* SwFlowFrm::CastFlowFrm
2697 |*
2698 |* Ersterstellung MA 03. May. 95
2699 |* Letzte Aenderung AMA 02. Dec. 97
2700 |*
2701 |*************************************************************************/
2702
CastFlowFrm(SwFrm * pFrm)2703 SwFlowFrm *SwFlowFrm::CastFlowFrm( SwFrm *pFrm )
2704 {
2705 if ( pFrm->IsCntntFrm() )
2706 return (SwCntntFrm*)pFrm;
2707 if ( pFrm->IsTabFrm() )
2708 return (SwTabFrm*)pFrm;
2709 if ( pFrm->IsSctFrm() )
2710 return (SwSectionFrm*)pFrm;
2711 return 0;
2712 }
2713
CastFlowFrm(const SwFrm * pFrm)2714 const SwFlowFrm *SwFlowFrm::CastFlowFrm( const SwFrm *pFrm )
2715 {
2716 if ( pFrm->IsCntntFrm() )
2717 return (SwCntntFrm*)pFrm;
2718 if ( pFrm->IsTabFrm() )
2719 return (SwTabFrm*)pFrm;
2720 if ( pFrm->IsSctFrm() )
2721 return (SwSectionFrm*)pFrm;
2722 return 0;
2723 }
2724