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