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