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