1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: txtftn.cxx,v $
10 * $Revision: 1.51.208.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include "pagefrm.hxx"
38 #include <SwPortionHandler.hxx>
42 #include <ftninfo.hxx>
43 #include <charfmt.hxx>
44 #include <dflyobj.hxx>
46 #include <svx/brshitem.hxx>
47 #include <svx/charrotateitem.hxx>
48 #include <breakit.hxx>
49 #ifndef _COM_SUN_STAR_I18N_SCRIPTTYPE_HDL_
50 #include <com/sun/star/i18n/ScriptType.hdl>
53 // OD 2004-05-24 #i28701#
54 #include <sortedobjs.hxx>
57 #include "swfont.hxx" // new SwFont
62 #include "itrform2.hxx"
63 #include "ftnfrm.hxx" // FindQuoVadisFrm(),
64 #include "pagedesc.hxx"
65 #include "redlnitr.hxx" // SwRedlnItr
66 #include "sectfrm.hxx" // SwSectionFrm
67 #include "layouter.hxx" // Endnote-Collection
68 #include "frmtool.hxx"
69 #include "ndindex.hxx"
71 using namespace ::com::sun::star
;
73 /*************************************************************************
75 *************************************************************************/
77 sal_Bool
SwTxtFrm::_IsFtnNumFrm() const
79 const SwFtnFrm
* pFtn
= FindFtnFrm()->GetMaster();
80 while( pFtn
&& !pFtn
->ContainsCntnt() )
81 pFtn
= pFtn
->GetMaster();
85 /*************************************************************************
87 *************************************************************************/
89 // Sucht innerhalb einer Master-Follow-Kette den richtigen TxtFrm zum SwTxtFtn
91 SwTxtFrm
*SwTxtFrm::FindFtnRef( const SwTxtFtn
*pFtn
)
93 SwTxtFrm
*pFrm
= this;
94 const sal_Bool bFwd
= *pFtn
->GetStart() >= GetOfst();
97 if( SwFtnBossFrm::FindFtn( pFrm
, pFtn
) )
99 pFrm
= bFwd
? pFrm
->GetFollow() :
100 pFrm
->IsFollow() ? pFrm
->FindMaster() : 0;
105 /*************************************************************************
107 *************************************************************************/
110 void SwTxtFrm::CalcFtnFlag()
112 void SwTxtFrm::CalcFtnFlag( xub_StrLen nStop
)//Fuer den Test von SplitFrm
117 const SwpHints
*pHints
= GetTxtNode()->GetpSwpHints();
121 const USHORT nSize
= pHints
->Count();
124 const xub_StrLen nEnd
= GetFollow() ? GetFollow()->GetOfst() : STRING_LEN
;
126 const xub_StrLen nEnd
= nStop
!= STRING_LEN
? nStop
127 : GetFollow() ? GetFollow()->GetOfst() : STRING_LEN
;
130 for ( USHORT i
= 0; i
< nSize
; ++i
)
132 const SwTxtAttr
*pHt
= (*pHints
)[i
];
133 if ( pHt
->Which() == RES_TXTATR_FTN
)
135 const xub_StrLen nIdx
= *pHt
->GetStart();
138 if( GetOfst() <= nIdx
)
147 /*************************************************************************
148 * CalcPrepFtnAdjust()
149 *************************************************************************/
151 sal_Bool
SwTxtFrm::CalcPrepFtnAdjust()
153 ASSERT( HasFtn(), "Wer ruft mich da?" );
154 SwFtnBossFrm
*pBoss
= FindFtnBossFrm( sal_True
);
155 const SwFtnFrm
*pFtn
= pBoss
->FindFirstFtn( this );
156 if( pFtn
&& FTNPOS_CHAPTER
!= GetNode()->GetDoc()->GetFtnInfo().ePos
&&
157 ( !pBoss
->GetUpper()->IsSctFrm() ||
158 !((SwSectionFrm
*)pBoss
->GetUpper())->IsFtnAtEnd() ) )
160 const SwFtnContFrm
*pCont
= pBoss
->FindFtnCont();
161 sal_Bool bReArrange
= sal_True
;
164 if ( pCont
&& (*fnRect
->fnYDiff
)( (pCont
->Frm().*fnRect
->fnGetTop
)(),
165 (Frm().*fnRect
->fnGetBottom
)() ) > 0 )
167 pBoss
->RearrangeFtns( (Frm().*fnRect
->fnGetBottom
)(), sal_False
,
171 pFtn
= pBoss
->FindFirstFtn( this );
174 bReArrange
= sal_False
;
175 if( !pCont
|| !pFtn
|| bReArrange
!= (pFtn
->FindFtnBossFrm() == pBoss
) )
177 SwTxtFormatInfo
aInf( this );
178 SwTxtFormatter
aLine( this, &aInf
);
180 SetPara( 0 ); //Wird ggf. geloescht!
189 /*************************************************************************
192 * Local helper function. Checks if nLower should be taken as the boundary
194 *************************************************************************/
196 SwTwips
lcl_GetFtnLower( const SwTxtFrm
* pFrm
, SwTwips nLower
)
198 // nLower is an absolute value. It denotes the bottom of the line
199 // containing the footnote.
202 ASSERT( !pFrm
->IsVertical() || !pFrm
->IsSwapped(),
203 "lcl_GetFtnLower with swapped frame" );
206 SwTwips nRet
= nLower
;
209 // Check if text is inside a table.
211 if ( pFrm
->IsInTab() )
214 // If pFrm is inside a table, we have to check if
215 // a) The table is not allowed to split or
216 // b) The table row is not allowed to split
218 // Inside a table, there are no footnotes,
219 // see SwFrm::FindFtnBossFrm. So we don't have to check
220 // the case that pFrm is inside a (footnote collecting) section
223 const SwFrm
* pRow
= pFrm
;
224 while( !pRow
->IsRowFrm() || !pRow
->GetUpper()->IsTabFrm() )
225 pRow
= pRow
->GetUpper();
226 const SwTabFrm
* pTabFrm
= (SwTabFrm
*)pRow
->GetUpper();
228 ASSERT( pTabFrm
&& pRow
&&
229 pRow
->GetUpper()->IsTabFrm(), "Upper of row should be tab" )
231 const BOOL bDontSplit
= !pTabFrm
->IsFollow() &&
232 !pTabFrm
->IsLayoutSplitAllowed();
236 nMin
= (pTabFrm
->Frm().*fnRect
->fnGetBottom
)();
237 else if ( !((SwRowFrm
*)pRow
)->IsRowSplitAllowed() )
238 nMin
= (pRow
->Frm().*fnRect
->fnGetBottom
)();
240 if ( nMin
&& (*fnRect
->fnYDiff
)( nMin
, nLower
) > 0 )
243 nAdd
= (pRow
->GetUpper()->*fnRect
->fnGetBottomMargin
)();
246 nAdd
= (pFrm
->*fnRect
->fnGetBottomMargin
)();
256 // #i10770#: If there are fly frames anchored at previous paragraphs,
257 // the deadline should consider their lower borders.
258 const SwFrm
* pStartFrm
= pFrm
->GetUpper()->GetLower();
259 ASSERT( pStartFrm
, "Upper has no lower" )
260 SwTwips nFlyLower
= bVert
? LONG_MAX
: 0;
261 while ( pStartFrm
!= pFrm
)
263 ASSERT( pStartFrm
, "Frame chain is broken" )
264 if ( pStartFrm
->GetDrawObjs() )
266 const SwSortedObjs
&rObjs
= *pStartFrm
->GetDrawObjs();
267 for ( USHORT i
= 0; i
< rObjs
.Count(); ++i
)
269 SwAnchoredObject
* pAnchoredObj
= rObjs
[i
];
270 SwRect
aRect( pAnchoredObj
->GetObjRect() );
272 if ( !pAnchoredObj
->ISA(SwFlyFrm
) ||
273 static_cast<SwFlyFrm
*>(pAnchoredObj
)->IsValid() )
275 const SwTwips nBottom
= (aRect
.*fnRect
->fnGetBottom
)();
276 if ( (*fnRect
->fnYDiff
)( nBottom
, nFlyLower
) > 0 )
282 pStartFrm
= pStartFrm
->GetNext();
286 nRet
= Min( nRet
, nFlyLower
);
288 nRet
= Max( nRet
, nFlyLower
);
294 /*************************************************************************
295 * SwTxtFrm::GetFtnLine()
296 *************************************************************************/
298 SwTwips
SwTxtFrm::GetFtnLine( const SwTxtFtn
*pFtn
) const
300 ASSERT( ! IsVertical() || ! IsSwapped(),
301 "SwTxtFrm::GetFtnLine with swapped frame" )
303 SwTxtFrm
*pThis
= (SwTxtFrm
*)this;
307 // #109071# GetFormatted() does not work here, bacause most probably
308 // the frame is currently locked. We return the previous value.
309 return pThis
->mnFtnLine
> 0 ?
311 IsVertical() ? Frm().Left() : Frm().Bottom();
314 SWAP_IF_NOT_SWAPPED( this )
316 SwTxtInfo
aInf( pThis
);
317 SwTxtIter
aLine( pThis
, &aInf
);
318 const xub_StrLen nPos
= *pFtn
->GetStart();
319 aLine
.CharToLine( nPos
);
321 SwTwips nRet
= aLine
.Y() + SwTwips(aLine
.GetLineHeight());
323 nRet
= SwitchHorizontalToVertical( nRet
);
327 nRet
= lcl_GetFtnLower( pThis
, nRet
);
329 pThis
->mnFtnLine
= nRet
;
333 /*************************************************************************
334 * SwTxtFrm::GetFtnRstHeight()
335 *************************************************************************/
337 // Ermittelt die max. erreichbare Hoehe des TxtFrm im Ftn-Bereich.
338 // Sie wird eingeschraenkt durch den unteren Rand der Zeile mit
341 SwTwips
SwTxtFrm::_GetFtnFrmHeight() const
343 ASSERT( !IsFollow() && IsInFtn(), "SwTxtFrm::SetFtnLine: moon walk" );
345 const SwFtnFrm
*pFtnFrm
= FindFtnFrm();
346 const SwTxtFrm
*pRef
= (const SwTxtFrm
*)pFtnFrm
->GetRef();
347 const SwFtnBossFrm
*pBoss
= FindFtnBossFrm();
348 if( pBoss
!= pRef
->FindFtnBossFrm( !pFtnFrm
->GetAttr()->
349 GetFtn().IsEndNote() ) )
352 SWAP_IF_SWAPPED( this )
354 SwTwips nHeight
= pRef
->IsInFtnConnect() ?
355 1 : pRef
->GetFtnLine( pFtnFrm
->GetAttr() );
358 // So komisch es aussehen mag: Die erste Ftn auf der Seite darf sich
359 // nicht mit der Ftn-Referenz beruehren, wenn wir im Ftn-Bereich Text
361 const SwFrm
*pCont
= pFtnFrm
->GetUpper();
362 //Hoehe innerhalb des Cont, die ich mir 'eh noch genehmigen darf.
364 SwTwips nTmp
= (*fnRect
->fnYDiff
)( (pCont
->*fnRect
->fnGetPrtBottom
)(),
365 (Frm().*fnRect
->fnGetTop
)() );
370 sal_Bool bInvalidPos
= sal_False
;
371 const SwLayoutFrm
* pTmp
= GetUpper();
372 while( !bInvalidPos
&& pTmp
)
374 bInvalidPos
= !pTmp
->GetValidPosFlag() ||
375 !pTmp
->Lower()->GetValidPosFlag();
378 pTmp
= pTmp
->GetUpper();
380 ASSERT( bInvalidPos
, "Hanging below FtnCont" );
384 if ( (*fnRect
->fnYDiff
)( (pCont
->Frm().*fnRect
->fnGetTop
)(), nHeight
) > 0 )
386 //Wachstumspotential den Containers.
387 if ( !pRef
->IsInFtnConnect() )
389 SwSaveFtnHeight
aSave( (SwFtnBossFrm
*)pBoss
, nHeight
);
390 nHeight
= ((SwFtnContFrm
*)pCont
)->Grow( LONG_MAX
, sal_True
);
393 nHeight
= ((SwFtnContFrm
*)pCont
)->Grow( LONG_MAX
, sal_True
);
400 { // The container has to shrink
401 nTmp
+= (*fnRect
->fnYDiff
)( (pCont
->Frm().*fnRect
->fnGetTop
)(), nHeight
);
414 /*************************************************************************
415 * SwTxtFrm::FindQuoVadisFrm()
416 *************************************************************************/
418 SwTxtFrm
*SwTxtFrm::FindQuoVadisFrm()
420 // Erstmal feststellen, ob wir in einem FtnFrm stehen:
421 if( GetIndPrev() || !IsInFtn() )
424 // Zum Vorgaenger-FtnFrm
425 SwFtnFrm
*pFtnFrm
= FindFtnFrm()->GetMaster();
429 // Nun den letzten Cntnt:
430 const SwCntntFrm
*pCnt
= pFtnFrm
->ContainsCntnt();
433 const SwCntntFrm
*pLast
;
436 pCnt
= pCnt
->GetNextCntntFrm();
437 } while( pCnt
&& pFtnFrm
->IsAnLower( pCnt
) );
438 return (SwTxtFrm
*)pLast
;
441 /*************************************************************************
442 * SwTxtFrm::RemoveFtn()
443 *************************************************************************/
445 void SwTxtFrm::RemoveFtn( const xub_StrLen nStart
, const xub_StrLen nLen
)
447 if ( !IsFtnAllowed() )
450 SwpHints
*pHints
= GetTxtNode()->GetpSwpHints();
454 sal_Bool bRollBack
= nLen
!= STRING_LEN
;
455 USHORT nSize
= pHints
->Count();
460 nEnd
= nStart
+ nLen
;
461 pSource
= GetFollow();
473 SwPageFrm
* pUpdate
= NULL
;
474 sal_Bool bRemove
= sal_False
;
475 SwFtnBossFrm
*pFtnBoss
= 0;
476 SwFtnBossFrm
*pEndBoss
= 0;
478 = FTNPOS_CHAPTER
== GetNode()->GetDoc()->GetFtnInfo().ePos
;
479 for ( USHORT i
= nSize
; i
; )
481 SwTxtAttr
*pHt
= pHints
->GetTextHint(--i
);
482 if ( RES_TXTATR_FTN
!= pHt
->Which() )
485 const xub_StrLen nIdx
= *pHt
->GetStart();
491 SwTxtFtn
*pFtn
= (SwTxtFtn
*)pHt
;
492 sal_Bool bEndn
= pFtn
->GetFtn().IsEndNote();
497 pEndBoss
= pSource
->FindFtnBossFrm();
503 pFtnBoss
= pSource
->FindFtnBossFrm( sal_True
);
504 if( pFtnBoss
->GetUpper()->IsSctFrm() )
506 SwSectionFrm
* pSect
= (SwSectionFrm
*)
507 pFtnBoss
->GetUpper();
508 if( pSect
->IsFtnAtEnd() )
509 bFtnEndDoc
= sal_False
;
514 // Wir loeschen nicht, sondern wollen die Ftn verschieben.
515 // Drei Faelle koennen auftreten:
516 // 1) Es gibt weder Follow noch PrevFollow
517 // -> RemoveFtn() (vielleicht sogar ein ASSERT wert)
518 // 2) nStart > GetOfst, ich habe einen Follow
519 // -> Ftn wandert in den Follow
520 // 3) nStart < GetOfst, ich bin ein Follow
521 // -> Ftn wandert in den PrevFollow
522 // beide muessen auf einer Seite/in einer Spalte stehen.
524 SwFtnFrm
*pFtnFrm
= bEndn
? pEndBoss
->FindFtn( pSource
, pFtn
) :
525 pFtnBoss
->FindFtn( pSource
, pFtn
);
529 const sal_Bool bEndDoc
= bEndn
? sal_True
: bFtnEndDoc
;
534 pFtnFrm
->SetRef( this );
535 pFtnFrm
= pFtnFrm
->GetFollow();
539 else if( GetFollow() )
541 SwCntntFrm
*pDest
= GetFollow();
542 while( pDest
->GetFollow() && ((SwTxtFrm
*)pDest
->
543 GetFollow())->GetOfst() <= nIdx
)
544 pDest
= pDest
->GetFollow();
545 ASSERT( !pDest
->FindFtnBossFrm( !bEndn
)->FindFtn(
546 pDest
,pFtn
),"SwTxtFrm::RemoveFtn: footnote exists");
548 //Nicht ummelden sondern immer Moven.
549 // OD 08.11.2002 #104840# - use <SwlayoutFrm::IsBefore(::)>
551 !pFtnFrm
->FindFtnBossFrm()->IsBefore( pDest
->FindFtnBossFrm( !bEndn
) )
554 SwPageFrm
* pTmp
= pFtnFrm
->FindPageFrm();
555 if( pUpdate
&& pUpdate
!= pTmp
)
556 pUpdate
->UpdateFtnNum();
560 pFtnFrm
->SetRef( pDest
);
561 pFtnFrm
= pFtnFrm
->GetFollow();
567 pEndBoss
->MoveFtns( this, pDest
, pFtn
);
569 pFtnBoss
->MoveFtns( this, pDest
, pFtn
);
572 ((SwTxtFrm
*)pDest
)->SetFtn( sal_True
);
574 ASSERT( pDest
->FindFtnBossFrm( !bEndn
)->FindFtn( pDest
,
575 pFtn
),"SwTxtFrm::RemoveFtn: footnote ChgRef failed");
579 if( !bEndDoc
|| ( bEndn
&& pEndBoss
->IsInSct() &&
580 !SwLayouter::Collecting( GetNode()->GetDoc(),
581 pEndBoss
->FindSctFrm(), NULL
) ) )
584 pEndBoss
->RemoveFtn( this, pFtn
);
586 pFtnBoss
->RemoveFtn( this, pFtn
);
587 bRemove
= bRemove
|| !bEndDoc
;
588 ASSERT( bEndn
? !pEndBoss
->FindFtn( this, pFtn
) :
589 !pFtnBoss
->FindFtn( this, pFtn
),
590 "SwTxtFrm::RemoveFtn: can't get off that footnote" );
597 pUpdate
->UpdateFtnNum();
598 // Wir bringen die Oszillation zum stehen:
599 if( bRemove
&& !bFtnEndDoc
&& HasPara() )
605 // Folgendes Problem: Aus dem FindBreak heraus wird das RemoveFtn aufgerufen,
606 // weil die letzte Zeile an den Follow abgegeben werden soll. Der Offset
607 // des Follows ist aber veraltet, er wird demnaechst gesetzt. CalcFntFlag ist
608 // auf einen richtigen Follow-Offset angewiesen. Deshalb wird hier kurzfristig
609 // der Follow-Offset manipuliert.
610 xub_StrLen nOldOfst
= STRING_LEN
;
611 if( HasFollow() && nStart
> GetOfst() )
613 nOldOfst
= GetFollow()->GetOfst();
614 GetFollow()->ManipOfst( nStart
+ ( bRollBack
? nLen
: 0 ) );
616 pSource
->CalcFtnFlag();
617 if( nOldOfst
< STRING_LEN
)
618 GetFollow()->ManipOfst( nOldOfst
);
621 /*************************************************************************
622 * SwTxtFormatter::ConnectFtn()
623 *************************************************************************/
624 // sal_False, wenn irgendetwas schief gegangen ist.
625 // Es gibt eigentlich nur zwei Moeglichkeiten:
626 // a) Die Ftn ist bereits vorhanden
627 // => dann wird sie gemoved, wenn ein anderer pSrcFrm gefunden wurde
628 // b) Die Ftn ist nicht vorhanden
629 // => dann wird sie fuer uns angelegt.
630 // Ob die Ftn schliesslich auf unserer Spalte/Seite landet oder nicht,
631 // spielt in diesem Zusammenhang keine Rolle.
632 // Optimierungen bei Endnoten.
633 // Noch ein Problem: wenn die Deadline im Ftn-Bereich liegt, muss die
634 // Ftn verschoben werden.
636 void SwTxtFrm::ConnectFtn( SwTxtFtn
*pFtn
, const SwTwips nDeadLine
)
638 ASSERT( !IsVertical() || !IsSwapped(),
639 "SwTxtFrm::ConnectFtn with swapped frame" );
642 bInFtnConnect
= sal_True
; //Bloss zuruecksetzen!
643 sal_Bool bEnd
= pFtn
->GetFtn().IsEndNote();
646 // We want to store this value, because it is needed as a fallback
647 // in GetFtnLine(), if there is no paragraph information available
649 mnFtnLine
= nDeadLine
;
651 // Wir brauchen immer einen Boss (Spalte/Seite)
653 SwCntntFrm
*pCntnt
= this;
654 if( bEnd
&& IsInSct() )
656 pSect
= FindSctFrm();
657 if( pSect
->IsEndnAtEnd() )
658 pCntnt
= pSect
->FindLastCntnt( FINDMODE_ENDNOTE
);
663 SwFtnBossFrm
*pBoss
= pCntnt
->FindFtnBossFrm( !bEnd
);
665 #if OSL_DEBUG_LEVEL > 1
666 SwTwips nRstHeight
= GetRstHeight();
669 pSect
= pBoss
->FindSctFrm();
670 sal_Bool bDocEnd
= bEnd
? !( pSect
&& pSect
->IsEndnAtEnd() ) :
671 ( !( pSect
&& pSect
->IsFtnAtEnd() ) &&
672 FTNPOS_CHAPTER
== GetNode()->GetDoc()->GetFtnInfo().ePos
);
673 //Ftn kann beim Follow angemeldet sein.
674 SwCntntFrm
*pSrcFrm
= FindFtnRef( pFtn
);
678 if( pSect
&& pSrcFrm
)
680 SwFtnFrm
*pFtnFrm
= pBoss
->FindFtn( pSrcFrm
, pFtn
);
681 if( pFtnFrm
&& pFtnFrm
->IsInSct() )
683 pBoss
->RemoveFtn( pSrcFrm
, pFtn
);
688 else if( bEnd
&& pSect
)
690 SwFtnFrm
*pFtnFrm
= pSrcFrm
? pBoss
->FindFtn( pSrcFrm
, pFtn
) : NULL
;
691 if( pFtnFrm
&& !pFtnFrm
->GetUpper() )
693 SwDoc
*pDoc
= GetNode()->GetDoc();
694 if( SwLayouter::Collecting( pDoc
, pSect
, pFtnFrm
) )
698 SwFtnFrm
*pNew
= new SwFtnFrm(pDoc
->GetDfltFrmFmt(),this,pFtn
);
699 SwNodeIndex
aIdx( *pFtn
->GetStartNode(), 1 );
700 ::_InsertCnt( pNew
, pDoc
, aIdx
.GetIndex() );
701 GetNode()->getIDocumentLayoutAccess()->GetLayouter()->CollectEndnote( pNew
);
703 else if( pSrcFrm
!= this )
704 pBoss
->ChangeFtnRef( pSrcFrm
, pFtn
, this );
705 bInFtnConnect
= sal_False
;
710 SwFtnBossFrm
*pFtnBoss
= pFtnFrm
->FindFtnBossFrm();
711 if( !pFtnBoss
->IsInSct() ||
712 pFtnBoss
->ImplFindSctFrm()->GetSection()!=pSect
->GetSection() )
714 pBoss
->RemoveFtn( pSrcFrm
, pFtn
);
720 if( bDocEnd
|| bEnd
)
723 pBoss
->AppendFtn( this, pFtn
);
724 else if( pSrcFrm
!= this )
725 pBoss
->ChangeFtnRef( pSrcFrm
, pFtn
, this );
726 bInFtnConnect
= sal_False
;
730 SwSaveFtnHeight
aHeight( pBoss
, nDeadLine
);
732 if( !pSrcFrm
) // Es wurde ueberhaupt keine Ftn gefunden.
733 pBoss
->AppendFtn( this, pFtn
);
736 SwFtnFrm
*pFtnFrm
= pBoss
->FindFtn( pSrcFrm
, pFtn
);
737 SwFtnBossFrm
*pFtnBoss
= pFtnFrm
->FindFtnBossFrm();
739 sal_Bool bBrutal
= sal_False
;
741 if( pFtnBoss
== pBoss
) // Ref und Ftn sind auf der selben Seite/Spalte.
743 SwFrm
*pCont
= pFtnFrm
->GetUpper();
746 long nDiff
= (*fnRect
->fnYDiff
)( (pCont
->Frm().*fnRect
->fnGetTop
)(),
751 //Wenn die Fussnote bei einem Follow angemeldet ist, so ist
752 //es jetzt an der Zeit sie umzumelden.
753 if ( pSrcFrm
!= this )
754 pBoss
->ChangeFtnRef( pSrcFrm
, pFtn
, this );
755 //Es steht Platz zur Verfuegung, also kann die Fussnote evtl.
757 if ( pFtnFrm
->GetFollow() && nDiff
> 0 )
759 SwTwips nHeight
= (pCont
->Frm().*fnRect
->fnGetHeight
)();
760 pBoss
->RearrangeFtns( nDeadLine
, sal_False
, pFtn
);
763 ViewShell
*pSh
= GetShell();
764 if ( pSh
&& nHeight
== (pCont
->Frm().*fnRect
->fnGetHeight
)() )
765 //Damit uns nix durch die Lappen geht.
766 pSh
->InvalidateWindows( pCont
->Frm() );
768 bInFtnConnect
= sal_False
;
776 // Ref und Ftn sind nicht auf einer Seite, Move-Versuch ist noetig.
778 while( pTmp
->GetNext() && pSrcFrm
!= pTmp
)
779 pTmp
= pTmp
->GetNext();
780 if( pSrcFrm
== pTmp
)
783 { // Wenn unser Boss in einem spaltigen Bereich sitzt, es aber auf
784 // der Seite schon einen FtnContainer gibt, hilft nur die brutale
786 if( pSect
&& pSect
->FindFtnBossFrm( !bEnd
)->FindFtnCont() )
788 // OD 08.11.2002 #104840# - use <SwLayoutFrm::IsBefore(..)>
789 else if ( !pFtnFrm
->GetPrev() ||
790 pFtnBoss
->IsBefore( pBoss
)
793 SwFtnBossFrm
*pSrcBoss
= pSrcFrm
->FindFtnBossFrm( !bEnd
);
794 pSrcBoss
->MoveFtns( pSrcFrm
, this, pFtn
);
797 pBoss
->ChangeFtnRef( pSrcFrm
, pFtn
, this );
801 // Die brutale Loesung: Fussnote entfernen und appenden.
802 // Es muss SetFtnDeadLine() gerufen werden, weil nach
803 // RemoveFtn die nMaxFtnHeight evtl. besser auf unsere Wuensche
804 // eingestellt werden kann.
807 pBoss
->RemoveFtn( pSrcFrm
, pFtn
, sal_False
);
808 SwSaveFtnHeight
*pHeight
= bEnd
? NULL
:
809 new SwSaveFtnHeight( pBoss
, nDeadLine
);
810 pBoss
->AppendFtn( this, pFtn
);
815 // In spaltigen Bereichen, die noch nicht bis zum Seitenrand gehen,
816 // ist kein RearrangeFtns sinnvoll, da der Fussnotencontainer noch
817 // nicht kalkuliert worden ist.
818 if( !pSect
|| !pSect
->Growable() )
820 // Umgebung validieren, um Oszillationen zu verhindern.
821 SwSaveFtnHeight
aNochmal( pBoss
, nDeadLine
);
823 pBoss
->RearrangeFtns( nDeadLine
, sal_True
);
826 else if( pSect
->IsFtnAtEnd() )
832 #if OSL_DEBUG_LEVEL > 1
833 // pFtnFrm kann sich durch Calc veraendert haben ...
834 SwFtnFrm
*pFtnFrm
= pBoss
->FindFtn( this, pFtn
);
835 if( pFtnFrm
&& pBoss
!= pFtnFrm
->FindFtnBossFrm( !bEnd
) )
840 nRstHeight
= GetRstHeight();
842 bInFtnConnect
= sal_False
;
848 /*************************************************************************
849 * SwTxtFormatter::NewFtnPortion()
850 *************************************************************************/
852 // Die Portion fuer die Ftn-Referenz im Text
853 SwFtnPortion
*SwTxtFormatter::NewFtnPortion( SwTxtFormatInfo
&rInf
,
856 ASSERT( ! pFrm
->IsVertical() || pFrm
->IsSwapped(),
857 "NewFtnPortion with unswapped frame" );
859 if( !pFrm
->IsFtnAllowed() )
862 SwTxtFtn
*pFtn
= (SwTxtFtn
*)pHint
;
863 SwFmtFtn
& rFtn
= (SwFmtFtn
&)pFtn
->GetFtn();
864 SwDoc
*pDoc
= pFrm
->GetNode()->GetDoc();
867 return new SwFtnPortion( rFtn
.GetViewNumStr( *pDoc
), pFrm
, pFtn
);
869 SWAP_IF_SWAPPED( pFrm
)
873 KSHORT nOldReal
= pCurr
->GetRealHeight();
874 KSHORT nOldAscent
= pCurr
->GetAscent();
875 KSHORT nOldHeight
= pCurr
->Height();
876 ((SwTxtFormatter
*)this)->CalcRealHeight();
877 nReal
= pCurr
->GetRealHeight();
878 if( nReal
< nOldReal
)
880 pCurr
->SetRealHeight( nOldReal
);
881 pCurr
->Height( nOldHeight
);
882 pCurr
->SetAscent( nOldAscent
);
885 SwTwips nLower
= Y() + nReal
;
887 const bool bVertical
= pFrm
->IsVertical();
889 nLower
= pFrm
->SwitchHorizontalToVertical( nLower
);
891 nLower
= lcl_GetFtnLower( pFrm
, nLower
);
893 //6995: Wir frischen nur auf. Das Connect tut fuer diesen Fall nix
894 //Brauchbares, sondern wuerde stattdessen fuer diesen Fall meist die
895 //Ftn wegwerfen und neu erzeugen.
897 if( !rInf
.IsQuick() )
898 pFrm
->ConnectFtn( pFtn
, nLower
);
900 SwTxtFrm
*pScrFrm
= pFrm
->FindFtnRef( pFtn
);
901 SwFtnBossFrm
*pBoss
= pFrm
->FindFtnBossFrm( !rFtn
.IsEndNote() );
902 SwFtnFrm
*pFtnFrm
= NULL
;
904 pFtnFrm
= pBoss
->FindFtn( pScrFrm
, pFtn
);
906 // Wir erkundigen uns, ob durch unser Append irgendeine
907 // Fussnote noch auf der Seite/Spalte steht. Wenn nicht verschwindet
908 // auch unsere Zeile. Dies fuehrt zu folgendem erwuenschten
909 // Verhalten: Ftn1 pass noch auf die Seite/Spalte, Ftn2 nicht mehr.
910 // Also bleibt die Ftn2-Referenz auf der Seite/Spalte stehen. Die
911 // Fussnote selbst folgt aber erst auf der naechsten Seite/Spalte.
912 // Ausnahme: Wenn keine weitere Zeile auf diese Seite/Spalte passt,
913 // so sollte die Ftn2-Referenz auch auf die naechste wandern.
914 if( !rFtn
.IsEndNote() )
916 SwSectionFrm
*pSct
= pBoss
->FindSctFrm();
917 sal_Bool bAtSctEnd
= pSct
&& pSct
->IsFtnAtEnd();
918 if( FTNPOS_CHAPTER
!= pDoc
->GetFtnInfo().ePos
|| bAtSctEnd
)
920 SwFrm
* pFtnCont
= pBoss
->FindFtnCont();
921 // Wenn der Boss in einem Bereich liegt, kann es sich nur um eine
922 // Spalte dieses Bereichs handeln. Wenn dies nicht die erste Spalte
923 // ist, duerfen wir ausweichen
924 if( !pFrm
->IsInTab() && ( GetLineNr() > 1 || pFrm
->GetPrev() ||
925 ( !bAtSctEnd
&& pFrm
->GetIndPrev() ) ||
926 ( pSct
&& pBoss
->GetPrev() ) ) )
930 rInf
.SetStop( sal_True
);
936 // Es darf keine Fussnotencontainer in spaltigen Bereichen und
937 // gleichzeitig auf der Seite/Seitenspalte geben
938 if( pSct
&& !bAtSctEnd
) // liegt unser Container in einem (spaltigen) Bereich?
940 SwFtnBossFrm
* pTmp
= pBoss
->FindSctFrm()->FindFtnBossFrm( sal_True
);
941 SwFtnContFrm
* pFtnC
= pTmp
->FindFtnCont();
944 SwFtnFrm
* pTmpFrm
= (SwFtnFrm
*)pFtnC
->Lower();
945 if( pTmpFrm
&& *pTmpFrm
< pFtn
)
947 rInf
.SetStop( sal_True
);
953 // Ist dies die letzte passende Zeile?
954 SwTwips nTmpBot
= Y() + nReal
* 2;
957 nTmpBot
= pFrm
->SwitchHorizontalToVertical( nTmpBot
);
961 const long nDiff
= (*fnRect
->fnYDiff
)(
962 (pFtnCont
->Frm().*fnRect
->fnGetTop
)(),
965 if( pScrFrm
&& nDiff
< 0 )
969 SwFtnBossFrm
*pFtnBoss
= pFtnFrm
->FindFtnBossFrm();
970 if( pFtnBoss
!= pBoss
)
972 // Wir sind in der letzte Zeile und die Fussnote
973 // ist auf eine andere Seite gewandert, dann wollen
975 rInf
.SetStop( sal_True
);
985 // Endlich: FtnPortion anlegen und raus hier...
986 SwFtnPortion
*pRet
= new SwFtnPortion( rFtn
.GetViewNumStr( *pDoc
),
988 rInf
.SetFtnInside( sal_True
);
995 /*************************************************************************
996 * SwTxtFormatter::NewFtnNumPortion()
997 *************************************************************************/
999 // Die Portion fuer die Ftn-Nummerierung im Ftn-Bereich
1001 SwNumberPortion
*SwTxtFormatter::NewFtnNumPortion( SwTxtFormatInfo
&rInf
) const
1003 ASSERT( pFrm
->IsInFtn() && !pFrm
->GetIndPrev() && !rInf
.IsFtnDone(),
1004 "This is the wrong place for a ftnnumber" );
1005 if( rInf
.GetTxtStart() != nStart
||
1006 rInf
.GetTxtStart() != rInf
.GetIdx() )
1009 const SwFtnFrm
* pFtnFrm
= pFrm
->FindFtnFrm();
1010 const SwTxtFtn
* pFtn
= pFtnFrm
->GetAttr();
1012 // Aha, wir sind also im Fussnotenbereich
1013 SwFmtFtn
& rFtn
= (SwFmtFtn
&)pFtn
->GetFtn();
1015 SwDoc
*pDoc
= pFrm
->GetNode()->GetDoc();
1016 XubString
aFtnTxt( rFtn
.GetViewNumStr( *pDoc
, sal_True
));
1018 const SwEndNoteInfo
* pInfo
;
1019 if( rFtn
.IsEndNote() )
1020 pInfo
= &pDoc
->GetEndNoteInfo();
1022 pInfo
= &pDoc
->GetFtnInfo();
1023 const SwAttrSet
& rSet
= pInfo
->GetCharFmt(*pDoc
)->GetAttrSet();
1025 const SwAttrSet
* pParSet
= &rInf
.GetCharAttr();
1026 const IDocumentSettingAccess
* pIDSA
= pFrm
->GetTxtNode()->getIDocumentSettingAccess();
1027 SwFont
*pNumFnt
= new SwFont( pParSet
, pIDSA
);
1029 // --> FME 2005-02-17 #i37142#
1030 // Underline style of paragraph font should not be considered
1031 // Overline style of paragraph font should not be considered
1032 // Weight style of paragraph font should not be considered
1033 // Posture style of paragraph font should not be considered
1034 // See also #i18463# and SwTxtFormatter::NewNumberPortion()
1035 pNumFnt
->SetUnderline( UNDERLINE_NONE
);
1036 pNumFnt
->SetOverline( UNDERLINE_NONE
);
1037 pNumFnt
->SetItalic( ITALIC_NONE
, SW_LATIN
);
1038 pNumFnt
->SetItalic( ITALIC_NONE
, SW_CJK
);
1039 pNumFnt
->SetItalic( ITALIC_NONE
, SW_CTL
);
1040 pNumFnt
->SetWeight( WEIGHT_NORMAL
, SW_LATIN
);
1041 pNumFnt
->SetWeight( WEIGHT_NORMAL
, SW_CJK
);
1042 pNumFnt
->SetWeight( WEIGHT_NORMAL
, SW_CTL
);
1045 pNumFnt
->SetDiffFnt(&rSet
, pIDSA
);
1046 pNumFnt
->SetVertical( pNumFnt
->GetOrientation(), pFrm
->IsVertical() );
1048 SwFtnNumPortion
* pNewPor
= new SwFtnNumPortion( aFtnTxt
, pNumFnt
);
1049 pNewPor
->SetLeft( !pFrm
->IsRightToLeft() );
1053 /*************************************************************************
1054 * SwTxtFormatter::NewErgoSumPortion()
1055 *************************************************************************/
1057 XubString
lcl_GetPageNumber( const SwPageFrm
* pPage
)
1059 ASSERT( pPage
, "GetPageNumber: Homeless TxtFrm" );
1060 MSHORT nVirtNum
= pPage
->GetVirtPageNum();
1061 const SvxNumberType
& rNum
= pPage
->GetPageDesc()->GetNumType();
1062 return rNum
.GetNumStr( nVirtNum
);
1065 SwErgoSumPortion
*SwTxtFormatter::NewErgoSumPortion( SwTxtFormatInfo
&rInf
) const
1067 // Wir koennen nicht davon ausgehen, dass wir ein Follow sind
1068 // 7983: GetIdx() nicht nStart
1069 if( !pFrm
->IsInFtn() || pFrm
->GetPrev() ||
1070 rInf
.IsErgoDone() || rInf
.GetIdx() != pFrm
->GetOfst() ||
1071 pFrm
->ImplFindFtnFrm()->GetAttr()->GetFtn().IsEndNote() )
1074 // Aha, wir sind also im Fussnotenbereich
1075 const SwFtnInfo
&rFtnInfo
= pFrm
->GetNode()->GetDoc()->GetFtnInfo();
1076 SwTxtFrm
*pQuoFrm
= pFrm
->FindQuoVadisFrm();
1079 const SwPageFrm
* pPage
= pFrm
->FindPageFrm();
1080 const SwPageFrm
* pQuoPage
= pQuoFrm
->FindPageFrm();
1081 if( pPage
== pQuoFrm
->FindPageFrm() )
1082 return 0; // Wenn der QuoVadis auf der selben (spaltigen) Seite steht
1083 const XubString aPage
= lcl_GetPageNumber( pPage
);
1084 SwParaPortion
*pPara
= pQuoFrm
->GetPara();
1086 pPara
->SetErgoSumNum( aPage
);
1087 if( !rFtnInfo
.aErgoSum
.Len() )
1089 SwErgoSumPortion
*pErgo
= new SwErgoSumPortion( rFtnInfo
.aErgoSum
,
1090 lcl_GetPageNumber( pQuoPage
) );
1094 /*************************************************************************
1095 * SwTxtFormatter::FormatQuoVadis()
1096 *************************************************************************/
1098 xub_StrLen
SwTxtFormatter::FormatQuoVadis( const xub_StrLen nOffset
)
1100 ASSERT( ! pFrm
->IsVertical() || ! pFrm
->IsSwapped(),
1101 "SwTxtFormatter::FormatQuoVadis with swapped frame" );
1103 if( !pFrm
->IsInFtn() || pFrm
->ImplFindFtnFrm()->GetAttr()->GetFtn().IsEndNote() )
1106 const SwFrm
* pErgoFrm
= pFrm
->FindFtnFrm()->GetFollow();
1107 if( !pErgoFrm
&& pFrm
->HasFollow() )
1108 pErgoFrm
= pFrm
->GetFollow();
1112 if( pErgoFrm
== pFrm
->GetNext() )
1114 SwFrm
*pCol
= pFrm
->FindColFrm();
1115 while( pCol
&& !pCol
->GetNext() )
1116 pCol
= pCol
->GetUpper()->FindColFrm();
1122 const SwPageFrm
* pPage
= pFrm
->FindPageFrm();
1123 const SwPageFrm
* pErgoPage
= pErgoFrm
->FindPageFrm();
1124 if( pPage
== pErgoPage
)
1125 return nOffset
; // Wenn der ErgoSum auf der selben Seite steht
1128 SwTxtFormatInfo
&rInf
= GetInfo();
1129 const SwFtnInfo
&rFtnInfo
= pFrm
->GetNode()->GetDoc()->GetFtnInfo();
1130 if( !rFtnInfo
.aQuoVadis
.Len() )
1133 // Ein Wort zu QuoVadis/ErgoSum:
1134 // Fuer diese Texte wird der am Absatz eingestellte Font verwendet.
1135 // Wir initialisieren uns also:
1138 SeekStartAndChg( rInf
, sal_True
);
1139 if( GetRedln() && pCurr
->HasRedline() )
1140 GetRedln()->Seek( *pFnt
, nOffset
, 0 );
1142 // Ein fieser Sonderfall: Flyfrms reichen in die Zeile und stehen
1143 // natuerlich da, wo wir unseren Quovadis Text reinsetzen wollen.
1144 // Erst mal sehen, ob es so schlimm ist:
1145 SwLinePortion
*pPor
= pCurr
->GetFirstPortion();
1146 KSHORT nLastLeft
= 0;
1149 if ( pPor
->IsFlyPortion() )
1150 nLastLeft
= ( (SwFlyPortion
*) pPor
)->Fix() +
1151 ( (SwFlyPortion
*) pPor
)->Width();
1152 pPor
= pPor
->GetPortion();
1154 // Das alte Spiel: wir wollen, dass die Zeile an einer bestimmten
1155 // Stelle umbricht, also beeinflussen wir die Width.
1156 // nLastLeft ist jetzt quasi der rechte Rand.
1157 const KSHORT nOldRealWidth
= rInf
.RealWidth();
1158 rInf
.RealWidth( nOldRealWidth
- nLastLeft
);
1160 XubString aErgo
= lcl_GetPageNumber( pErgoFrm
->FindPageFrm() );
1161 SwQuoVadisPortion
*pQuo
= new SwQuoVadisPortion(rFtnInfo
.aQuoVadis
, aErgo
);
1162 pQuo
->SetAscent( rInf
.GetAscent() );
1163 pQuo
->Height( rInf
.GetTxtHeight() );
1164 pQuo
->Format( rInf
);
1165 USHORT nQuoWidth
= pQuo
->Width();
1166 SwLinePortion
* pCurrPor
= pQuo
;
1168 while ( rInf
.GetRest() )
1170 SwLinePortion
* pFollow
= rInf
.GetRest();
1172 pCurrPor
->Move( rInf
);
1174 ASSERT( pFollow
->IsQuoVadisPortion(),
1175 "Quo Vadis, rest of QuoVadisPortion" )
1177 // format the rest and append it to the other QuoVadis parts
1178 pFollow
->Format( rInf
);
1179 nQuoWidth
= nQuoWidth
+ pFollow
->Width();
1181 pCurrPor
->Append( pFollow
);
1185 nLastLeft
= nOldRealWidth
- nQuoWidth
;
1186 Right( Right() - nQuoWidth
);
1188 SWAP_IF_NOT_SWAPPED( pFrm
)
1190 const xub_StrLen nRet
= FormatLine( nStart
);
1194 Right( rInf
.Left() + nOldRealWidth
- 1 );
1196 nLastLeft
= nOldRealWidth
- pCurr
->Width();
1199 // Es kann durchaus sein, dass am Ende eine Marginportion steht,
1200 // die beim erneuten Aufspannen nur Aerger bereiten wuerde.
1201 pPor
= pCurr
->FindLastPortion();
1202 SwGluePortion
*pGlue
= pPor
->IsMarginPortion() ?
1203 (SwMarginPortion
*) pPor
: 0;
1209 pGlue
->SetAscent( 0 );
1210 pGlue
->SetPortion( NULL
);
1211 pGlue
->SetFixWidth(0);
1214 // Luxus: Wir sorgen durch das Aufspannen von Glues dafuer,
1215 // dass der QuoVadis-Text rechts erscheint:
1216 nLastLeft
= nLastLeft
- nQuoWidth
;
1219 if( nLastLeft
> pQuo
->GetAscent() ) // Mindestabstand
1221 switch( GetAdjust() )
1223 case SVX_ADJUST_BLOCK
:
1225 if( !pCurr
->GetLen() ||
1226 CH_BREAK
!= GetInfo().GetChar(nStart
+pCurr
->GetLen()-1))
1227 nLastLeft
= pQuo
->GetAscent();
1228 nQuoWidth
= nQuoWidth
+ nLastLeft
;
1231 case SVX_ADJUST_RIGHT
:
1233 nLastLeft
= pQuo
->GetAscent();
1234 nQuoWidth
= nQuoWidth
+ nLastLeft
;
1237 case SVX_ADJUST_CENTER
:
1239 nQuoWidth
= nQuoWidth
+ pQuo
->GetAscent();
1240 long nDiff
= nLastLeft
- nQuoWidth
;
1243 nLastLeft
= pQuo
->GetAscent();
1244 nQuoWidth
= (USHORT
)(-nDiff
+ nLastLeft
);
1249 nLastLeft
= USHORT(( pQuo
->GetAscent() + nDiff
) / 2);
1254 nQuoWidth
= nQuoWidth
+ nLastLeft
;
1258 nQuoWidth
= nQuoWidth
+ nLastLeft
;
1261 pGlue
= new SwGluePortion(0);
1262 pGlue
->Width( nLastLeft
);
1263 pPor
->Append( pGlue
);
1264 pPor
= pPor
->GetPortion();
1268 // Jetzt aber: die QuoVadis-Portion wird angedockt:
1272 // pPor->Append deletes the pPortoin pointer of pPor. Therefore
1273 // we have to keep a pointer to the next portion
1274 pQuo
= (SwQuoVadisPortion
*)pCurrPor
->GetPortion();
1275 pPor
->Append( pCurrPor
);
1276 pPor
= pPor
->GetPortion();
1280 pCurr
->Width( pCurr
->Width() + KSHORT( nQuoWidth
) );
1282 // Und noch einmal adjustieren wegen des Adjustment und nicht zu Letzt
1283 // wegen folgendem Sonderfall: In der Zeile hat der DummUser durchgaengig
1284 // einen kleineren Font eingestellt als der vom QuoVadis-Text ...
1285 CalcAdjustLine( pCurr
);
1287 #if OSL_DEBUG_LEVEL > 1
1288 if( OPTDBG( rInf
) )
1290 // aDbstream << "FormatQuoVadis:" << endl;
1291 // pCurr->DebugPortions( aDbstream, rInf.GetTxt(), nStart );
1300 /*************************************************************************
1301 * SwTxtFormatter::MakeDummyLine()
1302 *************************************************************************/
1304 // MakeDummyLine() erzeugt eine Line, die bis zum unteren Seitenrand
1305 // reicht. DummyLines bzw. DummyPortions sorgen dafuer, dass Oszillationen
1306 // zum stehen kommen, weil Rueckflussmoeglichkeiten genommen werden.
1307 // Sie werden bei absatzgebundenen Frames in Fussnoten und bei Ftn-
1308 // Oszillationen verwendet.
1310 void SwTxtFormatter::MakeDummyLine()
1312 KSHORT nRstHeight
= GetFrmRstHeight();
1313 if( pCurr
&& nRstHeight
> pCurr
->Height() )
1315 SwLineLayout
*pLay
= new SwLineLayout
;
1316 nRstHeight
= nRstHeight
- pCurr
->Height();
1317 pLay
->Height( nRstHeight
);
1318 pLay
->SetAscent( nRstHeight
);
1324 /*************************************************************************
1326 *************************************************************************/
1329 SwTxtSizeInfo
*pInf
;
1333 SwFtnSave( const SwTxtSizeInfo
&rInf
,
1334 const SwTxtFtn
*pTxtFtn
,
1335 const bool bApplyGivenScriptType
,
1336 const BYTE nGivenScriptType
);
1340 /*************************************************************************
1341 * SwFtnSave::SwFtnSave()
1342 *************************************************************************/
1344 SwFtnSave::SwFtnSave( const SwTxtSizeInfo
&rInf
,
1345 const SwTxtFtn
* pTxtFtn
,
1346 const bool bApplyGivenScriptType
,
1347 const BYTE nGivenScriptType
)
1348 : pInf( &((SwTxtSizeInfo
&)rInf
) )
1352 if( pTxtFtn
&& rInf
.GetTxtFrm() )
1354 pFnt
= ((SwTxtSizeInfo
&)rInf
).GetFont();
1355 pOld
= new SwFont( *pFnt
);
1356 pOld
->GetTox() = pFnt
->GetTox();
1358 SwFmtFtn
& rFtn
= (SwFmtFtn
&)pTxtFtn
->GetFtn();
1359 const SwDoc
*pDoc
= rInf
.GetTxtFrm()->GetNode()->GetDoc();
1361 // --> OD 2009-01-29 #i98418#
1362 if ( bApplyGivenScriptType
)
1364 pFnt
->SetActual( nGivenScriptType
);
1368 // examine text and set script
1369 String
aTmpStr( rFtn
.GetViewNumStr( *pDoc
) );
1370 pFnt
->SetActual( SwScriptInfo::WhichFont( 0, &aTmpStr
, 0 ) );
1374 const SwEndNoteInfo
* pInfo
;
1375 if( rFtn
.IsEndNote() )
1376 pInfo
= &pDoc
->GetEndNoteInfo();
1378 pInfo
= &pDoc
->GetFtnInfo();
1379 const SwAttrSet
& rSet
= pInfo
->GetAnchorCharFmt((SwDoc
&)*pDoc
)->GetAttrSet();
1380 pFnt
->SetDiffFnt( &rSet
, rInf
.GetTxtFrm()->GetNode()->getIDocumentSettingAccess() );
1382 // we reduce footnote size, if we are inside a double line portion
1383 if ( ! pOld
->GetEscapement() && 50 == pOld
->GetPropr() )
1385 Size aSize
= pFnt
->GetSize( pFnt
->GetActual() );
1386 pFnt
->SetSize( Size( (long)aSize
.Width() / 2,
1387 (long)aSize
.Height() / 2 ),
1388 pFnt
->GetActual() );
1391 // set the correct rotation at the footnote font
1392 const SfxPoolItem
* pItem
;
1393 if( SFX_ITEM_SET
== rSet
.GetItemState( RES_CHRATR_ROTATE
,
1395 pFnt
->SetVertical( ((SvxCharRotateItem
*)pItem
)->GetValue(),
1396 rInf
.GetTxtFrm()->IsVertical() );
1398 pFnt
->ChgPhysFnt( pInf
->GetVsh(), *pInf
->GetOut() );
1400 if( SFX_ITEM_SET
== rSet
.GetItemState( RES_CHRATR_BACKGROUND
,
1402 pFnt
->SetBackColor( new Color( ((SvxBrushItem
*)pItem
)->GetColor() ) );
1408 /*************************************************************************
1409 * SwFtnSave::~SwFtnSave()
1410 *************************************************************************/
1412 SwFtnSave::~SwFtnSave()
1416 // SwFont zurueckstellen
1418 pFnt
->GetTox() = pOld
->GetTox();
1419 pFnt
->ChgPhysFnt( pInf
->GetVsh(), *pInf
->GetOut() );
1424 /*************************************************************************
1425 * SwFtnPortion::SwFtnPortion()
1426 *************************************************************************/
1428 SwFtnPortion::SwFtnPortion( const XubString
&rExpand
, SwTxtFrm
*pFrame
,
1429 SwTxtFtn
*pFootn
, KSHORT nReal
)
1430 : SwFldPortion( rExpand
, 0 )
1433 , nOrigHeight( nReal
)
1434 // --> OD 2009-01-29 #i98418#
1435 , mbPreferredScriptTypeSet( false )
1436 , mnPreferredScriptType( SW_LATIN
)
1440 SetWhichPor( POR_FTN
);
1443 /*************************************************************************
1444 * SwFtnPortion::GetExpTxt()
1445 *************************************************************************/
1447 sal_Bool
SwFtnPortion::GetExpTxt( const SwTxtSizeInfo
&, XubString
&rTxt
) const
1453 /*************************************************************************
1454 * virtual SwFtnPortion::Format()
1455 *************************************************************************/
1457 sal_Bool
SwFtnPortion::Format( SwTxtFormatInfo
&rInf
)
1459 // --> OD 2009-01-29 #i98418#
1460 // SwFtnSave aFtnSave( rInf, pFtn );
1461 SwFtnSave
aFtnSave( rInf
, pFtn
, mbPreferredScriptTypeSet
, mnPreferredScriptType
);
1463 // the idx is manipulated in SwExpandPortion::Format
1464 // this flag indicates, that a footnote is allowed to trigger
1465 // an underflow during SwTxtGuess::Guess
1466 rInf
.SetFakeLineStart( rInf
.GetIdx() > rInf
.GetLineStart() );
1467 sal_Bool bFull
= SwFldPortion::Format( rInf
);
1468 rInf
.SetFakeLineStart( sal_False
);
1469 SetAscent( rInf
.GetAscent() );
1470 Height( rInf
.GetTxtHeight() );
1471 rInf
.SetFtnDone( !bFull
);
1477 /*************************************************************************
1478 * virtual SwFtnPortion::Paint()
1479 *************************************************************************/
1481 void SwFtnPortion::Paint( const SwTxtPaintInfo
&rInf
) const
1483 // --> OD 2009-01-29 #i98418#
1484 // SwFtnSave aFtnSave( rInf, pFtn );
1485 SwFtnSave
aFtnSave( rInf
, pFtn
, mbPreferredScriptTypeSet
, mnPreferredScriptType
);
1487 rInf
.DrawViewOpt( *this, POR_FTN
);
1488 SwExpandPortion::Paint( rInf
);
1491 /*************************************************************************
1492 * virtual SwFtnPortion::GetTxtSize()
1493 *************************************************************************/
1495 SwPosSize
SwFtnPortion::GetTxtSize( const SwTxtSizeInfo
&rInfo
) const
1497 // --> OD 2009-01-29 #i98418#
1498 // SwFtnSave aFtnSave( rInfo, pFtn );
1499 SwFtnSave
aFtnSave( rInfo
, pFtn
, mbPreferredScriptTypeSet
, mnPreferredScriptType
);
1501 return SwExpandPortion::GetTxtSize( rInfo
);
1504 // --> OD 2009-01-29 #i98418#
1505 void SwFtnPortion::SetPreferredScriptType( BYTE nPreferredScriptType
)
1507 mbPreferredScriptTypeSet
= true;
1508 mnPreferredScriptType
= nPreferredScriptType
;
1512 /*************************************************************************
1513 * class SwQuoVadisPortion
1514 *************************************************************************/
1516 SwFldPortion
*SwQuoVadisPortion::Clone( const XubString
&rExpand
) const
1517 { return new SwQuoVadisPortion( rExpand
, aErgo
); }
1519 SwQuoVadisPortion::SwQuoVadisPortion( const XubString
&rExp
, const XubString
& rStr
)
1520 : SwFldPortion( rExp
), aErgo(rStr
)
1523 SetWhichPor( POR_QUOVADIS
);
1526 /*************************************************************************
1527 * virtual SwQuoVadisPortion::Format()
1528 *************************************************************************/
1530 sal_Bool
SwQuoVadisPortion::Format( SwTxtFormatInfo
&rInf
)
1532 // erster Versuch, vielleicht passt der Text
1533 CheckScript( rInf
);
1534 sal_Bool bFull
= SwFldPortion::Format( rInf
);
1539 // zweiter Versuch, wir kuerzen den String:
1540 aExpand
= XubString( "...", RTL_TEXTENCODING_MS_1252
);
1541 bFull
= SwFldPortion::Format( rInf
);
1544 // dritter Versuch, es langt: jetzt wird gestaucht:
1545 Width( USHORT(rInf
.Width() - rInf
.X()) );
1547 // 8317: keine mehrzeiligen Felder bei QuoVadis und ErgoSum
1548 if( rInf
.GetRest() )
1550 delete rInf
.GetRest();
1557 /*************************************************************************
1558 * virtual SwQuoVadisPortion::GetExpTxt()
1559 *************************************************************************/
1561 sal_Bool
SwQuoVadisPortion::GetExpTxt( const SwTxtSizeInfo
&, XubString
&rTxt
) const
1564 // if this QuoVadisPortion has a follow, the follow is responsible for
1566 if ( ! HasFollow() )
1571 /*************************************************************************
1572 * virtual SwQuoVadisPortion::HandlePortion()
1573 *************************************************************************/
1575 void SwQuoVadisPortion::HandlePortion( SwPortionHandler
& rPH
) const
1577 String
aString( aExpand
);
1579 rPH
.Special( GetLen(), aString
, GetWhichPor() );
1582 /*************************************************************************
1583 * virtual SwQuoVadisPortion::Paint()
1584 *************************************************************************/
1586 void SwQuoVadisPortion::Paint( const SwTxtPaintInfo
&rInf
) const
1588 // Wir wollen _immer_ per DrawStretchText ausgeben,
1589 // weil nErgo schnell mal wechseln kann.
1592 rInf
.DrawViewOpt( *this, POR_QUOVADIS
);
1593 SwTxtSlot
aDiffTxt( &rInf
, this, true, false );
1594 SwFontSave
aSave( rInf
, pFnt
);
1595 rInf
.DrawText( *this, rInf
.GetLen(), sal_True
);
1599 /*************************************************************************
1600 * class SwErgoSumPortion
1601 *************************************************************************/
1603 SwFldPortion
*SwErgoSumPortion::Clone( const XubString
&rExpand
) const
1605 UniString aTmp
; // = UniString::CreateFromInt32( 0 );
1606 return new SwErgoSumPortion( rExpand
, aTmp
);
1609 SwErgoSumPortion::SwErgoSumPortion( const XubString
&rExp
, const XubString
& rStr
)
1610 : SwFldPortion( rExp
)
1615 // 7773: sinnvolle Massnahme: ein Blank Abstand zum Text
1617 SetWhichPor( POR_ERGOSUM
);
1620 xub_StrLen
SwErgoSumPortion::GetCrsrOfst( const KSHORT
) const
1625 /*************************************************************************
1626 * virtual SwErgoSumPortion::Format()
1627 *************************************************************************/
1629 sal_Bool
SwErgoSumPortion::Format( SwTxtFormatInfo
&rInf
)
1631 sal_Bool bFull
= SwFldPortion::Format( rInf
);
1633 rInf
.SetErgoDone( sal_True
);
1635 // 8317: keine mehrzeiligen Felder bei QuoVadis und ErgoSum
1636 if( bFull
&& rInf
.GetRest() )
1638 delete rInf
.GetRest();
1642 // We return false in order to get some text into the current line,
1643 // even if it's full (better than looping)
1648 /*************************************************************************
1649 * SwParaPortion::SetErgoSumNum()
1650 *************************************************************************/
1652 void SwParaPortion::SetErgoSumNum( const XubString
& rErgo
)
1654 SwLineLayout
*pLay
= this;
1655 while( pLay
->GetNext() )
1658 pLay
= pLay
->GetNext();
1660 SwLinePortion
*pPor
= pLay
;
1661 SwQuoVadisPortion
*pQuo
= 0;
1662 while( pPor
&& !pQuo
)
1664 if ( pPor
->IsQuoVadisPortion() )
1665 pQuo
= (SwQuoVadisPortion
*)pPor
;
1666 pPor
= pPor
->GetPortion();
1669 pQuo
->SetNumber( rErgo
);
1672 /*************************************************************************
1673 * SwParaPortion::UpdateQuoVadis()
1675 * Wird im SwTxtFrm::Prepare() gerufen
1676 *************************************************************************/
1678 sal_Bool
SwParaPortion::UpdateQuoVadis( const XubString
&rQuo
)
1680 SwLineLayout
*pLay
= this;
1681 while( pLay
->GetNext() )
1684 pLay
= pLay
->GetNext();
1686 SwLinePortion
*pPor
= pLay
;
1687 SwQuoVadisPortion
*pQuo
= 0;
1688 while( pPor
&& !pQuo
)
1690 if ( pPor
->IsQuoVadisPortion() )
1691 pQuo
= (SwQuoVadisPortion
*)pPor
;
1692 pPor
= pPor
->GetPortion();
1698 return pQuo
->GetQuoTxt() == rQuo
;