LibreOffice Module sw (master)  1
ddefld.cxx
Go to the documentation of this file.
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 <sal/config.h>
21 
22 #include <o3tl/any.hxx>
23 #include <osl/diagnose.h>
24 #include <osl/thread.h>
25 #include <sfx2/linkmgr.hxx>
26 #include <sot/exchange.hxx>
27 #include <doc.hxx>
29 #include <IDocumentState.hxx>
31 #include <editsh.hxx>
32 #include <fmtfld.hxx>
33 #include <ddefld.hxx>
34 #include <swbaslnk.hxx>
35 #include <unofldmid.h>
36 #include <hints.hxx>
37 #include <calbck.hxx>
38 
39 using namespace ::com::sun::star;
40 
41 #define DDE_TXT_ENCODING osl_getThreadTextEncoding()
42 
44 {
46 public:
48  : SwBaseLink( nUpdateType, SotClipboardFormatId::STRING ),
49  rFieldType( rType )
50  {}
51 
52  virtual void Closed() override;
53  virtual ::sfx2::SvBaseLink::UpdateResult DataChanged(
54  const OUString& rMimeType, const css::uno::Any & rValue ) override;
55 
56  virtual const SwNode* GetAnchor() const override;
57  virtual bool IsInRange( sal_uLong nSttNd, sal_uLong nEndNd ) const override;
58 };
59 
61  const uno::Any & rValue )
62 {
63  switch( SotExchange::GetFormatIdFromMimeType( rMimeType ) )
64  {
65  case SotClipboardFormatId::STRING:
66  if( !IsNoDataFlag() )
67  {
68  uno::Sequence< sal_Int8 > aSeq;
69  rValue >>= aSeq;
70  OUString sStr( reinterpret_cast<char const *>(aSeq.getConstArray()), aSeq.getLength(), DDE_TXT_ENCODING );
71 
72  // remove not needed CR-LF at the end
73  sal_Int32 n = sStr.getLength();
74  while( n && 0 == sStr[ n-1 ] )
75  --n;
76  if( n && 0x0a == sStr[ n-1 ] )
77  --n;
78  if( n && 0x0d == sStr[ n-1 ] )
79  --n;
80 
81  bool bDel = n != sStr.getLength();
82  if( bDel )
83  sStr = sStr.copy( 0, n );
84 
85  rFieldType.SetExpansion( sStr );
86  // set Expansion first! (otherwise this flag will be deleted)
87  rFieldType.SetCRLFDelFlag( bDel );
88  }
89  break;
90 
91  // other formats
92  default:
93  return SUCCESS;
94  }
95 
96  OSL_ENSURE( rFieldType.GetDoc(), "no pDoc" );
97 
98  // no dependencies left?
100  {
103 
104  // Search for fields. If no valid found, disconnect.
105  SwMsgPoolItem aUpdateDDE( RES_UPDATEDDETBL );
106  bool bCallModify = false;
108 
110  for(SwClient* pLast = aIter.First(); pLast; pLast = aIter.Next())
111  {
112  // a DDE table or a DDE field attribute in the text
113  if( dynamic_cast<const SwFormatField *>(pLast) == nullptr ||
114  static_cast<SwFormatField*>(pLast)->GetTextField() )
115  {
116  if( !bCallModify )
117  {
118  if( pESh )
119  pESh->StartAllAction();
120  else if( pSh )
121  pSh->StartAction();
122  }
123  pLast->ModifyNotification( nullptr, &aUpdateDDE );
124  bCallModify = true;
125  }
126  }
127 
129 
130  if( bCallModify )
131  {
132  if( pESh )
133  pESh->EndAllAction();
134  else if( pSh )
135  pSh->EndAction();
136 
137  if( pSh )
139  }
140  }
141 
142  return SUCCESS;
143 }
144 
146 {
147  if( rFieldType.GetDoc() && !rFieldType.GetDoc()->IsInDtor() )
148  {
149  // advise goes, convert all fields into text?
152  if( pESh )
153  {
154  pESh->StartAllAction();
155  pESh->FieldToText( &rFieldType );
156  pESh->EndAllAction();
157  }
158  else
159  {
160  pSh->StartAction();
161  // to call at the doc ??
162  pSh->EndAction();
163  }
164  }
165  SvBaseLink::Closed();
166 }
167 
169 
171 {
172  // here, any anchor of the normal NodesArray should be sufficient
173  const SwNode* pNd = nullptr;
174  rFieldType.CallSwClientNotify(sw::LinkAnchorSearchHint(rFieldType.GetDoc()->GetNodes(), pNd));
175  return pNd;
176 }
177 
178 bool SwIntrnlRefLink::IsInRange( sal_uLong nSttNd, sal_uLong nEndNd ) const
179 {
180  bool bInRange = false;
181  rFieldType.CallSwClientNotify(sw::InRangeSearchHint(
182  nSttNd, nEndNd, bInRange));
183  return bInRange;
184 }
185 
186 SwDDEFieldType::SwDDEFieldType(const OUString& rName,
187  const OUString& rCmd, SfxLinkUpdateMode nUpdateType )
188  : SwFieldType( SwFieldIds::Dde ),
189  aName( rName ), pDoc( nullptr ), nRefCnt( 0 )
190 {
191  bCRLFFlag = bDeleted = false;
192  refLink = new SwIntrnlRefLink( *this, nUpdateType );
193  SetCmd( rCmd );
194 }
195 
197 {
198  if( pDoc && !pDoc->IsInDtor() )
200  refLink->Disconnect();
201 }
202 
203 std::unique_ptr<SwFieldType> SwDDEFieldType::Copy() const
204 {
205  std::unique_ptr<SwDDEFieldType> pType(new SwDDEFieldType( aName, GetCmd(), GetType() ));
206  pType->aExpansion = aExpansion;
207  pType->bCRLFFlag = bCRLFFlag;
208  pType->bDeleted = bDeleted;
209  pType->SetDoc( pDoc );
210  return pType;
211 }
212 
213 OUString SwDDEFieldType::GetName() const
214 {
215  return aName;
216 }
217 
218 void SwDDEFieldType::SetCmd( const OUString& _aStr )
219 {
220  OUString aStr = _aStr;
221  sal_Int32 nIndex = 0;
222  do
223  {
224  aStr = aStr.replaceFirst(" ", " ", &nIndex);
225  } while (nIndex>=0);
226  refLink->SetLinkSourceName( aStr );
227 }
228 
229 OUString const & SwDDEFieldType::GetCmd() const
230 {
231  return refLink->GetLinkSourceName();
232 }
233 
235 {
236  if( pNewDoc == pDoc )
237  return;
238 
239  if( pDoc && refLink.is() )
240  {
241  OSL_ENSURE( !nRefCnt, "How do we get the references?" );
243  }
244 
245  pDoc = pNewDoc;
246  if( pDoc && nRefCnt )
247  {
250  }
251 }
252 
254 {
255  if( nRefCnt )
256  {
260  refLink->Update();
261  }
262  else
263  {
264  Disconnect();
266  }
267 }
268 
269 void SwDDEFieldType::QueryValue( uno::Any& rVal, sal_uInt16 nWhichId ) const
270 {
271  sal_Int32 nPart = -1;
272  switch( nWhichId )
273  {
274  case FIELD_PROP_PAR2: nPart = 2; break;
275  case FIELD_PROP_PAR4: nPart = 1; break;
276  case FIELD_PROP_SUBTYPE: nPart = 0; break;
277  case FIELD_PROP_BOOL1:
278  rVal <<= GetType() == SfxLinkUpdateMode::ALWAYS;
279  break;
280  case FIELD_PROP_PAR5:
281  rVal <<= aExpansion;
282  break;
283  default:
284  assert(false);
285  }
286  if ( nPart>=0 )
287  rVal <<= GetCmd().getToken(nPart, sfx2::cTokenSeparator);
288 }
289 
290 void SwDDEFieldType::PutValue( const uno::Any& rVal, sal_uInt16 nWhichId )
291 {
292  sal_Int32 nPart = -1;
293  switch( nWhichId )
294  {
295  case FIELD_PROP_PAR2: nPart = 2; break;
296  case FIELD_PROP_PAR4: nPart = 1; break;
297  case FIELD_PROP_SUBTYPE: nPart = 0; break;
298  case FIELD_PROP_BOOL1:
299  SetType( *o3tl::doAccess<bool>(rVal) ?
300  SfxLinkUpdateMode::ALWAYS :
301  SfxLinkUpdateMode::ONCALL );
302  break;
303  case FIELD_PROP_PAR5:
304  rVal >>= aExpansion;
305  break;
306  default:
307  assert(false);
308  }
309  if( nPart>=0 )
310  {
311  const OUString sOldCmd( GetCmd() );
312  OUStringBuffer sNewCmd;
313  sal_Int32 nIndex = 0;
314  for (sal_Int32 i=0; i<3; ++i)
315  {
316  OUString sToken = sOldCmd.getToken(0, sfx2::cTokenSeparator, nIndex);
317  if (i==nPart)
318  {
319  rVal >>= sToken;
320  }
321  sNewCmd.append((i < 2)
322  ? sToken + OUStringChar(sfx2::cTokenSeparator) : sToken);
323  }
324  SetCmd( sNewCmd.makeStringAndClear() );
325  }
326 }
327 
329  : SwField(pInitType)
330 {
331 }
332 
334 {
335  if( GetTyp()->HasOnlyOneListener() )
336  static_cast<SwDDEFieldType*>(GetTyp())->Disconnect();
337 }
338 
339 OUString SwDDEField::ExpandImpl(SwRootFrame const*const) const
340 {
341  OUString aStr = static_cast<SwDDEFieldType*>(GetTyp())->GetExpansion();
342  aStr = aStr.replaceAll("\r", "");
343  aStr = aStr.replaceAll("\t", " ");
344  aStr = aStr.replaceAll("\n", "|");
345  if (aStr.endsWith("|"))
346  {
347  return aStr.copy(0, aStr.getLength()-1);
348  }
349  return aStr;
350 }
351 
352 std::unique_ptr<SwField> SwDDEField::Copy() const
353 {
354  return std::make_unique<SwDDEField>(static_cast<SwDDEFieldType*>(GetTyp()));
355 }
356 
358 OUString SwDDEField::GetPar1() const
359 {
360  return static_cast<const SwDDEFieldType*>(GetTyp())->GetName();
361 }
362 
364 OUString SwDDEField::GetPar2() const
365 {
366  return static_cast<const SwDDEFieldType*>(GetTyp())->GetCmd();
367 }
368 
370 void SwDDEField::SetPar2(const OUString& rStr)
371 {
372  static_cast<SwDDEFieldType*>(GetTyp())->SetCmd(rStr);
373 }
374 
375 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Instances of SwFields and those derived from it occur 0 to n times.
Definition: fldbas.hxx:234
bool is() const
sal_uInt16 nRefCnt
Definition: ddefld.hxx:59
virtual void SetPar2(const OUString &rStr) override
set field type command
Definition: ddefld.cxx:370
STRING
void SetCmd(const OUString &aStr)
Definition: ddefld.cxx:218
SwDDEFieldType(const OUString &rName, const OUString &rCmd, SfxLinkUpdateMode)
Definition: ddefld.cxx:186
#define FIELD_PROP_PAR5
Definition: unofldmid.h:43
virtual ~SwDDEField() override
Definition: ddefld.cxx:333
virtual void SetModified()=0
Must be called manually at changes of format.
sal_uIntPtr sal_uLong
const sal_Unicode cTokenSeparator
void SetType(SfxLinkUpdateMode nType)
Definition: ddefld.hxx:84
Base class of all fields.
Definition: fldbas.hxx:280
SfxLinkUpdateMode GetType() const
Definition: ddefld.hxx:83
Definition: doc.hxx:185
void Disconnect()
Definition: ddefld.hxx:89
TElementType * Next()
Definition: calbck.hxx:373
IDocumentLinksAdministration const & getIDocumentLinksAdministration() const
Definition: doc.cxx:259
OUString const aName
Definition: ddefld.hxx:53
virtual ~LinkAnchorSearchHint() override
Definition: ddefld.cxx:168
bool HasWriterListeners() const
Definition: calbck.hxx:208
void EndAllAction()
Definition: edws.cxx:96
The root element of a Writer document layout.
Definition: rootfrm.hxx:79
#define FIELD_PROP_SUBTYPE
Definition: unofldmid.h:27
#define RES_UPDATEDDETBL
Definition: hintids.hxx:295
OUString const & GetCmd() const
Definition: ddefld.cxx:229
const SwDoc * GetDoc() const
Definition: ddefld.hxx:94
virtual OUString ExpandImpl(SwRootFrame const *pLayout) const override
Definition: ddefld.cxx:339
SAL_DLLPRIVATE void RefCntChgd()
Definition: ddefld.cxx:253
bool bCRLFFlag
Definition: ddefld.hxx:60
void SetDoc(SwDoc *pDoc)
Definition: ddefld.cxx:234
virtual void PutValue(const css::uno::Any &rVal, sal_uInt16 nWhich) override
Definition: ddefld.cxx:290
SwDoc * GetDoc() const
Definition: viewsh.hxx:284
SotClipboardFormatId
virtual std::unique_ptr< SwFieldType > Copy() const override
Definition: ddefld.cxx:203
void SetCRLFDelFlag(bool bFlag)
Definition: ddefld.hxx:101
T * get() const
#define DDE_TXT_ENCODING
Definition: ddefld.cxx:41
SwDoc * pDoc
Definition: ddefld.hxx:57
void Remove(SvBaseLink const *pLink)
SwEditShell const * GetEditShell() const
Definition: doccorr.cxx:317
virtual OUString GetPar1() const override
Get parameter via types.
Definition: ddefld.cxx:358
TElementType * First()
Definition: calbck.hxx:342
int i
SwFieldIds
Definition: fldbas.hxx:38
virtual OUString GetPar2() const override
get field type command
Definition: ddefld.cxx:364
void StartAction()
Definition: viewsh.hxx:592
void UnlockModify()
Definition: calbck.hxx:214
IDocumentState const & getIDocumentState() const
Definition: doc.cxx:393
void LockModify()
Definition: calbck.hxx:213
SwDDEField(SwDDEFieldType *)
Definition: ddefld.cxx:328
bool bDeleted
Definition: ddefld.hxx:61
IDocumentLayoutAccess const & getIDocumentLayoutAccess() const
Definition: doc.cxx:404
void InsertDDELink(SvBaseLink *, const OUString &rServer, const OUString &rTopic, const OUString &rItem)
SwFieldType * GetTyp() const
Definition: fldbas.hxx:383
void EndAction(const bool bIdleEnd=false)
Definition: viewsh.hxx:597
#define FIELD_PROP_BOOL1
Definition: unofldmid.h:28
bool IsModifyLocked() const
Definition: calbck.hxx:218
void SetExpansion(const OUString &rStr)
Definition: ddefld.hxx:71
void FieldToText(SwFieldType const *pType)
Definition: edfld.cxx:123
OUString aExpansion
Definition: ddefld.hxx:54
#define FIELD_PROP_PAR2
Definition: unofldmid.h:24
virtual const SwViewShell * GetCurrentViewShell() const =0
Returns the layout set at the document.
static SotClipboardFormatId GetFormatIdFromMimeType(const OUString &rMimeType)
tools::SvRef< sfx2::SvBaseLink > refLink
Definition: ddefld.hxx:56
virtual sfx2::LinkManager & GetLinkManager()=0
OString const aName
bool IsInDtor() const
Definition: doc.hxx:397
#define FIELD_PROP_PAR4
Definition: unofldmid.h:36
virtual std::unique_ptr< SwField > Copy() const override
Definition: ddefld.cxx:352
virtual ~SwDDEFieldType() override
Definition: ddefld.cxx:196
void StartAllAction()
For all views of this document.
Definition: edws.cxx:85
virtual OUString GetName() const override
Only in derived classes.
Definition: ddefld.cxx:213
aStr
virtual void QueryValue(css::uno::Any &rVal, sal_uInt16 nWhich) const override
Definition: ddefld.cxx:269
SfxLinkUpdateMode
virtual bool IsVisibleLinks() const =0
Insert links in-/visibly into LinkManager (linked ranges).
Base class of the Writer document model elements.
Definition: node.hxx:79