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 582 : 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 582 : if ( rName.toChar() != '\'' ) // initial quote
79 578 : 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 4 : INetProtocol eProt = INetURLObject::CompareProtocolScheme( rName.copy(1) );
84 4 : if ( eProt == INET_PROT_NOT_VALID )
85 0 : return false;
86 :
87 4 : OUString aPrefix = INetURLObject::GetScheme( eProt );
88 4 : sal_Int32 nPrefLen = aPrefix.getLength();
89 :
90 8 : OUStringBuffer aUrlBuf, aTabNameBuf;
91 4 : aUrlBuf.append( aPrefix );
92 4 : sal_Int32 n = rName.getLength();
93 4 : const sal_Unicode* p = rName.getStr();
94 :
95 4 : bool bInUrl = true;
96 4 : sal_Unicode cPrev = 0;
97 162 : for (sal_Int32 i = nPrefLen+1; i < n; ++i) // start the loop after quote and prefix
98 : {
99 158 : const sal_Unicode c = p[i];
100 158 : if (bInUrl)
101 : {
102 : // parsing file URL
103 130 : if (c == '#')
104 : {
105 4 : if (cPrev != '\'')
106 0 : return false;
107 :
108 4 : rUrl = aUrlBuf.makeStringAndClear();
109 4 : rUrl = rUrl.copy(0, rUrl.getLength()-1); // remove the trailing single-quote.
110 4 : bInUrl = false;
111 : }
112 : else
113 126 : aUrlBuf.append(c);
114 : }
115 : else
116 : // parsing sheet name.
117 28 : aTabNameBuf.append(c);
118 :
119 158 : cPrev = c;
120 : }
121 :
122 4 : if (bInUrl)
123 0 : return false;
124 :
125 4 : if (aTabNameBuf.isEmpty())
126 0 : return false;
127 :
128 4 : rExtTabName = aTabNameBuf.makeStringAndClear();
129 :
130 8 : return true;
131 : }
132 :
133 4 : ScXMLExternalTabData::ScXMLExternalTabData() :
134 4 : mpCacheTable(), mnRow(0), mnCol(0), mnFileId(0)
135 : {
136 4 : }
137 :
138 582 : 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 582 : bPrintEntireSheet(true)
147 : {
148 : // get start offset in file (if available)
149 582 : nStartOffset = GetScImport().GetByteOffset();
150 :
151 582 : ScXMLTabProtectionData aProtectData;
152 1164 : OUString sName;
153 1164 : OUString sStyleName;
154 582 : sal_Int16 nAttrCount(xAttrList.is() ? xAttrList->getLength() : 0);
155 582 : const SvXMLTokenMap& rAttrTokenMap = GetScImport().GetTableAttrTokenMap();
156 1844 : for( sal_Int16 i=0; i < nAttrCount; ++i )
157 : {
158 1262 : const OUString& sAttrName(xAttrList->getNameByIndex( i ));
159 2524 : OUString aLocalName;
160 1262 : sal_uInt16 nPrefix(GetScImport().GetNamespaceMap().GetKeyByAttrName(
161 1262 : sAttrName, &aLocalName ));
162 2524 : const OUString& sValue(xAttrList->getValueByIndex( i ));
163 :
164 1262 : switch( rAttrTokenMap.Get( nPrefix, aLocalName ) )
165 : {
166 : case XML_TOK_TABLE_NAME:
167 582 : sName = sValue;
168 582 : break;
169 : case XML_TOK_TABLE_STYLE_NAME:
170 582 : sStyleName = sValue;
171 582 : break;
172 : case XML_TOK_TABLE_PROTECTED:
173 4 : aProtectData.mbProtected = IsXMLToken(sValue, XML_TRUE);
174 4 : 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 94 : if (IsXMLToken(sValue, XML_FALSE))
190 94 : bPrintEntireSheet = false;
191 : }
192 94 : break;
193 : }
194 1262 : }
195 :
196 1164 : OUString aExtUrl, aExtTabName;
197 582 : if (lcl_isExternalRefCache(sName, aExtUrl, aExtTabName))
198 : {
199 : // This is an external ref cache table.
200 4 : pExternalRefInfo.reset(new ScXMLExternalTabData);
201 4 : pExternalRefInfo->maFileUrl = aExtUrl;
202 4 : ScDocument* pDoc = GetScImport().GetDocument();
203 4 : if (pDoc)
204 : {
205 4 : ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
206 4 : pExternalRefInfo->mnFileId = pRefMgr->getExternalFileId(aExtUrl);
207 4 : pExternalRefInfo->mpCacheTable = pRefMgr->getCacheTable(pExternalRefInfo->mnFileId, aExtTabName, true);
208 4 : pExternalRefInfo->mpCacheTable->setWholeTableCached();
209 : }
210 : }
211 : else
212 : {
213 : // This is a regular table.
214 578 : GetScImport().GetTables().NewSheet(sName, sStyleName, aProtectData);
215 1164 : }
216 582 : }
217 :
218 1164 : ScXMLTableContext::~ScXMLTableContext()
219 : {
220 1164 : }
221 :
222 9032 : 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 9032 : const SvXMLTokenMap& rTokenMap(GetScImport().GetTableElemTokenMap());
228 9032 : sal_uInt16 nToken = rTokenMap.Get(nPrefix, rLName);
229 9032 : if (pExternalRefInfo.get())
230 : {
231 : // We only care about the table-row and table-source elements for
232 : // external cache data.
233 96 : 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 88 : GetScImport(), nPrefix, rLName, xAttrList, *pExternalRefInfo);
244 : case XML_TOK_TABLE_SOURCE:
245 : return new ScXMLExternalRefTabSourceContext(
246 4 : GetScImport(), nPrefix, rLName, xAttrList, *pExternalRefInfo);
247 : default:
248 : ;
249 : }
250 :
251 4 : return new SvXMLImportContext(GetImport(), nPrefix, rLName);
252 : }
253 :
254 8936 : SvXMLImportContext *pContext(0);
255 :
256 8936 : 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 4 : false, true );
270 4 : 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 2294 : rLName, xAttrList );
284 2294 : break;
285 : case XML_TOK_TABLE_PROTECTION:
286 : case XML_TOK_TABLE_PROTECTION_EXT:
287 4 : pContext = new ScXMLTableProtectionContext( GetScImport(), nPrefix, rLName, xAttrList );
288 4 : break;
289 : case XML_TOK_TABLE_ROW_GROUP:
290 : pContext = new ScXMLTableRowsContext( GetScImport(), nPrefix,
291 : rLName, xAttrList,
292 4 : false, true );
293 4 : break;
294 : case XML_TOK_TABLE_HEADER_ROWS:
295 : pContext = new ScXMLTableRowsContext( GetScImport(), nPrefix,
296 : rLName, xAttrList,
297 4 : true, false );
298 4 : 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 6460 : );
309 6460 : 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 76 : pContext = new ScXMLTableShapesContext( GetScImport(), nPrefix, rLName, xAttrList);
318 76 : break;
319 : case XML_TOK_TABLE_FORMS:
320 : {
321 52 : GetScImport().GetFormImport()->startPage(GetScImport().GetTables().GetCurrentXDrawPage());
322 52 : bStartFormPage = true;
323 52 : pContext = GetScImport().GetFormImport()->createOfficeFormsContext( GetScImport(), nPrefix, rLName );
324 : }
325 52 : 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 30 : pContext = new ScXMLConditionalFormatsContext( GetScImport(), nPrefix, rLName );
336 30 : break;
337 : default:
338 : ;
339 : }
340 :
341 8936 : if( !pContext )
342 0 : pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
343 :
344 8936 : return pContext;
345 : }
346 :
347 582 : void ScXMLTableContext::EndElement()
348 : {
349 582 : ScXMLImport::MutexGuard aMutexGuard(GetScImport());
350 582 : ScXMLImport& rImport = GetScImport();
351 582 : rImport.GetStylesImportHelper()->EndTable();
352 582 : ScDocument* pDoc(rImport.GetDocument());
353 582 : if (!pDoc)
354 582 : return;
355 :
356 582 : ScMyTables& rTables = rImport.GetTables();
357 582 : SCTAB nCurTab = rTables.GetCurrentSheet();
358 582 : 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 582 : else if (!bPrintEntireSheet)
369 : // Sheet has "print entire sheet" option by default. Remove it.
370 94 : pDoc->ClearPrintRanges(nCurTab);
371 :
372 582 : ScOutlineTable* pOutlineTable(pDoc->GetOutlineTable(nCurTab, false));
373 582 : if (pOutlineTable)
374 : {
375 4 : ScOutlineArray& rColArray(pOutlineTable->GetColArray());
376 4 : size_t nDepth = rColArray.GetDepth();
377 20 : for (size_t i = 0; i < nDepth; ++i)
378 : {
379 16 : size_t nCount = rColArray.GetCount(i);
380 32 : for (size_t j = 0; j < nCount; ++j)
381 : {
382 16 : const ScOutlineEntry* pEntry = rColArray.GetEntry(i, j);
383 16 : if (pEntry->IsHidden())
384 2 : rColArray.SetVisibleBelow(i, j, false);
385 : }
386 : }
387 4 : ScOutlineArray& rRowArray(pOutlineTable->GetRowArray());
388 4 : nDepth = rRowArray.GetDepth();
389 20 : for (size_t i = 0; i < nDepth; ++i)
390 : {
391 16 : size_t nCount = rRowArray.GetCount(i);
392 32 : for (size_t j = 0; j < nCount; ++j)
393 : {
394 16 : const ScOutlineEntry* pEntry = rRowArray.GetEntry(i, j);
395 16 : if (pEntry->IsHidden())
396 2 : rRowArray.SetVisibleBelow(i, j, false);
397 : }
398 : }
399 : }
400 582 : if (rTables.HasDrawPage())
401 : {
402 156 : if (rTables.HasXShapes())
403 : {
404 118 : rImport.GetShapeImport()->popGroupAndSort();
405 118 : uno::Reference < drawing::XShapes > xTempShapes(rTables.GetCurrentXShapes());
406 118 : rImport.GetShapeImport()->endPage(xTempShapes);
407 : }
408 156 : if (bStartFormPage)
409 52 : rImport.GetFormImport()->endPage();
410 : }
411 :
412 582 : rTables.DeleteTable();
413 582 : rImport.ProgressBarIncrement(false);
414 :
415 : // store stream positions
416 582 : if (!pExternalRefInfo.get() && nStartOffset >= 0 /* && nEndOffset >= 0 */)
417 : {
418 492 : ScSheetSaveData* pSheetData = ScModelObj::getImplementation(rImport.GetModel())->GetSheetSaveData();
419 492 : SCTAB nTab = rTables.GetCurrentSheet();
420 : // pSheetData->AddStreamPos( nTab, nStartOffset, nEndOffset );
421 492 : pSheetData->StartStreamPos( nTab, nStartOffset );
422 582 : }
423 : }
424 :
425 12 : ScXMLImport& ScXMLTableProtectionContext::GetScImport()
426 : {
427 12 : return static_cast<ScXMLImport&>(GetImport());
428 : }
429 :
430 4 : ScXMLTableProtectionContext::ScXMLTableProtectionContext(
431 : ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLName,
432 : const Reference<XAttributeList>& xAttrList ) :
433 4 : SvXMLImportContext( rImport, nPrefix, rLName )
434 : {
435 4 : const SvXMLTokenMap& rAttrTokenMap = GetScImport().GetTableProtectionAttrTokenMap();
436 4 : bool bSelectProtectedCells = false;
437 4 : bool bSelectUnprotectedCells = false;
438 :
439 4 : sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
440 :
441 8 : for (sal_Int16 i = 0; i < nAttrCount; ++i)
442 : {
443 4 : const OUString& aAttrName = xAttrList->getNameByIndex(i);
444 8 : const OUString aValue = xAttrList->getValueByIndex(i);
445 :
446 8 : OUString aLocalName;
447 4 : sal_uInt16 nLocalPrefix = GetScImport().GetNamespaceMap().GetKeyByAttrName(
448 4 : aAttrName, &aLocalName);
449 :
450 4 : 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 4 : bSelectUnprotectedCells = IsXMLToken(aValue, XML_TRUE);
459 4 : break;
460 : default:
461 : SAL_WARN("sc", "unknown attribute: " << aAttrName);
462 : }
463 4 : }
464 :
465 4 : ScXMLTabProtectionData& rProtectData = GetScImport().GetTables().GetCurrentProtectionData();
466 4 : rProtectData.mbSelectProtectedCells = bSelectProtectedCells;
467 4 : rProtectData.mbSelectUnprotectedCells = bSelectUnprotectedCells;
468 4 : }
469 :
470 8 : ScXMLTableProtectionContext::~ScXMLTableProtectionContext()
471 : {
472 8 : }
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 4 : void ScXMLTableProtectionContext::EndElement()
481 : {
482 232 : }
483 :
484 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|