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/xmlnamespace.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());
56 ScXMLDDELinkContext::ScXMLDDELinkContext( ScXMLImport
& rImport
) :
57 ScXMLImportContext( rImport
),
68 // here are no attributes
71 ScXMLDDELinkContext::~ScXMLDDELinkContext()
75 uno::Reference
< xml::sax::XFastContextHandler
> SAL_CALL
ScXMLDDELinkContext::createFastChildContext(
76 sal_Int32 nElement
, const uno::Reference
< xml::sax::XFastAttributeList
>& xAttrList
)
78 SvXMLImportContext
*pContext
= nullptr;
79 sax_fastparser::FastAttributeList
*pAttribList
=
80 &sax_fastparser::castToFastAttributeList( xAttrList
);
84 case XML_ELEMENT( OFFICE
, XML_DDE_SOURCE
):
85 pContext
= new ScXMLDDESourceContext(GetScImport(), pAttribList
, this);
87 case XML_ELEMENT( TABLE
, XML_TABLE
):
88 pContext
= new ScXMLDDETableContext(GetScImport(), this);
95 void ScXMLDDELinkContext::CreateDDELink()
97 if (GetScImport().GetDocument() &&
98 !sApplication
.isEmpty() &&
102 GetScImport().GetDocument()->CreateDdeLink(sApplication
, sTopic
, sItem
, nMode
, ScMatrixRef());
104 if(GetScImport().GetDocument()->FindDdeLink(sApplication
, sTopic
, sItem
, nMode
, nPos
))
109 SAL_WARN("sc" , "DDE Link not inserted");
114 void ScXMLDDELinkContext::AddCellToRow(const ScDDELinkCell
& aCell
)
116 aDDELinkRow
.push_back(aCell
);
119 void ScXMLDDELinkContext::AddRowsToTable(const sal_Int32 nRowsP
)
121 for (sal_Int32 i
= 0; i
< nRowsP
; ++i
)
122 aDDELinkTable
.insert(aDDELinkTable
.end(), aDDELinkRow
.begin(), aDDELinkRow
.end());
126 void SAL_CALL
ScXMLDDELinkContext::endFastElement( sal_Int32
/*nElement*/ )
128 ScDocument
* pDoc
= GetScImport().GetDocument();
129 if (!(nPosition
> -1 && nColumns
&& nRows
))
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)
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");
145 ScMatrixRef pMatrix
= new ScMatrix(static_cast<SCSIZE
>(nColumns
), static_cast<SCSIZE
>(nRows
), 0.0);
150 svl::SharedStringPool
& rPool
= pDoc
->GetSharedStringPool();
151 for (const auto& rDDELinkCell
: aDDELinkTable
)
153 if (nIndex
% nColumns
== 0)
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
);
168 pMatrix
->PutDouble( rDDELinkCell
.fValue
, nScCol
, nScRow
);
173 GetScImport().GetDocument()->SetDdeLinkResultMatrix( static_cast< sal_uInt16
>( nPosition
), pMatrix
);
176 ScXMLDDESourceContext::ScXMLDDESourceContext( ScXMLImport
& rImport
,
177 const rtl::Reference
<sax_fastparser::FastAttributeList
>& rAttrList
,
178 ScXMLDDELinkContext
* pTempDDELink
) :
179 ScXMLImportContext( rImport
),
180 pDDELink(pTempDDELink
)
182 if ( !rAttrList
.is() )
185 for (auto &aIter
: *rAttrList
)
187 switch (aIter
.getToken())
189 case XML_ELEMENT( OFFICE
, XML_DDE_APPLICATION
):
190 pDDELink
->SetApplication(aIter
.toString());
192 case XML_ELEMENT( OFFICE
, XML_DDE_TOPIC
):
193 pDDELink
->SetTopic(aIter
.toString());
195 case XML_ELEMENT( OFFICE
, XML_DDE_ITEM
):
196 pDDELink
->SetItem(aIter
.toString());
198 case XML_ELEMENT( TABLE
, XML_CONVERSION_MODE
):
199 if (IsXMLToken(aIter
, XML_INTO_ENGLISH_NUMBER
))
200 pDDELink
->SetMode(SC_DDE_ENGLISH
);
201 else if (IsXMLToken(aIter
, XML_KEEP_TEXT
))
202 pDDELink
->SetMode(SC_DDE_TEXT
);
204 pDDELink
->SetMode(SC_DDE_DEFAULT
);
210 ScXMLDDESourceContext::~ScXMLDDESourceContext()
214 void SAL_CALL
ScXMLDDESourceContext::endFastElement( sal_Int32
/*nElement*/ )
216 pDDELink
->CreateDDELink();
219 ScXMLDDETableContext::ScXMLDDETableContext( ScXMLImport
& rImport
,
220 ScXMLDDELinkContext
* pTempDDELink
) :
221 ScXMLImportContext( rImport
),
222 pDDELink(pTempDDELink
)
224 // here are no attributes
227 ScXMLDDETableContext::~ScXMLDDETableContext()
231 uno::Reference
< xml::sax::XFastContextHandler
> SAL_CALL
ScXMLDDETableContext::createFastChildContext(
232 sal_Int32 nElement
, const uno::Reference
< xml::sax::XFastAttributeList
>& xAttrList
)
234 SvXMLImportContext
*pContext
= nullptr;
235 sax_fastparser::FastAttributeList
*pAttribList
=
236 &sax_fastparser::castToFastAttributeList( xAttrList
);
240 case XML_ELEMENT( TABLE
, XML_TABLE_COLUMN
):
241 pContext
= new ScXMLDDEColumnContext(GetScImport(), pAttribList
, pDDELink
);
243 case XML_ELEMENT( TABLE
, XML_TABLE_ROW
):
244 pContext
= new ScXMLDDERowContext(GetScImport(), pAttribList
, pDDELink
);
251 ScXMLDDEColumnContext::ScXMLDDEColumnContext( ScXMLImport
& rImport
,
252 const rtl::Reference
<sax_fastparser::FastAttributeList
>& rAttrList
,
253 ScXMLDDELinkContext
* pDDELink
) :
254 ScXMLImportContext( rImport
)
256 if ( rAttrList
.is() )
259 auto aIter( rAttrList
->find( XML_ELEMENT( TABLE
, XML_NUMBER_COLUMNS_REPEATED
) ) );
260 if (aIter
!= rAttrList
->end())
261 nCols
= aIter
.toInt32();
263 pDDELink
->AddColumns(nCols
);
267 ScXMLDDEColumnContext::~ScXMLDDEColumnContext()
271 ScXMLDDERowContext::ScXMLDDERowContext( ScXMLImport
& rImport
,
272 const rtl::Reference
<sax_fastparser::FastAttributeList
>& rAttrList
,
273 ScXMLDDELinkContext
* pTempDDELink
) :
274 ScXMLImportContext( rImport
),
275 pDDELink(pTempDDELink
),
278 if ( rAttrList
.is() )
280 auto aIter( rAttrList
->find( XML_ELEMENT( TABLE
, XML_NUMBER_ROWS_REPEATED
) ) );
281 if (aIter
!= rAttrList
->end())
282 nRows
= aIter
.toInt32();
284 pDDELink
->AddRows(nRows
);
288 ScXMLDDERowContext::~ScXMLDDERowContext()
292 uno::Reference
< xml::sax::XFastContextHandler
> SAL_CALL
ScXMLDDERowContext::createFastChildContext(
293 sal_Int32 nElement
, const uno::Reference
< xml::sax::XFastAttributeList
>& xAttrList
)
295 SvXMLImportContext
*pContext
= nullptr;
296 sax_fastparser::FastAttributeList
*pAttribList
=
297 &sax_fastparser::castToFastAttributeList( xAttrList
);
299 if (nElement
== XML_ELEMENT( TABLE
, XML_TABLE_CELL
))
300 pContext
= new ScXMLDDECellContext(GetScImport(), pAttribList
, pDDELink
);
305 void SAL_CALL
ScXMLDDERowContext::endFastElement( sal_Int32
/*nElement*/ )
307 pDDELink
->AddRowsToTable(nRows
);
310 ScXMLDDECellContext::ScXMLDDECellContext( ScXMLImport
& rImport
,
311 const rtl::Reference
<sax_fastparser::FastAttributeList
>& rAttrList
,
312 ScXMLDDELinkContext
* pTempDDELink
) :
313 ScXMLImportContext( rImport
),
320 pDDELink(pTempDDELink
)
322 if ( !rAttrList
.is() )
325 for (auto &aIter
: *rAttrList
)
327 switch (aIter
.getToken())
329 case XML_ELEMENT( OFFICE
, XML_VALUE_TYPE
):
330 if (IsXMLToken(aIter
, XML_STRING
))
335 case XML_ELEMENT( OFFICE
, XML_STRING_VALUE
):
336 sValue
= aIter
.toString();
340 case XML_ELEMENT( OFFICE
, XML_VALUE
):
341 fValue
= aIter
.toDouble();
345 case XML_ELEMENT( TABLE
, XML_NUMBER_COLUMNS_REPEATED
):
346 nCells
= aIter
.toInt32();
352 ScXMLDDECellContext::~ScXMLDDECellContext()
356 void SAL_CALL
ScXMLDDECellContext::endFastElement( sal_Int32
/*nElement*/ )
358 OSL_ENSURE(bString
== bString2
, "something wrong with this type");
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
);
368 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */