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