LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/sw/source/core/text - frmcrsr.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 265 843 31.4 %
Date: 2013-07-09 Functions: 17 34 50.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10