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

Generated by: LCOV version 1.11