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