blob: ff61f393153841d41c288f0be784846bff4c2732 [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> // fuer RES_..
#include <frame.hxx> // fuer AttrCache
#include <format.hxx>
#include <hints.hxx> // fuer SwFmtChg
#include <doc.hxx>
#include <paratr.hxx> // fuer SwParaFmt - SwHyphenBug
#include <swcache.hxx>
#include <fmtcolfunc.hxx>
TYPEINIT1( SwFmt, SwClient ); //rtti fuer SwFmt
/*************************************************************************
|* SwFmt::SwFmt
*************************************************************************/
SwFmt::SwFmt( SwAttrPool& rPool, const sal_Char* pFmtNm,
const sal_uInt16* pWhichRanges, SwFmt *pDrvdFrm, sal_uInt16 nFmtWhich )
: SwModify( pDrvdFrm ),
aSet( rPool, pWhichRanges ),
nWhichId( nFmtWhich ),
nFmtId( 0 ),
nPoolFmtId( USHRT_MAX ),
nPoolHelpId( USHRT_MAX ),
nPoolHlpFileId( UCHAR_MAX )
{
aFmtName.AssignAscii( pFmtNm );
bWritten = bFmtInDTOR = bAutoUpdateFmt = sal_False; // LAYER_IMPL
bAutoFmt = sal_True;
if( pDrvdFrm )
aSet.SetParent( &pDrvdFrm->aSet );
}
SwFmt::SwFmt( SwAttrPool& rPool, const String &rFmtNm,
const sal_uInt16* pWhichRanges, SwFmt *pDrvdFrm, sal_uInt16 nFmtWhich )
: SwModify( pDrvdFrm ),
aFmtName( rFmtNm ),
aSet( rPool, pWhichRanges ),
nWhichId( nFmtWhich ),
nFmtId( 0 ),
nPoolFmtId( USHRT_MAX ),
nPoolHelpId( USHRT_MAX ),
nPoolHlpFileId( UCHAR_MAX )
{
bWritten = bFmtInDTOR = bAutoUpdateFmt = sal_False; // LAYER_IMPL
bAutoFmt = sal_True;
if( pDrvdFrm )
aSet.SetParent( &pDrvdFrm->aSet );
}
SwFmt::SwFmt( const SwFmt& rFmt )
: SwModify( rFmt.DerivedFrom() ),
aFmtName( rFmt.aFmtName ),
aSet( rFmt.aSet ),
nWhichId( rFmt.nWhichId ),
nFmtId( 0 ),
nPoolFmtId( rFmt.GetPoolFmtId() ),
nPoolHelpId( rFmt.GetPoolHelpId() ),
nPoolHlpFileId( rFmt.GetPoolHlpFileId() )
{
bWritten = bFmtInDTOR = sal_False; // LAYER_IMPL
bAutoFmt = rFmt.bAutoFmt;
bAutoUpdateFmt = rFmt.bAutoUpdateFmt;
if( rFmt.DerivedFrom() )
aSet.SetParent( &rFmt.DerivedFrom()->aSet );
// einige Sonderbehandlungen fuer Attribute
aSet.SetModifyAtAttr( this );
}
/*************************************************************************
|* SwFmt &SwFmt::operator=(const SwFmt& aFmt)
|*
|* Beschreibung Dokument 1.14
|* Ersterstellung JP 22.11.90
|* Letzte Aenderung JP 05.08.94
*************************************************************************/
SwFmt &SwFmt::operator=(const SwFmt& rFmt)
{
nWhichId = rFmt.nWhichId;
nPoolFmtId = rFmt.GetPoolFmtId();
nPoolHelpId = rFmt.GetPoolHelpId();
nPoolHlpFileId = rFmt.GetPoolHlpFileId();
if ( IsInCache() )
{
SwFrm::GetCache().Delete( this );
SetInCache( sal_False );
}
SetInSwFntCache( sal_False );
// kopiere nur das Attribut-Delta Array
SwAttrSet aOld( *aSet.GetPool(), aSet.GetRanges() ),
aNew( *aSet.GetPool(), aSet.GetRanges() );
aSet.Intersect_BC( rFmt.aSet, &aOld, &aNew );
aSet.Put_BC( rFmt.aSet, &aOld, &aNew );
// einige Sonderbehandlungen fuer Attribute
aSet.SetModifyAtAttr( this );
// PoolItem-Attr erzeugen fuers Modify !!!
if( aOld.Count() )
{
SwAttrSetChg aChgOld( aSet, aOld );
SwAttrSetChg aChgNew( aSet, aNew );
ModifyNotification( &aChgOld, &aChgNew ); // alle veraenderten werden verschickt
}
if( GetRegisteredIn() != rFmt.GetRegisteredIn() )
{
if( GetRegisteredIn() )
GetRegisteredInNonConst()->Remove(this);
if(rFmt.GetRegisteredIn())
{
const_cast<SwFmt&>(rFmt).GetRegisteredInNonConst()->Add(this);
aSet.SetParent( &rFmt.aSet );
}
else
aSet.SetParent( 0 );
}
bAutoFmt = rFmt.bAutoFmt;
bAutoUpdateFmt = rFmt.bAutoUpdateFmt;
return *this;
}
void SwFmt::SetName( const String& rNewName, sal_Bool bBroadcast )
{
ASSERT(!IsDefault(), "SetName: Defaultformat" );
if( bBroadcast )
{
SwStringMsgPoolItem aOld( RES_NAME_CHANGED, aFmtName );
SwStringMsgPoolItem aNew( RES_NAME_CHANGED, rNewName );
aFmtName = rNewName;
ModifyNotification( &aOld, &aNew );
}
else
{
aFmtName = rNewName;
}
}
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* diese Funktion wird in jedem Copy-Ctor gerufen, damit die
* Attribute kopiert werden. Diese koennen erst kopiert werden,
* wenn die abgeleitet Klasse existiert, denn beim Setzen der
* Attribute wird die Which()-Methode gerufen, die hier in der
* Basis-Klasse auf 0 defaultet ist.
*
* Zusatz: JP 8.4.1994
* Wird ueber Dokumentgrenzen kopiert, so muss das neue Dokument
* mit angeben werden, in dem this steht. Z.Z. ist das fuers
* DropCaps wichtig, dieses haelt Daten, die tief kopiert werden
* muessen !!
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
void SwFmt::CopyAttrs( const SwFmt& rFmt, sal_Bool bReplace )
{
// kopiere nur das Attribut-Delta Array
if ( IsInCache() )
{
SwFrm::GetCache().Delete( this );
SetInCache( sal_False );
}
SetInSwFntCache( sal_False );
// Sonderbehandlung fuer einige Attribute
SwAttrSet* pChgSet = (SwAttrSet*)&rFmt.aSet;
if( !bReplace ) // nur die neu, die nicht gesetzt sind ??
{
if( pChgSet == (SwAttrSet*)&rFmt.aSet ) // Set hier kopieren
pChgSet = new SwAttrSet( rFmt.aSet );
pChgSet->Differentiate( aSet );
}
// kopiere nur das Attribut-Delta Array
if( pChgSet->GetPool() != aSet.GetPool() )
pChgSet->CopyToModify( *this );
else
{
SwAttrSet aOld( *aSet.GetPool(), aSet.GetRanges() ),
aNew( *aSet.GetPool(), aSet.GetRanges() );
if ( 0 != aSet.Put_BC( *pChgSet, &aOld, &aNew ) )
{
// einige Sonderbehandlungen fuer Attribute
aSet.SetModifyAtAttr( this );
SwAttrSetChg aChgOld( aSet, aOld );
SwAttrSetChg aChgNew( aSet, aNew );
ModifyNotification( &aChgOld, &aChgNew ); // alle veraenderten werden verschickt
}
}
if( pChgSet != (SwAttrSet*)&rFmt.aSet ) // Set hier angelegt ?
delete pChgSet;
}
/*************************************************************************
|* SwFmt::~SwFmt()
|*
|* Beschreibung Dokument 1.14
|* Ersterstellung JP 22.11.90
|* Letzte Aenderung JP 14.02.91
*************************************************************************/
SwFmt::~SwFmt()
{
/* das passiert bei der ObjectDying Message */
/* alle Abhaengigen auf DerivedFrom umhaengen */
if( GetDepends() )
{
ASSERT(DerivedFrom(), "SwFmt::~SwFmt: Def Abhaengige!" );
bFmtInDTOR = sal_True;
SwFmt *pParentFmt = DerivedFrom();
if (!pParentFmt) // see #112405#
{
DBG_ERROR( "~SwFmt: parent format missing" );
}
else
{
while( GetDepends() && pParentFmt)
{
SwFmtChg aOldFmt(this);
SwFmtChg aNewFmt(pParentFmt);
SwClient * pDepend = (SwClient*)GetDepends();
pParentFmt->Add(pDepend);
pDepend->ModifyNotification(&aOldFmt, &aNewFmt);
}
}
}
}
/*************************************************************************
|* void SwFmt::Modify( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue )
|*
|* Beschreibung Dokument 1.14
|* Ersterstellung JP 22.11.90
|* Letzte Aenderung JP 05.08.94
*************************************************************************/
void SwFmt::Modify( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue )
{
sal_Bool bWeiter = sal_True; // sal_True = Propagierung an die Abhaengigen
sal_uInt16 nWhich = pOldValue ? pOldValue->Which() :
pNewValue ? pNewValue->Which() : 0 ;
switch( nWhich )
{
case 0: break; // Which-Id von 0 ???
case RES_OBJECTDYING :
{
// ist das sterbende Object das "Parent"-Format von diesen Format,
// dann haengt sich dieses Format an den Parent vom Parent
SwFmt * pFmt = (SwFmt *) ((SwPtrMsgPoolItem *)pNewValue)->pObject;
// nicht umhaengen wenn dieses das oberste Format ist !!
if( GetRegisteredIn() && GetRegisteredIn() == pFmt )
{
if( pFmt->GetRegisteredIn() )
{
// wenn Parent, dann im neuen Parent wieder anmelden
pFmt->DerivedFrom()->Add( this );
aSet.SetParent( &DerivedFrom()->aSet );
}
else
{
// sonst auf jeden Fall beim sterbenden abmelden
DerivedFrom()->Remove( this );
aSet.SetParent( 0 );
}
}
} // OBJECTDYING
break;
case RES_ATTRSET_CHG:
if( ((SwAttrSetChg*)pOldValue)->GetTheChgdSet() != &aSet )
{
//nur die weiter geben, die hier nicht gesetzt sind !!
SwAttrSetChg aOld( *(SwAttrSetChg*)pOldValue );
SwAttrSetChg aNew( *(SwAttrSetChg*)pNewValue );
aOld.GetChgSet()->Differentiate( aSet );
aNew.GetChgSet()->Differentiate( aSet );
if( aNew.Count() )
// keine mehr gesetzt, dann Ende !!
NotifyClients( &aOld, &aNew );
bWeiter = sal_False;
}
break;
case RES_FMT_CHG:
// falls mein Format Parent umgesetzt wird, dann melde ich
// meinen Attrset beim Neuen an.
// sein eigenes Modify ueberspringen !!
if( ((SwFmtChg*)pOldValue)->pChangedFmt != this &&
((SwFmtChg*)pNewValue)->pChangedFmt == DerivedFrom() )
{
// den Set an den neuen Parent haengen
aSet.SetParent( DerivedFrom() ? &DerivedFrom()->aSet : 0 );
}
break;
case RES_RESET_FMTWRITTEN:
{
// IsWritten-Flag zuruecksetzen. Hint nur an abhanegige
// Formate (und keine Frames) propagieren.
// mba: the code does the opposite from what is written in the comment!
ResetWritten();
// mba: here we don't use the additional stuff from NotifyClients().
// should we?!
// mba: move the code that ignores this event to the clients
ModifyBroadcast( pOldValue, pNewValue, TYPE(SwFmt) );
bWeiter = sal_False;
}
break;
default:
{
// Ist das Attribut in diesem Format definiert, dann auf
// NICHT weiter propagieren !!
if( SFX_ITEM_SET == aSet.GetItemState( nWhich, sal_False ))
{
// wie finde ich heraus, ob nicht ich die Message versende ??
// aber wer ruft das hier ????
//ASSERT( sal_False, "Modify ohne Absender verschickt" );
//JP 11.06.96: DropCaps koennen hierher kommen
ASSERT( RES_PARATR_DROP == nWhich, "Modify ohne Absender verschickt" );
bWeiter = sal_False;
}
} // default
} // switch
if( bWeiter )
{
// laufe durch alle abhaengigen Formate
NotifyClients( pOldValue, pNewValue );
}
}
sal_Bool SwFmt::SetDerivedFrom(SwFmt *pDerFrom)
{
if ( pDerFrom )
{
// Zyklus?
const SwFmt* pFmt = pDerFrom;
while ( pFmt != 0 )
{
if ( pFmt == this )
return sal_False;
pFmt=pFmt->DerivedFrom();
}
}
else
{
// Nichts angegeben, Dflt-Format suchen
pDerFrom = this;
while ( pDerFrom->DerivedFrom() )
pDerFrom = pDerFrom->DerivedFrom();
}
if ( (pDerFrom == DerivedFrom()) || (pDerFrom == this) )
return sal_False;
ASSERT( Which()==pDerFrom->Which()
|| ( Which()==RES_CONDTXTFMTCOLL && pDerFrom->Which()==RES_TXTFMTCOLL)
|| ( Which()==RES_TXTFMTCOLL && pDerFrom->Which()==RES_CONDTXTFMTCOLL)
|| ( Which()==RES_FLYFRMFMT && pDerFrom->Which()==RES_FRMFMT ),
"SetDerivedFrom: Aepfel von Birnen ableiten?");
if ( IsInCache() )
{
SwFrm::GetCache().Delete( this );
SetInCache( sal_False );
}
SetInSwFntCache( sal_False );
pDerFrom->Add(this);
aSet.SetParent( &pDerFrom->aSet );
SwFmtChg aOldFmt(this);
SwFmtChg aNewFmt(this);
ModifyNotification( &aOldFmt, &aNewFmt );
return sal_True;
}
sal_Bool SwFmt::SetFmtAttr(const SfxPoolItem& rAttr )
{
if ( IsInCache() || IsInSwFntCache() )
{
const sal_uInt16 nWhich = rAttr.Which();
CheckCaching( nWhich );
}
// wenn Modify gelockt ist, werden keine Modifies verschickt;
// fuer FrmFmt's immer das Modify verschicken!
sal_Bool bRet = sal_False;
const sal_uInt16 nFmtWhich = Which();
if( IsModifyLocked() || (!GetDepends() &&
(RES_GRFFMTCOLL == nFmtWhich ||
RES_TXTFMTCOLL == nFmtWhich ) ) )
{
if( 0 != ( bRet = (0 != aSet.Put( rAttr ))) )
aSet.SetModifyAtAttr( this );
if ( nFmtWhich == RES_TXTFMTCOLL && rAttr.Which() == RES_PARATR_NUMRULE )
{
TxtFmtCollFunc::CheckTxtFmtCollForDeletionOfAssignmentToOutlineStyle( this );
}
}
else
{
// kopiere nur das Attribut-Delta Array
SwAttrSet aOld( *aSet.GetPool(), aSet.GetRanges() ),
aNew( *aSet.GetPool(), aSet.GetRanges() );
bRet = 0 != aSet.Put_BC( rAttr, &aOld, &aNew );
if( bRet )
{
// einige Sonderbehandlungen fuer Attribute
aSet.SetModifyAtAttr( this );
SwAttrSetChg aChgOld( aSet, aOld );
SwAttrSetChg aChgNew( aSet, aNew );
ModifyNotification( &aChgOld, &aChgNew ); // alle veraenderten werden verschickt
}
}
return bRet;
}
sal_Bool SwFmt::SetFmtAttr( const SfxItemSet& rSet )
{
if( !rSet.Count() )
return sal_False;
if ( IsInCache() )
{
SwFrm::GetCache().Delete( this );
SetInCache( sal_False );
}
SetInSwFntCache( sal_False );
// wenn Modify gelockt ist, werden keine Modifies verschickt;
// fuer FrmFmt's immer das Modify verschicken!
sal_Bool bRet = sal_False;
const sal_uInt16 nFmtWhich = Which();
if ( IsModifyLocked() ||
( !GetDepends() &&
( RES_GRFFMTCOLL == nFmtWhich ||
RES_TXTFMTCOLL == nFmtWhich ) ) )
{
if( 0 != ( bRet = (0 != aSet.Put( rSet ))) )
aSet.SetModifyAtAttr( this );
if ( nFmtWhich == RES_TXTFMTCOLL )
{
TxtFmtCollFunc::CheckTxtFmtCollForDeletionOfAssignmentToOutlineStyle( this );
}
}
else
{
SwAttrSet aOld( *aSet.GetPool(), aSet.GetRanges() ),
aNew( *aSet.GetPool(), aSet.GetRanges() );
bRet = 0 != aSet.Put_BC( rSet, &aOld, &aNew );
if( bRet )
{
// einige Sonderbehandlungen fuer Attribute
aSet.SetModifyAtAttr( this );
SwAttrSetChg aChgOld( aSet, aOld );
SwAttrSetChg aChgNew( aSet, aNew );
ModifyNotification( &aChgOld, &aChgNew ); // alle veraenderten werden verschickt
}
}
return bRet;
}
// Nimmt den Hint mit nWhich aus dem Delta-Array
sal_Bool SwFmt::ResetFmtAttr( sal_uInt16 nWhich1, sal_uInt16 nWhich2 )
{
if( !aSet.Count() )
return sal_False;
if( !nWhich2 || nWhich2 < nWhich1 )
nWhich2 = nWhich1; // dann setze auf 1. Id, nur dieses Item
if ( IsInCache() || IsInSwFntCache() )
{
for( sal_uInt16 n = nWhich1; n < nWhich2; ++n )
CheckCaching( n );
}
// wenn Modify gelockt ist, werden keine Modifies verschickt
if( IsModifyLocked() )
return 0 != (( nWhich2 == nWhich1 )
? aSet.ClearItem( nWhich1 )
: aSet.ClearItem_BC( nWhich1, nWhich2 ));
SwAttrSet aOld( *aSet.GetPool(), aSet.GetRanges() ),
aNew( *aSet.GetPool(), aSet.GetRanges() );
sal_Bool bRet = 0 != aSet.ClearItem_BC( nWhich1, nWhich2, &aOld, &aNew );
if( bRet )
{
SwAttrSetChg aChgOld( aSet, aOld );
SwAttrSetChg aChgNew( aSet, aNew );
ModifyNotification( &aChgOld, &aChgNew ); // alle veraenderten werden verschickt
}
return bRet;
}
// --> OD 2007-01-24 #i73790#
// method renamed
sal_uInt16 SwFmt::ResetAllFmtAttr()
// <--
{
if( !aSet.Count() )
return 0;
if ( IsInCache() )
{
SwFrm::GetCache().Delete( this );
SetInCache( sal_False );
}
SetInSwFntCache( sal_False );
// wenn Modify gelockt ist, werden keine Modifies verschickt
if( IsModifyLocked() )
return aSet.ClearItem( 0 );
SwAttrSet aOld( *aSet.GetPool(), aSet.GetRanges() ),
aNew( *aSet.GetPool(), aSet.GetRanges() );
sal_Bool bRet = 0 != aSet.ClearItem_BC( 0, &aOld, &aNew );
if( bRet )
{
SwAttrSetChg aChgOld( aSet, aOld );
SwAttrSetChg aChgNew( aSet, aNew );
ModifyNotification( &aChgOld, &aChgNew ); // alle veraenderten werden verschickt
}
return aNew.Count();
}
/*************************************************************************
|* void SwFmt::GetInfo( const SfxPoolItem& ) const
|*
|* Beschreibung
|* Ersterstellung JP 18.04.94
|* Letzte Aenderung JP 05.08.94
*************************************************************************/
sal_Bool SwFmt::GetInfo( SfxPoolItem& rInfo ) const
{
sal_Bool bRet = SwModify::GetInfo( rInfo );
return bRet;
}
void SwFmt::DelDiffs( const SfxItemSet& rSet )
{
if( !aSet.Count() )
return;
if ( IsInCache() )
{
SwFrm::GetCache().Delete( this );
SetInCache( sal_False );
}
SetInSwFntCache( sal_False );
// wenn Modify gelockt ist, werden keine Modifies verschickt
if( IsModifyLocked() )
{
aSet.Intersect( rSet );
return;
}
SwAttrSet aOld( *aSet.GetPool(), aSet.GetRanges() ),
aNew( *aSet.GetPool(), aSet.GetRanges() );
sal_Bool bRet = 0 != aSet.Intersect_BC( rSet, &aOld, &aNew );
if( bRet )
{
SwAttrSetChg aChgOld( aSet, aOld );
SwAttrSetChg aChgNew( aSet, aNew );
ModifyNotification( &aChgOld, &aChgNew ); // alle veraenderten werden verschickt
}
}
/** SwFmt::IsBackgroundTransparent - for feature #99657#
OD 22.08.2002
Virtual method to determine, if background of format is transparent.
Default implementation returns false. Thus, subclasses have to overload
method, if the specific subclass can have a transparent background.
@author OD
@return false, default implementation
*/
sal_Bool SwFmt::IsBackgroundTransparent() const
{
return sal_False;
}
/** SwFmt::IsShadowTransparent - for feature #99657#
OD 22.08.2002
Virtual method to determine, if shadow of format is transparent.
Default implementation returns false. Thus, subclasses have to overload
method, if the specific subclass can have a transparent shadow.
@author OD
@return false, default implementation
*/
sal_Bool SwFmt::IsShadowTransparent() const
{
return sal_False;
}
/*
* Document Interface Access
*/
const IDocumentSettingAccess* SwFmt::getIDocumentSettingAccess() const { return GetDoc(); }
const IDocumentDrawModelAccess* SwFmt::getIDocumentDrawModelAccess() const { return GetDoc(); }
IDocumentDrawModelAccess* SwFmt::getIDocumentDrawModelAccess() { return GetDoc(); }
const IDocumentLayoutAccess* SwFmt::getIDocumentLayoutAccess() const { return GetDoc(); }
IDocumentLayoutAccess* SwFmt::getIDocumentLayoutAccess() { return GetDoc(); }
IDocumentTimerAccess* SwFmt::getIDocumentTimerAccess() { return GetDoc(); }
IDocumentFieldsAccess* SwFmt::getIDocumentFieldsAccess() { return GetDoc(); }
IDocumentChartDataProviderAccess* SwFmt::getIDocumentChartDataProviderAccess() { return GetDoc(); }