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