Files
libreoffice/sw/source/core/text/porlin.cxx

450 lines
13 KiB
C++
Raw Normal View History

2000-09-18 23:08:29 +00:00
/*************************************************************************
*
* OpenOffice.org - a multi-platform office productivity suite
2000-09-18 23:08:29 +00:00
*
* $RCSfile: porlin.cxx,v $
2000-09-18 23:08:29 +00:00
*
* $Revision: 1.23 $
2000-09-18 23:08:29 +00:00
*
* last change: $Author: rt $ $Date: 2005-09-09 05:00:16 $
2000-09-18 23:08:29 +00:00
*
* The Contents of this file are made available subject to
* the terms of GNU Lesser General Public License Version 2.1.
2000-09-18 23:08:29 +00:00
*
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2005 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
2000-09-18 23:08:29 +00:00
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
2000-09-18 23:08:29 +00:00
*
* This library 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 for more details.
2000-09-18 23:08:29 +00:00
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
2000-09-18 23:08:29 +00:00
*
************************************************************************/
#pragma hdrstop
#ifdef BIDI
#ifndef _OUTDEV_HXX //autogen
#include <vcl/outdev.hxx>
#endif
#endif
#ifndef _SW_PORTIONHANDLER_HXX
#include <SwPortionHandler.hxx>
#endif
2000-09-18 23:08:29 +00:00
#include "errhdl.hxx" // ASSERT
#include "txtcfg.hxx"
#include "porlin.hxx"
#include "inftxt.hxx"
#include "portxt.hxx"
2000-10-30 09:00:34 +00:00
#include "pormulti.hxx"
2000-09-18 23:08:29 +00:00
#include "porglue.hxx"
#include "inftxt.hxx"
#include "blink.hxx"
#ifndef PRODUCT
sal_Bool ChkChain( SwLinePortion *pStart )
{
SwLinePortion *pPor = pStart->GetPortion();
MSHORT nCount = 0;
while( pPor )
{
++nCount;
ASSERT( nCount < 200 && pPor != pStart,
"ChkChain(): lost in chains" );
if( nCount >= 200 || pPor == pStart )
{
// der Lebensretter
pPor = pStart->GetPortion();
pStart->SetPortion(0);
pPor->Truncate();
pStart->SetPortion( pPor );
return sal_False;
}
pPor = pPor->GetPortion();
}
return sal_True;
}
#endif
#if OSL_DEBUG_LEVEL > 1
2000-09-18 23:08:29 +00:00
const sal_Char *GetPortionName( const MSHORT nType );
#endif
SwLinePortion::~SwLinePortion()
{
if( pBlink )
pBlink->Delete( this );
}
SwLinePortion *SwLinePortion::Compress()
{
return GetLen() || Width() ? this : 0;
}
KSHORT SwLinePortion::GetViewWidth( const SwTxtSizeInfo & ) const
{
return 0;
}
/*************************************************************************
* SwLinePortion::SwLinePortion( )
*************************************************************************/
SwLinePortion::SwLinePortion( ) :
nLineLength( 0 ),
nAscent( 0 ),
pPortion( NULL )
{
}
/*************************************************************************
* SwLinePortion::PrePaint()
2000-09-18 23:08:29 +00:00
*************************************************************************/
void SwLinePortion::PrePaint( const SwTxtPaintInfo& rInf,
const SwLinePortion* pLast ) const
2000-09-18 23:08:29 +00:00
{
ASSERT( rInf.OnWin(), "SwLinePortion::PrePaint: don't prepaint on a printer");
2000-09-18 23:08:29 +00:00
ASSERT( !Width(), "SwLinePortion::PrePaint: For Width()==0 only!");
const KSHORT nViewWidth = GetViewWidth( rInf );
if( ! nViewWidth )
2000-09-18 23:08:29 +00:00
return;
2000-09-18 23:08:29 +00:00
const KSHORT nHalfView = nViewWidth / 2;
USHORT nLastWidth = pLast->Width();
2000-09-18 23:08:29 +00:00
2000-10-30 09:00:34 +00:00
if ( pLast->InSpaceGrp() && rInf.GetSpaceAdd() )
nLastWidth += (USHORT)pLast->CalcSpacing( rInf.GetSpaceAdd(), rInf );
KSHORT nPos;
SwTxtPaintInfo aInf( rInf );
#ifdef BIDI
const BOOL bBidiPor = ( rInf.GetTxtFrm()->IsRightToLeft() ) !=
( 0 != ( TEXT_LAYOUT_BIDI_RTL & rInf.GetOut()->GetLayoutMode() ) );
USHORT nDir = bBidiPor ?
1800 :
rInf.GetFont()->GetOrientation( rInf.GetTxtFrm()->IsVertical() );
#else
USHORT nDir = rInf.GetFont()->GetOrientation( rInf.GetTxtFrm()->IsVertical() );
#endif
switch ( nDir )
{
case 0 :
nPos = KSHORT( rInf.X() );
if( nLastWidth > nHalfView )
nPos += nLastWidth - nHalfView;
aInf.X( nPos );
break;
case 900 :
nPos = KSHORT( rInf.Y() );
if( nLastWidth > nHalfView )
nPos -= nLastWidth + nHalfView;
aInf.Y( nPos );
break;
#ifdef BIDI
case 1800 :
nPos = KSHORT( rInf.X() );
if( nLastWidth > nHalfView )
nPos -= nLastWidth + nHalfView;
aInf.X( nPos );
break;
#endif
case 2700 :
nPos = KSHORT( rInf.Y() );
if( nLastWidth > nHalfView )
nPos += nLastWidth - nHalfView;
aInf.Y( nPos );
break;
}
2000-09-18 23:08:29 +00:00
SwLinePortion *pThis = (SwLinePortion*)this;
pThis->Width( nViewWidth );
Paint( aInf );
pThis->Width(0);
}
/*************************************************************************
* SwLinePortion::CalcTxtSize()
*************************************************************************/
void SwLinePortion::CalcTxtSize( const SwTxtSizeInfo &rInf )
{
if( GetLen() == rInf.GetLen() )
*((SwPosSize*)this) = GetTxtSize( rInf );
else
{
SwTxtSizeInfo aInf( rInf );
aInf.SetLen( GetLen() );
*((SwPosSize*)this) = GetTxtSize( aInf );
}
}
/*************************************************************************
* SwLinePortion::Truncate()
*
* Es werden alle nachfolgenden Portions geloescht.
*************************************************************************/
void SwLinePortion::_Truncate()
{
SwLinePortion *pPos = pPortion;
do
{ ASSERT( pPos != this, "SwLinePortion::Truncate: loop" );
SwLinePortion *pLast = pPos;
pPos = pPos->GetPortion();
pLast->SetPortion( 0 );
delete pLast;
} while( pPos );
pPortion = 0;
}
/*************************************************************************
* virtual SwLinePortion::Insert()
*
* Es wird immer hinter uns eingefuegt.
*************************************************************************/
SwLinePortion *SwLinePortion::Insert( SwLinePortion *pIns )
{
pIns->FindLastPortion()->SetPortion( pPortion );
SetPortion( pIns );
#ifndef PRODUCT
ChkChain( this );
#endif
return pIns;
}
/*************************************************************************
* SwLinePortion::FindLastPortion()
*************************************************************************/
SwLinePortion *SwLinePortion::FindLastPortion()
{
register SwLinePortion *pPos = this;
// An das Ende wandern und pLinPortion an den letzten haengen ...
while( pPos->GetPortion() )
{
DBG_LOOP;
pPos = pPos->GetPortion();
}
return pPos;
}
/*************************************************************************
* virtual SwLinePortion::Append()
*************************************************************************/
SwLinePortion *SwLinePortion::Append( SwLinePortion *pIns )
{
SwLinePortion *pPos = FindLastPortion();
pPos->SetPortion( pIns );
pIns->SetPortion( 0 );
#ifndef PRODUCT
ChkChain( this );
#endif
return pIns;
}
/*************************************************************************
* virtual SwLinePortion::Cut()
*************************************************************************/
SwLinePortion *SwLinePortion::Cut( SwLinePortion *pVictim )
{
SwLinePortion *pPrev = pVictim->FindPrevPortion( this );
ASSERT( pPrev, "SwLinePortion::Cut(): can't cut" );
pPrev->SetPortion( pVictim->GetPortion() );
pVictim->SetPortion(0);
return pVictim;
}
/*************************************************************************
* SwLinePortion::FindPrevPortion()
*************************************************************************/
SwLinePortion *SwLinePortion::FindPrevPortion( const SwLinePortion *pRoot )
{
ASSERT( pRoot != this, "SwLinePortion::FindPrevPortion(): invalid root" );
SwLinePortion *pPos = (SwLinePortion*)pRoot;
while( pPos->GetPortion() && pPos->GetPortion() != this )
{
DBG_LOOP;
pPos = pPos->GetPortion();
}
ASSERT( pPos->GetPortion(),
"SwLinePortion::FindPrevPortion: blowing in the wind");
return pPos;
}
/*************************************************************************
* virtual SwLinePortion::GetCrsrOfst()
*************************************************************************/
xub_StrLen SwLinePortion::GetCrsrOfst( const KSHORT nOfst ) const
{
if( nOfst > ( PrtWidth() / 2 ) )
return GetLen();
else
return 0;
}
/*************************************************************************
* virtual SwLinePortion::GetTxtSize()
*************************************************************************/
SwPosSize SwLinePortion::GetTxtSize( const SwTxtSizeInfo & ) const
{
ASSERT( !this, "SwLinePortion::GetTxtSize: don't ask me about sizes, "
"I'm only a stupid SwLinePortion" );
return SwPosSize();
}
#ifndef PRODUCT
/*************************************************************************
* virtual SwLinePortion::Check()
*************************************************************************/
sal_Bool SwLinePortion::Check( SvStream &, SwTxtSizeInfo & ) //$ ostream
{
return sal_True;
}
#endif
/*************************************************************************
* virtual SwLinePortion::Format()
*************************************************************************/
sal_Bool SwLinePortion::Format( SwTxtFormatInfo &rInf )
{
if( rInf.X() > rInf.Width() )
{
Truncate();
rInf.SetUnderFlow( this );
return sal_True;
}
register const SwLinePortion *pLast = rInf.GetLast();
Height( pLast->Height() );
SetAscent( pLast->GetAscent() );
const KSHORT nNewWidth = static_cast<USHORT>(rInf.X() + PrtWidth());
2000-09-18 23:08:29 +00:00
// Nur Portions mit echter Breite koennen ein sal_True zurueckliefern
// Notizen beispielsweise setzen niemals bFull==sal_True
if( rInf.Width() <= nNewWidth && PrtWidth() && ! IsKernPortion() )
2000-09-18 23:08:29 +00:00
{
Truncate();
if( nNewWidth > rInf.Width() )
PrtWidth( nNewWidth - rInf.Width() );
rInf.GetLast()->FormatEOL( rInf );
return sal_True;
}
return sal_False;
}
/*************************************************************************
* virtual SwLinePortion::FormatEOL()
*************************************************************************/
// Format end of line
void SwLinePortion::FormatEOL( SwTxtFormatInfo &rInf )
{ }
/*************************************************************************
* SwLinePortion::Move()
*************************************************************************/
void SwLinePortion::Move( SwTxtPaintInfo &rInf )
{
BOOL bB2T = rInf.GetDirection() == DIR_BOTTOM2TOP;
2002-03-21 08:19:43 +00:00
#ifdef BIDI
const BOOL bFrmDir = rInf.GetTxtFrm()->IsRightToLeft();
BOOL bCounterDir = ( ! bFrmDir && DIR_RIGHT2LEFT == rInf.GetDirection() ) ||
( bFrmDir && DIR_LEFT2RIGHT == rInf.GetDirection() );
#endif
2000-10-30 09:00:34 +00:00
if ( InSpaceGrp() && rInf.GetSpaceAdd() )
2000-12-21 08:10:30 +00:00
{
SwTwips nTmp = PrtWidth() + CalcSpacing( rInf.GetSpaceAdd(), rInf );
if( rInf.IsRotated() )
rInf.Y( rInf.Y() + ( bB2T ? -nTmp : nTmp ) );
2002-03-21 08:19:43 +00:00
#ifdef BIDI
else if ( bCounterDir )
rInf.X( rInf.X() - nTmp );
#endif
2000-12-21 08:10:30 +00:00
else
rInf.X( rInf.X() + nTmp );
}
2000-09-18 23:08:29 +00:00
else
{
2001-04-09 09:44:17 +00:00
if( InFixMargGrp() && !IsMarginPortion() )
2000-09-18 23:08:29 +00:00
{
rInf.IncSpaceIdx();
2001-04-09 09:44:17 +00:00
rInf.IncKanaIdx();
2000-09-18 23:08:29 +00:00
}
2000-12-21 08:10:30 +00:00
if( rInf.IsRotated() )
rInf.Y( rInf.Y() + ( bB2T ? -PrtWidth() : PrtWidth() ) );
#ifdef BIDI
2002-03-21 08:19:43 +00:00
else if ( bCounterDir )
rInf.X( rInf.X() - PrtWidth() );
#endif
2000-12-21 08:10:30 +00:00
else
rInf.X( rInf.X() + PrtWidth() );
2000-09-18 23:08:29 +00:00
}
2000-10-30 09:00:34 +00:00
if( IsMultiPortion() && ((SwMultiPortion*)this)->HasTabulator() )
rInf.IncSpaceIdx();
2000-09-18 23:08:29 +00:00
rInf.SetIdx( rInf.GetIdx() + GetLen() );
}
2000-10-30 09:00:34 +00:00
/*************************************************************************
* virtual SwLinePortion::CalcSpacing()
*************************************************************************/
long SwLinePortion::CalcSpacing( long nSpaceAdd, const SwTxtSizeInfo &rInf ) const
2000-10-30 09:00:34 +00:00
{
return 0;
}
2000-09-18 23:08:29 +00:00
/*************************************************************************
* virtual SwLinePortion::GetExpTxt()
*************************************************************************/
sal_Bool SwLinePortion::GetExpTxt( const SwTxtSizeInfo &rInf, XubString &rTxt ) const
{
return sal_False;
}
/*************************************************************************
* virtual SwLinePortion::HandlePortion()
*************************************************************************/
void SwLinePortion::HandlePortion( SwPortionHandler& rPH ) const
{
String aString;
rPH.Special( GetLen(), aString, GetWhichPor() );
}
2000-09-18 23:08:29 +00:00