LCOV - code coverage report
Current view: top level - sw/source/core/text - txtftn.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 734 0.0 %
Date: 2014-04-14 Functions: 0 36 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "viewsh.hxx"
      21             : #include "doc.hxx"
      22             : #include "pagefrm.hxx"
      23             : #include "rootfrm.hxx"
      24             : #include "ndtxt.hxx"
      25             : #include "txtatr.hxx"
      26             : #include <SwPortionHandler.hxx>
      27             : #include <txtftn.hxx>
      28             : #include <flyfrm.hxx>
      29             : #include <fmtftn.hxx>
      30             : #include <ftninfo.hxx>
      31             : #include <charfmt.hxx>
      32             : #include <dflyobj.hxx>
      33             : #include <rowfrm.hxx>
      34             : #include <editeng/brushitem.hxx>
      35             : #include <editeng/charrotateitem.hxx>
      36             : #include <breakit.hxx>
      37             : #include <com/sun/star/i18n/ScriptType.hpp>
      38             : #include <tabfrm.hxx>
      39             : // #i28701#
      40             : #include <sortedobjs.hxx>
      41             : 
      42             : #include "swfont.hxx"
      43             : #include "porftn.hxx"
      44             : #include "porfly.hxx"
      45             : #include "porlay.hxx"
      46             : #include "txtfrm.hxx"
      47             : #include "itrform2.hxx"
      48             : #include "ftnfrm.hxx"
      49             : #include "pagedesc.hxx"
      50             : #include "redlnitr.hxx"
      51             : #include "sectfrm.hxx"
      52             : #include "layouter.hxx"
      53             : #include "frmtool.hxx"
      54             : #include "ndindex.hxx"
      55             : 
      56             : using namespace ::com::sun::star;
      57             : 
      58           0 : bool SwTxtFrm::_IsFtnNumFrm() const
      59             : {
      60           0 :     const SwFtnFrm* pFtn = FindFtnFrm()->GetMaster();
      61           0 :     while( pFtn && !pFtn->ContainsCntnt() )
      62           0 :         pFtn = pFtn->GetMaster();
      63           0 :     return !pFtn;
      64             : }
      65             : 
      66             : // Sucht innerhalb einer Master-Follow-Kette den richtigen TxtFrm zum SwTxtFtn
      67           0 : SwTxtFrm *SwTxtFrm::FindFtnRef( const SwTxtFtn *pFtn )
      68             : {
      69           0 :     SwTxtFrm *pFrm = this;
      70           0 :     const bool bFwd = *pFtn->GetStart() >= GetOfst();
      71           0 :     while( pFrm )
      72             :     {
      73           0 :         if( SwFtnBossFrm::FindFtn( pFrm, pFtn ) )
      74           0 :             return pFrm;
      75             :         pFrm = bFwd ? pFrm->GetFollow() :
      76           0 :                       pFrm->IsFollow() ? pFrm->FindMaster() : 0;
      77             :     }
      78           0 :     return pFrm;
      79             : }
      80             : 
      81             : #ifdef DBG_UTIL
      82             : void SwTxtFrm::CalcFtnFlag( sal_Int32 nStop )// For testing the SplitFrm
      83             : #else
      84           0 : void SwTxtFrm::CalcFtnFlag()
      85             : #endif
      86             : {
      87           0 :     bFtn = false;
      88             : 
      89           0 :     const SwpHints *pHints = GetTxtNode()->GetpSwpHints();
      90           0 :     if( !pHints )
      91           0 :         return;
      92             : 
      93           0 :     const sal_uInt16 nSize = pHints->Count();
      94             : 
      95             : #ifdef DBG_UTIL
      96             :     const sal_Int32 nEnd = nStop != COMPLETE_STRING ? nStop
      97             :                         : GetFollow() ? GetFollow()->GetOfst() : COMPLETE_STRING;
      98             : #else
      99           0 :     const sal_Int32 nEnd = GetFollow() ? GetFollow()->GetOfst() : COMPLETE_STRING;
     100             : #endif
     101             : 
     102           0 :     for ( sal_uInt16 i = 0; i < nSize; ++i )
     103             :     {
     104           0 :         const SwTxtAttr *pHt = (*pHints)[i];
     105           0 :         if ( pHt->Which() == RES_TXTATR_FTN )
     106             :         {
     107           0 :             const sal_Int32 nIdx = *pHt->GetStart();
     108           0 :             if ( nEnd < nIdx )
     109           0 :                 break;
     110           0 :             if( GetOfst() <= nIdx )
     111             :             {
     112           0 :                 bFtn = true;
     113           0 :                 break;
     114             :             }
     115             :         }
     116             :     }
     117             : }
     118             : 
     119           0 : bool SwTxtFrm::CalcPrepFtnAdjust()
     120             : {
     121             :     OSL_ENSURE( HasFtn(), "Wer ruft mich da?" );
     122           0 :     SwFtnBossFrm *pBoss = FindFtnBossFrm( true );
     123           0 :     const SwFtnFrm *pFtn = pBoss->FindFirstFtn( this );
     124           0 :     if( pFtn && FTNPOS_CHAPTER != GetNode()->GetDoc()->GetFtnInfo().ePos &&
     125           0 :         ( !pBoss->GetUpper()->IsSctFrm() ||
     126           0 :         !((SwSectionFrm*)pBoss->GetUpper())->IsFtnAtEnd() ) )
     127             :     {
     128           0 :         const SwFtnContFrm *pCont = pBoss->FindFtnCont();
     129           0 :         bool bReArrange = true;
     130             : 
     131           0 :         SWRECTFN( this )
     132           0 :         if ( pCont && (*fnRect->fnYDiff)( (pCont->Frm().*fnRect->fnGetTop)(),
     133           0 :                                           (Frm().*fnRect->fnGetBottom)() ) > 0 )
     134             :         {
     135           0 :             pBoss->RearrangeFtns( (Frm().*fnRect->fnGetBottom)(), false,
     136           0 :                                   pFtn->GetAttr() );
     137           0 :             ValidateBodyFrm();
     138           0 :             ValidateFrm();
     139           0 :             pFtn = pBoss->FindFirstFtn( this );
     140             :         }
     141             :         else
     142           0 :             bReArrange = false;
     143           0 :         if( !pCont || !pFtn || bReArrange != (pFtn->FindFtnBossFrm() == pBoss) )
     144             :         {
     145           0 :             SwTxtFormatInfo aInf( this );
     146           0 :             SwTxtFormatter aLine( this, &aInf );
     147           0 :             aLine.TruncLines();
     148           0 :             SetPara( 0 );       //Wird ggf. geloescht!
     149           0 :             ResetPreps();
     150           0 :             return false;
     151             :         }
     152             :     }
     153           0 :     return true;
     154             : }
     155             : 
     156             : /*************************************************************************
     157             :  *                      lcl_GetFtnLower()
     158             :  *
     159             :  * Local helper function. Checks if nLower should be taken as the boundary
     160             :  * for the footnote.
     161             :  *************************************************************************/
     162             : 
     163           0 : static SwTwips lcl_GetFtnLower( const SwTxtFrm* pFrm, SwTwips nLower )
     164             : {
     165             :     // nLower is an absolute value. It denotes the bottom of the line
     166             :     // containing the footnote.
     167           0 :     SWRECTFN( pFrm )
     168             : 
     169             :     OSL_ENSURE( !pFrm->IsVertical() || !pFrm->IsSwapped(),
     170             :             "lcl_GetFtnLower with swapped frame" );
     171             : 
     172             :     SwTwips nAdd;
     173           0 :     SwTwips nRet = nLower;
     174             : 
     175             :     // Check if text is inside a table.
     176           0 :     if ( pFrm->IsInTab() )
     177             :     {
     178             :         // If pFrm is inside a table, we have to check if
     179             :         // a) The table is not allowed to split or
     180             :         // b) The table row is not allowed to split
     181             : 
     182             :         // Inside a table, there are no footnotes,
     183             :         // see SwFrm::FindFtnBossFrm. So we don't have to check
     184             :         // the case that pFrm is inside a (footnote collecting) section
     185             :         // within the table.
     186           0 :         const SwFrm* pRow = pFrm;
     187           0 :         while( !pRow->IsRowFrm() || !pRow->GetUpper()->IsTabFrm() )
     188           0 :             pRow = pRow->GetUpper();
     189           0 :         const SwTabFrm* pTabFrm = (SwTabFrm*)pRow->GetUpper();
     190             : 
     191             :         OSL_ENSURE( pTabFrm && pRow &&
     192             :                 pRow->GetUpper()->IsTabFrm(), "Upper of row should be tab" );
     193             : 
     194           0 :         const bool bDontSplit = !pTabFrm->IsFollow() &&
     195           0 :                                 !pTabFrm->IsLayoutSplitAllowed();
     196             : 
     197           0 :         SwTwips nMin = 0;
     198           0 :         if ( bDontSplit )
     199           0 :             nMin = (pTabFrm->Frm().*fnRect->fnGetBottom)();
     200           0 :         else if ( !((SwRowFrm*)pRow)->IsRowSplitAllowed() )
     201           0 :             nMin = (pRow->Frm().*fnRect->fnGetBottom)();
     202             : 
     203           0 :         if ( nMin && (*fnRect->fnYDiff)( nMin, nLower ) > 0 )
     204           0 :             nRet = nMin;
     205             : 
     206           0 :         nAdd = (pRow->GetUpper()->*fnRect->fnGetBottomMargin)();
     207             :     }
     208             :     else
     209           0 :         nAdd = (pFrm->*fnRect->fnGetBottomMargin)();
     210             : 
     211           0 :     if( nAdd > 0 )
     212             :     {
     213           0 :         if ( bVert )
     214           0 :             nRet -= nAdd;
     215             :         else
     216           0 :             nRet += nAdd;
     217             :     }
     218             : 
     219             :     // #i10770#: If there are fly frames anchored at previous paragraphs,
     220             :     // the deadline should consider their lower borders.
     221           0 :     const SwFrm* pStartFrm = pFrm->GetUpper()->GetLower();
     222             :     OSL_ENSURE( pStartFrm, "Upper has no lower" );
     223           0 :     SwTwips nFlyLower = bVert ? LONG_MAX : 0;
     224           0 :     while ( pStartFrm != pFrm )
     225             :     {
     226             :         OSL_ENSURE( pStartFrm, "Frame chain is broken" );
     227           0 :         if ( pStartFrm->GetDrawObjs() )
     228             :         {
     229           0 :             const SwSortedObjs &rObjs = *pStartFrm->GetDrawObjs();
     230           0 :             for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
     231             :             {
     232           0 :                 SwAnchoredObject* pAnchoredObj = rObjs[i];
     233           0 :                 SwRect aRect( pAnchoredObj->GetObjRect() );
     234             : 
     235           0 :                 if ( !pAnchoredObj->ISA(SwFlyFrm) ||
     236           0 :                      static_cast<SwFlyFrm*>(pAnchoredObj)->IsValid() )
     237             :                 {
     238           0 :                     const SwTwips nBottom = (aRect.*fnRect->fnGetBottom)();
     239           0 :                     if ( (*fnRect->fnYDiff)( nBottom, nFlyLower ) > 0 )
     240           0 :                         nFlyLower = nBottom;
     241             :                 }
     242             :             }
     243             :         }
     244             : 
     245           0 :         pStartFrm = pStartFrm->GetNext();
     246             :     }
     247             : 
     248           0 :     if ( bVert )
     249           0 :         nRet = std::min( nRet, nFlyLower );
     250             :     else
     251           0 :         nRet = std::max( nRet, nFlyLower );
     252             : 
     253           0 :     return nRet;
     254             : }
     255             : 
     256           0 : SwTwips SwTxtFrm::GetFtnLine( const SwTxtFtn *pFtn ) const
     257             : {
     258             :     OSL_ENSURE( ! IsVertical() || ! IsSwapped(),
     259             :             "SwTxtFrm::GetFtnLine with swapped frame" );
     260             : 
     261           0 :     SwTxtFrm *pThis = (SwTxtFrm*)this;
     262             : 
     263           0 :     if( !HasPara() )
     264             :     {
     265             :         // #109071# GetFormatted() does not work here, bacause most probably
     266             :         // the frame is currently locked. We return the previous value.
     267           0 :         return pThis->mnFtnLine > 0 ?
     268             :                pThis->mnFtnLine :
     269           0 :                IsVertical() ? Frm().Left() : Frm().Bottom();
     270             :     }
     271             : 
     272           0 :     SWAP_IF_NOT_SWAPPED( this )
     273             : 
     274           0 :     SwTxtInfo aInf( pThis );
     275           0 :     SwTxtIter aLine( pThis, &aInf );
     276           0 :     const sal_Int32 nPos = *pFtn->GetStart();
     277           0 :     aLine.CharToLine( nPos );
     278             : 
     279           0 :     SwTwips nRet = aLine.Y() + SwTwips(aLine.GetLineHeight());
     280           0 :     if( IsVertical() )
     281           0 :         nRet = SwitchHorizontalToVertical( nRet );
     282             : 
     283           0 :     UNDO_SWAP( this )
     284             : 
     285           0 :     nRet = lcl_GetFtnLower( pThis, nRet );
     286             : 
     287           0 :     pThis->mnFtnLine = nRet;
     288           0 :     return nRet;
     289             : }
     290             : 
     291             : // Ermittelt die max. erreichbare Hoehe des TxtFrm im Ftn-Bereich.
     292             : // Sie wird eingeschraenkt durch den unteren Rand der Zeile mit
     293             : // der Ftn-Referenz.
     294           0 : SwTwips SwTxtFrm::_GetFtnFrmHeight() const
     295             : {
     296             :     OSL_ENSURE( !IsFollow() && IsInFtn(), "SwTxtFrm::SetFtnLine: moon walk" );
     297             : 
     298           0 :     const SwFtnFrm *pFtnFrm = FindFtnFrm();
     299           0 :     const SwTxtFrm *pRef = (const SwTxtFrm *)pFtnFrm->GetRef();
     300           0 :     const SwFtnBossFrm *pBoss = FindFtnBossFrm();
     301           0 :     if( pBoss != pRef->FindFtnBossFrm( !pFtnFrm->GetAttr()->
     302           0 :                                         GetFtn().IsEndNote() ) )
     303           0 :         return 0;
     304             : 
     305           0 :     SWAP_IF_SWAPPED( this )
     306             : 
     307           0 :     SwTwips nHeight = pRef->IsInFtnConnect() ?
     308           0 :                             1 : pRef->GetFtnLine( pFtnFrm->GetAttr() );
     309           0 :     if( nHeight )
     310             :     {
     311             :         // So komisch es aussehen mag: Die erste Ftn auf der Seite darf sich
     312             :         // nicht mit der Ftn-Referenz beruehren, wenn wir im Ftn-Bereich Text
     313             :         // eingeben.
     314           0 :         const SwFrm *pCont = pFtnFrm->GetUpper();
     315             :         //Hoehe innerhalb des Cont, die ich mir 'eh noch genehmigen darf.
     316           0 :         SWRECTFN( pCont )
     317           0 :         SwTwips nTmp = (*fnRect->fnYDiff)( (pCont->*fnRect->fnGetPrtBottom)(),
     318           0 :                                            (Frm().*fnRect->fnGetTop)() );
     319             : 
     320             : #if OSL_DEBUG_LEVEL > 0
     321             :         if( nTmp < 0 )
     322             :         {
     323             :             bool bInvalidPos = false;
     324             :             const SwLayoutFrm* pTmp = GetUpper();
     325             :             while( !bInvalidPos && pTmp )
     326             :             {
     327             :                 bInvalidPos = !pTmp->GetValidPosFlag() ||
     328             :                                !pTmp->Lower()->GetValidPosFlag();
     329             :                 if( pTmp == pCont )
     330             :                     break;
     331             :                 pTmp = pTmp->GetUpper();
     332             :             }
     333             :             OSL_ENSURE( bInvalidPos, "Hanging below FtnCont" );
     334             :         }
     335             : #endif
     336             : 
     337           0 :         if ( (*fnRect->fnYDiff)( (pCont->Frm().*fnRect->fnGetTop)(), nHeight) > 0 )
     338             :         {
     339             :             //Wachstumspotential den Containers.
     340           0 :             if ( !pRef->IsInFtnConnect() )
     341             :             {
     342           0 :                 SwSaveFtnHeight aSave( (SwFtnBossFrm*)pBoss, nHeight  );
     343           0 :                 nHeight = ((SwFtnContFrm*)pCont)->Grow( LONG_MAX, true );
     344             :             }
     345             :             else
     346           0 :                 nHeight = ((SwFtnContFrm*)pCont)->Grow( LONG_MAX, true );
     347             : 
     348           0 :             nHeight += nTmp;
     349           0 :             if( nHeight < 0 )
     350           0 :                 nHeight = 0;
     351             :         }
     352             :         else
     353             :         {   // The container has to shrink
     354           0 :             nTmp += (*fnRect->fnYDiff)( (pCont->Frm().*fnRect->fnGetTop)(), nHeight);
     355           0 :             if( nTmp > 0 )
     356           0 :                 nHeight = nTmp;
     357             :             else
     358           0 :                 nHeight = 0;
     359             :         }
     360             :     }
     361             : 
     362           0 :     UNDO_SWAP( this )
     363             : 
     364           0 :     return nHeight;
     365             : }
     366             : 
     367           0 : SwTxtFrm *SwTxtFrm::FindQuoVadisFrm()
     368             : {
     369             :     // Erstmal feststellen, ob wir in einem FtnFrm stehen:
     370           0 :     if( GetIndPrev() || !IsInFtn() )
     371           0 :         return 0;
     372             : 
     373             :     // Zum Vorgaenger-FtnFrm
     374           0 :     SwFtnFrm *pFtnFrm = FindFtnFrm()->GetMaster();
     375           0 :     if( !pFtnFrm )
     376           0 :         return 0;
     377             : 
     378             :     // Nun den letzten Cntnt:
     379           0 :     const SwCntntFrm *pCnt = pFtnFrm->ContainsCntnt();
     380           0 :     if( !pCnt )
     381           0 :         return NULL;
     382             :     const SwCntntFrm *pLast;
     383           0 :     do
     384           0 :     {   pLast = pCnt;
     385           0 :         pCnt = pCnt->GetNextCntntFrm();
     386           0 :     } while( pCnt && pFtnFrm->IsAnLower( pCnt ) );
     387           0 :     return (SwTxtFrm*)pLast;
     388             : }
     389             : 
     390           0 : void SwTxtFrm::RemoveFtn( const sal_Int32 nStart, const sal_Int32 nLen )
     391             : {
     392           0 :     if ( !IsFtnAllowed() )
     393           0 :         return;
     394             : 
     395           0 :     SwpHints *pHints = GetTxtNode()->GetpSwpHints();
     396           0 :     if( !pHints )
     397           0 :         return;
     398             : 
     399           0 :     bool bRollBack = nLen != COMPLETE_STRING;
     400           0 :     sal_uInt16 nSize = pHints->Count();
     401             :     sal_Int32 nEnd;
     402             :     SwTxtFrm* pSource;
     403           0 :     if( bRollBack )
     404             :     {
     405           0 :         nEnd = nStart + nLen;
     406           0 :         pSource = GetFollow();
     407           0 :         if( !pSource )
     408           0 :             return;
     409             :     }
     410             :     else
     411             :     {
     412           0 :         nEnd = COMPLETE_STRING;
     413           0 :         pSource = this;
     414             :     }
     415             : 
     416           0 :     if( nSize )
     417             :     {
     418           0 :         SwPageFrm* pUpdate = NULL;
     419           0 :         bool bRemove = false;
     420           0 :         SwFtnBossFrm *pFtnBoss = 0;
     421           0 :         SwFtnBossFrm *pEndBoss = 0;
     422             :         bool bFtnEndDoc
     423           0 :             = FTNPOS_CHAPTER == GetNode()->GetDoc()->GetFtnInfo().ePos;
     424           0 :         for ( sal_uInt16 i = nSize; i; )
     425             :         {
     426           0 :             SwTxtAttr *pHt = pHints->GetTextHint(--i);
     427           0 :             if ( RES_TXTATR_FTN != pHt->Which() )
     428           0 :                 continue;
     429             : 
     430           0 :             const sal_Int32 nIdx = *pHt->GetStart();
     431           0 :             if( nStart > nIdx )
     432           0 :                 break;
     433             : 
     434           0 :             if( nEnd >= nIdx )
     435             :             {
     436           0 :                 SwTxtFtn *pFtn = (SwTxtFtn*)pHt;
     437           0 :                 const bool bEndn = pFtn->GetFtn().IsEndNote();
     438             : 
     439           0 :                 if( bEndn )
     440             :                 {
     441           0 :                     if( !pEndBoss )
     442           0 :                         pEndBoss = pSource->FindFtnBossFrm();
     443             :                 }
     444             :                 else
     445             :                 {
     446           0 :                     if( !pFtnBoss )
     447             :                     {
     448           0 :                         pFtnBoss = pSource->FindFtnBossFrm( true );
     449           0 :                         if( pFtnBoss->GetUpper()->IsSctFrm() )
     450             :                         {
     451             :                             SwSectionFrm* pSect = (SwSectionFrm*)
     452           0 :                                                   pFtnBoss->GetUpper();
     453           0 :                             if( pSect->IsFtnAtEnd() )
     454           0 :                                 bFtnEndDoc = false;
     455             :                         }
     456             :                     }
     457             :                 }
     458             : 
     459             :                 // Wir loeschen nicht, sondern wollen die Ftn verschieben.
     460             :                 // Drei Faelle koennen auftreten:
     461             :                 // 1) Es gibt weder Follow noch PrevFollow
     462             :                 //    -> RemoveFtn()  (vielleicht sogar ein OSL_ENSURE(wert)
     463             :                 // 2) nStart > GetOfst, ich habe einen Follow
     464             :                 //    -> Ftn wandert in den Follow
     465             :                 // 3) nStart < GetOfst, ich bin ein Follow
     466             :                 //    -> Ftn wandert in den PrevFollow
     467             :                 // beide muessen auf einer Seite/in einer Spalte stehen.
     468             : 
     469             :                 SwFtnFrm *pFtnFrm = bEndn ? pEndBoss->FindFtn( pSource, pFtn ) :
     470           0 :                                             pFtnBoss->FindFtn( pSource, pFtn );
     471             : 
     472           0 :                 if( pFtnFrm )
     473             :                 {
     474           0 :                     const bool bEndDoc = bEndn || bFtnEndDoc;
     475           0 :                     if( bRollBack )
     476             :                     {
     477           0 :                         while ( pFtnFrm )
     478             :                         {
     479           0 :                             pFtnFrm->SetRef( this );
     480           0 :                             pFtnFrm = pFtnFrm->GetFollow();
     481           0 :                             SetFtn( true );
     482             :                         }
     483             :                     }
     484           0 :                     else if( GetFollow() )
     485             :                     {
     486           0 :                         SwCntntFrm *pDest = GetFollow();
     487           0 :                         while( pDest->GetFollow() && ((SwTxtFrm*)pDest->
     488           0 :                                GetFollow())->GetOfst() <= nIdx )
     489           0 :                             pDest = pDest->GetFollow();
     490             :                         OSL_ENSURE( !pDest->FindFtnBossFrm( !bEndn )->FindFtn(
     491             :                             pDest,pFtn),"SwTxtFrm::RemoveFtn: footnote exists");
     492             : 
     493             :                         //Nicht ummelden sondern immer Moven.
     494             :                         // OD 08.11.2002 #104840# - use <SwlayoutFrm::IsBefore(::)>
     495           0 :                         if ( bEndDoc ||
     496           0 :                              !pFtnFrm->FindFtnBossFrm()->IsBefore( pDest->FindFtnBossFrm( !bEndn ) )
     497             :                            )
     498             :                         {
     499           0 :                             SwPageFrm* pTmp = pFtnFrm->FindPageFrm();
     500           0 :                             if( pUpdate && pUpdate != pTmp )
     501           0 :                                 pUpdate->UpdateFtnNum();
     502           0 :                             pUpdate = pTmp;
     503           0 :                             while ( pFtnFrm )
     504             :                             {
     505           0 :                                 pFtnFrm->SetRef( pDest );
     506           0 :                                 pFtnFrm = pFtnFrm->GetFollow();
     507             :                             }
     508             :                         }
     509             :                         else
     510             :                         {
     511           0 :                             pFtnBoss->MoveFtns( this, pDest, pFtn );
     512           0 :                             bRemove = true;
     513             :                         }
     514           0 :                         ((SwTxtFrm*)pDest)->SetFtn( true );
     515             : 
     516             :                         OSL_ENSURE( pDest->FindFtnBossFrm( !bEndn )->FindFtn( pDest,
     517             :                            pFtn),"SwTxtFrm::RemoveFtn: footnote ChgRef failed");
     518             :                     }
     519             :                     else
     520             :                     {
     521           0 :                         if( !bEndDoc || ( bEndn && pEndBoss->IsInSct() &&
     522           0 :                             !SwLayouter::Collecting( GetNode()->GetDoc(),
     523           0 :                             pEndBoss->FindSctFrm(), NULL ) ) )
     524             :                         {
     525           0 :                             if( bEndn )
     526           0 :                                 pEndBoss->RemoveFtn( this, pFtn );
     527             :                             else
     528           0 :                                 pFtnBoss->RemoveFtn( this, pFtn );
     529           0 :                             bRemove = bRemove || !bEndDoc;
     530             :                             OSL_ENSURE( bEndn ? !pEndBoss->FindFtn( this, pFtn ) :
     531             :                                     !pFtnBoss->FindFtn( this, pFtn ),
     532             :                             "SwTxtFrm::RemoveFtn: can't get off that footnote" );
     533             :                         }
     534             :                     }
     535             :                 }
     536             :             }
     537             :         }
     538           0 :         if( pUpdate )
     539           0 :             pUpdate->UpdateFtnNum();
     540             :         // Wir bringen die Oszillation zum stehen:
     541           0 :         if( bRemove && !bFtnEndDoc && HasPara() )
     542             :         {
     543           0 :             ValidateBodyFrm();
     544           0 :             ValidateFrm();
     545             :         }
     546             :     }
     547             :     // Folgendes Problem: Aus dem FindBreak heraus wird das RemoveFtn aufgerufen,
     548             :     // weil die letzte Zeile an den Follow abgegeben werden soll. Der Offset
     549             :     // des Follows ist aber veraltet, er wird demnaechst gesetzt. CalcFntFlag ist
     550             :     // auf einen richtigen Follow-Offset angewiesen. Deshalb wird hier kurzfristig
     551             :     // der Follow-Offset manipuliert.
     552           0 :     sal_Int32 nOldOfst = COMPLETE_STRING;
     553           0 :     if( HasFollow() && nStart > GetOfst() )
     554             :     {
     555           0 :         nOldOfst = GetFollow()->GetOfst();
     556           0 :         GetFollow()->ManipOfst( nStart + ( bRollBack ? nLen : 0 ) );
     557             :     }
     558           0 :     pSource->CalcFtnFlag();
     559           0 :     if( nOldOfst < COMPLETE_STRING )
     560           0 :         GetFollow()->ManipOfst( nOldOfst );
     561             : }
     562             : 
     563             : // false, wenn irgendetwas schief gegangen ist.
     564             : // Es gibt eigentlich nur zwei Moeglichkeiten:
     565             : // a) Die Ftn ist bereits vorhanden
     566             : // => dann wird sie gemoved, wenn ein anderer pSrcFrm gefunden wurde
     567             : // b) Die Ftn ist nicht vorhanden
     568             : // => dann wird sie fuer uns angelegt.
     569             : // Ob die Ftn schliesslich auf unserer Spalte/Seite landet oder nicht,
     570             : // spielt in diesem Zusammenhang keine Rolle.
     571             : // Optimierungen bei Endnoten.
     572             : // Noch ein Problem: wenn die Deadline im Ftn-Bereich liegt, muss die
     573             : // Ftn verschoben werden.
     574           0 : void SwTxtFrm::ConnectFtn( SwTxtFtn *pFtn, const SwTwips nDeadLine )
     575             : {
     576             :     OSL_ENSURE( !IsVertical() || !IsSwapped(),
     577             :             "SwTxtFrm::ConnectFtn with swapped frame" );
     578             : 
     579           0 :     bFtn = true;
     580           0 :     bInFtnConnect = true;   //Bloss zuruecksetzen!
     581           0 :     const bool bEnd = pFtn->GetFtn().IsEndNote();
     582             : 
     583             :     // We want to store this value, because it is needed as a fallback
     584             :     // in GetFtnLine(), if there is no paragraph information available
     585           0 :     mnFtnLine = nDeadLine;
     586             : 
     587             :     // Wir brauchen immer einen Boss (Spalte/Seite)
     588             :     SwSectionFrm *pSect;
     589           0 :     SwCntntFrm *pCntnt = this;
     590           0 :     if( bEnd && IsInSct() )
     591             :     {
     592           0 :         pSect = FindSctFrm();
     593           0 :         if( pSect->IsEndnAtEnd() )
     594           0 :             pCntnt = pSect->FindLastCntnt( FINDMODE_ENDNOTE );
     595           0 :         if( !pCntnt )
     596           0 :             pCntnt = this;
     597             :     }
     598             : 
     599           0 :     SwFtnBossFrm *pBoss = pCntnt->FindFtnBossFrm( !bEnd );
     600             : 
     601             : #if OSL_DEBUG_LEVEL > 1
     602             :     SwTwips nRstHeight = GetRstHeight();
     603             : #endif
     604             : 
     605           0 :     pSect = pBoss->FindSctFrm();
     606           0 :     bool bDocEnd = bEnd ? !( pSect && pSect->IsEndnAtEnd() ) :
     607           0 :                    ( !( pSect && pSect->IsFtnAtEnd() ) &&
     608           0 :                        FTNPOS_CHAPTER == GetNode()->GetDoc()->GetFtnInfo().ePos );
     609             :     //Ftn kann beim Follow angemeldet sein.
     610           0 :     SwCntntFrm *pSrcFrm = FindFtnRef( pFtn );
     611             : 
     612           0 :     if( bDocEnd )
     613             :     {
     614           0 :         if( pSect && pSrcFrm )
     615             :         {
     616           0 :             SwFtnFrm *pFtnFrm = pBoss->FindFtn( pSrcFrm, pFtn );
     617           0 :             if( pFtnFrm && pFtnFrm->IsInSct() )
     618             :             {
     619           0 :                 pBoss->RemoveFtn( pSrcFrm, pFtn );
     620           0 :                 pSrcFrm = 0;
     621             :             }
     622             :         }
     623             :     }
     624           0 :     else if( bEnd && pSect )
     625             :     {
     626           0 :         SwFtnFrm *pFtnFrm = pSrcFrm ? pBoss->FindFtn( pSrcFrm, pFtn ) : NULL;
     627           0 :         if( pFtnFrm && !pFtnFrm->GetUpper() )
     628           0 :             pFtnFrm = NULL;
     629           0 :         SwDoc *pDoc = GetNode()->GetDoc();
     630           0 :         if( SwLayouter::Collecting( pDoc, pSect, pFtnFrm ) )
     631             :         {
     632           0 :             if( !pSrcFrm )
     633             :             {
     634           0 :                 SwFtnFrm *pNew = new SwFtnFrm(pDoc->GetDfltFrmFmt(),this,this,pFtn);
     635           0 :                  SwNodeIndex aIdx( *pFtn->GetStartNode(), 1 );
     636           0 :                  ::_InsertCnt( pNew, pDoc, aIdx.GetIndex() );
     637           0 :                 GetNode()->getIDocumentLayoutAccess()->GetLayouter()->CollectEndnote( pNew );
     638             :             }
     639           0 :             else if( pSrcFrm != this )
     640           0 :                 pBoss->ChangeFtnRef( pSrcFrm, pFtn, this );
     641           0 :             bInFtnConnect = false;
     642           0 :             return;
     643             :         }
     644           0 :         else if( pSrcFrm )
     645             :         {
     646           0 :             SwFtnBossFrm *pFtnBoss = pFtnFrm->FindFtnBossFrm();
     647           0 :             if( !pFtnBoss->IsInSct() ||
     648           0 :                 pFtnBoss->ImplFindSctFrm()->GetSection()!=pSect->GetSection() )
     649             :             {
     650           0 :                 pBoss->RemoveFtn( pSrcFrm, pFtn );
     651           0 :                 pSrcFrm = 0;
     652             :             }
     653             :         }
     654             :     }
     655             : 
     656           0 :     if( bDocEnd || bEnd )
     657             :     {
     658           0 :         if( !pSrcFrm )
     659           0 :             pBoss->AppendFtn( this, pFtn );
     660           0 :         else if( pSrcFrm != this )
     661           0 :             pBoss->ChangeFtnRef( pSrcFrm, pFtn, this );
     662           0 :         bInFtnConnect = false;
     663           0 :         return;
     664             :     }
     665             : 
     666           0 :     SwSaveFtnHeight aHeight( pBoss, nDeadLine );
     667             : 
     668           0 :     if( !pSrcFrm )      // Es wurde ueberhaupt keine Ftn gefunden.
     669           0 :         pBoss->AppendFtn( this, pFtn );
     670             :     else
     671             :     {
     672           0 :         SwFtnFrm *pFtnFrm = pBoss->FindFtn( pSrcFrm, pFtn );
     673           0 :         SwFtnBossFrm *pFtnBoss = pFtnFrm->FindFtnBossFrm();
     674             : 
     675           0 :         bool bBrutal = false;
     676             : 
     677           0 :         if( pFtnBoss == pBoss ) // Ref und Ftn sind auf der selben Seite/Spalte.
     678             :         {
     679           0 :             SwFrm *pCont = pFtnFrm->GetUpper();
     680             : 
     681           0 :             SWRECTFN ( pCont )
     682           0 :             long nDiff = (*fnRect->fnYDiff)( (pCont->Frm().*fnRect->fnGetTop)(),
     683           0 :                                              nDeadLine );
     684             : 
     685           0 :             if( nDiff >= 0 )
     686             :             {
     687             :                 //Wenn die Fussnote bei einem Follow angemeldet ist, so ist
     688             :                 //es jetzt an der Zeit sie umzumelden.
     689           0 :                 if ( pSrcFrm != this )
     690           0 :                     pBoss->ChangeFtnRef( pSrcFrm, pFtn, this );
     691             :                 //Es steht Platz zur Verfuegung, also kann die Fussnote evtl.
     692             :                 //wachsen.
     693           0 :                 if ( pFtnFrm->GetFollow() && nDiff > 0 )
     694             :                 {
     695           0 :                     SwTwips nHeight = (pCont->Frm().*fnRect->fnGetHeight)();
     696           0 :                     pBoss->RearrangeFtns( nDeadLine, false, pFtn );
     697           0 :                     ValidateBodyFrm();
     698           0 :                     ValidateFrm();
     699           0 :                     SwViewShell *pSh = getRootFrm()->GetCurrShell();
     700           0 :                     if ( pSh && nHeight == (pCont->Frm().*fnRect->fnGetHeight)() )
     701             :                         //Damit uns nix durch die Lappen geht.
     702           0 :                         pSh->InvalidateWindows( pCont->Frm() );
     703             :                 }
     704           0 :                 bInFtnConnect = false;
     705           0 :                 return;
     706             :             }
     707             :             else
     708           0 :                 bBrutal = true;
     709             :         }
     710             :         else
     711             :         {
     712             :             // Ref und Ftn sind nicht auf einer Seite, Move-Versuch ist noetig.
     713           0 :             SwFrm* pTmp = this;
     714           0 :             while( pTmp->GetNext() && pSrcFrm != pTmp )
     715           0 :                 pTmp = pTmp->GetNext();
     716           0 :             if( pSrcFrm == pTmp )
     717           0 :                 bBrutal = true;
     718             :             else
     719             :             {   // Wenn unser Boss in einem spaltigen Bereich sitzt, es aber auf
     720             :                 // der Seite schon einen FtnContainer gibt, hilft nur die brutale
     721             :                 // Methode
     722           0 :                 if( pSect && pSect->FindFtnBossFrm( !bEnd )->FindFtnCont() )
     723           0 :                     bBrutal = true;
     724             :                 // OD 08.11.2002 #104840# - use <SwLayoutFrm::IsBefore(..)>
     725           0 :                 else if ( !pFtnFrm->GetPrev() ||
     726           0 :                           pFtnBoss->IsBefore( pBoss )
     727             :                         )
     728             :                 {
     729           0 :                     SwFtnBossFrm *pSrcBoss = pSrcFrm->FindFtnBossFrm( !bEnd );
     730           0 :                     pSrcBoss->MoveFtns( pSrcFrm, this, pFtn );
     731             :                 }
     732             :                 else
     733           0 :                     pBoss->ChangeFtnRef( pSrcFrm, pFtn, this );
     734             :             }
     735             :         }
     736             : 
     737             :         // Die brutale Loesung: Fussnote entfernen und appenden.
     738             :         // Es muss SetFtnDeadLine() gerufen werden, weil nach
     739             :         // RemoveFtn die nMaxFtnHeight evtl. besser auf unsere Wuensche
     740             :         // eingestellt werden kann.
     741           0 :         if( bBrutal )
     742             :         {
     743           0 :             pBoss->RemoveFtn( pSrcFrm, pFtn, false );
     744             :             SwSaveFtnHeight *pHeight = bEnd ? NULL :
     745           0 :                 new SwSaveFtnHeight( pBoss, nDeadLine );
     746           0 :             pBoss->AppendFtn( this, pFtn );
     747           0 :             delete pHeight;
     748             :         }
     749             :     }
     750             : 
     751             :     // In spaltigen Bereichen, die noch nicht bis zum Seitenrand gehen,
     752             :     // ist kein RearrangeFtns sinnvoll, da der Fussnotencontainer noch
     753             :     // nicht kalkuliert worden ist.
     754           0 :     if( !pSect || !pSect->Growable() )
     755             :     {
     756             :         // Umgebung validieren, um Oszillationen zu verhindern.
     757           0 :         SwSaveFtnHeight aNochmal( pBoss, nDeadLine );
     758           0 :         ValidateBodyFrm();
     759           0 :         pBoss->RearrangeFtns( nDeadLine, true );
     760           0 :         ValidateFrm();
     761             :     }
     762           0 :     else if( pSect->IsFtnAtEnd() )
     763             :     {
     764           0 :         ValidateBodyFrm();
     765           0 :         ValidateFrm();
     766             :     }
     767             : 
     768             : #if OSL_DEBUG_LEVEL > 1
     769             :     // pFtnFrm kann sich durch Calc veraendert haben ...
     770             :     SwFtnFrm *pFtnFrm = pBoss->FindFtn( this, pFtn );
     771             :     if( pFtnFrm && pBoss != pFtnFrm->FindFtnBossFrm( !bEnd ) )
     772             :     {
     773             :         int bla = 5;
     774             :         (void)bla;
     775             :     }
     776             :     nRstHeight = GetRstHeight();
     777             :     (void)nRstHeight;
     778             : #endif
     779           0 :     bInFtnConnect = false;
     780           0 :     return;
     781             : }
     782             : 
     783             : // Die Portion fuer die Ftn-Referenz im Text
     784           0 : SwFtnPortion *SwTxtFormatter::NewFtnPortion( SwTxtFormatInfo &rInf,
     785             :                                              SwTxtAttr *pHint )
     786             : {
     787             :     OSL_ENSURE( ! pFrm->IsVertical() || pFrm->IsSwapped(),
     788             :             "NewFtnPortion with unswapped frame" );
     789             : 
     790           0 :     if( !pFrm->IsFtnAllowed() )
     791           0 :         return 0;
     792             : 
     793           0 :     SwTxtFtn  *pFtn = (SwTxtFtn*)pHint;
     794           0 :     SwFmtFtn& rFtn = (SwFmtFtn&)pFtn->GetFtn();
     795           0 :     SwDoc *pDoc = pFrm->GetNode()->GetDoc();
     796             : 
     797           0 :     if( rInf.IsTest() )
     798           0 :         return new SwFtnPortion( rFtn.GetViewNumStr( *pDoc ), pFtn );
     799             : 
     800           0 :     SWAP_IF_SWAPPED( pFrm )
     801             : 
     802             :     KSHORT nReal;
     803             :     {
     804           0 :         KSHORT nOldReal = pCurr->GetRealHeight();
     805           0 :         KSHORT nOldAscent = pCurr->GetAscent();
     806           0 :         KSHORT nOldHeight = pCurr->Height();
     807           0 :         ((SwTxtFormatter*)this)->CalcRealHeight();
     808           0 :         nReal = pCurr->GetRealHeight();
     809           0 :         if( nReal < nOldReal )
     810           0 :             nReal = nOldReal;
     811           0 :         pCurr->SetRealHeight( nOldReal );
     812           0 :         pCurr->Height( nOldHeight );
     813           0 :         pCurr->SetAscent( nOldAscent );
     814             :     }
     815             : 
     816           0 :     SwTwips nLower = Y() + nReal;
     817             : 
     818           0 :     const bool bVertical = pFrm->IsVertical();
     819           0 :     if( bVertical )
     820           0 :         nLower = pFrm->SwitchHorizontalToVertical( nLower );
     821             : 
     822           0 :     nLower = lcl_GetFtnLower( pFrm, nLower );
     823             : 
     824             :     //6995: Wir frischen nur auf. Das Connect tut fuer diesen Fall nix
     825             :     //Brauchbares, sondern wuerde stattdessen fuer diesen Fall meist die
     826             :     //Ftn wegwerfen und neu erzeugen.
     827             : 
     828           0 :     if( !rInf.IsQuick() )
     829           0 :         pFrm->ConnectFtn( pFtn, nLower );
     830             : 
     831           0 :     SwTxtFrm *pScrFrm = pFrm->FindFtnRef( pFtn );
     832           0 :     SwFtnBossFrm *pBoss = pFrm->FindFtnBossFrm( !rFtn.IsEndNote() );
     833           0 :     SwFtnFrm *pFtnFrm = NULL;
     834           0 :     if( pScrFrm )
     835           0 :         pFtnFrm = pBoss->FindFtn( pScrFrm, pFtn );
     836             : 
     837             :     // Wir erkundigen uns, ob durch unser Append irgendeine
     838             :     // Fussnote noch auf der Seite/Spalte steht. Wenn nicht verschwindet
     839             :     // auch unsere Zeile. Dies fuehrt zu folgendem erwuenschten
     840             :     // Verhalten: Ftn1 pass noch auf die Seite/Spalte, Ftn2 nicht mehr.
     841             :     // Also bleibt die Ftn2-Referenz auf der Seite/Spalte stehen. Die
     842             :     // Fussnote selbst folgt aber erst auf der naechsten Seite/Spalte.
     843             :     // Ausnahme: Wenn keine weitere Zeile auf diese Seite/Spalte passt,
     844             :     // so sollte die Ftn2-Referenz auch auf die naechste wandern.
     845           0 :     if( !rFtn.IsEndNote() )
     846             :     {
     847           0 :         SwSectionFrm *pSct = pBoss->FindSctFrm();
     848           0 :         bool bAtSctEnd = pSct && pSct->IsFtnAtEnd();
     849           0 :         if( FTNPOS_CHAPTER != pDoc->GetFtnInfo().ePos || bAtSctEnd )
     850             :         {
     851           0 :             SwFrm* pFtnCont = pBoss->FindFtnCont();
     852             :             // Wenn der Boss in einem Bereich liegt, kann es sich nur um eine
     853             :             // Spalte dieses Bereichs handeln. Wenn dies nicht die erste Spalte
     854             :             // ist, duerfen wir ausweichen
     855           0 :             if( !pFrm->IsInTab() && ( GetLineNr() > 1 || pFrm->GetPrev() ||
     856           0 :                 ( !bAtSctEnd && pFrm->GetIndPrev() ) ||
     857           0 :                 ( pSct && pBoss->GetPrev() ) ) )
     858             :             {
     859           0 :                 if( !pFtnCont )
     860             :                 {
     861           0 :                     rInf.SetStop( true );
     862           0 :                     UNDO_SWAP( pFrm )
     863           0 :                     return 0;
     864             :                 }
     865             :                 else
     866             :                 {
     867             :                     // Es darf keine Fussnotencontainer in spaltigen Bereichen und
     868             :                     // gleichzeitig auf der Seite/Seitenspalte geben
     869           0 :                     if( pSct && !bAtSctEnd ) // liegt unser Container in einem (spaltigen) Bereich?
     870             :                     {
     871           0 :                         SwFtnBossFrm* pTmp = pBoss->FindSctFrm()->FindFtnBossFrm( true );
     872           0 :                         SwFtnContFrm* pFtnC = pTmp->FindFtnCont();
     873           0 :                         if( pFtnC )
     874             :                         {
     875           0 :                             SwFtnFrm* pTmpFrm = (SwFtnFrm*)pFtnC->Lower();
     876           0 :                             if( pTmpFrm && *pTmpFrm < pFtn )
     877             :                             {
     878           0 :                                 rInf.SetStop( true );
     879           0 :                                 UNDO_SWAP( pFrm )
     880           0 :                                 return 0;
     881             :                             }
     882             :                         }
     883             :                     }
     884             :                     // Ist dies die letzte passende Zeile?
     885           0 :                     SwTwips nTmpBot = Y() + nReal * 2;
     886             : 
     887           0 :                     if( bVertical )
     888           0 :                         nTmpBot = pFrm->SwitchHorizontalToVertical( nTmpBot );
     889             : 
     890           0 :                     SWRECTFN( pFtnCont )
     891             : 
     892             :                     const long nDiff = (*fnRect->fnYDiff)(
     893           0 :                                             (pFtnCont->Frm().*fnRect->fnGetTop)(),
     894           0 :                                              nTmpBot );
     895             : 
     896           0 :                     if( pScrFrm && nDiff < 0 )
     897             :                     {
     898           0 :                         if( pFtnFrm )
     899             :                         {
     900           0 :                             SwFtnBossFrm *pFtnBoss = pFtnFrm->FindFtnBossFrm();
     901           0 :                             if( pFtnBoss != pBoss )
     902             :                             {
     903             :                                 // Wir sind in der letzte Zeile und die Fussnote
     904             :                                 // ist auf eine andere Seite gewandert, dann wollen
     905             :                                 // wir mit ...
     906           0 :                                 rInf.SetStop( true );
     907           0 :                                 UNDO_SWAP( pFrm )
     908           0 :                                 return 0;
     909             :                             }
     910             :                         }
     911             :                     }
     912             :                 }
     913             :             }
     914             :         }
     915             :     }
     916             :     // Endlich: FtnPortion anlegen und raus hier...
     917             :     SwFtnPortion *pRet = new SwFtnPortion( rFtn.GetViewNumStr( *pDoc ),
     918           0 :                                            pFtn, nReal );
     919           0 :     rInf.SetFtnInside( true );
     920             : 
     921           0 :     UNDO_SWAP( pFrm )
     922             : 
     923           0 :     return pRet;
     924             :  }
     925             : 
     926             : // Die Portion fuer die Ftn-Nummerierung im Ftn-Bereich
     927           0 : SwNumberPortion *SwTxtFormatter::NewFtnNumPortion( SwTxtFormatInfo &rInf ) const
     928             : {
     929             :     OSL_ENSURE( pFrm->IsInFtn() && !pFrm->GetIndPrev() && !rInf.IsFtnDone(),
     930             :             "This is the wrong place for a ftnnumber" );
     931           0 :     if( rInf.GetTxtStart() != nStart ||
     932           0 :         rInf.GetTxtStart() != rInf.GetIdx() )
     933           0 :         return 0;
     934             : 
     935           0 :     const SwFtnFrm* pFtnFrm = pFrm->FindFtnFrm();
     936           0 :     const SwTxtFtn* pFtn = pFtnFrm->GetAttr();
     937             : 
     938             :     // Aha, wir sind also im Fussnotenbereich
     939           0 :     SwFmtFtn& rFtn = (SwFmtFtn&)pFtn->GetFtn();
     940             : 
     941           0 :     SwDoc *pDoc = pFrm->GetNode()->GetDoc();
     942           0 :     OUString aFtnTxt( rFtn.GetViewNumStr( *pDoc, true ));
     943             : 
     944             :     const SwEndNoteInfo* pInfo;
     945           0 :     if( rFtn.IsEndNote() )
     946           0 :         pInfo = &pDoc->GetEndNoteInfo();
     947             :     else
     948           0 :         pInfo = &pDoc->GetFtnInfo();
     949           0 :     const SwAttrSet& rSet = pInfo->GetCharFmt(*pDoc)->GetAttrSet();
     950             : 
     951           0 :     const SwAttrSet* pParSet = &rInf.GetCharAttr();
     952           0 :     const IDocumentSettingAccess* pIDSA = pFrm->GetTxtNode()->getIDocumentSettingAccess();
     953           0 :     SwFont *pNumFnt = new SwFont( pParSet, pIDSA );
     954             : 
     955             :     // #i37142#
     956             :     // Underline style of paragraph font should not be considered
     957             :     // Overline style of paragraph font should not be considered
     958             :     // Weight style of paragraph font should not be considered
     959             :     // Posture style of paragraph font should not be considered
     960             :     // See also #i18463# and SwTxtFormatter::NewNumberPortion()
     961           0 :     pNumFnt->SetUnderline( UNDERLINE_NONE );
     962           0 :     pNumFnt->SetOverline( UNDERLINE_NONE );
     963           0 :     pNumFnt->SetItalic( ITALIC_NONE, SW_LATIN );
     964           0 :     pNumFnt->SetItalic( ITALIC_NONE, SW_CJK );
     965           0 :     pNumFnt->SetItalic( ITALIC_NONE, SW_CTL );
     966           0 :     pNumFnt->SetWeight( WEIGHT_NORMAL, SW_LATIN );
     967           0 :     pNumFnt->SetWeight( WEIGHT_NORMAL, SW_CJK );
     968           0 :     pNumFnt->SetWeight( WEIGHT_NORMAL, SW_CTL );
     969             : 
     970           0 :     pNumFnt->SetDiffFnt(&rSet, pIDSA );
     971           0 :     pNumFnt->SetVertical( pNumFnt->GetOrientation(), pFrm->IsVertical() );
     972             : 
     973           0 :     SwFtnNumPortion* pNewPor = new SwFtnNumPortion( aFtnTxt, pNumFnt );
     974           0 :     pNewPor->SetLeft( !pFrm->IsRightToLeft() );
     975           0 :     return pNewPor;
     976             : }
     977             : 
     978             : /*************************************************************************
     979             :  *                  SwTxtFormatter::NewErgoSumPortion()
     980             :  *************************************************************************/
     981           0 : OUString lcl_GetPageNumber( const SwPageFrm* pPage )
     982             : {
     983             :     OSL_ENSURE( pPage, "GetPageNumber: Homeless TxtFrm" );
     984           0 :     MSHORT nVirtNum = pPage->GetVirtPageNum();
     985           0 :     const SvxNumberType& rNum = pPage->GetPageDesc()->GetNumType();
     986           0 :     return rNum.GetNumStr( nVirtNum );
     987             : }
     988             : 
     989           0 : SwErgoSumPortion *SwTxtFormatter::NewErgoSumPortion( SwTxtFormatInfo &rInf ) const
     990             : {
     991             :     // Wir koennen nicht davon ausgehen, dass wir ein Follow sind
     992             :     // 7983: GetIdx() nicht nStart
     993           0 :     if( !pFrm->IsInFtn()  || pFrm->GetPrev() ||
     994           0 :         rInf.IsErgoDone() || rInf.GetIdx() != pFrm->GetOfst() ||
     995           0 :         pFrm->ImplFindFtnFrm()->GetAttr()->GetFtn().IsEndNote() )
     996           0 :         return 0;
     997             : 
     998             :     // Aha, wir sind also im Fussnotenbereich
     999           0 :     const SwFtnInfo &rFtnInfo = pFrm->GetNode()->GetDoc()->GetFtnInfo();
    1000           0 :     SwTxtFrm *pQuoFrm = pFrm->FindQuoVadisFrm();
    1001           0 :     if( !pQuoFrm )
    1002           0 :         return 0;
    1003           0 :     const SwPageFrm* pPage = pFrm->FindPageFrm();
    1004           0 :     const SwPageFrm* pQuoPage = pQuoFrm->FindPageFrm();
    1005           0 :     if( pPage == pQuoFrm->FindPageFrm() )
    1006           0 :         return 0; // Wenn der QuoVadis auf der selben (spaltigen) Seite steht
    1007           0 :     const OUString aPage = lcl_GetPageNumber( pPage );
    1008           0 :     SwParaPortion *pPara = pQuoFrm->GetPara();
    1009           0 :     if( pPara )
    1010           0 :         pPara->SetErgoSumNum( aPage );
    1011           0 :     if( rFtnInfo.aErgoSum.isEmpty() )
    1012           0 :         return 0;
    1013             :     SwErgoSumPortion *pErgo = new SwErgoSumPortion( rFtnInfo.aErgoSum,
    1014           0 :                                 lcl_GetPageNumber( pQuoPage ) );
    1015           0 :     return pErgo;
    1016             : }
    1017             : 
    1018           0 : sal_Int32 SwTxtFormatter::FormatQuoVadis( const sal_Int32 nOffset )
    1019             : {
    1020             :     OSL_ENSURE( ! pFrm->IsVertical() || ! pFrm->IsSwapped(),
    1021             :             "SwTxtFormatter::FormatQuoVadis with swapped frame" );
    1022             : 
    1023           0 :     if( !pFrm->IsInFtn() || pFrm->ImplFindFtnFrm()->GetAttr()->GetFtn().IsEndNote() )
    1024           0 :         return nOffset;
    1025             : 
    1026           0 :     const SwFrm* pErgoFrm = pFrm->FindFtnFrm()->GetFollow();
    1027           0 :     if( !pErgoFrm && pFrm->HasFollow() )
    1028           0 :         pErgoFrm = pFrm->GetFollow();
    1029           0 :     if( !pErgoFrm )
    1030           0 :         return nOffset;
    1031             : 
    1032           0 :     if( pErgoFrm == pFrm->GetNext() )
    1033             :     {
    1034           0 :         SwFrm *pCol = pFrm->FindColFrm();
    1035           0 :         while( pCol && !pCol->GetNext() )
    1036           0 :             pCol = pCol->GetUpper()->FindColFrm();
    1037           0 :         if( pCol )
    1038           0 :             return nOffset;
    1039             :     }
    1040             :     else
    1041             :     {
    1042           0 :         const SwPageFrm* pPage = pFrm->FindPageFrm();
    1043           0 :         const SwPageFrm* pErgoPage = pErgoFrm->FindPageFrm();
    1044           0 :         if( pPage == pErgoPage )
    1045           0 :             return nOffset; // Wenn der ErgoSum auf der selben Seite steht
    1046             :     }
    1047             : 
    1048           0 :     SwTxtFormatInfo &rInf = GetInfo();
    1049           0 :     const SwFtnInfo &rFtnInfo = pFrm->GetNode()->GetDoc()->GetFtnInfo();
    1050           0 :     if( rFtnInfo.aQuoVadis.isEmpty() )
    1051           0 :         return nOffset;
    1052             : 
    1053             :     // Ein Wort zu QuoVadis/ErgoSum:
    1054             :     // Fuer diese Texte wird der am Absatz eingestellte Font verwendet.
    1055             :     // Wir initialisieren uns also:
    1056             : //  ResetFont();
    1057           0 :     FeedInf( rInf );
    1058           0 :     SeekStartAndChg( rInf, true );
    1059           0 :     if( GetRedln() && pCurr->HasRedline() )
    1060           0 :         GetRedln()->Seek( *pFnt, nOffset, 0 );
    1061             : 
    1062             :     // Ein fieser Sonderfall: Flyfrms reichen in die Zeile und stehen
    1063             :     // natuerlich da, wo wir unseren Quovadis Text reinsetzen wollen.
    1064             :     // Erst mal sehen, ob es so schlimm ist:
    1065           0 :     SwLinePortion *pPor = pCurr->GetFirstPortion();
    1066           0 :     KSHORT nLastLeft = 0;
    1067           0 :     while( pPor )
    1068             :     {
    1069           0 :         if ( pPor->IsFlyPortion() )
    1070           0 :             nLastLeft = ( (SwFlyPortion*) pPor)->Fix() +
    1071           0 :                         ( (SwFlyPortion*) pPor)->Width();
    1072           0 :         pPor = pPor->GetPortion();
    1073             :     }
    1074             :     // Das alte Spiel: wir wollen, dass die Zeile an einer bestimmten
    1075             :     // Stelle umbricht, also beeinflussen wir die Width.
    1076             :     // nLastLeft ist jetzt quasi der rechte Rand.
    1077           0 :     const KSHORT nOldRealWidth = rInf.RealWidth();
    1078           0 :     rInf.RealWidth( nOldRealWidth - nLastLeft );
    1079             : 
    1080           0 :     OUString aErgo = lcl_GetPageNumber( pErgoFrm->FindPageFrm() );
    1081           0 :     SwQuoVadisPortion *pQuo = new SwQuoVadisPortion(rFtnInfo.aQuoVadis, aErgo );
    1082           0 :     pQuo->SetAscent( rInf.GetAscent()  );
    1083           0 :     pQuo->Height( rInf.GetTxtHeight() );
    1084           0 :     pQuo->Format( rInf );
    1085           0 :     sal_uInt16 nQuoWidth = pQuo->Width();
    1086           0 :     SwLinePortion* pCurrPor = pQuo;
    1087             : 
    1088           0 :     while ( rInf.GetRest() )
    1089             :     {
    1090           0 :         SwLinePortion* pFollow = rInf.GetRest();
    1091           0 :         rInf.SetRest( 0 );
    1092           0 :         pCurrPor->Move( rInf );
    1093             : 
    1094             :         OSL_ENSURE( pFollow->IsQuoVadisPortion(),
    1095             :                 "Quo Vadis, rest of QuoVadisPortion" );
    1096             : 
    1097             :         // format the rest and append it to the other QuoVadis parts
    1098           0 :         pFollow->Format( rInf );
    1099           0 :         nQuoWidth = nQuoWidth + pFollow->Width();
    1100             : 
    1101           0 :         pCurrPor->Append( pFollow );
    1102           0 :         pCurrPor = pFollow;
    1103             :     }
    1104             : 
    1105           0 :     nLastLeft = nOldRealWidth - nQuoWidth;
    1106           0 :     Right( Right() - nQuoWidth );
    1107             : 
    1108           0 :     SWAP_IF_NOT_SWAPPED( pFrm )
    1109             : 
    1110           0 :     const sal_Int32 nRet = FormatLine( nStart );
    1111             : 
    1112           0 :     UNDO_SWAP( pFrm )
    1113             : 
    1114           0 :     Right( rInf.Left() + nOldRealWidth - 1 );
    1115             : 
    1116           0 :     nLastLeft = nOldRealWidth - pCurr->Width();
    1117           0 :     FeedInf( rInf );
    1118             : 
    1119             :     // Es kann durchaus sein, dass am Ende eine Marginportion steht,
    1120             :     // die beim erneuten Aufspannen nur Aerger bereiten wuerde.
    1121           0 :     pPor = pCurr->FindLastPortion();
    1122           0 :     SwGluePortion *pGlue = pPor->IsMarginPortion() ?
    1123           0 :         (SwMarginPortion*) pPor : 0;
    1124           0 :     if( pGlue )
    1125             :     {
    1126           0 :         pGlue->Height( 0 );
    1127           0 :         pGlue->Width( 0 );
    1128           0 :         pGlue->SetLen( 0 );
    1129           0 :         pGlue->SetAscent( 0 );
    1130           0 :         pGlue->SetPortion( NULL );
    1131           0 :         pGlue->SetFixWidth(0);
    1132             :     }
    1133             : 
    1134             :     // Luxus: Wir sorgen durch das Aufspannen von Glues dafuer,
    1135             :     // dass der QuoVadis-Text rechts erscheint:
    1136           0 :     nLastLeft = nLastLeft - nQuoWidth;
    1137           0 :     if( nLastLeft )
    1138             :     {
    1139           0 :         if( nLastLeft > pQuo->GetAscent() ) // Mindestabstand
    1140             :         {
    1141           0 :             switch( GetAdjust() )
    1142             :             {
    1143             :                 case SVX_ADJUST_BLOCK:
    1144             :                 {
    1145           0 :                     if( !pCurr->GetLen() ||
    1146           0 :                         CH_BREAK != GetInfo().GetChar(nStart+pCurr->GetLen()-1))
    1147           0 :                         nLastLeft = pQuo->GetAscent();
    1148           0 :                     nQuoWidth = nQuoWidth + nLastLeft;
    1149           0 :                     break;
    1150             :                 }
    1151             :                 case SVX_ADJUST_RIGHT:
    1152             :                 {
    1153           0 :                     nLastLeft = pQuo->GetAscent();
    1154           0 :                     nQuoWidth = nQuoWidth + nLastLeft;
    1155           0 :                     break;
    1156             :                 }
    1157             :                 case SVX_ADJUST_CENTER:
    1158             :                 {
    1159           0 :                     nQuoWidth = nQuoWidth + pQuo->GetAscent();
    1160           0 :                     long nDiff = nLastLeft - nQuoWidth;
    1161           0 :                     if( nDiff < 0 )
    1162             :                     {
    1163           0 :                         nLastLeft = pQuo->GetAscent();
    1164           0 :                         nQuoWidth = (sal_uInt16)(-nDiff + nLastLeft);
    1165             :                     }
    1166             :                     else
    1167             :                     {
    1168           0 :                         nQuoWidth = 0;
    1169           0 :                         nLastLeft = sal_uInt16(( pQuo->GetAscent() + nDiff ) / 2);
    1170             :                     }
    1171           0 :                     break;
    1172             :                 }
    1173             :                 default:
    1174           0 :                     nQuoWidth = nQuoWidth + nLastLeft;
    1175             :             }
    1176             :         }
    1177             :         else
    1178           0 :             nQuoWidth = nQuoWidth + nLastLeft;
    1179           0 :         if( nLastLeft )
    1180             :         {
    1181           0 :             pGlue = new SwGluePortion(0);
    1182           0 :             pGlue->Width( nLastLeft );
    1183           0 :             pPor->Append( pGlue );
    1184           0 :             pPor = pPor->GetPortion();
    1185             :         }
    1186             :     }
    1187             : 
    1188             :     // Jetzt aber: die QuoVadis-Portion wird angedockt:
    1189           0 :     pCurrPor = pQuo;
    1190           0 :     while ( pCurrPor )
    1191             :     {
    1192             :         // pPor->Append deletes the pPortoin pointer of pPor. Therefore
    1193             :         // we have to keep a pointer to the next portion
    1194           0 :         pQuo = (SwQuoVadisPortion*)pCurrPor->GetPortion();
    1195           0 :         pPor->Append( pCurrPor );
    1196           0 :         pPor = pPor->GetPortion();
    1197           0 :         pCurrPor = pQuo;
    1198             :     }
    1199             : 
    1200           0 :     pCurr->Width( pCurr->Width() + KSHORT( nQuoWidth ) );
    1201             : 
    1202             :     // Und noch einmal adjustieren wegen des Adjustment und nicht zu Letzt
    1203             :     // wegen folgendem Sonderfall: In der Zeile hat der DummUser durchgaengig
    1204             :     // einen kleineren Font eingestellt als der vom QuoVadis-Text ...
    1205           0 :     CalcAdjustLine( pCurr );
    1206             : 
    1207             :     // Uff...
    1208           0 :     return nRet;
    1209             : }
    1210             : 
    1211             : // MakeDummyLine() erzeugt eine Line, die bis zum unteren Seitenrand
    1212             : // reicht. DummyLines bzw. DummyPortions sorgen dafuer, dass Oszillationen
    1213             : // zum stehen kommen, weil Rueckflussmoeglichkeiten genommen werden.
    1214             : // Sie werden bei absatzgebundenen Frames in Fussnoten und bei Ftn-
    1215             : // Oszillationen verwendet.
    1216           0 : void SwTxtFormatter::MakeDummyLine()
    1217             : {
    1218           0 :     KSHORT nRstHeight = GetFrmRstHeight();
    1219           0 :     if( pCurr && nRstHeight > pCurr->Height() )
    1220             :     {
    1221           0 :         SwLineLayout *pLay = new SwLineLayout;
    1222           0 :         nRstHeight = nRstHeight - pCurr->Height();
    1223           0 :         pLay->Height( nRstHeight );
    1224           0 :         pLay->SetAscent( nRstHeight );
    1225           0 :         Insert( pLay );
    1226           0 :         Next();
    1227             :     }
    1228           0 : }
    1229             : 
    1230             : class SwFtnSave
    1231             : {
    1232             :     SwTxtSizeInfo *pInf;
    1233             :     SwFont       *pFnt;
    1234             :     SwFont       *pOld;
    1235             : public:
    1236             :     SwFtnSave( const SwTxtSizeInfo &rInf,
    1237             :                const SwTxtFtn *pTxtFtn,
    1238             :                const bool bApplyGivenScriptType,
    1239             :                const sal_uInt8 nGivenScriptType );
    1240             :    ~SwFtnSave();
    1241             : };
    1242             : 
    1243           0 : SwFtnSave::SwFtnSave( const SwTxtSizeInfo &rInf,
    1244             :                       const SwTxtFtn* pTxtFtn,
    1245             :                       const bool bApplyGivenScriptType,
    1246             :                       const sal_uInt8 nGivenScriptType )
    1247             :     : pInf( &((SwTxtSizeInfo&)rInf) )
    1248             :     , pFnt( 0 )
    1249           0 :     , pOld( 0 )
    1250             : {
    1251           0 :     if( pTxtFtn && rInf.GetTxtFrm() )
    1252             :     {
    1253           0 :         pFnt = ((SwTxtSizeInfo&)rInf).GetFont();
    1254           0 :           pOld = new SwFont( *pFnt );
    1255           0 :         pOld->GetTox() = pFnt->GetTox();
    1256           0 :         pFnt->GetTox() = 0;
    1257           0 :         SwFmtFtn& rFtn = (SwFmtFtn&)pTxtFtn->GetFtn();
    1258           0 :         const SwDoc *pDoc = rInf.GetTxtFrm()->GetNode()->GetDoc();
    1259             : 
    1260             :         // #i98418#
    1261           0 :         if ( bApplyGivenScriptType )
    1262             :         {
    1263           0 :             pFnt->SetActual( nGivenScriptType );
    1264             :         }
    1265             :         else
    1266             :         {
    1267             :             // examine text and set script
    1268           0 :             OUString aTmpStr( rFtn.GetViewNumStr( *pDoc ) );
    1269           0 :             pFnt->SetActual( SwScriptInfo::WhichFont( 0, &aTmpStr, 0 ) );
    1270             :         }
    1271             : 
    1272             :         const SwEndNoteInfo* pInfo;
    1273           0 :         if( rFtn.IsEndNote() )
    1274           0 :             pInfo = &pDoc->GetEndNoteInfo();
    1275             :         else
    1276           0 :             pInfo = &pDoc->GetFtnInfo();
    1277           0 :         const SwAttrSet& rSet = pInfo->GetAnchorCharFmt((SwDoc&)*pDoc)->GetAttrSet();
    1278           0 :         pFnt->SetDiffFnt( &rSet, rInf.GetTxtFrm()->GetNode()->getIDocumentSettingAccess() );
    1279             : 
    1280             :         // we reduce footnote size, if we are inside a double line portion
    1281           0 :         if ( ! pOld->GetEscapement() && 50 == pOld->GetPropr() )
    1282             :         {
    1283           0 :             Size aSize = pFnt->GetSize( pFnt->GetActual() );
    1284           0 :             pFnt->SetSize( Size( (long)aSize.Width() / 2,
    1285           0 :                                  (long)aSize.Height() / 2 ),
    1286           0 :                            pFnt->GetActual() );
    1287             :         }
    1288             : 
    1289             :         // set the correct rotation at the footnote font
    1290             :         const SfxPoolItem* pItem;
    1291           0 :         if( SFX_ITEM_SET == rSet.GetItemState( RES_CHRATR_ROTATE,
    1292           0 :             true, &pItem ))
    1293           0 :             pFnt->SetVertical( ((SvxCharRotateItem*)pItem)->GetValue(),
    1294           0 :                                 rInf.GetTxtFrm()->IsVertical() );
    1295             : 
    1296           0 :         pFnt->ChgPhysFnt( pInf->GetVsh(), *pInf->GetOut() );
    1297             : 
    1298           0 :         if( SFX_ITEM_SET == rSet.GetItemState( RES_CHRATR_BACKGROUND,
    1299           0 :             true, &pItem ))
    1300           0 :             pFnt->SetBackColor( new Color( ((SvxBrushItem*)pItem)->GetColor() ) );
    1301             :     }
    1302             :     else
    1303           0 :         pFnt = NULL;
    1304           0 : }
    1305             : 
    1306           0 : SwFtnSave::~SwFtnSave()
    1307             : {
    1308           0 :     if( pFnt )
    1309             :     {
    1310             :         // SwFont zurueckstellen
    1311           0 :         *pFnt = *pOld;
    1312           0 :         pFnt->GetTox() = pOld->GetTox();
    1313           0 :         pFnt->ChgPhysFnt( pInf->GetVsh(), *pInf->GetOut() );
    1314           0 :         delete pOld;
    1315             :     }
    1316           0 : }
    1317             : 
    1318           0 : SwFtnPortion::SwFtnPortion( const OUString &rExpand,
    1319             :                             SwTxtFtn *pFootn, KSHORT nReal )
    1320             :         : SwFldPortion( rExpand, 0 )
    1321             :         , pFtn(pFootn)
    1322             :         , nOrigHeight( nReal )
    1323             :         // #i98418#
    1324             :         , mbPreferredScriptTypeSet( false )
    1325           0 :         , mnPreferredScriptType( SW_LATIN )
    1326             : {
    1327           0 :     SetLen(1);
    1328           0 :     SetWhichPor( POR_FTN );
    1329           0 : }
    1330             : 
    1331           0 : bool SwFtnPortion::GetExpTxt( const SwTxtSizeInfo &, OUString &rTxt ) const
    1332             : {
    1333           0 :     rTxt = aExpand;
    1334           0 :     return true;
    1335             : }
    1336             : 
    1337           0 : bool SwFtnPortion::Format( SwTxtFormatInfo &rInf )
    1338             : {
    1339             :     // #i98418#
    1340             : //    SwFtnSave aFtnSave( rInf, pFtn );
    1341           0 :     SwFtnSave aFtnSave( rInf, pFtn, mbPreferredScriptTypeSet, mnPreferredScriptType );
    1342             :     // the idx is manipulated in SwExpandPortion::Format
    1343             :     // this flag indicates, that a footnote is allowed to trigger
    1344             :     // an underflow during SwTxtGuess::Guess
    1345           0 :     rInf.SetFakeLineStart( rInf.GetIdx() > rInf.GetLineStart() );
    1346           0 :     const bool bFull = SwFldPortion::Format( rInf );
    1347           0 :     rInf.SetFakeLineStart( false );
    1348           0 :     SetAscent( rInf.GetAscent() );
    1349           0 :     Height( rInf.GetTxtHeight() );
    1350           0 :     rInf.SetFtnDone( !bFull );
    1351           0 :     if( !bFull )
    1352           0 :         rInf.SetParaFtn();
    1353           0 :     return bFull;
    1354             : }
    1355             : 
    1356           0 : void SwFtnPortion::Paint( const SwTxtPaintInfo &rInf ) const
    1357             : {
    1358             :     // #i98418#
    1359             : //    SwFtnSave aFtnSave( rInf, pFtn );
    1360           0 :     SwFtnSave aFtnSave( rInf, pFtn, mbPreferredScriptTypeSet, mnPreferredScriptType );
    1361           0 :     rInf.DrawViewOpt( *this, POR_FTN );
    1362           0 :     SwExpandPortion::Paint( rInf );
    1363           0 : }
    1364             : 
    1365           0 : SwPosSize SwFtnPortion::GetTxtSize( const SwTxtSizeInfo &rInfo ) const
    1366             : {
    1367             :     // #i98418#
    1368             : //    SwFtnSave aFtnSave( rInfo, pFtn );
    1369           0 :     SwFtnSave aFtnSave( rInfo, pFtn, mbPreferredScriptTypeSet, mnPreferredScriptType );
    1370           0 :     return SwExpandPortion::GetTxtSize( rInfo );
    1371             : }
    1372             : 
    1373             : // #i98418#
    1374           0 : void SwFtnPortion::SetPreferredScriptType( sal_uInt8 nPreferredScriptType )
    1375             : {
    1376           0 :     mbPreferredScriptTypeSet = true;
    1377           0 :     mnPreferredScriptType = nPreferredScriptType;
    1378           0 : }
    1379             : 
    1380           0 : SwFldPortion *SwQuoVadisPortion::Clone( const OUString &rExpand ) const
    1381             : {
    1382           0 :     return new SwQuoVadisPortion( rExpand, aErgo );
    1383             : }
    1384             : 
    1385           0 : SwQuoVadisPortion::SwQuoVadisPortion( const OUString &rExp, const OUString& rStr )
    1386           0 :     : SwFldPortion( rExp ), aErgo(rStr)
    1387             : {
    1388           0 :     SetLen(0);
    1389           0 :     SetWhichPor( POR_QUOVADIS );
    1390           0 : }
    1391             : 
    1392           0 : bool SwQuoVadisPortion::Format( SwTxtFormatInfo &rInf )
    1393             : {
    1394             :     // erster Versuch, vielleicht passt der Text
    1395           0 :     CheckScript( rInf );
    1396           0 :     bool bFull = SwFldPortion::Format( rInf );
    1397           0 :     SetLen( 0 );
    1398             : 
    1399           0 :     if( bFull )
    1400             :     {
    1401             :         // zweiter Versuch, wir kuerzen den String:
    1402           0 :         aExpand = "...";
    1403           0 :         bFull = SwFldPortion::Format( rInf );
    1404           0 :         SetLen( 0 );
    1405           0 :         if( bFull  )
    1406             :             // dritter Versuch, es langt: jetzt wird gestaucht:
    1407           0 :             Width( sal_uInt16(rInf.Width() - rInf.X()) );
    1408             : 
    1409             :         // 8317: keine mehrzeiligen Felder bei QuoVadis und ErgoSum
    1410           0 :         if( rInf.GetRest() )
    1411             :         {
    1412           0 :             delete rInf.GetRest();
    1413           0 :             rInf.SetRest( 0 );
    1414             :         }
    1415             :     }
    1416           0 :     return bFull;
    1417             : }
    1418             : 
    1419           0 : bool SwQuoVadisPortion::GetExpTxt( const SwTxtSizeInfo &, OUString &rTxt ) const
    1420             : {
    1421           0 :     rTxt = aExpand;
    1422             :     // if this QuoVadisPortion has a follow, the follow is responsible for
    1423             :     // the ergo text.
    1424           0 :     if ( ! HasFollow() )
    1425           0 :         rTxt += aErgo;
    1426           0 :     return true;
    1427             : }
    1428             : 
    1429           0 : void SwQuoVadisPortion::HandlePortion( SwPortionHandler& rPH ) const
    1430             : {
    1431           0 :     OUString aString( aExpand );
    1432           0 :     aString += aErgo;
    1433           0 :     rPH.Special( GetLen(), aString, GetWhichPor() );
    1434           0 : }
    1435             : 
    1436           0 : void SwQuoVadisPortion::Paint( const SwTxtPaintInfo &rInf ) const
    1437             : {
    1438             :     // Wir wollen _immer_ per DrawStretchText ausgeben,
    1439             :     // weil nErgo schnell mal wechseln kann.
    1440           0 :     if( PrtWidth() )
    1441             :     {
    1442           0 :         rInf.DrawViewOpt( *this, POR_QUOVADIS );
    1443           0 :         SwTxtSlot aDiffTxt( &rInf, this, true, false );
    1444           0 :         SwFontSave aSave( rInf, pFnt );
    1445           0 :         rInf.DrawText( *this, rInf.GetLen(), true );
    1446             :     }
    1447           0 : }
    1448             : 
    1449           0 : SwFldPortion *SwErgoSumPortion::Clone( const OUString &rExpand ) const
    1450             : {
    1451           0 :     return new SwErgoSumPortion( rExpand, OUString() );
    1452             : }
    1453             : 
    1454           0 : SwErgoSumPortion::SwErgoSumPortion(const OUString &rExp, const OUString& rStr)
    1455           0 :     : SwFldPortion( rExp )
    1456             : {
    1457           0 :     SetLen(0);
    1458           0 :     aExpand += rStr;
    1459             : 
    1460             :     // 7773: sinnvolle Massnahme: ein Blank Abstand zum Text
    1461           0 :     aExpand += " ";
    1462           0 :     SetWhichPor( POR_ERGOSUM );
    1463           0 : }
    1464             : 
    1465           0 : sal_Int32 SwErgoSumPortion::GetCrsrOfst( const KSHORT ) const
    1466             : {
    1467           0 :     return 0;
    1468             : }
    1469             : 
    1470           0 : bool SwErgoSumPortion::Format( SwTxtFormatInfo &rInf )
    1471             : {
    1472           0 :     const bool bFull = SwFldPortion::Format( rInf );
    1473           0 :     SetLen( 0 );
    1474           0 :     rInf.SetErgoDone( true );
    1475             : 
    1476             :     // 8317: keine mehrzeiligen Felder bei QuoVadis und ErgoSum
    1477           0 :     if( bFull && rInf.GetRest() )
    1478             :     {
    1479           0 :         delete rInf.GetRest();
    1480           0 :         rInf.SetRest( 0 );
    1481             :     }
    1482             : 
    1483             :     // We return false in order to get some text into the current line,
    1484             :     // even if it's full (better than looping)
    1485           0 :     return false;
    1486             : }
    1487             : 
    1488           0 : void SwParaPortion::SetErgoSumNum( const OUString& rErgo )
    1489             : {
    1490           0 :     SwLineLayout *pLay = this;
    1491           0 :     while( pLay->GetNext() )
    1492             :     {
    1493           0 :         pLay = pLay->GetNext();
    1494             :     }
    1495           0 :     SwLinePortion     *pPor = pLay;
    1496           0 :     SwQuoVadisPortion *pQuo = 0;
    1497           0 :     while( pPor && !pQuo )
    1498             :     {
    1499           0 :         if ( pPor->IsQuoVadisPortion() )
    1500           0 :             pQuo = (SwQuoVadisPortion*)pPor;
    1501           0 :         pPor = pPor->GetPortion();
    1502             :     }
    1503           0 :     if( pQuo )
    1504           0 :         pQuo->SetNumber( rErgo );
    1505           0 : }
    1506             : 
    1507             : /*************************************************************************
    1508             :  *                      SwParaPortion::UpdateQuoVadis()
    1509             :  *
    1510             :  * Wird im SwTxtFrm::Prepare() gerufen
    1511             :  *************************************************************************/
    1512             : 
    1513           0 : bool SwParaPortion::UpdateQuoVadis( const OUString &rQuo )
    1514             : {
    1515           0 :     SwLineLayout *pLay = this;
    1516           0 :     while( pLay->GetNext() )
    1517             :     {
    1518           0 :         pLay = pLay->GetNext();
    1519             :     }
    1520           0 :     SwLinePortion     *pPor = pLay;
    1521           0 :     SwQuoVadisPortion *pQuo = 0;
    1522           0 :     while( pPor && !pQuo )
    1523             :     {
    1524           0 :         if ( pPor->IsQuoVadisPortion() )
    1525           0 :             pQuo = (SwQuoVadisPortion*)pPor;
    1526           0 :         pPor = pPor->GetPortion();
    1527             :     }
    1528             : 
    1529           0 :     if( !pQuo )
    1530           0 :         return false;
    1531             : 
    1532           0 :     return pQuo->GetQuoTxt() == rQuo;
    1533             : }
    1534             : 
    1535             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10