tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sc / source / filter / xml / xmlexternaltabi.cxx
blob7931440c12d0106834caa5fe65249290369e561f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 "xmlexternaltabi.hxx"
21 #include "xmlimprt.hxx"
22 #include "xmltabi.hxx"
23 #include "xmlstyli.hxx"
25 #include <document.hxx>
26 #include <documentimport.hxx>
28 #include <svl/sharedstringpool.hxx>
29 #include <xmloff/xmlnamespace.hxx>
30 #include <xmloff/xmltoken.hxx>
31 #include <xmloff/xmluconv.hxx>
33 #include <sax/tools/converter.hxx>
35 #include <com/sun/star/util/NumberFormat.hpp>
37 using namespace ::com::sun::star;
38 using namespace ::com::sun::star::xml::sax;
39 using namespace ::xmloff::token;
41 using ::com::sun::star::uno::Reference;
43 ScXMLExternalRefTabSourceContext::ScXMLExternalRefTabSourceContext(
44 ScXMLImport& rImport,
45 const rtl::Reference<sax_fastparser::FastAttributeList>& rAttrList, ScXMLExternalTabData& rRefInfo ) :
46 ScXMLImportContext( rImport ),
47 mrExternalRefInfo(rRefInfo)
49 using namespace ::xmloff::token;
51 if ( !rAttrList.is() )
52 return;
54 for (auto &it : *rAttrList)
56 sal_Int32 nAttrToken = it.getToken();
57 if ( nAttrToken == XML_ELEMENT( XLINK, XML_HREF ) )
58 maRelativeUrl = it.toString();
59 else if ( nAttrToken == XML_ELEMENT( TABLE, XML_TABLE_NAME ) )
60 // todo
62 else if ( nAttrToken == XML_ELEMENT( TABLE, XML_FILTER_NAME ) )
63 maFilterName = it.toString();
64 else if ( nAttrToken == XML_ELEMENT( TABLE, XML_FILTER_OPTIONS ) )
65 maFilterOptions = it.toString();
69 ScXMLExternalRefTabSourceContext::~ScXMLExternalRefTabSourceContext()
73 /**
74 * Make sure the URL is a valid relative URL, mainly to avoid storing
75 * absolute URL as relative URL by accident. For now, we only check the first
76 * three characters which are assumed to be always '../', because the relative
77 * URL for an external document is always in reference to the content.xml
78 * fragment of the original document.
80 static bool lcl_isValidRelativeURL(const OUString& rUrl)
82 sal_Int32 n = ::std::min( rUrl.getLength(), static_cast<sal_Int32>(3));
83 if (n < 3)
84 return false;
85 const sal_Unicode* p = rUrl.getStr();
86 for (sal_Int32 i = 0; i < n; ++i)
88 sal_Unicode c = p[i];
89 if (i < 2 && c != '.')
90 // the path must begin with '..'
91 return false;
92 else if (i == 2 && c != '/')
93 // a '/' path separator must follow
94 return false;
96 return true;
99 void SAL_CALL ScXMLExternalRefTabSourceContext::endFastElement( sal_Int32 /*nElement*/ )
101 ScDocument* pDoc = GetScImport().GetDocument();
102 if (!pDoc)
103 return;
105 ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
106 if (lcl_isValidRelativeURL(maRelativeUrl))
107 pRefMgr->setRelativeFileName(mrExternalRefInfo.mnFileId, maRelativeUrl);
108 pRefMgr->setFilterData(mrExternalRefInfo.mnFileId, maFilterName, maFilterOptions);
111 ScXMLExternalRefRowsContext::ScXMLExternalRefRowsContext(
112 ScXMLImport& rImport, ScXMLExternalTabData& rRefInfo ) :
113 ScXMLImportContext( rImport ),
114 mrExternalRefInfo(rRefInfo)
118 ScXMLExternalRefRowsContext::~ScXMLExternalRefRowsContext()
122 Reference< XFastContextHandler > SAL_CALL ScXMLExternalRefRowsContext::createFastChildContext(
123 sal_Int32 nElement, const Reference< XFastAttributeList >& xAttrList )
125 // #i101319# row elements inside group, rows or header-rows
126 // are treated like row elements directly in the table element
128 sax_fastparser::FastAttributeList *pAttribList =
129 &sax_fastparser::castToFastAttributeList( xAttrList );
131 switch (nElement)
133 case XML_ELEMENT(TABLE, XML_TABLE_ROW_GROUP):
134 case XML_ELEMENT(TABLE, XML_TABLE_HEADER_ROWS):
135 case XML_ELEMENT(TABLE, XML_TABLE_ROWS):
136 return new ScXMLExternalRefRowsContext(
137 GetScImport(), mrExternalRefInfo);
138 case XML_ELEMENT(TABLE, XML_TABLE_ROW):
139 return new ScXMLExternalRefRowContext(
140 GetScImport(), pAttribList, mrExternalRefInfo);
141 default:
142 XMLOFF_WARN_UNKNOWN_ELEMENT("sc", nElement);
144 return nullptr;
147 ScXMLExternalRefRowContext::ScXMLExternalRefRowContext(
148 ScXMLImport& rImport,
149 const rtl::Reference<sax_fastparser::FastAttributeList>& rAttrList, ScXMLExternalTabData& rRefInfo ) :
150 ScXMLImportContext( rImport ),
151 mrScImport(rImport),
152 mrExternalRefInfo(rRefInfo),
153 mnRepeatRowCount(1)
155 mrExternalRefInfo.mnCol = 0;
157 for (auto &it : *rAttrList)
159 switch (it.getToken())
161 case XML_ELEMENT(TABLE, XML_NUMBER_ROWS_REPEATED):
163 mnRepeatRowCount = std::max(it.toInt32(), static_cast<sal_Int32>(1));
165 break;
170 ScXMLExternalRefRowContext::~ScXMLExternalRefRowContext()
174 Reference< XFastContextHandler > SAL_CALL ScXMLExternalRefRowContext::createFastChildContext(
175 sal_Int32 nElement, const Reference< XFastAttributeList >& xAttrList )
177 sax_fastparser::FastAttributeList *pAttribList =
178 &sax_fastparser::castToFastAttributeList( xAttrList );
180 if (nElement == XML_ELEMENT(TABLE, XML_TABLE_CELL) || nElement == XML_ELEMENT(TABLE, XML_COVERED_TABLE_CELL))
181 return new ScXMLExternalRefCellContext(mrScImport, pAttribList, mrExternalRefInfo);
183 return nullptr;
186 void SAL_CALL ScXMLExternalRefRowContext::endFastElement( sal_Int32 /* nElement */ )
188 ScExternalRefCache::TableTypeRef pTab = mrExternalRefInfo.mpCacheTable;
190 for (sal_Int32 i = 1; i < mnRepeatRowCount; ++i)
192 // Performance: duplicates of a non-existent row will still not exist.
193 // Don't find that out for every cell.
194 // External references often are a sparse matrix.
195 if (i == 1 && !pTab->hasRow( mrExternalRefInfo.mnRow))
197 mrExternalRefInfo.mnRow += mnRepeatRowCount;
198 return;
201 for (sal_Int32 j = 0; j < mrExternalRefInfo.mnCol; ++j)
203 ScExternalRefCache::TokenRef pToken = pTab->getCell(
204 static_cast<SCCOL>(j), static_cast<SCROW>(mrExternalRefInfo.mnRow));
206 if (pToken)
208 pTab->setCell(static_cast<SCCOL>(j),
209 static_cast<SCROW>(mrExternalRefInfo.mnRow+i), pToken);
213 mrExternalRefInfo.mnRow += mnRepeatRowCount;
216 ScXMLExternalRefCellContext::ScXMLExternalRefCellContext(
217 ScXMLImport& rImport,
218 const rtl::Reference<sax_fastparser::FastAttributeList>& rAttrList, ScXMLExternalTabData& rRefInfo ) :
219 ScXMLImportContext( rImport ),
220 mrScImport(rImport),
221 mrExternalRefInfo(rRefInfo),
222 mfCellValue(0.0),
223 mnRepeatCount(1),
224 mnNumberFormat(-1),
225 mnCellType(css::util::NumberFormat::UNDEFINED),
226 mbIsNumeric(false),
227 mbIsEmpty(true)
229 using namespace ::xmloff::token;
231 for (auto &it : *rAttrList)
233 switch ( it.getToken() )
235 case XML_ELEMENT(TABLE, XML_STYLE_NAME):
237 XMLTableStylesContext* pStyles = static_cast<XMLTableStylesContext*>(mrScImport.GetAutoStyles());
238 const XMLTableStyleContext* pStyle = static_cast<const XMLTableStyleContext*>(
239 pStyles->FindStyleChildContext(XmlStyleFamily::TABLE_CELL, it.toString(), true));
240 if (pStyle)
241 mnNumberFormat = const_cast<XMLTableStyleContext*>(pStyle)->GetNumberFormat();
243 break;
244 case XML_ELEMENT(TABLE, XML_NUMBER_COLUMNS_REPEATED):
246 mnRepeatCount = ::std::max( it.toInt32(), static_cast<sal_Int32>(1) );
248 break;
249 case XML_ELEMENT(OFFICE, XML_VALUE_TYPE):
251 mnCellType = ScXMLImport::GetCellType( it.toCString(), it.getLength() );
253 break;
254 case XML_ELEMENT(OFFICE, XML_VALUE):
256 if ( !it.isEmpty() )
258 mfCellValue = it.toDouble();
259 mbIsNumeric = true;
260 mbIsEmpty = false;
263 break;
264 case XML_ELEMENT(OFFICE, XML_DATE_VALUE):
266 if ( !it.isEmpty() && mrScImport.SetNullDateOnUnitConverter() )
268 mrScImport.GetMM100UnitConverter().convertDateTime( mfCellValue, it.toView() );
269 mbIsNumeric = true;
270 mbIsEmpty = false;
273 break;
274 case XML_ELEMENT(OFFICE, XML_TIME_VALUE):
276 if ( !it.isEmpty() )
278 ::sax::Converter::convertDuration( mfCellValue, it.toView() );
279 mbIsNumeric = true;
280 mbIsEmpty = false;
283 break;
284 case XML_ELEMENT(OFFICE, XML_STRING_VALUE):
286 if ( !it.isEmpty() )
288 maCellString = it.toString();
289 mbIsNumeric = false;
290 mbIsEmpty = false;
293 break;
294 case XML_ELEMENT(OFFICE, XML_BOOLEAN_VALUE):
296 if ( !it.isEmpty() )
298 mfCellValue = IsXMLToken( it, XML_TRUE ) ? 1.0 : 0.0;
299 mbIsNumeric = true;
300 mbIsEmpty = false;
303 break;
304 default:
310 ScXMLExternalRefCellContext::~ScXMLExternalRefCellContext()
314 Reference< XFastContextHandler > SAL_CALL ScXMLExternalRefCellContext::createFastChildContext(
315 sal_Int32 nElement, const Reference< XFastAttributeList >& /*xAttrList*/ )
317 if (nElement == XML_ELEMENT(TEXT, XML_P))
318 return new ScXMLExternalRefCellTextContext(mrScImport, *this);
320 return nullptr;
323 void SAL_CALL ScXMLExternalRefCellContext::endFastElement( sal_Int32 /*nElement*/ )
325 if (!maCellString.isEmpty())
326 mbIsEmpty = false;
328 for (sal_Int32 i = 0; i < mnRepeatCount; ++i, ++mrExternalRefInfo.mnCol)
330 if (mbIsEmpty)
331 continue;
333 ScExternalRefCache::TokenRef aToken;
334 if (mbIsNumeric)
335 aToken.reset(new formula::FormulaDoubleToken(mfCellValue));
336 else
338 ScDocument& rDoc = mrScImport.GetDoc().getDoc();
339 svl::SharedString aSS = rDoc.GetSharedStringPool().intern(maCellString);
340 aToken.reset(new formula::FormulaStringToken(std::move(aSS)));
343 sal_uInt32 nNumFmt = mnNumberFormat >= 0 ? static_cast<sal_uInt32>(mnNumberFormat) : 0;
344 mrExternalRefInfo.mpCacheTable->setCell(
345 static_cast<SCCOL>(mrExternalRefInfo.mnCol),
346 static_cast<SCROW>(mrExternalRefInfo.mnRow),
347 aToken, nNumFmt);
351 void ScXMLExternalRefCellContext::SetCellString(const OUString& rStr)
353 maCellString = rStr;
356 ScXMLExternalRefCellTextContext::ScXMLExternalRefCellTextContext(
357 ScXMLImport& rImport,
358 ScXMLExternalRefCellContext& rParent ) :
359 ScXMLImportContext( rImport ),
360 mrParent(rParent)
364 ScXMLExternalRefCellTextContext::~ScXMLExternalRefCellTextContext()
368 void SAL_CALL ScXMLExternalRefCellTextContext::characters( const OUString& rChars )
370 maCellStrBuf.append( rChars );
373 void SAL_CALL ScXMLExternalRefCellTextContext::endFastElement( sal_Int32 /*nElement*/ )
375 mrParent.SetCellString( maCellStrBuf.makeStringAndClear() );
378 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */