LCOV - code coverage report
Current view: top level - sw/source/core/text - frmcrsr.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 841 0.0 %
Date: 2014-04-14 Functions: 0 32 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 "ndtxt.hxx"
      21             : #include "pam.hxx"
      22             : #include "frmtool.hxx"
      23             : #include "viewopt.hxx"
      24             : #include "paratr.hxx"
      25             : #include "rootfrm.hxx"
      26             : #include "pagefrm.hxx"
      27             : #include "colfrm.hxx"
      28             : #include "txttypes.hxx"
      29             : #include <sfx2/printer.hxx>
      30             : #include <editeng/lrspitem.hxx>
      31             : #include <editeng/tstpitem.hxx>
      32             : #include <editeng/ulspitem.hxx>
      33             : #include <editeng/lspcitem.hxx>
      34             : #include <pormulti.hxx>
      35             : #include <doc.hxx>
      36             : #include <sortedobjs.hxx>
      37             : 
      38             : #include <unicode/ubidi.h>
      39             : 
      40             : #include "txtfrm.hxx"
      41             : #include "inftxt.hxx"
      42             : #include "itrtxt.hxx"
      43             : #include "crstate.hxx"
      44             : #include "viewsh.hxx"
      45             : #include "swfntcch.hxx"
      46             : #include "flyfrm.hxx"
      47             : 
      48             : #define MIN_OFFSET_STEP 10
      49             : 
      50             : using namespace ::com::sun::star;
      51             : 
      52             : /*
      53             :  * - SurvivalKit: For how long do we get past the last char of the line.
      54             :  * - RightMargin abstains from adjusting position with -1
      55             :  * - GetCharRect returns a GetEndCharRect for MV_RIGHTMARGIN
      56             :  * - GetEndCharRect sets bRightMargin to true
      57             :  * - SwTxtCursor::bRightMargin is set to false by CharCrsrToLine
      58             :  */
      59             : 
      60             : namespace
      61             : {
      62             : 
      63           0 : SwTxtFrm *GetAdjFrmAtPos( SwTxtFrm *pFrm, const SwPosition &rPos,
      64             :                           const bool bRightMargin, const bool bNoScroll = true )
      65             : {
      66             :     // RightMargin in the last master line
      67           0 :     const sal_Int32 nOffset = rPos.nContent.GetIndex();
      68           0 :     SwTxtFrm *pFrmAtPos = pFrm;
      69           0 :     if( !bNoScroll || pFrm->GetFollow() )
      70             :     {
      71           0 :         pFrmAtPos = pFrm->GetFrmAtPos( rPos );
      72           0 :         if( nOffset < pFrmAtPos->GetOfst() &&
      73           0 :             !pFrmAtPos->IsFollow() )
      74             :         {
      75           0 :             sal_Int32 nNew = nOffset;
      76           0 :             if( nNew < MIN_OFFSET_STEP )
      77           0 :                 nNew = 0;
      78             :             else
      79           0 :                 nNew -= MIN_OFFSET_STEP;
      80           0 :             sw_ChangeOffset( pFrmAtPos, nNew );
      81             :         }
      82             :     }
      83           0 :     while( pFrm != pFrmAtPos )
      84             :     {
      85           0 :         pFrm = pFrmAtPos;
      86           0 :         pFrm->GetFormatted();
      87           0 :         pFrmAtPos = (SwTxtFrm*)pFrm->GetFrmAtPos( rPos );
      88             :     }
      89             : 
      90           0 :     if( nOffset && bRightMargin )
      91             :     {
      92           0 :         while( pFrmAtPos && pFrmAtPos->GetOfst() == nOffset &&
      93           0 :                pFrmAtPos->IsFollow() )
      94             :         {
      95           0 :             pFrmAtPos->GetFormatted();
      96           0 :             pFrmAtPos = pFrmAtPos->FindMaster();
      97             :         }
      98             :         OSL_ENSURE( pFrmAtPos, "+GetCharRect: no frame with my rightmargin" );
      99             :     }
     100           0 :     return pFrmAtPos ? pFrmAtPos : pFrm;
     101             : }
     102             : 
     103             : }
     104             : 
     105           0 : bool sw_ChangeOffset( SwTxtFrm* pFrm, sal_Int32 nNew )
     106             : {
     107             :     // Do not scroll in areas and outside of flies
     108             :     OSL_ENSURE( !pFrm->IsFollow(), "Illegal Scrolling by Follow!" );
     109           0 :     if( pFrm->GetOfst() != nNew && !pFrm->IsInSct() )
     110             :     {
     111           0 :         SwFlyFrm *pFly = pFrm->FindFlyFrm();
     112             :         // Attention: if e.g. in a column frame the size is still invalid
     113             :         // we must not scroll around just like that
     114           0 :         if ( ( pFly && pFly->IsValid() &&
     115           0 :              !pFly->GetNextLink() && !pFly->GetPrevLink() ) ||
     116           0 :              ( !pFly && pFrm->IsInTab() ) )
     117             :         {
     118           0 :             SwViewShell* pVsh = pFrm->getRootFrm()->GetCurrShell();
     119           0 :             if( pVsh )
     120             :             {
     121           0 :                 if( pVsh->GetNext() != pVsh ||
     122           0 :                     ( pFrm->GetDrawObjs() && pFrm->GetDrawObjs()->Count() ) )
     123             :                 {
     124           0 :                     if( !pFrm->GetOfst() )
     125           0 :                         return false;
     126           0 :                     nNew = 0;
     127             :                 }
     128           0 :                 pFrm->SetOfst( nNew );
     129           0 :                 pFrm->SetPara( 0 );
     130           0 :                 pFrm->GetFormatted();
     131           0 :                 if( pFrm->Frm().HasArea() )
     132           0 :                     pFrm->getRootFrm()->GetCurrShell()->InvalidateWindows( pFrm->Frm() );
     133           0 :                 return true;
     134             :             }
     135             :         }
     136             :     }
     137           0 :     return false;
     138             : }
     139             : 
     140             : /*************************************************************************
     141             :  *                      GetFrmAtOfst(), GetFrmAtPos()
     142             :  *************************************************************************/
     143             : 
     144           0 : SwTxtFrm& SwTxtFrm::GetFrmAtOfst( const sal_Int32 nWhere )
     145             : {
     146           0 :     SwTxtFrm* pRet = this;
     147           0 :     while( pRet->HasFollow() && nWhere >= pRet->GetFollow()->GetOfst() )
     148           0 :         pRet = pRet->GetFollow();
     149           0 :     return *pRet;
     150             : }
     151             : 
     152           0 : SwTxtFrm *SwTxtFrm::GetFrmAtPos( const SwPosition &rPos )
     153             : {
     154           0 :     SwTxtFrm *pFoll = (SwTxtFrm*)this;
     155           0 :     while( pFoll->GetFollow() )
     156             :     {
     157           0 :         if( rPos.nContent.GetIndex() > pFoll->GetFollow()->GetOfst() )
     158           0 :             pFoll = pFoll->GetFollow();
     159             :         else
     160             :         {
     161           0 :             if( rPos.nContent.GetIndex() == pFoll->GetFollow()->GetOfst()
     162           0 :                  && !SwTxtCursor::IsRightMargin() )
     163           0 :                  pFoll = pFoll->GetFollow();
     164             :             else
     165           0 :                 break;
     166             :         }
     167             :     }
     168           0 :     return pFoll;
     169             : }
     170             : 
     171             : /*************************************************************************
     172             :  *                      SwTxtFrm::GetCharRect()
     173             :  *************************************************************************/
     174             : 
     175             : /*
     176             :  * GetCharRect() returns the char's char line described by aPos.
     177             :  * GetCrsrOfst() does the reverse: It goes from a document coordinate to
     178             :  * a Pam.
     179             :  * Both are virtual in the frame base class and thus are redefined here.
     180             :  */
     181             : 
     182           0 : bool SwTxtFrm::GetCharRect( SwRect& rOrig, const SwPosition &rPos,
     183             :                             SwCrsrMoveState *pCMS ) const
     184             : {
     185             :     OSL_ENSURE( ! IsVertical() || ! IsSwapped(),"SwTxtFrm::GetCharRect with swapped frame" );
     186             : 
     187           0 :     if( IsLocked() || IsHiddenNow() )
     188           0 :         return false;
     189             : 
     190             :     // Find the right frame first. We need to keep in mind that:
     191             :     // - the cached information could be invalid  (GetPara() == 0)
     192             :     // - we could have a Follow
     193             :     // - the Follow chain grows dynamically; the one we end up in
     194             :     //   needs to be formatted
     195             : 
     196             :     // Optimisation: reading ahead saves us a GetAdjFrmAtPos
     197           0 :     const bool bRightMargin = pCMS && ( MV_RIGHTMARGIN == pCMS->eState );
     198           0 :     const bool bNoScroll = pCMS && pCMS->bNoScroll;
     199             :     SwTxtFrm *pFrm = GetAdjFrmAtPos( (SwTxtFrm*)this, rPos, bRightMargin,
     200           0 :                                      bNoScroll );
     201           0 :     pFrm->GetFormatted();
     202           0 :     const SwFrm* pTmpFrm = (SwFrm*)pFrm->GetUpper();
     203             : 
     204           0 :     SWRECTFN ( pFrm )
     205           0 :     const SwTwips nUpperMaxY = (pTmpFrm->*fnRect->fnGetPrtBottom)();
     206           0 :     const SwTwips nFrmMaxY = (pFrm->*fnRect->fnGetPrtBottom)();
     207             : 
     208             :     // nMaxY is an absolute value
     209             :     //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
     210             :     SwTwips nMaxY = bVert ?
     211           0 :                     ( bVertL2R ? std::min( nFrmMaxY, nUpperMaxY ) : std::max( nFrmMaxY, nUpperMaxY ) ) :
     212           0 :                     std::min( nFrmMaxY, nUpperMaxY );
     213             : 
     214           0 :     bool bRet = false;
     215             : 
     216           0 :     if ( pFrm->IsEmpty() || ! (pFrm->Prt().*fnRect->fnGetHeight)() )
     217             :     {
     218           0 :         Point aPnt1 = pFrm->Frm().Pos() + pFrm->Prt().Pos();
     219           0 :         SwTxtNode* pTxtNd = ((SwTxtFrm*)this)->GetTxtNode();
     220             :         short nFirstOffset;
     221           0 :         pTxtNd->GetFirstLineOfsWithNum( nFirstOffset );
     222             : 
     223           0 :         Point aPnt2;
     224           0 :         if ( bVert )
     225             :         {
     226           0 :             if( nFirstOffset > 0 )
     227           0 :                 aPnt1.Y() += nFirstOffset;
     228             :             //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
     229           0 :             if ( aPnt1.X() < nMaxY && !bVertL2R )
     230           0 :                 aPnt1.X() = nMaxY;
     231           0 :             aPnt2.X() = aPnt1.X() + pFrm->Prt().Width();
     232           0 :             aPnt2.Y() = aPnt1.Y();
     233           0 :             if( aPnt2.X() < nMaxY )
     234           0 :                 aPnt2.X() = nMaxY;
     235             :         }
     236             :         else
     237             :         {
     238           0 :             if( nFirstOffset > 0 )
     239           0 :                 aPnt1.X() += nFirstOffset;
     240             : 
     241           0 :             if( aPnt1.Y() > nMaxY )
     242           0 :                 aPnt1.Y() = nMaxY;
     243           0 :             aPnt2.X() = aPnt1.X();
     244           0 :             aPnt2.Y() = aPnt1.Y() + pFrm->Prt().Height();
     245           0 :             if( aPnt2.Y() > nMaxY )
     246           0 :                 aPnt2.Y() = nMaxY;
     247             :         }
     248             : 
     249           0 :         rOrig = SwRect( aPnt1, aPnt2 );
     250             : 
     251           0 :         if ( pCMS )
     252             :         {
     253           0 :             pCMS->aRealHeight.X() = 0;
     254           0 :             pCMS->aRealHeight.Y() = bVert ? -rOrig.Width() : rOrig.Height();
     255             :         }
     256             : 
     257           0 :         if ( pFrm->IsRightToLeft() )
     258           0 :             pFrm->SwitchLTRtoRTL( rOrig );
     259             : 
     260           0 :         bRet = true;
     261             :     }
     262             :     else
     263             :     {
     264           0 :         if( !pFrm->HasPara() )
     265           0 :             return false;
     266             : 
     267           0 :         SwFrmSwapper aSwapper( pFrm, true );
     268           0 :         if ( bVert )
     269           0 :             nMaxY = pFrm->SwitchVerticalToHorizontal( nMaxY );
     270             : 
     271           0 :         bool bGoOn = true;
     272           0 :         const sal_Int32 nOffset = rPos.nContent.GetIndex();
     273             :         sal_Int32 nNextOfst;
     274             : 
     275           0 :         do
     276             :         {
     277             :             {
     278           0 :                 SwTxtSizeInfo aInf( pFrm );
     279           0 :                 SwTxtCursor  aLine( pFrm, &aInf );
     280           0 :                 nNextOfst = aLine.GetEnd();
     281             :                 // See comment in AdjustFrm
     282             :                 // Include the line's last char?
     283             :                 bRet = bRightMargin ? aLine.GetEndCharRect( &rOrig, nOffset, pCMS, nMaxY )
     284           0 :                                 : aLine.GetCharRect( &rOrig, nOffset, pCMS, nMaxY );
     285             :             }
     286             : 
     287           0 :             if ( pFrm->IsRightToLeft() )
     288           0 :                 pFrm->SwitchLTRtoRTL( rOrig );
     289             : 
     290           0 :             if ( bVert )
     291           0 :                 pFrm->SwitchHorizontalToVertical( rOrig );
     292             : 
     293           0 :             if( pFrm->IsUndersized() && pCMS && !pFrm->GetNext() &&
     294           0 :                 (rOrig.*fnRect->fnGetBottom)() == nUpperMaxY &&
     295           0 :                 pFrm->GetOfst() < nOffset &&
     296           0 :                 !pFrm->IsFollow() && !bNoScroll &&
     297           0 :                 pFrm->GetTxtNode()->GetTxt().getLength() != nNextOfst)
     298             :             {
     299           0 :                 bGoOn = sw_ChangeOffset( pFrm, nNextOfst );
     300             :             }
     301             :             else
     302           0 :                 bGoOn = false;
     303             :         } while ( bGoOn );
     304             : 
     305           0 :         if ( pCMS )
     306             :         {
     307           0 :             if ( pFrm->IsRightToLeft() )
     308             :             {
     309           0 :                 if( pCMS->b2Lines && pCMS->p2Lines)
     310             :                 {
     311           0 :                     pFrm->SwitchLTRtoRTL( pCMS->p2Lines->aLine );
     312           0 :                     pFrm->SwitchLTRtoRTL( pCMS->p2Lines->aPortion );
     313             :                 }
     314             :             }
     315             : 
     316           0 :             if ( bVert )
     317             :             {
     318           0 :                 if ( pCMS->bRealHeight )
     319             :                 {
     320           0 :                     pCMS->aRealHeight.Y() = -pCMS->aRealHeight.Y();
     321           0 :                     if ( pCMS->aRealHeight.Y() < 0 )
     322             :                     {
     323             :                         // writing direction is from top to bottom
     324           0 :                         pCMS->aRealHeight.X() =  ( rOrig.Width() -
     325           0 :                                                     pCMS->aRealHeight.X() +
     326           0 :                                                     pCMS->aRealHeight.Y() );
     327             :                     }
     328             :                 }
     329           0 :                 if( pCMS->b2Lines && pCMS->p2Lines)
     330             :                 {
     331           0 :                     pFrm->SwitchHorizontalToVertical( pCMS->p2Lines->aLine );
     332           0 :                     pFrm->SwitchHorizontalToVertical( pCMS->p2Lines->aPortion );
     333             :                 }
     334             :             }
     335             : 
     336           0 :         }
     337             :     }
     338           0 :     if( bRet )
     339             :     {
     340           0 :         SwPageFrm *pPage = pFrm->FindPageFrm();
     341             :         OSL_ENSURE( pPage, "Text escaped from page?" );
     342           0 :         const SwTwips nOrigTop = (rOrig.*fnRect->fnGetTop)();
     343           0 :         const SwTwips nPageTop = (pPage->Frm().*fnRect->fnGetTop)();
     344           0 :         const SwTwips nPageBott = (pPage->Frm().*fnRect->fnGetBottom)();
     345             : 
     346             :         // We have the following situation: if the frame is in an invalid
     347             :         // sectionframe, it's possible that the frame is outside the page.
     348             :         // If we restrict the cursor position to the page area, we enforce
     349             :         // the formatting of the page, of the section frame and the frame itself.
     350           0 :         if( (*fnRect->fnYDiff)( nPageTop, nOrigTop ) > 0 )
     351           0 :             (rOrig.*fnRect->fnSetTop)( nPageTop );
     352             : 
     353           0 :         if ( (*fnRect->fnYDiff)( nOrigTop, nPageBott ) > 0 )
     354           0 :             (rOrig.*fnRect->fnSetTop)( nPageBott );
     355             :     }
     356             : 
     357           0 :     return bRet;
     358             : }
     359             : 
     360             : /*************************************************************************
     361             :  *                      SwTxtFrm::GetAutoPos()
     362             :  *************************************************************************/
     363             : 
     364             : /*
     365             :  * GetAutoPos() looks up the char's char line which is described by rPos
     366             :  * and is used by the auto-positioned frame.
     367             :  */
     368             : 
     369           0 : bool SwTxtFrm::GetAutoPos( SwRect& rOrig, const SwPosition &rPos ) const
     370             : {
     371           0 :     if( IsHiddenNow() )
     372           0 :         return false;
     373             : 
     374           0 :     const sal_Int32 nOffset = rPos.nContent.GetIndex();
     375           0 :     SwTxtFrm* pFrm = &(const_cast<SwTxtFrm*>(this)->GetFrmAtOfst( nOffset ));
     376             : 
     377           0 :     pFrm->GetFormatted();
     378           0 :     const SwFrm* pTmpFrm = (SwFrm*)pFrm->GetUpper();
     379             : 
     380           0 :     SWRECTFN( pTmpFrm )
     381           0 :     SwTwips nUpperMaxY = (pTmpFrm->*fnRect->fnGetPrtBottom)();
     382             : 
     383             :     // nMaxY is in absolute value
     384             :     //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
     385             :     SwTwips nMaxY = bVert ?
     386           0 :                     ( bVertL2R ? std::min( (pFrm->*fnRect->fnGetPrtBottom)(), nUpperMaxY ) : std::max( (pFrm->*fnRect->fnGetPrtBottom)(), nUpperMaxY ) ) :
     387           0 :                     std::min( (pFrm->*fnRect->fnGetPrtBottom)(), nUpperMaxY );
     388             : 
     389           0 :     if ( pFrm->IsEmpty() || ! (pFrm->Prt().*fnRect->fnGetHeight)() )
     390             :     {
     391           0 :         Point aPnt1 = pFrm->Frm().Pos() + pFrm->Prt().Pos();
     392           0 :         Point aPnt2;
     393           0 :         if ( bVert )
     394             :         {
     395           0 :             if ( aPnt1.X() < nMaxY && !bVertL2R )
     396           0 :                 aPnt1.X() = nMaxY;
     397             : 
     398           0 :             aPnt2.X() = aPnt1.X() + pFrm->Prt().Width();
     399           0 :             aPnt2.Y() = aPnt1.Y();
     400           0 :             if( aPnt2.X() < nMaxY )
     401           0 :                 aPnt2.X() = nMaxY;
     402             :         }
     403             :         else
     404             :         {
     405           0 :             if( aPnt1.Y() > nMaxY )
     406           0 :                 aPnt1.Y() = nMaxY;
     407           0 :             aPnt2.X() = aPnt1.X();
     408           0 :             aPnt2.Y() = aPnt1.Y() + pFrm->Prt().Height();
     409           0 :             if( aPnt2.Y() > nMaxY )
     410           0 :                 aPnt2.Y() = nMaxY;
     411             :         }
     412           0 :         rOrig = SwRect( aPnt1, aPnt2 );
     413           0 :         return true;
     414             :     }
     415             :     else
     416             :     {
     417           0 :         if( !pFrm->HasPara() )
     418           0 :             return false;
     419             : 
     420           0 :         SwFrmSwapper aSwapper( pFrm, true );
     421           0 :         if ( bVert )
     422           0 :             nMaxY = pFrm->SwitchVerticalToHorizontal( nMaxY );
     423             : 
     424           0 :         SwTxtSizeInfo aInf( pFrm );
     425           0 :         SwTxtCursor aLine( pFrm, &aInf );
     426           0 :         SwCrsrMoveState aTmpState( MV_SETONLYTEXT );
     427           0 :         aTmpState.bRealHeight = true;
     428           0 :         if( aLine.GetCharRect( &rOrig, nOffset, &aTmpState, nMaxY ) )
     429             :         {
     430           0 :             if( aTmpState.aRealHeight.X() >= 0 )
     431             :             {
     432           0 :                 rOrig.Pos().Y() += aTmpState.aRealHeight.X();
     433           0 :                 rOrig.Height( aTmpState.aRealHeight.Y() );
     434             :             }
     435             : 
     436           0 :             if ( pFrm->IsRightToLeft() )
     437           0 :                 pFrm->SwitchLTRtoRTL( rOrig );
     438             : 
     439           0 :             if ( bVert )
     440           0 :                 pFrm->SwitchHorizontalToVertical( rOrig );
     441             : 
     442           0 :             return true;
     443             :         }
     444           0 :         return false;
     445             :     }
     446             : }
     447             : 
     448             : /** determine top of line for given position in the text frame
     449             : 
     450             :     - Top of first paragraph line is the top of the printing area of the text frame
     451             :     - If a proportional line spacing is applied use top of anchor character as
     452             :       top of the line.
     453             : */
     454           0 : bool SwTxtFrm::GetTopOfLine( SwTwips& _onTopOfLine,
     455             :                              const SwPosition& _rPos ) const
     456             : {
     457           0 :     bool bRet = true;
     458             : 
     459             :     // get position offset
     460           0 :     const sal_Int32 nOffset = _rPos.nContent.GetIndex();
     461             : 
     462           0 :     if ( GetTxt().getLength() < nOffset )
     463             :     {
     464           0 :         bRet = false;
     465             :     }
     466             :     else
     467             :     {
     468           0 :         SWRECTFN( this )
     469           0 :         if ( IsEmpty() || !(Prt().*fnRect->fnGetHeight)() )
     470             :         {
     471             :             // consider upper space amount considered
     472             :             // for previous frame and the page grid.
     473           0 :             _onTopOfLine = (this->*fnRect->fnGetPrtTop)();
     474             :         }
     475             :         else
     476             :         {
     477             :             // determine formatted text frame that contains the requested position
     478           0 :             SwTxtFrm* pFrm = &(const_cast<SwTxtFrm*>(this)->GetFrmAtOfst( nOffset ));
     479           0 :             pFrm->GetFormatted();
     480           0 :             SWREFRESHFN( pFrm )
     481             :             // If proportional line spacing is applied
     482             :             // to the text frame, the top of the anchor character is also the
     483             :             // top of the line.
     484             :             // Otherwise the line layout determines the top of the line
     485           0 :             const SvxLineSpacingItem& rSpace = GetAttrSet()->GetLineSpacing();
     486           0 :             if ( rSpace.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_PROP )
     487             :             {
     488           0 :                 SwRect aCharRect;
     489           0 :                 if ( GetAutoPos( aCharRect, _rPos ) )
     490             :                 {
     491           0 :                     _onTopOfLine = (aCharRect.*fnRect->fnGetTop)();
     492             :                 }
     493             :                 else
     494             :                 {
     495           0 :                     bRet = false;
     496             :                 }
     497             :             }
     498             :             else
     499             :             {
     500             :                 // assure that text frame is in a horizontal layout
     501           0 :                 SwFrmSwapper aSwapper( pFrm, true );
     502             :                 // determine text line that contains the requested position
     503           0 :                 SwTxtSizeInfo aInf( pFrm );
     504           0 :                 SwTxtCursor aLine( pFrm, &aInf );
     505           0 :                 aLine.CharCrsrToLine( nOffset );
     506             :                 // determine top of line
     507           0 :                 _onTopOfLine = aLine.Y();
     508           0 :                 if ( bVert )
     509             :                 {
     510           0 :                     _onTopOfLine = pFrm->SwitchHorizontalToVertical( _onTopOfLine );
     511           0 :                 }
     512             :             }
     513             :         }
     514             :     }
     515             : 
     516           0 :     return bRet;
     517             : }
     518             : 
     519             : /*************************************************************************
     520             :  *                      SwTxtFrm::_GetCrsrOfst()
     521             :  *************************************************************************/
     522             : 
     523             : // Minimum distance of non-empty lines is a little less than 2 cm
     524             : #define FILL_MIN_DIST 1100
     525             : 
     526             : struct SwFillData
     527             : {
     528             :     SwRect aFrm;
     529             :     const SwCrsrMoveState *pCMS;
     530             :     SwPosition* pPos;
     531             :     const Point& rPoint;
     532             :     SwTwips nLineWidth;
     533             :     bool bFirstLine : 1;
     534             :     bool bInner     : 1;
     535             :     bool bColumn    : 1;
     536             :     bool bEmpty     : 1;
     537           0 :     SwFillData( const SwCrsrMoveState *pC, SwPosition* pP, const SwRect& rR,
     538             :         const Point& rPt ) : aFrm( rR ), pCMS( pC ), pPos( pP ), rPoint( rPt ),
     539             :         nLineWidth( 0 ), bFirstLine( true ), bInner( false ), bColumn( false ),
     540           0 :         bEmpty( true ){}
     541           0 :     SwFillMode Mode() const { return pCMS->pFill->eMode; }
     542           0 :     long X() const { return rPoint.X(); }
     543           0 :     long Y() const { return rPoint.Y(); }
     544           0 :     long Left() const { return aFrm.Left(); }
     545           0 :     long Right() const { return aFrm.Right(); }
     546           0 :     long Bottom() const { return aFrm.Bottom(); }
     547             :     SwRect& Frm() { return aFrm; }
     548           0 :     SwFillCrsrPos &Fill() const { return *pCMS->pFill; }
     549           0 :     void SetTab( MSHORT nNew ) { pCMS->pFill->nTabCnt = nNew; }
     550           0 :     void SetSpace( MSHORT nNew ) { pCMS->pFill->nSpaceCnt = nNew; }
     551           0 :     void SetOrient( const sal_Int16 eNew ){ pCMS->pFill->eOrient = eNew; }
     552             : };
     553             : 
     554           0 : bool SwTxtFrm::_GetCrsrOfst(SwPosition* pPos, const Point& rPoint,
     555             :                     const bool bChgFrm, SwCrsrMoveState* pCMS ) const
     556             : {
     557             :     // _GetCrsrOfst is called by GetCrsrOfst and GetKeyCrsrOfst.
     558             :     // Never just a return false.
     559             : 
     560           0 :     if( IsLocked() || IsHiddenNow() )
     561           0 :         return false;
     562             : 
     563           0 :     ((SwTxtFrm*)this)->GetFormatted();
     564             : 
     565           0 :     Point aOldPoint( rPoint );
     566             : 
     567           0 :     if ( IsVertical() )
     568             :     {
     569           0 :         SwitchVerticalToHorizontal( (Point&)rPoint );
     570           0 :         ((SwTxtFrm*)this)->SwapWidthAndHeight();
     571             :     }
     572             : 
     573           0 :     if ( IsRightToLeft() )
     574           0 :         SwitchRTLtoLTR( (Point&)rPoint );
     575             : 
     576           0 :     SwFillData *pFillData = ( pCMS && pCMS->pFill ) ?
     577           0 :                         new SwFillData( pCMS, pPos, Frm(), rPoint ) : NULL;
     578             : 
     579           0 :     if ( IsEmpty() )
     580             :     {
     581           0 :         SwTxtNode* pTxtNd = ((SwTxtFrm*)this)->GetTxtNode();
     582           0 :         pPos->nNode = *pTxtNd;
     583           0 :         pPos->nContent.Assign( pTxtNd, 0 );
     584           0 :         if( pCMS && pCMS->bFieldInfo )
     585             :         {
     586           0 :             SwTwips nDiff = rPoint.X() - Frm().Left() - Prt().Left();
     587           0 :             if( nDiff > 50 || nDiff < 0 )
     588           0 :                 ((SwCrsrMoveState*)pCMS)->bPosCorr = true;
     589             :         }
     590             :     }
     591             :     else
     592             :     {
     593           0 :         SwTxtSizeInfo aInf( (SwTxtFrm*)this );
     594           0 :         SwTxtCursor  aLine( ((SwTxtFrm*)this), &aInf );
     595             : 
     596             :         // See comment in AdjustFrm()
     597           0 :         SwTwips nMaxY = Frm().Top() + Prt().Top() + Prt().Height();
     598           0 :         aLine.TwipsToLine( rPoint.Y() );
     599           0 :         while( aLine.Y() + aLine.GetLineHeight() > nMaxY )
     600             :         {
     601           0 :             if( !aLine.Prev() )
     602           0 :                 break;
     603             :         }
     604             : 
     605           0 :         if( aLine.GetDropLines() >= aLine.GetLineNr() && 1 != aLine.GetLineNr()
     606           0 :             && rPoint.X() < aLine.FirstLeft() + aLine.GetDropLeft() )
     607           0 :             while( aLine.GetLineNr() > 1 )
     608           0 :                 aLine.Prev();
     609             : 
     610           0 :         sal_Int32 nOffset = aLine.GetCrsrOfst( pPos, rPoint, bChgFrm, pCMS );
     611             : 
     612           0 :         if( pCMS && pCMS->eState == MV_NONE && aLine.GetEnd() == nOffset )
     613           0 :             ((SwCrsrMoveState*)pCMS)->eState = MV_RIGHTMARGIN;
     614             : 
     615             :     // pPos is a pure IN parameter and must not be evaluated.
     616             :     // pIter->GetCrsrOfst returns from a nesting with COMPLETE_STRING.
     617             :     // If SwTxtIter::GetCrsrOfst calls GetCrsrOfst further by itself
     618             :     // nNode changes the position.
     619             :     // In such cases, pPos must not be calculated.
     620           0 :         if( COMPLETE_STRING != nOffset )
     621             :         {
     622           0 :             SwTxtNode* pTxtNd = ((SwTxtFrm*)this)->GetTxtNode();
     623           0 :             pPos->nNode = *pTxtNd;
     624           0 :             pPos->nContent.Assign( pTxtNd, nOffset );
     625           0 :             if( pFillData )
     626             :             {
     627           0 :                 if (pTxtNd->GetTxt().getLength() > nOffset ||
     628           0 :                     rPoint.Y() < Frm().Top() )
     629           0 :                     pFillData->bInner = true;
     630           0 :                 pFillData->bFirstLine = aLine.GetLineNr() < 2;
     631           0 :                 if (pTxtNd->GetTxt().getLength())
     632             :                 {
     633           0 :                     pFillData->bEmpty = false;
     634           0 :                     pFillData->nLineWidth = aLine.GetCurr()->Width();
     635             :                 }
     636             :             }
     637           0 :         }
     638             :     }
     639           0 :     bool bChgFillData = false;
     640           0 :     if( pFillData && FindPageFrm()->Frm().IsInside( aOldPoint ) )
     641             :     {
     642           0 :         FillCrsrPos( *pFillData );
     643           0 :         bChgFillData = true;
     644             :     }
     645             : 
     646           0 :     if ( IsVertical() )
     647             :     {
     648           0 :         if ( bChgFillData )
     649           0 :             SwitchHorizontalToVertical( pFillData->Fill().aCrsr.Pos() );
     650           0 :         ((SwTxtFrm*)this)->SwapWidthAndHeight();
     651             :     }
     652             : 
     653           0 :     if ( IsRightToLeft() && bChgFillData )
     654             :     {
     655           0 :             SwitchLTRtoRTL( pFillData->Fill().aCrsr.Pos() );
     656           0 :             const sal_Int16 eOrient = pFillData->pCMS->pFill->eOrient;
     657             : 
     658           0 :             if ( text::HoriOrientation::LEFT == eOrient )
     659           0 :                 pFillData->SetOrient( text::HoriOrientation::RIGHT );
     660           0 :             else if ( text::HoriOrientation::RIGHT == eOrient )
     661           0 :                 pFillData->SetOrient( text::HoriOrientation::LEFT );
     662             :     }
     663             : 
     664           0 :     (Point&)rPoint = aOldPoint;
     665           0 :     delete pFillData;
     666             : 
     667           0 :     return true;
     668             : }
     669             : 
     670             : /*************************************************************************
     671             :  *                 virtual SwTxtFrm::GetCrsrOfst()
     672             :  *************************************************************************/
     673             : 
     674           0 : bool SwTxtFrm::GetCrsrOfst(SwPosition* pPos, Point& rPoint,
     675             :                                SwCrsrMoveState* pCMS, bool ) const
     676             : {
     677           0 :     MSHORT nChgFrm = 2;
     678           0 :     if( pCMS )
     679             :     {
     680           0 :         if( MV_UPDOWN == pCMS->eState )
     681           0 :             nChgFrm = 0;
     682           0 :         else if( MV_SETONLYTEXT == pCMS->eState ||
     683           0 :                  MV_TBLSEL == pCMS->eState )
     684           0 :             nChgFrm = 1;
     685             :     }
     686           0 :     return _GetCrsrOfst( pPos, rPoint, nChgFrm != 0, pCMS );
     687             : }
     688             : 
     689             : /*************************************************************************
     690             :  *                      SwTxtFrm::LeftMargin()
     691             :  *************************************************************************/
     692             : 
     693             : /*
     694             :  * Layout-oriented cursor movement to the line start.
     695             :  */
     696             : 
     697           0 : bool SwTxtFrm::LeftMargin(SwPaM *pPam) const
     698             : {
     699           0 :     if( ((const SwNode*)pPam->GetNode()) != GetNode() )
     700           0 :         pPam->GetPoint()->nNode = *((SwTxtFrm*)this)->GetTxtNode();
     701             : 
     702           0 :     SwTxtFrm *pFrm = GetAdjFrmAtPos( (SwTxtFrm*)this, *pPam->GetPoint(),
     703           0 :                                      SwTxtCursor::IsRightMargin() );
     704           0 :     pFrm->GetFormatted();
     705             :     sal_Int32 nIndx;
     706           0 :     if ( pFrm->IsEmpty() )
     707           0 :         nIndx = 0;
     708             :     else
     709             :     {
     710           0 :         SwTxtSizeInfo aInf( pFrm );
     711           0 :         SwTxtCursor  aLine( pFrm, &aInf );
     712             : 
     713           0 :         aLine.CharCrsrToLine(pPam->GetPoint()->nContent.GetIndex());
     714           0 :         nIndx = aLine.GetStart();
     715           0 :         if( pFrm->GetOfst() && !pFrm->IsFollow() && !aLine.GetPrev() )
     716             :         {
     717           0 :             sw_ChangeOffset( pFrm, 0 );
     718           0 :             nIndx = 0;
     719           0 :         }
     720             :     }
     721           0 :     pPam->GetPoint()->nContent = SwIndex( pFrm->GetTxtNode(), nIndx );
     722           0 :     SwTxtCursor::SetRightMargin( false );
     723           0 :     return true;
     724             : }
     725             : 
     726             : /*************************************************************************
     727             :  *                      SwTxtFrm::RightMargin()
     728             :  *************************************************************************/
     729             : 
     730             : /*
     731             :  * To the line end: That's the position before the last char of the line.
     732             :  * Exception: In the last line, it should be able to place the cursor after
     733             :  * the last char in order to append text.
     734             :  */
     735             : 
     736           0 : bool SwTxtFrm::RightMargin(SwPaM *pPam, bool bAPI) const
     737             : {
     738           0 :     if( ((const SwNode*)pPam->GetNode()) != GetNode() )
     739           0 :         pPam->GetPoint()->nNode = *((SwTxtFrm*)this)->GetTxtNode();
     740             : 
     741           0 :     SwTxtFrm *pFrm = GetAdjFrmAtPos( (SwTxtFrm*)this, *pPam->GetPoint(),
     742           0 :                                      SwTxtCursor::IsRightMargin() );
     743           0 :     pFrm->GetFormatted();
     744             :     sal_Int32 nRightMargin;
     745           0 :     if ( IsEmpty() )
     746           0 :         nRightMargin = 0;
     747             :     else
     748             :     {
     749           0 :         SwTxtSizeInfo aInf( pFrm );
     750           0 :         SwTxtCursor  aLine( pFrm, &aInf );
     751             : 
     752           0 :         aLine.CharCrsrToLine(pPam->GetPoint()->nContent.GetIndex());
     753           0 :         nRightMargin = aLine.GetStart() + aLine.GetCurr()->GetLen();
     754             : 
     755             :         // We skip hard line brakes
     756           0 :         if( aLine.GetCurr()->GetLen() &&
     757           0 :             CH_BREAK == aInf.GetTxt()[nRightMargin - 1])
     758           0 :             --nRightMargin;
     759           0 :         else if( !bAPI && (aLine.GetNext() || pFrm->GetFollow()) )
     760             :         {
     761           0 :             while( nRightMargin > aLine.GetStart() &&
     762           0 :                 ' ' == aInf.GetTxt()[nRightMargin - 1])
     763           0 :                 --nRightMargin;
     764           0 :         }
     765             :     }
     766           0 :     pPam->GetPoint()->nContent = SwIndex( pFrm->GetTxtNode(), nRightMargin );
     767           0 :     SwTxtCursor::SetRightMargin( !bAPI );
     768           0 :     return true;
     769             : }
     770             : 
     771             : /*************************************************************************
     772             :  *                      SwTxtFrm::_UnitUp()
     773             :  *************************************************************************/
     774             : 
     775             : // The following two methods try to put the Crsr into the next/succsessive
     776             : // line. If we do not have a preceding/successive line we forward the call
     777             : // to the base class.
     778             : // The Crsr's horizontal justification is done afterwards by the CrsrShell.
     779             : 
     780             : class SwSetToRightMargin
     781             : {
     782             :     bool bRight;
     783             : public:
     784           0 :     inline SwSetToRightMargin() : bRight( false ) { }
     785           0 :     inline ~SwSetToRightMargin() { SwTxtCursor::SetRightMargin( bRight ); }
     786           0 :     inline void SetRight( const bool bNew ) { bRight = bNew; }
     787             : };
     788             : 
     789           0 : bool SwTxtFrm::_UnitUp( SwPaM *pPam, const SwTwips nOffset,
     790             :                         bool bSetInReadOnly ) const
     791             : {
     792             :     // Set the RightMargin if needed
     793           0 :     SwSetToRightMargin aSet;
     794             : 
     795           0 :     if( IsInTab() &&
     796           0 :         pPam->GetNode( true )->StartOfSectionNode() !=
     797           0 :         pPam->GetNode( false )->StartOfSectionNode() )
     798             :     {
     799             :         // If the PaM is located within different boxes, we have a table selection,
     800             :         // which is handled by the base class.
     801           0 :         return SwCntntFrm::UnitUp( pPam, nOffset, bSetInReadOnly );
     802             :     }
     803             : 
     804           0 :     ((SwTxtFrm*)this)->GetFormatted();
     805           0 :     const sal_Int32 nPos = pPam->GetPoint()->nContent.GetIndex();
     806           0 :     SwRect aCharBox;
     807             : 
     808           0 :     if( !IsEmpty() && !IsHiddenNow() )
     809             :     {
     810           0 :         sal_Int32 nFormat = COMPLETE_STRING;
     811             :         do
     812             :         {
     813           0 :             if( nFormat != COMPLETE_STRING && !IsFollow() )
     814           0 :                 sw_ChangeOffset( ((SwTxtFrm*)this), nFormat );
     815             : 
     816           0 :             SwTxtSizeInfo aInf( (SwTxtFrm*)this );
     817           0 :             SwTxtCursor  aLine( ((SwTxtFrm*)this), &aInf );
     818             : 
     819             :             // Optimize away flys with no flow and IsDummy()
     820           0 :             if( nPos )
     821           0 :                 aLine.CharCrsrToLine( nPos );
     822             :             else
     823           0 :                 aLine.Top();
     824             : 
     825           0 :             const SwLineLayout *pPrevLine = aLine.GetPrevLine();
     826           0 :             const sal_Int32 nStart = aLine.GetStart();
     827           0 :             aLine.GetCharRect( &aCharBox, nPos );
     828             : 
     829           0 :             bool bSecondOfDouble = ( aInf.IsMulti() && ! aInf.IsFirstMulti() );
     830           0 :             bool bPrevLine = ( pPrevLine && pPrevLine != aLine.GetCurr() );
     831             : 
     832           0 :             if( !pPrevLine && !bSecondOfDouble && GetOfst() && !IsFollow() )
     833             :             {
     834           0 :                 nFormat = GetOfst();
     835           0 :                 sal_Int32 nDiff = aLine.GetLength();
     836           0 :                 if( !nDiff )
     837           0 :                     nDiff = MIN_OFFSET_STEP;
     838           0 :                 if( nFormat > nDiff )
     839           0 :                     nFormat = nFormat - nDiff;
     840             :                 else
     841           0 :                     nFormat = 0;
     842           0 :                 continue;
     843             :             }
     844             : 
     845             :             // We select the target line for the cursor, in case we are in a
     846             :             // double line portion, prev line = curr line
     847           0 :             if( bPrevLine && !bSecondOfDouble )
     848             :             {
     849           0 :                 aLine.PrevLine();
     850           0 :                 while ( aLine.GetStart() == nStart &&
     851           0 :                         0 != ( pPrevLine = aLine.GetPrevLine() ) &&
     852           0 :                         pPrevLine != aLine.GetCurr() )
     853           0 :                     aLine.PrevLine();
     854             :             }
     855             : 
     856           0 :             if ( bPrevLine || bSecondOfDouble )
     857             :             {
     858           0 :                 aCharBox.SSize().Width() /= 2;
     859           0 :                 aCharBox.Pos().X() = aCharBox.Pos().X() - 150;
     860             : 
     861             :                 // See comment in SwTxtFrm::GetCrsrOfst()
     862             : #if OSL_DEBUG_LEVEL > 0
     863             :                 const sal_uLong nOldNode = pPam->GetPoint()->nNode.GetIndex();
     864             : #endif
     865             :                 // The node should not be changed
     866             :                 sal_Int32 nTmpOfst = aLine.GetCrsrOfst( pPam->GetPoint(),
     867           0 :                                                          aCharBox.Pos(), false );
     868             : #if OSL_DEBUG_LEVEL > 0
     869             :                 OSL_ENSURE( nOldNode == pPam->GetPoint()->nNode.GetIndex(),
     870             :                         "SwTxtFrm::UnitUp: illegal node change" );
     871             : #endif
     872             : 
     873             :                 // We make sure that we move up.
     874           0 :                 if( nTmpOfst >= nStart && nStart && !bSecondOfDouble )
     875             :                 {
     876           0 :                     nTmpOfst = nStart;
     877           0 :                     aSet.SetRight( true );
     878             :                 }
     879           0 :                 pPam->GetPoint()->nContent =
     880           0 :                       SwIndex( ((SwTxtFrm*)this)->GetTxtNode(), nTmpOfst );
     881           0 :                 return true;
     882             :             }
     883             : 
     884           0 :             if ( IsFollow() )
     885             :             {
     886           0 :                 aLine.GetCharRect( &aCharBox, nPos );
     887           0 :                 aCharBox.SSize().Width() /= 2;
     888             :             }
     889           0 :             break;
     890           0 :         } while ( true );
     891             :     }
     892             :     /* If 'this' is a follow and a prev failed, we need to go to the
     893             :      * last line of the master, which is us.
     894             :      * Or: If we are a follow with follow, we need to get the master.
     895             :      */
     896           0 :     if ( IsFollow() )
     897             :     {
     898           0 :         const SwTxtFrm *pTmpPrev = FindMaster();
     899           0 :         sal_Int32 nOffs = GetOfst();
     900           0 :         if( pTmpPrev )
     901             :         {
     902           0 :             SwViewShell *pSh = getRootFrm()->GetCurrShell();
     903           0 :             const bool bProtectedAllowed = pSh && pSh->GetViewOptions()->IsCursorInProtectedArea();
     904           0 :             const SwTxtFrm *pPrevPrev = pTmpPrev;
     905             :             // We skip protected frames and frames without content here
     906           0 :             while( pPrevPrev && ( pPrevPrev->GetOfst() == nOffs ||
     907           0 :                    ( !bProtectedAllowed && pPrevPrev->IsProtected() ) ) )
     908             :             {
     909           0 :                 pTmpPrev = pPrevPrev;
     910           0 :                 nOffs = pTmpPrev->GetOfst();
     911           0 :                 if ( pPrevPrev->IsFollow() )
     912           0 :                     pPrevPrev = pTmpPrev->FindMaster();
     913             :                 else
     914           0 :                     pPrevPrev = NULL;
     915             :             }
     916           0 :             if ( !pPrevPrev )
     917           0 :                 return pTmpPrev->SwCntntFrm::UnitUp( pPam, nOffset, bSetInReadOnly );
     918           0 :             aCharBox.Pos().Y() = pPrevPrev->Frm().Bottom() - 1;
     919           0 :             return pPrevPrev->GetKeyCrsrOfst( pPam->GetPoint(), aCharBox.Pos() );
     920             :         }
     921             :     }
     922           0 :     return SwCntntFrm::UnitUp( pPam, nOffset, bSetInReadOnly );
     923             : }
     924             : 
     925             : // Used for Bidi. nPos is the logical position in the string, bLeft indicates
     926             : // if left arrow or right arrow was pressed. The return values are:
     927             : // nPos: the new visual position
     928             : // bLeft: whether the break iterator has to add or subtract from the
     929             : //        current position
     930           0 : static void lcl_VisualMoveRecursion( const SwLineLayout& rCurrLine, sal_Int32 nIdx,
     931             :                               sal_Int32& nPos, bool& bRight,
     932             :                               sal_uInt8& nCrsrLevel, sal_uInt8 nDefaultDir )
     933             : {
     934           0 :     const SwLinePortion* pPor = rCurrLine.GetFirstPortion();
     935           0 :     const SwLinePortion* pLast = 0;
     936             : 
     937             :     // What's the current portion?
     938           0 :     while ( pPor && nIdx + pPor->GetLen() <= nPos )
     939             :     {
     940           0 :         nIdx = nIdx + pPor->GetLen();
     941           0 :         pLast = pPor;
     942           0 :         pPor = pPor->GetPortion();
     943             :     }
     944             : 
     945           0 :     if ( bRight )
     946             :     {
     947           0 :         bool bRecurse = pPor && pPor->IsMultiPortion() &&
     948           0 :                            ((SwMultiPortion*)pPor)->IsBidi();
     949             : 
     950             :         // 1. special case: at beginning of bidi portion
     951           0 :         if ( bRecurse && nIdx == nPos )
     952             :         {
     953           0 :             nPos = nPos + pPor->GetLen();
     954             : 
     955             :             // leave bidi portion
     956           0 :             if ( nCrsrLevel != nDefaultDir )
     957             :             {
     958           0 :                 bRecurse = false;
     959             :             }
     960             :             else
     961             :                 // special case:
     962             :                 // buffer: abcXYZ123 in LTR paragraph
     963             :                 // view:   abc123ZYX
     964             :                 // cursor is between c and X in the buffer and cursor level = 0
     965           0 :                 nCrsrLevel++;
     966             :         }
     967             : 
     968             :         // 2. special case: at beginning of portion after bidi portion
     969           0 :         else if ( pLast && pLast->IsMultiPortion() &&
     970           0 :                  ((SwMultiPortion*)pLast)->IsBidi() && nIdx == nPos )
     971             :         {
     972             :             // enter bidi portion
     973           0 :             if ( nCrsrLevel != nDefaultDir )
     974             :             {
     975           0 :                 bRecurse = true;
     976           0 :                 nIdx = nIdx - pLast->GetLen();
     977           0 :                 pPor = pLast;
     978             :             }
     979             :         }
     980             : 
     981             :         // Recursion
     982           0 :         if ( bRecurse )
     983             :         {
     984           0 :             const SwLineLayout& rLine = ((SwMultiPortion*)pPor)->GetRoot();
     985           0 :             sal_Int32 nTmpPos = nPos - nIdx;
     986           0 :             bool bTmpForward = ! bRight;
     987           0 :             sal_uInt8 nTmpCrsrLevel = nCrsrLevel;
     988             :             lcl_VisualMoveRecursion( rLine, 0, nTmpPos, bTmpForward,
     989           0 :                                      nTmpCrsrLevel, nDefaultDir + 1 );
     990             : 
     991           0 :             nPos = nTmpPos + nIdx;
     992           0 :             bRight = bTmpForward;
     993           0 :             nCrsrLevel = nTmpCrsrLevel;
     994             :         }
     995             : 
     996             :         // go forward
     997             :         else
     998             :         {
     999           0 :             bRight = true;
    1000           0 :             nCrsrLevel = nDefaultDir;
    1001             :         }
    1002             : 
    1003             :     }
    1004             :     else
    1005             :     {
    1006           0 :         bool bRecurse = pPor && pPor->IsMultiPortion() && ((SwMultiPortion*)pPor)->IsBidi();
    1007             : 
    1008             :         // 1. special case: at beginning of bidi portion
    1009           0 :         if ( bRecurse && nIdx == nPos )
    1010             :         {
    1011             :             // leave bidi portion
    1012           0 :             if ( nCrsrLevel == nDefaultDir )
    1013             :             {
    1014           0 :                 bRecurse = false;
    1015             :             }
    1016             :         }
    1017             : 
    1018             :         // 2. special case: at beginning of portion after bidi portion
    1019           0 :         else if ( pLast && pLast->IsMultiPortion() &&
    1020           0 :                  ((SwMultiPortion*)pLast)->IsBidi() && nIdx == nPos )
    1021             :         {
    1022           0 :             nPos = nPos - pLast->GetLen();
    1023             : 
    1024             :             // enter bidi portion
    1025           0 :             if ( nCrsrLevel % 2 == nDefaultDir % 2 )
    1026             :             {
    1027           0 :                 bRecurse = true;
    1028           0 :                 nIdx = nIdx - pLast->GetLen();
    1029           0 :                 pPor = pLast;
    1030             : 
    1031             :                 // special case:
    1032             :                 // buffer: abcXYZ123 in LTR paragraph
    1033             :                 // view:   abc123ZYX
    1034             :                 // cursor is behind 3 in the buffer and cursor level = 2
    1035           0 :                 if ( nDefaultDir + 2 == nCrsrLevel )
    1036           0 :                     nPos = nPos + pLast->GetLen();
    1037             :             }
    1038             :         }
    1039             : 
    1040             :         // go forward
    1041           0 :         if ( bRecurse )
    1042             :         {
    1043           0 :             const SwLineLayout& rLine = ((SwMultiPortion*)pPor)->GetRoot();
    1044           0 :             sal_Int32 nTmpPos = nPos - nIdx;
    1045           0 :             bool bTmpForward = ! bRight;
    1046           0 :             sal_uInt8 nTmpCrsrLevel = nCrsrLevel;
    1047             :             lcl_VisualMoveRecursion( rLine, 0, nTmpPos, bTmpForward,
    1048           0 :                                      nTmpCrsrLevel, nDefaultDir + 1 );
    1049             : 
    1050             :             // special case:
    1051             :             // buffer: abcXYZ123 in LTR paragraph
    1052             :             // view:   abc123ZYX
    1053             :             // cursor is between Z and 1 in the buffer and cursor level = 2
    1054           0 :             if ( nTmpPos == pPor->GetLen() && nTmpCrsrLevel == nDefaultDir + 1 )
    1055             :             {
    1056           0 :                 nTmpPos = nTmpPos - pPor->GetLen();
    1057           0 :                 nTmpCrsrLevel = nDefaultDir;
    1058           0 :                 bTmpForward = ! bTmpForward;
    1059             :             }
    1060             : 
    1061           0 :             nPos = nTmpPos + nIdx;
    1062           0 :             bRight = bTmpForward;
    1063           0 :             nCrsrLevel = nTmpCrsrLevel;
    1064             :         }
    1065             : 
    1066             :         // go backward
    1067             :         else
    1068             :         {
    1069           0 :             bRight = false;
    1070           0 :             nCrsrLevel = nDefaultDir;
    1071             :         }
    1072             :     }
    1073           0 : }
    1074             : 
    1075           0 : void SwTxtFrm::PrepareVisualMove( sal_Int32& nPos, sal_uInt8& nCrsrLevel,
    1076             :                                   bool& bForward, bool bInsertCrsr )
    1077             : {
    1078           0 :     if( IsEmpty() || IsHiddenNow() )
    1079           0 :         return;
    1080             : 
    1081           0 :     ((SwTxtFrm*)this)->GetFormatted();
    1082             : 
    1083           0 :     SwTxtSizeInfo aInf( (SwTxtFrm*)this );
    1084           0 :     SwTxtCursor  aLine( ((SwTxtFrm*)this), &aInf );
    1085             : 
    1086           0 :     if( nPos )
    1087           0 :         aLine.CharCrsrToLine( nPos );
    1088             :     else
    1089           0 :         aLine.Top();
    1090             : 
    1091           0 :     const SwLineLayout* pLine = aLine.GetCurr();
    1092           0 :     const sal_Int32 nStt = aLine.GetStart();
    1093           0 :     const sal_Int32 nLen = pLine->GetLen();
    1094             : 
    1095             :     // We have to distinguish between an insert and overwrite cursor:
    1096             :     // The insert cursor position depends on the cursor level:
    1097             :     // buffer:  abcXYZdef in LTR paragraph
    1098             :     // display: abcZYXdef
    1099             :     // If cursor is between c and X in the buffer and cursor level is 0,
    1100             :     // the cursor blinks between c and Z and -> sets the cursor between Z and Y.
    1101             :     // If the cursor level is 1, the cursor blinks between X and d and
    1102             :     // -> sets the cursor between d and e.
    1103             :     // The overwrite cursor simply travels to the next visual character.
    1104           0 :     if ( bInsertCrsr )
    1105             :     {
    1106             :         lcl_VisualMoveRecursion( *pLine, nStt, nPos, bForward,
    1107           0 :                                  nCrsrLevel, IsRightToLeft() ? 1 : 0 );
    1108           0 :         return;
    1109             :     }
    1110             : 
    1111           0 :     const sal_uInt8 nDefaultDir = static_cast<sal_uInt8>(IsRightToLeft() ? UBIDI_RTL : UBIDI_LTR);
    1112           0 :     const bool bVisualRight = ( nDefaultDir == UBIDI_LTR && bForward ) ||
    1113           0 :                                   ( nDefaultDir == UBIDI_RTL && ! bForward );
    1114             : 
    1115             :     // Bidi functions from icu 2.0
    1116             : 
    1117           0 :     const sal_Unicode* pLineString = GetTxtNode()->GetTxt().getStr();
    1118             : 
    1119           0 :     UErrorCode nError = U_ZERO_ERROR;
    1120           0 :     UBiDi* pBidi = ubidi_openSized( nLen, 0, &nError );
    1121           0 :     ubidi_setPara( pBidi, reinterpret_cast<const UChar *>(pLineString), nLen, nDefaultDir, NULL, &nError ); // UChar != sal_Unicode in MinGW
    1122             : 
    1123           0 :     sal_Int32 nTmpPos = 0;
    1124           0 :     bool bOutOfBounds = false;
    1125             : 
    1126           0 :     if ( nPos < nStt + nLen )
    1127             :     {
    1128           0 :         nTmpPos = ubidi_getVisualIndex( pBidi, nPos, &nError );
    1129             : 
    1130             :         // visual indices are always LTR aligned
    1131           0 :         if ( bVisualRight )
    1132             :         {
    1133           0 :             if ( nTmpPos + 1 < nStt + nLen )
    1134           0 :                 ++nTmpPos;
    1135             :             else
    1136             :             {
    1137           0 :                 nPos = nDefaultDir == UBIDI_RTL ? 0 : nStt + nLen;
    1138           0 :                 bOutOfBounds = true;
    1139             :             }
    1140             :         }
    1141             :         else
    1142             :         {
    1143           0 :             if ( nTmpPos )
    1144           0 :                 --nTmpPos;
    1145             :             else
    1146             :             {
    1147           0 :                 nPos = nDefaultDir == UBIDI_RTL ? nStt + nLen : 0;
    1148           0 :                 bOutOfBounds = true;
    1149             :             }
    1150             :         }
    1151             :     }
    1152             :     else
    1153             :     {
    1154           0 :         nTmpPos = nDefaultDir == UBIDI_LTR ? nPos - 1 : 0;
    1155             :     }
    1156             : 
    1157           0 :     if ( ! bOutOfBounds )
    1158             :     {
    1159           0 :         nPos = ubidi_getLogicalIndex( pBidi, nTmpPos, &nError );
    1160             : 
    1161           0 :         if ( bForward )
    1162             :         {
    1163           0 :             if ( nPos )
    1164           0 :                 --nPos;
    1165             :             else
    1166             :             {
    1167           0 :                 ++nPos;
    1168           0 :                 bForward = ! bForward;
    1169             :             }
    1170             :         }
    1171             :         else
    1172           0 :             ++nPos;
    1173             :     }
    1174             : 
    1175           0 :     ubidi_close( pBidi );
    1176             : }
    1177             : 
    1178             : /*************************************************************************
    1179             :  *                      SwTxtFrm::_UnitDown()
    1180             :  *************************************************************************/
    1181             : 
    1182           0 : bool SwTxtFrm::_UnitDown(SwPaM *pPam, const SwTwips nOffset,
    1183             :                          bool bSetInReadOnly ) const
    1184             : {
    1185             : 
    1186           0 :     if ( IsInTab() &&
    1187           0 :         pPam->GetNode( true )->StartOfSectionNode() !=
    1188           0 :         pPam->GetNode( false )->StartOfSectionNode() )
    1189             :     {
    1190             :         // If the PaM is located within different boxes, we have a table selection,
    1191             :         // which is handled by the base class.
    1192           0 :         return SwCntntFrm::UnitDown( pPam, nOffset, bSetInReadOnly );
    1193             :     }
    1194           0 :     ((SwTxtFrm*)this)->GetFormatted();
    1195           0 :     const sal_Int32 nPos = pPam->GetPoint()->nContent.GetIndex();
    1196           0 :     SwRect aCharBox;
    1197           0 :     const SwCntntFrm *pTmpFollow = 0;
    1198             : 
    1199           0 :     if ( IsVertical() )
    1200           0 :         ((SwTxtFrm*)this)->SwapWidthAndHeight();
    1201             : 
    1202           0 :     if ( !IsEmpty() && !IsHiddenNow() )
    1203             :     {
    1204           0 :         sal_Int32 nFormat = COMPLETE_STRING;
    1205             :         do
    1206             :         {
    1207           0 :             if( nFormat != COMPLETE_STRING && !IsFollow() &&
    1208           0 :                 !sw_ChangeOffset( ((SwTxtFrm*)this), nFormat ) )
    1209           0 :                 break;
    1210             : 
    1211           0 :             SwTxtSizeInfo aInf( (SwTxtFrm*)this );
    1212           0 :             SwTxtCursor  aLine( ((SwTxtFrm*)this), &aInf );
    1213           0 :             nFormat = aLine.GetEnd();
    1214             : 
    1215           0 :             aLine.CharCrsrToLine( nPos );
    1216             : 
    1217           0 :             const SwLineLayout* pNextLine = aLine.GetNextLine();
    1218           0 :             const sal_Int32 nStart = aLine.GetStart();
    1219           0 :             aLine.GetCharRect( &aCharBox, nPos );
    1220             : 
    1221           0 :             bool bFirstOfDouble = ( aInf.IsMulti() && aInf.IsFirstMulti() );
    1222             : 
    1223           0 :             if( pNextLine || bFirstOfDouble )
    1224             :             {
    1225           0 :                 aCharBox.SSize().Width() /= 2;
    1226             : #if OSL_DEBUG_LEVEL > 0
    1227             :                 // See comment in SwTxtFrm::GetCrsrOfst()
    1228             :                 const sal_uLong nOldNode = pPam->GetPoint()->nNode.GetIndex();
    1229             : #endif
    1230           0 :                 if ( pNextLine && ! bFirstOfDouble )
    1231           0 :                     aLine.NextLine();
    1232             : 
    1233             :                 sal_Int32 nTmpOfst = aLine.GetCrsrOfst( pPam->GetPoint(),
    1234           0 :                                  aCharBox.Pos(), false );
    1235             : #if OSL_DEBUG_LEVEL > 0
    1236             :                 OSL_ENSURE( nOldNode == pPam->GetPoint()->nNode.GetIndex(),
    1237             :                     "SwTxtFrm::UnitDown: illegal node change" );
    1238             : #endif
    1239             : 
    1240             :                 // We make sure that we move down.
    1241           0 :                 if( nTmpOfst <= nStart && ! bFirstOfDouble )
    1242           0 :                     nTmpOfst = nStart + 1;
    1243           0 :                 pPam->GetPoint()->nContent =
    1244           0 :                       SwIndex( ((SwTxtFrm*)this)->GetTxtNode(), nTmpOfst );
    1245             : 
    1246           0 :                 if ( IsVertical() )
    1247           0 :                     ((SwTxtFrm*)this)->SwapWidthAndHeight();
    1248             : 
    1249           0 :                 return true;
    1250             :             }
    1251           0 :             if( 0 != ( pTmpFollow = GetFollow() ) )
    1252             :             {   // Skip protected follows
    1253           0 :                 const SwCntntFrm* pTmp = pTmpFollow;
    1254           0 :                 SwViewShell *pSh = getRootFrm()->GetCurrShell();
    1255           0 :                 if( !pSh || !pSh->GetViewOptions()->IsCursorInProtectedArea() )
    1256             :                 {
    1257           0 :                     while( pTmpFollow && pTmpFollow->IsProtected() )
    1258             :                     {
    1259           0 :                         pTmp = pTmpFollow;
    1260           0 :                         pTmpFollow = pTmpFollow->GetFollow();
    1261             :                     }
    1262             :                 }
    1263           0 :                 if( !pTmpFollow ) // Only protected ones left
    1264             :                 {
    1265           0 :                     if ( IsVertical() )
    1266           0 :                         ((SwTxtFrm*)this)->SwapWidthAndHeight();
    1267           0 :                     return pTmp->SwCntntFrm::UnitDown( pPam, nOffset, bSetInReadOnly );
    1268             :                 }
    1269             : 
    1270           0 :                 aLine.GetCharRect( &aCharBox, nPos );
    1271           0 :                 aCharBox.SSize().Width() /= 2;
    1272             :             }
    1273           0 :             else if( !IsFollow() )
    1274             :             {
    1275           0 :                 sal_Int32 nTmpLen = aInf.GetTxt().getLength();
    1276           0 :                 if( aLine.GetEnd() < nTmpLen )
    1277             :                 {
    1278           0 :                     if( nFormat <= GetOfst() )
    1279             :                     {
    1280           0 :                         nFormat = std::min( sal_Int32( GetOfst() + MIN_OFFSET_STEP ),
    1281           0 :                                        static_cast<sal_Int32>(nTmpLen) );
    1282           0 :                         if( nFormat <= GetOfst() )
    1283           0 :                             break;
    1284             :                     }
    1285           0 :                     continue;
    1286             :                 }
    1287             :             }
    1288           0 :             break;
    1289           0 :         } while( true );
    1290             :     }
    1291             :     else
    1292           0 :         pTmpFollow = GetFollow();
    1293             : 
    1294           0 :     if ( IsVertical() )
    1295           0 :         ((SwTxtFrm*)this)->SwapWidthAndHeight();
    1296             : 
    1297             :     // We take a shortcut for follows
    1298           0 :     if( pTmpFollow )
    1299             :     {
    1300           0 :         aCharBox.Pos().Y() = pTmpFollow->Frm().Top() + 1;
    1301             :         return ((SwTxtFrm*)pTmpFollow)->GetKeyCrsrOfst( pPam->GetPoint(),
    1302           0 :                                                      aCharBox.Pos() );
    1303             :     }
    1304           0 :     return SwCntntFrm::UnitDown( pPam, nOffset, bSetInReadOnly );
    1305             : }
    1306             : 
    1307             : /*************************************************************************
    1308             :  *                   virtual SwTxtFrm::UnitUp()
    1309             :  *************************************************************************/
    1310             : 
    1311           0 : bool SwTxtFrm::UnitUp(SwPaM *pPam, const SwTwips nOffset,
    1312             :                       bool bSetInReadOnly ) const
    1313             : {
    1314             :     /* We call CntntNode::GertFrm() in CrsrSh::Up().
    1315             :      * This _always returns the master.
    1316             :      * In order to not mess with cursor travelling, we correct here
    1317             :      * in SwTxtFrm.
    1318             :      * We calculate UnitUp for pFrm. pFrm is either a master (= this) or a
    1319             :      * follow (!= this).
    1320             :      */
    1321           0 :     const SwTxtFrm *pFrm = GetAdjFrmAtPos( (SwTxtFrm*)this, *(pPam->GetPoint()),
    1322           0 :                                            SwTxtCursor::IsRightMargin() );
    1323           0 :     const bool bRet = pFrm->_UnitUp( pPam, nOffset, bSetInReadOnly );
    1324             : 
    1325             :     // No SwTxtCursor::SetRightMargin( false );
    1326             :     // Instead we have a SwSetToRightMargin in _UnitUp
    1327           0 :     return bRet;
    1328             : }
    1329             : 
    1330             : /*************************************************************************
    1331             :  *                   virtual SwTxtFrm::UnitDown()
    1332             :  *************************************************************************/
    1333             : 
    1334           0 : bool SwTxtFrm::UnitDown(SwPaM *pPam, const SwTwips nOffset,
    1335             :                         bool bSetInReadOnly ) const
    1336             : {
    1337           0 :     const SwTxtFrm *pFrm = GetAdjFrmAtPos((SwTxtFrm*)this, *(pPam->GetPoint()),
    1338           0 :                                            SwTxtCursor::IsRightMargin() );
    1339           0 :     const bool bRet = pFrm->_UnitDown( pPam, nOffset, bSetInReadOnly );
    1340           0 :     SwTxtCursor::SetRightMargin( false );
    1341           0 :     return bRet;
    1342             : }
    1343             : 
    1344           0 : void SwTxtFrm::FillCrsrPos( SwFillData& rFill ) const
    1345             : {
    1346           0 :     if( !rFill.bColumn && GetUpper()->IsColBodyFrm() ) // ColumnFrms now with BodyFrm
    1347             :     {
    1348             :         const SwColumnFrm* pTmp =
    1349           0 :             (SwColumnFrm*)GetUpper()->GetUpper()->GetUpper()->Lower(); // The 1st column
    1350             :         // The first SwFrm in BodyFrm of the first column
    1351           0 :         const SwFrm* pFrm = ((SwLayoutFrm*)pTmp->Lower())->Lower();
    1352           0 :         MSHORT nNextCol = 0;
    1353             :         // In which column do we end up in?
    1354           0 :         while( rFill.X() > pTmp->Frm().Right() && pTmp->GetNext() )
    1355             :         {
    1356           0 :             pTmp = (SwColumnFrm*)pTmp->GetNext();
    1357           0 :             if( ((SwLayoutFrm*)pTmp->Lower())->Lower() ) // ColumnFrms now with BodyFrm
    1358             :             {
    1359           0 :                 pFrm = ((SwLayoutFrm*)pTmp->Lower())->Lower();
    1360           0 :                 nNextCol = 0;
    1361             :             }
    1362             :             else
    1363           0 :                 ++nNextCol; // Empty columns require column brakes
    1364             :         }
    1365           0 :         if( pTmp != GetUpper()->GetUpper() ) // Did we end up in another column?
    1366             :         {
    1367           0 :             if( !pFrm )
    1368           0 :                 return;
    1369           0 :             if( nNextCol )
    1370             :             {
    1371           0 :                 while( pFrm->GetNext() )
    1372           0 :                     pFrm = pFrm->GetNext();
    1373             :             }
    1374             :             else
    1375             :             {
    1376           0 :                 while( pFrm->GetNext() && pFrm->Frm().Bottom() < rFill.Y() )
    1377           0 :                     pFrm = pFrm->GetNext();
    1378             :             }
    1379             :             // No filling, if the last frame in the targeted column does
    1380             :             // not contain a paragraph, but e.g. a table
    1381           0 :             if( pFrm->IsTxtFrm() )
    1382             :             {
    1383           0 :                 rFill.Fill().nColumnCnt = nNextCol;
    1384           0 :                 rFill.bColumn = true;
    1385           0 :                 if( rFill.pPos )
    1386             :                 {
    1387           0 :                     SwTxtNode* pTxtNd = ((SwTxtFrm*)pFrm)->GetTxtNode();
    1388           0 :                     rFill.pPos->nNode = *pTxtNd;
    1389             :                     rFill.pPos->nContent.Assign(
    1390           0 :                             pTxtNd, pTxtNd->GetTxt().getLength());
    1391             :                 }
    1392           0 :                 if( nNextCol )
    1393             :                 {
    1394           0 :                     rFill.aFrm = pTmp->Prt();
    1395           0 :                     rFill.aFrm += pTmp->Frm().Pos();
    1396             :                 }
    1397             :                 else
    1398           0 :                     rFill.aFrm = pFrm->Frm();
    1399           0 :                 ((SwTxtFrm*)pFrm)->FillCrsrPos( rFill );
    1400             :             }
    1401           0 :             return;
    1402             :         }
    1403             :     }
    1404             :     SwFont *pFnt;
    1405           0 :     SwTxtFmtColl* pColl = GetTxtNode()->GetTxtColl();
    1406           0 :     MSHORT nFirst = GetTxtNode()->GetSwAttrSet().GetULSpace().GetLower();
    1407           0 :     SwTwips nDiff = rFill.Y() - Frm().Bottom();
    1408           0 :     if( nDiff < nFirst )
    1409           0 :         nDiff = -1;
    1410             :     else
    1411           0 :         pColl = &pColl->GetNextTxtFmtColl();
    1412           0 :     SwAttrSet aSet( ((SwDoc*)GetTxtNode()->GetDoc())->GetAttrPool(), aTxtFmtCollSetRange );
    1413           0 :     const SwAttrSet* pSet = &pColl->GetAttrSet();
    1414           0 :     SwViewShell *pSh = getRootFrm()->GetCurrShell();
    1415           0 :     if( GetTxtNode()->HasSwAttrSet() )
    1416             :     {
    1417           0 :         aSet.Put( *GetTxtNode()->GetpSwAttrSet() );
    1418           0 :         aSet.SetParent( pSet );
    1419           0 :         pSet = &aSet;
    1420           0 :         pFnt = new SwFont( pSet, GetNode()->getIDocumentSettingAccess() );
    1421             :     }
    1422             :     else
    1423             :     {
    1424           0 :         SwFontAccess aFontAccess( pColl, pSh );
    1425           0 :         pFnt = new SwFont( *aFontAccess.Get()->GetFont() );
    1426           0 :         pFnt->ChkMagic( pSh, pFnt->GetActual() );
    1427             :     }
    1428           0 :     OutputDevice* pOut = pSh->GetOut();
    1429           0 :     if( !pSh->GetViewOptions()->getBrowseMode() || pSh->GetViewOptions()->IsPrtFormat() )
    1430           0 :         pOut = GetTxtNode()->getIDocumentDeviceAccess()->getReferenceDevice( true );
    1431             : 
    1432           0 :     pFnt->SetFntChg( true );
    1433           0 :     pFnt->ChgPhysFnt( pSh, *pOut );
    1434             : 
    1435           0 :     SwTwips nLineHeight = pFnt->GetHeight( pSh, *pOut );
    1436             : 
    1437           0 :     bool bFill = false;
    1438           0 :     if( nLineHeight )
    1439             :     {
    1440           0 :         bFill = true;
    1441           0 :         const SvxULSpaceItem &rUL = pSet->GetULSpace();
    1442           0 :         SwTwips nDist = std::max( rUL.GetLower(), rUL.GetUpper() );
    1443           0 :         if( rFill.Fill().nColumnCnt )
    1444             :         {
    1445           0 :             rFill.aFrm.Height( nLineHeight );
    1446           0 :             nDiff = rFill.Y() - rFill.Bottom();
    1447           0 :             nFirst = 0;
    1448             :         }
    1449           0 :         else if( nDist < nFirst )
    1450           0 :             nFirst = nFirst - (sal_uInt16)nDist;
    1451             :         else
    1452           0 :             nFirst = 0;
    1453           0 :         nDist = std::max( nDist, long( GetLineSpace() ) );
    1454           0 :         nDist += nLineHeight;
    1455           0 :         nDiff -= nFirst;
    1456             : 
    1457           0 :         if( nDiff > 0 )
    1458             :         {
    1459           0 :             nDiff /= nDist;
    1460           0 :             rFill.Fill().nParaCnt = static_cast<sal_uInt16>(nDiff + 1);
    1461           0 :             rFill.nLineWidth = 0;
    1462           0 :             rFill.bInner = false;
    1463           0 :             rFill.bEmpty = true;
    1464           0 :             rFill.SetOrient( text::HoriOrientation::LEFT );
    1465             :         }
    1466             :         else
    1467           0 :             nDiff = -1;
    1468           0 :         if( rFill.bInner )
    1469           0 :             bFill = false;
    1470             :         else
    1471             :         {
    1472           0 :             const SvxTabStopItem &rRuler = pSet->GetTabStops();
    1473           0 :             const SvxLRSpaceItem &rLRSpace = pSet->GetLRSpace();
    1474             : 
    1475           0 :             SwRect &rRect = rFill.Fill().aCrsr;
    1476           0 :             rRect.Top( rFill.Bottom() + (nDiff+1) * nDist - nLineHeight );
    1477           0 :             if( nFirst && nDiff > -1 )
    1478           0 :                 rRect.Top( rRect.Top() + nFirst );
    1479           0 :             rRect.Height( nLineHeight );
    1480           0 :             SwTwips nLeft = rFill.Left() + rLRSpace.GetLeft() +
    1481           0 :                             GetTxtNode()->GetLeftMarginWithNum();
    1482           0 :             SwTwips nRight = rFill.Right() - rLRSpace.GetRight();
    1483           0 :             SwTwips nCenter = ( nLeft + nRight ) / 2;
    1484           0 :             rRect.Left( nLeft );
    1485           0 :             if( FILL_MARGIN == rFill.Mode() )
    1486             :             {
    1487           0 :                 if( rFill.bEmpty )
    1488             :                 {
    1489           0 :                     rFill.SetOrient( text::HoriOrientation::LEFT );
    1490           0 :                     if( rFill.X() < nCenter )
    1491             :                     {
    1492           0 :                         if( rFill.X() > ( nLeft + 2 * nCenter ) / 3 )
    1493             :                         {
    1494           0 :                             rFill.SetOrient( text::HoriOrientation::CENTER );
    1495           0 :                             rRect.Left( nCenter );
    1496             :                         }
    1497             :                     }
    1498           0 :                     else if( rFill.X() > ( nRight + 2 * nCenter ) / 3 )
    1499             :                     {
    1500           0 :                         rFill.SetOrient( text::HoriOrientation::RIGHT );
    1501           0 :                         rRect.Left( nRight );
    1502             :                     }
    1503             :                     else
    1504             :                     {
    1505           0 :                         rFill.SetOrient( text::HoriOrientation::CENTER );
    1506           0 :                         rRect.Left( nCenter );
    1507             :                     }
    1508             :                 }
    1509             :                 else
    1510           0 :                     bFill = false;
    1511             :             }
    1512             :             else
    1513             :             {
    1514           0 :                 SwTwips nSpace = 0;
    1515           0 :                 if( FILL_TAB != rFill.Mode() )
    1516             :                 {
    1517           0 :                     const OUString aTmp("  ");
    1518           0 :                     SwDrawTextInfo aDrawInf( pSh, *pOut, 0, aTmp, 0, 2 );
    1519           0 :                     nSpace = pFnt->_GetTxtSize( aDrawInf ).Width()/2;
    1520             :                 }
    1521           0 :                 if( rFill.X() >= nRight )
    1522             :                 {
    1523           0 :                     if( FILL_INDENT != rFill.Mode() && ( rFill.bEmpty ||
    1524           0 :                         rFill.X() > rFill.nLineWidth + FILL_MIN_DIST ) )
    1525             :                     {
    1526           0 :                         rFill.SetOrient( text::HoriOrientation::RIGHT );
    1527           0 :                         rRect.Left( nRight );
    1528             :                     }
    1529             :                     else
    1530           0 :                         bFill = false;
    1531             :                 }
    1532           0 :                 else if( FILL_INDENT == rFill.Mode() )
    1533             :                 {
    1534           0 :                     SwTwips nIndent = rFill.X();
    1535           0 :                     if( !rFill.bEmpty || nIndent > nRight )
    1536           0 :                         bFill = false;
    1537             :                     else
    1538             :                     {
    1539           0 :                         nIndent -= rFill.Left();
    1540           0 :                         if( nIndent >= 0 && nSpace )
    1541             :                         {
    1542           0 :                             nIndent /= nSpace;
    1543           0 :                             nIndent *= nSpace;
    1544           0 :                             rFill.SetTab( MSHORT( nIndent ) );
    1545           0 :                             rRect.Left( nIndent + rFill.Left() );
    1546             :                         }
    1547             :                         else
    1548           0 :                             bFill = false;
    1549             :                     }
    1550             :                 }
    1551           0 :                 else if( rFill.X() > nLeft )
    1552             :                 {
    1553           0 :                     SwTwips nTxtLeft = rFill.Left() + rLRSpace.GetTxtLeft() +
    1554           0 :                                     GetTxtNode()->GetLeftMarginWithNum( true );
    1555           0 :                     rFill.nLineWidth += rFill.bFirstLine ? nLeft : nTxtLeft;
    1556           0 :                     SwTwips nLeftTab = nLeft;
    1557           0 :                     SwTwips nRightTab = nLeft;
    1558           0 :                     MSHORT nSpaceCnt = 0;
    1559           0 :                     MSHORT nTabCnt = 0;
    1560           0 :                     MSHORT nIdx = 0;
    1561           0 :                     do
    1562             :                     {
    1563           0 :                         nLeftTab = nRightTab;
    1564           0 :                         if( nIdx < rRuler.Count() )
    1565             :                         {
    1566           0 :                             const SvxTabStop &rTabStop = rRuler.operator[](nIdx);
    1567           0 :                             nRightTab = nTxtLeft + rTabStop.GetTabPos();
    1568           0 :                             if( nLeftTab < nTxtLeft && nRightTab > nTxtLeft )
    1569           0 :                                 nRightTab = nTxtLeft;
    1570             :                             else
    1571           0 :                                 ++nIdx;
    1572           0 :                             if( nRightTab > rFill.nLineWidth )
    1573           0 :                                 ++nTabCnt;
    1574             :                         }
    1575             :                         else
    1576             :                         {
    1577             :                             const SvxTabStopItem& rTab =
    1578             :                                 (const SvxTabStopItem &)pSet->
    1579           0 :                                 GetPool()->GetDefaultItem( RES_PARATR_TABSTOP );
    1580           0 :                             MSHORT nDefTabDist = (MSHORT)rTab[0].GetTabPos();
    1581           0 :                             nRightTab = nLeftTab - nTxtLeft;
    1582           0 :                             nRightTab /= nDefTabDist;
    1583           0 :                             nRightTab = nRightTab * nDefTabDist + nTxtLeft;
    1584           0 :                             while ( nRightTab <= nLeftTab )
    1585           0 :                                 nRightTab += nDefTabDist;
    1586           0 :                             if( nRightTab > rFill.nLineWidth )
    1587           0 :                                 ++nTabCnt;
    1588           0 :                             while ( nRightTab < rFill.X() )
    1589             :                             {
    1590           0 :                                 nRightTab += nDefTabDist;
    1591           0 :                                 if( nRightTab > rFill.nLineWidth )
    1592           0 :                                     ++nTabCnt;
    1593             :                             }
    1594           0 :                             if( nLeftTab < nRightTab - nDefTabDist )
    1595           0 :                                 nLeftTab = nRightTab - nDefTabDist;
    1596             :                         }
    1597           0 :                         if( nRightTab > nRight )
    1598           0 :                             nRightTab = nRight;
    1599             :                     }
    1600           0 :                     while( rFill.X() > nRightTab );
    1601           0 :                     --nTabCnt;
    1602           0 :                     if( FILL_TAB != rFill.Mode() )
    1603             :                     {
    1604           0 :                         if( nSpace > 0 )
    1605             :                         {
    1606           0 :                             if( !nTabCnt )
    1607           0 :                                 nLeftTab = rFill.nLineWidth;
    1608           0 :                             while( nLeftTab < rFill.X() )
    1609             :                             {
    1610           0 :                                 nLeftTab += nSpace;
    1611           0 :                                 ++nSpaceCnt;
    1612             :                             }
    1613           0 :                             if( nSpaceCnt )
    1614             :                             {
    1615           0 :                                 nLeftTab -= nSpace;
    1616           0 :                                 --nSpaceCnt;
    1617             :                             }
    1618           0 :                             if( rFill.X() - nLeftTab > nRightTab - rFill.X() )
    1619             :                             {
    1620           0 :                                 nSpaceCnt = 0;
    1621           0 :                                 ++nTabCnt;
    1622           0 :                                 rRect.Left( nRightTab );
    1623             :                             }
    1624             :                             else
    1625             :                             {
    1626           0 :                                 if( rFill.X() - nLeftTab > nSpace/2 )
    1627             :                                 {
    1628           0 :                                     ++nSpaceCnt;
    1629           0 :                                     rRect.Left( nLeftTab + nSpace );
    1630             :                                 }
    1631             :                                 else
    1632           0 :                                     rRect.Left( nLeftTab );
    1633             :                             }
    1634             :                         }
    1635           0 :                         else if( rFill.X() - nLeftTab < nRightTab - rFill.X() )
    1636           0 :                             rRect.Left( nLeftTab );
    1637             :                         else
    1638             :                         {
    1639           0 :                             if( nRightTab >= nRight )
    1640             :                             {
    1641           0 :                                 rFill.SetOrient( text::HoriOrientation::RIGHT );
    1642           0 :                                 rRect.Left( nRight );
    1643           0 :                                 nTabCnt = 0;
    1644           0 :                                 nSpaceCnt = 0;
    1645             :                             }
    1646             :                             else
    1647             :                             {
    1648           0 :                                 rRect.Left( nRightTab );
    1649           0 :                                 ++nTabCnt;
    1650             :                             }
    1651             :                         }
    1652             :                     }
    1653             :                     else
    1654             :                     {
    1655           0 :                         if( rFill.X() - nLeftTab < nRightTab - rFill.X() )
    1656           0 :                             rRect.Left( nLeftTab );
    1657             :                         else
    1658             :                         {
    1659           0 :                             if( nRightTab >= nRight )
    1660             :                             {
    1661           0 :                                 rFill.SetOrient( text::HoriOrientation::RIGHT );
    1662           0 :                                 rRect.Left( nRight );
    1663           0 :                                 nTabCnt = 0;
    1664           0 :                                 nSpaceCnt = 0;
    1665             :                             }
    1666             :                             else
    1667             :                             {
    1668           0 :                                 rRect.Left( nRightTab );
    1669           0 :                                 ++nTabCnt;
    1670             :                             }
    1671             :                         }
    1672             :                     }
    1673           0 :                     rFill.SetTab( nTabCnt );
    1674           0 :                     rFill.SetSpace( nSpaceCnt );
    1675           0 :                     if( bFill )
    1676             :                     {
    1677           0 :                         if( std::abs( rFill.X() - nCenter ) <=
    1678           0 :                             std::abs( rFill.X() - rRect.Left() ) )
    1679             :                         {
    1680           0 :                             rFill.SetOrient( text::HoriOrientation::CENTER );
    1681           0 :                             rFill.SetTab( 0 );
    1682           0 :                             rFill.SetSpace( 0 );
    1683           0 :                             rRect.Left( nCenter );
    1684             :                         }
    1685           0 :                         if( !rFill.bEmpty )
    1686           0 :                             rFill.nLineWidth += FILL_MIN_DIST;
    1687           0 :                         if( rRect.Left() < rFill.nLineWidth )
    1688           0 :                             bFill = false;
    1689             :                     }
    1690             :                 }
    1691             :             }
    1692             :             // Do we extend over the page's/column's/etc. lower edge?
    1693           0 :             const SwFrm* pUp = GetUpper();
    1694           0 :             if( pUp->IsInSct() )
    1695             :             {
    1696           0 :                 if( pUp->IsSctFrm() )
    1697           0 :                     pUp = pUp->GetUpper();
    1698           0 :                 else if( pUp->IsColBodyFrm() &&
    1699           0 :                          pUp->GetUpper()->GetUpper()->IsSctFrm() )
    1700           0 :                     pUp = pUp->GetUpper()->GetUpper()->GetUpper();
    1701             :             }
    1702           0 :             SWRECTFN( this )
    1703           0 :             SwTwips nLimit = (pUp->*fnRect->fnGetPrtBottom)();
    1704           0 :             SwTwips nRectBottom = rRect.Bottom();
    1705           0 :             if ( bVert )
    1706           0 :                 nRectBottom = SwitchHorizontalToVertical( nRectBottom );
    1707             : 
    1708           0 :             if( (*fnRect->fnYDiff)( nLimit, nRectBottom ) < 0 )
    1709           0 :                 bFill = false;
    1710             :             else
    1711           0 :                 rRect.Width( 1 );
    1712             :         }
    1713             :     }
    1714           0 :     ((SwCrsrMoveState*)rFill.pCMS)->bFillRet = bFill;
    1715           0 :     delete pFnt;
    1716             : }
    1717             : 
    1718             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10