diff options
Diffstat (limited to 'sw/source/core/fields/ddefld.cxx')
-rw-r--r-- | sw/source/core/fields/ddefld.cxx | 443 |
1 files changed, 443 insertions, 0 deletions
diff --git a/sw/source/core/fields/ddefld.cxx b/sw/source/core/fields/ddefld.cxx new file mode 100644 index 000000000000..4c6e08187c75 --- /dev/null +++ b/sw/source/core/fields/ddefld.cxx @@ -0,0 +1,443 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" + + +#include <sfx2/linkmgr.hxx> +#include <doc.hxx> +#include <editsh.hxx> +#include <ndtxt.hxx> +#include <fmtfld.hxx> +#include <txtfld.hxx> +#include <ddefld.hxx> +#include <swtable.hxx> +#include <swbaslnk.hxx> +#include <swddetbl.hxx> +#include <unofldmid.h> +#include <hints.hxx> + +using rtl::OUString; +using namespace ::com::sun::star; + +#define DDE_TXT_ENCODING gsl_getSystemTextEncoding() + +/*-------------------------------------------------------------------- + Beschreibung: Globale Variablen + --------------------------------------------------------------------*/ + +class SwIntrnlRefLink : public SwBaseLink +{ + SwDDEFieldType& rFldType; +public: + SwIntrnlRefLink( SwDDEFieldType& rType, sal_uInt16 nUpdateType, sal_uInt16 nFmt ) + : SwBaseLink( nUpdateType, nFmt ), + rFldType( rType ) + {} + + virtual void Closed(); + virtual void DataChanged( const String& rMimeType, + const uno::Any & rValue ); + + virtual const SwNode* GetAnchor() const; + virtual sal_Bool IsInRange( sal_uLong nSttNd, sal_uLong nEndNd, xub_StrLen nStt = 0, + xub_StrLen nEnd = STRING_NOTFOUND ) const; +}; + + +void SwIntrnlRefLink::DataChanged( const String& rMimeType, + const uno::Any & rValue ) +{ + switch( SotExchange::GetFormatIdFromMimeType( rMimeType ) ) + { + case FORMAT_STRING: + if( !IsNoDataFlag() ) + { + uno::Sequence< sal_Int8 > aSeq; + rValue >>= aSeq; + String sStr( (sal_Char*)aSeq.getConstArray(), static_cast<xub_StrLen>(aSeq.getLength()), + DDE_TXT_ENCODING ); + + // CR-LF am Ende entfernen, ist ueberfluessig! + xub_StrLen n = sStr.Len(); + while( n && 0 == sStr.GetChar( n-1 ) ) + --n; + if( n && 0x0a == sStr.GetChar( n-1 ) ) + --n; + if( n && 0x0d == sStr.GetChar( n-1 ) ) + --n; + + sal_Bool bDel = n != sStr.Len(); + if( bDel ) + sStr.Erase( n ); + + rFldType.SetExpansion( sStr ); + // erst Expansion setzen! (sonst wird das Flag geloescht!) + rFldType.SetCRLFDelFlag( bDel ); + } + break; + + // weitere Formate ... + default: + return; + } + + OSL_ENSURE( rFldType.GetDoc(), "Kein pDoc" ); + + // keine Abhaengigen mehr? + if( rFldType.GetDepends() && !rFldType.IsModifyLocked() && !ChkNoDataFlag() ) + { + ViewShell* pSh; + SwEditShell* pESh = rFldType.GetDoc()->GetEditShell( &pSh ); + + // dann suchen wir uns mal alle Felder. Wird kein gueltiges + // gefunden, dann Disconnecten wir uns! + SwMsgPoolItem aUpdateDDE( RES_UPDATEDDETBL ); + int bCallModify = sal_False; + rFldType.LockModify(); + + SwClientIter aIter( rFldType ); // TODO + SwClient * pLast = aIter.GoStart(); + if( pLast ) // konnte zum Anfang gesprungen werden ?? + do { + // eine DDE-Tabelle oder ein DDE-FeldAttribut im Text + if( !pLast->IsA( TYPE( SwFmtFld ) ) || + ((SwFmtFld*)pLast)->GetTxtFld() ) + { + if( !bCallModify ) + { + if( pESh ) + pESh->StartAllAction(); + else if( pSh ) + pSh->StartAction(); + } + pLast->ModifyNotification( 0, &aUpdateDDE ); + bCallModify = sal_True; + } + } while( 0 != ( pLast = aIter++ )); + + rFldType.UnlockModify(); + + if( bCallModify ) + { + if( pESh ) + pESh->EndAllAction(); + else if( pSh ) + pSh->EndAction(); + + if( pSh ) + pSh->GetDoc()->SetModified(); + } + } +} + +void SwIntrnlRefLink::Closed() +{ + if( rFldType.GetDoc() && !rFldType.GetDoc()->IsInDtor() ) + { + // Advise verabschiedet sich, alle Felder in Text umwandeln ? + ViewShell* pSh; + SwEditShell* pESh = rFldType.GetDoc()->GetEditShell( &pSh ); + if( pESh ) + { + pESh->StartAllAction(); + pESh->FieldToText( &rFldType ); + pESh->EndAllAction(); + } + else + { + pSh->StartAction(); + // am Doc aufrufen ?? + pSh->EndAction(); + } + } + SvBaseLink::Closed(); +} + +const SwNode* SwIntrnlRefLink::GetAnchor() const +{ + // hier sollte irgend ein Anchor aus dem normalen Nodes-Array reichen + const SwNode* pNd = 0; + SwClientIter aIter( rFldType ); // TODO + SwClient * pLast = aIter.GoStart(); + if( pLast ) // konnte zum Anfang gesprungen werden ?? + do { + // eine DDE-Tabelle oder ein DDE-FeldAttribut im Text + if( !pLast->IsA( TYPE( SwFmtFld ) )) + { + SwDepend* pDep = (SwDepend*)pLast; + SwDDETable* pDDETbl = (SwDDETable*)pDep->GetToTell(); + pNd = pDDETbl->GetTabSortBoxes()[0]->GetSttNd(); + } + else if( ((SwFmtFld*)pLast)->GetTxtFld() ) + pNd = ((SwFmtFld*)pLast)->GetTxtFld()->GetpTxtNode(); + + if( pNd && &rFldType.GetDoc()->GetNodes() == &pNd->GetNodes() ) + break; + pNd = 0; + } while( 0 != ( pLast = aIter++ )); + + return pNd; +} + +sal_Bool SwIntrnlRefLink::IsInRange( sal_uLong nSttNd, sal_uLong nEndNd, + xub_StrLen nStt, xub_StrLen nEnd ) const +{ + // hier sollte irgend ein Anchor aus dem normalen Nodes-Array reichen + SwNodes* pNds = &rFldType.GetDoc()->GetNodes(); + SwClientIter aIter( rFldType ); // TODO + SwClient * pLast = aIter.GoStart(); + if( pLast ) // konnte zum Anfang gesprungen werden ?? + do { + // eine DDE-Tabelle oder ein DDE-FeldAttribut im Text + if( !pLast->IsA( TYPE( SwFmtFld ) )) + { + SwDepend* pDep = (SwDepend*)pLast; + SwDDETable* pDDETbl = (SwDDETable*)pDep->GetToTell(); + const SwTableNode* pTblNd = pDDETbl->GetTabSortBoxes()[0]-> + GetSttNd()->FindTableNode(); + if( pTblNd->GetNodes().IsDocNodes() && + nSttNd < pTblNd->EndOfSectionIndex() && + nEndNd > pTblNd->GetIndex() ) + return sal_True; + } + else if( ((SwFmtFld*)pLast)->GetTxtFld() ) + { + const SwTxtFld* pTFld = ((SwFmtFld*)pLast)->GetTxtFld(); + const SwTxtNode* pNd = pTFld->GetpTxtNode(); + if( pNd && pNds == &pNd->GetNodes() ) + { + sal_uLong nNdPos = pNd->GetIndex(); + if( nSttNd <= nNdPos && nNdPos <= nEndNd && + ( nNdPos != nSttNd || *pTFld->GetStart() >= nStt ) && + ( nNdPos != nEndNd || *pTFld->GetStart() < nEnd )) + return sal_True; + } + } + } while( 0 != ( pLast = aIter++ )); + + return sal_False; +} + +SwDDEFieldType::SwDDEFieldType(const String& rName, + const String& rCmd, sal_uInt16 nUpdateType ) + : SwFieldType( RES_DDEFLD ), + aName( rName ), pDoc( 0 ), nRefCnt( 0 ) +{ + bCRLFFlag = bDeleted = sal_False; + refLink = new SwIntrnlRefLink( *this, nUpdateType, FORMAT_STRING ); + SetCmd( rCmd ); +} + +SwDDEFieldType::~SwDDEFieldType() +{ + if( pDoc && !pDoc->IsInDtor() ) + pDoc->GetLinkManager().Remove( refLink ); + refLink->Disconnect(); +} + +SwFieldType* SwDDEFieldType::Copy() const +{ + SwDDEFieldType* pType = new SwDDEFieldType( aName, GetCmd(), GetType() ); + pType->aExpansion = aExpansion; + pType->bCRLFFlag = bCRLFFlag; + pType->bDeleted = bDeleted; + pType->SetDoc( pDoc ); + return pType; +} + +const String& SwDDEFieldType::GetName() const +{ + return aName; +} + +void SwDDEFieldType::SetCmd( const String& rStr ) +{ + String sCmd( rStr ); + xub_StrLen nPos; + while( STRING_NOTFOUND != (nPos = sCmd.SearchAscii( " " )) ) + sCmd.Erase( nPos, 1 ); + refLink->SetLinkSourceName( sCmd ); +} + +String SwDDEFieldType::GetCmd() const +{ + return refLink->GetLinkSourceName(); +} + +void SwDDEFieldType::SetDoc( SwDoc* pNewDoc ) +{ + if( pNewDoc == pDoc ) + return; + + if( pDoc && refLink.Is() ) + { + OSL_ENSURE( !nRefCnt, "wie kommen die Referenzen rueber?" ); + pDoc->GetLinkManager().Remove( refLink ); + } + + pDoc = pNewDoc; + if( pDoc && nRefCnt ) + { + refLink->SetVisible( pDoc->IsVisibleLinks() ); + pDoc->GetLinkManager().InsertDDELink( refLink ); + } +} + + +void SwDDEFieldType::_RefCntChgd() +{ + if( nRefCnt ) + { + refLink->SetVisible( pDoc->IsVisibleLinks() ); + pDoc->GetLinkManager().InsertDDELink( refLink ); + if( pDoc->GetCurrentViewShell() ) //swmod 071108//swmod 071225 + UpdateNow(); + } + else + { + Disconnect(); + pDoc->GetLinkManager().Remove( refLink ); + } +} + +bool SwDDEFieldType::QueryValue( uno::Any& rVal, sal_uInt16 nWhichId ) const +{ + sal_uInt8 nPart = 0; + switch( nWhichId ) + { + case FIELD_PROP_PAR2: nPart = 3; break; + case FIELD_PROP_PAR4: nPart = 2; break; + case FIELD_PROP_SUBTYPE: nPart = 1; break; + case FIELD_PROP_BOOL1: + { + sal_Bool bSet = GetType() == sfx2::LINKUPDATE_ALWAYS ? sal_True : sal_False; + rVal.setValue(&bSet, ::getBooleanCppuType()); + } + break; + case FIELD_PROP_PAR5: + rVal <<= ::rtl::OUString(aExpansion); + break; + default: + OSL_FAIL("illegal property"); + } + if( nPart ) + rVal <<= OUString(GetCmd().GetToken(nPart-1, sfx2::cTokenSeperator)); + return true; +} + +bool SwDDEFieldType::PutValue( const uno::Any& rVal, sal_uInt16 nWhichId ) +{ + sal_uInt8 nPart = 0; + switch( nWhichId ) + { + case FIELD_PROP_PAR2: nPart = 3; break; + case FIELD_PROP_PAR4: nPart = 2; break; + case FIELD_PROP_SUBTYPE: nPart = 1; break; + case FIELD_PROP_BOOL1: + SetType( static_cast<sal_uInt16>(*(sal_Bool*)rVal.getValue() ? + sfx2::LINKUPDATE_ALWAYS : + sfx2::LINKUPDATE_ONCALL ) ); + break; + case FIELD_PROP_PAR5: + { + ::rtl::OUString sTemp; + rVal >>= sTemp; + aExpansion = sTemp; + } + break; + default: + OSL_FAIL("illegal property"); + } + if( nPart ) + { + String sTmp, sCmd( GetCmd() ); + while(3 > sCmd.GetTokenCount(sfx2::cTokenSeperator)) + sCmd += sfx2::cTokenSeperator; + sCmd.SetToken( nPart-1, sfx2::cTokenSeperator, ::GetString( rVal, sTmp ) ); + SetCmd( sCmd ); + } + return true; +} + +SwDDEField::SwDDEField( SwDDEFieldType* pInitType ) + : SwField(pInitType) +{ +} + +SwDDEField::~SwDDEField() +{ + if( GetTyp()->IsLastDepend() ) + ((SwDDEFieldType*)GetTyp())->Disconnect(); +} + +String SwDDEField::Expand() const +{ + xub_StrLen nPos; + String aStr( ((SwDDEFieldType*)GetTyp())->GetExpansion() ); + + aStr.EraseAllChars( '\r' ); + while( (nPos = aStr.Search( '\t' )) != STRING_NOTFOUND ) + aStr.SetChar( nPos, ' ' ); + while( (nPos = aStr.Search( '\n' )) != STRING_NOTFOUND ) + aStr.SetChar( nPos, '|' ); + if( aStr.Len() && ( aStr.GetChar( aStr.Len()-1 ) == '|') ) + aStr.Erase( aStr.Len()-1, 1 ); + return aStr; +} + +SwField* SwDDEField::Copy() const +{ + return new SwDDEField((SwDDEFieldType*)GetTyp()); +} + +/*-------------------------------------------------------------------- + Beschreibung: Parameter des Typen erfragen + Name + --------------------------------------------------------------------*/ +const String& SwDDEField::GetPar1() const +{ + return ((SwDDEFieldType*)GetTyp())->GetName(); +} + +/*-------------------------------------------------------------------- + Beschreibung: Parameter des Typen erfragen + Commando + --------------------------------------------------------------------*/ +String SwDDEField::GetPar2() const +{ + return ((SwDDEFieldType*)GetTyp())->GetCmd(); +} + +void SwDDEField::SetPar2(const String& rStr) +{ + ((SwDDEFieldType*)GetTyp())->SetCmd(rStr); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |