Added a new compatibility option to keep the previous behavior, but changed the default to avoid lines insertion for tabs when there are tab stops set beyond the end margin
1940 lines
64 KiB
C++
1940 lines
64 KiB
C++
/* -*- 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.
|
|
*
|
|
************************************************************************/
|
|
|
|
// MARKER(update_precomp.py): autogen include statement, do not remove
|
|
#include "precompiled_sw.hxx"
|
|
|
|
|
|
#include <com/sun/star/uno/Sequence.h>
|
|
#include <unotools/linguprops.hxx>
|
|
#include <unotools/lingucfg.hxx>
|
|
#include <hintids.hxx>
|
|
#include <sfx2/printer.hxx>
|
|
#include <editeng/hyznitem.hxx>
|
|
#include <editeng/escpitem.hxx>
|
|
#include <editeng/hngpnctitem.hxx>
|
|
#include <editeng/scriptspaceitem.hxx>
|
|
#include <editeng/brshitem.hxx>
|
|
#include <editeng/splwrap.hxx>
|
|
#include <editeng/pgrditem.hxx>
|
|
#include <editeng/tstpitem.hxx>
|
|
|
|
#include <SwSmartTagMgr.hxx>
|
|
#include <linguistic/lngprops.hxx>
|
|
#include <editeng/unolingu.hxx>
|
|
#include <breakit.hxx>
|
|
#include <editeng/forbiddenruleitem.hxx>
|
|
#include <txatbase.hxx>
|
|
#include <fmtinfmt.hxx>
|
|
#include <swmodule.hxx>
|
|
#include <vcl/svapp.hxx>
|
|
#include <vcl/wrkwin.hxx>
|
|
#include <viewsh.hxx> // ViewShell
|
|
#include <viewopt.hxx> // SwViewOptions
|
|
#include <frmtool.hxx> // DrawGraphic
|
|
#include <IDocumentSettingAccess.hxx>
|
|
#include <IDocumentDeviceAccess.hxx>
|
|
#include <paratr.hxx> // SwFmtDrop
|
|
#include <rootfrm.hxx> // SwRootFrm
|
|
#include <inftxt.hxx> // SwTxtInfo
|
|
#include <blink.hxx> // SwBlink
|
|
#include <noteurl.hxx> // SwNoteURL
|
|
#include <porftn.hxx> // SwFtnPortion
|
|
#include <porrst.hxx> // SwHangingPortion
|
|
#include <itratr.hxx>
|
|
#include <accessibilityoptions.hxx>
|
|
#include <wrong.hxx>
|
|
#include <doc.hxx>
|
|
#include <pam.hxx>
|
|
#include <SwGrammarMarkUp.hxx>
|
|
#include <cstdio>
|
|
// #i12836# enhanced pdf export
|
|
#include <EnhancedPDFExportHelper.hxx>
|
|
|
|
#include <unomid.h>
|
|
|
|
#if OSL_DEBUG_LEVEL > 1
|
|
#include <stdio.h>
|
|
#endif
|
|
|
|
using namespace ::com::sun::star;
|
|
using namespace ::com::sun::star::linguistic2;
|
|
using namespace ::com::sun::star::uno;
|
|
using namespace ::com::sun::star::beans;
|
|
|
|
|
|
#define CHAR_UNDERSCORE ((sal_Unicode)0x005F)
|
|
#define CHAR_LEFT_ARROW ((sal_Unicode)0x25C0)
|
|
#define CHAR_RIGHT_ARROW ((sal_Unicode)0x25B6)
|
|
#define CHAR_TAB ((sal_Unicode)0x2192)
|
|
#define CHAR_TAB_RTL ((sal_Unicode)0x2190)
|
|
#define CHAR_LINEBREAK ((sal_Unicode)0x21B5)
|
|
#define CHAR_LINEBREAK_RTL ((sal_Unicode)0x21B3)
|
|
|
|
#define DRAW_SPECIAL_OPTIONS_CENTER 1
|
|
#define DRAW_SPECIAL_OPTIONS_ROTATE 2
|
|
|
|
//
|
|
// variable moved to class <numfunc:GetDefBulletConfig>
|
|
//extern const sal_Char sBulletFntName[];
|
|
namespace numfunc
|
|
{
|
|
extern const String& GetDefBulletFontname();
|
|
extern bool IsDefBulletFontUserDefined();
|
|
}
|
|
|
|
#if OSL_DEBUG_LEVEL > 1
|
|
// Test2: WYSIWYG++
|
|
// Test4: WYSIWYG debug
|
|
static sal_Bool bDbgLow = sal_False;
|
|
#endif
|
|
|
|
#if OSL_DEBUG_LEVEL > 1
|
|
sal_Bool SwTxtSizeInfo::IsOptCalm() const { return !GetOpt().IsTest3(); }
|
|
sal_Bool SwTxtSizeInfo::IsOptLow() const { return bDbgLow; }
|
|
sal_Bool SwTxtSizeInfo::IsOptDbg() const { return GetOpt().IsTest4(); }
|
|
sal_Bool SwTxtSizeInfo::IsOptTest1() const { return GetOpt().IsTest1(); }
|
|
sal_Bool SwTxtSizeInfo::IsOptTest2() const { return GetOpt().IsTest2(); }
|
|
sal_Bool SwTxtSizeInfo::IsOptTest3() const { return GetOpt().IsTest3(); }
|
|
sal_Bool SwTxtSizeInfo::IsOptTest4() const { return GetOpt().IsTest4(); }
|
|
sal_Bool SwTxtSizeInfo::IsOptTest5() const { return GetOpt().IsTest5(); }
|
|
sal_Bool SwTxtSizeInfo::IsOptTest6() const { return GetOpt().IsTest6(); }
|
|
sal_Bool SwTxtSizeInfo::IsOptTest7() const { return GetOpt().IsTest7(); }
|
|
sal_Bool SwTxtSizeInfo::IsOptTest8() const { return GetOpt().IsTest8(); }
|
|
#endif
|
|
|
|
/*************************************************************************
|
|
* SwLineInfo::SwLineInfo()
|
|
*************************************************************************/
|
|
|
|
SwLineInfo::SwLineInfo()
|
|
: pRuler( 0 ),
|
|
pSpace( 0 ),
|
|
nVertAlign( 0 ),
|
|
nDefTabStop( 0 ),
|
|
bListTabStopIncluded( false ),
|
|
nListTabStopPosition( 0 )
|
|
{
|
|
}
|
|
|
|
SwLineInfo::~SwLineInfo()
|
|
{
|
|
delete pRuler;
|
|
}
|
|
void SwLineInfo::CtorInitLineInfo( const SwAttrSet& rAttrSet,
|
|
const SwTxtNode& rTxtNode )
|
|
{
|
|
delete pRuler;
|
|
pRuler = new SvxTabStopItem( rAttrSet.GetTabStops() );
|
|
if ( rTxtNode.GetListTabStopPosition( nListTabStopPosition ) )
|
|
{
|
|
bListTabStopIncluded = true;
|
|
|
|
// insert the list tab stop into SvxTabItem instance <pRuler>
|
|
const SvxTabStop aListTabStop( nListTabStopPosition,
|
|
SVX_TAB_ADJUST_LEFT );
|
|
pRuler->Insert( aListTabStop );
|
|
|
|
// remove default tab stops, which are before the inserted list tab stop
|
|
for ( sal_uInt16 i = 0; i < pRuler->Count(); i++ )
|
|
{
|
|
if ( (*pRuler)[i].GetTabPos() < nListTabStopPosition &&
|
|
(*pRuler)[i].GetAdjustment() == SVX_TAB_ADJUST_DEFAULT )
|
|
{
|
|
pRuler->Remove(i);
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( !rTxtNode.getIDocumentSettingAccess()->get(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT) )
|
|
{
|
|
// remove default tab stop at position 0
|
|
for ( sal_uInt16 i = 0; i < pRuler->Count(); i++ )
|
|
{
|
|
if ( (*pRuler)[i].GetTabPos() == 0 &&
|
|
(*pRuler)[i].GetAdjustment() == SVX_TAB_ADJUST_DEFAULT )
|
|
{
|
|
pRuler->Remove(i);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
pSpace = &rAttrSet.GetLineSpacing();
|
|
nVertAlign = rAttrSet.GetParaVertAlign().GetValue();
|
|
nDefTabStop = MSHRT_MAX;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SwTxtInfo::CtorInitTxtInfo()
|
|
*************************************************************************/
|
|
|
|
void SwTxtInfo::CtorInitTxtInfo( SwTxtFrm *pFrm )
|
|
{
|
|
pPara = pFrm->GetPara();
|
|
nTxtStart = pFrm->GetOfst();
|
|
if( !pPara )
|
|
{
|
|
OSL_ENSURE( pPara, "+SwTxtInfo::CTOR: missing paragraph information" );
|
|
pFrm->Format();
|
|
pPara = pFrm->GetPara();
|
|
}
|
|
}
|
|
|
|
SwTxtInfo::SwTxtInfo( const SwTxtInfo &rInf )
|
|
: pPara( ((SwTxtInfo&)rInf).GetParaPortion() ),
|
|
nTxtStart( rInf.GetTxtStart() )
|
|
{ }
|
|
|
|
|
|
#if OSL_DEBUG_LEVEL > 1
|
|
/*************************************************************************
|
|
* ChkOutDev()
|
|
*************************************************************************/
|
|
|
|
void ChkOutDev( const SwTxtSizeInfo &rInf )
|
|
{
|
|
if ( !rInf.GetVsh() )
|
|
return;
|
|
|
|
const OutputDevice* pOut = rInf.GetOut();
|
|
const OutputDevice* pRef = rInf.GetRefDev();
|
|
OSL_ENSURE( pOut && pRef, "ChkOutDev: invalid output devices" );
|
|
}
|
|
#endif // PRODUCT
|
|
|
|
|
|
inline xub_StrLen GetMinLen( const SwTxtSizeInfo &rInf )
|
|
{
|
|
const xub_StrLen nInfLen = rInf.GetIdx() + rInf.GetLen();
|
|
return Min( rInf.GetTxt().Len(), nInfLen );
|
|
}
|
|
|
|
|
|
SwTxtSizeInfo::SwTxtSizeInfo( const SwTxtSizeInfo &rNew )
|
|
: SwTxtInfo( rNew ),
|
|
pKanaComp(((SwTxtSizeInfo&)rNew).GetpKanaComp()),
|
|
pVsh(((SwTxtSizeInfo&)rNew).GetVsh()),
|
|
pOut(((SwTxtSizeInfo&)rNew).GetOut()),
|
|
pRef(((SwTxtSizeInfo&)rNew).GetRefDev()),
|
|
pFnt(((SwTxtSizeInfo&)rNew).GetFont()),
|
|
pUnderFnt(((SwTxtSizeInfo&)rNew).GetUnderFnt()),
|
|
pFrm(rNew.pFrm),
|
|
pOpt(&rNew.GetOpt()),
|
|
pTxt(&rNew.GetTxt()),
|
|
nIdx(rNew.GetIdx()),
|
|
nLen(rNew.GetLen()),
|
|
nKanaIdx( rNew.GetKanaIdx() ),
|
|
bOnWin( rNew.OnWin() ),
|
|
bNotEOL( rNew.NotEOL() ),
|
|
bURLNotify( rNew.URLNotify() ),
|
|
bStopUnderFlow( rNew.StopUnderFlow() ),
|
|
bFtnInside( rNew.IsFtnInside() ),
|
|
bOtherThanFtnInside( rNew.IsOtherThanFtnInside() ),
|
|
bMulti( rNew.IsMulti() ),
|
|
bFirstMulti( rNew.IsFirstMulti() ),
|
|
bRuby( rNew.IsRuby() ),
|
|
bHanging( rNew.IsHanging() ),
|
|
bScriptSpace( rNew.HasScriptSpace() ),
|
|
bForbiddenChars( rNew.HasForbiddenChars() ),
|
|
bSnapToGrid( rNew.SnapToGrid() ),
|
|
nDirection( rNew.GetDirection() )
|
|
{
|
|
#if OSL_DEBUG_LEVEL > 1
|
|
ChkOutDev( *this );
|
|
#endif
|
|
}
|
|
|
|
void SwTxtSizeInfo::CtorInitTxtSizeInfo( SwTxtFrm *pFrame, SwFont *pNewFnt,
|
|
const xub_StrLen nNewIdx, const xub_StrLen nNewLen )
|
|
{
|
|
pKanaComp = NULL;
|
|
nKanaIdx = 0;
|
|
pFrm = pFrame;
|
|
CtorInitTxtInfo( pFrm );
|
|
const SwTxtNode *pNd = pFrm->GetTxtNode();
|
|
pVsh = pFrm->getRootFrm()->GetCurrShell();
|
|
|
|
// Get the output and reference device
|
|
if ( pVsh )
|
|
{
|
|
pOut = pVsh->GetOut();
|
|
pRef = &pVsh->GetRefDev();
|
|
bOnWin = pVsh->GetWin() || OUTDEV_WINDOW == pOut->GetOutDevType();
|
|
}
|
|
else
|
|
{
|
|
//Zugriff ueber StarONE, es muss keine Shell existieren oder aktiv sein.
|
|
if ( pNd->getIDocumentSettingAccess()->get(IDocumentSettingAccess::HTML_MODE) )
|
|
{
|
|
//in Ermangelung eines Besseren kann hier ja wohl nur noch das
|
|
//AppWin genommen werden?
|
|
pOut = GetpApp()->GetDefaultDevice();
|
|
}
|
|
else
|
|
pOut = pNd->getIDocumentDeviceAccess()->getPrinter( false );
|
|
|
|
pRef = pOut;
|
|
}
|
|
|
|
#if OSL_DEBUG_LEVEL > 1
|
|
ChkOutDev( *this );
|
|
#endif
|
|
|
|
// Set default layout mode ( LTR or RTL ).
|
|
if ( pFrm->IsRightToLeft() )
|
|
{
|
|
pOut->SetLayoutMode( TEXT_LAYOUT_BIDI_STRONG | TEXT_LAYOUT_BIDI_RTL );
|
|
pRef->SetLayoutMode( TEXT_LAYOUT_BIDI_STRONG | TEXT_LAYOUT_BIDI_RTL );
|
|
nDirection = DIR_RIGHT2LEFT;
|
|
}
|
|
else
|
|
{
|
|
pOut->SetLayoutMode( TEXT_LAYOUT_BIDI_STRONG );
|
|
pRef->SetLayoutMode( TEXT_LAYOUT_BIDI_STRONG );
|
|
nDirection = DIR_LEFT2RIGHT;
|
|
}
|
|
|
|
//
|
|
// The Options
|
|
//
|
|
pOpt = pVsh ?
|
|
pVsh->GetViewOptions() :
|
|
SW_MOD()->GetViewOption( pNd->getIDocumentSettingAccess()->get(IDocumentSettingAccess::HTML_MODE) ); //Options vom Module wg. StarONE
|
|
|
|
// bURLNotify wird gesetzt, wenn MakeGraphic dies vorbereitet
|
|
// TODO: Aufdr?seln
|
|
bURLNotify = pNoteURL && !bOnWin;
|
|
|
|
SetSnapToGrid( pNd->GetSwAttrSet().GetParaGrid().GetValue() &&
|
|
pFrm->IsInDocBody() );
|
|
|
|
pFnt = pNewFnt;
|
|
pUnderFnt = 0;
|
|
pTxt = &pNd->GetTxt();
|
|
|
|
nIdx = nNewIdx;
|
|
nLen = nNewLen;
|
|
bNotEOL = sal_False;
|
|
bStopUnderFlow = bFtnInside = bOtherThanFtnInside = sal_False;
|
|
bMulti = bFirstMulti = bRuby = bHanging = bScriptSpace =
|
|
bForbiddenChars = sal_False;
|
|
|
|
SetLen( GetMinLen( *this ) );
|
|
}
|
|
|
|
SwTxtSizeInfo::SwTxtSizeInfo( const SwTxtSizeInfo &rNew, const XubString &rTxt,
|
|
const xub_StrLen nIndex, const xub_StrLen nLength )
|
|
: SwTxtInfo( rNew ),
|
|
pKanaComp(((SwTxtSizeInfo&)rNew).GetpKanaComp()),
|
|
pVsh(((SwTxtSizeInfo&)rNew).GetVsh()),
|
|
pOut(((SwTxtSizeInfo&)rNew).GetOut()),
|
|
pRef(((SwTxtSizeInfo&)rNew).GetRefDev()),
|
|
pFnt(((SwTxtSizeInfo&)rNew).GetFont()),
|
|
pUnderFnt(((SwTxtSizeInfo&)rNew).GetUnderFnt()),
|
|
pFrm( rNew.pFrm ),
|
|
pOpt(&rNew.GetOpt()),
|
|
pTxt(&rTxt),
|
|
nIdx(nIndex),
|
|
nLen(nLength),
|
|
nKanaIdx( rNew.GetKanaIdx() ),
|
|
bOnWin( rNew.OnWin() ),
|
|
bNotEOL( rNew.NotEOL() ),
|
|
bURLNotify( rNew.URLNotify() ),
|
|
bStopUnderFlow( rNew.StopUnderFlow() ),
|
|
bFtnInside( rNew.IsFtnInside() ),
|
|
bOtherThanFtnInside( rNew.IsOtherThanFtnInside() ),
|
|
bMulti( rNew.IsMulti() ),
|
|
bFirstMulti( rNew.IsFirstMulti() ),
|
|
bRuby( rNew.IsRuby() ),
|
|
bHanging( rNew.IsHanging() ),
|
|
bScriptSpace( rNew.HasScriptSpace() ),
|
|
bForbiddenChars( rNew.HasForbiddenChars() ),
|
|
bSnapToGrid( rNew.SnapToGrid() ),
|
|
nDirection( rNew.GetDirection() )
|
|
{
|
|
#if OSL_DEBUG_LEVEL > 1
|
|
ChkOutDev( *this );
|
|
#endif
|
|
SetLen( GetMinLen( *this ) );
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SwTxtSizeInfo::SelectFont()
|
|
*************************************************************************/
|
|
|
|
void SwTxtSizeInfo::SelectFont()
|
|
{
|
|
// 8731: Der Weg muss ueber ChgPhysFnt gehen, sonst geraet
|
|
// der FontMetricCache durcheinander. In diesem Fall steht pLastMet
|
|
// auf dem alten Wert.
|
|
// Falsch: GetOut()->SetFont( GetFont()->GetFnt() );
|
|
GetFont()->Invalidate();
|
|
GetFont()->ChgPhysFnt( pVsh, *GetOut() );
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SwTxtSizeInfo::NoteAnimation()
|
|
*************************************************************************/
|
|
|
|
void SwTxtSizeInfo::NoteAnimation() const
|
|
{
|
|
if( OnWin() )
|
|
SwRootFrm::FlushVout();
|
|
|
|
OSL_ENSURE( pOut == pVsh->GetOut(),
|
|
"SwTxtSizeInfo::NoteAnimation() changed pOut" );
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SwTxtSizeInfo::GetTxtSize()
|
|
*************************************************************************/
|
|
|
|
SwPosSize SwTxtSizeInfo::GetTxtSize( OutputDevice* pOutDev,
|
|
const SwScriptInfo* pSI,
|
|
const XubString& rTxt,
|
|
const xub_StrLen nIndex,
|
|
const xub_StrLen nLength,
|
|
const sal_uInt16 nComp ) const
|
|
{
|
|
SwDrawTextInfo aDrawInf( pVsh, *pOutDev, pSI, rTxt, nIndex, nLength );
|
|
aDrawInf.SetFrm( pFrm );
|
|
aDrawInf.SetFont( pFnt );
|
|
aDrawInf.SetSnapToGrid( SnapToGrid() );
|
|
aDrawInf.SetKanaComp( nComp );
|
|
SwPosSize aSize = pFnt->_GetTxtSize( aDrawInf );
|
|
return aSize;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SwTxtSizeInfo::GetTxtSize()
|
|
*************************************************************************/
|
|
|
|
SwPosSize SwTxtSizeInfo::GetTxtSize() const
|
|
{
|
|
const SwScriptInfo& rSI =
|
|
( (SwParaPortion*)GetParaPortion() )->GetScriptInfo();
|
|
|
|
// in some cases, compression is not allowed or surpressed for
|
|
// performance reasons
|
|
sal_uInt16 nComp =( SW_CJK == GetFont()->GetActual() &&
|
|
rSI.CountCompChg() &&
|
|
! IsMulti() ) ?
|
|
GetKanaComp() :
|
|
0 ;
|
|
|
|
SwDrawTextInfo aDrawInf( pVsh, *pOut, &rSI, *pTxt, nIdx, nLen );
|
|
aDrawInf.SetFrm( pFrm );
|
|
aDrawInf.SetFont( pFnt );
|
|
aDrawInf.SetSnapToGrid( SnapToGrid() );
|
|
aDrawInf.SetKanaComp( nComp );
|
|
return pFnt->_GetTxtSize( aDrawInf );
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SwTxtSizeInfo::GetTxtSize()
|
|
*************************************************************************/
|
|
|
|
void SwTxtSizeInfo::GetTxtSize( const SwScriptInfo* pSI, const xub_StrLen nIndex,
|
|
const xub_StrLen nLength, const sal_uInt16 nComp,
|
|
sal_uInt16& nMinSize, sal_uInt16& nMaxSizeDiff ) const
|
|
{
|
|
SwDrawTextInfo aDrawInf( pVsh, *pOut, pSI, *pTxt, nIndex, nLength );
|
|
aDrawInf.SetFrm( pFrm );
|
|
aDrawInf.SetFont( pFnt );
|
|
aDrawInf.SetSnapToGrid( SnapToGrid() );
|
|
aDrawInf.SetKanaComp( nComp );
|
|
SwPosSize aSize = pFnt->_GetTxtSize( aDrawInf );
|
|
nMaxSizeDiff = (sal_uInt16)aDrawInf.GetKanaDiff();
|
|
nMinSize = aSize.Width();
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SwTxtSizeInfo::GetTxtBreak()
|
|
*************************************************************************/
|
|
|
|
xub_StrLen SwTxtSizeInfo::GetTxtBreak( const long nLineWidth,
|
|
const xub_StrLen nMaxLen,
|
|
const sal_uInt16 nComp ) const
|
|
{
|
|
const SwScriptInfo& rScriptInfo =
|
|
( (SwParaPortion*)GetParaPortion() )->GetScriptInfo();
|
|
|
|
OSL_ENSURE( pRef == pOut, "GetTxtBreak is supposed to use the RefDev" );
|
|
SwDrawTextInfo aDrawInf( pVsh, *pOut, &rScriptInfo,
|
|
*pTxt, GetIdx(), nMaxLen );
|
|
aDrawInf.SetFrm( pFrm );
|
|
aDrawInf.SetFont( pFnt );
|
|
aDrawInf.SetSnapToGrid( SnapToGrid() );
|
|
aDrawInf.SetKanaComp( nComp );
|
|
aDrawInf.SetHyphPos( 0 );
|
|
|
|
return pFnt->GetTxtBreak( aDrawInf, nLineWidth );
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SwTxtSizeInfo::GetTxtBreak()
|
|
*************************************************************************/
|
|
|
|
xub_StrLen SwTxtSizeInfo::GetTxtBreak( const long nLineWidth,
|
|
const xub_StrLen nMaxLen,
|
|
const sal_uInt16 nComp,
|
|
xub_StrLen& rExtraCharPos ) const
|
|
{
|
|
const SwScriptInfo& rScriptInfo =
|
|
( (SwParaPortion*)GetParaPortion() )->GetScriptInfo();
|
|
|
|
OSL_ENSURE( pRef == pOut, "GetTxtBreak is supposed to use the RefDev" );
|
|
SwDrawTextInfo aDrawInf( pVsh, *pOut, &rScriptInfo,
|
|
*pTxt, GetIdx(), nMaxLen );
|
|
aDrawInf.SetFrm( pFrm );
|
|
aDrawInf.SetFont( pFnt );
|
|
aDrawInf.SetSnapToGrid( SnapToGrid() );
|
|
aDrawInf.SetKanaComp( nComp );
|
|
aDrawInf.SetHyphPos( &rExtraCharPos );
|
|
|
|
return pFnt->GetTxtBreak( aDrawInf, nLineWidth );
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SwTxtPaintInfo::CtorInitTxtPaintInfo()
|
|
*************************************************************************/
|
|
|
|
void SwTxtPaintInfo::CtorInitTxtPaintInfo( SwTxtFrm *pFrame, const SwRect &rPaint )
|
|
{
|
|
CtorInitTxtSizeInfo( pFrame );
|
|
aTxtFly.CtorInitTxtFly( pFrame ),
|
|
aPaintRect = rPaint;
|
|
nSpaceIdx = 0;
|
|
pSpaceAdd = NULL;
|
|
pWrongList = NULL;
|
|
pGrammarCheckList = NULL;
|
|
pSmartTags = NULL; // SMARTTAGS
|
|
|
|
#if OSL_DEBUG_LEVEL > 1
|
|
pBrushItem = ((SvxBrushItem*)-1);
|
|
#else
|
|
pBrushItem = 0;
|
|
#endif
|
|
}
|
|
|
|
SwTxtPaintInfo::SwTxtPaintInfo( const SwTxtPaintInfo &rInf, const XubString &rTxt )
|
|
: SwTxtSizeInfo( rInf, rTxt ),
|
|
pWrongList( rInf.GetpWrongList() ),
|
|
pGrammarCheckList( rInf.GetGrammarCheckList() ),
|
|
pSmartTags( rInf.GetSmartTags() ), // SMARTTAGS
|
|
pSpaceAdd( rInf.GetpSpaceAdd() ),
|
|
pBrushItem( rInf.GetBrushItem() ),
|
|
aTxtFly( *rInf.GetTxtFly() ),
|
|
aPos( rInf.GetPos() ),
|
|
aPaintRect( rInf.GetPaintRect() ),
|
|
nSpaceIdx( rInf.GetSpaceIdx() )
|
|
{ }
|
|
|
|
SwTxtPaintInfo::SwTxtPaintInfo( const SwTxtPaintInfo &rInf )
|
|
: SwTxtSizeInfo( rInf ),
|
|
pWrongList( rInf.GetpWrongList() ),
|
|
pGrammarCheckList( rInf.GetGrammarCheckList() ),
|
|
pSmartTags( rInf.GetSmartTags() ), // SMARTTAGS
|
|
pSpaceAdd( rInf.GetpSpaceAdd() ),
|
|
pBrushItem( rInf.GetBrushItem() ),
|
|
aTxtFly( *rInf.GetTxtFly() ),
|
|
aPos( rInf.GetPos() ),
|
|
aPaintRect( rInf.GetPaintRect() ),
|
|
nSpaceIdx( rInf.GetSpaceIdx() )
|
|
{ }
|
|
|
|
extern Color aGlobalRetoucheColor;
|
|
|
|
/*************************************************************************
|
|
* lcl_IsDarkBackground
|
|
*
|
|
* Returns if the current background color is dark.
|
|
*************************************************************************/
|
|
|
|
sal_Bool lcl_IsDarkBackground( const SwTxtPaintInfo& rInf )
|
|
{
|
|
const Color* pCol = rInf.GetFont()->GetBackColor();
|
|
if( ! pCol || COL_TRANSPARENT == pCol->GetColor() )
|
|
{
|
|
const SvxBrushItem* pItem;
|
|
SwRect aOrigBackRect;
|
|
|
|
/// OD 21.08.2002
|
|
/// consider, that [GetBackgroundBrush(...)] can set <pCol>
|
|
/// - see implementation in /core/layout/paintfrm.cxx
|
|
/// OD 21.08.2002 #99657#
|
|
/// There is a background color, if there is a background brush and
|
|
/// its color is *not* "no fill"/"auto fill".
|
|
if( rInf.GetTxtFrm()->GetBackgroundBrush( pItem, pCol, aOrigBackRect, sal_False ) )
|
|
{
|
|
if ( !pCol )
|
|
pCol = &pItem->GetColor();
|
|
|
|
/// OD 30.08.2002 #99657#
|
|
/// determined color <pCol> can be <COL_TRANSPARENT>. Thus, check it.
|
|
if ( pCol->GetColor() == COL_TRANSPARENT)
|
|
pCol = NULL;
|
|
}
|
|
else
|
|
pCol = NULL;
|
|
}
|
|
|
|
|
|
if( !pCol )
|
|
pCol = &aGlobalRetoucheColor;
|
|
|
|
return pCol->IsDark();
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SwTxtPaintInfo::_DrawText()
|
|
*************************************************************************/
|
|
|
|
void SwTxtPaintInfo::_DrawText( const XubString &rText, const SwLinePortion &rPor,
|
|
const xub_StrLen nStart, const xub_StrLen nLength,
|
|
const sal_Bool bKern, const sal_Bool bWrong,
|
|
const sal_Bool bSmartTag,
|
|
const sal_Bool bGrammarCheck ) // SMARTTAGS
|
|
{
|
|
if( !nLength )
|
|
return;
|
|
|
|
if( GetFont()->IsBlink() && OnWin() && rPor.Width() )
|
|
{
|
|
// check if accessibility options allow blinking portions:
|
|
const ViewShell* pSh = GetTxtFrm()->getRootFrm()->GetCurrShell();
|
|
if ( pSh && ! pSh->GetAccessibilityOptions()->IsStopAnimatedText() &&
|
|
! pSh->IsPreView() )
|
|
{
|
|
if( !pBlink )
|
|
pBlink = new SwBlink();
|
|
|
|
Point aPoint( aPos );
|
|
|
|
if ( GetTxtFrm()->IsRightToLeft() )
|
|
GetTxtFrm()->SwitchLTRtoRTL( aPoint );
|
|
|
|
if ( TEXT_LAYOUT_BIDI_STRONG != GetOut()->GetLayoutMode() )
|
|
aPoint.X() -= rPor.Width();
|
|
|
|
if ( GetTxtFrm()->IsVertical() )
|
|
GetTxtFrm()->SwitchHorizontalToVertical( aPoint );
|
|
|
|
pBlink->Insert( aPoint, &rPor, GetTxtFrm(), pFnt->GetOrientation() );
|
|
|
|
if( !pBlink->IsVisible() )
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
delete pBlink;
|
|
pBlink = NULL;
|
|
}
|
|
}
|
|
|
|
// The SwScriptInfo is useless if we are inside a field portion
|
|
SwScriptInfo* pSI = 0;
|
|
if ( ! rPor.InFldGrp() )
|
|
pSI = &GetParaPortion()->GetScriptInfo();
|
|
|
|
// in some cases, kana compression is not allowed or surpressed for
|
|
// performance reasons
|
|
sal_uInt16 nComp = 0;
|
|
if ( ! IsMulti() )
|
|
nComp = GetKanaComp();
|
|
|
|
sal_Bool bCfgIsAutoGrammar = sal_False;
|
|
SvtLinguConfig().GetProperty( C2U( UPN_IS_GRAMMAR_AUTO ) ) >>= bCfgIsAutoGrammar;
|
|
const sal_Bool bBullet = OnWin() && GetOpt().IsBlank() && IsNoSymbol();
|
|
const sal_Bool bTmpWrong = bWrong && OnWin() && GetOpt().IsOnlineSpell();
|
|
const sal_Bool bTmpGrammarCheck = bGrammarCheck && OnWin() && bCfgIsAutoGrammar && GetOpt().IsOnlineSpell();
|
|
const sal_Bool bTmpSmart = bSmartTag && OnWin() && !GetOpt().IsPagePreview() && SwSmartTagMgr::Get().IsSmartTagsEnabled(); // SMARTTAGS
|
|
|
|
OSL_ENSURE( GetParaPortion(), "No paragraph!");
|
|
SwDrawTextInfo aDrawInf( pFrm->getRootFrm()->GetCurrShell(), *pOut, pSI, rText, nStart, nLength,
|
|
rPor.Width(), bBullet );
|
|
|
|
aDrawInf.SetLeft( GetPaintRect().Left() );
|
|
aDrawInf.SetRight( GetPaintRect().Right() );
|
|
aDrawInf.SetUnderFnt( pUnderFnt );
|
|
|
|
const long nSpaceAdd = ( rPor.IsBlankPortion() || rPor.IsDropPortion() ||
|
|
rPor.InNumberGrp() ) ? 0 : GetSpaceAdd();
|
|
if ( nSpaceAdd )
|
|
{
|
|
xub_StrLen nCharCnt;
|
|
// #i41860# Thai justified alignemt needs some
|
|
// additional information:
|
|
aDrawInf.SetNumberOfBlanks( rPor.InTxtGrp() ?
|
|
static_cast<const SwTxtPortion&>(rPor).GetSpaceCnt( *this, nCharCnt ) :
|
|
0 );
|
|
}
|
|
|
|
aDrawInf.SetSpace( nSpaceAdd );
|
|
aDrawInf.SetKanaComp( nComp );
|
|
|
|
// the font is used to identify the current script via nActual
|
|
aDrawInf.SetFont( pFnt );
|
|
// the frame is used to identify the orientation
|
|
aDrawInf.SetFrm( GetTxtFrm() );
|
|
// we have to know if the paragraph should snap to grid
|
|
aDrawInf.SetSnapToGrid( SnapToGrid() );
|
|
// for underlining we must know when not to add extra space behind
|
|
// a character in justified mode
|
|
aDrawInf.SetSpaceStop( ! rPor.GetPortion() ||
|
|
rPor.GetPortion()->InFixMargGrp() ||
|
|
rPor.GetPortion()->IsHolePortion() );
|
|
|
|
if( GetTxtFly()->IsOn() )
|
|
{
|
|
// aPos muss als TopLeft vorliegen, weil die ClipRects sonst
|
|
// nicht berechnet werden koennen.
|
|
const Point aPoint( aPos.X(), aPos.Y() - rPor.GetAscent() );
|
|
const Size aSize( rPor.Width(), rPor.Height() );
|
|
aDrawInf.SetPos( aPoint );
|
|
aDrawInf.SetSize( aSize );
|
|
aDrawInf.SetAscent( rPor.GetAscent() );
|
|
aDrawInf.SetKern( bKern ? rPor.Width() : 0 );
|
|
aDrawInf.SetWrong( bTmpWrong ? pWrongList : NULL );
|
|
aDrawInf.SetGrammarCheck( bTmpGrammarCheck ? pGrammarCheckList : NULL );
|
|
aDrawInf.SetSmartTags( bTmpSmart ? pSmartTags : NULL ); // SMARTTAGS
|
|
GetTxtFly()->DrawTextOpaque( aDrawInf );
|
|
}
|
|
else
|
|
{
|
|
aDrawInf.SetPos( aPos );
|
|
if( bKern )
|
|
pFnt->_DrawStretchText( aDrawInf );
|
|
else
|
|
{
|
|
aDrawInf.SetWrong( bTmpWrong ? pWrongList : NULL );
|
|
aDrawInf.SetGrammarCheck( bTmpGrammarCheck ? pGrammarCheckList : NULL );
|
|
aDrawInf.SetSmartTags( bTmpSmart ? pSmartTags : NULL ); // SMARTTAGS
|
|
pFnt->_DrawText( aDrawInf );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SwTxtPaintInfo::CalcRect()
|
|
*************************************************************************/
|
|
|
|
void SwTxtPaintInfo::CalcRect( const SwLinePortion& rPor,
|
|
SwRect* pRect, SwRect* pIntersect ) const
|
|
{
|
|
Size aSize( rPor.Width(), rPor.Height() );
|
|
if( rPor.IsHangingPortion() )
|
|
aSize.Width() = ((SwHangingPortion&)rPor).GetInnerWidth();
|
|
if( rPor.InSpaceGrp() && GetSpaceAdd() )
|
|
{
|
|
SwTwips nAdd = rPor.CalcSpacing( GetSpaceAdd(), *this );
|
|
if( rPor.InFldGrp() && GetSpaceAdd() < 0 && nAdd )
|
|
nAdd += GetSpaceAdd() / SPACING_PRECISION_FACTOR;
|
|
aSize.Width() += nAdd;
|
|
}
|
|
|
|
Point aPoint;
|
|
|
|
if( IsRotated() )
|
|
{
|
|
long nTmp = aSize.Width();
|
|
aSize.Width() = aSize.Height();
|
|
aSize.Height() = nTmp;
|
|
if ( 1 == GetDirection() )
|
|
{
|
|
aPoint.A() = X() - rPor.GetAscent();
|
|
aPoint.B() = Y() - aSize.Height();
|
|
}
|
|
else
|
|
{
|
|
aPoint.A() = X() - rPor.Height() + rPor.GetAscent();
|
|
aPoint.B() = Y();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
aPoint.A() = X();
|
|
//Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
|
|
if ( GetTxtFrm()->IsVertLR() )
|
|
aPoint.B() = Y() - rPor.Height() + rPor.GetAscent();
|
|
else
|
|
aPoint.B() = Y() - rPor.GetAscent();
|
|
}
|
|
|
|
// Adjust x coordinate if we are inside a bidi portion
|
|
const sal_Bool bFrmDir = GetTxtFrm()->IsRightToLeft();
|
|
sal_Bool bCounterDir = ( ! bFrmDir && DIR_RIGHT2LEFT == GetDirection() ) ||
|
|
( bFrmDir && DIR_LEFT2RIGHT == GetDirection() );
|
|
|
|
if ( bCounterDir )
|
|
aPoint.A() -= aSize.Width();
|
|
|
|
SwRect aRect( aPoint, aSize );
|
|
|
|
if ( GetTxtFrm()->IsRightToLeft() )
|
|
GetTxtFrm()->SwitchLTRtoRTL( aRect );
|
|
|
|
if ( GetTxtFrm()->IsVertical() )
|
|
GetTxtFrm()->SwitchHorizontalToVertical( aRect );
|
|
|
|
if ( pRect )
|
|
*pRect = aRect;
|
|
|
|
if( aRect.HasArea() && pIntersect )
|
|
{
|
|
::SwAlignRect( aRect, (ViewShell*)GetVsh() );
|
|
|
|
if ( GetOut()->IsClipRegion() )
|
|
{
|
|
SwRect aClip( GetOut()->GetClipRegion().GetBoundRect() );
|
|
aRect.Intersection( aClip );
|
|
}
|
|
|
|
*pIntersect = aRect;
|
|
}
|
|
}
|
|
|
|
/*************************************************************************
|
|
* lcl_DrawSpecial
|
|
*
|
|
* Draws a special portion, e.g., line break portion, tab portion.
|
|
* rPor - The portion
|
|
* rRect - The rectangle surrounding the character
|
|
* pCol - Specify a color for the character
|
|
* bCenter - Draw the character centered, otherwise left aligned
|
|
* bRotate - Rotate the character if character rotation is set
|
|
*************************************************************************/
|
|
|
|
static void lcl_DrawSpecial( const SwTxtPaintInfo& rInf, const SwLinePortion& rPor,
|
|
SwRect& rRect, const Color* pCol, sal_Unicode cChar,
|
|
sal_uInt8 nOptions )
|
|
{
|
|
sal_Bool bCenter = 0 != ( nOptions & DRAW_SPECIAL_OPTIONS_CENTER );
|
|
sal_Bool bRotate = 0 != ( nOptions & DRAW_SPECIAL_OPTIONS_ROTATE );
|
|
|
|
// rRect is given in absolute coordinates
|
|
if ( rInf.GetTxtFrm()->IsRightToLeft() )
|
|
rInf.GetTxtFrm()->SwitchRTLtoLTR( rRect );
|
|
if ( rInf.GetTxtFrm()->IsVertical() )
|
|
rInf.GetTxtFrm()->SwitchVerticalToHorizontal( rRect );
|
|
|
|
const SwFont* pOldFnt = rInf.GetFont();
|
|
|
|
// Font is generated only once:
|
|
static SwFont* pFnt = 0;
|
|
if ( ! pFnt )
|
|
{
|
|
pFnt = new SwFont( *pOldFnt );
|
|
pFnt->SetFamily( FAMILY_DONTKNOW, pFnt->GetActual() );
|
|
pFnt->SetName( numfunc::GetDefBulletFontname(), pFnt->GetActual() );
|
|
pFnt->SetStyleName( aEmptyStr, pFnt->GetActual() );
|
|
pFnt->SetCharSet( RTL_TEXTENCODING_SYMBOL, pFnt->GetActual() );
|
|
}
|
|
|
|
// Some of the current values are set at the font:
|
|
if ( ! bRotate )
|
|
pFnt->SetVertical( 0, rInf.GetTxtFrm()->IsVertical() );
|
|
else
|
|
pFnt->SetVertical( pOldFnt->GetOrientation() );
|
|
|
|
if ( pCol )
|
|
pFnt->SetColor( *pCol );
|
|
else
|
|
pFnt->SetColor( pOldFnt->GetColor() );
|
|
|
|
Size aFontSize( 0, SPECIAL_FONT_HEIGHT );
|
|
pFnt->SetSize( aFontSize, pFnt->GetActual() );
|
|
|
|
((SwTxtPaintInfo&)rInf).SetFont( pFnt );
|
|
|
|
// The maximum width depends on the current orientation
|
|
const sal_uInt16 nDir = pFnt->GetOrientation( rInf.GetTxtFrm()->IsVertical() );
|
|
SwTwips nMaxWidth = 0;
|
|
switch ( nDir )
|
|
{
|
|
case 0 :
|
|
nMaxWidth = rRect.Width();
|
|
break;
|
|
case 900 :
|
|
case 2700 :
|
|
nMaxWidth = rRect.Height();
|
|
break;
|
|
default:
|
|
OSL_FAIL( "Unknown direction set at font" );
|
|
break;
|
|
}
|
|
|
|
// check if char fits into rectangle
|
|
const XubString aTmp( cChar );
|
|
aFontSize = rInf.GetTxtSize( aTmp ).SvLSize();
|
|
while ( aFontSize.Width() > nMaxWidth )
|
|
{
|
|
SwTwips nFactor = ( 100 * aFontSize.Width() ) / nMaxWidth;
|
|
const SwTwips nOldWidth = aFontSize.Width();
|
|
|
|
// new height for font
|
|
const sal_uInt8 nAct = pFnt->GetActual();
|
|
aFontSize.Height() = ( 100 * pFnt->GetSize( nAct ).Height() ) / nFactor;
|
|
aFontSize.Width() = ( 100 * pFnt->GetSize( nAct).Width() ) / nFactor;
|
|
|
|
if ( !aFontSize.Width() && !aFontSize.Height() )
|
|
break;
|
|
|
|
pFnt->SetSize( aFontSize, nAct );
|
|
|
|
aFontSize = rInf.GetTxtSize( aTmp ).SvLSize();
|
|
|
|
if ( aFontSize.Width() >= nOldWidth )
|
|
break;
|
|
}
|
|
|
|
const Point aOldPos( rInf.GetPos() );
|
|
|
|
// adjust values so that tab is vertically and horizontally centered
|
|
SwTwips nX = rRect.Left();
|
|
SwTwips nY = rRect.Top();
|
|
switch ( nDir )
|
|
{
|
|
case 0 :
|
|
if ( bCenter )
|
|
nX += ( rRect.Width() - aFontSize.Width() ) / 2;
|
|
nY += ( rRect.Height() - aFontSize.Height() ) / 2 + rInf.GetAscent();
|
|
break;
|
|
case 900 :
|
|
if ( bCenter )
|
|
nX += ( rRect.Width() - aFontSize.Height() ) / 2 + rInf.GetAscent();
|
|
nY += ( rRect.Height() + aFontSize.Width() ) / 2;
|
|
break;
|
|
case 2700 :
|
|
if ( bCenter )
|
|
nX += ( rRect.Width() + aFontSize.Height() ) / 2 - rInf.GetAscent();
|
|
nY += ( rRect.Height() - aFontSize.Width() ) / 2;
|
|
break;
|
|
}
|
|
|
|
Point aTmpPos( nX, nY );
|
|
((SwTxtPaintInfo&)rInf).SetPos( aTmpPos );
|
|
sal_uInt16 nOldWidth = rPor.Width();
|
|
((SwLinePortion&)rPor).Width( (sal_uInt16)aFontSize.Width() );
|
|
rInf.DrawText( aTmp, rPor );
|
|
((SwLinePortion&)rPor).Width( nOldWidth );
|
|
((SwTxtPaintInfo&)rInf).SetFont( (SwFont*)pOldFnt );
|
|
((SwTxtPaintInfo&)rInf).SetPos( aOldPos );
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SwTxtPaintInfo::DrawRect()
|
|
*************************************************************************/
|
|
|
|
void SwTxtPaintInfo::DrawRect( const SwRect &rRect, sal_Bool bNoGraphic,
|
|
sal_Bool bRetouche ) const
|
|
{
|
|
if ( OnWin() || !bRetouche )
|
|
{
|
|
if( aTxtFly.IsOn() )
|
|
((SwTxtPaintInfo*)this)->GetTxtFly()->
|
|
DrawFlyRect( pOut, rRect, *this, bNoGraphic );
|
|
else if ( bNoGraphic )
|
|
pOut->DrawRect( rRect.SVRect() );
|
|
else
|
|
{
|
|
OSL_ENSURE( ((SvxBrushItem*)-1) != pBrushItem, "DrawRect: Uninitialized BrushItem!" );
|
|
::DrawGraphic( pBrushItem, pOut, aItemRect, rRect );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SwTxtPaintInfo::DrawTab()
|
|
*************************************************************************/
|
|
|
|
void SwTxtPaintInfo::DrawTab( const SwLinePortion &rPor ) const
|
|
{
|
|
if( OnWin() )
|
|
{
|
|
SwRect aRect;
|
|
CalcRect( rPor, &aRect );
|
|
|
|
if ( ! aRect.HasArea() )
|
|
return;
|
|
|
|
const sal_Unicode cChar = GetTxtFrm()->IsRightToLeft() ?
|
|
CHAR_TAB_RTL : CHAR_TAB;
|
|
const sal_uInt8 nOptions = DRAW_SPECIAL_OPTIONS_CENTER |
|
|
DRAW_SPECIAL_OPTIONS_ROTATE;
|
|
lcl_DrawSpecial( *this, rPor, aRect, 0, cChar, nOptions );
|
|
}
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SwTxtPaintInfo::DrawLineBreak()
|
|
*************************************************************************/
|
|
|
|
void SwTxtPaintInfo::DrawLineBreak( const SwLinePortion &rPor ) const
|
|
{
|
|
if( OnWin() )
|
|
{
|
|
KSHORT nOldWidth = rPor.Width();
|
|
((SwLinePortion&)rPor).Width( LINE_BREAK_WIDTH );
|
|
|
|
SwRect aRect;
|
|
CalcRect( rPor, &aRect );
|
|
|
|
if( aRect.HasArea() )
|
|
{
|
|
const sal_Unicode cChar = GetTxtFrm()->IsRightToLeft() ?
|
|
CHAR_LINEBREAK_RTL : CHAR_LINEBREAK;
|
|
const sal_uInt8 nOptions = 0;
|
|
lcl_DrawSpecial( *this, rPor, aRect, 0, cChar, nOptions );
|
|
}
|
|
|
|
((SwLinePortion&)rPor).Width( nOldWidth );
|
|
}
|
|
}
|
|
|
|
|
|
/*************************************************************************
|
|
* SwTxtPaintInfo::DrawRedArrow()
|
|
*************************************************************************/
|
|
|
|
void SwTxtPaintInfo::DrawRedArrow( const SwLinePortion &rPor ) const
|
|
{
|
|
Size aSize( SPECIAL_FONT_HEIGHT, SPECIAL_FONT_HEIGHT );
|
|
SwRect aRect( ((SwArrowPortion&)rPor).GetPos(), aSize );
|
|
sal_Unicode cChar;
|
|
if( ((SwArrowPortion&)rPor).IsLeft() )
|
|
{
|
|
aRect.Pos().Y() += 20 - GetAscent();
|
|
aRect.Pos().X() += 20;
|
|
if( aSize.Height() > rPor.Height() )
|
|
aRect.Height( rPor.Height() );
|
|
cChar = CHAR_LEFT_ARROW;
|
|
}
|
|
else
|
|
{
|
|
if( aSize.Height() > rPor.Height() )
|
|
aRect.Height( rPor.Height() );
|
|
aRect.Pos().Y() -= aRect.Height() + 20;
|
|
aRect.Pos().X() -= aRect.Width() + 20;
|
|
cChar = CHAR_RIGHT_ARROW;
|
|
}
|
|
|
|
if ( GetTxtFrm()->IsVertical() )
|
|
GetTxtFrm()->SwitchHorizontalToVertical( aRect );
|
|
|
|
Color aCol( COL_LIGHTRED );
|
|
|
|
if( aRect.HasArea() )
|
|
{
|
|
const sal_uInt8 nOptions = 0;
|
|
lcl_DrawSpecial( *this, rPor, aRect, &aCol, cChar, nOptions );
|
|
}
|
|
}
|
|
|
|
|
|
/*************************************************************************
|
|
* SwTxtPaintInfo::DrawPostIts()
|
|
*************************************************************************/
|
|
|
|
void SwTxtPaintInfo::DrawPostIts( const SwLinePortion&, sal_Bool bScript ) const
|
|
{
|
|
if( OnWin() && pOpt->IsPostIts() )
|
|
{
|
|
Size aSize;
|
|
Point aTmp;
|
|
|
|
const sal_uInt16 nPostItsWidth = pOpt->GetPostItsWidth( GetOut() );
|
|
const sal_uInt16 nFontHeight = pFnt->GetHeight( pVsh, *GetOut() );
|
|
const sal_uInt16 nFontAscent = pFnt->GetAscent( pVsh, *GetOut() );
|
|
|
|
switch ( pFnt->GetOrientation( GetTxtFrm()->IsVertical() ) )
|
|
{
|
|
case 0 :
|
|
aSize.Width() = nPostItsWidth;
|
|
aSize.Height() = nFontHeight;
|
|
aTmp.X() = aPos.X();
|
|
aTmp.Y() = aPos.Y() - nFontAscent;
|
|
break;
|
|
case 900 :
|
|
aSize.Height() = nPostItsWidth;
|
|
aSize.Width() = nFontHeight;
|
|
aTmp.X() = aPos.X() - nFontAscent;
|
|
aTmp.Y() = aPos.Y();
|
|
break;
|
|
case 2700 :
|
|
aSize.Height() = nPostItsWidth;
|
|
aSize.Width() = nFontHeight;
|
|
aTmp.X() = aPos.X() - nFontHeight +
|
|
nFontAscent;
|
|
aTmp.Y() = aPos.Y();
|
|
break;
|
|
}
|
|
|
|
SwRect aTmpRect( aTmp, aSize );
|
|
|
|
if ( GetTxtFrm()->IsRightToLeft() )
|
|
GetTxtFrm()->SwitchLTRtoRTL( aTmpRect );
|
|
|
|
if ( GetTxtFrm()->IsVertical() )
|
|
GetTxtFrm()->SwitchHorizontalToVertical( aTmpRect );
|
|
|
|
const Rectangle aRect( aTmpRect.SVRect() );
|
|
pOpt->PaintPostIts( (OutputDevice*)GetOut(), aRect, bScript );
|
|
}
|
|
}
|
|
|
|
void SwTxtPaintInfo::DrawCheckBox( const SwFieldFormPortion &rPor, bool checked) const
|
|
{
|
|
SwRect aIntersect;
|
|
CalcRect( rPor, &aIntersect, 0 );
|
|
if ( aIntersect.HasArea() )
|
|
{
|
|
if (OnWin() && SwViewOption::IsFieldShadings() &&
|
|
!GetOpt().IsPagePreview())
|
|
{
|
|
OutputDevice* pOut_ = (OutputDevice*)GetOut();
|
|
pOut_->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
|
|
pOut_->SetFillColor( SwViewOption::GetFieldShadingsColor() );
|
|
pOut_->SetLineColor();
|
|
pOut_->DrawRect( aIntersect.SVRect() );
|
|
pOut_->Pop();
|
|
}
|
|
const int delta=10;
|
|
Rectangle r(aIntersect.Left()+delta, aIntersect.Top()+delta, aIntersect.Right()-delta, aIntersect.Bottom()-delta);
|
|
pOut->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
|
|
pOut->SetLineColor( Color(0, 0, 0));
|
|
pOut->SetFillColor();
|
|
pOut->DrawRect( r );
|
|
if (checked) {
|
|
pOut->DrawLine(r.TopLeft(), r.BottomRight());
|
|
pOut->DrawLine(r.TopRight(), r.BottomLeft());
|
|
}
|
|
pOut->Pop();
|
|
}
|
|
}
|
|
/*************************************************************************
|
|
* SwTxtPaintInfo::DrawBackGround()
|
|
*************************************************************************/
|
|
void SwTxtPaintInfo::DrawBackground( const SwLinePortion &rPor ) const
|
|
{
|
|
OSL_ENSURE( OnWin(), "SwTxtPaintInfo::DrawBackground: printer polution ?" );
|
|
|
|
SwRect aIntersect;
|
|
CalcRect( rPor, 0, &aIntersect );
|
|
|
|
if ( aIntersect.HasArea() )
|
|
{
|
|
OutputDevice* pTmpOut = (OutputDevice*)GetOut();
|
|
pTmpOut->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
|
|
|
|
// For dark background we do not want to have a filled rectangle
|
|
if ( GetVsh() && GetVsh()->GetWin() && lcl_IsDarkBackground( *this ) )
|
|
{
|
|
pTmpOut->SetLineColor( SwViewOption::GetFontColor().GetColor() );
|
|
}
|
|
else
|
|
{
|
|
pTmpOut->SetFillColor( SwViewOption::GetFieldShadingsColor() );
|
|
pTmpOut->SetLineColor();
|
|
}
|
|
|
|
DrawRect( aIntersect, sal_True );
|
|
pTmpOut->Pop();
|
|
}
|
|
}
|
|
|
|
void SwTxtPaintInfo::_DrawBackBrush( const SwLinePortion &rPor ) const
|
|
{
|
|
{
|
|
SwRect aIntersect;
|
|
CalcRect( rPor, &aIntersect, 0 );
|
|
if(aIntersect.HasArea())
|
|
{
|
|
SwTxtNode *pNd = pFrm->GetTxtNode();
|
|
const ::sw::mark::IMark* pFieldmark = NULL;
|
|
if(pNd)
|
|
{
|
|
const SwDoc *doc=pNd->GetDoc();
|
|
if(doc)
|
|
{
|
|
SwIndex aIndex(pNd, GetIdx());
|
|
SwPosition aPosition(*pNd, aIndex);
|
|
pFieldmark=doc->getIDocumentMarkAccess()->getFieldmarkFor(aPosition);
|
|
}
|
|
}
|
|
bool bIsStartMark=(1==GetLen() && CH_TXT_ATR_FIELDSTART==GetTxt().GetChar(GetIdx()));
|
|
if(pFieldmark) {
|
|
OSL_TRACE("Found Fieldmark");
|
|
#if OSL_DEBUG_LEVEL > 1
|
|
rtl::OUString str = pFieldmark->ToString( );
|
|
fprintf( stderr, "%s\n", rtl::OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr( ) );
|
|
#endif
|
|
}
|
|
if(bIsStartMark) OSL_TRACE("Found StartMark");
|
|
if (OnWin() && (pFieldmark!=NULL || bIsStartMark) &&
|
|
SwViewOption::IsFieldShadings() &&
|
|
!GetOpt().IsPagePreview())
|
|
{
|
|
OutputDevice* pOutDev = (OutputDevice*)GetOut();
|
|
pOutDev->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
|
|
pOutDev->SetFillColor( SwViewOption::GetFieldShadingsColor() );
|
|
pOutDev->SetLineColor( );
|
|
pOutDev->DrawRect( aIntersect.SVRect() );
|
|
pOutDev->Pop();
|
|
}
|
|
}
|
|
}
|
|
if( !pFnt->GetBackColor() ) return;
|
|
|
|
OSL_ENSURE( pFnt->GetBackColor(), "DrawBackBrush: Lost Color" );
|
|
|
|
SwRect aIntersect;
|
|
CalcRect( rPor, 0, &aIntersect );
|
|
|
|
if ( aIntersect.HasArea() )
|
|
{
|
|
OutputDevice* pTmpOut = (OutputDevice*)GetOut();
|
|
|
|
// #i16816# tagged pdf support
|
|
SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *pTmpOut );
|
|
|
|
pTmpOut->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
|
|
|
|
pTmpOut->SetFillColor( *pFnt->GetBackColor() );
|
|
pTmpOut->SetLineColor();
|
|
|
|
DrawRect( aIntersect, sal_True, sal_False );
|
|
|
|
pTmpOut->Pop();
|
|
}
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SwTxtPaintInfo::DrawViewOpt()
|
|
*************************************************************************/
|
|
|
|
void SwTxtPaintInfo::DrawViewOpt( const SwLinePortion &rPor,
|
|
const MSHORT nWhich ) const
|
|
{
|
|
if( OnWin() && !IsMulti() )
|
|
{
|
|
sal_Bool bDraw = sal_False;
|
|
switch( nWhich )
|
|
{
|
|
case POR_FTN:
|
|
case POR_QUOVADIS:
|
|
case POR_NUMBER:
|
|
case POR_FLD:
|
|
case POR_URL:
|
|
case POR_HIDDEN:
|
|
case POR_TOX:
|
|
case POR_REF:
|
|
case POR_META:
|
|
case POR_CONTROLCHAR:
|
|
if ( !GetOpt().IsPagePreview() &&
|
|
!GetOpt().IsReadonly() &&
|
|
SwViewOption::IsFieldShadings() &&
|
|
(POR_NUMBER != nWhich ||
|
|
pFrm->GetTxtNode()->HasMarkedLabel())) // #i27615#
|
|
bDraw = sal_True;
|
|
break;
|
|
case POR_TAB: if ( GetOpt().IsTab() ) bDraw = sal_True; break;
|
|
case POR_SOFTHYPH: if ( GetOpt().IsSoftHyph() )bDraw = sal_True; break;
|
|
case POR_BLANK: if ( GetOpt().IsHardBlank())bDraw = sal_True; break;
|
|
default:
|
|
{
|
|
OSL_ENSURE( !this, "SwTxtPaintInfo::DrawViewOpt: don't know how to draw this" );
|
|
break;
|
|
}
|
|
}
|
|
if ( bDraw )
|
|
DrawBackground( rPor );
|
|
}
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SwTxtPaintInfo::_NotifyURL()
|
|
*************************************************************************/
|
|
|
|
void SwTxtPaintInfo::_NotifyURL( const SwLinePortion &rPor ) const
|
|
{
|
|
OSL_ENSURE( pNoteURL, "NotifyURL: pNoteURL gone with the wind!" );
|
|
|
|
SwRect aIntersect;
|
|
CalcRect( rPor, 0, &aIntersect );
|
|
|
|
if( aIntersect.HasArea() )
|
|
{
|
|
SwTxtNode *pNd = (SwTxtNode*)GetTxtFrm()->GetTxtNode();
|
|
SwTxtAttr *const pAttr =
|
|
pNd->GetTxtAttrAt(GetIdx(), RES_TXTATR_INETFMT);
|
|
if( pAttr )
|
|
{
|
|
const SwFmtINetFmt& rFmt = pAttr->GetINetFmt();
|
|
pNoteURL->InsertURLNote( rFmt.GetValue(), rFmt.GetTargetFrame(),
|
|
aIntersect );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*************************************************************************
|
|
* lcl_InitHyphValues()
|
|
*************************************************************************/
|
|
|
|
static void lcl_InitHyphValues( PropertyValues &rVals,
|
|
sal_Int16 nMinLeading, sal_Int16 nMinTrailing )
|
|
{
|
|
sal_Int32 nLen = rVals.getLength();
|
|
|
|
if (0 == nLen) // yet to be initialized?
|
|
{
|
|
rVals.realloc( 2 );
|
|
PropertyValue *pVal = rVals.getArray();
|
|
|
|
pVal[0].Name = C2U( UPN_HYPH_MIN_LEADING );
|
|
pVal[0].Handle = UPH_HYPH_MIN_LEADING;
|
|
pVal[0].Value <<= nMinLeading;
|
|
|
|
pVal[1].Name = C2U( UPN_HYPH_MIN_TRAILING );
|
|
pVal[1].Handle = UPH_HYPH_MIN_TRAILING;
|
|
pVal[1].Value <<= nMinTrailing;
|
|
}
|
|
else if (2 == nLen) // already initialized once?
|
|
{
|
|
PropertyValue *pVal = rVals.getArray();
|
|
pVal[0].Value <<= nMinLeading;
|
|
pVal[1].Value <<= nMinTrailing;
|
|
}
|
|
else {
|
|
OSL_FAIL( "unxpected size of sequence" );
|
|
}
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SwTxtFormatInfo::GetHyphValues()
|
|
*************************************************************************/
|
|
|
|
const PropertyValues & SwTxtFormatInfo::GetHyphValues() const
|
|
{
|
|
OSL_ENSURE( 2 == aHyphVals.getLength(),
|
|
"hyphenation values not yet initialized" );
|
|
return aHyphVals;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SwTxtFormatInfo::InitHyph()
|
|
*************************************************************************/
|
|
|
|
sal_Bool SwTxtFormatInfo::InitHyph( const sal_Bool bAutoHyphen )
|
|
{
|
|
const SwAttrSet& rAttrSet = GetTxtFrm()->GetTxtNode()->GetSwAttrSet();
|
|
SetHanging( rAttrSet.GetHangingPunctuation().GetValue() );
|
|
SetScriptSpace( rAttrSet.GetScriptSpace().GetValue() );
|
|
SetForbiddenChars( rAttrSet.GetForbiddenRule().GetValue() );
|
|
const SvxHyphenZoneItem &rAttr = rAttrSet.GetHyphenZone();
|
|
MaxHyph() = rAttr.GetMaxHyphens();
|
|
sal_Bool bAuto = bAutoHyphen || rAttr.IsHyphen();
|
|
if( bAuto || bInterHyph )
|
|
{
|
|
nHyphStart = nHyphWrdStart = STRING_LEN;
|
|
nHyphWrdLen = 0;
|
|
|
|
const sal_Int16 nMinimalLeading = Max(rAttr.GetMinLead(), sal_uInt8(2));
|
|
const sal_Int16 nMinimalTrailing = rAttr.GetMinTrail();
|
|
lcl_InitHyphValues( aHyphVals, nMinimalLeading, nMinimalTrailing);
|
|
}
|
|
return bAuto;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SwTxtFormatInfo::CtorInitTxtFormatInfo()
|
|
*************************************************************************/
|
|
|
|
void SwTxtFormatInfo::CtorInitTxtFormatInfo( SwTxtFrm *pNewFrm, const sal_Bool bNewInterHyph,
|
|
const sal_Bool bNewQuick, const sal_Bool bTst )
|
|
{
|
|
CtorInitTxtPaintInfo( pNewFrm, SwRect() );
|
|
|
|
bQuick = bNewQuick;
|
|
bInterHyph = bNewInterHyph;
|
|
|
|
//! needs to be done in this order
|
|
nMinLeading = 2;
|
|
nMinTrailing = 2;
|
|
nMinWordLength = 0;
|
|
bAutoHyph = InitHyph();
|
|
|
|
bIgnoreFly = sal_False;
|
|
bFakeLineStart = sal_False;
|
|
bShift = sal_False;
|
|
bDropInit = sal_False;
|
|
bTestFormat = bTst;
|
|
nLeft = 0;
|
|
nRight = 0;
|
|
nFirst = 0;
|
|
nRealWidth = 0;
|
|
nForcedLeftMargin = 0;
|
|
pRest = 0;
|
|
nLineHeight = 0;
|
|
nLineNettoHeight = 0;
|
|
SetLineStart(0);
|
|
Init();
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SwTxtFormatInfo::IsHyphenate()
|
|
*************************************************************************/
|
|
// Trennen oder nicht trennen, das ist hier die Frage:
|
|
// - in keinem Fall trennen, wenn der Hyphenator ERROR zurueckliefert,
|
|
// oder wenn als Sprache NOLANGUAGE eingestellt ist.
|
|
// - ansonsten immer trennen, wenn interaktive Trennung vorliegt
|
|
// - wenn keine interakt. Trennung, dann nur trennen, wenn im ParaFmt
|
|
// automatische Trennung eingestellt ist.
|
|
|
|
sal_Bool SwTxtFormatInfo::IsHyphenate() const
|
|
{
|
|
if( !bInterHyph && !bAutoHyph )
|
|
return sal_False;
|
|
|
|
LanguageType eTmp = GetFont()->GetLanguage();
|
|
if( LANGUAGE_DONTKNOW == eTmp || LANGUAGE_NONE == eTmp )
|
|
return sal_False;
|
|
|
|
uno::Reference< XHyphenator > xHyph = ::GetHyphenator();
|
|
if (bInterHyph && xHyph.is())
|
|
SvxSpellWrapper::CheckHyphLang( xHyph, eTmp );
|
|
|
|
if( !xHyph.is() || !xHyph->hasLocale( pBreakIt->GetLocale(eTmp) ) )
|
|
return sal_False;
|
|
return sal_True;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SwTxtFormatInfo::GetDropFmt()
|
|
*************************************************************************/
|
|
|
|
// Dropcaps vom SwTxtFormatter::CTOR gerufen.
|
|
const SwFmtDrop *SwTxtFormatInfo::GetDropFmt() const
|
|
{
|
|
const SwFmtDrop *pDrop = &GetTxtFrm()->GetTxtNode()->GetSwAttrSet().GetDrop();
|
|
if( 1 >= pDrop->GetLines() ||
|
|
( !pDrop->GetChars() && !pDrop->GetWholeWord() ) )
|
|
pDrop = 0;
|
|
return pDrop;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SwTxtFormatInfo::Init()
|
|
*************************************************************************/
|
|
|
|
void SwTxtFormatInfo::Init()
|
|
{
|
|
// Nicht initialisieren: pRest, nLeft, nRight, nFirst, nRealWidth
|
|
X(0);
|
|
bArrowDone = bFull = bFtnDone = bErgoDone = bNumDone = bNoEndHyph =
|
|
bNoMidHyph = bStop = bNewLine = bUnderFlow = bTabOverflow = sal_False;
|
|
|
|
// generally we do not allow number portions in follows, except...
|
|
if ( GetTxtFrm()->IsFollow() )
|
|
{
|
|
const SwTxtFrm* pMaster = GetTxtFrm()->FindMaster();
|
|
OSL_ENSURE(pMaster, "pTxtFrm without Master");
|
|
const SwLinePortion* pTmpPara = pMaster ? pMaster->GetPara() : NULL;
|
|
|
|
// there is a master for this follow and the master does not have
|
|
// any contents (especially it does not have a number portion)
|
|
bNumDone = ! pTmpPara ||
|
|
! ((SwParaPortion*)pTmpPara)->GetFirstPortion()->IsFlyPortion();
|
|
}
|
|
|
|
pRoot = 0;
|
|
pLast = 0;
|
|
pFly = 0;
|
|
pLastFld = 0;
|
|
pLastTab = 0;
|
|
pUnderFlow = 0;
|
|
cTabDecimal = 0;
|
|
nWidth = nRealWidth;
|
|
nForcedLeftMargin = 0;
|
|
nSoftHyphPos = 0;
|
|
nUnderScorePos = STRING_LEN;
|
|
cHookChar = 0;
|
|
SetIdx(0);
|
|
SetLen( GetTxt().Len() );
|
|
SetPaintOfst(0);
|
|
}
|
|
|
|
/*--------------------------------------------------
|
|
* There are a few differences between a copy constructor
|
|
* and the following constructor for multi-line formatting.
|
|
* The root is the first line inside the multi-portion,
|
|
* the line start is the actual position in the text,
|
|
* the line width is the rest width from the surrounding line
|
|
* and the bMulti and bFirstMulti-flag has to be set correctly.
|
|
* --------------------------------------------------*/
|
|
|
|
SwTxtFormatInfo::SwTxtFormatInfo( const SwTxtFormatInfo& rInf,
|
|
SwLineLayout& rLay, SwTwips nActWidth ) : SwTxtPaintInfo( rInf ),
|
|
bTabOverflow( sal_False )
|
|
{
|
|
pRoot = &rLay;
|
|
pLast = &rLay;
|
|
pFly = NULL;
|
|
pLastFld = NULL;
|
|
pUnderFlow = NULL;
|
|
pRest = NULL;
|
|
pLastTab = NULL;
|
|
|
|
nSoftHyphPos = 0;
|
|
nUnderScorePos = STRING_LEN;
|
|
nHyphStart = 0;
|
|
nHyphWrdStart = 0;
|
|
nHyphWrdLen = 0;
|
|
nLineStart = rInf.GetIdx();
|
|
nLeft = rInf.nLeft;
|
|
nRight = rInf.nRight;
|
|
nFirst = rInf.nLeft;
|
|
nRealWidth = KSHORT(nActWidth);
|
|
nWidth = nRealWidth;
|
|
nLineHeight = 0;
|
|
nLineNettoHeight = 0;
|
|
nForcedLeftMargin = 0;
|
|
|
|
nMinLeading = 0;
|
|
nMinTrailing = 0;
|
|
nMinWordLength = 0;
|
|
bFull = sal_False;
|
|
bFtnDone = sal_True;
|
|
bErgoDone = sal_True;
|
|
bNumDone = sal_True;
|
|
bArrowDone = sal_True;
|
|
bStop = sal_False;
|
|
bNewLine = sal_True;
|
|
bShift = sal_False;
|
|
bUnderFlow = sal_False;
|
|
bInterHyph = sal_False;
|
|
bAutoHyph = sal_False;
|
|
bDropInit = sal_False;
|
|
bQuick = rInf.bQuick;
|
|
bNoEndHyph = sal_False;
|
|
bNoMidHyph = sal_False;
|
|
bIgnoreFly = sal_False;
|
|
bFakeLineStart = sal_False;
|
|
|
|
cTabDecimal = 0;
|
|
cHookChar = 0;
|
|
nMaxHyph = 0;
|
|
bTestFormat = rInf.bTestFormat;
|
|
SetMulti( sal_True );
|
|
SetFirstMulti( rInf.IsFirstMulti() );
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SwTxtFormatInfo::_CheckFtnPortion()
|
|
*************************************************************************/
|
|
|
|
sal_Bool SwTxtFormatInfo::_CheckFtnPortion( SwLineLayout* pCurr )
|
|
{
|
|
KSHORT nHeight = pCurr->GetRealHeight();
|
|
SwLinePortion *pPor = pCurr->GetPortion();
|
|
sal_Bool bRet = sal_False;
|
|
while( pPor )
|
|
{
|
|
if( pPor->IsFtnPortion() && nHeight > ((SwFtnPortion*)pPor)->Orig() )
|
|
{
|
|
bRet = sal_True;
|
|
SetLineHeight( nHeight );
|
|
SetLineNettoHeight( pCurr->Height() );
|
|
break;
|
|
}
|
|
pPor = pPor->GetPortion();
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*************************************************************************
|
|
* SwTxtFormatInfo::ScanPortionEnd()
|
|
*************************************************************************/
|
|
xub_StrLen SwTxtFormatInfo::ScanPortionEnd( const xub_StrLen nStart,
|
|
const xub_StrLen nEnd )
|
|
{
|
|
cHookChar = 0;
|
|
xub_StrLen i = nStart;
|
|
|
|
//
|
|
// Used for decimal tab handling:
|
|
//
|
|
const xub_Unicode cTabDec = GetLastTab() ? (sal_Unicode)GetTabDecimal() : 0;
|
|
const xub_Unicode cThousandSep = ',' == cTabDec ? '.' : ',';
|
|
// #i45951# German (Switzerland) uses ' as thousand separator
|
|
const xub_Unicode cThousandSep2 = ',' == cTabDec ? '.' : '\'';
|
|
|
|
bool bNumFound = false;
|
|
const bool bTabCompat = GetTxtFrm()->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TAB_COMPAT);
|
|
|
|
for( ; i < nEnd; ++i )
|
|
{
|
|
const xub_Unicode cPos = GetChar( i );
|
|
switch( cPos )
|
|
{
|
|
case CH_TXTATR_BREAKWORD:
|
|
case CH_TXTATR_INWORD:
|
|
if( !HasHint( i ))
|
|
break;
|
|
// no break;
|
|
|
|
case CHAR_SOFTHYPHEN:
|
|
case CHAR_HARDHYPHEN:
|
|
case CHAR_HARDBLANK:
|
|
case CH_TAB:
|
|
case CH_BREAK:
|
|
case CHAR_ZWSP :
|
|
case CHAR_ZWNBSP :
|
|
cHookChar = cPos;
|
|
return i;
|
|
|
|
case CHAR_UNDERSCORE:
|
|
if ( STRING_LEN == nUnderScorePos )
|
|
nUnderScorePos = i;
|
|
break;
|
|
|
|
default:
|
|
if ( cTabDec )
|
|
{
|
|
if( cTabDec == cPos )
|
|
{
|
|
OSL_ENSURE( cPos, "Unexpected end of string" );
|
|
if( cPos ) // robust
|
|
{
|
|
cHookChar = cPos;
|
|
return i;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Compatibility: First non-digit character behind a
|
|
// a digit character becomes the hook character
|
|
//
|
|
if ( bTabCompat )
|
|
{
|
|
if ( ( 0x2F < cPos && cPos < 0x3A ) ||
|
|
( bNumFound && ( cPos == cThousandSep || cPos == cThousandSep2 ) ) )
|
|
{
|
|
bNumFound = true;
|
|
}
|
|
else
|
|
{
|
|
if ( bNumFound )
|
|
{
|
|
cHookChar = cPos;
|
|
SetTabDecimal( cPos );
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// #130210# Check if character *behind* the portion has
|
|
// to become the hook:
|
|
if ( i == nEnd && i < GetTxt().Len() && bNumFound )
|
|
{
|
|
const xub_Unicode cPos = GetChar( i );
|
|
if ( cPos != cTabDec && cPos != cThousandSep && cPos !=cThousandSep2 && ( 0x2F >= cPos || cPos >= 0x3A ) )
|
|
{
|
|
cHookChar = GetChar( i );
|
|
SetTabDecimal( cHookChar );
|
|
}
|
|
}
|
|
|
|
return i;
|
|
}
|
|
|
|
sal_Bool SwTxtFormatInfo::LastKernPortion()
|
|
{
|
|
if( GetLast() )
|
|
{
|
|
if( GetLast()->IsKernPortion() )
|
|
return sal_True;
|
|
if( GetLast()->Width() || ( GetLast()->GetLen() &&
|
|
!GetLast()->IsHolePortion() ) )
|
|
return sal_False;
|
|
}
|
|
SwLinePortion* pPor = GetRoot();
|
|
SwLinePortion *pKern = NULL;
|
|
while( pPor )
|
|
{
|
|
if( pPor->IsKernPortion() )
|
|
pKern = pPor;
|
|
else if( pPor->Width() || ( pPor->GetLen() && !pPor->IsHolePortion() ) )
|
|
pKern = NULL;
|
|
pPor = pPor->GetPortion();
|
|
}
|
|
if( pKern )
|
|
{
|
|
SetLast( pKern );
|
|
return sal_True;
|
|
}
|
|
return sal_False;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* class SwTxtSlot
|
|
*************************************************************************/
|
|
|
|
SwTxtSlot::SwTxtSlot( const SwTxtSizeInfo *pNew, const SwLinePortion *pPor,
|
|
bool bTxtLen, bool bExgLists, const sal_Char *pCh )
|
|
: pOldTxt( 0 ),
|
|
pOldSmartTagList( 0 ),
|
|
pOldGrammarCheckList( 0 ),
|
|
pTempList( 0 )
|
|
{
|
|
if( pCh )
|
|
{
|
|
aTxt = XubString( pCh, RTL_TEXTENCODING_MS_1252 );
|
|
bOn = sal_True;
|
|
}
|
|
else
|
|
bOn = pPor->GetExpTxt( *pNew, aTxt );
|
|
|
|
// Der Text wird ausgetauscht...
|
|
if( bOn )
|
|
{
|
|
pInf = (SwTxtSizeInfo*)pNew;
|
|
nIdx = pInf->GetIdx();
|
|
nLen = pInf->GetLen();
|
|
pOldTxt = &(pInf->GetTxt());
|
|
pInf->SetTxt( aTxt );
|
|
pInf->SetIdx( 0 );
|
|
pInf->SetLen( bTxtLen ? pInf->GetTxt().Len() : pPor->GetLen() );
|
|
|
|
// ST2
|
|
if ( bExgLists )
|
|
{
|
|
pOldSmartTagList = static_cast<SwTxtPaintInfo*>(pInf)->GetSmartTags();
|
|
if ( pOldSmartTagList )
|
|
{
|
|
const sal_uInt16 nPos = pOldSmartTagList->GetWrongPos(nIdx);
|
|
const xub_StrLen nListPos = pOldSmartTagList->Pos(nPos);
|
|
if( nListPos == nIdx )
|
|
((SwTxtPaintInfo*)pInf)->SetSmartTags( pOldSmartTagList->SubList( nPos ) );
|
|
else if( !pTempList && nPos < pOldSmartTagList->Count() && nListPos < nIdx && aTxt.Len() )
|
|
{
|
|
pTempList = new SwWrongList( WRONGLIST_SMARTTAG );
|
|
pTempList->Insert( rtl::OUString(), 0, 0, aTxt.Len(), 0 );
|
|
((SwTxtPaintInfo*)pInf)->SetSmartTags( pTempList );
|
|
}
|
|
else
|
|
((SwTxtPaintInfo*)pInf)->SetSmartTags( 0);
|
|
}
|
|
pOldGrammarCheckList = static_cast<SwTxtPaintInfo*>(pInf)->GetGrammarCheckList();
|
|
if ( pOldGrammarCheckList )
|
|
{
|
|
const sal_uInt16 nPos = pOldGrammarCheckList->GetWrongPos(nIdx);
|
|
const xub_StrLen nListPos = pOldGrammarCheckList->Pos(nPos);
|
|
if( nListPos == nIdx )
|
|
((SwTxtPaintInfo*)pInf)->SetGrammarCheckList( pOldGrammarCheckList->SubList( nPos ) );
|
|
else if( !pTempList && nPos < pOldGrammarCheckList->Count() && nListPos < nIdx && aTxt.Len() )
|
|
{
|
|
pTempList = new SwWrongList( WRONGLIST_GRAMMAR );
|
|
pTempList->Insert( rtl::OUString(), 0, 0, aTxt.Len(), 0 );
|
|
((SwTxtPaintInfo*)pInf)->SetGrammarCheckList( pTempList );
|
|
}
|
|
else
|
|
((SwTxtPaintInfo*)pInf)->SetGrammarCheckList( 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SwTxtSlot::~SwTxtSlot()
|
|
*************************************************************************/
|
|
|
|
SwTxtSlot::~SwTxtSlot()
|
|
{
|
|
if( bOn )
|
|
{
|
|
pInf->SetTxt( *pOldTxt );
|
|
pInf->SetIdx( nIdx );
|
|
pInf->SetLen( nLen );
|
|
|
|
// ST2
|
|
// Restore old smart tag list
|
|
if ( pOldSmartTagList )
|
|
((SwTxtPaintInfo*)pInf)->SetSmartTags( pOldSmartTagList );
|
|
if ( pOldGrammarCheckList )
|
|
((SwTxtPaintInfo*)pInf)->SetGrammarCheckList( pOldGrammarCheckList );
|
|
delete pTempList;
|
|
}
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SwFontSave::SwFontSave()
|
|
*************************************************************************/
|
|
|
|
SwFontSave::SwFontSave( const SwTxtSizeInfo &rInf, SwFont *pNew,
|
|
SwAttrIter* pItr )
|
|
: pFnt( pNew ? ((SwTxtSizeInfo&)rInf).GetFont() : 0 )
|
|
{
|
|
if( pFnt )
|
|
{
|
|
pInf = &((SwTxtSizeInfo&)rInf);
|
|
// In these cases we temporarily switch to the new font:
|
|
// 1. the fonts have a different magic number
|
|
// 2. they have different script types
|
|
// 3. their background colors differ (this is not covered by 1.)
|
|
if( pFnt->DifferentMagic( pNew, pFnt->GetActual() ) ||
|
|
pNew->GetActual() != pFnt->GetActual() ||
|
|
( ! pNew->GetBackColor() && pFnt->GetBackColor() ) ||
|
|
( pNew->GetBackColor() && ! pFnt->GetBackColor() ) ||
|
|
( pNew->GetBackColor() && pFnt->GetBackColor() &&
|
|
( *pNew->GetBackColor() != *pFnt->GetBackColor() ) ) )
|
|
{
|
|
pNew->SetTransparent( sal_True );
|
|
pNew->SetAlign( ALIGN_BASELINE );
|
|
pInf->SetFont( pNew );
|
|
}
|
|
else
|
|
pFnt = 0;
|
|
pNew->Invalidate();
|
|
pNew->ChgPhysFnt( pInf->GetVsh(), *pInf->GetOut() );
|
|
if( pItr && pItr->GetFnt() == pFnt )
|
|
{
|
|
pIter = pItr;
|
|
pIter->SetFnt( pNew );
|
|
}
|
|
else
|
|
pIter = NULL;
|
|
}
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SwFontSave::~SwFontSave()
|
|
*************************************************************************/
|
|
|
|
SwFontSave::~SwFontSave()
|
|
{
|
|
if( pFnt )
|
|
{
|
|
// SwFont zurueckstellen
|
|
pFnt->Invalidate();
|
|
pInf->SetFont( pFnt );
|
|
if( pIter )
|
|
{
|
|
pIter->SetFnt( pFnt );
|
|
pIter->nPos = STRING_LEN;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SwDefFontSave::SwDefFontSave()
|
|
*************************************************************************/
|
|
|
|
SwDefFontSave::SwDefFontSave( const SwTxtSizeInfo &rInf )
|
|
: pFnt( ((SwTxtSizeInfo&)rInf).GetFont() )
|
|
{
|
|
const sal_Bool bTmpAlter = pFnt->GetFixKerning() ||
|
|
( RTL_TEXTENCODING_SYMBOL == pFnt->GetCharSet(pFnt->GetActual()) )
|
|
;
|
|
|
|
const sal_Bool bFamily = bTmpAlter &&
|
|
pFnt->GetName( pFnt->GetActual() ) != numfunc::GetDefBulletFontname();
|
|
const sal_Bool bRotation = (sal_Bool)pFnt->GetOrientation() &&
|
|
! rInf.GetTxtFrm()->IsVertical();
|
|
|
|
if( bFamily || bRotation )
|
|
{
|
|
pNewFnt = new SwFont( *pFnt );
|
|
|
|
if ( bFamily )
|
|
{
|
|
pNewFnt->SetFamily( FAMILY_DONTKNOW, pFnt->GetActual() );
|
|
pNewFnt->SetName( numfunc::GetDefBulletFontname(), pFnt->GetActual() );
|
|
pNewFnt->SetStyleName( aEmptyStr, pFnt->GetActual() );
|
|
pNewFnt->SetCharSet( RTL_TEXTENCODING_SYMBOL, pFnt->GetActual() );
|
|
pNewFnt->SetFixKerning( 0 );
|
|
}
|
|
|
|
if ( bRotation )
|
|
pNewFnt->SetVertical( 0, rInf.GetTxtFrm()->IsVertical() );
|
|
|
|
pInf = &((SwTxtSizeInfo&)rInf);
|
|
pNewFnt->Invalidate();
|
|
pInf->SetFont( pNewFnt );
|
|
}
|
|
else
|
|
{
|
|
pFnt = 0;
|
|
pNewFnt = 0;
|
|
}
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SwDefFontSave::~SwDefFontSave()
|
|
*************************************************************************/
|
|
|
|
SwDefFontSave::~SwDefFontSave()
|
|
{
|
|
if( pFnt )
|
|
{
|
|
delete pNewFnt;
|
|
// SwFont zurueckstellen
|
|
pFnt->Invalidate();
|
|
pInf->SetFont( pFnt );
|
|
}
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SwTxtFormatInfo::ChgHyph()
|
|
*************************************************************************/
|
|
|
|
sal_Bool SwTxtFormatInfo::ChgHyph( const sal_Bool bNew )
|
|
{
|
|
const sal_Bool bOld = bAutoHyph;
|
|
if( bAutoHyph != bNew )
|
|
{
|
|
bAutoHyph = bNew;
|
|
InitHyph( bNew );
|
|
// 5744: Sprache am Hyphenator einstellen.
|
|
if( pFnt )
|
|
pFnt->ChgPhysFnt( pVsh, *pOut );
|
|
}
|
|
return bOld;
|
|
}
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|