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
),
63 // here are no attributes
66 ScXMLDDELinkContext::~ScXMLDDELinkContext()
70 uno::Reference
< xml::sax::XFastContextHandler
> SAL_CALL
ScXMLDDELinkContext::createFastChildContext(
71 sal_Int32 nElement
, const uno::Reference
< xml::sax::XFastAttributeList
>& xAttrList
)
73 SvXMLImportContext
*pContext
= nullptr;
74 sax_fastparser::FastAttributeList
*pAttribList
=
75 &sax_fastparser::castToFastAttributeList( xAttrList
);
79 case XML_ELEMENT( OFFICE
, XML_DDE_SOURCE
):
80 pContext
= new ScXMLDDESourceContext(GetScImport(), pAttribList
, this);
82 case XML_ELEMENT( TABLE
, XML_TABLE
):
83 pContext
= new ScXMLDDETableContext(GetScImport(), this);
90 void ScXMLDDELinkContext::CreateDDELink()
92 if (GetScImport().GetDocument() &&
93 !sApplication
.isEmpty() &&
97 GetScImport().GetDocument()->CreateDdeLink(sApplication
, sTopic
, sItem
, nMode
, ScMatrixRef());
99 if(GetScImport().GetDocument()->FindDdeLink(sApplication
, sTopic
, sItem
, nMode
, nPos
))
104 SAL_WARN("sc" , "DDE Link not inserted");
109 void ScXMLDDELinkContext::AddCellToRow(const ScDDELinkCell
& aCell
)
111 aDDELinkRow
.push_back(aCell
);
114 void ScXMLDDELinkContext::AddRowsToTable(const sal_Int32 nRowsP
)
116 for (sal_Int32 i
= 0; i
< nRowsP
; ++i
)
117 aDDELinkTable
.insert(aDDELinkTable
.end(), aDDELinkRow
.begin(), aDDELinkRow
.end());
121 void SAL_CALL
ScXMLDDELinkContext::endFastElement( sal_Int32
/*nElement*/ )
123 ScDocument
* pDoc
= GetScImport().GetDocument();
124 if (!(nPosition
> -1 && nColumns
&& nRows
))
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)
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");
140 ScMatrixRef pMatrix
= new ScMatrix(static_cast<SCSIZE
>(nColumns
), static_cast<SCSIZE
>(nRows
), 0.0);
145 svl::SharedStringPool
& rPool
= pDoc
->GetSharedStringPool();
146 for (const auto& rDDELinkCell
: aDDELinkTable
)
148 if (nIndex
% nColumns
== 0)
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
);
163 pMatrix
->PutDouble( rDDELinkCell
.fValue
, nScCol
, nScRow
);
168 GetScImport().GetDocument()->SetDdeLinkResultMatrix( static_cast< sal_uInt16
>( nPosition
), pMatrix
);
171 ScXMLDDESourceContext::ScXMLDDESourceContext( ScXMLImport
& rImport
,
172 const rtl::Reference
<sax_fastparser::FastAttributeList
>& rAttrList
,
173 ScXMLDDELinkContext
* pTempDDELink
) :
174 ScXMLImportContext( rImport
),
175 pDDELink(pTempDDELink
)
177 if ( !rAttrList
.is() )
180 for (auto &aIter
: *rAttrList
)
182 switch (aIter
.getToken())
184 case XML_ELEMENT( OFFICE
, XML_DDE_APPLICATION
):
185 pDDELink
->SetApplication(aIter
.toString());
187 case XML_ELEMENT( OFFICE
, XML_DDE_TOPIC
):
188 pDDELink
->SetTopic(aIter
.toString());
190 case XML_ELEMENT( OFFICE
, XML_DDE_ITEM
):
191 pDDELink
->SetItem(aIter
.toString());
193 case XML_ELEMENT( TABLE
, XML_CONVERSION_MODE
):
194 if (IsXMLToken(aIter
, XML_INTO_ENGLISH_NUMBER
))
195 pDDELink
->SetMode(SC_DDE_ENGLISH
);
196 else if (IsXMLToken(aIter
, XML_KEEP_TEXT
))
197 pDDELink
->SetMode(SC_DDE_TEXT
);
199 pDDELink
->SetMode(SC_DDE_DEFAULT
);
205 ScXMLDDESourceContext::~ScXMLDDESourceContext()
209 void SAL_CALL
ScXMLDDESourceContext::endFastElement( sal_Int32
/*nElement*/ )
211 pDDELink
->CreateDDELink();
214 ScXMLDDETableContext::ScXMLDDETableContext( ScXMLImport
& rImport
,
215 ScXMLDDELinkContext
* pTempDDELink
) :
216 ScXMLImportContext( rImport
),
217 pDDELink(pTempDDELink
)
219 // here are no attributes
222 ScXMLDDETableContext::~ScXMLDDETableContext()
226 uno::Reference
< xml::sax::XFastContextHandler
> SAL_CALL
ScXMLDDETableContext::createFastChildContext(
227 sal_Int32 nElement
, const uno::Reference
< xml::sax::XFastAttributeList
>& xAttrList
)
229 SvXMLImportContext
*pContext
= nullptr;
230 sax_fastparser::FastAttributeList
*pAttribList
=
231 &sax_fastparser::castToFastAttributeList( xAttrList
);
235 case XML_ELEMENT( TABLE
, XML_TABLE_COLUMN
):
236 pContext
= new ScXMLDDEColumnContext(GetScImport(), pAttribList
, pDDELink
);
238 case XML_ELEMENT( TABLE
, XML_TABLE_ROW
):
239 pContext
= new ScXMLDDERowContext(GetScImport(), pAttribList
, pDDELink
);
246 ScXMLDDEColumnContext::ScXMLDDEColumnContext( ScXMLImport
& rImport
,
247 const rtl::Reference
<sax_fastparser::FastAttributeList
>& rAttrList
,
248 ScXMLDDELinkContext
* pDDELink
) :
249 ScXMLImportContext( rImport
)
251 if ( rAttrList
.is() )
254 auto aIter( rAttrList
->find( XML_ELEMENT( TABLE
, XML_NUMBER_COLUMNS_REPEATED
) ) );
255 if (aIter
!= rAttrList
->end())
256 nCols
= aIter
.toInt32();
258 pDDELink
->AddColumns(nCols
);
262 ScXMLDDEColumnContext::~ScXMLDDEColumnContext()
266 ScXMLDDERowContext::ScXMLDDERowContext( ScXMLImport
& rImport
,
267 const rtl::Reference
<sax_fastparser::FastAttributeList
>& rAttrList
,
268 ScXMLDDELinkContext
* pTempDDELink
) :
269 ScXMLImportContext( rImport
),
270 pDDELink(pTempDDELink
),
273 if ( rAttrList
.is() )
275 auto aIter( rAttrList
->find( XML_ELEMENT( TABLE
, XML_NUMBER_ROWS_REPEATED
) ) );
276 if (aIter
!= rAttrList
->end())
277 nRows
= aIter
.toInt32();
279 pDDELink
->AddRows(nRows
);
283 ScXMLDDERowContext::~ScXMLDDERowContext()
287 uno::Reference
< xml::sax::XFastContextHandler
> SAL_CALL
ScXMLDDERowContext::createFastChildContext(
288 sal_Int32 nElement
, const uno::Reference
< xml::sax::XFastAttributeList
>& xAttrList
)
290 SvXMLImportContext
*pContext
= nullptr;
291 sax_fastparser::FastAttributeList
*pAttribList
=
292 &sax_fastparser::castToFastAttributeList( xAttrList
);
294 if (nElement
== XML_ELEMENT( TABLE
, XML_TABLE_CELL
))
295 pContext
= new ScXMLDDECellContext(GetScImport(), pAttribList
, pDDELink
);
300 void SAL_CALL
ScXMLDDERowContext::endFastElement( sal_Int32
/*nElement*/ )
302 pDDELink
->AddRowsToTable(nRows
);
305 ScXMLDDECellContext::ScXMLDDECellContext( ScXMLImport
& rImport
,
306 const rtl::Reference
<sax_fastparser::FastAttributeList
>& rAttrList
,
307 ScXMLDDELinkContext
* pTempDDELink
) :
308 ScXMLImportContext( rImport
),
314 pDDELink(pTempDDELink
)
316 if ( !rAttrList
.is() )
319 for (auto &aIter
: *rAttrList
)
321 switch (aIter
.getToken())
323 case XML_ELEMENT( OFFICE
, XML_VALUE_TYPE
):
324 if (IsXMLToken(aIter
, XML_STRING
))
329 case XML_ELEMENT( OFFICE
, XML_STRING_VALUE
):
330 sValue
= aIter
.toString();
334 case XML_ELEMENT( OFFICE
, XML_VALUE
):
335 fValue
= aIter
.toDouble();
339 case XML_ELEMENT( TABLE
, XML_NUMBER_COLUMNS_REPEATED
):
340 nCells
= aIter
.toInt32();
346 ScXMLDDECellContext::~ScXMLDDECellContext()
350 void SAL_CALL
ScXMLDDECellContext::endFastElement( sal_Int32
/*nElement*/ )
352 OSL_ENSURE(bString
== bString2
, "something wrong with this type");
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
);
362 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */