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 "xmltabi.hxx"
21 : #include "xmlimprt.hxx"
22 : #include "xmlrowi.hxx"
23 : #include "xmlcoli.hxx"
24 : #include "xmlsceni.hxx"
25 : #include "xmlexternaltabi.hxx"
26 : #include "xmlnexpi.hxx"
27 : #include "document.hxx"
28 : #include "docuno.hxx"
29 : #include "olinetab.hxx"
30 : #include "XMLConverter.hxx"
31 : #include "XMLTableShapesContext.hxx"
32 : #include "XMLTableSourceContext.hxx"
33 : #include "XMLStylesImportHelper.hxx"
34 : #include "rangeutl.hxx"
35 : #include "externalrefmgr.hxx"
36 : #include "sheetdata.hxx"
37 : #include "xmlcondformat.hxx"
38 :
39 : #include <xmloff/xmltkmap.hxx>
40 : #include <xmloff/nmspmap.hxx>
41 : #include <xmloff/xmltoken.hxx>
42 : #include <xmloff/XMLEventsImportContext.hxx>
43 :
44 : #include <tools/urlobj.hxx>
45 :
46 : #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
47 : #include <com/sun/star/sheet/XSpreadsheets.hpp>
48 : #include <com/sun/star/sheet/XSpreadsheet.hpp>
49 : #include <com/sun/star/sheet/XPrintAreas.hpp>
50 : #include <com/sun/star/table/CellAddress.hpp>
51 :
52 : using namespace com::sun::star;
53 : using namespace xmloff::token;
54 : using ::com::sun::star::uno::Reference;
55 : using ::com::sun::star::uno::Sequence;
56 : using ::com::sun::star::uno::UNO_QUERY;
57 : using ::com::sun::star::xml::sax::XAttributeList;
58 :
59 : /**
60 : * Determine whether this table is an external reference cache from its
61 : * name. There is currently no way of determining whether a table is a
62 : * regular table or an external reference cache other than examining the
63 : * name itself. We should probably introduce a new boolean value for
64 : * table:table element and use it instead of doing this, to make it more
65 : * reliable and future-proof.
66 : *
67 : * @param rName
68 : *
69 : * @return
70 : */
71 337 : static bool lcl_isExternalRefCache(const OUString& rName, OUString& rUrl, OUString& rExtTabName)
72 : {
73 : // 'file:///path/to/file.ods'#MySheet
74 : // 'file:///path/to/file.ods'#MySheet with space
75 : // 'file:///path/to/file's.ods'#Sheet (Notice the quote in the file name.
76 : // That's allowed.)
77 :
78 337 : if ( rName.toChar() != '\'' ) // initial quote
79 331 : return false;
80 :
81 : // #i114504# Other schemes besides "file:" are also allowed.
82 : // CompareProtocolScheme is quick, only looks at the start of the string.
83 6 : INetProtocol eProt = INetURLObject::CompareProtocolScheme( rName.copy(1) );
84 6 : if ( eProt == INetProtocol::NotValid )
85 0 : return false;
86 :
87 6 : OUString aPrefix = INetURLObject::GetScheme( eProt );
88 6 : sal_Int32 nPrefLen = aPrefix.getLength();
89 :
90 12 : OUStringBuffer aUrlBuf, aTabNameBuf;
91 6 : aUrlBuf.append( aPrefix );
92 6 : sal_Int32 n = rName.getLength();
93 6 : const sal_Unicode* p = rName.getStr();
94 :
95 6 : bool bInUrl = true;
96 6 : sal_Unicode cPrev = 0;
97 619 : for (sal_Int32 i = nPrefLen+1; i < n; ++i) // start the loop after quote and prefix
98 : {
99 613 : const sal_Unicode c = p[i];
100 613 : if (bInUrl)
101 : {
102 : // parsing file URL
103 576 : if (c == '#')
104 : {
105 6 : if (cPrev != '\'')
106 0 : return false;
107 :
108 6 : rUrl = aUrlBuf.makeStringAndClear();
109 6 : rUrl = rUrl.copy(0, rUrl.getLength()-1); // remove the trailing single-quote.
110 6 : bInUrl = false;
111 : }
112 : else
113 570 : aUrlBuf.append(c);
114 : }
115 : else
116 : // parsing sheet name.
117 37 : aTabNameBuf.append(c);
118 :
119 613 : cPrev = c;
120 : }
121 :
122 6 : if (bInUrl)
123 0 : return false;
124 :
125 6 : if (aTabNameBuf.isEmpty())
126 0 : return false;
127 :
128 6 : rExtTabName = aTabNameBuf.makeStringAndClear();
129 :
130 12 : return true;
131 : }
132 :
133 6 : ScXMLExternalTabData::ScXMLExternalTabData() :
134 6 : mpCacheTable(), mnRow(0), mnCol(0), mnFileId(0)
135 : {
136 6 : }
137 :
138 337 : ScXMLTableContext::ScXMLTableContext( ScXMLImport& rImport,
139 : sal_uInt16 nPrfx,
140 : const OUString& rLName,
141 : const ::com::sun::star::uno::Reference<
142 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList ) :
143 : SvXMLImportContext( rImport, nPrfx, rLName ),
144 : nStartOffset(-1),
145 : bStartFormPage(false),
146 337 : bPrintEntireSheet(true)
147 : {
148 : // get start offset in file (if available)
149 337 : nStartOffset = GetScImport().GetByteOffset();
150 :
151 337 : ScXMLTabProtectionData aProtectData;
152 674 : OUString sName;
153 674 : OUString sStyleName;
154 337 : sal_Int16 nAttrCount(xAttrList.is() ? xAttrList->getLength() : 0);
155 337 : const SvXMLTokenMap& rAttrTokenMap = GetScImport().GetTableAttrTokenMap();
156 1068 : for( sal_Int16 i=0; i < nAttrCount; ++i )
157 : {
158 731 : const OUString& sAttrName(xAttrList->getNameByIndex( i ));
159 1462 : OUString aLocalName;
160 731 : sal_uInt16 nPrefix(GetScImport().GetNamespaceMap().GetKeyByAttrName(
161 731 : sAttrName, &aLocalName ));
162 1462 : const OUString& sValue(xAttrList->getValueByIndex( i ));
163 :
164 731 : switch( rAttrTokenMap.Get( nPrefix, aLocalName ) )
165 : {
166 : case XML_TOK_TABLE_NAME:
167 337 : sName = sValue;
168 337 : break;
169 : case XML_TOK_TABLE_STYLE_NAME:
170 337 : sStyleName = sValue;
171 337 : break;
172 : case XML_TOK_TABLE_PROTECTED:
173 2 : aProtectData.mbProtected = IsXMLToken(sValue, XML_TRUE);
174 2 : break;
175 : case XML_TOK_TABLE_PRINT_RANGES:
176 0 : sPrintRanges = sValue;
177 0 : break;
178 : case XML_TOK_TABLE_PASSWORD:
179 0 : aProtectData.maPassword = sValue;
180 0 : break;
181 : case XML_TOK_TABLE_PASSHASH:
182 0 : aProtectData.meHash1 = ScPassHashHelper::getHashTypeFromURI(sValue);
183 0 : break;
184 : case XML_TOK_TABLE_PASSHASH_2:
185 0 : aProtectData.meHash2 = ScPassHashHelper::getHashTypeFromURI(sValue);
186 0 : break;
187 : case XML_TOK_TABLE_PRINT:
188 : {
189 55 : if (IsXMLToken(sValue, XML_FALSE))
190 55 : bPrintEntireSheet = false;
191 : }
192 55 : break;
193 : }
194 731 : }
195 :
196 674 : OUString aExtUrl, aExtTabName;
197 337 : if (lcl_isExternalRefCache(sName, aExtUrl, aExtTabName))
198 : {
199 : // This is an external ref cache table.
200 6 : pExternalRefInfo.reset(new ScXMLExternalTabData);
201 6 : pExternalRefInfo->maFileUrl = aExtUrl;
202 6 : ScDocument* pDoc = GetScImport().GetDocument();
203 6 : if (pDoc)
204 : {
205 6 : ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
206 6 : pExternalRefInfo->mnFileId = pRefMgr->getExternalFileId(aExtUrl);
207 6 : pExternalRefInfo->mpCacheTable = pRefMgr->getCacheTable(pExternalRefInfo->mnFileId, aExtTabName, true);
208 6 : pExternalRefInfo->mpCacheTable->setWholeTableCached();
209 : }
210 : }
211 : else
212 : {
213 : // This is a regular table.
214 331 : GetScImport().GetTables().NewSheet(sName, sStyleName, aProtectData);
215 674 : }
216 337 : }
217 :
218 674 : ScXMLTableContext::~ScXMLTableContext()
219 : {
220 674 : }
221 :
222 5370 : SvXMLImportContext *ScXMLTableContext::CreateChildContext( sal_uInt16 nPrefix,
223 : const OUString& rLName,
224 : const ::com::sun::star::uno::Reference<
225 : ::com::sun::star::xml::sax::XAttributeList>& xAttrList )
226 : {
227 5370 : const SvXMLTokenMap& rTokenMap(GetScImport().GetTableElemTokenMap());
228 5370 : sal_uInt16 nToken = rTokenMap.Get(nPrefix, rLName);
229 5370 : if (pExternalRefInfo.get())
230 : {
231 : // We only care about the table-row and table-source elements for
232 : // external cache data.
233 80 : switch (nToken)
234 : {
235 : case XML_TOK_TABLE_ROW_GROUP:
236 : case XML_TOK_TABLE_HEADER_ROWS:
237 : case XML_TOK_TABLE_ROWS:
238 : // #i101319# don't discard rows in groups or header (repeat range)
239 : return new ScXMLExternalRefRowsContext(
240 0 : GetScImport(), nPrefix, rLName, xAttrList, *pExternalRefInfo);
241 : case XML_TOK_TABLE_ROW:
242 : return new ScXMLExternalRefRowContext(
243 68 : GetScImport(), nPrefix, rLName, xAttrList, *pExternalRefInfo);
244 : case XML_TOK_TABLE_SOURCE:
245 : return new ScXMLExternalRefTabSourceContext(
246 6 : GetScImport(), nPrefix, rLName, xAttrList, *pExternalRefInfo);
247 : default:
248 : ;
249 : }
250 :
251 6 : return new SvXMLImportContext(GetImport(), nPrefix, rLName);
252 : }
253 :
254 5290 : SvXMLImportContext *pContext(0);
255 :
256 5290 : switch (nToken)
257 : {
258 : case XML_TOK_TABLE_NAMED_EXPRESSIONS:
259 : {
260 8 : SCTAB nTab = GetScImport().GetTables().GetCurrentSheet();
261 : pContext = new ScXMLNamedExpressionsContext(
262 : GetScImport(), nPrefix, rLName, xAttrList,
263 8 : new ScXMLNamedExpressionsContext::SheetLocalInserter(GetScImport(), nTab));
264 : }
265 8 : break;
266 : case XML_TOK_TABLE_COL_GROUP:
267 : pContext = new ScXMLTableColsContext( GetScImport(), nPrefix,
268 : rLName, xAttrList,
269 2 : false, true );
270 2 : break;
271 : case XML_TOK_TABLE_HEADER_COLS:
272 : pContext = new ScXMLTableColsContext( GetScImport(), nPrefix,
273 : rLName, xAttrList,
274 0 : true, false );
275 0 : break;
276 : case XML_TOK_TABLE_COLS:
277 : pContext = new ScXMLTableColsContext( GetScImport(), nPrefix,
278 : rLName, xAttrList,
279 0 : false, false );
280 0 : break;
281 : case XML_TOK_TABLE_COL:
282 : pContext = new ScXMLTableColContext( GetScImport(), nPrefix,
283 1296 : rLName, xAttrList );
284 1296 : break;
285 : case XML_TOK_TABLE_PROTECTION:
286 : case XML_TOK_TABLE_PROTECTION_EXT:
287 2 : pContext = new ScXMLTableProtectionContext( GetScImport(), nPrefix, rLName, xAttrList );
288 2 : break;
289 : case XML_TOK_TABLE_ROW_GROUP:
290 : pContext = new ScXMLTableRowsContext( GetScImport(), nPrefix,
291 : rLName, xAttrList,
292 2 : false, true );
293 2 : break;
294 : case XML_TOK_TABLE_HEADER_ROWS:
295 : pContext = new ScXMLTableRowsContext( GetScImport(), nPrefix,
296 : rLName, xAttrList,
297 2 : true, false );
298 2 : break;
299 : case XML_TOK_TABLE_ROWS:
300 : pContext = new ScXMLTableRowsContext( GetScImport(), nPrefix,
301 : rLName, xAttrList,
302 0 : false, false );
303 0 : break;
304 : case XML_TOK_TABLE_ROW:
305 : pContext = new ScXMLTableRowContext( GetScImport(), nPrefix,
306 : rLName, xAttrList//,
307 : //this
308 3867 : );
309 3867 : break;
310 : case XML_TOK_TABLE_SOURCE:
311 0 : pContext = new ScXMLTableSourceContext( GetScImport(), nPrefix, rLName, xAttrList);
312 0 : break;
313 : case XML_TOK_TABLE_SCENARIO:
314 0 : pContext = new ScXMLTableScenarioContext( GetScImport(), nPrefix, rLName, xAttrList);
315 0 : break;
316 : case XML_TOK_TABLE_SHAPES:
317 56 : pContext = new ScXMLTableShapesContext( GetScImport(), nPrefix, rLName, xAttrList);
318 56 : break;
319 : case XML_TOK_TABLE_FORMS:
320 : {
321 31 : GetScImport().GetFormImport()->startPage(GetScImport().GetTables().GetCurrentXDrawPage());
322 31 : bStartFormPage = true;
323 31 : pContext = xmloff::OFormLayerXMLImport::createOfficeFormsContext( GetScImport(), nPrefix, rLName );
324 : }
325 31 : break;
326 : case XML_TOK_TABLE_EVENT_LISTENERS:
327 : case XML_TOK_TABLE_EVENT_LISTENERS_EXT:
328 : {
329 : // use XEventsSupplier interface of the sheet
330 0 : uno::Reference<document::XEventsSupplier> xSupplier( GetScImport().GetTables().GetCurrentXSheet(), uno::UNO_QUERY );
331 0 : pContext = new XMLEventsImportContext( GetImport(), nPrefix, rLName, xSupplier );
332 : }
333 0 : break;
334 : case XML_TOK_TABLE_CONDFORMATS:
335 24 : pContext = new ScXMLConditionalFormatsContext( GetScImport(), nPrefix, rLName );
336 24 : break;
337 : default:
338 : ;
339 : }
340 :
341 5290 : if( !pContext )
342 0 : pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
343 :
344 5290 : return pContext;
345 : }
346 :
347 337 : void ScXMLTableContext::EndElement()
348 : {
349 337 : ScXMLImport::MutexGuard aMutexGuard(GetScImport());
350 337 : ScXMLImport& rImport = GetScImport();
351 337 : rImport.GetStylesImportHelper()->EndTable();
352 337 : ScDocument* pDoc(rImport.GetDocument());
353 337 : if (!pDoc)
354 337 : return;
355 :
356 337 : ScMyTables& rTables = rImport.GetTables();
357 337 : SCTAB nCurTab = rTables.GetCurrentSheet();
358 337 : if (!sPrintRanges.isEmpty())
359 : {
360 0 : ScRangeList aRangeList;
361 0 : ScRangeStringConverter::GetRangeListFromString( aRangeList, sPrintRanges, pDoc, ::formula::FormulaGrammar::CONV_OOO );
362 0 : size_t nCount = aRangeList.size();
363 0 : for (size_t i=0; i< nCount; i++ )
364 : {
365 0 : pDoc->AddPrintRange( nCurTab, *aRangeList[i] );
366 0 : }
367 : }
368 337 : else if (!bPrintEntireSheet)
369 : // Sheet has "print entire sheet" option by default. Remove it.
370 55 : pDoc->ClearPrintRanges(nCurTab);
371 :
372 337 : ScOutlineTable* pOutlineTable(pDoc->GetOutlineTable(nCurTab, false));
373 337 : if (pOutlineTable)
374 : {
375 2 : ScOutlineArray& rColArray(pOutlineTable->GetColArray());
376 2 : size_t nDepth = rColArray.GetDepth();
377 10 : for (size_t i = 0; i < nDepth; ++i)
378 : {
379 8 : size_t nCount = rColArray.GetCount(i);
380 16 : for (size_t j = 0; j < nCount; ++j)
381 : {
382 8 : const ScOutlineEntry* pEntry = rColArray.GetEntry(i, j);
383 8 : if (pEntry->IsHidden())
384 1 : rColArray.SetVisibleBelow(i, j, false);
385 : }
386 : }
387 2 : ScOutlineArray& rRowArray(pOutlineTable->GetRowArray());
388 2 : nDepth = rRowArray.GetDepth();
389 10 : for (size_t i = 0; i < nDepth; ++i)
390 : {
391 8 : size_t nCount = rRowArray.GetCount(i);
392 16 : for (size_t j = 0; j < nCount; ++j)
393 : {
394 8 : const ScOutlineEntry* pEntry = rRowArray.GetEntry(i, j);
395 8 : if (pEntry->IsHidden())
396 1 : rRowArray.SetVisibleBelow(i, j, false);
397 : }
398 : }
399 : }
400 337 : if (rTables.HasDrawPage())
401 : {
402 101 : if (rTables.HasXShapes())
403 : {
404 80 : rImport.GetShapeImport()->popGroupAndSort();
405 80 : uno::Reference < drawing::XShapes > xTempShapes(rTables.GetCurrentXShapes());
406 80 : rImport.GetShapeImport()->endPage(xTempShapes);
407 : }
408 101 : if (bStartFormPage)
409 31 : rImport.GetFormImport()->endPage();
410 : }
411 :
412 337 : rTables.DeleteTable();
413 337 : rImport.ProgressBarIncrement(false);
414 :
415 : // store stream positions
416 337 : if (!pExternalRefInfo.get() && nStartOffset >= 0 /* && nEndOffset >= 0 */)
417 : {
418 287 : ScSheetSaveData* pSheetData = ScModelObj::getImplementation(rImport.GetModel())->GetSheetSaveData();
419 287 : SCTAB nTab = rTables.GetCurrentSheet();
420 : // pSheetData->AddStreamPos( nTab, nStartOffset, nEndOffset );
421 287 : pSheetData->StartStreamPos( nTab, nStartOffset );
422 337 : }
423 : }
424 :
425 6 : ScXMLImport& ScXMLTableProtectionContext::GetScImport()
426 : {
427 6 : return static_cast<ScXMLImport&>(GetImport());
428 : }
429 :
430 2 : ScXMLTableProtectionContext::ScXMLTableProtectionContext(
431 : ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLName,
432 : const Reference<XAttributeList>& xAttrList ) :
433 2 : SvXMLImportContext( rImport, nPrefix, rLName )
434 : {
435 2 : const SvXMLTokenMap& rAttrTokenMap = GetScImport().GetTableProtectionAttrTokenMap();
436 2 : bool bSelectProtectedCells = false;
437 2 : bool bSelectUnprotectedCells = false;
438 :
439 2 : sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
440 :
441 4 : for (sal_Int16 i = 0; i < nAttrCount; ++i)
442 : {
443 2 : const OUString& aAttrName = xAttrList->getNameByIndex(i);
444 4 : const OUString aValue = xAttrList->getValueByIndex(i);
445 :
446 4 : OUString aLocalName;
447 2 : sal_uInt16 nLocalPrefix = GetScImport().GetNamespaceMap().GetKeyByAttrName(
448 2 : aAttrName, &aLocalName);
449 :
450 2 : switch (rAttrTokenMap.Get(nLocalPrefix, aLocalName))
451 : {
452 : case XML_TOK_TABLE_SELECT_PROTECTED_CELLS:
453 : case XML_TOK_TABLE_SELECT_PROTECTED_CELLS_EXT:
454 0 : bSelectProtectedCells = IsXMLToken(aValue, XML_TRUE);
455 0 : break;
456 : case XML_TOK_TABLE_SELECT_UNPROTECTED_CELLS:
457 : case XML_TOK_TABLE_SELECT_UNPROTECTED_CELLS_EXT:
458 2 : bSelectUnprotectedCells = IsXMLToken(aValue, XML_TRUE);
459 2 : break;
460 : default:
461 : SAL_WARN("sc", "unknown attribute: " << aAttrName);
462 : }
463 2 : }
464 :
465 2 : ScXMLTabProtectionData& rProtectData = GetScImport().GetTables().GetCurrentProtectionData();
466 2 : rProtectData.mbSelectProtectedCells = bSelectProtectedCells;
467 2 : rProtectData.mbSelectUnprotectedCells = bSelectUnprotectedCells;
468 2 : }
469 :
470 4 : ScXMLTableProtectionContext::~ScXMLTableProtectionContext()
471 : {
472 4 : }
473 :
474 0 : SvXMLImportContext* ScXMLTableProtectionContext::CreateChildContext(
475 : sal_uInt16 /*nPrefix*/, const OUString& /*rLocalName*/, const Reference<XAttributeList>& /*xAttrList*/ )
476 : {
477 0 : return NULL;
478 : }
479 :
480 2 : void ScXMLTableProtectionContext::EndElement()
481 : {
482 158 : }
483 :
484 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|