blob: f79f89b9ab4d4bc2643d745e0d03182203a6b8a2 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"
#include <hintids.hxx>
#include <sfx2/printer.hxx>
#include <editeng/lspcitem.hxx>
#include <editeng/adjitem.hxx>
#include <editeng/escpitem.hxx>
#include <editeng/lrspitem.hxx>
#include <editeng/pgrditem.hxx>
#include <vcl/window.hxx>
#include <vcl/svapp.hxx>
#include <viewsh.hxx> // ViewShell
#include <viewopt.hxx>
#include <ndtxt.hxx> // SwTxtNode
#include <pagefrm.hxx> // SwPageFrm
#include <paratr.hxx>
#include <SwPortionHandler.hxx>
#include <txtcfg.hxx>
#include <porrst.hxx>
#include <inftxt.hxx>
#include <txtpaint.hxx> // ClipVout
#include <swfntcch.hxx> // SwFontAccess
#include <tgrditem.hxx>
#include <pagedesc.hxx> // SwPageDesc
#include <frmatr.hxx>
#include <redlnitr.hxx> // SwRedlineItr
#include <porfly.hxx> // SwFlyPortion
#include <atrhndl.hxx>
#include "rootfrm.hxx"
#include <IDocumentRedlineAccess.hxx>
#include <IDocumentSettingAccess.hxx>
#include <IDocumentDeviceAccess.hxx>
/*************************************************************************
* 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( CH_PAR );
rInf.DrawText( aTmp, *this );
}
}
/*************************************************************************
* class SwBreakPortion
*************************************************************************/
SwBreakPortion::SwBreakPortion( const SwLinePortion &rPortion )
: SwLinePortion( rPortion )
{
nLineLength = 1;
SetWhichPor( POR_BRK );
}
xub_StrLen SwBreakPortion::GetCrsrOfst( const KSHORT ) const
{ return 0; }
KSHORT SwBreakPortion::GetViewWidth( const SwTxtSizeInfo & ) 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() )
rInf.DrawLineBreak( *this );
}
/*************************************************************************
* virtual SwBreakPortion::Format()
*************************************************************************/
sal_Bool SwBreakPortion::Format( SwTxtFormatInfo &rInf )
{
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;
}
/*************************************************************************
* virtual SwBreakPortion::HandlePortion()
*************************************************************************/
void SwBreakPortion::HandlePortion( SwPortionHandler& rPH ) const
{
rPH.Text( GetLen(), GetWhichPor() );
}
SwKernPortion::SwKernPortion( SwLinePortion &rPortion, short nKrn,
sal_Bool bBG, sal_Bool bGK ) :
nKern( nKrn ), bBackground( bBG ), bGridKern( bGK )
{
Height( rPortion.Height() );
SetAscent( rPortion.GetAscent() );
nLineLength = 0;
SetWhichPor( POR_KERN );
if( nKern > 0 )
Width( nKern );
rPortion.Insert( this );
}
SwKernPortion::SwKernPortion( const SwLinePortion& rPortion ) :
nKern( 0 ), bBackground( sal_False ), bGridKern( sal_True )
{
Height( rPortion.Height() );
SetAscent( rPortion.GetAscent() );
nLineLength = 0;
SetWhichPor( POR_KERN );
}
void SwKernPortion::Paint( const SwTxtPaintInfo &rInf ) const
{
if( Width() )
{
// bBackground is set for Kerning Portions between two fields
if ( bBackground )
rInf.DrawViewOpt( *this, POR_FLD );
rInf.DrawBackBrush( *this );
// do we have to repaint a post it portion?
if( rInf.OnWin() && pPortion && !pPortion->Width() )
pPortion->PrePaint( rInf, this );
if( rInf.GetFont()->IsPaintBlank() )
{
static sal_Char __READONLY_DATA sDoubleSpace[] = " ";
XubString aTxtDouble( sDoubleSpace, RTL_TEXTENCODING_MS_1252 );
// --> FME 2006-07-12 #b6439097#
SwRect aClipRect;
rInf.CalcRect( *this, &aClipRect, 0 );
SwSaveClip aClip( (OutputDevice*)rInf.GetOut() );
aClip.ChgClip( aClipRect, 0 );
// <--
rInf.DrawText( aTxtDouble, *this, 0, 2, sal_True );
}
}
}
void SwKernPortion::FormatEOL( SwTxtFormatInfo &rInf )
{
if ( bGridKern )
return;
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( (sal_uInt16)(rInf.GetTxtFrm()->Prt().Height()) );
aPos.X() = rInf.GetTxtFrm()->Frm().Left() +
rInf.GetTxtFrm()->Prt().Right();
aPos.Y() = rInf.GetTxtFrm()->Frm().Top() +
rInf.GetTxtFrm()->Prt().Bottom();
SetWhichPor( POR_ARROW );
}
void SwArrowPortion::Paint( const SwTxtPaintInfo &rInf ) const
{
((SwArrowPortion*)this)->aPos = rInf.GetPos();
}
SwLinePortion *SwArrowPortion::Compress() { return this; }
SwTwips SwTxtFrm::EmptyHeight() const
{
ASSERT( ! IsVertical() || ! IsSwapped(),"SwTxtFrm::EmptyHeight with swapped frame" );
SwFont *pFnt;
const SwTxtNode& rTxtNode = *GetTxtNode();
const IDocumentSettingAccess* pIDSA = rTxtNode.getIDocumentSettingAccess();
ViewShell *pSh = getRootFrm()->GetCurrShell();
if ( rTxtNode.HasSwAttrSet() )
{
const SwAttrSet *pAttrSet = &( rTxtNode.GetSwAttrSet() );
pFnt = new SwFont( pAttrSet, pIDSA );
}
else
{
SwFontAccess aFontAccess( &rTxtNode.GetAnyFmtColl(), pSh);
pFnt = new SwFont( *aFontAccess.Get()->GetFont() );
pFnt->ChkMagic( pSh, pFnt->GetActual() );
}
if ( IsVertical() )
pFnt->SetVertical( 2700 );
OutputDevice* pOut = pSh ? pSh->GetOut() : 0;
if ( !pOut || !pSh->GetViewOptions()->getBrowseMode() ||
pSh->GetViewOptions()->IsPrtFormat() )
{
pOut = rTxtNode.getIDocumentDeviceAccess()->getReferenceDevice(true);
}
const IDocumentRedlineAccess* pIDRA = rTxtNode.getIDocumentRedlineAccess();
if( IDocumentRedlineAccess::IsShowChanges( pIDRA->GetRedlineMode() ) )
{
MSHORT nRedlPos = pIDRA->GetRedlinePos( rTxtNode, USHRT_MAX );
if( MSHRT_MAX != nRedlPos )
{
SwAttrHandler aAttrHandler;
aAttrHandler.Init( GetTxtNode()->GetSwAttrSet(),
*GetTxtNode()->getIDocumentSettingAccess(), NULL );
SwRedlineItr aRedln( rTxtNode, *pFnt, aAttrHandler,
nRedlPos, sal_True );
}
}
SwTwips nRet;
if( !pOut )
nRet = IsVertical() ?
Prt().SSize().Width() + 1 :
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()
{
ASSERT( ! IsVertical() || ! IsSwapped(),"SwTxtFrm::FormatEmpty with swapped frame" );
if ( HasFollow() || GetTxtNode()->GetpSwpHints() ||
0 != GetTxtNode()->GetNumRule() ||
GetTxtNode()->HasHiddenCharAttribute( true ) ||
IsInFtn() || ( HasPara() && GetPara()->IsPrepMustFit() ) )
return sal_False;
const SwAttrSet& aSet = GetTxtNode()->GetSwAttrSet();
const SvxAdjust nAdjust = aSet.GetAdjust().GetAdjust();
if( ( ( ! IsRightToLeft() && ( SVX_ADJUST_LEFT != nAdjust ) ) ||
( IsRightToLeft() && ( SVX_ADJUST_RIGHT != nAdjust ) ) ) ||
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();
if ( GetTxtNode()->GetSwAttrSet().GetParaGrid().GetValue() &&
IsInDocBody() )
{
GETGRID( FindPageFrm() )
if ( pGrid )
nHeight = pGrid->GetBaseHeight() + pGrid->GetRubyHeight();
}
SWRECTFN( this )
const SwTwips nChg = nHeight - (Prt().*fnRect->fnGetHeight)();
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;
// --> OD 2004-11-17 #i35635# - call method <HideAndShowObjects()>
// to assure that objects anchored at the empty paragraph are
// correctly visible resp. invisible.
HideAndShowObjects();
// <--
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() )
{
SWRECTFN( pFrm )
rRegStart = (pFrm->*fnRect->fnGetPrtTop)();
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 = getRootFrm()->GetCurrShell();
SwFontAccess aFontAccess( pFmt, pSh );
SwFont aFnt( *aFontAccess.Get()->GetFont() );
OutputDevice *pOut = 0;
if( !pSh || !pSh->GetViewOptions()->getBrowseMode() ||
pSh->GetViewOptions()->IsPrtFormat() )
pOut = GetTxtNode()->getIDocumentDeviceAccess()->getReferenceDevice( true );
if( pSh && !pOut )
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 = 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 );
}
}
}
const long nTmpDiff = pDesc->GetRegAscent() - rRegDiff;
if ( bVert )
rRegStart -= nTmpDiff;
else
rRegStart += nTmpDiff;
}
}
}
return ( 0 != rRegDiff );
}
/*************************************************************************
* virtual SwHiddenTextPortion::Paint()
*************************************************************************/
void SwHiddenTextPortion::Paint( const SwTxtPaintInfo & rInf) const
{
(void)rInf;
#if OSL_DEBUG_LEVEL > 1
OutputDevice* pOut = (OutputDevice*)rInf.GetOut();
Color aCol( SwViewOption::GetFieldShadingsColor() );
Color aOldColor( pOut->GetFillColor() );
pOut->SetFillColor( aCol );
Point aPos( rInf.GetPos() );
aPos.Y() -= 150;
aPos.X() -= 25;
SwRect aRect( aPos, Size( 100, 200 ) );
((OutputDevice*)pOut)->DrawRect( aRect.SVRect() );
pOut->SetFillColor( aOldColor );
#endif
}
/*************************************************************************
* virtual SwHiddenTextPortion::Format()
*************************************************************************/
sal_Bool SwHiddenTextPortion::Format( SwTxtFormatInfo &rInf )
{
Width( 0 );
rInf.GetTxtFrm()->HideFootnotes( rInf.GetIdx(), rInf.GetIdx() + GetLen() );
return sal_False;
};
/*************************************************************************
* virtual SwControlCharPortion::Paint()
*************************************************************************/
void SwControlCharPortion::Paint( const SwTxtPaintInfo &rInf ) const
{
if ( Width() ) // is only set during prepaint mode
{
rInf.DrawViewOpt( *this, POR_CONTROLCHAR );
if ( !rInf.GetOpt().IsPagePreview() &&
!rInf.GetOpt().IsReadonly() &&
SwViewOption::IsFieldShadings() &&
CHAR_ZWNBSP != mcChar )
{
SwFont aTmpFont( *rInf.GetFont() );
aTmpFont.SetEscapement( CHAR_ZWSP == mcChar ? DFLT_ESC_AUTO_SUB : -25 );
const sal_uInt16 nProp = 40;
aTmpFont.SetProportion( nProp ); // a smaller font
SwFontSave aFontSave( rInf, &aTmpFont );
String aOutString;
switch ( mcChar )
{
case CHAR_ZWSP :
aOutString = '/'; break;
// case CHAR_LRM :
// rTxt = sal_Unicode(0x2514); break;
// case CHAR_RLM :
// rTxt = sal_Unicode(0x2518); break;
}
if ( !mnHalfCharWidth )
mnHalfCharWidth = rInf.GetTxtSize( aOutString ).Width() / 2;
Point aOldPos = rInf.GetPos();
Point aNewPos( aOldPos );
aNewPos.X() = aNewPos.X() + ( Width() / 2 ) - mnHalfCharWidth;
const_cast< SwTxtPaintInfo& >( rInf ).SetPos( aNewPos );
rInf.DrawText( aOutString, *this );
const_cast< SwTxtPaintInfo& >( rInf ).SetPos( aOldPos );
}
}
}
/*************************************************************************
* virtual SwControlCharPortion::Format()
*************************************************************************/
sal_Bool SwControlCharPortion::Format( SwTxtFormatInfo &rInf )
{
const SwLinePortion* pRoot = rInf.GetRoot();
Width( 0 );
Height( pRoot->Height() );
SetAscent( pRoot->GetAscent() );
return sal_False;
}
/*************************************************************************
* virtual SwControlCharPortion::GetViewWidth()
*************************************************************************/
KSHORT SwControlCharPortion::GetViewWidth( const SwTxtSizeInfo& rInf ) const
{
if( !mnViewWidth )
mnViewWidth = rInf.GetTxtSize( ' ' ).Width();
return mnViewWidth;
}