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/zforlist.hxx>
28 #include <svl/sharedstringpool.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  OUString aLine;
142  SCSIZE nCols = 1; // empty string -> an empty line
143  SCSIZE nRows = 1;
144  if (!aLinkStr.isEmpty())
145  {
146  nRows = static_cast<SCSIZE>(comphelper::string::getTokenCount(aLinkStr, '\n'));
147  aLine = aLinkStr.getToken( 0, '\n' );
148  if (!aLine.isEmpty())
149  nCols = static_cast<SCSIZE>(comphelper::string::getTokenCount(aLine, '\t'));
150  }
151 
152  if (!nRows || !nCols) // no data
153  {
154  pResult.reset();
155  }
156  else // split data
157  {
158  // always newly re-create matrix, so that bIsString doesn't get mixed up
159  pResult = new ScMatrix(nCols, nRows, 0.0);
160 
161  SvNumberFormatter* pFormatter = rDoc.GetFormatTable();
163 
164  // nMode determines how the text is interpreted (#44455#/#49783#):
165  // SC_DDE_DEFAULT - number format from cell template "Standard"
166  // SC_DDE_ENGLISH - standard number format for English/US
167  // SC_DDE_TEXT - without NumberFormatter directly as string
168  sal_uLong nStdFormat = 0;
169  if ( nMode == SC_DDE_DEFAULT )
170  {
171  ScPatternAttr* pDefPattern = rDoc.GetDefPattern(); // contains standard template
172  if ( pDefPattern )
173  nStdFormat = pDefPattern->GetNumberFormat( pFormatter );
174  }
175  else if ( nMode == SC_DDE_ENGLISH )
176  nStdFormat = pFormatter->GetStandardIndex(LANGUAGE_ENGLISH_US);
177 
178  OUString aEntry;
179  for (SCSIZE nR=0; nR<nRows; nR++)
180  {
181  aLine = aLinkStr.getToken( static_cast<sal_Int32>(nR), '\n' );
182  for (SCSIZE nC=0; nC<nCols; nC++)
183  {
184  aEntry = aLine.getToken( static_cast<sal_Int32>(nC), '\t' );
185  sal_uInt32 nIndex = nStdFormat;
186  double fVal = double();
187  if ( nMode != SC_DDE_TEXT && pFormatter->IsNumberFormat( aEntry, nIndex, fVal ) )
188  pResult->PutDouble( fVal, nC, nR );
189  else if (aEntry.isEmpty())
190  // empty cell
191  pResult->PutEmpty(nC, nR);
192  else
193  pResult->PutString(rPool.intern(aEntry), nC, nR);
194  }
195  }
196  }
197 
198  // Something happened...
199 
200  if (HasListeners())
201  {
202  Broadcast(ScHint(SfxHintId::ScDataChanged, ScAddress()));
203  rDoc.TrackFormulas(); // must happen immediately
205 
206  // StartTrackTimer asynchronously calls TrackFormulas, Broadcast(FID_DATACHANGED),
207  // ResetChanged, SetModified and Invalidate(SID_SAVEDOC/SID_DOC_MODIFIED)
208  // TrackFormulas additionally once again immediately, so that, e.g., a formula still
209  // located in the FormulaTrack doesn't get calculated by IdleCalc (#61676#)
210 
211  // notify Uno objects (for XRefreshListener)
212  // must be after TrackFormulas
213  //TODO: do this asynchronously?
214  ScLinkRefreshedHint aHint;
215  aHint.SetDdeLink( aAppl, aTopic, aItem );
216  rDoc.BroadcastUno( aHint );
217  }
218 
219  return SUCCESS;
220 }
221 
223 {
224  bool bWas = bIsInUpdate;
225  bIsInUpdate = true; // Remove() can trigger reschedule??!?
226 
227  ScDocument& rStackDoc = rDoc; // member rDoc can't be used after removing the link
228 
229  sfx2::LinkManager* pLinkMgr = rDoc.GetLinkManager();
230  pLinkMgr->Remove( this); // deletes this
231 
232  if ( pLinkMgr->GetLinks().empty() ) // deleted the last one ?
233  {
234  SfxBindings* pBindings = rStackDoc.GetViewBindings(); // don't use member rDoc!
235  if (pBindings)
236  pBindings->Invalidate( SID_LINKS );
237  }
238 
239  bIsInUpdate = bWas;
240 }
241 
243 {
244  return pResult.get();
245 }
246 
248 {
249  pResult = pRes;
250 }
251 
253 {
254  if (bIsInUpdate)
255  bNeedUpdate = true; // cannot be executed now
256  else
257  {
258  bIsInUpdate = true;
260  Update();
262  bIsInUpdate = false;
263  bNeedUpdate = false;
264  }
265 }
266 
267 /* 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:1017
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:566
#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:292
SvStream & ReadCharAsBool(bool &rBool)
void Invalidate(sal_uInt16 nId)
const sal_uInt8 SC_DDE_TEXT
Definition: document.hxx:294
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:1018
::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:441
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:527
void BroadcastUno(const SfxHint &rHint)
Definition: documen3.cxx:949
sal_uInt32 GetNumberFormat(SvNumberFormatter *) const
Definition: patattr.cxx:1256
SvStream & ReadUChar(unsigned char &rChar)
static bool GetString(OUString &rString, const css::uno::Any &rAny, sal_uInt16 nEncoding)
Definition: rangeseq.cxx:433
#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:1190
rtl_TextEncoding GetStreamCharSet() const
SC_DLLPUBLIC ScPatternAttr * GetDefPattern() const
Definition: document.cxx:6082
bool HasListeners() const
void StartTrackTimer()
Definition: documen2.cxx:313
const sal_uInt8 SC_DDE_ENGLISH
Definition: document.hxx:293
SC_DLLPUBLIC sfx2::LinkManager * GetLinkManager()
Definition: documen2.cxx:218
SfxLinkUpdateMode
OUString ReadUniOrByteString(rtl_TextEncoding eSrcCharSet)