bump product version to 4.1.6.2
[LibreOffice.git] / sc / source / filter / excel / xicontent.cxx
blobe9430bf75e4d307abdc5addbc028a2d92034c7cd
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "xicontent.hxx"
21 #include <sfx2/objsh.hxx>
22 #include <sfx2/docfile.hxx>
23 #include <tools/urlobj.hxx>
24 #include <editeng/editeng.hxx>
25 #include <editeng/editobj.hxx>
26 #include <sfx2/linkmgr.hxx>
27 #include <svl/itemset.hxx>
28 #include "scitems.hxx"
29 #include <editeng/eeitem.hxx>
30 #include <svl/intitem.hxx>
31 #include <svl/stritem.hxx>
32 #include <editeng/flditem.hxx>
33 #include <editeng/fhgtitem.hxx>
34 #include <editeng/wghtitem.hxx>
35 #include <editeng/udlnitem.hxx>
36 #include <editeng/postitem.hxx>
37 #include <editeng/colritem.hxx>
38 #include <editeng/crossedoutitem.hxx>
39 #include "stringutil.hxx"
40 #include "document.hxx"
41 #include "editutil.hxx"
42 #include "formulacell.hxx"
43 #include "validat.hxx"
44 #include "patattr.hxx"
45 #include "docpool.hxx"
46 #include "rangenam.hxx"
47 #include "arealink.hxx"
48 #include "stlsheet.hxx"
49 #include "scextopt.hxx"
50 #include "xlformula.hxx"
51 #include "xltracer.hxx"
52 #include "xistream.hxx"
53 #include "xihelper.hxx"
54 #include "xistyle.hxx"
55 #include "xiescher.hxx"
56 #include "xiname.hxx"
58 #include "excform.hxx"
59 #include "tabprotection.hxx"
61 #include <memory>
63 using ::com::sun::star::uno::Sequence;
64 using ::std::auto_ptr;
66 // Shared string table ========================================================
68 XclImpSst::XclImpSst( const XclImpRoot& rRoot ) :
69 XclImpRoot( rRoot )
73 void XclImpSst::ReadSst( XclImpStream& rStrm )
75 rStrm.Ignore( 4 );
76 sal_uInt32 nStrCount(0);
77 rStrm >> nStrCount;
78 maStrings.clear();
79 maStrings.reserve( static_cast< size_t >( nStrCount ) );
80 while( (nStrCount > 0) && rStrm.IsValid() )
82 XclImpString aString;
83 aString.Read( rStrm );
84 maStrings.push_back( aString );
85 --nStrCount;
89 const XclImpString* XclImpSst::GetString( sal_uInt32 nSstIndex ) const
91 return (nSstIndex < maStrings.size()) ? &maStrings[ nSstIndex ] : 0;
94 // Hyperlinks =================================================================
96 namespace {
98 /** Reads character array and stores it into rString.
99 @param nChars Number of following characters (not byte count!).
100 @param b16Bit true = 16-bit characters, false = 8-bit characters. */
101 void lclAppendString32( String& rString, XclImpStream& rStrm, sal_uInt32 nChars, bool b16Bit )
103 sal_uInt16 nReadChars = ulimit_cast< sal_uInt16 >( nChars );
104 rString.Append( rStrm.ReadRawUniString( nReadChars, b16Bit ) );
105 // ignore remaining chars
106 sal_Size nIgnore = nChars - nReadChars;
107 if( b16Bit )
108 nIgnore *= 2;
109 rStrm.Ignore( nIgnore );
112 /** Reads 32-bit string length and the character array and stores it into rString.
113 @param b16Bit true = 16-bit characters, false = 8-bit characters. */
114 void lclAppendString32( String& rString, XclImpStream& rStrm, bool b16Bit )
116 lclAppendString32( rString, rStrm, rStrm.ReaduInt32(), b16Bit );
119 /** Reads 32-bit string length and ignores following character array.
120 @param b16Bit true = 16-bit characters, false = 8-bit characters. */
121 void lclIgnoreString32( XclImpStream& rStrm, bool b16Bit )
123 sal_uInt32 nChars(0);
124 rStrm >> nChars;
125 if( b16Bit )
126 nChars *= 2;
127 rStrm.Ignore( nChars );
130 /** Converts a path to an absolute path.
131 @param rPath The source path. The resulting path is returned here.
132 @param nLevel Number of parent directories to add in front of the path. */
133 void lclGetAbsPath( String& rPath, sal_uInt16 nLevel, SfxObjectShell* pDocShell )
135 String aTmpStr;
136 while( nLevel )
138 aTmpStr.AppendAscii( "../" );
139 --nLevel;
141 aTmpStr += rPath;
143 if( pDocShell )
145 bool bWasAbs = false;
146 rPath = pDocShell->GetMedium()->GetURLObject().smartRel2Abs( aTmpStr, bWasAbs ).GetMainURL( INetURLObject::NO_DECODE );
147 // full path as stored in SvxURLField must be encoded
149 else
150 rPath = aTmpStr;
153 /** Inserts the URL into a text cell. Does not modify value or formula cells. */
154 void lclInsertUrl( const XclImpRoot& rRoot, const String& rUrl, SCCOL nScCol, SCROW nScRow, SCTAB nScTab )
156 ScDocument& rDoc = rRoot.GetDoc();
157 ScAddress aScPos( nScCol, nScRow, nScTab );
158 CellType eCellType = rDoc.GetCellType( aScPos );
159 switch( eCellType )
161 // #i54261# hyperlinks in string cells
162 case CELLTYPE_STRING:
163 case CELLTYPE_EDIT:
165 OUString aDisplText = rDoc.GetString(nScCol, nScRow, nScTab);
166 if (aDisplText.isEmpty())
167 aDisplText = rUrl;
169 ScEditEngineDefaulter& rEE = rRoot.GetEditEngine();
170 SvxURLField aUrlField( rUrl, aDisplText, SVXURLFORMAT_APPDEFAULT );
172 const EditTextObject* pEditObj = rDoc.GetEditText(aScPos);
173 if( pEditObj )
175 rEE.SetText( *pEditObj );
176 rEE.QuickInsertField( SvxFieldItem( aUrlField, EE_FEATURE_FIELD ), ESelection( 0, 0, EE_PARA_ALL, 0 ) );
178 else
180 rEE.SetText( EMPTY_STRING );
181 rEE.QuickInsertField( SvxFieldItem( aUrlField, EE_FEATURE_FIELD ), ESelection() );
182 if( const ScPatternAttr* pPattern = rDoc.GetPattern( aScPos.Col(), aScPos.Row(), nScTab ) )
184 SfxItemSet aItemSet( rEE.GetEmptyItemSet() );
185 pPattern->FillEditItemSet( &aItemSet );
186 rEE.QuickSetAttribs( aItemSet, ESelection( 0, 0, EE_PARA_ALL, 0 ) );
190 // The cell will own the text object instance.
191 rDoc.SetEditText(aScPos, rEE.CreateTextObject());
193 break;
195 default:
196 // Handle other cell types e.g. formulas ( and ? ) that have associated
197 // hyperlinks.
198 // Ideally all hyperlinks should be treated as below. For the moment,
199 // given the current absence of ods support lets just handle what we
200 // previously didn't handle the new way.
201 // Unfortunately we won't be able to preserve such hyperlinks when
202 // saving to ods. Note: when we are able to save such hyperlinks to ods
203 // we should handle *all* imported hyperlinks as below ( e.g. as cell
204 // attribute ) for better interoperability.
206 SfxStringItem aItem( ATTR_HYPERLINK, rUrl );
207 rDoc.ApplyAttr( nScCol, nScRow, nScTab, aItem );
208 break;
213 } // namespace
215 // ----------------------------------------------------------------------------
217 void XclImpHyperlink::ReadHlink( XclImpStream& rStrm )
219 XclRange aXclRange( ScAddress::UNINITIALIZED );
220 rStrm >> aXclRange;
221 // #i80006# Excel silently ignores invalid hi-byte of column index (TODO: everywhere?)
222 aXclRange.maFirst.mnCol &= 0xFF;
223 aXclRange.maLast.mnCol &= 0xFF;
224 String aString = ReadEmbeddedData( rStrm );
225 if ( aString.Len() > 0 )
226 rStrm.GetRoot().GetXFRangeBuffer().SetHyperlink( aXclRange, aString );
229 String XclImpHyperlink::ReadEmbeddedData( XclImpStream& rStrm )
231 const XclImpRoot& rRoot = rStrm.GetRoot();
232 SfxObjectShell* pDocShell = rRoot.GetDocShell();
234 OSL_ENSURE_BIFF( rRoot.GetBiff() == EXC_BIFF8 );
236 XclGuid aGuid;
237 rStrm >> aGuid;
238 rStrm.Ignore( 4 );
239 sal_uInt32 nFlags(0);
240 rStrm >> nFlags;
242 OSL_ENSURE( aGuid == XclTools::maGuidStdLink, "XclImpHyperlink::ReadEmbeddedData - unknown header GUID" );
244 SAL_WNODEPRECATED_DECLARATIONS_PUSH
245 ::std::auto_ptr< String > xLongName; // link / file name
246 ::std::auto_ptr< String > xShortName; // 8.3-representation of file name
247 ::std::auto_ptr< String > xTextMark; // text mark
248 SAL_WNODEPRECATED_DECLARATIONS_POP
250 // description (ignore)
251 if( ::get_flag( nFlags, EXC_HLINK_DESCR ) )
252 lclIgnoreString32( rStrm, true );
253 // target frame (ignore) !! DESCR/FRAME - is this the right order? (never seen them together)
254 if( ::get_flag( nFlags, EXC_HLINK_FRAME ) )
255 lclIgnoreString32( rStrm, true );
257 // URL fields are zero-terminated - do not let the stream replace them
258 // in the lclAppendString32() with the '?' character.
259 rStrm.SetNulSubstChar( '\0' );
261 // UNC path
262 if( ::get_flag( nFlags, EXC_HLINK_UNC ) )
264 xLongName.reset( new String );
265 lclAppendString32( *xLongName, rStrm, true );
266 lclGetAbsPath( *xLongName, 0, pDocShell );
268 // file link or URL
269 else if( ::get_flag( nFlags, EXC_HLINK_BODY ) )
271 rStrm >> aGuid;
273 if( aGuid == XclTools::maGuidFileMoniker )
275 sal_uInt16 nLevel = 0; // counter for level to climb down in path
276 rStrm >> nLevel;
277 xShortName.reset( new String );
278 lclAppendString32( *xShortName, rStrm, false );
279 rStrm.Ignore( 24 );
281 sal_uInt32 nStrLen = 0;
282 rStrm >> nStrLen;
283 if( nStrLen )
285 nStrLen = 0;
286 rStrm >> nStrLen;
287 nStrLen /= 2; // it's byte count here...
288 rStrm.Ignore( 2 );
289 xLongName.reset( new String );
290 lclAppendString32( *xLongName, rStrm, nStrLen, true );
291 lclGetAbsPath( *xLongName, nLevel, pDocShell );
293 else
294 lclGetAbsPath( *xShortName, nLevel, pDocShell );
296 else if( aGuid == XclTools::maGuidUrlMoniker )
298 sal_uInt32 nStrLen(0);
299 rStrm >> nStrLen;
300 nStrLen /= 2; // it's byte count here...
301 xLongName.reset( new String );
302 lclAppendString32( *xLongName, rStrm, nStrLen, true );
303 if( !::get_flag( nFlags, EXC_HLINK_ABS ) )
304 lclGetAbsPath( *xLongName, 0, pDocShell );
306 else
308 OSL_FAIL( "XclImpHyperlink::ReadEmbeddedData - unknown content GUID" );
312 // text mark
313 if( ::get_flag( nFlags, EXC_HLINK_MARK ) )
315 xTextMark.reset( new String );
316 lclAppendString32( *xTextMark, rStrm, true );
319 rStrm.SetNulSubstChar(); // back to default
321 OSL_ENSURE( rStrm.GetRecLeft() == 0, "XclImpHyperlink::ReadEmbeddedData - record size mismatch" );
323 if( !xLongName.get() && xShortName.get() )
324 xLongName = xShortName;
325 else if( !xLongName.get() && xTextMark.get() )
326 xLongName.reset( new String );
328 if( xLongName.get() )
330 if( xTextMark.get() )
332 if( xLongName->Len() == 0 )
333 xTextMark->SearchAndReplaceAll( '!', '.' );
334 xLongName->Append( '#' );
335 xLongName->Append( *xTextMark );
337 return *xLongName;
339 return String::EmptyString();
342 void XclImpHyperlink::ConvertToValidTabName(String& rUrl)
344 xub_StrLen n = rUrl.Len();
345 if (n < 4)
346 // Needs at least 4 characters.
347 return;
349 sal_Unicode c = rUrl.GetChar(0);
350 if (c != sal_Unicode('#'))
351 // the 1st character must be '#'.
352 return;
354 String aNewUrl(OUString('#')), aTabName;
356 bool bInQuote = false;
357 bool bQuoteTabName = false;
358 for (xub_StrLen i = 1; i < n; ++i)
360 c = rUrl.GetChar(i);
361 if (c == sal_Unicode('\''))
363 if (bInQuote && i+1 < n && rUrl.GetChar(i+1) == sal_Unicode('\''))
365 // Two consecutive single quotes ('') signify a single literal
366 // quite. When this occurs, the whole table name needs to be
367 // quoted.
368 bQuoteTabName = true;
369 aTabName.Append(c);
370 aTabName.Append(c);
371 ++i;
372 continue;
375 bInQuote = !bInQuote;
376 if (!bInQuote && aTabName.Len() > 0)
378 if (bQuoteTabName)
379 aNewUrl.Append(sal_Unicode('\''));
380 aNewUrl.Append(aTabName);
381 if (bQuoteTabName)
382 aNewUrl.Append(sal_Unicode('\''));
385 else if (bInQuote)
386 aTabName.Append(c);
387 else
388 aNewUrl.Append(c);
391 if (bInQuote)
392 // It should be outside the quotes!
393 return;
395 // All is good. Pass the new URL.
396 rUrl = aNewUrl;
399 void XclImpHyperlink::InsertUrl( const XclImpRoot& rRoot, const XclRange& rXclRange, const String& rUrl )
401 String aUrl(rUrl);
402 ConvertToValidTabName(aUrl);
404 SCTAB nScTab = rRoot.GetCurrScTab();
405 ScRange aScRange( ScAddress::UNINITIALIZED );
406 if( rRoot.GetAddressConverter().ConvertRange( aScRange, rXclRange, nScTab, nScTab, true ) )
408 SCCOL nScCol1, nScCol2;
409 SCROW nScRow1, nScRow2;
410 aScRange.GetVars( nScCol1, nScRow1, nScTab, nScCol2, nScRow2, nScTab );
411 for( SCCOL nScCol = nScCol1; nScCol <= nScCol2; ++nScCol )
412 for( SCROW nScRow = nScRow1; nScRow <= nScRow2; ++nScRow )
413 lclInsertUrl( rRoot, aUrl, nScCol, nScRow, nScTab );
417 // Label ranges ===============================================================
419 void XclImpLabelranges::ReadLabelranges( XclImpStream& rStrm )
421 const XclImpRoot& rRoot = rStrm.GetRoot();
422 OSL_ENSURE_BIFF( rRoot.GetBiff() == EXC_BIFF8 );
424 ScDocument& rDoc = rRoot.GetDoc();
425 SCTAB nScTab = rRoot.GetCurrScTab();
426 XclImpAddressConverter& rAddrConv = rRoot.GetAddressConverter();
427 ScRangePairListRef xLabelRangesRef;
428 const ScRange* pScRange = 0;
430 XclRangeList aRowXclRanges, aColXclRanges;
431 rStrm >> aRowXclRanges >> aColXclRanges;
433 // row label ranges
434 ScRangeList aRowScRanges;
435 rAddrConv.ConvertRangeList( aRowScRanges, aRowXclRanges, nScTab, false );
436 xLabelRangesRef = rDoc.GetRowNameRangesRef();
437 for ( size_t i = 0, nRanges = aRowScRanges.size(); i < nRanges; ++i )
439 pScRange = aRowScRanges[ i ];
440 ScRange aDataRange( *pScRange );
441 if( aDataRange.aEnd.Col() < MAXCOL )
443 aDataRange.aStart.SetCol( aDataRange.aEnd.Col() + 1 );
444 aDataRange.aEnd.SetCol( MAXCOL );
446 else if( aDataRange.aStart.Col() > 0 )
448 aDataRange.aEnd.SetCol( aDataRange.aStart.Col() - 1 );
449 aDataRange.aStart.SetCol( 0 );
451 xLabelRangesRef->Append( ScRangePair( *pScRange, aDataRange ) );
454 // column label ranges
455 ScRangeList aColScRanges;
456 rAddrConv.ConvertRangeList( aColScRanges, aColXclRanges, nScTab, false );
457 xLabelRangesRef = rDoc.GetColNameRangesRef();
459 for ( size_t i = 0, nRanges = aColScRanges.size(); i < nRanges; ++i )
461 pScRange = aColScRanges[ i ];
462 ScRange aDataRange( *pScRange );
463 if( aDataRange.aEnd.Row() < MAXROW )
465 aDataRange.aStart.SetRow( aDataRange.aEnd.Row() + 1 );
466 aDataRange.aEnd.SetRow( MAXROW );
468 else if( aDataRange.aStart.Row() > 0 )
470 aDataRange.aEnd.SetRow( aDataRange.aStart.Row() - 1 );
471 aDataRange.aStart.SetRow( 0 );
473 xLabelRangesRef->Append( ScRangePair( *pScRange, aDataRange ) );
477 // Conditional formatting =====================================================
479 XclImpCondFormat::XclImpCondFormat( const XclImpRoot& rRoot, sal_uInt32 nFormatIndex ) :
480 XclImpRoot( rRoot ),
481 mnFormatIndex( nFormatIndex ),
482 mnCondCount( 0 ),
483 mnCondIndex( 0 )
487 XclImpCondFormat::~XclImpCondFormat()
491 void XclImpCondFormat::ReadCondfmt( XclImpStream& rStrm )
493 OSL_ENSURE( !mnCondCount, "XclImpCondFormat::ReadCondfmt - already initialized" );
494 XclRangeList aXclRanges;
495 rStrm >> mnCondCount;
496 rStrm.Ignore( 10 );
497 rStrm >> aXclRanges;
498 GetAddressConverter().ConvertRangeList( maRanges, aXclRanges, GetCurrScTab(), true );
501 void XclImpCondFormat::ReadCF( XclImpStream& rStrm )
503 if( mnCondIndex >= mnCondCount )
505 OSL_FAIL( "XclImpCondFormat::ReadCF - CF without leading CONDFMT" );
506 return;
509 // entire conditional format outside of valid range?
510 if( maRanges.empty() )
511 return;
513 sal_uInt8 nType(0), nOperator(0);
514 sal_uInt16 nFmlaSize1(0), nFmlaSize2(0);
515 sal_uInt32 nFlags(0);
517 rStrm >> nType >> nOperator >> nFmlaSize1 >> nFmlaSize2 >> nFlags;
518 rStrm.Ignore( 2 );
520 // *** mode and comparison operator ***
522 ScConditionMode eMode = SC_COND_NONE;
523 switch( nType )
525 case EXC_CF_TYPE_CELL:
527 switch( nOperator )
529 case EXC_CF_CMP_BETWEEN: eMode = SC_COND_BETWEEN; break;
530 case EXC_CF_CMP_NOT_BETWEEN: eMode = SC_COND_NOTBETWEEN; break;
531 case EXC_CF_CMP_EQUAL: eMode = SC_COND_EQUAL; break;
532 case EXC_CF_CMP_NOT_EQUAL: eMode = SC_COND_NOTEQUAL; break;
533 case EXC_CF_CMP_GREATER: eMode = SC_COND_GREATER; break;
534 case EXC_CF_CMP_LESS: eMode = SC_COND_LESS; break;
535 case EXC_CF_CMP_GREATER_EQUAL: eMode = SC_COND_EQGREATER; break;
536 case EXC_CF_CMP_LESS_EQUAL: eMode = SC_COND_EQLESS; break;
537 default:
538 OSL_TRACE( "XclImpCondFormat::ReadCF - unknown CF comparison 0x%02hX", nOperator );
541 break;
543 case EXC_CF_TYPE_FMLA:
544 eMode = SC_COND_DIRECT;
545 break;
547 default:
548 OSL_TRACE( "XclImpCondFormat::ReadCF - unknown CF mode 0x%02hX", nType );
549 return;
552 // *** create style sheet ***
554 String aStyleName( XclTools::GetCondFormatStyleName( GetCurrScTab(), mnFormatIndex, mnCondIndex ) );
555 SfxItemSet& rStyleItemSet = ScfTools::MakeCellStyleSheet( GetStyleSheetPool(), aStyleName, true ).GetItemSet();
557 const XclImpPalette& rPalette = GetPalette();
559 // *** font block ***
561 if( ::get_flag( nFlags, EXC_CF_BLOCK_FONT ) )
563 XclImpFont aFont( GetRoot() );
564 aFont.ReadCFFontBlock( rStrm );
565 aFont.FillToItemSet( rStyleItemSet, EXC_FONTITEM_CELL );
568 // *** border block ***
570 if( ::get_flag( nFlags, EXC_CF_BLOCK_BORDER ) )
572 sal_uInt16 nLineStyle(0);
573 sal_uInt32 nLineColor(0);
574 rStrm >> nLineStyle >> nLineColor;
575 rStrm.Ignore( 2 );
577 XclImpCellBorder aBorder;
578 aBorder.FillFromCF8( nLineStyle, nLineColor, nFlags );
579 aBorder.FillToItemSet( rStyleItemSet, rPalette );
582 // *** pattern block ***
584 if( ::get_flag( nFlags, EXC_CF_BLOCK_AREA ) )
586 sal_uInt16 nPattern(0), nColor(0);
587 rStrm >> nPattern >> nColor;
589 XclImpCellArea aArea;
590 aArea.FillFromCF8( nPattern, nColor, nFlags );
591 aArea.FillToItemSet( rStyleItemSet, rPalette );
594 // *** formulas ***
596 const ScAddress& rPos = maRanges.front()->aStart; // assured above that maRanges is not empty
597 ExcelToSc& rFmlaConv = GetOldFmlaConverter();
599 SAL_WNODEPRECATED_DECLARATIONS_PUSH
600 ::std::auto_ptr< ScTokenArray > xTokArr1;
601 SAL_WNODEPRECATED_DECLARATIONS_POP
602 if( nFmlaSize1 > 0 )
604 const ScTokenArray* pTokArr = 0;
605 rFmlaConv.Reset( rPos );
606 rFmlaConv.Convert( pTokArr, rStrm, nFmlaSize1, false, FT_CondFormat );
607 // formula converter owns pTokArr -> create a copy of the token array
608 if( pTokArr )
609 xTokArr1.reset( pTokArr->Clone() );
612 SAL_WNODEPRECATED_DECLARATIONS_PUSH
613 ::std::auto_ptr< ScTokenArray > pTokArr2;
614 SAL_WNODEPRECATED_DECLARATIONS_POP
615 if( nFmlaSize2 > 0 )
617 const ScTokenArray* pTokArr = 0;
618 rFmlaConv.Reset( rPos );
619 rFmlaConv.Convert( pTokArr, rStrm, nFmlaSize2, false, FT_CondFormat );
620 // formula converter owns pTokArr -> create a copy of the token array
621 if( pTokArr )
622 pTokArr2.reset( pTokArr->Clone() );
625 // *** create the Calc conditional formatting ***
627 if( !mxScCondFmt.get() )
629 sal_uLong nKey = 0;
630 mxScCondFmt.reset( new ScConditionalFormat( nKey, GetDocPtr() ) );
631 if(maRanges.size() > 1)
632 maRanges.Join(*maRanges[0], true);
633 mxScCondFmt->AddRange(maRanges);
636 ScCondFormatEntry* pEntry = new ScCondFormatEntry( eMode, xTokArr1.get(), pTokArr2.get(), GetDocPtr(), rPos, aStyleName );
637 mxScCondFmt->AddEntry( pEntry );
638 ++mnCondIndex;
641 void XclImpCondFormat::Apply()
643 if( mxScCondFmt.get() )
645 ScDocument& rDoc = GetDoc();
647 SCTAB nTab = maRanges.front()->aStart.Tab();
648 sal_uLong nKey = rDoc.AddCondFormat( mxScCondFmt->Clone(), nTab );
650 rDoc.AddCondFormatData( maRanges, nTab, nKey );
654 // ----------------------------------------------------------------------------
656 XclImpCondFormatManager::XclImpCondFormatManager( const XclImpRoot& rRoot ) :
657 XclImpRoot( rRoot )
661 void XclImpCondFormatManager::ReadCondfmt( XclImpStream& rStrm )
663 XclImpCondFormat* pFmt = new XclImpCondFormat( GetRoot(), maCondFmtList.size() );
664 pFmt->ReadCondfmt( rStrm );
665 maCondFmtList.push_back( pFmt );
668 void XclImpCondFormatManager::ReadCF( XclImpStream& rStrm )
670 OSL_ENSURE( !maCondFmtList.empty(), "XclImpCondFormatManager::ReadCF - CF without leading CONDFMT" );
671 if( !maCondFmtList.empty() )
672 maCondFmtList.back().ReadCF( rStrm );
675 void XclImpCondFormatManager::Apply()
677 for( XclImpCondFmtList::iterator itFmt = maCondFmtList.begin(); itFmt != maCondFmtList.end(); ++itFmt )
678 itFmt->Apply();
679 maCondFmtList.clear();
682 // Data Validation ============================================================
684 XclImpValidationManager::DVItem::DVItem( const ScRangeList& rRanges, const ScValidationData& rValidData ) :
685 maRanges(rRanges), maValidData(rValidData) {}
687 XclImpValidationManager::XclImpValidationManager( const XclImpRoot& rRoot ) :
688 XclImpRoot( rRoot )
692 void XclImpValidationManager::ReadDval( XclImpStream& rStrm )
694 const XclImpRoot& rRoot = rStrm.GetRoot();
695 OSL_ENSURE_BIFF( rRoot.GetBiff() == EXC_BIFF8 );
697 sal_uInt32 nObjId(0);
698 rStrm.Ignore( 10 );
699 rStrm >> nObjId;
700 if( nObjId != EXC_DVAL_NOOBJ )
702 OSL_ENSURE( nObjId <= 0xFFFF, "XclImpValidation::ReadDval - invalid object ID" );
703 rRoot.GetCurrSheetDrawing().SetSkipObj( static_cast< sal_uInt16 >( nObjId ) );
707 void XclImpValidationManager::ReadDV( XclImpStream& rStrm )
709 const XclImpRoot& rRoot = rStrm.GetRoot();
710 OSL_ENSURE_BIFF( rRoot.GetBiff() == EXC_BIFF8 );
712 ScDocument& rDoc = rRoot.GetDoc();
713 SCTAB nScTab = rRoot.GetCurrScTab();
714 ExcelToSc& rFmlaConv = rRoot.GetOldFmlaConverter();
716 // flags
717 sal_uInt32 nFlags(0);
718 rStrm >> nFlags;
720 // message strings
721 /* Empty strings are single NUL characters in Excel (string length is 1).
722 -> Do not let the stream replace them with '?' characters. */
723 rStrm.SetNulSubstChar( '\0' );
724 String aPromptTitle( rStrm.ReadUniString() );
725 String aErrorTitle( rStrm.ReadUniString() );
726 String aPromptMessage( rStrm.ReadUniString() );
727 String aErrorMessage( rStrm.ReadUniString() );
728 rStrm.SetNulSubstChar(); // back to default
730 // formula(s)
731 if ( rStrm.GetRecLeft() <= 8 )
732 // Not enough bytes left in the record. Bail out.
733 return;
736 // first formula
737 // string list is single tStr token with NUL separators -> replace them with LF
738 rStrm.SetNulSubstChar( '\n' );
739 SAL_WNODEPRECATED_DECLARATIONS_PUSH
740 ::std::auto_ptr< ScTokenArray > xTokArr1;
741 SAL_WNODEPRECATED_DECLARATIONS_POP
743 sal_uInt16 nLen = 0;
744 rStrm >> nLen;
745 rStrm.Ignore( 2 );
746 if( nLen > 0 )
748 const ScTokenArray* pTokArr = 0;
749 rFmlaConv.Reset();
750 rFmlaConv.Convert( pTokArr, rStrm, nLen, false, FT_CondFormat );
751 // formula converter owns pTokArr -> create a copy of the token array
752 if( pTokArr )
753 xTokArr1.reset( pTokArr->Clone() );
755 rStrm.SetNulSubstChar(); // back to default
757 // second formula
758 SAL_WNODEPRECATED_DECLARATIONS_PUSH
759 ::std::auto_ptr< ScTokenArray > xTokArr2;
760 SAL_WNODEPRECATED_DECLARATIONS_POP
762 nLen = 0;
763 rStrm >> nLen;
764 rStrm.Ignore( 2 );
765 if( nLen > 0 )
767 const ScTokenArray* pTokArr = 0;
768 rFmlaConv.Reset();
769 rFmlaConv.Convert( pTokArr, rStrm, nLen, false, FT_CondFormat );
770 // formula converter owns pTokArr -> create a copy of the token array
771 if( pTokArr )
772 xTokArr2.reset( pTokArr->Clone() );
775 // read all cell ranges
776 XclRangeList aXclRanges;
777 rStrm >> aXclRanges;
779 // convert to Calc range list
780 ScRangeList aScRanges;
781 rRoot.GetAddressConverter().ConvertRangeList( aScRanges, aXclRanges, nScTab, true );
783 // only continue if there are valid ranges
784 if ( aScRanges.empty() )
785 return;
787 bool bIsValid = true; // valid settings in flags field
789 ScValidationMode eValMode = SC_VALID_ANY;
790 switch( nFlags & EXC_DV_MODE_MASK )
792 case EXC_DV_MODE_ANY: eValMode = SC_VALID_ANY; break;
793 case EXC_DV_MODE_WHOLE: eValMode = SC_VALID_WHOLE; break;
794 case EXC_DV_MODE_DECIMAL: eValMode = SC_VALID_DECIMAL; break;
795 case EXC_DV_MODE_LIST: eValMode = SC_VALID_LIST; break;
796 case EXC_DV_MODE_DATE: eValMode = SC_VALID_DATE; break;
797 case EXC_DV_MODE_TIME: eValMode = SC_VALID_TIME; break;
798 case EXC_DV_MODE_TEXTLEN: eValMode = SC_VALID_TEXTLEN; break;
799 case EXC_DV_MODE_CUSTOM: eValMode = SC_VALID_CUSTOM; break;
800 default: bIsValid = false;
802 rRoot.GetTracer().TraceDVType(eValMode == SC_VALID_CUSTOM);
804 ScConditionMode eCondMode = SC_COND_BETWEEN;
805 switch( nFlags & EXC_DV_COND_MASK )
807 case EXC_DV_COND_BETWEEN: eCondMode = SC_COND_BETWEEN; break;
808 case EXC_DV_COND_NOTBETWEEN:eCondMode = SC_COND_NOTBETWEEN; break;
809 case EXC_DV_COND_EQUAL: eCondMode = SC_COND_EQUAL; break;
810 case EXC_DV_COND_NOTEQUAL: eCondMode = SC_COND_NOTEQUAL; break;
811 case EXC_DV_COND_GREATER: eCondMode = SC_COND_GREATER; break;
812 case EXC_DV_COND_LESS: eCondMode = SC_COND_LESS; break;
813 case EXC_DV_COND_EQGREATER: eCondMode = SC_COND_EQGREATER; break;
814 case EXC_DV_COND_EQLESS: eCondMode = SC_COND_EQLESS; break;
815 default: bIsValid = false;
818 if ( !bIsValid )
819 // No valid validation found. Bail out.
820 return;
823 // first range for base address for relative references
824 const ScRange& rScRange = *aScRanges.front(); // aScRanges is not empty
826 // process string list of a list validity (convert to list of string tokens)
827 if( xTokArr1.get() && (eValMode == SC_VALID_LIST) && ::get_flag( nFlags, EXC_DV_STRINGLIST ) )
828 XclTokenArrayHelper::ConvertStringToList( *xTokArr1, '\n', true );
830 maDVItems.push_back(
831 new DVItem(aScRanges, ScValidationData(eValMode, eCondMode, xTokArr1.get(), xTokArr2.get(), &rDoc, rScRange.aStart)));
832 DVItem& rItem = maDVItems.back();
834 rItem.maValidData.SetIgnoreBlank( ::get_flag( nFlags, EXC_DV_IGNOREBLANK ) );
835 rItem.maValidData.SetListType( ::get_flagvalue( nFlags, EXC_DV_SUPPRESSDROPDOWN, ValidListType::INVISIBLE, ValidListType::UNSORTED ) );
837 // *** prompt box ***
838 if( aPromptTitle.Len() || aPromptMessage.Len() )
840 // set any text stored in the record
841 rItem.maValidData.SetInput( aPromptTitle, aPromptMessage );
842 if( !::get_flag( nFlags, EXC_DV_SHOWPROMPT ) )
843 rItem.maValidData.ResetInput();
846 // *** error box ***
847 ScValidErrorStyle eErrStyle = SC_VALERR_STOP;
848 switch( nFlags & EXC_DV_ERROR_MASK )
850 case EXC_DV_ERROR_WARNING: eErrStyle = SC_VALERR_WARNING; break;
851 case EXC_DV_ERROR_INFO: eErrStyle = SC_VALERR_INFO; break;
853 // set texts and error style
854 rItem.maValidData.SetError( aErrorTitle, aErrorMessage, eErrStyle );
855 if( !::get_flag( nFlags, EXC_DV_SHOWERROR ) )
856 rItem.maValidData.ResetError();
859 void XclImpValidationManager::Apply()
861 ScDocument& rDoc = GetRoot().GetDoc();
862 DVItemList::iterator itr = maDVItems.begin(), itrEnd = maDVItems.end();
863 for (; itr != itrEnd; ++itr)
865 DVItem& rItem = *itr;
866 // set the handle ID
867 sal_uLong nHandle = rDoc.AddValidationEntry( rItem.maValidData );
868 ScPatternAttr aPattern( rDoc.GetPool() );
869 aPattern.GetItemSet().Put( SfxUInt32Item( ATTR_VALIDDATA, nHandle ) );
871 // apply all ranges
872 for ( size_t i = 0, nRanges = rItem.maRanges.size(); i < nRanges; ++i )
874 const ScRange* pScRange = rItem.maRanges[ i ];
875 rDoc.ApplyPatternAreaTab( pScRange->aStart.Col(), pScRange->aStart.Row(),
876 pScRange->aEnd.Col(), pScRange->aEnd.Row(), pScRange->aStart.Tab(), aPattern );
879 maDVItems.clear();
882 // Web queries ================================================================
884 XclImpWebQuery::XclImpWebQuery( const ScRange& rDestRange ) :
885 maDestRange( rDestRange ),
886 meMode( xlWQUnknown ),
887 mnRefresh( 0 )
891 void XclImpWebQuery::ReadParamqry( XclImpStream& rStrm )
893 sal_uInt16 nFlags = rStrm.ReaduInt16();
894 sal_uInt16 nType = ::extract_value< sal_uInt16 >( nFlags, 0, 3 );
895 if( (nType == EXC_PQRYTYPE_WEBQUERY) && ::get_flag( nFlags, EXC_PQRY_WEBQUERY ) )
897 if( ::get_flag( nFlags, EXC_PQRY_TABLES ) )
899 meMode = xlWQAllTables;
900 maTables = ScfTools::GetHTMLTablesName();
902 else
904 meMode = xlWQDocument;
905 maTables = ScfTools::GetHTMLDocName();
910 void XclImpWebQuery::ReadWqstring( XclImpStream& rStrm )
912 maURL = rStrm.ReadUniString();
915 void XclImpWebQuery::ReadWqsettings( XclImpStream& rStrm )
917 rStrm.Ignore( 10 );
918 sal_uInt16 nFlags(0);
919 rStrm >> nFlags;
920 rStrm.Ignore( 10 );
921 rStrm >> mnRefresh;
923 if( ::get_flag( nFlags, EXC_WQSETT_SPECTABLES ) && (meMode == xlWQAllTables) )
924 meMode = xlWQSpecTables;
927 void XclImpWebQuery::ReadWqtables( XclImpStream& rStrm )
929 if( meMode == xlWQSpecTables )
931 rStrm.Ignore( 4 );
932 OUString aTables( rStrm.ReadUniString() );
934 const sal_Unicode cSep = ';';
935 OUString aQuotedPairs( "\"\"" );
936 xub_StrLen nTokenCnt = ScStringUtil::GetQuotedTokenCount( aTables, aQuotedPairs, ',' );
937 maTables.Erase();
938 sal_Int32 nStringIx = 0;
939 for( xub_StrLen nToken = 0; nToken < nTokenCnt; ++nToken )
941 OUString aToken( ScStringUtil::GetQuotedToken( aTables, 0, aQuotedPairs, ',', nStringIx ) );
942 sal_Int32 nTabNum = CharClass::isAsciiNumeric( aToken ) ? aToken.toInt32() : 0;
943 if( nTabNum > 0 )
944 maTables = ScGlobal::addToken( maTables, ScfTools::GetNameFromHTMLIndex( static_cast< sal_uInt32 >( nTabNum ) ), cSep );
945 else
947 ScGlobal::EraseQuotes( aToken, '"', false );
948 if( !aToken.isEmpty() )
949 maTables = ScGlobal::addToken( maTables, ScfTools::GetNameFromHTMLName( aToken ), cSep );
955 void XclImpWebQuery::Apply( ScDocument& rDoc, const String& rFilterName )
957 if( maURL.Len() && (meMode != xlWQUnknown) && rDoc.GetDocumentShell() )
959 ScAreaLink* pLink = new ScAreaLink( rDoc.GetDocumentShell(),
960 maURL, rFilterName, EMPTY_STRING, maTables, maDestRange, mnRefresh * 60UL );
961 rDoc.GetLinkManager()->InsertFileLink( *pLink, OBJECT_CLIENT_FILE,
962 maURL, &rFilterName, &maTables );
966 // ----------------------------------------------------------------------------
968 XclImpWebQueryBuffer::XclImpWebQueryBuffer( const XclImpRoot& rRoot ) :
969 XclImpRoot( rRoot )
973 void XclImpWebQueryBuffer::ReadQsi( XclImpStream& rStrm )
975 if( GetBiff() == EXC_BIFF8 )
977 rStrm.Ignore( 10 );
978 String aXclName( rStrm.ReadUniString() );
980 // #i64794# Excel replaces spaces with underscores
981 aXclName.SearchAndReplaceAll( ' ', '_' );
983 // find the defined name used in Calc
984 if( const XclImpName* pName = GetNameManager().FindName( aXclName, GetCurrScTab() ) )
986 if( const ScRangeData* pRangeData = pName->GetScRangeData() )
988 ScRange aRange;
989 if( pRangeData->IsReference( aRange ) )
990 maWQList.push_back( new XclImpWebQuery( aRange ) );
994 else
996 DBG_ERROR_BIFF();
1000 void XclImpWebQueryBuffer::ReadParamqry( XclImpStream& rStrm )
1002 if (!maWQList.empty())
1003 maWQList.back().ReadParamqry( rStrm );
1006 void XclImpWebQueryBuffer::ReadWqstring( XclImpStream& rStrm )
1008 if (!maWQList.empty())
1009 maWQList.back().ReadWqstring( rStrm );
1012 void XclImpWebQueryBuffer::ReadWqsettings( XclImpStream& rStrm )
1014 if (!maWQList.empty())
1015 maWQList.back().ReadWqsettings( rStrm );
1018 void XclImpWebQueryBuffer::ReadWqtables( XclImpStream& rStrm )
1020 if (!maWQList.empty())
1021 maWQList.back().ReadWqtables( rStrm );
1024 void XclImpWebQueryBuffer::Apply()
1026 ScDocument& rDoc = GetDoc();
1027 String aFilterName( RTL_CONSTASCII_USTRINGPARAM( EXC_WEBQRY_FILTER ) );
1028 for( XclImpWebQueryList::iterator itQuery = maWQList.begin(); itQuery != maWQList.end(); ++itQuery )
1029 itQuery->Apply( rDoc, aFilterName );
1032 // Decryption =================================================================
1034 namespace {
1036 XclImpDecrypterRef lclReadFilepass5( XclImpStream& rStrm )
1038 XclImpDecrypterRef xDecr;
1039 OSL_ENSURE( rStrm.GetRecLeft() == 4, "lclReadFilepass5 - wrong record size" );
1040 if( rStrm.GetRecLeft() == 4 )
1042 sal_uInt16 nKey(0), nHash(0);
1043 rStrm >> nKey >> nHash;
1044 xDecr.reset( new XclImpBiff5Decrypter( nKey, nHash ) );
1046 return xDecr;
1049 XclImpDecrypterRef lclReadFilepass8_Standard( XclImpStream& rStrm )
1051 XclImpDecrypterRef xDecr;
1052 OSL_ENSURE( rStrm.GetRecLeft() == 48, "lclReadFilepass8 - wrong record size" );
1053 if( rStrm.GetRecLeft() == 48 )
1055 sal_uInt8 pnSalt[ 16 ];
1056 sal_uInt8 pnVerifier[ 16 ];
1057 sal_uInt8 pnVerifierHash[ 16 ];
1058 rStrm.Read( pnSalt, 16 );
1059 rStrm.Read( pnVerifier, 16 );
1060 rStrm.Read( pnVerifierHash, 16 );
1061 xDecr.reset( new XclImpBiff8Decrypter( pnSalt, pnVerifier, pnVerifierHash ) );
1063 return xDecr;
1066 XclImpDecrypterRef lclReadFilepass8_Strong( XclImpStream& /*rStrm*/ )
1068 // not supported
1069 return XclImpDecrypterRef();
1072 XclImpDecrypterRef lclReadFilepass8( XclImpStream& rStrm )
1074 XclImpDecrypterRef xDecr;
1076 sal_uInt16 nMode(0);
1077 rStrm >> nMode;
1078 switch( nMode )
1080 case EXC_FILEPASS_BIFF5:
1081 xDecr = lclReadFilepass5( rStrm );
1082 break;
1084 case EXC_FILEPASS_BIFF8:
1086 rStrm.Ignore( 2 );
1087 sal_uInt16 nSubMode(0);
1088 rStrm >> nSubMode;
1089 switch( nSubMode )
1091 case EXC_FILEPASS_BIFF8_STD:
1092 xDecr = lclReadFilepass8_Standard( rStrm );
1093 break;
1094 case EXC_FILEPASS_BIFF8_STRONG:
1095 xDecr = lclReadFilepass8_Strong( rStrm );
1096 break;
1097 default:
1098 OSL_FAIL( "lclReadFilepass8 - unknown BIFF8 encryption sub mode" );
1101 break;
1103 default:
1104 OSL_FAIL( "lclReadFilepass8 - unknown encryption mode" );
1107 return xDecr;
1110 } // namespace
1112 // ----------------------------------------------------------------------------
1114 ErrCode XclImpDecryptHelper::ReadFilepass( XclImpStream& rStrm )
1116 XclImpDecrypterRef xDecr;
1117 rStrm.DisableDecryption();
1119 // read the FILEPASS record and create a new decrypter object
1120 switch( rStrm.GetRoot().GetBiff() )
1122 case EXC_BIFF2:
1123 case EXC_BIFF3:
1124 case EXC_BIFF4:
1125 case EXC_BIFF5: xDecr = lclReadFilepass5( rStrm ); break;
1126 case EXC_BIFF8: xDecr = lclReadFilepass8( rStrm ); break;
1127 default: DBG_ERROR_BIFF();
1130 // set decrypter at import stream
1131 rStrm.SetDecrypter( xDecr );
1133 // request and verify a password (decrypter implements IDocPasswordVerifier)
1134 if( xDecr )
1135 rStrm.GetRoot().RequestEncryptionData( *xDecr );
1137 // return error code (success, wrong password, etc.)
1138 return xDecr ? xDecr->GetError() : EXC_ENCR_ERROR_UNSUPP_CRYPT;
1141 // Document protection ========================================================
1143 XclImpDocProtectBuffer::XclImpDocProtectBuffer( const XclImpRoot& rRoot ) :
1144 XclImpRoot( rRoot ),
1145 mnPassHash(0x0000),
1146 mbDocProtect(false),
1147 mbWinProtect(false)
1151 void XclImpDocProtectBuffer::ReadDocProtect( XclImpStream& rStrm )
1153 mbDocProtect = rStrm.ReaduInt16() ? true : false;
1156 void XclImpDocProtectBuffer::ReadWinProtect( XclImpStream& rStrm )
1158 mbWinProtect = rStrm.ReaduInt16() ? true : false;
1161 void XclImpDocProtectBuffer::ReadPasswordHash( XclImpStream& rStrm )
1163 rStrm.EnableDecryption();
1164 mnPassHash = rStrm.ReaduInt16();
1167 void XclImpDocProtectBuffer::Apply() const
1169 if (!mbDocProtect && !mbWinProtect)
1170 // Excel requires either the structure or windows protection is set.
1171 // If neither is set then the document is not protected at all.
1172 return;
1174 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1175 auto_ptr<ScDocProtection> pProtect(new ScDocProtection);
1176 SAL_WNODEPRECATED_DECLARATIONS_POP
1177 pProtect->setProtected(true);
1179 if (mnPassHash)
1181 // 16-bit password pash.
1182 Sequence<sal_Int8> aPass(2);
1183 aPass[0] = (mnPassHash >> 8) & 0xFF;
1184 aPass[1] = mnPassHash & 0xFF;
1185 pProtect->setPasswordHash(aPass, PASSHASH_XL);
1188 // document protection options
1189 pProtect->setOption(ScDocProtection::STRUCTURE, mbDocProtect);
1190 pProtect->setOption(ScDocProtection::WINDOWS, mbWinProtect);
1192 GetDoc().SetDocProtection(pProtect.get());
1195 // Sheet Protection ===========================================================
1197 XclImpSheetProtectBuffer::Sheet::Sheet() :
1198 mbProtected(false),
1199 mnPasswordHash(0x0000),
1200 mnOptions(0x4400)
1204 // ----------------------------------------------------------------------------
1206 XclImpSheetProtectBuffer::Sheet::Sheet(const Sheet& r) :
1207 mbProtected(r.mbProtected),
1208 mnPasswordHash(r.mnPasswordHash),
1209 mnOptions(r.mnOptions)
1213 XclImpSheetProtectBuffer::XclImpSheetProtectBuffer( const XclImpRoot& rRoot ) :
1214 XclImpRoot( rRoot )
1218 void XclImpSheetProtectBuffer::ReadProtect( XclImpStream& rStrm, SCTAB nTab )
1220 if ( rStrm.ReaduInt16() )
1222 Sheet* pSheet = GetSheetItem(nTab);
1223 if (pSheet)
1224 pSheet->mbProtected = true;
1228 void XclImpSheetProtectBuffer::ReadOptions( XclImpStream& rStrm, SCTAB nTab )
1230 rStrm.Ignore(12);
1232 // feature type can be either 2 or 4. If 2, this record stores flag for
1233 // enhanced protection, whereas if 4 it stores flag for smart tag.
1234 sal_uInt16 nFeatureType(0);
1235 rStrm >> nFeatureType;
1236 if (nFeatureType != 2)
1237 // We currently only support import of enhanced protection data.
1238 return;
1240 rStrm.Ignore(1); // always 1
1242 // The flag size specifies the size of bytes that follows that stores
1243 // feature data. If -1 it depends on the feature type imported earlier.
1244 // For enhanced protection data, the size is always 4. For the most xls
1245 // documents out there this value is almost always -1.
1246 sal_Int32 nFlagSize(0);
1247 rStrm >> nFlagSize;
1248 if (nFlagSize != -1)
1249 return;
1251 // There are actually 4 bytes to read, but the upper 2 bytes currently
1252 // don't store any bits.
1253 sal_uInt16 nOptions(0);
1254 rStrm >> nOptions;
1256 Sheet* pSheet = GetSheetItem(nTab);
1257 if (pSheet)
1258 pSheet->mnOptions = nOptions;
1261 void XclImpSheetProtectBuffer::ReadPasswordHash( XclImpStream& rStrm, SCTAB nTab )
1263 sal_uInt16 nHash(0);
1264 rStrm >> nHash;
1265 Sheet* pSheet = GetSheetItem(nTab);
1266 if (pSheet)
1267 pSheet->mnPasswordHash = nHash;
1270 void XclImpSheetProtectBuffer::Apply() const
1272 for (ProtectedSheetMap::const_iterator itr = maProtectedSheets.begin(), itrEnd = maProtectedSheets.end();
1273 itr != itrEnd; ++itr)
1275 if (!itr->second.mbProtected)
1276 // This sheet is (for whatever reason) not protected.
1277 continue;
1279 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1280 auto_ptr<ScTableProtection> pProtect(new ScTableProtection);
1281 SAL_WNODEPRECATED_DECLARATIONS_POP
1282 pProtect->setProtected(true);
1284 // 16-bit hash password
1285 const sal_uInt16 nHash = itr->second.mnPasswordHash;
1286 if (nHash)
1288 Sequence<sal_Int8> aPass(2);
1289 aPass[0] = (nHash >> 8) & 0xFF;
1290 aPass[1] = nHash & 0xFF;
1291 pProtect->setPasswordHash(aPass, PASSHASH_XL);
1294 // sheet protection options
1295 const sal_uInt16 nOptions = itr->second.mnOptions;
1296 pProtect->setOption( ScTableProtection::OBJECTS, (nOptions & 0x0001) );
1297 pProtect->setOption( ScTableProtection::SCENARIOS, (nOptions & 0x0002) );
1298 pProtect->setOption( ScTableProtection::FORMAT_CELLS, (nOptions & 0x0004) );
1299 pProtect->setOption( ScTableProtection::FORMAT_COLUMNS, (nOptions & 0x0008) );
1300 pProtect->setOption( ScTableProtection::FORMAT_ROWS, (nOptions & 0x0010) );
1301 pProtect->setOption( ScTableProtection::INSERT_COLUMNS, (nOptions & 0x0020) );
1302 pProtect->setOption( ScTableProtection::INSERT_ROWS, (nOptions & 0x0040) );
1303 pProtect->setOption( ScTableProtection::INSERT_HYPERLINKS, (nOptions & 0x0080) );
1304 pProtect->setOption( ScTableProtection::DELETE_COLUMNS, (nOptions & 0x0100) );
1305 pProtect->setOption( ScTableProtection::DELETE_ROWS, (nOptions & 0x0200) );
1306 pProtect->setOption( ScTableProtection::SELECT_LOCKED_CELLS, (nOptions & 0x0400) );
1307 pProtect->setOption( ScTableProtection::SORT, (nOptions & 0x0800) );
1308 pProtect->setOption( ScTableProtection::AUTOFILTER, (nOptions & 0x1000) );
1309 pProtect->setOption( ScTableProtection::PIVOT_TABLES, (nOptions & 0x2000) );
1310 pProtect->setOption( ScTableProtection::SELECT_UNLOCKED_CELLS, (nOptions & 0x4000) );
1312 // all done. now commit.
1313 GetDoc().SetTabProtection(itr->first, pProtect.get());
1317 XclImpSheetProtectBuffer::Sheet* XclImpSheetProtectBuffer::GetSheetItem( SCTAB nTab )
1319 ProtectedSheetMap::iterator itr = maProtectedSheets.find(nTab);
1320 if (itr == maProtectedSheets.end())
1322 // new sheet
1323 if ( !maProtectedSheets.insert( ProtectedSheetMap::value_type(nTab, Sheet()) ).second )
1324 return NULL;
1326 itr = maProtectedSheets.find(nTab);
1329 return &itr->second;
1332 // ============================================================================
1334 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */