LibreOffice Module sc (master)  1
ddelink.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 <comphelper/fileformat.h>
21 #include <comphelper/string.hxx>
22 #include <osl/thread.h>
23 #include <sot/exchange.hxx>
24 #include <sfx2/linkmgr.hxx>
25 #include <sfx2/bindings.hxx>
26 #include <svl/numformat.hxx>
27 #include <svl/sharedstringpool.hxx>
28 #include <o3tl/string_view.hxx>
29 
30 #include <ddelink.hxx>
31 #include <brdcst.hxx>
32 #include <document.hxx>
33 #include <scmatrix.hxx>
34 #include <patattr.hxx>
35 #include <rechead.hxx>
36 #include <rangeseq.hxx>
37 #include <sc.hrc>
38 #include <hints.hxx>
39 
40 
41 bool ScDdeLink::bIsInUpdate = false;
42 
43 ScDdeLink::ScDdeLink( ScDocument& rD, const OUString& rA, const OUString& rT, const OUString& rI,
44  sal_uInt8 nM ) :
46  rDoc( rD ),
47  aAppl( rA ),
48  aTopic( rT ),
49  aItem( rI ),
50  nMode( nM ),
51  bNeedUpdate( false ),
52  pResult( nullptr )
53 {
54 }
55 
57 {
58  // cancel connection
59 
60  // pResult is refcounted
61 }
62 
63 ScDdeLink::ScDdeLink( ScDocument& rD, const ScDdeLink& rOther ) :
65  rDoc ( rD ),
66  aAppl ( rOther.aAppl ),
67  aTopic ( rOther.aTopic ),
68  aItem ( rOther.aItem ),
69  nMode ( rOther.nMode ),
70  bNeedUpdate( false ),
71  pResult ( nullptr )
72 {
73  if (rOther.pResult)
74  pResult = rOther.pResult->Clone();
75 }
76 
79  rDoc( rD ),
80  bNeedUpdate( false ),
81  pResult( nullptr )
82 {
83  rHdr.StartEntry();
84 
85  rtl_TextEncoding eCharSet = rStream.GetStreamCharSet();
86  aAppl = rStream.ReadUniOrByteString( eCharSet );
87  aTopic = rStream.ReadUniOrByteString( eCharSet );
88  aItem = rStream.ReadUniOrByteString( eCharSet );
89 
90  bool bHasValue;
91  rStream.ReadCharAsBool( bHasValue );
92  if ( bHasValue )
93  pResult = new ScMatrix(0, 0);
94 
95  if (rHdr.BytesLeft()) // new in 388b and the 364w (RealTime Client) version
96  rStream.ReadUChar( nMode );
97  else
99 
100  rHdr.EndEntry();
101 }
102 
103 void ScDdeLink::Store( SvStream& rStream, ScMultipleWriteHeader& rHdr ) const
104 {
105  rHdr.StartEntry();
106 
107  rtl_TextEncoding eCharSet = rStream.GetStreamCharSet();
108  rStream.WriteUniOrByteString( aAppl, eCharSet );
109  rStream.WriteUniOrByteString( aTopic, eCharSet );
110  rStream.WriteUniOrByteString( aItem, eCharSet );
111 
112  bool bHasValue = ( pResult != nullptr );
113  rStream.WriteBool( bHasValue );
114 
115  if( rStream.GetVersion() > SOFFICE_FILEFORMAT_40 ) // not with 4.0 Export
116  rStream.WriteUChar( nMode ); // since 388b
117 
118  // links with Mode != SC_DDE_DEFAULT are completely omitted in 4.0 Export
119  // (from ScDocument::SaveDdeLinks)
120 
121  rHdr.EndEntry();
122 }
123 
125  const OUString& rMimeType, const css::uno::Any & rValue )
126 {
127  // we only master strings...
128  if ( SotClipboardFormatId::STRING != SotExchange::GetFormatIdFromMimeType( rMimeType ))
129  return SUCCESS;
130 
131  OUString aLinkStr;
132  ScByteSequenceToString::GetString( aLinkStr, rValue, osl_getThreadTextEncoding() );
133  aLinkStr = convertLineEnd(aLinkStr, LINEEND_LF);
134 
135  // if string ends with line end, discard:
136 
137  sal_Int32 nLen = aLinkStr.getLength();
138  if (nLen && aLinkStr[nLen-1] == '\n')
139  aLinkStr = aLinkStr.copy(0, nLen-1);
140 
141  SCSIZE nCols = 1; // empty string -> an empty line
142  SCSIZE nRows = 1;
143  if (!aLinkStr.isEmpty())
144  {
145  nRows = static_cast<SCSIZE>(comphelper::string::getTokenCount(aLinkStr, '\n'));
146  std::u16string_view aLine = o3tl::getToken(aLinkStr, 0, '\n' );
147  if (!aLine.empty())
148  nCols = static_cast<SCSIZE>(comphelper::string::getTokenCount(aLine, '\t'));
149  }
150 
151  if (!nRows || !nCols) // no data
152  {
153  pResult.reset();
154  }
155  else // split data
156  {
157  // always newly re-create matrix, so that bIsString doesn't get mixed up
158  pResult = new ScMatrix(nCols, nRows, 0.0);
159 
160  SvNumberFormatter* pFormatter = rDoc.GetFormatTable();
162 
163  // nMode determines how the text is interpreted (#44455#/#49783#):
164  // SC_DDE_DEFAULT - number format from cell template "Standard"
165  // SC_DDE_ENGLISH - standard number format for English/US
166  // SC_DDE_TEXT - without NumberFormatter directly as string
167  sal_uLong nStdFormat = 0;
168  if ( nMode == SC_DDE_DEFAULT )
169  {
170  ScPatternAttr* pDefPattern = rDoc.GetDefPattern(); // contains standard template
171  if ( pDefPattern )
172  nStdFormat = pDefPattern->GetNumberFormat( pFormatter );
173  }
174  else if ( nMode == SC_DDE_ENGLISH )
175  nStdFormat = pFormatter->GetStandardIndex(LANGUAGE_ENGLISH_US);
176 
177  for (SCSIZE nR=0; nR<nRows; nR++)
178  {
179  std::u16string_view aLine = o3tl::getToken(aLinkStr, static_cast<sal_Int32>(nR), '\n' );
180  for (SCSIZE nC=0; nC<nCols; nC++)
181  {
182  OUString aEntry( o3tl::getToken(aLine, static_cast<sal_Int32>(nC), '\t' ) );
183  sal_uInt32 nIndex = nStdFormat;
184  double fVal = double();
185  if ( nMode != SC_DDE_TEXT && pFormatter->IsNumberFormat( aEntry, nIndex, fVal ) )
186  pResult->PutDouble( fVal, nC, nR );
187  else if (aEntry.isEmpty())
188  // empty cell
189  pResult->PutEmpty(nC, nR);
190  else
191  pResult->PutString(rPool.intern(aEntry), nC, nR);
192  }
193  }
194  }
195 
196  // Something happened...
197 
198  if (HasListeners())
199  {
200  Broadcast(ScHint(SfxHintId::ScDataChanged, ScAddress()));
201  rDoc.TrackFormulas(); // must happen immediately
203 
204  // StartTrackTimer asynchronously calls TrackFormulas, Broadcast(FID_DATACHANGED),
205  // ResetChanged, SetModified and Invalidate(SID_SAVEDOC/SID_DOC_MODIFIED)
206  // TrackFormulas additionally once again immediately, so that, e.g., a formula still
207  // located in the FormulaTrack doesn't get calculated by IdleCalc (#61676#)
208 
209  // notify Uno objects (for XRefreshListener)
210  // must be after TrackFormulas
211  //TODO: do this asynchronously?
212  ScLinkRefreshedHint aHint;
213  aHint.SetDdeLink( aAppl, aTopic, aItem );
214  rDoc.BroadcastUno( aHint );
215  }
216 
217  return SUCCESS;
218 }
219 
221 {
222  bool bWas = bIsInUpdate;
223  bIsInUpdate = true; // Remove() can trigger reschedule??!?
224 
225  ScDocument& rStackDoc = rDoc; // member rDoc can't be used after removing the link
226 
227  sfx2::LinkManager* pLinkMgr = rDoc.GetLinkManager();
228  pLinkMgr->Remove( this); // deletes this
229 
230  if ( pLinkMgr->GetLinks().empty() ) // deleted the last one ?
231  {
232  SfxBindings* pBindings = rStackDoc.GetViewBindings(); // don't use member rDoc!
233  if (pBindings)
234  pBindings->Invalidate( SID_LINKS );
235  }
236 
237  bIsInUpdate = bWas;
238 }
239 
241 {
242  return pResult.get();
243 }
244 
246 {
247  pResult = pRes;
248 }
249 
251 {
252  if (bIsInUpdate)
253  bNeedUpdate = true; // cannot be executed now
254  else
255  {
256  bIsInUpdate = true;
258  Update();
260  bIsInUpdate = false;
261  bNeedUpdate = false;
262  }
263 }
264 
265 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SvStream & WriteBool(bool b)
Matrix data type that can store values of mixed types.
Definition: scmatrix.hxx:112
void IncInDdeLinkUpdate()
Definition: document.hxx:1040
STRING
sal_Int32 nIndex
TOOLS_DLLPUBLIC OString convertLineEnd(const OString &rIn, LineEnd eLineEnd)
SharedString intern(const OUString &rStr)
SC_DLLPUBLIC svl::SharedStringPool & GetSharedStringPool()
Definition: documen2.cxx:584
#define LANGUAGE_ENGLISH_US
sal_uInt64 BytesLeft() const
Definition: rechead.cxx:97
sal_Int32 GetVersion() const
sal_uIntPtr sal_uLong
const sal_uInt8 SC_DDE_DEFAULT
Definition: document.hxx:300
SvStream & ReadCharAsBool(bool &rBool)
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
void Invalidate(sal_uInt16 nId)
const sal_uInt8 SC_DDE_TEXT
Definition: document.hxx:302
size_t SCSIZE
size_t typedef to be able to find places where code was changed from USHORT to size_t and is used to ...
Definition: address.hxx:44
sal_uInt32 GetStandardIndex(LanguageType eLnge=LANGUAGE_DONTKNOW)
void DecInDdeLinkUpdate()
Definition: document.hxx:1041
::boost::intrusive_ptr< ScMatrix > ScMatrixRef
Definition: types.hxx:25
SotClipboardFormatId
void SetDdeLink(const OUString &rA, const OUString &rT, const OUString &rI)
Definition: hints.cxx:67
sal_Int32 getTokenCount(std::string_view rIn, char cTok)
SC_DLLPUBLIC SvNumberFormatter * GetFormatTable() const
Definition: documen2.cxx:459
LINEEND_LF
void Broadcast(const SfxHint &rHint)
const SvBaseLinks & GetLinks() const
void Remove(SvBaseLink const *pLink)
bool IsNumberFormat(const OUString &sString, sal_uInt32 &F_Index, double &fOutNumber, SvNumInputOptions eInputOptions=SvNumInputOptions::NONE)
void TrackFormulas(SfxHintId nHintId=SfxHintId::ScDataChanged)
Definition: documen7.cxx:530
void BroadcastUno(const SfxHint &rHint)
Definition: documen3.cxx:952
sal_uInt32 GetNumberFormat(SvNumberFormatter *) const
Definition: patattr.cxx:1301
SvStream & ReadUChar(unsigned char &rChar)
static bool GetString(OUString &rString, const css::uno::Any &rAny, sal_uInt16 nEncoding)
Definition: rangeseq.cxx:432
#define SOFFICE_FILEFORMAT_40
unsigned char sal_uInt8
static SotClipboardFormatId GetFormatIdFromMimeType(const OUString &rMimeType)
SvStream & WriteUChar(unsigned char nChar)
SvStream & WriteUniOrByteString(std::u16string_view rStr, rtl_TextEncoding eDestCharSet)
SfxBindings * GetViewBindings()
Definition: documen8.cxx:1188
rtl_TextEncoding GetStreamCharSet() const
SC_DLLPUBLIC ScPatternAttr * GetDefPattern() const
Definition: document.cxx:6151
bool HasListeners() const
void StartTrackTimer()
Definition: documen2.cxx:324
const sal_uInt8 SC_DDE_ENGLISH
Definition: document.hxx:301
SC_DLLPUBLIC sfx2::LinkManager * GetLinkManager()
Definition: documen2.cxx:229
SfxLinkUpdateMode
bool m_bDetectedRangeSegmentation false
OUString ReadUniOrByteString(rtl_TextEncoding eSrcCharSet)