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