Files
libreoffice/sw/source/core/text/txtfld.cxx
Oliver Bolte c5f0899c41 INTEGRATION: CWS pchfix02 (1.23.2); FILE MERGED
2006/09/01 17:52:06 kaib 1.23.2.1: #i68856# Added header markers and pch files
2006-09-16 20:40:30 +00:00

496 lines
17 KiB
C++

/*************************************************************************
*
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: txtfld.cxx,v $
*
* $Revision: 1.24 $
*
* last change: $Author: obo $ $Date: 2006-09-16 21:40:30 $
*
* The Contents of this file are made available subject to
* the terms of GNU Lesser General Public License Version 2.1.
*
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2005 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
************************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"
#include "hintids.hxx"
#ifndef _FMTFLD_HXX //autogen
#include <fmtfld.hxx>
#endif
#ifndef _TXTFLD_HXX //autogen
#include <txtfld.hxx>
#endif
#ifndef _CHARFMT_HXX //autogen
#include <charfmt.hxx>
#endif
#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()
#ifndef _PORMULTI_HXX
#include <pormulti.hxx> // SwMultiPortion
#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;
SwFrm *pFrame = (SwFrm*)pFrm;
SwField *pFld = (SwField*)pHint->GetFld().GetFld();
const sal_Bool bName = rInf.GetOpt().IsFldName();
SwCharFmt* pChFmt = 0;
sal_Bool bNewFlyPor = sal_False,
bINet = sal_False;
// Sprache setzen
((SwTxtFormatter*)this)->SeekAndChg( rInf );
pFld->SetLanguage( GetFnt()->GetLanguage() );
ViewShell *pSh = rInf.GetVsh();
switch( pFld->GetTyp()->Which() )
{
case RES_SCRIPTFLD:
case RES_POSTITFLD:
pRet = new SwPostItsPortion( RES_SCRIPTFLD == pFld->GetTyp()->Which() );
break;
case RES_COMBINED_CHARS:
{
String sStr( pFld->GetCntnt( bName ));
if( bName )
pRet = new SwFldPortion( sStr );
else
pRet = new SwCombinedPortion( sStr );
}
break;
case RES_HIDDENTXTFLD:
pRet = new SwHiddenPortion(pFld->GetCntnt( bName ));
break;
case RES_CHAPTERFLD:
if( !bName && pSh && !pSh->Imp()->IsUpdateExpFlds() )
{
((SwChapterField*)pFld)->ChangeExpansion( pFrame,
&((SwTxtFld*)pHint)->GetTxtNode() );
}
pRet = new SwFldPortion( pFld->GetCntnt( bName ) );
break;
case RES_DOCSTATFLD:
if( !bName && pSh && !pSh->Imp()->IsUpdateExpFlds() )
((SwDocStatField*)pFld)->ChangeExpansion( pFrame );
pRet = new SwFldPortion( pFld->GetCntnt( bName ) );
break;
case RES_PAGENUMBERFLD:
{
if( !bName && pSh && !pSh->Imp()->IsUpdateExpFlds() )
{
SwPageNumberFieldType *pPageNr = (SwPageNumberFieldType *)pFld->GetTyp();
const SwRootFrm* pTmpRootFrm = pSh->GetLayout();
const sal_Bool bVirt = pTmpRootFrm->IsVirtPageNum();
SwDoc* pDoc = pSh->GetDoc();
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);
}
pRet = new SwFldPortion( pFld->GetCntnt( bName ) );
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 );
}
}
pRet = new SwFldPortion( pFld->GetCntnt( bName ) );
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 );
}
*/
}
pRet = new SwFldPortion( pFld->GetCntnt( bName ) );
break;
}
case RES_REFPAGEGETFLD:
if( !bName && pSh && !pSh->Imp()->IsUpdateExpFlds() )
((SwRefPageGetField*)pFld)->ChangeExpansion( pFrame, (SwTxtFld*)pHint );
pRet = new SwFldPortion( pFld->GetCntnt( bName ) );
break;
case RES_JUMPEDITFLD:
if( !bName )
pChFmt = ((SwJumpEditField*)pFld)->GetCharFmt();
bNewFlyPor = sal_True;
break;
default:
{
pRet = new SwFldPortion(pFld->GetCntnt( bName ) );
}
}
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() );
}
pRet = new SwFldPortion( pFld->GetCntnt( bName ), pTmpFnt );
}
return pRet;
}
/*************************************************************************
* SwTxtFormatter::NewExtraPortion()
*************************************************************************/
SwLinePortion *SwTxtFormatter::NewExtraPortion( SwTxtFormatInfo &rInf )
{
SwTxtAttr *pHint = GetAttr( rInf.GetIdx() );
SwLinePortion *pRet = 0;
if( !pHint )
{
#if OSL_DEBUG_LEVEL > 1
// aDbstream << "NewExtraPortion: hint not found?" << endl;
#endif
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_SOFTHYPH :
{
pRet = new SwSoftHyphPortion;
break;
}
case RES_TXTATR_HARDBLANK :
{
pRet = new SwBlankPortion( ((SwTxtHardBlank*)pHint)->GetChar() );
break;
}
case RES_TXTATR_FIELD :
{
pRet = NewFldPortion( rInf, pHint );
break;
}
case RES_TXTATR_REFMARK :
{
pRet = new SwIsoRefPortion;
break;
}
case RES_TXTATR_TOXMARK :
{
pRet = new SwIsoToxPortion;
break;
}
default: ;
}
if( !pRet )
{
#if OSL_DEBUG_LEVEL > 1
// aDbstream << "NewExtraPortion: unknown hint" << endl;
#endif
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->IsCounted())
{
CONST SwNumFmt &rNumFmt = pNumRule->Get( pTxtNd->GetLevel() );
const sal_Bool bLeft = SVX_ADJUST_LEFT == rNumFmt.GetNumAdjust();
const sal_Bool bCenter = SVX_ADJUST_CENTER == rNumFmt.GetNumAdjust();
const KSHORT nMinDist = rNumFmt.GetCharTextDistance();
if( SVX_NUM_BITMAP == rNumFmt.GetNumberingType() )
{
pRet = new SwGrfNumPortion( (SwFrm*)GetTxtFrm(),rNumFmt.GetBrush(),
rNumFmt.GetGraphicOrientation(), rNumFmt.GetGraphicSize(),
bLeft, bCenter, nMinDist );
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
// Weight style of paragraph font should not be considered
// Posture style of paragraph font should not be considered
pNumFnt->SetUnderline( 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 BYTE 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() );
pRet = new SwBulletPortion( rNumFmt.GetBulletChar(), pNumFnt, bLeft,
bCenter, nMinDist );
}
else
{
// --> OD 2006-06-02 #b6432095#
// use method <SwNumRule::MakeNumString(..)> instead of
// method <SwTxtNode::GetNumString()>, because for levels with
// numbering none the prefix and the suffix strings have to be provided.
// XubString aTxt( pTxtNd->GetNumString() );
XubString aTxt( pNumRule->MakeNumString( *(pTxtNd->GetNum()) ) );
// <--
// 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 );
}
//
// 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() );
pRet = new SwNumberPortion( aTxt, pNumFnt, bLeft, bCenter,
nMinDist );
}
}
}
}
return pRet;
}
/* -----------------26.06.2003 13:54-----------------
--------------------------------------------------*/
void SwTxtFld::NotifyContentChange(SwFmtFld& rFmtFld)
{
//if not in undo section notify the change
if(pMyTxtNd && pMyTxtNd->GetNodes().IsDocNodes())
pMyTxtNd->Modify(0, &rFmtFld);
}
// #111840#
SwPosition * SwTxtFld::GetPosition() const
{
return GetTxtNode().GetPosition(this);
}