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 #define DDE_TXT_ENCODING osl_getThreadTextEncoding()
41 
42 bool ScDdeLink::bIsInUpdate = false;
43 
44 ScDdeLink::ScDdeLink( ScDocument& rD, const OUString& rA, const OUString& rT, const OUString& rI,
45  sal_uInt8 nM ) :
47  rDoc( rD ),
48  aAppl( rA ),
49  aTopic( rT ),
50  aItem( rI ),
51  nMode( nM ),
52  bNeedUpdate( false ),
53  pResult( nullptr )
54 {
55 }
56 
58 {
59  // cancel connection
60 
61  // pResult is refcounted
62 }
63 
64 ScDdeLink::ScDdeLink( ScDocument& rD, const ScDdeLink& rOther ) :
66  rDoc ( rD ),
67  aAppl ( rOther.aAppl ),
68  aTopic ( rOther.aTopic ),
69  aItem ( rOther.aItem ),
70  nMode ( rOther.nMode ),
71  bNeedUpdate( false ),
72  pResult ( nullptr )
73 {
74  if (rOther.pResult)
75  pResult = rOther.pResult->Clone();
76 }
77 
80  rDoc( rD ),
81  bNeedUpdate( false ),
82  pResult( nullptr )
83 {
84  rHdr.StartEntry();
85 
86  rtl_TextEncoding eCharSet = rStream.GetStreamCharSet();
87  aAppl = rStream.ReadUniOrByteString( eCharSet );
88  aTopic = rStream.ReadUniOrByteString( eCharSet );
89  aItem = rStream.ReadUniOrByteString( eCharSet );
90 
91  bool bHasValue;
92  rStream.ReadCharAsBool( bHasValue );
93  if ( bHasValue )
94  pResult = new ScMatrix(0, 0);
95 
96  if (rHdr.BytesLeft()) // new in 388b and the 364w (RealTime Client) version
97  rStream.ReadUChar( nMode );
98  else
100 
101  rHdr.EndEntry();
102 }
103 
104 void ScDdeLink::Store( SvStream& rStream, ScMultipleWriteHeader& rHdr ) const
105 {
106  rHdr.StartEntry();
107 
108  rtl_TextEncoding eCharSet = rStream.GetStreamCharSet();
109  rStream.WriteUniOrByteString( aAppl, eCharSet );
110  rStream.WriteUniOrByteString( aTopic, eCharSet );
111  rStream.WriteUniOrByteString( aItem, eCharSet );
112 
113  bool bHasValue = ( pResult != nullptr );
114  rStream.WriteBool( bHasValue );
115 
116  if( rStream.GetVersion() > SOFFICE_FILEFORMAT_40 ) // not with 4.0 Export
117  rStream.WriteUChar( nMode ); // since 388b
118 
119  // links with Mode != SC_DDE_DEFAULT are completely omitted in 4.0 Export
120  // (from ScDocument::SaveDdeLinks)
121 
122  rHdr.EndEntry();
123 }
124 
126  const OUString& rMimeType, const css::uno::Any & rValue )
127 {
128  // we only master strings...
129  if ( SotClipboardFormatId::STRING != SotExchange::GetFormatIdFromMimeType( rMimeType ))
130  return SUCCESS;
131 
132  OUString aLinkStr;
134  aLinkStr = convertLineEnd(aLinkStr, LINEEND_LF);
135 
136  // if string ends with line end, discard:
137 
138  sal_Int32 nLen = aLinkStr.getLength();
139  if (nLen && aLinkStr[nLen-1] == '\n')
140  aLinkStr = aLinkStr.copy(0, nLen-1);
141 
142  OUString aLine;
143  SCSIZE nCols = 1; // empty string -> an empty line
144  SCSIZE nRows = 1;
145  if (!aLinkStr.isEmpty())
146  {
147  nRows = static_cast<SCSIZE>(comphelper::string::getTokenCount(aLinkStr, '\n'));
148  aLine = aLinkStr.getToken( 0, '\n' );
149  if (!aLine.isEmpty())
150  nCols = static_cast<SCSIZE>(comphelper::string::getTokenCount(aLine, '\t'));
151  }
152 
153  if (!nRows || !nCols) // no data
154  {
155  pResult.reset();
156  }
157  else // split data
158  {
159  // always newly re-create matrix, so that bIsString doesn't get mixed up
160  pResult = new ScMatrix(nCols, nRows, 0.0);
161 
162  SvNumberFormatter* pFormatter = rDoc.GetFormatTable();
164 
165  // nMode determines how the text is interpreted (#44455#/#49783#):
166  // SC_DDE_DEFAULT - number format from cell template "Standard"
167  // SC_DDE_ENGLISH - standard number format for English/US
168  // SC_DDE_TEXT - without NumberFormatter directly as string
169  sal_uLong nStdFormat = 0;
170  if ( nMode == SC_DDE_DEFAULT )
171  {
172  ScPatternAttr* pDefPattern = rDoc.GetDefPattern(); // contains standard template
173  if ( pDefPattern )
174  nStdFormat = pDefPattern->GetNumberFormat( pFormatter );
175  }
176  else if ( nMode == SC_DDE_ENGLISH )
177  nStdFormat = pFormatter->GetStandardIndex(LANGUAGE_ENGLISH_US);
178 
179  OUString aEntry;
180  for (SCSIZE nR=0; nR<nRows; nR++)
181  {
182  aLine = aLinkStr.getToken( static_cast<sal_Int32>(nR), '\n' );
183  for (SCSIZE nC=0; nC<nCols; nC++)
184  {
185  aEntry = aLine.getToken( static_cast<sal_Int32>(nC), '\t' );
186  sal_uInt32 nIndex = nStdFormat;
187  double fVal = double();
188  if ( nMode != SC_DDE_TEXT && pFormatter->IsNumberFormat( aEntry, nIndex, fVal ) )
189  pResult->PutDouble( fVal, nC, nR );
190  else if (aEntry.isEmpty())
191  // empty cell
192  pResult->PutEmpty(nC, nR);
193  else
194  pResult->PutString(rPool.intern(aEntry), nC, nR);
195  }
196  }
197  }
198 
199  // Something happened...
200 
201  if (HasListeners())
202  {
203  Broadcast(ScHint(SfxHintId::ScDataChanged, ScAddress()));
204  rDoc.TrackFormulas(); // must happen immediately
206 
207  // StartTrackTimer asynchronously calls TrackFormulas, Broadcast(FID_DATACHANGED),
208  // ResetChanged, SetModified and Invalidate(SID_SAVEDOC/SID_DOC_MODIFIED)
209  // TrackFormulas additionally once again immediately, so that, e.g., a formula still
210  // located in the FormulaTrack doesn't get calculated by IdleCalc (#61676#)
211 
212  // notify Uno objects (for XRefreshListener)
213  // must be after TrackFormulas
214  //TODO: do this asynchronously?
215  ScLinkRefreshedHint aHint;
216  aHint.SetDdeLink( aAppl, aTopic, aItem );
217  rDoc.BroadcastUno( aHint );
218  }
219 
220  return SUCCESS;
221 }
222 
224 {
225  bool bWas = bIsInUpdate;
226  bIsInUpdate = true; // Remove() can trigger reschedule??!?
227 
228  ScDocument& rStackDoc = rDoc; // member rDoc can't be used after removing the link
229 
230  sfx2::LinkManager* pLinkMgr = rDoc.GetLinkManager();
231  pLinkMgr->Remove( this); // deletes this
232 
233  if ( pLinkMgr->GetLinks().empty() ) // deleted the last one ?
234  {
235  SfxBindings* pBindings = rStackDoc.GetViewBindings(); // don't use member rDoc!
236  if (pBindings)
237  pBindings->Invalidate( SID_LINKS );
238  }
239 
240  bIsInUpdate = bWas;
241 }
242 
244 {
245  return pResult.get();
246 }
247 
249 {
250  pResult = pRes;
251 }
252 
254 {
255  if (bIsInUpdate)
256  bNeedUpdate = true; // cannot be executed now
257  else
258  {
259  bIsInUpdate = true;
261  Update();
263  bIsInUpdate = false;
264  bNeedUpdate = false;
265  }
266 }
267 
268 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SvStream & WriteBool(bool b)
Matrix data type that can store values of mixed types.
Definition: scmatrix.hxx:113
void IncInDdeLinkUpdate()
Definition: document.hxx:1015
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:562
#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:45
sal_uInt32 GetStandardIndex(LanguageType eLnge=LANGUAGE_DONTKNOW)
void DecInDdeLinkUpdate()
Definition: document.hxx:1016
SvStream & WriteUniOrByteString(const OUString &rStr, rtl_TextEncoding eDestCharSet)
::boost::intrusive_ptr< ScMatrix > ScMatrixRef
Definition: types.hxx:26
SotClipboardFormatId
void SetDdeLink(const OUString &rA, const OUString &rT, const OUString &rI)
Definition: hints.cxx:68
SC_DLLPUBLIC SvNumberFormatter * GetFormatTable() const
Definition: documen2.cxx:437
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:526
void BroadcastUno(const SfxHint &rHint)
Definition: documen3.cxx:943
sal_uInt32 GetNumberFormat(SvNumberFormatter *) const
Definition: patattr.cxx:1257
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:1186
rtl_TextEncoding GetStreamCharSet() const
SC_DLLPUBLIC ScPatternAttr * GetDefPattern() const
Definition: document.cxx:6049
bool HasListeners() const
void StartTrackTimer()
Definition: documen2.cxx:309
const sal_uInt8 SC_DDE_ENGLISH
Definition: document.hxx:292
SC_DLLPUBLIC sfx2::LinkManager * GetLinkManager()
Definition: documen2.cxx:214
SfxLinkUpdateMode
OUString ReadUniOrByteString(rtl_TextEncoding eSrcCharSet)