blob: 77a065bec0e3372a36ac0c93d53928c1e6b6e277 [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 <fmtfld.hxx>
#include <txtfld.hxx>
#include <charfmt.hxx>
#include "viewsh.hxx" // NewFldPortion, GetDoc()
#include "doc.hxx" // NewFldPortion, GetSysFldType()
#include "rootfrm.hxx" // Info ueber virt. PageNumber
#include "pagefrm.hxx" // NewFldPortion, GetVirtPageNum()
#include "ndtxt.hxx" // NewNumberPortion, pHints->GetNum()
#include "fldbas.hxx" // SwField
#include "viewopt.hxx" // SwViewOptions
#include "flyfrm.hxx" //IsInBody()
#include "viewimp.hxx"
#include "txtatr.hxx" // SwTxtFld
#include "txtcfg.hxx"
#include "swfont.hxx" // NewFldPortion, new SwFont
#include "fntcache.hxx" // NewFldPortion, SwFntAccess
#include "porfld.hxx"
#include "porftn.hxx" // NewExtraPortion
#include "porref.hxx" // NewExtraPortion
#include "portox.hxx" // NewExtraPortion
#include "porhyph.hxx" // NewExtraPortion
#include "porfly.hxx" // NewExtraPortion
#include "itrform2.hxx" // SwTxtFormatter
#include "chpfld.hxx"
#include "dbfld.hxx"
#include "expfld.hxx"
#include "docufld.hxx"
#include "pagedesc.hxx" // NewFldPortion, GetNum()
#include <pormulti.hxx> // SwMultiPortion
#include "fmtmeta.hxx" // lcl_NewMetaPortion
#ifndef _REFFLD_HXX
#include "reffld.hxx"
#endif
#ifndef _FLDDAT_HXX
#include "flddat.hxx"
#endif
/*************************************************************************
* SwTxtFormatter::NewFldPortion()
*************************************************************************/
sal_Bool lcl_IsInBody( SwFrm *pFrm )
{
if ( pFrm->IsInDocBody() )
return sal_True;
else
{
const SwFrm *pTmp = pFrm;
const SwFlyFrm *pFly;
while ( 0 != (pFly = pTmp->FindFlyFrm()) )
pTmp = pFly->GetAnchorFrm();
return pTmp->IsInDocBody();
}
}
SwExpandPortion *SwTxtFormatter::NewFldPortion( SwTxtFormatInfo &rInf,
const SwTxtAttr *pHint ) const
{
SwExpandPortion *pRet = 0;
SwFrm *pFrame = (SwFrm*)pFrm;
SwField *pFld = (SwField*)pHint->GetFmtFld().GetField();
const sal_Bool bName = rInf.GetOpt().IsFldName();
SwCharFmt* pChFmt = 0;
sal_Bool bNewFlyPor = sal_False,
bINet = sal_False;
sal_uInt16 subType;
// set language
((SwTxtFormatter*)this)->SeekAndChg( rInf );
if (pFld->GetLanguage() != GetFnt()->GetLanguage())
{
pFld->SetLanguage( GetFnt()->GetLanguage() );
// let the visual note know about its new language
if (pFld->GetTyp()->Which()==RES_POSTITFLD)
const_cast<SwFmtFld*> (&pHint->GetFmtFld())->Broadcast( SwFmtFldHint( &pHint->GetFmtFld(), SWFMTFLD_LANGUAGE ) );
}
ViewShell *pSh = rInf.GetVsh();
SwDoc *const pDoc( (pSh) ? pSh->GetDoc() : 0 );
bool const bInClipboard( (pDoc) ? pDoc->IsClipBoard() : true );
sal_Bool bPlaceHolder = sal_False;
switch( pFld->GetTyp()->Which() )
{
case RES_SCRIPTFLD:
case RES_POSTITFLD:
pRet = new SwPostItsPortion( RES_SCRIPTFLD == pFld->GetTyp()->Which() );
break;
case RES_COMBINED_CHARS:
{
if( bName )
{
String const sName( pFld->GetFieldName() );
pRet = new SwFldPortion(sName);
}
else
{
String const sContent( pFld->ExpandField(bInClipboard) );
pRet = new SwCombinedPortion(sContent);
}
}
break;
case RES_HIDDENTXTFLD:
{
String const str( (bName)
? pFld->GetFieldName()
: pFld->ExpandField(bInClipboard) );
pRet = new SwHiddenPortion(str);
}
break;
case RES_CHAPTERFLD:
if( !bName && pSh && !pSh->Imp()->IsUpdateExpFlds() )
{
((SwChapterField*)pFld)->ChangeExpansion( pFrame,
&((SwTxtFld*)pHint)->GetTxtNode() );
}
{
String const str( (bName)
? pFld->GetFieldName()
: pFld->ExpandField(bInClipboard) );
pRet = new SwFldPortion( str );
}
break;
case RES_DOCSTATFLD:
if( !bName && pSh && !pSh->Imp()->IsUpdateExpFlds() )
{
((SwDocStatField*)pFld)->ChangeExpansion( pFrame );
}
{
String const str( (bName)
? pFld->GetFieldName()
: pFld->ExpandField(bInClipboard) );
pRet = new SwFldPortion( str );
}
if(pRet)
((SwFldPortion*)pRet)->m_nAttrFldType= ATTR_PAGECOOUNTFLD;
break;
case RES_PAGENUMBERFLD:
{
if( !bName && pSh && pSh->GetLayout() && !pSh->Imp()->IsUpdateExpFlds() )//swmod 080122
{
SwPageNumberFieldType *pPageNr = (SwPageNumberFieldType *)pFld->GetTyp();
const SwRootFrm* pTmpRootFrm = pSh->GetLayout();
const sal_Bool bVirt = pTmpRootFrm->IsVirtPageNum();
MSHORT nVirtNum = pFrame->GetVirtPageNum();
MSHORT nNumPages = pTmpRootFrm->GetPageNum();
sal_Int16 nNumFmt = -1;
if(SVX_NUM_PAGEDESC == pFld->GetFormat())
nNumFmt = pFrame->FindPageFrm()->GetPageDesc()->GetNumType().GetNumberingType();
pPageNr->ChangeExpansion( pDoc, nVirtNum, nNumPages,
bVirt, nNumFmt > -1 ? &nNumFmt : 0);
}
{
String const str( (bName)
? pFld->GetFieldName()
: pFld->ExpandField(bInClipboard) );
pRet = new SwFldPortion( str );
}
if(pRet)
((SwFldPortion*)pRet)->m_nAttrFldType= ATTR_PAGENUMBERFLD;
break;
}
case RES_GETEXPFLD:
{
if( !bName && pSh && !pSh->Imp()->IsUpdateExpFlds() )
{
SwGetExpField* pExpFld = (SwGetExpField*)pFld;
if( !::lcl_IsInBody( pFrame ) )
{
pExpFld->ChgBodyTxtFlag( sal_False );
pExpFld->ChangeExpansion( *pFrame, *((SwTxtFld*)pHint) );
}
else if( !pExpFld->IsInBodyTxt() )
{
// war vorher anders, also erst expandieren, dann umsetzen!!
pExpFld->ChangeExpansion( *pFrame, *((SwTxtFld*)pHint) );
pExpFld->ChgBodyTxtFlag( sal_True );
}
}
{
String const str( (bName)
? pFld->GetFieldName()
: pFld->ExpandField(bInClipboard) );
pRet = new SwFldPortion( str );
}
break;
}
case RES_DBFLD:
{
if( !bName )
{
SwDBField* pDBFld = (SwDBField*)pFld;
pDBFld->ChgBodyTxtFlag( ::lcl_IsInBody( pFrame ) );
/* Solange das ChangeExpansion auskommentiert ist.
* Aktualisieren in Kopf/Fuszeilen geht aktuell nicht.
if( !::lcl_IsInBody( pFrame ) )
{
pDBFld->ChgBodyTxtFlag( sal_False );
pDBFld->ChangeExpansion( pFrame, (SwTxtFld*)pHint );
}
else if( !pDBFld->IsInBodyTxt() )
{
// war vorher anders, also erst expandieren, dann umsetzen!!
pDBFld->ChangeExpansion( pFrame, (SwTxtFld*)pHint );
pDBFld->ChgBodyTxtFlag( sal_True );
}
*/
}
{
String const str( (bName)
? pFld->GetFieldName()
: pFld->ExpandField(bInClipboard) );
pRet = new SwFldPortion(str);
}
break;
}
case RES_REFPAGEGETFLD:
if( !bName && pSh && !pSh->Imp()->IsUpdateExpFlds() )
{
((SwRefPageGetField*)pFld)->ChangeExpansion( pFrame, (SwTxtFld*)pHint );
}
{
String const str( (bName)
? pFld->GetFieldName()
: pFld->ExpandField(bInClipboard) );
pRet = new SwFldPortion(str);
}
break;
case RES_JUMPEDITFLD:
if( !bName )
pChFmt = ((SwJumpEditField*)pFld)->GetCharFmt();
bNewFlyPor = sal_True;
bPlaceHolder = sal_True;
break;
case RES_GETREFFLD:
subType = ((SwGetRefField*)pFld)->GetSubType();
{
String const str( (bName)
? pFld->GetFieldName()
: pFld->ExpandField(bInClipboard) );
pRet = new SwFldPortion(str);
}
if(pRet)
{
if( subType == REF_BOOKMARK )
((SwFldPortion*)pRet)->m_nAttrFldType = ATTR_BOOKMARKFLD;
else if( subType == REF_SETREFATTR )
((SwFldPortion*)pRet)->m_nAttrFldType = ATTR_SETREFATTRFLD;
break;
}
case RES_DATETIMEFLD:
subType = ((SwDateTimeField*)pFld)->GetSubType();
{
String const str( (bName)
? pFld->GetFieldName()
: pFld->ExpandField(bInClipboard) );
pRet = new SwFldPortion(str);
}
if(pRet)
{
if( subType & DATEFLD )
((SwFldPortion*)pRet)->m_nAttrFldType= ATTR_DATEFLD;
else if( subType & TIMEFLD )
((SwFldPortion*)pRet)->m_nAttrFldType = ATTR_TIMEFLD;
break;
}
default:
{
String const str( (bName)
? pFld->GetFieldName()
: pFld->ExpandField(bInClipboard) );
pRet = new SwFldPortion(str);
}
}
if( bNewFlyPor )
{
SwFont *pTmpFnt = 0;
if( !bName )
{
pTmpFnt = new SwFont( *pFnt );
if( bINet )
{
SwAttrPool* pPool = pChFmt->GetAttrSet().GetPool();
SfxItemSet aSet( *pPool, RES_CHRATR_BEGIN, RES_CHRATR_END );
SfxItemSet aTmpSet( aSet );
pFrm->GetTxtNode()->GetAttr(aSet,rInf.GetIdx(),rInf.GetIdx()+1);
aTmpSet.Set( pChFmt->GetAttrSet() );
aTmpSet.Differentiate( aSet );
if( aTmpSet.Count() )
pTmpFnt->SetDiffFnt( &aTmpSet, pFrm->GetTxtNode()->getIDocumentSettingAccess() );
}
else
pTmpFnt->SetDiffFnt( &pChFmt->GetAttrSet(), pFrm->GetTxtNode()->getIDocumentSettingAccess() );
}
{
String const str( (bName)
? pFld->GetFieldName()
: pFld->ExpandField(bInClipboard) );
pRet = new SwFldPortion(str, pTmpFnt, bPlaceHolder);
}
}
return pRet;
}
/*************************************************************************
* SwTxtFormatter::TryNewNoLengthPortion()
*************************************************************************/
SwFldPortion * lcl_NewMetaPortion(SwTxtAttr & rHint, const bool bPrefix)
{
::sw::Meta *const pMeta(
static_cast<SwFmtMeta &>(rHint.GetAttr()).GetMeta() );
::rtl::OUString fix;
::sw::MetaField *const pField( dynamic_cast< ::sw::MetaField * >(pMeta) );
OSL_ENSURE(pField, "lcl_NewMetaPortion: no meta field?");
if (pField)
{
pField->GetPrefixAndSuffix((bPrefix) ? &fix : 0, (bPrefix) ? 0 : &fix);
}
return new SwFldPortion( fix );
}
/** Try to create a new portion with zero length, for an end of a hint
(where there is no CH_TXTATR). Because there may be multiple hint ends at a
given index, m_nHintEndIndex is used to keep track of the already created
portions. But the portions created here may actually be deleted again,
due to UnderFlow. In that case, m_nHintEndIndex must be decremented,
so the portion will be created again on the next line.
*/
SwExpandPortion *
SwTxtFormatter::TryNewNoLengthPortion(SwTxtFormatInfo & rInfo)
{
if (pHints)
{
const xub_StrLen nIdx(rInfo.GetIdx());
while (m_nHintEndIndex < pHints->GetEndCount())
{
SwTxtAttr & rHint( *pHints->GetEnd(m_nHintEndIndex) );
xub_StrLen const nEnd( *rHint.GetAnyEnd() );
if (nEnd > nIdx)
{
break;
}
++m_nHintEndIndex;
if (nEnd == nIdx)
{
if (RES_TXTATR_METAFIELD == rHint.Which())
{
SwFldPortion *const pPortion(
lcl_NewMetaPortion(rHint, false));
pPortion->SetNoLength(); // no CH_TXTATR at hint end!
return pPortion;
}
}
}
}
return 0;
}
/*************************************************************************
* SwTxtFormatter::NewExtraPortion()
*************************************************************************/
SwLinePortion *SwTxtFormatter::NewExtraPortion( SwTxtFormatInfo &rInf )
{
SwTxtAttr *pHint = GetAttr( rInf.GetIdx() );
SwLinePortion *pRet = 0;
if( !pHint )
{
pRet = new SwTxtPortion;
pRet->SetLen( 1 );
rInf.SetLen( 1 );
return pRet;
}
switch( pHint->Which() )
{
case RES_TXTATR_FLYCNT :
{
pRet = NewFlyCntPortion( rInf, pHint );
break;
}
case RES_TXTATR_FTN :
{
pRet = NewFtnPortion( rInf, pHint );
break;
}
case RES_TXTATR_FIELD :
case RES_TXTATR_ANNOTATION :
{
pRet = NewFldPortion( rInf, pHint );
break;
}
case RES_TXTATR_REFMARK :
{
pRet = new SwIsoRefPortion;
break;
}
case RES_TXTATR_TOXMARK :
{
pRet = new SwIsoToxPortion;
break;
}
case RES_TXTATR_METAFIELD:
{
pRet = lcl_NewMetaPortion( *pHint, true );
break;
}
default: ;
}
if( !pRet )
{
const XubString aNothing;
pRet = new SwFldPortion( aNothing );
rInf.SetLen( 1 );
}
return pRet;
}
/*************************************************************************
* SwTxtFormatter::NewNumberPortion()
*************************************************************************/
SwNumberPortion *SwTxtFormatter::NewNumberPortion( SwTxtFormatInfo &rInf ) const
{
if( rInf.IsNumDone() || rInf.GetTxtStart() != nStart
|| rInf.GetTxtStart() != rInf.GetIdx() )
return 0;
SwNumberPortion *pRet = 0;
const SwTxtNode* pTxtNd = GetTxtFrm()->GetTxtNode();
const SwNumRule* pNumRule = pTxtNd->GetNumRule();
// hat ein "gueltige" Nummer ?
if( pTxtNd->IsNumbered() && pTxtNd->IsCountedInList())
{
const SwNumFmt &rNumFmt = pNumRule->Get( static_cast<sal_uInt16>(pTxtNd->GetActualListLevel()) );
const sal_Bool bLeft = SVX_ADJUST_LEFT == rNumFmt.GetNumAdjust();
const sal_Bool bCenter = SVX_ADJUST_CENTER == rNumFmt.GetNumAdjust();
// --> OD 2008-01-23 #newlistlevelattrs#
const bool bLabelAlignmentPosAndSpaceModeActive(
rNumFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT );
const KSHORT nMinDist = bLabelAlignmentPosAndSpaceModeActive
? 0 : rNumFmt.GetCharTextDistance();
// <--
if( SVX_NUM_BITMAP == rNumFmt.GetNumberingType() )
{
// --> OD 2008-01-23 #newlistlevelattrs#
pRet = new SwGrfNumPortion( (SwFrm*)GetTxtFrm(),
pTxtNd->GetLabelFollowedBy(),
rNumFmt.GetBrush(),
rNumFmt.GetGraphicOrientation(),
rNumFmt.GetGraphicSize(),
bLeft, bCenter, nMinDist,
bLabelAlignmentPosAndSpaceModeActive );
// <--
long nTmpA = rInf.GetLast()->GetAscent();
long nTmpD = rInf.GetLast()->Height() - nTmpA;
if( !rInf.IsTest() )
((SwGrfNumPortion*)pRet)->SetBase( nTmpA, nTmpD, nTmpA, nTmpD );
}
else
{
// Der SwFont wird dynamisch angelegt und im CTOR uebergeben,
// weil das CharFmt nur einen SV-Font zurueckliefert.
// Im Dtor vom SwNumberPortion wird der SwFont deletet.
SwFont *pNumFnt = 0;
const SwAttrSet* pFmt = rNumFmt.GetCharFmt() ?
&rNumFmt.GetCharFmt()->GetAttrSet() :
NULL;
const IDocumentSettingAccess* pIDSA = pTxtNd->getIDocumentSettingAccess();
if( SVX_NUM_CHAR_SPECIAL == rNumFmt.GetNumberingType() )
{
const Font *pFmtFnt = rNumFmt.GetBulletFont();
//
// Build a new bullet font basing on the current paragraph font:
//
pNumFnt = new SwFont( &rInf.GetCharAttr(), pIDSA );
// --> FME 2005-08-11 #i53199#
if ( !pIDSA->get(IDocumentSettingAccess::DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT) )
{
// i18463:
// Underline style of paragraph font should not be considered
// Overline style of paragraph font should not be considered
// Weight style of paragraph font should not be considered
// Posture style of paragraph font should not be considered
pNumFnt->SetUnderline( UNDERLINE_NONE );
pNumFnt->SetOverline( UNDERLINE_NONE );
pNumFnt->SetItalic( ITALIC_NONE, SW_LATIN );
pNumFnt->SetItalic( ITALIC_NONE, SW_CJK );
pNumFnt->SetItalic( ITALIC_NONE, SW_CTL );
pNumFnt->SetWeight( WEIGHT_NORMAL, SW_LATIN );
pNumFnt->SetWeight( WEIGHT_NORMAL, SW_CJK );
pNumFnt->SetWeight( WEIGHT_NORMAL, SW_CTL );
}
//
// Apply the explicit attributes from the character style
// associated with the numering to the new bullet font.
//
if( pFmt )
pNumFnt->SetDiffFnt( pFmt, pIDSA );
if ( pFmtFnt )
{
const sal_uInt8 nAct = pNumFnt->GetActual();
pNumFnt->SetFamily( pFmtFnt->GetFamily(), nAct );
pNumFnt->SetName( pFmtFnt->GetName(), nAct );
pNumFnt->SetStyleName( pFmtFnt->GetStyleName(), nAct );
pNumFnt->SetCharSet( pFmtFnt->GetCharSet(), nAct );
pNumFnt->SetPitch( pFmtFnt->GetPitch(), nAct );
}
// we do not allow a vertical font
pNumFnt->SetVertical( pNumFnt->GetOrientation(),
pFrm->IsVertical() );
// --> OD 2008-01-23 #newlistelevelattrs#
pRet = new SwBulletPortion( rNumFmt.GetBulletChar(),
pTxtNd->GetLabelFollowedBy(),
pNumFnt,
bLeft, bCenter, nMinDist,
bLabelAlignmentPosAndSpaceModeActive );
// <--
}
else
{
XubString aTxt( pTxtNd->GetNumString() );
// --> OD 2008-01-23 #newlistlevelattrs#
if ( aTxt.Len() > 0 )
{
aTxt.Insert( pTxtNd->GetLabelFollowedBy() );
}
// <--
// 7974: Nicht nur eine Optimierung...
// Eine Numberportion ohne Text wird die Breite von 0
// erhalten. Die nachfolgende Textportion wird im BreakLine
// in das BreakCut laufen, obwohl rInf.GetLast()->GetFlyPortion()
// vorliegt!
if( aTxt.Len() )
{
//
// Build a new numbering font basing on the current paragraph font:
//
pNumFnt = new SwFont( &rInf.GetCharAttr(), pIDSA );
// --> FME 2005-08-11 #i53199#
if ( !pIDSA->get(IDocumentSettingAccess::DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT) )
{
// i18463:
// Underline style of paragraph font should not be considered
pNumFnt->SetUnderline( UNDERLINE_NONE );
// Overline style of paragraph font should not be considered
pNumFnt->SetOverline( UNDERLINE_NONE );
}
//
// Apply the explicit attributes from the character style
// associated with the numering to the new bullet font.
//
if( pFmt )
pNumFnt->SetDiffFnt( pFmt, pIDSA );
// we do not allow a vertical font
pNumFnt->SetVertical( pNumFnt->GetOrientation(), pFrm->IsVertical() );
// --> OD 2008-01-23 #newlistlevelattrs#
pRet = new SwNumberPortion( aTxt, pNumFnt,
bLeft, bCenter, nMinDist,
bLabelAlignmentPosAndSpaceModeActive );
// <--
}
}
}
}
return pRet;
}