xref: /trunk/main/sw/source/core/fields/ddefld.cxx (revision 2f121198)
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