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