/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/


#ifdef _MSC_VER
#pragma hdrstop
#endif

#include <osl/diagnose.h>
#include "paratr.hxx"

#include <horiornt.hxx>


#include <bf_svx/adjitem.hxx>
#include <bf_svx/lspcitem.hxx>
#include <bf_svx/lrspitem.hxx>

#include <frmatr.hxx>

#ifdef VERTICAL_LAYOUT
#include <pagedesc.hxx> // SwPageDesc
#endif

#include "txtcfg.hxx"
#include "itrtxt.hxx"

#include "porfld.hxx"       // SwFldPortion::IsFollow()
#include "porfly.hxx"       // GetFlyCrsrOfst()
#include "pordrop.hxx"
#include "crstate.hxx"      // SwCrsrMoveState
#include <pormulti.hxx>     // SwMultiPortion
namespace binfilter {

// Nicht reentrant !!!
// wird in GetCharRect gesetzt und im UnitUp/Down ausgewertet.
sal_Bool SwTxtCursor::bRightMargin = sal_False;


/*************************************************************************
 *                    lcl_GetPositionInsideField
 *
 * After calculating the position of a character during GetCharRect
 * this function allows to find the coordinates of a position (defined
 * in pCMS->pSpecialPos) inside a special portion (e.g., a field)
 *************************************************************************/

/*************************************************************************
 *                SwTxtMargin::CtorInit()
 *************************************************************************/
/*M*/ void SwTxtMargin::CtorInit( SwTxtFrm *pFrm1, SwTxtSizeInfo *pNewInf )
/*M*/ {
/*M*/   SwTxtIter::CtorInit( pFrm1, pNewInf );
/*M*/
/*M*/   pInf = pNewInf;
/*M*/   GetInfo().SetFont( GetFnt() );
/*M*/   SwTxtNode *pNode = pFrm1->GetTxtNode();
/*M*/
/*M*/   const SvxLRSpaceItem &rSpace =
/*M*/       pFrm1->GetTxtNode()->GetSwAttrSet().GetLRSpace();
/*M*/
/*M*/ #ifdef BIDI
/*M*/     //
/*M*/     // Carefully adjust the text formatting ranges.
/*M*/     //
/*M*/     const int nLMWithNum = pNode->GetLeftMarginWithNum( sal_True );
/*M*/     if ( pFrm1->IsRightToLeft() )
/*M*/         nLeft = pFrm1->Frm().Left() + pFrm1->Prt().Left() + nLMWithNum -
/*M*/                 ( rSpace.GetTxtFirstLineOfst() < 0 ?
/*M*/                   rSpace.GetTxtFirstLineOfst() :
/*M*/                   0 );
/*M*/     else
/*M*/         nLeft = Max( long( rSpace.GetTxtLeft() + nLMWithNum), pFrm1->Prt().Left() ) +
/*M*/                 pFrm1->Frm().Left();
/*M*/ #else
/*M*/     nLeft = Max( long( rSpace.GetTxtLeft() + pNode->GetLeftMarginWithNum(sal_True) ),
/*M*/                  pFrm1->Prt().Left() ) +
/*M*/             pFrm1->Frm().Left();
/*M*/ #endif
/*M*/
/*M*/     nRight = pFrm1->Frm().Left() + pFrm1->Prt().Left() + pFrm1->Prt().Width();
/*M*/
/*M*/   if( nLeft >= nRight )
/*M*/       nLeft = pFrm1->Prt().Left() + pFrm1->Frm().Left();
/*M*/   if( nLeft >= nRight ) // z.B. bei grossen Absatzeinzuegen in schmalen Tabellenspalten
/*M*/       nRight = nLeft + 1; // einen goennen wir uns immer
/*M*/   if( pFrm1->IsFollow() && pFrm1->GetOfst() )
/*M*/       nFirst = nLeft;
/*M*/   else
/*M*/   {
/*M*/       short nFLOfst;
/*M*/       long nFirstLineOfs;
/*M*/       if( !pNode->GetFirstLineOfsWithNum( nFLOfst ) &&
/*M*/           rSpace.IsAutoFirst() )
/*M*/       {
/*M*/           nFirstLineOfs = GetFnt()->GetSize( GetFnt()->GetActual() ).Height();
/*M*/           const SvxLineSpacingItem *pSpace = aLineInf.GetLineSpacing();
/*M*/           if( pSpace )
/*M*/           {
/*M*/               switch( pSpace->GetLineSpaceRule() )
/*M*/               {
/*M*/                   case SVX_LINE_SPACE_AUTO:
/*M*/                   break;
/*M*/                   case SVX_LINE_SPACE_MIN:
/*M*/                   {
/*M*/                       if( nFirstLineOfs < KSHORT( pSpace->GetLineHeight() ) )
/*M*/                           nFirstLineOfs = pSpace->GetLineHeight();
/*M*/                       break;
/*M*/                   }
/*M*/                   case SVX_LINE_SPACE_FIX:
/*M*/                       nFirstLineOfs = pSpace->GetLineHeight();
/*M*/                   break;
/*M*/                   default: OSL_FAIL( ": unknown LineSpaceRule" );
/*M*/               }
/*M*/               switch( pSpace->GetInterLineSpaceRule() )
/*M*/               {
/*M*/                   case SVX_INTER_LINE_SPACE_OFF:
/*M*/                   break;
/*M*/                   case SVX_INTER_LINE_SPACE_PROP:
/*M*/                   {
/*M*/                       long nTmp = pSpace->GetPropLineSpace();
/*M*/                       // 50% ist das Minimum, bei 0% schalten wir auf
/*M*/                       // den Defaultwert 100% um ...
/*M*/                       if( nTmp < 50 )
/*M*/                           nTmp = nTmp ? 50 : 100;
/*M*/
/*M*/                       nTmp *= nFirstLineOfs;
/*M*/                       nTmp /= 100;
/*M*/                       if( !nTmp )
/*M*/                           ++nTmp;
/*M*/                       nFirstLineOfs = (KSHORT)nTmp;
/*M*/                       break;
/*M*/                   }
/*M*/                   case SVX_INTER_LINE_SPACE_FIX:
/*M*/                   {
/*M*/                       nFirstLineOfs += pSpace->GetInterLineSpace();
/*M*/                       break;
/*M*/                   }
/*M*/                   default: OSL_FAIL( ": unknown InterLineSpaceRule" );
/*M*/               }
/*M*/           }
/*M*/       }
/*M*/       else
/*M*/           nFirstLineOfs = nFLOfst;
/*M*/
/*M*/ #ifdef BIDI
/*M*/         if ( pFrm1->IsRightToLeft() )
/*M*/             nFirst = nLeft + nFirstLineOfs;
/*M*/         else
/*M*/             nFirst = Max( rSpace.GetTxtLeft() + nLMWithNum + nFirstLineOfs,
/*M*/                           pFrm1->Prt().Left() ) + pFrm1->Frm().Left();
/*M*/ #else
/*M*/       nFirst = Max( rSpace.GetTxtLeft() + pNode->GetLeftMarginWithNum( sal_True )
/*M*/           + nFirstLineOfs, pFrm1->Prt().Left() ) + pFrm1->Frm().Left();
/*M*/ #endif
/*M*/
/*M*/       if( nFirst >= nRight )
/*M*/           nFirst = nRight - 1;
/*M*/   }
/*M*/     const SvxAdjustItem& rAdjust = pFrm1->GetTxtNode()->GetSwAttrSet().GetAdjust();
/*M*/   nAdjust = rAdjust.GetAdjust();
/*M*/
/*M*/ #ifdef BIDI
/*M*/     // left is left and right is right
/*M*/     if ( pFrm1->IsRightToLeft() )
/*M*/     {
/*M*/         if ( SVX_ADJUST_LEFT == nAdjust )
/*M*/             nAdjust = SVX_ADJUST_RIGHT;
/*M*/         else if ( SVX_ADJUST_RIGHT == nAdjust )
/*M*/             nAdjust = SVX_ADJUST_LEFT;
/*M*/     }
/*M*/ #endif
/*M*/
/*M*/   bOneBlock = rAdjust.GetOneWord() == SVX_ADJUST_BLOCK;
/*M*/   bLastBlock = rAdjust.GetLastBlock() == SVX_ADJUST_BLOCK;
/*M*/   bLastCenter = rAdjust.GetLastBlock() == SVX_ADJUST_CENTER;
/*N*/ #if OSL_DEBUG_LEVEL > 1
/*M*/   static sal_Bool bOne = sal_False;
/*M*/   static sal_Bool bLast = sal_False;
/*M*/   static sal_Bool bCenter = sal_False;
/*M*/   bOneBlock |= bOne;
/*M*/   bLastBlock |= bLast;
/*M*/   bLastCenter |= bCenter;
/*M*/ #endif
/*M*/   DropInit();
/*M*/ }

/*************************************************************************
 *                SwTxtMargin::DropInit()
 *************************************************************************/
/*N*/ void SwTxtMargin::DropInit()
/*N*/ {
/*N*/   nDropLeft = nDropLines = nDropHeight = nDropDescent = 0;
/*N*/   const SwParaPortion *pPara = GetInfo().GetParaPortion();
/*N*/   if( pPara )
/*N*/   {
/*N*/       const SwDropPortion *pPorDrop = pPara->FindDropPortion();
/*N*/       if ( pPorDrop )
/*N*/       {
/*N*/           nDropLeft = pPorDrop->GetDropLeft();
/*N*/           nDropLines = pPorDrop->GetLines();
/*N*/           nDropHeight = pPorDrop->GetDropHeight();
/*N*/           nDropDescent = pPorDrop->GetDropDescent();
/*N*/       }
/*N*/   }
/*N*/ }

/*************************************************************************
 *                SwTxtMargin::GetLineStart()
 *************************************************************************/

// Unter Beruecksichtigung des Erstzeileneinzuges und der angebenen Breite.
/*N*/ SwTwips SwTxtMargin::GetLineStart() const
/*N*/ {
/*N*/   SwTwips nRet = GetLeftMargin();
/*N*/   if( GetAdjust() != SVX_ADJUST_LEFT &&
/*N*/       !pCurr->GetFirstPortion()->IsMarginPortion() )
/*N*/   {
/*N*/       // Wenn die erste Portion ein Margin ist, dann wird das
/*N*/       // Adjustment durch die Portions ausgedrueckt.
/*N*/       if( GetAdjust() == SVX_ADJUST_RIGHT )
/*N*/           nRet = Right() - CurrWidth();
/*N*/       else if( GetAdjust() == SVX_ADJUST_CENTER )
/*N*/           nRet += (GetLineWidth() - CurrWidth()) / 2;
/*N*/   }
/*N*/   return nRet;
/*N*/ }

/*************************************************************************
 *                      SwTxtCursor::CtorInit()
 *************************************************************************/
/*N*/ void SwTxtCursor::CtorInit( SwTxtFrm *pFrm2, SwTxtSizeInfo *pInf2 )
/*N*/ {
/*N*/   SwTxtMargin::CtorInit( pFrm2, pInf2 );
/*N*/   // 6096: Vorsicht, die Iteratoren sind abgeleitet!
/*N*/   // GetInfo().SetOut( GetInfo().GetWin() );
/*N*/ }

/*************************************************************************
 * void SwTxtCursor::_GetCharRect(..)
 * internal function, called by SwTxtCursor::GetCharRect() to calculate
 * the relative character position in the current line.
 * pOrig referes to x and y coordinates, width and height of the cursor
 * pCMS is used for restricting the cursor, if there are different font
 * heights in one line ( first value = offset to y of pOrig, second
 * value = real height of (shortened) cursor
 *************************************************************************/

/*N*/ void SwTxtCursor::_GetCharRect( SwRect* pOrig, const xub_StrLen nOfst,
/*N*/     SwCrsrMoveState* pCMS )
/*N*/ {
/*N*/   const XubString &rText = GetInfo().GetTxt();
/*N*/   SwTxtSizeInfo aInf( GetInfo(), rText, nStart );
/*N*/   if( GetPropFont() )
/*?*/       aInf.GetFont()->SetProportion( GetPropFont() );
/*N*/   KSHORT nTmpAscent, nTmpHeight;  // Zeilenhoehe
/*N*/   CalcAscentAndHeight( nTmpAscent, nTmpHeight );
/*N*/   const Size  aCharSize( 1, nTmpHeight );
/*N*/   const Point aCharPos;
/*N*/   pOrig->Pos( aCharPos );
/*N*/   pOrig->SSize( aCharSize );
/*N*/
/*N*/     // If we are looking for a position inside a field which covers
/*N*/     // more than one line we may not skip any "empty portions" at the
/*N*/     // beginning of a line
/*N*/     const sal_Bool bInsideFirstField = pCMS && pCMS->pSpecialPos &&
/*N*/                                        ( pCMS->pSpecialPos->nLineOfst ||
/*N*/                                          SP_EXTEND_RANGE_BEFORE ==
/*N*/                                          pCMS->pSpecialPos->nExtendRange );
/*N*/
/*N*/   sal_Bool bWidth = pCMS && pCMS->bRealWidth;
/*N*/   if( !pCurr->GetLen() && !pCurr->Width() )
/*N*/   {
/*N*/       if ( pCMS && pCMS->bRealHeight )
/*N*/       {
/*N*/           pCMS->aRealHeight.X() = 0;
/*N*/           pCMS->aRealHeight.Y() = nTmpHeight;
/*N*/       }
/*N*/   }
/*N*/   else
/*N*/   {
/*N*/       KSHORT nPorHeight = nTmpHeight;
/*N*/       KSHORT nPorAscent = nTmpAscent;
/*N*/       SwTwips nX = 0;
/*N*/       SwTwips nFirst1 = 0;
/*N*/       SwLinePortion *pPor = pCurr->GetFirstPortion();
/*N*/         SvShorts* pSpaceAdd = pCurr->GetpSpaceAdd();
/*N*/         SvUShorts* pKanaComp = pCurr->GetpKanaComp();
/*N*/         MSHORT nSpaceIdx = 0;
/*N*/         MSHORT nKanaIdx = 0;
/*N*/       short nSpaceAdd = pSpaceAdd ? (*pSpaceAdd)[0] : 0;
/*N*/
/*N*/         sal_Bool bNoTxt = sal_True;
/*N*/
/*N*/       // Zuerst werden alle Portions ohne Len am Zeilenanfang uebersprungen.
/*N*/       // Ausnahme bilden die fiesen Spezialportions aus WhichFirstPortion:
/*N*/       // Num, ErgoSum, FtnNum, FeldReste
/*N*/       // 8477: aber auch die einzige Textportion einer leeren Zeile mit
/*N*/       // Right/Center-Adjustment! Also nicht nur pPor->GetExpandPortion() ...
/*N*/
/*N*/         while( pPor && !pPor->GetLen() && ! bInsideFirstField )
/*N*/       {
/*N*/           nX += pPor->Width();
/*N*/           if( bNoTxt )
/*N*/               nFirst1 = nX;
/*N*/           // 8670: EndPortions zaehlen hier einmal als TxtPortions.
/*N*/           if( pPor->InTxtGrp() || pPor->IsBreakPortion() )
/*N*/           {
/*N*/               bNoTxt = sal_False;
/*N*/               nFirst1 = nX;
/*N*/           }
/*N*/             if( pPor->IsMultiPortion() && ((SwMultiPortion*)pPor)->HasTabulator() )
/*N*/           {
/*?*/                 if ( pSpaceAdd )
/*?*/                 {
/*?*/                     if ( ++nSpaceIdx < pSpaceAdd->Count() )
/*?*/                         nSpaceAdd = (*pSpaceAdd)[nSpaceIdx];
/*?*/                     else
/*?*/                         nSpaceAdd = 0;
/*?*/                 }
/*?*/
/*?*/                 if( pKanaComp && ( nKanaIdx + 1 ) < pKanaComp->Count() )
/*?*/                     ++nKanaIdx;
/*N*/           }
/*N*/           if( pPor->InFixMargGrp() )
/*N*/           {
/*N*/               if( pPor->IsMarginPortion() )
/*N*/                   bNoTxt = sal_False;
/*N*/                 else
/*N*/                 {
/*N*/                     // fix margin portion => next SpaceAdd, KanaComp value
/*N*/                     if( pSpaceAdd )
/*N*/                     {
/*N*/                         if ( ++nSpaceIdx < pSpaceAdd->Count() )
/*N*/                             nSpaceAdd = (*pSpaceAdd)[nSpaceIdx];
/*N*/                         else
/*N*/                             nSpaceAdd = 0;
/*N*/                     }
/*N*/
/*N*/                     if( pKanaComp && ( nKanaIdx + 1 ) < pKanaComp->Count() )
/*N*/                         ++nKanaIdx;
/*N*/                 }
/*N*/           }
/*N*/           pPor = pPor->GetPortion();
/*N*/       }
/*N*/
/*N*/       if( !pPor )
/*N*/       {
/*N*/           // Es sind nur Spezialportions unterwegs.
/*N*/           nX = nFirst1;
/*N*/       }
/*N*/       else
/*N*/       {
/*N*/             if( !pPor->IsMarginPortion() && !pPor->IsPostItsPortion() &&
/*N*/               (!pPor->InFldGrp() || pPor->GetAscent() ) )
/*N*/           {
/*N*/               nPorHeight = pPor->Height();
/*N*/               nPorAscent = pPor->GetAscent();
/*N*/           }
/*N*/ #ifdef BIDI
/*N*/           while( pPor && !pPor->IsBreakPortion() && ( aInf.GetIdx() < nOfst ||
/*N*/                    ( bWidth && ( pPor->IsKernPortion() || pPor->IsMultiPortion() ) ) ) )
/*N*/ #else
/*N*/           while( pPor && !pPor->IsBreakPortion() && ( aInf.GetIdx() < nOfst ||
/*N*/                    ( bWidth && pPor->IsMultiPortion() ) ) )
/*N*/ #endif
/*N*/           {
/*N*/               if( !pPor->IsMarginPortion() && !pPor->IsPostItsPortion() &&
/*N*/                   (!pPor->InFldGrp() || pPor->GetAscent() ) )
/*N*/               {
/*N*/                   nPorHeight = pPor->Height();
/*N*/                   nPorAscent = pPor->GetAscent();
/*N*/               }
/*N*/
/*N*/                 // If we are behind the portion, we add the portion width to
/*N*/                 // nX. Special case: nOfst = aInf.GetIdx() + pPor->GetLen().
/*N*/                 // For common portions (including BidiPortions) we want to add
/*N*/                 // the portion width to nX. For MultiPortions, nExtra = 0,
/*N*/                 // therefore we go to the 'else' branch and start a recursion.
/*N*/                 const BYTE nExtra = pPor->IsMultiPortion() &&
/*N*/                                     ! ((SwMultiPortion*)pPor)->IsBidi() &&
/*N*/                                     ! bWidth ? 0 : 1;
/*N*/                 if ( aInf.GetIdx() + pPor->GetLen() < nOfst + nExtra )
/*N*/               {
/*N*/                   if ( !( pPor->InSpaceGrp() && nSpaceAdd ) )
/*N*/                   {
/*N*/                         if( pPor->InFixMargGrp() && ! pPor->IsMarginPortion() )
/*N*/                       {
/*N*/                             // update to current SpaceAdd, KanaComp values
/*N*/                             if ( pSpaceAdd )
/*N*/                             {
/*?*/                                 if ( ++nSpaceIdx < pSpaceAdd->Count() )
/*?*/                                     nSpaceAdd = (*pSpaceAdd)[nSpaceIdx];
/*?*/                                 else
/*?*/                                     nSpaceAdd = 0;
/*?*/                             }
/*N*/
/*N*/                             if ( pKanaComp &&
/*N*/                                 ( nKanaIdx + 1 ) < pKanaComp->Count()
/*N*/                                 )
/*N*/                                 ++nKanaIdx;
/*N*/                         }
/*N*/                       if ( !pPor->IsFlyPortion() || ( pPor->GetPortion() &&
/*N*/                               !pPor->GetPortion()->IsMarginPortion() ) )
/*N*/                           nX += pPor->PrtWidth();
/*N*/                   }
/*N*/                     if( pPor->IsMultiPortion() )
/*N*/                     {
/*N*/                         if ( ((SwMultiPortion*)pPor)->HasTabulator() )
/*N*/                   {
/*?*/                         if ( pSpaceAdd )
/*?*/                         {
/*?*/                             if ( ++nSpaceIdx < pSpaceAdd->Count() )
/*?*/                                 nSpaceAdd = (*pSpaceAdd)[nSpaceIdx];
/*?*/                             else
/*?*/                                 nSpaceAdd = 0;
/*?*/                         }
/*?*/
/*?*/                         if( pKanaComp && ( nKanaIdx + 1 ) < pKanaComp->Count() )
/*?*/                             ++nKanaIdx;
/*N*/                   }
/*N*/
/*N*/                     }
/*N*/
/*N*/                   aInf.SetIdx( aInf.GetIdx() + pPor->GetLen() );
/*N*/                     pPor = pPor->GetPortion();
/*N*/               }
/*N*/               else
/*N*/               {
/*N*/                   if ( pPor->PrtWidth() )
/*N*/                   {
/*N*/                       xub_StrLen nOldLen = pPor->GetLen();
/*N*/                       pPor->SetLen( nOfst - aInf.GetIdx() );
/*N*/                       aInf.SetLen( pPor->GetLen() );
/*N*/                       if( nX || !pPor->InNumberGrp() )
/*N*/                       {
/*N*/                           SeekAndChg( aInf );
/*N*/                           const sal_Bool bOldOnWin = aInf.OnWin();
/*N*/                           aInf.SetOnWin( sal_False ); // keine BULLETs!
/*N*/                           SwTwips nTmp = nX;
/*N*/                             aInf.SetKanaComp( pKanaComp );
/*N*/                             aInf.SetKanaIdx( nKanaIdx );
/*N*/                             nX += pPor->GetTxtSize( aInf ).Width();
/*N*/                           aInf.SetOnWin( bOldOnWin );
/*N*/                           if ( pPor->InSpaceGrp() && nSpaceAdd )
/*N*/                               nX += pPor->CalcSpacing( nSpaceAdd, aInf );
/*N*/                           if( bWidth )
/*N*/                           {
/*?*/                               pPor->SetLen( pPor->GetLen() + 1 );
/*?*/                               aInf.SetLen( pPor->GetLen() );
/*?*/                               aInf.SetOnWin( sal_False ); // keine BULLETs!
/*?*/                               nTmp += pPor->GetTxtSize( aInf ).Width();
/*?*/                               aInf.SetOnWin( bOldOnWin );
/*?*/                               if ( pPor->InSpaceGrp() && nSpaceAdd )
/*?*/                                   nTmp += pPor->CalcSpacing(nSpaceAdd, aInf);
/*?*/                               pOrig->Width( nTmp - nX );
/*N*/                           }
/*N*/                       }
/*N*/                       pPor->SetLen( nOldLen );
/*N*/                   }
/*N*/                   bWidth = sal_False;
/*N*/                   break;
/*N*/               }
/*N*/           }
/*N*/       }
/*N*/
/*N*/       if( pPor )
/*N*/       {
/*N*/             OSL_ENSURE( !pPor->InNumberGrp() || bInsideFirstField, "Number surprise" );
/*N*/           sal_Bool bEmptyFld = sal_False;
/*N*/           if( pPor->InFldGrp() && pPor->GetLen() )
/*N*/           {
/*N*/               SwFldPortion *pTmp = (SwFldPortion*)pPor;
/*N*/               while( pTmp->HasFollow() && !pTmp->GetExp().Len() )
/*N*/               {
/*?*/                   KSHORT nAddX = pTmp->Width();
/*?*/                   SwLinePortion *pNext = pTmp->GetPortion();
/*?*/                   while( pNext && !pNext->InFldGrp() )
/*?*/                   {
/*?*/                       OSL_ENSURE( !pNext->GetLen(), "Where's my field follow?" );
/*?*/                       nAddX += pNext->Width();
/*?*/                       pNext = pNext->GetPortion();
/*?*/                   }
/*?*/                   if( !pNext )
/*?*/                       break;
/*?*/                   pTmp = (SwFldPortion*)pNext;
/*?*/                   nPorHeight = pTmp->Height();
/*?*/                   nPorAscent = pTmp->GetAscent();
/*?*/                   nX += nAddX;
/*?*/                   bEmptyFld = sal_True;
/*N*/               }
/*N*/           }
/*N*/           // 8513: Felder im Blocksatz, ueberspringen
/*N*/             while( pPor && !pPor->GetLen() && ! bInsideFirstField &&
/*N*/                    ( pPor->IsFlyPortion() || pPor->IsKernPortion() ||
/*N*/                      pPor->IsBlankPortion() || pPor->InTabGrp() ||
/*N*/                      ( !bEmptyFld && pPor->InFldGrp() ) ) )
/*N*/           {
/*?*/               if ( pPor->InSpaceGrp() && nSpaceAdd )
/*?*/                   nX += pPor->PrtWidth() +
/*?*/                         pPor->CalcSpacing( nSpaceAdd, aInf );
/*?*/               else
/*?*/               {
/*?*/                     if( pPor->InFixMargGrp() && ! pPor->IsMarginPortion() )
/*?*/                   {
/*?*/                         if ( pSpaceAdd )
/*?*/                         {
/*?*/                             if ( ++nSpaceIdx < pSpaceAdd->Count() )
/*?*/                                 nSpaceAdd = (*pSpaceAdd)[nSpaceIdx];
/*?*/                             else
/*?*/                                 nSpaceAdd = 0;
/*?*/                         }
/*?*/
/*?*/                         if( pKanaComp && ( nKanaIdx + 1 ) < pKanaComp->Count() )
/*?*/                             ++nKanaIdx;
/*?*/                   }
/*?*/                   if ( !pPor->IsFlyPortion() || ( pPor->GetPortion() &&
/*?*/                           !pPor->GetPortion()->IsMarginPortion() ) )
/*?*/                       nX += pPor->PrtWidth();
/*?*/               }
/*?*/                 if( pPor->IsMultiPortion() &&
/*?*/                     ((SwMultiPortion*)pPor)->HasTabulator() )
/*?*/               {
/*?*/                     if ( pSpaceAdd )
/*?*/                     {
/*?*/                         if ( ++nSpaceIdx < pSpaceAdd->Count() )
/*?*/                             nSpaceAdd = (*pSpaceAdd)[nSpaceIdx];
/*?*/                         else
/*?*/                             nSpaceAdd = 0;
/*?*/                     }
/*?*/
/*?*/                     if( pKanaComp && ( nKanaIdx + 1 ) < pKanaComp->Count() )
/*?*/                         ++nKanaIdx;
/*?*/               }
/*?*/               if( !pPor->IsFlyPortion() )
/*?*/               {
/*?*/                   nPorHeight = pPor->Height();
/*?*/                   nPorAscent = pPor->GetAscent();
/*?*/               }
/*?*/               pPor = pPor->GetPortion();
/*N*/           }
/*N*/
/*N*/           if( aInf.GetIdx() == nOfst && pPor && pPor->InHyphGrp() &&
/*N*/               pPor->GetPortion() && pPor->GetPortion()->InFixGrp() )
/*N*/           {
/*N*/               // Alle Sonderportions muessen uebersprungen werden
/*N*/               // Beispiel: zu-[FLY]sammen, 'u' == 19, 's' == 20; Right()
/*N*/               // Ohne den Ausgleich landen wir vor '-' mit dem
/*N*/               // Ausgleich vor 's'.
/*N*/               while( pPor && !pPor->GetLen() )
/*N*/               {
///*N*/                     DBG_LOOP;
/*N*/                   nX += pPor->Width();
/*N*/                   if( !pPor->IsMarginPortion() )
/*N*/                   {
/*N*/                       nPorHeight = pPor->Height();
/*N*/                       nPorAscent = pPor->GetAscent();
/*N*/                   }
/*N*/                   pPor = pPor->GetPortion();
/*N*/               }
/*N*/           }
/*N*/           if( pPor && pCMS )
/*N*/           {
/*N*/               if( pCMS->bFieldInfo && pPor->InFldGrp() && pPor->Width() )
/*N*/                   pOrig->Width( pPor->Width() );
/*N*/               if( pPor->IsDropPortion() )
/*N*/                 {
/*?*/                   nPorAscent = ((SwDropPortion*)pPor)->GetDropHeight();
/*?*/                     // The drop height is only calculated, if we have more than
/*?*/                     // one line. Otherwise it is 0.
/*?*/                     if ( ! nPorAscent)
/*?*/                         nPorAscent = pPor->Height();
/*?*/                   nPorHeight = nPorAscent;
/*?*/                   pOrig->Height( nPorHeight +
/*?*/                       ((SwDropPortion*)pPor)->GetDropDescent() );
/*?*/                   if( nTmpHeight < pOrig->Height() )
/*?*/                   {
/*?*/                       nTmpAscent = nPorAscent;
/*?*/                       nTmpHeight = USHORT( pOrig->Height() );
/*?*/                   }
/*N*/               }
/*N*/               if( bWidth && pPor->PrtWidth() && pPor->GetLen() &&
/*N*/                   aInf.GetIdx() == nOfst )
/*N*/               {
/*?*/                   if( !pPor->IsFlyPortion() && pPor->Height() &&
/*?*/                       pPor->GetAscent() )
/*?*/                   {
/*?*/                       nPorHeight = pPor->Height();
/*?*/                       nPorAscent = pPor->GetAscent();
/*?*/                   }
/*?*/                   SwTwips nTmp;
/*?*/                   if( 2 > pPor->GetLen() )
/*?*/                   {
/*?*/                       nTmp = pPor->Width();
/*?*/                       if ( pPor->InSpaceGrp() && nSpaceAdd )
/*?*/                           nTmp += pPor->CalcSpacing( nSpaceAdd, aInf );
/*?*/                   }
/*?*/                   else
/*?*/                   {
/*?*/                       const sal_Bool bOldOnWin = aInf.OnWin();
/*?*/                       xub_StrLen nOldLen = pPor->GetLen();
/*?*/                       pPor->SetLen( 1 );
/*?*/                       aInf.SetLen( pPor->GetLen() );
/*?*/                       SeekAndChg( aInf );
/*?*/                       aInf.SetOnWin( sal_False ); // keine BULLETs!
/*?*/                         aInf.SetKanaComp( pKanaComp );
/*?*/                         aInf.SetKanaIdx( nKanaIdx );
/*?*/                       nTmp = pPor->GetTxtSize( aInf ).Width();
/*?*/                       aInf.SetOnWin( bOldOnWin );
/*?*/                       if ( pPor->InSpaceGrp() && nSpaceAdd )
/*?*/                           nTmp += pPor->CalcSpacing( nSpaceAdd, aInf );
/*?*/                       pPor->SetLen( nOldLen );
/*?*/                   }
/*?*/                   pOrig->Width( nTmp );
/*N*/               }
/*N*/             }
/*N*/         }
/*N*/
/*N*/       pOrig->Pos().X() += nX;
/*N*/
/*N*/       if ( pCMS && pCMS->bRealHeight )
/*N*/       {
/*N*/ #ifdef VERTICAL_LAYOUT
/*N*/             nTmpAscent = AdjustBaseLine( *pCurr, 0, nPorHeight, nPorAscent );
/*N*/ #else
/*N*/             nTmpAscent = AdjustBaseLine( *pCurr, nPorHeight, nPorAscent );
/*N*/ #endif
/*N*/             if ( nTmpAscent > nPorAscent )
/*N*/               pCMS->aRealHeight.X() = nTmpAscent - nPorAscent;
/*N*/           else
/*N*/               pCMS->aRealHeight.X() = 0;
/*N*/           OSL_ENSURE( nPorHeight, "GetCharRect: Missing Portion-Height" );
/*N*/           if ( nTmpHeight > nPorHeight )
/*N*/               pCMS->aRealHeight.Y() = nPorHeight;
/*N*/           else
/*N*/               pCMS->aRealHeight.Y() = nTmpHeight;
/*N*/       }
/*N*/   }
/*N*/ }

/*************************************************************************
 *                      SwTxtCursor::GetCharRect()
 *************************************************************************/

/*N*/ sal_Bool SwTxtCursor::GetCharRect( SwRect* pOrig, const xub_StrLen nOfst,
/*N*/                              SwCrsrMoveState* pCMS, const long nMax )
/*N*/ {
/*N*/   CharCrsrToLine(nOfst);
/*N*/
/*N*/     // Indicates that a position inside a special portion (field, number portion)
/*N*/     // is requested.
/*N*/     const sal_Bool bSpecialPos = pCMS && pCMS->pSpecialPos;
/*N*/     xub_StrLen nFindOfst = nOfst;
/*N*/
/*N*/     if ( bSpecialPos )
/*N*/     {
/*?*/         xub_StrLen nLineOfst = pCMS->pSpecialPos->nLineOfst;
/*?*/         BYTE nExtendRange = pCMS->pSpecialPos->nExtendRange;
/*?*/
/*?*/         OSL_ENSURE( ! nLineOfst || SP_EXTEND_RANGE_BEFORE != nExtendRange,
/*?*/                 "LineOffset AND Number Portion?" );
/*?*/         (void)nLineOfst;
/*?*/
/*?*/         // portions which are behind the string
/*?*/         if ( SP_EXTEND_RANGE_BEHIND == nExtendRange )
/*?*/             ++nFindOfst;
/*?*/
/*?*/         // skip lines for fields which cover more than one line
/*?*/         for ( USHORT i = 0; i < pCMS->pSpecialPos->nLineOfst; i++ )
/*?*/             Next();
/*N*/     }
/*N*/
/*N*/   // Adjustierung ggf. nachholen
/*N*/   GetAdjusted();
/*N*/
/*N*/   const Point aCharPos( GetTopLeft() );
/*N*/   sal_Bool bRet = sal_True;
/*N*/
/*N*/     _GetCharRect( pOrig, nFindOfst, pCMS );
/*N*/
/*N*/     const SwTwips nRight1 = Right() - 12;
/*N*/
/*N*/     pOrig->Pos().X() += aCharPos.X();
/*N*/   pOrig->Pos().Y() += aCharPos.Y();
/*N*/
/*N*/   if( pCMS && pCMS->b2Lines && pCMS->p2Lines )
/*N*/   {
/*?*/       pCMS->p2Lines->aLine.Pos().X() += aCharPos.X();
/*?*/       pCMS->p2Lines->aLine.Pos().Y() += aCharPos.Y();
/*?*/       pCMS->p2Lines->aPortion.Pos().X() += aCharPos.X();
/*?*/       pCMS->p2Lines->aPortion.Pos().Y() += aCharPos.Y();
/*N*/   }
/*N*/
/*N*/   if( pOrig->Left() > nRight1 )
/*?*/       pOrig->Pos().X() = nRight1;
/*N*/
/*N*/   if( nMax )
/*N*/   {
/*N*/
/*N*/ #ifdef VERTICAL_LAYOUT
/*N*/         if( pOrig->Top() + pOrig->Height() > nMax )
/*N*/       {
/*N*/           if( pOrig->Top() > nMax )
/*N*/               pOrig->Top( nMax );
/*N*/             pOrig->Height( nMax - pOrig->Top() );
/*N*/ #else
/*N*/       if( pOrig->Bottom() > nMax )
/*N*/       {
/*N*/           if( pOrig->Top() > nMax )
/*N*/               pOrig->Top( nMax );
/*N*/           pOrig->Bottom( nMax );
/*N*/ #endif
/*N*/       }
/*N*/       if ( pCMS && pCMS->bRealHeight && pCMS->aRealHeight.Y() >= 0 )
/*N*/       {
/*N*/           long nTmp = pCMS->aRealHeight.X() + pOrig->Top();
/*N*/           if( nTmp >= nMax )
/*N*/           {
/*?*/               pCMS->aRealHeight.X() = nMax - pOrig->Top();
/*?*/               pCMS->aRealHeight.Y() = 0;
/*N*/           }
/*N*/           else if( nTmp + pCMS->aRealHeight.Y() > nMax )
/*?*/               pCMS->aRealHeight.Y() = nMax - nTmp;
/*N*/       }
/*N*/   }
/*N*/   long nOut = pOrig->Right() - GetTxtFrm()->Frm().Right();
/*N*/   if( nOut > 0 )
/*N*/   {
/*N*/       if( GetTxtFrm()->Frm().Width() < GetTxtFrm()->Prt().Left()
/*N*/                                  + GetTxtFrm()->Prt().Width() )
/*?*/           nOut += GetTxtFrm()->Frm().Width() - GetTxtFrm()->Prt().Left()
/*?*/                   - GetTxtFrm()->Prt().Width();
/*N*/       if( nOut > 0 )
/*?*/           pOrig->Pos().X() -= nOut + 10;
/*N*/   }
/*N*/   return bRet;
/*N*/ }

/*************************************************************************
 *                      SwTxtCursor::GetCrsrOfst()
 *
 * Return: Offset im String
 *************************************************************************/
/*N*/ xub_StrLen SwTxtCursor::GetCrsrOfst( SwPosition *pPos, const Point &rPoint,
/*N*/                    const MSHORT nChgNode, const SwCrsrMoveState* pCMS ) const
/*N*/ {
/*N*/   // Adjustierung ggf. nachholen
/*N*/   GetAdjusted();
/*N*/
/*N*/   const XubString &rText = GetInfo().GetTxt();
/*N*/   xub_StrLen nOffset = 0;
/*N*/
/*N*/   // x ist der horizontale Offset innerhalb der Zeile.
/*N*/   SwTwips x = rPoint.X();
/*N*/   CONST SwTwips nLeftMargin  = GetLineStart();
/*N*/   SwTwips nRightMargin = GetLineEnd();
/*N*/   if( nRightMargin == nLeftMargin )
/*N*/       nRightMargin += 30;
/*N*/
/*N*/   const sal_Bool bLeftOver = x < nLeftMargin;
/*N*/   if( bLeftOver )
/*N*/       x = nLeftMargin;
/*N*/   const sal_Bool bRightOver = x > nRightMargin;
/*N*/   if( bRightOver )
/*N*/       x = nRightMargin;
/*N*/
/*N*/   sal_Bool bRightAllowed = pCMS && ( pCMS->eState == MV_NONE );
/*N*/
/*N*/   // Bis hierher in Dokumentkoordinaten.
/*N*/   x -= nLeftMargin;
/*N*/
/*N*/   KSHORT nX = KSHORT( x );
/*N*/
/*N*/   // Wenn es in der Zeile Attributwechsel gibt, den Abschnitt
/*N*/   // suchen, in dem nX liegt.
/*N*/   SwLinePortion *pPor = pCurr->GetFirstPortion();
/*N*/   xub_StrLen nCurrStart  = nStart;
/*N*/   sal_Bool bLastPortion;
/*N*/   sal_Bool bHolePortion = sal_False;
/*N*/   sal_Bool bLastHyph = sal_False;
/*N*/
/*N*/   SvShorts *pSpaceAdd = pCurr->GetpSpaceAdd();
/*N*/     SvUShorts *pKanaComp = pCurr->GetpKanaComp();
/*N*/   xub_StrLen nOldIdx = GetInfo().GetIdx();
/*N*/   MSHORT nSpaceIdx = 0;
/*N*/     MSHORT nKanaIdx = 0;
/*N*/   short nSpaceAdd = pSpaceAdd ? (*pSpaceAdd)[0] : 0;
/*N*/     short nKanaComp = pKanaComp ? (*pKanaComp)[0] : 0;
/*N*/
/*N*/   // nWidth ist die Breite der Zeile, oder die Breite des
/*N*/   // Abschnitts mit dem Fontwechsel, in dem nX liegt.
/*N*/
/*N*/   KSHORT nWidth = pPor->Width();
/*N*/     if ( pSpaceAdd || pKanaComp )
/*N*/   {
/*?*/       if ( pPor->InSpaceGrp() && nSpaceAdd )
/*?*/       {
/*?*/           ((SwTxtSizeInfo&)GetInfo()).SetIdx( nCurrStart );
/*?*/           nWidth += USHORT( pPor->CalcSpacing( nSpaceAdd, GetInfo() ) );
/*?*/       }
/*?*/         if( ( pPor->InFixMargGrp() && ! pPor->IsMarginPortion() ) ||
/*?*/             ( pPor->IsMultiPortion() && ((SwMultiPortion*)pPor)->HasTabulator() )
/*?*/           )
/*?*/       {
/*?*/             if ( pSpaceAdd )
/*?*/             {
/*?*/                 if ( ++nSpaceIdx < pSpaceAdd->Count() )
/*?*/                     nSpaceAdd = (*pSpaceAdd)[nSpaceIdx];
/*?*/                 else
/*?*/                     nSpaceAdd = 0;
/*?*/             }
/*?*/
/*?*/             if( pKanaComp )
/*?*/             {
/*?*/                 if ( nKanaIdx + 1 < pKanaComp->Count() )
/*?*/                     nKanaComp = (*pKanaComp)[++nKanaIdx];
/*?*/                 else
/*?*/                     nKanaComp = 0;
/*?*/             }
/*N*/       }
/*N*/   }
/*N*/
/*N*/     KSHORT nWidth30 = 0;
/*N*/     if ( !pPor->IsPostItsPortion() )
/*N*/         nWidth30 = ! nWidth && pPor->GetLen() && pPor->InToxRefOrFldGrp() ?
/*N*/                      30 :
/*N*/                      nWidth;
/*N*/
/*N*/   while(!(bLastPortion = (0 == pPor->GetPortion())) && nWidth30 < nX &&
/*N*/       !pPor->IsBreakPortion() )
/*N*/   {
/*?*/       nX -= nWidth;
/*?*/       nCurrStart += pPor->GetLen();
/*?*/       bHolePortion = pPor->IsHolePortion();
/*?*/       pPor = pPor->GetPortion();
/*?*/       nWidth = pPor->Width();
/*?*/         if ( pSpaceAdd || pKanaComp )
/*?*/       {
/*?*/           if ( pPor->InSpaceGrp() && nSpaceAdd )
/*?*/           {
/*?*/               ((SwTxtSizeInfo&)GetInfo()).SetIdx( nCurrStart );
/*?*/               nWidth += USHORT( pPor->CalcSpacing( nSpaceAdd, GetInfo() ) );
/*?*/           }
/*?*/
/*?*/             if( ( pPor->InFixMargGrp() && ! pPor->IsMarginPortion() ) ||
/*?*/                 ( pPor->IsMultiPortion() && ((SwMultiPortion*)pPor)->HasTabulator() )
/*?*/               )
/*?*/           {
/*?*/                 if ( pSpaceAdd )
/*?*/                 {
/*?*/                     if ( ++nSpaceIdx < pSpaceAdd->Count() )
/*?*/                         nSpaceAdd = (*pSpaceAdd)[nSpaceIdx];
/*?*/                     else
/*?*/                         nSpaceAdd = 0;
/*?*/                 }
/*?*/
/*?*/                 if ( pKanaComp )
/*?*/                 {
/*?*/                     if( nKanaIdx + 1 < pKanaComp->Count() )
/*?*/                         nKanaComp = (*pKanaComp)[++nKanaIdx];
/*?*/                     else
/*?*/                         nKanaComp = 0;
/*?*/                 }
/*?*/           }
/*?*/       }
/*?*/
/*?*/         if ( !pPor->IsPostItsPortion() )
/*?*/             nWidth30 = ! nWidth && pPor->GetLen() && pPor->InToxRefOrFldGrp() ?
/*?*/                          30 :
/*?*/                          nWidth;
/*?*/       if( !pPor->IsFlyPortion() && !pPor->IsMarginPortion() )
/*?*/           bLastHyph = pPor->InHyphGrp();
/*N*/   }
/*N*/
/*N*/   if( nX==nWidth )
/*N*/   {
/*N*/       SwLinePortion *pNextPor = pPor->GetPortion();
/*N*/       while( pNextPor && pNextPor->InFldGrp() && !pNextPor->Width() )
/*N*/       {
/*?*/           nCurrStart += pPor->GetLen();
/*?*/           pPor = pNextPor;
/*?*/           if( !pPor->IsFlyPortion() && !pPor->IsMarginPortion() )
/*?*/               bLastHyph = pPor->InHyphGrp();
/*?*/           pNextPor = pPor->GetPortion();
/*N*/       }
/*N*/   }
/*N*/
/*N*/   ((SwTxtSizeInfo&)GetInfo()).SetIdx( nOldIdx );
/*N*/
/*N*/   xub_StrLen nLength = pPor->GetLen();
/*N*/
/*N*/   sal_Bool bFieldInfo = pCMS && pCMS->bFieldInfo;
/*N*/
/*N*/   if( bFieldInfo && ( nWidth30 < nX || bRightOver || bLeftOver ||
/*N*/       ( pPor->InNumberGrp() && !pPor->IsFtnNumPortion() ) ||
/*N*/       ( pPor->IsMarginPortion() && nWidth > nX + 30 ) ) )
/*?*/       ((SwCrsrMoveState*)pCMS)->bPosCorr = sal_True;
/*N*/
/*N*/   // 7684: Wir sind genau auf der HyphPortion angelangt und muessen dafuer
/*N*/   // sorgen, dass wir in dem String landen.
/*N*/   // 7993: Wenn die Laenge 0 ist muessen wir raus...
/*N*/   if( !nLength )
/*N*/   {
/*N*/       if( pCMS )
/*N*/       {
/*N*/           if( pPor->IsFlyPortion() && bFieldInfo )
/*?*/               ((SwCrsrMoveState*)pCMS)->bPosCorr = sal_True;
/*N*/
/*N*/           if( pPor->IsFtnNumPortion() && !bRightOver && nX )
/*?*/               ((SwCrsrMoveState*)pCMS)->bFtnNoInfo = sal_True;
/*N*/       }
/*N*/       if( !nCurrStart )
/*N*/           return 0;
/*N*/
/*N*/        // 7849, 7816: auf pPor->GetHyphPortion kann nicht verzichtet werden!
/*N*/       if( bHolePortion || ( !bRightAllowed && bLastHyph ) ||
/*N*/           ( pPor->IsMarginPortion() && !pPor->GetPortion() &&
/*N*/           // 46598: In der letzten Zeile eines zentrierten Absatzes wollen
/*N*/           // wir auch mal hinter dem letzten Zeichen landen.
/*?*/               nCurrStart < rText.Len() ) )
/*?*/           --nCurrStart;
/*N*/       else if( pPor->InFldGrp() && ((SwFldPortion*)pPor)->IsFollow()
/*N*/                && nWidth > nX )
/*N*/         {
/*?*/           if( bFieldInfo )
/*?*/               --nCurrStart;
/*?*/           else
/*?*/           {
/*?*/               KSHORT nHeight = pPor->Height();
/*?*/               if ( !nHeight || nHeight > nWidth )
/*?*/                   nHeight = nWidth;
/*?*/               if( nChgNode && nWidth - nHeight/2 > nX )
/*?*/                   --nCurrStart;
/*?*/           }
/*N*/       }
/*N*/       return nCurrStart;
/*N*/   }
/*N*/   if ( 1 == nLength )
/*N*/   {
/*?*/       if ( nWidth )
/*?*/       {
/*?*/           // Sonst kommen wir nicht mehr in zeichengeb. Rahmen hinein...
/*?*/           if( !( nChgNode && pPos && pPor->IsFlyCntPortion() ) )
/*?*/           {
/*?*/               if ( pPor->InFldGrp() ||
/*?*/                      ( pPor->IsMultiPortion() &&
/*?*/                        ((SwMultiPortion*)pPor)->IsBidi()  ) )
/*?*/               {
/*?*/                   KSHORT nHeight = 0;
/*?*/                   if( !bFieldInfo )
/*?*/                   {
/*?*/                       nHeight = pPor->Height();
/*?*/                       if ( !nHeight || nHeight > nWidth )
/*?*/                           nHeight = nWidth;
/*?*/                   }
/*?*/                   if( nWidth - nHeight/2 <= nX &&
/*?*/                         ( ! pPor->InFldGrp() ||
/*?*/                           !((SwFldPortion*)pPor)->HasFollow() ) )
/*?*/                         ++nCurrStart;
/*?*/               }
/*?*/                 else if ( ( !pPor->IsFlyPortion() || ( pPor->GetPortion() &&
/*?*/                   !pPor->GetPortion()->IsMarginPortion() &&
/*?*/                     !pPor->GetPortion()->IsHolePortion() ) )
/*?*/                          && ( nWidth/2 < nX ) &&
/*?*/                          ( !bFieldInfo ||
/*?*/                             ( pPor->GetPortion() &&
/*?*/                               pPor->GetPortion()->IsPostItsPortion() ) )
/*?*/                        && ( bRightAllowed || !bLastHyph ))
/*?*/                   ++nCurrStart;
/*?*/               return nCurrStart;
/*?*/           }
/*?*/       }
/*?*/       else
/*?*/       {
/*?*/           if ( pPor->IsPostItsPortion() || pPor->IsBreakPortion() ||
/*?*/                pPor->InToxRefGrp() )
/*?*/               return nCurrStart;
/*?*/           if ( pPor->InFldGrp() )
/*?*/           {
/*?*/               if( bRightOver && !((SwFldPortion*)pPor)->HasFollow() )
/*?*/                   ++nCurrStart;
/*?*/               return nCurrStart;
/*?*/           }
/*?*/       }
/*N*/   }
/*N*/
/*N*/   if( bLastPortion && (pCurr->GetNext() || pFrm->GetFollow() ) )
/*N*/       --nLength;
/*N*/
/*N*/     if( nWidth > nX ||
/*N*/       ( nWidth == nX && pPor->IsMultiPortion() && ((SwMultiPortion*)pPor)->IsDouble() ) )
/*N*/   {
/*N*/       if( pPor->InTxtGrp() )
/*N*/       {
/*N*/           BYTE nOldProp;
/*N*/           if( GetPropFont() )
/*N*/           {
/*?*/               ((SwFont*)GetFnt())->SetProportion( GetPropFont() );
/*?*/               nOldProp = GetFnt()->GetPropr();
/*N*/           }
/*N*/           else
/*N*/               nOldProp = 0;
/*N*/           {
/*N*/               SwTxtSizeInfo aSizeInf( GetInfo(), rText, nCurrStart );
/*N*/               ((SwTxtCursor*)this)->SeekAndChg( aSizeInf );
/*N*/               SwTxtSlot aDiffTxt( &aSizeInf, ((SwTxtPortion*)pPor) );
/*N*/               SwFontSave aSave( aSizeInf, pPor->IsDropPortion() ?
/*N*/                       ((SwDropPortion*)pPor)->GetFnt() : NULL );
/*N*/
/*N*/                 SwParaPortion* pPara = (SwParaPortion*)GetInfo().GetParaPortion();
/*N*/                 OSL_ENSURE( pPara, "No paragraph!" );
/*N*/
/*N*/                 SwDrawTextInfo aDrawInf( aSizeInf.GetVsh(),
/*N*/                                          *aSizeInf.GetOut(),
/*N*/                                          &pPara->GetScriptInfo(),
/*N*/                                          aSizeInf.GetTxt(),
/*N*/                                          aSizeInf.GetIdx(),
/*N*/                                          pPor->GetLen() );
/*N*/                 aDrawInf.SetOfst( nX );
/*N*/                 aDrawInf.SetSpace( nSpaceAdd );
/*N*/                 aDrawInf.SetFont( aSizeInf.GetFont() );
/*N*/                 aDrawInf.SetFrm( pFrm );
/*N*/                 aDrawInf.SetSnapToGrid( aSizeInf.SnapToGrid() );
/*N*/                 aDrawInf.SetPosMatchesBounds( pCMS && pCMS->bPosMatchesBounds );
/*N*/
/*N*/                 if ( SW_CJK == aSizeInf.GetFont()->GetActual() &&
/*N*/                      pPara->GetScriptInfo().CountCompChg() &&
/*N*/                     ! pPor->InFldGrp() )
/*?*/                     aDrawInf.SetKanaComp( nKanaComp );
/*N*/
/*N*/                 nLength = aSizeInf.GetFont()->_GetCrsrOfst( aDrawInf );
/*N*/
/*N*/                 if ( pCMS )
/*N*/                     ((SwCrsrMoveState*)pCMS)->nCursorBidiLevel =
/*N*/                         aDrawInf.GetCursorBidiLevel();
/*N*/
/*N*/                 if( bFieldInfo && nLength == pPor->GetLen() &&
/*N*/                     ( ! pPor->GetPortion() ||
/*N*/                       ! pPor->GetPortion()->IsPostItsPortion() ) )
/*N*/                   --nLength;
/*N*/           }
/*N*/           if( nOldProp )
/*?*/               ((SwFont*)GetFnt())->SetProportion( nOldProp );
/*N*/       }
/*N*/   }
/*N*/   nOffset = nCurrStart + nLength;
/*N*/
/*N*/   // 7684: Wir sind vor der HyphPortion angelangt und muessen dafuer
/*N*/   // sorgen, dass wir in dem String landen.
/*N*/   // Bei Zeilenenden vor FlyFrms muessen ebenso behandelt werden.
/*N*/
/*N*/   if( nOffset && pPor->GetLen() == nLength && pPor->GetPortion() &&
/*N*/       !pPor->GetPortion()->GetLen() && pPor->GetPortion()->InHyphGrp() )
/*N*/       --nOffset;
/*N*/
/*N*/   return nOffset;
/*N*/ }

}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
