Files
libreoffice/sw/source/core/text/porrst.cxx
2001-04-10 13:45:09 +00:00

556 lines
18 KiB
C++

/*************************************************************************
*
* $RCSfile: porrst.cxx,v $
*
* $Revision: 1.5 $
*
* last change: $Author: fme $ $Date: 2001-04-10 14:42:43 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
*
* - GNU Lesser General Public License Version 2.1
* - Sun Industry Standards Source License Version 1.1
*
* Sun Microsystems Inc., October, 2000
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2000 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
*
* 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.
*
* 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.
*
* 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
*
*
* Sun Industry Standards Source License Version 1.1
* =================================================
* The contents of this file are subject to the Sun Industry Standards
* Source License Version 1.1 (the "License"); You may not use this file
* except in compliance with the License. You may obtain a copy of the
* License at http://www.openoffice.org/license.html.
*
* Software provided under this License is provided on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
* See the License for the specific provisions governing your rights and
* obligations concerning the Software.
*
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
*
* Copyright: 2000 by Sun Microsystems, Inc.
*
* All Rights Reserved.
*
* Contributor(s): _______________________________________
*
*
************************************************************************/
#ifdef PRECOMPILED
#include "core_pch.hxx"
#endif
#pragma hdrstop
#ifndef _HINTIDS_HXX
#include <hintids.hxx>
#endif
#ifndef _SFX_PRINTER_HXX //autogen
#include <sfx2/printer.hxx>
#endif
#ifndef _SVX_LSPCITEM_HXX //autogen
#include <svx/lspcitem.hxx>
#endif
#ifndef _SVX_TEXTCONV_HXX //autogen
#include <svx/textconv.hxx>
#endif
#ifndef _SVX_ADJITEM_HXX //autogen
#include <svx/adjitem.hxx>
#endif
#ifndef _SVX_LRSPITEM_HXX //autogen
#include <svx/lrspitem.hxx>
#endif
#ifndef _WINDOW_HXX //autogen
#include <vcl/window.hxx>
#endif
#ifndef _SV_SVAPP_HXX
#include <vcl/svapp.hxx>
#endif
#ifndef _TEXTCONV_HXX //autogen
#include <svx/textconv.hxx>
#endif
#ifndef _DOC_HXX
#include <doc.hxx>
#endif
#ifndef _VIEWSH_HXX
#include <viewsh.hxx> // ViewShell
#endif
#ifndef _VIEWOPT_HXX
#include <viewopt.hxx>
#endif
#ifndef _NDTXT_HXX
#include <ndtxt.hxx> // SwTxtNode
#endif
#ifndef _PAGEFRM_HXX
#include <pagefrm.hxx> // SwPageFrm
#endif
#ifndef _PARATR_HXX
#include <paratr.hxx>
#endif
#ifndef _ERRHDL_HXX
#include <errhdl.hxx> // ASSERT
#endif
#ifndef _TXTCFG_HXX
#include <txtcfg.hxx>
#endif
#ifndef _PORRST_HXX
#include <porrst.hxx>
#endif
#ifndef _INFTXT_HXX
#include <inftxt.hxx>
#endif
#ifndef _TXTPAINT_HXX
#include <txtpaint.hxx> // ClipVout
#endif
#ifndef _TXTFRM_HXX
#include <txtfrm.hxx> // SwTxtFrm
#endif
#ifndef _SWFNTCCH_HXX
#include <swfntcch.hxx> // SwFontAccess
#endif
#ifndef _PAGEDESC_HXX
#include <pagedesc.hxx> // SwPageDesc
#endif
#ifndef _FRMSH_HXX
#include <frmsh.hxx>
#endif
#ifndef _FRMATR_HXX
#include <frmatr.hxx>
#endif
#ifndef _REDLNITR_HXX
#include <redlnitr.hxx> // SwRedlineItr
#endif
#ifndef _PORFLY_HXX
#include <porfly.hxx> // SwFlyPortion
#endif
#ifndef _ATRHNDL_HXX
#include <atrhndl.hxx>
#endif
/*************************************************************************
* class SwTmpEndPortion
*************************************************************************/
SwTmpEndPortion::SwTmpEndPortion( const SwLinePortion &rPortion )
{
Height( rPortion.Height() );
SetAscent( rPortion.GetAscent() );
SetWhichPor( POR_TMPEND );
}
/*************************************************************************
* virtual SwTmpEndPortion::Paint()
*************************************************************************/
void SwTmpEndPortion::Paint( const SwTxtPaintInfo &rInf ) const
{
if( rInf.OnWin() && rInf.GetOpt().IsParagraph() )
{
SwDefFontSave aSave( rInf );
const XubString aTmp( sal_Char(aSave.IsAlter() ? CH_PAR_ALTER : CH_PAR),
RTL_TEXTENCODING_MS_1252 );
rInf.DrawText( aTmp, *this );
}
}
/*************************************************************************
* class SwBreakPortion
*************************************************************************/
SwBreakPortion::SwBreakPortion( const SwLinePortion &rPortion )
: SwLinePortion( rPortion ), nViewWidth( 0 ), nRestWidth( 0 )
{
nLineLength = 1;
SetWhichPor( POR_BRK );
}
xub_StrLen SwBreakPortion::GetCrsrOfst( const KSHORT ) const
{ return 0; }
KSHORT SwBreakPortion::GetViewWidth( const SwTxtSizeInfo &rInf ) const
{ return 0; }
SwLinePortion *SwBreakPortion::Compress()
{ return (GetPortion() && GetPortion()->InTxtGrp() ? 0 : this); }
void SwBreakPortion::Paint( const SwTxtPaintInfo &rInf ) const
{
if( rInf.OnWin() && rInf.GetOpt().IsLineBreak() )
{
((SwBreakPortion*)this)->CalcViewWidth( rInf );
if( nViewWidth && nViewWidth <= nRestWidth )
rInf.DrawLineBreak( *this );
}
}
/*************************************************************************
* SwBreakPortion::CalcViewWidth()
*************************************************************************/
void SwBreakPortion::CalcViewWidth( const SwTxtSizeInfo &rInf )
{
ASSERT( rInf.GetOpt().IsLineBreak(), "SwBreakPortion::CalcViewWidth: zombie" );
// Im Mormalfall folgt auf ein Break keine weitere Portion, nur wenn im Blocksatz
// auch die letzte Zeile im Blocksatz ist, folgt eine Marginportion der Breite 0,
// ist die Zeile zentriert, so folgt eine Marginportion mit Breite > 0.
if( GetPortion() )
{
if( GetPortion()->IsFlyPortion() )
{
short nTmp = ((SwFlyPortion*)GetPortion())->GetPrtGlue();
nRestWidth = nTmp > 0 ? nTmp : 0;
}
else
nRestWidth = GetPortion()->Width();
}
if( rInf.GetWin() && nRestWidth )
{
if( !nViewWidth )
nViewWidth = (KSHORT)rInf.GetOpt().GetLineBreakWidth( rInf.GetWin() );
}
else
nViewWidth = 0;
}
/*************************************************************************
* virtual SwBreakPortion::Format()
*************************************************************************/
sal_Bool SwBreakPortion::Format( SwTxtFormatInfo &rInf )
{
nRestWidth = rInf.Width() - rInf.X();
register const SwLinePortion *pRoot = rInf.GetRoot();
Width( 0 );
Height( pRoot->Height() );
SetAscent( pRoot->GetAscent() );
if ( rInf.GetIdx()+1 == rInf.GetTxt().Len() )
rInf.SetNewLine( sal_True );
return sal_True;
}
SwKernPortion::SwKernPortion( SwLinePortion &rPortion, short nKrn ) :
nKern( nKrn )
{
Height( rPortion.Height() );
SetAscent( rPortion.GetAscent() );
nLineLength = 0;
SetWhichPor( POR_KERN );
if( nKern > 0 )
Width( nKern );
rPortion.Insert( this );
}
void SwKernPortion::Paint( const SwTxtPaintInfo &rInf ) const
{
if( Width() )
{
rInf.DrawBackBrush( *this );
if( rInf.GetFont()->IsPaintBlank() )
{
static sal_Char __READONLY_DATA sDoubleSpace[] = " ";
// Tabs mit Fuellung
if( rInf.OnWin() ) // Keine Luecken am Bildschirm
((SwKernPortion*)this)->Width( Width() + 12 );
XubString aTxt( sDoubleSpace, RTL_TEXTENCODING_MS_1252 );
rInf.DrawText( aTxt, *this, 0, 2, sal_True );
if( rInf.OnWin() )
((SwKernPortion*)this)->Width( Width() - 12 );
}
}
}
void SwKernPortion::FormatEOL( SwTxtFormatInfo &rInf )
{
if( rInf.GetLast() == this )
rInf.SetLast( FindPrevPortion( rInf.GetRoot() ) );
if( nKern < 0 )
Width( -nKern );
else
Width( 0 );
rInf.GetLast()->FormatEOL( rInf );
}
SwArrowPortion::SwArrowPortion( const SwLinePortion &rPortion ) :
bLeft( sal_True )
{
Height( rPortion.Height() );
SetAscent( rPortion.GetAscent() );
nLineLength = 0;
SetWhichPor( POR_ARROW );
}
SwArrowPortion::SwArrowPortion( const SwTxtPaintInfo &rInf )
: bLeft( sal_False )
{
Height( rInf.GetTxtFrm()->Prt().Height() );
aPos.X() = rInf.GetTxtFrm()->Frm().Left() +
rInf.GetTxtFrm()->Prt().Right();
aPos.Y() = rInf.GetTxtFrm()->Frm().Top() +
rInf.GetTxtFrm()->Prt().Bottom();
}
void SwArrowPortion::Paint( const SwTxtPaintInfo &rInf ) const
{
((SwArrowPortion*)this)->aPos = rInf.GetPos();
}
void SwArrowPortion::PaintIt( OutputDevice *pOut ) const
{
Size aSize( 6, 12 );
aSize = pOut->PixelToLogic( aSize );
SwRect aRect( GetPos(), aSize );
if( bLeft )
{
aRect.Pos().Y() += 20 - GetAscent();
aRect.Pos().X() += 20;
if( aSize.Height() > Height() )
aRect.Height( Height() );
}
else
{
if( aSize.Height() > Height() )
aRect.Height( Height() );
aRect.Pos().Y() -= aRect.Height() + 20;
aRect.Pos().X() -= aRect.Width() + 20;
}
Color aCol( COL_LIGHTRED );
SvxFont::DrawArrow( *pOut, aRect.SVRect(), aSize, aCol, bLeft );
}
SwLinePortion *SwArrowPortion::Compress() { return this; }
SwTwips SwTxtFrm::EmptyHeight() const
{
SwFont *pFnt;
const SwTxtNode& rTxtNode = *GetTxtNode();
ViewShell *pSh = GetShell();
if ( rTxtNode.HasSwAttrSet() )
{
const SwAttrSet *pAttrSet = &( rTxtNode.GetSwAttrSet() );
pFnt = new SwFont( pAttrSet, GetTxtNode()->GetDoc() );
}
else
{
SwFontAccess aFontAccess( &rTxtNode.GetAnyFmtColl(), pSh);
pFnt = new SwFont( *aFontAccess.Get()->GetFont() );
pFnt->ChkMagic( pSh, pFnt->GetActual() );
}
OutputDevice *pOut = pSh ? pSh->GetOut() : 0;
if ( !pOut || !rTxtNode.GetDoc()->IsBrowseMode() ||
( pSh->GetViewOptions()->IsPrtFormat() ) )
{
Printer *pPrt = rTxtNode.GetDoc()->GetPrt();
if( !pOut || ( pPrt && pPrt->IsValid() ) )
pOut = pPrt;
}
const SwDoc* pDoc = rTxtNode.GetDoc();
if( ::IsShowChanges( pDoc->GetRedlineMode() ) )
{
MSHORT nRedlPos = pDoc->GetRedlinePos( rTxtNode );
if( MSHRT_MAX != nRedlPos )
{
SwAttrHandler aAttrHandler;
aAttrHandler.Init( GetTxtNode()->GetSwAttrSet(),
*GetTxtNode()->GetDoc() );
SwRedlineItr aRedln( rTxtNode, *pFnt, aAttrHandler,
nRedlPos, sal_True );
}
}
SwTwips nRet;
if( !pOut )
nRet = Prt().SSize().Height() + 1;
else
{
pFnt->SetFntChg( sal_True );
pFnt->ChgPhysFnt( pSh, pOut );
nRet = pFnt->GetHeight( pSh, pOut );
}
delete pFnt;
return nRet;
}
/*************************************************************************
* SwTxtFrm::FormatEmpty()
*************************************************************************/
sal_Bool SwTxtFrm::FormatEmpty()
{
if ( HasFollow() || GetTxtNode()->GetpSwpHints() ||
0 != GetTxtNode()->GetNumRule() ||
0 != GetTxtNode()->GetOutlineNum() ||
IsInFtn() || ( HasPara() && GetPara()->IsPrepMustFit() ) )
return sal_False;
const SwAttrSet& aSet = GetTxtNode()->GetSwAttrSet();
if( SVX_ADJUST_LEFT != aSet.GetAdjust().GetAdjust()
|| aSet.GetRegister().GetValue() )
return sal_False;
const SvxLineSpacingItem &rSpacing = aSet.GetLineSpacing();
if( SVX_LINE_SPACE_MIN == rSpacing.GetLineSpaceRule() ||
SVX_LINE_SPACE_FIX == rSpacing.GetLineSpaceRule() ||
aSet.GetLRSpace().IsAutoFirst() )
return sal_False;
else
{
SwTxtFly aTxtFly( this );
SwRect aRect;
sal_Bool bFirstFlyCheck = 0 != Prt().Height();
if ( bFirstFlyCheck &&
aTxtFly.IsOn() && aTxtFly.IsAnyObj( aRect ) )
return sal_False;
else
{
SwTwips nHeight = EmptyHeight();
const SwTwips nChg = nHeight - Prt().SSize().Height();
if( !nChg )
SetUndersized( sal_False );
AdjustFrm( nChg );
if( HasBlinkPor() )
{
ClearPara();
ResetBlinkPor();
}
SetCacheIdx( MSHRT_MAX );
if( !IsEmpty() )
{
SetEmpty( sal_True );
SetCompletePaint();
}
if( !bFirstFlyCheck &&
aTxtFly.IsOn() && aTxtFly.IsAnyObj( aRect ) )
return sal_False;
return sal_True;
}
}
}
sal_Bool SwTxtFrm::FillRegister( SwTwips& rRegStart, KSHORT& rRegDiff )
{
const SwFrm *pFrm = this;
rRegDiff = 0;
while( !( ( FRM_BODY | FRM_FLY )
& pFrm->GetType() ) && pFrm->GetUpper() )
pFrm = pFrm->GetUpper();
if( ( FRM_BODY| FRM_FLY ) & pFrm->GetType() )
{
rRegStart = pFrm->Frm().Top() + pFrm->Prt().Top();
pFrm = pFrm->FindPageFrm();
if( pFrm->IsPageFrm() )
{
SwPageDesc* pDesc = ((SwPageFrm*)pFrm)->FindPageDesc();
if( pDesc )
{
rRegDiff = pDesc->GetRegHeight();
if( !rRegDiff )
{
const SwTxtFmtColl *pFmt = pDesc->GetRegisterFmtColl();
if( pFmt )
{
const SvxLineSpacingItem &rSpace = pFmt->GetLineSpacing();
if( SVX_LINE_SPACE_FIX == rSpace.GetLineSpaceRule() )
{
rRegDiff = rSpace.GetLineHeight();
pDesc->SetRegHeight( rRegDiff );
pDesc->SetRegAscent( ( 4 * rRegDiff ) / 5 );
}
else
{
ViewShell *pSh = GetShell();
SwFontAccess aFontAccess( pFmt, pSh );
SwFont aFnt( *aFontAccess.Get()->GetFont() );
OutputDevice *pOut = 0;
if( !GetTxtNode()->GetDoc()->IsBrowseMode() ||
(pSh && pSh->GetViewOptions()->IsPrtFormat()) )
pOut = GetTxtNode()->GetDoc()->GetPrt();
if( (!pOut || !((Printer*)pOut)->IsValid()) && pSh )
pOut = pSh->GetWin();
if( !pOut )
pOut = GetpApp()->GetDefaultDevice();
MapMode aOldMap( pOut->GetMapMode() );
pOut->SetMapMode( MapMode( MAP_TWIP ) );
aFnt.ChgFnt( pSh, pOut );
rRegDiff = aFnt.GetHeight( pSh, pOut );
KSHORT nNettoHeight = rRegDiff;
switch( rSpace.GetLineSpaceRule() )
{
case SVX_LINE_SPACE_AUTO:
break;
case SVX_LINE_SPACE_MIN:
{
if( rRegDiff < KSHORT( rSpace.GetLineHeight() ) )
rRegDiff = rSpace.GetLineHeight();
break;
}
default: ASSERT(
sal_False, ": unknown LineSpaceRule" );
}
switch( rSpace.GetInterLineSpaceRule() )
{
case SVX_INTER_LINE_SPACE_OFF:
break;
case SVX_INTER_LINE_SPACE_PROP:
{
long nTmp = rSpace.GetPropLineSpace();
if( nTmp < 50 )
nTmp = nTmp ? 50 : 100;
nTmp *= rRegDiff;
nTmp /= 100;
if( !nTmp )
++nTmp;
rRegDiff = (KSHORT)nTmp;
nNettoHeight = rRegDiff;
break;
}
case SVX_INTER_LINE_SPACE_FIX:
{
rRegDiff += rSpace.GetInterLineSpace();
nNettoHeight = rRegDiff;
break;
}
default: ASSERT( sal_False, ": unknown InterLineSpaceRule" );
}
pDesc->SetRegHeight( rRegDiff );
pDesc->SetRegAscent( rRegDiff - nNettoHeight +
aFnt.GetAscent( pSh, pOut ) );
pOut->SetMapMode( aOldMap );
}
}
}
rRegStart += pDesc->GetRegAscent() - rRegDiff;
}
}
}
return ( 0 != rRegDiff );
}