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