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