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 28 #include <sfx2/linkmgr.hxx> 29 #include <doc.hxx> 30 #include <editsh.hxx> 31 #include <errhdl.hxx> 32 #include <ndtxt.hxx> 33 #include <fmtfld.hxx> 34 #include <txtfld.hxx> 35 #include <ddefld.hxx> 36 #include <swtable.hxx> 37 #include <swbaslnk.hxx> 38 #include <swddetbl.hxx> 39 #include <unofldmid.h> 40 #include <hints.hxx> 41 42 using rtl::OUString; 43 using namespace ::com::sun::star; 44 45 #define DDE_TXT_ENCODING gsl_getSystemTextEncoding() 46 47 /*-------------------------------------------------------------------- 48 Beschreibung: Globale Variablen 49 --------------------------------------------------------------------*/ 50 51 class SwIntrnlRefLink : public SwBaseLink 52 { 53 SwDDEFieldType& rFldType; 54 public: 55 SwIntrnlRefLink( SwDDEFieldType& rType, sal_uInt16 nUpdateType, sal_uInt16 nFmt ) 56 : SwBaseLink( nUpdateType, nFmt ), 57 rFldType( rType ) 58 {} 59 60 virtual void Closed(); 61 virtual void DataChanged( const String& rMimeType, 62 const uno::Any & rValue ); 63 64 virtual const SwNode* GetAnchor() const; 65 virtual sal_Bool IsInRange( sal_uLong nSttNd, sal_uLong nEndNd, xub_StrLen nStt = 0, 66 xub_StrLen nEnd = STRING_NOTFOUND ) const; 67 }; 68 69 70 void SwIntrnlRefLink::DataChanged( const String& rMimeType, 71 const uno::Any & rValue ) 72 { 73 switch( SotExchange::GetFormatIdFromMimeType( rMimeType ) ) 74 { 75 case FORMAT_STRING: 76 if( !IsNoDataFlag() ) 77 { 78 uno::Sequence< sal_Int8 > aSeq; 79 rValue >>= aSeq; 80 String sStr( (sal_Char*)aSeq.getConstArray(), static_cast<xub_StrLen>(aSeq.getLength()), 81 DDE_TXT_ENCODING ); 82 83 // CR-LF am Ende entfernen, ist ueberfluessig! 84 xub_StrLen n = sStr.Len(); 85 while( n && 0 == sStr.GetChar( n-1 ) ) 86 --n; 87 if( n && 0x0a == sStr.GetChar( n-1 ) ) 88 --n; 89 if( n && 0x0d == sStr.GetChar( n-1 ) ) 90 --n; 91 92 sal_Bool bDel = n != sStr.Len(); 93 if( bDel ) 94 sStr.Erase( n ); 95 96 rFldType.SetExpansion( sStr ); 97 // erst Expansion setzen! (sonst wird das Flag geloescht!) 98 rFldType.SetCRLFDelFlag( bDel ); 99 } 100 break; 101 102 // weitere Formate ... 103 default: 104 return; 105 } 106 107 ASSERT( rFldType.GetDoc(), "Kein pDoc" ); 108 109 // keine Abhaengigen mehr? 110 if( rFldType.GetDepends() && !rFldType.IsModifyLocked() && !ChkNoDataFlag() ) 111 { 112 ViewShell* pSh; 113 SwEditShell* pESh = rFldType.GetDoc()->GetEditShell( &pSh ); 114 115 // dann suchen wir uns mal alle Felder. Wird kein gueltiges 116 // gefunden, dann Disconnecten wir uns! 117 SwMsgPoolItem aUpdateDDE( RES_UPDATEDDETBL ); 118 int bCallModify = sal_False; 119 rFldType.LockModify(); 120 121 SwClientIter aIter( rFldType ); // TODO 122 SwClient * pLast = aIter.GoStart(); 123 if( pLast ) // konnte zum Anfang gesprungen werden ?? 124 do { 125 // eine DDE-Tabelle oder ein DDE-FeldAttribut im Text 126 if( !pLast->IsA( TYPE( SwFmtFld ) ) || 127 ((SwFmtFld*)pLast)->GetTxtFld() ) 128 { 129 if( !bCallModify ) 130 { 131 if( pESh ) 132 pESh->StartAllAction(); 133 else if( pSh ) 134 pSh->StartAction(); 135 } 136 pLast->ModifyNotification( 0, &aUpdateDDE ); 137 bCallModify = sal_True; 138 } 139 } while( 0 != ( pLast = ++aIter )); 140 141 rFldType.UnlockModify(); 142 143 if( bCallModify ) 144 { 145 if( pESh ) 146 pESh->EndAllAction(); 147 else if( pSh ) 148 pSh->EndAction(); 149 150 if( pSh ) 151 pSh->GetDoc()->SetModified(); 152 } 153 } 154 } 155 156 void SwIntrnlRefLink::Closed() 157 { 158 if( rFldType.GetDoc() && !rFldType.GetDoc()->IsInDtor() ) 159 { 160 // Advise verabschiedet sich, alle Felder in Text umwandeln ? 161 ViewShell* pSh; 162 SwEditShell* pESh = rFldType.GetDoc()->GetEditShell( &pSh ); 163 if( pESh ) 164 { 165 pESh->StartAllAction(); 166 pESh->FieldToText( &rFldType ); 167 pESh->EndAllAction(); 168 } 169 else 170 { 171 pSh->StartAction(); 172 // am Doc aufrufen ?? 173 pSh->EndAction(); 174 } 175 } 176 SvBaseLink::Closed(); 177 } 178 179 const SwNode* SwIntrnlRefLink::GetAnchor() const 180 { 181 // hier sollte irgend ein Anchor aus dem normalen Nodes-Array reichen 182 const SwNode* pNd = 0; 183 SwClientIter aIter( rFldType ); // TODO 184 SwClient * pLast = aIter.GoStart(); 185 if( pLast ) // konnte zum Anfang gesprungen werden ?? 186 do { 187 // eine DDE-Tabelle oder ein DDE-FeldAttribut im Text 188 if( !pLast->IsA( TYPE( SwFmtFld ) )) 189 { 190 SwDepend* pDep = (SwDepend*)pLast; 191 SwDDETable* pDDETbl = (SwDDETable*)pDep->GetToTell(); 192 pNd = pDDETbl->GetTabSortBoxes()[0]->GetSttNd(); 193 } 194 else if( ((SwFmtFld*)pLast)->GetTxtFld() ) 195 pNd = ((SwFmtFld*)pLast)->GetTxtFld()->GetpTxtNode(); 196 197 if( pNd && &rFldType.GetDoc()->GetNodes() == &pNd->GetNodes() ) 198 break; 199 pNd = 0; 200 } while( 0 != ( pLast = ++aIter )); 201 202 return pNd; 203 } 204 205 sal_Bool SwIntrnlRefLink::IsInRange( sal_uLong nSttNd, sal_uLong nEndNd, 206 xub_StrLen nStt, xub_StrLen nEnd ) const 207 { 208 // hier sollte irgend ein Anchor aus dem normalen Nodes-Array reichen 209 SwNodes* pNds = &rFldType.GetDoc()->GetNodes(); 210 SwClientIter aIter( rFldType ); // TODO 211 SwClient * pLast = aIter.GoStart(); 212 if( pLast ) // konnte zum Anfang gesprungen werden ?? 213 do { 214 // eine DDE-Tabelle oder ein DDE-FeldAttribut im Text 215 if( !pLast->IsA( TYPE( SwFmtFld ) )) 216 { 217 SwDepend* pDep = (SwDepend*)pLast; 218 SwDDETable* pDDETbl = (SwDDETable*)pDep->GetToTell(); 219 const SwTableNode* pTblNd = pDDETbl->GetTabSortBoxes()[0]-> 220 GetSttNd()->FindTableNode(); 221 if( pTblNd->GetNodes().IsDocNodes() && 222 nSttNd < pTblNd->EndOfSectionIndex() && 223 nEndNd > pTblNd->GetIndex() ) 224 return sal_True; 225 } 226 else if( ((SwFmtFld*)pLast)->GetTxtFld() ) 227 { 228 const SwTxtFld* pTFld = ((SwFmtFld*)pLast)->GetTxtFld(); 229 const SwTxtNode* pNd = pTFld->GetpTxtNode(); 230 if( pNd && pNds == &pNd->GetNodes() ) 231 { 232 sal_uLong nNdPos = pNd->GetIndex(); 233 if( nSttNd <= nNdPos && nNdPos <= nEndNd && 234 ( nNdPos != nSttNd || *pTFld->GetStart() >= nStt ) && 235 ( nNdPos != nEndNd || *pTFld->GetStart() < nEnd )) 236 return sal_True; 237 } 238 } 239 } while( 0 != ( pLast = ++aIter )); 240 241 return sal_False; 242 } 243 244 SwDDEFieldType::SwDDEFieldType(const String& rName, 245 const String& rCmd, sal_uInt16 nUpdateType ) 246 : SwFieldType( RES_DDEFLD ), 247 aName( rName ), pDoc( 0 ), nRefCnt( 0 ) 248 { 249 bCRLFFlag = bDeleted = sal_False; 250 refLink = new SwIntrnlRefLink( *this, nUpdateType, FORMAT_STRING ); 251 SetCmd( rCmd ); 252 } 253 254 SwDDEFieldType::~SwDDEFieldType() 255 { 256 if( pDoc && !pDoc->IsInDtor() ) 257 pDoc->GetLinkManager().Remove( refLink ); 258 refLink->Disconnect(); 259 } 260 261 SwFieldType* SwDDEFieldType::Copy() const 262 { 263 SwDDEFieldType* pType = new SwDDEFieldType( aName, GetCmd(), GetType() ); 264 pType->aExpansion = aExpansion; 265 pType->bCRLFFlag = bCRLFFlag; 266 pType->bDeleted = bDeleted; 267 pType->SetDoc( pDoc ); 268 return pType; 269 } 270 271 const String& SwDDEFieldType::GetName() const 272 { 273 return aName; 274 } 275 276 void SwDDEFieldType::SetCmd( const String& rStr ) 277 { 278 String sCmd( rStr ); 279 xub_StrLen nPos; 280 while( STRING_NOTFOUND != (nPos = sCmd.SearchAscii( " " )) ) 281 sCmd.Erase( nPos, 1 ); 282 refLink->SetLinkSourceName( sCmd ); 283 } 284 285 String SwDDEFieldType::GetCmd() const 286 { 287 return refLink->GetLinkSourceName(); 288 } 289 290 void SwDDEFieldType::SetDoc( SwDoc* pNewDoc ) 291 { 292 if( pNewDoc == pDoc ) 293 return; 294 295 if( pDoc && refLink.Is() ) 296 { 297 ASSERT( !nRefCnt, "wie kommen die Referenzen rueber?" ); 298 pDoc->GetLinkManager().Remove( refLink ); 299 } 300 301 pDoc = pNewDoc; 302 if( pDoc && nRefCnt ) 303 { 304 refLink->SetVisible( pDoc->IsVisibleLinks() ); 305 pDoc->GetLinkManager().InsertDDELink( refLink ); 306 } 307 } 308 309 310 void SwDDEFieldType::_RefCntChgd() 311 { 312 if( nRefCnt ) 313 { 314 refLink->SetVisible( pDoc->IsVisibleLinks() ); 315 pDoc->GetLinkManager().InsertDDELink( refLink ); 316 if( pDoc->GetCurrentViewShell() ) //swmod 071108//swmod 071225 317 UpdateNow(); 318 } 319 else 320 { 321 Disconnect(); 322 pDoc->GetLinkManager().Remove( refLink ); 323 } 324 } 325 /* -----------------------------28.08.00 16:23-------------------------------- 326 327 ---------------------------------------------------------------------------*/ 328 sal_Bool SwDDEFieldType::QueryValue( uno::Any& rVal, sal_uInt16 nWhichId ) const 329 { 330 sal_uInt8 nPart = 0; 331 switch( nWhichId ) 332 { 333 case FIELD_PROP_PAR2: nPart = 3; break; 334 case FIELD_PROP_PAR4: nPart = 2; break; 335 case FIELD_PROP_SUBTYPE: nPart = 1; break; 336 case FIELD_PROP_BOOL1: 337 { 338 sal_Bool bSet = GetType() == sfx2::LINKUPDATE_ALWAYS ? sal_True : sal_False; 339 rVal.setValue(&bSet, ::getBooleanCppuType()); 340 } 341 break; 342 case FIELD_PROP_PAR5: 343 rVal <<= ::rtl::OUString(aExpansion); 344 break; 345 default: 346 DBG_ERROR("illegal property"); 347 } 348 if( nPart ) 349 rVal <<= OUString(GetCmd().GetToken(nPart-1, sfx2::cTokenSeperator)); 350 return sal_True; 351 } 352 /* -----------------------------28.08.00 16:23-------------------------------- 353 354 ---------------------------------------------------------------------------*/ 355 sal_Bool SwDDEFieldType::PutValue( const uno::Any& rVal, sal_uInt16 nWhichId ) 356 { 357 sal_uInt8 nPart = 0; 358 switch( nWhichId ) 359 { 360 case FIELD_PROP_PAR2: nPart = 3; break; 361 case FIELD_PROP_PAR4: nPart = 2; break; 362 case FIELD_PROP_SUBTYPE: nPart = 1; break; 363 case FIELD_PROP_BOOL1: 364 SetType( static_cast<sal_uInt16>(*(sal_Bool*)rVal.getValue() ? 365 sfx2::LINKUPDATE_ALWAYS : 366 sfx2::LINKUPDATE_ONCALL ) ); 367 break; 368 case FIELD_PROP_PAR5: 369 { 370 ::rtl::OUString sTemp; 371 rVal >>= sTemp; 372 aExpansion = sTemp; 373 } 374 break; 375 default: 376 DBG_ERROR("illegal property"); 377 } 378 if( nPart ) 379 { 380 String sTmp, sCmd( GetCmd() ); 381 while(3 > sCmd.GetTokenCount(sfx2::cTokenSeperator)) 382 sCmd += sfx2::cTokenSeperator; 383 sCmd.SetToken( nPart-1, sfx2::cTokenSeperator, ::GetString( rVal, sTmp ) ); 384 SetCmd( sCmd ); 385 } 386 return sal_True; 387 } 388 /* --------------------------------------------------------------------------- 389 390 ---------------------------------------------------------------------------*/ 391 SwDDEField::SwDDEField( SwDDEFieldType* pInitType ) 392 : SwField(pInitType) 393 { 394 } 395 396 SwDDEField::~SwDDEField() 397 { 398 if( GetTyp()->IsLastDepend() ) 399 ((SwDDEFieldType*)GetTyp())->Disconnect(); 400 } 401 402 String SwDDEField::Expand() const 403 { 404 xub_StrLen nPos; 405 String aStr( ((SwDDEFieldType*)GetTyp())->GetExpansion() ); 406 407 aStr.EraseAllChars( '\r' ); 408 while( (nPos = aStr.Search( '\t' )) != STRING_NOTFOUND ) 409 aStr.SetChar( nPos, ' ' ); 410 while( (nPos = aStr.Search( '\n' )) != STRING_NOTFOUND ) 411 aStr.SetChar( nPos, '|' ); 412 if( aStr.Len() && ( aStr.GetChar( aStr.Len()-1 ) == '|') ) 413 aStr.Erase( aStr.Len()-1, 1 ); 414 return aStr; 415 } 416 417 SwField* SwDDEField::Copy() const 418 { 419 return new SwDDEField((SwDDEFieldType*)GetTyp()); 420 } 421 422 /*-------------------------------------------------------------------- 423 Beschreibung: Parameter des Typen erfragen 424 Name 425 --------------------------------------------------------------------*/ 426 const String& SwDDEField::GetPar1() const 427 { 428 return ((SwDDEFieldType*)GetTyp())->GetName(); 429 } 430 431 /*-------------------------------------------------------------------- 432 Beschreibung: Parameter des Typen erfragen 433 Commando 434 --------------------------------------------------------------------*/ 435 String SwDDEField::GetPar2() const 436 { 437 return ((SwDDEFieldType*)GetTyp())->GetCmd(); 438 } 439 440 void SwDDEField::SetPar2(const String& rStr) 441 { 442 ((SwDDEFieldType*)GetTyp())->SetCmd(rStr); 443 } 444 445