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 <txtftn.hxx>
21 : #include <fmtftn.hxx>
22 : #include <ftnidx.hxx>
23 : #include <pagefrm.hxx>
24 : #include <colfrm.hxx>
25 : #include <rootfrm.hxx>
26 : #include <frmtool.hxx>
27 : #include <ftnfrm.hxx>
28 : #include <txtfrm.hxx>
29 : #include <tabfrm.hxx>
30 : #include <pagedesc.hxx>
31 : #include <ftninfo.hxx>
32 : #include <sectfrm.hxx>
33 : #include <objectformatter.hxx>
34 : #include "viewopt.hxx"
35 : #include <switerator.hxx>
36 :
37 : #define ENDNOTE 0x80000000
38 :
39 : /// Search the position of an attribute in the FtnArray at the document,
40 : /// because all footnotes are located there, ordered by their index.
41 420 : static sal_uLong lcl_FindFtnPos( const SwDoc *pDoc, const SwTxtFtn *pAttr )
42 : {
43 420 : const SwFtnIdxs &rFtnIdxs = pDoc->GetFtnIdxs();
44 :
45 420 : SwTxtFtn* pBla = (SwTxtFtn*)pAttr;
46 420 : SwFtnIdxs::const_iterator it = rFtnIdxs.find( pBla );
47 420 : if ( it != rFtnIdxs.end() )
48 : {
49 420 : sal_uInt16 nRet = it - rFtnIdxs.begin();
50 420 : if( pAttr->GetFtn().IsEndNote() )
51 108 : return sal_uLong(nRet) + ENDNOTE;
52 312 : return nRet;
53 : }
54 : OSL_ENSURE( !pDoc, "FtnPos not found." );
55 0 : return 0;
56 : }
57 :
58 0 : bool SwFtnFrm::operator<( const SwTxtFtn* pTxtFtn ) const
59 : {
60 0 : const SwDoc* pDoc = GetFmt()->GetDoc();
61 : OSL_ENSURE( pDoc, "SwFtnFrm: Missing doc!" );
62 0 : return lcl_FindFtnPos( pDoc, GetAttr() ) <
63 0 : lcl_FindFtnPos( pDoc, pTxtFtn );
64 : }
65 :
66 : /*
67 : |*
68 : |* bool lcl_NextFtnBoss( SwFtnBossFrm* pBoss, SwPageFrm* pPage)
69 : |* sets pBoss on the next SwFtnBossFrm, which can either be a column
70 : |* or a page (without columns). If the page changes meanwhile,
71 : |* pPage contains the new page and this function returns sal_True.
72 : |*
73 : |*/
74 :
75 338 : static bool lcl_NextFtnBoss( SwFtnBossFrm* &rpBoss, SwPageFrm* &rpPage,
76 : bool bDontLeave )
77 : {
78 338 : if( rpBoss->IsColumnFrm() )
79 : {
80 30 : if( rpBoss->GetNext() )
81 : {
82 8 : rpBoss = (SwFtnBossFrm*)rpBoss->GetNext(); //next column
83 8 : return false;
84 : }
85 22 : if( rpBoss->IsInSct() )
86 : {
87 22 : SwSectionFrm* pSct = rpBoss->FindSctFrm()->GetFollow();
88 22 : if( pSct )
89 : {
90 : OSL_ENSURE( pSct->Lower() && pSct->Lower()->IsColumnFrm(),
91 : "Where's the column?" );
92 0 : rpBoss = (SwColumnFrm*)pSct->Lower();
93 0 : SwPageFrm* pOld = rpPage;
94 0 : rpPage = pSct->FindPageFrm();
95 0 : return pOld != rpPage;
96 : }
97 22 : else if( bDontLeave )
98 : {
99 0 : rpPage = NULL;
100 0 : rpBoss = NULL;
101 0 : return false;
102 : }
103 : }
104 : }
105 330 : rpPage = (SwPageFrm*)rpPage->GetNext(); // next page
106 330 : rpBoss = rpPage;
107 330 : if( rpPage )
108 : {
109 26 : SwLayoutFrm* pBody = rpPage->FindBodyCont();
110 26 : if( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrm() )
111 0 : rpBoss = (SwFtnBossFrm*)pBody->Lower(); // first column
112 : }
113 330 : return true;
114 : }
115 :
116 : /// @returns column number if pBoss is a column, otherwise 0.
117 648 : static sal_uInt16 lcl_ColumnNum( const SwFrm* pBoss )
118 : {
119 648 : sal_uInt16 nRet = 0;
120 648 : if( !pBoss->IsColumnFrm() )
121 564 : return 0;
122 : const SwFrm* pCol;
123 84 : if( pBoss->IsInSct() )
124 : {
125 84 : pCol = pBoss->GetUpper()->FindColFrm();
126 84 : if( pBoss->GetNext() || pBoss->GetPrev() )
127 : {
128 332 : while( pBoss )
129 : {
130 164 : ++nRet; // Section columns
131 164 : pBoss = pBoss->GetPrev();
132 : }
133 : }
134 : }
135 : else
136 0 : pCol = pBoss;
137 168 : while( pCol )
138 : {
139 0 : nRet += 256; // Page columns
140 0 : pCol = pCol->GetPrev();
141 : }
142 84 : return nRet;
143 : }
144 :
145 126 : SwFtnContFrm::SwFtnContFrm( SwFrmFmt *pFmt, SwFrm* pSib ):
146 126 : SwLayoutFrm( pFmt, pSib )
147 : {
148 126 : mnType = FRMC_FTNCONT;
149 126 : }
150 :
151 :
152 : // lcl_Undersize(..) walks over a SwFrm and its contents
153 : // and returns the sum of all requested TxtFrm magnifications.
154 :
155 794 : static long lcl_Undersize( const SwFrm* pFrm )
156 : {
157 794 : long nRet = 0;
158 794 : SWRECTFN( pFrm )
159 794 : if( pFrm->IsTxtFrm() )
160 : {
161 440 : if( ((SwTxtFrm*)pFrm)->IsUndersized() )
162 : {
163 : // Does this TxtFrm would like to be a little bit bigger?
164 0 : nRet = ((SwTxtFrm*)pFrm)->GetParHeight() -
165 0 : (pFrm->Prt().*fnRect->fnGetHeight)();
166 0 : if( nRet < 0 )
167 0 : nRet = 0;
168 : }
169 : }
170 354 : else if( pFrm->IsLayoutFrm() )
171 : {
172 354 : const SwFrm* pNxt = ((SwLayoutFrm*)pFrm)->Lower();
173 1158 : while( pNxt )
174 : {
175 450 : nRet += lcl_Undersize( pNxt );
176 450 : pNxt = pNxt->GetNext();
177 : }
178 : }
179 794 : return nRet;
180 : }
181 :
182 : /// "format" the frame (Fixsize is not set here).
183 332 : void SwFtnContFrm::Format( const SwBorderAttrs * )
184 : {
185 : // calculate total border, only one distance to the top
186 332 : const SwPageFrm* pPage = FindPageFrm();
187 332 : const SwPageFtnInfo &rInf = pPage->GetPageDesc()->GetFtnInfo();
188 664 : const SwTwips nBorder = rInf.GetTopDist() + rInf.GetBottomDist() +
189 664 : rInf.GetLineWidth();
190 332 : SWRECTFN( this )
191 332 : if ( !mbValidPrtArea )
192 : {
193 332 : mbValidPrtArea = true;
194 332 : (Prt().*fnRect->fnSetTop)( nBorder );
195 332 : (Prt().*fnRect->fnSetWidth)( (Frm().*fnRect->fnGetWidth)() );
196 332 : (Prt().*fnRect->fnSetHeight)((Frm().*fnRect->fnGetHeight)() - nBorder );
197 332 : if( (Prt().*fnRect->fnGetHeight)() < 0 && !pPage->IsFtnPage() )
198 102 : mbValidSize = false;
199 : }
200 :
201 332 : if ( !mbValidSize )
202 : {
203 332 : bool bGrow = pPage->IsFtnPage();
204 332 : if( bGrow )
205 : {
206 26 : const SwViewShell *pSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0;
207 26 : if( pSh && pSh->GetViewOptions()->getBrowseMode() )
208 0 : bGrow = false;
209 : }
210 332 : if( bGrow )
211 26 : Grow( LONG_MAX, false );
212 : else
213 : {
214 : // VarSize is determined based on the content plus the borders
215 306 : SwTwips nRemaining = 0;
216 306 : SwFrm *pFrm = pLower;
217 956 : while ( pFrm )
218 : { // lcl_Undersize(..) respects (recursively) TxtFrms, which
219 : // would like to be bigger. They are created especially in
220 : // columnized borders, if these do not have their maximum
221 : // size yet.
222 344 : nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)() + lcl_Undersize( pFrm );
223 344 : pFrm = pFrm->GetNext();
224 : }
225 : // add the own border
226 306 : nRemaining += nBorder;
227 :
228 : SwTwips nDiff;
229 306 : if( IsInSct() )
230 : {
231 10 : nDiff = -(Frm().*fnRect->fnBottomDist)(
232 10 : (GetUpper()->*fnRect->fnGetPrtBottom)() );
233 10 : if( nDiff > 0 )
234 : {
235 0 : if( nDiff > (Frm().*fnRect->fnGetHeight)() )
236 0 : nDiff = (Frm().*fnRect->fnGetHeight)();
237 0 : (Frm().*fnRect->fnAddBottom)( -nDiff );
238 0 : (Prt().*fnRect->fnAddHeight)( -nDiff );
239 : }
240 : }
241 306 : nDiff = (Frm().*fnRect->fnGetHeight)() - nRemaining;
242 306 : if ( nDiff > 0 )
243 0 : Shrink( nDiff );
244 306 : else if ( nDiff < 0 )
245 : {
246 102 : Grow( -nDiff );
247 : // It may happen that there is less space available,
248 : // than what the border needs - the size of the PrtArea
249 : // will then be negative.
250 102 : SwTwips nPrtHeight = (Prt().*fnRect->fnGetHeight)();
251 102 : if( nPrtHeight < 0 )
252 : {
253 0 : const SwTwips nTmpDiff = std::max( (Prt().*fnRect->fnGetTop)(),
254 0 : -nPrtHeight );
255 0 : (Prt().*fnRect->fnSubTop)( nTmpDiff );
256 : }
257 : }
258 : }
259 332 : mbValidSize = true;
260 : }
261 332 : }
262 :
263 1048 : SwTwips SwFtnContFrm::GrowFrm( SwTwips nDist, bool bTst, bool )
264 : {
265 : // No check if FixSize since FtnContainer are variable up to their max. height.
266 : // If the max. height is LONG_MAX, take as much space as needed.
267 : // If the page is a special footnote page, take also as much as possible.
268 : assert(GetUpper() && GetUpper()->IsFtnBossFrm());
269 :
270 1048 : SWRECTFN( this )
271 1970 : if( (Frm().*fnRect->fnGetHeight)() > 0 &&
272 922 : nDist > ( LONG_MAX - (Frm().*fnRect->fnGetHeight)() ) )
273 466 : nDist = LONG_MAX - (Frm().*fnRect->fnGetHeight)();
274 :
275 1048 : SwFtnBossFrm *pBoss = static_cast<SwFtnBossFrm*>(GetUpper());
276 1048 : if( IsInSct() )
277 : {
278 26 : SwSectionFrm* pSect = FindSctFrm();
279 : OSL_ENSURE( pSect, "GrowFrm: Missing SectFrm" );
280 : // In a section, which has to maximize, a footnotecontainer is allowed
281 : // to grow, when the section can't grow anymore.
282 62 : if( !bTst && !pSect->IsColLocked() &&
283 26 : pSect->ToMaximize( false ) && pSect->Growable() )
284 : {
285 0 : pSect->InvalidateSize();
286 0 : return 0;
287 : }
288 : }
289 1048 : const SwViewShell *pSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0;
290 1048 : const bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
291 1048 : SwPageFrm *pPage = pBoss->FindPageFrm();
292 1048 : if ( bBrowseMode || !pPage->IsFtnPage() )
293 : {
294 936 : if ( pBoss->GetMaxFtnHeight() != LONG_MAX )
295 : {
296 934 : nDist = std::min( nDist, pBoss->GetMaxFtnHeight()
297 934 : - (Frm().*fnRect->fnGetHeight)() );
298 934 : if ( nDist <= 0 )
299 0 : return 0L;
300 : }
301 : // FtnBoss also influences the max value
302 936 : if( !IsInSct() )
303 : {
304 910 : const SwTwips nMax = pBoss->GetVarSpace();
305 910 : if ( nDist > nMax )
306 418 : nDist = nMax;
307 910 : if ( nDist <= 0 )
308 0 : return 0L;
309 : }
310 : }
311 112 : else if( nDist > (GetPrev()->Frm().*fnRect->fnGetHeight)() )
312 : // do not use more space than the body has
313 112 : nDist = (GetPrev()->Frm().*fnRect->fnGetHeight)();
314 :
315 1048 : long nAvail = 0;
316 1048 : if ( bBrowseMode )
317 : {
318 0 : nAvail = GetUpper()->Prt().Height();
319 0 : const SwFrm *pAvail = GetUpper()->Lower();
320 0 : do
321 0 : { nAvail -= pAvail->Frm().Height();
322 0 : pAvail = pAvail->GetNext();
323 : } while ( pAvail );
324 0 : if ( nAvail > nDist )
325 0 : nAvail = nDist;
326 : }
327 :
328 1048 : if ( !bTst )
329 : {
330 340 : (Frm().*fnRect->fnSetHeight)( (Frm().*fnRect->fnGetHeight)() + nDist );
331 :
332 340 : if( IsVertical() && !IsVertLR() && !IsReverse() )
333 0 : Frm().Pos().X() -= nDist;
334 : }
335 1048 : long nGrow = nDist - nAvail,
336 1048 : nReal = 0;
337 1048 : if ( nGrow > 0 )
338 : {
339 960 : sal_uInt8 nAdjust = pBoss->NeighbourhoodAdjustment( this );
340 960 : if( NA_ONLY_ADJUST == nAdjust )
341 960 : nReal = AdjustNeighbourhood( nGrow, bTst );
342 : else
343 : {
344 0 : if( NA_GROW_ADJUST == nAdjust )
345 : {
346 0 : SwFrm* pFtn = Lower();
347 0 : if( pFtn )
348 : {
349 0 : while( pFtn->GetNext() )
350 0 : pFtn = pFtn->GetNext();
351 0 : if( ((SwFtnFrm*)pFtn)->GetAttr()->GetFtn().IsEndNote() )
352 : {
353 0 : nReal = AdjustNeighbourhood( nGrow, bTst );
354 0 : nAdjust = NA_GROW_SHRINK; // no more AdjustNeighbourhood
355 : }
356 : }
357 : }
358 0 : nReal += pBoss->Grow( nGrow - nReal, bTst );
359 0 : if( ( NA_GROW_ADJUST == nAdjust || NA_ADJUST_GROW == nAdjust )
360 0 : && nReal < nGrow )
361 0 : nReal += AdjustNeighbourhood( nGrow - nReal, bTst );
362 : }
363 : }
364 :
365 1048 : nReal += nAvail;
366 :
367 1048 : if ( !bTst )
368 : {
369 340 : if ( nReal != nDist )
370 : {
371 0 : nDist -= nReal;
372 : // We can only respect the boundless wish so much
373 0 : Frm().SSize().Height() -= nDist;
374 :
375 0 : if( IsVertical() && !IsVertLR() && !IsReverse() )
376 0 : Frm().Pos().X() += nDist;
377 : }
378 :
379 : // growing happens upwards, so successors to not need to be invalidated
380 340 : if( nReal )
381 : {
382 338 : _InvalidateSize();
383 338 : _InvalidatePos();
384 338 : InvalidatePage( pPage );
385 : }
386 : }
387 1048 : return nReal;
388 : }
389 :
390 56 : SwTwips SwFtnContFrm::ShrinkFrm( SwTwips nDiff, bool bTst, bool bInfo )
391 : {
392 56 : SwPageFrm *pPage = FindPageFrm();
393 56 : bool bShrink = false;
394 56 : if ( pPage )
395 : {
396 56 : if( !pPage->IsFtnPage() )
397 46 : bShrink = true;
398 : else
399 : {
400 10 : const SwViewShell *pSh = getRootFrm()->GetCurrShell();
401 10 : if( pSh && pSh->GetViewOptions()->getBrowseMode() )
402 0 : bShrink = true;
403 : }
404 : }
405 56 : if( bShrink )
406 : {
407 46 : SwTwips nRet = SwLayoutFrm::ShrinkFrm( nDiff, bTst, bInfo );
408 46 : if( IsInSct() && !bTst )
409 2 : FindSctFrm()->InvalidateNextPos();
410 46 : if ( !bTst && nRet )
411 : {
412 44 : _InvalidatePos();
413 44 : InvalidatePage( pPage );
414 : }
415 46 : return nRet;
416 : }
417 10 : return 0;
418 : }
419 :
420 178 : SwFtnFrm::SwFtnFrm( SwFrmFmt *pFmt, SwFrm* pSib, SwCntntFrm *pCnt, SwTxtFtn *pAt ):
421 : SwLayoutFrm( pFmt, pSib ),
422 : pFollow( 0 ),
423 : pMaster( 0 ),
424 : pRef( pCnt ),
425 : pAttr( pAt ),
426 : bBackMoveLocked( false ),
427 : // #i49383#
428 178 : mbUnlockPosOfLowerObjs( true )
429 : {
430 178 : mnType = FRMC_FTN;
431 178 : }
432 :
433 178 : void SwFtnFrm::InvalidateNxtFtnCnts( SwPageFrm *pPage )
434 : {
435 178 : if ( GetNext() )
436 : {
437 6 : SwFrm *pCnt = ((SwLayoutFrm*)GetNext())->ContainsAny();
438 6 : if( pCnt )
439 : {
440 6 : pCnt->InvalidatePage( pPage );
441 6 : pCnt->_InvalidatePrt();
442 6 : do
443 6 : { pCnt->_InvalidatePos();
444 6 : if( pCnt->IsSctFrm() )
445 : {
446 0 : SwFrm* pTmp = ((SwSectionFrm*)pCnt)->ContainsAny();
447 0 : if( pTmp )
448 0 : pTmp->_InvalidatePos();
449 : }
450 6 : pCnt->GetUpper()->_InvalidateSize();
451 6 : pCnt = pCnt->FindNext();
452 6 : } while ( pCnt && GetUpper()->IsAnLower( pCnt ) );
453 : }
454 : }
455 178 : }
456 :
457 : #ifdef DBG_UTIL
458 : SwTwips SwFtnFrm::GrowFrm( SwTwips nDist, bool bTst, bool bInfo )
459 : {
460 : static sal_uInt16 nNum = USHRT_MAX;
461 : SwTxtFtn* pTxtFtn = GetAttr();
462 : if ( pTxtFtn->GetFtn().GetNumber() == nNum )
463 : {
464 : int bla = 5;
465 : (void)bla;
466 :
467 : }
468 : return SwLayoutFrm::GrowFrm( nDist, bTst, bInfo );
469 : }
470 :
471 : SwTwips SwFtnFrm::ShrinkFrm( SwTwips nDist, bool bTst, bool bInfo )
472 : {
473 : static sal_uInt16 nNum = USHRT_MAX;
474 : if( nNum != USHRT_MAX )
475 : {
476 : SwTxtFtn* pTxtFtn = GetAttr();
477 : if( pTxtFtn->GetFtn().GetNumber() == nNum )
478 : {
479 : int bla = 5;
480 : (void)bla;
481 : }
482 : }
483 : return SwLayoutFrm::ShrinkFrm( nDist, bTst, bInfo );
484 : }
485 : #endif
486 :
487 178 : void SwFtnFrm::Cut()
488 : {
489 178 : if ( GetNext() )
490 46 : GetNext()->InvalidatePos();
491 132 : else if ( GetPrev() )
492 6 : GetPrev()->SetRetouche();
493 :
494 : // first move then shrink Upper
495 178 : SwLayoutFrm *pUp = GetUpper();
496 :
497 : // correct chaining
498 178 : SwFtnFrm *pFtn = (SwFtnFrm*)this;
499 178 : if ( pFtn->GetFollow() )
500 0 : pFtn->GetFollow()->SetMaster( pFtn->GetMaster() );
501 178 : if ( pFtn->GetMaster() )
502 0 : pFtn->GetMaster()->SetFollow( pFtn->GetFollow() );
503 178 : pFtn->SetFollow( 0 );
504 178 : pFtn->SetMaster( 0 );
505 :
506 : // cut all connections
507 178 : Remove();
508 :
509 178 : if ( pUp )
510 : {
511 : // The last footnote takes its container along
512 178 : if ( !pUp->Lower() )
513 : {
514 126 : SwPageFrm *pPage = pUp->FindPageFrm();
515 126 : if ( pPage )
516 : {
517 126 : SwLayoutFrm *pBody = pPage->FindBodyCont();
518 126 : if( pBody && !pBody->ContainsCntnt() )
519 24 : pPage->getRootFrm()->SetSuperfluous();
520 : }
521 126 : SwSectionFrm* pSect = pUp->FindSctFrm();
522 126 : pUp->Cut();
523 126 : delete pUp;
524 : // If the last footnote container was removed from a column
525 : // section without a Follow, then this section can be shrinked.
526 126 : if( pSect && !pSect->ToMaximize( false ) && !pSect->IsColLocked() )
527 2 : pSect->_InvalidateSize();
528 : }
529 : else
530 52 : { if ( Frm().Height() )
531 48 : pUp->Shrink( Frm().Height() );
532 52 : pUp->SetCompletePaint();
533 52 : pUp->InvalidatePage();
534 : }
535 : }
536 178 : }
537 :
538 178 : void SwFtnFrm::Paste( SwFrm* pParent, SwFrm* pSibling )
539 : {
540 : OSL_ENSURE( pParent, "no parent in Paste." );
541 : OSL_ENSURE( pParent->IsLayoutFrm(), "Parent is CntntFrm." );
542 : OSL_ENSURE( pParent != this, "I am my own parent." );
543 : OSL_ENSURE( pSibling != this, "I am my own sibling." );
544 : OSL_ENSURE( !GetPrev() && !GetNext() && !GetUpper(),
545 : "I am still somewhere registered." );
546 :
547 : // insert into tree structure
548 178 : InsertBefore( (SwLayoutFrm*)pParent, pSibling );
549 :
550 178 : SWRECTFN( this )
551 178 : if( (Frm().*fnRect->fnGetWidth)()!=(pParent->Prt().*fnRect->fnGetWidth)() )
552 52 : _InvalidateSize();
553 178 : _InvalidatePos();
554 178 : SwPageFrm *pPage = FindPageFrm();
555 178 : InvalidatePage( pPage );
556 178 : if ( GetNext() )
557 6 : GetNext()->_InvalidatePos();
558 178 : if( (Frm().*fnRect->fnGetHeight)() )
559 0 : pParent->Grow( (Frm().*fnRect->fnGetHeight)() );
560 :
561 : // If the predecessor is the master and/or the successor is the Follow,
562 : // then take their content and destroy them.
563 178 : if ( GetPrev() && GetPrev() == GetMaster() )
564 : { OSL_ENSURE( SwFlowFrm::CastFlowFrm( GetPrev()->GetLower() ),
565 : "Footnote without content?" );
566 : (SwFlowFrm::CastFlowFrm( GetPrev()->GetLower()))->
567 0 : MoveSubTree( this, GetLower() );
568 0 : SwFrm *pDel = GetPrev();
569 0 : pDel->Cut();
570 0 : delete pDel;
571 : }
572 178 : if ( GetNext() && GetNext() == GetFollow() )
573 : { OSL_ENSURE( SwFlowFrm::CastFlowFrm( GetNext()->GetLower() ),
574 : "Footnote without content?" );
575 0 : (SwFlowFrm::CastFlowFrm( GetNext()->GetLower()))->MoveSubTree( this );
576 0 : SwFrm *pDel = GetNext();
577 0 : pDel->Cut();
578 0 : delete pDel;
579 : }
580 : #if OSL_DEBUG_LEVEL > 0
581 : SwDoc *pDoc = GetFmt()->GetDoc();
582 : if ( GetPrev() )
583 : {
584 : OSL_ENSURE( lcl_FindFtnPos( pDoc, ((SwFtnFrm*)GetPrev())->GetAttr() ) <=
585 : lcl_FindFtnPos( pDoc, GetAttr() ), "Prev is not FtnPrev" );
586 : }
587 : if ( GetNext() )
588 : {
589 : OSL_ENSURE( lcl_FindFtnPos( pDoc, GetAttr() ) <=
590 : lcl_FindFtnPos( pDoc, ((SwFtnFrm*)GetNext())->GetAttr() ),
591 : "Next is not FtnNext" );
592 : }
593 : #endif
594 178 : InvalidateNxtFtnCnts( pPage );
595 178 : }
596 :
597 : /// Return the next layout leaf in that the frame can be moved.
598 : /// New pages will only be created if the parameter is sal_True.
599 0 : SwLayoutFrm *SwFrm::GetNextFtnLeaf( MakePageType eMakePage )
600 : {
601 0 : SwFtnBossFrm *pOldBoss = FindFtnBossFrm();
602 0 : SwPageFrm* pOldPage = pOldBoss->FindPageFrm();
603 : SwPageFrm* pPage;
604 0 : SwFtnBossFrm *pBoss = pOldBoss->IsColumnFrm() ?
605 0 : (SwFtnBossFrm*)pOldBoss->GetNext() : 0; // next column, if existing
606 0 : if( pBoss )
607 0 : pPage = NULL;
608 : else
609 : {
610 0 : if( pOldBoss->GetUpper()->IsSctFrm() )
611 : { // this can only be in a column area
612 0 : SwLayoutFrm* pNxt = pOldBoss->GetNextSctLeaf( eMakePage );
613 0 : if( pNxt )
614 : {
615 : OSL_ENSURE( pNxt->IsColBodyFrm(), "GetNextFtnLeaf: Funny Leaf" );
616 0 : pBoss = (SwFtnBossFrm*)pNxt->GetUpper();
617 0 : pPage = pBoss->FindPageFrm();
618 : }
619 : else
620 0 : return 0;
621 : }
622 : else
623 : {
624 : // next page
625 0 : pPage = (SwPageFrm*)pOldPage->GetNext();
626 : // skip empty pages
627 0 : if( pPage && pPage->IsEmptyPage() )
628 0 : pPage = (SwPageFrm*)pPage->GetNext();
629 0 : pBoss = pPage;
630 : }
631 : }
632 : // What do we have until here?
633 : // pBoss != NULL, pPage==NULL => pBoss is the next column on the same page
634 : // pBoss != NULL, pPage!=NULL => pBoss and pPage are the following page (empty pages skipped)
635 : // pBoss == NULL => pPage == NULL, so there are no following pages
636 :
637 : // If the footnote has already a Follow we do not need to search.
638 : // However, if there are unwanted empty columns/pages between Ftn and Follow,
639 : // create another Follow on the next best column/page and the rest will sort itself out.
640 0 : SwFtnFrm *pFtn = FindFtnFrm();
641 0 : if ( pFtn && pFtn->GetFollow() )
642 : {
643 0 : SwFtnBossFrm* pTmpBoss = pFtn->GetFollow()->FindFtnBossFrm();
644 : // Following cases will be handled:
645 : // 1. both "FtnBoss"es are neighboring columns/pages
646 : // 2. the new one is the first column of a neighboring page
647 : // 3. the new one is the first column in a section of the next page
648 0 : while( pTmpBoss != pBoss && pTmpBoss && !pTmpBoss->GetPrev() )
649 0 : pTmpBoss = pTmpBoss->GetUpper()->FindFtnBossFrm();
650 0 : if( pTmpBoss == pBoss )
651 0 : return pFtn->GetFollow();
652 : }
653 :
654 : // If no pBoss could be found or it is a "wrong" page, we need a new page.
655 0 : if ( !pBoss || ( pPage && pPage->IsEndNotePage() && !pOldPage->IsEndNotePage() ) )
656 : {
657 0 : if ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT )
658 : {
659 0 : pBoss = InsertPage( pOldPage, pOldPage->IsFtnPage() );
660 0 : ((SwPageFrm*)pBoss)->SetEndNotePage( pOldPage->IsEndNotePage() );
661 : }
662 : else
663 0 : return 0;
664 : }
665 0 : if( pBoss->IsPageFrm() )
666 : {
667 : // If this page has columns, then go to the first one
668 0 : SwLayoutFrm* pLay = pBoss->FindBodyCont();
669 0 : if( pLay && pLay->Lower() && pLay->Lower()->IsColumnFrm() )
670 0 : pBoss = (SwFtnBossFrm*)pLay->Lower();
671 : }
672 : // found column/page - add myself
673 0 : SwFtnContFrm *pCont = pBoss->FindFtnCont();
674 0 : if ( !pCont && pBoss->GetMaxFtnHeight() &&
675 0 : ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT ) )
676 0 : pCont = pBoss->MakeFtnCont();
677 0 : return pCont;
678 : }
679 :
680 : /// Get the preceeding layout leaf in that the frame can be moved.
681 74 : SwLayoutFrm *SwFrm::GetPrevFtnLeaf( MakePageType eMakeFtn )
682 : {
683 : // The predecessor of a footnote is (if possible)
684 : // the master of the chain of the footnote.
685 74 : SwFtnFrm *pFtn = FindFtnFrm();
686 74 : SwLayoutFrm *pRet = pFtn->GetMaster();
687 :
688 74 : SwFtnBossFrm* pOldBoss = FindFtnBossFrm();
689 74 : SwPageFrm *pOldPage = pOldBoss->FindPageFrm();
690 :
691 74 : if ( !pOldBoss->GetPrev() && !pOldPage->GetPrev() )
692 0 : return pRet; // there is neither a predecessor column nor page
693 :
694 74 : if ( !pRet )
695 : {
696 74 : bool bEndn = pFtn->GetAttr()->GetFtn().IsEndNote();
697 74 : SwFrm* pTmpRef = NULL;
698 74 : if( bEndn && pFtn->IsInSct() )
699 : {
700 0 : SwSectionFrm* pSect = pFtn->FindSctFrm();
701 0 : if( pSect->IsEndnAtEnd() )
702 0 : pTmpRef = pSect->FindLastCntnt( FINDMODE_LASTCNT );
703 : }
704 74 : if( !pTmpRef )
705 74 : pTmpRef = pFtn->GetRef();
706 74 : SwFtnBossFrm* pStop = pTmpRef->FindFtnBossFrm( !bEndn );
707 :
708 74 : const sal_uInt16 nNum = pStop->GetPhyPageNum();
709 :
710 : // Do not leave the corresponding page if the footnote should
711 : // be shown at the document ending or the footnote is an endnote.
712 74 : const bool bEndNote = pOldPage->IsEndNotePage();
713 74 : const bool bFtnEndDoc = pOldPage->IsFtnPage();
714 74 : SwFtnBossFrm* pNxtBoss = pOldBoss;
715 74 : SwSectionFrm *pSect = pNxtBoss->GetUpper()->IsSctFrm() ?
716 74 : (SwSectionFrm*)pNxtBoss->GetUpper() : 0;
717 :
718 0 : do
719 : {
720 74 : if( pNxtBoss->IsColumnFrm() && pNxtBoss->GetPrev() )
721 0 : pNxtBoss = (SwFtnBossFrm*)pNxtBoss->GetPrev(); // one column backwards
722 : else // one page backwards
723 : {
724 74 : SwLayoutFrm* pBody = 0;
725 74 : if( pSect )
726 : {
727 0 : if( pSect->IsFtnLock() )
728 : {
729 0 : if( pNxtBoss == pOldBoss )
730 0 : return 0;
731 0 : pStop = pNxtBoss;
732 : }
733 : else
734 : {
735 0 : pSect = (SwSectionFrm*)pSect->FindMaster();
736 0 : if( !pSect || !pSect->Lower() )
737 0 : return 0;
738 : OSL_ENSURE( pSect->Lower()->IsColumnFrm(),
739 : "GetPrevFtnLeaf: Where's the column?" );
740 0 : pNxtBoss = (SwFtnBossFrm*)pSect->Lower();
741 0 : pBody = pSect;
742 : }
743 : }
744 : else
745 : {
746 74 : SwPageFrm* pPage = (SwPageFrm*)pNxtBoss->FindPageFrm()->GetPrev();
747 222 : if( !pPage || pPage->GetPhyPageNum() < nNum ||
748 152 : bEndNote != pPage->IsEndNotePage() || bFtnEndDoc != pPage->IsFtnPage() )
749 74 : return NULL; // no further pages found
750 0 : pNxtBoss = pPage;
751 0 : pBody = pPage->FindBodyCont();
752 : }
753 : // We have the previous page, we might need to find the last column of it
754 0 : if( pBody )
755 : {
756 0 : if ( pBody->Lower() && pBody->Lower()->IsColumnFrm() )
757 : {
758 0 : pNxtBoss = static_cast<SwFtnBossFrm*>(pBody->GetLastLower());
759 : }
760 : }
761 : }
762 0 : SwFtnContFrm *pCont = pNxtBoss->FindFtnCont();
763 0 : if ( pCont )
764 : {
765 0 : pRet = pCont;
766 0 : break;
767 : }
768 0 : if ( pStop == pNxtBoss )
769 : {
770 : // Reached the column/page of the reference.
771 : // Try to add a container and paste our content.
772 0 : if ( eMakeFtn == MAKEPAGE_FTN && pNxtBoss->GetMaxFtnHeight() )
773 0 : pRet = pNxtBoss->MakeFtnCont();
774 0 : break;
775 : }
776 : } while( !pRet );
777 : }
778 0 : if ( pRet )
779 : {
780 0 : const SwFtnBossFrm* pNewBoss = pRet->FindFtnBossFrm();
781 0 : bool bJump = false;
782 0 : if( pOldBoss->IsColumnFrm() && pOldBoss->GetPrev() ) // a previous column exists
783 0 : bJump = pOldBoss->GetPrev() != (SwFrm*)pNewBoss; // did we chose it?
784 0 : else if( pNewBoss->IsColumnFrm() && pNewBoss->GetNext() )
785 0 : bJump = true; // there is another column after the boss (not the old boss)
786 : else
787 : {
788 : // Will be reached only if old and new boss are both either pages or the last (new)
789 : // or first (old) column of a page. In this case, check if pages were skipped.
790 0 : sal_uInt16 nDiff = pOldPage->GetPhyPageNum() - pRet->FindPageFrm()->GetPhyPageNum();
791 0 : if ( nDiff > 2 ||
792 0 : (nDiff > 1 && !((SwPageFrm*)pOldPage->GetPrev())->IsEmptyPage()) )
793 0 : bJump = true;
794 : }
795 0 : if( bJump )
796 0 : SwFlowFrm::SetMoveBwdJump( true );
797 : }
798 0 : return pRet;
799 : }
800 :
801 49798 : bool SwFrm::IsFtnAllowed() const
802 : {
803 49798 : if ( !IsInDocBody() )
804 13254 : return false;
805 :
806 36544 : if ( IsInTab() )
807 : {
808 : // no footnotes in repeated headlines
809 13238 : const SwTabFrm *pTab = ((SwFrm*)this)->ImplFindTabFrm();
810 13238 : if ( pTab->IsFollow() )
811 3732 : return !pTab->IsInHeadline( *this );
812 : }
813 32812 : return true;
814 : }
815 :
816 24 : void SwRootFrm::UpdateFtnNums()
817 : {
818 : // page numbering only if set at the document
819 24 : if ( GetFmt()->GetDoc()->GetFtnInfo().eNum == FTNNUM_PAGE )
820 : {
821 0 : SwPageFrm *pPage = (SwPageFrm*)Lower();
822 0 : while ( pPage && !pPage->IsFtnPage() )
823 : {
824 0 : pPage->UpdateFtnNum();
825 0 : pPage = (SwPageFrm*)pPage->GetNext();
826 : }
827 : }
828 24 : }
829 :
830 : /// remove all footnotes (not the references) and all footnote pages
831 7396 : void sw_RemoveFtns( SwFtnBossFrm* pBoss, bool bPageOnly, bool bEndNotes )
832 : {
833 7396 : do
834 : {
835 7396 : SwFtnContFrm *pCont = pBoss->FindFtnCont();
836 7396 : if ( pCont )
837 : {
838 116 : SwFtnFrm *pFtn = (SwFtnFrm*)pCont->Lower();
839 : OSL_ENSURE( pFtn, "Footnote content without footnote." );
840 116 : if ( bPageOnly )
841 0 : while ( pFtn->GetMaster() )
842 0 : pFtn = pFtn->GetMaster();
843 148 : do
844 : {
845 148 : SwFtnFrm *pNxt = (SwFtnFrm*)pFtn->GetNext();
846 148 : if ( !pFtn->GetAttr()->GetFtn().IsEndNote() ||
847 : bEndNotes )
848 : {
849 148 : pFtn->GetRef()->Prepare( PREP_FTN, (void*)pFtn->GetAttr() );
850 148 : if ( bPageOnly && !pNxt )
851 0 : pNxt = pFtn->GetFollow();
852 148 : pFtn->Cut();
853 148 : delete pFtn;
854 : }
855 148 : pFtn = pNxt;
856 :
857 : } while ( pFtn );
858 : }
859 7396 : if( !pBoss->IsInSct() )
860 : {
861 : // A sectionframe with the Ftn/EndnAtEnd-flags may contain
862 : // foot/endnotes. If the last lower frame of the bodyframe is
863 : // a multicolumned sectionframe, it may contain footnotes, too.
864 7216 : SwLayoutFrm* pBody = pBoss->FindBodyCont();
865 7216 : if( pBody && pBody->Lower() )
866 : {
867 7114 : SwFrm* pLow = pBody->Lower();
868 45978 : while (pLow)
869 : {
870 64434 : if( pLow->IsSctFrm() && ( !pLow->GetNext() ||
871 578 : ((SwSectionFrm*)pLow)->IsAnyNoteAtEnd() ) &&
872 32190 : ((SwSectionFrm*)pLow)->Lower() &&
873 220 : ((SwSectionFrm*)pLow)->Lower()->IsColumnFrm() )
874 78 : sw_RemoveFtns( (SwColumnFrm*)((SwSectionFrm*)pLow)->Lower(),
875 156 : bPageOnly, bEndNotes );
876 31750 : pLow = pLow->GetNext();
877 : }
878 : }
879 : }
880 : // is there another column?
881 7396 : pBoss = pBoss->IsColumnFrm() ? (SwColumnFrm*)pBoss->GetNext() : NULL;
882 : } while( pBoss );
883 7292 : }
884 :
885 5294 : void SwRootFrm::RemoveFtns( SwPageFrm *pPage, bool bPageOnly, bool bEndNotes )
886 : {
887 5294 : if ( !pPage )
888 5266 : pPage = (SwPageFrm*)Lower();
889 :
890 7162 : do
891 : { // On columned pages we have to clean up in all columns
892 : SwFtnBossFrm* pBoss;
893 7190 : SwLayoutFrm* pBody = pPage->FindBodyCont();
894 7190 : if( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrm() )
895 26 : pBoss = (SwFtnBossFrm*)pBody->Lower(); // the first column
896 : else
897 7164 : pBoss = pPage; // no columns
898 7190 : sw_RemoveFtns( pBoss, bPageOnly, bEndNotes );
899 7190 : if ( !bPageOnly )
900 : {
901 7210 : if ( pPage->IsFtnPage() &&
902 46 : (!pPage->IsEndNotePage() || bEndNotes) )
903 : {
904 24 : SwFrm *pDel = pPage;
905 24 : pPage = (SwPageFrm*)pPage->GetNext();
906 24 : pDel->Cut();
907 24 : delete pDel;
908 : }
909 : else
910 7138 : pPage = (SwPageFrm*)pPage->GetNext();
911 : }
912 : else
913 28 : break;
914 :
915 : } while ( pPage );
916 5294 : }
917 :
918 : /// Change the page template of the footnote pages
919 2 : void SwRootFrm::CheckFtnPageDescs( bool bEndNote )
920 : {
921 2 : SwPageFrm *pPage = (SwPageFrm*)Lower();
922 6 : while ( pPage && !pPage->IsFtnPage() )
923 2 : pPage = (SwPageFrm*)pPage->GetNext();
924 4 : while ( pPage && pPage->IsEndNotePage() != bEndNote )
925 0 : pPage = (SwPageFrm*)pPage->GetNext();
926 :
927 2 : if ( pPage )
928 2 : SwFrm::CheckPageDescs( pPage, false );
929 2 : }
930 :
931 : /** Insert a footnote container
932 : *
933 : * A footnote container is always placed directly behind the body text.
934 : *
935 : * The frame format (FrmFmt) is always the default frame format.
936 : *
937 : * @return footnote container frame
938 : */
939 126 : SwFtnContFrm *SwFtnBossFrm::MakeFtnCont()
940 : {
941 : SAL_WARN_IF(FindFtnCont(), "sw.core", "footnote container exists already");
942 :
943 126 : SwFtnContFrm *pNew = new SwFtnContFrm( GetFmt()->GetDoc()->GetDfltFrmFmt(), this );
944 126 : SwLayoutFrm *pLay = FindBodyCont();
945 126 : pNew->Paste( this, pLay->GetNext() );
946 126 : return pNew;
947 : }
948 :
949 16475 : SwFtnContFrm *SwFtnBossFrm::FindFtnCont()
950 : {
951 16475 : SwFrm *pFrm = Lower();
952 55847 : while( pFrm && !pFrm->IsFtnContFrm() )
953 22897 : pFrm = pFrm->GetNext();
954 :
955 : #if OSL_DEBUG_LEVEL > 0
956 : if ( pFrm )
957 : {
958 : SwFrm *pFtn = pFrm->GetLower();
959 : OSL_ENSURE( pFtn, "Content without footnote." );
960 : while ( pFtn )
961 : {
962 : OSL_ENSURE( pFtn->IsFtnFrm(), "Neighbor of footnote is not a footnote." );
963 : pFtn = pFtn->GetNext();
964 : }
965 : }
966 : #endif
967 :
968 16475 : return (SwFtnContFrm*)pFrm;
969 : }
970 :
971 : /// Search the next available footnote container.
972 542 : SwFtnContFrm *SwFtnBossFrm::FindNearestFtnCont( bool bDontLeave )
973 : {
974 542 : SwFtnContFrm *pCont = 0;
975 542 : if ( !GetFmt()->GetDoc()->GetFtnIdxs().empty() )
976 : {
977 542 : pCont = FindFtnCont();
978 542 : if ( !pCont )
979 : {
980 258 : SwPageFrm *pPage = FindPageFrm();
981 258 : SwFtnBossFrm* pBoss = this;
982 258 : bool bEndNote = pPage->IsEndNotePage();
983 270 : do
984 : {
985 270 : bool bChgPage = lcl_NextFtnBoss( pBoss, pPage, bDontLeave );
986 : // Found another boss? When changing pages, also the endnote flag must match.
987 270 : if( pBoss && ( !bChgPage || pPage->IsEndNotePage() == bEndNote ) )
988 12 : pCont = pBoss->FindFtnCont();
989 266 : } while ( !pCont && pPage );
990 : }
991 : }
992 542 : return pCont;
993 : }
994 :
995 406 : SwFtnFrm *SwFtnBossFrm::FindFirstFtn()
996 : {
997 : // search for the nearest footnote container
998 406 : SwFtnContFrm *pCont = FindNearestFtnCont();
999 406 : if ( !pCont )
1000 128 : return 0;
1001 :
1002 : // Starting from the first footnote, search the first
1003 : // footnote that is referenced by the current column/page
1004 :
1005 278 : SwFtnFrm *pRet = (SwFtnFrm*)pCont->Lower();
1006 278 : const sal_uInt16 nRefNum = FindPageFrm()->GetPhyPageNum();
1007 278 : const sal_uInt16 nRefCol = lcl_ColumnNum( this );
1008 : sal_uInt16 nPgNum, nColNum; // page number, column number
1009 : SwFtnBossFrm* pBoss;
1010 : SwPageFrm* pPage;
1011 278 : if( pRet )
1012 : {
1013 278 : pBoss = pRet->GetRef()->FindFtnBossFrm();
1014 : OSL_ENSURE( pBoss, "FindFirstFtn: No boss found" );
1015 278 : if( !pBoss )
1016 0 : return NULL; // ?There must be a bug, but no GPF
1017 278 : pPage = pBoss->FindPageFrm();
1018 278 : nPgNum = pPage->GetPhyPageNum();
1019 278 : if ( nPgNum == nRefNum )
1020 : {
1021 264 : nColNum = lcl_ColumnNum( pBoss );
1022 264 : if( nColNum == nRefCol )
1023 264 : return pRet; // found
1024 0 : else if( nColNum > nRefCol )
1025 0 : return NULL; // at least one column too far
1026 : }
1027 14 : else if ( nPgNum > nRefNum )
1028 0 : return NULL; // at least one column too far
1029 : }
1030 : else
1031 0 : return NULL;
1032 : // Done if Ref is on a subsequent page or on the same page in a subsequent column
1033 :
1034 26 : do
1035 : {
1036 52 : while ( pRet->GetFollow() )
1037 0 : pRet = pRet->GetFollow();
1038 :
1039 26 : SwFtnFrm *pNxt = (SwFtnFrm*)pRet->GetNext();
1040 26 : if ( !pNxt )
1041 : {
1042 14 : pBoss = pRet->FindFtnBossFrm();
1043 14 : pPage = pBoss->FindPageFrm();
1044 14 : lcl_NextFtnBoss( pBoss, pPage, false ); // next FtnBoss
1045 14 : pCont = pBoss ? pBoss->FindNearestFtnCont() : 0;
1046 14 : if ( pCont )
1047 0 : pNxt = (SwFtnFrm*)pCont->Lower();
1048 : }
1049 26 : if ( pNxt )
1050 : {
1051 12 : pRet = pNxt;
1052 12 : pBoss = pRet->GetRef()->FindFtnBossFrm();
1053 12 : pPage = pBoss->FindPageFrm();
1054 12 : nPgNum = pPage->GetPhyPageNum();
1055 12 : if ( nPgNum == nRefNum )
1056 : {
1057 0 : nColNum = lcl_ColumnNum( pBoss );
1058 0 : if( nColNum == nRefCol )
1059 0 : break; // found
1060 0 : else if( nColNum > nRefCol )
1061 0 : pRet = 0; // at least one column too far
1062 : }
1063 12 : else if ( nPgNum > nRefNum )
1064 0 : pRet = 0; // at least a page too far
1065 : }
1066 : else
1067 14 : pRet = 0; // there is none
1068 : } while( pRet );
1069 14 : return pRet;
1070 : }
1071 :
1072 : /// Get the first footnote of a given content
1073 60 : const SwFtnFrm *SwFtnBossFrm::FindFirstFtn( SwCntntFrm *pCnt ) const
1074 : {
1075 60 : const SwFtnFrm *pRet = ((SwFtnBossFrm*)this)->FindFirstFtn();
1076 60 : if ( pRet )
1077 : {
1078 56 : const sal_uInt16 nColNum = lcl_ColumnNum( this );
1079 56 : const sal_uInt16 nPageNum = GetPhyPageNum();
1080 132 : while ( pRet && (pRet->GetRef() != pCnt) )
1081 : {
1082 40 : while ( pRet->GetFollow() )
1083 0 : pRet = pRet->GetFollow();
1084 :
1085 20 : if ( pRet->GetNext() )
1086 12 : pRet = (const SwFtnFrm*)pRet->GetNext();
1087 : else
1088 8 : { SwFtnBossFrm *pBoss = (SwFtnBossFrm*)pRet->FindFtnBossFrm();
1089 8 : SwPageFrm *pPage = pBoss->FindPageFrm();
1090 8 : lcl_NextFtnBoss( pBoss, pPage, false ); // next FtnBoss
1091 8 : SwFtnContFrm *pCont = pBoss ? pBoss->FindNearestFtnCont() : 0;
1092 8 : pRet = pCont ? (SwFtnFrm*)pCont->Lower() : 0;
1093 : }
1094 20 : if ( pRet )
1095 : {
1096 20 : const SwFtnBossFrm* pBoss = pRet->GetRef()->FindFtnBossFrm();
1097 40 : if( pBoss->GetPhyPageNum() != nPageNum ||
1098 20 : nColNum != lcl_ColumnNum( pBoss ) )
1099 0 : pRet = 0;
1100 : }
1101 : }
1102 : }
1103 60 : return pRet;
1104 : }
1105 :
1106 178 : void SwFtnBossFrm::ResetFtn( const SwFtnFrm *pCheck )
1107 : {
1108 : // Destroy the incarnations of footnotes to an attribute, if they don't
1109 : // belong to pAssumed
1110 : OSL_ENSURE( !pCheck->GetMaster(), "given master is not a Master." );
1111 :
1112 178 : SwNodeIndex aIdx( *pCheck->GetAttr()->GetStartNode(), 1 );
1113 178 : SwCntntNode *pNd = aIdx.GetNode().GetCntntNode();
1114 178 : if ( !pNd )
1115 0 : pNd = pCheck->GetFmt()->GetDoc()->
1116 0 : GetNodes().GoNextSection( &aIdx, true, false );
1117 356 : SwIterator<SwFrm,SwCntntNode> aIter( *pNd );
1118 178 : SwFrm* pFrm = aIter.First();
1119 534 : while( pFrm )
1120 : {
1121 178 : if( pFrm->getRootFrm() == pCheck->getRootFrm() )
1122 : {
1123 178 : SwFrm *pTmp = pFrm->GetUpper();
1124 356 : while ( pTmp && !pTmp->IsFtnFrm() )
1125 0 : pTmp = pTmp->GetUpper();
1126 :
1127 178 : SwFtnFrm *pFtn = (SwFtnFrm*)pTmp;
1128 356 : while ( pFtn && pFtn->GetMaster() )
1129 0 : pFtn = pFtn->GetMaster();
1130 178 : if ( pFtn != pCheck )
1131 : {
1132 0 : while ( pFtn )
1133 : {
1134 0 : SwFtnFrm *pNxt = pFtn->GetFollow();
1135 0 : pFtn->Cut();
1136 0 : delete pFtn;
1137 0 : pFtn = pNxt;
1138 : }
1139 : }
1140 : }
1141 :
1142 178 : pFrm = aIter.Next();
1143 178 : }
1144 178 : }
1145 :
1146 178 : void SwFtnBossFrm::InsertFtn( SwFtnFrm* pNew )
1147 : {
1148 : // Place the footnote in front of the footnote whose attribute
1149 : // is in front of the new one (get position via the Doc).
1150 : // If there is no footnote in this footnote-boss yet, create a new container.
1151 : // If there is a container but no footnote for this footnote-boss yet, place
1152 : // the footnote behind the last footnote of the closest previous column/page.
1153 :
1154 178 : ResetFtn( pNew );
1155 178 : SwFtnFrm *pSibling = FindFirstFtn();
1156 178 : bool bDontLeave = false;
1157 :
1158 : // Ok, a sibling has been found, but is the sibling in an acceptable
1159 : // environment?
1160 178 : if( IsInSct() )
1161 : {
1162 6 : SwSectionFrm* pMySect = ImplFindSctFrm();
1163 6 : bool bEndnt = pNew->GetAttr()->GetFtn().IsEndNote();
1164 6 : if( bEndnt )
1165 : {
1166 0 : const SwSectionFmt* pEndFmt = pMySect->GetEndSectFmt();
1167 0 : bDontLeave = 0 != pEndFmt;
1168 0 : if( pSibling )
1169 : {
1170 0 : if( pEndFmt )
1171 : {
1172 0 : if( !pSibling->IsInSct() ||
1173 0 : !pSibling->ImplFindSctFrm()->IsDescendantFrom( pEndFmt ) )
1174 0 : pSibling = NULL;
1175 : }
1176 0 : else if( pSibling->IsInSct() )
1177 0 : pSibling = NULL;
1178 : }
1179 : }
1180 : else
1181 : {
1182 6 : bDontLeave = pMySect->IsFtnAtEnd();
1183 6 : if( pSibling )
1184 : {
1185 2 : if( pMySect->IsFtnAtEnd() )
1186 : {
1187 0 : if( !pSibling->IsInSct() ||
1188 0 : !pMySect->IsAnFollow( pSibling->ImplFindSctFrm() ) )
1189 0 : pSibling = NULL;
1190 : }
1191 2 : else if( pSibling->IsInSct() )
1192 2 : pSibling = NULL;
1193 : }
1194 : }
1195 : }
1196 :
1197 216 : if( pSibling && pSibling->FindPageFrm()->IsEndNotePage() !=
1198 38 : FindPageFrm()->IsEndNotePage() )
1199 0 : pSibling = NULL;
1200 :
1201 : // use the Doc to find out the position
1202 178 : SwDoc *pDoc = GetFmt()->GetDoc();
1203 178 : const sal_uLong nStPos = ::lcl_FindFtnPos( pDoc, pNew->GetAttr() );
1204 :
1205 178 : sal_uLong nCmpPos = 0;
1206 178 : sal_uLong nLastPos = 0;
1207 178 : SwFtnContFrm *pParent = 0;
1208 178 : if( pSibling )
1209 : {
1210 38 : nCmpPos = ::lcl_FindFtnPos( pDoc, pSibling->GetAttr() );
1211 38 : if( nCmpPos > nStPos )
1212 8 : pSibling = NULL;
1213 : }
1214 :
1215 178 : if ( !pSibling )
1216 148 : { pParent = FindFtnCont();
1217 148 : if ( !pParent )
1218 : {
1219 : // There is no footnote container yet. Before creating one, keep in mind that
1220 : // there might exist another following footnote that must be placed before the
1221 : // new inserted one e.g. because it was divided over multiple pages etc.
1222 126 : pParent = FindNearestFtnCont( bDontLeave );
1223 126 : if ( pParent )
1224 : {
1225 2 : SwFtnFrm *pFtn = (SwFtnFrm*)pParent->Lower();
1226 2 : if ( pFtn )
1227 : {
1228 :
1229 2 : nCmpPos = ::lcl_FindFtnPos( pDoc, pFtn->GetAttr() );
1230 2 : if ( nCmpPos > nStPos )
1231 2 : pParent = 0;
1232 : }
1233 : else
1234 0 : pParent = 0;
1235 : }
1236 : }
1237 148 : if ( !pParent )
1238 : // here, we are sure that we can create a footnote container
1239 126 : pParent = MakeFtnCont();
1240 : else
1241 : {
1242 : // Based on the first footnote below the Parent, search for the first footnote whose
1243 : // index is after the index of the newly inserted, to place the new one correctly
1244 22 : pSibling = (SwFtnFrm*)pParent->Lower();
1245 22 : if ( !pSibling )
1246 : { OSL_ENSURE( false, "Could not find space for footnote.");
1247 178 : return;
1248 : }
1249 22 : nCmpPos = ::lcl_FindFtnPos( pDoc, pSibling->GetAttr() );
1250 :
1251 22 : SwFtnBossFrm *pNxtB = this; // remember the last one to not
1252 22 : SwFtnFrm *pLastSib = 0; // go too far.
1253 :
1254 56 : while ( pSibling && nCmpPos <= nStPos )
1255 : {
1256 28 : pLastSib = pSibling; // potential candidate
1257 28 : nLastPos = nCmpPos;
1258 :
1259 56 : while ( pSibling->GetFollow() )
1260 0 : pSibling = pSibling->GetFollow();
1261 :
1262 28 : if ( pSibling->GetNext() )
1263 : {
1264 12 : pSibling = (SwFtnFrm*)pSibling->GetNext();
1265 : OSL_ENSURE( !pSibling->GetMaster() || ( ENDNOTE > nStPos &&
1266 : pSibling->GetAttr()->GetFtn().IsEndNote() ),
1267 : "InsertFtn: Master expected I" );
1268 : }
1269 : else
1270 : {
1271 16 : pNxtB = pSibling->FindFtnBossFrm();
1272 16 : SwPageFrm *pSibPage = pNxtB->FindPageFrm();
1273 16 : bool bEndNote = pSibPage->IsEndNotePage();
1274 16 : bool bChgPage = lcl_NextFtnBoss( pNxtB, pSibPage, bDontLeave );
1275 : // When changing pages, also the endnote flag must match.
1276 4 : SwFtnContFrm *pCont = pNxtB && ( !bChgPage ||
1277 2 : pSibPage->IsEndNotePage() == bEndNote )
1278 16 : ? pNxtB->FindNearestFtnCont( bDontLeave ) : 0;
1279 16 : if( pCont )
1280 0 : pSibling = (SwFtnFrm*)pCont->Lower();
1281 : else // no further FtnContainer, insert after pSibling
1282 16 : break;
1283 : }
1284 12 : if ( pSibling )
1285 : {
1286 12 : nCmpPos = ::lcl_FindFtnPos( pDoc, pSibling->GetAttr() );
1287 : OSL_ENSURE( nCmpPos > nLastPos, "InsertFtn: Order of FtnFrm's buggy" );
1288 : }
1289 : }
1290 : // pLastSib is the last footnote before the new one and
1291 : // pSibling is empty or the first one afterw the new one
1292 22 : if ( pSibling && pLastSib && (pSibling != pLastSib) )
1293 : {
1294 : // too far?
1295 0 : if ( nCmpPos > nStPos )
1296 0 : pSibling = pLastSib;
1297 : }
1298 22 : else if ( !pSibling )
1299 : {
1300 : // Last chance: Take the last footnote of the parent.
1301 : // Special case that happens e.g. when moving paragraphs with multiple footnotes.
1302 : // To keep the order, use the parent of the last inspected footnote.
1303 0 : pSibling = pLastSib;
1304 0 : while( pSibling->GetFollow() )
1305 0 : pSibling = pSibling->GetFollow();
1306 : OSL_ENSURE( !pSibling->GetNext(), "InsertFtn: Who's that guy?" );
1307 : }
1308 : }
1309 : }
1310 : else
1311 : {
1312 : // First footnote of the column/page found. Now search from there for the first one on the
1313 : // same column/page whose index is after the given one. The last one found is the predecessor.
1314 30 : SwFtnBossFrm* pBoss = pNew->GetRef()->FindFtnBossFrm(
1315 60 : !pNew->GetAttr()->GetFtn().IsEndNote() );
1316 30 : sal_uInt16 nRefNum = pBoss->GetPhyPageNum(); // page number of the new footnote
1317 30 : sal_uInt16 nRefCol = lcl_ColumnNum( pBoss ); // column number of the new footnote
1318 30 : bool bEnd = false;
1319 30 : SwFtnFrm *pLastSib = 0;
1320 90 : while ( pSibling && !bEnd && (nCmpPos <= nStPos) )
1321 : {
1322 30 : pLastSib = pSibling;
1323 30 : nLastPos = nCmpPos;
1324 :
1325 60 : while ( pSibling->GetFollow() )
1326 0 : pSibling = pSibling->GetFollow();
1327 :
1328 30 : SwFtnFrm *pFoll = (SwFtnFrm*)pSibling->GetNext();
1329 30 : if ( pFoll )
1330 : {
1331 0 : pBoss = pSibling->GetRef()->FindFtnBossFrm( !pSibling->
1332 0 : GetAttr()->GetFtn().IsEndNote() );
1333 : sal_uInt16 nTmpRef;
1334 0 : if( nStPos >= ENDNOTE ||
1335 0 : (nTmpRef = pBoss->GetPhyPageNum()) < nRefNum ||
1336 0 : ( nTmpRef == nRefNum && lcl_ColumnNum( pBoss ) <= nRefCol ))
1337 0 : pSibling = pFoll;
1338 : else
1339 0 : bEnd = true;
1340 : }
1341 : else
1342 : {
1343 30 : SwFtnBossFrm* pNxtB = pSibling->FindFtnBossFrm();
1344 30 : SwPageFrm *pSibPage = pNxtB->FindPageFrm();
1345 30 : bool bEndNote = pSibPage->IsEndNotePage();
1346 30 : bool bChgPage = lcl_NextFtnBoss( pNxtB, pSibPage, bDontLeave );
1347 : // When changing pages, also the endnote flag must match.
1348 16 : SwFtnContFrm *pCont = pNxtB && ( !bChgPage ||
1349 8 : pSibPage->IsEndNotePage() == bEndNote )
1350 32 : ? pNxtB->FindNearestFtnCont( bDontLeave ) : 0;
1351 30 : if ( pCont )
1352 0 : pSibling = (SwFtnFrm*)pCont->Lower();
1353 : else
1354 30 : bEnd = true;
1355 : }
1356 30 : if ( !bEnd && pSibling )
1357 0 : nCmpPos = ::lcl_FindFtnPos( pDoc, pSibling->GetAttr() );
1358 30 : if ( pSibling && pLastSib && (pSibling != pLastSib) )
1359 : {
1360 : // too far?
1361 0 : if ( (nLastPos < nCmpPos) && (nCmpPos > nStPos) )
1362 : {
1363 0 : pSibling = pLastSib;
1364 0 : bEnd = true;
1365 : }
1366 : }
1367 : }
1368 : }
1369 178 : if ( pSibling )
1370 : {
1371 52 : nCmpPos = ::lcl_FindFtnPos( pDoc, pSibling->GetAttr() );
1372 52 : if ( nCmpPos < nStPos )
1373 : {
1374 92 : while ( pSibling->GetFollow() )
1375 0 : pSibling = pSibling->GetFollow();
1376 46 : pParent = (SwFtnContFrm*)pSibling->GetUpper();
1377 46 : pSibling = (SwFtnFrm*)pSibling->GetNext();
1378 : }
1379 : else
1380 : {
1381 6 : if( pSibling->GetMaster() )
1382 : {
1383 0 : if( ENDNOTE > nCmpPos || nStPos >= ENDNOTE )
1384 : {
1385 : OSL_FAIL( "InsertFtn: Master expected II" );
1386 0 : do
1387 0 : pSibling = pSibling->GetMaster();
1388 0 : while ( pSibling->GetMaster() );
1389 : }
1390 : }
1391 6 : pParent = (SwFtnContFrm*)pSibling->GetUpper();
1392 : }
1393 : }
1394 : OSL_ENSURE( pParent, "paste in space?" );
1395 178 : pNew->Paste( pParent, pSibling );
1396 : }
1397 :
1398 178 : void SwFtnBossFrm::AppendFtn( SwCntntFrm *pRef, SwTxtFtn *pAttr )
1399 : {
1400 : // If the footnote already exists, do nothing.
1401 178 : if ( FindFtn( pRef, pAttr ) )
1402 0 : return;
1403 :
1404 : // If footnotes are inserted at the end of the document,
1405 : // we only need to search from the relevant page on.
1406 : // If there is none yet, we need to create one.
1407 : // If it is an Endnote, we need to search for or create an
1408 : // Endnote page.
1409 178 : SwDoc *pDoc = GetFmt()->GetDoc();
1410 178 : SwFtnBossFrm *pBoss = this;
1411 178 : SwPageFrm *pPage = FindPageFrm();
1412 178 : SwPageFrm *pMyPage = pPage;
1413 178 : bool bChgPage = false;
1414 178 : bool bEnd = false;
1415 178 : if ( pAttr->GetFtn().IsEndNote() )
1416 : {
1417 36 : bEnd = true;
1418 46 : if( GetUpper()->IsSctFrm() &&
1419 10 : ((SwSectionFrm*)GetUpper())->IsEndnAtEnd() )
1420 : {
1421 : SwFrm* pLast =
1422 0 : ((SwSectionFrm*)GetUpper())->FindLastCntnt( FINDMODE_ENDNOTE );
1423 0 : if( pLast )
1424 : {
1425 0 : pBoss = pLast->FindFtnBossFrm();
1426 0 : pPage = pBoss->FindPageFrm();
1427 : }
1428 : }
1429 : else
1430 : {
1431 86 : while ( pPage->GetNext() && !pPage->IsEndNotePage() )
1432 : {
1433 14 : pPage = (SwPageFrm*)pPage->GetNext();
1434 14 : bChgPage = true;
1435 : }
1436 36 : if ( !pPage->IsEndNotePage() )
1437 : {
1438 22 : SwPageDesc *pDesc = pDoc->GetEndNoteInfo().GetPageDesc( *pDoc );
1439 22 : pPage = ::InsertNewPage( *pDesc, pPage->GetUpper(),
1440 44 : !pPage->OnRightPage(), false, false, true, 0 );
1441 22 : pPage->SetEndNotePage( true );
1442 22 : bChgPage = true;
1443 : }
1444 : else
1445 : {
1446 : // At least we can search the approximately correct page.
1447 : // To ensure to be finished in finite time even if hundreds
1448 : // of footnotes exist
1449 14 : SwPageFrm *pNxt = (SwPageFrm*)pPage->GetNext();
1450 14 : const sal_uLong nStPos = ::lcl_FindFtnPos( pDoc, pAttr );
1451 28 : while ( pNxt && pNxt->IsEndNotePage() )
1452 : {
1453 0 : SwFtnContFrm *pCont = pNxt->FindFtnCont();
1454 0 : if ( pCont && pCont->Lower() )
1455 : {
1456 : OSL_ENSURE( pCont->Lower()->IsFtnFrm(), "no footnote in the container" );
1457 0 : if ( nStPos > ::lcl_FindFtnPos( pDoc,
1458 0 : ((SwFtnFrm*)pCont->Lower())->GetAttr()))
1459 : {
1460 0 : pPage = pNxt;
1461 0 : pNxt = (SwPageFrm*)pPage->GetNext();
1462 0 : continue;
1463 : }
1464 : }
1465 0 : break;
1466 : }
1467 : }
1468 : }
1469 : }
1470 146 : else if( FTNPOS_CHAPTER == pDoc->GetFtnInfo().ePos && ( !GetUpper()->
1471 2 : IsSctFrm() || !((SwSectionFrm*)GetUpper())->IsFtnAtEnd() ) )
1472 : {
1473 4 : while ( pPage->GetNext() && !pPage->IsFtnPage() &&
1474 0 : !((SwPageFrm*)pPage->GetNext())->IsEndNotePage() )
1475 : {
1476 0 : pPage = (SwPageFrm*)pPage->GetNext();
1477 0 : bChgPage = true;
1478 : }
1479 :
1480 2 : if ( !pPage->IsFtnPage() )
1481 : {
1482 2 : SwPageDesc *pDesc = pDoc->GetFtnInfo().GetPageDesc( *pDoc );
1483 2 : pPage = ::InsertNewPage( *pDesc, pPage->GetUpper(),
1484 4 : !pPage->OnRightPage(), false, false, true, pPage->GetNext() );
1485 2 : bChgPage = true;
1486 : }
1487 : else
1488 : {
1489 : // We can at least search the approximately correct page
1490 : // to ensure that we will finish in finite time even if
1491 : // hundreds of footnotes exist.
1492 0 : SwPageFrm *pNxt = (SwPageFrm*)pPage->GetNext();
1493 0 : const sal_uLong nStPos = ::lcl_FindFtnPos( pDoc, pAttr );
1494 0 : while ( pNxt && pNxt->IsFtnPage() && !pNxt->IsEndNotePage() )
1495 : {
1496 0 : SwFtnContFrm *pCont = pNxt->FindFtnCont();
1497 0 : if ( pCont && pCont->Lower() )
1498 : {
1499 : OSL_ENSURE( pCont->Lower()->IsFtnFrm(), "no footnote in the container" );
1500 0 : if ( nStPos > ::lcl_FindFtnPos( pDoc,
1501 0 : ((SwFtnFrm*)pCont->Lower())->GetAttr()))
1502 : {
1503 0 : pPage = pNxt;
1504 0 : pNxt = (SwPageFrm*)pPage->GetNext();
1505 0 : continue;
1506 : }
1507 : }
1508 0 : break;
1509 : }
1510 : }
1511 : }
1512 :
1513 : // For now, create a footnote and the corresponding content frames
1514 178 : if ( !pAttr->GetStartNode() )
1515 : {
1516 : OSL_ENSURE( false, "no footnote content." );
1517 0 : return;
1518 : }
1519 :
1520 : // If there is already a footnote content on the column/page,
1521 : // another one cannot be created in a column area.
1522 178 : if( pBoss->IsInSct() && pBoss->IsColumnFrm() && !pPage->IsFtnPage() )
1523 : {
1524 6 : SwSectionFrm* pSct = pBoss->FindSctFrm();
1525 6 : if( bEnd ? !pSct->IsEndnAtEnd() : !pSct->IsFtnAtEnd() )
1526 : {
1527 6 : SwFtnContFrm* pFtnCont = pSct->FindFtnBossFrm(!bEnd)->FindFtnCont();
1528 6 : if( pFtnCont )
1529 : {
1530 0 : SwFtnFrm* pTmp = (SwFtnFrm*)pFtnCont->Lower();
1531 0 : if( bEnd )
1532 0 : while( pTmp && !pTmp->GetAttr()->GetFtn().IsEndNote() )
1533 0 : pTmp = (SwFtnFrm*)pTmp->GetNext();
1534 0 : if( pTmp && *pTmp < pAttr )
1535 0 : return;
1536 : }
1537 : }
1538 : }
1539 :
1540 178 : SwFtnFrm *pNew = new SwFtnFrm( pDoc->GetDfltFrmFmt(), this, pRef, pAttr );
1541 : {
1542 178 : SwNodeIndex aIdx( *pAttr->GetStartNode(), 1 );
1543 178 : ::_InsertCnt( pNew, pDoc, aIdx.GetIndex() );
1544 : }
1545 : // If the page was changed or newly created,
1546 : // we need to place ourselves in the first column
1547 178 : if( bChgPage )
1548 : {
1549 38 : SwLayoutFrm* pBody = pPage->FindBodyCont();
1550 : OSL_ENSURE( pBody, "AppendFtn: NoPageBody?" );
1551 38 : if( pBody->Lower() && pBody->Lower()->IsColumnFrm() )
1552 0 : pBoss = (SwFtnBossFrm*)pBody->Lower();
1553 : else
1554 38 : pBoss = pPage; // page if no columns exist
1555 : }
1556 178 : pBoss->InsertFtn( pNew );
1557 178 : if ( pNew->GetUpper() ) // inserted or not?
1558 : {
1559 178 : ::RegistFlys( pNew->FindPageFrm(), pNew );
1560 178 : SwSectionFrm* pSect = FindSctFrm();
1561 : // The content of a FtnContainer in a (column) section only need to be calculated
1562 : // if the section streches already to the bottom edge of the Upper.
1563 200 : if( pSect && !pSect->IsJoinLocked() && ( bEnd ? !pSect->IsEndnAtEnd() :
1564 190 : !pSect->IsFtnAtEnd() ) && pSect->Growable() )
1565 6 : pSect->InvalidateSize();
1566 : else
1567 : {
1568 : // #i49383# - disable unlock of position of
1569 : // lower objects during format of footnote content.
1570 172 : const bool bOldFtnFrmLocked( pNew->IsColLocked() );
1571 172 : pNew->ColLock();
1572 172 : pNew->KeepLockPosOfLowerObjs();
1573 : // #i57914# - adjust fix #i49383#
1574 172 : SwCntntFrm *pCnt = pNew->ContainsCntnt();
1575 532 : while ( pCnt && pCnt->FindFtnFrm()->GetAttr() == pAttr )
1576 : {
1577 188 : pCnt->Calc();
1578 : // #i49383# - format anchored objects
1579 188 : if ( pCnt->IsTxtFrm() && pCnt->IsValid() )
1580 : {
1581 188 : if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt,
1582 188 : *(pCnt->FindPageFrm()) ) )
1583 : {
1584 : // restart format with first content
1585 0 : pCnt = pNew->ContainsCntnt();
1586 0 : continue;
1587 : }
1588 : }
1589 188 : pCnt = (SwCntntFrm*)pCnt->FindNextCnt();
1590 : }
1591 : // #i49383#
1592 172 : if ( !bOldFtnFrmLocked )
1593 : {
1594 172 : pNew->ColUnlock();
1595 : }
1596 : // #i57914# - adjust fix #i49383#
1597 : // enable lock of lower object position before format of footnote frame.
1598 172 : pNew->UnlockPosOfLowerObjs();
1599 172 : pNew->Calc();
1600 : // #i57914# - adjust fix #i49383#
1601 516 : if ( !bOldFtnFrmLocked && !pNew->GetLower() &&
1602 172 : !pNew->IsColLocked() && !pNew->IsBackMoveLocked() )
1603 : {
1604 0 : pNew->Cut();
1605 0 : delete pNew;
1606 : }
1607 : }
1608 178 : pMyPage->UpdateFtnNum();
1609 : }
1610 : else
1611 0 : delete pNew;
1612 : }
1613 :
1614 1120 : SwFtnFrm *SwFtnBossFrm::FindFtn( const SwCntntFrm *pRef, const SwTxtFtn *pAttr )
1615 : {
1616 : // the easiest and savest way goes via the attribute
1617 : OSL_ENSURE( pAttr->GetStartNode(), "FtnAtr without StartNode." );
1618 1120 : SwNodeIndex aIdx( *pAttr->GetStartNode(), 1 );
1619 1120 : SwCntntNode *pNd = aIdx.GetNode().GetCntntNode();
1620 1120 : if ( !pNd )
1621 : pNd = pRef->GetAttrSet()->GetDoc()->
1622 0 : GetNodes().GoNextSection( &aIdx, true, false );
1623 1120 : if ( !pNd )
1624 0 : return 0;
1625 2240 : SwIterator<SwFrm,SwCntntNode> aIter( *pNd );
1626 1120 : SwFrm* pFrm = aIter.First();
1627 1120 : if( pFrm )
1628 0 : do
1629 : {
1630 768 : pFrm = pFrm->GetUpper();
1631 : // #i28500#, #i27243# Due to the endnode collector, there are
1632 : // SwFtnFrms, which are not in the layout. Therefore the
1633 : // bInfFtn flags are not set correctly, and a cell of FindFtnFrm
1634 : // would return 0. Therefore we better call ImplFindFtnFrm().
1635 768 : SwFtnFrm *pFtn = pFrm->ImplFindFtnFrm();
1636 768 : if ( pFtn && pFtn->GetRef() == pRef )
1637 : {
1638 : // The following condition becomes true, if the whole
1639 : // footnotecontent is a section. While no frames exist,
1640 : // the HiddenFlag of the section is set, this causes
1641 : // the GoNextSection-function leaves the footnote.
1642 768 : if( pFtn->GetAttr() != pAttr )
1643 0 : return 0;
1644 1536 : while ( pFtn && pFtn->GetMaster() )
1645 0 : pFtn = pFtn->GetMaster();
1646 768 : return pFtn;
1647 : }
1648 :
1649 : } while ( 0 != (pFrm = aIter.Next()) );
1650 :
1651 1472 : return 0;
1652 : }
1653 :
1654 30 : void SwFtnBossFrm::RemoveFtn( const SwCntntFrm *pRef, const SwTxtFtn *pAttr,
1655 : bool bPrep )
1656 : {
1657 30 : SwFtnFrm *pFtn = FindFtn( pRef, pAttr );
1658 30 : if( pFtn )
1659 : {
1660 30 : do
1661 : {
1662 30 : SwFtnFrm *pFoll = pFtn->GetFollow();
1663 30 : pFtn->Cut();
1664 30 : delete pFtn;
1665 30 : pFtn = pFoll;
1666 : } while ( pFtn );
1667 30 : if( bPrep && pRef->IsFollow() )
1668 : {
1669 : OSL_ENSURE( pRef->IsTxtFrm(), "NoTxtFrm has Footnote?" );
1670 0 : SwTxtFrm* pMaster = (SwTxtFrm*)pRef->FindMaster();
1671 0 : if( !pMaster->IsLocked() )
1672 0 : pMaster->Prepare( PREP_FTN_GONE );
1673 : }
1674 : }
1675 30 : FindPageFrm()->UpdateFtnNum();
1676 30 : }
1677 :
1678 0 : void SwFtnBossFrm::ChangeFtnRef( const SwCntntFrm *pOld, const SwTxtFtn *pAttr,
1679 : SwCntntFrm *pNew )
1680 : {
1681 0 : SwFtnFrm *pFtn = FindFtn( pOld, pAttr );
1682 0 : while ( pFtn )
1683 : {
1684 0 : pFtn->SetRef( pNew );
1685 0 : pFtn = pFtn->GetFollow();
1686 : }
1687 0 : }
1688 :
1689 : /// OD 03.04.2003 #108446# - add parameter <_bCollectOnlyPreviousFtns> in
1690 : /// order to control, if only footnotes, which are positioned before the
1691 : /// footnote boss frame <this> have to be collected.
1692 0 : void SwFtnBossFrm::CollectFtns( const SwCntntFrm* _pRef,
1693 : SwFtnBossFrm* _pOld,
1694 : SwFtnFrms& _rFtnArr,
1695 : const bool _bCollectOnlyPreviousFtns )
1696 : {
1697 0 : SwFtnFrm *pFtn = _pOld->FindFirstFtn();
1698 0 : while( !pFtn )
1699 : {
1700 0 : if( _pOld->IsColumnFrm() )
1701 : {
1702 : // visit columns
1703 0 : while ( !pFtn && _pOld->GetPrev() )
1704 : {
1705 : // Still no problem if no footnote was found yet. The loop is needed to pick up
1706 : // following rows in tables. In all other cases it might correct bad contexts.
1707 0 : _pOld = (SwFtnBossFrm*)_pOld->GetPrev();
1708 0 : pFtn = _pOld->FindFirstFtn();
1709 : }
1710 : }
1711 0 : if( !pFtn )
1712 : {
1713 : // previous page
1714 : SwPageFrm* pPg;
1715 0 : for ( SwFrm* pTmp = _pOld;
1716 0 : 0 != ( pPg = (SwPageFrm*)pTmp->FindPageFrm()->GetPrev())
1717 0 : && pPg->IsEmptyPage() ;
1718 : )
1719 : {
1720 0 : pTmp = pPg;
1721 : }
1722 0 : if( !pPg )
1723 0 : return;
1724 :
1725 0 : SwLayoutFrm* pBody = pPg->FindBodyCont();
1726 0 : if( pBody->Lower() && pBody->Lower()->IsColumnFrm() )
1727 : {
1728 : // multiple columns on one page => search last column
1729 0 : _pOld = static_cast<SwFtnBossFrm*>(pBody->GetLastLower());
1730 : }
1731 : else
1732 0 : _pOld = pPg; // single column page
1733 0 : pFtn = _pOld->FindFirstFtn();
1734 : }
1735 : }
1736 : // OD 03.04.2003 #108446# - consider new parameter <_bCollectOnlyPreviousFtns>
1737 0 : SwFtnBossFrm* pRefBossFrm = NULL;
1738 0 : if ( _bCollectOnlyPreviousFtns )
1739 : {
1740 0 : pRefBossFrm = this;
1741 : }
1742 0 : _CollectFtns( _pRef, pFtn, _rFtnArr, _bCollectOnlyPreviousFtns, pRefBossFrm );
1743 : }
1744 :
1745 0 : inline void FtnInArr( SwFtnFrms& rFtnArr, SwFtnFrm* pFtn )
1746 : {
1747 0 : if ( rFtnArr.end() == std::find( rFtnArr.begin(), rFtnArr.end(), pFtn ) )
1748 0 : rFtnArr.push_back( pFtn );
1749 0 : }
1750 :
1751 : /// OD 03.04.2003 #108446# - add parameters <_bCollectOnlyPreviousFtns> and
1752 : /// <_pRefFtnBossFrm> in order to control, if only footnotes, which are positioned
1753 : /// before the given reference footnote boss frame have to be collected.
1754 : /// Note: if parameter <_bCollectOnlyPreviousFtns> is true, then parameter
1755 : /// <_pRefFtnBossFrm> have to be referenced to an object.
1756 : /// Adjust parameter names.
1757 0 : void SwFtnBossFrm::_CollectFtns( const SwCntntFrm* _pRef,
1758 : SwFtnFrm* _pFtn,
1759 : SwFtnFrms& _rFtnArr,
1760 : bool _bCollectOnlyPreviousFtns,
1761 : const SwFtnBossFrm* _pRefFtnBossFrm)
1762 : {
1763 : // OD 03.04.2003 #108446# - assert, that no reference footnote boss frame
1764 : // is set, in spite of the order, that only previous footnotes has to be
1765 : // collected.
1766 : OSL_ENSURE( !_bCollectOnlyPreviousFtns || _pRefFtnBossFrm,
1767 : "<SwFtnBossFrm::_CollectFtns(..)> - No reference footnote boss frame for collecting only previous footnotes set.\nCrash will be caused!" );
1768 :
1769 : // Collect all footnotes referenced by pRef (attribute by attribute), combine them
1770 : // (the content might be divided over multiple pages) and cut them.
1771 :
1772 : // For robustness, we do not log the corresponding footnotes here. If a footnote
1773 : // is touched twice, there might be a crash. This allows this function here to
1774 : // also handle corrupt layouts in some degrees (without loops or even crashes).
1775 0 : SwFtnFrms aNotFtnArr;
1776 :
1777 : // here we have a footnote placed in front of the first one of the reference
1778 : OSL_ENSURE( !_pFtn->GetMaster() || _pFtn->GetRef() != _pRef, "move FollowFtn?" );
1779 0 : while ( _pFtn->GetMaster() )
1780 0 : _pFtn = _pFtn->GetMaster();
1781 :
1782 0 : bool bFound = false;
1783 :
1784 0 : do
1785 : {
1786 : // Search for the next footnote in this column/page so that
1787 : // we do not start from zero again after cutting one footnote.
1788 0 : SwFtnFrm *pNxtFtn = _pFtn;
1789 0 : while ( pNxtFtn->GetFollow() )
1790 0 : pNxtFtn = pNxtFtn->GetFollow();
1791 0 : pNxtFtn = (SwFtnFrm*)pNxtFtn->GetNext();
1792 :
1793 0 : if ( !pNxtFtn )
1794 : {
1795 0 : SwFtnBossFrm* pBoss = _pFtn->FindFtnBossFrm();
1796 0 : SwPageFrm* pPage = pBoss->FindPageFrm();
1797 0 : do
1798 : {
1799 0 : lcl_NextFtnBoss( pBoss, pPage, false );
1800 0 : if( pBoss )
1801 : {
1802 0 : SwLayoutFrm* pCont = pBoss->FindFtnCont();
1803 0 : if( pCont )
1804 : {
1805 0 : pNxtFtn = (SwFtnFrm*)pCont->Lower();
1806 0 : if( pNxtFtn )
1807 : {
1808 0 : while( pNxtFtn->GetMaster() )
1809 0 : pNxtFtn = pNxtFtn->GetMaster();
1810 0 : if( pNxtFtn == _pFtn )
1811 0 : pNxtFtn = NULL;
1812 : }
1813 : }
1814 : }
1815 0 : } while( !pNxtFtn && pBoss );
1816 : }
1817 0 : else if( !pNxtFtn->GetAttr()->GetFtn().IsEndNote() )
1818 : { OSL_ENSURE( !pNxtFtn->GetMaster(), "_CollectFtn: Master expected" );
1819 0 : while ( pNxtFtn->GetMaster() )
1820 0 : pNxtFtn = pNxtFtn->GetMaster();
1821 : }
1822 0 : if ( pNxtFtn == _pFtn )
1823 : {
1824 : OSL_FAIL( "_CollectFtn: Vicious circle" );
1825 0 : pNxtFtn = 0;
1826 : }
1827 :
1828 : // OD 03.04.2003 #108446# - determine, if found footnote has to be collected.
1829 0 : bool bCollectFoundFtn = false;
1830 0 : if ( _pFtn->GetRef() == _pRef && !_pFtn->GetAttr()->GetFtn().IsEndNote() )
1831 : {
1832 0 : if ( _bCollectOnlyPreviousFtns )
1833 : {
1834 0 : SwFtnBossFrm* pBossOfFoundFtn = _pFtn->FindFtnBossFrm( true );
1835 : OSL_ENSURE( pBossOfFoundFtn,
1836 : "<SwFtnBossFrm::_CollectFtns(..)> - footnote boss frame of found footnote frame missing.\nWrong layout!" );
1837 0 : if ( !pBossOfFoundFtn || // don't crash, if no footnote boss is found.
1838 0 : pBossOfFoundFtn->IsBefore( _pRefFtnBossFrm )
1839 : )
1840 : {
1841 0 : bCollectFoundFtn = true;
1842 : }
1843 : }
1844 : else
1845 : {
1846 0 : bCollectFoundFtn = true;
1847 : }
1848 : }
1849 :
1850 0 : if ( bCollectFoundFtn )
1851 : {
1852 : OSL_ENSURE( !_pFtn->GetMaster(), "move FollowFtn?" );
1853 0 : SwFtnFrm *pNxt = _pFtn->GetFollow();
1854 0 : while ( pNxt )
1855 : {
1856 0 : SwFrm *pCnt = pNxt->ContainsAny();
1857 0 : if ( pCnt )
1858 : {
1859 : // destroy the follow on the way as it is empty
1860 0 : do
1861 0 : { SwFrm *pNxtCnt = pCnt->GetNext();
1862 0 : pCnt->Cut();
1863 0 : pCnt->Paste( _pFtn );
1864 0 : pCnt = pNxtCnt;
1865 : } while ( pCnt );
1866 : }
1867 : else
1868 : {
1869 : OSL_ENSURE( !pNxt, "footnote without content?" );
1870 0 : pNxt->Cut();
1871 0 : delete pNxt;
1872 : }
1873 0 : pNxt = _pFtn->GetFollow();
1874 : }
1875 0 : _pFtn->Cut();
1876 0 : FtnInArr( _rFtnArr, _pFtn );
1877 0 : bFound = true;
1878 : }
1879 : else
1880 : {
1881 0 : FtnInArr( aNotFtnArr, _pFtn );
1882 0 : if( bFound )
1883 0 : break;
1884 : }
1885 0 : if ( pNxtFtn &&
1886 0 : _rFtnArr.end() == std::find( _rFtnArr.begin(), _rFtnArr.end(), pNxtFtn ) &&
1887 0 : aNotFtnArr.end() == std::find( aNotFtnArr.begin(), aNotFtnArr.end(), pNxtFtn ) )
1888 0 : _pFtn = pNxtFtn;
1889 : else
1890 0 : break;
1891 : }
1892 0 : while ( _pFtn );
1893 0 : }
1894 :
1895 0 : void SwFtnBossFrm::_MoveFtns( SwFtnFrms &rFtnArr, bool bCalc )
1896 : {
1897 : // All footnotes referenced by pRef need to be moved
1898 : // to a new position (based on the new column/page)
1899 0 : const sal_uInt16 nMyNum = FindPageFrm()->GetPhyPageNum();
1900 0 : const sal_uInt16 nMyCol = lcl_ColumnNum( this );
1901 0 : SWRECTFN( this )
1902 :
1903 : // #i21478# - keep last inserted footnote in order to
1904 : // format the content of the following one.
1905 0 : SwFtnFrm* pLastInsertedFtn = 0L;
1906 0 : for ( sal_uInt16 i = 0; i < rFtnArr.size(); ++i )
1907 : {
1908 0 : SwFtnFrm *pFtn = rFtnArr[i];
1909 :
1910 0 : SwFtnBossFrm* pRefBoss = pFtn->GetRef()->FindFtnBossFrm( true );
1911 0 : if( pRefBoss != this )
1912 : {
1913 0 : const sal_uInt16 nRefNum = pRefBoss->FindPageFrm()->GetPhyPageNum();
1914 0 : const sal_uInt16 nRefCol = lcl_ColumnNum( this );
1915 0 : if( nRefNum < nMyNum || ( nRefNum == nMyNum && nRefCol <= nMyCol ) )
1916 0 : pRefBoss = this;
1917 : }
1918 0 : pRefBoss->InsertFtn( pFtn );
1919 :
1920 0 : if ( pFtn->GetUpper() ) // robust, e.g. with duplicates
1921 : {
1922 : // First condense the content so that footnote frames that do not fit on the page
1923 : // do not do too much harm (Loop 66312). So, the footnote content first grows as
1924 : // soon as the content gets formatted and it is sure that it fits on the page.
1925 0 : SwFrm *pCnt = pFtn->ContainsAny();
1926 0 : while( pCnt )
1927 : {
1928 0 : if( pCnt->IsLayoutFrm() )
1929 : {
1930 0 : SwFrm* pTmp = ((SwLayoutFrm*)pCnt)->ContainsAny();
1931 0 : while( pTmp && ((SwLayoutFrm*)pCnt)->IsAnLower( pTmp ) )
1932 : {
1933 0 : pTmp->Prepare( PREP_MOVEFTN );
1934 0 : (pTmp->Frm().*fnRect->fnSetHeight)(0);
1935 0 : (pTmp->Prt().*fnRect->fnSetHeight)(0);
1936 0 : pTmp = pTmp->FindNext();
1937 : }
1938 : }
1939 : else
1940 0 : pCnt->Prepare( PREP_MOVEFTN );
1941 0 : (pCnt->Frm().*fnRect->fnSetHeight)(0);
1942 0 : (pCnt->Prt().*fnRect->fnSetHeight)(0);
1943 0 : pCnt = pCnt->GetNext();
1944 : }
1945 0 : (pFtn->Frm().*fnRect->fnSetHeight)(0);
1946 0 : (pFtn->Prt().*fnRect->fnSetHeight)(0);
1947 0 : pFtn->Calc();
1948 0 : pFtn->GetUpper()->Calc();
1949 :
1950 0 : if( bCalc )
1951 : {
1952 0 : SwTxtFtn *pAttr = pFtn->GetAttr();
1953 0 : pCnt = pFtn->ContainsAny();
1954 0 : bool bUnlock = !pFtn->IsBackMoveLocked();
1955 0 : pFtn->LockBackMove();
1956 :
1957 : // #i49383# - disable unlock of position of
1958 : // lower objects during format of footnote content.
1959 0 : pFtn->KeepLockPosOfLowerObjs();
1960 : // #i57914# - adjust fix #i49383#
1961 :
1962 0 : while ( pCnt && pCnt->FindFtnFrm()->GetAttr() == pAttr )
1963 : {
1964 0 : pCnt->_InvalidatePos();
1965 0 : pCnt->Calc();
1966 : // #i49383# - format anchored objects
1967 0 : if ( pCnt->IsTxtFrm() && pCnt->IsValid() )
1968 : {
1969 0 : if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt,
1970 0 : *(pCnt->FindPageFrm()) ) )
1971 : {
1972 : // restart format with first content
1973 0 : pCnt = pFtn->ContainsAny();
1974 0 : continue;
1975 : }
1976 : }
1977 0 : if( pCnt->IsSctFrm() )
1978 : {
1979 : // If the area is not empty, iterate also over the content
1980 0 : SwFrm* pTmp = ((SwSectionFrm*)pCnt)->ContainsAny();
1981 0 : if( pTmp )
1982 0 : pCnt = pTmp;
1983 : else
1984 0 : pCnt = pCnt->FindNext();
1985 : }
1986 : else
1987 0 : pCnt = pCnt->FindNext();
1988 : }
1989 0 : if( bUnlock )
1990 : {
1991 0 : pFtn->UnlockBackMove();
1992 0 : if( !pFtn->ContainsAny() && !pFtn->IsColLocked() )
1993 : {
1994 0 : pFtn->Cut();
1995 0 : delete pFtn;
1996 : // #i21478#
1997 0 : pFtn = 0L;
1998 : }
1999 : }
2000 : // #i49383#
2001 0 : if ( pFtn )
2002 : {
2003 : // #i57914# - adjust fix #i49383#
2004 : // enable lock of lower object position before format of footnote frame.
2005 0 : pFtn->UnlockPosOfLowerObjs();
2006 0 : pFtn->Calc();
2007 : }
2008 : }
2009 : }
2010 : else
2011 : { OSL_ENSURE( !pFtn->GetMaster() && !pFtn->GetFollow(),
2012 : "DelFtn and Master/Follow?" );
2013 0 : delete pFtn;
2014 : // #i21478#
2015 0 : pFtn = 0L;
2016 : }
2017 :
2018 : // #i21478#
2019 0 : if ( pFtn )
2020 : {
2021 0 : pLastInsertedFtn = pFtn;
2022 : }
2023 : }
2024 :
2025 : // #i21478# - format content of footnote following
2026 : // the new inserted ones.
2027 0 : if ( bCalc && pLastInsertedFtn )
2028 : {
2029 0 : if ( pLastInsertedFtn->GetNext() )
2030 : {
2031 0 : SwFtnFrm* pNextFtn = static_cast<SwFtnFrm*>(pLastInsertedFtn->GetNext());
2032 0 : SwTxtFtn* pAttr = pNextFtn->GetAttr();
2033 0 : SwFrm* pCnt = pNextFtn->ContainsAny();
2034 :
2035 0 : bool bUnlock = !pNextFtn->IsBackMoveLocked();
2036 0 : pNextFtn->LockBackMove();
2037 : // #i49383# - disable unlock of position of
2038 : // lower objects during format of footnote content.
2039 0 : pNextFtn->KeepLockPosOfLowerObjs();
2040 : // #i57914# - adjust fix #i49383#
2041 :
2042 0 : while ( pCnt && pCnt->FindFtnFrm()->GetAttr() == pAttr )
2043 : {
2044 0 : pCnt->_InvalidatePos();
2045 0 : pCnt->Calc();
2046 : // #i49383# - format anchored objects
2047 0 : if ( pCnt->IsTxtFrm() && pCnt->IsValid() )
2048 : {
2049 0 : if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt,
2050 0 : *(pCnt->FindPageFrm()) ) )
2051 : {
2052 : // restart format with first content
2053 0 : pCnt = pNextFtn->ContainsAny();
2054 0 : continue;
2055 : }
2056 : }
2057 0 : if( pCnt->IsSctFrm() )
2058 : {
2059 : // If the area is not empty, iterate also over the content
2060 0 : SwFrm* pTmp = ((SwSectionFrm*)pCnt)->ContainsAny();
2061 0 : if( pTmp )
2062 0 : pCnt = pTmp;
2063 : else
2064 0 : pCnt = pCnt->FindNext();
2065 : }
2066 : else
2067 0 : pCnt = pCnt->FindNext();
2068 : }
2069 0 : if( bUnlock )
2070 : {
2071 0 : pNextFtn->UnlockBackMove();
2072 : }
2073 : // #i49383#
2074 : // #i57914# - adjust fix #i49383#
2075 : // enable lock of lower object position before format of footnote frame.
2076 0 : pNextFtn->UnlockPosOfLowerObjs();
2077 0 : pNextFtn->Calc();
2078 : }
2079 : }
2080 0 : }
2081 :
2082 0 : void SwFtnBossFrm::MoveFtns( const SwCntntFrm *pSrc, SwCntntFrm *pDest,
2083 : SwTxtFtn *pAttr )
2084 : {
2085 0 : if( ( GetFmt()->GetDoc()->GetFtnInfo().ePos == FTNPOS_CHAPTER &&
2086 0 : (!GetUpper()->IsSctFrm() || !((SwSectionFrm*)GetUpper())->IsFtnAtEnd()))
2087 0 : || pAttr->GetFtn().IsEndNote() )
2088 0 : return;
2089 :
2090 : OSL_ENSURE( this == pSrc->FindFtnBossFrm( true ),
2091 : "SwPageFrm::MoveFtns: source frame isn't on that FtnBoss" );
2092 :
2093 0 : SwFtnFrm *pFtn = FindFirstFtn();
2094 0 : if( pFtn )
2095 : {
2096 0 : ChangeFtnRef( pSrc, pAttr, pDest );
2097 0 : SwFtnBossFrm *pDestBoss = pDest->FindFtnBossFrm( true );
2098 : OSL_ENSURE( pDestBoss, "+SwPageFrm::MoveFtns: no destination boss" );
2099 0 : if( pDestBoss ) // robust
2100 : {
2101 0 : SwFtnFrms aFtnArr;
2102 0 : SwFtnBossFrm::_CollectFtns( pDest, pFtn, aFtnArr );
2103 0 : if ( !aFtnArr.empty() )
2104 : {
2105 0 : pDestBoss->_MoveFtns( aFtnArr, true );
2106 0 : SwPageFrm* pSrcPage = FindPageFrm();
2107 0 : SwPageFrm* pDestPage = pDestBoss->FindPageFrm();
2108 : // update FtnNum only at page change
2109 0 : if( pSrcPage != pDestPage )
2110 : {
2111 0 : if( pSrcPage->GetPhyPageNum() > pDestPage->GetPhyPageNum() )
2112 0 : pSrcPage->UpdateFtnNum();
2113 0 : pDestPage->UpdateFtnNum();
2114 : }
2115 0 : }
2116 : }
2117 : }
2118 : }
2119 :
2120 168 : void SwFtnBossFrm::RearrangeFtns( const SwTwips nDeadLine, const bool bLock,
2121 : const SwTxtFtn *pAttr )
2122 : {
2123 : // Format all footnotes of a column/page so that they might change the column/page.
2124 :
2125 168 : SwSaveFtnHeight aSave( this, nDeadLine );
2126 168 : SwFtnFrm *pFtn = FindFirstFtn();
2127 168 : if( pFtn && pFtn->GetPrev() && bLock )
2128 : {
2129 0 : SwFtnFrm* pFirst = (SwFtnFrm*)pFtn->GetUpper()->Lower();
2130 0 : SwFrm* pCntnt = pFirst->ContainsAny();
2131 0 : if( pCntnt )
2132 : {
2133 0 : bool bUnlock = !pFirst->IsBackMoveLocked();
2134 0 : pFirst->LockBackMove();
2135 0 : pFirst->Calc();
2136 0 : pCntnt->Calc();
2137 : // #i49383# - format anchored objects
2138 0 : if ( pCntnt->IsTxtFrm() && pCntnt->IsValid() )
2139 : {
2140 : SwObjectFormatter::FormatObjsAtFrm( *pCntnt,
2141 0 : *(pCntnt->FindPageFrm()) );
2142 : }
2143 0 : if( bUnlock )
2144 0 : pFirst->UnlockBackMove();
2145 : }
2146 0 : pFtn = FindFirstFtn();
2147 : }
2148 168 : SwDoc *pDoc = GetFmt()->GetDoc();
2149 168 : const sal_uLong nFtnPos = pAttr ? ::lcl_FindFtnPos( pDoc, pAttr ) : 0;
2150 168 : SwFrm *pCnt = pFtn ? pFtn->ContainsAny() : 0;
2151 168 : if ( pCnt )
2152 : {
2153 168 : bool bMore = true;
2154 168 : bool bStart = pAttr == 0; // If no attribute is given, process all
2155 : // #i49383# - disable unlock of position of
2156 : // lower objects during format of footnote and footnote content.
2157 168 : SwFtnFrm* pLastFtnFrm( 0L );
2158 : // footnote frame needs to be locked, if <bLock> isn't set.
2159 168 : bool bUnlockLastFtnFrm( false );
2160 276 : do
2161 : {
2162 276 : if( !bStart )
2163 38 : bStart = ::lcl_FindFtnPos( pDoc, pCnt->FindFtnFrm()->GetAttr() )
2164 38 : == nFtnPos;
2165 276 : if( bStart )
2166 : {
2167 266 : pCnt->_InvalidatePos();
2168 266 : pCnt->_InvalidateSize();
2169 266 : pCnt->Prepare( PREP_ADJUST_FRM );
2170 266 : SwFtnFrm* pFtnFrm = pCnt->FindFtnFrm();
2171 : // #i49383#
2172 266 : if ( pFtnFrm != pLastFtnFrm )
2173 : {
2174 218 : if ( pLastFtnFrm )
2175 : {
2176 50 : if ( !bLock && bUnlockLastFtnFrm )
2177 : {
2178 0 : pLastFtnFrm->ColUnlock();
2179 : }
2180 : // #i57914# - adjust fix #i49383#
2181 : // enable lock of lower object position before format of footnote frame.
2182 50 : pLastFtnFrm->UnlockPosOfLowerObjs();
2183 50 : pLastFtnFrm->Calc();
2184 100 : if ( !bLock && bUnlockLastFtnFrm &&
2185 0 : !pLastFtnFrm->GetLower() &&
2186 50 : !pLastFtnFrm->IsColLocked() &&
2187 0 : !pLastFtnFrm->IsBackMoveLocked() )
2188 : {
2189 0 : pLastFtnFrm->Cut();
2190 0 : delete pLastFtnFrm;
2191 0 : pLastFtnFrm = 0L;
2192 : }
2193 : }
2194 218 : if ( !bLock )
2195 : {
2196 28 : bUnlockLastFtnFrm = !pFtnFrm->IsColLocked();
2197 28 : pFtnFrm->ColLock();
2198 : }
2199 218 : pFtnFrm->KeepLockPosOfLowerObjs();
2200 218 : pLastFtnFrm = pFtnFrm;
2201 : }
2202 : // OD 30.10.2002 #97265# - invalidate position of footnote
2203 : // frame, if it's below its footnote container, in order to
2204 : // assure its correct position, probably calculating its previous
2205 : // footnote frames.
2206 : {
2207 266 : SWRECTFN( this );
2208 266 : SwFrm* aFtnContFrm = pFtnFrm->GetUpper();
2209 266 : if ( (pFtnFrm->Frm().*fnRect->fnTopDist)((aFtnContFrm->*fnRect->fnGetPrtBottom)()) > 0 )
2210 : {
2211 0 : pFtnFrm->_InvalidatePos();
2212 : }
2213 : }
2214 266 : if ( bLock )
2215 : {
2216 212 : bool bUnlock = !pFtnFrm->IsBackMoveLocked();
2217 212 : pFtnFrm->LockBackMove();
2218 212 : pFtnFrm->Calc();
2219 212 : pCnt->Calc();
2220 : // #i49383# - format anchored objects
2221 212 : if ( pCnt->IsTxtFrm() && pCnt->IsValid() )
2222 : {
2223 212 : if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt,
2224 212 : *(pCnt->FindPageFrm()) ) )
2225 : {
2226 : // restart format with first content
2227 0 : pCnt = pFtn->ContainsAny();
2228 0 : continue;
2229 : }
2230 : }
2231 212 : if( bUnlock )
2232 : {
2233 212 : pFtnFrm->UnlockBackMove();
2234 212 : if( !pFtnFrm->Lower() &&
2235 0 : !pFtnFrm->IsColLocked() )
2236 : {
2237 : // #i49383#
2238 : OSL_ENSURE( pLastFtnFrm == pFtnFrm,
2239 : "<SwFtnBossFrm::RearrangeFtns(..)> - <pLastFtnFrm> != <pFtnFrm>" );
2240 0 : pLastFtnFrm = 0L;
2241 0 : pFtnFrm->Cut();
2242 0 : delete pFtnFrm;
2243 : }
2244 : }
2245 : }
2246 : else
2247 : {
2248 54 : pFtnFrm->Calc();
2249 54 : pCnt->Calc();
2250 : // #i49383# - format anchored objects
2251 54 : if ( pCnt->IsTxtFrm() && pCnt->IsValid() )
2252 : {
2253 48 : if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt,
2254 48 : *(pCnt->FindPageFrm()) ) )
2255 : {
2256 : // restart format with first content
2257 0 : pCnt = pFtn->ContainsAny();
2258 0 : continue;
2259 : }
2260 : }
2261 : }
2262 : }
2263 276 : SwSectionFrm *pDel = NULL;
2264 276 : if( pCnt->IsSctFrm() )
2265 : {
2266 6 : SwFrm* pTmp = ((SwSectionFrm*)pCnt)->ContainsAny();
2267 6 : if( pTmp )
2268 : {
2269 6 : pCnt = pTmp;
2270 6 : continue;
2271 : }
2272 0 : pDel = (SwSectionFrm*)pCnt;
2273 : }
2274 270 : if ( pCnt->GetNext() )
2275 36 : pCnt = pCnt->GetNext();
2276 : else
2277 : {
2278 234 : pCnt = pCnt->FindNext();
2279 234 : if ( pCnt )
2280 : {
2281 72 : SwFtnFrm* pFtnFrm = pCnt->FindFtnFrm();
2282 144 : if( pFtnFrm->GetRef()->FindFtnBossFrm(
2283 144 : pFtnFrm->GetAttr()->GetFtn().IsEndNote() ) != this )
2284 0 : bMore = false;
2285 : }
2286 : else
2287 162 : bMore = false;
2288 : }
2289 270 : if( pDel )
2290 : {
2291 0 : pDel->Cut();
2292 0 : delete pDel;
2293 : }
2294 270 : if ( bMore )
2295 : {
2296 : // Go not further than to the provided footnote (if given)
2297 144 : if ( pAttr &&
2298 : (::lcl_FindFtnPos( pDoc,
2299 36 : pCnt->FindFtnFrm()->GetAttr()) > nFtnPos ) )
2300 6 : bMore = false;
2301 : }
2302 : } while ( bMore );
2303 : // #i49383#
2304 168 : if ( pLastFtnFrm )
2305 : {
2306 168 : if ( !bLock && bUnlockLastFtnFrm )
2307 : {
2308 28 : pLastFtnFrm->ColUnlock();
2309 : }
2310 : // #i57914# - adjust fix #i49383#
2311 : // enable lock of lower object position before format of footnote frame.
2312 168 : pLastFtnFrm->UnlockPosOfLowerObjs();
2313 168 : pLastFtnFrm->Calc();
2314 392 : if ( !bLock && bUnlockLastFtnFrm &&
2315 28 : !pLastFtnFrm->GetLower() &&
2316 168 : !pLastFtnFrm->IsColLocked() &&
2317 0 : !pLastFtnFrm->IsBackMoveLocked() )
2318 : {
2319 0 : pLastFtnFrm->Cut();
2320 0 : delete pLastFtnFrm;
2321 : }
2322 : }
2323 168 : }
2324 168 : }
2325 :
2326 208 : void SwPageFrm::UpdateFtnNum()
2327 : {
2328 : // page numbering only if set at the document
2329 208 : if ( GetFmt()->GetDoc()->GetFtnInfo().eNum != FTNNUM_PAGE )
2330 208 : return;
2331 :
2332 0 : SwLayoutFrm* pBody = FindBodyCont();
2333 0 : if( !pBody || !pBody->Lower() )
2334 0 : return;
2335 :
2336 0 : SwCntntFrm* pCntnt = pBody->ContainsCntnt();
2337 0 : sal_uInt16 nNum = 0;
2338 :
2339 0 : while( pCntnt && pCntnt->FindPageFrm() == this )
2340 : {
2341 0 : if( ((SwTxtFrm*)pCntnt)->HasFtn() )
2342 : {
2343 0 : SwFtnBossFrm* pBoss = pCntnt->FindFtnBossFrm( true );
2344 0 : if( pBoss->GetUpper()->IsSctFrm() &&
2345 0 : ((SwSectionFrm*)pBoss->GetUpper())->IsOwnFtnNum() )
2346 0 : pCntnt = ((SwSectionFrm*)pBoss->GetUpper())->FindLastCntnt();
2347 : else
2348 : {
2349 0 : SwFtnFrm* pFtn = (SwFtnFrm*)pBoss->FindFirstFtn( pCntnt );
2350 0 : while( pFtn )
2351 : {
2352 0 : SwTxtFtn* pTxtFtn = pFtn->GetAttr();
2353 0 : if( !pTxtFtn->GetFtn().IsEndNote() &&
2354 0 : pTxtFtn->GetFtn().GetNumStr().isEmpty() &&
2355 0 : !pFtn->GetMaster() &&
2356 0 : (pTxtFtn->GetFtn().GetNumber() != ++nNum) )
2357 : {
2358 0 : pTxtFtn->SetNumber( nNum, OUString() );
2359 : }
2360 0 : if ( pFtn->GetNext() )
2361 0 : pFtn = (SwFtnFrm*)pFtn->GetNext();
2362 : else
2363 : {
2364 0 : SwFtnBossFrm* pTmpBoss = pFtn->FindFtnBossFrm( true );
2365 0 : if( pTmpBoss )
2366 : {
2367 0 : SwPageFrm* pPage = pTmpBoss->FindPageFrm();
2368 0 : pFtn = NULL;
2369 0 : lcl_NextFtnBoss( pTmpBoss, pPage, false );
2370 0 : SwFtnContFrm *pCont = pTmpBoss ? pTmpBoss->FindNearestFtnCont() : NULL;
2371 0 : if ( pCont )
2372 0 : pFtn = (SwFtnFrm*)pCont->Lower();
2373 : }
2374 : }
2375 0 : if( pFtn && pFtn->GetRef() != pCntnt )
2376 0 : pFtn = NULL;
2377 : }
2378 : }
2379 : }
2380 0 : pCntnt = pCntnt->FindNextCnt();
2381 : }
2382 : }
2383 :
2384 6416 : void SwFtnBossFrm::SetFtnDeadLine( const SwTwips nDeadLine )
2385 : {
2386 6416 : SwFrm *pBody = FindBodyCont();
2387 6416 : pBody->Calc();
2388 :
2389 6416 : SwFrm *pCont = FindFtnCont();
2390 6416 : const SwTwips nMax = nMaxFtnHeight;// current should exceed MaxHeight
2391 6416 : SWRECTFN( this )
2392 6416 : if ( pCont )
2393 : {
2394 636 : pCont->Calc();
2395 636 : nMaxFtnHeight = -(pCont->Frm().*fnRect->fnBottomDist)( nDeadLine );
2396 : }
2397 : else
2398 5780 : nMaxFtnHeight = -(pBody->Frm().*fnRect->fnBottomDist)( nDeadLine );
2399 :
2400 6416 : const SwViewShell *pSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0;
2401 6416 : if( pSh && pSh->GetViewOptions()->getBrowseMode() )
2402 0 : nMaxFtnHeight += pBody->Grow( LONG_MAX, true );
2403 6416 : if ( IsInSct() )
2404 3234 : nMaxFtnHeight += FindSctFrm()->Grow( LONG_MAX, true );
2405 :
2406 6416 : if ( nMaxFtnHeight < 0 )
2407 3108 : nMaxFtnHeight = 0;
2408 6416 : if ( nMax != LONG_MAX && nMaxFtnHeight > nMax )
2409 50 : nMaxFtnHeight = nMax;
2410 6416 : }
2411 :
2412 7086 : SwTwips SwFtnBossFrm::GetVarSpace() const
2413 : {
2414 : // To not fall below 20% of the page height
2415 : // (in contrast to MSOffice where footnotes can fill a whole column/page)
2416 :
2417 7086 : const SwPageFrm* pPg = FindPageFrm();
2418 : OSL_ENSURE( pPg || IsInSct(), "Footnote lost page" );
2419 :
2420 7086 : const SwFrm *pBody = FindBodyCont();
2421 : SwTwips nRet;
2422 7086 : if( pBody )
2423 : {
2424 7086 : SWRECTFN( this )
2425 7086 : if( IsInSct() )
2426 : {
2427 32 : nRet = 0;
2428 64 : SwTwips nTmp = (*fnRect->fnYDiff)( (pBody->*fnRect->fnGetPrtTop)(),
2429 96 : (Frm().*fnRect->fnGetTop)() );
2430 32 : const SwSectionFrm* pSect = FindSctFrm();
2431 : // Endnotes in a ftncontainer causes a deadline:
2432 : // the bottom of the last contentfrm
2433 32 : if( pSect->IsEndnAtEnd() ) // endnotes allowed?
2434 : {
2435 : OSL_ENSURE( !Lower() || !Lower()->GetNext() || Lower()->GetNext()->
2436 : IsFtnContFrm(), "FtnContainer expected" );
2437 0 : const SwFtnContFrm* pCont = Lower() ?
2438 0 : (SwFtnContFrm*)Lower()->GetNext() : 0;
2439 0 : if( pCont )
2440 : {
2441 0 : SwFtnFrm* pFtn = (SwFtnFrm*)pCont->Lower();
2442 0 : while( pFtn)
2443 : {
2444 0 : if( pFtn->GetAttr()->GetFtn().IsEndNote() )
2445 : { // endnote found
2446 0 : SwFrm* pFrm = ((SwLayoutFrm*)Lower())->Lower();
2447 0 : if( pFrm )
2448 : {
2449 0 : while( pFrm->GetNext() )
2450 0 : pFrm = pFrm->GetNext(); // last cntntfrm
2451 : nTmp += (*fnRect->fnYDiff)(
2452 0 : (Frm().*fnRect->fnGetTop)(),
2453 0 : (pFrm->Frm().*fnRect->fnGetBottom)() );
2454 : }
2455 0 : break;
2456 : }
2457 0 : pFtn = (SwFtnFrm*)pFtn->GetNext();
2458 : }
2459 : }
2460 : }
2461 32 : if( nTmp < nRet )
2462 0 : nRet = nTmp;
2463 : }
2464 : else
2465 7054 : nRet = - (pPg->Prt().*fnRect->fnGetHeight)()/5;
2466 7086 : nRet += (pBody->Frm().*fnRect->fnGetHeight)();
2467 7086 : if( nRet < 0 )
2468 0 : nRet = 0;
2469 : }
2470 : else
2471 0 : nRet = 0;
2472 7086 : if ( IsPageFrm() )
2473 : {
2474 7054 : const SwViewShell *pSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0;
2475 7054 : if( pSh && pSh->GetViewOptions()->getBrowseMode() )
2476 0 : nRet += BROWSE_HEIGHT - Frm().Height();
2477 : }
2478 7086 : return nRet;
2479 : }
2480 :
2481 : /** Obtain if pFrm's size adjustment should be processed
2482 : *
2483 : * For a page frame of columns directly below the page AdjustNeighbourhood() needs
2484 : * to be called, or Grow()/ Shrink() for frame columns respectively.
2485 : *
2486 : * A column section is special, since if there is a footnote container in a column
2487 : * and those footnotes are not collected, it is handled like a page frame.
2488 : *
2489 : * @see AdjustNeighbourhood()
2490 : * @see Grow()
2491 : * @see Shrink()
2492 : */
2493 13780 : sal_uInt8 SwFtnBossFrm::_NeighbourhoodAdjustment( const SwFrm* ) const
2494 : {
2495 13780 : sal_uInt8 nRet = NA_ONLY_ADJUST;
2496 13780 : if( GetUpper() && !GetUpper()->IsPageBodyFrm() )
2497 : {
2498 : // column sections need grow/shrink
2499 13724 : if( GetUpper()->IsFlyFrm() )
2500 0 : nRet = NA_GROW_SHRINK;
2501 : else
2502 : {
2503 : OSL_ENSURE( GetUpper()->IsSctFrm(), "NeighbourhoodAdjustment: Unexpected Upper" );
2504 13724 : if( !GetNext() && !GetPrev() )
2505 54 : nRet = NA_GROW_ADJUST; // section with a single column (FtnAtEnd)
2506 : else
2507 : {
2508 13670 : const SwFrm* pTmp = Lower();
2509 : OSL_ENSURE( pTmp, "NeighbourhoodAdjustment: Missing Lower()" );
2510 13670 : if( !pTmp->GetNext() )
2511 13632 : nRet = NA_GROW_SHRINK;
2512 38 : else if( !GetUpper()->IsColLocked() )
2513 6 : nRet = NA_ADJUST_GROW;
2514 : OSL_ENSURE( !pTmp->GetNext() || pTmp->GetNext()->IsFtnContFrm(),
2515 : "NeighbourhoodAdjustment: Who's that guy?" );
2516 : }
2517 : }
2518 : }
2519 13780 : return nRet;
2520 : }
2521 :
2522 0 : void SwPageFrm::SetColMaxFtnHeight()
2523 : {
2524 0 : SwLayoutFrm *pBody = FindBodyCont();
2525 0 : if( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrm() )
2526 : {
2527 0 : SwColumnFrm* pCol = (SwColumnFrm*)pBody->Lower();
2528 0 : do
2529 : {
2530 0 : pCol->SetMaxFtnHeight( GetMaxFtnHeight() );
2531 0 : pCol = (SwColumnFrm*)pCol->GetNext();
2532 : } while ( pCol );
2533 : }
2534 0 : }
2535 :
2536 3762 : bool SwLayoutFrm::MoveLowerFtns( SwCntntFrm *pStart, SwFtnBossFrm *pOldBoss,
2537 : SwFtnBossFrm *pNewBoss, const bool bFtnNums )
2538 : {
2539 3762 : SwDoc *pDoc = GetFmt()->GetDoc();
2540 3762 : if ( pDoc->GetFtnIdxs().empty() )
2541 3712 : return false;
2542 50 : if( pDoc->GetFtnInfo().ePos == FTNPOS_CHAPTER &&
2543 0 : ( !IsInSct() || !FindSctFrm()->IsFtnAtEnd() ) )
2544 0 : return true;
2545 :
2546 50 : if ( !pNewBoss )
2547 0 : pNewBoss = FindFtnBossFrm( true );
2548 50 : if ( pNewBoss == pOldBoss )
2549 0 : return false;
2550 :
2551 50 : bool bMoved = false;
2552 50 : if( !pStart )
2553 0 : pStart = ContainsCntnt();
2554 :
2555 50 : SwFtnFrms aFtnArr;
2556 :
2557 1994 : while ( IsAnLower( pStart ) )
2558 : {
2559 1894 : if ( ((SwTxtFrm*)pStart)->HasFtn() )
2560 : {
2561 : // OD 03.04.2003 #108446# - To avoid unnecessary moves of footnotes
2562 : // use new parameter <_bCollectOnlyPreviousFtn> (4th parameter of
2563 : // method <SwFtnBossFrm::CollectFtn(..)>) to control, that only
2564 : // footnotes have to be collected, that are positioned before the
2565 : // new dedicated footnote boss frame.
2566 0 : pNewBoss->CollectFtns( pStart, pOldBoss, aFtnArr, true );
2567 : }
2568 1894 : pStart = pStart->GetNextCntntFrm();
2569 : }
2570 :
2571 : OSL_ENSURE( pOldBoss->IsInSct() == pNewBoss->IsInSct(),
2572 : "MoveLowerFtns: Section confusion" );
2573 : SwFtnFrms *pFtnArr;
2574 50 : SwLayoutFrm* pNewChief = 0;
2575 50 : SwLayoutFrm* pOldChief = 0;
2576 :
2577 50 : bool bFoundCandidate = false;
2578 50 : if (pStart && pOldBoss->IsInSct())
2579 : {
2580 22 : pOldChief = pOldBoss->FindSctFrm();
2581 22 : pNewChief = pNewBoss->FindSctFrm();
2582 22 : bFoundCandidate = pOldChief != pNewChief;
2583 : }
2584 :
2585 50 : if (bFoundCandidate)
2586 : {
2587 8 : pFtnArr = new SwFtnFrms;
2588 8 : pOldChief = pOldBoss->FindFtnBossFrm( true );
2589 8 : pNewChief = pNewBoss->FindFtnBossFrm( true );
2590 20 : while( pOldChief->IsAnLower( pStart ) )
2591 : {
2592 4 : if ( ((SwTxtFrm*)pStart)->HasFtn() )
2593 : ((SwFtnBossFrm*)pNewChief)->CollectFtns( pStart,
2594 0 : (SwFtnBossFrm*)pOldBoss, *pFtnArr );
2595 4 : pStart = pStart->GetNextCntntFrm();
2596 : }
2597 8 : if( pFtnArr->empty() )
2598 : {
2599 8 : delete pFtnArr;
2600 8 : pFtnArr = NULL;
2601 : }
2602 : }
2603 : else
2604 42 : pFtnArr = NULL;
2605 :
2606 50 : if ( !aFtnArr.empty() || pFtnArr )
2607 : {
2608 0 : if( !aFtnArr.empty() )
2609 0 : pNewBoss->_MoveFtns( aFtnArr, true );
2610 0 : if( pFtnArr )
2611 : {
2612 0 : ((SwFtnBossFrm*)pNewChief)->_MoveFtns( *pFtnArr, true );
2613 0 : delete pFtnArr;
2614 : }
2615 0 : bMoved = true;
2616 :
2617 : // update FtnNum only at page change
2618 0 : if ( bFtnNums )
2619 : {
2620 0 : SwPageFrm* pOldPage = pOldBoss->FindPageFrm();
2621 0 : SwPageFrm* pNewPage =pNewBoss->FindPageFrm();
2622 0 : if( pOldPage != pNewPage )
2623 : {
2624 0 : pOldPage->UpdateFtnNum();
2625 0 : pNewPage->UpdateFtnNum();
2626 : }
2627 : }
2628 : }
2629 50 : return bMoved;
2630 : }
2631 :
2632 0 : bool SwCntntFrm::MoveFtnCntFwd( bool bMakePage, SwFtnBossFrm *pOldBoss )
2633 : {
2634 : OSL_ENSURE( IsInFtn(), "no footnote." );
2635 0 : SwLayoutFrm *pFtn = FindFtnFrm();
2636 :
2637 : // The first paragraph in the first footnote in the first column in the
2638 : // sectionfrm at the top of the page has not to move forward, if the
2639 : // columnbody is empty.
2640 0 : if( pOldBoss->IsInSct() && !pOldBoss->GetIndPrev() && !GetIndPrev() &&
2641 0 : !pFtn->GetPrev() )
2642 : {
2643 0 : SwLayoutFrm* pBody = pOldBoss->FindBodyCont();
2644 0 : if( !pBody || !pBody->Lower() )
2645 0 : return true;
2646 : }
2647 :
2648 : //fix(9538): if the footnote has neighbors behind itself, remove them temporarily
2649 0 : SwLayoutFrm *pNxt = (SwLayoutFrm*)pFtn->GetNext();
2650 0 : SwLayoutFrm *pLst = 0;
2651 0 : while ( pNxt )
2652 : {
2653 0 : while ( pNxt->GetNext() )
2654 0 : pNxt = (SwLayoutFrm*)pNxt->GetNext();
2655 0 : if ( pNxt == pLst )
2656 0 : pNxt = 0;
2657 : else
2658 0 : { pLst = pNxt;
2659 0 : SwCntntFrm *pCnt = pNxt->ContainsCntnt();
2660 0 : if( pCnt )
2661 0 : pCnt->MoveFtnCntFwd( true, pOldBoss );
2662 0 : pNxt = (SwLayoutFrm*)pFtn->GetNext();
2663 : }
2664 : }
2665 :
2666 0 : bool bSamePage = true;
2667 : SwLayoutFrm *pNewUpper =
2668 0 : GetLeaf( bMakePage ? MAKEPAGE_INSERT : MAKEPAGE_NONE, true );
2669 :
2670 0 : if ( pNewUpper )
2671 : {
2672 0 : bool bSameBoss = true;
2673 0 : SwFtnBossFrm * const pNewBoss = pNewUpper->FindFtnBossFrm();
2674 : // Are we changing the column/page?
2675 0 : if ( !( bSameBoss = (pNewBoss == pOldBoss) ) )
2676 : {
2677 0 : bSamePage = pOldBoss->FindPageFrm() == pNewBoss->FindPageFrm(); // page change?
2678 0 : pNewUpper->Calc();
2679 : }
2680 :
2681 : // The layout leaf of the footnote is either a footnote container or a footnote.
2682 : // If it is a footnote and it has the same footnote reference like the old Upper,
2683 : // then move the content inside of it.
2684 : // If it is a container or the reference differs, create a new footnote and add
2685 : // it into the container.
2686 : // Create also a SectionFrame if currently in a area inside a footnote.
2687 0 : SwFtnFrm* pTmpFtn = pNewUpper->IsFtnFrm() ? ((SwFtnFrm*)pNewUpper) : 0;
2688 0 : if( !pTmpFtn )
2689 : {
2690 : OSL_ENSURE( pNewUpper->IsFtnContFrm(), "New Upper not a FtnCont.");
2691 0 : SwFtnContFrm *pCont = (SwFtnContFrm*)pNewUpper;
2692 :
2693 : // create footnote
2694 0 : SwFtnFrm *pOld = FindFtnFrm();
2695 0 : pTmpFtn = new SwFtnFrm( pOld->GetFmt()->GetDoc()->GetDfltFrmFmt(),
2696 0 : pOld, pOld->GetRef(), pOld->GetAttr() );
2697 : // chaining of footnotes
2698 0 : if ( pOld->GetFollow() )
2699 : {
2700 0 : pTmpFtn->SetFollow( pOld->GetFollow() );
2701 0 : pOld->GetFollow()->SetMaster( pTmpFtn );
2702 : }
2703 0 : pOld->SetFollow( pTmpFtn );
2704 0 : pTmpFtn->SetMaster( pOld );
2705 0 : SwFrm* pNx = pCont->Lower();
2706 0 : if( pNx && pTmpFtn->GetAttr()->GetFtn().IsEndNote() )
2707 0 : while(pNx && !((SwFtnFrm*)pNx)->GetAttr()->GetFtn().IsEndNote())
2708 0 : pNx = pNx->GetNext();
2709 0 : pTmpFtn->Paste( pCont, pNx );
2710 0 : pTmpFtn->Calc();
2711 : }
2712 : OSL_ENSURE( pTmpFtn->GetAttr() == FindFtnFrm()->GetAttr(), "Wrong Footnote!" );
2713 : // areas inside of footnotes get a special treatment
2714 0 : SwLayoutFrm *pNewUp = pTmpFtn;
2715 0 : if( IsInSct() )
2716 : {
2717 0 : SwSectionFrm* pSect = FindSctFrm();
2718 : // area inside of a footnote (or only footnote in an area)?
2719 0 : if( pSect->IsInFtn() )
2720 : {
2721 0 : if( pTmpFtn->Lower() && pTmpFtn->Lower()->IsSctFrm() &&
2722 0 : pSect->GetFollow() == (SwSectionFrm*)pTmpFtn->Lower() )
2723 0 : pNewUp = (SwSectionFrm*)pTmpFtn->Lower();
2724 : else
2725 : {
2726 0 : pNewUp = new SwSectionFrm( *pSect, false );
2727 0 : pNewUp->InsertBefore( pTmpFtn, pTmpFtn->Lower() );
2728 0 : static_cast<SwSectionFrm*>(pNewUp)->Init();
2729 0 : pNewUp->Frm().Pos() = pTmpFtn->Frm().Pos();
2730 0 : pNewUp->Frm().Pos().Y() += 1; // for notifications
2731 :
2732 : // If the section frame has a successor then the latter needs
2733 : // to be moved behind the new Follow of the section frame.
2734 0 : SwFrm* pTmp = pSect->GetNext();
2735 0 : if( pTmp )
2736 : {
2737 : SwFlowFrm* pTmpNxt;
2738 0 : if( pTmp->IsCntntFrm() )
2739 0 : pTmpNxt = (SwCntntFrm*)pTmp;
2740 0 : else if( pTmp->IsSctFrm() )
2741 0 : pTmpNxt = (SwSectionFrm*)pTmp;
2742 : else
2743 : {
2744 : OSL_ENSURE( pTmp->IsTabFrm(), "GetNextSctLeaf: Wrong Type" );
2745 0 : pTmpNxt = (SwTabFrm*)pTmp;
2746 : }
2747 0 : pTmpNxt->MoveSubTree( pTmpFtn, pNewUp->GetNext() );
2748 : }
2749 : }
2750 : }
2751 : }
2752 :
2753 0 : MoveSubTree( pNewUp, pNewUp->Lower() );
2754 :
2755 0 : if( !bSameBoss )
2756 0 : Prepare( PREP_BOSS_CHGD );
2757 : }
2758 0 : return bSamePage;
2759 : }
2760 :
2761 6416 : SwSaveFtnHeight::SwSaveFtnHeight( SwFtnBossFrm *pBs, const SwTwips nDeadLine ) :
2762 : pBoss( pBs ),
2763 6416 : nOldHeight( pBs->GetMaxFtnHeight() )
2764 : {
2765 6416 : pBoss->SetFtnDeadLine( nDeadLine );
2766 6416 : nNewHeight = pBoss->GetMaxFtnHeight();
2767 6416 : }
2768 :
2769 6416 : SwSaveFtnHeight::~SwSaveFtnHeight()
2770 : {
2771 : // If somebody tweaked the deadline meanwhile, we let it happen
2772 6416 : if ( nNewHeight == pBoss->GetMaxFtnHeight() )
2773 6416 : pBoss->nMaxFtnHeight = nOldHeight;
2774 6416 : }
2775 :
2776 : #ifdef DBG_UTIL
2777 : //JP 15.10.2001: in a non pro version test if the attribute has the same
2778 : // meaning which his reference is
2779 :
2780 : // Normally, the pRef member and the GetRefFromAttr() result has to be
2781 : // identically. Sometimes footnote will be moved from a master to its follow,
2782 : // but the GetRef() is called first, so we have to ignore a master/follow
2783 : // mismatch.
2784 :
2785 : const SwCntntFrm* SwFtnFrm::GetRef() const
2786 : {
2787 : const SwCntntFrm* pRefAttr = GetRefFromAttr();
2788 : SAL_WARN_IF( pRef != pRefAttr && !pRef->IsAnFollow( pRefAttr )
2789 : && !pRefAttr->IsAnFollow( pRef ),
2790 : "sw", "access to deleted Frame? pRef != pAttr->GetRef()" );
2791 : return pRef;
2792 : }
2793 :
2794 : SwCntntFrm* SwFtnFrm::GetRef()
2795 : {
2796 : const SwCntntFrm* pRefAttr = GetRefFromAttr();
2797 : SAL_WARN_IF( pRef != pRefAttr && !pRef->IsAnFollow( pRefAttr )
2798 : && !pRefAttr->IsAnFollow( pRef ),
2799 : "sw", "access to deleted Frame? pRef != pAttr->GetRef()" );
2800 : return pRef;
2801 : }
2802 : #endif
2803 :
2804 0 : const SwCntntFrm* SwFtnFrm::GetRefFromAttr() const
2805 : {
2806 0 : SwFtnFrm* pThis = (SwFtnFrm*)this;
2807 0 : return pThis->GetRefFromAttr();
2808 : }
2809 :
2810 8 : SwCntntFrm* SwFtnFrm::GetRefFromAttr()
2811 : {
2812 : assert(pAttr && "invalid Attribute");
2813 8 : SwTxtNode& rTNd = (SwTxtNode&)pAttr->GetTxtNode();
2814 8 : SwPosition aPos( rTNd, SwIndex( &rTNd, pAttr->GetStart() ));
2815 8 : SwCntntFrm* pCFrm = rTNd.getLayoutFrm( getRootFrm(), 0, &aPos, false );
2816 8 : return pCFrm;
2817 : }
2818 :
2819 : /** search for last content in the current footnote frame
2820 :
2821 : OD 2005-12-02 #i27138#
2822 : */
2823 0 : SwCntntFrm* SwFtnFrm::FindLastCntnt()
2824 : {
2825 0 : SwCntntFrm* pLastCntntFrm( 0L );
2826 :
2827 : // find last lower, which is a content frame or contains content.
2828 : // hidden text frames, empty sections and empty tables have to be skipped.
2829 0 : SwFrm* pLastLowerOfFtn( GetLower() );
2830 0 : SwFrm* pTmpLastLower( pLastLowerOfFtn );
2831 0 : while ( pTmpLastLower && pTmpLastLower->GetNext() )
2832 : {
2833 0 : pTmpLastLower = pTmpLastLower->GetNext();
2834 0 : if ( ( pTmpLastLower->IsTxtFrm() &&
2835 0 : !static_cast<SwTxtFrm*>(pTmpLastLower)->IsHiddenNow() ) ||
2836 0 : ( pTmpLastLower->IsSctFrm() &&
2837 0 : static_cast<SwSectionFrm*>(pTmpLastLower)->GetSection() &&
2838 0 : static_cast<SwSectionFrm*>(pTmpLastLower)->ContainsCntnt() ) ||
2839 0 : ( pTmpLastLower->IsTabFrm() &&
2840 0 : static_cast<SwTabFrm*>(pTmpLastLower)->ContainsCntnt() ) )
2841 : {
2842 0 : pLastLowerOfFtn = pTmpLastLower;
2843 : }
2844 : }
2845 :
2846 : // determine last content frame depending on type of found last lower.
2847 0 : if ( pLastLowerOfFtn && pLastLowerOfFtn->IsTabFrm() )
2848 : {
2849 0 : pLastCntntFrm = static_cast<SwTabFrm*>(pLastLowerOfFtn)->FindLastCntnt();
2850 : }
2851 0 : else if ( pLastLowerOfFtn && pLastLowerOfFtn->IsSctFrm() )
2852 : {
2853 0 : pLastCntntFrm = static_cast<SwSectionFrm*>(pLastLowerOfFtn)->FindLastCntnt();
2854 : }
2855 : else
2856 : {
2857 0 : pLastCntntFrm = dynamic_cast<SwCntntFrm*>(pLastLowerOfFtn);
2858 : }
2859 :
2860 0 : return pLastCntntFrm;
2861 270 : }
2862 :
2863 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|