xref: /AOO41X/main/sw/source/core/layout/ftnfrm.cxx (revision ca62e2c2083b5d0995f1245bad6c2edfb455fbec)
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