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