LibreOffice Module sc (master)  1
XMLDDELinksContext.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 "XMLDDELinksContext.hxx"
21 #include "xmlimprt.hxx"
22 #include <document.hxx>
23 #include <scmatrix.hxx>
24 #include <xmloff/xmltoken.hxx>
25 #include <xmloff/xmlnmspe.hxx>
26 #include <svl/sharedstringpool.hxx>
27 #include <osl/diagnose.h>
28 #include <sal/log.hxx>
29 
30 using namespace com::sun::star;
31 using namespace xmloff::token;
32 
34  ScXMLImportContext( rImport )
35 {
36  // here are no attributes
37  rImport.LockSolarMutex();
38 }
39 
41 {
43 }
44 
45 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL ScXMLDDELinksContext::createFastChildContext(
46  sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ )
47 {
48  SvXMLImportContext *pContext = nullptr;
49 
50  if ( nElement == XML_ELEMENT( TABLE, XML_DDE_LINK) )
51  pContext = new ScXMLDDELinkContext(GetScImport());
52 
53  return pContext;
54 }
55 
57  ScXMLImportContext( rImport ),
58  aDDELinkTable(),
59  aDDELinkRow(),
60  sApplication(),
61  sTopic(),
62  sItem(),
63  nPosition(-1),
64  nColumns(0),
65  nRows(0),
66  nMode(SC_DDE_DEFAULT)
67 {
68  // here are no attributes
69 }
70 
72 {
73 }
74 
75 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL ScXMLDDELinkContext::createFastChildContext(
76  sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& xAttrList )
77 {
78  SvXMLImportContext *pContext = nullptr;
81 
82  switch (nElement)
83  {
85  pContext = new ScXMLDDESourceContext(GetScImport(), pAttribList, this);
86  break;
87  case XML_ELEMENT( TABLE, XML_TABLE ):
88  pContext = new ScXMLDDETableContext(GetScImport(), this);
89  break;
90  }
91 
92  return pContext;
93 }
94 
96 {
97  if (GetScImport().GetDocument() &&
98  !sApplication.isEmpty() &&
99  !sTopic.isEmpty() &&
100  !sItem.isEmpty())
101  {
103  size_t nPos;
104  if(GetScImport().GetDocument()->FindDdeLink(sApplication, sTopic, sItem, nMode, nPos))
105  nPosition = nPos;
106  else
107  {
108  nPosition = -1;
109  SAL_WARN("sc" , "DDE Link not inserted");
110  }
111  }
112 }
113 
115 {
116  aDDELinkRow.push_back(aCell);
117 }
118 
119 void ScXMLDDELinkContext::AddRowsToTable(const sal_Int32 nRowsP)
120 {
121  for (sal_Int32 i = 0; i < nRowsP; ++i)
122  aDDELinkTable.insert(aDDELinkTable.end(), aDDELinkRow.begin(), aDDELinkRow.end());
123  aDDELinkRow.clear();
124 }
125 
126 void SAL_CALL ScXMLDDELinkContext::endFastElement( sal_Int32 /*nElement*/ )
127 {
128  ScDocument* pDoc = GetScImport().GetDocument();
129  if (!(nPosition > -1 && nColumns && nRows))
130  return;
131 
132  bool bSizeMatch = (static_cast<size_t>(nColumns * nRows) == aDDELinkTable.size());
133  OSL_ENSURE( bSizeMatch, "ScXMLDDELinkContext::EndElement: matrix dimension doesn't match cells count");
134  // Excel writes bad ODF in that it does not write the
135  // table:number-columns-repeated attribute of the
136  // <table:table-column> element, but apparently uses the number of
137  // <table:table-cell> elements within a <table:table-row> element to
138  // determine the column count instead. Be lenient ...
139  if (!bSizeMatch && nColumns == 1)
140  {
141  nColumns = aDDELinkTable.size() / nRows;
142  OSL_ENSURE( static_cast<size_t>(nColumns * nRows) == aDDELinkTable.size(),
143  "ScXMLDDELinkContext::EndElement: adapted matrix dimension doesn't match either");
144  }
145  ScMatrixRef pMatrix = new ScMatrix(static_cast<SCSIZE>(nColumns), static_cast<SCSIZE>(nRows), 0.0);
146  sal_Int32 nCol(0);
147  sal_Int32 nRow(-1);
148  sal_Int32 nIndex(0);
149 
151  for (const auto& rDDELinkCell : aDDELinkTable)
152  {
153  if (nIndex % nColumns == 0)
154  {
155  ++nRow;
156  nCol = 0;
157  }
158  else
159  ++nCol;
160 
161  SCSIZE nScCol( static_cast< SCSIZE >( nCol ) );
162  SCSIZE nScRow( static_cast< SCSIZE >( nRow ) );
163  if( rDDELinkCell.bEmpty )
164  pMatrix->PutEmpty( nScCol, nScRow );
165  else if( rDDELinkCell.bString )
166  pMatrix->PutString(rPool.intern(rDDELinkCell.sValue), nScCol, nScRow);
167  else
168  pMatrix->PutDouble( rDDELinkCell.fValue, nScCol, nScRow );
169 
170  ++nIndex;
171  }
172 
173  GetScImport().GetDocument()->SetDdeLinkResultMatrix( static_cast< sal_uInt16 >( nPosition ), pMatrix );
174 }
175 
178  ScXMLDDELinkContext* pTempDDELink) :
179  ScXMLImportContext( rImport ),
180  pDDELink(pTempDDELink)
181 {
182  if ( !rAttrList.is() )
183  return;
184 
185  for (auto &aIter : *rAttrList)
186  {
187  switch (aIter.getToken())
188  {
190  pDDELink->SetApplication(aIter.toString());
191  break;
193  pDDELink->SetTopic(aIter.toString());
194  break;
196  pDDELink->SetItem(aIter.toString());
197  break;
201  else if (IsXMLToken(aIter, XML_KEEP_TEXT))
203  else
205  break;
206  }
207  }
208 }
209 
211 {
212 }
213 
214 void SAL_CALL ScXMLDDESourceContext::endFastElement( sal_Int32 /*nElement*/ )
215 {
217 }
218 
220  ScXMLDDELinkContext* pTempDDELink) :
221  ScXMLImportContext( rImport ),
222  pDDELink(pTempDDELink)
223 {
224  // here are no attributes
225 }
226 
228 {
229 }
230 
231 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL ScXMLDDETableContext::createFastChildContext(
232  sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& xAttrList )
233 {
234  SvXMLImportContext *pContext = nullptr;
235  sax_fastparser::FastAttributeList *pAttribList =
237 
238  switch (nElement)
239  {
241  pContext = new ScXMLDDEColumnContext(GetScImport(), pAttribList, pDDELink);
242  break;
244  pContext = new ScXMLDDERowContext(GetScImport(), pAttribList, pDDELink);
245  break;
246  }
247 
248  return pContext;
249 }
250 
253  ScXMLDDELinkContext* pDDELink) :
254  ScXMLImportContext( rImport )
255 {
256  if ( rAttrList.is() )
257  {
258  sal_Int32 nCols(1);
259  auto aIter( rAttrList->find( XML_ELEMENT( TABLE, XML_NUMBER_COLUMNS_REPEATED ) ) );
260  if (aIter != rAttrList->end())
261  nCols = aIter.toInt32();
262 
263  pDDELink->AddColumns(nCols);
264  }
265 }
266 
268 {
269 }
270 
273  ScXMLDDELinkContext* pTempDDELink) :
274  ScXMLImportContext( rImport ),
275  pDDELink(pTempDDELink),
276  nRows(1)
277 {
278  if ( rAttrList.is() )
279  {
280  auto aIter( rAttrList->find( XML_ELEMENT( TABLE, XML_NUMBER_ROWS_REPEATED ) ) );
281  if (aIter != rAttrList->end())
282  nRows = aIter.toInt32();
283 
285  }
286 }
287 
289 {
290 }
291 
292 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL ScXMLDDERowContext::createFastChildContext(
293  sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& xAttrList )
294 {
295  SvXMLImportContext *pContext = nullptr;
296  sax_fastparser::FastAttributeList *pAttribList =
298 
299  if (nElement == XML_ELEMENT( TABLE, XML_TABLE_CELL ))
300  pContext = new ScXMLDDECellContext(GetScImport(), pAttribList, pDDELink);
301 
302  return pContext;
303 }
304 
305 void SAL_CALL ScXMLDDERowContext::endFastElement( sal_Int32 /*nElement*/ )
306 {
308 }
309 
312  ScXMLDDELinkContext* pTempDDELink) :
313  ScXMLImportContext( rImport ),
314  sValue(),
315  fValue(),
316  nCells(1),
317  bString(true),
318  bString2(true),
319  bEmpty(true),
320  pDDELink(pTempDDELink)
321 {
322  if ( !rAttrList.is() )
323  return;
324 
325  for (auto &aIter : *rAttrList)
326  {
327  switch (aIter.getToken())
328  {
330  if (IsXMLToken(aIter, XML_STRING))
331  bString = true;
332  else
333  bString = false;
334  break;
336  sValue = aIter.toString();
337  bEmpty = false;
338  bString2 = true;
339  break;
340  case XML_ELEMENT( OFFICE, XML_VALUE ):
341  fValue = aIter.toDouble();
342  bEmpty = false;
343  bString2 = false;
344  break;
346  nCells = aIter.toInt32();
347  break;
348  }
349  }
350 }
351 
353 {
354 }
355 
356 void SAL_CALL ScXMLDDECellContext::endFastElement( sal_Int32 /*nElement*/ )
357 {
358  OSL_ENSURE(bString == bString2, "something wrong with this type");
359  ScDDELinkCell aCell;
360  aCell.sValue = sValue;
361  aCell.fValue = fValue;
362  aCell.bEmpty = bEmpty;
363  aCell.bString = bString2;
364  for(sal_Int32 i = 0; i < nCells; ++i)
365  pDDELink->AddCellToRow(aCell);
366 }
367 
368 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Matrix data type that can store values of mixed types.
Definition: scmatrix.hxx:113
void AddColumns(const sal_Int32 nValue)
ScXMLDDESourceContext(ScXMLImport &rImport, const rtl::Reference< sax_fastparser::FastAttributeList > &rAttrList, ScXMLDDELinkContext *pDDELink)
bool IsXMLToken(const OUString &rString, enum XMLTokenEnum eToken)
XML_NUMBER_ROWS_REPEATED
ScDDELinkCells aDDELinkTable
sal_Int32 nIndex
SharedString intern(const OUString &rStr)
SC_DLLPUBLIC svl::SharedStringPool & GetSharedStringPool()
Definition: documen2.cxx:563
XML_VALUE_TYPE
void SetTopic(const OUString &sValue)
XML_STRING
virtual ~ScXMLDDESourceContext() override
ScXMLDDETableContext(ScXMLImport &rImport, ScXMLDDELinkContext *pDDELink)
ScDocument * GetDocument()
Definition: xmlimprt.hxx:296
ScXMLDDELinkContext(ScXMLImport &rImport)
virtual ~ScXMLDDELinksContext() override
ScXMLDDELinksContext(ScXMLImport &rImport)
const sal_uInt8 SC_DDE_DEFAULT
Definition: document.hxx:291
SC_DLLPUBLIC bool CreateDdeLink(const OUString &rAppl, const OUString &rTopic, const OUString &rItem, sal_uInt8 nMode, const ScMatrixRef &pResults)
Tries to find a DDE link or creates a new, if not extant.
Definition: documen8.cxx:991
XML_VALUE
XML_CONVERSION_MODE
virtual void SAL_CALL endFastElement(sal_Int32 nElement) override
FastAttributeList & castToFastAttributeList(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
const sal_uInt8 SC_DDE_TEXT
Definition: document.hxx:293
ScXMLDDERowContext(ScXMLImport &rImport, const rtl::Reference< sax_fastparser::FastAttributeList > &rAttrList, ScXMLDDELinkContext *pDDELink)
virtual void SAL_CALL endFastElement(sal_Int32 nElement) override
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList) override
ScXMLDDELinkContext * pDDELink
XML_DDE_LINK
virtual ~ScXMLDDEColumnContext() override
XML_TABLE_CELL
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList) override
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
XML_TABLE
void LockSolarMutex()
Definition: xmlimprt.cxx:1699
XML_NUMBER_COLUMNS_REPEATED
bool SetDdeLinkResultMatrix(size_t nDdePos, const ScMatrixRef &pResults)
Sets a result matrix for the specified DDE link.
Definition: documen8.cxx:1022
ScXMLDDELinkContext * pDDELink
::boost::intrusive_ptr< ScMatrix > ScMatrixRef
Definition: types.hxx:26
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList) override
ScXMLDDECellContext(ScXMLImport &rImport, const rtl::Reference< sax_fastparser::FastAttributeList > &rAttrList, ScXMLDDELinkContext *pDDELink)
void AddCellToRow(const ScDDELinkCell &aCell)
ScDDELinkCells aDDELinkRow
This class exists only to provide GetScImport() to its derived classes.
XML_TABLE_ROW
ScXMLDDELinkContext * pDDELink
int i
XML_DDE_SOURCE
XML_DDE_APPLICATION
virtual ~ScXMLDDECellContext() override
XML_STRING_VALUE
XML_INTO_ENGLISH_NUMBER
ScXMLImport & GetScImport()
virtual ~ScXMLDDELinkContext() override
void SetItem(const OUString &sValue)
ScXMLDDEColumnContext(ScXMLImport &rImport, const rtl::Reference< sax_fastparser::FastAttributeList > &rAttrList, ScXMLDDELinkContext *pDDELink)
TABLE
virtual ~ScXMLDDETableContext() override
void UnlockSolarMutex()
Definition: xmlimprt.cxx:1717
XML_DDE_TOPIC
void SetMode(const sal_uInt8 nValue)
#define XML_ELEMENT(prefix, name)
XML_DDE_ITEM
XML_TABLE_COLUMN
ScXMLDDELinkContext * pDDELink
virtual ~ScXMLDDERowContext() override
void AddRowsToTable(const sal_Int32 nRows)
#define SAL_WARN(area, stream)
virtual void SAL_CALL endFastElement(sal_Int32 nElement) override
const sal_uInt8 SC_DDE_ENGLISH
Definition: document.hxx:292
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList) override
void SetApplication(const OUString &sValue)
virtual void SAL_CALL endFastElement(sal_Int32 nElement) override
XML_KEEP_TEXT
void AddRows(const sal_Int32 nValue)
sal_uInt16 nPos