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