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 : #include <osl/thread.h>
21 : #include <sfx2/linkmgr.hxx>
22 : #include <doc.hxx>
23 : #include <IDocumentLinksAdministration.hxx>
24 : #include <IDocumentState.hxx>
25 : #include <IDocumentLayoutAccess.hxx>
26 : #include <editsh.hxx>
27 : #include <ndtxt.hxx>
28 : #include <fmtfld.hxx>
29 : #include <txtfld.hxx>
30 : #include <ddefld.hxx>
31 : #include <swtable.hxx>
32 : #include <swbaslnk.hxx>
33 : #include <swddetbl.hxx>
34 : #include <unofldmid.h>
35 : #include <hints.hxx>
36 :
37 : using namespace ::com::sun::star;
38 :
39 : #define DDE_TXT_ENCODING osl_getThreadTextEncoding()
40 :
41 0 : class SwIntrnlRefLink : public SwBaseLink
42 : {
43 : SwDDEFieldType& rFldType;
44 : public:
45 0 : SwIntrnlRefLink( SwDDEFieldType& rType, sal_uInt16 nUpdateType, sal_uInt16 nFmt )
46 : : SwBaseLink( nUpdateType, nFmt ),
47 0 : rFldType( rType )
48 0 : {}
49 :
50 : virtual void Closed() SAL_OVERRIDE;
51 : virtual ::sfx2::SvBaseLink::UpdateResult DataChanged(
52 : const OUString& rMimeType, const ::com::sun::star::uno::Any & rValue ) SAL_OVERRIDE;
53 :
54 : virtual const SwNode* GetAnchor() const SAL_OVERRIDE;
55 : virtual bool IsInRange( sal_uLong nSttNd, sal_uLong nEndNd, sal_Int32 nStt = 0,
56 : sal_Int32 nEnd = -1 ) const SAL_OVERRIDE;
57 : };
58 :
59 0 : ::sfx2::SvBaseLink::UpdateResult SwIntrnlRefLink::DataChanged( const OUString& rMimeType,
60 : const uno::Any & rValue )
61 : {
62 0 : switch( SotExchange::GetFormatIdFromMimeType( rMimeType ) )
63 : {
64 : case FORMAT_STRING:
65 0 : if( !IsNoDataFlag() )
66 : {
67 0 : uno::Sequence< sal_Int8 > aSeq;
68 0 : rValue >>= aSeq;
69 0 : OUString sStr( (sal_Char*)aSeq.getConstArray(), aSeq.getLength(), DDE_TXT_ENCODING );
70 :
71 : // remove not needed CR-LF at the end
72 0 : sal_Int32 n = sStr.getLength();
73 0 : while( n && 0 == sStr[ n-1 ] )
74 0 : --n;
75 0 : if( n && 0x0a == sStr[ n-1 ] )
76 0 : --n;
77 0 : if( n && 0x0d == sStr[ n-1 ] )
78 0 : --n;
79 :
80 0 : bool bDel = n != sStr.getLength();
81 0 : if( bDel )
82 0 : sStr = sStr.copy( 0, n );
83 :
84 0 : rFldType.SetExpansion( sStr );
85 : // set Expansion first! (otherwise this flag will be deleted)
86 0 : rFldType.SetCRLFDelFlag( bDel );
87 : }
88 0 : break;
89 :
90 : // other formats
91 : default:
92 0 : return SUCCESS;
93 : }
94 :
95 : OSL_ENSURE( rFldType.GetDoc(), "no pDoc" );
96 :
97 : // no dependencies left?
98 0 : if( rFldType.GetDepends() && !rFldType.IsModifyLocked() && !ChkNoDataFlag() )
99 : {
100 0 : SwViewShell* pSh = rFldType.GetDoc()->getIDocumentLayoutAccess().GetCurrentViewShell();
101 0 : SwEditShell* pESh = rFldType.GetDoc()->GetEditShell();
102 :
103 : // Search for fields. If no valid found, disconnect.
104 0 : SwMsgPoolItem aUpdateDDE( RES_UPDATEDDETBL );
105 0 : int bCallModify = sal_False;
106 0 : rFldType.LockModify();
107 :
108 0 : SwClientIter aIter( rFldType ); // TODO
109 0 : SwClient * pLast = aIter.GoStart();
110 0 : if( pLast ) // Could we jump to beginning?
111 0 : do {
112 : // a DDE table or a DDE field attribute in the text
113 0 : if( !pLast->IsA( TYPE( SwFmtFld ) ) ||
114 0 : ((SwFmtFld*)pLast)->GetTxtFld() )
115 : {
116 0 : if( !bCallModify )
117 : {
118 0 : if( pESh )
119 0 : pESh->StartAllAction();
120 0 : else if( pSh )
121 0 : pSh->StartAction();
122 : }
123 0 : pLast->ModifyNotification( 0, &aUpdateDDE );
124 0 : bCallModify = sal_True;
125 : }
126 : } while( 0 != ( pLast = ++aIter ));
127 :
128 0 : rFldType.UnlockModify();
129 :
130 0 : if( bCallModify )
131 : {
132 0 : if( pESh )
133 0 : pESh->EndAllAction();
134 0 : else if( pSh )
135 0 : pSh->EndAction();
136 :
137 0 : if( pSh )
138 0 : pSh->GetDoc()->getIDocumentState().SetModified();
139 0 : }
140 : }
141 :
142 0 : return SUCCESS;
143 : }
144 :
145 0 : void SwIntrnlRefLink::Closed()
146 : {
147 0 : if( rFldType.GetDoc() && !rFldType.GetDoc()->IsInDtor() )
148 : {
149 : // advise goes, convert all fields into text?
150 0 : SwViewShell* pSh = rFldType.GetDoc()->getIDocumentLayoutAccess().GetCurrentViewShell();
151 0 : SwEditShell* pESh = rFldType.GetDoc()->GetEditShell();
152 0 : if( pESh )
153 : {
154 0 : pESh->StartAllAction();
155 0 : pESh->FieldToText( &rFldType );
156 0 : pESh->EndAllAction();
157 : }
158 : else
159 : {
160 0 : pSh->StartAction();
161 : // am Doc aufrufen ??
162 0 : pSh->EndAction();
163 : }
164 : }
165 0 : SvBaseLink::Closed();
166 0 : }
167 :
168 0 : const SwNode* SwIntrnlRefLink::GetAnchor() const
169 : {
170 : // here, any anchor of the normal NodesArray should be sufficient
171 0 : const SwNode* pNd = 0;
172 0 : SwClientIter aIter( rFldType ); // TODO
173 0 : SwClient * pLast = aIter.GoStart();
174 0 : if( pLast ) // Could we jump to beginning?
175 0 : do {
176 : // a DDE table or a DDE field attribute in the text
177 0 : if( !pLast->IsA( TYPE( SwFmtFld ) ))
178 : {
179 0 : SwDepend* pDep = (SwDepend*)pLast;
180 0 : SwDDETable* pDDETbl = (SwDDETable*)pDep->GetToTell();
181 0 : pNd = pDDETbl->GetTabSortBoxes()[0]->GetSttNd();
182 : }
183 0 : else if( ((SwFmtFld*)pLast)->GetTxtFld() )
184 0 : pNd = ((SwFmtFld*)pLast)->GetTxtFld()->GetpTxtNode();
185 :
186 0 : if( pNd && &rFldType.GetDoc()->GetNodes() == &pNd->GetNodes() )
187 0 : break;
188 0 : pNd = 0;
189 : } while( 0 != ( pLast = ++aIter ));
190 :
191 0 : return pNd;
192 : }
193 :
194 0 : bool SwIntrnlRefLink::IsInRange( sal_uLong nSttNd, sal_uLong nEndNd,
195 : sal_Int32 nStt, sal_Int32 nEnd ) const
196 : {
197 : // here, any anchor of the normal NodesArray should be sufficient
198 0 : SwNodes* pNds = &rFldType.GetDoc()->GetNodes();
199 0 : SwClientIter aIter( rFldType ); // TODO
200 0 : SwClient * pLast = aIter.GoStart();
201 0 : if( pLast ) // Could we jump to beginning?
202 0 : do {
203 : // a DDE table or a DDE field attribute in the text
204 0 : if( !pLast->IsA( TYPE( SwFmtFld ) ))
205 : {
206 0 : SwDepend* pDep = (SwDepend*)pLast;
207 0 : SwDDETable* pDDETbl = (SwDDETable*)pDep->GetToTell();
208 0 : const SwTableNode* pTblNd = pDDETbl->GetTabSortBoxes()[0]->
209 0 : GetSttNd()->FindTableNode();
210 0 : if( pTblNd->GetNodes().IsDocNodes() &&
211 0 : nSttNd < pTblNd->EndOfSectionIndex() &&
212 0 : nEndNd > pTblNd->GetIndex() )
213 0 : return true;
214 : }
215 0 : else if( ((SwFmtFld*)pLast)->GetTxtFld() )
216 : {
217 0 : const SwTxtFld* pTFld = ((SwFmtFld*)pLast)->GetTxtFld();
218 0 : const SwTxtNode* pNd = pTFld->GetpTxtNode();
219 0 : if( pNd && pNds == &pNd->GetNodes() )
220 : {
221 0 : sal_uLong nNdPos = pNd->GetIndex();
222 0 : if( nSttNd <= nNdPos && nNdPos <= nEndNd &&
223 0 : ( nNdPos != nSttNd || pTFld->GetStart() >= nStt ) &&
224 0 : ( nNdPos != nEndNd || pTFld->GetStart() < nEnd ))
225 0 : return true;
226 : }
227 : }
228 : } while( 0 != ( pLast = ++aIter ));
229 :
230 0 : return false;
231 : }
232 :
233 0 : SwDDEFieldType::SwDDEFieldType(const OUString& rName,
234 : const OUString& rCmd, sal_uInt16 nUpdateType )
235 : : SwFieldType( RES_DDEFLD ),
236 0 : aName( rName ), pDoc( 0 ), nRefCnt( 0 )
237 : {
238 0 : bCRLFFlag = bDeleted = false;
239 0 : refLink = new SwIntrnlRefLink( *this, nUpdateType, FORMAT_STRING );
240 0 : SetCmd( rCmd );
241 0 : }
242 :
243 0 : SwDDEFieldType::~SwDDEFieldType()
244 : {
245 0 : if( pDoc && !pDoc->IsInDtor() )
246 0 : pDoc->getIDocumentLinksAdministration().GetLinkManager().Remove( refLink );
247 0 : refLink->Disconnect();
248 0 : }
249 :
250 0 : SwFieldType* SwDDEFieldType::Copy() const
251 : {
252 0 : SwDDEFieldType* pType = new SwDDEFieldType( aName, GetCmd(), GetType() );
253 0 : pType->aExpansion = aExpansion;
254 0 : pType->bCRLFFlag = bCRLFFlag;
255 0 : pType->bDeleted = bDeleted;
256 0 : pType->SetDoc( pDoc );
257 0 : return pType;
258 : }
259 :
260 0 : OUString SwDDEFieldType::GetName() const
261 : {
262 0 : return aName;
263 : }
264 :
265 0 : void SwDDEFieldType::SetCmd( const OUString& _aStr )
266 : {
267 0 : OUString aStr = _aStr;
268 0 : sal_Int32 nIndex = 0;
269 0 : do
270 : {
271 0 : aStr = aStr.replaceFirst(" ", " ", &nIndex);
272 0 : } while (nIndex>=0);
273 0 : refLink->SetLinkSourceName( aStr );
274 0 : }
275 :
276 0 : OUString SwDDEFieldType::GetCmd() const
277 : {
278 0 : return refLink->GetLinkSourceName();
279 : }
280 :
281 0 : void SwDDEFieldType::SetDoc( SwDoc* pNewDoc )
282 : {
283 0 : if( pNewDoc == pDoc )
284 0 : return;
285 :
286 0 : if( pDoc && refLink.Is() )
287 : {
288 : OSL_ENSURE( !nRefCnt, "How do we get the references?" );
289 0 : pDoc->getIDocumentLinksAdministration().GetLinkManager().Remove( refLink );
290 : }
291 :
292 0 : pDoc = pNewDoc;
293 0 : if( pDoc && nRefCnt )
294 : {
295 0 : refLink->SetVisible( pDoc->getIDocumentLinksAdministration().IsVisibleLinks() );
296 0 : pDoc->getIDocumentLinksAdministration().GetLinkManager().InsertDDELink( refLink );
297 : }
298 : }
299 :
300 0 : void SwDDEFieldType::_RefCntChgd()
301 : {
302 0 : if( nRefCnt )
303 : {
304 0 : refLink->SetVisible( pDoc->getIDocumentLinksAdministration().IsVisibleLinks() );
305 0 : pDoc->getIDocumentLinksAdministration().GetLinkManager().InsertDDELink( refLink );
306 0 : if( pDoc->getIDocumentLayoutAccess().GetCurrentViewShell() )
307 0 : UpdateNow();
308 : }
309 : else
310 : {
311 0 : Disconnect();
312 0 : pDoc->getIDocumentLinksAdministration().GetLinkManager().Remove( refLink );
313 : }
314 0 : }
315 :
316 0 : bool SwDDEFieldType::QueryValue( uno::Any& rVal, sal_uInt16 nWhichId ) const
317 : {
318 0 : sal_Int32 nPart = -1;
319 0 : switch( nWhichId )
320 : {
321 0 : case FIELD_PROP_PAR2: nPart = 2; break;
322 0 : case FIELD_PROP_PAR4: nPart = 1; break;
323 0 : case FIELD_PROP_SUBTYPE: nPart = 0; break;
324 : case FIELD_PROP_BOOL1:
325 : {
326 0 : sal_Bool bSet = GetType() == sfx2::LINKUPDATE_ALWAYS ? sal_True : sal_False;
327 0 : rVal.setValue(&bSet, ::getBooleanCppuType());
328 : }
329 0 : break;
330 : case FIELD_PROP_PAR5:
331 0 : rVal <<= aExpansion;
332 0 : break;
333 : default:
334 : OSL_FAIL("illegal property");
335 : }
336 0 : if ( nPart>=0 )
337 0 : rVal <<= GetCmd().getToken(nPart, sfx2::cTokenSeparator);
338 0 : return true;
339 : }
340 :
341 0 : bool SwDDEFieldType::PutValue( const uno::Any& rVal, sal_uInt16 nWhichId )
342 : {
343 0 : sal_Int32 nPart = -1;
344 0 : switch( nWhichId )
345 : {
346 0 : case FIELD_PROP_PAR2: nPart = 2; break;
347 0 : case FIELD_PROP_PAR4: nPart = 1; break;
348 0 : case FIELD_PROP_SUBTYPE: nPart = 0; break;
349 : case FIELD_PROP_BOOL1:
350 0 : SetType( static_cast<sal_uInt16>(*(sal_Bool*)rVal.getValue() ?
351 : sfx2::LINKUPDATE_ALWAYS :
352 0 : sfx2::LINKUPDATE_ONCALL ) );
353 0 : break;
354 : case FIELD_PROP_PAR5:
355 0 : rVal >>= aExpansion;
356 0 : break;
357 : default:
358 : OSL_FAIL("illegal property");
359 : }
360 0 : if( nPart>=0 )
361 : {
362 0 : const OUString sOldCmd( GetCmd() );
363 0 : OUString sNewCmd;
364 0 : sal_Int32 nIndex = 0;
365 0 : for (sal_Int32 i=0; i<3; ++i)
366 : {
367 0 : OUString sToken = sOldCmd.getToken(0, sfx2::cTokenSeparator, nIndex);
368 0 : if (i==nPart)
369 : {
370 0 : rVal >>= sToken;
371 : }
372 0 : sNewCmd += (i < 2)
373 0 : ? sToken + OUString(sfx2::cTokenSeparator) : sToken;
374 0 : }
375 0 : SetCmd( sNewCmd );
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 : OUString SwDDEField::Expand() const
392 : {
393 0 : OUString aStr = ((SwDDEFieldType*)GetTyp())->GetExpansion();
394 0 : aStr = aStr.replaceAll("\r", OUString());
395 0 : aStr = aStr.replaceAll("\t", " ");
396 0 : aStr = aStr.replaceAll("\n", "|");
397 0 : if (aStr.endsWith("|"))
398 : {
399 0 : return aStr.copy(0, aStr.getLength()-1);
400 : }
401 0 : return aStr;
402 : }
403 :
404 0 : SwField* SwDDEField::Copy() const
405 : {
406 0 : return new SwDDEField((SwDDEFieldType*)GetTyp());
407 : }
408 :
409 : /// get field type name
410 0 : OUString SwDDEField::GetPar1() const
411 : {
412 0 : return ((const SwDDEFieldType*)GetTyp())->GetName();
413 : }
414 :
415 : /// get field type command
416 0 : OUString SwDDEField::GetPar2() const
417 : {
418 0 : return ((const SwDDEFieldType*)GetTyp())->GetCmd();
419 : }
420 :
421 : /// set field type command
422 0 : void SwDDEField::SetPar2(const OUString& rStr)
423 : {
424 0 : ((SwDDEFieldType*)GetTyp())->SetCmd(rStr);
425 270 : }
426 :
427 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|