xref: /aoo41x/main/sw/source/core/fields/ddefld.cxx (revision efeef26f)
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:
SwIntrnlRefLink(SwDDEFieldType & rType,sal_uInt16 nUpdateType,sal_uInt16 nFmt)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 
DataChanged(const String & rMimeType,const uno::Any & rValue)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 
Closed()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 
GetAnchor() const179 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 
IsInRange(sal_uLong nSttNd,sal_uLong nEndNd,xub_StrLen nStt,xub_StrLen nEnd) const205 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 
SwDDEFieldType(const String & rName,const String & rCmd,sal_uInt16 nUpdateType)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 
~SwDDEFieldType()254 SwDDEFieldType::~SwDDEFieldType()
255 {
256 	if( pDoc && !pDoc->IsInDtor() )
257 		pDoc->GetLinkManager().Remove( refLink );
258 	refLink->Disconnect();
259 }
260 
Copy() const261 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 
GetName() const271 const String& SwDDEFieldType::GetName() const
272 {
273 	return aName;
274 }
275 
SetCmd(const String & rStr)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 
GetCmd() const285 String SwDDEFieldType::GetCmd() const
286 {
287 	return refLink->GetLinkSourceName();
288 }
289 
SetDoc(SwDoc * pNewDoc)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 
_RefCntChgd()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  ---------------------------------------------------------------------------*/
QueryValue(uno::Any & rVal,sal_uInt16 nWhichId) const328 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  ---------------------------------------------------------------------------*/
PutValue(const uno::Any & rVal,sal_uInt16 nWhichId)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  ---------------------------------------------------------------------------*/
SwDDEField(SwDDEFieldType * pInitType)391 SwDDEField::SwDDEField( SwDDEFieldType* pInitType )
392 	: SwField(pInitType)
393 {
394 }
395 
~SwDDEField()396 SwDDEField::~SwDDEField()
397 {
398 	if( GetTyp()->IsLastDepend() )
399 		((SwDDEFieldType*)GetTyp())->Disconnect();
400 }
401 
Expand() const402 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 
Copy() const417 SwField* SwDDEField::Copy() const
418 {
419 	return new SwDDEField((SwDDEFieldType*)GetTyp());
420 }
421 
422 /*--------------------------------------------------------------------
423 	Beschreibung: Parameter des Typen erfragen
424 				  Name
425  --------------------------------------------------------------------*/
GetPar1() const426 const String& SwDDEField::GetPar1() const
427 {
428 	return ((SwDDEFieldType*)GetTyp())->GetName();
429 }
430 
431 /*--------------------------------------------------------------------
432 	Beschreibung: Parameter des Typen erfragen
433 				  Commando
434  --------------------------------------------------------------------*/
GetPar2() const435 String SwDDEField::GetPar2() const
436 {
437 	return ((SwDDEFieldType*)GetTyp())->GetCmd();
438 }
439 
SetPar2(const String & rStr)440 void SwDDEField::SetPar2(const String& rStr)
441 {
442 	((SwDDEFieldType*)GetTyp())->SetCmd(rStr);
443 }
444 
445