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/zforlist.hxx>
27 #include <svl/sharedstringpool.hxx>
28 
29 #include <ddelink.hxx>
30 #include <brdcst.hxx>
31 #include <document.hxx>
32 #include <scmatrix.hxx>
33 #include <patattr.hxx>
34 #include <rechead.hxx>
35 #include <rangeseq.hxx>
36 #include <sc.hrc>
37 #include <hints.hxx>
38 
39 
40 bool ScDdeLink::bIsInUpdate = false;
41 
42 ScDdeLink::ScDdeLink( ScDocument& rD, const OUString& rA, const OUString& rT, const OUString& rI,
43  sal_uInt8 nM ) :
45  rDoc( rD ),
46  aAppl( rA ),
47  aTopic( rT ),
48  aItem( rI ),
49  nMode( nM ),
50  bNeedUpdate( false ),
51  pResult( nullptr )
52 {
53 }
54 
56 {
57  // cancel connection
58 
59  // pResult is refcounted
60 }
61 
62 ScDdeLink::ScDdeLink( ScDocument& rD, const ScDdeLink& rOther ) :
64  rDoc ( rD ),
65  aAppl ( rOther.aAppl ),
66  aTopic ( rOther.aTopic ),
67  aItem ( rOther.aItem ),
68  nMode ( rOther.nMode ),
69  bNeedUpdate( false ),
70  pResult ( nullptr )
71 {
72  if (rOther.pResult)
73  pResult = rOther.pResult->Clone();
74 }
75 
78  rDoc( rD ),
79  bNeedUpdate( false ),
80  pResult( nullptr )
81 {
82  rHdr.StartEntry();
83 
84  rtl_TextEncoding eCharSet = rStream.GetStreamCharSet();
85  aAppl = rStream.ReadUniOrByteString( eCharSet );
86  aTopic = rStream.ReadUniOrByteString( eCharSet );
87  aItem = rStream.ReadUniOrByteString( eCharSet );
88 
89  bool bHasValue;
90  rStream.ReadCharAsBool( bHasValue );
91  if ( bHasValue )
92  pResult = new ScMatrix(0, 0);
93 
94  if (rHdr.BytesLeft()) // new in 388b and the 364w (RealTime Client) version
95  rStream.ReadUChar( nMode );
96  else
98 
99  rHdr.EndEntry();
100 }
101 
102 void ScDdeLink::Store( SvStream& rStream, ScMultipleWriteHeader& rHdr ) const
103 {
104  rHdr.StartEntry();
105 
106  rtl_TextEncoding eCharSet = rStream.GetStreamCharSet();
107  rStream.WriteUniOrByteString( aAppl, eCharSet );
108  rStream.WriteUniOrByteString( aTopic, eCharSet );
109  rStream.WriteUniOrByteString( aItem, eCharSet );
110 
111  bool bHasValue = ( pResult != nullptr );
112  rStream.WriteBool( bHasValue );
113 
114  if( rStream.GetVersion() > SOFFICE_FILEFORMAT_40 ) // not with 4.0 Export
115  rStream.WriteUChar( nMode ); // since 388b
116 
117  // links with Mode != SC_DDE_DEFAULT are completely omitted in 4.0 Export
118  // (from ScDocument::SaveDdeLinks)
119 
120  rHdr.EndEntry();
121 }
122 
124  const OUString& rMimeType, const css::uno::Any & rValue )
125 {
126  // we only master strings...
127  if ( SotClipboardFormatId::STRING != SotExchange::GetFormatIdFromMimeType( rMimeType ))
128  return SUCCESS;
129 
130  OUString aLinkStr;
131  ScByteSequenceToString::GetString( aLinkStr, rValue, osl_getThreadTextEncoding() );
132  aLinkStr = convertLineEnd(aLinkStr, LINEEND_LF);
133 
134  // if string ends with line end, discard:
135 
136  sal_Int32 nLen = aLinkStr.getLength();
137  if (nLen && aLinkStr[nLen-1] == '\n')
138  aLinkStr = aLinkStr.copy(0, nLen-1);
139 
140  OUString aLine;
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  aLine = aLinkStr.getToken( 0, '\n' );
147  if (!aLine.isEmpty())
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  OUString aEntry;
178  for (SCSIZE nR=0; nR<nRows; nR++)
179  {
180  aLine = aLinkStr.getToken( static_cast<sal_Int32>(nR), '\n' );
181  for (SCSIZE nC=0; nC<nCols; nC++)
182  {
183  aEntry = aLine.getToken( static_cast<sal_Int32>(nC), '\t' );
184  sal_uInt32 nIndex = nStdFormat;
185  double fVal = double();
186  if ( nMode != SC_DDE_TEXT && pFormatter->IsNumberFormat( aEntry, nIndex, fVal ) )
187  pResult->PutDouble( fVal, nC, nR );
188  else if (aEntry.isEmpty())
189  // empty cell
190  pResult->PutEmpty(nC, nR);
191  else
192  pResult->PutString(rPool.intern(aEntry), nC, nR);
193  }
194  }
195  }
196 
197  // Something happened...
198 
199  if (HasListeners())
200  {
201  Broadcast(ScHint(SfxHintId::ScDataChanged, ScAddress()));
202  rDoc.TrackFormulas(); // must happen immediately
204 
205  // StartTrackTimer asynchronously calls TrackFormulas, Broadcast(FID_DATACHANGED),
206  // ResetChanged, SetModified and Invalidate(SID_SAVEDOC/SID_DOC_MODIFIED)
207  // TrackFormulas additionally once again immediately, so that, e.g., a formula still
208  // located in the FormulaTrack doesn't get calculated by IdleCalc (#61676#)
209 
210  // notify Uno objects (for XRefreshListener)
211  // must be after TrackFormulas
212  //TODO: do this asynchronously?
213  ScLinkRefreshedHint aHint;
214  aHint.SetDdeLink( aAppl, aTopic, aItem );
215  rDoc.BroadcastUno( aHint );
216  }
217 
218  return SUCCESS;
219 }
220 
222 {
223  bool bWas = bIsInUpdate;
224  bIsInUpdate = true; // Remove() can trigger reschedule??!?
225 
226  ScDocument& rStackDoc = rDoc; // member rDoc can't be used after removing the link
227 
228  sfx2::LinkManager* pLinkMgr = rDoc.GetLinkManager();
229  pLinkMgr->Remove( this); // deletes this
230 
231  if ( pLinkMgr->GetLinks().empty() ) // deleted the last one ?
232  {
233  SfxBindings* pBindings = rStackDoc.GetViewBindings(); // don't use member rDoc!
234  if (pBindings)
235  pBindings->Invalidate( SID_LINKS );
236  }
237 
238  bIsInUpdate = bWas;
239 }
240 
242 {
243  return pResult.get();
244 }
245 
247 {
248  pResult = pRes;
249 }
250 
252 {
253  if (bIsInUpdate)
254  bNeedUpdate = true; // cannot be executed now
255  else
256  {
257  bIsInUpdate = true;
259  Update();
261  bIsInUpdate = false;
262  bNeedUpdate = false;
263  }
264 }
265 
266 /* 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:1016
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:565
#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:291
SvStream & ReadCharAsBool(bool &rBool)
void Invalidate(sal_uInt16 nId)
const sal_uInt8 SC_DDE_TEXT
Definition: document.hxx:293
sal_Int32 getTokenCount(const OString &rIn, char cTok)
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:1017
SvStream & WriteUniOrByteString(const OUString &rStr, rtl_TextEncoding eDestCharSet)
::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
SC_DLLPUBLIC SvNumberFormatter * GetFormatTable() const
Definition: documen2.cxx:440
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:1255
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)
SfxBindings * GetViewBindings()
Definition: documen8.cxx:1188
rtl_TextEncoding GetStreamCharSet() const
SC_DLLPUBLIC ScPatternAttr * GetDefPattern() const
Definition: document.cxx:6043
bool HasListeners() const
void StartTrackTimer()
Definition: documen2.cxx:312
const sal_uInt8 SC_DDE_ENGLISH
Definition: document.hxx:292
SC_DLLPUBLIC sfx2::LinkManager * GetLinkManager()
Definition: documen2.cxx:217
SfxLinkUpdateMode
OUString ReadUniOrByteString(rtl_TextEncoding eSrcCharSet)