xref: /trunk/main/sc/source/filter/xml/xmltabi.cxx (revision dffa72de)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26 
27 
28 
29 // INCLUDE ---------------------------------------------------------------
30 
31 #include "xmltabi.hxx"
32 #include "xmlimprt.hxx"
33 #include "xmlrowi.hxx"
34 #include "xmlcoli.hxx"
35 #include "xmlsceni.hxx"
36 #include "xmlexternaltabi.hxx"
37 #include "document.hxx"
38 #include "docuno.hxx"
39 #include "olinetab.hxx"
40 #include "XMLConverter.hxx"
41 #include "XMLTableShapesContext.hxx"
42 #include "XMLTableSourceContext.hxx"
43 #include "XMLStylesImportHelper.hxx"
44 #include "rangeutl.hxx"
45 #include "externalrefmgr.hxx"
46 #include "sheetdata.hxx"
47 #include "xmlnexpi.hxx"
48 
49 #include <xmloff/xmltkmap.hxx>
50 #include <xmloff/nmspmap.hxx>
51 #include <xmloff/formsimp.hxx>
52 #include <xmloff/xmltoken.hxx>
53 #include <xmloff/XMLEventsImportContext.hxx>
54 
55 #include <tools/urlobj.hxx>
56 
57 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
58 #include <com/sun/star/sheet/XSpreadsheets.hpp>
59 #include <com/sun/star/sheet/XSpreadsheet.hpp>
60 #include <com/sun/star/sheet/XPrintAreas.hpp>
61 #include <com/sun/star/table/CellAddress.hpp>
62 
63 using namespace com::sun::star;
64 using namespace xmloff::token;
65 
66 /**
67  * Determine whether this table is an external reference cache from its
68  * name.  There is currently no way of determining whether a table is a
69  * regular table or an external reference cache other than examining the
70  * name itself.  We should probably introduce a new boolean value for
71  * table:table element and use it instead of doing this, to make it more
72  * reliable and future-proof.
73  *
74  * @param rName
75  *
76  * @return
77  */
lcl_isExternalRefCache(const rtl::OUString & rName,rtl::OUString & rUrl,rtl::OUString & rExtTabName)78 static bool lcl_isExternalRefCache(const rtl::OUString& rName, rtl::OUString& rUrl, rtl::OUString& rExtTabName)
79 {
80     // 'file:///path/to/file.ods'#MySheet
81     // 'file:///path/to/file.ods'#MySheet with space
82     // 'file:///path/to/file's.ods'#Sheet (Notice the quote in the file name.
83     //  That's allowed.)
84 
85     if ( rName.toChar() != '\'' )       // initial quote
86         return false;
87 
88     // #i114504# Other schemes besides "file:" are also allowed.
89     // CompareProtocolScheme is quick, only looks at the start of the string.
90     INetProtocol eProt = INetURLObject::CompareProtocolScheme( rName.copy(1) );
91     if ( eProt == INET_PROT_NOT_VALID )
92         return false;
93 
94     rtl::OUString aPrefix = INetURLObject::GetScheme( eProt );
95     sal_Int32 nPrefLen = aPrefix.getLength();
96 
97     rtl::OUStringBuffer aUrlBuf, aTabNameBuf;
98     aUrlBuf.append( aPrefix );
99     sal_Int32 n = rName.getLength();
100     const sal_Unicode* p = rName.getStr();
101 
102     bool bInUrl = true;
103     sal_Unicode cPrev = 0;
104     for (sal_Int32 i = nPrefLen+1; i < n; ++i)      // start the loop after quote and prefix
105     {
106         const sal_Unicode c = p[i];
107         if (bInUrl)
108         {
109             // parsing file URL
110             if (c == '#')
111             {
112                 if (cPrev != '\'')
113                     return false;
114 
115                 rUrl = aUrlBuf.makeStringAndClear();
116                 rUrl = rUrl.copy(0, rUrl.getLength()-1); // remove the trailing single-quote.
117                 bInUrl = false;
118             }
119             else
120                 aUrlBuf.append(c);
121         }
122         else
123             // parsing sheet name.
124             aTabNameBuf.append(c);
125 
126         cPrev = c;
127     }
128 
129     if (bInUrl)
130         return false;
131 
132     if (aTabNameBuf.getLength() == 0)
133         return false;
134 
135     rExtTabName = aTabNameBuf.makeStringAndClear();
136 
137     return true;
138 }
139 
ScXMLExternalTabData()140 ScXMLExternalTabData::ScXMLExternalTabData() :
141     mpCacheTable(), mnRow(0), mnCol(0), mnFileId(0)
142 {
143 }
144 
145 //------------------------------------------------------------------
146 
ScXMLTableContext(ScXMLImport & rImport,sal_uInt16 nPrfx,const::rtl::OUString & rLName,const::com::sun::star::uno::Reference<::com::sun::star::xml::sax::XAttributeList> & xAttrList,const sal_Bool bTempIsSubTable,const sal_Int32 nSpannedCols)147 ScXMLTableContext::ScXMLTableContext( ScXMLImport& rImport,
148 									  sal_uInt16 nPrfx,
149 									  const ::rtl::OUString& rLName,
150 									  const ::com::sun::star::uno::Reference<
151 									  ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
152 									  const sal_Bool bTempIsSubTable,
153 									  const sal_Int32 nSpannedCols) :
154 	SvXMLImportContext( rImport, nPrfx, rLName ),
155     pExternalRefInfo(NULL),
156     nStartOffset(-1),
157 	bStartFormPage(sal_False),
158     bPrintEntireSheet(sal_True)
159 {
160     // get start offset in file (if available)
161     nStartOffset = GetScImport().GetByteOffset();
162 
163 	if (!bTempIsSubTable)
164 	{
165 		sal_Bool bProtection(sal_False);
166 		rtl::OUString sName;
167 		rtl::OUString sStyleName;
168 		rtl::OUString sPassword;
169 		sal_Int16 nAttrCount(xAttrList.is() ? xAttrList->getLength() : 0);
170 		const SvXMLTokenMap& rAttrTokenMap = GetScImport().GetTableAttrTokenMap();
171 		for( sal_Int16 i=0; i < nAttrCount; ++i )
172 		{
173 			const rtl::OUString& sAttrName(xAttrList->getNameByIndex( i ));
174 			rtl::OUString aLocalName;
175 			sal_uInt16 nPrefix(GetScImport().GetNamespaceMap().GetKeyByAttrName(
176 												sAttrName, &aLocalName ));
177 			const rtl::OUString& sValue(xAttrList->getValueByIndex( i ));
178 
179 			switch( rAttrTokenMap.Get( nPrefix, aLocalName ) )
180 			{
181 				case XML_TOK_TABLE_NAME:
182 						sName = sValue;
183 					break;
184 				case XML_TOK_TABLE_STYLE_NAME:
185 						sStyleName = sValue;
186 					break;
187 				case XML_TOK_TABLE_PROTECTION:
188 						bProtection = IsXMLToken(sValue, XML_TRUE);
189 					break;
190 				case XML_TOK_TABLE_PRINT_RANGES:
191 						sPrintRanges = sValue;
192 					break;
193 				case XML_TOK_TABLE_PASSWORD:
194 						sPassword = sValue;
195 					break;
196                 case XML_TOK_TABLE_PRINT:
197                     {
198                         if (IsXMLToken(sValue, XML_FALSE))
199                             bPrintEntireSheet = sal_False;
200                     }
201                     break;
202 			}
203 		}
204 
205         rtl::OUString aExtUrl, aExtTabName;
206         if (lcl_isExternalRefCache(sName, aExtUrl, aExtTabName))
207         {
208             // This is an external ref cache table.
209             pExternalRefInfo.reset(new ScXMLExternalTabData);
210             pExternalRefInfo->maFileUrl = aExtUrl;
211             ScDocument* pDoc = GetScImport().GetDocument();
212             if (pDoc)
213             {
214                 ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
215                 pExternalRefInfo->mnFileId = pRefMgr->getExternalFileId(aExtUrl);
216                 pExternalRefInfo->mpCacheTable = pRefMgr->getCacheTable(pExternalRefInfo->mnFileId, aExtTabName, true);
217                 pExternalRefInfo->mpCacheTable->setWholeTableCached();
218             }
219         }
220         else
221         {
222             // This is a regular table.
223             GetScImport().GetTables().NewSheet(sName, sStyleName, bProtection, sPassword);
224         }
225 	}
226 	else
227 	{
228 		GetScImport().GetTables().NewTable(nSpannedCols);
229 	}
230 }
231 
~ScXMLTableContext()232 ScXMLTableContext::~ScXMLTableContext()
233 {
234 }
235 
CreateChildContext(sal_uInt16 nPrefix,const::rtl::OUString & rLName,const::com::sun::star::uno::Reference<::com::sun::star::xml::sax::XAttributeList> & xAttrList)236 SvXMLImportContext *ScXMLTableContext::CreateChildContext( sal_uInt16 nPrefix,
237 											const ::rtl::OUString& rLName,
238 											const ::com::sun::star::uno::Reference<
239 									  	::com::sun::star::xml::sax::XAttributeList>& xAttrList )
240 {
241 	const SvXMLTokenMap& rTokenMap(GetScImport().GetTableElemTokenMap());
242     sal_uInt16 nToken = rTokenMap.Get(nPrefix, rLName);
243     if (pExternalRefInfo.get())
244     {
245         // We only care about the table-row and table-source elements for
246         // external cache data.
247         switch (nToken)
248         {
249             case XML_TOK_TABLE_ROW_GROUP:
250             case XML_TOK_TABLE_HEADER_ROWS:
251             case XML_TOK_TABLE_ROWS:
252                 // #i101319# don't discard rows in groups or header (repeat range)
253                 return new ScXMLExternalRefRowsContext(
254                     GetScImport(), nPrefix, rLName, xAttrList, *pExternalRefInfo);
255             case XML_TOK_TABLE_ROW:
256                 return new ScXMLExternalRefRowContext(
257                     GetScImport(), nPrefix, rLName, xAttrList, *pExternalRefInfo);
258             case XML_TOK_TABLE_SOURCE:
259                 return new ScXMLExternalRefTabSourceContext(
260                     GetScImport(), nPrefix, rLName, xAttrList, *pExternalRefInfo);
261             default:
262                 ;
263         }
264 
265         return new SvXMLImportContext(GetImport(), nPrefix, rLName);
266     }
267 
268 	SvXMLImportContext *pContext(0);
269 
270 	switch (nToken)
271 	{
272 	case XML_TOK_TABLE_COL_GROUP:
273 		pContext = new ScXMLTableColsContext( GetScImport(), nPrefix,
274 												   rLName, xAttrList,
275 												   sal_False, sal_True );
276 		break;
277 	case XML_TOK_TABLE_HEADER_COLS:
278 		pContext = new ScXMLTableColsContext( GetScImport(), nPrefix,
279 												   rLName, xAttrList,
280 												   sal_True, sal_False );
281 		break;
282 	case XML_TOK_TABLE_COLS:
283 		pContext = new ScXMLTableColsContext( GetScImport(), nPrefix,
284 												   rLName, xAttrList,
285 												   sal_False, sal_False );
286 		break;
287 	case XML_TOK_TABLE_COL:
288 			pContext = new ScXMLTableColContext( GetScImport(), nPrefix,
289 													  rLName, xAttrList );
290 		break;
291 	case XML_TOK_TABLE_ROW_GROUP:
292 		pContext = new ScXMLTableRowsContext( GetScImport(), nPrefix,
293 												   rLName, xAttrList,
294 												   sal_False, sal_True );
295 		break;
296 	case XML_TOK_TABLE_HEADER_ROWS:
297 		pContext = new ScXMLTableRowsContext( GetScImport(), nPrefix,
298 												   rLName, xAttrList,
299 												   sal_True, sal_False );
300 		break;
301 	case XML_TOK_TABLE_ROWS:
302 		pContext = new ScXMLTableRowsContext( GetScImport(), nPrefix,
303 												   rLName, xAttrList,
304 												   sal_False, sal_False );
305 		break;
306 	case XML_TOK_TABLE_ROW:
307 			pContext = new ScXMLTableRowContext( GetScImport(), nPrefix,
308 													  rLName, xAttrList//,
309 													  //this
310 													  );
311 		break;
312 	case XML_TOK_TABLE_SOURCE:
313 		pContext = new ScXMLTableSourceContext( GetScImport(), nPrefix, rLName, xAttrList);
314 		break;
315 	case XML_TOK_TABLE_SCENARIO:
316 		pContext = new ScXMLTableScenarioContext( GetScImport(), nPrefix, rLName, xAttrList);
317 		break;
318 	case XML_TOK_TABLE_SHAPES:
319 		pContext = new ScXMLTableShapesContext( GetScImport(), nPrefix, rLName, xAttrList);
320 		break;
321 	case XML_TOK_TABLE_FORMS:
322 		{
323 			GetScImport().GetFormImport()->startPage(GetScImport().GetTables().GetCurrentXDrawPage());
324 			bStartFormPage = sal_True;
325 			pContext = GetScImport().GetFormImport()->createOfficeFormsContext( GetScImport(), nPrefix, rLName );
326 		}
327 		break;
328 	case XML_TOK_TABLE_NAMED_EXPRESSIONS:
329 		{
330 			SCTAB nCurrentSheet = static_cast<SCTAB>(GetScImport().GetTables().GetCurrentSheet());
331 			pContext = new ScXMLNamedExpressionsContext ( GetScImport(), nPrefix, rLName, xAttrList );//worksheetname
332 			static_cast<ScXMLNamedExpressionsContext*>(pContext)->SetScope( nCurrentSheet );
333 		}
334 		break;
335     case XML_TOK_TABLE_EVENT_LISTENERS:
336     case XML_TOK_TABLE_EVENT_LISTENERS_EXT:
337         {
338             // use XEventsSupplier interface of the sheet
339             uno::Reference<document::XEventsSupplier> xSupplier( GetScImport().GetTables().GetCurrentXSheet(), uno::UNO_QUERY );
340             pContext = new XMLEventsImportContext( GetImport(), nPrefix, rLName, xSupplier );
341         }
342         break;
343     default:
344         ;
345 	}
346 
347 	if( !pContext )
348 		pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
349 
350 	return pContext;
351 }
352 
EndElement()353 void ScXMLTableContext::EndElement()
354 {
355     // get end offset in file (if available)
356 //    sal_Int32 nEndOffset = GetScImport().GetByteOffset();
357 
358 	GetScImport().LockSolarMutex();
359 	GetScImport().GetStylesImportHelper()->EndTable();
360 	ScDocument* pDoc(GetScImport().GetDocument());
361 	if (pDoc)
362 	{
363 		if (sPrintRanges.getLength())
364 		{
365 			uno::Reference< sheet::XPrintAreas > xPrintAreas( GetScImport().GetTables().GetCurrentXSheet(), uno::UNO_QUERY );
366 			if( xPrintAreas.is() )
367 			{
368 				uno::Sequence< table::CellRangeAddress > aRangeList;
369 				ScRangeStringConverter::GetRangeListFromString( aRangeList, sPrintRanges, pDoc, ::formula::FormulaGrammar::CONV_OOO );
370 				xPrintAreas->setPrintAreas( aRangeList );
371 			}
372 		}
373         else if (bPrintEntireSheet) pDoc->SetPrintEntireSheet(static_cast<SCTAB>(GetScImport().GetTables().GetCurrentSheet()));
374 
375 		ScOutlineTable* pOutlineTable(pDoc->GetOutlineTable(static_cast<SCTAB>(GetScImport().GetTables().GetCurrentSheet()), sal_False));
376 		if (pOutlineTable)
377 		{
378 			ScOutlineArray* pColArray(pOutlineTable->GetColArray());
379 			sal_Int32 nDepth(pColArray->GetDepth());
380             sal_Int32 i;
381             for (i = 0; i < nDepth; ++i)
382 			{
383 				sal_Int32 nCount(pColArray->GetCount(static_cast<sal_uInt16>(i)));
384 				for (sal_Int32 j = 0; j < nCount; ++j)
385 				{
386 					ScOutlineEntry* pEntry(pColArray->GetEntry(static_cast<sal_uInt16>(i), static_cast<sal_uInt16>(j)));
387 					if (pEntry->IsHidden())
388 						pColArray->SetVisibleBelow(static_cast<sal_uInt16>(i), static_cast<sal_uInt16>(j), sal_False);
389 				}
390 			}
391 			ScOutlineArray* pRowArray(pOutlineTable->GetRowArray());
392 			nDepth = pRowArray->GetDepth();
393 			for (i = 0; i < nDepth; ++i)
394 			{
395 				sal_Int32 nCount(pRowArray->GetCount(static_cast<sal_uInt16>(i)));
396 				for (sal_Int32 j = 0; j < nCount; ++j)
397 				{
398 					ScOutlineEntry* pEntry(pRowArray->GetEntry(static_cast<sal_uInt16>(i), static_cast<sal_uInt16>(j)));
399 					if (pEntry->IsHidden())
400 						pRowArray->SetVisibleBelow(static_cast<sal_uInt16>(i), static_cast<sal_uInt16>(j), sal_False);
401 				}
402 			}
403 		}
404 		if (GetScImport().GetTables().HasDrawPage())
405 		{
406 			if (GetScImport().GetTables().HasXShapes())
407 			{
408 				GetScImport().GetShapeImport()->popGroupAndSort();
409 				uno::Reference < drawing::XShapes > xTempShapes(GetScImport().GetTables().GetCurrentXShapes());
410 				GetScImport().GetShapeImport()->endPage(xTempShapes);
411 			}
412 			if (bStartFormPage)
413 				GetScImport().GetFormImport()->endPage();
414 		}
415 
416 		GetScImport().GetTables().DeleteTable();
417 		GetScImport().ProgressBarIncrement(sal_False);
418 
419         // store stream positions
420         if (!pExternalRefInfo.get() && nStartOffset >= 0 /* && nEndOffset >= 0 */)
421         {
422             ScSheetSaveData* pSheetData = ScModelObj::getImplementation(GetScImport().GetModel())->GetSheetSaveData();
423             sal_Int32 nTab = GetScImport().GetTables().GetCurrentSheet();
424             // pSheetData->AddStreamPos( nTab, nStartOffset, nEndOffset );
425             pSheetData->StartStreamPos( nTab, nStartOffset );
426         }
427 	}
428 	GetScImport().UnlockSolarMutex();
429 }
430 
431