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