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

Generated by: LCOV version 1.10