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/xmlnamespace.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  nPosition(-1),
59  nColumns(0),
60  nRows(0),
61  nMode(SC_DDE_DEFAULT)
62 {
63  // here are no attributes
64 }
65 
67 {
68 }
69 
70 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL ScXMLDDELinkContext::createFastChildContext(
71  sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& xAttrList )
72 {
73  SvXMLImportContext *pContext = nullptr;
76 
77  switch (nElement)
78  {
80  pContext = new ScXMLDDESourceContext(GetScImport(), pAttribList, this);
81  break;
82  case XML_ELEMENT( TABLE, XML_TABLE ):
83  pContext = new ScXMLDDETableContext(GetScImport(), this);
84  break;
85  }
86 
87  return pContext;
88 }
89 
91 {
92  if (GetScImport().GetDocument() &&
93  !sApplication.isEmpty() &&
94  !sTopic.isEmpty() &&
95  !sItem.isEmpty())
96  {
98  size_t nPos;
99  if(GetScImport().GetDocument()->FindDdeLink(sApplication, sTopic, sItem, nMode, nPos))
100  nPosition = nPos;
101  else
102  {
103  nPosition = -1;
104  SAL_WARN("sc" , "DDE Link not inserted");
105  }
106  }
107 }
108 
110 {
111  aDDELinkRow.push_back(aCell);
112 }
113 
114 void ScXMLDDELinkContext::AddRowsToTable(const sal_Int32 nRowsP)
115 {
116  for (sal_Int32 i = 0; i < nRowsP; ++i)
117  aDDELinkTable.insert(aDDELinkTable.end(), aDDELinkRow.begin(), aDDELinkRow.end());
118  aDDELinkRow.clear();
119 }
120 
121 void SAL_CALL ScXMLDDELinkContext::endFastElement( sal_Int32 /*nElement*/ )
122 {
123  ScDocument* pDoc = GetScImport().GetDocument();
124  if (!(nPosition > -1 && nColumns && nRows))
125  return;
126 
127  bool bSizeMatch = (static_cast<size_t>(nColumns * nRows) == aDDELinkTable.size());
128  OSL_ENSURE( bSizeMatch, "ScXMLDDELinkContext::EndElement: matrix dimension doesn't match cells count");
129  // Excel writes bad ODF in that it does not write the
130  // table:number-columns-repeated attribute of the
131  // <table:table-column> element, but apparently uses the number of
132  // <table:table-cell> elements within a <table:table-row> element to
133  // determine the column count instead. Be lenient ...
134  if (!bSizeMatch && nColumns == 1)
135  {
136  nColumns = aDDELinkTable.size() / nRows;
137  OSL_ENSURE( static_cast<size_t>(nColumns * nRows) == aDDELinkTable.size(),
138  "ScXMLDDELinkContext::EndElement: adapted matrix dimension doesn't match either");
139  }
140  ScMatrixRef pMatrix = new ScMatrix(static_cast<SCSIZE>(nColumns), static_cast<SCSIZE>(nRows), 0.0);
141  sal_Int32 nCol(0);
142  sal_Int32 nRow(-1);
143  sal_Int32 nIndex(0);
144 
146  for (const auto& rDDELinkCell : aDDELinkTable)
147  {
148  if (nIndex % nColumns == 0)
149  {
150  ++nRow;
151  nCol = 0;
152  }
153  else
154  ++nCol;
155 
156  SCSIZE nScCol( static_cast< SCSIZE >( nCol ) );
157  SCSIZE nScRow( static_cast< SCSIZE >( nRow ) );
158  if( rDDELinkCell.bEmpty )
159  pMatrix->PutEmpty( nScCol, nScRow );
160  else if( rDDELinkCell.bString )
161  pMatrix->PutString(rPool.intern(rDDELinkCell.sValue), nScCol, nScRow);
162  else
163  pMatrix->PutDouble( rDDELinkCell.fValue, nScCol, nScRow );
164 
165  ++nIndex;
166  }
167 
168  GetScImport().GetDocument()->SetDdeLinkResultMatrix( static_cast< sal_uInt16 >( nPosition ), pMatrix );
169 }
170 
173  ScXMLDDELinkContext* pTempDDELink) :
174  ScXMLImportContext( rImport ),
175  pDDELink(pTempDDELink)
176 {
177  if ( !rAttrList.is() )
178  return;
179 
180  for (auto &aIter : *rAttrList)
181  {
182  switch (aIter.getToken())
183  {
185  pDDELink->SetApplication(aIter.toString());
186  break;
188  pDDELink->SetTopic(aIter.toString());
189  break;
191  pDDELink->SetItem(aIter.toString());
192  break;
196  else if (IsXMLToken(aIter, XML_KEEP_TEXT))
198  else
200  break;
201  }
202  }
203 }
204 
206 {
207 }
208 
209 void SAL_CALL ScXMLDDESourceContext::endFastElement( sal_Int32 /*nElement*/ )
210 {
212 }
213 
215  ScXMLDDELinkContext* pTempDDELink) :
216  ScXMLImportContext( rImport ),
217  pDDELink(pTempDDELink)
218 {
219  // here are no attributes
220 }
221 
223 {
224 }
225 
226 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL ScXMLDDETableContext::createFastChildContext(
227  sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& xAttrList )
228 {
229  SvXMLImportContext *pContext = nullptr;
230  sax_fastparser::FastAttributeList *pAttribList =
232 
233  switch (nElement)
234  {
236  pContext = new ScXMLDDEColumnContext(GetScImport(), pAttribList, pDDELink);
237  break;
239  pContext = new ScXMLDDERowContext(GetScImport(), pAttribList, pDDELink);
240  break;
241  }
242 
243  return pContext;
244 }
245 
248  ScXMLDDELinkContext* pDDELink) :
249  ScXMLImportContext( rImport )
250 {
251  if ( rAttrList.is() )
252  {
253  sal_Int32 nCols(1);
254  auto aIter( rAttrList->find( XML_ELEMENT( TABLE, XML_NUMBER_COLUMNS_REPEATED ) ) );
255  if (aIter != rAttrList->end())
256  nCols = aIter.toInt32();
257 
258  pDDELink->AddColumns(nCols);
259  }
260 }
261 
263 {
264 }
265 
268  ScXMLDDELinkContext* pTempDDELink) :
269  ScXMLImportContext( rImport ),
270  pDDELink(pTempDDELink),
271  nRows(1)
272 {
273  if ( rAttrList.is() )
274  {
275  auto aIter( rAttrList->find( XML_ELEMENT( TABLE, XML_NUMBER_ROWS_REPEATED ) ) );
276  if (aIter != rAttrList->end())
277  nRows = aIter.toInt32();
278 
280  }
281 }
282 
284 {
285 }
286 
287 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL ScXMLDDERowContext::createFastChildContext(
288  sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& xAttrList )
289 {
290  SvXMLImportContext *pContext = nullptr;
291  sax_fastparser::FastAttributeList *pAttribList =
293 
294  if (nElement == XML_ELEMENT( TABLE, XML_TABLE_CELL ))
295  pContext = new ScXMLDDECellContext(GetScImport(), pAttribList, pDDELink);
296 
297  return pContext;
298 }
299 
300 void SAL_CALL ScXMLDDERowContext::endFastElement( sal_Int32 /*nElement*/ )
301 {
303 }
304 
307  ScXMLDDELinkContext* pTempDDELink) :
308  ScXMLImportContext( rImport ),
309  fValue(),
310  nCells(1),
311  bString(true),
312  bString2(true),
313  bEmpty(true),
314  pDDELink(pTempDDELink)
315 {
316  if ( !rAttrList.is() )
317  return;
318 
319  for (auto &aIter : *rAttrList)
320  {
321  switch (aIter.getToken())
322  {
324  if (IsXMLToken(aIter, XML_STRING))
325  bString = true;
326  else
327  bString = false;
328  break;
330  sValue = aIter.toString();
331  bEmpty = false;
332  bString2 = true;
333  break;
334  case XML_ELEMENT( OFFICE, XML_VALUE ):
335  fValue = aIter.toDouble();
336  bEmpty = false;
337  bString2 = false;
338  break;
340  nCells = aIter.toInt32();
341  break;
342  }
343  }
344 }
345 
347 {
348 }
349 
350 void SAL_CALL ScXMLDDECellContext::endFastElement( sal_Int32 /*nElement*/ )
351 {
352  OSL_ENSURE(bString == bString2, "something wrong with this type");
353  ScDDELinkCell aCell;
354  aCell.sValue = sValue;
355  aCell.fValue = fValue;
356  aCell.bEmpty = bEmpty;
357  aCell.bString = bString2;
358  for(sal_Int32 i = 0; i < nCells; ++i)
359  pDDELink->AddCellToRow(aCell);
360 }
361 
362 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Matrix data type that can store values of mixed types.
Definition: scmatrix.hxx:112
void AddColumns(const sal_Int32 nValue)
ScXMLDDESourceContext(ScXMLImport &rImport, const rtl::Reference< sax_fastparser::FastAttributeList > &rAttrList, ScXMLDDELinkContext *pDDELink)
ScDDELinkCells aDDELinkTable
sal_Int32 nIndex
SharedString intern(const OUString &rStr)
SC_DLLPUBLIC svl::SharedStringPool & GetSharedStringPool()
Definition: documen2.cxx:566
XML_DDE_ITEM
void SetTopic(const OUString &sValue)
virtual ~ScXMLDDESourceContext() override
ScXMLDDETableContext(ScXMLImport &rImport, ScXMLDDELinkContext *pDDELink)
ScDocument * GetDocument()
Definition: xmlimprt.hxx:205
ScXMLDDELinkContext(ScXMLImport &rImport)
virtual ~ScXMLDDELinksContext() override
ScXMLDDELinksContext(ScXMLImport &rImport)
XML_DDE_APPLICATION
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:995
XML_VALUE_TYPE
virtual void SAL_CALL endFastElement(sal_Int32 nElement) override
bool IsXMLToken(std::u16string_view rString, enum XMLTokenEnum eToken)
FastAttributeList & castToFastAttributeList(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
XML_VALUE
XML_TABLE_CELL
const sal_uInt8 SC_DDE_TEXT
Definition: document.hxx:293
XML_KEEP_TEXT
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
virtual ~ScXMLDDEColumnContext() 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
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
void LockSolarMutex()
Definition: xmlimprt.cxx:1508
bool SetDdeLinkResultMatrix(size_t nDdePos, const ScMatrixRef &pResults)
Sets a result matrix for the specified DDE link.
Definition: documen8.cxx:1026
ScXMLDDELinkContext * pDDELink
::boost::intrusive_ptr< ScMatrix > ScMatrixRef
Definition: types.hxx:25
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_NUMBER_COLUMNS_REPEATED
XML_TABLE_ROW
XML_DDE_LINK
ScXMLDDELinkContext * pDDELink
int i
XML_INTO_ENGLISH_NUMBER
XML_TABLE
virtual ~ScXMLDDECellContext() override
ScXMLImport & GetScImport()
XML_STRING_VALUE
virtual ~ScXMLDDELinkContext() override
void SetItem(const OUString &sValue)
ScXMLDDEColumnContext(ScXMLImport &rImport, const rtl::Reference< sax_fastparser::FastAttributeList > &rAttrList, ScXMLDDELinkContext *pDDELink)
TABLE
virtual ~ScXMLDDETableContext() override
XML_TABLE_COLUMN
XML_NUMBER_ROWS_REPEATED
void UnlockSolarMutex()
Definition: xmlimprt.cxx:1526
void SetMode(const sal_uInt8 nValue)
#define XML_ELEMENT(prefix, name)
XML_DDE_TOPIC
ScXMLDDELinkContext * pDDELink
virtual ~ScXMLDDERowContext() override
void AddRowsToTable(const sal_Int32 nRows)
XML_STRING
#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
void AddRows(const sal_Int32 nValue)
XML_DDE_SOURCE
sal_uInt16 nPos
XML_CONVERSION_MODE