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