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 <calbck.hxx>
36 :
37 : #define ENDNOTE 0x80000000
38 :
39 : /// Search the position of an attribute in the FootnoteArray at the document,
40 : /// because all footnotes are located there, ordered by their index.
41 234 : static sal_uLong lcl_FindFootnotePos( const SwDoc *pDoc, const SwTextFootnote *pAttr )
42 : {
43 234 : const SwFootnoteIdxs &rFootnoteIdxs = pDoc->GetFootnoteIdxs();
44 :
45 234 : SwTextFootnote* pBla = const_cast<SwTextFootnote*>(pAttr);
46 234 : SwFootnoteIdxs::const_iterator it = rFootnoteIdxs.find( pBla );
47 234 : if ( it != rFootnoteIdxs.end() )
48 : {
49 234 : sal_uLong nRet = it - rFootnoteIdxs.begin();
50 234 : if( pAttr->GetFootnote().IsEndNote() )
51 68 : return nRet + ENDNOTE;
52 166 : return nRet;
53 : }
54 : OSL_ENSURE( !pDoc, "FootnotePos not found." );
55 0 : return 0;
56 : }
57 :
58 0 : bool SwFootnoteFrm::operator<( const SwTextFootnote* pTextFootnote ) const
59 : {
60 0 : const SwDoc* pDoc = GetFormat()->GetDoc();
61 : OSL_ENSURE( pDoc, "SwFootnoteFrm: Missing doc!" );
62 0 : return lcl_FindFootnotePos( pDoc, GetAttr() ) <
63 0 : lcl_FindFootnotePos( pDoc, pTextFootnote );
64 : }
65 :
66 : /*
67 : |*
68 : |* bool lcl_NextFootnoteBoss( SwFootnoteBossFrm* pBoss, SwPageFrm* pPage)
69 : |* sets pBoss on the next SwFootnoteBossFrm, 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 true.
72 : |*
73 : |*/
74 :
75 278 : static bool lcl_NextFootnoteBoss( SwFootnoteBossFrm* &rpBoss, SwPageFrm* &rpPage,
76 : bool bDontLeave )
77 : {
78 278 : if( rpBoss->IsColumnFrm() )
79 : {
80 120 : if( rpBoss->GetNext() )
81 : {
82 56 : rpBoss = static_cast<SwFootnoteBossFrm*>(rpBoss->GetNext()); //next column
83 56 : return false;
84 : }
85 64 : if( rpBoss->IsInSct() )
86 : {
87 64 : SwSectionFrm* pSct = rpBoss->FindSctFrm()->GetFollow();
88 64 : if( pSct )
89 : {
90 : OSL_ENSURE( pSct->Lower() && pSct->Lower()->IsColumnFrm(),
91 : "Where's the column?" );
92 22 : rpBoss = static_cast<SwColumnFrm*>(pSct->Lower());
93 22 : SwPageFrm* pOld = rpPage;
94 22 : rpPage = pSct->FindPageFrm();
95 22 : return pOld != rpPage;
96 : }
97 42 : else if( bDontLeave )
98 : {
99 16 : rpPage = NULL;
100 16 : rpBoss = NULL;
101 16 : return false;
102 : }
103 : }
104 : }
105 184 : rpPage = static_cast<SwPageFrm*>(rpPage->GetNext()); // next page
106 184 : rpBoss = rpPage;
107 184 : if( rpPage )
108 : {
109 17 : SwLayoutFrm* pBody = rpPage->FindBodyCont();
110 17 : if( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrm() )
111 0 : rpBoss = static_cast<SwFootnoteBossFrm*>(pBody->Lower()); // first column
112 : }
113 184 : return true;
114 : }
115 :
116 : /// @returns column number if pBoss is a column, otherwise 0.
117 416 : static sal_uInt16 lcl_ColumnNum( const SwFrm* pBoss )
118 : {
119 416 : sal_uInt16 nRet = 0;
120 416 : if( !pBoss->IsColumnFrm() )
121 284 : return 0;
122 : const SwFrm* pCol;
123 132 : if( pBoss->IsInSct() )
124 : {
125 132 : pCol = pBoss->GetUpper()->FindColFrm();
126 132 : if( pBoss->GetNext() || pBoss->GetPrev() )
127 : {
128 490 : while( pBoss )
129 : {
130 226 : ++nRet; // Section columns
131 226 : pBoss = pBoss->GetPrev();
132 : }
133 : }
134 : }
135 : else
136 0 : pCol = pBoss;
137 264 : while( pCol )
138 : {
139 0 : nRet += 256; // Page columns
140 0 : pCol = pCol->GetPrev();
141 : }
142 132 : return nRet;
143 : }
144 :
145 87 : SwFootnoteContFrm::SwFootnoteContFrm( SwFrameFormat *pFormat, SwFrm* pSib ):
146 87 : SwLayoutFrm( pFormat, pSib )
147 : {
148 87 : mnFrmType = FRM_FTNCONT;
149 87 : }
150 :
151 :
152 : // lcl_Undersize(..) walks over a SwFrm and its contents
153 : // and returns the sum of all requested TextFrm magnifications.
154 :
155 532 : static long lcl_Undersize( const SwFrm* pFrm )
156 : {
157 532 : long nRet = 0;
158 532 : SWRECTFN( pFrm )
159 532 : if( pFrm->IsTextFrm() )
160 : {
161 292 : if( static_cast<const SwTextFrm*>(pFrm)->IsUndersized() )
162 : {
163 : // Does this TextFrm would like to be a little bit bigger?
164 4 : nRet = static_cast<const SwTextFrm*>(pFrm)->GetParHeight() -
165 4 : (pFrm->Prt().*fnRect->fnGetHeight)();
166 4 : if( nRet < 0 )
167 0 : nRet = 0;
168 : }
169 : }
170 240 : else if( pFrm->IsLayoutFrm() )
171 : {
172 240 : const SwFrm* pNxt = static_cast<const SwLayoutFrm*>(pFrm)->Lower();
173 776 : while( pNxt )
174 : {
175 296 : nRet += lcl_Undersize( pNxt );
176 296 : pNxt = pNxt->GetNext();
177 : }
178 : }
179 532 : return nRet;
180 : }
181 :
182 : /// "format" the frame (Fixsize is not set here).
183 250 : void SwFootnoteContFrm::Format( const SwBorderAttrs * )
184 : {
185 : // calculate total border, only one distance to the top
186 250 : const SwPageFrm* pPage = FindPageFrm();
187 250 : const SwPageFootnoteInfo &rInf = pPage->GetPageDesc()->GetFootnoteInfo();
188 500 : const SwTwips nBorder = rInf.GetTopDist() + rInf.GetBottomDist() +
189 500 : rInf.GetLineWidth();
190 250 : SWRECTFN( this )
191 250 : if ( !mbValidPrtArea )
192 : {
193 250 : mbValidPrtArea = true;
194 250 : (Prt().*fnRect->fnSetTop)( nBorder );
195 250 : (Prt().*fnRect->fnSetWidth)( (Frm().*fnRect->fnGetWidth)() );
196 250 : (Prt().*fnRect->fnSetHeight)((Frm().*fnRect->fnGetHeight)() - nBorder );
197 250 : if( (Prt().*fnRect->fnGetHeight)() < 0 && !pPage->IsFootnotePage() )
198 58 : mbValidSize = false;
199 : }
200 :
201 250 : if ( !mbValidSize )
202 : {
203 236 : bool bGrow = pPage->IsFootnotePage();
204 236 : if( bGrow )
205 : {
206 16 : const SwViewShell *pSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0;
207 16 : if( pSh && pSh->GetViewOptions()->getBrowseMode() )
208 0 : bGrow = false;
209 : }
210 236 : if( bGrow )
211 16 : Grow( LONG_MAX, false );
212 : else
213 : {
214 : // VarSize is determined based on the content plus the borders
215 220 : SwTwips nRemaining = 0;
216 220 : SwFrm *pFrm = m_pLower;
217 676 : while ( pFrm )
218 : { // lcl_Undersize(..) respects (recursively) TextFrms, 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 236 : nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)() + lcl_Undersize( pFrm );
223 236 : pFrm = pFrm->GetNext();
224 : }
225 : // add the own border
226 220 : nRemaining += nBorder;
227 :
228 : SwTwips nDiff;
229 220 : if( IsInSct() )
230 : {
231 71 : nDiff = -(Frm().*fnRect->fnBottomDist)(
232 71 : (GetUpper()->*fnRect->fnGetPrtBottom)() );
233 71 : 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 220 : nDiff = (Frm().*fnRect->fnGetHeight)() - nRemaining;
242 220 : if ( nDiff > 0 )
243 14 : Shrink( nDiff );
244 206 : else if ( nDiff < 0 )
245 : {
246 58 : 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 58 : SwTwips nPrtHeight = (Prt().*fnRect->fnGetHeight)();
251 58 : if( nPrtHeight < 0 )
252 : {
253 4 : const SwTwips nTmpDiff = std::max( (Prt().*fnRect->fnGetTop)(),
254 8 : -nPrtHeight );
255 4 : (Prt().*fnRect->fnSubTop)( nTmpDiff );
256 : }
257 : }
258 : }
259 236 : mbValidSize = true;
260 : }
261 250 : }
262 :
263 831 : SwTwips SwFootnoteContFrm::GrowFrm( SwTwips nDist, bool bTst, bool )
264 : {
265 : // No check if FixSize since FootnoteContainer 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()->IsFootnoteBossFrm());
269 :
270 831 : SWRECTFN( this )
271 1559 : if( (Frm().*fnRect->fnGetHeight)() > 0 &&
272 728 : nDist > ( LONG_MAX - (Frm().*fnRect->fnGetHeight)() ) )
273 320 : nDist = LONG_MAX - (Frm().*fnRect->fnGetHeight)();
274 :
275 831 : SwFootnoteBossFrm *pBoss = static_cast<SwFootnoteBossFrm*>(GetUpper());
276 831 : if( IsInSct() )
277 : {
278 131 : 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 341 : if( !bTst && !pSect->IsColLocked() &&
283 151 : pSect->ToMaximize( false ) && pSect->Growable() )
284 : {
285 0 : pSect->InvalidateSize();
286 0 : return 0;
287 : }
288 : }
289 831 : const SwViewShell *pSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0;
290 831 : const bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
291 831 : SwPageFrm *pPage = pBoss->FindPageFrm();
292 831 : if ( bBrowseMode || !pPage->IsFootnotePage() )
293 : {
294 612 : if ( pBoss->GetMaxFootnoteHeight() != LONG_MAX )
295 : {
296 502 : nDist = std::min( nDist, pBoss->GetMaxFootnoteHeight()
297 502 : - (Frm().*fnRect->fnGetHeight)() );
298 502 : if ( nDist <= 0 )
299 0 : return 0L;
300 : }
301 : // FootnoteBoss also influences the max value
302 612 : if( !IsInSct() )
303 : {
304 481 : const SwTwips nMax = pBoss->GetVarSpace();
305 481 : if ( nDist > nMax )
306 233 : nDist = nMax;
307 481 : if ( nDist <= 0 )
308 0 : return 0L;
309 : }
310 : }
311 219 : else if( nDist > (GetPrev()->Frm().*fnRect->fnGetHeight)() )
312 : // do not use more space than the body has
313 219 : nDist = (GetPrev()->Frm().*fnRect->fnGetHeight)();
314 :
315 831 : long nAvail = 0;
316 831 : 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 831 : if ( !bTst )
329 : {
330 242 : (Frm().*fnRect->fnSetHeight)( (Frm().*fnRect->fnGetHeight)() + nDist );
331 :
332 242 : if( IsVertical() && !IsVertLR() && !IsReverse() )
333 0 : Frm().Pos().X() -= nDist;
334 : }
335 831 : long nGrow = nDist - nAvail,
336 831 : nReal = 0;
337 831 : if ( nGrow > 0 )
338 : {
339 627 : sal_uInt8 nAdjust = pBoss->NeighbourhoodAdjustment( this );
340 627 : if( NA_ONLY_ADJUST == nAdjust )
341 606 : nReal = AdjustNeighbourhood( nGrow, bTst );
342 : else
343 : {
344 21 : if( NA_GROW_ADJUST == nAdjust )
345 : {
346 0 : SwFrm* pFootnote = Lower();
347 0 : if( pFootnote )
348 : {
349 0 : while( pFootnote->GetNext() )
350 0 : pFootnote = pFootnote->GetNext();
351 0 : if( static_cast<SwFootnoteFrm*>(pFootnote)->GetAttr()->GetFootnote().IsEndNote() )
352 : {
353 0 : nReal = AdjustNeighbourhood( nGrow, bTst );
354 0 : nAdjust = NA_GROW_SHRINK; // no more AdjustNeighbourhood
355 : }
356 : }
357 : }
358 21 : nReal += pBoss->Grow( nGrow - nReal, bTst );
359 21 : if( ( NA_GROW_ADJUST == nAdjust || NA_ADJUST_GROW == nAdjust )
360 21 : && nReal < nGrow )
361 21 : nReal += AdjustNeighbourhood( nGrow - nReal, bTst );
362 : }
363 : }
364 :
365 831 : nReal += nAvail;
366 :
367 831 : if ( !bTst )
368 : {
369 242 : if ( nReal != nDist )
370 : {
371 22 : nDist -= nReal;
372 : // We can only respect the boundless wish so much
373 22 : Frm().SSize().Height() -= nDist;
374 :
375 22 : 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 242 : if( nReal )
381 : {
382 207 : _InvalidateSize();
383 207 : _InvalidatePos();
384 207 : InvalidatePage( pPage );
385 : }
386 : }
387 831 : return nReal;
388 : }
389 :
390 67 : SwTwips SwFootnoteContFrm::ShrinkFrm( SwTwips nDiff, bool bTst, bool bInfo )
391 : {
392 67 : SwPageFrm *pPage = FindPageFrm();
393 67 : bool bShrink = false;
394 67 : if ( pPage )
395 : {
396 67 : if( !pPage->IsFootnotePage() )
397 37 : bShrink = true;
398 : else
399 : {
400 30 : const SwViewShell *pSh = getRootFrm()->GetCurrShell();
401 30 : if( pSh && pSh->GetViewOptions()->getBrowseMode() )
402 0 : bShrink = true;
403 : }
404 : }
405 67 : if( bShrink )
406 : {
407 37 : SwTwips nRet = SwLayoutFrm::ShrinkFrm( nDiff, bTst, bInfo );
408 37 : if( IsInSct() && !bTst )
409 16 : FindSctFrm()->InvalidateNextPos();
410 37 : if ( !bTst && nRet )
411 : {
412 36 : _InvalidatePos();
413 36 : InvalidatePage( pPage );
414 : }
415 37 : return nRet;
416 : }
417 30 : return 0;
418 : }
419 :
420 100 : SwFootnoteFrm::SwFootnoteFrm( SwFrameFormat *pFormat, SwFrm* pSib, SwContentFrm *pCnt, SwTextFootnote *pAt ):
421 : SwLayoutFrm( pFormat, pSib ),
422 : pFollow( 0 ),
423 : pMaster( 0 ),
424 : pRef( pCnt ),
425 : pAttr( pAt ),
426 : bBackMoveLocked( false ),
427 : // #i49383#
428 100 : mbUnlockPosOfLowerObjs( true )
429 : {
430 100 : mnFrmType = FRM_FTN;
431 100 : }
432 :
433 125 : void SwFootnoteFrm::InvalidateNxtFootnoteCnts( SwPageFrm *pPage )
434 : {
435 125 : if ( GetNext() )
436 : {
437 3 : SwFrm *pCnt = static_cast<SwLayoutFrm*>(GetNext())->ContainsAny();
438 3 : if( pCnt )
439 : {
440 3 : pCnt->InvalidatePage( pPage );
441 3 : pCnt->_InvalidatePrt();
442 3 : do
443 3 : { pCnt->_InvalidatePos();
444 3 : if( pCnt->IsSctFrm() )
445 : {
446 0 : SwFrm* pTmp = static_cast<SwSectionFrm*>(pCnt)->ContainsAny();
447 0 : if( pTmp )
448 0 : pTmp->_InvalidatePos();
449 : }
450 3 : pCnt->GetUpper()->_InvalidateSize();
451 3 : pCnt = pCnt->FindNext();
452 3 : } while ( pCnt && GetUpper()->IsAnLower( pCnt ) );
453 : }
454 : }
455 125 : }
456 :
457 : #ifdef DBG_UTIL
458 : SwTwips SwFootnoteFrm::GrowFrm( SwTwips nDist, bool bTst, bool bInfo )
459 : {
460 : static sal_uInt16 nNum = USHRT_MAX;
461 : SwTextFootnote* pTextFootnote = GetAttr();
462 : if ( pTextFootnote->GetFootnote().GetNumber() == nNum )
463 : {
464 : int bla = 5;
465 : (void)bla;
466 :
467 : }
468 : return SwLayoutFrm::GrowFrm( nDist, bTst, bInfo );
469 : }
470 :
471 : SwTwips SwFootnoteFrm::ShrinkFrm( SwTwips nDist, bool bTst, bool bInfo )
472 : {
473 : static sal_uInt16 nNum = USHRT_MAX;
474 : if( nNum != USHRT_MAX )
475 : {
476 : SwTextFootnote* pTextFootnote = GetAttr();
477 : if( pTextFootnote->GetFootnote().GetNumber() == nNum )
478 : {
479 : int bla = 5;
480 : (void)bla;
481 : }
482 : }
483 : return SwLayoutFrm::ShrinkFrm( nDist, bTst, bInfo );
484 : }
485 : #endif
486 :
487 114 : void SwFootnoteFrm::Cut()
488 : {
489 114 : if ( GetNext() )
490 23 : GetNext()->InvalidatePos();
491 91 : else if ( GetPrev() )
492 4 : GetPrev()->SetRetouche();
493 :
494 : // first move then shrink Upper
495 114 : SwLayoutFrm *pUp = GetUpper();
496 :
497 : // correct chaining
498 114 : SwFootnoteFrm *pFootnote = this;
499 114 : if ( pFootnote->GetFollow() )
500 4 : pFootnote->GetFollow()->SetMaster( pFootnote->GetMaster() );
501 114 : if ( pFootnote->GetMaster() )
502 6 : pFootnote->GetMaster()->SetFollow( pFootnote->GetFollow() );
503 114 : pFootnote->SetFollow( 0 );
504 114 : pFootnote->SetMaster( 0 );
505 :
506 : // cut all connections
507 114 : RemoveFromLayout();
508 :
509 114 : if ( pUp )
510 : {
511 : // The last footnote takes its container along
512 114 : if ( !pUp->Lower() )
513 : {
514 87 : SwPageFrm *pPage = pUp->FindPageFrm();
515 87 : if ( pPage )
516 : {
517 87 : SwLayoutFrm *pBody = pPage->FindBodyCont();
518 87 : if( pBody && !pBody->ContainsContent() )
519 15 : pPage->getRootFrm()->SetSuperfluous();
520 : }
521 87 : SwSectionFrm* pSect = pUp->FindSctFrm();
522 87 : pUp->Cut();
523 87 : SwFrm::DestroyFrm(pUp);
524 : // If the last footnote container was removed from a column
525 : // section without a Follow, then this section can be shrunk.
526 87 : if( pSect && !pSect->ToMaximize( false ) && !pSect->IsColLocked() )
527 7 : pSect->_InvalidateSize();
528 : }
529 : else
530 27 : { if ( Frm().Height() )
531 25 : pUp->Shrink( Frm().Height() );
532 27 : pUp->SetCompletePaint();
533 27 : pUp->InvalidatePage();
534 : }
535 : }
536 114 : }
537 :
538 114 : void SwFootnoteFrm::Paste( SwFrm* pParent, SwFrm* pSibling )
539 : {
540 : OSL_ENSURE( pParent, "no parent in Paste." );
541 : OSL_ENSURE( pParent->IsLayoutFrm(), "Parent is ContentFrm." );
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 114 : InsertBefore( static_cast<SwLayoutFrm*>(pParent), pSibling );
549 :
550 114 : SWRECTFN( this )
551 114 : if( (Frm().*fnRect->fnGetWidth)()!=(pParent->Prt().*fnRect->fnGetWidth)() )
552 50 : _InvalidateSize();
553 114 : _InvalidatePos();
554 114 : SwPageFrm *pPage = FindPageFrm();
555 114 : InvalidatePage( pPage );
556 114 : if ( GetNext() )
557 3 : GetNext()->_InvalidatePos();
558 114 : if( (Frm().*fnRect->fnGetHeight)() )
559 14 : 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 114 : 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 : SwFrm::DestroyFrm(pDel);
571 : }
572 114 : 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 : SwFrm::DestroyFrm(pDel);
579 : }
580 : #if OSL_DEBUG_LEVEL > 0
581 : SwDoc *pDoc = GetFormat()->GetDoc();
582 : if ( GetPrev() )
583 : {
584 : OSL_ENSURE( lcl_FindFootnotePos( pDoc, static_cast<SwFootnoteFrm*>(GetPrev())->GetAttr() ) <=
585 : lcl_FindFootnotePos( pDoc, GetAttr() ), "Prev is not FootnotePrev" );
586 : }
587 : if ( GetNext() )
588 : {
589 : OSL_ENSURE( lcl_FindFootnotePos( pDoc, GetAttr() ) <=
590 : lcl_FindFootnotePos( pDoc, static_cast<SwFootnoteFrm*>(GetNext())->GetAttr() ),
591 : "Next is not FootnoteNext" );
592 : }
593 : #endif
594 114 : InvalidateNxtFootnoteCnts( pPage );
595 114 : }
596 :
597 : /// Return the next layout leaf in that the frame can be moved.
598 : /// New pages will only be created if specified by the parameter.
599 12 : SwLayoutFrm *SwFrm::GetNextFootnoteLeaf( MakePageType eMakePage )
600 : {
601 12 : SwFootnoteBossFrm *pOldBoss = FindFootnoteBossFrm();
602 12 : SwPageFrm* pOldPage = pOldBoss->FindPageFrm();
603 : SwPageFrm* pPage;
604 12 : SwFootnoteBossFrm *pBoss = pOldBoss->IsColumnFrm() ?
605 12 : static_cast<SwFootnoteBossFrm*>(pOldBoss->GetNext()) : 0; // next column, if existing
606 12 : if( pBoss )
607 1 : pPage = NULL;
608 : else
609 : {
610 11 : if( pOldBoss->GetUpper()->IsSctFrm() )
611 : { // this can only be in a column area
612 4 : SwLayoutFrm* pNxt = pOldBoss->GetNextSctLeaf( eMakePage );
613 4 : if( pNxt )
614 : {
615 : OSL_ENSURE( pNxt->IsColBodyFrm(), "GetNextFootnoteLeaf: Funny Leaf" );
616 4 : pBoss = static_cast<SwFootnoteBossFrm*>(pNxt->GetUpper());
617 4 : pPage = pBoss->FindPageFrm();
618 : }
619 : else
620 0 : return 0;
621 : }
622 : else
623 : {
624 : // next page
625 7 : pPage = static_cast<SwPageFrm*>(pOldPage->GetNext());
626 : // skip empty pages
627 7 : if( pPage && pPage->IsEmptyPage() )
628 0 : pPage = static_cast<SwPageFrm*>(pPage->GetNext());
629 7 : 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 Footnote and Follow,
639 : // create another Follow on the next best column/page and the rest will sort itself out.
640 12 : SwFootnoteFrm *pFootnote = FindFootnoteFrm();
641 12 : if ( pFootnote && pFootnote->GetFollow() )
642 : {
643 3 : SwFootnoteBossFrm* pTmpBoss = pFootnote->GetFollow()->FindFootnoteBossFrm();
644 : // Following cases will be handled:
645 : // 1. both "FootnoteBoss"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 6 : while( pTmpBoss != pBoss && pTmpBoss && !pTmpBoss->GetPrev() )
649 0 : pTmpBoss = pTmpBoss->GetUpper()->FindFootnoteBossFrm();
650 3 : if( pTmpBoss == pBoss )
651 3 : return pFootnote->GetFollow();
652 : }
653 :
654 : // If no pBoss could be found or it is a "wrong" page, we need a new page.
655 9 : if ( !pBoss || ( pPage && pPage->IsEndNotePage() && !pOldPage->IsEndNotePage() ) )
656 : {
657 4 : if ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT )
658 : {
659 4 : pBoss = InsertPage( pOldPage, pOldPage->IsFootnotePage() );
660 4 : static_cast<SwPageFrm*>(pBoss)->SetEndNotePage( pOldPage->IsEndNotePage() );
661 : }
662 : else
663 0 : return 0;
664 : }
665 9 : if( pBoss->IsPageFrm() )
666 : {
667 : // If this page has columns, then go to the first one
668 4 : SwLayoutFrm* pLay = pBoss->FindBodyCont();
669 4 : if( pLay && pLay->Lower() && pLay->Lower()->IsColumnFrm() )
670 0 : pBoss = static_cast<SwFootnoteBossFrm*>(pLay->Lower());
671 : }
672 : // found column/page - add myself
673 9 : SwFootnoteContFrm *pCont = pBoss->FindFootnoteCont();
674 18 : if ( !pCont && pBoss->GetMaxFootnoteHeight() &&
675 9 : ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT ) )
676 9 : pCont = pBoss->MakeFootnoteCont();
677 9 : return pCont;
678 : }
679 :
680 : /// Get the preceding layout leaf in that the frame can be moved.
681 61 : SwLayoutFrm *SwFrm::GetPrevFootnoteLeaf( MakePageType eMakeFootnote )
682 : {
683 : // The predecessor of a footnote is (if possible)
684 : // the master of the chain of the footnote.
685 61 : SwFootnoteFrm *pFootnote = FindFootnoteFrm();
686 61 : SwLayoutFrm *pRet = pFootnote->GetMaster();
687 :
688 61 : SwFootnoteBossFrm* pOldBoss = FindFootnoteBossFrm();
689 61 : SwPageFrm *pOldPage = pOldBoss->FindPageFrm();
690 :
691 61 : if ( !pOldBoss->GetPrev() && !pOldPage->GetPrev() )
692 0 : return pRet; // there is neither a predecessor column nor page
693 :
694 61 : if ( !pRet )
695 : {
696 31 : bool bEndn = pFootnote->GetAttr()->GetFootnote().IsEndNote();
697 31 : SwFrm* pTmpRef = NULL;
698 31 : if( bEndn && pFootnote->IsInSct() )
699 : {
700 0 : SwSectionFrm* pSect = pFootnote->FindSctFrm();
701 0 : if( pSect->IsEndnAtEnd() )
702 0 : pTmpRef = pSect->FindLastContent( FINDMODE_LASTCNT );
703 : }
704 31 : if( !pTmpRef )
705 31 : pTmpRef = pFootnote->GetRef();
706 31 : SwFootnoteBossFrm* pStop = pTmpRef->FindFootnoteBossFrm( !bEndn );
707 :
708 31 : 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 31 : const bool bEndNote = pOldPage->IsEndNotePage();
713 31 : const bool bFootnoteEndDoc = pOldPage->IsFootnotePage();
714 31 : SwFootnoteBossFrm* pNxtBoss = pOldBoss;
715 31 : SwSectionFrm *pSect = pNxtBoss->GetUpper()->IsSctFrm() ?
716 31 : static_cast<SwSectionFrm*>(pNxtBoss->GetUpper()) : 0;
717 :
718 0 : do
719 : {
720 31 : if( pNxtBoss->IsColumnFrm() && pNxtBoss->GetPrev() )
721 0 : pNxtBoss = static_cast<SwFootnoteBossFrm*>(pNxtBoss->GetPrev()); // one column backwards
722 : else // one page backwards
723 : {
724 31 : SwLayoutFrm* pBody = 0;
725 31 : if( pSect )
726 : {
727 0 : if( pSect->IsFootnoteLock() )
728 : {
729 0 : if( pNxtBoss == pOldBoss )
730 0 : return 0;
731 0 : pStop = pNxtBoss;
732 : }
733 : else
734 : {
735 0 : pSect = pSect->FindMaster();
736 0 : if( !pSect || !pSect->Lower() )
737 0 : return 0;
738 : OSL_ENSURE( pSect->Lower()->IsColumnFrm(),
739 : "GetPrevFootnoteLeaf: Where's the column?" );
740 0 : pNxtBoss = static_cast<SwFootnoteBossFrm*>(pSect->Lower());
741 0 : pBody = pSect;
742 : }
743 : }
744 : else
745 : {
746 31 : SwPageFrm* pPage = static_cast<SwPageFrm*>(pNxtBoss->FindPageFrm()->GetPrev());
747 93 : if( !pPage || pPage->GetPhyPageNum() < nNum ||
748 64 : bEndNote != pPage->IsEndNotePage() || bFootnoteEndDoc != pPage->IsFootnotePage() )
749 31 : 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<SwFootnoteBossFrm*>(pBody->GetLastLower());
759 : }
760 : }
761 : }
762 0 : SwFootnoteContFrm *pCont = pNxtBoss->FindFootnoteCont();
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 ( eMakeFootnote == MAKEPAGE_FTN && pNxtBoss->GetMaxFootnoteHeight() )
773 0 : pRet = pNxtBoss->MakeFootnoteCont();
774 0 : break;
775 : }
776 : } while( !pRet );
777 : }
778 30 : if ( pRet )
779 : {
780 30 : const SwFootnoteBossFrm* pNewBoss = pRet->FindFootnoteBossFrm();
781 30 : bool bJump = false;
782 30 : if( pOldBoss->IsColumnFrm() && pOldBoss->GetPrev() ) // a previous column exists
783 0 : bJump = pOldBoss->GetPrev() != static_cast<SwFrm const *>(pNewBoss); // did we chose it?
784 30 : 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 30 : const sal_uInt16 nDiff = pOldPage->GetPhyPageNum() - pRet->FindPageFrm()->GetPhyPageNum();
791 53 : if ( nDiff > 2 ||
792 23 : (nDiff > 1 && !static_cast<SwPageFrm*>(pOldPage->GetPrev())->IsEmptyPage()) )
793 23 : bJump = true;
794 : }
795 30 : if( bJump )
796 23 : SwFlowFrm::SetMoveBwdJump( true );
797 : }
798 30 : return pRet;
799 : }
800 :
801 26305 : bool SwFrm::IsFootnoteAllowed() const
802 : {
803 26305 : if ( !IsInDocBody() )
804 7413 : return false;
805 :
806 18892 : if ( IsInTab() )
807 : {
808 : // no footnotes in repeated headlines
809 6560 : const SwTabFrm *pTab = const_cast<SwFrm*>(this)->ImplFindTabFrm();
810 6560 : if ( pTab->IsFollow() )
811 1096 : return !pTab->IsInHeadline( *this );
812 : }
813 17796 : return true;
814 : }
815 :
816 12 : void SwRootFrm::UpdateFootnoteNums()
817 : {
818 : // page numbering only if set at the document
819 12 : if ( GetFormat()->GetDoc()->GetFootnoteInfo().eNum == FTNNUM_PAGE )
820 : {
821 0 : SwPageFrm *pPage = static_cast<SwPageFrm*>(Lower());
822 0 : while ( pPage && !pPage->IsFootnotePage() )
823 : {
824 0 : pPage->UpdateFootnoteNum();
825 0 : pPage = static_cast<SwPageFrm*>(pPage->GetNext());
826 : }
827 : }
828 12 : }
829 :
830 : /// remove all footnotes (not the references) and all footnote pages
831 4262 : void sw_RemoveFootnotes( SwFootnoteBossFrm* pBoss, bool bPageOnly, bool bEndNotes )
832 : {
833 4262 : do
834 : {
835 4262 : SwFootnoteContFrm *pCont = pBoss->FindFootnoteCont();
836 4262 : if ( pCont )
837 : {
838 63 : SwFootnoteFrm *pFootnote = static_cast<SwFootnoteFrm*>(pCont->Lower());
839 : OSL_ENSURE( pFootnote, "Footnote content without footnote." );
840 63 : if ( bPageOnly )
841 0 : while ( pFootnote->GetMaster() )
842 0 : pFootnote = pFootnote->GetMaster();
843 79 : do
844 : {
845 79 : SwFootnoteFrm *pNxt = static_cast<SwFootnoteFrm*>(pFootnote->GetNext());
846 79 : if ( !pFootnote->GetAttr()->GetFootnote().IsEndNote() ||
847 : bEndNotes )
848 : {
849 79 : pFootnote->GetRef()->Prepare( PREP_FTN, static_cast<void*>(pFootnote->GetAttr()) );
850 79 : if ( bPageOnly && !pNxt )
851 0 : pNxt = pFootnote->GetFollow();
852 79 : pFootnote->Cut();
853 79 : SwFrm::DestroyFrm(pFootnote);
854 : }
855 79 : pFootnote = pNxt;
856 :
857 : } while ( pFootnote );
858 : }
859 4262 : if( !pBoss->IsInSct() )
860 : {
861 : // A sectionframe with the Footnote/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 4177 : SwLayoutFrm* pBody = pBoss->FindBodyCont();
865 4177 : if( pBody && pBody->Lower() )
866 : {
867 4092 : SwFrm* pLow = pBody->Lower();
868 26615 : while (pLow)
869 : {
870 37365 : if( pLow->IsSctFrm() && ( !pLow->GetNext() ||
871 316 : static_cast<SwSectionFrm*>(pLow)->IsAnyNoteAtEnd() ) &&
872 18686 : static_cast<SwSectionFrm*>(pLow)->Lower() &&
873 127 : static_cast<SwSectionFrm*>(pLow)->Lower()->IsColumnFrm() )
874 41 : sw_RemoveFootnotes( static_cast<SwColumnFrm*>(static_cast<SwSectionFrm*>(pLow)->Lower()),
875 82 : bPageOnly, bEndNotes );
876 18431 : pLow = pLow->GetNext();
877 : }
878 : }
879 : }
880 : // is there another column?
881 4262 : pBoss = pBoss->IsColumnFrm() ? static_cast<SwColumnFrm*>(pBoss->GetNext()) : NULL;
882 : } while( pBoss );
883 4206 : }
884 :
885 3056 : void SwRootFrm::RemoveFootnotes( SwPageFrm *pPage, bool bPageOnly, bool bEndNotes )
886 : {
887 3056 : if ( !pPage )
888 3041 : pPage = static_cast<SwPageFrm*>(Lower());
889 :
890 4149 : do
891 : { // On columned pages we have to clean up in all columns
892 : SwFootnoteBossFrm* pBoss;
893 4164 : SwLayoutFrm* pBody = pPage->FindBodyCont();
894 4164 : if( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrm() )
895 13 : pBoss = static_cast<SwFootnoteBossFrm*>(pBody->Lower()); // the first column
896 : else
897 4151 : pBoss = pPage; // no columns
898 4164 : sw_RemoveFootnotes( pBoss, bPageOnly, bEndNotes );
899 4164 : if ( !bPageOnly )
900 : {
901 4179 : if ( pPage->IsFootnotePage() &&
902 29 : (!pPage->IsEndNotePage() || bEndNotes) )
903 : {
904 15 : SwFrm *pDel = pPage;
905 15 : pPage = static_cast<SwPageFrm*>(pPage->GetNext());
906 15 : pDel->Cut();
907 15 : SwFrm::DestroyFrm(pDel);
908 : }
909 : else
910 4134 : pPage = static_cast<SwPageFrm*>(pPage->GetNext());
911 : }
912 : else
913 15 : break;
914 :
915 : } while ( pPage );
916 3056 : }
917 :
918 : /// Change the page template of the footnote pages
919 1 : void SwRootFrm::CheckFootnotePageDescs( bool bEndNote )
920 : {
921 1 : SwPageFrm *pPage = static_cast<SwPageFrm*>(Lower());
922 3 : while ( pPage && !pPage->IsFootnotePage() )
923 1 : pPage = static_cast<SwPageFrm*>(pPage->GetNext());
924 2 : while ( pPage && pPage->IsEndNotePage() != bEndNote )
925 0 : pPage = static_cast<SwPageFrm*>(pPage->GetNext());
926 :
927 1 : if ( pPage )
928 1 : SwFrm::CheckPageDescs( pPage, false );
929 1 : }
930 :
931 : /** Insert a footnote container
932 : *
933 : * A footnote container is always placed directly behind the body text.
934 : *
935 : * The frame format (FrameFormat) is always the default frame format.
936 : *
937 : * @return footnote container frame
938 : */
939 87 : SwFootnoteContFrm *SwFootnoteBossFrm::MakeFootnoteCont()
940 : {
941 : SAL_WARN_IF(FindFootnoteCont(), "sw.core", "footnote container exists already");
942 :
943 87 : SwFootnoteContFrm *pNew = new SwFootnoteContFrm( GetFormat()->GetDoc()->GetDfltFrameFormat(), this );
944 87 : SwLayoutFrm *pLay = FindBodyCont();
945 87 : pNew->Paste( this, pLay->GetNext() );
946 87 : return pNew;
947 : }
948 :
949 9567 : SwFootnoteContFrm *SwFootnoteBossFrm::FindFootnoteCont()
950 : {
951 9567 : SwFrm *pFrm = Lower();
952 31741 : while( pFrm && !pFrm->IsFootnoteContFrm() )
953 12607 : pFrm = pFrm->GetNext();
954 :
955 : #if OSL_DEBUG_LEVEL > 0
956 : if ( pFrm )
957 : {
958 : SwFrm *pFootnote = pFrm->GetLower();
959 : OSL_ENSURE( pFootnote, "Content without footnote." );
960 : while ( pFootnote )
961 : {
962 : OSL_ENSURE( pFootnote->IsFootnoteFrm(), "Neighbor of footnote is not a footnote." );
963 : pFootnote = pFootnote->GetNext();
964 : }
965 : }
966 : #endif
967 :
968 9567 : return static_cast<SwFootnoteContFrm*>(pFrm);
969 : }
970 :
971 : /// Search the next available footnote container.
972 324 : SwFootnoteContFrm *SwFootnoteBossFrm::FindNearestFootnoteCont( bool bDontLeave )
973 : {
974 324 : SwFootnoteContFrm *pCont = 0;
975 324 : if ( !GetFormat()->GetDoc()->GetFootnoteIdxs().empty() )
976 : {
977 324 : pCont = FindFootnoteCont();
978 324 : if ( !pCont )
979 : {
980 160 : SwPageFrm *pPage = FindPageFrm();
981 160 : SwFootnoteBossFrm* pBoss = this;
982 160 : bool bEndNote = pPage->IsEndNotePage();
983 243 : do
984 : {
985 243 : bool bChgPage = lcl_NextFootnoteBoss( pBoss, pPage, bDontLeave );
986 : // Found another boss? When changing pages, also the endnote flag must match.
987 243 : if( pBoss && ( !bChgPage || pPage->IsEndNotePage() == bEndNote ) )
988 83 : pCont = pBoss->FindFootnoteCont();
989 241 : } while ( !pCont && pPage );
990 : }
991 : }
992 324 : return pCont;
993 : }
994 :
995 240 : SwFootnoteFrm *SwFootnoteBossFrm::FindFirstFootnote()
996 : {
997 : // search for the nearest footnote container
998 240 : SwFootnoteContFrm *pCont = FindNearestFootnoteCont();
999 240 : if ( !pCont )
1000 79 : return 0;
1001 :
1002 : // Starting from the first footnote, search the first
1003 : // footnote that is referenced by the current column/page
1004 :
1005 161 : SwFootnoteFrm *pRet = static_cast<SwFootnoteFrm*>(pCont->Lower());
1006 161 : const sal_uInt16 nRefNum = FindPageFrm()->GetPhyPageNum();
1007 161 : const sal_uInt16 nRefCol = lcl_ColumnNum( this );
1008 : sal_uInt16 nPgNum, nColNum; // page number, column number
1009 : SwFootnoteBossFrm* pBoss;
1010 : SwPageFrm* pPage;
1011 161 : if( pRet )
1012 : {
1013 161 : pBoss = pRet->GetRef()->FindFootnoteBossFrm();
1014 : OSL_ENSURE( pBoss, "FindFirstFootnote: No boss found" );
1015 161 : if( !pBoss )
1016 0 : return NULL; // ?There must be a bug, but no GPF
1017 161 : pPage = pBoss->FindPageFrm();
1018 161 : nPgNum = pPage->GetPhyPageNum();
1019 161 : if ( nPgNum == nRefNum )
1020 : {
1021 154 : nColNum = lcl_ColumnNum( pBoss );
1022 154 : if( nColNum == nRefCol )
1023 154 : return pRet; // found
1024 0 : else if( nColNum > nRefCol )
1025 0 : return NULL; // at least one column too far
1026 : }
1027 7 : 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 13 : do
1035 : {
1036 26 : while ( pRet->GetFollow() )
1037 0 : pRet = pRet->GetFollow();
1038 :
1039 13 : SwFootnoteFrm *pNxt = static_cast<SwFootnoteFrm*>(pRet->GetNext());
1040 13 : if ( !pNxt )
1041 : {
1042 7 : pBoss = pRet->FindFootnoteBossFrm();
1043 7 : pPage = pBoss->FindPageFrm();
1044 7 : lcl_NextFootnoteBoss( pBoss, pPage, false ); // next FootnoteBoss
1045 7 : pCont = pBoss ? pBoss->FindNearestFootnoteCont() : 0;
1046 7 : if ( pCont )
1047 0 : pNxt = static_cast<SwFootnoteFrm*>(pCont->Lower());
1048 : }
1049 13 : if ( pNxt )
1050 : {
1051 6 : pRet = pNxt;
1052 6 : pBoss = pRet->GetRef()->FindFootnoteBossFrm();
1053 6 : pPage = pBoss->FindPageFrm();
1054 6 : nPgNum = pPage->GetPhyPageNum();
1055 6 : 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 6 : else if ( nPgNum > nRefNum )
1064 0 : pRet = 0; // at least a page too far
1065 : }
1066 : else
1067 7 : pRet = 0; // there is none
1068 : } while( pRet );
1069 7 : return pRet;
1070 : }
1071 :
1072 : /// Get the first footnote of a given content
1073 48 : const SwFootnoteFrm *SwFootnoteBossFrm::FindFirstFootnote( SwContentFrm *pCnt ) const
1074 : {
1075 48 : const SwFootnoteFrm *pRet = const_cast<SwFootnoteBossFrm*>(this)->FindFirstFootnote();
1076 48 : if ( pRet )
1077 : {
1078 46 : const sal_uInt16 nColNum = lcl_ColumnNum( this );
1079 46 : const sal_uInt16 nPageNum = GetPhyPageNum();
1080 102 : while ( pRet && (pRet->GetRef() != pCnt) )
1081 : {
1082 20 : while ( pRet->GetFollow() )
1083 0 : pRet = pRet->GetFollow();
1084 :
1085 10 : if ( pRet->GetNext() )
1086 6 : pRet = static_cast<const SwFootnoteFrm*>(pRet->GetNext());
1087 : else
1088 4 : { SwFootnoteBossFrm *pBoss = const_cast<SwFootnoteBossFrm*>(pRet->FindFootnoteBossFrm());
1089 4 : SwPageFrm *pPage = pBoss->FindPageFrm();
1090 4 : lcl_NextFootnoteBoss( pBoss, pPage, false ); // next FootnoteBoss
1091 4 : SwFootnoteContFrm *pCont = pBoss ? pBoss->FindNearestFootnoteCont() : 0;
1092 4 : pRet = pCont ? static_cast<SwFootnoteFrm*>(pCont->Lower()) : 0;
1093 : }
1094 10 : if ( pRet )
1095 : {
1096 10 : const SwFootnoteBossFrm* pBoss = pRet->GetRef()->FindFootnoteBossFrm();
1097 20 : if( pBoss->GetPhyPageNum() != nPageNum ||
1098 10 : nColNum != lcl_ColumnNum( pBoss ) )
1099 0 : pRet = 0;
1100 : }
1101 : }
1102 : }
1103 48 : return pRet;
1104 : }
1105 :
1106 105 : void SwFootnoteBossFrm::ResetFootnote( const SwFootnoteFrm *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 105 : SwNodeIndex aIdx( *pCheck->GetAttr()->GetStartNode(), 1 );
1113 105 : SwContentNode *pNd = aIdx.GetNode().GetContentNode();
1114 105 : if ( !pNd )
1115 0 : pNd = pCheck->GetFormat()->GetDoc()->
1116 0 : GetNodes().GoNextSection( &aIdx, true, false );
1117 210 : SwIterator<SwFrm,SwContentNode> aIter( *pNd );
1118 105 : SwFrm* pFrm = aIter.First();
1119 320 : while( pFrm )
1120 : {
1121 110 : if( pFrm->getRootFrm() == pCheck->getRootFrm() )
1122 : {
1123 110 : SwFrm *pTmp = pFrm->GetUpper();
1124 220 : while ( pTmp && !pTmp->IsFootnoteFrm() )
1125 0 : pTmp = pTmp->GetUpper();
1126 :
1127 110 : SwFootnoteFrm *pFootnote = static_cast<SwFootnoteFrm*>(pTmp);
1128 220 : while ( pFootnote && pFootnote->GetMaster() )
1129 0 : pFootnote = pFootnote->GetMaster();
1130 110 : if ( pFootnote != pCheck )
1131 : {
1132 0 : while ( pFootnote )
1133 : {
1134 0 : SwFootnoteFrm *pNxt = pFootnote->GetFollow();
1135 0 : pFootnote->Cut();
1136 0 : SwFrm::DestroyFrm(pFootnote);
1137 0 : pFootnote = pNxt;
1138 : }
1139 : }
1140 : }
1141 :
1142 110 : pFrm = aIter.Next();
1143 105 : }
1144 105 : }
1145 :
1146 105 : void SwFootnoteBossFrm::InsertFootnote( SwFootnoteFrm* 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 105 : ResetFootnote( pNew );
1155 105 : SwFootnoteFrm *pSibling = FindFirstFootnote();
1156 105 : bool bDontLeave = false;
1157 :
1158 : // Ok, a sibling has been found, but is the sibling in an acceptable
1159 : // environment?
1160 105 : if( IsInSct() )
1161 : {
1162 19 : SwSectionFrm* pMySect = ImplFindSctFrm();
1163 19 : bool bEndnt = pNew->GetAttr()->GetFootnote().IsEndNote();
1164 19 : if( bEndnt )
1165 : {
1166 15 : const SwSectionFormat* pEndFormat = pMySect->GetEndSectFormat();
1167 15 : bDontLeave = 0 != pEndFormat;
1168 15 : if( pSibling )
1169 : {
1170 1 : if( pEndFormat )
1171 : {
1172 2 : if( !pSibling->IsInSct() ||
1173 1 : !pSibling->ImplFindSctFrm()->IsDescendantFrom( pEndFormat ) )
1174 0 : pSibling = NULL;
1175 : }
1176 0 : else if( pSibling->IsInSct() )
1177 0 : pSibling = NULL;
1178 : }
1179 : }
1180 : else
1181 : {
1182 4 : bDontLeave = pMySect->IsFootnoteAtEnd();
1183 4 : if( pSibling )
1184 : {
1185 1 : if( pMySect->IsFootnoteAtEnd() )
1186 : {
1187 0 : if( !pSibling->IsInSct() ||
1188 0 : !pMySect->IsAnFollow( pSibling->ImplFindSctFrm() ) )
1189 0 : pSibling = NULL;
1190 : }
1191 1 : else if( pSibling->IsInSct() )
1192 1 : pSibling = NULL;
1193 : }
1194 : }
1195 : }
1196 :
1197 125 : if( pSibling && pSibling->FindPageFrm()->IsEndNotePage() !=
1198 20 : FindPageFrm()->IsEndNotePage() )
1199 0 : pSibling = NULL;
1200 :
1201 : // use the Doc to find out the position
1202 105 : SwDoc *pDoc = GetFormat()->GetDoc();
1203 105 : const sal_uLong nStPos = ::lcl_FindFootnotePos( pDoc, pNew->GetAttr() );
1204 :
1205 105 : sal_uLong nCmpPos = 0;
1206 105 : sal_uLong nLastPos = 0;
1207 105 : SwFootnoteContFrm *pParent = 0;
1208 105 : if( pSibling )
1209 : {
1210 20 : nCmpPos = ::lcl_FindFootnotePos( pDoc, pSibling->GetAttr() );
1211 20 : if( nCmpPos > nStPos )
1212 4 : pSibling = NULL;
1213 : }
1214 :
1215 105 : if ( !pSibling )
1216 89 : { pParent = FindFootnoteCont();
1217 89 : 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 78 : pParent = FindNearestFootnoteCont( bDontLeave );
1223 78 : if ( pParent )
1224 : {
1225 1 : SwFootnoteFrm *pFootnote = static_cast<SwFootnoteFrm*>(pParent->Lower());
1226 1 : if ( pFootnote )
1227 : {
1228 :
1229 1 : nCmpPos = ::lcl_FindFootnotePos( pDoc, pFootnote->GetAttr() );
1230 1 : if ( nCmpPos > nStPos )
1231 1 : pParent = 0;
1232 : }
1233 : else
1234 0 : pParent = 0;
1235 : }
1236 : }
1237 89 : if ( !pParent )
1238 : // here, we are sure that we can create a footnote container
1239 78 : pParent = MakeFootnoteCont();
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 11 : pSibling = static_cast<SwFootnoteFrm*>(pParent->Lower());
1245 11 : if ( !pSibling )
1246 : { OSL_ENSURE( false, "Could not find space for footnote.");
1247 105 : return;
1248 : }
1249 11 : nCmpPos = ::lcl_FindFootnotePos( pDoc, pSibling->GetAttr() );
1250 :
1251 : SwFootnoteBossFrm *pNxtB; // remember the last one to not
1252 11 : SwFootnoteFrm *pLastSib = 0; // go too far.
1253 :
1254 28 : while ( pSibling && nCmpPos <= nStPos )
1255 : {
1256 14 : pLastSib = pSibling; // potential candidate
1257 14 : nLastPos = nCmpPos;
1258 :
1259 28 : while ( pSibling->GetFollow() )
1260 0 : pSibling = pSibling->GetFollow();
1261 :
1262 14 : if ( pSibling->GetNext() )
1263 : {
1264 6 : pSibling = static_cast<SwFootnoteFrm*>(pSibling->GetNext());
1265 : OSL_ENSURE( !pSibling->GetMaster() || ( ENDNOTE > nStPos &&
1266 : pSibling->GetAttr()->GetFootnote().IsEndNote() ),
1267 : "InsertFootnote: Master expected I" );
1268 : }
1269 : else
1270 : {
1271 8 : pNxtB = pSibling->FindFootnoteBossFrm();
1272 8 : SwPageFrm *pSibPage = pNxtB->FindPageFrm();
1273 8 : bool bEndNote = pSibPage->IsEndNotePage();
1274 8 : bool bChgPage = lcl_NextFootnoteBoss( pNxtB, pSibPage, bDontLeave );
1275 : // When changing pages, also the endnote flag must match.
1276 2 : SwFootnoteContFrm *pCont = pNxtB && ( !bChgPage ||
1277 1 : pSibPage->IsEndNotePage() == bEndNote )
1278 8 : ? pNxtB->FindNearestFootnoteCont( bDontLeave ) : 0;
1279 8 : if( pCont )
1280 0 : pSibling = static_cast<SwFootnoteFrm*>(pCont->Lower());
1281 : else // no further FootnoteContainer, insert after pSibling
1282 8 : break;
1283 : }
1284 6 : if ( pSibling )
1285 : {
1286 6 : nCmpPos = ::lcl_FindFootnotePos( pDoc, pSibling->GetAttr() );
1287 : OSL_ENSURE( nCmpPos > nLastPos, "InsertFootnote: Order of FootnoteFrm'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 11 : if ( pSibling && pLastSib && (pSibling != pLastSib) )
1293 : {
1294 : // too far?
1295 0 : if ( nCmpPos > nStPos )
1296 0 : pSibling = pLastSib;
1297 : }
1298 11 : 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(), "InsertFootnote: 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 16 : SwFootnoteBossFrm* pBoss = pNew->GetRef()->FindFootnoteBossFrm(
1315 32 : !pNew->GetAttr()->GetFootnote().IsEndNote() );
1316 16 : sal_uInt16 nRefNum = pBoss->GetPhyPageNum(); // page number of the new footnote
1317 16 : sal_uInt16 nRefCol = lcl_ColumnNum( pBoss ); // column number of the new footnote
1318 16 : bool bEnd = false;
1319 16 : SwFootnoteFrm *pLastSib = 0;
1320 48 : while ( pSibling && !bEnd && (nCmpPos <= nStPos) )
1321 : {
1322 16 : pLastSib = pSibling;
1323 16 : nLastPos = nCmpPos;
1324 :
1325 32 : while ( pSibling->GetFollow() )
1326 0 : pSibling = pSibling->GetFollow();
1327 :
1328 16 : SwFootnoteFrm *pFoll = static_cast<SwFootnoteFrm*>(pSibling->GetNext());
1329 16 : if ( pFoll )
1330 : {
1331 0 : pBoss = pSibling->GetRef()->FindFootnoteBossFrm( !pSibling->
1332 0 : GetAttr()->GetFootnote().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 16 : SwFootnoteBossFrm* pNxtB = pSibling->FindFootnoteBossFrm();
1344 16 : SwPageFrm *pSibPage = pNxtB->FindPageFrm();
1345 16 : bool bEndNote = pSibPage->IsEndNotePage();
1346 16 : bool bChgPage = lcl_NextFootnoteBoss( pNxtB, pSibPage, bDontLeave );
1347 : // When changing pages, also the endnote flag must match.
1348 9 : SwFootnoteContFrm *pCont = pNxtB && ( !bChgPage ||
1349 4 : pSibPage->IsEndNotePage() == bEndNote )
1350 18 : ? pNxtB->FindNearestFootnoteCont( bDontLeave ) : 0;
1351 16 : if ( pCont )
1352 0 : pSibling = static_cast<SwFootnoteFrm*>(pCont->Lower());
1353 : else
1354 16 : bEnd = true;
1355 : }
1356 16 : if ( !bEnd && pSibling )
1357 0 : nCmpPos = ::lcl_FindFootnotePos( pDoc, pSibling->GetAttr() );
1358 16 : 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 105 : if ( pSibling )
1370 : {
1371 27 : nCmpPos = ::lcl_FindFootnotePos( pDoc, pSibling->GetAttr() );
1372 27 : if ( nCmpPos < nStPos )
1373 : {
1374 48 : while ( pSibling->GetFollow() )
1375 0 : pSibling = pSibling->GetFollow();
1376 24 : pParent = static_cast<SwFootnoteContFrm*>(pSibling->GetUpper());
1377 24 : pSibling = static_cast<SwFootnoteFrm*>(pSibling->GetNext());
1378 : }
1379 : else
1380 : {
1381 3 : if( pSibling->GetMaster() )
1382 : {
1383 0 : if( ENDNOTE > nCmpPos || nStPos >= ENDNOTE )
1384 : {
1385 : OSL_FAIL( "InsertFootnote: Master expected II" );
1386 0 : do
1387 0 : pSibling = pSibling->GetMaster();
1388 0 : while ( pSibling->GetMaster() );
1389 : }
1390 : }
1391 3 : pParent = static_cast<SwFootnoteContFrm*>(pSibling->GetUpper());
1392 : }
1393 : }
1394 : OSL_ENSURE( pParent, "paste in space?" );
1395 105 : pNew->Paste( pParent, pSibling );
1396 : }
1397 :
1398 90 : void SwFootnoteBossFrm::AppendFootnote( SwContentFrm *pRef, SwTextFootnote *pAttr )
1399 : {
1400 : // If the footnote already exists, do nothing.
1401 90 : if ( FindFootnote( 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 90 : SwDoc *pDoc = GetFormat()->GetDoc();
1410 90 : SwFootnoteBossFrm *pBoss = this;
1411 90 : SwPageFrm *pPage = FindPageFrm();
1412 90 : SwPageFrm *pMyPage = pPage;
1413 90 : bool bChgPage = false;
1414 90 : bool bEnd = false;
1415 90 : if ( pAttr->GetFootnote().IsEndNote() )
1416 : {
1417 17 : bEnd = true;
1418 22 : if( GetUpper()->IsSctFrm() &&
1419 5 : static_cast<SwSectionFrm*>(GetUpper())->IsEndnAtEnd() )
1420 : {
1421 : SwFrm* pLast =
1422 0 : static_cast<SwSectionFrm*>(GetUpper())->FindLastContent( FINDMODE_ENDNOTE );
1423 0 : if( pLast )
1424 : {
1425 0 : pBoss = pLast->FindFootnoteBossFrm();
1426 0 : pPage = pBoss->FindPageFrm();
1427 : }
1428 : }
1429 : else
1430 : {
1431 41 : while ( pPage->GetNext() && !pPage->IsEndNotePage() )
1432 : {
1433 7 : pPage = static_cast<SwPageFrm*>(pPage->GetNext());
1434 7 : bChgPage = true;
1435 : }
1436 17 : if ( !pPage->IsEndNotePage() )
1437 : {
1438 10 : SwPageDesc *pDesc = pDoc->GetEndNoteInfo().GetPageDesc( *pDoc );
1439 10 : pPage = ::InsertNewPage( *pDesc, pPage->GetUpper(),
1440 20 : !pPage->OnRightPage(), false, false, true, 0 );
1441 10 : pPage->SetEndNotePage( true );
1442 10 : 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 7 : SwPageFrm *pNxt = static_cast<SwPageFrm*>(pPage->GetNext());
1450 7 : const sal_uLong nStPos = ::lcl_FindFootnotePos( pDoc, pAttr );
1451 14 : while ( pNxt && pNxt->IsEndNotePage() )
1452 : {
1453 0 : SwFootnoteContFrm *pCont = pNxt->FindFootnoteCont();
1454 0 : if ( pCont && pCont->Lower() )
1455 : {
1456 : OSL_ENSURE( pCont->Lower()->IsFootnoteFrm(), "no footnote in the container" );
1457 0 : if ( nStPos > ::lcl_FindFootnotePos( pDoc,
1458 0 : static_cast<SwFootnoteFrm*>(pCont->Lower())->GetAttr()))
1459 : {
1460 0 : pPage = pNxt;
1461 0 : pNxt = static_cast<SwPageFrm*>(pPage->GetNext());
1462 0 : continue;
1463 : }
1464 : }
1465 0 : break;
1466 : }
1467 : }
1468 : }
1469 : }
1470 75 : else if( FTNPOS_CHAPTER == pDoc->GetFootnoteInfo().ePos && ( !GetUpper()->
1471 1 : IsSctFrm() || !static_cast<SwSectionFrm*>(GetUpper())->IsFootnoteAtEnd() ) )
1472 : {
1473 2 : while ( pPage->GetNext() && !pPage->IsFootnotePage() &&
1474 0 : !static_cast<SwPageFrm*>(pPage->GetNext())->IsEndNotePage() )
1475 : {
1476 0 : pPage = static_cast<SwPageFrm*>(pPage->GetNext());
1477 0 : bChgPage = true;
1478 : }
1479 :
1480 1 : if ( !pPage->IsFootnotePage() )
1481 : {
1482 1 : SwPageDesc *pDesc = pDoc->GetFootnoteInfo().GetPageDesc( *pDoc );
1483 1 : pPage = ::InsertNewPage( *pDesc, pPage->GetUpper(),
1484 2 : !pPage->OnRightPage(), false, false, true, pPage->GetNext() );
1485 1 : 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 = static_cast<SwPageFrm*>(pPage->GetNext());
1493 0 : const sal_uLong nStPos = ::lcl_FindFootnotePos( pDoc, pAttr );
1494 0 : while ( pNxt && pNxt->IsFootnotePage() && !pNxt->IsEndNotePage() )
1495 : {
1496 0 : SwFootnoteContFrm *pCont = pNxt->FindFootnoteCont();
1497 0 : if ( pCont && pCont->Lower() )
1498 : {
1499 : OSL_ENSURE( pCont->Lower()->IsFootnoteFrm(), "no footnote in the container" );
1500 0 : if ( nStPos > ::lcl_FindFootnotePos( pDoc,
1501 0 : static_cast<SwFootnoteFrm*>(pCont->Lower())->GetAttr()))
1502 : {
1503 0 : pPage = pNxt;
1504 0 : pNxt = static_cast<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 90 : 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 90 : if( pBoss->IsInSct() && pBoss->IsColumnFrm() && !pPage->IsFootnotePage() )
1523 : {
1524 4 : SwSectionFrm* pSct = pBoss->FindSctFrm();
1525 4 : if( bEnd ? !pSct->IsEndnAtEnd() : !pSct->IsFootnoteAtEnd() )
1526 : {
1527 3 : SwFootnoteContFrm* pFootnoteCont = pSct->FindFootnoteBossFrm(!bEnd)->FindFootnoteCont();
1528 3 : if( pFootnoteCont )
1529 : {
1530 0 : SwFootnoteFrm* pTmp = static_cast<SwFootnoteFrm*>(pFootnoteCont->Lower());
1531 0 : if( bEnd )
1532 0 : while( pTmp && !pTmp->GetAttr()->GetFootnote().IsEndNote() )
1533 0 : pTmp = static_cast<SwFootnoteFrm*>(pTmp->GetNext());
1534 0 : if( pTmp && *pTmp < pAttr )
1535 0 : return;
1536 : }
1537 : }
1538 : }
1539 :
1540 90 : SwFootnoteFrm *pNew = new SwFootnoteFrm( pDoc->GetDfltFrameFormat(), this, pRef, pAttr );
1541 : {
1542 90 : SwNodeIndex aIdx( *pAttr->GetStartNode(), 1 );
1543 90 : ::_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 90 : if( bChgPage )
1548 : {
1549 18 : SwLayoutFrm* pBody = pPage->FindBodyCont();
1550 : OSL_ENSURE( pBody, "AppendFootnote: NoPageBody?" );
1551 18 : if( pBody->Lower() && pBody->Lower()->IsColumnFrm() )
1552 0 : pBoss = static_cast<SwFootnoteBossFrm*>(pBody->Lower());
1553 : else
1554 18 : pBoss = pPage; // page if no columns exist
1555 : }
1556 90 : pBoss->InsertFootnote( pNew );
1557 90 : if ( pNew->GetUpper() ) // inserted or not?
1558 : {
1559 90 : ::RegistFlys( pNew->FindPageFrm(), pNew );
1560 90 : SwSectionFrm* pSect = FindSctFrm();
1561 : // The content of a FootnoteContainer in a (column) section only need to be calculated
1562 : // if the section stretches already to the bottom edge of the Upper.
1563 102 : if( pSect && !pSect->IsJoinLocked() && ( bEnd ? !pSect->IsEndnAtEnd() :
1564 96 : !pSect->IsFootnoteAtEnd() ) && pSect->Growable() )
1565 3 : pSect->InvalidateSize();
1566 : else
1567 : {
1568 : // #i49383# - disable unlock of position of
1569 : // lower objects during format of footnote content.
1570 87 : const bool bOldFootnoteFrmLocked( pNew->IsColLocked() );
1571 87 : pNew->ColLock();
1572 87 : pNew->KeepLockPosOfLowerObjs();
1573 : // #i57914# - adjust fix #i49383#
1574 87 : SwContentFrm *pCnt = pNew->ContainsContent();
1575 313 : while ( pCnt && pCnt->FindFootnoteFrm()->GetAttr() == pAttr )
1576 : {
1577 139 : pCnt->Calc();
1578 : // #i49383# - format anchored objects
1579 139 : if ( pCnt->IsTextFrm() && pCnt->IsValid() )
1580 : {
1581 139 : if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt,
1582 139 : *(pCnt->FindPageFrm()) ) )
1583 : {
1584 : // restart format with first content
1585 0 : pCnt = pNew->ContainsContent();
1586 0 : continue;
1587 : }
1588 : }
1589 139 : pCnt = pCnt->FindNextCnt();
1590 : }
1591 : // #i49383#
1592 87 : if ( !bOldFootnoteFrmLocked )
1593 : {
1594 87 : pNew->ColUnlock();
1595 : }
1596 : // #i57914# - adjust fix #i49383#
1597 : // enable lock of lower object position before format of footnote frame.
1598 87 : pNew->UnlockPosOfLowerObjs();
1599 87 : pNew->Calc();
1600 : // #i57914# - adjust fix #i49383#
1601 261 : if ( !bOldFootnoteFrmLocked && !pNew->GetLower() &&
1602 87 : !pNew->IsColLocked() && !pNew->IsBackMoveLocked() )
1603 : {
1604 0 : pNew->Cut();
1605 0 : SwFrm::DestroyFrm(pNew);
1606 : }
1607 : }
1608 90 : pMyPage->UpdateFootnoteNum();
1609 : }
1610 : else
1611 0 : SwFrm::DestroyFrm(pNew);
1612 : }
1613 :
1614 592 : SwFootnoteFrm *SwFootnoteBossFrm::FindFootnote( const SwContentFrm *pRef, const SwTextFootnote *pAttr )
1615 : {
1616 : // the easiest and savest way goes via the attribute
1617 : OSL_ENSURE( pAttr->GetStartNode(), "FootnoteAtr without StartNode." );
1618 592 : SwNodeIndex aIdx( *pAttr->GetStartNode(), 1 );
1619 592 : SwContentNode *pNd = aIdx.GetNode().GetContentNode();
1620 592 : if ( !pNd )
1621 : pNd = pRef->GetAttrSet()->GetDoc()->
1622 0 : GetNodes().GoNextSection( &aIdx, true, false );
1623 592 : if ( !pNd )
1624 0 : return 0;
1625 1184 : SwIterator<SwFrm,SwContentNode> aIter( *pNd );
1626 592 : SwFrm* pFrm = aIter.First();
1627 592 : if( pFrm )
1628 0 : do
1629 : {
1630 413 : pFrm = pFrm->GetUpper();
1631 : // #i28500#, #i27243# Due to the endnode collector, there are
1632 : // SwFootnoteFrms, which are not in the layout. Therefore the
1633 : // bInfFootnote flags are not set correctly, and a cell of FindFootnoteFrm
1634 : // would return 0. Therefore we better call ImplFindFootnoteFrm().
1635 413 : SwFootnoteFrm *pFootnote = pFrm->ImplFindFootnoteFrm();
1636 413 : if ( pFootnote && pFootnote->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 413 : if( pFootnote->GetAttr() != pAttr )
1643 0 : return 0;
1644 826 : while ( pFootnote && pFootnote->GetMaster() )
1645 0 : pFootnote = pFootnote->GetMaster();
1646 413 : return pFootnote;
1647 : }
1648 :
1649 : } while ( 0 != (pFrm = aIter.Next()) );
1650 :
1651 771 : return 0;
1652 : }
1653 :
1654 15 : void SwFootnoteBossFrm::RemoveFootnote( const SwContentFrm *pRef, const SwTextFootnote *pAttr,
1655 : bool bPrep )
1656 : {
1657 15 : SwFootnoteFrm *pFootnote = FindFootnote( pRef, pAttr );
1658 15 : if( pFootnote )
1659 : {
1660 15 : do
1661 : {
1662 15 : SwFootnoteFrm *pFoll = pFootnote->GetFollow();
1663 15 : pFootnote->Cut();
1664 15 : SwFrm::DestroyFrm(pFootnote);
1665 15 : pFootnote = pFoll;
1666 : } while ( pFootnote );
1667 15 : if( bPrep && pRef->IsFollow() )
1668 : {
1669 : OSL_ENSURE( pRef->IsTextFrm(), "NoTextFrm has Footnote?" );
1670 0 : SwTextFrm* pMaster = pRef->FindMaster();
1671 0 : if( !pMaster->IsLocked() )
1672 0 : pMaster->Prepare( PREP_FTN_GONE );
1673 : }
1674 : }
1675 15 : FindPageFrm()->UpdateFootnoteNum();
1676 15 : }
1677 :
1678 0 : void SwFootnoteBossFrm::ChangeFootnoteRef( const SwContentFrm *pOld, const SwTextFootnote *pAttr,
1679 : SwContentFrm *pNew )
1680 : {
1681 0 : SwFootnoteFrm *pFootnote = FindFootnote( pOld, pAttr );
1682 0 : while ( pFootnote )
1683 : {
1684 0 : pFootnote->SetRef( pNew );
1685 0 : pFootnote = pFootnote->GetFollow();
1686 : }
1687 0 : }
1688 :
1689 : /// OD 03.04.2003 #108446# - add parameter <_bCollectOnlyPreviousFootnotes> 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 SwFootnoteBossFrm::CollectFootnotes( const SwContentFrm* _pRef,
1693 : SwFootnoteBossFrm* _pOld,
1694 : SwFootnoteFrms& _rFootnoteArr,
1695 : const bool _bCollectOnlyPreviousFootnotes )
1696 : {
1697 0 : SwFootnoteFrm *pFootnote = _pOld->FindFirstFootnote();
1698 0 : while( !pFootnote )
1699 : {
1700 0 : if( _pOld->IsColumnFrm() )
1701 : {
1702 : // visit columns
1703 0 : while ( !pFootnote && _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 = static_cast<SwFootnoteBossFrm*>(_pOld->GetPrev());
1708 0 : pFootnote = _pOld->FindFirstFootnote();
1709 : }
1710 : }
1711 0 : if( !pFootnote )
1712 : {
1713 : // previous page
1714 : SwPageFrm* pPg;
1715 0 : for ( SwFrm* pTmp = _pOld;
1716 0 : 0 != ( pPg = static_cast<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<SwFootnoteBossFrm*>(pBody->GetLastLower());
1730 : }
1731 : else
1732 0 : _pOld = pPg; // single column page
1733 0 : pFootnote = _pOld->FindFirstFootnote();
1734 : }
1735 : }
1736 : // OD 03.04.2003 #108446# - consider new parameter <_bCollectOnlyPreviousFootnotes>
1737 0 : SwFootnoteBossFrm* pRefBossFrm = NULL;
1738 0 : if ( _bCollectOnlyPreviousFootnotes )
1739 : {
1740 0 : pRefBossFrm = this;
1741 : }
1742 0 : _CollectFootnotes( _pRef, pFootnote, _rFootnoteArr, _bCollectOnlyPreviousFootnotes, pRefBossFrm );
1743 : }
1744 :
1745 0 : inline void FootnoteInArr( SwFootnoteFrms& rFootnoteArr, SwFootnoteFrm* pFootnote )
1746 : {
1747 0 : if ( rFootnoteArr.end() == std::find( rFootnoteArr.begin(), rFootnoteArr.end(), pFootnote ) )
1748 0 : rFootnoteArr.push_back( pFootnote );
1749 0 : }
1750 :
1751 : /// OD 03.04.2003 #108446# - add parameters <_bCollectOnlyPreviousFootnotes> and
1752 : /// <_pRefFootnoteBossFrm> 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 <_bCollectOnlyPreviousFootnotes> is true, then parameter
1755 : /// <_pRefFootnoteBossFrm> have to be referenced to an object.
1756 : /// Adjust parameter names.
1757 0 : void SwFootnoteBossFrm::_CollectFootnotes( const SwContentFrm* _pRef,
1758 : SwFootnoteFrm* _pFootnote,
1759 : SwFootnoteFrms& _rFootnoteArr,
1760 : bool _bCollectOnlyPreviousFootnotes,
1761 : const SwFootnoteBossFrm* _pRefFootnoteBossFrm)
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( !_bCollectOnlyPreviousFootnotes || _pRefFootnoteBossFrm,
1767 : "<SwFootnoteBossFrm::_CollectFootnotes(..)> - 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 : SwFootnoteFrms aNotFootnoteArr;
1776 :
1777 : // here we have a footnote placed in front of the first one of the reference
1778 : OSL_ENSURE( !_pFootnote->GetMaster() || _pFootnote->GetRef() != _pRef, "move FollowFootnote?" );
1779 0 : while ( _pFootnote->GetMaster() )
1780 0 : _pFootnote = _pFootnote->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 : SwFootnoteFrm *pNxtFootnote = _pFootnote;
1789 0 : while ( pNxtFootnote->GetFollow() )
1790 0 : pNxtFootnote = pNxtFootnote->GetFollow();
1791 0 : pNxtFootnote = static_cast<SwFootnoteFrm*>(pNxtFootnote->GetNext());
1792 :
1793 0 : if ( !pNxtFootnote )
1794 : {
1795 0 : SwFootnoteBossFrm* pBoss = _pFootnote->FindFootnoteBossFrm();
1796 0 : SwPageFrm* pPage = pBoss->FindPageFrm();
1797 0 : do
1798 : {
1799 0 : lcl_NextFootnoteBoss( pBoss, pPage, false );
1800 0 : if( pBoss )
1801 : {
1802 0 : SwLayoutFrm* pCont = pBoss->FindFootnoteCont();
1803 0 : if( pCont )
1804 : {
1805 0 : pNxtFootnote = static_cast<SwFootnoteFrm*>(pCont->Lower());
1806 0 : if( pNxtFootnote )
1807 : {
1808 0 : while( pNxtFootnote->GetMaster() )
1809 0 : pNxtFootnote = pNxtFootnote->GetMaster();
1810 0 : if( pNxtFootnote == _pFootnote )
1811 0 : pNxtFootnote = NULL;
1812 : }
1813 : }
1814 : }
1815 0 : } while( !pNxtFootnote && pBoss );
1816 : }
1817 0 : else if( !pNxtFootnote->GetAttr()->GetFootnote().IsEndNote() )
1818 : { OSL_ENSURE( !pNxtFootnote->GetMaster(), "_CollectFootnote: Master expected" );
1819 0 : while ( pNxtFootnote->GetMaster() )
1820 0 : pNxtFootnote = pNxtFootnote->GetMaster();
1821 : }
1822 0 : if ( pNxtFootnote == _pFootnote )
1823 : {
1824 : OSL_FAIL( "_CollectFootnote: Vicious circle" );
1825 0 : pNxtFootnote = 0;
1826 : }
1827 :
1828 : // OD 03.04.2003 #108446# - determine, if found footnote has to be collected.
1829 0 : bool bCollectFoundFootnote = false;
1830 0 : if ( _pFootnote->GetRef() == _pRef && !_pFootnote->GetAttr()->GetFootnote().IsEndNote() )
1831 : {
1832 0 : if ( _bCollectOnlyPreviousFootnotes )
1833 : {
1834 0 : SwFootnoteBossFrm* pBossOfFoundFootnote = _pFootnote->FindFootnoteBossFrm( true );
1835 : OSL_ENSURE( pBossOfFoundFootnote,
1836 : "<SwFootnoteBossFrm::_CollectFootnotes(..)> - footnote boss frame of found footnote frame missing.\nWrong layout!" );
1837 0 : if ( !pBossOfFoundFootnote || // don't crash, if no footnote boss is found.
1838 0 : pBossOfFoundFootnote->IsBefore( _pRefFootnoteBossFrm )
1839 : )
1840 : {
1841 0 : bCollectFoundFootnote = true;
1842 : }
1843 : }
1844 : else
1845 : {
1846 0 : bCollectFoundFootnote = true;
1847 : }
1848 : }
1849 :
1850 0 : if ( bCollectFoundFootnote )
1851 : {
1852 : OSL_ENSURE( !_pFootnote->GetMaster(), "move FollowFootnote?" );
1853 0 : SwFootnoteFrm *pNxt = _pFootnote->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( _pFootnote );
1864 0 : pCnt = pNxtCnt;
1865 : } while ( pCnt );
1866 : }
1867 : else
1868 : {
1869 : OSL_ENSURE( !pNxt, "footnote without content?" );
1870 0 : pNxt->Cut();
1871 0 : SwFrm::DestroyFrm(pNxt);
1872 : }
1873 0 : pNxt = _pFootnote->GetFollow();
1874 : }
1875 0 : _pFootnote->Cut();
1876 0 : FootnoteInArr( _rFootnoteArr, _pFootnote );
1877 0 : bFound = true;
1878 : }
1879 : else
1880 : {
1881 0 : FootnoteInArr( aNotFootnoteArr, _pFootnote );
1882 0 : if( bFound )
1883 0 : break;
1884 : }
1885 0 : if ( pNxtFootnote &&
1886 0 : _rFootnoteArr.end() == std::find( _rFootnoteArr.begin(), _rFootnoteArr.end(), pNxtFootnote ) &&
1887 0 : aNotFootnoteArr.end() == std::find( aNotFootnoteArr.begin(), aNotFootnoteArr.end(), pNxtFootnote ) )
1888 0 : _pFootnote = pNxtFootnote;
1889 : else
1890 0 : break;
1891 : }
1892 0 : while ( _pFootnote );
1893 0 : }
1894 :
1895 15 : void SwFootnoteBossFrm::_MoveFootnotes( SwFootnoteFrms &rFootnoteArr, 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 15 : const sal_uInt16 nMyNum = FindPageFrm()->GetPhyPageNum();
1900 15 : const sal_uInt16 nMyCol = lcl_ColumnNum( this );
1901 15 : SWRECTFN( this )
1902 :
1903 : // #i21478# - keep last inserted footnote in order to
1904 : // format the content of the following one.
1905 15 : SwFootnoteFrm* pLastInsertedFootnote = 0L;
1906 30 : for ( size_t i = 0; i < rFootnoteArr.size(); ++i )
1907 : {
1908 15 : SwFootnoteFrm *pFootnote = rFootnoteArr[i];
1909 :
1910 15 : SwFootnoteBossFrm* pRefBoss = pFootnote->GetRef()->FindFootnoteBossFrm( true );
1911 15 : if( pRefBoss != this )
1912 : {
1913 14 : const sal_uInt16 nRefNum = pRefBoss->FindPageFrm()->GetPhyPageNum();
1914 14 : const sal_uInt16 nRefCol = lcl_ColumnNum( this );
1915 14 : if( nRefNum < nMyNum || ( nRefNum == nMyNum && nRefCol <= nMyCol ) )
1916 14 : pRefBoss = this;
1917 : }
1918 15 : pRefBoss->InsertFootnote( pFootnote );
1919 :
1920 15 : if ( pFootnote->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 15 : SwFrm *pCnt = pFootnote->ContainsAny();
1926 50 : while( pCnt )
1927 : {
1928 20 : if( pCnt->IsLayoutFrm() )
1929 : {
1930 0 : SwFrm* pTmp = static_cast<SwLayoutFrm*>(pCnt)->ContainsAny();
1931 0 : while( pTmp && static_cast<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 20 : pCnt->Prepare( PREP_MOVEFTN );
1941 20 : (pCnt->Frm().*fnRect->fnSetHeight)(0);
1942 20 : (pCnt->Prt().*fnRect->fnSetHeight)(0);
1943 20 : pCnt = pCnt->GetNext();
1944 : }
1945 15 : (pFootnote->Frm().*fnRect->fnSetHeight)(0);
1946 15 : (pFootnote->Prt().*fnRect->fnSetHeight)(0);
1947 15 : pFootnote->Calc();
1948 15 : pFootnote->GetUpper()->Calc();
1949 :
1950 15 : if( bCalc )
1951 : {
1952 0 : SwTextFootnote *pAttr = pFootnote->GetAttr();
1953 0 : pCnt = pFootnote->ContainsAny();
1954 0 : bool bUnlock = !pFootnote->IsBackMoveLocked();
1955 0 : pFootnote->LockBackMove();
1956 :
1957 : // #i49383# - disable unlock of position of
1958 : // lower objects during format of footnote content.
1959 0 : pFootnote->KeepLockPosOfLowerObjs();
1960 : // #i57914# - adjust fix #i49383#
1961 :
1962 0 : while ( pCnt && pCnt->FindFootnoteFrm()->GetAttr() == pAttr )
1963 : {
1964 0 : pCnt->_InvalidatePos();
1965 0 : pCnt->Calc();
1966 : // #i49383# - format anchored objects
1967 0 : if ( pCnt->IsTextFrm() && pCnt->IsValid() )
1968 : {
1969 0 : if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt,
1970 0 : *(pCnt->FindPageFrm()) ) )
1971 : {
1972 : // restart format with first content
1973 0 : pCnt = pFootnote->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 = static_cast<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 : pFootnote->UnlockBackMove();
1992 0 : if( !pFootnote->ContainsAny() && !pFootnote->IsColLocked() )
1993 : {
1994 0 : pFootnote->Cut();
1995 0 : SwFrm::DestroyFrm(pFootnote);
1996 : // #i21478#
1997 0 : pFootnote = 0L;
1998 : }
1999 : }
2000 : // #i49383#
2001 0 : if ( pFootnote )
2002 : {
2003 : // #i57914# - adjust fix #i49383#
2004 : // enable lock of lower object position before format of footnote frame.
2005 0 : pFootnote->UnlockPosOfLowerObjs();
2006 0 : pFootnote->Calc();
2007 : }
2008 : }
2009 : }
2010 : else
2011 : { OSL_ENSURE( !pFootnote->GetMaster() && !pFootnote->GetFollow(),
2012 : "DelFootnote and Master/Follow?" );
2013 0 : SwFrm::DestroyFrm(pFootnote);
2014 : // #i21478#
2015 0 : pFootnote = 0L;
2016 : }
2017 :
2018 : // #i21478#
2019 15 : if ( pFootnote )
2020 : {
2021 15 : pLastInsertedFootnote = pFootnote;
2022 : }
2023 : }
2024 :
2025 : // #i21478# - format content of footnote following
2026 : // the new inserted ones.
2027 15 : if ( bCalc && pLastInsertedFootnote )
2028 : {
2029 0 : if ( pLastInsertedFootnote->GetNext() )
2030 : {
2031 0 : SwFootnoteFrm* pNextFootnote = static_cast<SwFootnoteFrm*>(pLastInsertedFootnote->GetNext());
2032 0 : SwTextFootnote* pAttr = pNextFootnote->GetAttr();
2033 0 : SwFrm* pCnt = pNextFootnote->ContainsAny();
2034 :
2035 0 : bool bUnlock = !pNextFootnote->IsBackMoveLocked();
2036 0 : pNextFootnote->LockBackMove();
2037 : // #i49383# - disable unlock of position of
2038 : // lower objects during format of footnote content.
2039 0 : pNextFootnote->KeepLockPosOfLowerObjs();
2040 : // #i57914# - adjust fix #i49383#
2041 :
2042 0 : while ( pCnt && pCnt->FindFootnoteFrm()->GetAttr() == pAttr )
2043 : {
2044 0 : pCnt->_InvalidatePos();
2045 0 : pCnt->Calc();
2046 : // #i49383# - format anchored objects
2047 0 : if ( pCnt->IsTextFrm() && pCnt->IsValid() )
2048 : {
2049 0 : if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt,
2050 0 : *(pCnt->FindPageFrm()) ) )
2051 : {
2052 : // restart format with first content
2053 0 : pCnt = pNextFootnote->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 = static_cast<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 : pNextFootnote->UnlockBackMove();
2072 : }
2073 : // #i49383#
2074 : // #i57914# - adjust fix #i49383#
2075 : // enable lock of lower object position before format of footnote frame.
2076 0 : pNextFootnote->UnlockPosOfLowerObjs();
2077 0 : pNextFootnote->Calc();
2078 : }
2079 : }
2080 15 : }
2081 :
2082 0 : void SwFootnoteBossFrm::MoveFootnotes( const SwContentFrm *pSrc, SwContentFrm *pDest,
2083 : SwTextFootnote *pAttr )
2084 : {
2085 0 : if( ( GetFormat()->GetDoc()->GetFootnoteInfo().ePos == FTNPOS_CHAPTER &&
2086 0 : (!GetUpper()->IsSctFrm() || !static_cast<SwSectionFrm*>(GetUpper())->IsFootnoteAtEnd()))
2087 0 : || pAttr->GetFootnote().IsEndNote() )
2088 0 : return;
2089 :
2090 : OSL_ENSURE( this == pSrc->FindFootnoteBossFrm( true ),
2091 : "SwPageFrm::MoveFootnotes: source frame isn't on that FootnoteBoss" );
2092 :
2093 0 : SwFootnoteFrm *pFootnote = FindFirstFootnote();
2094 0 : if( pFootnote )
2095 : {
2096 0 : ChangeFootnoteRef( pSrc, pAttr, pDest );
2097 0 : SwFootnoteBossFrm *pDestBoss = pDest->FindFootnoteBossFrm( true );
2098 : OSL_ENSURE( pDestBoss, "+SwPageFrm::MoveFootnotes: no destination boss" );
2099 0 : if( pDestBoss ) // robust
2100 : {
2101 0 : SwFootnoteFrms aFootnoteArr;
2102 0 : SwFootnoteBossFrm::_CollectFootnotes( pDest, pFootnote, aFootnoteArr );
2103 0 : if ( !aFootnoteArr.empty() )
2104 : {
2105 0 : pDestBoss->_MoveFootnotes( aFootnoteArr, true );
2106 0 : SwPageFrm* pSrcPage = FindPageFrm();
2107 0 : SwPageFrm* pDestPage = pDestBoss->FindPageFrm();
2108 : // update FootnoteNum only at page change
2109 0 : if( pSrcPage != pDestPage )
2110 : {
2111 0 : if( pSrcPage->GetPhyPageNum() > pDestPage->GetPhyPageNum() )
2112 0 : pSrcPage->UpdateFootnoteNum();
2113 0 : pDestPage->UpdateFootnoteNum();
2114 : }
2115 0 : }
2116 : }
2117 : }
2118 : }
2119 :
2120 87 : void SwFootnoteBossFrm::RearrangeFootnotes( const SwTwips nDeadLine, const bool bLock,
2121 : const SwTextFootnote *pAttr )
2122 : {
2123 : // Format all footnotes of a column/page so that they might change the column/page.
2124 :
2125 87 : SwSaveFootnoteHeight aSave( this, nDeadLine );
2126 87 : SwFootnoteFrm *pFootnote = FindFirstFootnote();
2127 87 : if( pFootnote && pFootnote->GetPrev() && bLock )
2128 : {
2129 0 : SwFootnoteFrm* pFirst = static_cast<SwFootnoteFrm*>(pFootnote->GetUpper()->Lower());
2130 0 : SwFrm* pContent = pFirst->ContainsAny();
2131 0 : if( pContent )
2132 : {
2133 0 : bool bUnlock = !pFirst->IsBackMoveLocked();
2134 0 : pFirst->LockBackMove();
2135 0 : pFirst->Calc();
2136 0 : pContent->Calc();
2137 : // #i49383# - format anchored objects
2138 0 : if ( pContent->IsTextFrm() && pContent->IsValid() )
2139 : {
2140 : SwObjectFormatter::FormatObjsAtFrm( *pContent,
2141 0 : *(pContent->FindPageFrm()) );
2142 : }
2143 0 : if( bUnlock )
2144 0 : pFirst->UnlockBackMove();
2145 : }
2146 0 : pFootnote = FindFirstFootnote();
2147 : }
2148 87 : SwDoc *pDoc = GetFormat()->GetDoc();
2149 87 : const sal_uLong nFootnotePos = pAttr ? ::lcl_FindFootnotePos( pDoc, pAttr ) : 0;
2150 87 : SwFrm *pCnt = pFootnote ? pFootnote->ContainsAny() : 0;
2151 87 : if ( pCnt )
2152 : {
2153 87 : bool bMore = true;
2154 87 : 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 87 : SwFootnoteFrm* pLastFootnoteFrm( 0L );
2158 : // footnote frame needs to be locked, if <bLock> isn't set.
2159 87 : bool bUnlockLastFootnoteFrm( false );
2160 146 : do
2161 : {
2162 146 : if( !bStart )
2163 20 : bStart = ::lcl_FindFootnotePos( pDoc, pCnt->FindFootnoteFrm()->GetAttr() )
2164 20 : == nFootnotePos;
2165 146 : if( bStart )
2166 : {
2167 141 : pCnt->_InvalidatePos();
2168 141 : pCnt->_InvalidateSize();
2169 141 : pCnt->Prepare( PREP_ADJUST_FRM );
2170 141 : SwFootnoteFrm* pFootnoteFrm = pCnt->FindFootnoteFrm();
2171 : // #i49383#
2172 141 : if ( pFootnoteFrm != pLastFootnoteFrm )
2173 : {
2174 112 : if ( pLastFootnoteFrm )
2175 : {
2176 25 : if ( !bLock && bUnlockLastFootnoteFrm )
2177 : {
2178 0 : pLastFootnoteFrm->ColUnlock();
2179 : }
2180 : // #i57914# - adjust fix #i49383#
2181 : // enable lock of lower object position before format of footnote frame.
2182 25 : pLastFootnoteFrm->UnlockPosOfLowerObjs();
2183 25 : pLastFootnoteFrm->Calc();
2184 50 : if ( !bLock && bUnlockLastFootnoteFrm &&
2185 0 : !pLastFootnoteFrm->GetLower() &&
2186 25 : !pLastFootnoteFrm->IsColLocked() &&
2187 0 : !pLastFootnoteFrm->IsBackMoveLocked() )
2188 : {
2189 0 : pLastFootnoteFrm->Cut();
2190 0 : SwFrm::DestroyFrm(pLastFootnoteFrm);
2191 0 : pLastFootnoteFrm = 0L;
2192 : }
2193 : }
2194 112 : if ( !bLock )
2195 : {
2196 15 : bUnlockLastFootnoteFrm = !pFootnoteFrm->IsColLocked();
2197 15 : pFootnoteFrm->ColLock();
2198 : }
2199 112 : pFootnoteFrm->KeepLockPosOfLowerObjs();
2200 112 : pLastFootnoteFrm = pFootnoteFrm;
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 141 : SWRECTFN( this );
2208 141 : SwFrm* aFootnoteContFrm = pFootnoteFrm->GetUpper();
2209 141 : if ( (pFootnoteFrm->Frm().*fnRect->fnTopDist)((aFootnoteContFrm->*fnRect->fnGetPrtBottom)()) > 0 )
2210 : {
2211 0 : pFootnoteFrm->_InvalidatePos();
2212 : }
2213 : }
2214 141 : if ( bLock )
2215 : {
2216 108 : bool bUnlock = !pFootnoteFrm->IsBackMoveLocked();
2217 108 : pFootnoteFrm->LockBackMove();
2218 108 : pFootnoteFrm->Calc();
2219 108 : pCnt->Calc();
2220 : // #i49383# - format anchored objects
2221 108 : if ( pCnt->IsTextFrm() && pCnt->IsValid() )
2222 : {
2223 108 : if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt,
2224 108 : *(pCnt->FindPageFrm()) ) )
2225 : {
2226 : // restart format with first content
2227 0 : pCnt = pFootnote->ContainsAny();
2228 0 : continue;
2229 : }
2230 : }
2231 108 : if( bUnlock )
2232 : {
2233 108 : pFootnoteFrm->UnlockBackMove();
2234 108 : if( !pFootnoteFrm->Lower() &&
2235 0 : !pFootnoteFrm->IsColLocked() )
2236 : {
2237 : // #i49383#
2238 : OSL_ENSURE( pLastFootnoteFrm == pFootnoteFrm,
2239 : "<SwFootnoteBossFrm::RearrangeFootnotes(..)> - <pLastFootnoteFrm> != <pFootnoteFrm>" );
2240 0 : pLastFootnoteFrm = 0L;
2241 0 : pFootnoteFrm->Cut();
2242 0 : SwFrm::DestroyFrm(pFootnoteFrm);
2243 : }
2244 : }
2245 : }
2246 : else
2247 : {
2248 33 : pFootnoteFrm->Calc();
2249 33 : pCnt->Calc();
2250 : // #i49383# - format anchored objects
2251 33 : if ( pCnt->IsTextFrm() && pCnt->IsValid() )
2252 : {
2253 29 : if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt,
2254 29 : *(pCnt->FindPageFrm()) ) )
2255 : {
2256 : // restart format with first content
2257 0 : pCnt = pFootnote->ContainsAny();
2258 0 : continue;
2259 : }
2260 : }
2261 : }
2262 : }
2263 146 : SwSectionFrm *pDel = NULL;
2264 146 : if( pCnt->IsSctFrm() )
2265 : {
2266 4 : SwFrm* pTmp = static_cast<SwSectionFrm*>(pCnt)->ContainsAny();
2267 4 : if( pTmp )
2268 : {
2269 4 : pCnt = pTmp;
2270 4 : continue;
2271 : }
2272 0 : pDel = static_cast<SwSectionFrm*>(pCnt);
2273 : }
2274 142 : if ( pCnt->GetNext() )
2275 21 : pCnt = pCnt->GetNext();
2276 : else
2277 : {
2278 121 : pCnt = pCnt->FindNext();
2279 121 : if ( pCnt )
2280 : {
2281 37 : SwFootnoteFrm* pFootnoteFrm = pCnt->FindFootnoteFrm();
2282 74 : if( pFootnoteFrm->GetRef()->FindFootnoteBossFrm(
2283 74 : pFootnoteFrm->GetAttr()->GetFootnote().IsEndNote() ) != this )
2284 0 : bMore = false;
2285 : }
2286 : else
2287 84 : bMore = false;
2288 : }
2289 142 : if( pDel )
2290 : {
2291 0 : bool bUnlockLastFootnoteFrmGuard = pLastFootnoteFrm && !pLastFootnoteFrm->IsColLocked();
2292 0 : if (bUnlockLastFootnoteFrmGuard)
2293 0 : pLastFootnoteFrm->ColLock();
2294 0 : pDel->Cut();
2295 0 : if (bUnlockLastFootnoteFrmGuard)
2296 0 : pLastFootnoteFrm->ColUnlock();
2297 0 : SwFrm::DestroyFrm(pDel);
2298 : }
2299 142 : if ( bMore )
2300 : {
2301 : // Go not further than to the provided footnote (if given)
2302 80 : if ( pAttr &&
2303 : (::lcl_FindFootnotePos( pDoc,
2304 22 : pCnt->FindFootnoteFrm()->GetAttr()) > nFootnotePos ) )
2305 3 : bMore = false;
2306 : }
2307 : } while ( bMore );
2308 : // #i49383#
2309 87 : if ( pLastFootnoteFrm )
2310 : {
2311 87 : if ( !bLock && bUnlockLastFootnoteFrm )
2312 : {
2313 15 : pLastFootnoteFrm->ColUnlock();
2314 : }
2315 : // #i57914# - adjust fix #i49383#
2316 : // enable lock of lower object position before format of footnote frame.
2317 87 : pLastFootnoteFrm->UnlockPosOfLowerObjs();
2318 87 : pLastFootnoteFrm->Calc();
2319 204 : if ( !bLock && bUnlockLastFootnoteFrm &&
2320 15 : !pLastFootnoteFrm->GetLower() &&
2321 87 : !pLastFootnoteFrm->IsColLocked() &&
2322 0 : !pLastFootnoteFrm->IsBackMoveLocked() )
2323 : {
2324 0 : pLastFootnoteFrm->Cut();
2325 0 : SwFrm::DestroyFrm(pLastFootnoteFrm);
2326 : }
2327 : }
2328 87 : }
2329 87 : }
2330 :
2331 105 : void SwPageFrm::UpdateFootnoteNum()
2332 : {
2333 : // page numbering only if set at the document
2334 105 : if ( GetFormat()->GetDoc()->GetFootnoteInfo().eNum != FTNNUM_PAGE )
2335 105 : return;
2336 :
2337 0 : SwLayoutFrm* pBody = FindBodyCont();
2338 0 : if( !pBody || !pBody->Lower() )
2339 0 : return;
2340 :
2341 0 : SwContentFrm* pContent = pBody->ContainsContent();
2342 0 : sal_uInt16 nNum = 0;
2343 :
2344 0 : while( pContent && pContent->FindPageFrm() == this )
2345 : {
2346 0 : if( static_cast<SwTextFrm*>(pContent)->HasFootnote() )
2347 : {
2348 0 : SwFootnoteBossFrm* pBoss = pContent->FindFootnoteBossFrm( true );
2349 0 : if( pBoss->GetUpper()->IsSctFrm() &&
2350 0 : static_cast<SwSectionFrm*>(pBoss->GetUpper())->IsOwnFootnoteNum() )
2351 0 : pContent = static_cast<SwSectionFrm*>(pBoss->GetUpper())->FindLastContent();
2352 : else
2353 : {
2354 0 : SwFootnoteFrm* pFootnote = const_cast<SwFootnoteFrm*>(pBoss->FindFirstFootnote( pContent ));
2355 0 : while( pFootnote )
2356 : {
2357 0 : SwTextFootnote* pTextFootnote = pFootnote->GetAttr();
2358 0 : if( !pTextFootnote->GetFootnote().IsEndNote() &&
2359 0 : pTextFootnote->GetFootnote().GetNumStr().isEmpty() &&
2360 0 : !pFootnote->GetMaster() &&
2361 0 : (pTextFootnote->GetFootnote().GetNumber() != ++nNum) )
2362 : {
2363 0 : pTextFootnote->SetNumber( nNum, OUString() );
2364 : }
2365 0 : if ( pFootnote->GetNext() )
2366 0 : pFootnote = static_cast<SwFootnoteFrm*>(pFootnote->GetNext());
2367 : else
2368 : {
2369 0 : SwFootnoteBossFrm* pTmpBoss = pFootnote->FindFootnoteBossFrm( true );
2370 0 : if( pTmpBoss )
2371 : {
2372 0 : SwPageFrm* pPage = pTmpBoss->FindPageFrm();
2373 0 : pFootnote = NULL;
2374 0 : lcl_NextFootnoteBoss( pTmpBoss, pPage, false );
2375 0 : SwFootnoteContFrm *pCont = pTmpBoss ? pTmpBoss->FindNearestFootnoteCont() : NULL;
2376 0 : if ( pCont )
2377 0 : pFootnote = static_cast<SwFootnoteFrm*>(pCont->Lower());
2378 : }
2379 : }
2380 0 : if( pFootnote && pFootnote->GetRef() != pContent )
2381 0 : pFootnote = NULL;
2382 : }
2383 : }
2384 : }
2385 0 : pContent = pContent->FindNextCnt();
2386 : }
2387 : }
2388 :
2389 3589 : void SwFootnoteBossFrm::SetFootnoteDeadLine( const SwTwips nDeadLine )
2390 : {
2391 3589 : SwFrm *pBody = FindBodyCont();
2392 3589 : pBody->Calc();
2393 :
2394 3589 : SwFrm *pCont = FindFootnoteCont();
2395 3589 : const SwTwips nMax = nMaxFootnoteHeight;// current should exceed MaxHeight
2396 3589 : SWRECTFN( this )
2397 3589 : if ( pCont )
2398 : {
2399 430 : pCont->Calc();
2400 430 : nMaxFootnoteHeight = -(pCont->Frm().*fnRect->fnBottomDist)( nDeadLine );
2401 : }
2402 : else
2403 3159 : nMaxFootnoteHeight = -(pBody->Frm().*fnRect->fnBottomDist)( nDeadLine );
2404 :
2405 3589 : const SwViewShell *pSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0;
2406 3589 : if( pSh && pSh->GetViewOptions()->getBrowseMode() )
2407 0 : nMaxFootnoteHeight += pBody->Grow( LONG_MAX, true );
2408 3589 : if ( IsInSct() )
2409 1657 : nMaxFootnoteHeight += FindSctFrm()->Grow( LONG_MAX, true );
2410 :
2411 3589 : if ( nMaxFootnoteHeight < 0 )
2412 1827 : nMaxFootnoteHeight = 0;
2413 3589 : if ( nMax != LONG_MAX && nMaxFootnoteHeight > nMax )
2414 26 : nMaxFootnoteHeight = nMax;
2415 3589 : }
2416 :
2417 3847 : SwTwips SwFootnoteBossFrm::GetVarSpace() const
2418 : {
2419 : // To not fall below 20% of the page height
2420 : // (in contrast to MSOffice where footnotes can fill a whole column/page)
2421 :
2422 3847 : const SwPageFrm* pPg = FindPageFrm();
2423 : OSL_ENSURE( pPg || IsInSct(), "Footnote lost page" );
2424 :
2425 3847 : const SwFrm *pBody = FindBodyCont();
2426 : SwTwips nRet;
2427 3847 : if( pBody )
2428 : {
2429 3847 : SWRECTFN( this )
2430 3847 : if( IsInSct() )
2431 : {
2432 145 : nRet = 0;
2433 290 : SwTwips nTmp = (*fnRect->fnYDiff)( (pBody->*fnRect->fnGetPrtTop)(),
2434 435 : (Frm().*fnRect->fnGetTop)() );
2435 145 : const SwSectionFrm* pSect = FindSctFrm();
2436 : // Endnotes in a ftncontainer causes a deadline:
2437 : // the bottom of the last contentfrm
2438 145 : if( pSect->IsEndnAtEnd() ) // endnotes allowed?
2439 : {
2440 : OSL_ENSURE( !Lower() || !Lower()->GetNext() || Lower()->GetNext()->
2441 : IsFootnoteContFrm(), "FootnoteContainer expected" );
2442 128 : const SwFootnoteContFrm* pCont = Lower() ?
2443 128 : static_cast<const SwFootnoteContFrm*>(Lower()->GetNext()) : 0;
2444 128 : if( pCont )
2445 : {
2446 128 : const SwFootnoteFrm* pFootnote = static_cast<const SwFootnoteFrm*>(pCont->Lower());
2447 266 : while( pFootnote)
2448 : {
2449 116 : if( pFootnote->GetAttr()->GetFootnote().IsEndNote() )
2450 : { // endnote found
2451 106 : const SwFrm* pFrm = static_cast<const SwLayoutFrm*>(Lower())->Lower();
2452 106 : if( pFrm )
2453 : {
2454 204 : while( pFrm->GetNext() )
2455 0 : pFrm = pFrm->GetNext(); // last cntntfrm
2456 : nTmp += (*fnRect->fnYDiff)(
2457 204 : (Frm().*fnRect->fnGetTop)(),
2458 306 : (pFrm->Frm().*fnRect->fnGetBottom)() );
2459 : }
2460 106 : break;
2461 : }
2462 10 : pFootnote = static_cast<const SwFootnoteFrm*>(pFootnote->GetNext());
2463 : }
2464 : }
2465 : }
2466 145 : if( nTmp < nRet )
2467 102 : nRet = nTmp;
2468 : }
2469 : else
2470 3702 : nRet = - (pPg->Prt().*fnRect->fnGetHeight)()/5;
2471 3847 : nRet += (pBody->Frm().*fnRect->fnGetHeight)();
2472 3847 : if( nRet < 0 )
2473 1 : nRet = 0;
2474 : }
2475 : else
2476 0 : nRet = 0;
2477 3847 : if ( IsPageFrm() )
2478 : {
2479 3702 : const SwViewShell *pSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0;
2480 3702 : if( pSh && pSh->GetViewOptions()->getBrowseMode() )
2481 0 : nRet += BROWSE_HEIGHT - Frm().Height();
2482 : }
2483 3847 : return nRet;
2484 : }
2485 :
2486 : /** Obtain if pFrm's size adjustment should be processed
2487 : *
2488 : * For a page frame of columns directly below the page AdjustNeighbourhood() needs
2489 : * to be called, or Grow()/ Shrink() for frame columns respectively.
2490 : *
2491 : * A column section is special, since if there is a footnote container in a column
2492 : * and those footnotes are not collected, it is handled like a page frame.
2493 : *
2494 : * @see AdjustNeighbourhood()
2495 : * @see Grow()
2496 : * @see Shrink()
2497 : */
2498 6887 : sal_uInt8 SwFootnoteBossFrm::_NeighbourhoodAdjustment( const SwFrm* ) const
2499 : {
2500 6887 : sal_uInt8 nRet = NA_ONLY_ADJUST;
2501 6887 : if( GetUpper() && !GetUpper()->IsPageBodyFrm() )
2502 : {
2503 : // column sections need grow/shrink
2504 6859 : if( GetUpper()->IsFlyFrm() )
2505 0 : nRet = NA_GROW_SHRINK;
2506 : else
2507 : {
2508 : OSL_ENSURE( GetUpper()->IsSctFrm(), "NeighbourhoodAdjustment: Unexpected Upper" );
2509 6859 : if( !GetNext() && !GetPrev() )
2510 0 : nRet = NA_GROW_ADJUST; // section with a single column (FootnoteAtEnd)
2511 : else
2512 : {
2513 6859 : const SwFrm* pTmp = Lower();
2514 : OSL_ENSURE( pTmp, "NeighbourhoodAdjustment: Missing Lower()" );
2515 6859 : if( !pTmp->GetNext() )
2516 6653 : nRet = NA_GROW_SHRINK;
2517 206 : else if( !GetUpper()->IsColLocked() )
2518 29 : nRet = NA_ADJUST_GROW;
2519 : OSL_ENSURE( !pTmp->GetNext() || pTmp->GetNext()->IsFootnoteContFrm(),
2520 : "NeighbourhoodAdjustment: Who's that guy?" );
2521 : }
2522 : }
2523 : }
2524 6887 : return nRet;
2525 : }
2526 :
2527 2 : void SwPageFrm::SetColMaxFootnoteHeight()
2528 : {
2529 2 : SwLayoutFrm *pBody = FindBodyCont();
2530 2 : if( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrm() )
2531 : {
2532 0 : SwColumnFrm* pCol = static_cast<SwColumnFrm*>(pBody->Lower());
2533 0 : do
2534 : {
2535 0 : pCol->SetMaxFootnoteHeight( GetMaxFootnoteHeight() );
2536 0 : pCol = static_cast<SwColumnFrm*>(pCol->GetNext());
2537 : } while ( pCol );
2538 : }
2539 2 : }
2540 :
2541 1953 : bool SwLayoutFrm::MoveLowerFootnotes( SwContentFrm *pStart, SwFootnoteBossFrm *pOldBoss,
2542 : SwFootnoteBossFrm *pNewBoss, const bool bFootnoteNums )
2543 : {
2544 1953 : SwDoc *pDoc = GetFormat()->GetDoc();
2545 1953 : if ( pDoc->GetFootnoteIdxs().empty() )
2546 1925 : return false;
2547 28 : if( pDoc->GetFootnoteInfo().ePos == FTNPOS_CHAPTER &&
2548 0 : ( !IsInSct() || !FindSctFrm()->IsFootnoteAtEnd() ) )
2549 0 : return true;
2550 :
2551 28 : if ( !pNewBoss )
2552 0 : pNewBoss = FindFootnoteBossFrm( true );
2553 28 : if ( pNewBoss == pOldBoss )
2554 0 : return false;
2555 :
2556 28 : bool bMoved = false;
2557 28 : if( !pStart )
2558 0 : pStart = ContainsContent();
2559 :
2560 28 : SwFootnoteFrms aFootnoteArr;
2561 :
2562 1006 : while ( IsAnLower( pStart ) )
2563 : {
2564 950 : if ( static_cast<SwTextFrm*>(pStart)->HasFootnote() )
2565 : {
2566 : // OD 03.04.2003 #108446# - To avoid unnecessary moves of footnotes
2567 : // use new parameter <_bCollectOnlyPreviousFootnote> (4th parameter of
2568 : // method <SwFootnoteBossFrm::CollectFootnote(..)>) to control, that only
2569 : // footnotes have to be collected, that are positioned before the
2570 : // new dedicated footnote boss frame.
2571 0 : pNewBoss->CollectFootnotes( pStart, pOldBoss, aFootnoteArr, true );
2572 : }
2573 950 : pStart = pStart->GetNextContentFrm();
2574 : }
2575 :
2576 : OSL_ENSURE( pOldBoss->IsInSct() == pNewBoss->IsInSct(),
2577 : "MoveLowerFootnotes: Section confusion" );
2578 : SwFootnoteFrms *pFootnoteArr;
2579 28 : SwLayoutFrm* pNewChief = 0;
2580 28 : SwLayoutFrm* pOldChief = 0;
2581 :
2582 28 : bool bFoundCandidate = false;
2583 28 : if (pStart && pOldBoss->IsInSct())
2584 : {
2585 13 : pOldChief = pOldBoss->FindSctFrm();
2586 13 : pNewChief = pNewBoss->FindSctFrm();
2587 13 : bFoundCandidate = pOldChief != pNewChief;
2588 : }
2589 :
2590 28 : if (bFoundCandidate)
2591 : {
2592 4 : pFootnoteArr = new SwFootnoteFrms;
2593 4 : pOldChief = pOldBoss->FindFootnoteBossFrm( true );
2594 4 : pNewChief = pNewBoss->FindFootnoteBossFrm( true );
2595 10 : while( pOldChief->IsAnLower( pStart ) )
2596 : {
2597 2 : if ( static_cast<SwTextFrm*>(pStart)->HasFootnote() )
2598 : static_cast<SwFootnoteBossFrm*>(pNewChief)->CollectFootnotes( pStart,
2599 0 : pOldBoss, *pFootnoteArr );
2600 2 : pStart = pStart->GetNextContentFrm();
2601 : }
2602 4 : if( pFootnoteArr->empty() )
2603 : {
2604 4 : delete pFootnoteArr;
2605 4 : pFootnoteArr = NULL;
2606 : }
2607 : }
2608 : else
2609 24 : pFootnoteArr = NULL;
2610 :
2611 28 : if ( !aFootnoteArr.empty() || pFootnoteArr )
2612 : {
2613 0 : if( !aFootnoteArr.empty() )
2614 0 : pNewBoss->_MoveFootnotes( aFootnoteArr, true );
2615 0 : if( pFootnoteArr )
2616 : {
2617 0 : static_cast<SwFootnoteBossFrm*>(pNewChief)->_MoveFootnotes( *pFootnoteArr, true );
2618 0 : delete pFootnoteArr;
2619 : }
2620 0 : bMoved = true;
2621 :
2622 : // update FootnoteNum only at page change
2623 0 : if ( bFootnoteNums )
2624 : {
2625 0 : SwPageFrm* pOldPage = pOldBoss->FindPageFrm();
2626 0 : SwPageFrm* pNewPage =pNewBoss->FindPageFrm();
2627 0 : if( pOldPage != pNewPage )
2628 : {
2629 0 : pOldPage->UpdateFootnoteNum();
2630 0 : pNewPage->UpdateFootnoteNum();
2631 : }
2632 : }
2633 : }
2634 28 : return bMoved;
2635 : }
2636 :
2637 12 : bool SwContentFrm::MoveFootnoteCntFwd( bool bMakePage, SwFootnoteBossFrm *pOldBoss )
2638 : {
2639 : OSL_ENSURE( IsInFootnote(), "no footnote." );
2640 12 : SwLayoutFrm *pFootnote = FindFootnoteFrm();
2641 :
2642 : // The first paragraph in the first footnote in the first column in the
2643 : // sectionfrm at the top of the page has not to move forward, if the
2644 : // columnbody is empty.
2645 12 : if( pOldBoss->IsInSct() && !pOldBoss->GetIndPrev() && !GetIndPrev() &&
2646 0 : !pFootnote->GetPrev() )
2647 : {
2648 0 : SwLayoutFrm* pBody = pOldBoss->FindBodyCont();
2649 0 : if( !pBody || !pBody->Lower() )
2650 0 : return true;
2651 : }
2652 :
2653 : //fix(9538): if the footnote has neighbors behind itself, remove them temporarily
2654 12 : SwLayoutFrm *pNxt = static_cast<SwLayoutFrm*>(pFootnote->GetNext());
2655 12 : SwLayoutFrm *pLst = 0;
2656 24 : while ( pNxt )
2657 : {
2658 0 : while ( pNxt->GetNext() )
2659 0 : pNxt = static_cast<SwLayoutFrm*>(pNxt->GetNext());
2660 0 : if ( pNxt == pLst )
2661 0 : pNxt = 0;
2662 : else
2663 0 : { pLst = pNxt;
2664 0 : SwContentFrm *pCnt = pNxt->ContainsContent();
2665 0 : if( pCnt )
2666 0 : pCnt->MoveFootnoteCntFwd( true, pOldBoss );
2667 0 : pNxt = static_cast<SwLayoutFrm*>(pFootnote->GetNext());
2668 : }
2669 : }
2670 :
2671 12 : bool bSamePage = true;
2672 : SwLayoutFrm *pNewUpper =
2673 12 : GetLeaf( bMakePage ? MAKEPAGE_INSERT : MAKEPAGE_NONE, true );
2674 :
2675 12 : if ( pNewUpper )
2676 : {
2677 12 : bool bSameBoss = true;
2678 12 : SwFootnoteBossFrm * const pNewBoss = pNewUpper->FindFootnoteBossFrm();
2679 : // Are we changing the column/page?
2680 12 : if ( !( bSameBoss = (pNewBoss == pOldBoss) ) )
2681 : {
2682 12 : bSamePage = pOldBoss->FindPageFrm() == pNewBoss->FindPageFrm(); // page change?
2683 12 : pNewUpper->Calc();
2684 : }
2685 :
2686 : // The layout leaf of the footnote is either a footnote container or a footnote.
2687 : // If it is a footnote and it has the same footnote reference like the old Upper,
2688 : // then move the content inside of it.
2689 : // If it is a container or the reference differs, create a new footnote and add
2690 : // it into the container.
2691 : // Create also a SectionFrame if currently in a area inside a footnote.
2692 12 : SwFootnoteFrm* pTmpFootnote = pNewUpper->IsFootnoteFrm() ? static_cast<SwFootnoteFrm*>(pNewUpper) : 0;
2693 12 : if( !pTmpFootnote )
2694 : {
2695 : OSL_ENSURE( pNewUpper->IsFootnoteContFrm(), "New Upper not a FootnoteCont.");
2696 9 : SwFootnoteContFrm *pCont = static_cast<SwFootnoteContFrm*>(pNewUpper);
2697 :
2698 : // create footnote
2699 9 : SwFootnoteFrm *pOld = FindFootnoteFrm();
2700 9 : pTmpFootnote = new SwFootnoteFrm( pOld->GetFormat()->GetDoc()->GetDfltFrameFormat(),
2701 9 : pOld, pOld->GetRef(), pOld->GetAttr() );
2702 : // chaining of footnotes
2703 9 : if ( pOld->GetFollow() )
2704 : {
2705 0 : pTmpFootnote->SetFollow( pOld->GetFollow() );
2706 0 : pOld->GetFollow()->SetMaster( pTmpFootnote );
2707 : }
2708 9 : pOld->SetFollow( pTmpFootnote );
2709 9 : pTmpFootnote->SetMaster( pOld );
2710 9 : SwFrm* pNx = pCont->Lower();
2711 9 : if( pNx && pTmpFootnote->GetAttr()->GetFootnote().IsEndNote() )
2712 0 : while(pNx && !static_cast<SwFootnoteFrm*>(pNx)->GetAttr()->GetFootnote().IsEndNote())
2713 0 : pNx = pNx->GetNext();
2714 9 : pTmpFootnote->Paste( pCont, pNx );
2715 9 : pTmpFootnote->Calc();
2716 : }
2717 : OSL_ENSURE( pTmpFootnote->GetAttr() == FindFootnoteFrm()->GetAttr(), "Wrong Footnote!" );
2718 : // areas inside of footnotes get a special treatment
2719 12 : SwLayoutFrm *pNewUp = pTmpFootnote;
2720 12 : if( IsInSct() )
2721 : {
2722 12 : SwSectionFrm* pSect = FindSctFrm();
2723 : // area inside of a footnote (or only footnote in an area)?
2724 12 : if( pSect->IsInFootnote() )
2725 : {
2726 10 : if( pTmpFootnote->Lower() && pTmpFootnote->Lower()->IsSctFrm() &&
2727 3 : pSect->GetFollow() == static_cast<SwSectionFrm*>(pTmpFootnote->Lower()) )
2728 1 : pNewUp = static_cast<SwSectionFrm*>(pTmpFootnote->Lower());
2729 : else
2730 : {
2731 6 : pNewUp = new SwSectionFrm( *pSect, false );
2732 6 : pNewUp->InsertBefore( pTmpFootnote, pTmpFootnote->Lower() );
2733 6 : static_cast<SwSectionFrm*>(pNewUp)->Init();
2734 6 : pNewUp->Frm().Pos() = pTmpFootnote->Frm().Pos();
2735 6 : pNewUp->Frm().Pos().Y() += 1; // for notifications
2736 :
2737 : // If the section frame has a successor then the latter needs
2738 : // to be moved behind the new Follow of the section frame.
2739 6 : SwFrm* pTmp = pSect->GetNext();
2740 6 : if( pTmp )
2741 : {
2742 : SwFlowFrm* pTmpNxt;
2743 6 : if( pTmp->IsContentFrm() )
2744 5 : pTmpNxt = static_cast<SwContentFrm*>(pTmp);
2745 1 : else if( pTmp->IsSctFrm() )
2746 1 : pTmpNxt = static_cast<SwSectionFrm*>(pTmp);
2747 : else
2748 : {
2749 : OSL_ENSURE( pTmp->IsTabFrm(), "GetNextSctLeaf: Wrong Type" );
2750 0 : pTmpNxt = static_cast<SwTabFrm*>(pTmp);
2751 : }
2752 6 : pTmpNxt->MoveSubTree( pTmpFootnote, pNewUp->GetNext() );
2753 : }
2754 : }
2755 : }
2756 : }
2757 :
2758 12 : MoveSubTree( pNewUp, pNewUp->Lower() );
2759 :
2760 12 : if( !bSameBoss )
2761 12 : Prepare( PREP_BOSS_CHGD );
2762 : }
2763 12 : return bSamePage;
2764 : }
2765 :
2766 3589 : SwSaveFootnoteHeight::SwSaveFootnoteHeight( SwFootnoteBossFrm *pBs, const SwTwips nDeadLine ) :
2767 : pBoss( pBs ),
2768 3589 : nOldHeight( pBs->GetMaxFootnoteHeight() )
2769 : {
2770 3589 : pBoss->SetFootnoteDeadLine( nDeadLine );
2771 3589 : nNewHeight = pBoss->GetMaxFootnoteHeight();
2772 3589 : }
2773 :
2774 3589 : SwSaveFootnoteHeight::~SwSaveFootnoteHeight()
2775 : {
2776 : // If somebody tweaked the deadline meanwhile, we let it happen
2777 3589 : if ( nNewHeight == pBoss->GetMaxFootnoteHeight() )
2778 3589 : pBoss->nMaxFootnoteHeight = nOldHeight;
2779 3589 : }
2780 :
2781 : #ifdef DBG_UTIL
2782 : //JP 15.10.2001: in a non pro version test if the attribute has the same
2783 : // meaning which his reference is
2784 :
2785 : // Normally, the pRef member and the GetRefFromAttr() result has to be
2786 : // identically. Sometimes footnote will be moved from a master to its follow,
2787 : // but the GetRef() is called first, so we have to ignore a master/follow
2788 : // mismatch.
2789 :
2790 : const SwContentFrm* SwFootnoteFrm::GetRef() const
2791 : {
2792 : const SwContentFrm* pRefAttr = GetRefFromAttr();
2793 : SAL_WARN_IF( pRef != pRefAttr && !pRef->IsAnFollow( pRefAttr )
2794 : && !pRefAttr->IsAnFollow( pRef ),
2795 : "sw", "access to deleted Frame? pRef != pAttr->GetRef()" );
2796 : return pRef;
2797 : }
2798 :
2799 : SwContentFrm* SwFootnoteFrm::GetRef()
2800 : {
2801 : const SwContentFrm* pRefAttr = GetRefFromAttr();
2802 : SAL_WARN_IF( pRef != pRefAttr && !pRef->IsAnFollow( pRefAttr )
2803 : && !pRefAttr->IsAnFollow( pRef ),
2804 : "sw", "access to deleted Frame? pRef != pAttr->GetRef()" );
2805 : return pRef;
2806 : }
2807 : #endif
2808 :
2809 0 : const SwContentFrm* SwFootnoteFrm::GetRefFromAttr() const
2810 : {
2811 0 : SwFootnoteFrm* pThis = const_cast<SwFootnoteFrm*>(this);
2812 0 : return pThis->GetRefFromAttr();
2813 : }
2814 :
2815 3 : SwContentFrm* SwFootnoteFrm::GetRefFromAttr()
2816 : {
2817 : assert(pAttr && "invalid Attribute");
2818 3 : SwTextNode& rTNd = (SwTextNode&)pAttr->GetTextNode();
2819 3 : SwPosition aPos( rTNd, SwIndex( &rTNd, pAttr->GetStart() ));
2820 3 : SwContentFrm* pCFrm = rTNd.getLayoutFrm( getRootFrm(), 0, &aPos, false );
2821 3 : return pCFrm;
2822 : }
2823 :
2824 : /** search for last content in the current footnote frame
2825 :
2826 : OD 2005-12-02 #i27138#
2827 : */
2828 0 : SwContentFrm* SwFootnoteFrm::FindLastContent()
2829 : {
2830 0 : SwContentFrm* pLastContentFrm( 0L );
2831 :
2832 : // find last lower, which is a content frame or contains content.
2833 : // hidden text frames, empty sections and empty tables have to be skipped.
2834 0 : SwFrm* pLastLowerOfFootnote( GetLower() );
2835 0 : SwFrm* pTmpLastLower( pLastLowerOfFootnote );
2836 0 : while ( pTmpLastLower && pTmpLastLower->GetNext() )
2837 : {
2838 0 : pTmpLastLower = pTmpLastLower->GetNext();
2839 0 : if ( ( pTmpLastLower->IsTextFrm() &&
2840 0 : !static_cast<SwTextFrm*>(pTmpLastLower)->IsHiddenNow() ) ||
2841 0 : ( pTmpLastLower->IsSctFrm() &&
2842 0 : static_cast<SwSectionFrm*>(pTmpLastLower)->GetSection() &&
2843 0 : static_cast<SwSectionFrm*>(pTmpLastLower)->ContainsContent() ) ||
2844 0 : ( pTmpLastLower->IsTabFrm() &&
2845 0 : static_cast<SwTabFrm*>(pTmpLastLower)->ContainsContent() ) )
2846 : {
2847 0 : pLastLowerOfFootnote = pTmpLastLower;
2848 : }
2849 : }
2850 :
2851 : // determine last content frame depending on type of found last lower.
2852 0 : if ( pLastLowerOfFootnote && pLastLowerOfFootnote->IsTabFrm() )
2853 : {
2854 0 : pLastContentFrm = static_cast<SwTabFrm*>(pLastLowerOfFootnote)->FindLastContent();
2855 : }
2856 0 : else if ( pLastLowerOfFootnote && pLastLowerOfFootnote->IsSctFrm() )
2857 : {
2858 0 : pLastContentFrm = static_cast<SwSectionFrm*>(pLastLowerOfFootnote)->FindLastContent();
2859 : }
2860 : else
2861 : {
2862 0 : pLastContentFrm = dynamic_cast<SwContentFrm*>(pLastLowerOfFootnote);
2863 : }
2864 :
2865 0 : return pLastContentFrm;
2866 177 : }
2867 :
2868 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|