LCOV - code coverage report
Current view: top level - libreoffice/sw/source/core/text - itrcrsr.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 189 922 20.5 %
Date: 2012-12-27 Functions: 7 11 63.6 %
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             : 
      21             : #include "hintids.hxx"
      22             : #include "ndtxt.hxx"
      23             : #include "frmfmt.hxx"
      24             : #include "paratr.hxx"
      25             : #include "flyfrm.hxx"
      26             : #include "pam.hxx"
      27             : #include "swselectionlist.hxx"
      28             : #include <sortedobjs.hxx>
      29             : #include <editeng/protitem.hxx>
      30             : #include <editeng/adjitem.hxx>
      31             : #include <editeng/lspcitem.hxx>
      32             : #include <editeng/lrspitem.hxx>
      33             : #include <frmatr.hxx>
      34             : #include <pagedesc.hxx> // SwPageDesc
      35             : #include <tgrditem.hxx>
      36             : #include <IDocumentSettingAccess.hxx>
      37             : #include <pagefrm.hxx>
      38             : 
      39             : #include "itrtxt.hxx"
      40             : #include "txtfrm.hxx"
      41             : #include "flyfrms.hxx"
      42             : #include "porglue.hxx"      // SwFlyCnt
      43             : #include "porfld.hxx"       // SwFldPortion::IsFollow()
      44             : #include "porfly.hxx"       // GetFlyCrsrOfst()
      45             : #include "pordrop.hxx"
      46             : #include "crstate.hxx"      // SwCrsrMoveState
      47             : #include <pormulti.hxx>     // SwMultiPortion
      48             : // #i111284#
      49             : #include <numrule.hxx>
      50             : 
      51             : // Nicht reentrant !!!
      52             : // wird in GetCharRect gesetzt und im UnitUp/Down ausgewertet.
      53             : sal_Bool SwTxtCursor::bRightMargin = sal_False;
      54             : 
      55             : 
      56             : /*************************************************************************
      57             :  *                    lcl_GetCharRectInsideField
      58             :  *
      59             :  * After calculating the position of a character during GetCharRect
      60             :  * this function allows to find the coordinates of a position (defined
      61             :  * in pCMS->pSpecialPos) inside a special portion (e.g., a field)
      62             :  *************************************************************************/
      63           0 : static void lcl_GetCharRectInsideField( SwTxtSizeInfo& rInf, SwRect& rOrig,
      64             :                                  const SwCrsrMoveState& rCMS,
      65             :                                  const SwLinePortion& rPor )
      66             : {
      67             :     OSL_ENSURE( rCMS.pSpecialPos, "Information about special pos missing" );
      68             : 
      69           0 :     if ( rPor.InFldGrp() && ((SwFldPortion&)rPor).GetExp().Len() )
      70             :     {
      71           0 :         const sal_uInt16 nCharOfst = rCMS.pSpecialPos->nCharOfst;
      72           0 :         sal_uInt16 nFldIdx = 0;
      73           0 :         sal_uInt16 nFldLen = 0;
      74             : 
      75           0 :         const XubString* pString = 0;
      76           0 :         const SwLinePortion* pPor = &rPor;
      77           0 :         do
      78             :         {
      79           0 :             if ( pPor->InFldGrp() )
      80             :             {
      81           0 :                 pString = &((SwFldPortion*)pPor)->GetExp();
      82           0 :                 nFldLen = pString->Len();
      83             :             }
      84             :             else
      85             :             {
      86           0 :                 pString = 0;
      87           0 :                 nFldLen = 0;
      88             :             }
      89             : 
      90           0 :             if ( ! pPor->GetPortion() || nFldIdx + nFldLen > nCharOfst )
      91           0 :                 break;
      92             : 
      93           0 :             nFldIdx = nFldIdx + nFldLen;
      94           0 :             rOrig.Pos().X() += pPor->Width();
      95           0 :             pPor = pPor->GetPortion();
      96             : 
      97             :         } while ( sal_True );
      98             : 
      99             :         OSL_ENSURE( nCharOfst >= nFldIdx, "Request of position inside field failed" );
     100           0 :         sal_uInt16 nLen = nCharOfst - nFldIdx + 1;
     101             : 
     102           0 :         if ( pString )
     103             :         {
     104             :             // get script for field portion
     105           0 :             rInf.GetFont()->SetActual( SwScriptInfo::WhichFont( 0, pString, 0 ) );
     106             : 
     107           0 :             xub_StrLen nOldLen = pPor->GetLen();
     108           0 :             ((SwLinePortion*)pPor)->SetLen( nLen - 1 );
     109           0 :             const SwTwips nX1 = pPor->GetLen() ?
     110           0 :                                 pPor->GetTxtSize( rInf ).Width() :
     111           0 :                                 0;
     112             : 
     113           0 :             SwTwips nX2 = 0;
     114           0 :             if ( rCMS.bRealWidth )
     115             :             {
     116           0 :                 ((SwLinePortion*)pPor)->SetLen( nLen );
     117           0 :                 nX2 = pPor->GetTxtSize( rInf ).Width();
     118             :             }
     119             : 
     120           0 :             ((SwLinePortion*)pPor)->SetLen( nOldLen );
     121             : 
     122           0 :             rOrig.Pos().X() += nX1;
     123             :             rOrig.Width( ( nX2 > nX1 ) ?
     124             :                          ( nX2 - nX1 ) :
     125           0 :                            1 );
     126             :         }
     127             :     }
     128             :     else
     129             :     {
     130             :         // special cases: no common fields, e.g., graphic number portion,
     131             :         // FlyInCntPortions, Notes
     132           0 :         rOrig.Width( rCMS.bRealWidth && rPor.Width() ? rPor.Width() : 1 );
     133             :     }
     134           0 : }
     135             : 
     136             : // #i111284#
     137             : namespace {
     138        4150 :     bool AreListLevelIndentsApplicableAndLabelAlignmentActive( const SwTxtNode& rTxtNode )
     139             :     {
     140        4150 :         bool bRet( false );
     141             : 
     142        4150 :         if ( rTxtNode.AreListLevelIndentsApplicable() )
     143             :         {
     144             :             const SwNumFmt& rNumFmt =
     145         123 :                     rTxtNode.GetNumRule()->Get( static_cast<sal_uInt16>(rTxtNode.GetActualListLevel()) );
     146         123 :             if ( rNumFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
     147             :             {
     148         123 :                 bRet = true;
     149             :             }
     150             :         }
     151             : 
     152        4150 :         return bRet;
     153             :     }
     154             : } // end of anonymous namespace
     155             : 
     156             : /*************************************************************************
     157             :  *                SwTxtMargin::CtorInitTxtMargin()
     158             :  *************************************************************************/
     159        4150 : void SwTxtMargin::CtorInitTxtMargin( SwTxtFrm *pNewFrm, SwTxtSizeInfo *pNewInf )
     160             : {
     161        4150 :     CtorInitTxtIter( pNewFrm, pNewInf );
     162             : 
     163        4150 :     pInf = pNewInf;
     164        4150 :     GetInfo().SetFont( GetFnt() );
     165        4150 :     const SwTxtNode *pNode = pFrm->GetTxtNode();
     166             : 
     167        4150 :     const SvxLRSpaceItem &rSpace = pFrm->GetTxtNode()->GetSwAttrSet().GetLRSpace();
     168             :     // #i95907#
     169             :     // #i111284#
     170             :     const bool bListLevelIndentsApplicableAndLabelAlignmentActive(
     171        4150 :         AreListLevelIndentsApplicableAndLabelAlignmentActive( *(pFrm->GetTxtNode()) ) );
     172             : 
     173             :     //
     174             :     // Carefully adjust the text formatting ranges.
     175             :     //
     176             :     // This whole area desperately needs some rework. There are
     177             :     // quite a couple of values that need to be considered:
     178             :     // 1. paragraph indent
     179             :     // 2. paragraph first line indent
     180             :     // 3. numbering indent
     181             :     // 4. numbering spacing to text
     182             :     // 5. paragraph border
     183             :     // Note: These values have already been used during calculation
     184             :     // of the printing area of the paragraph.
     185        4150 :     const int nLMWithNum = pNode->GetLeftMarginWithNum( sal_True );
     186        4150 :     if ( pFrm->IsRightToLeft() )
     187             :     {
     188             :         // this calculation is identical this the calculation for L2R layout - see below
     189           0 :         nLeft = pFrm->Frm().Left() +
     190           0 :                 pFrm->Prt().Left() +
     191             :                 nLMWithNum -
     192           0 :                 pNode->GetLeftMarginWithNum( sal_False ) -
     193             :                 // #i95907#
     194             :                 // #i111284#
     195             : //                rSpace.GetLeft() +
     196             : //                rSpace.GetTxtLeft();
     197             :                 ( bListLevelIndentsApplicableAndLabelAlignmentActive
     198             :                   ? 0
     199           0 :                   : ( rSpace.GetLeft() - rSpace.GetTxtLeft() ) );
     200             :     }
     201             :     else
     202             :     {
     203             :         // #i95907#
     204             :         // #i111284#
     205        8177 :         if ( bListLevelIndentsApplicableAndLabelAlignmentActive ||
     206        4027 :              !pNode->getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING) )
     207             :         {
     208             :             // this calculation is identical this the calculation for R2L layout - see above
     209        4150 :             nLeft = pFrm->Frm().Left() +
     210        4150 :                     pFrm->Prt().Left() +
     211             :                     nLMWithNum -
     212        4150 :                     pNode->GetLeftMarginWithNum( sal_False ) -
     213             :                     // #i95907#
     214             :                     // #i111284#
     215             :                     ( bListLevelIndentsApplicableAndLabelAlignmentActive
     216             :                       ? 0
     217        8300 :                       : ( rSpace.GetLeft() - rSpace.GetTxtLeft() ) );
     218             :         }
     219             :         else
     220             :         {
     221           0 :             nLeft = pFrm->Frm().Left() +
     222           0 :                     Max( long( rSpace.GetTxtLeft() + nLMWithNum ),
     223           0 :                          pFrm->Prt().Left() );
     224             :         }
     225             :     }
     226             : 
     227        4150 :     nRight = pFrm->Frm().Left() + pFrm->Prt().Left() + pFrm->Prt().Width();
     228             : 
     229        4168 :     if( nLeft >= nRight &&
     230             :          // #i53066# Omit adjustment of nLeft for numbered
     231             :          // paras inside cells inside new documents:
     232           9 :         ( pNode->getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING) ||
     233           9 :           !pFrm->IsInTab() ||
     234             :           !nLMWithNum ) )
     235             :     {
     236           9 :         nLeft = pFrm->Prt().Left() + pFrm->Frm().Left();
     237           9 :         if( nLeft >= nRight )   // z.B. bei grossen Absatzeinzuegen in schmalen Tabellenspalten
     238           5 :             nRight = nLeft + 1; // einen goennen wir uns immer
     239             :     }
     240             : 
     241        4150 :     if( pFrm->IsFollow() && pFrm->GetOfst() )
     242           0 :         nFirst = nLeft;
     243             :     else
     244             :     {
     245        4150 :         short nFLOfst = 0;
     246        4150 :         long nFirstLineOfs = 0;
     247        8118 :         if( !pNode->GetFirstLineOfsWithNum( nFLOfst ) &&
     248        3968 :             rSpace.IsAutoFirst() )
     249             :         {
     250           0 :             nFirstLineOfs = GetFnt()->GetSize( GetFnt()->GetActual() ).Height();
     251           0 :             const SvxLineSpacingItem *pSpace = aLineInf.GetLineSpacing();
     252           0 :             if( pSpace )
     253             :             {
     254           0 :                 switch( pSpace->GetLineSpaceRule() )
     255             :                 {
     256             :                     case SVX_LINE_SPACE_AUTO:
     257           0 :                     break;
     258             :                     case SVX_LINE_SPACE_MIN:
     259             :                     {
     260           0 :                         if( nFirstLineOfs < KSHORT( pSpace->GetLineHeight() ) )
     261           0 :                             nFirstLineOfs = pSpace->GetLineHeight();
     262           0 :                         break;
     263             :                     }
     264             :                     case SVX_LINE_SPACE_FIX:
     265           0 :                         nFirstLineOfs = pSpace->GetLineHeight();
     266           0 :                     break;
     267             :                     default: OSL_FAIL( ": unknown LineSpaceRule" );
     268             :                 }
     269           0 :                 switch( pSpace->GetInterLineSpaceRule() )
     270             :                 {
     271             :                     case SVX_INTER_LINE_SPACE_OFF:
     272           0 :                     break;
     273             :                     case SVX_INTER_LINE_SPACE_PROP:
     274             :                     {
     275           0 :                         long nTmp = pSpace->GetPropLineSpace();
     276             :                         // 50% ist das Minimum, bei 0% schalten wir auf
     277             :                         // den Defaultwert 100% um ...
     278           0 :                         if( nTmp < 50 )
     279           0 :                             nTmp = nTmp ? 50 : 100;
     280             : 
     281           0 :                         nTmp *= nFirstLineOfs;
     282           0 :                         nTmp /= 100;
     283           0 :                         if( !nTmp )
     284           0 :                             ++nTmp;
     285           0 :                         nFirstLineOfs = (KSHORT)nTmp;
     286           0 :                         break;
     287             :                     }
     288             :                     case SVX_INTER_LINE_SPACE_FIX:
     289             :                     {
     290           0 :                         nFirstLineOfs += pSpace->GetInterLineSpace();
     291           0 :                         break;
     292             :                     }
     293             :                     default: OSL_FAIL( ": unknown InterLineSpaceRule" );
     294             :                 }
     295             :             }
     296             :         }
     297             :         else
     298        4150 :             nFirstLineOfs = nFLOfst;
     299             : 
     300             :         // #i95907#
     301             :         // #i111284#
     302        8177 :         if ( pFrm->IsRightToLeft() ||
     303             :              bListLevelIndentsApplicableAndLabelAlignmentActive ||
     304        4027 :              !pNode->getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING) )
     305             :         {
     306        4150 :             nFirst = nLeft + nFirstLineOfs;
     307             :         }
     308             :         else
     309             :         {
     310           0 :               nFirst = pFrm->Frm().Left() +
     311           0 :                      Max( rSpace.GetTxtLeft() + nLMWithNum+ nFirstLineOfs,
     312           0 :                           pFrm->Prt().Left() );
     313             :         }
     314             : 
     315             :         // Note: <SwTxtFrm::GetAdditionalFirstLineOffset()> returns a negative
     316             :         //       value for the new list label postion and space mode LABEL_ALIGNMENT
     317             :         //       and label alignment CENTER and RIGHT in L2R layout respectively
     318             :         //       label alignment LEFT and CENTER in R2L layout
     319        4150 :         nFirst += pFrm->GetAdditionalFirstLineOffset();
     320             : 
     321        4150 :         if( nFirst >= nRight )
     322           0 :             nFirst = nRight - 1;
     323             :     }
     324        4150 :     const SvxAdjustItem& rAdjust = pFrm->GetTxtNode()->GetSwAttrSet().GetAdjust();
     325        4150 :     nAdjust = static_cast<sal_uInt16>(rAdjust.GetAdjust());
     326             : 
     327             :     // left is left and right is right
     328        4150 :     if ( pFrm->IsRightToLeft() )
     329             :     {
     330           0 :         if ( SVX_ADJUST_LEFT == nAdjust )
     331           0 :             nAdjust = SVX_ADJUST_RIGHT;
     332           0 :         else if ( SVX_ADJUST_RIGHT == nAdjust )
     333           0 :             nAdjust = SVX_ADJUST_LEFT;
     334             :     }
     335             : 
     336        4150 :     bOneBlock = rAdjust.GetOneWord() == SVX_ADJUST_BLOCK;
     337        4150 :     bLastBlock = rAdjust.GetLastBlock() == SVX_ADJUST_BLOCK;
     338        4150 :     bLastCenter = rAdjust.GetLastBlock() == SVX_ADJUST_CENTER;
     339             : 
     340             :     // #i91133#
     341        4150 :     mnTabLeft = pNode->GetLeftMarginForTabCalculation();
     342             : 
     343             : #if OSL_DEBUG_LEVEL > 1
     344             :     static sal_Bool bOne = sal_False;
     345             :     static sal_Bool bLast = sal_False;
     346             :     static sal_Bool bCenter = sal_False;
     347             :     bOneBlock |= bOne;
     348             :     bLastBlock |= bLast;
     349             :     bLastCenter |= bCenter;
     350             : #endif
     351        4150 :     DropInit();
     352        4150 : }
     353             : 
     354             : /*************************************************************************
     355             :  *                SwTxtMargin::DropInit()
     356             :  *************************************************************************/
     357        4150 : void SwTxtMargin::DropInit()
     358             : {
     359        4150 :     nDropLeft = nDropLines = nDropHeight = nDropDescent = 0;
     360        4150 :     const SwParaPortion *pPara = GetInfo().GetParaPortion();
     361        4150 :     if( pPara )
     362             :     {
     363        4150 :         const SwDropPortion *pPorDrop = pPara->FindDropPortion();
     364        4150 :         if ( pPorDrop )
     365             :         {
     366           0 :             nDropLeft = pPorDrop->GetDropLeft();
     367           0 :             nDropLines = pPorDrop->GetLines();
     368           0 :             nDropHeight = pPorDrop->GetDropHeight();
     369           0 :             nDropDescent = pPorDrop->GetDropDescent();
     370             :         }
     371             :     }
     372        4150 : }
     373             : 
     374             : /*************************************************************************
     375             :  *                SwTxtMargin::GetLineStart()
     376             :  *************************************************************************/
     377             : 
     378             : // Unter Beruecksichtigung des Erstzeileneinzuges und der angebenen Breite.
     379        3489 : SwTwips SwTxtMargin::GetLineStart() const
     380             : {
     381        3489 :     SwTwips nRet = GetLeftMargin();
     382        3684 :     if( GetAdjust() != SVX_ADJUST_LEFT &&
     383         195 :         !pCurr->GetFirstPortion()->IsMarginPortion() )
     384             :     {
     385             :         // Wenn die erste Portion ein Margin ist, dann wird das
     386             :         // Adjustment durch die Portions ausgedrueckt.
     387          73 :         if( GetAdjust() == SVX_ADJUST_RIGHT )
     388           6 :             nRet = Right() - CurrWidth();
     389          67 :         else if( GetAdjust() == SVX_ADJUST_CENTER )
     390          31 :             nRet += (GetLineWidth() - CurrWidth()) / 2;
     391             :     }
     392        3489 :     return nRet;
     393             : }
     394             : 
     395             : /*************************************************************************
     396             :  *                      SwTxtCursor::CtorInitTxtCursor()
     397             :  *************************************************************************/
     398        3443 : void SwTxtCursor::CtorInitTxtCursor( SwTxtFrm *pNewFrm, SwTxtSizeInfo *pNewInf )
     399             : {
     400        3443 :     CtorInitTxtMargin( pNewFrm, pNewInf );
     401             :     // 6096: Vorsicht, die Iteratoren sind abgeleitet!
     402             :     // GetInfo().SetOut( GetInfo().GetWin() );
     403        3443 : }
     404             : 
     405             : /*************************************************************************
     406             :  *                      SwTxtCursor::GetEndCharRect()
     407             :  *************************************************************************/
     408             : 
     409             : // 1170: Antikbug: Shift-Ende vergisst das letzte Zeichen ...
     410             : 
     411           0 : sal_Bool SwTxtCursor::GetEndCharRect( SwRect* pOrig, const xub_StrLen nOfst,
     412             :                                   SwCrsrMoveState* pCMS, const long nMax )
     413             : {
     414             :     // 1170: Mehrdeutigkeit von Dokumentpositionen
     415           0 :     bRightMargin = sal_True;
     416           0 :     CharCrsrToLine(nOfst);
     417             : 
     418             :     // Etwas verdreht: nOfst bezeichnet die Position hinter dem letzten
     419             :     // Zeichen der letzten Zeile == Position vor dem ersten Zeichen der
     420             :     // Zeile in der wir gerade stehen:
     421           0 :     if( nOfst != GetStart() || !pCurr->GetLen() )
     422             :     {
     423             :         // 8810: Masterzeile RightMargin, danach LeftMargin
     424           0 :         const sal_Bool bRet = GetCharRect( pOrig, nOfst, pCMS, nMax );
     425           0 :         bRightMargin = nOfst >= GetEnd() && nOfst < GetInfo().GetTxt().Len();
     426           0 :         return bRet;
     427             :     }
     428             : 
     429           0 :     if( !GetPrev() || !GetPrev()->GetLen() || !PrevLine() )
     430           0 :         return GetCharRect( pOrig, nOfst, pCMS, nMax );
     431             : 
     432             :     // Adjustierung ggf. nachholen
     433           0 :     GetAdjusted();
     434             : 
     435           0 :     KSHORT nX = 0;
     436           0 :     KSHORT nLast = 0;
     437           0 :     SwLinePortion *pPor = pCurr->GetFirstPortion();
     438             : 
     439             :     KSHORT nTmpHeight, nTmpAscent;
     440           0 :     CalcAscentAndHeight( nTmpAscent, nTmpHeight );
     441           0 :     KSHORT nPorHeight = nTmpHeight;
     442           0 :     KSHORT nPorAscent = nTmpAscent;
     443             : 
     444             :     // Die letzte Text/EndPortion der Zeile suchen
     445           0 :     while( pPor )
     446             :     {
     447           0 :         nX = nX + pPor->Width();
     448           0 :         if( pPor->InTxtGrp() || ( pPor->GetLen() && !pPor->IsFlyPortion()
     449           0 :             && !pPor->IsHolePortion() ) || pPor->IsBreakPortion() )
     450             :         {
     451           0 :             nLast = nX;
     452           0 :             nPorHeight = pPor->Height();
     453           0 :             nPorAscent = pPor->GetAscent();
     454             :         }
     455           0 :         pPor = pPor->GetPortion();
     456             :     }
     457             : 
     458           0 :     const Size aCharSize( 1, nTmpHeight );
     459           0 :     pOrig->Pos( GetTopLeft() );
     460           0 :     pOrig->SSize( aCharSize );
     461           0 :     pOrig->Pos().X() += nLast;
     462           0 :     const SwTwips nTmpRight = Right() - 1;
     463           0 :     if( pOrig->Left() > nTmpRight )
     464           0 :         pOrig->Pos().X() = nTmpRight;
     465             : 
     466           0 :     if ( pCMS && pCMS->bRealHeight )
     467             :     {
     468           0 :         if ( nTmpAscent > nPorAscent )
     469           0 :             pCMS->aRealHeight.X() = nTmpAscent - nPorAscent;
     470             :         else
     471           0 :             pCMS->aRealHeight.X() = 0;
     472             :         OSL_ENSURE( nPorHeight, "GetCharRect: Missing Portion-Height" );
     473           0 :         pCMS->aRealHeight.Y() = nPorHeight;
     474             :     }
     475             : 
     476           0 :     return sal_True;
     477             : }
     478             : 
     479             : /*************************************************************************
     480             :  * void SwTxtCursor::_GetCharRect(..)
     481             :  * internal function, called by SwTxtCursor::GetCharRect() to calculate
     482             :  * the relative character position in the current line.
     483             :  * pOrig referes to x and y coordinates, width and height of the cursor
     484             :  * pCMS is used for restricting the cursor, if there are different font
     485             :  * heights in one line ( first value = offset to y of pOrig, second
     486             :  * value = real height of (shortened) cursor
     487             :  *************************************************************************/
     488             : 
     489        2264 : void SwTxtCursor::_GetCharRect( SwRect* pOrig, const xub_StrLen nOfst,
     490             :     SwCrsrMoveState* pCMS )
     491             : {
     492        2264 :     const XubString &rText = GetInfo().GetTxt();
     493        2264 :     SwTxtSizeInfo aInf( GetInfo(), rText, nStart );
     494        2264 :     if( GetPropFont() )
     495           0 :         aInf.GetFont()->SetProportion( GetPropFont() );
     496             :     KSHORT nTmpAscent, nTmpHeight;  // Zeilenhoehe
     497        2264 :     CalcAscentAndHeight( nTmpAscent, nTmpHeight );
     498        2264 :     const Size  aCharSize( 1, nTmpHeight );
     499        2264 :     const Point aCharPos;
     500        2264 :     pOrig->Pos( aCharPos );
     501        2264 :     pOrig->SSize( aCharSize );
     502             : 
     503             :     // If we are looking for a position inside a field which covers
     504             :     // more than one line we may not skip any "empty portions" at the
     505             :     // beginning of a line
     506             :     const sal_Bool bInsideFirstField = pCMS && pCMS->pSpecialPos &&
     507             :                                        ( pCMS->pSpecialPos->nLineOfst ||
     508             :                                          SP_EXTEND_RANGE_BEFORE ==
     509        2264 :                                          pCMS->pSpecialPos->nExtendRange );
     510             : 
     511        2264 :     sal_Bool bWidth = pCMS && pCMS->bRealWidth;
     512        2264 :     if( !pCurr->GetLen() && !pCurr->Width() )
     513             :     {
     514         174 :         if ( pCMS && pCMS->bRealHeight )
     515             :         {
     516         174 :             pCMS->aRealHeight.X() = 0;
     517         174 :             pCMS->aRealHeight.Y() = nTmpHeight;
     518             :         }
     519             :     }
     520             :     else
     521             :     {
     522        2090 :         KSHORT nPorHeight = nTmpHeight;
     523        2090 :         KSHORT nPorAscent = nTmpAscent;
     524        2090 :         SwTwips nX = 0;
     525        2090 :         SwTwips nTmpFirst = 0;
     526        2090 :         SwLinePortion *pPor = pCurr->GetFirstPortion();
     527        2090 :         SwBidiPortion* pLastBidiPor = 0;
     528        2090 :         SwTwips nLastBidiPorWidth = 0;
     529        2090 :         std::deque<sal_uInt16>* pKanaComp = pCurr->GetpKanaComp();
     530        2090 :         MSHORT nSpaceIdx = 0;
     531        2090 :         size_t nKanaIdx = 0;
     532        2090 :         long nSpaceAdd = pCurr->IsSpaceAdd() ? pCurr->GetLLSpaceAdd( 0 ) : 0;
     533             : 
     534        2090 :         sal_Bool bNoTxt = sal_True;
     535             : 
     536             :         // Zuerst werden alle Portions ohne Len am Zeilenanfang uebersprungen.
     537             :         // Ausnahme bilden die fiesen Spezialportions aus WhichFirstPortion:
     538             :         // Num, ErgoSum, FtnNum, FeldReste
     539             :         // 8477: aber auch die einzige Textportion einer leeren Zeile mit
     540             :         // Right/Center-Adjustment! Also nicht nur pPor->GetExpandPortion() ...
     541        4412 :         while( pPor && !pPor->GetLen() && ! bInsideFirstField )
     542             :         {
     543         232 :             nX += pPor->Width();
     544         232 :             if ( pPor->InSpaceGrp() && nSpaceAdd )
     545           0 :                 nX += pPor->CalcSpacing( nSpaceAdd, aInf );
     546         232 :             if( bNoTxt )
     547         145 :                 nTmpFirst = nX;
     548             :             // 8670: EndPortions zaehlen hier einmal als TxtPortions.
     549             : //            if( pPor->InTxtGrp() || pPor->IsBreakPortion() )
     550         232 :             if( pPor->InTxtGrp() || pPor->IsBreakPortion() || pPor->InTabGrp() )
     551             :             {
     552         109 :                 bNoTxt = sal_False;
     553         109 :                 nTmpFirst = nX;
     554             :             }
     555         232 :             if( pPor->IsMultiPortion() && ((SwMultiPortion*)pPor)->HasTabulator() )
     556             :             {
     557           0 :                 if ( pCurr->IsSpaceAdd() )
     558             :                 {
     559           0 :                     if ( ++nSpaceIdx < pCurr->GetLLSpaceAddCount() )
     560           0 :                         nSpaceAdd = pCurr->GetLLSpaceAdd( nSpaceIdx );
     561             :                     else
     562           0 :                         nSpaceAdd = 0;
     563             :                 }
     564             : 
     565           0 :                 if( pKanaComp && ( nKanaIdx + 1 ) < pKanaComp->size() )
     566           0 :                     ++nKanaIdx;
     567             :             }
     568         232 :             if( pPor->InFixMargGrp() )
     569             :             {
     570         171 :                 if( pPor->IsMarginPortion() )
     571         118 :                     bNoTxt = sal_False;
     572             :                 else
     573             :                 {
     574             :                     // fix margin portion => next SpaceAdd, KanaComp value
     575          53 :                     if ( pCurr->IsSpaceAdd() )
     576             :                     {
     577           0 :                         if ( ++nSpaceIdx < pCurr->GetLLSpaceAddCount() )
     578           0 :                             nSpaceAdd = pCurr->GetLLSpaceAdd( nSpaceIdx );
     579             :                         else
     580           0 :                             nSpaceAdd = 0;
     581             :                     }
     582             : 
     583          53 :                     if( pKanaComp && ( nKanaIdx + 1 ) < pKanaComp->size() )
     584           0 :                         ++nKanaIdx;
     585             :                 }
     586             :             }
     587         232 :             pPor = pPor->GetPortion();
     588             :         }
     589             : 
     590        2090 :         if( !pPor )
     591             :         {
     592             :             // Es sind nur Spezialportions unterwegs.
     593          31 :             nX = nTmpFirst;
     594             :         }
     595             :         else
     596             :         {
     597        4130 :             if( !pPor->IsMarginPortion() && !pPor->IsPostItsPortion() &&
     598        2071 :                 (!pPor->InFldGrp() || pPor->GetAscent() ) )
     599             :             {
     600        2059 :                 nPorHeight = pPor->Height();
     601        2059 :                 nPorAscent = pPor->GetAscent();
     602             :             }
     603        4264 :             while( pPor && !pPor->IsBreakPortion() && ( aInf.GetIdx() < nOfst ||
     604           0 :                    ( bWidth && ( pPor->IsKernPortion() || pPor->IsMultiPortion() ) ) ) )
     605             :             {
     606         292 :                 if( !pPor->IsMarginPortion() && !pPor->IsPostItsPortion() &&
     607         146 :                     (!pPor->InFldGrp() || pPor->GetAscent() ) )
     608             :                 {
     609         146 :                     nPorHeight = pPor->Height();
     610         146 :                     nPorAscent = pPor->GetAscent();
     611             :                 }
     612             : 
     613             :                 // If we are behind the portion, we add the portion width to
     614             :                 // nX. Special case: nOfst = aInf.GetIdx() + pPor->GetLen().
     615             :                 // For common portions (including BidiPortions) we want to add
     616             :                 // the portion width to nX. For MultiPortions, nExtra = 0,
     617             :                 // therefore we go to the 'else' branch and start a recursion.
     618         146 :                 const sal_uInt8 nExtra = pPor->IsMultiPortion() &&
     619           0 :                                     ! ((SwMultiPortion*)pPor)->IsBidi() &&
     620         146 :                                     ! bWidth ? 0 : 1;
     621         146 :                 if ( aInf.GetIdx() + pPor->GetLen() < nOfst + nExtra )
     622             :                 {
     623         146 :                     if ( pPor->InSpaceGrp() && nSpaceAdd )
     624           0 :                         nX += pPor->PrtWidth() +
     625           0 :                               pPor->CalcSpacing( nSpaceAdd, aInf );
     626             :                     else
     627             :                     {
     628         146 :                         if( pPor->InFixMargGrp() && ! pPor->IsMarginPortion() )
     629             :                         {
     630             :                             // update to current SpaceAdd, KanaComp values
     631           4 :                             if ( pCurr->IsSpaceAdd() )
     632             :                             {
     633           0 :                                 if ( ++nSpaceIdx < pCurr->GetLLSpaceAddCount() )
     634           0 :                                     nSpaceAdd = pCurr->GetLLSpaceAdd( nSpaceIdx );
     635             :                                 else
     636           0 :                                     nSpaceAdd = 0;
     637             :                             }
     638             : 
     639           4 :                             if ( pKanaComp &&
     640           0 :                                 ( nKanaIdx + 1 ) < pKanaComp->size()
     641             :                                 )
     642           0 :                                 ++nKanaIdx;
     643             :                         }
     644         146 :                         if ( !pPor->IsFlyPortion() || ( pPor->GetPortion() &&
     645           0 :                                 !pPor->GetPortion()->IsMarginPortion() ) )
     646         146 :                             nX += pPor->PrtWidth();
     647             :                     }
     648         146 :                     if( pPor->IsMultiPortion() )
     649             :                     {
     650           0 :                         if ( ((SwMultiPortion*)pPor)->HasTabulator() )
     651             :                         {
     652           0 :                             if ( pCurr->IsSpaceAdd() )
     653             :                             {
     654           0 :                                 if ( ++nSpaceIdx < pCurr->GetLLSpaceAddCount() )
     655           0 :                                     nSpaceAdd = pCurr->GetLLSpaceAdd( nSpaceIdx );
     656             :                                 else
     657           0 :                                     nSpaceAdd = 0;
     658             :                             }
     659             : 
     660           0 :                             if( pKanaComp && ( nKanaIdx + 1 ) < pKanaComp->size() )
     661           0 :                                 ++nKanaIdx;
     662             :                         }
     663             : 
     664             :                         // if we are right behind a BidiPortion, we have to
     665             :                         // hold a pointer to the BidiPortion in order to
     666             :                         // find the correct cursor position, depending on the
     667             :                         // cursor level
     668           0 :                         if ( ((SwMultiPortion*)pPor)->IsBidi() &&
     669           0 :                              aInf.GetIdx() + pPor->GetLen() == nOfst )
     670             :                         {
     671           0 :                              pLastBidiPor = (SwBidiPortion*)pPor;
     672           0 :                              nLastBidiPorWidth = pLastBidiPor->Width() +
     673           0 :                                                  pLastBidiPor->CalcSpacing( nSpaceAdd, aInf );;
     674             :                         }
     675             :                     }
     676             : 
     677         146 :                     aInf.SetIdx( aInf.GetIdx() + pPor->GetLen() );
     678         146 :                     pPor = pPor->GetPortion();
     679             :                 }
     680             :                 else
     681             :                 {
     682           0 :                     if( pPor->IsMultiPortion() )
     683             :                     {
     684           0 :                         nTmpAscent = AdjustBaseLine( *pCurr, pPor );
     685           0 :                         GetInfo().SetMulti( sal_True );
     686           0 :                         pOrig->Pos().Y() += nTmpAscent - nPorAscent;
     687             : 
     688           0 :                         if( pCMS && pCMS->b2Lines )
     689             :                         {
     690           0 :                             sal_Bool bRecursion = sal_True;
     691           0 :                             if ( ! pCMS->p2Lines )
     692             :                             {
     693           0 :                                 pCMS->p2Lines = new Sw2LinesPos;
     694           0 :                                 pCMS->p2Lines->aLine = SwRect(aCharPos, aCharSize);
     695           0 :                                 bRecursion = sal_False;
     696             :                             }
     697             : 
     698           0 :                             if( ((SwMultiPortion*)pPor)->HasRotation() )
     699             :                             {
     700           0 :                                 if( ((SwMultiPortion*)pPor)->IsRevers() )
     701           0 :                                     pCMS->p2Lines->nMultiType = MT_ROT_270;
     702             :                                 else
     703           0 :                                     pCMS->p2Lines->nMultiType = MT_ROT_90;
     704             :                             }
     705           0 :                             else if( ((SwMultiPortion*)pPor)->IsDouble() )
     706           0 :                                 pCMS->p2Lines->nMultiType = MT_TWOLINE;
     707           0 :                             else if( ((SwMultiPortion*)pPor)->IsBidi() )
     708           0 :                                 pCMS->p2Lines->nMultiType = MT_BIDI;
     709             :                             else
     710           0 :                                 pCMS->p2Lines->nMultiType = MT_RUBY;
     711             : 
     712           0 :                             SwTwips nTmpWidth = pPor->Width();
     713           0 :                             if( nSpaceAdd )
     714           0 :                                 nTmpWidth += pPor->CalcSpacing(nSpaceAdd, aInf);
     715             : 
     716           0 :                             SwRect aRect( Point(aCharPos.X() + nX, pOrig->Top() ),
     717           0 :                                           Size( nTmpWidth, pPor->Height() ) );
     718             : 
     719           0 :                             if ( ! bRecursion )
     720           0 :                                 pCMS->p2Lines->aPortion = aRect;
     721             :                             else
     722           0 :                                 pCMS->p2Lines->aPortion2 = aRect;
     723             :                         }
     724             : 
     725             :                         // In a multi-portion we use GetCharRect()-function
     726             :                         // recursively and must add the x-position
     727             :                         // of the multi-portion.
     728           0 :                         xub_StrLen nOldStart = nStart;
     729           0 :                         SwTwips nOldY = nY;
     730           0 :                         sal_uInt8 nOldProp = GetPropFont();
     731           0 :                         nStart = aInf.GetIdx();
     732           0 :                         SwLineLayout* pOldCurr = pCurr;
     733           0 :                         pCurr = &((SwMultiPortion*)pPor)->GetRoot();
     734           0 :                         if( ((SwMultiPortion*)pPor)->IsDouble() )
     735           0 :                             SetPropFont( 50 );
     736             : 
     737           0 :                         GETGRID( GetTxtFrm()->FindPageFrm() )
     738           0 :                         const sal_Bool bHasGrid = pGrid && GetInfo().SnapToGrid();
     739             :                         const sal_uInt16 nRubyHeight = bHasGrid ?
     740           0 :                                                    pGrid->GetRubyHeight() : 0;
     741             : 
     742           0 :                         if( nStart + pCurr->GetLen() <= nOfst && GetNext() &&
     743           0 :                             ( ! ((SwMultiPortion*)pPor)->IsRuby() ||
     744           0 :                                 ((SwMultiPortion*)pPor)->OnTop() ) )
     745             :                         {
     746             :                             sal_uInt16 nOffset;
     747             :                             // in grid mode we may only add the height of the
     748             :                             // ruby line if ruby line is on top
     749           0 :                             if ( bHasGrid &&
     750           0 :                                 ((SwMultiPortion*)pPor)->IsRuby() &&
     751           0 :                                 ((SwMultiPortion*)pPor)->OnTop() )
     752           0 :                                 nOffset = nRubyHeight;
     753             :                             else
     754           0 :                                 nOffset = GetLineHeight();
     755             : 
     756           0 :                             pOrig->Pos().Y() += nOffset;
     757           0 :                             Next();
     758             :                         }
     759             : 
     760             :                         sal_Bool bSpaceChg = ((SwMultiPortion*)pPor)->
     761           0 :                                                 ChgSpaceAdd( pCurr, nSpaceAdd );
     762           0 :                         Point aOldPos = pOrig->Pos();
     763             : 
     764             :                         // Ok, for ruby portions in grid mode we have to
     765             :                         // temporarily set the inner line height to the
     766             :                         // outer line height because that value is needed
     767             :                         // for the adjustment inside the recursion
     768           0 :                         const sal_uInt16 nOldRubyHeight = pCurr->Height();
     769           0 :                         const sal_uInt16 nOldRubyRealHeight = pCurr->GetRealHeight();
     770             :                         const sal_Bool bChgHeight =
     771           0 :                                 ((SwMultiPortion*)pPor)->IsRuby() && bHasGrid;
     772             : 
     773           0 :                         if ( bChgHeight )
     774             :                         {
     775           0 :                             pCurr->Height( pOldCurr->Height() - nRubyHeight );
     776           0 :                             pCurr->SetRealHeight( pOldCurr->GetRealHeight() -
     777           0 :                                                   nRubyHeight );
     778             :                         }
     779             : 
     780           0 :                         SwLayoutModeModifier aLayoutModeModifier( *GetInfo().GetOut() );
     781           0 :                         if ( ((SwMultiPortion*)pPor)->IsBidi() )
     782             :                         {
     783             :                             aLayoutModeModifier.Modify(
     784           0 :                                 ((SwBidiPortion*)pPor)->GetLevel() % 2 );
     785             :                         }
     786             : 
     787           0 :                         _GetCharRect( pOrig, nOfst, pCMS );
     788             : 
     789           0 :                         if ( bChgHeight )
     790             :                         {
     791           0 :                             pCurr->Height( nOldRubyHeight );
     792           0 :                             pCurr->SetRealHeight( nOldRubyRealHeight );
     793             :                         }
     794             : 
     795             :                         // if we are still in the first row of
     796             :                         // our 2 line multiportion, we use the FirstMulti flag
     797             :                         // to indicate this
     798           0 :                         if ( ((SwMultiPortion*)pPor)->IsDouble() )
     799             :                         {
     800             :                             // the recursion may have damaged our font size
     801           0 :                             SetPropFont( nOldProp );
     802           0 :                             if ( !nOldProp )
     803           0 :                                 nOldProp = 100;
     804           0 :                             GetInfo().GetFont()->SetProportion( 100 );
     805             : 
     806           0 :                             if ( pCurr == &((SwMultiPortion*)pPor)->GetRoot() )
     807             :                             {
     808           0 :                                 GetInfo().SetFirstMulti( true );
     809             : 
     810             :                                 // we want to treat a double line portion like a
     811             :                                 // single line portion, if there is no text in
     812             :                                 // the second line
     813           0 :                                 if ( !pCurr->GetNext() ||
     814           0 :                                      !pCurr->GetNext()->GetLen() )
     815           0 :                                     GetInfo().SetMulti( sal_False );
     816             :                             }
     817             :                         }
     818             :                         // ruby portions are treated like single line portions
     819           0 :                         else if( ((SwMultiPortion*)pPor)->IsRuby() ||
     820           0 :                                  ((SwMultiPortion*)pPor)->IsBidi() )
     821           0 :                             GetInfo().SetMulti( sal_False );
     822             : 
     823             :                         // calculate cursor values
     824           0 :                         if( ((SwMultiPortion*)pPor)->HasRotation() )
     825             :                         {
     826           0 :                             GetInfo().SetMulti( sal_False );
     827           0 :                             long nTmp = pOrig->Width();
     828           0 :                             pOrig->Width( pOrig->Height() );
     829           0 :                             pOrig->Height( nTmp );
     830           0 :                             nTmp = pOrig->Left() - aOldPos.X();
     831             : 
     832             :                             // if we travel into our rotated portion from
     833             :                             // a line below, we have to take care, that the
     834             :                             // y coord in pOrig is less than line height:
     835           0 :                             if ( nTmp )
     836           0 :                                 nTmp--;
     837             : 
     838           0 :                             pOrig->Pos().X() = nX + aOldPos.X();
     839           0 :                             if( ((SwMultiPortion*)pPor)->IsRevers() )
     840           0 :                                 pOrig->Pos().Y() = aOldPos.Y() + nTmp;
     841             :                             else
     842           0 :                                 pOrig->Pos().Y() = aOldPos.Y()
     843           0 :                                     + pPor->Height() - nTmp - pOrig->Height();
     844           0 :                             if ( pCMS && pCMS->bRealHeight )
     845             :                             {
     846           0 :                                 pCMS->aRealHeight.Y() = -pCMS->aRealHeight.Y();
     847             :                                 // result for rotated multi portion is not
     848             :                                 // correct for reverse (270 degree) portions
     849           0 :                                 if( ((SwMultiPortion*)pPor)->IsRevers() )
     850             :                                 {
     851           0 :                                     if ( SvxParaVertAlignItem::AUTOMATIC ==
     852           0 :                                          GetLineInfo().GetVertAlign() )
     853             :                                         // if vertical alignment is set to auto,
     854             :                                         // we switch from base line alignment
     855             :                                         // to centered alignment
     856           0 :                                         pCMS->aRealHeight.X() =
     857           0 :                                             ( pOrig->Width() +
     858           0 :                                               pCMS->aRealHeight.Y() ) / 2;
     859             :                                     else
     860           0 :                                         pCMS->aRealHeight.X() =
     861           0 :                                             ( pOrig->Width() -
     862           0 :                                               pCMS->aRealHeight.X() +
     863           0 :                                               pCMS->aRealHeight.Y() );
     864             :                                 }
     865             :                             }
     866             :                         }
     867             :                         else
     868             :                         {
     869           0 :                             pOrig->Pos().Y() += aOldPos.Y();
     870           0 :                             if ( ((SwMultiPortion*)pPor)->IsBidi() )
     871             :                             {
     872           0 :                                 const SwTwips nPorWidth = pPor->Width() +
     873           0 :                                                          pPor->CalcSpacing( nSpaceAdd, aInf );
     874           0 :                                 const SwTwips nInsideOfst = pOrig->Pos().X();
     875           0 :                                 pOrig->Pos().X() = nX + nPorWidth -
     876           0 :                                                    nInsideOfst - pOrig->Width();
     877             :                             }
     878             :                             else
     879           0 :                                 pOrig->Pos().X() += nX;
     880             : 
     881           0 :                             if( ((SwMultiPortion*)pPor)->HasBrackets() )
     882           0 :                                 pOrig->Pos().X() +=
     883           0 :                                     ((SwDoubleLinePortion*)pPor)->PreWidth();
     884             :                         }
     885             : 
     886           0 :                         if( bSpaceChg )
     887           0 :                             SwDoubleLinePortion::ResetSpaceAdd( pCurr );
     888             : 
     889           0 :                         pCurr = pOldCurr;
     890           0 :                         nStart = nOldStart;
     891           0 :                         nY = nOldY;
     892           0 :                         bPrev = sal_False;
     893             : 
     894        2264 :                         return;
     895             :                     }
     896           0 :                     if ( pPor->PrtWidth() )
     897             :                     {
     898           0 :                         xub_StrLen nOldLen = pPor->GetLen();
     899           0 :                         pPor->SetLen( nOfst - aInf.GetIdx() );
     900           0 :                         aInf.SetLen( pPor->GetLen() );
     901           0 :                         if( nX || !pPor->InNumberGrp() )
     902             :                         {
     903           0 :                             SeekAndChg( aInf );
     904           0 :                             const bool bOldOnWin = aInf.OnWin();
     905           0 :                             aInf.SetOnWin( false ); // keine BULLETs!
     906           0 :                             SwTwips nTmp = nX;
     907           0 :                             aInf.SetKanaComp( pKanaComp );
     908           0 :                             aInf.SetKanaIdx( nKanaIdx );
     909           0 :                             nX += pPor->GetTxtSize( aInf ).Width();
     910           0 :                             aInf.SetOnWin( bOldOnWin );
     911           0 :                             if ( pPor->InSpaceGrp() && nSpaceAdd )
     912           0 :                                 nX += pPor->CalcSpacing( nSpaceAdd, aInf );
     913           0 :                             if( bWidth )
     914             :                             {
     915           0 :                                 pPor->SetLen( pPor->GetLen() + 1 );
     916           0 :                                 aInf.SetLen( pPor->GetLen() );
     917           0 :                                 aInf.SetOnWin( false ); // keine BULLETs!
     918           0 :                                 nTmp += pPor->GetTxtSize( aInf ).Width();
     919           0 :                                 aInf.SetOnWin( bOldOnWin );
     920           0 :                                 if ( pPor->InSpaceGrp() && nSpaceAdd )
     921           0 :                                     nTmp += pPor->CalcSpacing(nSpaceAdd, aInf);
     922           0 :                                 pOrig->Width( nTmp - nX );
     923             :                             }
     924             :                         }
     925           0 :                         pPor->SetLen( nOldLen );
     926             :                     }
     927           0 :                     bWidth = sal_False;
     928           0 :                     break;
     929             :                 }
     930             :             }
     931             :         }
     932             : 
     933        2090 :         if( pPor )
     934             :         {
     935             :             OSL_ENSURE( !pPor->InNumberGrp() || bInsideFirstField, "Number surprise" );
     936        2033 :             sal_Bool bEmptyFld = sal_False;
     937        2033 :             if( pPor->InFldGrp() && pPor->GetLen() )
     938             :             {
     939          12 :                 SwFldPortion *pTmp = (SwFldPortion*)pPor;
     940          24 :                 while( pTmp->HasFollow() && !pTmp->GetExp().Len() )
     941             :                 {
     942           0 :                     KSHORT nAddX = pTmp->Width();
     943           0 :                     SwLinePortion *pNext = pTmp->GetPortion();
     944           0 :                     while( pNext && !pNext->InFldGrp() )
     945             :                     {
     946             :                         OSL_ENSURE( !pNext->GetLen(), "Where's my field follow?" );
     947           0 :                         nAddX = nAddX + pNext->Width();
     948           0 :                         pNext = pNext->GetPortion();
     949             :                     }
     950           0 :                     if( !pNext )
     951           0 :                         break;
     952           0 :                     pTmp = (SwFldPortion*)pNext;
     953           0 :                     nPorHeight = pTmp->Height();
     954           0 :                     nPorAscent = pTmp->GetAscent();
     955           0 :                     nX += nAddX;
     956           0 :                     bEmptyFld = sal_True;
     957             :                 }
     958             :             }
     959             :             // 8513: Felder im Blocksatz, ueberspringen
     960        4066 :             while( pPor && !pPor->GetLen() && ! bInsideFirstField &&
     961           0 :                    ( pPor->IsFlyPortion() || pPor->IsKernPortion() ||
     962           0 :                      pPor->IsBlankPortion() || pPor->InTabGrp() ||
     963           0 :                      ( !bEmptyFld && pPor->InFldGrp() ) ) )
     964             :             {
     965           0 :                 if ( pPor->InSpaceGrp() && nSpaceAdd )
     966           0 :                     nX += pPor->PrtWidth() +
     967           0 :                           pPor->CalcSpacing( nSpaceAdd, aInf );
     968             :                 else
     969             :                 {
     970           0 :                     if( pPor->InFixMargGrp() && ! pPor->IsMarginPortion() )
     971             :                     {
     972           0 :                         if ( pCurr->IsSpaceAdd() )
     973             :                         {
     974           0 :                             if ( ++nSpaceIdx < pCurr->GetLLSpaceAddCount() )
     975           0 :                                 nSpaceAdd = pCurr->GetLLSpaceAdd( nSpaceIdx );
     976             :                             else
     977           0 :                                 nSpaceAdd = 0;
     978             :                         }
     979             : 
     980           0 :                         if( pKanaComp && ( nKanaIdx + 1 ) < pKanaComp->size() )
     981           0 :                             ++nKanaIdx;
     982             :                     }
     983           0 :                     if ( !pPor->IsFlyPortion() || ( pPor->GetPortion() &&
     984           0 :                             !pPor->GetPortion()->IsMarginPortion() ) )
     985           0 :                         nX += pPor->PrtWidth();
     986             :                 }
     987           0 :                 if( pPor->IsMultiPortion() &&
     988           0 :                     ((SwMultiPortion*)pPor)->HasTabulator() )
     989             :                 {
     990           0 :                     if ( pCurr->IsSpaceAdd() )
     991             :                     {
     992           0 :                         if ( ++nSpaceIdx < pCurr->GetLLSpaceAddCount() )
     993           0 :                             nSpaceAdd = pCurr->GetLLSpaceAdd( nSpaceIdx );
     994             :                         else
     995           0 :                             nSpaceAdd = 0;
     996             :                     }
     997             : 
     998           0 :                     if( pKanaComp && ( nKanaIdx + 1 ) < pKanaComp->size() )
     999           0 :                         ++nKanaIdx;
    1000             :                 }
    1001           0 :                 if( !pPor->IsFlyPortion() )
    1002             :                 {
    1003           0 :                     nPorHeight = pPor->Height();
    1004           0 :                     nPorAscent = pPor->GetAscent();
    1005             :                 }
    1006           0 :                 pPor = pPor->GetPortion();
    1007             :             }
    1008             : 
    1009        2033 :             if( aInf.GetIdx() == nOfst && pPor && pPor->InHyphGrp() &&
    1010           0 :                 pPor->GetPortion() && pPor->GetPortion()->InFixGrp() )
    1011             :             {
    1012             :                 // Alle Sonderportions muessen uebersprungen werden
    1013             :                 // Beispiel: zu-[FLY]sammen, 'u' == 19, 's' == 20; Right()
    1014             :                 // Ohne den Ausgleich landen wir vor '-' mit dem
    1015             :                 // Ausgleich vor 's'.
    1016           0 :                 while( pPor && !pPor->GetLen() )
    1017             :                 {
    1018           0 :                     nX += pPor->Width();
    1019           0 :                     if( !pPor->IsMarginPortion() )
    1020             :                     {
    1021           0 :                         nPorHeight = pPor->Height();
    1022           0 :                         nPorAscent = pPor->GetAscent();
    1023             :                     }
    1024           0 :                     pPor = pPor->GetPortion();
    1025             :                 }
    1026             :             }
    1027        2033 :             if( pPor && pCMS )
    1028             :             {
    1029        2004 :                 if( pCMS->bFieldInfo && pPor->InFldGrp() && pPor->Width() )
    1030           0 :                     pOrig->Width( pPor->Width() );
    1031        2004 :                 if( pPor->IsDropPortion() )
    1032             :                 {
    1033           0 :                     nPorAscent = ((SwDropPortion*)pPor)->GetDropHeight();
    1034             :                     // The drop height is only calculated, if we have more than
    1035             :                     // one line. Otherwise it is 0.
    1036           0 :                     if ( ! nPorAscent)
    1037           0 :                         nPorAscent = pPor->Height();
    1038           0 :                     nPorHeight = nPorAscent;
    1039             :                     pOrig->Height( nPorHeight +
    1040           0 :                         ((SwDropPortion*)pPor)->GetDropDescent() );
    1041           0 :                     if( nTmpHeight < pOrig->Height() )
    1042             :                     {
    1043           0 :                         nTmpAscent = nPorAscent;
    1044           0 :                         nTmpHeight = sal_uInt16( pOrig->Height() );
    1045             :                     }
    1046             :                 }
    1047        2004 :                 if( bWidth && pPor->PrtWidth() && pPor->GetLen() &&
    1048           0 :                     aInf.GetIdx() == nOfst )
    1049             :                 {
    1050           0 :                     if( !pPor->IsFlyPortion() && pPor->Height() &&
    1051           0 :                         pPor->GetAscent() )
    1052             :                     {
    1053           0 :                         nPorHeight = pPor->Height();
    1054           0 :                         nPorAscent = pPor->GetAscent();
    1055             :                     }
    1056             :                     SwTwips nTmp;
    1057           0 :                     if( 2 > pPor->GetLen() )
    1058             :                     {
    1059           0 :                         nTmp = pPor->Width();
    1060           0 :                         if ( pPor->InSpaceGrp() && nSpaceAdd )
    1061           0 :                             nTmp += pPor->CalcSpacing( nSpaceAdd, aInf );
    1062             :                     }
    1063             :                     else
    1064             :                     {
    1065           0 :                         const bool bOldOnWin = aInf.OnWin();
    1066           0 :                         xub_StrLen nOldLen = pPor->GetLen();
    1067           0 :                         pPor->SetLen( 1 );
    1068           0 :                         aInf.SetLen( pPor->GetLen() );
    1069           0 :                         SeekAndChg( aInf );
    1070           0 :                         aInf.SetOnWin( false ); // keine BULLETs!
    1071           0 :                         aInf.SetKanaComp( pKanaComp );
    1072           0 :                         aInf.SetKanaIdx( nKanaIdx );
    1073           0 :                         nTmp = pPor->GetTxtSize( aInf ).Width();
    1074           0 :                         aInf.SetOnWin( bOldOnWin );
    1075           0 :                         if ( pPor->InSpaceGrp() && nSpaceAdd )
    1076           0 :                             nTmp += pPor->CalcSpacing( nSpaceAdd, aInf );
    1077           0 :                         pPor->SetLen( nOldLen );
    1078             :                     }
    1079           0 :                     pOrig->Width( nTmp );
    1080             :                 }
    1081             : 
    1082             :                 // travel inside field portion?
    1083        2004 :                 if ( pCMS->pSpecialPos )
    1084             :                 {
    1085             :                     // apply attributes to font
    1086           0 :                     Seek( nOfst );
    1087           0 :                     lcl_GetCharRectInsideField( aInf, *pOrig, *pCMS, *pPor );
    1088             :                 }
    1089             :             }
    1090             :         }
    1091             : 
    1092             :         // special case: We are at the beginning of a BidiPortion or
    1093             :         // directly behind a BidiPortion
    1094        4094 :         if ( pCMS &&
    1095             :                 ( pLastBidiPor ||
    1096             :                 ( pPor &&
    1097        2004 :                   pPor->IsMultiPortion() &&
    1098           0 :                   ((SwMultiPortion*)pPor)->IsBidi() ) ) )
    1099             :         {
    1100             :             // we determine if the cursor has to blink before or behind
    1101             :             // the bidi portion
    1102           0 :             if ( pLastBidiPor )
    1103             :             {
    1104           0 :                 const sal_uInt8 nPortionLevel = pLastBidiPor->GetLevel();
    1105             : 
    1106           0 :                 if ( pCMS->nCursorBidiLevel >= nPortionLevel )
    1107             :                 {
    1108             :                     // we came from inside the bidi portion, we want to blink
    1109             :                     // behind the portion
    1110           0 :                     pOrig->Pos().X() -= nLastBidiPorWidth;
    1111             : 
    1112             :                     // Again, there is a special case: logically behind
    1113             :                     // the portion can actually mean that the cursor is inside
    1114             :                     // the portion. This can happen is the last portion
    1115             :                     // inside the bidi portion is a nested bidi portion
    1116             :                     SwLineLayout& rLineLayout =
    1117           0 :                             ((SwMultiPortion*)pLastBidiPor)->GetRoot();
    1118             : 
    1119           0 :                     const SwLinePortion *pLast = rLineLayout.FindLastPortion();
    1120           0 :                     if ( pLast->IsMultiPortion() )
    1121             :                     {
    1122             :                         OSL_ENSURE( ((SwMultiPortion*)pLast)->IsBidi(),
    1123             :                                  "Non-BidiPortion inside BidiPortion" );
    1124           0 :                         pOrig->Pos().X() += pLast->Width() +
    1125           0 :                                             pLast->CalcSpacing( nSpaceAdd, aInf );
    1126             :                     }
    1127             :                 }
    1128             :             }
    1129             :             else
    1130             :             {
    1131           0 :                 const sal_uInt8 nPortionLevel = ((SwBidiPortion*)pPor)->GetLevel();
    1132             : 
    1133           0 :                 if ( pCMS->nCursorBidiLevel >= nPortionLevel )
    1134             :                 {
    1135             :                     // we came from inside the bidi portion, we want to blink
    1136             :                     // behind the portion
    1137           0 :                     pOrig->Pos().X() += pPor->Width() +
    1138           0 :                                         pPor->CalcSpacing( nSpaceAdd, aInf );
    1139             :                 }
    1140             :             }
    1141             :         }
    1142             : 
    1143        2090 :         pOrig->Pos().X() += nX;
    1144             : 
    1145        2090 :         if ( pCMS && pCMS->bRealHeight )
    1146             :         {
    1147        2061 :             nTmpAscent = AdjustBaseLine( *pCurr, 0, nPorHeight, nPorAscent );
    1148        2061 :             if ( nTmpAscent > nPorAscent )
    1149         113 :                 pCMS->aRealHeight.X() = nTmpAscent - nPorAscent;
    1150             :             else
    1151        1948 :                 pCMS->aRealHeight.X() = 0;
    1152             :             OSL_ENSURE( nPorHeight, "GetCharRect: Missing Portion-Height" );
    1153        2061 :             if ( nTmpHeight > nPorHeight )
    1154         152 :                 pCMS->aRealHeight.Y() = nPorHeight;
    1155             :             else
    1156        1909 :                 pCMS->aRealHeight.Y() = nTmpHeight;
    1157             :         }
    1158        2264 :     }
    1159             : }
    1160             : 
    1161             : /*************************************************************************
    1162             :  *                      SwTxtCursor::GetCharRect()
    1163             :  *************************************************************************/
    1164             : 
    1165        2264 : sal_Bool SwTxtCursor::GetCharRect( SwRect* pOrig, const xub_StrLen nOfst,
    1166             :                                SwCrsrMoveState* pCMS, const long nMax )
    1167             : {
    1168        2264 :     CharCrsrToLine(nOfst);
    1169             : 
    1170             :     // Indicates that a position inside a special portion (field, number portion)
    1171             :     // is requested.
    1172        2264 :     const sal_Bool bSpecialPos = pCMS && pCMS->pSpecialPos;
    1173        2264 :     xub_StrLen nFindOfst = nOfst;
    1174             : 
    1175        2264 :     if ( bSpecialPos )
    1176             :     {
    1177           0 :         const sal_uInt8 nExtendRange = pCMS->pSpecialPos->nExtendRange;
    1178             : 
    1179             :         OSL_ENSURE( ! pCMS->pSpecialPos->nLineOfst || SP_EXTEND_RANGE_BEFORE != nExtendRange,
    1180             :                 "LineOffset AND Number Portion?" );
    1181             : 
    1182             :         // portions which are behind the string
    1183           0 :         if ( SP_EXTEND_RANGE_BEHIND == nExtendRange )
    1184           0 :             ++nFindOfst;
    1185             : 
    1186             :         // skip lines for fields which cover more than one line
    1187           0 :         for ( sal_uInt16 i = 0; i < pCMS->pSpecialPos->nLineOfst; i++ )
    1188           0 :             Next();
    1189             :     }
    1190             : 
    1191             :     // Adjustierung ggf. nachholen
    1192        2264 :     GetAdjusted();
    1193             : 
    1194        2264 :     const Point aCharPos( GetTopLeft() );
    1195        2264 :     sal_Bool bRet = sal_True;
    1196             : 
    1197        2264 :     _GetCharRect( pOrig, nFindOfst, pCMS );
    1198             : 
    1199        2264 :     const SwTwips nTmpRight = Right() - 12;
    1200             : 
    1201        2264 :     pOrig->Pos().X() += aCharPos.X();
    1202        2264 :     pOrig->Pos().Y() += aCharPos.Y();
    1203             : 
    1204        2264 :     if( pCMS && pCMS->b2Lines && pCMS->p2Lines )
    1205             :     {
    1206           0 :         pCMS->p2Lines->aLine.Pos().X() += aCharPos.X();
    1207           0 :         pCMS->p2Lines->aLine.Pos().Y() += aCharPos.Y();
    1208           0 :         pCMS->p2Lines->aPortion.Pos().X() += aCharPos.X();
    1209           0 :         pCMS->p2Lines->aPortion.Pos().Y() += aCharPos.Y();
    1210             :     }
    1211             : 
    1212        2264 :     if( pOrig->Left() > nTmpRight )
    1213           5 :         pOrig->Pos().X() = nTmpRight;
    1214             : 
    1215        2264 :     if( nMax )
    1216             :     {
    1217        2264 :         if( pOrig->Top() + pOrig->Height() > nMax )
    1218             :         {
    1219          13 :             if( pOrig->Top() > nMax )
    1220           0 :                 pOrig->Top( nMax );
    1221          13 :             pOrig->Height( nMax - pOrig->Top() );
    1222             :         }
    1223        2264 :         if ( pCMS && pCMS->bRealHeight && pCMS->aRealHeight.Y() >= 0 )
    1224             :         {
    1225        2235 :             long nTmp = pCMS->aRealHeight.X() + pOrig->Top();
    1226        2235 :             if( nTmp >= nMax )
    1227             :             {
    1228           0 :                 pCMS->aRealHeight.X() = nMax - pOrig->Top();
    1229           0 :                 pCMS->aRealHeight.Y() = 0;
    1230             :             }
    1231        2235 :             else if( nTmp + pCMS->aRealHeight.Y() > nMax )
    1232          13 :                 pCMS->aRealHeight.Y() = nMax - nTmp;
    1233             :         }
    1234             :     }
    1235        2264 :     long nOut = pOrig->Right() - GetTxtFrm()->Frm().Right();
    1236        2264 :     if( nOut > 0 )
    1237             :     {
    1238          10 :         if( GetTxtFrm()->Frm().Width() < GetTxtFrm()->Prt().Left()
    1239           5 :                                    + GetTxtFrm()->Prt().Width() )
    1240           0 :             nOut += GetTxtFrm()->Frm().Width() - GetTxtFrm()->Prt().Left()
    1241           0 :                     - GetTxtFrm()->Prt().Width();
    1242           5 :         if( nOut > 0 )
    1243           5 :             pOrig->Pos().X() -= nOut + 10;
    1244             :     }
    1245        2264 :     return bRet;
    1246             : }
    1247             : 
    1248             : /*************************************************************************
    1249             :  *                      SwTxtCursor::GetCrsrOfst()
    1250             :  *
    1251             :  * Return: Offset im String
    1252             :  *************************************************************************/
    1253           0 : xub_StrLen SwTxtCursor::GetCrsrOfst( SwPosition *pPos, const Point &rPoint,
    1254             :                      const MSHORT nChgNode, SwCrsrMoveState* pCMS ) const
    1255             : {
    1256             :     // Adjustierung ggf. nachholen
    1257           0 :     GetAdjusted();
    1258             : 
    1259           0 :     const XubString &rText = GetInfo().GetTxt();
    1260           0 :     xub_StrLen nOffset = 0;
    1261             : 
    1262             :     // x ist der horizontale Offset innerhalb der Zeile.
    1263           0 :     SwTwips x = rPoint.X();
    1264           0 :     const SwTwips nLeftMargin  = GetLineStart();
    1265           0 :     SwTwips nRightMargin = GetLineEnd();
    1266           0 :     if( nRightMargin == nLeftMargin )
    1267           0 :         nRightMargin += 30;
    1268             : 
    1269           0 :     const sal_Bool bLeftOver = x < nLeftMargin;
    1270           0 :     if( bLeftOver )
    1271           0 :         x = nLeftMargin;
    1272           0 :     const sal_Bool bRightOver = x > nRightMargin;
    1273           0 :     if( bRightOver )
    1274           0 :         x = nRightMargin;
    1275             : 
    1276           0 :     sal_Bool bRightAllowed = pCMS && ( pCMS->eState == MV_NONE );
    1277             : 
    1278             :     // Bis hierher in Dokumentkoordinaten.
    1279           0 :     x -= nLeftMargin;
    1280             : 
    1281           0 :     KSHORT nX = KSHORT( x );
    1282             : 
    1283             :     // Wenn es in der Zeile Attributwechsel gibt, den Abschnitt
    1284             :     // suchen, in dem nX liegt.
    1285           0 :     SwLinePortion *pPor = pCurr->GetFirstPortion();
    1286           0 :     xub_StrLen nCurrStart  = nStart;
    1287           0 :     sal_Bool bHolePortion = sal_False;
    1288           0 :     sal_Bool bLastHyph = sal_False;
    1289             : 
    1290           0 :     std::deque<sal_uInt16> *pKanaComp = pCurr->GetpKanaComp();
    1291           0 :     xub_StrLen nOldIdx = GetInfo().GetIdx();
    1292           0 :     MSHORT nSpaceIdx = 0;
    1293           0 :     size_t nKanaIdx = 0;
    1294           0 :     long nSpaceAdd = pCurr->IsSpaceAdd() ? pCurr->GetLLSpaceAdd( 0 ) : 0;
    1295           0 :     short nKanaComp = pKanaComp ? (*pKanaComp)[0] : 0;
    1296             : 
    1297             :     // nWidth ist die Breite der Zeile, oder die Breite des
    1298             :     // Abschnitts mit dem Fontwechsel, in dem nX liegt.
    1299             : 
    1300           0 :     KSHORT nWidth = pPor->Width();
    1301           0 :     if ( pCurr->IsSpaceAdd() || pKanaComp )
    1302             :     {
    1303           0 :         if ( pPor->InSpaceGrp() && nSpaceAdd )
    1304             :         {
    1305           0 :             ((SwTxtSizeInfo&)GetInfo()).SetIdx( nCurrStart );
    1306           0 :             nWidth = nWidth + sal_uInt16( pPor->CalcSpacing( nSpaceAdd, GetInfo() ) );
    1307             :         }
    1308           0 :         if( ( pPor->InFixMargGrp() && ! pPor->IsMarginPortion() ) ||
    1309           0 :             ( pPor->IsMultiPortion() && ((SwMultiPortion*)pPor)->HasTabulator() )
    1310             :           )
    1311             :         {
    1312           0 :             if ( pCurr->IsSpaceAdd() )
    1313             :             {
    1314           0 :                 if ( ++nSpaceIdx < pCurr->GetLLSpaceAddCount() )
    1315           0 :                     nSpaceAdd = pCurr->GetLLSpaceAdd( nSpaceIdx );
    1316             :                 else
    1317           0 :                     nSpaceAdd = 0;
    1318             :             }
    1319             : 
    1320           0 :             if( pKanaComp )
    1321             :             {
    1322           0 :                 if ( nKanaIdx + 1 < pKanaComp->size() )
    1323           0 :                     nKanaComp = (*pKanaComp)[++nKanaIdx];
    1324             :                 else
    1325           0 :                     nKanaComp = 0;
    1326             :             }
    1327             :         }
    1328             :     }
    1329             : 
    1330             :     KSHORT nWidth30;
    1331           0 :     if ( pPor->IsPostItsPortion() )
    1332           0 :         nWidth30 = 30 + pPor->GetViewWidth( GetInfo() ) / 2;
    1333             :     else
    1334           0 :         nWidth30 = ! nWidth && pPor->GetLen() && pPor->InToxRefOrFldGrp() ?
    1335             :                      30 :
    1336           0 :                      nWidth;
    1337             : 
    1338           0 :     while( pPor->GetPortion() && nWidth30 < nX && !pPor->IsBreakPortion() )
    1339             :     {
    1340           0 :         nX = nX - nWidth;
    1341           0 :         nCurrStart = nCurrStart + pPor->GetLen();
    1342           0 :         bHolePortion = pPor->IsHolePortion();
    1343           0 :         pPor = pPor->GetPortion();
    1344           0 :         nWidth = pPor->Width();
    1345           0 :         if ( pCurr->IsSpaceAdd() || pKanaComp )
    1346             :         {
    1347           0 :             if ( pPor->InSpaceGrp() && nSpaceAdd )
    1348             :             {
    1349           0 :                 ((SwTxtSizeInfo&)GetInfo()).SetIdx( nCurrStart );
    1350           0 :                 nWidth = nWidth + sal_uInt16( pPor->CalcSpacing( nSpaceAdd, GetInfo() ) );
    1351             :             }
    1352             : 
    1353           0 :             if( ( pPor->InFixMargGrp() && ! pPor->IsMarginPortion() ) ||
    1354           0 :                 ( pPor->IsMultiPortion() && ((SwMultiPortion*)pPor)->HasTabulator() )
    1355             :               )
    1356             :             {
    1357           0 :                 if ( pCurr->IsSpaceAdd() )
    1358             :                 {
    1359           0 :                     if ( ++nSpaceIdx < pCurr->GetLLSpaceAddCount() )
    1360           0 :                         nSpaceAdd = pCurr->GetLLSpaceAdd( nSpaceIdx );
    1361             :                     else
    1362           0 :                         nSpaceAdd = 0;
    1363             :                 }
    1364             : 
    1365           0 :                 if ( pKanaComp )
    1366             :                 {
    1367           0 :                     if( nKanaIdx + 1 < pKanaComp->size() )
    1368           0 :                         nKanaComp = (*pKanaComp)[++nKanaIdx];
    1369             :                     else
    1370           0 :                         nKanaComp = 0;
    1371             :                 }
    1372             :             }
    1373             :         }
    1374             : 
    1375           0 :         if ( pPor->IsPostItsPortion() )
    1376           0 :             nWidth30 = 30 +  pPor->GetViewWidth( GetInfo() ) / 2;
    1377             :         else
    1378           0 :             nWidth30 = ! nWidth && pPor->GetLen() && pPor->InToxRefOrFldGrp() ?
    1379             :                          30 :
    1380           0 :                          nWidth;
    1381           0 :         if( !pPor->IsFlyPortion() && !pPor->IsMarginPortion() )
    1382           0 :             bLastHyph = pPor->InHyphGrp();
    1383             :     }
    1384             : 
    1385           0 :     const sal_Bool bLastPortion = (0 == pPor->GetPortion());
    1386             : 
    1387           0 :     if( nX==nWidth )
    1388             :     {
    1389           0 :         SwLinePortion *pNextPor = pPor->GetPortion();
    1390           0 :         while( pNextPor && pNextPor->InFldGrp() && !pNextPor->Width() )
    1391             :         {
    1392           0 :             nCurrStart = nCurrStart + pPor->GetLen();
    1393           0 :             pPor = pNextPor;
    1394           0 :             if( !pPor->IsFlyPortion() && !pPor->IsMarginPortion() )
    1395           0 :                 bLastHyph = pPor->InHyphGrp();
    1396           0 :             pNextPor = pPor->GetPortion();
    1397             :         }
    1398             :     }
    1399             : 
    1400           0 :     ((SwTxtSizeInfo&)GetInfo()).SetIdx( nOldIdx );
    1401             : 
    1402           0 :     xub_StrLen nLength = pPor->GetLen();
    1403             : 
    1404           0 :     sal_Bool bFieldInfo = pCMS && pCMS->bFieldInfo;
    1405             : 
    1406           0 :     if( bFieldInfo && ( nWidth30 < nX || bRightOver || bLeftOver ||
    1407           0 :         ( pPor->InNumberGrp() && !pPor->IsFtnNumPortion() ) ||
    1408           0 :         ( pPor->IsMarginPortion() && nWidth > nX + 30 ) ) )
    1409           0 :         ((SwCrsrMoveState*)pCMS)->bPosCorr = sal_True;
    1410             : 
    1411             : 
    1412             :     // #i27615#
    1413           0 :     if (pCMS)
    1414             :     {
    1415           0 :         if( pCMS->bInFrontOfLabel)
    1416             :         {
    1417           0 :             if (! (2 * nX < nWidth && pPor->InNumberGrp() &&
    1418           0 :                    !pPor->IsFtnNumPortion()))
    1419           0 :                 pCMS->bInFrontOfLabel = sal_False;
    1420             :         }
    1421             :     }
    1422             : 
    1423             :     // 7684: Wir sind genau auf der HyphPortion angelangt und muessen dafuer
    1424             :     // sorgen, dass wir in dem String landen.
    1425             :     // 7993: Wenn die Laenge 0 ist muessen wir raus...
    1426           0 :     if( !nLength )
    1427             :     {
    1428           0 :         if( pCMS )
    1429             :         {
    1430           0 :             if( pPor->IsFlyPortion() && bFieldInfo )
    1431           0 :                 ((SwCrsrMoveState*)pCMS)->bPosCorr = sal_True;
    1432             : 
    1433           0 :             if (!bRightOver && nX)
    1434             :             {
    1435           0 :                 if( pPor->IsFtnNumPortion())
    1436           0 :                     ((SwCrsrMoveState*)pCMS)->bFtnNoInfo = sal_True;
    1437           0 :                 else if (pPor->InNumberGrp() ) // #i23726#
    1438             :                 {
    1439           0 :                     ((SwCrsrMoveState*)pCMS)->nInNumPostionOffset = nX;
    1440           0 :                     ((SwCrsrMoveState*)pCMS)->bInNumPortion = sal_True;
    1441             :                 }
    1442             :             }
    1443             :         }
    1444           0 :         if( !nCurrStart )
    1445           0 :             return 0;
    1446             : 
    1447             :          // 7849, 7816: auf pPor->GetHyphPortion kann nicht verzichtet werden!
    1448           0 :         if( bHolePortion || ( !bRightAllowed && bLastHyph ) ||
    1449           0 :             ( pPor->IsMarginPortion() && !pPor->GetPortion() &&
    1450             :             // 46598: In der letzten Zeile eines zentrierten Absatzes wollen
    1451             :             // wir auch mal hinter dem letzten Zeichen landen.
    1452           0 :               nCurrStart < rText.Len() ) )
    1453           0 :             --nCurrStart;
    1454           0 :         else if( pPor->InFldGrp() && ((SwFldPortion*)pPor)->IsFollow()
    1455             :                  && nWidth > nX )
    1456             :         {
    1457           0 :             if( bFieldInfo )
    1458           0 :                 --nCurrStart;
    1459             :             else
    1460             :             {
    1461           0 :                 KSHORT nHeight = pPor->Height();
    1462           0 :                 if ( !nHeight || nHeight > nWidth )
    1463           0 :                     nHeight = nWidth;
    1464           0 :                 if( nChgNode && nWidth - nHeight/2 > nX )
    1465           0 :                     --nCurrStart;
    1466             :             }
    1467             :         }
    1468           0 :         return nCurrStart;
    1469             :     }
    1470           0 :     if ( 1 == nLength )
    1471             :     {
    1472           0 :         if ( nWidth )
    1473             :         {
    1474             :             // Sonst kommen wir nicht mehr in zeichengeb. Rahmen hinein...
    1475           0 :             if( !( nChgNode && pPos && pPor->IsFlyCntPortion() ) )
    1476             :             {
    1477           0 :                 if ( pPor->InFldGrp() ||
    1478           0 :                      ( pPor->IsMultiPortion() &&
    1479           0 :                        ((SwMultiPortion*)pPor)->IsBidi()  ) )
    1480             :                 {
    1481           0 :                     KSHORT nHeight = 0;
    1482           0 :                     if( !bFieldInfo )
    1483             :                     {
    1484           0 :                         nHeight = pPor->Height();
    1485           0 :                         if ( !nHeight || nHeight > nWidth )
    1486           0 :                             nHeight = nWidth;
    1487             :                     }
    1488             : 
    1489           0 :                     if( nWidth - nHeight/2 <= nX &&
    1490           0 :                         ( ! pPor->InFldGrp() ||
    1491           0 :                           !((SwFldPortion*)pPor)->HasFollow() ) )
    1492           0 :                         ++nCurrStart;
    1493             :                 }
    1494           0 :                 else if ( ( !pPor->IsFlyPortion() || ( pPor->GetPortion() &&
    1495           0 :                     !pPor->GetPortion()->IsMarginPortion() &&
    1496           0 :                     !pPor->GetPortion()->IsHolePortion() ) )
    1497             :                          && ( nWidth/2 < nX ) &&
    1498             :                          ( !bFieldInfo ||
    1499           0 :                             ( pPor->GetPortion() &&
    1500           0 :                               pPor->GetPortion()->IsPostItsPortion() ) )
    1501             :                          && ( bRightAllowed || !bLastHyph ))
    1502           0 :                     ++nCurrStart;
    1503             : 
    1504             :                 // if we want to get the position inside the field, we should not return
    1505           0 :                 if ( !pCMS || !pCMS->pSpecialPos )
    1506           0 :                     return nCurrStart;
    1507             :             }
    1508             :         }
    1509             :         else
    1510             :         {
    1511           0 :             if ( pPor->IsPostItsPortion() || pPor->IsBreakPortion() ||
    1512           0 :                  pPor->InToxRefGrp() )
    1513           0 :                 return nCurrStart;
    1514           0 :             if ( pPor->InFldGrp() )
    1515             :             {
    1516           0 :                 if( bRightOver && !((SwFldPortion*)pPor)->HasFollow() )
    1517           0 :                     ++nCurrStart;
    1518           0 :                 return nCurrStart;
    1519             :             }
    1520             :         }
    1521             :     }
    1522             : 
    1523           0 :     if( bLastPortion && (pCurr->GetNext() || pFrm->GetFollow() ) )
    1524           0 :         --nLength;
    1525             : 
    1526           0 :     if( nWidth > nX ||
    1527           0 :       ( nWidth == nX && pPor->IsMultiPortion() && ((SwMultiPortion*)pPor)->IsDouble() ) )
    1528             :     {
    1529           0 :         if( pPor->IsMultiPortion() )
    1530             :         {
    1531             :             // In a multi-portion we use GetCrsrOfst()-function recursively
    1532           0 :             SwTwips nTmpY = rPoint.Y() - pCurr->GetAscent() + pPor->GetAscent();
    1533             :             // if we are in the first line of a double line portion, we have
    1534             :             // to add a value to nTmpY for not staying in this line
    1535             :             // we also want to skip the first line, if we are inside ruby
    1536           0 :             if ( ( ((SwTxtSizeInfo*)pInf)->IsMulti() &&
    1537           0 :                    ((SwTxtSizeInfo*)pInf)->IsFirstMulti() ) ||
    1538           0 :                  ( ((SwMultiPortion*)pPor)->IsRuby() &&
    1539           0 :                    ((SwMultiPortion*)pPor)->OnTop() ) )
    1540           0 :                 nTmpY += ((SwMultiPortion*)pPor)->Height();
    1541             : 
    1542             :             // Important for cursor traveling in ruby portions:
    1543             :             // We have to set nTmpY to 0 in order to stay in the first row
    1544             :             // if the phonetic line is the second row
    1545           0 :             if (   ((SwMultiPortion*)pPor)->IsRuby() &&
    1546           0 :                  ! ((SwMultiPortion*)pPor)->OnTop() )
    1547           0 :                 nTmpY = 0;
    1548             : 
    1549             :             SwTxtCursorSave aSave( (SwTxtCursor*)this, (SwMultiPortion*)pPor,
    1550           0 :                  nTmpY, nX, nCurrStart, nSpaceAdd );
    1551             : 
    1552           0 :             SwLayoutModeModifier aLayoutModeModifier( *GetInfo().GetOut() );
    1553           0 :             if ( ((SwMultiPortion*)pPor)->IsBidi() )
    1554             :             {
    1555           0 :                 const sal_uInt8 nBidiLevel = ((SwBidiPortion*)pPor)->GetLevel();
    1556           0 :                 aLayoutModeModifier.Modify( nBidiLevel % 2 );
    1557             :             }
    1558             : 
    1559           0 :             if( ((SwMultiPortion*)pPor)->HasRotation() )
    1560             :             {
    1561           0 :                 nTmpY -= nY;
    1562           0 :                 if( !((SwMultiPortion*)pPor)->IsRevers() )
    1563           0 :                     nTmpY = pPor->Height() - nTmpY;
    1564           0 :                 if( nTmpY < 0 )
    1565           0 :                     nTmpY = 0;
    1566           0 :                 nX = (KSHORT)nTmpY;
    1567             :             }
    1568             : 
    1569           0 :             if( ((SwMultiPortion*)pPor)->HasBrackets() )
    1570             :             {
    1571           0 :                 sal_uInt16 nPreWidth = ((SwDoubleLinePortion*)pPor)->PreWidth();
    1572           0 :                 if ( nX > nPreWidth )
    1573           0 :                     nX = nX - nPreWidth;
    1574             :                 else
    1575           0 :                     nX = 0;
    1576             :             }
    1577             : 
    1578           0 :             return GetCrsrOfst( pPos, Point( GetLineStart() + nX, rPoint.Y() ),
    1579           0 :                                 nChgNode, pCMS );
    1580             :         }
    1581           0 :         if( pPor->InTxtGrp() )
    1582             :         {
    1583             :             sal_uInt8 nOldProp;
    1584           0 :             if( GetPropFont() )
    1585             :             {
    1586           0 :                 ((SwFont*)GetFnt())->SetProportion( GetPropFont() );
    1587           0 :                 nOldProp = GetFnt()->GetPropr();
    1588             :             }
    1589             :             else
    1590           0 :                 nOldProp = 0;
    1591             :             {
    1592           0 :                 SwTxtSizeInfo aSizeInf( GetInfo(), rText, nCurrStart );
    1593           0 :                 ((SwTxtCursor*)this)->SeekAndChg( aSizeInf );
    1594           0 :                 SwTxtSlot aDiffTxt( &aSizeInf, ((SwTxtPortion*)pPor), false, false );
    1595           0 :                 SwFontSave aSave( aSizeInf, pPor->IsDropPortion() ?
    1596           0 :                         ((SwDropPortion*)pPor)->GetFnt() : NULL );
    1597             : 
    1598           0 :                 SwParaPortion* pPara = (SwParaPortion*)GetInfo().GetParaPortion();
    1599             :                 OSL_ENSURE( pPara, "No paragraph!" );
    1600             : 
    1601             :                 SwDrawTextInfo aDrawInf( aSizeInf.GetVsh(),
    1602           0 :                                          *aSizeInf.GetOut(),
    1603           0 :                                          &pPara->GetScriptInfo(),
    1604           0 :                                          aSizeInf.GetTxt(),
    1605           0 :                                          aSizeInf.GetIdx(),
    1606           0 :                                          pPor->GetLen() );
    1607           0 :                 aDrawInf.SetOfst( nX );
    1608             : 
    1609           0 :                 if ( nSpaceAdd )
    1610             :                 {
    1611             :                     xub_StrLen nCharCnt;
    1612             :                     // #i41860# Thai justified alignemt needs some
    1613             :                     // additional information:
    1614           0 :                     aDrawInf.SetNumberOfBlanks( pPor->InTxtGrp() ?
    1615           0 :                                                 static_cast<const SwTxtPortion*>(pPor)->GetSpaceCnt( aSizeInf, nCharCnt ) :
    1616           0 :                                                 0 );
    1617             :                 }
    1618             : 
    1619           0 :                 if ( pPor->InFldGrp() && pCMS && pCMS->pSpecialPos )
    1620           0 :                     aDrawInf.SetLen( STRING_LEN ); // SMARTTAGS
    1621             : 
    1622           0 :                 aDrawInf.SetSpace( nSpaceAdd );
    1623           0 :                 aDrawInf.SetFont( aSizeInf.GetFont() );
    1624           0 :                 aDrawInf.SetFrm( pFrm );
    1625           0 :                 aDrawInf.SetSnapToGrid( aSizeInf.SnapToGrid() );
    1626           0 :                 aDrawInf.SetPosMatchesBounds( pCMS && pCMS->bPosMatchesBounds );
    1627             : 
    1628           0 :                 if ( SW_CJK == aSizeInf.GetFont()->GetActual() &&
    1629           0 :                      pPara->GetScriptInfo().CountCompChg() &&
    1630           0 :                     ! pPor->InFldGrp() )
    1631           0 :                     aDrawInf.SetKanaComp( nKanaComp );
    1632             : 
    1633           0 :                 nLength = aSizeInf.GetFont()->_GetCrsrOfst( aDrawInf );
    1634             : 
    1635             :                 // get position inside field portion?
    1636           0 :                 if ( pPor->InFldGrp() && pCMS && pCMS->pSpecialPos )
    1637             :                 {
    1638           0 :                     pCMS->pSpecialPos->nCharOfst = nLength;
    1639           0 :                     nLength = 0; // SMARTTAGS
    1640             :                 }
    1641             : 
    1642             :                 // set cursor bidi level
    1643           0 :                 if ( pCMS )
    1644             :                     ((SwCrsrMoveState*)pCMS)->nCursorBidiLevel =
    1645           0 :                         aDrawInf.GetCursorBidiLevel();
    1646             : 
    1647           0 :                 if( bFieldInfo && nLength == pPor->GetLen() &&
    1648           0 :                     ( ! pPor->GetPortion() ||
    1649           0 :                       ! pPor->GetPortion()->IsPostItsPortion() ) )
    1650           0 :                     --nLength;
    1651             :             }
    1652           0 :             if( nOldProp )
    1653           0 :                 ((SwFont*)GetFnt())->SetProportion( nOldProp );
    1654             :         }
    1655             :         else
    1656             :         {
    1657           0 :             if( nChgNode && pPos && pPor->IsFlyCntPortion()
    1658           0 :                 && !( (SwFlyCntPortion*)pPor )->IsDraw() )
    1659             :             {
    1660             :                 // JP 24.11.94: liegt die Pos nicht im Fly, dann
    1661             :                 //              darf nicht mit STRING_LEN returnt werden!
    1662             :                 //              (BugId: 9692 + Aenderung in feshview)
    1663           0 :                 SwFlyInCntFrm *pTmp = ( (SwFlyCntPortion*)pPor )->GetFlyFrm();
    1664           0 :                 sal_Bool bChgNode = 1 < nChgNode;
    1665           0 :                 if( !bChgNode )
    1666             :                 {
    1667           0 :                     SwFrm* pLower = pTmp->GetLower();
    1668           0 :                     if( pLower && (pLower->IsTxtFrm() || pLower->IsLayoutFrm()) )
    1669           0 :                         bChgNode = sal_True;
    1670             :                 }
    1671           0 :                 Point aTmpPoint( rPoint );
    1672             : 
    1673           0 :                 if ( pFrm->IsRightToLeft() )
    1674           0 :                     pFrm->SwitchLTRtoRTL( aTmpPoint );
    1675             : 
    1676           0 :                 if ( pFrm->IsVertical() )
    1677           0 :                     pFrm->SwitchHorizontalToVertical( aTmpPoint );
    1678             : 
    1679           0 :                 if( bChgNode && pTmp->Frm().IsInside( aTmpPoint ) &&
    1680           0 :                     !( pTmp->IsProtected() ) )
    1681             :                 {
    1682             :                     nLength = ((SwFlyCntPortion*)pPor)->
    1683           0 :                               GetFlyCrsrOfst( nX, aTmpPoint, pPos, pCMS );
    1684             :                     // Sobald der Frame gewechselt wird, muessen wir aufpassen, dass
    1685             :                     // unser Font wieder im OutputDevice steht.
    1686             :                     // vgl. Paint und new SwFlyCntPortion !
    1687           0 :                     ((SwTxtSizeInfo*)pInf)->SelectFont();
    1688             : 
    1689             :                     // 6776: Das pIter->GetCrsrOfst returnt
    1690             :                     // aus einer Verschachtelung mit STRING_LEN.
    1691           0 :                     return STRING_LEN;
    1692             :                 }
    1693             :             }
    1694             :             else
    1695           0 :                 nLength = pPor->GetCrsrOfst( nX );
    1696             :         }
    1697             :     }
    1698           0 :     nOffset = nCurrStart + nLength;
    1699             : 
    1700             :     // 7684: Wir sind vor der HyphPortion angelangt und muessen dafuer
    1701             :     // sorgen, dass wir in dem String landen.
    1702             :     // Bei Zeilenenden vor FlyFrms muessen ebenso behandelt werden.
    1703             : 
    1704           0 :     if( nOffset && pPor->GetLen() == nLength && pPor->GetPortion() &&
    1705           0 :         !pPor->GetPortion()->GetLen() && pPor->GetPortion()->InHyphGrp() )
    1706           0 :         --nOffset;
    1707             : 
    1708           0 :     return nOffset;
    1709             : }
    1710             : 
    1711             : /** Looks for text portions which are inside the given rectangle
    1712             : 
    1713             :     For a rectangular text selection every text portions which is inside the given
    1714             :     rectangle has to be put into the SwSelectionList as SwPaM
    1715             :     From these SwPaM the SwCursors will be created.
    1716             : 
    1717             :     @param rSelList
    1718             :     The container for the overlapped text portions
    1719             : 
    1720             :     @param rRect
    1721             :     A rectangle in document coordinates, text inside this rectangle has to be
    1722             :     selected.
    1723             : 
    1724             :     @return [ true, false ]
    1725             :     true if any overlapping text portion has been found and put into list
    1726             :     false if no portion overlaps, the list has been unchanged
    1727             : */
    1728           0 : bool SwTxtFrm::FillSelection( SwSelectionList& rSelList, const SwRect& rRect ) const
    1729             : {
    1730           0 :     bool bRet = false;
    1731             :     // PaintArea() instead Frm() for negative indents
    1732           0 :     SwRect aTmpFrm( PaintArea() );
    1733           0 :     if( !rRect.IsOver( aTmpFrm ) )
    1734           0 :         return false;
    1735           0 :     if( rSelList.checkContext( this ) )
    1736             :     {
    1737           0 :         SwRect aRect( aTmpFrm );
    1738           0 :         aRect.Intersection( rRect );
    1739             :         // rNode without const to create SwPaMs
    1740           0 :         SwCntntNode &rNode = const_cast<SwCntntNode&>( *GetNode() );
    1741           0 :         SwNodeIndex aIdx( rNode );
    1742           0 :         SwPosition aPosL( aIdx, SwIndex( &rNode, 0 ) );
    1743           0 :         if( IsEmpty() )
    1744             :         {
    1745           0 :             SwPaM *pPam = new SwPaM( aPosL, aPosL );
    1746           0 :             rSelList.insertPaM( pPam );
    1747             :         }
    1748           0 :         else if( aRect.HasArea() )
    1749             :         {
    1750           0 :             xub_StrLen nOld = STRING_LEN;
    1751           0 :             SwPosition aPosR( aPosL );
    1752           0 :             Point aPoint;
    1753           0 :             SwTxtInfo aInf( const_cast<SwTxtFrm*>(this) );
    1754           0 :             SwTxtIter aLine( const_cast<SwTxtFrm*>(this), &aInf );
    1755             :             // We have to care for top-to-bottom layout, where right becomes top etc.
    1756           0 :             SWRECTFN( this )
    1757           0 :             SwTwips nTop = (aRect.*fnRect->fnGetTop)();
    1758           0 :             SwTwips nBottom = (aRect.*fnRect->fnGetBottom)();
    1759           0 :             SwTwips nLeft = (aRect.*fnRect->fnGetLeft)();
    1760           0 :             SwTwips nRight = (aRect.*fnRect->fnGetRight)();
    1761           0 :             SwTwips nY = aLine.Y(); // Top position of the first line
    1762           0 :             SwTwips nLastY = nY;
    1763           0 :             while( nY < nTop && aLine.Next() ) // line above rectangle
    1764             :             {
    1765           0 :                 nLastY = nY;
    1766           0 :                 nY = aLine.Y();
    1767             :             }
    1768           0 :             bool bLastLine = false;
    1769           0 :             if( nY < nTop && !aLine.GetNext() )
    1770             :             {
    1771           0 :                 bLastLine = true;
    1772           0 :                 nY += aLine.GetLineHeight();
    1773             :             }
    1774           0 :             do // check the lines for overlapping
    1775             :             {
    1776           0 :                 if( nLastY < nTop ) // if the last line was above rectangle
    1777           0 :                     nLastY = nTop;
    1778           0 :                 if( nY > nBottom ) // if the current line leaves the rectangle
    1779           0 :                     nY = nBottom;
    1780           0 :                 if( nY >= nLastY ) // gotcha: overlapping
    1781             :                 {
    1782           0 :                     nLastY += nY;
    1783           0 :                     nLastY /= 2;
    1784           0 :                     if( bVert )
    1785             :                     {
    1786           0 :                         aPoint.X() = nLastY;
    1787           0 :                         aPoint.Y() = nLeft;
    1788             :                     }
    1789             :                     else
    1790             :                     {
    1791           0 :                         aPoint.X() = nLeft;
    1792           0 :                         aPoint.Y() = nLastY;
    1793             :                     }
    1794             :                     // Looking for the position of the left border of the rectangle
    1795             :                     // in this text line
    1796           0 :                     SwCrsrMoveState aState( MV_UPDOWN );
    1797           0 :                     if( GetCrsrOfst( &aPosL, aPoint, &aState ) )
    1798             :                     {
    1799           0 :                         if( bVert )
    1800             :                         {
    1801           0 :                             aPoint.X() = nLastY;
    1802           0 :                             aPoint.Y() = nRight;
    1803             :                         }
    1804             :                         else
    1805             :                         {
    1806           0 :                             aPoint.X() = nRight;
    1807           0 :                             aPoint.Y() = nLastY;
    1808             :                         }
    1809             :                         // If we get a right position and if the left position
    1810             :                         // is not the same like the left position of the line before
    1811             :                         // which cound happen e.g. for field portions or fly frames
    1812             :                         // a SwPaM will be inserted with these positions
    1813           0 :                         if( GetCrsrOfst( &aPosR, aPoint, &aState ) &&
    1814           0 :                             nOld != aPosL.nContent.GetIndex() )
    1815             :                         {
    1816           0 :                             SwPaM *pPam = new SwPaM( aPosL, aPosR );
    1817           0 :                             rSelList.insertPaM( pPam );
    1818           0 :                             nOld = aPosL.nContent.GetIndex();
    1819             :                         }
    1820             :                     }
    1821             :                 }
    1822           0 :                 if( aLine.Next() )
    1823             :                 {
    1824           0 :                     nLastY = nY;
    1825           0 :                     nY = aLine.Y();
    1826             :                 }
    1827           0 :                 else if( !bLastLine )
    1828             :                 {
    1829           0 :                     bLastLine = true;
    1830           0 :                     nLastY = nY;
    1831           0 :                     nY += aLine.GetLineHeight();
    1832             :                 }
    1833             :                 else
    1834           0 :                     break;
    1835           0 :             }while( nLastY < nBottom );
    1836           0 :         }
    1837             :     }
    1838           0 :     if( GetDrawObjs() )
    1839             :     {
    1840           0 :         const SwSortedObjs &rObjs = *GetDrawObjs();
    1841           0 :         for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
    1842             :         {
    1843           0 :             const SwAnchoredObject* pAnchoredObj = rObjs[i];
    1844           0 :             if( !pAnchoredObj->ISA(SwFlyFrm) )
    1845           0 :                 continue;
    1846           0 :             const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pAnchoredObj);
    1847           0 :             if( pFly->IsFlyInCntFrm() && pFly->FillSelection( rSelList, rRect ) )
    1848           0 :                 bRet = true;
    1849             :         }
    1850             :     }
    1851           0 :     return bRet;
    1852             : }
    1853             : 
    1854             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10