xref: /aoo41x/main/sw/source/core/txtnode/atrfld.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 
31 #include "fldbas.hxx"          // fuer FieldType
32 #include <fmtfld.hxx>
33 #include <txtfld.hxx>
34 #include <docufld.hxx>
35 #include <doc.hxx>
36 
37 #include "reffld.hxx"
38 #include "ddefld.hxx"
39 #include "usrfld.hxx"
40 #include "expfld.hxx"
41 #include "swfont.hxx"       // fuer GetFldsColor
42 #include "ndtxt.hxx"        // SwTxtNode
43 #include "calc.hxx"         // Update fuer UserFields
44 #include "hints.hxx"
45 #include <IDocumentFieldsAccess.hxx>
46 #include <fieldhint.hxx>
47 #include <svl/smplhint.hxx>
48 
49 TYPEINIT3( SwFmtFld, SfxPoolItem, SwClient,SfxBroadcaster)
50 TYPEINIT1(SwFmtFldHint, SfxHint);
51 
52 /****************************************************************************
53  *
54  *  class SwFmtFld
55  *
56  ****************************************************************************/
57 
58 	// Konstruktor fuers Default vom Attribut-Pool
59 SwFmtFld::SwFmtFld()
60 	: SfxPoolItem( RES_TXTATR_FIELD ),
61 	SwClient( 0 ),
62 	pField( 0 ),
63 	pTxtAttr( 0 )
64 {
65 }
66 
67 SwFmtFld::SwFmtFld( const SwField &rFld )
68 	: SfxPoolItem( RES_TXTATR_FIELD ),
69 	SwClient( rFld.GetTyp() ),
70 	pTxtAttr( 0 )
71 {
72     pField = rFld.CopyField();
73 }
74 
75 // #i24434#
76 // Since Items are used in ItemPool and in default constructed ItemSets with
77 // full pool range, all items need to be clonable. Thus, this one needed to be
78 // corrected
79 SwFmtFld::SwFmtFld( const SwFmtFld& rAttr )
80     : SfxPoolItem( RES_TXTATR_FIELD ), SwClient(), SfxBroadcaster(),
81     pField( 0 ),
82     pTxtAttr( 0 )
83 {
84     if(rAttr.GetFld())
85 	{
86         rAttr.GetFld()->GetTyp()->Add(this);
87         pField = rAttr.GetFld()->CopyField();
88     }
89 }
90 
91 SwFmtFld::~SwFmtFld()
92 {
93 	SwFieldType* pType = pField ? pField->GetTyp() : 0;
94 
95 	if (pType && pType->Which() == RES_DBFLD)
96 		pType = 0;	// DB-Feldtypen zerstoeren sich selbst
97 
98 	Broadcast( SwFmtFldHint( this, SWFMTFLD_REMOVED ) );
99 	delete pField;
100 
101 	// bei einige FeldTypen muessen wir den FeldTypen noch loeschen
102 	if( pType && pType->IsLastDepend() )
103 	{
104 		sal_Bool bDel = sal_False;
105 		switch( pType->Which() )
106 		{
107 		case RES_USERFLD:
108 			bDel = ((SwUserFieldType*)pType)->IsDeleted();
109 			break;
110 
111 		case RES_SETEXPFLD:
112 			bDel = ((SwSetExpFieldType*)pType)->IsDeleted();
113 			break;
114 
115 		case RES_DDEFLD:
116 			bDel = ((SwDDEFieldType*)pType)->IsDeleted();
117 			break;
118 		}
119 
120 		if( bDel )
121 		{
122 			// vorm loeschen erstmal austragen
123 			pType->Remove( this );
124 			delete pType;
125 		}
126 	}
127 }
128 
129 void SwFmtFld::RegisterToFieldType( SwFieldType& rType )
130 {
131     rType.Add(this);
132 }
133 
134 
135 // #111840#
136 void SwFmtFld::SetFld(SwField * _pField)
137 {
138     if (NULL != pField)
139         delete pField;
140 
141     pField = _pField;
142 	Broadcast( SwFmtFldHint( this, SWFMTFLD_CHANGED ) );
143 }
144 
145 int SwFmtFld::operator==( const SfxPoolItem& rAttr ) const
146 {
147 	ASSERT( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
148     // OD 2004-05-14 #i29146# - correction: check, if <pField> and
149     // <((SwFmtFld&)rAttr).GetFld()> are set.
150     // OD 2004-05-14 #i29146# - items are equal, if both fields aren't set.
151     return ( pField && ((SwFmtFld&)rAttr).GetFld() &&
152              pField->GetTyp() == ((SwFmtFld&)rAttr).GetFld()->GetTyp() &&
153              pField->GetFormat() == ((SwFmtFld&)rAttr).GetFld()->GetFormat() ) ||
154            ( !pField && !((SwFmtFld&)rAttr).GetFld() );
155 }
156 
157 SfxPoolItem* SwFmtFld::Clone( SfxItemPool* ) const
158 {
159 	return new SwFmtFld( *this );
160 }
161 
162 void SwFmtFld::SwClientNotify( const SwModify&, const SfxHint& rHint )
163 {
164     if( !pTxtAttr )
165         return;
166 
167     const SwFieldHint* pHint = dynamic_cast<const SwFieldHint*>( &rHint );
168     if ( pHint )
169     {
170         // replace field content by text
171         SwPaM* pPaM = pHint->GetPaM();
172         SwDoc* pDoc = pPaM->GetDoc();
173         const SwTxtNode& rTxtNode = pTxtAttr->GetTxtNode();
174         pPaM->GetPoint()->nNode = rTxtNode;
175         pPaM->GetPoint()->nContent.Assign( (SwTxtNode*)&rTxtNode, *pTxtAttr->GetStart() );
176 
177         String const aEntry( GetFld()->ExpandField( pDoc->IsClipBoard() ) );
178         pPaM->SetMark();
179         pPaM->Move( fnMoveForward );
180         pDoc->DeleteRange( *pPaM );
181         pDoc->InsertString( *pPaM, aEntry );
182     }
183 }
184 
185 void SwFmtFld::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
186 {
187 	if( !pTxtAttr )
188 		return;
189 
190     // don't do anything, especially not expand!
191     if( pNew && pNew->Which() == RES_OBJECTDYING )
192         return;
193 
194 	SwTxtNode* pTxtNd = (SwTxtNode*)&pTxtAttr->GetTxtNode();
195 	ASSERT( pTxtNd, "wo ist denn mein Node?" );
196 	if( pNew )
197 	{
198 		switch( pNew->Which() )
199 		{
200 		case RES_TXTATR_FLDCHG:
201 				// "Farbe hat sich geaendert !"
202 				// this, this fuer "nur Painten"
203 				pTxtNd->ModifyNotification( this, this );
204 				return;
205 		case RES_REFMARKFLD_UPDATE:
206 				// GetReferenz-Felder aktualisieren
207 				if( RES_GETREFFLD == GetFld()->GetTyp()->Which() )
208                 {
209                     // --> OD 2007-09-06 #i81002#
210 //                    ((SwGetRefField*)GetFld())->UpdateField();
211                     dynamic_cast<SwGetRefField*>(GetFld())->UpdateField( pTxtAttr );
212                     // <--
213                 }
214 				break;
215 		case RES_DOCPOS_UPDATE:
216 				// Je nach DocPos aktualisieren (SwTxtFrm::Modify())
217 				pTxtNd->ModifyNotification( pNew, this );
218 				return;
219 
220 		case RES_ATTRSET_CHG:
221 		case RES_FMT_CHG:
222 				pTxtNd->ModifyNotification( pOld, pNew );
223 				return;
224         default:
225                 break;
226 		}
227 	}
228 
229 	switch (GetFld()->GetTyp()->Which())
230 	{
231 		case RES_HIDDENPARAFLD:
232 			if( !pOld || RES_HIDDENPARA_PRINT != pOld->Which() )
233 				break;
234 		case RES_DBSETNUMBERFLD:
235 		case RES_DBNUMSETFLD:
236 		case RES_DBNEXTSETFLD:
237 		case RES_DBNAMEFLD:
238 			pTxtNd->ModifyNotification( 0, pNew);
239 			return;
240 	}
241 
242 	if( RES_USERFLD == GetFld()->GetTyp()->Which() )
243 	{
244 		SwUserFieldType* pType = (SwUserFieldType*)GetFld()->GetTyp();
245 		if(!pType->IsValid())
246 		{
247 			SwCalc aCalc( *pTxtNd->GetDoc() );
248 			pType->GetValue( aCalc );
249 		}
250 	}
251 	pTxtAttr->Expand();
252 }
253 
254 sal_Bool SwFmtFld::GetInfo( SfxPoolItem& rInfo ) const
255 {
256 	const SwTxtNode* pTxtNd;
257 	if( RES_AUTOFMT_DOCNODE != rInfo.Which() ||
258 		!pTxtAttr || 0 == ( pTxtNd = pTxtAttr->GetpTxtNode() ) ||
259 		&pTxtNd->GetNodes() != ((SwAutoFmtGetDocNode&)rInfo).pNodes )
260 		return sal_True;
261 
262 	((SwAutoFmtGetDocNode&)rInfo).pCntntNode = pTxtNd;
263 	return sal_False;
264 }
265 
266 
267 sal_Bool SwFmtFld::IsFldInDoc() const
268 {
269 	const SwTxtNode* pTxtNd;
270 	return pTxtAttr && 0 != ( pTxtNd = pTxtAttr->GetpTxtNode() ) &&
271 			pTxtNd->GetNodes().IsDocNodes();
272 }
273 
274 sal_Bool SwFmtFld::IsProtect() const
275 {
276 	const SwTxtNode* pTxtNd;
277 	return pTxtAttr && 0 != ( pTxtNd = pTxtAttr->GetpTxtNode() ) &&
278 			pTxtNd->IsProtect();
279 }
280 
281 /*************************************************************************
282 |*
283 |*                SwTxtFld::SwTxtFld()
284 |*
285 |*    Beschreibung      Attribut fuer automatischen Text, Ctor
286 |*    Ersterstellung    BP 30.04.92
287 |*    Letzte Aenderung	JP 15.08.94
288 |*
289 *************************************************************************/
290 
291 SwTxtFld::SwTxtFld(SwFmtFld & rAttr, xub_StrLen const nStartPos)
292     : SwTxtAttr( rAttr, nStartPos )
293     , m_aExpand( rAttr.GetFld()->ExpandField(true) )
294     , m_pTxtNode( 0 )
295 {
296     rAttr.pTxtAttr = this;
297     SetHasDummyChar(true);
298 }
299 
300 SwTxtFld::~SwTxtFld( )
301 {
302     SwFmtFld & rFmtFld( static_cast<SwFmtFld &>(GetAttr()) );
303     if (this == rFmtFld.pTxtAttr)
304     {
305         rFmtFld.pTxtAttr = 0; // #i110140# invalidate!
306     }
307 }
308 
309 /*************************************************************************
310 |*
311 |*                SwTxtFld::Expand()
312 |*
313 |*    Beschreibung      exandiert das Feld und tauscht den Text im Node
314 |*    Ersterstellung    BP 30.04.92
315 |*    Letzte Aenderung	JP 15.08.94
316 |*
317 *************************************************************************/
318 
319 void SwTxtFld::Expand() const
320 {
321 	// Wenn das expandierte Feld sich nicht veraendert hat, wird returnt
322     ASSERT( m_pTxtNode, "SwTxtFld: where is my TxtNode?" );
323 
324 	const SwField* pFld = GetFld().GetFld();
325     XubString aNewExpand(
326         pFld->ExpandField(m_pTxtNode->GetDoc()->IsClipBoard()) );
327 
328     if( aNewExpand == m_aExpand )
329 	{
330 		// Bei Seitennummernfeldern
331 		const sal_uInt16 nWhich = pFld->GetTyp()->Which();
332 		if( RES_CHAPTERFLD != nWhich && RES_PAGENUMBERFLD != nWhich &&
333 			RES_REFPAGEGETFLD != nWhich &&
334             // --> FME 2005-05-23 #122919# Page count fields to not use aExpand
335             // during formatting, therefore an invalidation of the text frame
336             // has to be triggered even if aNewExpand == aExpand:
337             ( RES_DOCSTATFLD != nWhich || DS_PAGE != static_cast<const SwDocStatField*>(pFld)->GetSubType() ) &&
338             // <--
339             ( RES_GETEXPFLD != nWhich || ((SwGetExpField*)pFld)->IsInBodyTxt() ) )
340 		{
341 			// BP: das muesste man noch optimieren!
342 			//JP 12.06.97: stimmt, man sollte auf jedenfall eine Status-
343 			//				aenderung an die Frames posten
344             if( m_pTxtNode->CalcHiddenParaField() )
345             {
346                 m_pTxtNode->ModifyNotification( 0, 0 );
347             }
348 			return;
349 		}
350 	}
351 
352     m_aExpand = aNewExpand;
353 
354     // 0, this for formatting
355     m_pTxtNode->ModifyNotification( 0, const_cast<SwFmtFld*>( &GetFld() ) );
356 }
357 
358 /*************************************************************************
359  *                      SwTxtFld::CopyFld()
360  *************************************************************************/
361 
362 void SwTxtFld::CopyFld( SwTxtFld *pDest ) const
363 {
364     ASSERT( m_pTxtNode, "SwTxtFld: where is my TxtNode?" );
365     ASSERT( pDest->m_pTxtNode, "SwTxtFld: where is pDest's TxtNode?" );
366 
367     IDocumentFieldsAccess* pIDFA = m_pTxtNode->getIDocumentFieldsAccess();
368     IDocumentFieldsAccess* pDestIDFA = pDest->m_pTxtNode->getIDocumentFieldsAccess();
369 
370 	SwFmtFld& rFmtFld = (SwFmtFld&)pDest->GetFld();
371 	const sal_uInt16 nFldWhich = rFmtFld.GetFld()->GetTyp()->Which();
372 
373     if( pIDFA != pDestIDFA )
374 	{
375 		// Die Hints stehen in unterschiedlichen Dokumenten,
376 		// der Feldtyp muss im neuen Dokument angemeldet werden.
377 		// Z.B: Kopieren ins ClipBoard.
378 		SwFieldType* pFldType;
379 		if( nFldWhich != RES_DBFLD && nFldWhich != RES_USERFLD &&
380 			nFldWhich != RES_SETEXPFLD && nFldWhich != RES_DDEFLD &&
381 			RES_AUTHORITY != nFldWhich )
382             pFldType = pDestIDFA->GetSysFldType( nFldWhich );
383 		else
384             pFldType = pDestIDFA->InsertFldType( *rFmtFld.GetFld()->GetTyp() );
385 
386 		// Sonderbehandlung fuer DDE-Felder
387 		if( RES_DDEFLD == nFldWhich )
388 		{
389 			if( rFmtFld.GetTxtFld() )
390 				((SwDDEFieldType*)rFmtFld.GetFld()->GetTyp())->DecRefCnt();
391 			((SwDDEFieldType*)pFldType)->IncRefCnt();
392 		}
393 
394 		ASSERT( pFldType, "unbekannter FieldType" );
395 		pFldType->Add( &rFmtFld );          // ummelden
396 		rFmtFld.GetFld()->ChgTyp( pFldType );
397 	}
398 
399 	// Expressionfelder Updaten
400 	if( nFldWhich == RES_SETEXPFLD || nFldWhich == RES_GETEXPFLD ||
401 		nFldWhich == RES_HIDDENTXTFLD )
402 	{
403 		SwTxtFld* pFld = (SwTxtFld*)this;
404         pDestIDFA->UpdateExpFlds( pFld, true );
405 	}
406 	// Tabellenfelder auf externe Darstellung
407 	else if( RES_TABLEFLD == nFldWhich &&
408 		((SwTblField*)rFmtFld.GetFld())->IsIntrnlName() )
409 	{
410 		// erzeuge aus der internen (fuer CORE) die externe (fuer UI) Formel
411         const SwTableNode* pTblNd = m_pTxtNode->FindTableNode();
412 		if( pTblNd )		// steht in einer Tabelle
413 			((SwTblField*)rFmtFld.GetFld())->PtrToBoxNm( &pTblNd->GetTable() );
414 	}
415 }
416 
417 /* -----------------26.06.2003 13:54-----------------
418 
419  --------------------------------------------------*/
420 void SwTxtFld::NotifyContentChange(SwFmtFld& rFmtFld)
421 {
422     //if not in undo section notify the change
423     if (m_pTxtNode && m_pTxtNode->GetNodes().IsDocNodes())
424     {
425         m_pTxtNode->ModifyNotification(0, &rFmtFld);
426     }
427 }
428 
429 
430