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