Line data Source code
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/xmlnmspe.hxx>
26 : #include <xmloff/nmspmap.hxx>
27 : #include <sax/tools/converter.hxx>
28 : #include <svl/sharedstringpool.hxx>
29 :
30 : using namespace com::sun::star;
31 : using namespace xmloff::token;
32 :
33 0 : ScXMLDDELinksContext::ScXMLDDELinksContext( ScXMLImport& rImport,
34 : sal_uInt16 nPrfx,
35 : const OUString& rLName,
36 : const ::com::sun::star::uno::Reference<
37 : ::com::sun::star::xml::sax::XAttributeList>& /* xAttrList */ ) :
38 0 : SvXMLImportContext( rImport, nPrfx, rLName )
39 : {
40 : // here are no attributes
41 0 : rImport.LockSolarMutex();
42 0 : }
43 :
44 0 : ScXMLDDELinksContext::~ScXMLDDELinksContext()
45 : {
46 0 : GetScImport().UnlockSolarMutex();
47 0 : }
48 :
49 0 : SvXMLImportContext *ScXMLDDELinksContext::CreateChildContext( sal_uInt16 nPrefix,
50 : const OUString& rLName,
51 : const ::com::sun::star::uno::Reference<
52 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList )
53 : {
54 0 : SvXMLImportContext *pContext = 0;
55 :
56 0 : if ((nPrefix == XML_NAMESPACE_TABLE) && IsXMLToken(rLName, XML_DDE_LINK))
57 0 : pContext = new ScXMLDDELinkContext(GetScImport(), nPrefix, rLName, xAttrList);
58 :
59 0 : if( !pContext )
60 0 : pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
61 :
62 0 : return pContext;
63 : }
64 :
65 0 : void ScXMLDDELinksContext::EndElement()
66 : {
67 0 : }
68 :
69 0 : ScXMLDDELinkContext::ScXMLDDELinkContext( ScXMLImport& rImport,
70 : sal_uInt16 nPrfx,
71 : const OUString& rLName,
72 : const ::com::sun::star::uno::Reference<
73 : ::com::sun::star::xml::sax::XAttributeList>& /* xAttrList */ ) :
74 : SvXMLImportContext( rImport, nPrfx, rLName ),
75 : aDDELinkTable(),
76 : aDDELinkRow(),
77 : sApplication(),
78 : sTopic(),
79 : sItem(),
80 : nPosition(-1),
81 : nColumns(0),
82 : nRows(0),
83 0 : nMode(SC_DDE_DEFAULT)
84 : {
85 : // here are no attributes
86 0 : }
87 :
88 0 : ScXMLDDELinkContext::~ScXMLDDELinkContext()
89 : {
90 0 : }
91 :
92 0 : SvXMLImportContext *ScXMLDDELinkContext::CreateChildContext( sal_uInt16 nPrefix,
93 : const OUString& rLName,
94 : const ::com::sun::star::uno::Reference<
95 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList )
96 : {
97 0 : SvXMLImportContext *pContext = 0;
98 :
99 0 : if ((nPrefix == XML_NAMESPACE_OFFICE) && IsXMLToken(rLName, XML_DDE_SOURCE))
100 0 : pContext = new ScXMLDDESourceContext(GetScImport(), nPrefix, rLName, xAttrList, this);
101 0 : else if ((nPrefix == XML_NAMESPACE_TABLE) && IsXMLToken(rLName, XML_TABLE))
102 0 : pContext = new ScXMLDDETableContext(GetScImport(), nPrefix, rLName, xAttrList, this);
103 :
104 0 : if( !pContext )
105 0 : pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
106 :
107 0 : return pContext;
108 : }
109 :
110 0 : void ScXMLDDELinkContext::CreateDDELink()
111 : {
112 0 : if (GetScImport().GetDocument() &&
113 0 : !sApplication.isEmpty() &&
114 0 : !sTopic.isEmpty() &&
115 0 : !sItem.isEmpty())
116 : {
117 0 : GetScImport().GetDocument()->CreateDdeLink(sApplication, sTopic, sItem, nMode, ScMatrixRef());
118 : size_t nPos;
119 0 : if(GetScImport().GetDocument()->FindDdeLink(sApplication, sTopic, sItem, nMode, nPos))
120 0 : nPosition = nPos;
121 : else
122 : {
123 0 : nPosition = -1;
124 : SAL_WARN("sc" , "DDE Link not inserted");
125 : }
126 : }
127 0 : }
128 :
129 0 : void ScXMLDDELinkContext::AddCellToRow(const ScDDELinkCell& aCell)
130 : {
131 0 : aDDELinkRow.push_back(aCell);
132 0 : }
133 :
134 0 : void ScXMLDDELinkContext::AddRowsToTable(const sal_Int32 nRowsP)
135 : {
136 0 : for (sal_Int32 i = 0; i < nRowsP; ++i)
137 0 : aDDELinkTable.insert(aDDELinkTable.end(), aDDELinkRow.begin(), aDDELinkRow.end());
138 0 : aDDELinkRow.clear();
139 0 : }
140 :
141 0 : void ScXMLDDELinkContext::EndElement()
142 : {
143 0 : ScDocument* pDoc = GetScImport().GetDocument();
144 0 : if (nPosition > -1 && nColumns && nRows)
145 : {
146 0 : bool bSizeMatch = (static_cast<size_t>(nColumns * nRows) == aDDELinkTable.size());
147 : OSL_ENSURE( bSizeMatch, "ScXMLDDELinkContext::EndElement: matrix dimension doesn't match cells count");
148 : // Excel writes bad ODF in that it does not write the
149 : // table:number-columns-repeated attribute of the
150 : // <table:table-column> element, but apparently uses the number of
151 : // <table:table-cell> elements within a <table:table-row> element to
152 : // determine the column count instead. Be lenient ...
153 0 : if (!bSizeMatch && nColumns == 1)
154 : {
155 0 : nColumns = aDDELinkTable.size() / nRows;
156 : OSL_ENSURE( static_cast<size_t>(nColumns * nRows) == aDDELinkTable.size(),
157 : "ScXMLDDELinkContext::EndElement: adapted matrix dimension doesn't match either");
158 : }
159 0 : ScMatrixRef pMatrix = new ScMatrix(static_cast<SCSIZE>(nColumns), static_cast<SCSIZE>(nRows), 0.0);
160 0 : sal_Int32 nCol(0);
161 0 : sal_Int32 nRow(-1);
162 0 : sal_Int32 nIndex(0);
163 0 : ScDDELinkCells::iterator aItr(aDDELinkTable.begin());
164 0 : ScDDELinkCells::iterator aEndItr(aDDELinkTable.end());
165 :
166 0 : svl::SharedStringPool& rPool = pDoc->GetSharedStringPool();
167 0 : while (aItr != aEndItr)
168 : {
169 0 : if (nIndex % nColumns == 0)
170 : {
171 0 : ++nRow;
172 0 : nCol = 0;
173 : }
174 : else
175 0 : ++nCol;
176 :
177 0 : SCSIZE nScCol( static_cast< SCSIZE >( nCol ) );
178 0 : SCSIZE nScRow( static_cast< SCSIZE >( nRow ) );
179 0 : if( aItr->bEmpty )
180 0 : pMatrix->PutEmpty( nScCol, nScRow );
181 0 : else if( aItr->bString )
182 0 : pMatrix->PutString(rPool.intern(aItr->sValue), nScCol, nScRow);
183 : else
184 0 : pMatrix->PutDouble( aItr->fValue, nScCol, nScRow );
185 :
186 0 : ++nIndex;
187 0 : ++aItr;
188 : }
189 :
190 0 : GetScImport().GetDocument()->SetDdeLinkResultMatrix( static_cast< sal_uInt16 >( nPosition ), pMatrix );
191 : }
192 0 : }
193 :
194 0 : ScXMLDDESourceContext::ScXMLDDESourceContext( ScXMLImport& rImport,
195 : sal_uInt16 nPrfx,
196 : const OUString& rLName,
197 : const ::com::sun::star::uno::Reference<
198 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
199 : ScXMLDDELinkContext* pTempDDELink) :
200 : SvXMLImportContext( rImport, nPrfx, rLName ),
201 0 : pDDELink(pTempDDELink)
202 : {
203 0 : if( !xAttrList.is() ) return;
204 :
205 0 : sal_Int16 nAttrCount = xAttrList->getLength();
206 :
207 0 : for( sal_Int16 nIndex = 0; nIndex < nAttrCount; ++nIndex )
208 : {
209 0 : const OUString& sAttrName (xAttrList->getNameByIndex( nIndex ));
210 0 : const OUString& sValue (xAttrList->getValueByIndex( nIndex ));
211 0 : OUString aLocalName;
212 0 : sal_uInt16 nPrefix = GetScImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
213 :
214 0 : if (nPrefix == XML_NAMESPACE_OFFICE)
215 : {
216 0 : if (IsXMLToken(aLocalName, XML_DDE_APPLICATION))
217 0 : pDDELink->SetApplication(sValue);
218 0 : else if (IsXMLToken(aLocalName, XML_DDE_TOPIC))
219 0 : pDDELink->SetTopic(sValue);
220 0 : else if (IsXMLToken(aLocalName, XML_DDE_ITEM))
221 0 : pDDELink->SetItem(sValue);
222 : }
223 0 : else if ((nPrefix == XML_NAMESPACE_TABLE) && IsXMLToken(aLocalName, XML_CONVERSION_MODE))
224 : {
225 0 : if (IsXMLToken(sValue, XML_INTO_ENGLISH_NUMBER))
226 0 : pDDELink->SetMode(SC_DDE_ENGLISH);
227 0 : else if (IsXMLToken(sValue, XML_KEEP_TEXT))
228 0 : pDDELink->SetMode(SC_DDE_TEXT);
229 : else
230 0 : pDDELink->SetMode(SC_DDE_DEFAULT);
231 : }
232 0 : }
233 : }
234 :
235 0 : ScXMLDDESourceContext::~ScXMLDDESourceContext()
236 : {
237 0 : }
238 :
239 0 : SvXMLImportContext *ScXMLDDESourceContext::CreateChildContext( sal_uInt16 nPrefix,
240 : const OUString& rLName,
241 : const ::com::sun::star::uno::Reference<
242 : ::com::sun::star::xml::sax::XAttributeList>& /* xAttrList */ )
243 : {
244 0 : SvXMLImportContext *pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
245 :
246 0 : return pContext;
247 : }
248 :
249 0 : void ScXMLDDESourceContext::EndElement()
250 : {
251 0 : pDDELink->CreateDDELink();
252 0 : }
253 :
254 0 : ScXMLDDETableContext::ScXMLDDETableContext( ScXMLImport& rImport,
255 : sal_uInt16 nPrfx,
256 : const OUString& rLName,
257 : const ::com::sun::star::uno::Reference<
258 : ::com::sun::star::xml::sax::XAttributeList>& /* xAttrList */,
259 : ScXMLDDELinkContext* pTempDDELink) :
260 : SvXMLImportContext( rImport, nPrfx, rLName ),
261 0 : pDDELink(pTempDDELink)
262 : {
263 : // here are no attributes
264 0 : }
265 :
266 0 : ScXMLDDETableContext::~ScXMLDDETableContext()
267 : {
268 0 : }
269 :
270 0 : SvXMLImportContext *ScXMLDDETableContext::CreateChildContext( sal_uInt16 nPrefix,
271 : const OUString& rLName,
272 : const ::com::sun::star::uno::Reference<
273 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList )
274 : {
275 0 : SvXMLImportContext *pContext = NULL;
276 :
277 0 : if (nPrefix == XML_NAMESPACE_TABLE)
278 : {
279 0 : if (IsXMLToken(rLName, XML_TABLE_COLUMN))
280 0 : pContext = new ScXMLDDEColumnContext(GetScImport(), nPrefix, rLName, xAttrList, pDDELink);
281 0 : else if (IsXMLToken(rLName, XML_TABLE_ROW))
282 0 : pContext = new ScXMLDDERowContext(GetScImport(), nPrefix, rLName, xAttrList, pDDELink);
283 : }
284 :
285 0 : if (!pContext)
286 0 : pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
287 :
288 0 : return pContext;
289 : }
290 :
291 0 : void ScXMLDDETableContext::EndElement()
292 : {
293 0 : }
294 :
295 0 : ScXMLDDEColumnContext::ScXMLDDEColumnContext( ScXMLImport& rImport,
296 : sal_uInt16 nPrfx,
297 : const OUString& rLName,
298 : const ::com::sun::star::uno::Reference<
299 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
300 : ScXMLDDELinkContext* pTempDDELink) :
301 : SvXMLImportContext( rImport, nPrfx, rLName ),
302 0 : pDDELink(pTempDDELink)
303 : {
304 0 : if( !xAttrList.is() ) return;
305 0 : sal_Int32 nCols(1);
306 :
307 0 : sal_Int16 nAttrCount = xAttrList->getLength();
308 :
309 0 : for( sal_Int16 nIndex = 0; nIndex < nAttrCount; ++nIndex )
310 : {
311 0 : const OUString& sAttrName (xAttrList->getNameByIndex( nIndex ));
312 0 : const OUString& sValue (xAttrList->getValueByIndex( nIndex ));
313 0 : OUString aLocalName;
314 0 : sal_uInt16 nPrefix = GetScImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
315 :
316 0 : if (nPrefix == XML_NAMESPACE_TABLE)
317 0 : if (IsXMLToken(aLocalName, XML_NUMBER_COLUMNS_REPEATED))
318 : {
319 0 : ::sax::Converter::convertNumber(nCols, sValue);
320 : }
321 0 : }
322 0 : pDDELink->AddColumns(nCols);
323 : }
324 :
325 0 : ScXMLDDEColumnContext::~ScXMLDDEColumnContext()
326 : {
327 0 : }
328 :
329 0 : SvXMLImportContext *ScXMLDDEColumnContext::CreateChildContext( sal_uInt16 nPrefix,
330 : const OUString& rLName,
331 : const ::com::sun::star::uno::Reference<
332 : ::com::sun::star::xml::sax::XAttributeList>& /* xAttrList */ )
333 : {
334 0 : SvXMLImportContext *pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
335 :
336 0 : return pContext;
337 : }
338 :
339 0 : void ScXMLDDEColumnContext::EndElement()
340 : {
341 0 : }
342 :
343 0 : ScXMLDDERowContext::ScXMLDDERowContext( ScXMLImport& rImport,
344 : sal_uInt16 nPrfx,
345 : const OUString& rLName,
346 : const ::com::sun::star::uno::Reference<
347 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
348 : ScXMLDDELinkContext* pTempDDELink) :
349 : SvXMLImportContext( rImport, nPrfx, rLName ),
350 : pDDELink(pTempDDELink),
351 0 : nRows(1)
352 : {
353 0 : if( !xAttrList.is() ) return;
354 :
355 0 : sal_Int16 nAttrCount = xAttrList->getLength();
356 :
357 0 : for( sal_Int16 nIndex = 0; nIndex < nAttrCount; ++nIndex )
358 : {
359 0 : const OUString& sAttrName (xAttrList->getNameByIndex( nIndex ));
360 0 : const OUString& sValue (xAttrList->getValueByIndex( nIndex ));
361 0 : OUString aLocalName;
362 0 : sal_uInt16 nPrefix = GetScImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
363 :
364 0 : if (nPrefix == XML_NAMESPACE_TABLE)
365 0 : if (IsXMLToken(aLocalName, XML_NUMBER_ROWS_REPEATED))
366 : {
367 0 : ::sax::Converter::convertNumber(nRows, sValue);
368 : }
369 0 : }
370 0 : pDDELink->AddRows(nRows);
371 : }
372 :
373 0 : ScXMLDDERowContext::~ScXMLDDERowContext()
374 : {
375 0 : }
376 :
377 0 : SvXMLImportContext *ScXMLDDERowContext::CreateChildContext( sal_uInt16 nPrefix,
378 : const OUString& rLName,
379 : const ::com::sun::star::uno::Reference<
380 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList )
381 : {
382 0 : SvXMLImportContext *pContext = NULL;
383 :
384 0 : if (nPrefix == XML_NAMESPACE_TABLE)
385 0 : if (IsXMLToken(rLName, XML_TABLE_CELL))
386 0 : pContext = new ScXMLDDECellContext(GetScImport(), nPrefix, rLName, xAttrList, pDDELink);
387 :
388 0 : if (!pContext)
389 0 : pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
390 :
391 0 : return pContext;
392 : }
393 :
394 0 : void ScXMLDDERowContext::EndElement()
395 : {
396 0 : pDDELink->AddRowsToTable(nRows);
397 0 : }
398 :
399 0 : ScXMLDDECellContext::ScXMLDDECellContext( ScXMLImport& rImport,
400 : sal_uInt16 nPrfx,
401 : const OUString& rLName,
402 : const ::com::sun::star::uno::Reference<
403 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
404 : ScXMLDDELinkContext* pTempDDELink) :
405 : SvXMLImportContext( rImport, nPrfx, rLName ),
406 : sValue(),
407 : fValue(),
408 : nCells(1),
409 : bString(true),
410 : bString2(true),
411 : bEmpty(true),
412 0 : pDDELink(pTempDDELink)
413 : {
414 0 : if( !xAttrList.is() ) return;
415 :
416 0 : sal_Int16 nAttrCount = xAttrList->getLength();
417 :
418 0 : for( sal_Int16 nIndex = 0; nIndex < nAttrCount; ++nIndex )
419 : {
420 0 : const OUString& sAttrName (xAttrList->getNameByIndex( nIndex ));
421 0 : const OUString& sTempValue (xAttrList->getValueByIndex( nIndex ));
422 0 : OUString aLocalName;
423 0 : sal_uInt16 nPrefix = GetScImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
424 :
425 0 : if (nPrefix == XML_NAMESPACE_OFFICE)
426 : {
427 0 : if (IsXMLToken(aLocalName, XML_VALUE_TYPE))
428 : {
429 0 : if (IsXMLToken(sTempValue, XML_STRING))
430 0 : bString = true;
431 : else
432 0 : bString = false;
433 : }
434 0 : else if (IsXMLToken(aLocalName, XML_STRING_VALUE))
435 : {
436 0 : sValue = sTempValue;
437 0 : bEmpty = false;
438 0 : bString2 = true;
439 : }
440 0 : else if (IsXMLToken(aLocalName, XML_VALUE))
441 : {
442 0 : ::sax::Converter::convertDouble(fValue, sTempValue);
443 0 : bEmpty = false;
444 0 : bString2 = false;
445 : }
446 : }
447 0 : else if (nPrefix == XML_NAMESPACE_TABLE)
448 : {
449 0 : if (IsXMLToken(aLocalName, XML_NUMBER_COLUMNS_REPEATED))
450 : {
451 0 : ::sax::Converter::convertNumber(nCells, sTempValue);
452 : }
453 : }
454 0 : }
455 : }
456 :
457 0 : ScXMLDDECellContext::~ScXMLDDECellContext()
458 : {
459 0 : }
460 :
461 0 : SvXMLImportContext *ScXMLDDECellContext::CreateChildContext( sal_uInt16 nPrefix,
462 : const OUString& rLName,
463 : const ::com::sun::star::uno::Reference<
464 : ::com::sun::star::xml::sax::XAttributeList>& /* xAttrList */ )
465 : {
466 0 : SvXMLImportContext *pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
467 :
468 0 : return pContext;
469 : }
470 :
471 0 : void ScXMLDDECellContext::EndElement()
472 : {
473 : OSL_ENSURE(bString == bString2, "something wrong with this type");
474 0 : ScDDELinkCell aCell;
475 0 : aCell.sValue = sValue;
476 0 : aCell.fValue = fValue;
477 0 : aCell.bEmpty = bEmpty;
478 0 : aCell.bString = bString2;
479 0 : for(sal_Int32 i = 0; i < nCells; ++i)
480 0 : pDDELink->AddCellToRow(aCell);
481 228 : }
482 :
483 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|