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( sal_False, "No 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( sal_False, "Footnote container already available." );
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( sal_False, "No space for footnote found.");
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( sal_False, "No footnote content." );
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