xref: /AOO41X/main/sw/source/core/txtnode/atrfld.cxx (revision 707fc0d4d52eb4f69d89a98ffec6918ca5de6326)
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