1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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());
54 pContext
= new SvXMLImportContext( GetImport() );
59 ScXMLDDELinkContext::ScXMLDDELinkContext( ScXMLImport
& rImport
) :
60 ScXMLImportContext( rImport
),
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
);
87 case XML_ELEMENT( OFFICE
, XML_DDE_SOURCE
):
88 pContext
= new ScXMLDDESourceContext(GetScImport(), pAttribList
, this);
90 case XML_ELEMENT( TABLE
, XML_TABLE
):
91 pContext
= new ScXMLDDETableContext(GetScImport(), this);
96 pContext
= new SvXMLImportContext( GetImport() );
101 void ScXMLDDELinkContext::CreateDDELink()
103 if (GetScImport().GetDocument() &&
104 !sApplication
.isEmpty() &&
108 GetScImport().GetDocument()->CreateDdeLink(sApplication
, sTopic
, sItem
, nMode
, ScMatrixRef());
110 if(GetScImport().GetDocument()->FindDdeLink(sApplication
, sTopic
, sItem
, nMode
, nPos
))
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());
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);
155 svl::SharedStringPool
& rPool
= pDoc
->GetSharedStringPool();
156 for (const auto& rDDELinkCell
: aDDELinkTable
)
158 if (nIndex
% nColumns
== 0)
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
);
173 pMatrix
->PutDouble( rDDELinkCell
.fValue
, nScCol
, nScRow
);
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());
197 case XML_ELEMENT( OFFICE
, XML_DDE_TOPIC
):
198 pDDELink
->SetTopic(aIter
.toString());
200 case XML_ELEMENT( OFFICE
, XML_DDE_ITEM
):
201 pDDELink
->SetItem(aIter
.toString());
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
);
209 pDDELink
->SetMode(SC_DDE_DEFAULT
);
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
);
246 case XML_ELEMENT( TABLE
, XML_TABLE_COLUMN
):
247 pContext
= new ScXMLDDEColumnContext(GetScImport(), pAttribList
, pDDELink
);
249 case XML_ELEMENT( TABLE
, XML_TABLE_ROW
):
250 pContext
= new ScXMLDDERowContext(GetScImport(), pAttribList
, pDDELink
);
255 pContext
= new SvXMLImportContext( GetImport() );
260 ScXMLDDEColumnContext::ScXMLDDEColumnContext( ScXMLImport
& rImport
,
261 const rtl::Reference
<sax_fastparser::FastAttributeList
>& rAttrList
,
262 ScXMLDDELinkContext
* pDDELink
) :
263 ScXMLImportContext( rImport
)
265 if ( rAttrList
.is() )
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
),
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
);
312 pContext
= new SvXMLImportContext( GetImport() );
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
),
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
))
346 case XML_ELEMENT( OFFICE
, XML_STRING_VALUE
):
347 sValue
= aIter
.toString();
351 case XML_ELEMENT( OFFICE
, XML_VALUE
):
352 fValue
= aIter
.toDouble();
356 case XML_ELEMENT( TABLE
, XML_NUMBER_COLUMNS_REPEATED
):
357 nCells
= aIter
.toInt32();
364 ScXMLDDECellContext::~ScXMLDDECellContext()
368 void SAL_CALL
ScXMLDDECellContext::endFastElement( sal_Int32
/*nElement*/ )
370 OSL_ENSURE(bString
== bString2
, "something wrong with this type");
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: */