xref: /AOO41X/main/sc/source/filter/xml/XMLDDELinksContext.cxx (revision b3f79822e811ac3493b185030a72c3c5a51f32d8)
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