xref: /AOO41X/main/sw/source/core/layout/ftnfrm.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 
31 
32 #include <txtftn.hxx>
33 #include <fmtftn.hxx>
34 #include <ftnidx.hxx>
35 #include <pagefrm.hxx>
36 #include <colfrm.hxx>
37 #include <rootfrm.hxx>
38 #include <cntfrm.hxx>
39 #include <doc.hxx>
40 #include <ndtxt.hxx>
41 #include <frmtool.hxx>
42 #include <swtable.hxx>
43 #include <ftnfrm.hxx>
44 #include <txtfrm.hxx>
45 #include <tabfrm.hxx>
46 #include <pagedesc.hxx>
47 #include <ftninfo.hxx>
48 #include <ndindex.hxx>
49 #include <sectfrm.hxx>
50 #include <pam.hxx>
51 #include <objectformatter.hxx>
52 #include "viewopt.hxx"
53 #include "viewsh.hxx"
54 #include <switerator.hxx>
55 
56 /*************************************************************************
57 |*
58 |*	lcl_FindFtnPos()		Sucht die Position des Attributes im FtnArray am
59 |*		Dokument, dort stehen die Fussnoten gluecklicherweise nach ihrem
60 |*		Index sortiert.
61 |*
62 |*************************************************************************/
63 
64 #define ENDNOTE 0x80000000
65 
66 sal_uLong MA_FASTCALL lcl_FindFtnPos( const SwDoc *pDoc, const SwTxtFtn *pAttr )
67 {
68 	const SwFtnIdxs &rFtnIdxs = pDoc->GetFtnIdxs();
69 
70 #ifdef MA_DEBUG
71 	//Wenn das Array nicht stimmt haben wir ein Problem, denn viele
72 	//Ftn-Functions bauen auf dem Array auf.
73 	for ( sal_uInt16 k = 0; k+1 < rFtnIdxs.Count(); ++k )
74 	{
75 		SwIndex aIdx1(&pDoc->GetNodes());
76 		SwIndex aIdx2(&pDoc->GetNodes());
77 		rFtnIdxs[k]->pFtn->  GetTxtNode().GetIndex(aIdx1);
78 		rFtnIdxs[k+1]->pFtn->GetTxtNode().GetIndex(aIdx2);
79 		if ( aIdx1.GetIndex() > aIdx2.GetIndex() )
80 		{
81 			ASSERT( !rFtnIdxs.Count(), "FtnIdxs not up to date" );
82 		}
83 		else if ( aIdx1.GetIndex() == aIdx2.GetIndex() )
84 		{
85 			SwTxtFtn *p1 = rFtnIdxs[k];
86 			SwTxtFtn *p2 = rFtnIdxs[k+1];
87 			ASSERT( *p1->GetStart() < *p2->GetStart(),
88 					"FtnIdxs not up to date" );
89 		}
90 	}
91 #endif
92 
93 	sal_uInt16 nRet;
94 	SwTxtFtnPtr pBla = (SwTxtFtn*)pAttr;
95 	if ( rFtnIdxs.Seek_Entry( pBla, &nRet ) )
96 	{
97 		if( pAttr->GetFtn().IsEndNote() )
98 			return sal_uLong(nRet) + ENDNOTE;
99 		return nRet;
100 	}
101 	ASSERT( !pDoc, "FtnPos not found." );
102 	return 0;
103 }
104 
105 sal_Bool SwFtnFrm::operator<( const SwTxtFtn* pTxtFtn ) const
106 {
107 	const SwDoc* pDoc = GetFmt()->GetDoc();
108 	ASSERT( pDoc, "SwFtnFrm: Missing doc!" );
109 	return lcl_FindFtnPos( pDoc, GetAttr() ) <
110 		   lcl_FindFtnPos( pDoc, pTxtFtn );
111 }
112 
113 /*************************************************************************
114 |*
115 |*	sal_Bool lcl_NextFtnBoss( SwFtnBossFrm* pBoss, SwPageFrm* pPage)
116 |*  setzt pBoss auf den naechsten SwFtnBossFrm, das kann entweder eine Spalte
117 |*  oder eine Seite (ohne Spalten) sein. Wenn die Seite dabei gewechselt wird
118 |*  enthaelt pPage die neue Seite und die Funktion liefert sal_True.
119 |*
120 |*************************************************************************/
121 
122 sal_Bool lcl_NextFtnBoss( SwFtnBossFrm* &rpBoss, SwPageFrm* &rpPage,
123 	sal_Bool bDontLeave )
124 {
125 	if( rpBoss->IsColumnFrm() )
126 	{
127 		if( rpBoss->GetNext() )
128 		{
129 			rpBoss = (SwFtnBossFrm*)rpBoss->GetNext(); //naechste Spalte
130 			return sal_False;
131 		}
132 		if( rpBoss->IsInSct() )
133 		{
134 			SwSectionFrm* pSct = rpBoss->FindSctFrm()->GetFollow();
135 			if( pSct )
136 			{
137 				ASSERT( pSct->Lower() && pSct->Lower()->IsColumnFrm(),
138 						"Where's the column?" );
139 				rpBoss = (SwColumnFrm*)pSct->Lower();
140 				SwPageFrm* pOld = rpPage;
141 				rpPage = pSct->FindPageFrm();
142 				return pOld != rpPage;
143 			}
144 			else if( bDontLeave )
145 			{
146 				rpPage = NULL;
147 				rpBoss = NULL;
148 				return sal_False;
149 			}
150 		}
151 	}
152 	rpPage = (SwPageFrm*)rpPage->GetNext(); // naechste Seite
153 	rpBoss = rpPage;
154 	if( rpPage )
155 	{
156 		SwLayoutFrm* pBody = rpPage->FindBodyCont();
157 		if( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrm() )
158 			rpBoss = (SwFtnBossFrm*)pBody->Lower(); // erste Spalte
159 	}
160 	return sal_True;
161 }
162 
163 /*************************************************************************
164 |*
165 |*	sal_uInt16 lcl_ColumnNum( SwFrm* pBoss )
166 |*  liefert die Spaltennummer, wenn pBoss eine Spalte ist,
167 |*  sonst eine Null (bei Seiten).
168 |*
169 |*************************************************************************/
170 
171 sal_uInt16 lcl_ColumnNum( const SwFrm* pBoss )
172 {
173 	sal_uInt16 nRet = 0;
174 	if( !pBoss->IsColumnFrm() )
175 		return 0;
176 	const SwFrm* pCol;
177 	if( pBoss->IsInSct() )
178 	{
179 		pCol = pBoss->GetUpper()->FindColFrm();
180 		if( pBoss->GetNext() || pBoss->GetPrev() )
181 		{
182 			while( pBoss )
183 			{
184 				++nRet;                     // Section columns
185 				pBoss = pBoss->GetPrev();
186 			}
187 		}
188 	}
189 	else
190 		pCol = pBoss;
191 	while( pCol )
192 	{
193 		nRet += 256;					// Page columns
194 		pCol = pCol->GetPrev();
195 	}
196 	return nRet;
197 }
198 
199 /*************************************************************************
200 |*
201 |*	SwFtnContFrm::SwFtnContFrm()
202 |*
203 |*************************************************************************/
204 
205 
206 SwFtnContFrm::SwFtnContFrm( SwFrmFmt *pFmt, SwFrm* pSib ):
207 	SwLayoutFrm( pFmt, pSib )
208 {
209     nType = FRMC_FTNCONT;
210 }
211 
212 
213 // lcl_Undersize(..) klappert einen SwFrm und dessen Inneres ab
214 // und liefert die Summe aller TxtFrm-Vergroesserungswuensche
215 
216 long lcl_Undersize( const SwFrm* pFrm )
217 {
218 	long nRet = 0;
219     SWRECTFN( pFrm )
220 	if( pFrm->IsTxtFrm() )
221 	{
222 		if( ((SwTxtFrm*)pFrm)->IsUndersized() )
223         {
224 			// Dieser TxtFrm waere gern ein bisschen groesser
225             nRet = ((SwTxtFrm*)pFrm)->GetParHeight() -
226                     (pFrm->Prt().*fnRect->fnGetHeight)();
227             if( nRet < 0 )
228 				nRet = 0;
229         }
230 	}
231 	else if( pFrm->IsLayoutFrm() )
232 	{
233 		const SwFrm* pNxt = ((SwLayoutFrm*)pFrm)->Lower();
234 		while( pNxt )
235 		{
236 			nRet += lcl_Undersize( pNxt );
237 			pNxt = pNxt->GetNext();
238 		}
239 	}
240 	return nRet;
241 }
242 
243 /*************************************************************************
244 |*
245 |*	SwFtnContFrm::Format()
246 |*
247 |*	Beschreibung:		"Formatiert" den Frame;
248 |*						Die Fixsize wird hier nicht eingestellt.
249 |*
250 |*************************************************************************/
251 
252 
253 void SwFtnContFrm::Format( const SwBorderAttrs * )
254 {
255 	//GesamtBorder ermitteln, es gibt nur einen Abstand nach oben.
256 	const SwPageFrm* pPage = FindPageFrm();
257 	const SwPageFtnInfo &rInf = pPage->GetPageDesc()->GetFtnInfo();
258 	const SwTwips nBorder = rInf.GetTopDist() + rInf.GetBottomDist() +
259 							rInf.GetLineWidth();
260     SWRECTFN( this )
261 	if ( !bValidPrtArea )
262 	{
263 		bValidPrtArea = sal_True;
264         (Prt().*fnRect->fnSetTop)( nBorder );
265         (Prt().*fnRect->fnSetWidth)( (Frm().*fnRect->fnGetWidth)() );
266         (Prt().*fnRect->fnSetHeight)((Frm().*fnRect->fnGetHeight)() - nBorder );
267         if( (Prt().*fnRect->fnGetHeight)() < 0 && !pPage->IsFtnPage() )
268 			bValidSize = sal_False;
269 	}
270 
271 	if ( !bValidSize )
272 	{
273         bool bGrow = pPage->IsFtnPage();
274         if( bGrow )
275         {
276             const ViewShell *pSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0;
277             if( pSh && pSh->GetViewOptions()->getBrowseMode() )
278                 bGrow = false;
279         }
280         if( bGrow )
281                 Grow( LONG_MAX, sal_False );
282 		else
283 		{
284 			//Die Groesse in der VarSize wird durch den Inhalt plus den
285 			//Raendern bestimmt.
286 			SwTwips nRemaining = 0;
287 			SwFrm *pFrm = pLower;
288 			while ( pFrm )
289 			{   // lcl_Undersize(..) beruecksichtigt (rekursiv) TxtFrms, die gerne
290 				// groesser waeren. Diese entstehen insbesondere in spaltigen Rahmen,
291 				// wenn diese noch nicht ihre maximale Groesse haben.
292                 nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)()
293                               + lcl_Undersize( pFrm );
294 				pFrm = pFrm->GetNext();
295 			}
296 			//Jetzt noch den Rand addieren
297 			nRemaining += nBorder;
298 
299 			SwTwips nDiff;
300 			if( IsInSct() )
301 			{
302                 nDiff = -(Frm().*fnRect->fnBottomDist)(
303                                         (GetUpper()->*fnRect->fnGetPrtBottom)() );
304                 if( nDiff > 0 )
305 				{
306                     if( nDiff > (Frm().*fnRect->fnGetHeight)() )
307                         nDiff = (Frm().*fnRect->fnGetHeight)();
308                     (Frm().*fnRect->fnAddBottom)( -nDiff );
309                     (Prt().*fnRect->fnAddHeight)( -nDiff );
310 				}
311 			}
312             nDiff = (Frm().*fnRect->fnGetHeight)() - nRemaining;
313 			if ( nDiff > 0 )
314                 Shrink( nDiff );
315 			else if ( nDiff < 0 )
316 			{
317                 Grow( -nDiff );
318 				//Es kann passieren, dass weniger Platz zur Verfuegung steht,
319 				//als der bereits der Border benoetigt - die Groesse der
320 				//PrtArea wird dann negativ.
321                 SwTwips nPrtHeight = (Prt().*fnRect->fnGetHeight)();
322                 if( nPrtHeight < 0 )
323 				{
324                     const SwTwips nTmpDiff = Max( (Prt().*fnRect->fnGetTop)(),
325                                                 -nPrtHeight );
326                     (Prt().*fnRect->fnSubTop)( nTmpDiff );
327 				}
328 			}
329 		}
330 		bValidSize = sal_True;
331 	}
332 }
333 /*************************************************************************
334 |*
335 |*	SwFtnContFrm::GrowFrm(), ShrinkFrm()
336 |*
337 |*************************************************************************/
338 
339 SwTwips SwFtnContFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool )
340 {
341 	//Keine Pruefung ob FixSize oder nicht, die FtnContainer sind immer bis
342 	//zur Maximalhoehe variabel.
343 	//Wenn die Maximalhoehe LONG_MAX ist, so nehmen wir uns soviel Platz wie eben
344 	//moeglich.
345 	//Wenn die Seite eine spezielle Fussnotenseite ist, so nehmen wir uns auch
346 	//soviel Platz wie eben moeglich.
347 #ifdef DBG_UTIL
348 	if ( !GetUpper() || !GetUpper()->IsFtnBossFrm() )
349 	{	ASSERT( !this, "Keine FtnBoss." );
350 		return 0;
351 	}
352 #endif
353 
354     SWRECTFN( this )
355     if( (Frm().*fnRect->fnGetHeight)() > 0 &&
356          nDist > ( LONG_MAX - (Frm().*fnRect->fnGetHeight)() ) )
357         nDist = LONG_MAX - (Frm().*fnRect->fnGetHeight)();
358 
359 	SwFtnBossFrm *pBoss = (SwFtnBossFrm*)GetUpper();
360 	if( IsInSct() )
361 	{
362 		SwSectionFrm* pSect = FindSctFrm();
363 		ASSERT( pSect, "GrowFrm: Missing SectFrm" );
364 		// In a section, which has to maximize, a footnotecontainer is allowed
365 		// to grow, when the section can't grow anymore.
366 		if( !bTst && !pSect->IsColLocked() &&
367 			pSect->ToMaximize( sal_False ) && pSect->Growable() )
368 		{
369 			pSect->InvalidateSize();
370 			return 0;
371 		}
372 	}
373     const ViewShell *pSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0;
374     const sal_Bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
375     SwPageFrm *pPage = pBoss->FindPageFrm();
376     if ( bBrowseMode || !pPage->IsFtnPage() )
377     {
378 		if ( pBoss->GetMaxFtnHeight() != LONG_MAX )
379 		{
380             nDist = Min( nDist, pBoss->GetMaxFtnHeight()
381                          - (Frm().*fnRect->fnGetHeight)() );
382 			if ( nDist <= 0 )
383 				return 0L;
384 		}
385 		//Der FtnBoss will bezueglich des MaxWerts auch noch mitreden.
386 		if( !IsInSct() )
387 		{
388 			const SwTwips nMax = pBoss->GetVarSpace();
389 			if ( nDist > nMax )
390 				nDist = nMax;
391 			if ( nDist <= 0 )
392 				return 0L;
393 		}
394 	}
395     else if( nDist > (GetPrev()->Frm().*fnRect->fnGetHeight)() )
396 		//aber mehr als der Body kann koennen und wollen wir nun auch wieder
397 		//nicht herausruecken.
398         nDist = (GetPrev()->Frm().*fnRect->fnGetHeight)();
399 
400     long nAvail = 0;
401     if ( bBrowseMode )
402 	{
403         nAvail = GetUpper()->Prt().Height();
404 		const SwFrm *pAvail = GetUpper()->Lower();
405 		do
406         {   nAvail -= pAvail->Frm().Height();
407 			pAvail = pAvail->GetNext();
408 		} while ( pAvail );
409 		if ( nAvail > nDist )
410 			nAvail = nDist;
411 	}
412 
413     if ( !bTst )
414     {
415         (Frm().*fnRect->fnSetHeight)( (Frm().*fnRect->fnGetHeight)() + nDist );
416         //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
417         if( IsVertical() && !IsVertLR() && !IsReverse() )
418             Frm().Pos().X() -= nDist;
419     }
420 	long nGrow = nDist - nAvail,
421 		 nReal = 0;
422 	if ( nGrow > 0 )
423 	{
424 		sal_uInt8 nAdjust = pBoss->NeighbourhoodAdjustment( this );
425 		if( NA_ONLY_ADJUST == nAdjust )
426 			nReal = AdjustNeighbourhood( nGrow, bTst );
427 		else
428 		{
429 			if( NA_GROW_ADJUST == nAdjust )
430 			{
431 				SwFrm* pFtn = Lower();
432 				if( pFtn )
433 				{
434 					while( pFtn->GetNext() )
435 						pFtn = pFtn->GetNext();
436 					if( ((SwFtnFrm*)pFtn)->GetAttr()->GetFtn().IsEndNote() )
437 					{
438 						nReal = AdjustNeighbourhood( nGrow, bTst );
439 						nAdjust = NA_GROW_SHRINK; // no more AdjustNeighbourhood
440 					}
441 				}
442 			}
443             nReal += pBoss->Grow( nGrow - nReal, bTst );
444 			if( ( NA_GROW_ADJUST == nAdjust || NA_ADJUST_GROW == nAdjust )
445 				  && nReal < nGrow )
446 				nReal += AdjustNeighbourhood( nGrow - nReal, bTst );
447 		}
448 	}
449 
450 	nReal += nAvail;
451 
452 	if ( !bTst )
453 	{
454 		if ( nReal != nDist )
455         {
456             nDist -= nReal;
457 			//Den masslosen Wunsch koennen wir leider nur in Grenzen erfuellen.
458             Frm().SSize().Height() -= nDist;
459             //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
460             if( IsVertical() && !IsVertLR() && !IsReverse() )
461                 Frm().Pos().X() += nDist;
462         }
463 
464 		//Nachfolger braucht nicht invalidiert werden, denn wir wachsen
465 		//immer nach oben.
466 		if( nReal )
467 		{
468 			_InvalidateSize();
469 			_InvalidatePos();
470 			InvalidatePage( pPage );
471 		}
472 	}
473 	return nReal;
474 }
475 
476 
477 SwTwips SwFtnContFrm::ShrinkFrm( SwTwips nDiff, sal_Bool bTst, sal_Bool bInfo )
478 {
479 	SwPageFrm *pPage = FindPageFrm();
480     bool bShrink = false;
481     if ( pPage )
482     {
483         if( !pPage->IsFtnPage() )
484             bShrink = true;
485         else
486         {
487             const ViewShell *pSh = getRootFrm()->GetCurrShell();
488             if( pSh && pSh->GetViewOptions()->getBrowseMode() )
489                 bShrink = true;
490         }
491     }
492     if( bShrink )
493 	{
494         SwTwips nRet = SwLayoutFrm::ShrinkFrm( nDiff, bTst, bInfo );
495         if( IsInSct() && !bTst )
496             FindSctFrm()->InvalidateNextPos();
497 		if ( !bTst && nRet )
498 		{
499 			_InvalidatePos();
500 			InvalidatePage( pPage );
501 		}
502 		return nRet;
503 	}
504 	return 0;
505 }
506 
507 
508 /*************************************************************************
509 |*
510 |*	SwFtnFrm::SwFtnFrm()
511 |*
512 |*************************************************************************/
513 
514 
515 SwFtnFrm::SwFtnFrm( SwFrmFmt *pFmt, SwFrm* pSib, SwCntntFrm *pCnt, SwTxtFtn *pAt ):
516 	SwLayoutFrm( pFmt, pSib ),
517 	pFollow( 0 ),
518 	pMaster( 0 ),
519 	pRef( pCnt ),
520 	pAttr( pAt ),
521     bBackMoveLocked( sal_False ),
522     // --> OD 2005-08-11 #i49383#
523     mbUnlockPosOfLowerObjs( true )
524     // <--
525 {
526     nType = FRMC_FTN;
527 }
528 
529 /*************************************************************************
530 |*
531 |*	SwFtnFrm::InvalidateNxtFtnCnts()
532 |*
533 |*************************************************************************/
534 
535 
536 void SwFtnFrm::InvalidateNxtFtnCnts( SwPageFrm *pPage )
537 {
538 	if ( GetNext() )
539 	{
540 		SwFrm *pCnt = ((SwLayoutFrm*)GetNext())->ContainsAny();
541 		if( pCnt )
542 		{
543 			pCnt->InvalidatePage( pPage );
544 			pCnt->_InvalidatePrt();
545 			do
546 			{	pCnt->_InvalidatePos();
547 				if( pCnt->IsSctFrm() )
548 				{
549 					SwFrm* pTmp = ((SwSectionFrm*)pCnt)->ContainsAny();
550 					if( pTmp )
551 						pTmp->_InvalidatePos();
552 				}
553 				pCnt->GetUpper()->_InvalidateSize();
554 				pCnt = pCnt->FindNext();
555 			} while ( pCnt && GetUpper()->IsAnLower( pCnt ) );
556 		}
557 	}
558 }
559 
560 #ifdef DBG_UTIL
561 
562 SwTwips SwFtnFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
563 {
564 #if OSL_DEBUG_LEVEL > 1
565 	static sal_uInt16 nNum = USHRT_MAX;
566 	SwTxtFtn* pTxtFtn = GetAttr();
567 	if ( pTxtFtn->GetFtn().GetNumber() == nNum )
568 	{
569 		int bla = 5;
570         (void)bla;
571 
572 	}
573 #endif
574     return SwLayoutFrm::GrowFrm( nDist, bTst, bInfo );
575 }
576 
577 
578 SwTwips SwFtnFrm::ShrinkFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
579 {
580 #if OSL_DEBUG_LEVEL > 1
581 	static sal_uInt16 nNum = USHRT_MAX;
582 	if( nNum != USHRT_MAX )
583 	{
584 		SwTxtFtn* pTxtFtn = GetAttr();
585 		if( &pTxtFtn->GetAttr() && pTxtFtn->GetFtn().GetNumber() == nNum )
586 		{
587 			int bla = 5;
588             (void)bla;
589 		}
590 	}
591 #endif
592     return SwLayoutFrm::ShrinkFrm( nDist, bTst, bInfo );
593 }
594 #endif
595 
596 /*************************************************************************
597 |*
598 |*	SwFtnFrm::Cut()
599 |*
600 |*************************************************************************/
601 
602 
603 void SwFtnFrm::Cut()
604 {
605 	if ( GetNext() )
606 		GetNext()->InvalidatePos();
607 	else if ( GetPrev() )
608 		GetPrev()->SetRetouche();
609 
610 	//Erst removen, dann Upper Shrinken.
611 	SwLayoutFrm *pUp = GetUpper();
612 
613 	//Verkettung korrigieren.
614 	SwFtnFrm *pFtn = (SwFtnFrm*)this;
615 	if ( pFtn->GetFollow() )
616 		pFtn->GetFollow()->SetMaster( pFtn->GetMaster() );
617 	if ( pFtn->GetMaster() )
618 		pFtn->GetMaster()->SetFollow( pFtn->GetFollow() );
619 	pFtn->SetFollow( 0 );
620 	pFtn->SetMaster( 0 );
621 
622 	// Alle Verbindungen kappen.
623 	Remove();
624 
625 	if ( pUp )
626 	{
627 		//Die letzte Fussnote nimmt ihren Container mit.
628 		if ( !pUp->Lower() )
629 		{
630 			SwPageFrm *pPage = pUp->FindPageFrm();
631 			if ( pPage )
632 			{
633 				SwLayoutFrm *pBody = pPage->FindBodyCont();
634 				if( pBody && !pBody->ContainsCntnt() )
635 					pPage->getRootFrm()->SetSuperfluous();
636 			}
637 			SwSectionFrm* pSect = pUp->FindSctFrm();
638 			pUp->Cut();
639 			delete pUp;
640 			// Wenn der letzte Fussnotencontainer aus einem spaltigen Bereich verschwindet,
641 			// so kann dieser, falls er keinen Follow besitzt, zusammenschrumpfen.
642 			if( pSect && !pSect->ToMaximize( sal_False ) && !pSect->IsColLocked() )
643 				pSect->_InvalidateSize();
644 		}
645 		else
646 		{	if ( Frm().Height() )
647                 pUp->Shrink( Frm().Height() );
648 			pUp->SetCompletePaint();
649 			pUp->InvalidatePage();
650 		}
651 	}
652 }
653 
654 /*************************************************************************
655 |*
656 |*	SwFtnFrm::Paste()
657 |*
658 |*************************************************************************/
659 
660 
661 void SwFtnFrm::Paste(  SwFrm* pParent, SwFrm* pSibling )
662 {
663 	ASSERT( pParent, "Kein Parent fuer Paste." );
664 	ASSERT( pParent->IsLayoutFrm(), "Parent ist CntntFrm." );
665 	ASSERT( pParent != this, "Bin selbst der Parent." );
666 	ASSERT( pSibling != this, "Bin mein eigener Nachbar." );
667 	ASSERT( !GetPrev() && !GetNext() && !GetUpper(),
668 			"Bin noch irgendwo angemeldet." );
669 
670 	//In den Baum einhaengen.
671 	InsertBefore( (SwLayoutFrm*)pParent, pSibling );
672 
673     SWRECTFN( this )
674     if( (Frm().*fnRect->fnGetWidth)()!=(pParent->Prt().*fnRect->fnGetWidth)() )
675 		_InvalidateSize();
676 	_InvalidatePos();
677 	SwPageFrm *pPage = FindPageFrm();
678 	InvalidatePage( pPage );
679 	if ( GetNext() )
680 		GetNext()->_InvalidatePos();
681     if( (Frm().*fnRect->fnGetHeight)() )
682         pParent->Grow( (Frm().*fnRect->fnGetHeight)() );
683 
684 	//Wenn mein Vorgaenger mein Master ist und/oder wenn mein Nachfolger mein
685 	//Follow ist so kann ich deren Inhalt uebernehmen und sie vernichten.
686 	if ( GetPrev() && GetPrev() == GetMaster() )
687 	{	ASSERT( SwFlowFrm::CastFlowFrm( GetPrev()->GetLower() ),
688 				"Fussnote ohne Inhalt?" );
689 		(SwFlowFrm::CastFlowFrm( GetPrev()->GetLower()))->
690 			MoveSubTree( this, GetLower() );
691 		SwFrm *pDel = GetPrev();
692 		pDel->Cut();
693 		delete pDel;
694 	}
695 	if ( GetNext() && GetNext() == GetFollow() )
696 	{	ASSERT( SwFlowFrm::CastFlowFrm( GetNext()->GetLower() ),
697 				"Fussnote ohne Inhalt?" );
698 		(SwFlowFrm::CastFlowFrm( GetNext()->GetLower()))->MoveSubTree( this );
699 		SwFrm *pDel = GetNext();
700 		pDel->Cut();
701 		delete pDel;
702 	}
703 #ifdef DBG_UTIL
704 	SwDoc *pDoc = GetFmt()->GetDoc();
705 	if ( GetPrev() )
706 	{
707 		ASSERT( lcl_FindFtnPos( pDoc, ((SwFtnFrm*)GetPrev())->GetAttr() ) <=
708 				lcl_FindFtnPos( pDoc, GetAttr() ), "Prev ist not FtnPrev" );
709 	}
710 	if ( GetNext() )
711 	{
712 		ASSERT( lcl_FindFtnPos( pDoc, GetAttr() ) <=
713 				lcl_FindFtnPos( pDoc, ((SwFtnFrm*)GetNext())->GetAttr() ),
714 				"Next is not FtnNext" );
715 	}
716 #endif
717 	InvalidateNxtFtnCnts( pPage );
718 }
719 
720 /*************************************************************************
721 |*
722 |*	SwFrm::GetNextFtnLeaf()
723 |*
724 |*	Beschreibung		Liefert das naechste LayoutBlatt in den das
725 |* 		Frame gemoved werden kann.
726 |* 		Neue Seiten werden nur dann erzeugt, wenn der Parameter sal_True ist.
727 |*
728 |*************************************************************************/
729 
730 
731 SwLayoutFrm *SwFrm::GetNextFtnLeaf( MakePageType eMakePage )
732 {
733 	SwFtnBossFrm *pOldBoss = FindFtnBossFrm();
734 	SwPageFrm* pOldPage = pOldBoss->FindPageFrm();
735 	SwPageFrm* pPage;
736 	SwFtnBossFrm *pBoss = pOldBoss->IsColumnFrm() ?
737 		(SwFtnBossFrm*)pOldBoss->GetNext() : 0; // naechste Spalte, wenn vorhanden
738 	if( pBoss )
739 		pPage = NULL;
740 	else
741 	{
742 		if( pOldBoss->GetUpper()->IsSctFrm() )
743 		{   // Das kann nur in einem spaltigen Bereich sein
744 			SwLayoutFrm* pNxt = pOldBoss->GetNextSctLeaf( eMakePage );
745 			if( pNxt )
746 			{
747 				ASSERT( pNxt->IsColBodyFrm(), "GetNextFtnLeaf: Funny Leaf" );
748 				pBoss = (SwFtnBossFrm*)pNxt->GetUpper();
749 				pPage = pBoss->FindPageFrm();
750 			}
751 			else
752 				return 0;
753 		}
754 		else
755 		{
756 			// naechste Seite
757 			pPage = (SwPageFrm*)pOldPage->GetNext();
758 			// Leerseiten ueberspringen
759 			if( pPage && pPage->IsEmptyPage() )
760 				pPage =	(SwPageFrm*)pPage->GetNext();
761 			pBoss = pPage;
762 		}
763 	}
764 	// Was haben wir jetzt?
765 	// pBoss != NULL, pPage==NULL => pBoss ist die auf der gleichen Seite folgende Spalte
766 	// pBoss != NULL, pPage!=NULL => pBoss und pPage sind die folgende Seite (Empty uebersprungen)
767 	// pBoss == NULL => pPage == NULL, es gibt keine folgende Seite
768 
769 	//Wenn die Fussnote bereits einen Follow hat brauchen wir nicht zu suchen.
770 	//Wenn allerdings zwischen Ftn und Follow unerwuenschte Leerseiten/spalten
771 	//herumlungern, so legen wir auf der naechstbesten Seite/Spalte einen weiteren
772 	//Follow an, der Rest wird sich schon finden.
773 	SwFtnFrm *pFtn = FindFtnFrm();
774 	if ( pFtn && pFtn->GetFollow() )
775 	{
776 		SwFtnBossFrm* pTmpBoss = pFtn->GetFollow()->FindFtnBossFrm();
777 		// Folgende Faelle werden hier erkannt und akzeptiert
778 		// 1. Die FtnBosse sind benachbarte Seiten oder benachbarte Spalten
779 		// 2. Der neue ist die erste Spalte der benachbarten Seite
780 		// 3. Der neue ist die erste Spalte in einem Bereich in der naechsten Spalte/Seite
781 		while( pTmpBoss != pBoss && pTmpBoss && !pTmpBoss->GetPrev() )
782 			pTmpBoss = pTmpBoss->GetUpper()->FindFtnBossFrm();
783 		if( pTmpBoss == pBoss )
784 			return pFtn->GetFollow();
785 	}
786 
787 	// Wenn wir keinen pBoss gefunden haben oder es sich um eine "falsche" Seite handelt,
788 	// muss eine neue Seite her
789 	if ( !pBoss || ( pPage && pPage->IsEndNotePage() && !pOldPage->IsEndNotePage() ) )
790 	{
791 		if ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT )
792 		{
793 			pBoss = InsertPage( pOldPage, pOldPage->IsFtnPage() );
794 			((SwPageFrm*)pBoss)->SetEndNotePage( pOldPage->IsEndNotePage() );
795 		}
796 		else
797 			return 0;
798 	}
799 	if( pBoss->IsPageFrm() )
800 	{	// Wenn wir auf einer spaltigen Seite gelandet sind,
801 		// gehen wir in die erste Spalte
802 		SwLayoutFrm* pLay = pBoss->FindBodyCont();
803 		if( pLay && pLay->Lower() && pLay->Lower()->IsColumnFrm() )
804 			pBoss = (SwFtnBossFrm*)pLay->Lower();
805 	}
806 	//Seite/Spalte gefunden, da schummeln wir uns doch gleich mal 'rein
807 	SwFtnContFrm *pCont = pBoss->FindFtnCont();
808 	if ( !pCont && pBoss->GetMaxFtnHeight() &&
809 		 ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT ) )
810 		pCont = pBoss->MakeFtnCont();
811 	return pCont;
812 }
813 
814 /*************************************************************************
815 |*
816 |*	SwFrm::GetPrevFtnLeaf()
817 |*
818 |*	Beschreibung		Liefert das vorhergehende LayoutBlatt in das der
819 |* 		Frame gemoved werden kann.
820 |*
821 |*************************************************************************/
822 
823 
824 SwLayoutFrm *SwFrm::GetPrevFtnLeaf( MakePageType eMakeFtn )
825 {
826 	//Der Vorgaenger fuer eine Fussnote ist falls moeglich der Master
827 	//in der Fussnoteneigenen Verkettung.
828 	SwLayoutFrm *pRet = 0;
829 	SwFtnFrm *pFtn = FindFtnFrm();
830 	pRet = pFtn->GetMaster();
831 
832 	SwFtnBossFrm* pOldBoss = FindFtnBossFrm();
833 	SwPageFrm *pOldPage = pOldBoss->FindPageFrm();
834 
835 	if ( !pOldBoss->GetPrev() && !pOldPage->GetPrev() )
836 		return pRet; // es gibt weder eine Spalte noch eine Seite vor uns
837 
838 	if ( !pRet )
839 	{
840         bool bEndn = pFtn->GetAttr()->GetFtn().IsEndNote();
841 		SwFrm* pTmpRef = NULL;
842 		if( bEndn && pFtn->IsInSct() )
843 		{
844 			SwSectionFrm* pSect = pFtn->FindSctFrm();
845 			if( pSect->IsEndnAtEnd() )
846 				pTmpRef = pSect->FindLastCntnt( FINDMODE_LASTCNT );
847 		}
848 		if( !pTmpRef )
849 			pTmpRef = pFtn->GetRef();
850 		SwFtnBossFrm* pStop = pTmpRef->FindFtnBossFrm( !bEndn );
851 
852 		const sal_uInt16 nNum = pStop->GetPhyPageNum();
853 
854 		//Wenn die Fussnoten am Dokumentende angezeigt werden, so verlassen wir
855 		//die Entsprechenden Seiten nicht.
856 		//Selbiges gilt analog fuer die Endnotenseiten.
857 		const sal_Bool bEndNote = pOldPage->IsEndNotePage();
858 		const sal_Bool bFtnEndDoc = pOldPage->IsFtnPage();
859 		SwFtnBossFrm* pNxtBoss = pOldBoss;
860 		SwSectionFrm *pSect = pNxtBoss->GetUpper()->IsSctFrm() ?
861 							  (SwSectionFrm*)pNxtBoss->GetUpper() : 0;
862 
863 		do
864 		{
865 			if( pNxtBoss->IsColumnFrm() && pNxtBoss->GetPrev() )
866 				pNxtBoss = (SwFtnBossFrm*)pNxtBoss->GetPrev();	// eine Spalte zurueck
867 			else                				// oder eine Seite zurueck
868 			{
869                 SwLayoutFrm* pBody = 0;
870 				if( pSect )
871 				{
872 					if( pSect->IsFtnLock() )
873 					{
874 						if( pNxtBoss == pOldBoss )
875 							return 0;
876 						pStop = pNxtBoss;
877 					}
878 					else
879 					{
880                         pSect = (SwSectionFrm*)pSect->FindMaster();
881 						if( !pSect || !pSect->Lower() )
882 							return 0;
883 						ASSERT( pSect->Lower()->IsColumnFrm(),
884 								"GetPrevFtnLeaf: Where's the column?" );
885 						pNxtBoss = (SwFtnBossFrm*)pSect->Lower();
886 						pBody = pSect;
887 					}
888 				}
889 				else
890 				{
891 					SwPageFrm* pPage = (SwPageFrm*)pNxtBoss->FindPageFrm()->GetPrev();
892 					if( !pPage || pPage->GetPhyPageNum() < nNum ||
893 						bEndNote != pPage->IsEndNotePage() || bFtnEndDoc != pPage->IsFtnPage() )
894 						return NULL; // Keine in Frage kommende Seite mehr gefunden
895 					pNxtBoss = pPage;
896 					pBody = pPage->FindBodyCont();
897 				}
898 				// Die vorherige Seite haben wir nun, ggf. sollten wir in die letzte Spalte
899 				// der Seite wechseln
900 				if( pBody )
901 				{
902 					if ( pBody->Lower() && pBody->Lower()->IsColumnFrm() )
903 					{
904                         pNxtBoss = static_cast<SwFtnBossFrm*>(pBody->GetLastLower());
905                     }
906 				}
907 			}
908 			SwFtnContFrm *pCont = pNxtBoss->FindFtnCont();
909 			if ( pCont )
910 			{
911 				pRet = pCont;
912 				break;
913 			}
914 			if ( pStop == pNxtBoss )
915 			{	//Die Seite/Spalte auf der sich auch die Referenz tummelt, ist erreicht.
916 				//Wir koennen jetzt probehalber mal einen Container erzeugen und
917 				//uns hineinpasten.
918 				if ( eMakeFtn == MAKEPAGE_FTN && pNxtBoss->GetMaxFtnHeight() )
919 					pRet = pNxtBoss->MakeFtnCont();
920 				break;
921 			}
922 		} while( !pRet );
923 	}
924 	if ( pRet )
925 	{
926 		const SwFtnBossFrm* pNewBoss = pRet->FindFtnBossFrm();
927 		sal_Bool bJump = sal_False;
928 		if( pOldBoss->IsColumnFrm() && pOldBoss->GetPrev() ) // es gibt eine vorherige Spalte
929 			bJump = pOldBoss->GetPrev() != (SwFrm*)pNewBoss;		 // sind wir darin gelandet?
930 		else if( pNewBoss->IsColumnFrm() && pNewBoss->GetNext() )
931 			bJump = sal_True; // es gibt hinter dem neuen Boss noch eine Spalte, die aber nicht
932 						  // der alte Boss sein kann, das haben wir ja bereits geprueft.
933 		else // hier landen wir nur, wenn neuer und alter Boss entweder Seiten oder letzte (neu)
934 		{	// bzw. erste (alt) Spalten einer Seite sind. In diesem Fall muss noch geprueft
935 			// werden, ob Seiten ueberspringen wurden.
936 			sal_uInt16 nDiff = pOldPage->GetPhyPageNum() - pRet->FindPageFrm()->GetPhyPageNum();
937 			if ( nDiff > 2 ||
938 				 (nDiff > 1 && !((SwPageFrm*)pOldPage->GetPrev())->IsEmptyPage()) )
939 				bJump = sal_True;
940 		}
941 		if( bJump )
942 			SwFlowFrm::SetMoveBwdJump( sal_True );
943 	}
944 	return pRet;
945 }
946 
947 /*************************************************************************
948 |*
949 |*	SwFrm::IsFtnAllowed()
950 |*
951 |*************************************************************************/
952 
953 
954 sal_Bool SwFrm::IsFtnAllowed() const
955 {
956 	if ( !IsInDocBody() )
957 		return sal_False;
958 
959 	if ( IsInTab() )
960 	{
961 		//Keine Ftns in wiederholten Headlines.
962         const SwTabFrm *pTab = ((SwFrm*)this)->ImplFindTabFrm();
963         if ( pTab->IsFollow() )
964             return !pTab->IsInHeadline( *this );
965     }
966 	return sal_True;
967 }
968 
969 /*************************************************************************
970 |*
971 |*	SwRootFrm::UpdateFtnNums()
972 |*
973 |*************************************************************************/
974 
975 
976 void SwRootFrm::UpdateFtnNums()
977 {
978 	//Seitenweise Numerierung nur wenn es am Dokument so eingestellt ist.
979 	if ( GetFmt()->GetDoc()->GetFtnInfo().eNum == FTNNUM_PAGE )
980 	{
981 		SwPageFrm *pPage = (SwPageFrm*)Lower();
982 		while ( pPage && !pPage->IsFtnPage() )
983 		{
984 			pPage->UpdateFtnNum();
985 			pPage = (SwPageFrm*)pPage->GetNext();
986 		}
987 	}
988 }
989 
990 /*************************************************************************
991 |*
992 |*	RemoveFtns()		Entfernen aller Fussnoten (nicht etwa die Referenzen)
993 |*						und Entfernen aller Fussnotenseiten.
994 |*
995 |*************************************************************************/
996 
997 void lcl_RemoveFtns( SwFtnBossFrm* pBoss, sal_Bool bPageOnly, sal_Bool bEndNotes )
998 {
999 	do
1000 	{
1001 		SwFtnContFrm *pCont = pBoss->FindFtnCont();
1002 		if ( pCont )
1003 		{
1004 			SwFtnFrm *pFtn = (SwFtnFrm*)pCont->Lower();
1005 			ASSERT( pFtn, "FtnCont ohne Ftn." );
1006 			if ( bPageOnly )
1007 				while ( pFtn->GetMaster() )
1008 					pFtn = pFtn->GetMaster();
1009 			do
1010 			{
1011 				SwFtnFrm *pNxt = (SwFtnFrm*)pFtn->GetNext();
1012 				if ( !pFtn->GetAttr()->GetFtn().IsEndNote() ||
1013 						bEndNotes )
1014 				{
1015 					pFtn->GetRef()->Prepare( PREP_FTN, (void*)pFtn->GetAttr() );
1016 					if ( bPageOnly && !pNxt )
1017 						pNxt = pFtn->GetFollow();
1018 					pFtn->Cut();
1019 					delete pFtn;
1020 				}
1021 				pFtn = pNxt;
1022 
1023 			} while ( pFtn );
1024 		}
1025         if( !pBoss->IsInSct() )
1026 		{
1027 			// A sectionframe with the Ftn/EndnAtEnd-flags may contain
1028 			// foot/endnotes. If the last lower frame of the bodyframe is
1029 			// a multicolumned sectionframe, it may contain footnotes, too.
1030 			SwLayoutFrm* pBody = pBoss->FindBodyCont();
1031 			if( pBody && pBody->Lower() )
1032 			{
1033 				SwFrm* pLow = pBody->Lower();
1034 				while( pLow->GetNext() )
1035 				{
1036 					if( pLow->IsSctFrm() &&	( !pLow->GetNext() ||
1037 						((SwSectionFrm*)pLow)->IsAnyNoteAtEnd() ) &&
1038 						((SwSectionFrm*)pLow)->Lower() &&
1039 						((SwSectionFrm*)pLow)->Lower()->IsColumnFrm() )
1040 						lcl_RemoveFtns( (SwColumnFrm*)((SwSectionFrm*)pLow)->Lower(),
1041 							bPageOnly, bEndNotes );
1042 					pLow = pLow->GetNext();
1043 				}
1044 			}
1045 		}
1046 		// noch 'ne Spalte?
1047 		pBoss = pBoss->IsColumnFrm() ? (SwColumnFrm*)pBoss->GetNext() : NULL;
1048 	} while( pBoss );
1049 }
1050 
1051 void SwRootFrm::RemoveFtns( SwPageFrm *pPage, sal_Bool bPageOnly, sal_Bool bEndNotes )
1052 {
1053 	if ( !pPage )
1054 		pPage = (SwPageFrm*)Lower();
1055 
1056 	do
1057 	{	// Bei spaltigen Seiten muessen wir in allen Spalten aufraeumen
1058 		SwFtnBossFrm* pBoss;
1059 		SwLayoutFrm* pBody = pPage->FindBodyCont();
1060 		if( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrm() )
1061 			pBoss = (SwFtnBossFrm*)pBody->Lower(); // die erste Spalte
1062 		else
1063 			pBoss = pPage; // keine Spalten
1064 		lcl_RemoveFtns( pBoss, bPageOnly, bEndNotes );
1065 		if ( !bPageOnly )
1066 		{
1067 			if ( pPage->IsFtnPage() &&
1068 				 (!pPage->IsEndNotePage() || bEndNotes) )
1069 			{
1070 				SwFrm *pDel = pPage;
1071 				pPage = (SwPageFrm*)pPage->GetNext();
1072 				pDel->Cut();
1073 				delete pDel;
1074 			}
1075 			else
1076 				pPage = (SwPageFrm*)pPage->GetNext();
1077 		}
1078 		else
1079 			break;
1080 
1081 	} while ( pPage );
1082 }
1083 
1084 /*************************************************************************
1085 |*
1086 |*	SetFtnPageDescs()	Seitenvorlagen der Fussnotenseiten aendern
1087 |*
1088 |*************************************************************************/
1089 
1090 void SwRootFrm::CheckFtnPageDescs( sal_Bool bEndNote )
1091 {
1092 	SwPageFrm *pPage = (SwPageFrm*)Lower();
1093 	while ( pPage && !pPage->IsFtnPage() )
1094 		pPage = (SwPageFrm*)pPage->GetNext();
1095 	while ( pPage && pPage->IsEndNotePage() != bEndNote )
1096 		pPage = (SwPageFrm*)pPage->GetNext();
1097 	if ( pPage )
1098 		SwFrm::CheckPageDescs( pPage, sal_False );
1099 }
1100 
1101 
1102 /*************************************************************************
1103 |*
1104 |*	SwFtnBossFrm::MakeFtnCont()
1105 |*
1106 |*************************************************************************/
1107 
1108 
1109 SwFtnContFrm *SwFtnBossFrm::MakeFtnCont()
1110 {
1111 	//Einfuegen eines Fussnotencontainers. Der Fussnotencontainer sitzt
1112 	//immer direkt hinter dem Bodytext.
1113 	//Sein FrmFmt ist immer das DefaultFrmFmt.
1114 
1115 #ifdef DBG_UTIL
1116 	if ( FindFtnCont() )
1117 	{   ASSERT( !this, "Fussnotencontainer bereits vorhanden." );
1118 		return 0;
1119 	}
1120 #endif
1121 
1122 	SwFtnContFrm *pNew = new SwFtnContFrm( GetFmt()->GetDoc()->GetDfltFrmFmt(), this );
1123 	SwLayoutFrm *pLay = FindBodyCont();
1124 	pNew->Paste( this, pLay->GetNext() );
1125 	return pNew;
1126 }
1127 
1128 /*************************************************************************
1129 |*
1130 |*	SwFtnBossFrm::FindFtnCont()
1131 |*
1132 |*************************************************************************/
1133 
1134 
1135 SwFtnContFrm *SwFtnBossFrm::FindFtnCont()
1136 {
1137 	SwFrm *pFrm = Lower();
1138 	while( pFrm && !pFrm->IsFtnContFrm() )
1139 		pFrm = pFrm->GetNext();
1140 
1141 #ifdef DBG_UTIL
1142 	if ( pFrm )
1143 	{
1144 		SwFrm *pFtn = pFrm->GetLower();
1145 		ASSERT( pFtn, "Cont ohne Fussnote." );
1146 		while ( pFtn )
1147 		{
1148 			ASSERT( pFtn->IsFtnFrm(), "Nachbar von Fussnote keine Fussnote." );
1149 			pFtn = pFtn->GetNext();
1150 		}
1151 	}
1152 #endif
1153 
1154 	return (SwFtnContFrm*)pFrm;
1155 }
1156 
1157 /*************************************************************************
1158 |*
1159 |*	SwFtnBossFrm::FindNearestFtnCont()	Sucht den naechst greifbaren Fussnotencontainer.
1160 |*
1161 |*************************************************************************/
1162 
1163 SwFtnContFrm *SwFtnBossFrm::FindNearestFtnCont( sal_Bool bDontLeave )
1164 {
1165 	SwFtnContFrm *pCont = 0;
1166 	if ( GetFmt()->GetDoc()->GetFtnIdxs().Count() )
1167 	{
1168 		pCont = FindFtnCont();
1169 		if ( !pCont )
1170 		{
1171 			SwPageFrm *pPage = FindPageFrm();
1172 			SwFtnBossFrm* pBoss = this;
1173 			sal_Bool bEndNote = pPage->IsEndNotePage();
1174 			do
1175 			{
1176 				sal_Bool bChgPage = lcl_NextFtnBoss( pBoss, pPage, bDontLeave );
1177 				// Haben wir noch einen Boss gefunden? Bei einem Seitenwechsel muss
1178 				// zudem noch das EndNotenFlag uebereinstimmen
1179 				if( pBoss && ( !bChgPage || pPage->IsEndNotePage() == bEndNote ) )
1180 					pCont = pBoss->FindFtnCont();
1181 			} while ( !pCont && pPage );
1182 		}
1183 	}
1184 	return pCont;
1185 }
1186 
1187 
1188 /*************************************************************************
1189 |*
1190 |*	SwFtnBossFrm::FindFirstFtn()
1191 |*
1192 |* 	Beschreibung		Erste Fussnote des Fussnotenbosses suchen.
1193 |*
1194 |*************************************************************************/
1195 
1196 
1197 SwFtnFrm *SwFtnBossFrm::FindFirstFtn()
1198 {
1199 	//Erstmal den naechsten FussnotenContainer suchen.
1200 	SwFtnContFrm *pCont = FindNearestFtnCont();
1201 	if ( !pCont )
1202 		return 0;
1203 
1204 	//Ab der ersten Fussnote im Container die erste suchen, die
1205 	//von der aktuellen Spalte (bzw. einspaltigen Seite) referenziert wird.
1206 
1207 	SwFtnFrm *pRet = (SwFtnFrm*)pCont->Lower();
1208 	const sal_uInt16 nRefNum = FindPageFrm()->GetPhyPageNum();
1209 	const sal_uInt16 nRefCol = lcl_ColumnNum( this );
1210 	sal_uInt16 nPgNum, nColNum; //Seitennummer, Spaltennummer
1211 	SwFtnBossFrm* pBoss;
1212 	SwPageFrm* pPage;
1213 	if( pRet )
1214 	{
1215 		pBoss = pRet->GetRef()->FindFtnBossFrm();
1216 		ASSERT( pBoss, "FindFirstFtn: No boss found" );
1217 		if( !pBoss )
1218 			return sal_False; // ?There must be a bug, but no GPF
1219 		pPage = pBoss->FindPageFrm();
1220 		nPgNum = pPage->GetPhyPageNum();
1221 		if ( nPgNum == nRefNum )
1222 		{
1223 			nColNum = lcl_ColumnNum( pBoss );
1224 			if( nColNum == nRefCol )
1225 				return pRet; //hat ihn.
1226 			else if( nColNum > nRefCol )
1227 				return NULL; //mind. eine Spalte zu weit.
1228 		}
1229 		else if ( nPgNum > nRefNum )
1230 			return NULL;	//mind. eine Seite zu weit.
1231 	}
1232 	else
1233 		return NULL;
1234 	// Ende, wenn Ref auf einer spaeteren Seite oder auf der gleichen Seite in einer
1235 	// spaeteren Spalte liegt
1236 
1237 	do
1238 	{
1239 		while ( pRet->GetFollow() )
1240 			pRet = pRet->GetFollow();
1241 
1242 		SwFtnFrm *pNxt = (SwFtnFrm*)pRet->GetNext();
1243 		if ( !pNxt )
1244 		{
1245 			pBoss = pRet->FindFtnBossFrm();
1246 			pPage = pBoss->FindPageFrm();
1247 			lcl_NextFtnBoss( pBoss, pPage, sal_False ); // naechster FtnBoss
1248 			pCont = pBoss ? pBoss->FindNearestFtnCont() : 0;
1249 			if ( pCont )
1250 				pNxt = (SwFtnFrm*)pCont->Lower();
1251 		}
1252 		if ( pNxt )
1253 		{
1254 			pRet = pNxt;
1255 			pBoss = pRet->GetRef()->FindFtnBossFrm();
1256 			pPage = pBoss->FindPageFrm();
1257 			nPgNum = pPage->GetPhyPageNum();
1258 			if ( nPgNum == nRefNum )
1259 			{
1260 				nColNum = lcl_ColumnNum( pBoss );
1261 				if( nColNum == nRefCol )
1262 					break; //hat ihn.
1263 				else if( nColNum > nRefCol )
1264 					pRet = 0; //mind. eine Spalte zu weit.
1265 			}
1266 			else if ( nPgNum > nRefNum )
1267 				pRet = 0;	//mind. eine Seite zu weit.
1268 		}
1269 		else
1270 			pRet = 0;	//Gibt eben keinen.
1271 	} while( pRet );
1272 	return pRet;
1273 }
1274 
1275 /*************************************************************************
1276 |*
1277 |*	SwFtnBossFrm::FindFirstFtn()
1278 |*
1279 |* 	Beschreibunt		Erste Fussnote zum Cnt suchen.
1280 |*
1281 |*************************************************************************/
1282 
1283 
1284 const SwFtnFrm *SwFtnBossFrm::FindFirstFtn( SwCntntFrm *pCnt ) const
1285 {
1286 	const SwFtnFrm *pRet = ((SwFtnBossFrm*)this)->FindFirstFtn();
1287 	if ( pRet )
1288 	{
1289 		const sal_uInt16 nColNum = lcl_ColumnNum( this ); //Spaltennummer
1290 		const sal_uInt16 nPageNum = GetPhyPageNum();
1291 		while ( pRet && (pRet->GetRef() != pCnt) )
1292 		{
1293 			while ( pRet->GetFollow() )
1294 				pRet = pRet->GetFollow();
1295 
1296 			if ( pRet->GetNext() )
1297 				pRet = (const SwFtnFrm*)pRet->GetNext();
1298 			else
1299 			{	SwFtnBossFrm *pBoss = (SwFtnBossFrm*)pRet->FindFtnBossFrm();
1300 				SwPageFrm *pPage = pBoss->FindPageFrm();
1301 				lcl_NextFtnBoss( pBoss, pPage, sal_False ); // naechster FtnBoss
1302 				SwFtnContFrm *pCont = pBoss ? pBoss->FindNearestFtnCont() : 0;
1303 				pRet = pCont ? (SwFtnFrm*)pCont->Lower() : 0;
1304 			}
1305 			if ( pRet )
1306 			{
1307 				const SwFtnBossFrm* pBoss = pRet->GetRef()->FindFtnBossFrm();
1308 				if( pBoss->GetPhyPageNum() != nPageNum ||
1309 					nColNum != lcl_ColumnNum( pBoss ) )
1310 				pRet = 0;
1311 			}
1312 		}
1313 	}
1314 	return pRet;
1315 }
1316 
1317 /*************************************************************************
1318 |*
1319 |*	SwFtnBossFrm::ResetFtn()
1320 |*
1321 |*************************************************************************/
1322 
1323 
1324 void SwFtnBossFrm::ResetFtn( const SwFtnFrm *pCheck )
1325 {
1326 	//Vernichten der Inkarnationen von Fussnoten zum Attribut, wenn sie nicht
1327 	//zu pAssumed gehoeren.
1328 	ASSERT( !pCheck->GetMaster(), "Master not an Master." );
1329 
1330 	SwNodeIndex aIdx( *pCheck->GetAttr()->GetStartNode(), 1 );
1331 	SwCntntNode *pNd = aIdx.GetNode().GetCntntNode();
1332 	if ( !pNd )
1333 		pNd = pCheck->GetFmt()->GetDoc()->
1334 			  GetNodes().GoNextSection( &aIdx, sal_True, sal_False );
1335 	SwIterator<SwFrm,SwCntntNode> aIter( *pNd );
1336     SwFrm* pFrm = aIter.First();
1337 	while( pFrm )
1338 	{
1339             if( pFrm->getRootFrm() == pCheck->getRootFrm() )
1340             {
1341 			SwFrm *pTmp = pFrm->GetUpper();
1342 			while ( pTmp && !pTmp->IsFtnFrm() )
1343 				pTmp = pTmp->GetUpper();
1344 
1345 			SwFtnFrm *pFtn = (SwFtnFrm*)pTmp;
1346 			while ( pFtn && pFtn->GetMaster() )
1347 				pFtn = pFtn->GetMaster();
1348 			if ( pFtn != pCheck )
1349 			{
1350 				while ( pFtn )
1351 				{
1352 					SwFtnFrm *pNxt = pFtn->GetFollow();
1353 					pFtn->Cut();
1354 					delete pFtn;
1355 					pFtn = pNxt;
1356 				}
1357 			}
1358 		}
1359 
1360 		pFrm = aIter.Next();
1361 	}
1362 }
1363 
1364 /*************************************************************************
1365 |*
1366 |*	SwFtnBossFrm::InsertFtn()
1367 |*
1368 |*************************************************************************/
1369 
1370 
1371 void SwFtnBossFrm::InsertFtn( SwFtnFrm* pNew )
1372 {
1373 #if (OSL_DEBUG_LEVEL > 1) && defined(DBG_UTIL)
1374 	static sal_uInt16 nStop = 0;
1375 	if ( nStop == pNew->GetFrmId() )
1376 	{
1377 		int bla = 5;
1378         (void)bla;
1379 	}
1380 #endif
1381 	//Die Fussnote haben wir, sie muss jetzt nur noch irgendwo
1382 	//hin und zwar vor die Fussnote, deren Attribut vor das
1383 	//der neuen zeigt (Position wird ueber das Doc ermittelt)
1384 	//Gibt es in diesem Fussnotenboss noch keine Fussnoten, so muss eben ein
1385 	//Container erzeugt werden.
1386 	//Gibt es bereits einen Container aber noch keine Fussnote zu diesem
1387 	//Fussnotenboss, so muss die Fussnote hinter die letzte Fussnote der dichtesten
1388 	//Vorseite/spalte.
1389 
1390 	ResetFtn( pNew );
1391 	SwFtnFrm *pSibling = FindFirstFtn();
1392 	sal_Bool bDontLeave = sal_False;
1393 
1394 	// Ok, a sibling has been found, but is the sibling in an acceptable
1395 	// environment?
1396 	if( IsInSct() )
1397 	{
1398 		SwSectionFrm* pMySect = ImplFindSctFrm();
1399         bool bEndnt = pNew->GetAttr()->GetFtn().IsEndNote();
1400 		if( bEndnt )
1401 		{
1402 			const SwSectionFmt* pEndFmt = pMySect->GetEndSectFmt();
1403 			bDontLeave = 0 != pEndFmt;
1404 			if( pSibling )
1405 			{
1406 				if( pEndFmt )
1407 				{
1408 					if( !pSibling->IsInSct() ||
1409 						!pSibling->ImplFindSctFrm()->IsDescendantFrom( pEndFmt ) )
1410 						pSibling = NULL;
1411 				}
1412 				else if( pSibling->IsInSct() )
1413 					pSibling = NULL;
1414 			}
1415 		}
1416 		else
1417 		{
1418 			bDontLeave = pMySect->IsFtnAtEnd();
1419 			if( pSibling )
1420 			{
1421 				if( pMySect->IsFtnAtEnd() )
1422 				{
1423 					if( !pSibling->IsInSct() ||
1424 						!pMySect->IsAnFollow( pSibling->ImplFindSctFrm() ) )
1425 						pSibling = NULL;
1426 				}
1427 				else if( pSibling->IsInSct() )
1428 					pSibling = NULL;
1429 			}
1430 		}
1431 	}
1432 
1433 	if( pSibling && pSibling->FindPageFrm()->IsEndNotePage() !=
1434 		FindPageFrm()->IsEndNotePage() )
1435 		pSibling = NULL;
1436 
1437 	//Damit die Position herausgefunden werden kann.
1438 	SwDoc *pDoc = GetFmt()->GetDoc();
1439 	const sal_uLong nStPos = ::lcl_FindFtnPos( pDoc, pNew->GetAttr() );
1440 
1441 	sal_uLong nCmpPos = 0;
1442     sal_uLong nLastPos = 0;
1443 	SwFtnContFrm *pParent = 0;
1444 	if( pSibling )
1445 	{
1446 		nCmpPos = ::lcl_FindFtnPos( pDoc, pSibling->GetAttr() );
1447 		if( nCmpPos > nStPos )
1448 			pSibling = NULL;
1449 	}
1450 
1451 	if ( !pSibling )
1452 	{	pParent = FindFtnCont();
1453 		if ( !pParent )
1454 		{
1455 			//Es gibt noch keinen FussnotenContainer, also machen wir einen.
1456 			//HAAAAAAAALT! So einfach ist das leider mal wieder nicht: Es kann
1457 			//sein, dass irgendeine naechste Fussnote existiert die vor der
1458 			//einzufuegenden zu stehen hat, weil z.B. eine Fussnote ueber zig
1459 			//Seiten aufgespalten ist usw.
1460 			pParent = FindNearestFtnCont( bDontLeave );
1461 			if ( pParent )
1462 			{
1463 				SwFtnFrm *pFtn = (SwFtnFrm*)pParent->Lower();
1464 				if ( pFtn )
1465 				{
1466 
1467 					nCmpPos = ::lcl_FindFtnPos( pDoc, pFtn->GetAttr() );
1468 					if ( nCmpPos > nStPos )
1469 						pParent = 0;
1470 				}
1471 				else
1472 					pParent = 0;
1473 			}
1474 		}
1475 		if ( !pParent )
1476 			//Jetzt kann aber ein Fussnotencontainer gebaut werden.
1477 			pParent = MakeFtnCont();
1478 		else
1479 		{
1480 			//Ausgehend von der ersten Fussnote unterhalb des Parents wird die
1481 			//erste Fussnote gesucht deren Index hinter dem Index der
1482 			//einzufuegenden liegt; vor dieser kann der neue dann gepastet
1483 			//werden.
1484 			pSibling = (SwFtnFrm*)pParent->Lower();
1485 			if ( !pSibling )
1486 			{	ASSERT( !this, "Keinen Platz fuer Fussnote gefunden.");
1487 				return;
1488 			}
1489 			nCmpPos  = ::lcl_FindFtnPos( pDoc, pSibling->GetAttr() );
1490 
1491 			SwFtnBossFrm *pNxtB = this;	//Immer den letzten merken, damit wir nicht
1492 			SwFtnFrm  *pLastSib = 0;	//ueber das Ziel hinausschiessen.
1493 
1494 			while ( pSibling && nCmpPos <= nStPos )
1495 			{
1496 				pLastSib = pSibling; // der kommt schon mal in Frage
1497 				nLastPos = nCmpPos;
1498 
1499 				while ( pSibling->GetFollow() )
1500 					pSibling = pSibling->GetFollow();
1501 
1502 				if ( pSibling->GetNext() )
1503 				{
1504 					pSibling = (SwFtnFrm*)pSibling->GetNext();
1505 					ASSERT( !pSibling->GetMaster() || ( ENDNOTE > nStPos &&
1506 							pSibling->GetAttr()->GetFtn().IsEndNote() ),
1507 							"InsertFtn: Master expected I" );
1508 				}
1509 				else
1510 				{
1511 					pNxtB = pSibling->FindFtnBossFrm();
1512 					SwPageFrm *pSibPage = pNxtB->FindPageFrm();
1513 					sal_Bool bEndNote = pSibPage->IsEndNotePage();
1514 					sal_Bool bChgPage = lcl_NextFtnBoss( pNxtB, pSibPage, bDontLeave );
1515 					// Bei Seitenwechsel muss das EndNoteFlag ueberprueft werden.
1516 					SwFtnContFrm *pCont = pNxtB && ( !bChgPage ||
1517 						pSibPage->IsEndNotePage() == bEndNote )
1518 						? pNxtB->FindNearestFtnCont( bDontLeave ) : 0;
1519 					if( pCont )
1520 						pSibling = (SwFtnFrm*)pCont->Lower();
1521 					else // kein weiterer FtnContainer, dann werden  wir uns wohl hinter
1522 						break; // pSibling haengen
1523 				}
1524 				if ( pSibling )
1525 				{
1526 					nCmpPos = ::lcl_FindFtnPos( pDoc, pSibling->GetAttr() );
1527 					ASSERT( nCmpPos > nLastPos, "InsertFtn: Order of FtnFrm's buggy" );
1528 				}
1529 			}
1530 			// pLastSib ist jetzt die letzte Fussnote vor uns,
1531 			// pSibling leer oder die erste nach uns.
1532 			if ( pSibling && pLastSib && (pSibling != pLastSib) )
1533 			{	//Sind wir vielleicht bereits ueber das Ziel hinausgeschossen?
1534 				if ( nCmpPos > nStPos )
1535 					pSibling = pLastSib;
1536 			}
1537 			else if ( !pSibling )
1538 			{	//Eine Chance haben wir noch: wir nehmen einfach die letzte
1539 				//Fussnote im Parent. Ein Sonderfall, der z.B. beim
1540 				//zurueckfliessen von Absaetzen mit mehreren Fussnoten
1541 				//vorkommt.
1542 				//Damit wir nicht die Reihenfolge verwuerfeln muessen wir den
1543 				//Parent der letzten Fussnote, die wir an der Hand hatten benutzen.
1544 				pSibling = pLastSib;
1545 				while( pSibling->GetFollow() )
1546 					pSibling = pSibling->GetFollow();
1547 				ASSERT( !pSibling->GetNext(), "InsertFtn: Who's that guy?" );
1548 			}
1549 		}
1550 	}
1551 	else
1552 	{	//Die erste Fussnote der Spalte/Seite haben wir an der Hand, jetzt ausgehend
1553 		//von dieser die erste zur selben Spalte/Seite suchen deren Index hinter
1554 		//den uebergebenen zeigt, die letzte, die wir an der Hand hatten, ist
1555 		//dann der Vorgaenger.
1556 		SwFtnBossFrm* pBoss = pNew->GetRef()->FindFtnBossFrm(
1557 			!pNew->GetAttr()->GetFtn().IsEndNote() );
1558 		sal_uInt16 nRefNum = pBoss->GetPhyPageNum();	// Die Seiten- und
1559 		sal_uInt16 nRefCol = lcl_ColumnNum( pBoss );    // Spaltennummer der neuen Fussnote
1560 		sal_Bool bEnd = sal_False;
1561 		SwFtnFrm *pLastSib = 0;
1562 		while ( pSibling && !bEnd && (nCmpPos <= nStPos) )
1563 		{
1564 			pLastSib = pSibling;
1565 			nLastPos = nCmpPos;
1566 
1567 			while ( pSibling->GetFollow() )
1568 				pSibling = pSibling->GetFollow();
1569 
1570 			SwFtnFrm *pFoll = (SwFtnFrm*)pSibling->GetNext();
1571 			if ( pFoll )
1572 			{
1573 				pBoss = pSibling->GetRef()->FindFtnBossFrm( !pSibling->
1574 											GetAttr()->GetFtn().IsEndNote() );
1575 				sal_uInt16 nTmpRef;
1576 				if( nStPos >= ENDNOTE ||
1577 					(nTmpRef = pBoss->GetPhyPageNum()) < nRefNum ||
1578 					( nTmpRef == nRefNum && lcl_ColumnNum( pBoss ) <= nRefCol ))
1579 					pSibling = pFoll;
1580 				else
1581 					bEnd = sal_True;
1582 			}
1583 			else
1584 			{
1585 				SwFtnBossFrm* pNxtB = pSibling->FindFtnBossFrm();
1586 				SwPageFrm *pSibPage = pNxtB->FindPageFrm();
1587 				sal_Bool bEndNote = pSibPage->IsEndNotePage();
1588 				sal_Bool bChgPage = lcl_NextFtnBoss( pNxtB, pSibPage, bDontLeave );
1589 				// Bei Seitenwechsel muss das EndNoteFlag ueberprueft werden.
1590 				SwFtnContFrm *pCont = pNxtB && ( !bChgPage ||
1591 					pSibPage->IsEndNotePage() == bEndNote )
1592 					? pNxtB->FindNearestFtnCont( bDontLeave ) : 0;
1593 				if ( pCont )
1594 					pSibling = (SwFtnFrm*)pCont->Lower();
1595 				else
1596 					bEnd = sal_True;
1597 			}
1598 			if ( !bEnd && pSibling )
1599 				nCmpPos = ::lcl_FindFtnPos( pDoc, pSibling->GetAttr() );
1600 			if ( pSibling && pLastSib && (pSibling != pLastSib) )
1601 			{	//Sind wir vielleicht bereits ueber das Ziel hinausgeschossen?
1602 				if ( (nLastPos < nCmpPos) && (nCmpPos > nStPos) )
1603 				{
1604 					pSibling = pLastSib;
1605 					bEnd = sal_True;
1606 				}
1607 			}
1608 		}
1609 	}
1610 	if ( pSibling )
1611 	{
1612 		nCmpPos = ::lcl_FindFtnPos( pDoc, pSibling->GetAttr() );
1613 		if ( nCmpPos < nStPos )
1614 		{
1615 			while ( pSibling->GetFollow() )
1616 				pSibling = pSibling->GetFollow();
1617 			pParent = (SwFtnContFrm*)pSibling->GetUpper();
1618 			pSibling = (SwFtnFrm*)pSibling->GetNext();
1619 		}
1620 		else
1621 		{
1622 			if( pSibling->GetMaster() )
1623 			{
1624 				if( ENDNOTE > nCmpPos || nStPos >= ENDNOTE )
1625 				{
1626 					ASSERT( sal_False, "InsertFtn: Master expected II" );
1627 					do
1628 						pSibling = pSibling->GetMaster();
1629 					while ( pSibling->GetMaster() );
1630 				}
1631 			}
1632 			pParent = (SwFtnContFrm*)pSibling->GetUpper();
1633 		}
1634 	}
1635 	ASSERT( pParent, "paste in space?" );
1636 	pNew->Paste( pParent, pSibling );
1637 }
1638 
1639 /*************************************************************************
1640 |*
1641 |*	SwFtnBossFrm::AppendFtn()
1642 |*
1643 |*************************************************************************/
1644 
1645 
1646 void SwFtnBossFrm::AppendFtn( SwCntntFrm *pRef, SwTxtFtn *pAttr )
1647 {
1648 	//Wenn es die Fussnote schon gibt tun wir nix.
1649 	if ( FindFtn( pRef, pAttr ) )
1650 		return;
1651 
1652 	//Wenn Fussnoten am Dokumentende eingestellt sind, so brauchen wir 'eh erst
1653 	//ab der entsprechenden Seite zu suchen.
1654 	//Wenn es noch keine gibt, muss eben eine erzeugt werden.
1655 	//Wenn es sich um eine Endnote handelt, muss eine Endnotenseite gesucht
1656 	//bzw. erzeugt werden.
1657 	SwDoc *pDoc = GetFmt()->GetDoc();
1658 	SwFtnBossFrm *pBoss = this;
1659 	SwPageFrm *pPage = FindPageFrm();
1660 	SwPageFrm *pMyPage = pPage;
1661 	sal_Bool bChgPage = sal_False;
1662 	sal_Bool bEnd = sal_False;
1663 	if ( pAttr->GetFtn().IsEndNote() )
1664 	{
1665 		bEnd = sal_True;
1666 		if( GetUpper()->IsSctFrm() &&
1667 			((SwSectionFrm*)GetUpper())->IsEndnAtEnd() )
1668 		{
1669 			SwFrm* pLast =
1670 				((SwSectionFrm*)GetUpper())->FindLastCntnt( FINDMODE_ENDNOTE );
1671 			if( pLast )
1672 			{
1673 				pBoss = pLast->FindFtnBossFrm();
1674 				pPage = pBoss->FindPageFrm();
1675 			}
1676 		}
1677 		else
1678 		{
1679 			while ( pPage->GetNext() && !pPage->IsEndNotePage() )
1680 			{
1681 				pPage = (SwPageFrm*)pPage->GetNext();
1682 				bChgPage = sal_True;
1683 			}
1684 			if ( !pPage->IsEndNotePage() )
1685 			{
1686 				SwPageDesc *pDesc = pDoc->GetEndNoteInfo().GetPageDesc( *pDoc );
1687 				pPage = ::InsertNewPage( *pDesc, pPage->GetUpper(),
1688 						!pPage->OnRightPage(), sal_False, sal_True, 0 );
1689 				pPage->SetEndNotePage( sal_True );
1690 				bChgPage = sal_True;
1691 			}
1692 			else
1693 			{
1694 				//Wir koennen wenigstens schon mal ungefaehr die richtige Seite
1695 				//suchen. Damit stellen wir sicher das wir auch bei hunderten
1696 				//Fussnoten noch in endlicher Zeit fertig werden.
1697 				SwPageFrm *pNxt = (SwPageFrm*)pPage->GetNext();
1698 				const sal_uLong nStPos = ::lcl_FindFtnPos( pDoc, pAttr );
1699 				while ( pNxt && pNxt->IsEndNotePage() )
1700 				{
1701 					SwFtnContFrm *pCont = pNxt->FindFtnCont();
1702 					if ( pCont && pCont->Lower() )
1703 					{
1704 						ASSERT( pCont->Lower()->IsFtnFrm(), "Keine Ftn im Container" );
1705 						if ( nStPos > ::lcl_FindFtnPos( pDoc,
1706 										((SwFtnFrm*)pCont->Lower())->GetAttr()))
1707 						{
1708 							pPage = pNxt;
1709 							pNxt = (SwPageFrm*)pPage->GetNext();
1710 							continue;
1711 						}
1712 					}
1713 					break;
1714 				}
1715 			}
1716 		}
1717 	}
1718 	else if( FTNPOS_CHAPTER == pDoc->GetFtnInfo().ePos && ( !GetUpper()->
1719 			 IsSctFrm() || !((SwSectionFrm*)GetUpper())->IsFtnAtEnd() ) )
1720 	{
1721 		while ( pPage->GetNext() && !pPage->IsFtnPage() &&
1722 				!((SwPageFrm*)pPage->GetNext())->IsEndNotePage() )
1723 		{
1724 			pPage = (SwPageFrm*)pPage->GetNext();
1725 			bChgPage = sal_True;
1726 		}
1727 
1728 		if ( !pPage->IsFtnPage() )
1729 		{
1730 			SwPageDesc *pDesc = pDoc->GetFtnInfo().GetPageDesc( *pDoc );
1731 			pPage = ::InsertNewPage( *pDesc, pPage->GetUpper(),
1732 				!pPage->OnRightPage(), sal_False, sal_True, pPage->GetNext() );
1733 			bChgPage = sal_True;
1734 		}
1735 		else
1736 		{
1737 			//Wir koennen wenigstens schon mal ungefaehr die richtige Seite
1738 			//suchen. Damit stellen wir sicher das wir auch bei hunderten
1739 			//Fussnoten noch in endlicher Zeit fertig werden.
1740 			SwPageFrm *pNxt = (SwPageFrm*)pPage->GetNext();
1741 			const sal_uLong nStPos = ::lcl_FindFtnPos( pDoc, pAttr );
1742 			while ( pNxt && pNxt->IsFtnPage() && !pNxt->IsEndNotePage() )
1743 			{
1744 				SwFtnContFrm *pCont = pNxt->FindFtnCont();
1745 				if ( pCont && pCont->Lower() )
1746 				{
1747 					ASSERT( pCont->Lower()->IsFtnFrm(), "Keine Ftn im Container" );
1748 					if ( nStPos > ::lcl_FindFtnPos( pDoc,
1749 										((SwFtnFrm*)pCont->Lower())->GetAttr()))
1750 					{
1751 						pPage = pNxt;
1752 						pNxt = (SwPageFrm*)pPage->GetNext();
1753 						continue;
1754 					}
1755 				}
1756 				break;
1757 			}
1758 		}
1759 	}
1760 
1761 	//Erstmal eine Fussnote und die benoetigten CntntFrms anlegen.
1762 	if ( !pAttr->GetStartNode() )
1763 	{	ASSERT( !this, "Kein Fussnoteninhalt." );
1764 		return;
1765 	}
1766 
1767 	// Wenn es auf der Seite/Spalte bereits einen FtnCont gibt,
1768 	// kann in einen spaltigen Bereich keiner erzeugt werden.
1769 	if( pBoss->IsInSct() && pBoss->IsColumnFrm() && !pPage->IsFtnPage() )
1770 	{
1771 		SwSectionFrm* pSct = pBoss->FindSctFrm();
1772 		if( bEnd ? !pSct->IsEndnAtEnd() : !pSct->IsFtnAtEnd() )
1773 		{
1774 			SwFtnContFrm* pFtnCont = pSct->FindFtnBossFrm(!bEnd)->FindFtnCont();
1775 			if( pFtnCont )
1776 			{
1777 				SwFtnFrm* pTmp = (SwFtnFrm*)pFtnCont->Lower();
1778 				if( bEnd )
1779 					while( pTmp && !pTmp->GetAttr()->GetFtn().IsEndNote() )
1780 						pTmp = (SwFtnFrm*)pTmp->GetNext();
1781 				if( pTmp && *pTmp < pAttr )
1782 					return;
1783 			}
1784 		}
1785 	}
1786 
1787 	SwFtnFrm *pNew = new SwFtnFrm( pDoc->GetDfltFrmFmt(), this, pRef, pAttr );
1788 	{
1789 		SwNodeIndex aIdx( *pAttr->GetStartNode(), 1 );
1790 		::_InsertCnt( pNew, pDoc, aIdx.GetIndex() );
1791 	}
1792 	// Wenn die Seite gewechselt (oder gar neu angelegt) wurde,
1793 	// muessen wir uns dort in die erste Spalte setzen
1794 	if( bChgPage )
1795 	{
1796 		SwLayoutFrm* pBody = pPage->FindBodyCont();
1797 		ASSERT( pBody, "AppendFtn: NoPageBody?" );
1798 		if( pBody->Lower() && pBody->Lower()->IsColumnFrm() )
1799 			pBoss = (SwFtnBossFrm*)pBody->Lower();
1800 		else
1801 			pBoss = pPage; // bei nichtspaltigen Seiten auf die Seite selbst
1802 	}
1803 	pBoss->InsertFtn( pNew );
1804 	if ( pNew->GetUpper() ) 		//Eingesetzt oder nicht?
1805 	{
1806 		::RegistFlys( pNew->FindPageFrm(), pNew );
1807 		SwSectionFrm* pSect = FindSctFrm();
1808 		// Der Inhalt des FtnContainers in einem (spaltigen) Bereich
1809 		// braucht nur kalkuliert zu werden,
1810 		// wenn der Bereich bereits bis zur Unterkante seines Uppers geht.
1811 		if( pSect && !pSect->IsJoinLocked() && ( bEnd ? !pSect->IsEndnAtEnd() :
1812 			!pSect->IsFtnAtEnd() ) && pSect->Growable() )
1813 			pSect->InvalidateSize();
1814 		else
1815 		{
1816             // --> OD 2005-05-18 #i49383# - disable unlock of position of
1817             // lower objects during format of footnote content.
1818             const bool bOldFtnFrmLocked( pNew->IsColLocked() );
1819             pNew->ColLock();
1820             pNew->KeepLockPosOfLowerObjs();
1821             // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
1822             // no extra notify for footnote frame
1823 //            SwLayNotify* pFtnFrmNotitfy = new SwLayNotify( pNew );
1824             // <--
1825 			SwCntntFrm *pCnt = pNew->ContainsCntnt();
1826 			while ( pCnt &&	pCnt->FindFtnFrm()->GetAttr() == pAttr )
1827 			{
1828                 pCnt->Calc();
1829                 // --> OD 2005-05-17 #i49383# - format anchored objects
1830                 if ( pCnt->IsTxtFrm() && pCnt->IsValid() )
1831                 {
1832                     if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt,
1833                                                               *(pCnt->FindPageFrm()) ) )
1834                     {
1835                         // restart format with first content
1836                         pCnt = pNew->ContainsCntnt();
1837                         continue;
1838                     }
1839                 }
1840                 // <--
1841 				pCnt = (SwCntntFrm*)pCnt->FindNextCnt();
1842 			}
1843             // --> OD 2005-05-18 #i49383#
1844             if ( !bOldFtnFrmLocked )
1845             {
1846                 pNew->ColUnlock();
1847             }
1848             // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
1849             // enable lock of lower object position before format of footnote frame.
1850             pNew->UnlockPosOfLowerObjs();
1851             // <--
1852             pNew->Calc();
1853             // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
1854             // no extra notify for footnote frame
1855 //            pNew->UnlockPosOfLowerObjs();
1856 //            delete pFtnFrmNotitfy;
1857             // <--
1858             if ( !bOldFtnFrmLocked && !pNew->GetLower() &&
1859                  !pNew->IsColLocked() && !pNew->IsBackMoveLocked() )
1860             {
1861                 pNew->Cut();
1862                 delete pNew;
1863             }
1864             // <--
1865 		}
1866 		pMyPage->UpdateFtnNum();
1867 	}
1868 	else
1869 		delete pNew;
1870 }
1871 /*************************************************************************
1872 |*
1873 |*	SwFtnBossFrm::FindFtn()
1874 |*
1875 |*************************************************************************/
1876 
1877 
1878 SwFtnFrm *SwFtnBossFrm::FindFtn( const SwCntntFrm *pRef, const SwTxtFtn *pAttr )
1879 {
1880 	//Der einfachste und sicherste Weg geht ueber das Attribut.
1881 	ASSERT( pAttr->GetStartNode(), "FtnAtr ohne StartNode." );
1882 	SwNodeIndex aIdx( *pAttr->GetStartNode(), 1 );
1883 	SwCntntNode *pNd = aIdx.GetNode().GetCntntNode();
1884 	if ( !pNd )
1885 		pNd = pRef->GetAttrSet()->GetDoc()->
1886 			  GetNodes().GoNextSection( &aIdx, sal_True, sal_False );
1887 	if ( !pNd )
1888 		return 0;
1889 	SwIterator<SwFrm,SwCntntNode> aIter( *pNd );
1890     SwFrm* pFrm = aIter.First();
1891 	if( pFrm )
1892 		do
1893 		{
1894 				pFrm = pFrm->GetUpper();
1895                 // #i28500#, #i27243# Due to the endnode collector, there are
1896                 // SwFtnFrms, which are not in the layout. Therefore the
1897                 // bInfFtn flags are not set correctly, and a cell of FindFtnFrm
1898                 // would return 0. Therefore we better call ImplFindFtnFrm().
1899 				SwFtnFrm *pFtn = pFrm->ImplFindFtnFrm();
1900 				if ( pFtn && pFtn->GetRef() == pRef )
1901 				{
1902 					// The following condition becomes true, if the whole
1903 					// footnotecontent is a section. While no frames exist,
1904 					// the HiddenFlag of the section is set, this causes
1905 					// the GoNextSection-function leaves the footnote.
1906 					if( pFtn->GetAttr() != pAttr )
1907 						return 0;
1908 					while ( pFtn && pFtn->GetMaster() )
1909 						pFtn = pFtn->GetMaster();
1910 					return pFtn;
1911 				}
1912 
1913 		} while ( 0 != (pFrm = aIter.Next()) );
1914 
1915 	return 0;
1916 }
1917 /*************************************************************************
1918 |*
1919 |*	SwFtnBossFrm::RemoveFtn()
1920 |*
1921 |*************************************************************************/
1922 
1923 
1924 void SwFtnBossFrm::RemoveFtn( const SwCntntFrm *pRef, const SwTxtFtn *pAttr,
1925 							  sal_Bool bPrep )
1926 {
1927 	SwFtnFrm *pFtn = FindFtn( pRef, pAttr );
1928 	if( pFtn )
1929 	{
1930 		do
1931 		{
1932 			SwFtnFrm *pFoll = pFtn->GetFollow();
1933 			pFtn->Cut();
1934 			delete pFtn;
1935 			pFtn = pFoll;
1936 		} while ( pFtn );
1937 		if( bPrep && pRef->IsFollow() )
1938 		{
1939 			ASSERT( pRef->IsTxtFrm(), "NoTxtFrm has Footnote?" );
1940 			SwTxtFrm* pMaster = (SwTxtFrm*)pRef->FindMaster();
1941 			if( !pMaster->IsLocked() )
1942 				pMaster->Prepare( PREP_FTN_GONE );
1943 		}
1944 	}
1945 	FindPageFrm()->UpdateFtnNum();
1946 }
1947 
1948 /*************************************************************************
1949 |*
1950 |*	SwFtnBossFrm::ChangeFtnRef()
1951 |*
1952 |*************************************************************************/
1953 
1954 
1955 void SwFtnBossFrm::ChangeFtnRef( const SwCntntFrm *pOld, const SwTxtFtn *pAttr,
1956 								 SwCntntFrm *pNew )
1957 {
1958 	SwFtnFrm *pFtn = FindFtn( pOld, pAttr );
1959 	while ( pFtn )
1960 	{
1961 		pFtn->SetRef( pNew );
1962 		pFtn = pFtn->GetFollow();
1963 	}
1964 }
1965 
1966 /*************************************************************************
1967 |*
1968 |*	SwFtnBossFrm::CollectFtns()
1969 |*
1970 |*************************************************************************/
1971 
1972 
1973 /// OD 03.04.2003 #108446# - add parameter <_bCollectOnlyPreviousFtns> in
1974 /// order to control, if only footnotes, which are positioned before the
1975 /// footnote boss frame <this> have to be collected.
1976 void SwFtnBossFrm::CollectFtns( const SwCntntFrm* _pRef,
1977                                 SwFtnBossFrm*     _pOld,
1978                                 SvPtrarr&         _rFtnArr,
1979                                 const sal_Bool    _bCollectOnlyPreviousFtns )
1980 {
1981     SwFtnFrm *pFtn = _pOld->FindFirstFtn();
1982 	while( !pFtn )
1983 	{
1984         if( _pOld->IsColumnFrm() )
1985 		{   // Spalten abklappern
1986             while ( !pFtn && _pOld->GetPrev() )
1987 			{
1988 				//Wenn wir keine Fussnote gefunden haben, ist noch nicht alles zu
1989 				//spaet. Die Schleife wird beim Aufnehmen von Follow-Zeilen durch
1990 				//Tabellen benoetigt. Fuer alle anderen Faelle ist sie in der Lage
1991 				//'krumme' Verhaeltnisse zu korrigieren.
1992                 _pOld = (SwFtnBossFrm*)_pOld->GetPrev();
1993                 pFtn = _pOld->FindFirstFtn();
1994 			}
1995 		}
1996 		if( !pFtn )
1997 		{
1998 			//  vorherige Seite
1999 			SwPageFrm* pPg;
2000             for ( SwFrm* pTmp = _pOld;
2001                   0 != ( pPg = (SwPageFrm*)pTmp->FindPageFrm()->GetPrev())
2002                     && pPg->IsEmptyPage() ;
2003                 )
2004             {
2005 				pTmp = pPg;
2006             }
2007 			if( !pPg )
2008 				return;
2009 
2010 			SwLayoutFrm* pBody = pPg->FindBodyCont();
2011 			if( pBody->Lower() && pBody->Lower()->IsColumnFrm() )
2012             {
2013                 // mehrspaltige Seite => letzte Spalte suchen
2014                 _pOld = static_cast<SwFtnBossFrm*>(pBody->GetLastLower());
2015             }
2016 			else
2017                 _pOld = pPg; // einspaltige Seite
2018             pFtn = _pOld->FindFirstFtn();
2019 		}
2020 	}
2021     // OD 03.04.2003 #108446# - consider new parameter <_bCollectOnlyPreviousFtns>
2022     SwFtnBossFrm* pRefBossFrm = NULL;
2023     if ( _bCollectOnlyPreviousFtns )
2024     {
2025         pRefBossFrm = this;
2026     }
2027     _CollectFtns( _pRef, pFtn, _rFtnArr, _bCollectOnlyPreviousFtns, pRefBossFrm );
2028 }
2029 
2030 
2031 /*************************************************************************
2032 |*
2033 |*	SwFtnBossFrm::_CollectFtns()
2034 |*
2035 |*************************************************************************/
2036 inline void FtnInArr( SvPtrarr& rFtnArr, SwFtnFrm* pFtn )
2037 {
2038 	if ( USHRT_MAX == rFtnArr.GetPos( (VoidPtr)pFtn ) )
2039 		rFtnArr.Insert( (VoidPtr)pFtn, rFtnArr.Count() );
2040 }
2041 
2042 /// OD 03.04.2003 #108446# - add parameters <_bCollectOnlyPreviousFtns> and
2043 /// <_pRefFtnBossFrm> in order to control, if only footnotes, which are positioned
2044 /// before the given reference footnote boss frame have to be collected.
2045 /// Note: if parameter <_bCollectOnlyPreviousFtns> is true, then parameter
2046 /// <_pRefFtnBossFrm> have to be referenced to an object.
2047 /// Adjust parameter names.
2048 void SwFtnBossFrm::_CollectFtns( const SwCntntFrm*   _pRef,
2049                                  SwFtnFrm*           _pFtn,
2050                                  SvPtrarr&           _rFtnArr,
2051                                  sal_Bool            _bCollectOnlyPreviousFtns,
2052                                  const SwFtnBossFrm* _pRefFtnBossFrm)
2053 {
2054     // OD 03.04.2003 #108446# - assert, that no reference footnote boss frame
2055     // is set, in spite of the order, that only previous footnotes has to be
2056     // collected.
2057     ASSERT( !_bCollectOnlyPreviousFtns || _pRefFtnBossFrm,
2058             "<SwFtnBossFrm::_CollectFtns(..)> - No reference footnote boss frame for collecting only previous footnotes set.\nCrash will be caused!" );
2059 
2060     //Alle Fussnoten die von pRef referenziert werden nacheinander
2061 	//einsammeln (Attribut fuer Attribut), zusammengefuegen
2062 	//(der Inhalt zu einem Attribut kann ueber mehrere Seiten verteilt sein)
2063 	//und ausschneiden.
2064 
2065 	SvPtrarr aNotFtnArr( 20, 20 );	//Zur Robustheit werden hier die nicht
2066 									//dazugehoerigen Fussnoten eingetragen.
2067 									//Wenn eine Fussnote zweimal angefasst wird
2068 									//ists vorbei! So kommt die Funktion auch
2069 									//noch mit einem kaputten Layout
2070 									//einigermassen (ohne Schleife und Absturz)
2071 									//"klar".
2072 
2073 	//Hier sollte keiner mit einer Follow-Ftn ankommen, es sei denn er hat
2074 	//ernste Absichten (:-)); spricht er kommt mit einer Ftn an die vor der
2075 	//ersten der Referenz liegt.
2076     ASSERT( !_pFtn->GetMaster() || _pFtn->GetRef() != _pRef, "FollowFtn moven?" );
2077     while ( _pFtn->GetMaster() )
2078         _pFtn = _pFtn->GetMaster();
2079 
2080 	sal_Bool bFound = sal_False;
2081 
2082     while ( _pFtn )
2083 	{
2084 		//Erstmal die naechste Fussnote der Spalte/Seite suchen, damit wir nicht
2085 		//nach dem Cut jeder Fussnote von vorn anfangen muessen.
2086         SwFtnFrm *pNxtFtn = _pFtn;
2087 		while ( pNxtFtn->GetFollow() )
2088 			pNxtFtn = pNxtFtn->GetFollow();
2089 		pNxtFtn = (SwFtnFrm*)pNxtFtn->GetNext();
2090 
2091 		if ( !pNxtFtn )
2092 		{
2093             SwFtnBossFrm* pBoss = _pFtn->FindFtnBossFrm();
2094 			SwPageFrm* pPage = pBoss->FindPageFrm();
2095 			do
2096 			{
2097 				lcl_NextFtnBoss( pBoss, pPage, sal_False );
2098 				if( pBoss )
2099 				{
2100 					SwLayoutFrm* pCont = pBoss->FindFtnCont();
2101 					if( pCont )
2102 					{
2103 						pNxtFtn = (SwFtnFrm*)pCont->Lower();
2104 						if( pNxtFtn )
2105 						{
2106 							while( pNxtFtn->GetMaster() )
2107 								pNxtFtn = pNxtFtn->GetMaster();
2108                             if( pNxtFtn == _pFtn )
2109 								pNxtFtn = NULL;
2110 						}
2111 					}
2112 				}
2113 			} while( !pNxtFtn && pBoss );
2114 		}
2115 		else if( !pNxtFtn->GetAttr()->GetFtn().IsEndNote() )
2116 		{	ASSERT( !pNxtFtn->GetMaster(), "_CollectFtn: Master exspected" );
2117 			while ( pNxtFtn->GetMaster() )
2118 				pNxtFtn = pNxtFtn->GetMaster();
2119 		}
2120         if ( pNxtFtn == _pFtn )
2121 		{
2122 			ASSERT(	sal_False, "_CollectFtn: Devil's circle" );
2123 			pNxtFtn = 0;
2124 		}
2125 
2126         // OD 03.04.2003 #108446# - determine, if found footnote has to be collected.
2127         sal_Bool bCollectFoundFtn = sal_False;
2128         if ( _pFtn->GetRef() == _pRef && !_pFtn->GetAttr()->GetFtn().IsEndNote() )
2129 		{
2130             if ( _bCollectOnlyPreviousFtns )
2131             {
2132                 SwFtnBossFrm* pBossOfFoundFtn = _pFtn->FindFtnBossFrm( sal_True );
2133                 ASSERT( pBossOfFoundFtn,
2134                         "<SwFtnBossFrm::_CollectFtns(..)> - footnote boss frame of found footnote frame missing.\nWrong layout!" );
2135                 if ( !pBossOfFoundFtn ||    // don't crash, if no footnote boss is found.
2136                      pBossOfFoundFtn->IsBefore( _pRefFtnBossFrm )
2137                    )
2138                 {
2139                     bCollectFoundFtn = sal_True;
2140                 }
2141             }
2142             else
2143             {
2144                 bCollectFoundFtn = sal_True;
2145             }
2146         }
2147 
2148         if ( bCollectFoundFtn )
2149         {
2150             ASSERT( !_pFtn->GetMaster(), "FollowFtn moven?" );
2151             SwFtnFrm *pNxt = _pFtn->GetFollow();
2152 			while ( pNxt )
2153 			{
2154 				SwFrm *pCnt = pNxt->ContainsAny();
2155 				if ( pCnt )
2156 				{	//Unterwegs wird der Follow zerstoert weil er leer wird!
2157 					do
2158 					{	SwFrm *pNxtCnt = pCnt->GetNext();
2159 						pCnt->Cut();
2160                         pCnt->Paste( _pFtn );
2161 						pCnt = pNxtCnt;
2162 					} while ( pCnt );
2163 				}
2164 				else
2165 				{	ASSERT( !pNxt, "Fussnote ohne Inhalt?" );
2166 					pNxt->Cut();
2167 					delete pNxt;
2168 				}
2169                 pNxt = _pFtn->GetFollow();
2170 			}
2171             _pFtn->Cut();
2172             FtnInArr( _rFtnArr, _pFtn );
2173 			bFound = sal_True;
2174 		}
2175 		else
2176 		{
2177             FtnInArr( aNotFtnArr, _pFtn );
2178 			if( bFound )
2179 				break;
2180 		}
2181 		if ( pNxtFtn &&
2182              USHRT_MAX == _rFtnArr.GetPos( (VoidPtr)pNxtFtn ) &&
2183 			 USHRT_MAX == aNotFtnArr.GetPos( (VoidPtr)pNxtFtn ) )
2184             _pFtn = pNxtFtn;
2185 		else
2186 			break;
2187 	}
2188 }
2189 
2190 /*************************************************************************
2191 |*
2192 |*	SwFtnBossFrm::_MoveFtns()
2193 |*
2194 |*************************************************************************/
2195 
2196 
2197 void SwFtnBossFrm::_MoveFtns( SvPtrarr &rFtnArr, sal_Bool bCalc )
2198 {
2199 	//Alle Fussnoten die von pRef referenziert werden muessen von der
2200 	//aktuellen Position, die sich durch die alte Spalte/Seite ergab, auf eine
2201 	//neue Position, bestimmt durch die neue Spalte/Seite, gemoved werden.
2202 	const sal_uInt16 nMyNum = FindPageFrm()->GetPhyPageNum();
2203 	const sal_uInt16 nMyCol = lcl_ColumnNum( this );
2204     SWRECTFN( this )
2205 
2206     // --> OD 2004-06-11 #i21478# - keep last inserted footnote in order to
2207     // format the content of the following one.
2208     SwFtnFrm* pLastInsertedFtn = 0L;
2209     for ( sal_uInt16 i = 0; i < rFtnArr.Count(); ++i )
2210 	{
2211 		SwFtnFrm *pFtn = (SwFtnFrm*)rFtnArr[i];
2212 
2213 		SwFtnBossFrm* pRefBoss = pFtn->GetRef()->FindFtnBossFrm( sal_True );
2214 		if( pRefBoss != this )
2215 		{
2216 			const sal_uInt16 nRefNum = pRefBoss->FindPageFrm()->GetPhyPageNum();
2217 			const sal_uInt16 nRefCol = lcl_ColumnNum( this );
2218 			if( nRefNum < nMyNum || ( nRefNum == nMyNum && nRefCol <= nMyCol ) )
2219 				pRefBoss = this;
2220 		}
2221 		pRefBoss->InsertFtn( pFtn );
2222 
2223 		if ( pFtn->GetUpper() ) //Robust, z.B. bei doppelten
2224 		{
2225 			// Damit FtnFrms, die nicht auf die Seite passen, nicht fuer zuviel
2226 			// Unruhe sorgen (Loop 66312), wird ihr Inhalt zunaechst zusammengestaucht.
2227 			// Damit wird der FtnCont erst gegrowt, wenn der Inhalt formatiert wird
2228 			// und feststellt, dass er auf die Seite passt.
2229 			SwFrm *pCnt = pFtn->ContainsAny();
2230 			while( pCnt )
2231 			{
2232 				if( pCnt->IsLayoutFrm() )
2233 				{
2234 					SwFrm* pTmp = ((SwLayoutFrm*)pCnt)->ContainsAny();
2235 					while( pTmp && ((SwLayoutFrm*)pCnt)->IsAnLower( pTmp ) )
2236 					{
2237 						pTmp->Prepare( PREP_MOVEFTN );
2238                         (pTmp->Frm().*fnRect->fnSetHeight)(0);
2239                         (pTmp->Prt().*fnRect->fnSetHeight)(0);
2240 						pTmp = pTmp->FindNext();
2241 					}
2242 				}
2243 				else
2244 					pCnt->Prepare( PREP_MOVEFTN );
2245                 (pCnt->Frm().*fnRect->fnSetHeight)(0);
2246                 (pCnt->Prt().*fnRect->fnSetHeight)(0);
2247 				pCnt = pCnt->GetNext();
2248 			}
2249             (pFtn->Frm().*fnRect->fnSetHeight)(0);
2250             (pFtn->Prt().*fnRect->fnSetHeight)(0);
2251 			pFtn->Calc();
2252 			pFtn->GetUpper()->Calc();
2253 
2254 			if( bCalc )
2255 			{
2256 				SwTxtFtn *pAttr = pFtn->GetAttr();
2257 				pCnt = pFtn->ContainsAny();
2258                 sal_Bool bUnlock = !pFtn->IsBackMoveLocked();
2259 				pFtn->LockBackMove();
2260 
2261                 // --> OD 2005-05-18 #i49383# - disable unlock of position of
2262                 // lower objects during format of footnote content.
2263                 pFtn->KeepLockPosOfLowerObjs();
2264                 // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
2265                 // no extra notify for footnote frame
2266 //                SwLayNotify aFtnFrmNotitfy( pFtn );
2267                 // <--
2268 
2269 				while ( pCnt &&	pCnt->FindFtnFrm()->GetAttr() == pAttr )
2270 				{
2271 					pCnt->_InvalidatePos();
2272 					pCnt->Calc();
2273                     // --> OD 2005-05-17 #i49383# - format anchored objects
2274                     if ( pCnt->IsTxtFrm() && pCnt->IsValid() )
2275                     {
2276                         if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt,
2277                                                                   *(pCnt->FindPageFrm()) ) )
2278                         {
2279                             // restart format with first content
2280                             pCnt = pFtn->ContainsAny();
2281                             continue;
2282                         }
2283                     }
2284                     // <--
2285 					if( pCnt->IsSctFrm() )
2286 					{   // Wenn es sich um einen nichtleeren Bereich handelt,
2287 						// iterieren wir auch ueber seinen Inhalt
2288 						SwFrm* pTmp = ((SwSectionFrm*)pCnt)->ContainsAny();
2289 						if( pTmp )
2290 							pCnt = pTmp;
2291 						else
2292 							pCnt = pCnt->FindNext();
2293 					}
2294 					else
2295 						pCnt = pCnt->FindNext();
2296 				}
2297                 if( bUnlock )
2298                 {
2299                     pFtn->UnlockBackMove();
2300                     if( !pFtn->ContainsAny() && !pFtn->IsColLocked() )
2301                     {
2302                         pFtn->Cut();
2303                         delete pFtn;
2304                         // --> OD 2004-06-10 #i21478#
2305                         pFtn = 0L;
2306                     }
2307                 }
2308                 // --> OD 2005-05-18 #i49383#
2309                 if ( pFtn )
2310                 {
2311                     // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
2312                     // enable lock of lower object position before format of footnote frame.
2313                     pFtn->UnlockPosOfLowerObjs();
2314                     pFtn->Calc();
2315 //                    pFtn->UnlockPosOfLowerObjs();
2316                     // <--
2317                 }
2318                 // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
2319                 // no extra notify for footnote frame
2320 //                else
2321 //                {
2322 //                    aFtnFrmNotitfy.FrmDeleted();
2323 //                }
2324                 // <--
2325 			}
2326 		}
2327 		else
2328 		{	ASSERT( !pFtn->GetMaster() && !pFtn->GetFollow(),
2329 					"DelFtn und Master/Follow?" );
2330 			delete pFtn;
2331             // --> OD 2004-06-10 #i21478#
2332             pFtn = 0L;
2333 		}
2334 
2335         // --> OD 2004-06-10 #i21478#
2336         if ( pFtn )
2337         {
2338             pLastInsertedFtn = pFtn;
2339         }
2340 	}
2341 
2342     // --> OD 2004-06-10 #i21478# - format content of footnote following
2343     // the new inserted ones.
2344     if ( bCalc && pLastInsertedFtn )
2345     {
2346         if ( pLastInsertedFtn->GetNext() )
2347         {
2348             SwFtnFrm* pNextFtn = static_cast<SwFtnFrm*>(pLastInsertedFtn->GetNext());
2349             SwTxtFtn* pAttr = pNextFtn->GetAttr();
2350             SwFrm* pCnt = pNextFtn->ContainsAny();
2351 
2352             sal_Bool bUnlock = !pNextFtn->IsBackMoveLocked();
2353             pNextFtn->LockBackMove();
2354             // --> OD 2005-05-18 #i49383# - disable unlock of position of
2355             // lower objects during format of footnote content.
2356             pNextFtn->KeepLockPosOfLowerObjs();
2357             // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
2358             // no extra notify for footnote frame
2359 //            SwLayNotify aFtnFrmNotitfy( pNextFtn );
2360             // <--
2361 
2362             while ( pCnt && pCnt->FindFtnFrm()->GetAttr() == pAttr )
2363             {
2364                 pCnt->_InvalidatePos();
2365                 pCnt->Calc();
2366                 // --> OD 2005-05-17 #i49383# - format anchored objects
2367                 if ( pCnt->IsTxtFrm() && pCnt->IsValid() )
2368                 {
2369                     if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt,
2370                                                               *(pCnt->FindPageFrm()) ) )
2371                     {
2372                         // restart format with first content
2373                         pCnt = pNextFtn->ContainsAny();
2374                         continue;
2375                     }
2376                 }
2377                 // <--
2378                 if( pCnt->IsSctFrm() )
2379                 {   // Wenn es sich um einen nichtleeren Bereich handelt,
2380                     // iterieren wir auch ueber seinen Inhalt
2381                     SwFrm* pTmp = ((SwSectionFrm*)pCnt)->ContainsAny();
2382                     if( pTmp )
2383                         pCnt = pTmp;
2384                     else
2385                         pCnt = pCnt->FindNext();
2386                 }
2387                 else
2388                     pCnt = pCnt->FindNext();
2389             }
2390             if( bUnlock )
2391             {
2392                 pNextFtn->UnlockBackMove();
2393             }
2394             // --> OD 2005-05-18 #i49383#
2395             // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
2396             // enable lock of lower object position before format of footnote frame.
2397             pNextFtn->UnlockPosOfLowerObjs();
2398             pNextFtn->Calc();
2399 //            pNextFtn->UnlockPosOfLowerObjs();
2400             // <--
2401         }
2402     }
2403 }
2404 
2405 /*************************************************************************
2406 |*
2407 |*	SwFtnBossFrm::MoveFtns()
2408 |*
2409 |*************************************************************************/
2410 
2411 
2412 void SwFtnBossFrm::MoveFtns( const SwCntntFrm *pSrc, SwCntntFrm *pDest,
2413 							 SwTxtFtn *pAttr )
2414 {
2415 	if( ( GetFmt()->GetDoc()->GetFtnInfo().ePos == FTNPOS_CHAPTER &&
2416 		(!GetUpper()->IsSctFrm() || !((SwSectionFrm*)GetUpper())->IsFtnAtEnd()))
2417 		|| pAttr->GetFtn().IsEndNote() )
2418 		return;
2419 
2420 	ASSERT( this == pSrc->FindFtnBossFrm( sal_True ),
2421 			"SwPageFrm::MoveFtns: source frame isn't on that FtnBoss" );
2422 
2423 	SwFtnFrm *pFtn = FindFirstFtn();
2424 	if( pFtn )
2425 	{
2426 		ChangeFtnRef( pSrc, pAttr, pDest );
2427 		SwFtnBossFrm *pDestBoss = pDest->FindFtnBossFrm( sal_True );
2428 		ASSERT( pDestBoss, "+SwPageFrm::MoveFtns: no destination boss" );
2429 		if( pDestBoss ) 	// robust
2430 		{
2431 			SvPtrarr aFtnArr( 5, 5 );
2432 			pDestBoss->_CollectFtns( pDest, pFtn, aFtnArr );
2433 			if ( aFtnArr.Count() )
2434 			{
2435 				pDestBoss->_MoveFtns( aFtnArr, sal_True );
2436 				SwPageFrm* pSrcPage = FindPageFrm();
2437 				SwPageFrm* pDestPage = pDestBoss->FindPageFrm();
2438 				// Nur beim Seitenwechsel FtnNum Updaten
2439 				if( pSrcPage != pDestPage )
2440 				{
2441 					if( pSrcPage->GetPhyPageNum() > pDestPage->GetPhyPageNum() )
2442 						pSrcPage->UpdateFtnNum();
2443 					pDestPage->UpdateFtnNum();
2444 				}
2445 			}
2446 		}
2447 	}
2448 }
2449 
2450 /*************************************************************************
2451 |*
2452 |*	SwFtnBossFrm::RearrangeFtns()
2453 |*
2454 |*************************************************************************/
2455 
2456 
2457 void SwFtnBossFrm::RearrangeFtns( const SwTwips nDeadLine, const sal_Bool bLock,
2458 								  const SwTxtFtn *pAttr )
2459 {
2460 	//Alle Fussnoten der Spalte/Seite dergestalt anformatieren,
2461 	//dass sie ggf. die Spalte/Seite wechseln.
2462 
2463 	SwSaveFtnHeight aSave( this, nDeadLine );
2464 	SwFtnFrm *pFtn = FindFirstFtn();
2465 	if( pFtn && pFtn->GetPrev() && bLock )
2466 	{
2467 		SwFtnFrm* pFirst = (SwFtnFrm*)pFtn->GetUpper()->Lower();
2468 		SwFrm* pCntnt = pFirst->ContainsAny();
2469 		if( pCntnt )
2470 		{
2471             sal_Bool bUnlock = !pFirst->IsBackMoveLocked();
2472 			pFirst->LockBackMove();
2473 			pFirst->Calc();
2474 			pCntnt->Calc();
2475             // --> OD 2005-05-17 #i49383# - format anchored objects
2476             if ( pCntnt->IsTxtFrm() && pCntnt->IsValid() )
2477             {
2478                 SwObjectFormatter::FormatObjsAtFrm( *pCntnt,
2479                                                     *(pCntnt->FindPageFrm()) );
2480             }
2481             // <--
2482             if( bUnlock )
2483                 pFirst->UnlockBackMove();
2484 		}
2485 		pFtn = FindFirstFtn();
2486 	}
2487 	SwDoc *pDoc = GetFmt()->GetDoc();
2488 	const sal_uLong nFtnPos = pAttr ? ::lcl_FindFtnPos( pDoc, pAttr ) : 0;
2489 	SwFrm *pCnt = pFtn ? pFtn->ContainsAny() : 0;
2490 	if ( pCnt )
2491 	{
2492 		sal_Bool bMore = sal_True;
2493 		sal_Bool bStart = pAttr == 0; // wenn kein Attribut uebergeben wird, alle bearbeiten
2494         // --> OD 2005-05-18 #i49383# - disable unlock of position of
2495         // lower objects during format of footnote and footnote content.
2496         SwFtnFrm* pLastFtnFrm( 0L );
2497         // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
2498         // no extra notify for footnote frame
2499 //        SwLayNotify* pFtnFrmNotify( 0L );
2500         // footnote frame needs to be locked, if <bLock> isn't set.
2501         bool bUnlockLastFtnFrm( false );
2502         // <--
2503 		do
2504 		{
2505             if( !bStart )
2506 				bStart = ::lcl_FindFtnPos( pDoc, pCnt->FindFtnFrm()->GetAttr() )
2507 						 == nFtnPos;
2508 			if( bStart )
2509             {
2510                 pCnt->_InvalidatePos();
2511 				pCnt->_InvalidateSize();
2512 				pCnt->Prepare( PREP_ADJUST_FRM );
2513                 SwFtnFrm* pFtnFrm = pCnt->FindFtnFrm();
2514                 // --> OD 2005-05-18 #i49383#
2515                 if ( pFtnFrm != pLastFtnFrm )
2516                 {
2517                     if ( pLastFtnFrm )
2518                     {
2519                         if ( !bLock && bUnlockLastFtnFrm )
2520                         {
2521                             pLastFtnFrm->ColUnlock();
2522                         }
2523                         // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
2524                         // enable lock of lower object position before format of footnote frame.
2525                         pLastFtnFrm->UnlockPosOfLowerObjs();
2526                         pLastFtnFrm->Calc();
2527 //                        pLastFtnFrm->UnlockPosOfLowerObjs();
2528                         // no extra notify for footnote frame
2529 //                        delete pFtnFrmNotify;
2530                         // <--
2531                         if ( !bLock && bUnlockLastFtnFrm &&
2532                              !pLastFtnFrm->GetLower() &&
2533                              !pLastFtnFrm->IsColLocked() &&
2534                              !pLastFtnFrm->IsBackMoveLocked() )
2535                         {
2536                             pLastFtnFrm->Cut();
2537                             delete pLastFtnFrm;
2538                             pLastFtnFrm = 0L;
2539                         }
2540                     }
2541                     if ( !bLock )
2542                     {
2543                         bUnlockLastFtnFrm = !pFtnFrm->IsColLocked();
2544                         pFtnFrm->ColLock();
2545                     }
2546                     pFtnFrm->KeepLockPosOfLowerObjs();
2547                     pLastFtnFrm = pFtnFrm;
2548                     // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
2549                     // no extra notify for footnote frame
2550 //                    pFtnFrmNotify = new SwLayNotify( pLastFtnFrm );
2551                     // <--
2552                 }
2553                 // <--
2554                 // OD 30.10.2002 #97265# - invalidate position of footnote
2555                 // frame, if it's below its footnote container, in order to
2556                 // assure its correct position, probably calculating its previous
2557                 // footnote frames.
2558                 {
2559                     SWRECTFN( this );
2560                     SwFrm* aFtnContFrm = pFtnFrm->GetUpper();
2561                     if ( (pFtnFrm->Frm().*fnRect->fnTopDist)((aFtnContFrm->*fnRect->fnGetPrtBottom)()) > 0 )
2562                     {
2563                         pFtnFrm->_InvalidatePos();
2564                     }
2565                 }
2566                 if ( bLock )
2567 				{
2568                     sal_Bool bUnlock = !pFtnFrm->IsBackMoveLocked();
2569                     pFtnFrm->LockBackMove();
2570                     pFtnFrm->Calc();
2571 					pCnt->Calc();
2572                     // --> OD 2005-05-17 #i49383# - format anchored objects
2573                     if ( pCnt->IsTxtFrm() && pCnt->IsValid() )
2574                     {
2575                         if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt,
2576                                                                   *(pCnt->FindPageFrm()) ) )
2577                         {
2578                             // restart format with first content
2579                             pCnt = pFtn->ContainsAny();
2580                             continue;
2581                         }
2582                     }
2583                     // <--
2584                     if( bUnlock )
2585                     {
2586                         pFtnFrm->UnlockBackMove();
2587                         if( !pFtnFrm->Lower() &&
2588                             !pFtnFrm->IsColLocked() )
2589                         {
2590                             // --> OD 2005-08-10 #i49383#
2591                             ASSERT( pLastFtnFrm == pFtnFrm,
2592                                     "<SwFtnBossFrm::RearrangeFtns(..)> - <pLastFtnFrm> != <pFtnFrm>" );
2593                             pLastFtnFrm = 0L;
2594                             // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
2595                             // no extra notify for footnote frame
2596 //                            pFtnFrmNotify->FrmDeleted();
2597 //                            delete pFtnFrmNotify;
2598                             // <--
2599                             pFtnFrm->Cut();
2600                             delete pFtnFrm;
2601                         }
2602                     }
2603 				}
2604 				else
2605 				{
2606                     pFtnFrm->Calc();
2607 					pCnt->Calc();
2608                     // --> OD 2005-05-17 #i49383# - format anchored objects
2609                     if ( pCnt->IsTxtFrm() && pCnt->IsValid() )
2610                     {
2611                         if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt,
2612                                                                   *(pCnt->FindPageFrm()) ) )
2613                         {
2614                             // restart format with first content
2615                             pCnt = pFtn->ContainsAny();
2616                             continue;
2617                         }
2618                     }
2619                     // <--
2620 				}
2621 			}
2622 			SwSectionFrm *pDel = NULL;
2623 			if( pCnt->IsSctFrm() )
2624 			{
2625 				SwFrm* pTmp = ((SwSectionFrm*)pCnt)->ContainsAny();
2626 				if( pTmp )
2627 				{
2628 					pCnt = pTmp;
2629 					continue;
2630 				}
2631 				pDel = (SwSectionFrm*)pCnt;
2632 			}
2633 			if ( pCnt->GetNext() )
2634 				pCnt = pCnt->GetNext();
2635 			else
2636 			{
2637 				pCnt = pCnt->FindNext();
2638 				if ( pCnt )
2639 				{
2640                     SwFtnFrm* pFtnFrm = pCnt->FindFtnFrm();
2641                     if( pFtnFrm->GetRef()->FindFtnBossFrm(
2642                         pFtnFrm->GetAttr()->GetFtn().IsEndNote() ) != this )
2643 						bMore = sal_False;
2644 				}
2645 				else
2646 					bMore = sal_False;
2647 			}
2648 			if( pDel )
2649 			{
2650 				pDel->Cut();
2651 				delete pDel;
2652 			}
2653 			if ( bMore )
2654 			{
2655 				//Nicht weiter als bis zur angegebenen Fussnote, falls eine
2656 				//angegeben wurde.
2657 				if ( pAttr &&
2658 					 (::lcl_FindFtnPos( pDoc,
2659 									pCnt->FindFtnFrm()->GetAttr()) > nFtnPos ) )
2660 					bMore = sal_False;
2661 			}
2662 		} while ( bMore );
2663         // --> OD 2005-05-18 #i49383#
2664         if ( pLastFtnFrm )
2665         {
2666             if ( !bLock && bUnlockLastFtnFrm )
2667             {
2668                 pLastFtnFrm->ColUnlock();
2669             }
2670             // --> OD 2006-02-02 #i57914# - adjust fix #i49383#
2671             // enable lock of lower object position before format of footnote frame.
2672             pLastFtnFrm->UnlockPosOfLowerObjs();
2673             pLastFtnFrm->Calc();
2674 //            pLastFtnFrm->UnlockPosOfLowerObjs();
2675             // no extra notify for footnote frame
2676 //            delete pFtnFrmNotify;
2677             // <--
2678             if ( !bLock && bUnlockLastFtnFrm &&
2679                  !pLastFtnFrm->GetLower() &&
2680                  !pLastFtnFrm->IsColLocked() &&
2681                  !pLastFtnFrm->IsBackMoveLocked() )
2682             {
2683                 pLastFtnFrm->Cut();
2684                 delete pLastFtnFrm;
2685             }
2686         }
2687         // <--
2688 	}
2689 }
2690 
2691 /*************************************************************************
2692 |*
2693 |*	SwPageFrm::UpdateFtnNum()
2694 |*
2695 |*************************************************************************/
2696 
2697 void SwPageFrm::UpdateFtnNum()
2698 {
2699 	//Seitenweise Numerierung nur wenn es am Dokument so eingestellt ist.
2700 	if ( GetFmt()->GetDoc()->GetFtnInfo().eNum != FTNNUM_PAGE )
2701 		return;
2702 
2703 	SwLayoutFrm* pBody = FindBodyCont();
2704 	if( !pBody || !pBody->Lower() )
2705 		return;
2706 
2707 	SwCntntFrm* pCntnt = pBody->ContainsCntnt();
2708 	sal_uInt16 nNum = 0;
2709 
2710 	while( pCntnt && pCntnt->FindPageFrm() == this )
2711 	{
2712 		if( ((SwTxtFrm*)pCntnt)->HasFtn() )
2713 		{
2714 			SwFtnBossFrm* pBoss = pCntnt->FindFtnBossFrm( sal_True );
2715 			if( pBoss->GetUpper()->IsSctFrm() &&
2716 				((SwSectionFrm*)pBoss->GetUpper())->IsOwnFtnNum() )
2717 				pCntnt = ((SwSectionFrm*)pBoss->GetUpper())->FindLastCntnt();
2718 			else
2719 			{
2720 				SwFtnFrm* pFtn = (SwFtnFrm*)pBoss->FindFirstFtn( pCntnt );
2721 				while( pFtn )
2722 				{
2723 					SwTxtFtn* pTxtFtn = pFtn->GetAttr();
2724 					if( !pTxtFtn->GetFtn().IsEndNote() &&
2725 			 			!pTxtFtn->GetFtn().GetNumStr().Len() &&
2726 			 			!pFtn->GetMaster() &&
2727 			 			(pTxtFtn->GetFtn().GetNumber() != ++nNum) )
2728 						pTxtFtn->SetNumber( nNum );
2729 					if ( pFtn->GetNext() )
2730 						pFtn = (SwFtnFrm*)pFtn->GetNext();
2731 					else
2732 					{
2733                         SwFtnBossFrm* pTmpBoss = pFtn->FindFtnBossFrm( sal_True );
2734                         SwPageFrm* pPage = pTmpBoss->FindPageFrm();
2735 						pFtn = NULL;
2736                         lcl_NextFtnBoss( pTmpBoss, pPage, sal_False );
2737                         if( pTmpBoss )
2738 						{
2739                             SwFtnContFrm *pCont = pTmpBoss->FindNearestFtnCont();
2740 							if ( pCont )
2741 								pFtn = (SwFtnFrm*)pCont->Lower();
2742 						}
2743 					}
2744 					if( pFtn && pFtn->GetRef() != pCntnt )
2745 						pFtn = NULL;
2746 				}
2747 			}
2748 		}
2749 		pCntnt = pCntnt->FindNextCnt();
2750 	}
2751 }
2752 
2753 /*************************************************************************
2754 |*
2755 |*	SwFtnBossFrm::SetFtnDeadLine()
2756 |*
2757 |*************************************************************************/
2758 
2759 void SwFtnBossFrm::SetFtnDeadLine( const SwTwips nDeadLine )
2760 {
2761 	SwFrm *pBody = FindBodyCont();
2762 	pBody->Calc();
2763 
2764 	SwFrm *pCont = FindFtnCont();
2765 	const SwTwips nMax = nMaxFtnHeight;//Aktuelle MaxHeight nicht ueberschreiten.
2766     SWRECTFN( this )
2767 	if ( pCont )
2768 	{
2769 		pCont->Calc();
2770         nMaxFtnHeight = -(pCont->Frm().*fnRect->fnBottomDist)( nDeadLine );
2771 	}
2772 	else
2773         nMaxFtnHeight = -(pBody->Frm().*fnRect->fnBottomDist)( nDeadLine );
2774 
2775     const ViewShell *pSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0;
2776     if( pSh && pSh->GetViewOptions()->getBrowseMode() )
2777         nMaxFtnHeight += pBody->Grow( LONG_MAX, sal_True );
2778 	if ( IsInSct() )
2779         nMaxFtnHeight += FindSctFrm()->Grow( LONG_MAX, sal_True );
2780 
2781 	if ( nMaxFtnHeight < 0 )
2782 		nMaxFtnHeight = 0;
2783 	if ( nMax != LONG_MAX && nMaxFtnHeight > nMax )
2784 		nMaxFtnHeight = nMax;
2785 }
2786 
2787 /*************************************************************************
2788 |*
2789 |*	SwFtnBossFrm::GetVarSpace()
2790 |*
2791 |*************************************************************************/
2792 SwTwips SwFtnBossFrm::GetVarSpace() const
2793 {
2794 	//Fuer Seiten soll ein Wert von 20% der Seitenhoehe nicht unterschritten
2795 	//werden (->AMA: was macht MS da?)
2796 	//->AMA: Was ist da fuer Bereiche sinnvoll (und kompatibel zu MS ;-)?
2797 	//AMA: MS kennt scheinbar kein Begrenzung, die Fussnoten nehmen durchaus
2798 	// die ganze Seite/Spalte ein.
2799 
2800 	const SwPageFrm* pPg = FindPageFrm();
2801 	ASSERT( pPg || IsInSct(), "Footnote lost page" );
2802 
2803 	const SwFrm *pBody = FindBodyCont();
2804 	SwTwips nRet;
2805 	if( pBody )
2806 	{
2807         SWRECTFN( this )
2808 		if( IsInSct() )
2809 		{
2810 			nRet = 0;
2811             SwTwips nTmp = (*fnRect->fnYDiff)( (pBody->*fnRect->fnGetPrtTop)(),
2812                                                (Frm().*fnRect->fnGetTop)() );
2813 			const SwSectionFrm* pSect = FindSctFrm();
2814 			//  Endnotes in a ftncontainer causes a deadline:
2815 			// the bottom of the last contentfrm
2816 			if( pSect->IsEndnAtEnd() ) // endnotes allowed?
2817 			{
2818 				ASSERT( !Lower() || !Lower()->GetNext() || Lower()->GetNext()->
2819 						IsFtnContFrm(), "FtnContainer exspected" );
2820 				const SwFtnContFrm* pCont = Lower() ?
2821 					(SwFtnContFrm*)Lower()->GetNext() : 0;
2822 				if( pCont )
2823 				{
2824 					SwFtnFrm* pFtn = (SwFtnFrm*)pCont->Lower();
2825 					while( pFtn)
2826 					{
2827 						if( pFtn->GetAttr()->GetFtn().IsEndNote() )
2828 						{ // endnote found
2829 							SwFrm* pFrm = ((SwLayoutFrm*)Lower())->Lower();
2830 							if( pFrm )
2831 							{
2832 								while( pFrm->GetNext() )
2833 									pFrm = pFrm->GetNext(); // last cntntfrm
2834                                 nTmp += (*fnRect->fnYDiff)(
2835                                          (Frm().*fnRect->fnGetTop)(),
2836                                          (pFrm->Frm().*fnRect->fnGetBottom)() );
2837 							}
2838 							break;
2839 						}
2840 						pFtn = (SwFtnFrm*)pFtn->GetNext();
2841 					}
2842 				}
2843 			}
2844 			if( nTmp < nRet )
2845 				nRet = nTmp;
2846 		}
2847 		else
2848             nRet = - (pPg->Prt().*fnRect->fnGetHeight)()/5;
2849         nRet += (pBody->Frm().*fnRect->fnGetHeight)();
2850 		if( nRet < 0 )
2851 			nRet = 0;
2852 	}
2853 	else
2854 		nRet = 0;
2855     if ( IsPageFrm() )
2856     {
2857         const ViewShell *pSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0;
2858         if( pSh && pSh->GetViewOptions()->getBrowseMode() )
2859 		nRet += BROWSE_HEIGHT - Frm().Height();
2860     }
2861 	return nRet;
2862 }
2863 
2864 /*************************************************************************
2865 |*
2866 |*	SwFtnBossFrm::NeighbourhoodAdjustment(SwFrm*)
2867 |*
2868 |*	gibt Auskunft, ob die Groessenveraenderung von pFrm von AdjustNeighbourhood(...)
2869 |*	oder von Grow/Shrink(..) verarbeitet werden sollte.
2870 |*	Bei einem PageFrm oder in Spalten direkt unterhalb der Seite muss AdjustNei..
2871 |*  gerufen werden, in Rahmenspalten Grow/Shrink.
2872 |*	Spannend sind die spaltigen Bereiche: Wenn es in der Spalte einen Fussnotencontainer
2873 |* 	gibt und die Fussnoten nicht vom Bereich eingesammelt werden, ist ein Adjust..,
2874 |*	ansonsten ein Grow/Shrink notwendig.
2875 |*
2876 |*************************************************************************/
2877 
2878 sal_uInt8 SwFtnBossFrm::_NeighbourhoodAdjustment( const SwFrm* ) const
2879 {
2880 	sal_uInt8 nRet = NA_ONLY_ADJUST;
2881 	if( GetUpper() && !GetUpper()->IsPageBodyFrm() )
2882 	{
2883 		// Spaltige Rahmen erfordern Grow/Shrink
2884 		if( GetUpper()->IsFlyFrm() )
2885 			nRet = NA_GROW_SHRINK;
2886 		else
2887 		{
2888 			ASSERT( GetUpper()->IsSctFrm(), "NeighbourhoodAdjustment: Unexspected Upper" );
2889 			if( !GetNext() && !GetPrev() )
2890 				nRet = NA_GROW_ADJUST; // section with a single column (FtnAtEnd)
2891 			else
2892 			{
2893 				const SwFrm* pTmp = Lower();
2894 				ASSERT( pTmp, "NeighbourhoodAdjustment: Missing Lower()" );
2895 				if( !pTmp->GetNext() )
2896 					nRet = NA_GROW_SHRINK;
2897 				else if( !GetUpper()->IsColLocked() )
2898 					nRet = NA_ADJUST_GROW;
2899 				ASSERT( !pTmp->GetNext() || pTmp->GetNext()->IsFtnContFrm(),
2900 						"NeighbourhoodAdjustment: Who's that guy?" );
2901 			}
2902 		}
2903 	}
2904 	return nRet;
2905 }
2906 
2907 /*************************************************************************
2908 |*
2909 |*	SwPageFrm::SetColMaxFtnHeight()
2910 |*
2911 |*************************************************************************/
2912 void SwPageFrm::SetColMaxFtnHeight()
2913 {
2914 	SwLayoutFrm *pBody = FindBodyCont();
2915 	if( pBody && pBody->Lower() && pBody->Lower()->IsColumnFrm() )
2916 	{
2917 		SwColumnFrm* pCol = (SwColumnFrm*)pBody->Lower();
2918 		do
2919 		{
2920 			pCol->SetMaxFtnHeight( GetMaxFtnHeight() );
2921 			pCol = (SwColumnFrm*)pCol->GetNext();
2922 		} while ( pCol );
2923 	}
2924 }
2925 
2926 /*************************************************************************
2927 |*
2928 |*	SwLayoutFrm::MoveLowerFtns
2929 |*
2930 |*************************************************************************/
2931 
2932 
2933 sal_Bool SwLayoutFrm::MoveLowerFtns( SwCntntFrm *pStart, SwFtnBossFrm *pOldBoss,
2934 								 SwFtnBossFrm *pNewBoss, const sal_Bool bFtnNums )
2935 {
2936 	SwDoc *pDoc = GetFmt()->GetDoc();
2937 	if ( !pDoc->GetFtnIdxs().Count() )
2938 		return sal_False;
2939 	if( pDoc->GetFtnInfo().ePos == FTNPOS_CHAPTER &&
2940 		( !IsInSct() || !FindSctFrm()->IsFtnAtEnd() ) )
2941 		return sal_True;
2942 
2943 	if ( !pNewBoss )
2944 		pNewBoss = FindFtnBossFrm( sal_True );
2945 	if ( pNewBoss == pOldBoss )
2946 		return sal_False;
2947 
2948 	sal_Bool bMoved = sal_False;
2949 	if( !pStart )
2950 		pStart = ContainsCntnt();
2951 
2952 	SvPtrarr aFtnArr( 5, 5 );
2953 
2954     while ( IsAnLower( pStart ) )
2955 	{
2956 		if ( ((SwTxtFrm*)pStart)->HasFtn() )
2957         {
2958             // OD 03.04.2003 #108446# - To avoid unnecessary moves of footnotes
2959             // use new parameter <_bCollectOnlyPreviousFtn> (4th parameter of
2960             // method <SwFtnBossFrm::CollectFtn(..)>) to control, that only
2961             // footnotes have to be collected, that are positioned before the
2962             // new dedicated footnote boss frame.
2963             pNewBoss->CollectFtns( pStart, pOldBoss, aFtnArr, sal_True );
2964         }
2965 		pStart = pStart->GetNextCntntFrm();
2966 	}
2967 
2968 	ASSERT( pOldBoss->IsInSct() == pNewBoss->IsInSct(),
2969 			"MoveLowerFtns: Section confusion" );
2970 	SvPtrarr *pFtnArr;
2971     SwLayoutFrm* pNewChief = 0;
2972     SwLayoutFrm* pOldChief = 0;
2973 	if( pStart && pOldBoss->IsInSct() && ( pOldChief = pOldBoss->FindSctFrm() )
2974 		!= ( pNewChief = pNewBoss->FindSctFrm() ) )
2975 	{
2976 		pFtnArr = new SvPtrarr( 5, 5 );
2977 		pOldChief = pOldBoss->FindFtnBossFrm( sal_True );
2978 		pNewChief = pNewBoss->FindFtnBossFrm( sal_True );
2979 		while( pOldChief->IsAnLower( pStart ) )
2980 		{
2981 			if ( ((SwTxtFrm*)pStart)->HasFtn() )
2982 				((SwFtnBossFrm*)pNewChief)->CollectFtns( pStart,
2983 										(SwFtnBossFrm*)pOldBoss, *pFtnArr );
2984 			pStart = pStart->GetNextCntntFrm();
2985 		}
2986 		if( !pFtnArr->Count() )
2987 		{
2988 			delete pFtnArr;
2989 			pFtnArr = NULL;
2990 		}
2991 	}
2992 	else
2993 		pFtnArr = NULL;
2994 
2995 	if ( aFtnArr.Count() || pFtnArr )
2996 	{
2997 		if( aFtnArr.Count() )
2998 			pNewBoss->_MoveFtns( aFtnArr, sal_True );
2999 		if( pFtnArr )
3000 		{
3001 			((SwFtnBossFrm*)pNewChief)->_MoveFtns( *pFtnArr, sal_True );
3002 			delete pFtnArr;
3003 		}
3004 		bMoved = sal_True;
3005 
3006 		// Nur bei einem Seitenwechsel muss die FtnNum neu berechnet werden
3007 		if ( bFtnNums )
3008 		{
3009 			SwPageFrm* pOldPage = pOldBoss->FindPageFrm();
3010 			SwPageFrm* pNewPage =pNewBoss->FindPageFrm();
3011 			if( pOldPage != pNewPage )
3012 			{
3013 				pOldPage->UpdateFtnNum();
3014 				pNewPage->UpdateFtnNum();
3015 			}
3016 		}
3017 	}
3018 	return bMoved;
3019 }
3020 
3021 /*************************************************************************
3022 |*
3023 |*	SwLayoutFrm::MoveFtnCntFwd()
3024 |*
3025 |*************************************************************************/
3026 
3027 
3028 sal_Bool SwCntntFrm::MoveFtnCntFwd( sal_Bool bMakePage, SwFtnBossFrm *pOldBoss )
3029 {
3030 	ASSERT( IsInFtn(), "Keine Ftn." );
3031 	SwLayoutFrm *pFtn = FindFtnFrm();
3032 
3033 	// The first paragraph in the first footnote in the first column in the
3034 	// sectionfrm at the top of the page has not to move forward, if the
3035 	// columnbody is empty.
3036 	if( pOldBoss->IsInSct() && !pOldBoss->GetIndPrev() && !GetIndPrev() &&
3037 		!pFtn->GetPrev() )
3038 	{
3039 		SwLayoutFrm* pBody = pOldBoss->FindBodyCont();
3040 		if( !pBody || !pBody->Lower() )
3041 			return sal_True;
3042 	}
3043 
3044 	//fix(9538): Wenn die Ftn noch Nachbarn hinter sich hat, so muessen
3045 	//diese ersteinmal verschwinden.
3046 	SwLayoutFrm *pNxt = (SwLayoutFrm*)pFtn->GetNext();
3047 	SwLayoutFrm *pLst = 0;
3048 	while ( pNxt )
3049 	{
3050 		while ( pNxt->GetNext() )
3051 			pNxt = (SwLayoutFrm*)pNxt->GetNext();
3052 		if ( pNxt == pLst )
3053 			pNxt = 0;
3054 		else
3055 		{	pLst = pNxt;
3056 			SwCntntFrm *pCnt = pNxt->ContainsCntnt();
3057 			if( pCnt )
3058 				pCnt->MoveFtnCntFwd( sal_True, pOldBoss );
3059 			pNxt = (SwLayoutFrm*)pFtn->GetNext();
3060 		}
3061 	}
3062 
3063 	sal_Bool bSamePage = sal_True;
3064 	SwLayoutFrm *pNewUpper =
3065 				GetLeaf( bMakePage ? MAKEPAGE_INSERT : MAKEPAGE_NONE, sal_True );
3066 
3067 	if ( pNewUpper )
3068 	{
3069 		sal_Bool bSameBoss = sal_True;
3070 		SwFtnBossFrm * const pNewBoss = pNewUpper->FindFtnBossFrm();
3071 		//Wechseln wir die Spalte/Seite?
3072 		if ( sal_False == ( bSameBoss = pNewBoss == pOldBoss ) )
3073         {
3074             bSamePage = pOldBoss->FindPageFrm() == pNewBoss->FindPageFrm(); // Seitenwechsel?
3075 			pNewUpper->Calc();
3076 		}
3077 
3078 		//Das Layoutblatt, dass wir fuer Fussnoten bekommen ist entweder
3079 		//ein Fussnotencontainer oder eine Fussnote
3080 		//Wenn es eine Fussnote ist, und sie die gleiche Fussnotenreferez
3081 		//wie der alte Upper hat, so moven wir uns direkt hinein.
3082 		//Ist die Referenz einen andere oder ist es ein Container, so wird
3083 		//eine neue Fussnote erzeugt und in den Container gestellt.
3084 		// Wenn wir in einem Bereich innerhalb der Fussnote sind, muss
3085 		// SectionFrame noch angelegt werden.
3086 		SwFtnFrm* pTmpFtn = pNewUpper->IsFtnFrm() ? ((SwFtnFrm*)pNewUpper) : 0;
3087 		if( !pTmpFtn )
3088 		{
3089 			ASSERT( pNewUpper->IsFtnContFrm(), "Neuer Upper kein FtnCont.");
3090 			SwFtnContFrm *pCont = (SwFtnContFrm*)pNewUpper;
3091 
3092 			//Fussnote erzeugen.
3093 			SwFtnFrm *pOld = FindFtnFrm();
3094 			pTmpFtn = new SwFtnFrm( pOld->GetFmt()->GetDoc()->GetDfltFrmFmt(),
3095                                     pOld, pOld->GetRef(), pOld->GetAttr() );
3096 			//Verkettung der Fussnoten.
3097 			if ( pOld->GetFollow() )
3098 			{
3099 				pTmpFtn->SetFollow( pOld->GetFollow() );
3100 				pOld->GetFollow()->SetMaster( pTmpFtn );
3101 			}
3102 			pOld->SetFollow( pTmpFtn );
3103 			pTmpFtn->SetMaster( pOld );
3104 			SwFrm* pNx = pCont->Lower();
3105 			if( pNx && pTmpFtn->GetAttr()->GetFtn().IsEndNote() )
3106 				while(pNx && !((SwFtnFrm*)pNx)->GetAttr()->GetFtn().IsEndNote())
3107 					pNx = pNx->GetNext();
3108 			pTmpFtn->Paste( pCont, pNx );
3109 			pTmpFtn->Calc();
3110 		}
3111 		ASSERT( pTmpFtn->GetAttr() == FindFtnFrm()->GetAttr(), "Wrong Footnote!" );
3112 		// Bereiche in Fussnoten beduerfen besonderer Behandlung
3113 		SwLayoutFrm *pNewUp = pTmpFtn;
3114 		if( IsInSct() )
3115 		{
3116 			SwSectionFrm* pSect = FindSctFrm();
3117 			// Bereich in Fussnote (oder nur Fussnote in Bereich)?
3118 			if( pSect->IsInFtn() )
3119 			{
3120 				if( pTmpFtn->Lower() && pTmpFtn->Lower()->IsSctFrm() &&
3121 					pSect->GetFollow() == (SwSectionFrm*)pTmpFtn->Lower() )
3122 					pNewUp = (SwSectionFrm*)pTmpFtn->Lower();
3123 				else
3124 				{
3125                     pNewUp = new SwSectionFrm( *pSect, sal_False );
3126 					pNewUp->InsertBefore( pTmpFtn, pTmpFtn->Lower() );
3127                     static_cast<SwSectionFrm*>(pNewUp)->Init();
3128 					pNewUp->Frm().Pos() = pTmpFtn->Frm().Pos();
3129 					pNewUp->Frm().Pos().Y() += 1; //wg. Benachrichtigungen.
3130 
3131 					// Wenn unser Bereichsframe einen Nachfolger hat, so muss dieser
3132 					// umgehaengt werden hinter den neuen Follow der Bereichsframes.
3133 					SwFrm* pTmp = pSect->GetNext();
3134 					if( pTmp )
3135 					{
3136                         SwFlowFrm* pTmpNxt;
3137 						if( pTmp->IsCntntFrm() )
3138                             pTmpNxt = (SwCntntFrm*)pTmp;
3139 						else if( pTmp->IsSctFrm() )
3140                             pTmpNxt = (SwSectionFrm*)pTmp;
3141 						else
3142 						{
3143 							ASSERT( pTmp->IsTabFrm(), "GetNextSctLeaf: Wrong Type" );
3144                             pTmpNxt = (SwTabFrm*)pTmp;
3145 						}
3146                         pTmpNxt->MoveSubTree( pTmpFtn, pNewUp->GetNext() );
3147 					}
3148 				}
3149 			}
3150 		}
3151 
3152 		MoveSubTree( pNewUp, pNewUp->Lower() );
3153 
3154 		if( !bSameBoss )
3155 			Prepare( PREP_BOSS_CHGD );
3156 	}
3157 	return bSamePage;
3158 }
3159 
3160 /*************************************************************************
3161 |*
3162 |*	class SwSaveFtnHeight
3163 |*
3164 |*************************************************************************/
3165 
3166 
3167 SwSaveFtnHeight::SwSaveFtnHeight( SwFtnBossFrm *pBs, const SwTwips nDeadLine ) :
3168 	pBoss( pBs ),
3169 	nOldHeight( pBs->GetMaxFtnHeight() )
3170 {
3171 	pBoss->SetFtnDeadLine( nDeadLine );
3172 	nNewHeight = pBoss->GetMaxFtnHeight();
3173 }
3174 
3175 
3176 
3177 SwSaveFtnHeight::~SwSaveFtnHeight()
3178 {
3179 	//Wenn zwischendurch jemand an der DeadLine gedreht hat, so lassen wir
3180 	//ihm seinen Spass!
3181 	if ( nNewHeight == pBoss->GetMaxFtnHeight() )
3182 		pBoss->nMaxFtnHeight = nOldHeight;
3183 }
3184 
3185 
3186 #ifdef DBG_UTIL
3187 //JP 15.10.2001: in a non pro version test if the attribute has the same
3188 //				meaning which his reference is
3189 
3190 // Normally, the pRef member and the GetRefFromAttr() result has to be
3191 // identically. Sometimes footnote will be moved from a master to its follow,
3192 // but the GetRef() is called first, so we have to ignore a master/follow
3193 // mismatch.
3194 
3195 const SwCntntFrm* SwFtnFrm::GetRef() const
3196 {
3197     const SwCntntFrm* pRefAttr = GetRefFromAttr();
3198     ASSERT( pRef == pRefAttr || pRef->IsAnFollow( pRefAttr )
3199             || pRefAttr->IsAnFollow( pRef ),
3200             "access to deleted Frame? pRef != pAttr->GetRef()" );
3201 	return pRef;
3202 }
3203 
3204 SwCntntFrm* SwFtnFrm::GetRef()
3205 {
3206     const SwCntntFrm* pRefAttr = GetRefFromAttr();
3207     ASSERT( pRef == pRefAttr || pRef->IsAnFollow( pRefAttr )
3208             || pRefAttr->IsAnFollow( pRef ),
3209             "access to deleted Frame? pRef != pAttr->GetRef()" );
3210 	return pRef;
3211 }
3212 
3213 #endif
3214 
3215 const SwCntntFrm* SwFtnFrm::GetRefFromAttr()  const
3216 {
3217 	SwFtnFrm* pThis = (SwFtnFrm*)this;
3218 	return pThis->GetRefFromAttr();
3219 }
3220 
3221 SwCntntFrm* SwFtnFrm::GetRefFromAttr()
3222 {
3223 	ASSERT( pAttr, "invalid Attribute" );
3224 	SwTxtNode& rTNd = (SwTxtNode&)pAttr->GetTxtNode();
3225 	SwPosition aPos( rTNd, SwIndex( &rTNd, *pAttr->GetStart() ));
3226 	SwCntntFrm* pCFrm = rTNd.getLayoutFrm( getRootFrm(), 0, &aPos, sal_False );
3227 	return pCFrm;
3228 }
3229 
3230 /** search for last content in the current footnote frame
3231 
3232     OD 2005-12-02 #i27138#
3233 
3234     @author OD
3235 */
3236 SwCntntFrm* SwFtnFrm::FindLastCntnt()
3237 {
3238     SwCntntFrm* pLastCntntFrm( 0L );
3239 
3240     // find last lower, which is a content frame or contains content.
3241     // hidden text frames, empty sections and empty tables have to be skipped.
3242     SwFrm* pLastLowerOfFtn( GetLower() );
3243     SwFrm* pTmpLastLower( pLastLowerOfFtn );
3244     while ( pTmpLastLower && pTmpLastLower->GetNext() )
3245     {
3246         pTmpLastLower = pTmpLastLower->GetNext();
3247         if ( ( pTmpLastLower->IsTxtFrm() &&
3248                !static_cast<SwTxtFrm*>(pTmpLastLower)->IsHiddenNow() ) ||
3249              ( pTmpLastLower->IsSctFrm() &&
3250                static_cast<SwSectionFrm*>(pTmpLastLower)->GetSection() &&
3251                static_cast<SwSectionFrm*>(pTmpLastLower)->ContainsCntnt() ) ||
3252              ( pTmpLastLower->IsTabFrm() &&
3253                static_cast<SwTabFrm*>(pTmpLastLower)->ContainsCntnt() ) )
3254         {
3255             pLastLowerOfFtn = pTmpLastLower;
3256         }
3257     }
3258 
3259     // determine last content frame depending on type of found last lower.
3260     if ( pLastLowerOfFtn && pLastLowerOfFtn->IsTabFrm() )
3261     {
3262         pLastCntntFrm = static_cast<SwTabFrm*>(pLastLowerOfFtn)->FindLastCntnt();
3263     }
3264     else if ( pLastLowerOfFtn && pLastLowerOfFtn->IsSctFrm() )
3265     {
3266         pLastCntntFrm = static_cast<SwSectionFrm*>(pLastLowerOfFtn)->FindLastCntnt();
3267     }
3268     else
3269     {
3270         pLastCntntFrm = dynamic_cast<SwCntntFrm*>(pLastLowerOfFtn);
3271     }
3272 
3273     return pLastCntntFrm;
3274 }
3275 
3276