Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / sc / source / filter / xml / XMLDDELinksContext.cxx
blobdf0ee77f4fe1001ee646d49f6b48578cd5752388
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
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>
30 using namespace com::sun::star;
31 using namespace xmloff::token;
33 ScXMLDDELinksContext::ScXMLDDELinksContext( ScXMLImport& rImport ) :
34 ScXMLImportContext( rImport )
36 // here are no attributes
37 rImport.LockSolarMutex();
40 ScXMLDDELinksContext::~ScXMLDDELinksContext()
42 GetScImport().UnlockSolarMutex();
45 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL ScXMLDDELinksContext::createFastChildContext(
46 sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ )
48 SvXMLImportContext *pContext = nullptr;
50 if ( nElement == XML_ELEMENT( TABLE, XML_DDE_LINK) )
51 pContext = new ScXMLDDELinkContext(GetScImport());
53 if( !pContext )
54 pContext = new SvXMLImportContext( GetImport() );
56 return pContext;
59 ScXMLDDELinkContext::ScXMLDDELinkContext( ScXMLImport& rImport ) :
60 ScXMLImportContext( rImport ),
61 aDDELinkTable(),
62 aDDELinkRow(),
63 sApplication(),
64 sTopic(),
65 sItem(),
66 nPosition(-1),
67 nColumns(0),
68 nRows(0),
69 nMode(SC_DDE_DEFAULT)
71 // here are no attributes
74 ScXMLDDELinkContext::~ScXMLDDELinkContext()
78 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL ScXMLDDELinkContext::createFastChildContext(
79 sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& xAttrList )
81 SvXMLImportContext *pContext = nullptr;
82 sax_fastparser::FastAttributeList *pAttribList =
83 sax_fastparser::FastAttributeList::castToFastAttributeList( xAttrList );
85 switch (nElement)
87 case XML_ELEMENT( OFFICE, XML_DDE_SOURCE ):
88 pContext = new ScXMLDDESourceContext(GetScImport(), pAttribList, this);
89 break;
90 case XML_ELEMENT( TABLE, XML_TABLE ):
91 pContext = new ScXMLDDETableContext(GetScImport(), this);
92 break;
95 if( !pContext )
96 pContext = new SvXMLImportContext( GetImport() );
98 return pContext;
101 void ScXMLDDELinkContext::CreateDDELink()
103 if (GetScImport().GetDocument() &&
104 !sApplication.isEmpty() &&
105 !sTopic.isEmpty() &&
106 !sItem.isEmpty())
108 GetScImport().GetDocument()->CreateDdeLink(sApplication, sTopic, sItem, nMode, ScMatrixRef());
109 size_t nPos;
110 if(GetScImport().GetDocument()->FindDdeLink(sApplication, sTopic, sItem, nMode, nPos))
111 nPosition = nPos;
112 else
114 nPosition = -1;
115 SAL_WARN("sc" , "DDE Link not inserted");
120 void ScXMLDDELinkContext::AddCellToRow(const ScDDELinkCell& aCell)
122 aDDELinkRow.push_back(aCell);
125 void ScXMLDDELinkContext::AddRowsToTable(const sal_Int32 nRowsP)
127 for (sal_Int32 i = 0; i < nRowsP; ++i)
128 aDDELinkTable.insert(aDDELinkTable.end(), aDDELinkRow.begin(), aDDELinkRow.end());
129 aDDELinkRow.clear();
132 void SAL_CALL ScXMLDDELinkContext::endFastElement( sal_Int32 /*nElement*/ )
134 ScDocument* pDoc = GetScImport().GetDocument();
135 if (nPosition > -1 && nColumns && nRows)
137 bool bSizeMatch = (static_cast<size_t>(nColumns * nRows) == aDDELinkTable.size());
138 OSL_ENSURE( bSizeMatch, "ScXMLDDELinkContext::EndElement: matrix dimension doesn't match cells count");
139 // Excel writes bad ODF in that it does not write the
140 // table:number-columns-repeated attribute of the
141 // <table:table-column> element, but apparently uses the number of
142 // <table:table-cell> elements within a <table:table-row> element to
143 // determine the column count instead. Be lenient ...
144 if (!bSizeMatch && nColumns == 1)
146 nColumns = aDDELinkTable.size() / nRows;
147 OSL_ENSURE( static_cast<size_t>(nColumns * nRows) == aDDELinkTable.size(),
148 "ScXMLDDELinkContext::EndElement: adapted matrix dimension doesn't match either");
150 ScMatrixRef pMatrix = new ScMatrix(static_cast<SCSIZE>(nColumns), static_cast<SCSIZE>(nRows), 0.0);
151 sal_Int32 nCol(0);
152 sal_Int32 nRow(-1);
153 sal_Int32 nIndex(0);
155 svl::SharedStringPool& rPool = pDoc->GetSharedStringPool();
156 for (const auto& rDDELinkCell : aDDELinkTable)
158 if (nIndex % nColumns == 0)
160 ++nRow;
161 nCol = 0;
163 else
164 ++nCol;
166 SCSIZE nScCol( static_cast< SCSIZE >( nCol ) );
167 SCSIZE nScRow( static_cast< SCSIZE >( nRow ) );
168 if( rDDELinkCell.bEmpty )
169 pMatrix->PutEmpty( nScCol, nScRow );
170 else if( rDDELinkCell.bString )
171 pMatrix->PutString(rPool.intern(rDDELinkCell.sValue), nScCol, nScRow);
172 else
173 pMatrix->PutDouble( rDDELinkCell.fValue, nScCol, nScRow );
175 ++nIndex;
178 GetScImport().GetDocument()->SetDdeLinkResultMatrix( static_cast< sal_uInt16 >( nPosition ), pMatrix );
182 ScXMLDDESourceContext::ScXMLDDESourceContext( ScXMLImport& rImport,
183 const rtl::Reference<sax_fastparser::FastAttributeList>& rAttrList,
184 ScXMLDDELinkContext* pTempDDELink) :
185 ScXMLImportContext( rImport ),
186 pDDELink(pTempDDELink)
188 if ( rAttrList.is() )
190 for (auto &aIter : *rAttrList)
192 switch (aIter.getToken())
194 case XML_ELEMENT( OFFICE, XML_DDE_APPLICATION ):
195 pDDELink->SetApplication(aIter.toString());
196 break;
197 case XML_ELEMENT( OFFICE, XML_DDE_TOPIC ):
198 pDDELink->SetTopic(aIter.toString());
199 break;
200 case XML_ELEMENT( OFFICE, XML_DDE_ITEM ):
201 pDDELink->SetItem(aIter.toString());
202 break;
203 case XML_ELEMENT( TABLE, XML_CONVERSION_MODE ):
204 if (IsXMLToken(aIter, XML_INTO_ENGLISH_NUMBER))
205 pDDELink->SetMode(SC_DDE_ENGLISH);
206 else if (IsXMLToken(aIter, XML_KEEP_TEXT))
207 pDDELink->SetMode(SC_DDE_TEXT);
208 else
209 pDDELink->SetMode(SC_DDE_DEFAULT);
210 break;
216 ScXMLDDESourceContext::~ScXMLDDESourceContext()
220 void SAL_CALL ScXMLDDESourceContext::endFastElement( sal_Int32 /*nElement*/ )
222 pDDELink->CreateDDELink();
225 ScXMLDDETableContext::ScXMLDDETableContext( ScXMLImport& rImport,
226 ScXMLDDELinkContext* pTempDDELink) :
227 ScXMLImportContext( rImport ),
228 pDDELink(pTempDDELink)
230 // here are no attributes
233 ScXMLDDETableContext::~ScXMLDDETableContext()
237 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL ScXMLDDETableContext::createFastChildContext(
238 sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& xAttrList )
240 SvXMLImportContext *pContext = nullptr;
241 sax_fastparser::FastAttributeList *pAttribList =
242 sax_fastparser::FastAttributeList::castToFastAttributeList( xAttrList );
244 switch (nElement)
246 case XML_ELEMENT( TABLE, XML_TABLE_COLUMN ):
247 pContext = new ScXMLDDEColumnContext(GetScImport(), pAttribList, pDDELink);
248 break;
249 case XML_ELEMENT( TABLE, XML_TABLE_ROW ):
250 pContext = new ScXMLDDERowContext(GetScImport(), pAttribList, pDDELink);
251 break;
254 if (!pContext)
255 pContext = new SvXMLImportContext( GetImport() );
257 return pContext;
260 ScXMLDDEColumnContext::ScXMLDDEColumnContext( ScXMLImport& rImport,
261 const rtl::Reference<sax_fastparser::FastAttributeList>& rAttrList,
262 ScXMLDDELinkContext* pDDELink) :
263 ScXMLImportContext( rImport )
265 if ( rAttrList.is() )
267 sal_Int32 nCols(1);
268 auto aIter( rAttrList->find( XML_ELEMENT( TABLE, XML_NUMBER_COLUMNS_REPEATED ) ) );
269 if (aIter != rAttrList->end())
270 nCols = aIter.toInt32();
272 pDDELink->AddColumns(nCols);
276 ScXMLDDEColumnContext::~ScXMLDDEColumnContext()
280 ScXMLDDERowContext::ScXMLDDERowContext( ScXMLImport& rImport,
281 const rtl::Reference<sax_fastparser::FastAttributeList>& rAttrList,
282 ScXMLDDELinkContext* pTempDDELink) :
283 ScXMLImportContext( rImport ),
284 pDDELink(pTempDDELink),
285 nRows(1)
287 if ( rAttrList.is() )
289 auto aIter( rAttrList->find( XML_ELEMENT( TABLE, XML_NUMBER_ROWS_REPEATED ) ) );
290 if (aIter != rAttrList->end())
291 nRows = aIter.toInt32();
293 pDDELink->AddRows(nRows);
297 ScXMLDDERowContext::~ScXMLDDERowContext()
301 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL ScXMLDDERowContext::createFastChildContext(
302 sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& xAttrList )
304 SvXMLImportContext *pContext = nullptr;
305 sax_fastparser::FastAttributeList *pAttribList =
306 sax_fastparser::FastAttributeList::castToFastAttributeList( xAttrList );
308 if (nElement == XML_ELEMENT( TABLE, XML_TABLE_CELL ))
309 pContext = new ScXMLDDECellContext(GetScImport(), pAttribList, pDDELink);
311 if (!pContext)
312 pContext = new SvXMLImportContext( GetImport() );
314 return pContext;
317 void SAL_CALL ScXMLDDERowContext::endFastElement( sal_Int32 /*nElement*/ )
319 pDDELink->AddRowsToTable(nRows);
322 ScXMLDDECellContext::ScXMLDDECellContext( ScXMLImport& rImport,
323 const rtl::Reference<sax_fastparser::FastAttributeList>& rAttrList,
324 ScXMLDDELinkContext* pTempDDELink) :
325 ScXMLImportContext( rImport ),
326 sValue(),
327 fValue(),
328 nCells(1),
329 bString(true),
330 bString2(true),
331 bEmpty(true),
332 pDDELink(pTempDDELink)
334 if ( rAttrList.is() )
336 for (auto &aIter : *rAttrList)
338 switch (aIter.getToken())
340 case XML_ELEMENT( OFFICE, XML_VALUE_TYPE ):
341 if (IsXMLToken(aIter, XML_STRING))
342 bString = true;
343 else
344 bString = false;
345 break;
346 case XML_ELEMENT( OFFICE, XML_STRING_VALUE ):
347 sValue = aIter.toString();
348 bEmpty = false;
349 bString2 = true;
350 break;
351 case XML_ELEMENT( OFFICE, XML_VALUE ):
352 fValue = aIter.toDouble();
353 bEmpty = false;
354 bString2 = false;
355 break;
356 case XML_ELEMENT( TABLE, XML_NUMBER_COLUMNS_REPEATED ):
357 nCells = aIter.toInt32();
358 break;
364 ScXMLDDECellContext::~ScXMLDDECellContext()
368 void SAL_CALL ScXMLDDECellContext::endFastElement( sal_Int32 /*nElement*/ )
370 OSL_ENSURE(bString == bString2, "something wrong with this type");
371 ScDDELinkCell aCell;
372 aCell.sValue = sValue;
373 aCell.fValue = fValue;
374 aCell.bEmpty = bEmpty;
375 aCell.bString = bString2;
376 for(sal_Int32 i = 0; i < nCells; ++i)
377 pDDELink->AddCellToRow(aCell);
380 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */