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