ooo-build r13262 - in trunk: . patches/dev300
- From: kyoshida svn gnome org
- To: svn-commits-list gnome org
- Subject: ooo-build r13262 - in trunk: . patches/dev300
- Date: Thu, 17 Jul 2008 05:10:45 +0000 (UTC)
Author: kyoshida
Date: Thu Jul 17 05:10:45 2008
New Revision: 13262
URL: http://svn.gnome.org/viewvc/ooo-build?rev=13262&view=rev
Log:
2008-07-17 Kohei Yoshida <kyoshida novell com>
* patches/dev300/cws-scsheetprotection02-sc-m21.diff: renamed from the
original patch for milestones older than m25. The name is m21 because
that's the last milestone I have tested.
* patches/dev300/cws-scsheetprotection02-sc.diff: adopted to m25.
* patches/dev300/apply: added milestone check for these patches.
Added:
trunk/patches/dev300/cws-scsheetprotection02-sc-m21.diff
- copied unchanged from r13259, /trunk/patches/dev300/cws-scsheetprotection02-sc.diff
trunk/patches/dev300/cws-scsheetprotection02-sc.diff
Modified:
trunk/ChangeLog
trunk/patches/dev300/apply
Modified: trunk/patches/dev300/apply
==============================================================================
--- trunk/patches/dev300/apply (original)
+++ trunk/patches/dev300/apply Thu Jul 17 05:10:45 2008
@@ -728,7 +728,12 @@
# load, store and save the sheet protection options from and to an Excel file,
# and use that information to constrain cell cursor movement when the sheet is
# protected. Also to support encryption on Excel file export.
+[ CalcFixes >= dev300-m25 ]
cws-scsheetprotection02-sc.diff, i#60305, i#71468, i#84766, kohei
+[ CalcFixes < dev300-m25 ]
+cws-scsheetprotection02-sc-m21.diff, i#60305, i#71468, i#84766, kohei
+
+[ CalcFixes ]
cws-scsheetprotection02-windowsfix.diff, noelp
cws-scsheetprotection02-sfx2.diff, i#60305, i#71468, i#84766, kohei
cws-scsheetprotection02-svx.diff, i#60305, i#71468, i#84766, kohei
Added: trunk/patches/dev300/cws-scsheetprotection02-sc.diff
==============================================================================
--- (empty file)
+++ trunk/patches/dev300/cws-scsheetprotection02-sc.diff Thu Jul 17 05:10:45 2008
@@ -0,0 +1,7235 @@
+diff --git sc/inc/document.hxx sc/inc/document.hxx
+index 749c97d..953337c 100644
+--- sc/inc/document.hxx
++++ sc/inc/document.hxx
+@@ -89,6 +89,7 @@ class ScDBData;
+ class ScDetOpData;
+ class ScDetOpList;
+ class ScDocOptions;
++class ScDocProtection;
+ class ScDocumentPool;
+ class ScDrawLayer;
+ class ScExtDocOptions;
+@@ -104,6 +105,7 @@ class ScRangeName;
+ class ScStyleSheet;
+ class ScStyleSheetPool;
+ class ScTable;
++class ScTableProtection;
+ class ScTokenArray;
+ class ScValidationData;
+ class ScValidationDataList;
+@@ -276,7 +278,7 @@ private:
+
+ ScFieldEditEngine* pCacheFieldEditEngine;
+
+- com::sun::star::uno::Sequence<sal_Int8> aProtectPass;
++ ::std::auto_ptr<ScDocProtection> pDocProtection;
+ String aDocName; // opt: Dokumentname
+ ScRangePairListRef xColNameRanges;
+ ScRangePairListRef xRowNameRanges;
+@@ -340,7 +342,6 @@ private:
+
+ ScLkUpdMode eLinkMode;
+
+- BOOL bProtected;
+ BOOL bAutoCalc; // Automatisch Berechnen
+ BOOL bAutoCalcShellDisabled; // in/von/fuer ScDocShell disabled
+ // ob noch ForcedFormulas berechnet werden muessen,
+@@ -526,13 +527,16 @@ SC_DLLPUBLIC ScDBCollection* GetDBCollection() const;
+ inline SCTAB GetTableCount() const { return nMaxTableNumber; }
+ SvNumberFormatterIndexTable* GetFormatExchangeList() const { return pFormatExchangeList; }
+
+- void SetDocProtection( BOOL bProtect, const com::sun::star::uno::Sequence <sal_Int8>& aPass );
+- void SetTabProtection( SCTAB nTab, BOOL bProtect, const com::sun::star::uno::Sequence <sal_Int8>& aPass );
++ ScDocProtection* GetDocProtection() const;
++ void SetDocProtection(bool bProtect, const String& aPassText);
++ void SetDocProtection(const ScDocProtection* pProtect);
+ BOOL IsDocProtected() const;
+ BOOL IsDocEditable() const;
+ BOOL IsTabProtected( SCTAB nTab ) const;
+- const com::sun::star::uno::Sequence <sal_Int8>& GetDocPassword() const;
+- const com::sun::star::uno::Sequence <sal_Int8>& GetTabPassword( SCTAB nTab ) const;
++ ScTableProtection* GetTabProtection( SCTAB nTab ) const;
++ void SetTabProtection(SCTAB nTab, bool bProtect, const String& aPassText);
++ void SetTabProtection(SCTAB nTab, const ScTableProtection* pProtect);
++ void CopyTabProtection(SCTAB nTabSrc, SCTAB nTabDest);
+
+ void LockTable(SCTAB nTab);
+ void UnlockTable(SCTAB nTab);
+@@ -1504,6 +1508,8 @@ SC_DLLPUBLIC SvNumberFormatter* GetFormatTable() const;
+
+
+ private:
++ ScDocument(const ScDocument& r); // disabled with no definition
++
+ void SetAutoFilterFlags();
+ void FindMaxRotCol( SCTAB nTab, RowInfo* pRowInfo, SCSIZE nArrCount,
+ SCCOL nX1, SCCOL nX2 ) const;
+diff --git sc/inc/sc.hrc sc/inc/sc.hrc
+index 7753e5b..e7e8945 100644
+--- sc/inc/sc.hrc
++++ sc/inc/sc.hrc
+@@ -1652,6 +1652,11 @@
+ // Autoformat for DataPilot
+ #define SID_PIVOT_AFMT (SC_OOO_BUILD_START + 4)
+
++// Sheet and document protection with password
++#define RID_SCDLG_TABPROTECTION (SC_OOO_BUILD_START + 5)
++#define RID_SCDLG_DOCPROTECTION (SC_OOO_BUILD_START + 6)
++#define RID_SCDLG_RETYPEPASS (SC_OOO_BUILD_START + 7)
++#define RID_SCDLG_RETYPEPASS_INPUT (SC_OOO_BUILD_START + 8)
+
+
+ #endif
+diff --git sc/inc/scextopt.hxx sc/inc/scextopt.hxx
+index 772b77c..dac5afa 100644
+--- sc/inc/scextopt.hxx
++++ sc/inc/scextopt.hxx
+@@ -46,8 +46,6 @@ struct ScExtDocSettings
+ double mfTabBarWidth; /// Width of the tabbar, relative to frame window width (0.0 ... 1.0).
+ sal_uInt32 mnLinkCnt; /// Recursive counter for loading external documents.
+ SCTAB mnDisplTab; /// Index of displayed sheet.
+- bool mbWinProtected; /// true = Window properties are protected.
+- bool mbEncrypted; /// true = Imported file was encrypted.
+
+ explicit ScExtDocSettings();
+ };
+diff --git sc/inc/table.hxx sc/inc/table.hxx
+index 9bf6396..3f46d4c 100644
+--- sc/inc/table.hxx
++++ sc/inc/table.hxx
+@@ -39,6 +39,8 @@
+ #include "sortparam.hxx"
+ #include "compressedarray.hxx"
+
++#include <memory>
++
+ namespace utl {
+ class SearchParam;
+ class TextSearch;
+@@ -65,6 +67,7 @@ class ScRangeList;
+ class ScSortInfoArray;
+ class ScStyleSheet;
+ class ScTableLink;
++class ScTableProtection;
+ class ScUserListData;
+ class ScIndexMap;
+ struct RowInfo;
+@@ -102,8 +105,7 @@ private:
+ SCROW nRepeatStartY;
+ SCROW nRepeatEndY;
+
+- BOOL bProtected;
+- com::sun::star::uno::Sequence<sal_Int8> aProtectPass;
++ ::std::auto_ptr<ScTableProtection> pTabProtection;
+
+ USHORT* pColWidth;
+ ScSummableCompressedArray< SCROW, USHORT>* pRowHeight;
+@@ -218,10 +220,11 @@ public:
+ void SetPageStyle( const String& rName );
+ void PageStyleModified( const String& rNewName );
+
+- BOOL IsProtected() const { return bProtected; }
+- const com::sun::star::uno::Sequence<sal_Int8>& GetPassword() const { return aProtectPass; }
+- void SetProtection( BOOL bProtect, const com::sun::star::uno::Sequence<sal_Int8>& rPasswd )
+- { bProtected = bProtect; aProtectPass = rPasswd; }
++ BOOL IsProtected() const;
++ void SetProtection(BOOL bProtect, const com::sun::star::uno::Sequence<sal_Int8>& rPasswd);
++ void SetProtection(bool bProtect, const String& aPassText);
++ void SetProtection(const ScTableProtection* pProtect);
++ ScTableProtection* GetProtection();
+
+ Size GetPageSize() const;
+ void SetPageSize( const Size& rSize );
+diff --git sc/inc/tabprotection.hxx sc/inc/tabprotection.hxx
+new file mode 100644
+index 0000000..135a792
+--- /dev/null
++++ sc/inc/tabprotection.hxx
+@@ -0,0 +1,166 @@
++/*************************************************************************
++ *
++ * OpenOffice.org - a multi-platform office productivity suite
++ *
++ * $RCSfile: tabprotection.hxx,v $
++ *
++ * $Revision: 1.1.4.4 $
++ *
++ * last change: $Author: kohei $ $Date: 2008/05/20 05:17:39 $
++ *
++ * The Contents of this file are made available subject to
++ * the terms of GNU Lesser General Public License Version 2.1.
++ *
++ *
++ * GNU Lesser General Public License Version 2.1
++ * =============================================
++ * Copyright 2005 by Sun Microsystems, Inc.
++ * 901 San Antonio Road, Palo Alto, CA 94303, USA
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License version 2.1, as published by the Free Software Foundation.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ *
++ ************************************************************************/
++
++#ifndef SC_TAB_PROTECTION_HXX
++#define SC_TAB_PROTECTION_HXX
++
++#include "sal/types.h"
++#include <com/sun/star/uno/Sequence.hxx>
++
++#include "global.hxx"
++#include <vector>
++#include <memory>
++
++class ScTableProtectionImpl;
++
++enum ScPasswordHash
++{
++ PASSHASH_OOO = 0,
++ PASSHASH_XL
++};
++
++class SAL_NO_VTABLE ScPassHashProtectable
++{
++public:
++ virtual ~ScPassHashProtectable() = 0;
++
++ virtual bool isProtected() const = 0;
++ virtual bool isProtectedWithPass() const = 0;
++ virtual void setProtected(bool bProtected) = 0;
++
++ virtual bool isPasswordEmpty() const = 0;
++ virtual bool hasPasswordHash(ScPasswordHash eHash) const = 0;
++ virtual void setPassword(const String& aPassText) = 0;
++ virtual ::com::sun::star::uno::Sequence<sal_Int8> getPasswordHash(ScPasswordHash eHash) const = 0;
++ virtual void setPasswordHash(const ::com::sun::star::uno::Sequence<sal_Int8>& aPassword,
++ ScPasswordHash eHash = PASSHASH_OOO) = 0;
++ virtual bool verifyPassword(const String& aPassText) const = 0;
++};
++
++// ============================================================================
++
++class ScDocProtection : public ScPassHashProtectable
++{
++public:
++ enum Option
++ {
++ STRUCTURE = 0,
++ WINDOWS,
++ CONTENT,
++ NONE // last item - used to resize the vector
++ };
++
++ explicit ScDocProtection();
++ explicit ScDocProtection(const ScDocProtection& r);
++ virtual ~ScDocProtection();
++
++ virtual bool isProtected() const;
++ virtual bool isProtectedWithPass() const;
++ virtual void setProtected(bool bProtected);
++
++ virtual bool isPasswordEmpty() const;
++ virtual bool hasPasswordHash(ScPasswordHash eHash) const;
++ virtual void setPassword(const String& aPassText);
++ virtual ::com::sun::star::uno::Sequence<sal_Int8> getPasswordHash(ScPasswordHash eHash) const;
++ virtual void setPasswordHash(const ::com::sun::star::uno::Sequence<sal_Int8>& aPassword,
++ ScPasswordHash eHash = PASSHASH_OOO);
++ virtual bool verifyPassword(const String& aPassText) const;
++
++ bool isOptionEnabled(Option eOption) const;
++ void setOption(Option eOption, bool bEnabled);
++
++private:
++ ::std::auto_ptr<ScTableProtectionImpl> mpImpl;
++};
++
++// ============================================================================
++
++/** sheet protection state container
++
++ This class stores sheet's protection state: 1) whether the protection
++ is on, 2) password and/or password hash, and 3) any associated
++ protection options. This class is also used as a protection state
++ container for the undo/redo stack, in which case the password, hash and
++ the options need to be preserved even when the protection flag is
++ off. */
++class ScTableProtection : public ScPassHashProtectable
++{
++public:
++ enum Option
++ {
++ AUTOFILTER = 0,
++ DELETE_COLUMNS,
++ DELETE_ROWS,
++ FORMAT_CELLS,
++ FORMAT_COLUMNS,
++ FORMAT_ROWS,
++ INSERT_COLUMNS,
++ INSERT_HYPERLINKS,
++ INSERT_ROWS,
++ OBJECTS,
++ PIVOT_TABLES,
++ SCENARIOS,
++ SELECT_LOCKED_CELLS,
++ SELECT_UNLOCKED_CELLS,
++ SHEET,
++ SORT,
++ NONE // last item - used to resize the vector
++ };
++
++ explicit ScTableProtection();
++ explicit ScTableProtection(const ScTableProtection& r);
++ virtual ~ScTableProtection();
++
++ virtual bool isProtected() const;
++ virtual bool isProtectedWithPass() const;
++ virtual void setProtected(bool bProtected);
++
++ virtual bool isPasswordEmpty() const;
++ virtual bool hasPasswordHash(ScPasswordHash eHash) const;
++ virtual void setPassword(const String& aPassText);
++ virtual ::com::sun::star::uno::Sequence<sal_Int8> getPasswordHash(ScPasswordHash eHash) const;
++ virtual void setPasswordHash(const ::com::sun::star::uno::Sequence<sal_Int8>& aPassword,
++ ScPasswordHash eHash = PASSHASH_OOO);
++ virtual bool verifyPassword(const String& aPassText) const;
++
++ bool isOptionEnabled(Option eOption) const;
++ void setOption(Option eOption, bool bEnabled);
++
++private:
++ ::std::auto_ptr<ScTableProtectionImpl> mpImpl;
++};
++
++
++#endif
+diff --git sc/inc/warnpassword.hxx sc/inc/warnpassword.hxx
+index fbb405f..f7e3595 100644
+--- sc/inc/warnpassword.hxx
++++ sc/inc/warnpassword.hxx
+@@ -31,7 +31,7 @@
+ #ifndef SC_WARNPASSWORD_HXX
+ #define SC_WARNPASSWORD_HXX
+
+-
++#if 0
+
+ class SfxMedium;
+ /** Static API helper functions. */
+@@ -46,6 +46,7 @@ public:
+ static bool WarningOnPassword( SfxMedium& rMedium );
+ };
+
++#endif
+
+ #endif
+
+diff --git sc/source/core/data/documen2.cxx sc/source/core/data/documen2.cxx
+index 948fdad..3552fd5 100644
+--- sc/source/core/data/documen2.cxx
++++ sc/source/core/data/documen2.cxx
+@@ -150,6 +150,7 @@ ScDocument::ScDocument( ScDocumentMode eMode,
+ pChangeViewSettings( NULL ),
+ pScriptTypeData( NULL ),
+ pCacheFieldEditEngine( NULL ),
++ pDocProtection( NULL ),
+ pViewOptions( NULL ),
+ pDocOptions( NULL ),
+ pExtDocOptions( NULL ),
+@@ -173,7 +174,6 @@ ScDocument::ScDocument( ScDocumentMode eMode,
+ nHardRecalcState(0),
+ nVisibleTab( 0 ),
+ eLinkMode(LM_UNKNOWN),
+- bProtected( FALSE ),
+ bAutoCalc( eMode == SCDOCMODE_DOCUMENT ),
+ bAutoCalcShellDisabled( FALSE ),
+ bForcedFormulaPending( FALSE ),
+@@ -614,6 +614,7 @@ List& ScDocument::GetLoadedSymbolStringCellsList()
+
+ BOOL ScDocument::Load( SvStream& rStream, ScProgress* pProgress )
+ {
++#if 0
+ bLoadingDone = FALSE;
+
+ //----------------------------------------------------
+@@ -968,10 +969,13 @@ BOOL ScDocument::Load( SvStream& rStream, ScProgress* pProgress )
+ bLoadingDone = TRUE;
+
+ return !bError;
++#endif
++ return false;
+ }
+
+ BOOL ScDocument::Save( SvStream& rStream, ScProgress* pProgress ) const
+ {
++#if 0
+ ((ScDocument*)this)->bLoadingDone = FALSE; // nicht zwischendrin reinpfuschen lassen
+
+ ((ScDocument*)this)->bLostData = FALSE; // wird beim Speichern gesetzt
+@@ -1205,6 +1209,8 @@ BOOL ScDocument::Save( SvStream& rStream, ScProgress* pProgress ) const
+ ((ScDocument*)this)->bLoadingDone = TRUE;
+
+ return ( rStream.GetError() == SVSTREAM_OK );
++#endif
++ return false;
+ }
+
+ void ScDocument::SetLostData()
+diff --git sc/source/core/data/documen3.cxx sc/source/core/data/documen3.cxx
+index f898cc9..7e66c6e 100644
+--- sc/source/core/data/documen3.cxx
++++ sc/source/core/data/documen3.cxx
+@@ -78,6 +78,8 @@
+ #include "listenercalls.hxx"
+ #include "editutil.hxx" // ScPostIt EditTextObject
+ #include "postit.hxx"
++#include "svtools/PasswordHelper.hxx"
++#include "tabprotection.hxx"
+
+ using namespace com::sun::star;
+
+@@ -1690,28 +1692,37 @@ void ScDocument::SnapVisArea( Rectangle& rRect ) const
+ ScDrawLayer::MirrorRectRTL( rRect ); // back to real rectangle
+ }
+
+-void ScDocument::SetDocProtection( BOOL bProtect, const uno::Sequence<sal_Int8>& rPasswd )
++ScDocProtection* ScDocument::GetDocProtection() const
+ {
+- bProtected = bProtect;
+- aProtectPass = rPasswd;
++ return pDocProtection.get();
+ }
+
+-void ScDocument::SetTabProtection( SCTAB nTab, BOOL bProtect, const uno::Sequence<sal_Int8>& rPasswd )
++void ScDocument::SetDocProtection(bool bProtect, const String& aPassText)
+ {
+- if (VALIDTAB(nTab))
+- if (pTab[nTab])
+- pTab[nTab]->SetProtection( bProtect, rPasswd );
++ if (!pDocProtection.get())
++ pDocProtection.reset(new ScDocProtection);
++
++ pDocProtection->setProtected(bProtect);
++ pDocProtection->setPassword(aPassText);
++}
++
++void ScDocument::SetDocProtection(const ScDocProtection* pProtect)
++{
++ if (pProtect)
++ pDocProtection.reset(new ScDocProtection(*pProtect));
++ else
++ pDocProtection.reset(NULL);
+ }
+
+ BOOL ScDocument::IsDocProtected() const
+ {
+- return bProtected;
++ return pDocProtection.get() && pDocProtection->isProtected();
+ }
+
+ BOOL ScDocument::IsDocEditable() const
+ {
+ // import into read-only document is possible
+- return !bProtected && ( bImportingXML || mbChangeReadOnlyEnabled || !pShell || !pShell->IsReadOnly() );
++ return !IsDocProtected() && ( bImportingXML || mbChangeReadOnlyEnabled || !pShell || !pShell->IsReadOnly() );
+ }
+
+ BOOL ScDocument::IsTabProtected( SCTAB nTab ) const
+@@ -1724,19 +1735,34 @@ BOOL ScDocument::IsTabProtected( SCTAB nTab ) const
+ return FALSE;
+ }
+
+-const uno::Sequence<sal_Int8>& ScDocument::GetDocPassword() const
++ScTableProtection* ScDocument::GetTabProtection( SCTAB nTab ) const
+ {
+- return aProtectPass;
++ if (VALIDTAB(nTab) && pTab[nTab])
++ return pTab[nTab]->GetProtection();
++
++ return NULL;
+ }
+
+-const uno::Sequence<sal_Int8>& ScDocument::GetTabPassword( SCTAB nTab ) const
++void ScDocument::SetTabProtection(SCTAB nTab, bool bProtect, const String& aPassText)
+ {
+- if (VALIDTAB(nTab))
+- if (pTab[nTab])
+- return pTab[nTab]->GetPassword();
++ if (ValidTab(nTab) && pTab[nTab])
++ pTab[nTab]->SetProtection(bProtect, aPassText);
++}
+
+- DBG_ERROR("Falsche Tabellennummer");
+- return aProtectPass;
++void ScDocument::SetTabProtection(SCTAB nTab, const ScTableProtection* pProtect)
++{
++ if (!ValidTab(nTab))
++ return;
++
++ pTab[nTab]->SetProtection(pProtect);
++}
++
++void ScDocument::CopyTabProtection(SCTAB nTabSrc, SCTAB nTabDest)
++{
++ if (!ValidTab(nTabSrc) || !ValidTab(nTabDest))
++ return;
++
++ pTab[nTabDest]->SetProtection( pTab[nTabSrc]->GetProtection() );
+ }
+
+ const ScDocOptions& ScDocument::GetDocOptions() const
+diff --git sc/source/core/data/document.cxx sc/source/core/data/document.cxx
+index b727ffe..c93c1a7 100644
+--- sc/source/core/data/document.cxx
++++ sc/source/core/data/document.cxx
+@@ -90,6 +90,7 @@
+ #include "autonamecache.hxx"
+ #include "bcaslot.hxx"
+ #include "postit.hxx"
++#include "tabprotection.hxx"
+
+ struct ScDefaultAttr
+ {
+diff --git sc/source/core/data/makefile.mk sc/source/core/data/makefile.mk
+index c8ed91b..1cad27e 100644
+--- sc/source/core/data/makefile.mk
++++ sc/source/core/data/makefile.mk
+@@ -108,6 +108,7 @@ SLOFILES = \
+ $(SLO)$/table4.obj \
+ $(SLO)$/table5.obj \
+ $(SLO)$/table6.obj \
++ $(SLO)$/tabprotection.obj \
+ $(SLO)$/userdat.obj \
+ $(SLO)$/validat.obj \
+ $(SLO)$/postit.obj
+diff --git sc/source/core/data/table1.cxx sc/source/core/data/table1.cxx
+index 87de93f..9739af3 100644
+--- sc/source/core/data/table1.cxx
++++ sc/source/core/data/table1.cxx
+@@ -114,6 +114,7 @@
+ #include "progress.hxx"
+ #include "hints.hxx" // fuer Paint-Broadcast
+ #include "prnsave.hxx"
++#include "tabprotection.hxx"
+
+ // STATIC DATA -----------------------------------------------------------
+
+@@ -132,7 +133,7 @@ ScTable::ScTable( ScDocument* pDoc, SCTAB nNewTab, const String& rNewName,
+ bPageSizeValid( FALSE ),
+ nRepeatStartX( SCCOL_REPEAT_NONE ),
+ nRepeatStartY( SCROW_REPEAT_NONE ),
+- bProtected( FALSE ),
++ pTabProtection( NULL ),
+ pColWidth( NULL ),
+ pRowHeight( NULL ),
+ pColFlags( NULL ),
+diff --git sc/source/core/data/table2.cxx sc/source/core/data/table2.cxx
+index eda656d..6d1ecf9 100644
+--- sc/source/core/data/table2.cxx
++++ sc/source/core/data/table2.cxx
+@@ -294,7 +294,7 @@ void ScTable::DeleteArea(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, USH
+ // Zellschutz auf geschuetzter Tabelle nicht setzen
+ //
+
+- if ( bProtected && (nDelFlag & IDF_ATTRIB) )
++ if ( IsProtected() && (nDelFlag & IDF_ATTRIB) )
+ {
+ ScPatternAttr aPattern(pDocument->GetPool());
+ aPattern.GetItemSet().Put( ScProtectionAttr( FALSE ) );
+@@ -320,7 +320,7 @@ void ScTable::DeleteSelection( USHORT nDelFlag, const ScMarkData& rMark )
+ // Zellschutz auf geschuetzter Tabelle nicht setzen
+ //
+
+- if ( bProtected && (nDelFlag & IDF_ATTRIB) )
++ if ( IsProtected() && (nDelFlag & IDF_ATTRIB) )
+ {
+ ScDocumentPool* pPool = pDocument->GetPool();
+ SfxItemSet aSet( *pPool, ATTR_PATTERN_START, ATTR_PATTERN_END );
+@@ -363,7 +363,7 @@ void ScTable::CopyToClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
+
+ // ggf. Formeln durch Werte ersetzen
+
+- if (bProtected)
++ if ( IsProtected() )
+ for (i = nCol1; i <= nCol2; i++)
+ pTable->aCol[i].RemoveProtected(nRow1, nRow2);
+ }
+@@ -408,7 +408,7 @@ void ScTable::CopyFromClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
+ // Zellschutz auf geschuetzter Tabelle nicht setzen
+ //
+
+- if ( bProtected && (nInsFlag & IDF_ATTRIB) )
++ if ( IsProtected() && (nInsFlag & IDF_ATTRIB) )
+ {
+ ScPatternAttr aPattern(pDocument->GetPool());
+ aPattern.GetItemSet().Put( ScProtectionAttr( FALSE ) );
+@@ -1438,7 +1438,7 @@ BOOL ScTable::IsBlockEditable( SCCOL nCol1, SCROW nRow1, SCCOL nCol2,
+ BOOL bIsEditable = TRUE;
+ if ( nLockCount )
+ bIsEditable = FALSE;
+- else if ( bProtected && !pDocument->IsScenario(nTab) )
++ else if ( IsProtected() && !pDocument->IsScenario(nTab) )
+ {
+ if((bIsEditable = !HasAttrib( nCol1, nRow1, nCol2, nRow2, HASATTR_PROTECTED )) != FALSE)
+ {
+@@ -1505,7 +1505,7 @@ BOOL ScTable::IsSelectionEditable( const ScMarkData& rMark,
+ BOOL bIsEditable = TRUE;
+ if ( nLockCount )
+ bIsEditable = FALSE;
+- else if ( bProtected && !pDocument->IsScenario(nTab))
++ else if ( IsProtected() && !pDocument->IsScenario(nTab) )
+ {
+ if((bIsEditable = !HasAttribSelection( rMark, HASATTR_PROTECTED )) != FALSE)
+ {
+@@ -2815,11 +2815,16 @@ BOOL ScTable::Load( SvStream& rStream, USHORT /* nVersion */, ScProgress* /* pPr
+ rStream >> bScenario;
+ rStream.ReadByteString( aComment, rStream.GetStreamCharSet() );
+
++ BOOL bProtected;
+ rStream >> bProtected;
+ String aPass;
+ rStream.ReadByteString( aPass, rStream.GetStreamCharSet() );
+ if (aPass.Len())
++ {
++ ::com::sun::star::uno::Sequence<sal_Int8> aProtectPass;
+ SvPasswordHelper::GetHashPassword(aProtectPass, aPass);
++ SetProtection(bProtected, aProtectPass);
++ }
+
+ BOOL bOutline;
+ rStream >> bOutline;
+@@ -3091,6 +3096,7 @@ BOOL ScTable::Save( SvStream& rStream, long& /* rSavedDocCells */, ScProgress* /
+ rStream << bScenario;
+ rStream.WriteByteString( aComment, rStream.GetStreamCharSet() );
+
++ BOOL bProtected = IsProtected();
+ rStream << bProtected;
+ String aPass;
+ //rStream.WriteByteString( aProtectPass, rStream.GetStreamCharSet() );
+diff --git sc/source/core/data/table5.cxx sc/source/core/data/table5.cxx
+index e557c56..e773776 100644
+--- sc/source/core/data/table5.cxx
++++ sc/source/core/data/table5.cxx
+@@ -51,8 +51,11 @@
+ #include "stlpool.hxx"
+ #include "stlsheet.hxx"
+ #include "brdcst.hxx"
++#include "tabprotection.hxx"
+ #include "globstr.hrc"
+
++using ::com::sun::star::uno::Sequence;
++
+ // STATIC DATA -----------------------------------------------------------
+
+ #define GET_SCALEVALUE(set,id) ((const SfxUInt16Item&)(set.Get( id ))).GetValue()
+@@ -273,6 +276,42 @@ void ScTable::SetPageSize( const Size& rSize )
+ bPageSizeValid = FALSE;
+ }
+
++BOOL ScTable::IsProtected() const
++{
++ return pTabProtection.get() && pTabProtection->isProtected();
++}
++
++void ScTable::SetProtection(BOOL bProtect, const com::sun::star::uno::Sequence<sal_Int8>& rPasswd)
++{
++ if (!pTabProtection.get())
++ pTabProtection.reset(new ScTableProtection);
++
++ pTabProtection->setProtected( bProtect );
++ pTabProtection->setPasswordHash(rPasswd, PASSHASH_OOO);
++}
++
++void ScTable::SetProtection(bool bProtect, const String& aPassText)
++{
++ if (!pTabProtection.get())
++ pTabProtection.reset(new ScTableProtection);
++
++ pTabProtection->setProtected( bProtect );
++ pTabProtection->setPassword(aPassText);
++}
++
++void ScTable::SetProtection(const ScTableProtection* pProtect)
++{
++ if (pProtect)
++ pTabProtection.reset(new ScTableProtection(*pProtect));
++ else
++ pTabProtection.reset(NULL);
++}
++
++ScTableProtection* ScTable::GetProtection()
++{
++ return pTabProtection.get();
++}
++
+ Size ScTable::GetPageSize() const
+ {
+ if ( bPageSizeValid )
+diff --git sc/source/core/data/tabprotection.cxx sc/source/core/data/tabprotection.cxx
+new file mode 100644
+index 0000000..d96b6c8
+--- /dev/null
++++ sc/source/core/data/tabprotection.cxx
+@@ -0,0 +1,436 @@
++/*************************************************************************
++ *
++ * OpenOffice.org - a multi-platform office productivity suite
++ *
++ * $RCSfile: tabprotection.cxx,v $
++ *
++ * $Revision: 1.1.4.6 $
++ *
++ * last change: $Author: kohei $ $Date: 2008/05/22 22:31:10 $
++ *
++ * The Contents of this file are made available subject to
++ * the terms of GNU Lesser General Public License Version 2.1.
++ *
++ *
++ * GNU Lesser General Public License Version 2.1
++ * =============================================
++ * Copyright 2005 by Sun Microsystems, Inc.
++ * 901 San Antonio Road, Palo Alto, CA 94303, USA
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License version 2.1, as published by the Free Software Foundation.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ *
++ ************************************************************************/
++
++#include "tabprotection.hxx"
++#include "tools/debug.hxx"
++#include "svtools/PasswordHelper.hxx"
++
++#define DEBUG_TAB_PROTECTION 0
++
++using namespace ::com::sun::star;
++using ::com::sun::star::uno::Sequence;
++using ::rtl::OUString;
++
++// ============================================================================
++
++ScPassHashProtectable::~ScPassHashProtectable()
++{
++}
++
++// ============================================================================
++
++static sal_uInt16 lcl_getXLHashFromChar(const sal_Char* szPassword)
++{
++ sal_uInt16 cchPassword = strlen(szPassword);
++ sal_uInt16 wPasswordHash = 0;
++ if (!cchPassword)
++ return wPasswordHash;
++
++ const char* pch = &szPassword[cchPassword];
++ while (pch-- != szPassword)
++ {
++ wPasswordHash = ((wPasswordHash >> 14) & 0x01) |
++ ((wPasswordHash << 1) & 0x7fff);
++ wPasswordHash ^= *pch;
++ }
++
++ wPasswordHash = ((wPasswordHash >> 14) & 0x01) |
++ ((wPasswordHash << 1) & 0x7fff);
++
++ wPasswordHash ^= (0x8000 | ('N' << 8) | 'K');
++ wPasswordHash ^= cchPassword;
++
++ return wPasswordHash;
++}
++
++static Sequence<sal_Int8> lcl_getXLHash(const String& aPassText)
++{
++ const sal_Char* szBuf = OUStringToOString(OUString(aPassText), RTL_TEXTENCODING_UTF8).getStr();
++ sal_uInt16 nHash = lcl_getXLHashFromChar(szBuf);
++ Sequence<sal_Int8> aHash(2);
++ aHash[0] = (nHash >> 8) & 0xFF;
++ aHash[1] = nHash & 0xFF;
++ return aHash;
++}
++
++class ScTableProtectionImpl
++{
++public:
++ static ::com::sun::star::uno::Sequence<sal_Int8> hashPassword(const String& aPassText, ScPasswordHash eHash = PASSHASH_OOO);
++
++ explicit ScTableProtectionImpl(SCSIZE nOptSize);
++ explicit ScTableProtectionImpl(const ScTableProtectionImpl& r);
++
++ bool isProtected() const;
++ bool isProtectedWithPass() const;
++ void setProtected(bool bProtected);
++
++ bool isPasswordEmpty() const;
++ bool hasPasswordHash(ScPasswordHash eHash) const;
++ void setPassword(const String& aPassText);
++ ::com::sun::star::uno::Sequence<sal_Int8> getPasswordHash(ScPasswordHash eHash) const;
++ void setPasswordHash(const ::com::sun::star::uno::Sequence<sal_Int8>& aPassword, ScPasswordHash eHash = PASSHASH_OOO);
++ bool verifyPassword(const String& aPassText) const;
++
++ bool isOptionEnabled(SCSIZE nOptId) const;
++ void setOption(SCSIZE nOptId, bool bEnabled);
++
++private:
++ String maPassText;
++ ::com::sun::star::uno::Sequence<sal_Int8> maPassHash;
++ ::std::vector<bool> maOptions;
++ bool mbEmptyPass;
++ bool mbProtected;
++ ScPasswordHash meHash;
++};
++
++Sequence<sal_Int8> ScTableProtectionImpl::hashPassword(const String& aPassText, ScPasswordHash eHash)
++{
++ Sequence<sal_Int8> aHash;
++ switch (eHash)
++ {
++ case PASSHASH_XL:
++ aHash = lcl_getXLHash(aPassText);
++ break;
++ case PASSHASH_OOO:
++ default:
++ SvPasswordHelper::GetHashPassword(aHash, aPassText);
++ break;
++ }
++ return aHash;
++}
++
++ScTableProtectionImpl::ScTableProtectionImpl(SCSIZE nOptSize) :
++ maOptions(nOptSize),
++ mbEmptyPass(true),
++ mbProtected(false),
++ meHash(PASSHASH_OOO)
++{
++}
++
++ScTableProtectionImpl::ScTableProtectionImpl(const ScTableProtectionImpl& r) :
++ maPassText(r.maPassText),
++ maPassHash(r.maPassHash),
++ maOptions(r.maOptions),
++ mbEmptyPass(r.mbEmptyPass),
++ mbProtected(r.mbProtected),
++ meHash(r.meHash)
++{
++}
++
++bool ScTableProtectionImpl::isProtected() const
++{
++ return mbProtected;
++}
++
++bool ScTableProtectionImpl::isProtectedWithPass() const
++{
++ if (!mbProtected)
++ return false;
++
++ return maPassText.Len() || maPassHash.getLength();
++}
++
++void ScTableProtectionImpl::setProtected(bool bProtected)
++{
++ mbProtected = bProtected;
++ // We need to keep the old password even when the protection is off. So,
++ // don't erase the password data here.
++}
++
++void ScTableProtectionImpl::setPassword(const String& aPassText)
++{
++ // We can't hash it here because we don't know whether this document will
++ // get saved to Excel or ODF, depending on which we will need to use a
++ // different hashing algorithm. One alternative is to hash it using all
++ // hash algorithms that we support, and store them all.
++
++ maPassText = aPassText;
++ mbEmptyPass = aPassText.Len() == 0;
++ if (mbEmptyPass)
++ {
++ maPassHash = Sequence<sal_Int8>();
++ }
++}
++
++bool ScTableProtectionImpl::isPasswordEmpty() const
++{
++ return mbEmptyPass;
++}
++
++bool ScTableProtectionImpl::hasPasswordHash(ScPasswordHash eHash) const
++{
++ if (mbEmptyPass)
++ return true;
++
++ if (maPassText.Len())
++ return true;
++
++ if (meHash == eHash)
++ return true;
++
++ return false;
++}
++
++Sequence<sal_Int8> ScTableProtectionImpl::getPasswordHash(ScPasswordHash eHash) const
++{
++ if (mbEmptyPass)
++ // Flaged as empty.
++ return Sequence<sal_Int8>();
++
++ if (maPassText.Len())
++ // Cleartext password exists. Hash it.
++ return hashPassword(maPassText, eHash);
++
++ if (meHash == eHash)
++ // Stored hash exists.
++ return maPassHash;
++
++ // Failed to find a matching hash.
++ return Sequence<sal_Int8>();
++}
++
++void ScTableProtectionImpl::setPasswordHash(const uno::Sequence<sal_Int8>& aPassword, ScPasswordHash eHash)
++{
++ sal_Int32 nLen = aPassword.getLength();
++ mbEmptyPass = nLen <= 0 ? true : false;
++ meHash = eHash;
++ maPassHash = aPassword;
++
++#if DEBUG_TAB_PROTECTION
++ for (sal_Int32 i = 0; i < nLen; ++i)
++ printf("%2.2X ", static_cast<sal_uInt8>(aPassword[i]));
++ printf("\n");
++#endif
++}
++
++bool ScTableProtectionImpl::verifyPassword(const String& aPassText) const
++{
++#if DEBUG_TAB_PROTECTION
++ fprintf(stdout, "ScTableProtectionImpl::verifyPassword: input = '%s'\n",
++ OUStringToOString(rtl::OUString(aPassText), RTL_TEXTENCODING_UTF8).getStr());
++#endif
++
++ if (mbEmptyPass)
++ return aPassText.Len() == 0;
++
++ if (maPassText.Len())
++ // Clear text password exists, and this one takes precedence.
++ return aPassText.Equals(maPassText);
++
++ Sequence<sal_Int8> aHash = hashPassword(aPassText, meHash);
++
++#if DEBUG_TAB_PROTECTION
++ fprintf(stdout, "ScTableProtectionImpl::verifyPassword: hash = ");
++ for (sal_Int32 i = 0; i < aHash.getLength(); ++i)
++ printf("%2.2X ", static_cast<sal_uInt8>(aHash[i]));
++ printf("\n");
++#endif
++
++ return aHash == maPassHash;
++}
++
++bool ScTableProtectionImpl::isOptionEnabled(SCSIZE nOptId) const
++{
++ if ( maOptions.size() <= static_cast<size_t>(nOptId) )
++ {
++ DBG_ERROR("ScTableProtectionImpl::isOptionEnabled: wrong size");
++ return false;
++ }
++
++ return maOptions[nOptId];
++}
++
++void ScTableProtectionImpl::setOption(SCSIZE nOptId, bool bEnabled)
++{
++ if ( maOptions.size() <= static_cast<size_t>(nOptId) )
++ {
++ DBG_ERROR("ScTableProtectionImpl::setOption: wrong size");
++ return;
++ }
++
++ maOptions[nOptId] = bEnabled;
++}
++
++// ============================================================================
++
++ScDocProtection::ScDocProtection() :
++ mpImpl(new ScTableProtectionImpl(static_cast<SCSIZE>(ScDocProtection::NONE)))
++{
++}
++
++ScDocProtection::ScDocProtection(const ScDocProtection& r) :
++ mpImpl(new ScTableProtectionImpl(*r.mpImpl.get()))
++{
++}
++
++ScDocProtection::~ScDocProtection()
++{
++}
++
++bool ScDocProtection::isProtected() const
++{
++ return mpImpl->isProtected();
++}
++
++bool ScDocProtection::isProtectedWithPass() const
++{
++ return mpImpl->isProtectedWithPass();
++}
++
++void ScDocProtection::setProtected(bool bProtected)
++{
++ mpImpl->setProtected(bProtected);
++
++ // Currently Calc doesn't support document protection options. So, let's
++ // assume that when the document is protected, its structure is protected.
++ // We need to do this for Excel export.
++ mpImpl->setOption(ScDocProtection::STRUCTURE, bProtected);
++}
++
++bool ScDocProtection::isPasswordEmpty() const
++{
++ return mpImpl->isPasswordEmpty();
++}
++
++bool ScDocProtection::hasPasswordHash(ScPasswordHash eHash) const
++{
++ return mpImpl->hasPasswordHash(eHash);
++}
++
++void ScDocProtection::setPassword(const String& aPassText)
++{
++ mpImpl->setPassword(aPassText);
++}
++
++uno::Sequence<sal_Int8> ScDocProtection::getPasswordHash(ScPasswordHash eHash) const
++{
++ return mpImpl->getPasswordHash(eHash);
++}
++
++void ScDocProtection::setPasswordHash(const uno::Sequence<sal_Int8>& aPassword, ScPasswordHash eHash)
++{
++ mpImpl->setPasswordHash(aPassword, eHash);
++}
++
++bool ScDocProtection::verifyPassword(const String& aPassText) const
++{
++ return mpImpl->verifyPassword(aPassText);
++}
++
++bool ScDocProtection::isOptionEnabled(Option eOption) const
++{
++ return mpImpl->isOptionEnabled(eOption);
++}
++
++void ScDocProtection::setOption(Option eOption, bool bEnabled)
++{
++ mpImpl->setOption(eOption, bEnabled);
++}
++
++// ============================================================================
++
++ScTableProtection::ScTableProtection() :
++ mpImpl(new ScTableProtectionImpl(static_cast<SCSIZE>(ScTableProtection::NONE)))
++{
++ // Set default values for the options.
++ mpImpl->setOption(SELECT_LOCKED_CELLS, true);
++ mpImpl->setOption(SELECT_UNLOCKED_CELLS, true);
++}
++
++ScTableProtection::ScTableProtection(const ScTableProtection& r) :
++ mpImpl(new ScTableProtectionImpl(*r.mpImpl.get()))
++{
++}
++
++ScTableProtection::~ScTableProtection()
++{
++}
++
++bool ScTableProtection::isProtected() const
++{
++ return mpImpl->isProtected();
++}
++
++bool ScTableProtection::isProtectedWithPass() const
++{
++ return mpImpl->isProtectedWithPass();
++}
++
++void ScTableProtection::setProtected(bool bProtected)
++{
++ mpImpl->setProtected(bProtected);
++}
++
++bool ScTableProtection::isPasswordEmpty() const
++{
++ return mpImpl->isPasswordEmpty();
++}
++
++bool ScTableProtection::hasPasswordHash(ScPasswordHash eHash) const
++{
++ return mpImpl->hasPasswordHash(eHash);
++}
++
++void ScTableProtection::setPassword(const String& aPassText)
++{
++ mpImpl->setPassword(aPassText);
++}
++
++Sequence<sal_Int8> ScTableProtection::getPasswordHash(ScPasswordHash eHash) const
++{
++ return mpImpl->getPasswordHash(eHash);
++}
++
++void ScTableProtection::setPasswordHash(const uno::Sequence<sal_Int8>& aPassword, ScPasswordHash eHash)
++{
++ mpImpl->setPasswordHash(aPassword, eHash);
++}
++
++bool ScTableProtection::verifyPassword(const String& aPassText) const
++{
++ return mpImpl->verifyPassword(aPassText);
++}
++
++bool ScTableProtection::isOptionEnabled(Option eOption) const
++{
++ return mpImpl->isOptionEnabled(eOption);
++}
++
++void ScTableProtection::setOption(Option eOption, bool bEnabled)
++{
++ mpImpl->setOption(eOption, bEnabled);
++}
++
+diff --git sc/source/filter/excel/excdoc.cxx sc/source/filter/excel/excdoc.cxx
+index 837c972..d28222f 100644
+--- sc/source/filter/excel/excdoc.cxx
++++ sc/source/filter/excel/excdoc.cxx
+@@ -73,7 +73,6 @@
+ #include "excdoc.hxx"
+ #include "namebuff.hxx"
+
+-#include "xcl97dum.hxx"
+ #include "xcl97rec.hxx"
+ #include "xcl97esc.hxx"
+ #include "xetable.hxx"
+@@ -86,6 +85,8 @@
+ #include "xepivot.hxx"
+ #include "XclExpChangeTrack.hxx"
+
++#include "tabprotection.hxx"
++
+
+ static String lcl_GetVbaTabName( SCTAB n )
+ {
+@@ -151,7 +152,16 @@ void ExcTable::FillAsHeader( ExcBoundsheetList& rBoundsheetList )
+ Add( new ExcDummy_00 );
+ else
+ {
+- Add( new ExcDummy8_00a );
++ if ( IsDocumentEncrypted() )
++ Add( new XclExpFilePass(GetRoot()) );
++
++ Add( new XclExpInterfaceHdr );
++ Add( new XclExpMMS );
++ Add( new XclExpInterfaceEnd );
++ Add( new XclExpWriteAccess );
++ Add( new XclExpCodePage );
++ Add( new XclExpDSF );
++ Add( new XclExpExcel9File );
+ rR.pTabId = new XclExpChTrTabId( Max( nExcTabCount, nCodenames ) );
+ Add( rR.pTabId );
+ if( HasVbaStorage() )
+@@ -161,7 +171,8 @@ void ExcTable::FillAsHeader( ExcBoundsheetList& rBoundsheetList )
+ if( rCodeName.Len() )
+ Add( new XclCodename( rCodeName ) );
+ }
+- Add( new ExcDummy8_00b );
++
++ Add( new XclExpFnGroupCount );
+ }
+
+ // erst Namen- und Tabellen-Eintraege aufbauen
+@@ -181,15 +192,29 @@ void ExcTable::FillAsHeader( ExcBoundsheetList& rBoundsheetList )
+ aRecList.AppendRecord( CreateRecord( EXC_ID_NAME ) );
+ }
+
+- aRecList.AppendNewRecord( new XclExpWindowProtection( GetExtDocOptions().GetDocSettings().mbWinProtected ) );
+- aRecList.AppendNewRecord( new XclExpDocProtection( rDoc.IsDocProtected() ) );
+- aRecList.AppendNewRecord( new XclExpBoolRecord( EXC_ID_PASSWORD, false ) );
++ // document protection options
++ const ScDocProtection* pProtect = GetDoc().GetDocProtection();
++ if (pProtect && pProtect->isProtected())
++ {
++ Add( new XclExpWindowProtection(pProtect->isOptionEnabled(ScDocProtection::WINDOWS)) );
++ Add( new XclExpProtection(pProtect->isOptionEnabled(ScDocProtection::STRUCTURE)) );
++ Add( new XclExpPassHash(pProtect->getPasswordHash(PASSHASH_XL)) );
++ }
+
+ if( GetBiff() == EXC_BIFF8 )
+- Add( new ExcDummy8_040 );
++ {
++ Add( new XclExpProt4Rev );
++ Add( new XclExpProt4RevPass );
++ }
+
+ aRecList.AppendNewRecord( new XclExpWindow1( GetRoot() ) );
+
++ if ( GetBiff() == EXC_BIFF8 )
++ {
++ Add( new XclExpBoolRecord(0x0040, false) ); // BACKUP
++ Add( new XclExpBoolRecord(0x008D, false) ); // HIDEOBJ
++ }
++
+ if( GetBiff() <= EXC_BIFF5 )
+ {
+ Add( new ExcDummy_040 );
+@@ -198,9 +223,11 @@ void ExcTable::FillAsHeader( ExcBoundsheetList& rBoundsheetList )
+ }
+ else
+ {
++ // BIFF8
+ Add( new Exc1904( rDoc ) );
+ Add( new XclExpBoolRecord( 0x000E, !rDoc.GetDocOptions().IsCalcAsShown() ) );
+- Add( new ExcDummy8_041 );
++ Add( new XclExpBoolRecord(0x01B7, false) ); // REFRESHALL
++ Add( new XclExpBoolRecord(0x00DA, false) ); // BOOKBOOL
+ }
+
+ // Formatting: FONT, FORMAT, XF, STYLE, PALETTE
+@@ -259,10 +286,14 @@ void ExcTable::FillAsHeader( ExcBoundsheetList& rBoundsheetList )
+ aRecList.AppendRecord( CreateRecord( EXC_ID_EXTERNSHEET ) );
+ aRecList.AppendRecord( CreateRecord( EXC_ID_NAME ) );
+
++ Add( new XclExpUnknown01C1 );
++
+ // MSODRAWINGGROUP per-document data
+ Add( new XclMsodrawinggroup( rR, ESCHER_DggContainer ) );
+ // Shared string table: SST, EXTSST
+ aRecList.AppendRecord( CreateRecord( EXC_ID_SST ) );
++
++ Add( new XclExpUnknown0863 );
+ }
+
+ Add( new ExcEof );
+@@ -304,7 +335,7 @@ void ExcTable::FillAsTable( size_t nCodeNameIdx )
+ Add( new XclRefmode( rDoc ) );
+ Add( new XclIteration( rDoc ) );
+ Add( new XclDelta( rDoc ) );
+- Add( new ExcDummy8_02 );
++ Add( new XclExpBoolRecord(0x005F, true) ); // SAVERECALC
+ }
+
+ // GUTS (count & size of outline icons)
+@@ -321,8 +352,14 @@ void ExcTable::FillAsTable( size_t nCodeNameIdx )
+ // page settings (SETUP and various other records)
+ aRecList.AppendRecord( xPageSett );
+
+- if( rDoc.IsTabProtected( mnScTab ) )
+- Add( new XclProtection() );
++ const ScTableProtection* pTabProtect = rDoc.GetTabProtection(mnScTab);
++ if (pTabProtect && pTabProtect->isProtected())
++ {
++ Add( new XclExpProtection(true) );
++ Add( new XclExpBoolRecord(0x00DD, pTabProtect->isOptionEnabled(ScTableProtection::SCENARIOS)) );
++ Add( new XclExpBoolRecord(0x0063, pTabProtect->isOptionEnabled(ScTableProtection::OBJECTS)) );
++ Add( new XclExpPassHash(pTabProtect->getPasswordHash(PASSHASH_XL)) );
++ }
+
+ // local link table: EXTERNCOUNT, EXTERNSHEET
+ if( eBiff <= EXC_BIFF5 )
+@@ -368,6 +405,9 @@ void ExcTable::FillAsTable( size_t nCodeNameIdx )
+
+ if( eBiff == EXC_BIFF8 )
+ {
++ // sheet protection options
++ Add( new XclExpSheetProtectOptions( GetRoot(), mnScTab ) );
++
+ // web queries
+ Add( new XclExpWebQueryBuffer( GetRoot() ) );
+
+diff --git sc/source/filter/excel/excimp8.cxx sc/source/filter/excel/excimp8.cxx
+index 77fde45..d42738d 100644
+--- sc/source/filter/excel/excimp8.cxx
++++ sc/source/filter/excel/excimp8.cxx
+@@ -161,12 +161,6 @@ void ImportExcel8::Iteration( void )
+ }
+
+
+-void ImportExcel8:: WinProtection( void )
+-{
+- if( aIn.ReaduInt16() != 0 )
+- GetExtDocOptions().GetDocSettings().mbWinProtected = true;
+-}
+-
+ void ImportExcel8::Note( void )
+ {
+ GetObjectManager().ReadNote( maStrm );
+@@ -256,6 +250,11 @@ void ImportExcel8::Codename( BOOL bWorkbookGlobals )
+ }
+ }
+
++void ImportExcel8::SheetProtection( void )
++{
++ GetSheetProtectBuffer().ReadOptions( aIn, GetCurrScTab() );
++}
++
+ bool lcl_hasVBAEnabled()
+ {
+ uno::Reference< beans::XPropertySet > xProps( ::comphelper::getProcessServiceFactory(), uno::UNO_QUERY);
+@@ -302,6 +301,8 @@ void ImportExcel8::PostDocLoad( void )
+ pExcRoot->pAutoFilterBuffer->Apply();
+
+ GetWebQueryBuffer().Apply(); //! test if extant
++ GetSheetProtectBuffer().Apply();
++ GetDocProtectBuffer().Apply();
+
+ ImportExcel::PostDocLoad();
+
+diff --git sc/source/filter/excel/excrecds.cxx sc/source/filter/excel/excrecds.cxx
+index 16c04f1..81b97f0 100644
+--- sc/source/filter/excel/excrecds.cxx
++++ sc/source/filter/excel/excrecds.cxx
+@@ -99,6 +99,7 @@
+ #include "xcl97rec.hxx"
+
+
++using ::com::sun::star::uno::Sequence;
+
+ //--------------------------------------------------------- class ExcDummy_00 -
+ const BYTE ExcDummy_00::pMyData[] = {
+@@ -418,7 +419,9 @@ ExcBundlesheetBase::ExcBundlesheetBase() :
+ void ExcBundlesheetBase::UpdateStreamPos( XclExpStream& rStrm )
+ {
+ rStrm.SetSvStreamPos( nOwnPos );
++ rStrm.DisableEncryption();
+ rStrm << static_cast<sal_uInt32>(nStrPos);
++ rStrm.EnableEncryption();
+ }
+
+
+@@ -494,19 +497,41 @@ XclExpWsbool::XclExpWsbool( bool bFitToPages ) :
+ // XclExpWindowProtection ===============================================================
+
+ XclExpWindowProtection::XclExpWindowProtection(bool bValue) :
+- XclExpBoolRecord(EXC_ID_WINDOWPROTECT,bValue)
++ XclExpBoolRecord(EXC_ID_WINDOWPROTECT, bValue)
+ {
+ }
+
+ // XclExpDocProtection ===============================================================
+
+-XclExpDocProtection::XclExpDocProtection(bool bValue) :
+- XclExpBoolRecord(EXC_ID_PROTECT,bValue)
++XclExpProtection::XclExpProtection(bool bValue) :
++ XclExpBoolRecord(EXC_ID_PROTECT, bValue)
+ {
+ }
+
+ // ============================================================================
+
++XclExpPassHash::XclExpPassHash(const Sequence<sal_Int8>& aHash) :
++ XclExpRecord(EXC_ID_PASSWORD, 2),
++ mnHash(0x0000)
++{
++ if (aHash.getLength() >= 2)
++ {
++ mnHash = ((aHash[0] << 8) & 0xFFFF);
++ mnHash |= (aHash[1] & 0xFF);
++ }
++}
++
++XclExpPassHash::~XclExpPassHash()
++{
++}
++
++void XclExpPassHash::WriteBody(XclExpStream& rStrm)
++{
++ rStrm << mnHash;
++}
++
++// ============================================================================
++
+ XclExpFiltermode::XclExpFiltermode() :
+ XclExpEmptyRecord( EXC_ID_FILTERMODE )
+ {
+diff --git sc/source/filter/excel/impop.cxx sc/source/filter/excel/impop.cxx
+index ab1ca87..258a7c7 100644
+--- sc/source/filter/excel/impop.cxx
++++ sc/source/filter/excel/impop.cxx
+@@ -90,6 +90,7 @@
+ #include "xiview.hxx"
+ #include "xilink.hxx"
+ #include "xiescher.hxx"
++#include "xicontent.hxx"
+
+ #include "excimp8.hxx"
+ #include "excform.hxx"
+@@ -418,14 +419,9 @@ void ImportExcel::Eof( void )
+ }
+
+
+-BOOL ImportExcel::Password( void )
++void ImportExcel::SheetPassword( void )
+ {
+- // POST: return = TRUE, wenn Password <> 0
+- UINT16 nPasswd;
+-
+- aIn >> nPasswd;
+-
+- return nPasswd != 0x0000;
++ GetSheetProtectBuffer().ReadPasswordHash( aIn, GetCurrScTab() );
+ }
+
+
+@@ -439,6 +435,12 @@ void ImportExcel::Externsheet( void )
+ }
+
+
++void ImportExcel:: WinProtection( void )
++{
++ GetRoot().GetDocProtectBuffer().ReadWinProtect( aIn );
++}
++
++
+ void ImportExcel::Note( void )
+ {
+ XclAddress aXclPos;
+@@ -584,27 +586,24 @@ void ImportExcel::Defrowheight2( void )
+ }
+
+
+-void ImportExcel::Protect( void )
++void ImportExcel::SheetProtect( void )
+ {
+- if( aIn.ReaduInt16() )
+- {
+- uno::Sequence<sal_Int8> aEmptyPass;
+- GetDoc().SetTabProtection( GetCurrScTab(), TRUE, aEmptyPass );
+- }
++ GetRoot().GetSheetProtectBuffer().ReadProtect( aIn, GetCurrScTab() );
+ }
+
+ void ImportExcel::DocProtect( void )
+ {
+- if( aIn.ReaduInt16() )
+- {
+- uno::Sequence<sal_Int8> aEmptyPass;
+- GetDoc().SetDocProtection( TRUE, aEmptyPass );
+- }
++ GetRoot().GetDocProtectBuffer().ReadDocProtect( aIn );
+ }
+
++void ImportExcel::DocPasssword( void )
++{
++ GetRoot().GetDocProtectBuffer().ReadPasswordHash( aIn );
++}
+
+ void ImportExcel::Codepage( void )
+ {
++ maStrm.EnableDecryption();
+ SetCodePage( maStrm.ReaduInt16() );
+ }
+
+diff --git sc/source/filter/excel/read.cxx sc/source/filter/excel/read.cxx
+index 1a263d9..af1a2cc 100644
+--- sc/source/filter/excel/read.cxx
++++ sc/source/filter/excel/read.cxx
+@@ -363,7 +363,7 @@ FltError ImportExcel::Read( void )
+ Eof();
+ eAkt = Z_Ende;
+ break;
+- case 0x12: Protect(); break; // SHEET PROTECTION
++ case 0x12: SheetProtect(); break; // SHEET PROTECTION
+ case 0x14:
+ case 0x15: rPageSett.ReadHeaderFooter( maStrm ); break;
+ case 0x17: Externsheet(); break; // EXTERNSHEET [ 2345]
+@@ -477,7 +477,7 @@ FltError ImportExcel::Read( void )
+ Eof();
+ eAkt = Z_Biff4E;
+ break;
+- case 0x12: Protect(); break; // SHEET PROTECTION
++ case 0x12: SheetProtect(); break; // SHEET PROTECTION
+ case 0x14:
+ case 0x15: rPageSett.ReadHeaderFooter( maStrm ); break;
+ case 0x1A:
+@@ -603,7 +603,7 @@ FltError ImportExcel::Read( void )
+ eAkt = Z_Biff5T;
+ aIn.SeekGlobalPosition(); // und zurueck an alte Position
+ break;
+- case 0x12: Protect(); break; // SHEET PROTECTION
++ case 0x12: SheetProtect(); break; // SHEET PROTECTION
+ case 0x1A:
+ case 0x1B: rPageSett.ReadPageBreaks( maStrm ); break;
+ case 0x1D: rTabViewSett.ReadSelection( maStrm ); break;
+@@ -902,6 +902,7 @@ FltError ImportExcel8::Read( void )
+ }
+ break;
+ case 0x12: DocProtect(); break; // PROTECT [ 5678]
++ case 0x13: DocPasssword(); break;
+ case 0x19: WinProtection(); break;
+ case 0x2F: // FILEPASS [ 2345 ]
+ eLastErr = XclImpDecryptHelper::ReadFilepass( maStrm );
+@@ -1046,7 +1047,8 @@ FltError ImportExcel8::Read( void )
+ eAkt = EXC_STATE_SHEET;
+ aIn.SeekGlobalPosition(); // und zurueck an alte Position
+ break;
+- case 0x12: Protect(); break;
++ case 0x12: SheetProtect(); break;
++ case 0x13: SheetPassword(); break;
+ case 0x42: Codepage(); break; // CODEPAGE [ 2345 ]
+ case 0x55: DefColWidth(); break;
+ case 0x7D: Colinfo(); break; // COLINFO [ 345 ]
+@@ -1062,6 +1064,7 @@ FltError ImportExcel8::Read( void )
+ case 0x0221: Array34(); break; // ARRAY [ 34 ]
+ case 0x0225: Defrowheight345();break;//DEFAULTROWHEI[ 345 ]
+ case 0x04BC: Shrfmla(); break; // SHRFMLA [ 5 ]
++ case 0x0867: SheetProtection(); break; // SHEETPROTECTION
+ }
+ }
+ break;
+diff --git sc/source/filter/excel/xeroot.cxx sc/source/filter/excel/xeroot.cxx
+index aa0e713..0c32b52 100644
+--- sc/source/filter/excel/xeroot.cxx
++++ sc/source/filter/excel/xeroot.cxx
+@@ -32,7 +32,11 @@
+ #include "precompiled_sc.hxx"
+ #include "xeroot.hxx"
+ #include <sfx2/docfile.hxx>
++#include <sfx2/sfxsids.hrc>
+ #include <svtools/saveopt.hxx>
++#include <svtools/itemset.hxx>
++#include <svtools/stritem.hxx>
++#include <svtools/eitem.hxx>
+ #include "xltracer.hxx"
+ #include "xehelper.hxx"
+ #include "xeformula.hxx"
+@@ -42,8 +46,10 @@
+ #include "xecontent.hxx"
+ #include "xepivot.hxx"
+
+-// for filter manager
+-#include "excrecds.hxx"
++#include "excrecds.hxx" // for filter manager
++#include "tabprotection.hxx"
++#include "document.hxx"
++#include "scextopt.hxx"
+
+ // Global data ================================================================
+
+@@ -221,6 +227,40 @@ XclExpRecordRef XclExpRoot::CreateRecord( sal_uInt16 nRecId ) const
+ return xRec;
+ }
+
++bool XclExpRoot::IsDocumentEncrypted() const
++{
++ // We need to encrypt the content when the document structure is protected.
++ const ScDocProtection* pDocProt = GetDoc().GetDocProtection();
++ if (pDocProt && pDocProt->isProtected() && pDocProt->isOptionEnabled(ScDocProtection::STRUCTURE))
++ return true;
++
++ if (GetPassword().Len() > 0)
++ // Password is entered directly into the save dialog.
++ return true;
++
++ return false;
++}
++
++const String XclExpRoot::GetPassword() const
++{
++ SfxItemSet* pSet = GetMedium().GetItemSet();
++ if (!pSet)
++ return String();
++
++ const SfxPoolItem* pItem = NULL;
++ if (SFX_ITEM_SET == pSet->GetItemState(SID_PASSWORD, sal_True, &pItem))
++ {
++ const SfxStringItem* pStrItem = dynamic_cast<const SfxStringItem*>(pItem);
++ if (pStrItem)
++ {
++ // Password from the save dialog.
++ return pStrItem->GetValue();
++ }
++ }
++
++ return String();
++}
++
+ XclExpRootData::XclExpLinkMgrRef XclExpRoot::GetLocalLinkMgrRef() const
+ {
+ return IsInGlobals() ? mrExpData.mxGlobLinkMgr : mrExpData.mxLocLinkMgr;
+diff --git sc/source/filter/excel/xestream.cxx sc/source/filter/excel/xestream.cxx
+index 3a277dd..9e1a658 100644
+--- sc/source/filter/excel/xestream.cxx
++++ sc/source/filter/excel/xestream.cxx
+@@ -34,6 +34,9 @@
+ #include "xlstring.hxx"
+ #include "xeroot.hxx"
+
++#define DEBUG_XL_ENCRYPTION 0
++
++using ::std::vector;
+
+ // ============================================================================
+
+@@ -63,16 +66,19 @@ XclExpStream::~XclExpStream()
+ void XclExpStream::StartRecord( sal_uInt16 nRecId, sal_Size nRecSize )
+ {
+ DBG_ASSERT( !mbInRec, "XclExpStream::StartRecord - another record still open" );
++ DisableEncryption();
+ mnMaxContSize = mnCurrMaxSize = mnMaxRecSize;
+ mnPredictSize = nRecSize;
+ mbInRec = true;
+ InitRecord( nRecId );
+ SetSliceSize( 0 );
++ EnableEncryption();
+ }
+
+ void XclExpStream::EndRecord()
+ {
+ DBG_ASSERT( mbInRec, "XclExpStream::EndRecord - no record open" );
++ DisableEncryption();
+ UpdateRecSize();
+ mrStrm.Seek( STREAM_SEEK_TO_END );
+ mbInRec = false;
+@@ -84,6 +90,86 @@ void XclExpStream::SetSliceSize( sal_uInt16 nSize )
+ mnSliceSize = 0;
+ }
+
++XclExpStream& XclExpStream::operator<<( sal_Int8 nValue )
++{
++ PrepareWrite( 1 );
++ if (mbUseEncrypter && HasValidEncrypter())
++ mxEncrypter->Encrypt(mrStrm, nValue);
++ else
++ mrStrm << nValue;
++ return *this;
++}
++
++XclExpStream& XclExpStream::operator<<( sal_uInt8 nValue )
++{
++ PrepareWrite( 1 );
++ if (mbUseEncrypter && HasValidEncrypter())
++ mxEncrypter->Encrypt(mrStrm, nValue);
++ else
++ mrStrm << nValue;
++ return *this;
++}
++
++XclExpStream& XclExpStream::operator<<( sal_Int16 nValue )
++{
++ PrepareWrite( 2 );
++ if (mbUseEncrypter && HasValidEncrypter())
++ mxEncrypter->Encrypt(mrStrm, nValue);
++ else
++ mrStrm << nValue;
++ return *this;
++}
++
++XclExpStream& XclExpStream::operator<<( sal_uInt16 nValue )
++{
++ PrepareWrite( 2 );
++ if (mbUseEncrypter && HasValidEncrypter())
++ mxEncrypter->Encrypt(mrStrm, nValue);
++ else
++ mrStrm << nValue;
++ return *this;
++}
++
++XclExpStream& XclExpStream::operator<<( sal_Int32 nValue )
++{
++ PrepareWrite( 4 );
++ if (mbUseEncrypter && HasValidEncrypter())
++ mxEncrypter->Encrypt(mrStrm, nValue);
++ else
++ mrStrm << nValue;
++ return *this;
++}
++
++XclExpStream& XclExpStream::operator<<( sal_uInt32 nValue )
++{
++ PrepareWrite( 4 );
++ if (mbUseEncrypter && HasValidEncrypter())
++ mxEncrypter->Encrypt(mrStrm, nValue);
++ else
++ mrStrm << nValue;
++ return *this;
++}
++
++XclExpStream& XclExpStream::operator<<( float fValue )
++{
++ PrepareWrite( 4 );
++ if (mbUseEncrypter && HasValidEncrypter())
++ mxEncrypter->Encrypt(mrStrm, fValue);
++ else
++ mrStrm << fValue;
++ return *this;
++}
++
++XclExpStream& XclExpStream::operator<<( double fValue )
++{
++ PrepareWrite( 8 );
++ if (mbUseEncrypter && HasValidEncrypter())
++ mxEncrypter->Encrypt(mrStrm, fValue);
++ else
++ mrStrm << fValue;
++ return *this;
++}
++
+ sal_Size XclExpStream::Write( const void* pData, sal_Size nBytes )
+ {
+ sal_Size nRet = 0;
+@@ -98,9 +184,21 @@ sal_Size XclExpStream::Write( const void* pData, sal_Size nBytes )
+ while( bValid && (nBytesLeft > 0) )
+ {
+ sal_Size nWriteLen = ::std::min< sal_Size >( PrepareWrite(), nBytesLeft );
+- sal_Size nWriteRet = mrStrm.Write( pBuffer, nWriteLen );
++ sal_Size nWriteRet = nWriteLen;
++ if (mbUseEncrypter && HasValidEncrypter())
++ {
++ DBG_ASSERT(nWriteLen > 0, "XclExpStream::Write: write length is 0!");
++ vector<sal_uInt8> aBytes(nWriteLen);
++ memcpy(&aBytes[0], pBuffer, nWriteLen);
++ mxEncrypter->EncryptBytes(mrStrm, aBytes);
++ // TODO: How do I check if all the bytes have been successfully written ?
++ }
++ else
++ {
++ nWriteRet = mrStrm.Write( pBuffer, nWriteLen );
+ bValid = (nWriteLen == nWriteRet);
+ DBG_ASSERT( bValid, "XclExpStream::Write - stream write error" );
++ }
+ pBuffer += nWriteRet;
+ nRet += nWriteRet;
+ nBytesLeft -= nWriteRet;
+@@ -236,6 +334,26 @@ void XclExpStream::WriteCharBuffer( const ScfUInt8Vec& rBuffer )
+ Write( &rBuffer[ 0 ], rBuffer.size() );
+ }
+
++void XclExpStream::SetEncrypter( XclExpEncrypterRef xEncrypter )
++{
++ mxEncrypter = xEncrypter;
++}
++
++bool XclExpStream::HasValidEncrypter() const
++{
++ return mxEncrypter.is() && mxEncrypter->IsValid();
++}
++
++void XclExpStream::EnableEncryption( bool bEnable )
++{
++ mbUseEncrypter = bEnable && HasValidEncrypter();
++}
++
++void XclExpStream::DisableEncryption()
++{
++ EnableEncryption(false);
++}
++
+ sal_Size XclExpStream::SetSvStreamPos( sal_Size nPos )
+ {
+ DBG_ASSERT( !mbInRec, "XclExpStream::SetSvStreamPos - not allowed inside of a record" );
+@@ -327,3 +445,187 @@ void XclExpStream::WriteRawZeroBytes( sal_Size nBytes )
+
+ // ============================================================================
+
++XclExpBiff8Encrypter::XclExpBiff8Encrypter( const XclExpRoot& rRoot, const sal_uInt8 nDocId[16],
++ const sal_uInt8 nSalt[16] ) :
++ mrRoot(rRoot),
++ mnOldPos(STREAM_SEEK_TO_END),
++ mbValid(false)
++{
++ String aPass = rRoot.GetPassword();
++ if (aPass.Len() == 0)
++ // Empty password. Get the default biff8 password.
++ aPass = XclCryptoHelper::GetBiff8WbProtPassword();
++ Init(aPass, nDocId, nSalt);
++}
++
++XclExpBiff8Encrypter::~XclExpBiff8Encrypter()
++{
++}
++
++bool XclExpBiff8Encrypter::IsValid() const
++{
++ return mbValid;
++}
++
++void XclExpBiff8Encrypter::GetSaltDigest( sal_uInt8 nSaltDigest[16] ) const
++{
++ memcpy(nSaltDigest, mnSaltDigest, 16);
++}
++
++void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_uInt8 nData )
++{
++ vector<sal_uInt8> aByte(1);
++ aByte[0] = nData;
++ EncryptBytes(rStrm, aByte);
++}
++
++void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_uInt16 nData )
++{
++ ::std::vector<sal_uInt8> pnBytes(2);
++ pnBytes[0] = nData & 0xFF;
++ pnBytes[1] = (nData >> 8) & 0xFF;
++ EncryptBytes(rStrm, pnBytes);
++}
++
++void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_uInt32 nData )
++{
++ ::std::vector<sal_uInt8> pnBytes(4);
++ pnBytes[0] = nData & 0xFF;
++ pnBytes[1] = (nData >> 8) & 0xFF;
++ pnBytes[2] = (nData >> 16) & 0xFF;
++ pnBytes[3] = (nData >> 24) & 0xFF;
++ EncryptBytes(rStrm, pnBytes);
++}
++
++void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, float fValue )
++{
++ ::std::vector<sal_uInt8> pnBytes(4);
++ memcpy(&pnBytes[0], &fValue, 4);
++ EncryptBytes(rStrm, pnBytes);
++}
++
++void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, double fValue )
++{
++ ::std::vector<sal_uInt8> pnBytes(8);
++ memcpy(&pnBytes[0], &fValue, 8);
++ EncryptBytes(rStrm, pnBytes);
++}
++
++void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_Int8 nData )
++{
++ Encrypt(rStrm, static_cast<sal_uInt8>(nData));
++}
++
++void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_Int16 nData )
++{
++ Encrypt(rStrm, static_cast<sal_uInt16>(nData));
++}
++
++void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_Int32 nData )
++{
++ Encrypt(rStrm, static_cast<sal_uInt32>(nData));
++}
++
++void XclExpBiff8Encrypter::Init( const String& aPass, const sal_uInt8 nDocId[16],
++ const sal_uInt8 nSalt[16] )
++{
++ memset(mnSaltDigest, 0, sizeof(mnSaltDigest));
++
++ xub_StrLen nLen = aPass.Len();
++ bool bValid = (0 < nLen) && (nLen < 16);
++ if ( bValid )
++ {
++ // transform String to sal_uInt16 array
++ memset(mnPassw, 0, sizeof(mnPassw));
++ for (xub_StrLen nChar = 0; nChar < nLen; ++nChar)
++ mnPassw[nChar] = static_cast<sal_uInt16>(aPass.GetChar(nChar));
++
++ // copy document ID
++ memcpy(mnDocId, nDocId, sizeof(mnDocId));
++
++ // init codec
++ maCodec.InitKey(mnPassw, mnDocId);
++
++ // generate salt hash.
++ ::svx::MSCodec_Std97 aCodec;
++ aCodec.InitKey(mnPassw, mnDocId);
++ aCodec.CreateSaltDigest(nSalt, mnSaltDigest);
++
++ // verify to make sure it's in good shape.
++ bValid = maCodec.VerifyKey(nSalt, mnSaltDigest);
++ }
++
++ mbValid = bValid;
++}
++
++sal_uInt32 XclExpBiff8Encrypter::GetBlockPos( sal_Size nStrmPos ) const
++{
++ return static_cast<sal_uInt32>(nStrmPos / EXC_ENCR_BLOCKSIZE);
++}
++
++sal_uInt16 XclExpBiff8Encrypter::GetOffsetInBlock( sal_Size nStrmPos ) const
++{
++ return static_cast<sal_uInt16>(nStrmPos % EXC_ENCR_BLOCKSIZE);
++}
++
++void XclExpBiff8Encrypter::EncryptBytes( SvStream& rStrm, vector<sal_uInt8>& aBytes )
++{
++ sal_Size nStrmPos = rStrm.Tell();
++ sal_uInt16 nBlockOffset = GetOffsetInBlock(nStrmPos);
++ sal_uInt16 nBlockPos = GetBlockPos(nStrmPos);
++
++#if DEBUG_XL_ENCRYPTION
++ fprintf(stdout, "XclExpBiff8Encrypter::EncryptBytes: stream pos = %ld offset in block = %d block pos = %ld\n",
++ nStrmPos, nBlockOffset, nBlockPos);
++#endif
++
++ sal_uInt16 nSize = aBytes.size();
++ if (nSize == 0)
++ return;
++
++#if DEBUG_XL_ENCRYPTION
++ fprintf(stdout, "RAW: ");
++ for (sal_uInt16 i = 0; i < nSize; ++i)
++ fprintf(stdout, "%2.2X ", aBytes[i]);
++ fprintf(stdout, "\n");
++#endif
++
++ if (mnOldPos != nStrmPos)
++ {
++ sal_uInt16 nOldOffset = GetOffsetInBlock(mnOldPos);
++ sal_uInt16 nOldBlockPos = GetBlockPos(mnOldPos);
++
++ if ( (nBlockPos != nOldBlockPos) || (nBlockOffset < nOldOffset) )
++ {
++ maCodec.InitCipher(nBlockPos);
++ nOldOffset = 0;
++ }
++
++ if (nBlockOffset > nOldOffset)
++ maCodec.Skip(nBlockOffset - nOldOffset);
++ }
++
++ sal_uInt16 nBytesLeft = nSize;
++ sal_uInt16 nPos = 0;
++ while (nBytesLeft > 0)
++ {
++ sal_uInt16 nBlockLeft = EXC_ENCR_BLOCKSIZE - nBlockOffset;
++ sal_uInt16 nEncBytes = ::std::min(nBlockLeft, nBytesLeft);
++
++ bool bRet = maCodec.Encode(&aBytes[nPos], nEncBytes, &aBytes[nPos], nEncBytes);
++ DBG_ASSERT(bRet, "XclExpBiff8Encrypter::EncryptBytes: encryption failed!!");
++
++ sal_Size nRet = rStrm.Write(&aBytes[nPos], nEncBytes);
++ DBG_ASSERT(nRet == nEncBytes, "XclExpBiff8Encrypter::EncryptBytes: fail to write to stream!!");
++
++ nStrmPos = rStrm.Tell();
++ nBlockOffset = GetOffsetInBlock(nStrmPos);
++ nBlockPos = GetBlockPos(nStrmPos);
++ if (nBlockOffset == 0)
++ maCodec.InitCipher(nBlockPos);
++
++ nBytesLeft -= nEncBytes;
++ nPos += nEncBytes;
++ }
++ mnOldPos = nStrmPos;
++}
+diff --git sc/source/filter/excel/xicontent.cxx sc/source/filter/excel/xicontent.cxx
+index 6792e93..5d711d0 100644
+--- sc/source/filter/excel/xicontent.cxx
++++ sc/source/filter/excel/xicontent.cxx
+@@ -41,6 +41,7 @@
+ #include "scitems.hxx"
+ #include <svx/eeitem.hxx>
+ #include <svtools/intitem.hxx>
++#include <svtools/stritem.hxx>
+ #include <svx/flditem.hxx>
+ #include <svx/fhgtitem.hxx>
+ #include <svx/wghtitem.hxx>
+@@ -67,6 +68,12 @@
+ #include "xiname.hxx"
+
+ #include "excform.hxx"
++#include "tabprotection.hxx"
++
++#include <memory>
++
++using ::com::sun::star::uno::Sequence;
++using ::std::auto_ptr;
+
+ // Shared string table ========================================================
+
+@@ -1069,11 +1076,182 @@ ErrCode XclImpDecryptHelper::ReadFilepass( XclImpStream& rStrm )
+ };
+ // set decrypter at import stream
+ rStrm.SetDecrypter( xDecr );
+- // remember encryption for export
+- rStrm.GetRoot().GetExtDocOptions().GetDocSettings().mbEncrypted = true;
++
++ // Store the document password for export.
++ SfxItemSet* pSet = rStrm.GetRoot().GetDocShell()->GetMedium()->GetItemSet();
++ if (pSet)
++ {
++ String aPass = xDecr->GetPassword();
++ pSet->Put( SfxStringItem(SID_PASSWORD, aPass) );
++ }
+
+ return xDecr.is() ? xDecr->GetError() : EXC_ENCR_ERROR_UNSUPP_CRYPT;
+ }
+
++// Document protection ========================================================
++
++XclImpDocProtectBuffer::XclImpDocProtectBuffer( const XclImpRoot& rRoot ) :
++ XclImpRoot( rRoot ),
++ mnPassHash(0x0000),
++ mbDocProtect(false),
++ mbWinProtect(false)
++{
++}
++
++void XclImpDocProtectBuffer::ReadDocProtect( XclImpStream& rStrm )
++{
++ mbDocProtect = rStrm.ReaduInt16() ? true : false;
++}
++
++void XclImpDocProtectBuffer::ReadWinProtect( XclImpStream& rStrm )
++{
++ mbWinProtect = rStrm.ReaduInt16() ? true : false;
++}
++
++void XclImpDocProtectBuffer::ReadPasswordHash( XclImpStream& rStrm )
++{
++ rStrm.EnableDecryption();
++ mnPassHash = rStrm.ReaduInt16();
++}
++
++void XclImpDocProtectBuffer::Apply() const
++{
++ if (!mbDocProtect && !mbWinProtect)
++ // Excel requires either the structure or windows protection is set.
++ // If neither is set then the document is not protected at all.
++ return;
++
++ auto_ptr<ScDocProtection> pProtect(new ScDocProtection);
++ pProtect->setProtected(true);
++
++ if (mnPassHash)
++ {
++ // 16-bit password pash.
++ Sequence<sal_Int8> aPass(2);
++ aPass[0] = (mnPassHash >> 8) & 0xFF;
++ aPass[1] = mnPassHash & 0xFF;
++ pProtect->setPasswordHash(aPass, PASSHASH_XL);
++ }
++
++ // document protection options
++ pProtect->setOption(ScDocProtection::STRUCTURE, mbDocProtect);
++ pProtect->setOption(ScDocProtection::WINDOWS, mbWinProtect);
++
++ GetDoc().SetDocProtection(pProtect.get());
++}
++
++// Sheet Protection ===========================================================
++
++XclImpSheetProtectBuffer::Sheet::Sheet() :
++ mbProtected(false),
++ mnPasswordHash(0x0000),
++ mnOptions(0x4400)
++{
++}
++
++// ----------------------------------------------------------------------------
++
++XclImpSheetProtectBuffer::Sheet::Sheet(const Sheet& r) :
++ mbProtected(r.mbProtected),
++ mnPasswordHash(r.mnPasswordHash),
++ mnOptions(r.mnOptions)
++{
++}
++
++XclImpSheetProtectBuffer::XclImpSheetProtectBuffer( const XclImpRoot& rRoot ) :
++ XclImpRoot( rRoot )
++{
++}
++
++void XclImpSheetProtectBuffer::ReadProtect( XclImpStream& rStrm, SCTAB nTab )
++{
++ if ( rStrm.ReaduInt16() )
++ {
++ Sheet* pSheet = GetSheetItem(nTab);
++ if (pSheet)
++ pSheet->mbProtected = true;
++ }
++}
++
++void XclImpSheetProtectBuffer::ReadOptions( XclImpStream& rStrm, SCTAB nTab )
++{
++ rStrm.Ignore(19);
++ sal_uInt16 nOptions;
++ rStrm >> nOptions;
++
++ Sheet* pSheet = GetSheetItem(nTab);
++ if (pSheet)
++ pSheet->mnOptions = nOptions;
++}
++
++void XclImpSheetProtectBuffer::ReadPasswordHash( XclImpStream& rStrm, SCTAB nTab )
++{
++ sal_uInt16 nHash;
++ rStrm >> nHash;
++ Sheet* pSheet = GetSheetItem(nTab);
++ if (pSheet)
++ pSheet->mnPasswordHash = nHash;
++}
++
++void XclImpSheetProtectBuffer::Apply() const
++{
++ for (ProtectedSheetMap::const_iterator itr = maProtectedSheets.begin(), itrEnd = maProtectedSheets.end();
++ itr != itrEnd; ++itr)
++ {
++ if (!itr->second.mbProtected)
++ // This sheet is (for whatever reason) not protected.
++ continue;
++
++ auto_ptr<ScTableProtection> pProtect(new ScTableProtection);
++ pProtect->setProtected(true);
++
++ // 16-bit hash password
++ const sal_uInt16 nHash = itr->second.mnPasswordHash;
++ if (nHash)
++ {
++ Sequence<sal_Int8> aPass(2);
++ aPass[0] = (nHash >> 8) & 0xFF;
++ aPass[1] = nHash & 0xFF;
++ pProtect->setPasswordHash(aPass, PASSHASH_XL);
++ }
++
++ // sheet protection options
++ const sal_uInt16 nOptions = itr->second.mnOptions;
++ pProtect->setOption( ScTableProtection::OBJECTS, (nOptions & 0x0001) );
++ pProtect->setOption( ScTableProtection::SCENARIOS, (nOptions & 0x0002) );
++ pProtect->setOption( ScTableProtection::FORMAT_CELLS, (nOptions & 0x0004) );
++ pProtect->setOption( ScTableProtection::FORMAT_COLUMNS, (nOptions & 0x0008) );
++ pProtect->setOption( ScTableProtection::FORMAT_ROWS, (nOptions & 0x0010) );
++ pProtect->setOption( ScTableProtection::INSERT_COLUMNS, (nOptions & 0x0020) );
++ pProtect->setOption( ScTableProtection::INSERT_ROWS, (nOptions & 0x0040) );
++ pProtect->setOption( ScTableProtection::INSERT_HYPERLINKS, (nOptions & 0x0080) );
++ pProtect->setOption( ScTableProtection::DELETE_COLUMNS, (nOptions & 0x0100) );
++ pProtect->setOption( ScTableProtection::DELETE_ROWS, (nOptions & 0x0200) );
++ pProtect->setOption( ScTableProtection::SELECT_LOCKED_CELLS, (nOptions & 0x0400) );
++ pProtect->setOption( ScTableProtection::SORT, (nOptions & 0x0800) );
++ pProtect->setOption( ScTableProtection::AUTOFILTER, (nOptions & 0x1000) );
++ pProtect->setOption( ScTableProtection::PIVOT_TABLES, (nOptions & 0x2000) );
++ pProtect->setOption( ScTableProtection::SELECT_UNLOCKED_CELLS, (nOptions & 0x4000) );
++
++ // all done. now commit.
++ GetDoc().SetTabProtection(itr->first, pProtect.get());
++ }
++}
++
++XclImpSheetProtectBuffer::Sheet* XclImpSheetProtectBuffer::GetSheetItem( SCTAB nTab )
++{
++ ProtectedSheetMap::iterator itr = maProtectedSheets.find(nTab);
++ if (itr == maProtectedSheets.end())
++ {
++ // new sheet
++ if ( !maProtectedSheets.insert( ProtectedSheetMap::value_type(nTab, Sheet()) ).second )
++ return NULL;
++
++ itr = maProtectedSheets.find(nTab);
++ }
++
++ return &itr->second;
++}
++
+ // ============================================================================
+
+diff --git sc/source/filter/excel/xilink.cxx sc/source/filter/excel/xilink.cxx
+index 264e796..01932a5 100644
+--- sc/source/filter/excel/xilink.cxx
++++ sc/source/filter/excel/xilink.cxx
+@@ -264,6 +264,7 @@ void XclImpTabInfo::ReadTabid( XclImpStream& rStrm )
+ DBG_ASSERT_BIFF( rStrm.GetRoot().GetBiff() == EXC_BIFF8 );
+ if( rStrm.GetRoot().GetBiff() == EXC_BIFF8 )
+ {
++ rStrm.EnableDecryption();
+ sal_Size nReadCount = rStrm.GetRecLeft() / 2;
+ DBG_ASSERT( nReadCount <= 0xFFFF, "XclImpTabInfo::ReadTabid - record too long" );
+ maTabIdVec.clear();
+diff --git sc/source/filter/excel/xiroot.cxx sc/source/filter/excel/xiroot.cxx
+index 4e5173f..21e071a 100644
+--- sc/source/filter/excel/xiroot.cxx
++++ sc/source/filter/excel/xiroot.cxx
+@@ -52,6 +52,7 @@
+ XclImpRootData::XclImpRootData( XclBiff eBiff, SfxMedium& rMedium,
+ SotStorageRef xRootStrg, ScDocument& rDoc, rtl_TextEncoding eTextEnc ) :
+ XclRootData( eBiff, rMedium, xRootStrg, rDoc, eTextEnc, false ),
++ mbPassQueried( false ),
+ mbHasCodePage( false )
+ {
+ }
+@@ -86,6 +87,8 @@ XclImpRoot::XclImpRoot( XclImpRootData& rImpRootData ) :
+ GetOldRoot().pAutoFilterBuffer = new XclImpAutoFilterBuffer;
+ mrImpData.mxWebQueryBfr.reset( new XclImpWebQueryBuffer( GetRoot() ) );
+ mrImpData.mxPTableMgr.reset( new XclImpPivotTableManager( GetRoot() ) );
++ mrImpData.mxTabProtect.reset( new XclImpSheetProtectBuffer( GetRoot() ) );
++ mrImpData.mxDocProtect.reset( new XclImpDocProtectBuffer( GetRoot() ) );
+ }
+
+ mrImpData.mxPageSett.reset( new XclImpPageSettings( GetRoot() ) );
+@@ -224,6 +227,18 @@ XclImpPivotTableManager& XclImpRoot::GetPivotTableManager() const
+ return *mrImpData.mxPTableMgr;
+ }
+
++XclImpSheetProtectBuffer& XclImpRoot::GetSheetProtectBuffer() const
++{
++ DBG_ASSERT( mrImpData.mxTabProtect.is(), "XclImpRoot::GetSheetProtectBuffer - invalid call, wrong BIFF" );
++ return *mrImpData.mxTabProtect;
++}
++
++XclImpDocProtectBuffer& XclImpRoot::GetDocProtectBuffer() const
++{
++ DBG_ASSERT( mrImpData.mxDocProtect.is(), "XclImpRoot::GetDocProtectBuffer - invalid call, wrong BIFF" );
++ return *mrImpData.mxDocProtect;
++}
++
+ XclImpPageSettings& XclImpRoot::GetPageSettings() const
+ {
+ return *mrImpData.mxPageSett;
+@@ -247,5 +262,18 @@ String XclImpRoot::GetScAddInName( const String& rXclName ) const
+ return rXclName;
+ }
+
++const String& XclImpRoot::QueryPassword() const
++{
++ if( !mrImpData.mbPassQueried )
++ {
++ mrImpData.maPassw = ScfApiHelper::QueryPasswordForMedium( GetMedium() );
++ // set to true, even if dialog has been cancelled (never ask twice)
++ mrImpData.mbPassQueried = true;
++ fprintf(stdout, "XclImpRoot::QueryPassword: password = '%s'\n",
++ OUStringToOString(rtl::OUString(mrImpData.maPassw), RTL_TEXTENCODING_UTF8).getStr());fflush(stdout);
++ }
++ return mrImpData.maPassw;
++}
++
+ // ============================================================================
+
+diff --git sc/source/filter/excel/xistream.cxx sc/source/filter/excel/xistream.cxx
+index 745bc8a..176d2fd 100644
+--- sc/source/filter/excel/xistream.cxx
++++ sc/source/filter/excel/xistream.cxx
+@@ -36,6 +36,8 @@
+ #include "xlstring.hxx"
+ #include "xiroot.hxx"
+
++#include <vector>
++
+ // ============================================================================
+ // Decryption
+ // ============================================================================
+@@ -97,11 +99,21 @@ sal_uInt16 XclImpDecrypter::Read( SvStream& rStrm, void* pData, sal_uInt16 nByte
+ return nRet;
+ }
+
++const String XclImpDecrypter::GetPassword() const
++{
++ return maPass;
++}
++
+ void XclImpDecrypter::SetHasValidPassword( bool bValid )
+ {
+ mnError = bValid ? ERRCODE_NONE : EXC_ENCR_ERROR_WRONG_PASS;
+ }
+
++void XclImpDecrypter::SetPassword( const String& rPass )
++{
++ maPass = rPass;
++}
++
+ // ----------------------------------------------------------------------------
+
+ XclImpBiff5Decrypter::XclImpBiff5Decrypter( const XclImpRoot& rRoot, sal_uInt16 nKey, sal_uInt16 nHash )
+@@ -157,6 +169,9 @@ void XclImpBiff5Decrypter::Init( const ByteString& rPass, sal_uInt16 nKey, sal_u
+ // init codec
+ maCodec.InitKey( mpnPassw );
+ bValid = maCodec.VerifyKey( nKey, nHash );
++
++ String aUniPass( rPass, RTL_TEXTENCODING_MS_1252 );
++ SetPassword( aUniPass );
+ }
+
+ SetHasValidPassword( bValid );
+@@ -255,6 +270,8 @@ void XclImpBiff8Decrypter::Init(
+ // init codec
+ maCodec.InitKey( mpnPassw, mpnDocId );
+ bValid = maCodec.VerifyKey( pnSaltData, pnSaltHash );
++
++ SetPassword(rPass);
+ }
+
+ SetHasValidPassword( bValid );
+diff --git sc/source/filter/excel/xlroot.cxx sc/source/filter/excel/xlroot.cxx
+index d9ff647..cfe73d1 100644
+--- sc/source/filter/excel/xlroot.cxx
++++ sc/source/filter/excel/xlroot.cxx
+@@ -91,8 +91,7 @@ XclRootData::XclRootData( XclBiff eBiff, SfxMedium& rMedium,
+ mxRD( new RootData ),//!
+ mnCharWidth( 110 ),
+ mnScTab( 0 ),
+- mbExport( bExport ),
+- mbHasPassw( false )
++ mbExport( bExport )
+ {
+ // default script type, e.g. for empty cells
+ switch( ScGlobal::GetDefaultScriptType() )
+@@ -198,17 +197,6 @@ void XclRoot::SetCharWidth( const XclFontData& rFontData )
+ }
+ }
+
+-const String& XclRoot::QueryPassword() const
+-{
+- if( !mrData.mbHasPassw )
+- {
+- mrData.maPassw = ScfApiHelper::QueryPasswordForMedium( GetMedium() );
+- // set to true, even if dialog has been cancelled (never ask twice)
+- mrData.mbHasPassw = true;
+- }
+- return mrData.maPassw;
+-}
+-
+ bool XclRoot::HasVbaStorage() const
+ {
+ SotStorageRef xRootStrg = GetRootStorage();
+diff --git sc/source/filter/inc/excimp8.hxx sc/source/filter/inc/excimp8.hxx
+index 838d3b7..c1d18f9 100644
+--- sc/source/filter/inc/excimp8.hxx
++++ sc/source/filter/inc/excimp8.hxx
+@@ -62,7 +62,6 @@ class ImportExcel8 : public ImportExcel
+ void Delta( void ); // 0x10
+ void Iteration( void ); // 0x11
+ void Note( void ); // 0x1C
+- void WinProtection( void ); // 0x19
+ void Boundsheet( void ); // 0x85
+ void FilterMode( void ); // 0x9B
+ void AutoFilterInfo( void ); // 0x9D
+@@ -74,6 +73,7 @@ class ImportExcel8 : public ImportExcel
+
+ void Hlink( void ); // 0x01B8
+ void Codename( BOOL bWBGlobals ); // 0x01BA
++ void SheetProtection( void ); // 0x0867
+
+ virtual void EndSheet( void );
+ virtual void PostDocLoad( void );
+diff --git sc/source/filter/inc/excrecds.hxx sc/source/filter/inc/excrecds.hxx
+index 0d85d9b..78f60c0 100644
+--- sc/source/filter/inc/excrecds.hxx
++++ sc/source/filter/inc/excrecds.hxx
+@@ -244,10 +244,23 @@ class XclExpWindowProtection : public XclExpBoolRecord
+ };
+
+ // EXC_ID_PROTECT Document Protection
+-class XclExpDocProtection : public XclExpBoolRecord
++class XclExpProtection : public XclExpBoolRecord
+ {
+ public:
+- XclExpDocProtection(bool bValue);
++ XclExpProtection(bool bValue);
++};
++
++class XclExpPassHash : public XclExpRecord
++{
++public:
++ XclExpPassHash(const ::com::sun::star::uno::Sequence<sal_Int8>& aHash);
++ virtual ~XclExpPassHash();
++
++private:
++ virtual void WriteBody(XclExpStream& rStrm);
++
++private:
++ sal_uInt16 mnHash;
+ };
+
+
+diff --git sc/source/filter/inc/imp_op.hxx sc/source/filter/inc/imp_op.hxx
+index 274696f..4a7e8c6 100644
+--- sc/source/filter/inc/imp_op.hxx
++++ sc/source/filter/inc/imp_op.hxx
+@@ -134,9 +134,11 @@ protected:
+ void Bof2( void ); // 0x09
+ void Eof( void ); // 0x0A
+ void DocProtect( void ); // 0x12
+- void Protect( void ); // 0x12 Sheet Protection
+- BOOL Password( void ); // 0x13
++ void SheetProtect( void ); // 0x12 Sheet Protection
++ void DocPasssword( void ); // 0x13 document password
++ void SheetPassword( void ); // 0x13 sheet password
+ void Externsheet( void ); // 0x17
++ void WinProtection( void ); // 0x19
+ void Note( void ); // 0x1C
+ void Columndefault( void ); // 0x20
+ void Array25( void ); // 0x21
+diff --git sc/source/filter/inc/xcl97rec.hxx sc/source/filter/inc/xcl97rec.hxx
+index 2f7382a..b2f7346 100644
+--- sc/source/filter/inc/xcl97rec.hxx
++++ sc/source/filter/inc/xcl97rec.hxx
+@@ -35,6 +35,8 @@
+ #include "xcl97esc.hxx"
+ #include "xlstyle.hxx"
+
++#include <vector>
++
+ // --- class XclMsodrawing_Base --------------------------------------
+
+ class XclMsodrawing_Base
+@@ -57,29 +59,26 @@ public:
+
+ // --- class XclMsodrawinggroup --------------------------------------
+
+-class XclMsodrawinggroup : public XclMsodrawing_Base, public ExcRecord
++class XclMsodrawinggroup : public XclMsodrawing_Base, public XclExpRecord
+ {
+ private:
+
+- virtual void SaveCont( XclExpStream& rStrm );
++ virtual void WriteBody( XclExpStream& rStrm );
+
+ public:
+ XclMsodrawinggroup( RootData& rRoot,
+ UINT16 nEscherType = 0 );
+ virtual ~XclMsodrawinggroup();
+-
+- virtual UINT16 GetNum() const;
+- virtual sal_Size GetLen() const;
+ };
+
+
+ // --- class XclMsodrawing -------------------------------------------
+
+-class XclMsodrawing : public XclMsodrawing_Base, public ExcRecord
++class XclMsodrawing : public XclMsodrawing_Base, public XclExpRecord
+ {
+ private:
+
+- virtual void SaveCont( XclExpStream& rStrm );
++ virtual void WriteBody( XclExpStream& rStrm );
+
+ public:
+ XclMsodrawing(
+@@ -87,9 +86,6 @@ public:
+ UINT16 nEscherType = 0,
+ sal_Size nInitialSize = 0 );
+ virtual ~XclMsodrawing();
+-
+- virtual UINT16 GetNum() const;
+- virtual sal_Size GetLen() const;
+ };
+
+
+@@ -484,23 +480,24 @@ public:
+ virtual sal_Size GetLen() const;
+ };
+
++// ============================================================================
+
+-// ---- class XclProtection ------------------------------------------
+-
+-class XclProtection : public ExcDummyRec
++/** Represents a SHEETPROTECTION record that stores sheet protection
++ options. Note that a sheet still needs to save its sheet protection
++ options even when it's not protected. */
++class XclExpSheetProtectOptions : public XclExpRecord
+ {
+- // replacement for records PROTECT, SCENPROTECT, OBJPROTECT...
+-private:
+- static const BYTE pMyData[];
+- static const sal_Size nMyLen;
+ public:
+- virtual sal_Size GetLen( void ) const;
+- virtual const BYTE* GetData( void ) const;
+-};
++ explicit XclExpSheetProtectOptions( const XclExpRoot& rRoot, SCTAB nTab );
+
++private:
++ virtual void WriteBody( XclExpStream& rStrm );
+
+-// -------------------------------------------------------------------
++private:
++ sal_uInt16 mnOptions; /// Encoded sheet protection options.
++};
+
++// ============================================================================
+
+ class XclCalccount : public ExcRecord
+ {
+@@ -556,5 +553,162 @@ public:
+ XclRefmode( const ScDocument& );
+ };
+
++// ============================================================================
++
++class XclExpFilePass : public XclExpRecord
++{
++public:
++ explicit XclExpFilePass( const XclExpRoot& rRoot );
++ virtual ~XclExpFilePass();
++
++private:
++ virtual void WriteBody( XclExpStream& rStrm );
++
++private:
++ const XclExpRoot& mrRoot;
++};
++
++// ============================================================================
++
++class XclExpFnGroupCount : public XclExpRecord
++{
++public:
++ explicit XclExpFnGroupCount();
++ virtual ~XclExpFnGroupCount();
++
++private:
++ virtual void WriteBody( XclExpStream& rStrm );
++};
++
++// ============================================================================
++
++/** Beginning of User Interface Records */
++class XclExpInterfaceHdr : public XclExpRecord
++{
++public:
++ explicit XclExpInterfaceHdr();
++ virtual ~XclExpInterfaceHdr();
++
++private:
++ virtual void WriteBody( XclExpStream& rStrm );
++};
++
++// ============================================================================
++
++/** Beginning of User Interface Records */
++class XclExpInterfaceEnd : public XclExpRecord
++{
++public:
++ explicit XclExpInterfaceEnd();
++ virtual ~XclExpInterfaceEnd();
++
++private:
++ virtual void WriteBody( XclExpStream& rStrm );
++};
++
++// ============================================================================
++
++/** ADDMENU/DELMENU Record Group Count */
++class XclExpMMS : public XclExpRecord
++{
++public:
++ explicit XclExpMMS();
++ virtual ~XclExpMMS();
++
++private:
++ virtual void WriteBody( XclExpStream& rStrm );
++};
++
++// ============================================================================
++
++/** Write Access User Name - This record contains the user name, which is
++ the name you type when you install Excel. */
++class XclExpWriteAccess : public XclExpRecord
++{
++public:
++ explicit XclExpWriteAccess();
++ virtual ~XclExpWriteAccess();
++
++private:
++ virtual void WriteBody( XclExpStream& rStrm );
++};
++
++// ============================================================================
++
++class XclExpCodePage : public XclExpRecord
++{
++public:
++ explicit XclExpCodePage();
++ virtual ~XclExpCodePage();
++
++private:
++ virtual void WriteBody( XclExpStream& rStrm );
++};
++
++// ============================================================================
++
++class XclExpDSF : public XclExpRecord
++{
++public:
++ explicit XclExpDSF();
++ virtual ~XclExpDSF();
++
++private:
++ virtual void WriteBody( XclExpStream& rStrm );
++};
++
++// ============================================================================
++
++class XclExpProt4Rev : public XclExpRecord
++{
++public:
++ explicit XclExpProt4Rev();
++ virtual ~XclExpProt4Rev();
++
++private:
++ virtual void WriteBody( XclExpStream& rStrm );
++};
++
++// ============================================================================
++
++class XclExpProt4RevPass : public XclExpRecord
++{
++public:
++ explicit XclExpProt4RevPass();
++ virtual ~XclExpProt4RevPass();
++
++private:
++ virtual void WriteBody( XclExpStream& rStrm );
++};
++
++// ============================================================================
++
++/** What's this record for? It is a zero-byte record. */
++class XclExpExcel9File : public XclExpRecord
++{
++public:
++ explicit XclExpExcel9File();
++ virtual ~XclExpExcel9File();
++
++private:
++ virtual void WriteBody( XclExpStream& rStrm );
++};
++
++// ============================================================================
++
++class XclExpUnknown01C1 : public XclExpDummyRecord
++{
++public:
++ explicit XclExpUnknown01C1();
++};
++
++// ============================================================================
++
++class XclExpUnknown0863 : public XclExpDummyRecord
++{
++public:
++ explicit XclExpUnknown0863();
++};
++
+
+ #endif // _XCL97REC_HXX
+diff --git sc/source/filter/inc/xeroot.hxx sc/source/filter/inc/xeroot.hxx
+index 7e97e92..f4e1d25 100644
+--- sc/source/filter/inc/xeroot.hxx
++++ sc/source/filter/inc/xeroot.hxx
+@@ -154,7 +154,12 @@ public:
+ @param nRecId Identifier that specifies which record is returned. */
+ XclExpRecordRef CreateRecord( sal_uInt16 nRecId ) const;
+
++ bool IsDocumentEncrypted() const;
++
++ const String GetPassword() const;
++
+ private:
++
+ /** Returns the local or global link manager, depending on current context. */
+ XclExpRootData::XclExpLinkMgrRef GetLocalLinkMgrRef() const;
+
+diff --git sc/source/filter/inc/xestream.hxx sc/source/filter/inc/xestream.hxx
+index 514c65c..5d0e3a8 100644
+--- sc/source/filter/inc/xestream.hxx
++++ sc/source/filter/inc/xestream.hxx
+@@ -35,6 +35,9 @@
+
+ #include "xlstream.hxx"
+
++#include <svx/mscodec.hxx>
++#include <vector>
++
+ /* ============================================================================
+ Output stream class for Excel export
+ - CONTINUE record handling
+@@ -42,6 +45,8 @@ Output stream class for Excel export
+ ============================================================================ */
+
+ class XclExpRoot;
++class XclExpBiff8Encrypter;
++typedef ScfRef< XclExpBiff8Encrypter > XclExpEncrypterRef;
+
+ /** This class is used to export Excel record streams.
+ @descr An instance is constructed with an SvStream and the maximum size of Excel
+@@ -100,14 +105,14 @@ public:
+ /** Sets data slice length. 0 = no slices. */
+ void SetSliceSize( sal_uInt16 nSize );
+
+- inline XclExpStream& operator<<( sal_Int8 nValue );
+- inline XclExpStream& operator<<( sal_uInt8 nValue );
+- inline XclExpStream& operator<<( sal_Int16 nValue );
+- inline XclExpStream& operator<<( sal_uInt16 nValue );
+- inline XclExpStream& operator<<( sal_Int32 nValue );
+- inline XclExpStream& operator<<( sal_uInt32 nValue );
+- inline XclExpStream& operator<<( float fValue );
+- inline XclExpStream& operator<<( double fValue );
++ XclExpStream& operator<<( sal_Int8 nValue );
++ XclExpStream& operator<<( sal_uInt8 nValue );
++ XclExpStream& operator<<( sal_Int16 nValue );
++ XclExpStream& operator<<( sal_uInt16 nValue );
++ XclExpStream& operator<<( sal_Int32 nValue );
++ XclExpStream& operator<<( sal_uInt32 nValue );
++ XclExpStream& operator<<( float fValue );
++ XclExpStream& operator<<( double fValue );
+
+ /** Writes nBytes bytes from memory. */
+ sal_Size Write( const void* pData, sal_Size nBytes );
+@@ -148,6 +153,14 @@ public:
+ /** Returns the absolute position of the system stream. */
+ inline sal_Size GetSvStreamPos() const { return mrStrm.Tell(); }
+
++ void SetEncrypter( XclExpEncrypterRef xEncrypter );
++
++ bool HasValidEncrypter() const;
++
++ void EnableEncryption( bool bEnable = true );
++
++ void DisableEncryption();
++
+ private:
+ /** Writes header data, internal setup. */
+ void InitRecord( sal_uInt16 nRecId );
+@@ -170,6 +183,9 @@ private:
+ SvStream& mrStrm; /// Reference to the system output stream.
+ const XclExpRoot& mrRoot; /// Filter root data.
+
++ bool mbUseEncrypter;
++ XclExpEncrypterRef mxEncrypter;
++
+ // length data
+ sal_uInt16 mnMaxRecSize; /// Maximum size of record content.
+ sal_uInt16 mnMaxContSize; /// Maximum size of CONTINUE content.
+@@ -187,64 +203,51 @@ private:
+
+ // ----------------------------------------------------------------------------
+
+-inline XclExpStream& XclExpStream::operator<<( sal_Int8 nValue )
+-{
+- PrepareWrite( 1 );
+- mrStrm << nValue;
+- return *this;
+-}
+
+-inline XclExpStream& XclExpStream::operator<<( sal_uInt8 nValue )
+-{
+- PrepareWrite( 1 );
+- mrStrm << nValue;
+- return *this;
+-}
++// ============================================================================
+
+-inline XclExpStream& XclExpStream::operator<<( sal_Int16 nValue )
++class XclExpBiff8Encrypter
+ {
+- PrepareWrite( 2 );
+- mrStrm << nValue;
+- return *this;
+-}
++public:
++ explicit XclExpBiff8Encrypter( const XclExpRoot& rRoot, const sal_uInt8 nDocId[16],
++ const sal_uInt8 nSalt[16] );
++ ~XclExpBiff8Encrypter();
+
+-inline XclExpStream& XclExpStream::operator<<( sal_uInt16 nValue )
+-{
+- PrepareWrite( 2 );
+- mrStrm << nValue;
+- return *this;
+-}
++ bool IsValid() const;
+
+-inline XclExpStream& XclExpStream::operator<<( sal_Int32 nValue )
+-{
+- PrepareWrite( 4 );
+- mrStrm << nValue;
+- return *this;
+-}
++ void GetSaltDigest( sal_uInt8 nSaltDigest[16] ) const;
+
+-inline XclExpStream& XclExpStream::operator<<( sal_uInt32 nValue )
+-{
+- PrepareWrite( 4 );
+- mrStrm << nValue;
+- return *this;
+-}
++ void Encrypt( SvStream& rStrm, sal_uInt8 nData );
++ void Encrypt( SvStream& rStrm, sal_uInt16 nData );
++ void Encrypt( SvStream& rStrm, sal_uInt32 nData );
+
+-inline XclExpStream& XclExpStream::operator<<( float fValue )
+-{
+- PrepareWrite( 4 );
+- mrStrm << fValue;
+- return *this;
+-}
++ void Encrypt( SvStream& rStrm, sal_Int8 nData );
++ void Encrypt( SvStream& rStrm, sal_Int16 nData );
++ void Encrypt( SvStream& rStrm, sal_Int32 nData );
+
+-inline XclExpStream& XclExpStream::operator<<( double fValue )
+-{
+- PrepareWrite( 8 );
+- mrStrm << fValue;
+- return *this;
+-}
++ void Encrypt( SvStream& rStrm, float fValue );
++ void Encrypt( SvStream& rStrm, double fValue );
+
++ void EncryptBytes( SvStream& rStrm, ::std::vector<sal_uInt8>& aBytes );
+
+-// ============================================================================
++private:
++ void Init( const String& aPass, const sal_uInt8 nDocId[16],
++ const sal_uInt8 nSalt[16] );
++
++ sal_uInt32 GetBlockPos( sal_Size nStrmPos ) const;
++ sal_uInt16 GetOffsetInBlock( sal_Size nStrmPos ) const;
++
++
++private:
++ ::svx::MSCodec_Std97 maCodec; /// Crypto algorithm implementation.
++ sal_uInt16 mnPassw[16]; /// Cached password data for copy construction.
++ sal_uInt8 mnDocId[16]; /// Cached document ID for copy construction.
++ sal_uInt8 mnSaltDigest[16];
++
++ const XclExpRoot& mrRoot;
++ sal_Size mnOldPos; /// Last known stream position
++ bool mbValid;
++};
+
+ #endif
+
+diff --git sc/source/filter/inc/xetable.hxx sc/source/filter/inc/xetable.hxx
+index b565289..8efd337 100644
+--- sc/source/filter/inc/xetable.hxx
++++ sc/source/filter/inc/xetable.hxx
+@@ -1069,7 +1069,5 @@ private:
+ XclExpDvalRef mxDval; /// Data validation with DVAL and DV records.
+ };
+
+-// ============================================================================
+-
+ #endif
+
+diff --git sc/source/filter/inc/xicontent.hxx sc/source/filter/inc/xicontent.hxx
+index 48f6917..07b237a 100644
+--- sc/source/filter/inc/xicontent.hxx
++++ sc/source/filter/inc/xicontent.hxx
+@@ -37,6 +37,8 @@
+ #include "xistring.hxx"
+ #include "xiroot.hxx"
+
++#include <map>
++
+ /* ============================================================================
+ Classes to import the big Excel document contents (related to several cells or
+ globals for the document).
+@@ -249,5 +251,64 @@ public:
+
+ // ============================================================================
+
++// Document protection ========================================================
++
++class XclImpDocProtectBuffer : protected XclImpRoot
++{
++public:
++ explicit XclImpDocProtectBuffer( const XclImpRoot& rRoot );
++
++ /** document structure protection flag */
++ void ReadDocProtect( XclImpStream& rStrm );
++
++ /** document windows properties protection flag */
++ void ReadWinProtect( XclImpStream& rStrm );
++
++ void ReadPasswordHash( XclImpStream& rStrm );
++
++ void Apply() const;
++
++private:
++ sal_uInt16 mnPassHash;
++ bool mbDocProtect:1;
++ bool mbWinProtect:1;
++};
++
++// Sheet protection ===========================================================
++
++class XclImpSheetProtectBuffer : protected XclImpRoot
++{
++public:
++ explicit XclImpSheetProtectBuffer( const XclImpRoot& rRoot );
++
++ void ReadProtect( XclImpStream& rStrm, SCTAB nTab );
++
++ void ReadOptions( XclImpStream& rStrm, SCTAB nTab );
++
++ void ReadPasswordHash( XclImpStream& rStrm, SCTAB nTab );
++
++ void Apply() const;
++
++private:
++ struct Sheet
++ {
++ bool mbProtected;
++ sal_uInt16 mnPasswordHash;
++ sal_uInt16 mnOptions;
++
++ Sheet();
++ Sheet(const Sheet& r);
++ };
++
++ Sheet* GetSheetItem( SCTAB nTab );
++
++private:
++ typedef ::std::map<SCTAB, Sheet> ProtectedSheetMap;
++ ProtectedSheetMap maProtectedSheets;
++};
++
++
++// ============================================================================
++
+ #endif
+
+diff --git sc/source/filter/inc/xiroot.hxx sc/source/filter/inc/xiroot.hxx
+index 4e598b2..661d5cf 100644
+--- sc/source/filter/inc/xiroot.hxx
++++ sc/source/filter/inc/xiroot.hxx
+@@ -61,6 +61,8 @@ class XclImpPivotTableManager;
+ class XclImpPageSettings;
+ class XclImpDocViewSettings;
+ class XclImpTabViewSettings;
++class XclImpSheetProtectBuffer;
++class XclImpDocProtectBuffer;
+
+ class _ScRangeListTabs;
+ class ExcelToSc;
+@@ -87,6 +89,8 @@ struct XclImpRootData : public XclRootData
+ typedef ScfRef< XclImpPageSettings > XclImpPageSettRef;
+ typedef ScfRef< XclImpDocViewSettings > XclImpDocViewSettRef;
+ typedef ScfRef< XclImpTabViewSettings > XclImpTabViewSettRef;
++ typedef ScfRef< XclImpSheetProtectBuffer > XclImpTabProtectRef;
++ typedef ScfRef< XclImpDocProtectBuffer > XclImpDocProtectRef;
+
+ XclImpAddrConvRef mxAddrConv; /// The address converter.
+ XclImpFmlaCompRef mxFmlaComp; /// The formula compiler.
+@@ -110,6 +114,11 @@ struct XclImpRootData : public XclRootData
+ XclImpPageSettRef mxPageSett; /// Page settings for current sheet.
+ XclImpDocViewSettRef mxDocViewSett; /// View settings for entire document.
+ XclImpTabViewSettRef mxTabViewSett; /// View settings for current sheet.
++ XclImpTabProtectRef mxTabProtect; /// Sheet protection options for current sheet.
++ XclImpDocProtectRef mxDocProtect; /// Document protection options.
++
++ String maPassw; /// Entered password for stream decryption.
++ bool mbPassQueried; /// true = Password already querried.
+
+ bool mbHasCodePage; /// true = CODEPAGE record exists.
+
+@@ -181,6 +190,10 @@ public:
+ XclImpWebQueryBuffer& GetWebQueryBuffer() const;
+ /** Returns the pivot table manager. */
+ XclImpPivotTableManager& GetPivotTableManager() const;
++ /** Returns the sheet protection options of the current sheet. */
++ XclImpSheetProtectBuffer& GetSheetProtectBuffer() const;
++ /** Returns the document protection options. */
++ XclImpDocProtectBuffer& GetDocProtectBuffer() const;
+
+ /** Returns the page settings of the current sheet. */
+ XclImpPageSettings& GetPageSettings() const;
+@@ -192,6 +205,9 @@ public:
+ /** Returns the Calc add-in function name for an Excel function name. */
+ String GetScAddInName( const String& rXclName ) const;
+
++ /** Queries a password from the user and returns it (empty string -> input cancelled). */
++ const String& QueryPassword() const;
++
+ private:
+ mutable XclImpRootData& mrImpData; /// Reference to the global import data struct.
+ };
+diff --git sc/source/filter/inc/xistream.hxx sc/source/filter/inc/xistream.hxx
+index 1f73cde..2e024c1 100644
+--- sc/source/filter/inc/xistream.hxx
++++ sc/source/filter/inc/xistream.hxx
+@@ -73,6 +73,8 @@ public:
+ @return Count of bytes really read. */
+ sal_uInt16 Read( SvStream& rStrm, void* pData, sal_uInt16 nBytes );
+
++ const String GetPassword() const;
++
+ protected:
+ /** Protected copy c'tor for OnClone(). */
+ explicit XclImpDecrypter( const XclImpDecrypter& rSrc );
+@@ -80,6 +82,8 @@ protected:
+ /** Sets the decrypter to a state showing whether the password was correct. */
+ void SetHasValidPassword( bool bValid );
+
++ void SetPassword( const String& rPass );
++
+ private:
+ /** Implementation of cloning this object. */
+ virtual XclImpDecrypter* OnClone() const = 0;
+@@ -89,6 +93,7 @@ private:
+ virtual sal_uInt16 OnRead( SvStream& rStrm, sal_uInt8* pnData, sal_uInt16 nBytes ) = 0;
+
+ private:
++ String maPass; /// Stored password (needed for export)
+ ErrCode mnError; /// Decrypter error code.
+ sal_Size mnOldPos; /// Last known stream position.
+ sal_uInt16 mnRecSize; /// Current record size.
+diff --git sc/source/filter/inc/xlroot.hxx sc/source/filter/inc/xlroot.hxx
+index a09f5d0..38506c5 100644
+--- sc/source/filter/inc/xlroot.hxx
++++ sc/source/filter/inc/xlroot.hxx
+@@ -91,7 +91,6 @@ struct XclRootData
+ ScDocument& mrDoc; /// The source or destination document.
+ String maDocUrl; /// Document URL of imported/exported file.
+ String maBasePath; /// Base path of imported/exported file (path of maDocUrl).
+- String maPassw; /// Entered password for stream encryption/decryption.
+ rtl_TextEncoding meTextEnc; /// Text encoding to import/export byte strings.
+ LanguageType meSysLang; /// System language.
+ LanguageType meDocLang; /// Document language (import: from file, export: from system).
+@@ -115,7 +114,6 @@ struct XclRootData
+ long mnCharWidth; /// Width of '0' in default font (twips).
+ SCTAB mnScTab; /// Current Calc sheet index.
+ const bool mbExport; /// false = Import, true = Export.
+- bool mbHasPassw; /// true = Password already querried.
+
+ explicit XclRootData( XclBiff eBiff, SfxMedium& rMedium,
+ SotStorageRef xRootStrg, ScDocument& rDoc,
+@@ -181,8 +179,6 @@ public:
+ inline const String& GetDocUrl() const { return mrData.maDocUrl; }
+ /** Returns the base path of the imported/exported file. */
+ inline const String& GetBasePath() const { return mrData.maBasePath; }
+- /** Queries a password from the user and returns it (empty string -> input cancelled). */
+- const String& QueryPassword() const;
+
+ /** Returns the OLE2 root storage of the imported/exported file.
+ @return Pointer to root storage or 0, if the file is a simple stream. */
+diff --git sc/source/filter/starcalc/scflt.cxx sc/source/filter/starcalc/scflt.cxx
+index e94cc27..b91c61f 100644
+--- sc/source/filter/starcalc/scflt.cxx
++++ sc/source/filter/starcalc/scflt.cxx
+@@ -1148,9 +1148,9 @@ void Sc10Import::LoadProtect()
+ //rStream.Read(&SheetProtect, sizeof(SheetProtect));
+ lcl_ReadSheetProtect(rStream, SheetProtect);
+ nError = rStream.GetError();
+- uno::Sequence<sal_Int8> aPass;
+- SvPasswordHelper::GetHashPassword(aPass, SC10TOSTRING( SheetProtect.PassWord ));
+- pDoc->SetDocProtection( SheetProtect.Protect, aPass);
++// uno::Sequence<sal_Int8> aPass;
++// SvPasswordHelper::GetHashPassword(aPass, SC10TOSTRING( SheetProtect.PassWord ));
++// pDoc->SetDocProtection( SheetProtect.Protect, SC10TOSTRING( SheetProtect.PassWord ));
+ }
+
+
+@@ -1502,10 +1502,10 @@ void Sc10Import::LoadTables()
+
+ //rStream.Read(&TabProtect, sizeof(TabProtect));
+ lcl_ReadTabProtect(rStream, TabProtect);
+- uno::Sequence<sal_Int8> aPass;
+- SvPasswordHelper::GetHashPassword(aPass, SC10TOSTRING( TabProtect.PassWord ));
++// uno::Sequence<sal_Int8> aPass;
++// SvPasswordHelper::GetHashPassword(aPass, SC10TOSTRING( TabProtect.PassWord ));
+
+- pDoc->SetTabProtection( static_cast<SCTAB>(Tab), TabProtect.Protect, aPass);
++ pDoc->SetTabProtection( static_cast<SCTAB>(Tab), TabProtect.Protect, SC10TOSTRING( TabProtect.PassWord ));
+
+ rStream >> TabNo;
+
+diff --git sc/source/filter/xcl97/XclExpChangeTrack.cxx sc/source/filter/xcl97/XclExpChangeTrack.cxx
+index 4aec3d6..5b90f44 100644
+--- sc/source/filter/xcl97/XclExpChangeTrack.cxx
++++ sc/source/filter/xcl97/XclExpChangeTrack.cxx
+@@ -491,6 +491,7 @@ void XclExpChTrTabId::Copy( const XclExpChTrTabIdBuffer& rBuffer )
+
+ void XclExpChTrTabId::SaveCont( XclExpStream& rStrm )
+ {
++ rStrm.EnableEncryption();
+ if( pBuffer )
+ for( sal_uInt16* pElem = pBuffer; pElem < (pBuffer + nTabCount); pElem++ )
+ rStrm << *pElem;
+diff --git sc/source/filter/xcl97/makefile.mk sc/source/filter/xcl97/makefile.mk
+index 3620621..ecfc547 100644
+--- sc/source/filter/xcl97/makefile.mk
++++ sc/source/filter/xcl97/makefile.mk
+@@ -50,7 +50,6 @@ PROJECTPCHSOURCE=..\pch\filt_pch
+ # --- Files --------------------------------------------------------
+
+ SLOFILES = \
+- $(SLO)$/xcl97dum.obj \
+ $(SLO)$/xcl97esc.obj \
+ $(SLO)$/xcl97rec.obj \
+ $(SLO)$/XclImpChangeTrack.obj \
+diff --git sc/source/filter/xcl97/xcl97rec.cxx sc/source/filter/xcl97/xcl97rec.cxx
+index c1a4568..f0d45ea 100644
+--- sc/source/filter/xcl97/xcl97rec.cxx
++++ sc/source/filter/xcl97/xcl97rec.cxx
+@@ -78,6 +78,7 @@
+ #include "scextopt.hxx"
+ #include "docoptio.hxx"
+ #include "patattr.hxx"
++#include "tabprotection.hxx"
+
+ using ::rtl::OUString;
+ using namespace ::com::sun::star;
+@@ -132,9 +133,9 @@ sal_Size XclMsodrawing_Base::GetDataLen() const
+
+ // --- class XclMsodrawinggroup --------------------------------------
+
+-XclMsodrawinggroup::XclMsodrawinggroup( RootData& rRoot, UINT16 nEscherType )
+- :
+- XclMsodrawing_Base( *rRoot.pEscher )
++XclMsodrawinggroup::XclMsodrawinggroup( RootData& rRoot, UINT16 nEscherType ) :
++ XclMsodrawing_Base( *rRoot.pEscher ),
++ XclExpRecord(0x00EB, 2) // bogus record size since we don't know the actual size yet.
+ {
+ if ( nEscherType )
+ {
+@@ -179,7 +180,7 @@ XclMsodrawinggroup::~XclMsodrawinggroup()
+ }
+
+
+-void XclMsodrawinggroup::SaveCont( XclExpStream& rStrm )
++void XclMsodrawinggroup::WriteBody( XclExpStream& rStrm )
+ {
+ DBG_ASSERT( GetEscherEx()->GetStreamPos() == GetEscherEx()->GetOffsetFromMap( nStartPos ),
+ "XclMsodrawinggroup::SaveCont: Escher stream position mismatch" );
+@@ -187,23 +188,11 @@ void XclMsodrawinggroup::SaveCont( XclExpStream& rStrm )
+ }
+
+
+-UINT16 XclMsodrawinggroup::GetNum() const
+-{
+- return 0x00EB;
+-}
+-
+-
+-sal_Size XclMsodrawinggroup::GetLen() const
+-{
+- return GetDataLen();
+-}
+-
+-
+-
+ // --- class XclMsodrawing --------------------------------------
+
+ XclMsodrawing::XclMsodrawing( const XclExpRoot& rRoot, UINT16 nEscherType, sal_Size nInitialSize ) :
+- XclMsodrawing_Base( *rRoot.GetOldRoot().pEscher, nInitialSize )
++ XclMsodrawing_Base( *rRoot.GetOldRoot().pEscher, nInitialSize ),
++ XclExpRecord( 0x00EC, nInitialSize )
+ {
+ if ( nEscherType )
+ {
+@@ -229,7 +218,7 @@ XclMsodrawing::~XclMsodrawing()
+ }
+
+
+-void XclMsodrawing::SaveCont( XclExpStream& rStrm )
++void XclMsodrawing::WriteBody( XclExpStream& rStrm )
+ {
+ DBG_ASSERT( GetEscherEx()->GetStreamPos() == GetEscherEx()->GetOffsetFromMap( nStartPos ),
+ "XclMsodrawing::SaveCont: Escher stream position mismatch" );
+@@ -237,16 +226,6 @@ void XclMsodrawing::SaveCont( XclExpStream& rStrm )
+ }
+
+
+-UINT16 XclMsodrawing::GetNum() const
+-{
+- return 0x00EC;
+-}
+-
+-
+-sal_Size XclMsodrawing::GetLen() const
+-{
+- return GetDataLen();
+-}
+
+
+ // --- class XclObjList ----------------------------------------------
+@@ -883,6 +862,7 @@ ExcBof8_Base::ExcBof8_Base()
+
+ void ExcBof8_Base::SaveCont( XclExpStream& rStrm )
+ {
++ rStrm.DisableEncryption();
+ rStrm << nVers << nDocType << nRupBuild << nRupYear
+ << nFileHistory << nLowestBiffVer;
+ }
+@@ -943,7 +923,10 @@ void ExcBundlesheet8::SaveCont( XclExpStream& rStrm )
+ {
+ nOwnPos = rStrm.GetSvStreamPos();
+ // write dummy position, real position comes later
+- rStrm << sal_uInt32( 0 ) << nGrbit << aUnicodeName;
++ rStrm.DisableEncryption();
++ rStrm << sal_uInt32(0);
++ rStrm.EnableEncryption();
++ rStrm << nGrbit << aUnicodeName;
+ }
+
+
+@@ -1223,33 +1206,73 @@ sal_Size ExcEScenarioManager::GetLen() const
+ return 8;
+ }
+
++// ============================================================================
+
+-
+-// ---- class XclProtection ------------------------------------------
+-
+-const BYTE XclProtection::pMyData[] =
++struct XclExpTabProtectOption
+ {
+- 0x12, 0x00, 0x02, 0x00, 0x01, 0x00, // PROTECT
+- 0xDD, 0x00, 0x02, 0x00, 0x01, 0x00, // SCENPROTECT
+- 0x63, 0x00, 0x02, 0x00, 0x01, 0x00 // OBJPROTECT
++ ScTableProtection::Option eOption;
++ sal_uInt16 nMask;
+ };
+-const sal_Size XclProtection::nMyLen = sizeof( XclProtection::pMyData );
+
+-sal_Size XclProtection::GetLen( void ) const
++XclExpSheetProtectOptions::XclExpSheetProtectOptions( const XclExpRoot& rRoot, SCTAB nTab ) :
++ XclExpRecord( 0x0867, 23 )
+ {
+- return nMyLen;
++ static const XclExpTabProtectOption aTable[] =
++ {
++ { ScTableProtection::OBJECTS, 0x0001 },
++ { ScTableProtection::SCENARIOS, 0x0002 },
++ { ScTableProtection::FORMAT_CELLS, 0x0004 },
++ { ScTableProtection::FORMAT_COLUMNS, 0x0008 },
++ { ScTableProtection::FORMAT_ROWS, 0x0010 },
++ { ScTableProtection::INSERT_COLUMNS, 0x0020 },
++ { ScTableProtection::INSERT_ROWS, 0x0040 },
++ { ScTableProtection::INSERT_HYPERLINKS, 0x0080 },
++
++ { ScTableProtection::DELETE_COLUMNS, 0x0100 },
++ { ScTableProtection::DELETE_ROWS, 0x0200 },
++ { ScTableProtection::SELECT_LOCKED_CELLS, 0x0400 },
++ { ScTableProtection::SORT, 0x0800 },
++ { ScTableProtection::AUTOFILTER, 0x1000 },
++ { ScTableProtection::PIVOT_TABLES, 0x2000 },
++ { ScTableProtection::SELECT_UNLOCKED_CELLS, 0x4000 },
++
++ { ScTableProtection::NONE, 0x0000 }
++ };
++
++ mnOptions = 0x0000;
++ ScTableProtection* pProtect = rRoot.GetDoc().GetTabProtection(nTab);
++ if (!pProtect)
++ return;
++
++ for (int i = 0; aTable[i].nMask != 0x0000; ++i)
++ {
++ if ( pProtect->isOptionEnabled(aTable[i].eOption) )
++ mnOptions |= aTable[i].nMask;
++ }
+ }
+
+-
+-const BYTE* XclProtection::GetData( void ) const
++void XclExpSheetProtectOptions::WriteBody( XclExpStream& rStrm )
+ {
+- return pMyData;
+-}
+-
++ sal_uInt16 nBytes = 0x0867;
++ rStrm << nBytes;
+
++ sal_uChar nZero = 0x00;
++ for (int i = 0; i < 9; ++i)
++ rStrm << nZero;
+
++ nBytes = 0x0200;
++ rStrm << nBytes;
++ nBytes = 0x0100;
++ rStrm << nBytes;
++ nBytes = 0xFFFF;
++ rStrm << nBytes << nBytes;
+
++ rStrm << mnOptions;
++ nBytes = 0;
++ rStrm << nBytes;
++}
+
++// ============================================================================
+
+
+
+@@ -1337,3 +1360,250 @@ XclRefmode::XclRefmode( const ScDocument& rDoc ) :
+ XclExpBoolRecord( 0x000F, rDoc.GetAddressConvention() != ScAddress::CONV_XL_R1C1 )
+ {
+ }
++
++// ============================================================================
++
++XclExpFilePass::XclExpFilePass( const XclExpRoot& rRoot ) :
++ XclExpRecord(0x002F, 54),
++ mrRoot(rRoot)
++{
++}
++
++XclExpFilePass::~XclExpFilePass()
++{
++}
++
++void XclExpFilePass::WriteBody( XclExpStream& rStrm )
++{
++ static const sal_uInt8 nDocId[] = {
++ 0x17, 0xf7, 0x01, 0x08, 0xea, 0xad, 0x30, 0x5c,
++ 0x1a, 0x95, 0xa5, 0x75, 0xd6, 0x79, 0xcd, 0x8d };
++
++
++ static const sal_uInt8 nSalt[] = {
++ 0xa4, 0x5b, 0xf7, 0xe9, 0x9f, 0x55, 0x21, 0xc5,
++ 0xc5, 0x56, 0xa8, 0x0d, 0x39, 0x05, 0x3a, 0xb4 };
++
++ // 0x0000 - neither standard nor strong encryption
++ // 0x0001 - standard or strong encryption
++ rStrm << static_cast<sal_uInt16>(0x0001);
++
++ // 0x0000 - non standard encryption
++ // 0x0001 - standard encryption
++ sal_uInt16 nStdEnc = 0x0001;
++ rStrm << nStdEnc << nStdEnc;
++
++ sal_uInt8 nSaltHash[16];
++ XclExpEncrypterRef xEnc( new XclExpBiff8Encrypter(mrRoot, nDocId, nSalt) );
++ xEnc->GetSaltDigest(nSaltHash);
++
++ rStrm.Write(nDocId, 16);
++ rStrm.Write(nSalt, 16);
++ rStrm.Write(nSaltHash, 16);
++
++ rStrm.SetEncrypter(xEnc);
++}
++
++// ============================================================================
++
++XclExpFnGroupCount::XclExpFnGroupCount() :
++ XclExpRecord(0x009C, 2)
++{
++}
++
++XclExpFnGroupCount::~XclExpFnGroupCount()
++{
++}
++
++void XclExpFnGroupCount::WriteBody( XclExpStream& rStrm )
++{
++ rStrm << static_cast<sal_uInt16>(14);
++}
++
++// ============================================================================
++
++XclExpInterfaceHdr::XclExpInterfaceHdr() :
++ XclExpRecord(0x00E1, 2)
++{
++}
++
++XclExpInterfaceHdr::~XclExpInterfaceHdr()
++{
++}
++
++void XclExpInterfaceHdr::WriteBody( XclExpStream& rStrm )
++{
++ // The value must be the same value as the CODEPAGE record.
++ rStrm.DisableEncryption();
++ rStrm << static_cast<sal_uInt16>(0x04B0);
++}
++
++// ============================================================================
++
++XclExpInterfaceEnd::XclExpInterfaceEnd() :
++ XclExpRecord(0x00E2, 0)
++{
++}
++
++XclExpInterfaceEnd::~XclExpInterfaceEnd()
++{
++}
++
++void XclExpInterfaceEnd::WriteBody( XclExpStream& /*rStrm*/ )
++{
++}
++
++// ============================================================================
++
++XclExpMMS::XclExpMMS() :
++ XclExpRecord(0x00C1, 2)
++{
++}
++
++XclExpMMS::~XclExpMMS()
++{
++}
++
++void XclExpMMS::WriteBody( XclExpStream& rStrm )
++{
++ rStrm << static_cast<sal_uInt16>(0x0000);
++}
++
++// ============================================================================
++
++XclExpWriteAccess::XclExpWriteAccess() :
++ XclExpRecord(0x005C, 112)
++{
++}
++
++XclExpWriteAccess::~XclExpWriteAccess()
++{
++}
++
++void XclExpWriteAccess::WriteBody( XclExpStream& rStrm )
++{
++ static const sal_uInt8 aData[] = {
++ 0x04, 0x00, 0x00, 'C', 'a', 'l', 'c', 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
++ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
++
++ sal_Size nDataSize = sizeof(aData);
++ for (sal_Size i = 0; i < nDataSize; ++i)
++ rStrm << aData[i];
++}
++
++// ============================================================================
++
++XclExpCodePage::XclExpCodePage() :
++ XclExpRecord(0x0042, 2)
++{
++}
++
++XclExpCodePage::~XclExpCodePage()
++{
++}
++
++void XclExpCodePage::WriteBody( XclExpStream& rStrm )
++{
++ // 0x04B0 : UTF-16 (BIFF8)
++ rStrm << static_cast<sal_uInt16>(0x04B0);
++}
++
++// ============================================================================
++
++XclExpDSF::XclExpDSF() :
++ XclExpRecord(0x0161, 2)
++{
++}
++
++XclExpDSF::~XclExpDSF()
++{
++}
++
++void XclExpDSF::WriteBody( XclExpStream& rStrm )
++{
++ rStrm << static_cast<sal_uInt16>(0x0000);
++}
++
++// ============================================================================
++
++XclExpProt4Rev::XclExpProt4Rev() :
++ XclExpRecord(0x01AF, 2)
++{
++}
++
++XclExpProt4Rev::~XclExpProt4Rev()
++{
++}
++
++void XclExpProt4Rev::WriteBody( XclExpStream& rStrm )
++{
++ rStrm << static_cast<sal_uInt16>(0x0000);
++}
++
++// ============================================================================
++
++XclExpProt4RevPass::XclExpProt4RevPass() :
++ XclExpRecord(0x01BC, 2)
++{
++}
++
++XclExpProt4RevPass::~XclExpProt4RevPass()
++{
++}
++
++void XclExpProt4RevPass::WriteBody( XclExpStream& rStrm )
++{
++ rStrm << static_cast<sal_uInt16>(0x0000);
++}
++
++// ============================================================================
++
++XclExpExcel9File::XclExpExcel9File() :
++ XclExpRecord(0x01C0, 0)
++{
++}
++
++XclExpExcel9File::~XclExpExcel9File()
++{
++}
++
++void XclExpExcel9File::WriteBody( XclExpStream& /*rStrm*/ )
++{
++}
++
++// ============================================================================
++
++static const sal_uInt8 nData01C1[] = {
++ 0xC1, 0x01, 0x00, 0x00, 0x54, 0x8D, 0x01, 0x00
++};
++
++XclExpUnknown01C1::XclExpUnknown01C1() :
++ XclExpDummyRecord(0x01C1, nData01C1, sizeof(nData01C1))
++{
++}
++
++// ============================================================================
++
++static const sal_uInt8 nData0863[] = {
++ 0x63, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x02
++};
++
++XclExpUnknown0863::XclExpUnknown0863() :
++ XclExpDummyRecord(0x0863, nData0863, sizeof(nData0863))
++{
++}
++
+diff --git sc/source/filter/xml/xmlbodyi.cxx sc/source/filter/xml/xmlbodyi.cxx
+index 9f4a55e..bc9687f 100644
+--- sc/source/filter/xml/xmlbodyi.cxx
++++ sc/source/filter/xml/xmlbodyi.cxx
+@@ -52,6 +52,7 @@
+ #include "XMLTrackedChangesContext.hxx"
+ #include "XMLEmptyContext.hxx"
+ #include "scerrors.hxx"
++#include "tabprotection.hxx"
+
+ #include <xmloff/xmltkmap.hxx>
+ #include <xmloff/xmltoken.hxx>
+@@ -62,6 +63,8 @@
+ #include <sal/types.h>
+ #include <tools/debug.hxx>
+
++#include <memory>
++
+ using namespace com::sun::star;
+ using namespace xmloff::token;
+
+@@ -280,10 +283,17 @@ void ScXMLBodyContext::EndElement()
+ // #i37959# handle document protection after the sheet settings
+ if (bProtected)
+ {
++ ::std::auto_ptr<ScDocProtection> pProtection(new ScDocProtection);
++ pProtection->setProtected(true);
++
+ uno::Sequence<sal_Int8> aPass;
+ if (sPassword.getLength())
++ {
+ SvXMLUnitConverter::decodeBase64(aPass, sPassword);
+- pDoc->SetDocProtection(bProtected, aPass);
++ pProtection->setPasswordHash(aPass, PASSHASH_OOO);
++ }
++
++ pDoc->SetDocProtection(pProtection.get());
+ }
+ }
+ GetScImport().UnlockSolarMutex();
+diff --git sc/source/filter/xml/xmlexprt.cxx sc/source/filter/xml/xmlexprt.cxx
+index 951e00a..009796e 100644
+--- sc/source/filter/xml/xmlexprt.cxx
++++ sc/source/filter/xml/xmlexprt.cxx
+@@ -67,6 +67,7 @@
+ #include "rangeutl.hxx"
+ #include "convuno.hxx"
+ #include "postit.hxx"
++#include "tabprotection.hxx"
+
+ #include <xmloff/xmltoken.hxx>
+ #include <xmloff/xmlnmspe.hxx>
+@@ -1399,7 +1400,11 @@ void ScXMLExport::SetBodyAttributes()
+ {
+ AddAttribute(XML_NAMESPACE_TABLE, XML_STRUCTURE_PROTECTED, XML_TRUE);
+ rtl::OUStringBuffer aBuffer;
+- SvXMLUnitConverter::encodeBase64(aBuffer, pDoc->GetDocPassword());
++ uno::Sequence<sal_Int8> aPassHash;
++ const ScDocProtection* p = pDoc->GetDocProtection();
++ if (p)
++ aPassHash = p->getPasswordHash(PASSHASH_OOO);
++ SvXMLUnitConverter::encodeBase64(aBuffer, aPassHash);
+ if (aBuffer.getLength())
+ AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY, aBuffer.makeStringAndClear());
+ }
+@@ -1417,11 +1422,13 @@ void ScXMLExport::_ExportContent()
+ DBG_ERROR("no shared data setted");
+ }
+ ScXMLExportDatabaseRanges aExportDatabaseRanges(*this);
+- if (GetModel().is())
+- {
++ if (!GetModel().is())
++ return;
++
+ uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( GetModel(), uno::UNO_QUERY );
+- if ( xSpreadDoc.is() )
+- {
++ if ( !xSpreadDoc.is() )
++ return;
++
+ uno::Reference<container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY );
+ if ( xIndex.is() )
+ {
+@@ -1471,7 +1478,11 @@ void ScXMLExport::_ExportContent()
+ AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTED, XML_TRUE);
+ rtl::OUStringBuffer aBuffer;
+ if (pDoc)
+- SvXMLUnitConverter::encodeBase64(aBuffer, pDoc->GetTabPassword(static_cast<SCTAB>(nTable)));
++ {
++ ScTableProtection* pProtect = pDoc->GetTabProtection(static_cast<SCTAB>(nTable));
++ if (pProtect)
++ SvXMLUnitConverter::encodeBase64(aBuffer, pProtect->getPasswordHash(PASSHASH_OOO));
++ }
+ if (aBuffer.getLength())
+ AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY, aBuffer.makeStringAndClear());
+ }
+@@ -1585,8 +1596,6 @@ void ScXMLExport::_ExportContent()
+ aExportDDELinks.WriteDDELinks(xSpreadDoc);
+ IncrementProgressBar(sal_True, 0);
+ GetProgressBarHelper()->SetValue(GetProgressBarHelper()->GetReference());
+- }
+- }
+ }
+
+ void ScXMLExport::_ExportStyles( sal_Bool bUsed )
+diff --git sc/source/filter/xml/xmlsubti.cxx sc/source/filter/xml/xmlsubti.cxx
+index 8d45478..ab00932 100644
+--- sc/source/filter/xml/xmlsubti.cxx
++++ sc/source/filter/xml/xmlsubti.cxx
+@@ -42,6 +42,7 @@
+ #include "docuno.hxx"
+ #include "cellsuno.hxx"
+ #include "XMLStylesImportHelper.hxx"
++#include "tabprotection.hxx"
+
+ #include <xmloff/xmltkmap.hxx>
+ #include <xmloff/nmspmap.hxx>
+@@ -58,6 +59,10 @@
+ #include <com/sun/star/util/XProtectable.hpp>
+ #include <com/sun/star/sheet/XArrayFormulaRange.hpp>
+
++#include <memory>
++
++using ::std::auto_ptr;
++
+ //------------------------------------------------------------------
+
+ using namespace com::sun::star;
+@@ -639,13 +644,10 @@ void ScMyTables::DeleteTable()
+ {
+ uno::Sequence<sal_Int8> aPass;
+ SvXMLUnitConverter::decodeBase64(aPass, sPassword);
+- rImport.GetDocument()->SetTabProtection(static_cast<SCTAB>(nCurrentSheet), bProtection, aPass);
+- /*uno::Reference <util::XProtectable> xProtectable(xCurrentSheet, uno::UNO_QUERY);
+- if (xProtectable.is())
+- {
+- rtl::OUString sKey;
+- xProtectable->protect(sKey);
+- }*/
++ auto_ptr<ScTableProtection> pProtect(new ScTableProtection);
++ pProtect->setProtected(bProtection);
++ pProtect->setPasswordHash(aPass, PASSHASH_OOO);
++ rImport.GetDocument()->SetTabProtection(static_cast<SCTAB>(nCurrentSheet), pProtect.get());
+ }
+
+ rImport.UnlockSolarMutex();
+diff --git sc/source/ui/docshell/docfunc.cxx sc/source/ui/docshell/docfunc.cxx
+index 8b9b366..3127e4d 100644
+--- sc/source/ui/docshell/docfunc.cxx
++++ sc/source/ui/docshell/docfunc.cxx
+@@ -92,7 +92,12 @@
+ #include "editable.hxx"
+ #include "compiler.hxx"
+ #include "scui_def.hxx" //CHINA001
++#include "tabprotection.hxx"
++
++#include <memory>
++
+ using namespace com::sun::star;
++using ::com::sun::star::uno::Sequence;
+
+ // STATIC DATA -----------------------------------------------------------
+
+@@ -2601,103 +2606,152 @@ BOOL ScDocFunc::RemovePageBreak( BOOL bColumn, const ScAddress& rPos,
+
+ //------------------------------------------------------------------------
+
+-BOOL lcl_ValidPassword( ScDocument* pDoc, SCTAB nTab,
+- const String& rPassword,
+- uno::Sequence<sal_Int8>* pReturnOld = NULL )
++void ScDocFunc::ProtectSheet( SCTAB nTab, const ScTableProtection& rProtect )
+ {
+- uno::Sequence<sal_Int8> aOldPassword;
+- if ( nTab == TABLEID_DOC )
++ ScDocument* pDoc = rDocShell.GetDocument();
++
++ pDoc->SetTabProtection(nTab, &rProtect);
++ if (pDoc->IsUndoEnabled())
+ {
+- if (pDoc->IsDocProtected())
+- aOldPassword = pDoc->GetDocPassword();
+- }
+- else
++ ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
++ DBG_ASSERT(pProtect, "ScDocFunc::Unprotect: ScTableProtection pointer is NULL!");
++ if (pProtect)
+ {
+- if (pDoc->IsTabProtected(nTab))
+- aOldPassword = pDoc->GetTabPassword(nTab);
+- }
++ ::std::auto_ptr<ScTableProtection> p(new ScTableProtection(*pProtect));
++ p->setProtected(true); // just in case ...
++ rDocShell.GetUndoManager()->AddUndoAction(
++ new ScUndoTabProtect(&rDocShell, nTab, p) );
+
+- if (pReturnOld)
+- *pReturnOld = aOldPassword;
++ // ownership of auto_ptr now transferred to ScUndoTabProtect.
++ }
++ }
+
+- return ((aOldPassword.getLength() == 0) || SvPasswordHelper::CompareHashPassword(aOldPassword, rPassword));
++ rDocShell.PostPaintGridAll();
++ ScDocShellModificator aModificator(rDocShell);
++ aModificator.SetDocumentModified();
+ }
+
+-BOOL ScDocFunc::Protect( SCTAB nTab, const String& rPassword, BOOL bApi )
++BOOL ScDocFunc::Protect( SCTAB nTab, const String& rPassword, BOOL /*bApi*/ )
+ {
+- ScDocShellModificator aModificator( rDocShell );
+-
+ ScDocument* pDoc = rDocShell.GetDocument();
+- BOOL bUndo(pDoc->IsUndoEnabled());
+- BOOL bOk = lcl_ValidPassword( pDoc, nTab, rPassword);
+- if ( bOk )
++ if (nTab == TABLEID_DOC)
+ {
+- uno::Sequence<sal_Int8> aPass;
+- if (rPassword.Len())
+- SvPasswordHelper::GetHashPassword(aPass, rPassword);
++ // document protection
+
+- if (bUndo)
++ pDoc->SetDocProtection(true, rPassword);
++ if (pDoc->IsUndoEnabled())
++ {
++ ScDocProtection* pProtect = pDoc->GetDocProtection();
++ DBG_ASSERT(pProtect, "ScDocFunc::Unprotect: ScDocProtection pointer is NULL!");
++ if (pProtect)
+ {
++ ::std::auto_ptr<ScDocProtection> p(new ScDocProtection(*pProtect));
++ p->setProtected(true); // just in case ...
+ rDocShell.GetUndoManager()->AddUndoAction(
+- new ScUndoProtect( &rDocShell, nTab, TRUE, aPass ) );
++ new ScUndoDocProtect(&rDocShell, p) );
++ // ownership of auto_ptr is transferred to ScUndoDocProtect.
+ }
+-
+- if ( nTab == TABLEID_DOC )
+- pDoc->SetDocProtection( TRUE, aPass );
+- else
+- pDoc->SetTabProtection( nTab, TRUE, aPass );
+-
+- rDocShell.PostPaintGridAll();
+- aModificator.SetDocumentModified();
+ }
+- else if (!bApi)
++ }
++ else
+ {
+- // different password was set before
+-
+-//! rDocShell.ErrorMessage(...);
++ // sheet protection
+
+- InfoBox aBox( rDocShell.GetActiveDialogParent(), String( ScResId( SCSTR_WRONGPASSWORD ) ) );
+- aBox.Execute();
++ pDoc->SetTabProtection(nTab, true, rPassword);
++ if (pDoc->IsUndoEnabled())
++ {
++ ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
++ DBG_ASSERT(pProtect, "ScDocFunc::Unprotect: ScTableProtection pointer is NULL!");
++ if (pProtect)
++ {
++ ::std::auto_ptr<ScTableProtection> p(new ScTableProtection(*pProtect));
++ p->setProtected(true); // just in case ...
++ rDocShell.GetUndoManager()->AddUndoAction(
++ new ScUndoTabProtect(&rDocShell, nTab, p) );
++ // ownership of auto_ptr now transferred to ScUndoTabProtect.
++ }
++ }
+ }
+
+- return bOk;
++ rDocShell.PostPaintGridAll();
++ ScDocShellModificator aModificator( rDocShell );
++ aModificator.SetDocumentModified();
++
++ return true;
+ }
+
+ BOOL ScDocFunc::Unprotect( SCTAB nTab, const String& rPassword, BOOL bApi )
+ {
+- ScDocShellModificator aModificator( rDocShell );
+-
+ ScDocument* pDoc = rDocShell.GetDocument();
+- BOOL bUndo(pDoc->IsUndoEnabled());
+- uno::Sequence<sal_Int8> aOldPassword;
+- uno::Sequence<sal_Int8> aPass;
+- BOOL bOk = lcl_ValidPassword( pDoc, nTab, rPassword, &aOldPassword );
+- if ( bOk )
+- {
+- uno::Sequence<sal_Int8> aEmptyPass;
+- if ( nTab == TABLEID_DOC )
+- pDoc->SetDocProtection( FALSE, aEmptyPass );
+- else
+- pDoc->SetTabProtection( nTab, FALSE, aEmptyPass );
+
+- if (bUndo)
++ if (nTab == TABLEID_DOC)
++ {
++ // document protection
++
++ ScDocProtection* pDocProtect = pDoc->GetDocProtection();
++ if (!pDocProtect || !pDocProtect->isProtected())
++ // already unprotected (should not happen)!
++ return true;
++
++ // save the protection state before unprotect (for undo).
++ ::std::auto_ptr<ScDocProtection> pProtectCopy(new ScDocProtection(*pDocProtect));
++
++ if (!pDocProtect->verifyPassword(rPassword))
+ {
+- rDocShell.GetUndoManager()->AddUndoAction(
+- new ScUndoProtect( &rDocShell, nTab, FALSE, aOldPassword ) );
++ if (!bApi)
++ {
++ InfoBox aBox( rDocShell.GetActiveDialogParent(), String( ScResId( SCSTR_WRONGPASSWORD ) ) );
++ aBox.Execute();
++ }
++ return false;
+ }
+
+- rDocShell.PostPaintGridAll();
+- aModificator.SetDocumentModified();
++ pDoc->SetDocProtection(NULL);
++ if (pDoc->IsUndoEnabled())
++ {
++ pProtectCopy->setProtected(false);
++ rDocShell.GetUndoManager()->AddUndoAction(
++ new ScUndoDocProtect(&rDocShell, pProtectCopy) );
++ // ownership of auto_ptr now transferred to ScUndoTabProtect.
+ }
+- else if (!bApi)
++ }
++ else
+ {
+-//! rDocShell.ErrorMessage(...);
++ // sheet protection
++
++ ScTableProtection* pTabProtect = pDoc->GetTabProtection(nTab);
++ if (!pTabProtect || !pTabProtect->isProtected())
++ // already unprotected (should not happen)!
++ return true;
++
++ // save the protection state before unprotect (for undo).
++ ::std::auto_ptr<ScTableProtection> pProtectCopy(new ScTableProtection(*pTabProtect));
+
++ if (!pTabProtect->verifyPassword(rPassword))
++ {
++ if (!bApi)
++ {
+ InfoBox aBox( rDocShell.GetActiveDialogParent(), String( ScResId( SCSTR_WRONGPASSWORD ) ) );
+ aBox.Execute();
+ }
++ return false;
++ }
++
++ pDoc->SetTabProtection(nTab, NULL);
++ if (pDoc->IsUndoEnabled())
++ {
++ pProtectCopy->setProtected(false);
++ rDocShell.GetUndoManager()->AddUndoAction(
++ new ScUndoTabProtect(&rDocShell, nTab, pProtectCopy) );
++ // ownership of auto_ptr now transferred to ScUndoTabProtect.
++ }
++ }
++
++ rDocShell.PostPaintGridAll();
++ ScDocShellModificator aModificator( rDocShell );
++ aModificator.SetDocumentModified();
+
+- return bOk;
++ return true;
+ }
+
+ //------------------------------------------------------------------------
+diff --git sc/source/ui/docshell/docsh.cxx sc/source/ui/docshell/docsh.cxx
+index 8591efa..fd8e065 100644
+--- sc/source/ui/docshell/docsh.cxx
++++ sc/source/ui/docshell/docsh.cxx
+@@ -79,11 +79,6 @@
+ #include <sot/formats.hxx>
+ #define SOT_FORMATSTR_ID_STARCALC_30 SOT_FORMATSTR_ID_STARCALC
+
+-//REMOVE #ifndef SO2_DECL_SVSTORAGESTREAM_DEFINED
+-//REMOVE #define SO2_DECL_SVSTORAGESTREAM_DEFINED
+-//REMOVE SO2_DECL_REF(SotStorageStream)
+-//REMOVE #endif
+-
+ // INCLUDE ---------------------------------------------------------------
+
+ #include "cell.hxx"
+@@ -97,7 +92,6 @@
+ #include "scresid.hxx"
+ #include "sc.hrc"
+ #include "globstr.hrc"
+-//CHINA001 #include "tpstat.hxx"
+ #include "scerrors.hxx"
+ #include "brdcst.hxx"
+ #include "stlpool.hxx"
+@@ -126,6 +120,7 @@
+ #include "cfgids.hxx"
+ #include "warnpassword.hxx"
+ #include "optsolver.hxx"
++#include "tabprotection.hxx"
+
+ #include "docsh.hxx"
+ #include "docshimp.hxx"
+@@ -1970,6 +1965,32 @@ void ScDocShell::AsciiSave( SvStream& rStream, const ScImportOptions& rAsciiOpt
+ rStream.SetNumberFormatInt( nOldNumberFormatInt );
+ }
+
++/** Check for the compatibility of all password hashes. If there is at
++ least one hash that needs to be regenerated, it returns true. If all
++ hash values are Excel-compatible, then it returns false. */
++bool lcl_NeedHashRegen(const ScDocument& rDoc, ScPasswordHash eHash)
++{
++ if (rDoc.IsDocProtected())
++ {
++ const ScDocProtection* p = rDoc.GetDocProtection();
++ if (!p->isPasswordEmpty() && !p->hasPasswordHash(eHash))
++ return true;
++ }
++
++ SCTAB nTabCount = rDoc.GetTableCount();
++ for (SCTAB i = 0; i < nTabCount; ++i)
++ {
++ const ScTableProtection* p = rDoc.GetTabProtection(i);
++ if (!p || !p->isProtected())
++ // Sheet not protected. Skip it.
++ continue;
++
++ if (!p->isPasswordEmpty() && !p->hasPasswordHash(eHash))
++ return true;
++ }
++
++ return false;
++}
+
+ BOOL __EXPORT ScDocShell::ConvertTo( SfxMedium &rMed )
+ {
+@@ -2023,6 +2044,14 @@ BOOL __EXPORT ScDocShell::ConvertTo( SfxMedium &rMed )
+ aDocument.SetExtDocOptions( pExtDocOpt = new ScExtDocOptions );
+ pViewShell->GetViewData()->WriteExtOptions( *pExtDocOpt );
+
++ bool bNeedRetypePassDlg = lcl_NeedHashRegen(aDocument, PASSHASH_XL);
++ if (bNeedRetypePassDlg && !pViewShell->ExecuteRetypePassDlg(PASSHASH_XL))
++ {
++ SetError( ERRCODE_ABORT );
++ return false;
++ }
++
++#if 0
+ /* #115980 #If the imported document contained an encrypted password -
+ determine if we should save without it. */
+ ScExtDocSettings& rDocSett = pExtDocOpt->GetDocSettings();
+@@ -2032,6 +2061,7 @@ BOOL __EXPORT ScDocShell::ConvertTo( SfxMedium &rMed )
+ // #i42858# warn only on time
+ rDocSett.mbEncrypted = false;
+ }
++#endif
+ }
+
+ if( bDoSave )
+diff --git sc/source/ui/docshell/docsh5.cxx sc/source/ui/docshell/docsh5.cxx
+index 259b6bd..62c11ca 100644
+--- sc/source/ui/docshell/docsh5.cxx
++++ sc/source/ui/docshell/docsh5.cxx
+@@ -821,7 +821,7 @@ BOOL ScDocShell::MoveTable( SCTAB nSrcTab, SCTAB nDestTab, BOOL bCopy, BOOL bRec
+ ++nAdjSource; // new position of source table after CopyTab
+
+ if ( aDocument.IsTabProtected( nAdjSource ) )
+- aDocument.SetTabProtection( nDestTab, TRUE, aDocument.GetTabPassword( nAdjSource ) );
++ aDocument.CopyTabProtection(nAdjSource, nDestTab);
+
+ if (bRecord)
+ {
+diff --git sc/source/ui/inc/docfunc.hxx sc/source/ui/inc/docfunc.hxx
+index f95d833..00928c1 100644
+--- sc/source/ui/inc/docfunc.hxx
++++ sc/source/ui/inc/docfunc.hxx
+@@ -47,7 +47,7 @@ class ScRangeName;
+ class ScBaseCell;
+ class ScTokenArray;
+ struct ScTabOpParam;
+-
++class ScTableProtection;
+
+ // ---------------------------------------------------------------------------
+
+@@ -129,6 +129,8 @@ public:
+ BOOL RemovePageBreak( BOOL bColumn, const ScAddress& rPos,
+ BOOL bRecord, BOOL bSetModified, BOOL bApi );
+
++ void ProtectSheet( SCTAB nTab, const ScTableProtection& rProtect );
++
+ BOOL Protect( SCTAB nTab, const String& rPassword, BOOL bApi );
+ BOOL Unprotect( SCTAB nTab, const String& rPassword, BOOL bApi );
+
+diff --git sc/source/ui/inc/protectiondlg.hrc sc/source/ui/inc/protectiondlg.hrc
+new file mode 100644
+index 0000000..2eed38b
+--- /dev/null
++++ sc/source/ui/inc/protectiondlg.hrc
+@@ -0,0 +1,47 @@
++/*************************************************************************
++ *
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ *
++ * Copyright 2008 by Sun Microsystems, Inc.
++ *
++ * OpenOffice.org - a multi-platform office productivity suite
++ *
++ * $RCSfile: protectiondlg.hrc,v $
++ * $Revision: 1.1.2.1 $
++ *
++ * This file is part of OpenOffice.org.
++ *
++ * OpenOffice.org is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License version 3
++ * only, as published by the Free Software Foundation.
++ *
++ * OpenOffice.org is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU Lesser General Public License version 3 for more details
++ * (a copy is included in the LICENSE file that accompanied this code).
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * version 3 along with OpenOffice.org. If not, see
++ * <http://www.openoffice.org/license.html>
++ * for a copy of the LGPLv3 License.
++ *
++ ************************************************************************/
++
++#include <sc.hrc>
++
++#define BTN_OK 1
++#define BTN_CANCEL 2
++#define BTN_HELP 3
++
++#define BTN_PROTECT 4
++#define FT_PASSWORD1 5
++#define ED_PASSWORD1 6
++#define FT_PASSWORD2 7
++#define ED_PASSWORD2 8
++#define FL_OPTIONS 9
++#define FT_OPTIONS 10
++#define CLB_OPTIONS 11
++
++#define ST_SELECT_LOCKED_CELLS 50
++#define ST_SELECT_UNLOCKED_CELLS 51
+diff --git sc/source/ui/inc/protectiondlg.hxx sc/source/ui/inc/protectiondlg.hxx
+new file mode 100644
+index 0000000..263931f
+--- /dev/null
++++ sc/source/ui/inc/protectiondlg.hxx
+@@ -0,0 +1,85 @@
++/*************************************************************************
++ *
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ *
++ * Copyright 2008 by Sun Microsystems, Inc.
++ *
++ * OpenOffice.org - a multi-platform office productivity suite
++ *
++ * $RCSfile: protectiondlg.hxx,v $
++ * $Revision: 1.1.2.4 $
++ *
++ * This file is part of OpenOffice.org.
++ *
++ * OpenOffice.org is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License version 3
++ * only, as published by the Free Software Foundation.
++ *
++ * OpenOffice.org is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU Lesser General Public License version 3 for more details
++ * (a copy is included in the LICENSE file that accompanied this code).
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * version 3 along with OpenOffice.org. If not, see
++ * <http://www.openoffice.org/license.html>
++ * for a copy of the LGPLv3 License.
++ *
++ ************************************************************************/
++
++#ifndef SC_UI_PROTECTION_DLG_HXX
++#define SC_UI_PROTECTION_DLG_HXX
++
++#include <vcl/dialog.hxx>
++#include <vcl/button.hxx>
++#include <vcl/fixed.hxx>
++#include <vcl/edit.hxx>
++#include <svx/checklbx.hxx>
++
++class Window;
++class ScTableProtection;
++
++class ScTableProtectionDlg : public ModalDialog
++{
++public:
++ explicit ScTableProtectionDlg(Window* pParent);
++ virtual ~ScTableProtectionDlg();
++
++ virtual short Execute();
++
++ void SetDialogData(const ScTableProtection& rData);
++
++ void WriteData(ScTableProtection& rData) const;
++
++private:
++ ScTableProtectionDlg(); // disabled
++
++ void Init();
++
++ void EnableOptionalWidgets(bool bEnable = true);
++
++ CheckBox maBtnProtect;
++
++ FixedText maPassword1Text;
++ Edit maPassword1Edit;
++ FixedText maPassword2Text;
++ Edit maPassword2Edit;
++
++ FixedLine maOptionsLine;
++ FixedText maOptionsText;
++ SvxCheckListBox maOptionsListBox;
++
++ OKButton maBtnOk;
++ CancelButton maBtnCancel;
++ HelpButton maBtnHelp;
++
++ String maSelectLockedCells;
++ String maSelectUnlockedCells;
++
++ DECL_LINK( OKHdl, OKButton* );
++ DECL_LINK( CheckBoxHdl, CheckBox* );
++ DECL_LINK( PasswordModifyHdl, Edit* );
++};
++
++#endif
+diff --git sc/source/ui/inc/retypepassdlg.hrc sc/source/ui/inc/retypepassdlg.hrc
+new file mode 100644
+index 0000000..da24d64
+--- /dev/null
++++ sc/source/ui/inc/retypepassdlg.hrc
+@@ -0,0 +1,74 @@
++/*************************************************************************
++ *
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ *
++ * Copyright 2008 by Sun Microsystems, Inc.
++ *
++ * OpenOffice.org - a multi-platform office productivity suite
++ *
++ * $RCSfile: retypepassdlg.hrc,v $
++ * $Revision: 1.1.2.2 $
++ *
++ * This file is part of OpenOffice.org.
++ *
++ * OpenOffice.org is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License version 3
++ * only, as published by the Free Software Foundation.
++ *
++ * OpenOffice.org is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU Lesser General Public License version 3 for more details
++ * (a copy is included in the LICENSE file that accompanied this code).
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * version 3 along with OpenOffice.org. If not, see
++ * <http://www.openoffice.org/license.html>
++ * for a copy of the LGPLv3 License.
++ *
++ ************************************************************************/
++
++#include <sc.hrc>
++
++#define BTN_OK 1
++#define BTN_CANCEL 2
++#define BTN_HELP 3
++
++#define FT_DESC 10
++#define FL_DOCUMENT 11
++#define FT_DOCSTATUS 12
++#define BTN_RETYPE_DOC 13
++
++#define FL_SHEET 112
++
++#define FT_SHEETNAME1 113
++#define FT_SHEETSTATUS1 114
++#define BTN_RETYPE_SHEET1 115
++
++#define FT_SHEETNAME2 116
++#define FT_SHEETSTATUS2 117
++#define BTN_RETYPE_SHEET2 118
++
++#define FT_SHEETNAME3 119
++#define FT_SHEETSTATUS3 120
++#define BTN_RETYPE_SHEET3 121
++
++#define FT_SHEETNAME4 122
++#define FT_SHEETSTATUS4 123
++#define BTN_RETYPE_SHEET4 124
++
++#define SB_SCROLL 190
++
++#define STR_NOT_PROTECTED 200
++#define STR_NOT_PASS_PROTECTED 201
++#define STR_HASH_BAD 202
++#define STR_HASH_GOOD 203
++#define STR_HASH_REGENERATED 204
++
++#define FT_PASSWORD1 301
++#define ED_PASSWORD1 302
++#define FT_PASSWORD2 303
++#define ED_PASSWORD2 304
++#define BTN_MATCH_OLD_PASSWORD 305
++#define BTN_RETYPE_PASSWORD 306
++#define BTN_REMOVE_PASSWORD 307
+diff --git sc/source/ui/inc/retypepassdlg.hxx sc/source/ui/inc/retypepassdlg.hxx
+new file mode 100644
+index 0000000..4899d8f
+--- /dev/null
++++ sc/source/ui/inc/retypepassdlg.hxx
+@@ -0,0 +1,177 @@
++/*************************************************************************
++ *
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ *
++ * Copyright 2008 by Sun Microsystems, Inc.
++ *
++ * OpenOffice.org - a multi-platform office productivity suite
++ *
++ * $RCSfile: retypepassdlg.hxx,v $
++ * $Revision: 1.1.2.7 $
++ *
++ * This file is part of OpenOffice.org.
++ *
++ * OpenOffice.org is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License version 3
++ * only, as published by the Free Software Foundation.
++ *
++ * OpenOffice.org is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU Lesser General Public License version 3 for more details
++ * (a copy is included in the LICENSE file that accompanied this code).
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * version 3 along with OpenOffice.org. If not, see
++ * <http://www.openoffice.org/license.html>
++ * for a copy of the LGPLv3 License.
++ *
++ ************************************************************************/
++
++#ifndef SC_UI_RETYPEPASS_DLG_HXX
++#define SC_UI_RETYPEPASS_DLG_HXX
++
++#include <vcl/dialog.hxx>
++#include <vcl/button.hxx>
++#include <vcl/fixed.hxx>
++#include <vcl/edit.hxx>
++#include <vcl/scrbar.hxx>
++#include <svx/checklbx.hxx>
++#include <svtools/stdctrl.hxx>
++
++#include "tabprotection.hxx"
++
++#include <boost/shared_ptr.hpp>
++
++class Window;
++class ScDocProtection;
++class ScTableProtection;
++class ScDocument;
++
++class ScRetypePassDlg : public ModalDialog
++{
++public:
++ typedef ::boost::shared_ptr<ScDocProtection> DocProtectionPtr;
++ typedef ::boost::shared_ptr<ScTableProtection> TabProtectionPtr;
++
++ explicit ScRetypePassDlg(Window* pParent);
++ virtual ~ScRetypePassDlg();
++
++ virtual short Execute();
++
++ void SetData(const ScDocument& rDoc);
++ void SetDesiredHash(ScPasswordHash eHash);
++
++ /** Write the new set of password data to the document instance to
++ overwrite the current ones. */
++ void WriteNewDataToDocument(ScDocument& rDoc) const;
++
++private:
++ ScRetypePassDlg(); // disabled
++
++ void Init();
++ void PopulateDialog();
++ void SetDocData();
++ void SetTableData(sal_uInt8 nRowPos, SCTAB nTab);
++ void ResetTableRows();
++
++ /** Check the status of all hash values to see if it's okay to enable
++ the OK button. */
++ void CheckHashStatus();
++
++private:
++ OKButton maBtnOk;
++ CancelButton maBtnCancel;
++ HelpButton maBtnHelp;
++
++ FixedInfo maTextDescription;
++
++ FixedLine maLineDocument;
++ FixedText maTextDocStatus;
++ PushButton maBtnRetypeDoc;
++
++ FixedLine maLineSheet;
++ FixedText maTextSheetName1;
++ FixedText maTextSheetStatus1;
++ PushButton maBtnRetypeSheet1;
++
++ FixedText maTextSheetName2;
++ FixedText maTextSheetStatus2;
++ PushButton maBtnRetypeSheet2;
++
++ FixedText maTextSheetName3;
++ FixedText maTextSheetStatus3;
++ PushButton maBtnRetypeSheet3;
++
++ FixedText maTextSheetName4;
++ FixedText maTextSheetStatus4;
++ PushButton maBtnRetypeSheet4;
++
++ ScrollBar maScrollBar;
++
++ String maTextNotProtected;
++ String maTextNotPassProtected;
++ String maTextHashBad;
++ String maTextHashGood;
++ String maTextHashRegen;
++
++ DECL_LINK( OKHdl, OKButton* );
++ DECL_LINK( RetypeBtnHdl, PushButton* );
++ DECL_LINK( ScrollHdl, ScrollBar* );
++
++ struct TableItem
++ {
++ String maName;
++ TabProtectionPtr mpProtect;
++ };
++ ::std::vector<TableItem> maTableItems;
++
++ DocProtectionPtr mpDocItem;
++ size_t mnCurScrollPos;
++ ScPasswordHash meDesiredHash;
++};
++
++// ============================================================================
++
++class ScRetypePassInputDlg : public ModalDialog
++{
++public:
++ explicit ScRetypePassInputDlg(Window* pParent, ScPassHashProtectable* pProtected);
++ virtual ~ScRetypePassInputDlg();
++
++ virtual short Execute();
++
++ bool IsRemovePassword() const;
++ String GetNewPassword() const;
++
++private:
++ ScRetypePassInputDlg(); // disabled
++
++ void Init();
++ void CheckPasswordInput();
++
++private:
++ OKButton maBtnOk;
++ CancelButton maBtnCancel;
++ HelpButton maBtnHelp;
++
++ RadioButton maBtnRetypePassword;
++
++ FixedText maPassword1Text;
++ Edit maPassword1Edit;
++ FixedText maPassword2Text;
++ Edit maPassword2Edit;
++
++ CheckBox maBtnMatchOldPass;
++
++ RadioButton maBtnRemovePassword;
++
++ DECL_LINK( OKHdl, OKButton* );
++ DECL_LINK( RadioBtnHdl, RadioButton* );
++ DECL_LINK( CheckBoxHdl, CheckBox* );
++ DECL_LINK( PasswordModifyHdl, Edit* );
++
++ ScPassHashProtectable* mpProtected;
++};
++
++#endif
+diff --git sc/source/ui/inc/tabvwsh.hxx sc/source/ui/inc/tabvwsh.hxx
+index c6dd6a5..91059f7 100644
+--- sc/source/ui/inc/tabvwsh.hxx
++++ sc/source/ui/inc/tabvwsh.hxx
+@@ -38,6 +38,7 @@
+ #include "target.hxx"
+ #include "rangelst.hxx" // ScRangeListRef
+ #include "shellids.hxx"
++#include "tabprotection.hxx" // for ScPasswordHash
+
+ class FmFormShell;
+ class SbxObject;
+@@ -430,6 +431,8 @@ public:
+ void BroadcastAccessibility( const SfxHint &rHint );
+ BOOL HasAccessibilityObjects();
+
++ bool ExecuteRetypePassDlg(ScPasswordHash eDesiredHash);
++
+ using ScTabView::ShowCursor;
+ };
+
+diff --git sc/source/ui/inc/undotab.hxx sc/source/ui/inc/undotab.hxx
+index 1a976fe..0ed95c4 100644
+--- sc/source/ui/inc/undotab.hxx
++++ sc/source/ui/inc/undotab.hxx
+@@ -52,11 +52,15 @@
+
+ #include <com/sun/star/uno/Sequence.hxx>
+
++#include <memory>
++
+ class ScDocShell;
+ class ScDocument;
+ class SdrUndoAction;
+ class ScPrintRangeSaver;
+ class SdrObject;
++class ScDocProtection;
++class ScTableProtection;
+
+ //----------------------------------------------------------------------------
+
+@@ -335,14 +339,15 @@ private:
+ void DoChange( BOOL bShow ) const;
+ };
+
++// ============================================================================
+
+-class ScUndoProtect : public ScSimpleUndo
++/** This class implements undo & redo of document protect & unprotect
++ operations. */
++class ScUndoDocProtect : public ScSimpleUndo
+ {
+ public:
+- TYPEINFO();
+- ScUndoProtect( ScDocShell* pShell, SCTAB nNewTab,
+- BOOL bNewProtect, const com::sun::star::uno::Sequence<sal_Int8>& rNewPassword );
+- virtual ~ScUndoProtect();
++ ScUndoDocProtect(ScDocShell* pShell, ::std::auto_ptr<ScDocProtection> pProtectSettings);
++ virtual ~ScUndoDocProtect();
+
+ virtual void Undo();
+ virtual void Redo();
+@@ -352,11 +357,34 @@ public:
+ virtual String GetComment() const;
+
+ private:
+- SCTAB nTab;
+- BOOL bProtect;
+- com::sun::star::uno::Sequence<sal_Int8> aPassword;
++ ::std::auto_ptr<ScDocProtection> mpProtectSettings;
++
++ void DoProtect(bool bProtect);
++};
++
++// ============================================================================
++
++/** This class implements undo & redo of both protect and unprotect of
++ sheet. */
++class ScUndoTabProtect : public ScSimpleUndo
++{
++public:
++ ScUndoTabProtect(ScDocShell* pShell, SCTAB nTab,
++ ::std::auto_ptr<ScTableProtection> pProtectSettings);
++ virtual ~ScUndoTabProtect();
++
++ virtual void Undo();
++ virtual void Redo();
++ virtual void Repeat(SfxRepeatTarget& rTarget);
++ virtual BOOL CanRepeat(SfxRepeatTarget& rTarget) const;
++
++ virtual String GetComment() const;
++
++private:
++ SCTAB mnTab;
++ ::std::auto_ptr<ScTableProtection> mpProtectSettings;
+
+- void DoProtect( BOOL bDo );
++ void DoProtect(bool bProtect);
+ };
+
+
+diff --git sc/source/ui/inc/viewfunc.hxx sc/source/ui/inc/viewfunc.hxx
+index 097b353..57b92dc 100644
+--- sc/source/ui/inc/viewfunc.hxx
++++ sc/source/ui/inc/viewfunc.hxx
+@@ -69,6 +69,7 @@ class Exchange;
+ class ScRangeList;
+ class SvxHyperlinkItem;
+ class ScTransferObj;
++class ScTableProtection;
+
+ namespace com { namespace sun { namespace star { namespace datatransfer { class XTransferable; } } } }
+
+@@ -199,6 +200,8 @@ public:
+
+ void ChangeIndent( BOOL bIncrement );
+
++ void ProtectSheet( SCTAB nTab, const ScTableProtection& rProtect );
++
+ void Protect( SCTAB nTab, const String& rPassword );
+ BOOL Unprotect( SCTAB nTab, const String& rPassword );
+
+diff --git sc/source/ui/miscdlgs/makefile.mk sc/source/ui/miscdlgs/makefile.mk
+index bb81bba..aac2608 100644
+--- sc/source/ui/miscdlgs/makefile.mk
++++ sc/source/ui/miscdlgs/makefile.mk
+@@ -79,7 +79,9 @@ SLOFILES = \
+ $(SLO)$/warnbox.obj \
+ $(SLO)$/scuiautofmt.obj \
+ $(SLO)$/conflictsdlg.obj \
+- $(SLO)$/sharedocdlg.obj
++ $(SLO)$/sharedocdlg.obj \
++ $(SLO)$/protectiondlg.obj \
++ $(SLO)$/retypepassdlg.obj
+
+ EXCEPTIONSFILES = \
+ $(SLO)$/acredlin.obj \
+@@ -88,7 +90,9 @@ EXCEPTIONSFILES = \
+ $(SLO)$/optsolver.obj \
+ $(SLO)$/solveroptions.obj \
+ $(SLO)$/crnrdlg.obj \
+- $(SLO)$/solverutil.obj
++ $(SLO)$/solverutil.obj \
++ $(SLO)$/protectiondlg.obj \
++ $(SLO)$/retypepassdlg.obj
+
+ SRS1NAME=$(TARGET)
+ SRC1FILES = \
+@@ -97,7 +101,9 @@ SRC1FILES = \
+ highred.src \
+ linkarea.src \
+ conflictsdlg.src \
+- sharedocdlg.src
++ sharedocdlg.src \
++ protectiondlg.src \
++ retypepassdlg.src
+
+ LIB1TARGET = $(SLB)$/$(TARGET).lib
+
+@@ -119,7 +125,9 @@ LIB1OBJFILES = \
+ $(SLO)$/conflictsdlg.obj \
+ $(SLO)$/sharedocdlg.obj \
+ $(SLO)$/scuiautofmt.obj \
+- $(SLO)$/strindlg.obj
++ $(SLO)$/strindlg.obj \
++ $(SLO)$/protectiondlg.obj \
++ $(SLO)$/retypepassdlg.obj
+
+ # --- Tagets -------------------------------------------------------
+
+diff --git sc/source/ui/miscdlgs/protectiondlg.cxx sc/source/ui/miscdlgs/protectiondlg.cxx
+new file mode 100644
+index 0000000..ab77209
+--- /dev/null
++++ sc/source/ui/miscdlgs/protectiondlg.cxx
+@@ -0,0 +1,161 @@
++/*************************************************************************
++ *
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ *
++ * Copyright 2008 by Sun Microsystems, Inc.
++ *
++ * OpenOffice.org - a multi-platform office productivity suite
++ *
++ * $RCSfile: protectiondlg.cxx,v $
++ * $Revision: 1.1.2.6 $
++ *
++ * This file is part of OpenOffice.org.
++ *
++ * OpenOffice.org is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License version 3
++ * only, as published by the Free Software Foundation.
++ *
++ * OpenOffice.org is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU Lesser General Public License version 3 for more details
++ * (a copy is included in the LICENSE file that accompanied this code).
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * version 3 along with OpenOffice.org. If not, see
++ * <http://www.openoffice.org/license.html>
++ * for a copy of the LGPLv3 License.
++ *
++ ************************************************************************/
++
++#include "protectiondlg.hxx"
++#include "protectiondlg.hrc"
++#include "scresid.hxx"
++#include "tabprotection.hxx"
++
++#include <vcl/msgbox.hxx>
++
++
++// The order must match that of the list box.
++static const ScTableProtection::Option aOptions[] = {
++ ScTableProtection::SELECT_LOCKED_CELLS,
++ ScTableProtection::SELECT_UNLOCKED_CELLS,
++};
++static const USHORT nOptionCount = sizeof(aOptions)/sizeof(aOptions[0]);
++
++
++ScTableProtectionDlg::ScTableProtectionDlg(Window* pParent) :
++ ModalDialog(pParent, ScResId(RID_SCDLG_TABPROTECTION)),
++
++ maBtnProtect (this, ScResId(BTN_PROTECT)),
++ maPassword1Text (this, ScResId(FT_PASSWORD1)),
++ maPassword1Edit (this, ScResId(ED_PASSWORD1)),
++ maPassword2Text (this, ScResId(FT_PASSWORD2)),
++ maPassword2Edit (this, ScResId(ED_PASSWORD2)),
++ maOptionsLine (this, ScResId(FL_OPTIONS)),
++ maOptionsText (this, ScResId(FT_OPTIONS)),
++ maOptionsListBox(this, ScResId(CLB_OPTIONS)),
++
++ maBtnOk (this, ScResId(BTN_OK)),
++ maBtnCancel (this, ScResId(BTN_CANCEL)),
++ maBtnHelp (this, ScResId(BTN_HELP)),
++
++ maSelectLockedCells(ScResId(ST_SELECT_LOCKED_CELLS)),
++ maSelectUnlockedCells(ScResId(ST_SELECT_UNLOCKED_CELLS))
++{
++ Init();
++ FreeResource();
++}
++
++ScTableProtectionDlg::~ScTableProtectionDlg()
++{
++}
++
++short ScTableProtectionDlg::Execute()
++{
++ return ModalDialog::Execute();
++}
++
++void ScTableProtectionDlg::SetDialogData(const ScTableProtection& rData)
++{
++ for (USHORT i = 0; i < nOptionCount; ++i)
++ maOptionsListBox.CheckEntryPos(i, rData.isOptionEnabled(aOptions[i]));
++}
++
++void ScTableProtectionDlg::WriteData(ScTableProtection& rData) const
++{
++ rData.setProtected(maBtnProtect.IsChecked());
++
++ // We assume that the two password texts match.
++ rData.setPassword(maPassword1Edit.GetText());
++
++ for (USHORT i = 0; i < nOptionCount; ++i)
++ rData.setOption(aOptions[i], maOptionsListBox.IsChecked(i));
++}
++
++void ScTableProtectionDlg::Init()
++{
++ Link aLink = LINK( this, ScTableProtectionDlg, CheckBoxHdl );
++ maBtnProtect.SetClickHdl(aLink);
++
++ aLink = LINK( this, ScTableProtectionDlg, OKHdl );
++ maBtnOk.SetClickHdl(aLink);
++
++ aLink = LINK( this, ScTableProtectionDlg, PasswordModifyHdl );
++ maPassword1Edit.SetModifyHdl(aLink);
++ maPassword2Edit.SetModifyHdl(aLink);
++
++ maOptionsListBox.SetUpdateMode(false);
++ maOptionsListBox.Clear();
++
++ maOptionsListBox.InsertEntry(maSelectLockedCells);
++ maOptionsListBox.InsertEntry(maSelectUnlockedCells);
++
++ maOptionsListBox.CheckEntryPos(0, true);
++ maOptionsListBox.CheckEntryPos(1, true);
++
++ maOptionsListBox.SetUpdateMode(true);
++
++ // Set the default state of the dialog.
++ maBtnProtect.Check(true);
++ maPassword1Edit.GrabFocus();
++}
++
++void ScTableProtectionDlg::EnableOptionalWidgets(bool bEnable)
++{
++ maPassword1Text.Enable(bEnable);
++ maPassword1Edit.Enable(bEnable);
++ maPassword2Text.Enable(bEnable);
++ maPassword2Edit.Enable(bEnable);
++ maOptionsLine.Enable(bEnable);
++ maOptionsText.Enable(bEnable);
++
++ maOptionsListBox.Enable(bEnable);
++ maOptionsListBox.Invalidate();
++}
++
++IMPL_LINK( ScTableProtectionDlg, CheckBoxHdl, CheckBox*, pBtn )
++{
++ if (pBtn == &maBtnProtect)
++ {
++ bool bChecked = maBtnProtect.IsChecked();
++ EnableOptionalWidgets(bChecked);
++ maBtnOk.Enable(bChecked);
++ }
++
++ return 0;
++}
++
++IMPL_LINK( ScTableProtectionDlg, OKHdl, OKButton*, EMPTYARG )
++{
++ EndDialog(RET_OK);
++ return 0;
++}
++
++IMPL_LINK( ScTableProtectionDlg, PasswordModifyHdl, Edit*, EMPTYARG )
++{
++ String aPass1 = maPassword1Edit.GetText();
++ String aPass2 = maPassword2Edit.GetText();
++ maBtnOk.Enable(aPass1.Equals(aPass2));
++ return 0;
++}
+diff --git sc/source/ui/miscdlgs/protectiondlg.src sc/source/ui/miscdlgs/protectiondlg.src
+new file mode 100644
+index 0000000..14a1c85
+--- /dev/null
++++ sc/source/ui/miscdlgs/protectiondlg.src
+@@ -0,0 +1,130 @@
++/*************************************************************************
++ *
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ *
++ * Copyright 2008 by Sun Microsystems, Inc.
++ *
++ * OpenOffice.org - a multi-platform office productivity suite
++ *
++ * $RCSfile: protectiondlg.src,v $
++ * $Revision: 1.1.2.6 $
++ *
++ * This file is part of OpenOffice.org.
++ *
++ * OpenOffice.org is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License version 3
++ * only, as published by the Free Software Foundation.
++ *
++ * OpenOffice.org is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU Lesser General Public License version 3 for more details
++ * (a copy is included in the LICENSE file that accompanied this code).
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * version 3 along with OpenOffice.org. If not, see
++ * <http://www.openoffice.org/license.html>
++ * for a copy of the LGPLv3 License.
++ *
++ ************************************************************************/
++
++#include "protectiondlg.hrc"
++
++ModalDialog RID_SCDLG_TABPROTECTION
++{
++ Text [ en-US ] = "Protect Sheet" ;
++ Size = MAP_APPFONT ( 220 , 135 ) ;
++ Moveable = TRUE ;
++ Closeable = TRUE ;
++
++ OKButton BTN_OK
++ {
++ Pos = MAP_APPFONT ( 164 , 6 ) ;
++ Size = MAP_APPFONT ( 50 , 14 ) ;
++ DefButton = TRUE ;
++ };
++ CancelButton BTN_CANCEL
++ {
++ Pos = MAP_APPFONT ( 164 , 23 ) ;
++ Size = MAP_APPFONT ( 50 , 14 ) ;
++ };
++ HelpButton BTN_HELP
++ {
++ Pos = MAP_APPFONT ( 164 , 43 ) ;
++ Size = MAP_APPFONT ( 50 , 14 ) ;
++ };
++
++ CheckBox BTN_PROTECT
++ {
++ Pos = MAP_APPFONT ( 6 , 6 ) ;
++ Size = MAP_APPFONT ( 150 , 10 );
++
++ Text [ en-US ] = "P~rotect this sheet and the contents of locked cells" ;
++ };
++
++ FixedText FT_PASSWORD1
++ {
++ Pos = MAP_APPFONT ( 11, 23 );
++ Size = MAP_APPFONT ( 42, 10 );
++
++ Text [ en-US ] = "~Password" ;
++ };
++
++ Edit ED_PASSWORD1
++ {
++ Border = TRUE;
++ PassWord = TRUE;
++ Pos = MAP_APPFONT ( 56, 22 );
++ Size = MAP_APPFONT ( 75, 12 );
++ };
++
++ FixedText FT_PASSWORD2
++ {
++ Pos = MAP_APPFONT ( 11, 40 );
++ Size = MAP_APPFONT ( 42, 10 );
++
++ Text [ en-US ] = "~Confirm" ;
++ };
++
++ Edit ED_PASSWORD2
++ {
++ Border = TRUE;
++ PassWord = TRUE;
++ Pos = MAP_APPFONT ( 56, 39 );
++ Size = MAP_APPFONT ( 75, 12 );
++ };
++
++ FixedLine FL_OPTIONS
++ {
++ Pos = MAP_APPFONT ( 6, 60 );
++ Size = MAP_APPFONT ( 150, 8 );
++
++ Text [ en-US ] = "Options";
++ };
++
++ FixedText FT_OPTIONS
++ {
++ Pos = MAP_APPFONT ( 11, 74 );
++ Size = MAP_APPFONT ( 140, 8 );
++
++ Text [ en-US ] = "Allow all users of this sheet to:";
++ };
++
++ Control CLB_OPTIONS
++ {
++ Pos = MAP_APPFONT ( 11, 85 );
++ Size = MAP_APPFONT ( 140, 40 );
++ Border = TRUE ;
++ TabStop = TRUE ;
++ };
++
++ String ST_SELECT_LOCKED_CELLS
++ {
++ Text [ en-US ] = "Select locked cells";
++ };
++
++ String ST_SELECT_UNLOCKED_CELLS
++ {
++ Text [ en-US ] = "Select unlocked cells";
++ };
++};
+diff --git sc/source/ui/miscdlgs/retypepassdlg.cxx sc/source/ui/miscdlgs/retypepassdlg.cxx
+new file mode 100644
+index 0000000..28b41b8
+--- /dev/null
++++ sc/source/ui/miscdlgs/retypepassdlg.cxx
+@@ -0,0 +1,544 @@
++/*************************************************************************
++ *
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ *
++ * Copyright 2008 by Sun Microsystems, Inc.
++ *
++ * OpenOffice.org - a multi-platform office productivity suite
++ *
++ * $RCSfile: retypepassdlg.cxx,v $
++ * $Revision: 1.1.2.7 $
++ *
++ * This file is part of OpenOffice.org.
++ *
++ * OpenOffice.org is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License version 3
++ * only, as published by the Free Software Foundation.
++ *
++ * OpenOffice.org is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU Lesser General Public License version 3 for more details
++ * (a copy is included in the LICENSE file that accompanied this code).
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * version 3 along with OpenOffice.org. If not, see
++ * <http://www.openoffice.org/license.html>
++ * for a copy of the LGPLv3 License.
++ *
++ ************************************************************************/
++
++#include "retypepassdlg.hxx"
++#include "retypepassdlg.hrc"
++#include "scresid.hxx"
++#include "document.hxx"
++#include "tabprotection.hxx"
++
++#include <stdio.h>
++
++#include <vcl/msgbox.hxx>
++
++ScRetypePassDlg::ScRetypePassDlg(Window* pParent) :
++ ModalDialog(pParent, ScResId(RID_SCDLG_RETYPEPASS)),
++
++ maBtnOk (this, ScResId(BTN_OK)),
++ maBtnCancel (this, ScResId(BTN_CANCEL)),
++ maBtnHelp (this, ScResId(BTN_HELP)),
++
++ maTextDescription(this, ScResId(FT_DESC)),
++ maLineDocument(this, ScResId(FL_DOCUMENT)),
++ maTextDocStatus(this, ScResId(FT_DOCSTATUS)),
++ maBtnRetypeDoc(this, ScResId(BTN_RETYPE_DOC)),
++
++ maLineSheet(this, ScResId(FL_SHEET)),
++ maTextSheetName1(this, ScResId(FT_SHEETNAME1)),
++ maTextSheetStatus1(this, ScResId(FT_SHEETSTATUS1)),
++ maBtnRetypeSheet1(this, ScResId(BTN_RETYPE_SHEET1)),
++
++ maTextSheetName2(this, ScResId(FT_SHEETNAME2)),
++ maTextSheetStatus2(this, ScResId(FT_SHEETSTATUS2)),
++ maBtnRetypeSheet2(this, ScResId(BTN_RETYPE_SHEET2)),
++
++ maTextSheetName3(this, ScResId(FT_SHEETNAME3)),
++ maTextSheetStatus3(this, ScResId(FT_SHEETSTATUS3)),
++ maBtnRetypeSheet3(this, ScResId(BTN_RETYPE_SHEET3)),
++
++ maTextSheetName4(this, ScResId(FT_SHEETNAME4)),
++ maTextSheetStatus4(this, ScResId(FT_SHEETSTATUS4)),
++ maBtnRetypeSheet4(this, ScResId(BTN_RETYPE_SHEET4)),
++
++ maScrollBar (this, ScResId(SB_SCROLL)),
++
++ maTextNotProtected(ScResId(STR_NOT_PROTECTED)),
++ maTextNotPassProtected(ScResId(STR_NOT_PASS_PROTECTED)),
++ maTextHashBad(ScResId(STR_HASH_BAD)),
++ maTextHashGood(ScResId(STR_HASH_GOOD)),
++ maTextHashRegen(ScResId(STR_HASH_REGENERATED)),
++
++ mpDocItem(static_cast<ScDocProtection*>(NULL)),
++ mnCurScrollPos(0),
++ meDesiredHash(PASSHASH_OOO)
++{
++ Init();
++}
++
++ScRetypePassDlg::~ScRetypePassDlg()
++{
++}
++
++short ScRetypePassDlg::Execute()
++{
++ PopulateDialog();
++ CheckHashStatus();
++ return ModalDialog::Execute();
++}
++
++void ScRetypePassDlg::SetData(const ScDocument& rDoc)
++{
++ const ScDocProtection* pDocProtect = rDoc.GetDocProtection();
++ if (pDocProtect && pDocProtect->isProtected())
++ mpDocItem.reset(new ScDocProtection(*pDocProtect));
++
++ SCTAB nTabCount = rDoc.GetTableCount();
++ maTableItems.reserve(nTabCount);
++ for (SCTAB i = 0; i < nTabCount; ++i)
++ {
++ TableItem aTabItem;
++ rDoc.GetName(i, aTabItem.maName);
++
++ const ScTableProtection* pTabProtect = rDoc.GetTabProtection(i);
++ if (pTabProtect && pTabProtect->isProtected())
++ aTabItem.mpProtect.reset(new ScTableProtection(*pTabProtect));
++
++ maTableItems.push_back(aTabItem);
++ }
++}
++
++void ScRetypePassDlg::SetDesiredHash(ScPasswordHash eHash)
++{
++ meDesiredHash = eHash;
++}
++
++void ScRetypePassDlg::WriteNewDataToDocument(ScDocument& rDoc) const
++{
++ if (mpDocItem.get())
++ rDoc.SetDocProtection(mpDocItem.get());
++
++ SCTAB nTabCount = rDoc.GetTableCount();
++ size_t n = maTableItems.size();
++ for (size_t i = 0; i < n; ++i)
++ {
++ if (i >= nTabCount)
++ break;
++
++ ScTableProtection* pTabProtect = maTableItems[i].mpProtect.get();
++ if (pTabProtect)
++ rDoc.SetTabProtection(static_cast<SCTAB>(i), pTabProtect);
++ }
++}
++
++void ScRetypePassDlg::Init()
++{
++ Link aLink = LINK( this, ScRetypePassDlg, OKHdl );
++ maBtnOk.SetClickHdl(aLink);
++
++ aLink = LINK( this, ScRetypePassDlg, RetypeBtnHdl );
++ maBtnRetypeDoc.SetClickHdl(aLink);
++ maBtnRetypeSheet1.SetClickHdl(aLink);
++ maBtnRetypeSheet2.SetClickHdl(aLink);
++ maBtnRetypeSheet3.SetClickHdl(aLink);
++ maBtnRetypeSheet4.SetClickHdl(aLink);
++
++ maTextDocStatus.SetText(maTextNotProtected);
++ maTextSheetStatus1.SetText(maTextNotProtected);
++ maTextSheetStatus2.SetText(maTextNotProtected);
++ maTextSheetStatus3.SetText(maTextNotProtected);
++ maTextSheetStatus4.SetText(maTextNotProtected);
++ maBtnRetypeDoc.Disable();
++
++ // Make all sheet rows invisible.
++
++ maTextSheetName1.Show(false);
++ maTextSheetStatus1.Show(false);
++ maBtnRetypeSheet1.Show(false);
++ maBtnRetypeSheet1.Disable();
++
++ maTextSheetName2.Show(false);
++ maTextSheetStatus2.Show(false);
++ maBtnRetypeSheet2.Show(false);
++ maBtnRetypeSheet2.Disable();
++
++ maTextSheetName3.Show(false);
++ maTextSheetStatus3.Show(false);
++ maBtnRetypeSheet3.Show(false);
++ maBtnRetypeSheet3.Disable();
++
++ maTextSheetName4.Show(false);
++ maTextSheetStatus4.Show(false);
++ maBtnRetypeSheet4.Show(false);
++ maBtnRetypeSheet4.Disable();
++
++ maScrollBar.Show(false);
++
++ maScrollBar.SetEndScrollHdl( LINK( this, ScRetypePassDlg, ScrollHdl ) );
++ maScrollBar.SetScrollHdl( LINK( this, ScRetypePassDlg, ScrollHdl ) );
++
++ maScrollBar.SetPageSize(4);
++ maScrollBar.SetVisibleSize(4);
++ maScrollBar.SetLineSize(1);
++}
++
++void ScRetypePassDlg::PopulateDialog()
++{
++ // Document protection first.
++ SetDocData();
++
++ // Sheet protection next. We're only interested in the first 4 sheets
++ // (or less).
++ size_t n = maTableItems.size();
++ for (size_t i = 0; i < n && i < 4; ++i)
++ SetTableData(i, i);
++
++ if (n > 4)
++ {
++ maScrollBar.Show(true);
++ maScrollBar.SetRange(Range(0, n));
++ }
++}
++
++void ScRetypePassDlg::SetDocData()
++{
++ bool bBtnEnabled = false;
++ if (mpDocItem.get() && mpDocItem->isProtected())
++ {
++ if (mpDocItem->isPasswordEmpty())
++ maTextDocStatus.SetText(maTextNotPassProtected);
++ else if (mpDocItem->hasPasswordHash(meDesiredHash))
++ maTextDocStatus.SetText(maTextHashGood);
++ else
++ {
++ // incompatible hash
++ maTextDocStatus.SetText(maTextHashBad);
++ bBtnEnabled = true;
++ }
++ }
++ maBtnRetypeDoc.Enable(bBtnEnabled);
++}
++
++void ScRetypePassDlg::SetTableData(sal_uInt8 nRowPos, SCTAB nTab)
++{
++ if (nRowPos >= 4)
++ return;
++
++ FixedText* pName = NULL;
++ FixedText* pStatus = NULL;
++ PushButton* pBtn = NULL;
++ switch (nRowPos)
++ {
++ case 0:
++ pName = &maTextSheetName1;
++ pStatus = &maTextSheetStatus1;
++ pBtn = &maBtnRetypeSheet1;
++ break;
++ case 1:
++ pName = &maTextSheetName2;
++ pStatus = &maTextSheetStatus2;
++ pBtn = &maBtnRetypeSheet2;
++ break;
++ case 2:
++ pName = &maTextSheetName3;
++ pStatus = &maTextSheetStatus3;
++ pBtn = &maBtnRetypeSheet3;
++ break;
++ case 3:
++ pName = &maTextSheetName4;
++ pStatus = &maTextSheetStatus4;
++ pBtn = &maBtnRetypeSheet4;
++ break;
++ default:
++ return;
++ }
++
++ bool bBtnEnabled = false;
++ pName->SetText(maTableItems[nTab].maName);
++ pName->Show(true);
++ const ScTableProtection* pTabProtect = maTableItems[nTab].mpProtect.get();
++ if (pTabProtect && pTabProtect->isProtected())
++ {
++ if (pTabProtect->isPasswordEmpty())
++ pStatus->SetText(maTextNotPassProtected);
++ else if (pTabProtect->hasPasswordHash(meDesiredHash))
++ pStatus->SetText(maTextHashGood);
++ else
++ {
++ // incompatible hash
++ pStatus->SetText(maTextHashBad);
++ bBtnEnabled = true;
++ }
++ }
++ else
++ pStatus->SetText(maTextNotProtected);
++
++ pStatus->Show(true);
++ pBtn->Show(true);
++ pBtn->Enable(bBtnEnabled);
++}
++
++void ScRetypePassDlg::ResetTableRows()
++{
++ long nScrollPos = maScrollBar.GetThumbPos();
++ mnCurScrollPos = nScrollPos < 0 ? 0 : nScrollPos;
++ size_t nRowCount = maTableItems.size() - nScrollPos;
++ for (size_t i = 0; i < nRowCount; ++i)
++ SetTableData(i, i + nScrollPos);
++}
++
++bool lcl_IsInGoodStatus(ScPassHashProtectable* pProtected, ScPasswordHash eDesiredHash)
++{
++ if (!pProtected || !pProtected->isProtected())
++ // Not protected.
++ return true;
++
++ if (pProtected->isPasswordEmpty())
++ return true;
++
++ if (pProtected->hasPasswordHash(eDesiredHash))
++ return true;
++
++ return false;
++}
++
++void ScRetypePassDlg::CheckHashStatus()
++{
++ do
++ {
++ if (!lcl_IsInGoodStatus(mpDocItem.get(), meDesiredHash))
++ break;
++
++ bool bStatusGood = true;
++ size_t nTabCount = maTableItems.size();
++ for (size_t i = 0; i < nTabCount && bStatusGood; ++i)
++ {
++ if (!lcl_IsInGoodStatus(maTableItems[i].mpProtect.get(), meDesiredHash))
++ bStatusGood = false;
++ }
++ if (!bStatusGood)
++ break;
++
++ maBtnOk.Enable();
++ return;
++ }
++ while (false);
++
++ maBtnOk.Disable();
++}
++
++IMPL_LINK( ScRetypePassDlg, OKHdl, OKButton*, EMPTYARG )
++{
++ EndDialog(RET_OK);
++ return 0;
++}
++
++IMPL_LINK( ScRetypePassDlg, RetypeBtnHdl, PushButton*, pBtn )
++{
++ ScPassHashProtectable* pProtected = NULL;
++ if (pBtn == &maBtnRetypeDoc)
++ {
++ // document protection.
++ pProtected = mpDocItem.get();
++ }
++ else
++ {
++ // sheet protection.
++ size_t nTabPos = mnCurScrollPos;
++ if (pBtn == &maBtnRetypeSheet2)
++ nTabPos += 1;
++ else if (pBtn == &maBtnRetypeSheet3)
++ nTabPos += 2;
++ else if (pBtn == &maBtnRetypeSheet4)
++ nTabPos += 3;
++ else if (pBtn != &maBtnRetypeSheet1)
++ // This should never happen !
++ return 0;
++
++ if (nTabPos >= maTableItems.size())
++ // Likewise, this should never happen !
++ return 0;
++
++ pProtected = maTableItems[nTabPos].mpProtect.get();
++ }
++
++ if (!pProtected)
++ // What the ... !?
++ return 0;
++
++ ScRetypePassInputDlg aDlg(this, pProtected);
++ if (aDlg.Execute() == RET_OK)
++ {
++ // OK is pressed. Update the protected item.
++ if (aDlg.IsRemovePassword())
++ {
++ // Remove password from this item.
++ pProtected->setPassword(String());
++ }
++ else
++ {
++ // Set a new password.
++ String aNewPass = aDlg.GetNewPassword();
++ pProtected->setPassword(aNewPass);
++ }
++
++ SetDocData();
++ ResetTableRows();
++ CheckHashStatus();
++ }
++ return 0;
++}
++
++IMPL_LINK( ScRetypePassDlg, ScrollHdl, ScrollBar*, EMPTYARG )
++{
++ ResetTableRows();
++ return 0;
++}
++
++// ============================================================================
++
++ScRetypePassInputDlg::ScRetypePassInputDlg(Window* pParent, ScPassHashProtectable* pProtected) :
++ ModalDialog(pParent, ScResId(RID_SCDLG_RETYPEPASS_INPUT)),
++
++ maBtnOk (this, ScResId(BTN_OK)),
++ maBtnCancel (this, ScResId(BTN_CANCEL)),
++ maBtnHelp (this, ScResId(BTN_HELP)),
++
++ maBtnRetypePassword(this, ScResId(BTN_RETYPE_PASSWORD)),
++
++ maPassword1Text (this, ScResId(FT_PASSWORD1)),
++ maPassword1Edit (this, ScResId(ED_PASSWORD1)),
++ maPassword2Text (this, ScResId(FT_PASSWORD2)),
++ maPassword2Edit (this, ScResId(ED_PASSWORD2)),
++ maBtnMatchOldPass(this, ScResId(BTN_MATCH_OLD_PASSWORD)),
++
++ maBtnRemovePassword(this, ScResId(BTN_REMOVE_PASSWORD)),
++
++ mpProtected(pProtected)
++{
++ Init();
++}
++
++ScRetypePassInputDlg::~ScRetypePassInputDlg()
++{
++}
++
++short ScRetypePassInputDlg::Execute()
++{
++ return ModalDialog::Execute();
++}
++
++bool ScRetypePassInputDlg::IsRemovePassword() const
++{
++ return maBtnRemovePassword.IsChecked();
++}
++
++String ScRetypePassInputDlg::GetNewPassword() const
++{
++ return maPassword1Edit.GetText();
++}
++
++void ScRetypePassInputDlg::Init()
++{
++ Link aLink = LINK( this, ScRetypePassInputDlg, OKHdl );
++ maBtnOk.SetClickHdl(aLink);
++ aLink = LINK( this, ScRetypePassInputDlg, RadioBtnHdl );
++ maBtnRetypePassword.SetClickHdl(aLink);
++ maBtnRemovePassword.SetClickHdl(aLink);
++ aLink = LINK( this, ScRetypePassInputDlg, CheckBoxHdl );
++ maBtnMatchOldPass.SetClickHdl(aLink);
++ aLink = LINK( this, ScRetypePassInputDlg, PasswordModifyHdl );
++ maPassword1Edit.SetModifyHdl(aLink);
++ maPassword2Edit.SetModifyHdl(aLink);
++
++ maBtnOk.Disable();
++ maBtnRetypePassword.Check(true);
++ maBtnMatchOldPass.Check(true);
++ maPassword1Edit.GrabFocus();
++}
++
++void ScRetypePassInputDlg::CheckPasswordInput()
++{
++ String aPass1 = maPassword1Edit.GetText();
++ String aPass2 = maPassword2Edit.GetText();
++
++ if (!aPass1.Len() || !aPass2.Len())
++ {
++ // Empty password is not allowed.
++ maBtnOk.Disable();
++ return;
++ }
++
++ if (!aPass1.Equals(aPass2))
++ {
++ // The two passwords differ.
++ maBtnOk.Disable();
++ return;
++ }
++
++ if (!maBtnMatchOldPass.IsChecked())
++ {
++ maBtnOk.Enable();
++ return;
++ }
++
++ if (!mpProtected)
++ {
++ // This should never happen!
++ maBtnOk.Disable();
++ return;
++ }
++
++ bool bPassGood = mpProtected->verifyPassword(aPass1);
++ maBtnOk.Enable(bPassGood);
++}
++
++IMPL_LINK( ScRetypePassInputDlg, OKHdl, OKButton*, EMPTYARG )
++{
++ EndDialog(RET_OK);
++ return 0;
++}
++
++IMPL_LINK( ScRetypePassInputDlg, RadioBtnHdl, RadioButton*, pBtn )
++{
++ if (pBtn == &maBtnRetypePassword)
++ {
++ maBtnRemovePassword.Check(false);
++ maPassword1Text.Enable();
++ maPassword1Edit.Enable();
++ maPassword2Text.Enable();
++ maPassword2Edit.Enable();
++ maBtnMatchOldPass.Enable();
++ CheckPasswordInput();
++ }
++ else if (pBtn == &maBtnRemovePassword)
++ {
++ maBtnRetypePassword.Check(false);
++ maPassword1Text.Disable();
++ maPassword1Edit.Disable();
++ maPassword2Text.Disable();
++ maPassword2Edit.Disable();
++ maBtnMatchOldPass.Disable();
++ maBtnOk.Enable();
++ }
++
++ return 0;
++}
++
++IMPL_LINK( ScRetypePassInputDlg, CheckBoxHdl, CheckBox*, pBtn )
++{
++ CheckPasswordInput();
++ return 0;
++}
++
++IMPL_LINK( ScRetypePassInputDlg, PasswordModifyHdl, Edit*, pEdit )
++{
++ CheckPasswordInput();
++ return 0;
++}
+diff --git sc/source/ui/miscdlgs/retypepassdlg.src sc/source/ui/miscdlgs/retypepassdlg.src
+new file mode 100644
+index 0000000..4c45fbf
+--- /dev/null
++++ sc/source/ui/miscdlgs/retypepassdlg.src
+@@ -0,0 +1,316 @@
++/*************************************************************************
++ *
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ *
++ * Copyright 2008 by Sun Microsystems, Inc.
++ *
++ * OpenOffice.org - a multi-platform office productivity suite
++ *
++ * $RCSfile: retypepassdlg.src,v $
++ * $Revision: 1.1.2.3 $
++ *
++ * This file is part of OpenOffice.org.
++ *
++ * OpenOffice.org is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License version 3
++ * only, as published by the Free Software Foundation.
++ *
++ * OpenOffice.org is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU Lesser General Public License version 3 for more details
++ * (a copy is included in the LICENSE file that accompanied this code).
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * version 3 along with OpenOffice.org. If not, see
++ * <http://www.openoffice.org/license.html>
++ * for a copy of the LGPLv3 License.
++ *
++ ************************************************************************/
++
++#include "retypepassdlg.hrc"
++
++
++ModalDialog RID_SCDLG_RETYPEPASS
++{
++ Text [ en-US ] = "Re-type Password" ;
++ Size = MAP_APPFONT ( 260 , 165 ) ;
++ Moveable = TRUE ;
++ Closeable = TRUE ;
++
++ OKButton BTN_OK
++ {
++ Pos = MAP_APPFONT ( 204, 6 ) ;
++ Size = MAP_APPFONT ( 50, 14 ) ;
++ DefButton = TRUE ;
++ };
++
++ CancelButton BTN_CANCEL
++ {
++ Pos = MAP_APPFONT ( 204, 23 ) ;
++ Size = MAP_APPFONT ( 50, 14 ) ;
++ };
++
++ HelpButton BTN_HELP
++ {
++ Pos = MAP_APPFONT ( 204, 43 ) ;
++ Size = MAP_APPFONT ( 50, 14 ) ;
++ };
++
++ FixedText FT_DESC
++ {
++ Pos = MAP_APPFONT ( 6, 6 ) ;
++ Size = MAP_APPFONT ( 190, 36 );
++
++ WordBreak = TRUE ;
++
++ Text [ en-US ] = "The document you are about to export has one or more protected items with an incompatible password hash. Please re-type your password to re-generate password hash that is compatible with the exported format." ;
++ };
++
++ FixedLine FL_DOCUMENT
++ {
++ Pos = MAP_APPFONT ( 6, 48 );
++ Size = MAP_APPFONT ( 190, 8 );
++
++ Text [ en-US ] = "Document protection" ;
++ };
++
++ FixedText FT_DOCSTATUS
++ {
++ Pos = MAP_APPFONT ( 10, 62 );
++ Size = MAP_APPFONT ( 140, 8 );
++
++ Text [ en-US ] = "Status unknown" ;
++ };
++
++ PushButton BTN_RETYPE_DOC
++ {
++ Pos = MAP_APPFONT ( 158, 59 );
++ Size = MAP_APPFONT ( 30, 14 );
++
++ Text [ en-US ] = "Re-type" ;
++ };
++
++ FixedLine FL_SHEET
++ {
++ Pos = MAP_APPFONT ( 6, 83 );
++ Size = MAP_APPFONT ( 190, 8 );
++
++ Text [ en-US ] = "Sheet protection" ;
++ };
++
++ FixedText FT_SHEETNAME1
++ {
++ Pos = MAP_APPFONT ( 10, 97 );
++ Size = MAP_APPFONT ( 68, 8 );
++
++ Text [ en-US ] = "Sheet1 has a really long name" ;
++ };
++
++ FixedText FT_SHEETSTATUS1
++ {
++ Pos = MAP_APPFONT ( 82, 97 );
++ Size = MAP_APPFONT ( 72, 8 );
++
++ Text [ en-US ] = "Status unknown" ;
++ };
++
++ PushButton BTN_RETYPE_SHEET1
++ {
++ Pos = MAP_APPFONT ( 158, 94 );
++ Size = MAP_APPFONT ( 30, 14 );
++
++ Text [ en-US ] = "Re-type" ;
++ };
++
++ FixedText FT_SHEETNAME2
++ {
++ Pos = MAP_APPFONT ( 10, 113 );
++ Size = MAP_APPFONT ( 68, 8 );
++
++ Text [ en-US ] = "Sheet2" ;
++ };
++
++ FixedText FT_SHEETSTATUS2
++ {
++ Pos = MAP_APPFONT ( 82, 113 );
++ Size = MAP_APPFONT ( 72, 8 );
++
++ Text [ en-US ] = "Status unknown" ;
++ };
++
++ PushButton BTN_RETYPE_SHEET2
++ {
++ Pos = MAP_APPFONT ( 158, 110 );
++ Size = MAP_APPFONT ( 30, 14 );
++
++ Text [ en-US ] = "Re-type" ;
++ };
++
++ FixedText FT_SHEETNAME3
++ {
++ Pos = MAP_APPFONT ( 10, 129 );
++ Size = MAP_APPFONT ( 68, 8 );
++
++ Text [ en-US ] = "Sheet3" ;
++ };
++
++ FixedText FT_SHEETSTATUS3
++ {
++ Pos = MAP_APPFONT ( 82, 129 );
++ Size = MAP_APPFONT ( 72, 8 );
++
++ Text [ en-US ] = "Status unknown" ;
++ };
++
++ PushButton BTN_RETYPE_SHEET3
++ {
++ Pos = MAP_APPFONT ( 158, 126 );
++ Size = MAP_APPFONT ( 30, 14 );
++
++ Text [ en-US ] = "Re-type" ;
++ };
++
++ FixedText FT_SHEETNAME4
++ {
++ Pos = MAP_APPFONT ( 10, 145 );
++ Size = MAP_APPFONT ( 68, 8 );
++
++ Text [ en-US ] = "Sheet4" ;
++ };
++
++ FixedText FT_SHEETSTATUS4
++ {
++ Pos = MAP_APPFONT ( 82, 145 );
++ Size = MAP_APPFONT ( 72, 8 );
++
++ Text [ en-US ] = "Status unknown" ;
++ };
++
++ PushButton BTN_RETYPE_SHEET4
++ {
++ Pos = MAP_APPFONT ( 158, 142 );
++ Size = MAP_APPFONT ( 30, 14 );
++
++ Text [ en-US ] = "Re-type" ;
++ };
++
++ ScrollBar SB_SCROLL
++ {
++ Pos = MAP_APPFONT ( 190, 94 ) ;
++ Size = MAP_APPFONT ( 8, 61 ) ;
++ VScroll = TRUE ;
++ };
++
++ String STR_NOT_PROTECTED
++ {
++ Text [ en-US ] = "Not protected" ;
++ };
++
++ String STR_NOT_PASS_PROTECTED
++ {
++ Text [ en-US ] = "Not password-protected" ;
++ };
++
++ String STR_HASH_BAD
++ {
++ Text [ en-US ] = "Hash incompatible" ;
++ };
++
++ String STR_HASH_GOOD
++ {
++ Text [ en-US ] = "Hash compatible" ;
++ };
++
++ String STR_HASH_REGENERATED
++ {
++ Text [ en-US ] = "Hash re-generated" ;
++ };
++};
++
++// ----------------------------------------------------------------------------
++
++ModalDialog RID_SCDLG_RETYPEPASS_INPUT
++{
++ Text [ en-US ] = "Re-type Password" ;
++ Size = MAP_APPFONT ( 230 , 110 ) ;
++ Moveable = TRUE ;
++ Closeable = TRUE ;
++
++ OKButton BTN_OK
++ {
++ Pos = MAP_APPFONT ( 174, 6 ) ;
++ Size = MAP_APPFONT ( 50, 14 ) ;
++ DefButton = TRUE ;
++ };
++
++ CancelButton BTN_CANCEL
++ {
++ Pos = MAP_APPFONT ( 174, 23 ) ;
++ Size = MAP_APPFONT ( 50, 14 ) ;
++ };
++
++ HelpButton BTN_HELP
++ {
++ Pos = MAP_APPFONT ( 174, 43 ) ;
++ Size = MAP_APPFONT ( 50, 14 ) ;
++ };
++
++ RadioButton BTN_RETYPE_PASSWORD
++ {
++ Pos = MAP_APPFONT ( 11, 10 );
++ Size = MAP_APPFONT ( 150, 10 );
++
++ Text [ en-US ] = "Re-type password" ;
++ };
++
++ FixedText FT_PASSWORD1
++ {
++ Pos = MAP_APPFONT ( 20, 30 );
++ Size = MAP_APPFONT ( 42, 10 );
++
++ Text [ en-US ] = "~Password" ;
++ };
++
++ Edit ED_PASSWORD1
++ {
++ Border = TRUE;
++ PassWord = TRUE;
++ Pos = MAP_APPFONT ( 65, 29 );
++ Size = MAP_APPFONT ( 75, 12 );
++ };
++
++ FixedText FT_PASSWORD2
++ {
++ Pos = MAP_APPFONT ( 20, 45 );
++ Size = MAP_APPFONT ( 42, 10 );
++
++ Text [ en-US ] = "~Confirm" ;
++ };
++
++ Edit ED_PASSWORD2
++ {
++ Border = TRUE;
++ PassWord = TRUE;
++ Pos = MAP_APPFONT ( 65, 44 );
++ Size = MAP_APPFONT ( 75, 12 );
++ };
++
++ CheckBox BTN_MATCH_OLD_PASSWORD
++ {
++ Pos = MAP_APPFONT ( 20, 65 );
++ Size = MAP_APPFONT ( 150, 10 );
++
++ Text [ en-US ] = "New password must match the original password." ;
++ };
++
++ RadioButton BTN_REMOVE_PASSWORD
++ {
++ Pos = MAP_APPFONT ( 11, 90 );
++ Size = MAP_APPFONT ( 150, 10 );
++
++ Text [ en-US ] = "Remove password from this protected item." ;
++ };
++};
++
++
+diff --git sc/source/ui/undo/undotab.cxx sc/source/ui/undo/undotab.cxx
+index ff50b1e..37210df 100644
+--- sc/source/ui/undo/undotab.cxx
++++ sc/source/ui/undo/undotab.cxx
+@@ -61,6 +61,7 @@
+ #include "prnsave.hxx"
+ #include "printfun.hxx"
+ #include "chgtrack.hxx"
++#include "tabprotection.hxx"
+
+ // for ScUndoRenameObject - might me moved to another file later
+ #include <svx/svditer.hxx>
+@@ -72,6 +73,8 @@
+ extern BOOL bDrawIsInUndo; //! irgendwo als Member !!!
+
+ using namespace com::sun::star;
++using ::com::sun::star::uno::Sequence;
++using ::std::auto_ptr;
+
+ // STATIC DATA -----------------------------------------------------------
+
+@@ -85,7 +88,6 @@ TYPEINIT1(ScUndoMakeScenario, SfxUndoAction);
+ TYPEINIT1(ScUndoImportTab, SfxUndoAction);
+ TYPEINIT1(ScUndoRemoveLink, SfxUndoAction);
+ TYPEINIT1(ScUndoShowHideTab, SfxUndoAction);
+-TYPEINIT1(ScUndoProtect, SfxUndoAction);
+ TYPEINIT1(ScUndoPrintRange, SfxUndoAction);
+ TYPEINIT1(ScUndoScenarioFlags, SfxUndoAction);
+ TYPEINIT1(ScUndoRenameObject, SfxUndoAction);
+@@ -112,12 +114,12 @@ ScUndoInsertTab::ScUndoInsertTab( ScDocShell* pNewDocShell,
+ SetChangeTrack();
+ }
+
+-__EXPORT ScUndoInsertTab::~ScUndoInsertTab()
++ScUndoInsertTab::~ScUndoInsertTab()
+ {
+ DeleteSdrUndoAction( pDrawUndo );
+ }
+
+-String __EXPORT ScUndoInsertTab::GetComment() const
++String ScUndoInsertTab::GetComment() const
+ {
+ if (bAppend)
+ return ScGlobal::GetRscString( STR_UNDO_APPEND_TAB );
+@@ -138,7 +140,7 @@ void ScUndoInsertTab::SetChangeTrack()
+ nEndChangeAction = 0;
+ }
+
+-void __EXPORT ScUndoInsertTab::Undo()
++void ScUndoInsertTab::Undo()
+ {
+ ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+ pViewShell->SetTabNo(nTab);
+@@ -159,7 +161,7 @@ void __EXPORT ScUndoInsertTab::Undo()
+ pDocShell->Broadcast( SfxSimpleHint( SC_HINT_FORCESETTAB ) );
+ }
+
+-void __EXPORT ScUndoInsertTab::Redo()
++void ScUndoInsertTab::Redo()
+ {
+ ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+
+@@ -180,14 +182,14 @@ void __EXPORT ScUndoInsertTab::Redo()
+ SetChangeTrack();
+ }
+
+-void __EXPORT ScUndoInsertTab::Repeat(SfxRepeatTarget& rTarget)
++void ScUndoInsertTab::Repeat(SfxRepeatTarget& rTarget)
+ {
+ if (rTarget.ISA(ScTabViewTarget))
+ ((ScTabViewTarget&)rTarget).GetViewShell()->GetViewData()->GetDispatcher().
+ Execute(FID_INS_TABLE, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD);
+ }
+
+-BOOL __EXPORT ScUndoInsertTab::CanRepeat(SfxRepeatTarget& rTarget) const
++BOOL ScUndoInsertTab::CanRepeat(SfxRepeatTarget& rTarget) const
+ {
+ return (rTarget.ISA(ScTabViewTarget));
+ }
+@@ -211,7 +213,7 @@ ScUndoInsertTables::ScUndoInsertTables( ScDocShell* pNewDocShell,
+ SetChangeTrack();
+ }
+
+-__EXPORT ScUndoInsertTables::~ScUndoInsertTables()
++ScUndoInsertTables::~ScUndoInsertTables()
+ {
+ String *pStr=NULL;
+ if(pNameList!=NULL)
+@@ -227,7 +229,7 @@ __EXPORT ScUndoInsertTables::~ScUndoInsertTables()
+ DeleteSdrUndoAction( pDrawUndo );
+ }
+
+-String __EXPORT ScUndoInsertTables::GetComment() const
++String ScUndoInsertTables::GetComment() const
+ {
+ return ScGlobal::GetRscString( STR_UNDO_INSERT_TAB );
+ }
+@@ -252,7 +254,7 @@ void ScUndoInsertTables::SetChangeTrack()
+ nStartChangeAction = nEndChangeAction = 0;
+ }
+
+-void __EXPORT ScUndoInsertTables::Undo()
++void ScUndoInsertTables::Undo()
+ {
+ ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+ pViewShell->SetTabNo(nTab);
+@@ -282,7 +284,7 @@ void __EXPORT ScUndoInsertTables::Undo()
+ pDocShell->Broadcast( SfxSimpleHint( SC_HINT_FORCESETTAB ) );
+ }
+
+-void __EXPORT ScUndoInsertTables::Redo()
++void ScUndoInsertTables::Redo()
+ {
+ ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+
+@@ -299,14 +301,14 @@ void __EXPORT ScUndoInsertTables::Redo()
+ SetChangeTrack();
+ }
+
+-void __EXPORT ScUndoInsertTables::Repeat(SfxRepeatTarget& rTarget)
++void ScUndoInsertTables::Repeat(SfxRepeatTarget& rTarget)
+ {
+ if (rTarget.ISA(ScTabViewTarget))
+ ((ScTabViewTarget&)rTarget).GetViewShell()->GetViewData()->GetDispatcher().
+ Execute(FID_INS_TABLE, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD);
+ }
+
+-BOOL __EXPORT ScUndoInsertTables::CanRepeat(SfxRepeatTarget& rTarget) const
++BOOL ScUndoInsertTables::CanRepeat(SfxRepeatTarget& rTarget) const
+ {
+ return (rTarget.ISA(ScTabViewTarget));
+ }
+@@ -327,12 +329,12 @@ ScUndoDeleteTab::ScUndoDeleteTab( ScDocShell* pNewDocShell,const SvShorts &aTab,
+ SetChangeTrack();
+ }
+
+-__EXPORT ScUndoDeleteTab::~ScUndoDeleteTab()
++ScUndoDeleteTab::~ScUndoDeleteTab()
+ {
+ theTabs.Remove(0,theTabs.Count());
+ }
+
+-String __EXPORT ScUndoDeleteTab::GetComment() const
++String ScUndoDeleteTab::GetComment() const
+ {
+ return ScGlobal::GetRscString( STR_UNDO_DELETE_TAB );
+ }
+@@ -366,7 +368,7 @@ SCTAB lcl_GetVisibleTabBefore( ScDocument& rDoc, SCTAB nTab )
+ return nTab;
+ }
+
+-void __EXPORT ScUndoDeleteTab::Undo()
++void ScUndoDeleteTab::Undo()
+ {
+ BeginUndo();
+ int i=0;
+@@ -414,7 +416,7 @@ void __EXPORT ScUndoDeleteTab::Undo()
+ pDoc->SetVisible( nTab, pRefUndoDoc->IsVisible( nTab ) );
+
+ if ( pRefUndoDoc->IsTabProtected( nTab ) )
+- pDoc->SetTabProtection( nTab, TRUE, pRefUndoDoc->GetTabPassword( nTab ) );
++ pDoc->SetTabProtection(nTab, pRefUndoDoc->GetTabProtection(nTab));
+
+ // Drawing-Layer passiert beim MoveUndo::EndUndo
+ // pDoc->TransferDrawPage(pRefUndoDoc, nTab,nTab);
+@@ -450,7 +452,7 @@ void __EXPORT ScUndoDeleteTab::Undo()
+ // EndUndo();
+ }
+
+-void __EXPORT ScUndoDeleteTab::Redo()
++void ScUndoDeleteTab::Redo()
+ {
+ ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+ pViewShell->SetTabNo( lcl_GetVisibleTabBefore( *pDocShell->GetDocument(), theTabs[0] ) );
+@@ -469,7 +471,7 @@ void __EXPORT ScUndoDeleteTab::Redo()
+ pDocShell->Broadcast( SfxSimpleHint( SC_HINT_FORCESETTAB ) );
+ }
+
+-void __EXPORT ScUndoDeleteTab::Repeat(SfxRepeatTarget& rTarget)
++void ScUndoDeleteTab::Repeat(SfxRepeatTarget& rTarget)
+ {
+ if (rTarget.ISA(ScTabViewTarget))
+ {
+@@ -478,7 +480,7 @@ void __EXPORT ScUndoDeleteTab::Repeat(SfxRepeatTarget& rTarget)
+ }
+ }
+
+-BOOL __EXPORT ScUndoDeleteTab::CanRepeat(SfxRepeatTarget& rTarget) const
++BOOL ScUndoDeleteTab::CanRepeat(SfxRepeatTarget& rTarget) const
+ {
+ return (rTarget.ISA(ScTabViewTarget));
+ }
+@@ -500,11 +502,11 @@ ScUndoRenameTab::ScUndoRenameTab( ScDocShell* pNewDocShell,
+ sNewName = rNewName;
+ }
+
+-__EXPORT ScUndoRenameTab::~ScUndoRenameTab()
++ScUndoRenameTab::~ScUndoRenameTab()
+ {
+ }
+
+-String __EXPORT ScUndoRenameTab::GetComment() const
++String ScUndoRenameTab::GetComment() const
+ {
+ return ScGlobal::GetRscString( STR_UNDO_RENAME_TAB );
+ }
+@@ -526,22 +528,22 @@ void ScUndoRenameTab::DoChange( SCTAB nTabP, const String& rName ) const
+ pViewShell->UpdateInputHandler();
+ }
+
+-void __EXPORT ScUndoRenameTab::Undo()
++void ScUndoRenameTab::Undo()
+ {
+ DoChange(nTab, sOldName);
+ }
+
+-void __EXPORT ScUndoRenameTab::Redo()
++void ScUndoRenameTab::Redo()
+ {
+ DoChange(nTab, sNewName);
+ }
+
+-void __EXPORT ScUndoRenameTab::Repeat(SfxRepeatTarget& /* rTarget */)
++void ScUndoRenameTab::Repeat(SfxRepeatTarget& /* rTarget */)
+ {
+ // Repeat macht keinen Sinn
+ }
+
+-BOOL __EXPORT ScUndoRenameTab::CanRepeat(SfxRepeatTarget& /* rTarget */) const
++BOOL ScUndoRenameTab::CanRepeat(SfxRepeatTarget& /* rTarget */) const
+ {
+ return FALSE;
+ }
+@@ -565,13 +567,13 @@ ScUndoMoveTab::ScUndoMoveTab( ScDocShell* pNewDocShell,
+ theNewTabs.Insert(aNewTab[sal::static_int_cast<USHORT>(i)],theNewTabs.Count());
+ }
+
+-__EXPORT ScUndoMoveTab::~ScUndoMoveTab()
++ScUndoMoveTab::~ScUndoMoveTab()
+ {
+ theNewTabs.Remove(0,theNewTabs.Count());
+ theOldTabs.Remove(0,theOldTabs.Count());
+ }
+
+-String __EXPORT ScUndoMoveTab::GetComment() const
++String ScUndoMoveTab::GetComment() const
+ {
+ return ScGlobal::GetRscString( STR_UNDO_MOVE_TAB );
+ }
+@@ -618,22 +620,22 @@ void ScUndoMoveTab::DoChange( BOOL bUndo ) const
+ pDocShell->PostDataChanged();
+ }
+
+-void __EXPORT ScUndoMoveTab::Undo()
++void ScUndoMoveTab::Undo()
+ {
+ DoChange( TRUE );
+ }
+
+-void __EXPORT ScUndoMoveTab::Redo()
++void ScUndoMoveTab::Redo()
+ {
+ DoChange( FALSE );
+ }
+
+-void __EXPORT ScUndoMoveTab::Repeat(SfxRepeatTarget& /* rTarget */)
++void ScUndoMoveTab::Repeat(SfxRepeatTarget& /* rTarget */)
+ {
+ // kein Repeat ! ? !
+ }
+
+-BOOL __EXPORT ScUndoMoveTab::CanRepeat(SfxRepeatTarget& /* rTarget */) const
++BOOL ScUndoMoveTab::CanRepeat(SfxRepeatTarget& /* rTarget */) const
+ {
+ return FALSE;
+ }
+@@ -660,12 +662,12 @@ ScUndoCopyTab::ScUndoCopyTab( ScDocShell* pNewDocShell,
+ theNewTabs.Insert(aNewTab[sal::static_int_cast<USHORT>(i)],theNewTabs.Count());
+ }
+
+-__EXPORT ScUndoCopyTab::~ScUndoCopyTab()
++ScUndoCopyTab::~ScUndoCopyTab()
+ {
+ DeleteSdrUndoAction( pDrawUndo );
+ }
+
+-String __EXPORT ScUndoCopyTab::GetComment() const
++String ScUndoCopyTab::GetComment() const
+ {
+ return ScGlobal::GetRscString( STR_UNDO_COPY_TAB );
+ }
+@@ -684,7 +686,7 @@ void ScUndoCopyTab::DoChange() const
+ pDocShell->PostDataChanged();
+ }
+
+-void __EXPORT ScUndoCopyTab::Undo()
++void ScUndoCopyTab::Undo()
+ {
+ ScDocument* pDoc = pDocShell->GetDocument();
+
+@@ -717,7 +719,7 @@ void __EXPORT ScUndoCopyTab::Undo()
+ DoChange();
+ }
+
+-void __EXPORT ScUndoCopyTab::Redo()
++void ScUndoCopyTab::Redo()
+ {
+ ScDocument* pDoc = pDocShell->GetDocument();
+ ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+@@ -756,7 +758,7 @@ void __EXPORT ScUndoCopyTab::Redo()
+ }
+
+ if ( pDoc->IsTabProtected( nAdjSource ) )
+- pDoc->SetTabProtection( nNewTab, TRUE, pDoc->GetTabPassword( nAdjSource ) );
++ pDoc->CopyTabProtection(nAdjSource, nNewTab);
+ }
+
+ RedoSdrUndoAction( pDrawUndo ); // after the sheets are inserted
+@@ -767,12 +769,12 @@ void __EXPORT ScUndoCopyTab::Redo()
+
+ }
+
+-void __EXPORT ScUndoCopyTab::Repeat(SfxRepeatTarget& /* rTarget */)
++void ScUndoCopyTab::Repeat(SfxRepeatTarget& /* rTarget */)
+ {
+ // kein Repeat ! ? !
+ }
+
+-BOOL __EXPORT ScUndoCopyTab::CanRepeat(SfxRepeatTarget& /* rTarget */) const
++BOOL ScUndoCopyTab::CanRepeat(SfxRepeatTarget& /* rTarget */) const
+ {
+ return FALSE;
+ }
+@@ -801,17 +803,17 @@ ScUndoMakeScenario::ScUndoMakeScenario( ScDocShell* pNewDocShell,
+ pDrawUndo = GetSdrUndoAction( pDocShell->GetDocument() );
+ }
+
+-__EXPORT ScUndoMakeScenario::~ScUndoMakeScenario()
++ScUndoMakeScenario::~ScUndoMakeScenario()
+ {
+ DeleteSdrUndoAction( pDrawUndo );
+ }
+
+-String __EXPORT ScUndoMakeScenario::GetComment() const
++String ScUndoMakeScenario::GetComment() const
+ {
+ return ScGlobal::GetRscString( STR_UNDO_MAKESCENARIO );
+ }
+
+-void __EXPORT ScUndoMakeScenario::Undo()
++void ScUndoMakeScenario::Undo()
+ {
+ ScDocument* pDoc = pDocShell->GetDocument();
+
+@@ -836,7 +838,7 @@ void __EXPORT ScUndoMakeScenario::Undo()
+ pDocShell->Broadcast( SfxSimpleHint( SC_HINT_FORCESETTAB ) );
+ }
+
+-void __EXPORT ScUndoMakeScenario::Redo()
++void ScUndoMakeScenario::Redo()
+ {
+ ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+ if (pViewShell)
+@@ -858,7 +860,7 @@ void __EXPORT ScUndoMakeScenario::Redo()
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
+ }
+
+-void __EXPORT ScUndoMakeScenario::Repeat(SfxRepeatTarget& rTarget)
++void ScUndoMakeScenario::Repeat(SfxRepeatTarget& rTarget)
+ {
+ if (rTarget.ISA(ScTabViewTarget))
+ {
+@@ -866,7 +868,7 @@ void __EXPORT ScUndoMakeScenario::Repeat(SfxRepeatTarget& rTarget)
+ }
+ }
+
+-BOOL __EXPORT ScUndoMakeScenario::CanRepeat(SfxRepeatTarget& rTarget) const
++BOOL ScUndoMakeScenario::CanRepeat(SfxRepeatTarget& rTarget) const
+ {
+ return (rTarget.ISA(ScTabViewTarget));
+ }
+@@ -889,13 +891,13 @@ ScUndoImportTab::ScUndoImportTab( ScDocShell* pShell,
+ pDrawUndo = GetSdrUndoAction( pDocShell->GetDocument() );
+ }
+
+-__EXPORT ScUndoImportTab::~ScUndoImportTab()
++ScUndoImportTab::~ScUndoImportTab()
+ {
+ delete pRedoDoc;
+ DeleteSdrUndoAction( pDrawUndo );
+ }
+
+-String __EXPORT ScUndoImportTab::GetComment() const
++String ScUndoImportTab::GetComment() const
+ {
+ return ScGlobal::GetRscString( STR_UNDO_INSERT_TAB );
+ }
+@@ -922,7 +924,7 @@ void ScUndoImportTab::DoChange() const
+ PAINT_GRID | PAINT_TOP | PAINT_LEFT | PAINT_EXTRAS );
+ }
+
+-void __EXPORT ScUndoImportTab::Undo()
++void ScUndoImportTab::Undo()
+ {
+ //! eingefuegte Bereichsnamen etc.
+
+@@ -958,7 +960,7 @@ void __EXPORT ScUndoImportTab::Undo()
+ }
+
+ if ( pDoc->IsTabProtected( nTabPos ) )
+- pRedoDoc->SetTabProtection( nTabPos, TRUE, pDoc->GetTabPassword( nTabPos ) );
++ pRedoDoc->SetTabProtection(nTabPos, pDoc->GetTabProtection(nTabPos));
+ }
+
+ }
+@@ -973,7 +975,7 @@ void __EXPORT ScUndoImportTab::Undo()
+ DoChange();
+ }
+
+-void __EXPORT ScUndoImportTab::Redo()
++void ScUndoImportTab::Redo()
+ {
+ if (!pRedoDoc)
+ {
+@@ -1012,7 +1014,7 @@ void __EXPORT ScUndoImportTab::Redo()
+ }
+
+ if ( pRedoDoc->IsTabProtected( nTabPos ) )
+- pDoc->SetTabProtection( nTabPos, TRUE, pRedoDoc->GetTabPassword( nTabPos ) );
++ pDoc->SetTabProtection(nTabPos, pRedoDoc->GetTabProtection(nTabPos));
+ }
+
+ RedoSdrUndoAction( pDrawUndo ); // after the sheets are inserted
+@@ -1020,14 +1022,14 @@ void __EXPORT ScUndoImportTab::Redo()
+ DoChange();
+ }
+
+-void __EXPORT ScUndoImportTab::Repeat(SfxRepeatTarget& rTarget)
++void ScUndoImportTab::Repeat(SfxRepeatTarget& rTarget)
+ {
+ if (rTarget.ISA(ScTabViewTarget))
+ ((ScTabViewTarget&)rTarget).GetViewShell()->GetViewData()->GetDispatcher().
+ Execute(FID_INS_TABLE, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD);
+ }
+
+-BOOL __EXPORT ScUndoImportTab::CanRepeat(SfxRepeatTarget& rTarget) const
++BOOL ScUndoImportTab::CanRepeat(SfxRepeatTarget& rTarget) const
+ {
+ return (rTarget.ISA(ScTabViewTarget));
+ }
+@@ -1075,14 +1077,14 @@ ScUndoRemoveLink::ScUndoRemoveLink( ScDocShell* pShell, const String& rDoc ) :
+ }
+ }
+
+-__EXPORT ScUndoRemoveLink::~ScUndoRemoveLink()
++ScUndoRemoveLink::~ScUndoRemoveLink()
+ {
+ delete pTabs;
+ delete pModes;
+ delete[] pTabNames;
+ }
+
+-String __EXPORT ScUndoRemoveLink::GetComment() const
++String ScUndoRemoveLink::GetComment() const
+ {
+ return ScGlobal::GetRscString( STR_UNDO_REMOVELINK );
+ }
+@@ -1099,22 +1101,22 @@ void ScUndoRemoveLink::DoChange( BOOL bLink ) const
+ pDocShell->UpdateLinks();
+ }
+
+-void __EXPORT ScUndoRemoveLink::Undo()
++void ScUndoRemoveLink::Undo()
+ {
+ DoChange( TRUE );
+ }
+
+-void __EXPORT ScUndoRemoveLink::Redo()
++void ScUndoRemoveLink::Redo()
+ {
+ DoChange( FALSE );
+ }
+
+-void __EXPORT ScUndoRemoveLink::Repeat(SfxRepeatTarget& /* rTarget */)
++void ScUndoRemoveLink::Repeat(SfxRepeatTarget& /* rTarget */)
+ {
+ // gippsnich
+ }
+
+-BOOL __EXPORT ScUndoRemoveLink::CanRepeat(SfxRepeatTarget& /* rTarget */) const
++BOOL ScUndoRemoveLink::CanRepeat(SfxRepeatTarget& /* rTarget */) const
+ {
+ return FALSE;
+ }
+@@ -1132,7 +1134,7 @@ ScUndoShowHideTab::ScUndoShowHideTab( ScDocShell* pShell, SCTAB nNewTab, BOOL bN
+ {
+ }
+
+-__EXPORT ScUndoShowHideTab::~ScUndoShowHideTab()
++ScUndoShowHideTab::~ScUndoShowHideTab()
+ {
+ }
+
+@@ -1149,17 +1151,17 @@ void ScUndoShowHideTab::DoChange( BOOL bShowP ) const
+ pDocShell->SetDocumentModified();
+ }
+
+-void __EXPORT ScUndoShowHideTab::Undo()
++void ScUndoShowHideTab::Undo()
+ {
+ DoChange(!bShow);
+ }
+
+-void __EXPORT ScUndoShowHideTab::Redo()
++void ScUndoShowHideTab::Redo()
+ {
+ DoChange(bShow);
+ }
+
+-void __EXPORT ScUndoShowHideTab::Repeat(SfxRepeatTarget& rTarget)
++void ScUndoShowHideTab::Repeat(SfxRepeatTarget& rTarget)
+ {
+ if (rTarget.ISA(ScTabViewTarget))
+ ((ScTabViewTarget&)rTarget).GetViewShell()->GetViewData()->GetDispatcher().
+@@ -1167,53 +1169,44 @@ void __EXPORT ScUndoShowHideTab::Repeat(SfxRepeatTarget& rTarget)
+ SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD);
+ }
+
+-BOOL __EXPORT ScUndoShowHideTab::CanRepeat(SfxRepeatTarget& rTarget) const
++BOOL ScUndoShowHideTab::CanRepeat(SfxRepeatTarget& rTarget) const
+ {
+ return (rTarget.ISA(ScTabViewTarget));
+ }
+
+-String __EXPORT ScUndoShowHideTab::GetComment() const
++String ScUndoShowHideTab::GetComment() const
+ {
+ USHORT nId = bShow ? STR_UNDO_SHOWTAB : STR_UNDO_HIDETAB;
+ return ScGlobal::GetRscString( nId );
+ }
+
+-// -----------------------------------------------------------------------
+-//
+-// Tabelle/Dokument schuetzen oder Schutz aufheben
+-//
++// ============================================================================
+
+-ScUndoProtect::ScUndoProtect( ScDocShell* pShell, SCTAB nNewTab,
+- BOOL bNewProtect, const uno::Sequence<sal_Int8>& rNewPassword ) :
+- ScSimpleUndo( pShell ),
+- nTab( nNewTab ),
+- bProtect( bNewProtect ),
+- aPassword( rNewPassword )
++ScUndoDocProtect::ScUndoDocProtect(ScDocShell* pShell, auto_ptr<ScDocProtection> pProtectSettings) :
++ ScSimpleUndo(pShell),
++ mpProtectSettings(pProtectSettings)
+ {
+ }
+
+-__EXPORT ScUndoProtect::~ScUndoProtect()
++ScUndoDocProtect::~ScUndoDocProtect()
+ {
+ }
+
+-void ScUndoProtect::DoProtect( BOOL bDo )
++void ScUndoDocProtect::DoProtect(bool bProtect)
+ {
+ ScDocument* pDoc = pDocShell->GetDocument();
+
+- if (bDo)
++ if (bProtect)
+ {
+- if ( nTab == TABLEID_DOC )
+- pDoc->SetDocProtection( TRUE, aPassword );
+- else
+- pDoc->SetTabProtection( nTab, TRUE, aPassword );
++ // set protection.
++ auto_ptr<ScDocProtection> pCopy(new ScDocProtection(*mpProtectSettings));
++ pCopy->setProtected(true);
++ pDoc->SetDocProtection(pCopy.get());
+ }
+ else
+ {
+- uno::Sequence<sal_Int8> aEmptyPass;
+- if ( nTab == TABLEID_DOC )
+- pDoc->SetDocProtection( FALSE, aEmptyPass );
+- else
+- pDoc->SetTabProtection( nTab, FALSE, aEmptyPass );
++ // remove protection.
++ pDoc->SetDocProtection(NULL);
+ }
+
+ ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
+@@ -1226,37 +1219,103 @@ void ScUndoProtect::DoProtect( BOOL bDo )
+ pDocShell->PostPaintGridAll();
+ }
+
+-void __EXPORT ScUndoProtect::Undo()
++void ScUndoDocProtect::Undo()
+ {
+ BeginUndo();
+- DoProtect( !bProtect );
++ DoProtect(!mpProtectSettings->isProtected());
+ EndUndo();
+ }
+
+-void __EXPORT ScUndoProtect::Redo()
++void ScUndoDocProtect::Redo()
+ {
+ BeginRedo();
+- DoProtect( bProtect );
++ DoProtect(mpProtectSettings->isProtected());
+ EndRedo();
+ }
+
+-void __EXPORT ScUndoProtect::Repeat(SfxRepeatTarget& /* rTarget */)
++void ScUndoDocProtect::Repeat(SfxRepeatTarget& /* rTarget */)
+ {
+ // gippsnich
+ }
+
+-BOOL __EXPORT ScUndoProtect::CanRepeat(SfxRepeatTarget& /* rTarget */) const
++BOOL ScUndoDocProtect::CanRepeat(SfxRepeatTarget& /* rTarget */) const
+ {
+ return FALSE; // gippsnich
+ }
+
+-String __EXPORT ScUndoProtect::GetComment() const
++String ScUndoDocProtect::GetComment() const
++{
++ USHORT nId = mpProtectSettings->isProtected() ? STR_UNDO_PROTECT_DOC : STR_UNDO_UNPROTECT_DOC;
++ return ScGlobal::GetRscString( nId );
++}
++
++// ============================================================================
++
++ScUndoTabProtect::ScUndoTabProtect(ScDocShell* pShell, SCTAB nTab, auto_ptr<ScTableProtection> pProtectSettings) :
++ ScSimpleUndo(pShell),
++ mnTab(nTab),
++ mpProtectSettings(pProtectSettings)
++{
++}
++
++ScUndoTabProtect::~ScUndoTabProtect()
+ {
+- USHORT nId;
+- if ( nTab == TABLEID_DOC )
+- nId = bProtect ? STR_UNDO_PROTECT_DOC : STR_UNDO_UNPROTECT_DOC;
++}
++
++void ScUndoTabProtect::DoProtect(bool bProtect)
++{
++ ScDocument* pDoc = pDocShell->GetDocument();
++
++ if (bProtect)
++ {
++ // set protection.
++ auto_ptr<ScTableProtection> pCopy(new ScTableProtection(*mpProtectSettings));
++ pCopy->setProtected(true);
++ pDoc->SetTabProtection(mnTab, pCopy.get());
++ }
+ else
+- nId = bProtect ? STR_UNDO_PROTECT_TAB : STR_UNDO_UNPROTECT_TAB;
++ {
++ // remove protection.
++ pDoc->SetTabProtection(mnTab, NULL);
++ }
++
++ ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
++ if (pViewShell)
++ {
++ pViewShell->UpdateLayerLocks();
++ pViewShell->UpdateInputHandler(TRUE); // damit sofort wieder eingegeben werden kann
++ }
++
++ pDocShell->PostPaintGridAll();
++}
++
++void ScUndoTabProtect::Undo()
++{
++ BeginUndo();
++ DoProtect(!mpProtectSettings->isProtected());
++ EndUndo();
++}
++
++void ScUndoTabProtect::Redo()
++{
++ BeginRedo();
++ DoProtect(mpProtectSettings->isProtected());
++ EndRedo();
++}
++
++void ScUndoTabProtect::Repeat(SfxRepeatTarget& /* rTarget */)
++{
++ // gippsnich
++}
++
++BOOL ScUndoTabProtect::CanRepeat(SfxRepeatTarget& /* rTarget */) const
++{
++ return FALSE; // gippsnich
++}
++
++String ScUndoTabProtect::GetComment() const
++{
++ USHORT nId = mpProtectSettings->isProtected() ? STR_UNDO_PROTECT_TAB : STR_UNDO_UNPROTECT_TAB;
+ return ScGlobal::GetRscString( nId );
+ }
+
+@@ -1274,7 +1333,7 @@ ScUndoPrintRange::ScUndoPrintRange( ScDocShell* pShell, SCTAB nNewTab,
+ {
+ }
+
+-__EXPORT ScUndoPrintRange::~ScUndoPrintRange()
++ScUndoPrintRange::~ScUndoPrintRange()
+ {
+ delete pOldRanges;
+ delete pNewRanges;
+@@ -1297,31 +1356,31 @@ void ScUndoPrintRange::DoChange(BOOL bUndo)
+ pDocShell->PostPaint( ScRange(0,0,nTab,MAXCOL,MAXROW,nTab), PAINT_GRID );
+ }
+
+-void __EXPORT ScUndoPrintRange::Undo()
++void ScUndoPrintRange::Undo()
+ {
+ BeginUndo();
+ DoChange( TRUE );
+ EndUndo();
+ }
+
+-void __EXPORT ScUndoPrintRange::Redo()
++void ScUndoPrintRange::Redo()
+ {
+ BeginRedo();
+ DoChange( FALSE );
+ EndRedo();
+ }
+
+-void __EXPORT ScUndoPrintRange::Repeat(SfxRepeatTarget& /* rTarget */)
++void ScUndoPrintRange::Repeat(SfxRepeatTarget& /* rTarget */)
+ {
+ // gippsnich
+ }
+
+-BOOL __EXPORT ScUndoPrintRange::CanRepeat(SfxRepeatTarget& /* rTarget */) const
++BOOL ScUndoPrintRange::CanRepeat(SfxRepeatTarget& /* rTarget */) const
+ {
+ return FALSE; // gippsnich
+ }
+
+-String __EXPORT ScUndoPrintRange::GetComment() const
++String ScUndoPrintRange::GetComment() const
+ {
+ return ScGlobal::GetRscString( STR_UNDO_PRINTRANGES );
+ }
+@@ -1350,16 +1409,16 @@ ScUndoScenarioFlags::ScUndoScenarioFlags( ScDocShell* pNewDocShell, SCTAB nT,
+ {
+ }
+
+-__EXPORT ScUndoScenarioFlags::~ScUndoScenarioFlags()
++ScUndoScenarioFlags::~ScUndoScenarioFlags()
+ {
+ }
+
+-String __EXPORT ScUndoScenarioFlags::GetComment() const
++String ScUndoScenarioFlags::GetComment() const
+ {
+ return ScGlobal::GetRscString( STR_UNDO_EDITSCENARIO );
+ }
+
+-void __EXPORT ScUndoScenarioFlags::Undo()
++void ScUndoScenarioFlags::Undo()
+ {
+ ScDocument* pDoc = pDocShell->GetDocument();
+
+@@ -1376,7 +1435,7 @@ void __EXPORT ScUndoScenarioFlags::Undo()
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
+ }
+
+-void __EXPORT ScUndoScenarioFlags::Redo()
++void ScUndoScenarioFlags::Redo()
+ {
+ ScDocument* pDoc = pDocShell->GetDocument();
+
+@@ -1393,12 +1452,12 @@ void __EXPORT ScUndoScenarioFlags::Redo()
+ SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
+ }
+
+-void __EXPORT ScUndoScenarioFlags::Repeat(SfxRepeatTarget& /* rTarget */)
++void ScUndoScenarioFlags::Repeat(SfxRepeatTarget& /* rTarget */)
+ {
+ // Repeat macht keinen Sinn
+ }
+
+-BOOL __EXPORT ScUndoScenarioFlags::CanRepeat(SfxRepeatTarget& /* rTarget */) const
++BOOL ScUndoScenarioFlags::CanRepeat(SfxRepeatTarget& /* rTarget */) const
+ {
+ return FALSE;
+ }
+@@ -1498,7 +1557,7 @@ ScUndoLayoutRTL::ScUndoLayoutRTL( ScDocShell* pShell, SCTAB nNewTab, BOOL bNewRT
+ {
+ }
+
+-__EXPORT ScUndoLayoutRTL::~ScUndoLayoutRTL()
++ScUndoLayoutRTL::~ScUndoLayoutRTL()
+ {
+ }
+
+@@ -1518,29 +1577,29 @@ void ScUndoLayoutRTL::DoChange( BOOL bNew )
+ pDocShell->SetInUndo( FALSE );
+ }
+
+-void __EXPORT ScUndoLayoutRTL::Undo()
++void ScUndoLayoutRTL::Undo()
+ {
+ DoChange(!bRTL);
+ }
+
+-void __EXPORT ScUndoLayoutRTL::Redo()
++void ScUndoLayoutRTL::Redo()
+ {
+ DoChange(bRTL);
+ }
+
+-void __EXPORT ScUndoLayoutRTL::Repeat(SfxRepeatTarget& rTarget)
++void ScUndoLayoutRTL::Repeat(SfxRepeatTarget& rTarget)
+ {
+ if (rTarget.ISA(ScTabViewTarget))
+ ((ScTabViewTarget&)rTarget).GetViewShell()->GetViewData()->GetDispatcher().
+ Execute( FID_TAB_RTL, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD);
+ }
+
+-BOOL __EXPORT ScUndoLayoutRTL::CanRepeat(SfxRepeatTarget& rTarget) const
++BOOL ScUndoLayoutRTL::CanRepeat(SfxRepeatTarget& rTarget) const
+ {
+ return (rTarget.ISA(ScTabViewTarget));
+ }
+
+-String __EXPORT ScUndoLayoutRTL::GetComment() const
++String ScUndoLayoutRTL::GetComment() const
+ {
+ return ScGlobal::GetRscString( STR_UNDO_TAB_RTL );
+ }
+@@ -1560,7 +1619,7 @@ ScUndoSetGrammar::ScUndoSetGrammar( ScDocShell* pShell,
+ meOldGrammar = pDocShell->GetDocument()->GetGrammar();
+ }
+
+-__EXPORT ScUndoSetGrammar::~ScUndoSetGrammar()
++ScUndoSetGrammar::~ScUndoSetGrammar()
+ {
+ }
+
+@@ -1573,17 +1632,17 @@ void ScUndoSetGrammar::DoChange( ScGrammar::Grammar eGrammar )
+ pDocShell->SetInUndo( FALSE );
+ }
+
+-void __EXPORT ScUndoSetGrammar::Undo()
++void ScUndoSetGrammar::Undo()
+ {
+ DoChange( meOldGrammar );
+ }
+
+-void __EXPORT ScUndoSetGrammar::Redo()
++void ScUndoSetGrammar::Redo()
+ {
+ DoChange( meNewGrammar );
+ }
+
+-void __EXPORT ScUndoSetGrammar::Repeat(SfxRepeatTarget& /* rTarget */)
++void ScUndoSetGrammar::Repeat(SfxRepeatTarget& /* rTarget */)
+ {
+ #if 0
+ // erAck: 2006-09-07T23:00+0200 commented out in CWS scr1c1
+@@ -1593,12 +1652,12 @@ void __EXPORT ScUndoSetGrammar::Repeat(SfxRepeatTarget& /* rTarget */)
+ #endif
+ }
+
+-BOOL __EXPORT ScUndoSetGrammar::CanRepeat(SfxRepeatTarget& rTarget) const
++BOOL ScUndoSetGrammar::CanRepeat(SfxRepeatTarget& rTarget) const
+ {
+ return (rTarget.ISA(ScTabViewTarget));
+ }
+
+-String __EXPORT ScUndoSetGrammar::GetComment() const
++String ScUndoSetGrammar::GetComment() const
+ {
+ return ScGlobal::GetRscString( STR_UNDO_TAB_R1C1 );
+ }
+diff --git sc/source/ui/unoobj/warnpassword.cxx sc/source/ui/unoobj/warnpassword.cxx
+index 78f355d..659e372 100644
+--- sc/source/ui/unoobj/warnpassword.cxx
++++ sc/source/ui/unoobj/warnpassword.cxx
+@@ -32,6 +32,9 @@
+ #include "precompiled_sc.hxx"
+
+ // ============================================================================
++
++#if 0
++
+ #include "warnpassword.hxx"
+ #include <com/sun/star/task/XInteractionHandler.hpp>
+ #include <com/sun/star/task/XInteractionRequest.hpp>
+@@ -95,3 +98,5 @@ bool ScWarnPassword::WarningOnPassword( SfxMedium& rMedium )
+ }
+ return bReturn;
+ }
++
++#endif
+diff --git sc/source/ui/view/gridwin.cxx sc/source/ui/view/gridwin.cxx
+index cb57c92..89228b5 100644
+--- sc/source/ui/view/gridwin.cxx
++++ sc/source/ui/view/gridwin.cxx
+@@ -140,6 +140,7 @@
+ #include "drwlayer.hxx"
+ #include "attrib.hxx"
+ #include "cellsh.hxx"
++#include "tabprotection.hxx"
+
+ // #114409#
+ #include <vcl/salbtype.hxx> // FRound
+@@ -2033,11 +2034,12 @@ void __EXPORT ScGridWindow::MouseButtonUp( const MouseEvent& rMEvt )
+ Point aPos = rMEvt.GetPosPixel();
+ SCsCOL nPosX;
+ SCsROW nPosY;
++ SCTAB nTab = pViewData->GetTabNo();
+ pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY );
+- ScDPObject* pDPObj = pDoc->GetDPAtCursor( nPosX, nPosY, pViewData->GetTabNo() );
++ ScDPObject* pDPObj = pDoc->GetDPAtCursor( nPosX, nPosY, nTab );
+ if ( pDPObj && pDPObj->GetSaveData()->GetDrillDown() )
+ {
+- ScAddress aCellPos( nPosX, nPosY, pViewData->GetTabNo() );
++ ScAddress aCellPos( nPosX, nPosY, nTab );
+
+ // Check for header drill-down first.
+ sheet::DataPilotTableHeaderData aData;
+@@ -2076,17 +2078,35 @@ void __EXPORT ScGridWindow::MouseButtonUp( const MouseEvent& rMEvt )
+ return;
+ }
+
+- // edit cell contents
+- pViewData->GetViewShell()->UpdateInputHandler();
+- pScMod->SetInputMode( SC_INPUT_TABLE );
+- if (pViewData->HasEditView(eWhich))
+- {
+- // Text-Cursor gleich an die geklickte Stelle setzen
+- EditView* pEditView = pViewData->GetEditView( eWhich );
+- MouseEvent aEditEvt( rMEvt.GetPosPixel(), 1, MOUSE_SYNTHETIC, MOUSE_LEFT, 0 );
+- pEditView->MouseButtonDown( aEditEvt );
+- pEditView->MouseButtonUp( aEditEvt );
+- }
++ // Check for cell protection attribute.
++ ScTableProtection* pProtect = pDoc->GetTabProtection( nTab );
++ bool bEditAllowed = true;
++ if ( pProtect && pProtect->isProtected() )
++ {
++ bool bCellProtected = pDoc->HasAttrib(nPosX, nPosY, nTab, nPosX, nPosY, nTab, HASATTR_PROTECTED);
++ bool bSkipProtected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
++ bool bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
++
++ if ( bSkipProtected && bSkipUnprotected )
++ bEditAllowed = false;
++ else if ( (bCellProtected && bSkipProtected) || (!bCellProtected && bSkipUnprotected) )
++ bEditAllowed = false;
++ }
++
++ if ( bEditAllowed )
++ {
++ // edit cell contents
++ pViewData->GetViewShell()->UpdateInputHandler();
++ pScMod->SetInputMode( SC_INPUT_TABLE );
++ if (pViewData->HasEditView(eWhich))
++ {
++ // Text-Cursor gleich an die geklickte Stelle setzen
++ EditView* pEditView = pViewData->GetEditView( eWhich );
++ MouseEvent aEditEvt( rMEvt.GetPosPixel(), 1, MOUSE_SYNTHETIC, MOUSE_LEFT, 0 );
++ pEditView->MouseButtonDown( aEditEvt );
++ pEditView->MouseButtonUp( aEditEvt );
++ }
++ }
+ return;
+ }
+
+diff --git sc/source/ui/view/scextopt.cxx sc/source/ui/view/scextopt.cxx
+index 8ac6382..586f934 100644
+--- sc/source/ui/view/scextopt.cxx
++++ sc/source/ui/view/scextopt.cxx
+@@ -42,9 +42,7 @@ ScExtDocSettings::ScExtDocSettings() :
+ maOleSize( ScAddress::INITIALIZE_INVALID ),
+ mfTabBarWidth( -1.0 ),
+ mnLinkCnt( 0 ),
+- mnDisplTab( 0 ),
+- mbWinProtected( false ),
+- mbEncrypted( false )
++ mnDisplTab( 0 )
+ {
+ }
+
+diff --git sc/source/ui/view/select.cxx sc/source/ui/view/select.cxx
+index 9d4cdfd..d5e2257 100644
+--- sc/source/ui/view/select.cxx
++++ sc/source/ui/view/select.cxx
+@@ -47,6 +47,7 @@
+ //#include "dataobj.hxx"
+ #include "transobj.hxx"
+ #include "docsh.hxx"
++#include "tabprotection.hxx"
+
+ extern USHORT nScFillModeMouseModifier; // global.cxx
+
+@@ -322,6 +323,26 @@ BOOL ScViewFunctionSet::SetCursorAtCell( SCsCOL nPosX, SCsROW nPosY, BOOL bScrol
+ {
+ ScTabView* pView = pViewData->GetView();
+ SCTAB nTab = pViewData->GetTabNo();
++ ScDocument* pDoc = pViewData->GetDocument();
++
++ if ( pDoc->IsTabProtected(nTab) )
++ {
++ if (nPosX < 0 || nPosY < 0)
++ return false;
++
++ ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
++ bool bSkipProtected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
++ bool bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
++
++ if ( bSkipProtected && bSkipUnprotected )
++ return FALSE;
++
++ bool bCellProtected = pDoc->HasAttrib(nPosX, nPosY, nTab, nPosX, nPosY, nTab, HASATTR_PROTECTED);
++ if ( (bCellProtected && bSkipProtected) || (!bCellProtected && bSkipUnprotected) )
++ // Don't select this cell!
++ return FALSE;
++ }
++
+ ScModule* pScMod = SC_MOD();
+ BOOL bRefMode = pScMod->IsFormulaMode();
+
+@@ -374,7 +395,6 @@ BOOL ScViewFunctionSet::SetCursorAtCell( SCsCOL nPosX, SCsROW nPosY, BOOL bScrol
+
+ ScRange aDelRange;
+ BOOL bOldDelMark = pViewData->GetDelMark( aDelRange );
+- ScDocument* pDoc = pViewData->GetDocument();
+
+ if ( nPosX+1 >= (SCsCOL) nStartX && nPosX <= (SCsCOL) nEndX &&
+ nPosY+1 >= (SCsROW) nStartY && nPosY <= (SCsROW) nEndY &&
+@@ -510,7 +530,6 @@ BOOL ScViewFunctionSet::SetCursorAtCell( SCsCOL nPosX, SCsROW nPosY, BOOL bScrol
+ BYTE nMode = pViewData->GetFillMode();
+ if ( nMode == SC_FILL_EMBED_LT || nMode == SC_FILL_EMBED_RB )
+ {
+- ScDocument* pDoc = pViewData->GetDocument();
+ DBG_ASSERT( pDoc->IsEmbedded(), "!pDoc->IsEmbedded()" );
+ ScRange aRange;
+ pDoc->GetEmbedded( aRange);
+diff --git sc/source/ui/view/tabview3.cxx sc/source/ui/view/tabview3.cxx
+index dff3854..187adb5 100644
+--- sc/source/ui/view/tabview3.cxx
++++ sc/source/ui/view/tabview3.cxx
+@@ -68,6 +68,7 @@
+ #include "inputopt.hxx"
+ #include "rfindlst.hxx"
+ #include "hiranges.hxx"
++#include "tabprotection.hxx"
+ #include "viewuno.hxx"
+ #include "chartarr.hxx"
+ #include "anyrefdg.hxx"
+@@ -1020,6 +1021,17 @@ void ScTabView::MoveCursorRel( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode,
+ ScDocument* pDoc = aViewData.GetDocument();
+ SCTAB nTab = aViewData.GetTabNo();
+
++ bool bSkipProtected = false, bSkipUnprotected = false;
++ ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
++ if ( pProtect && pProtect->isProtected() )
++ {
++ bSkipProtected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
++ bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
++ }
++
++ if ( bSkipProtected && bSkipUnprotected )
++ return;
++
+ SCsCOL nOldX;
+ SCsROW nOldY;
+ SCsCOL nCurX;
+@@ -1039,7 +1051,7 @@ void ScTabView::MoveCursorRel( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode,
+ nCurY = (nMovY != 0) ? nOldY+nMovY : (SCsROW) aViewData.GetOldCurY();
+ }
+
+- BOOL bHidden;
++ BOOL bSkipCell = FALSE;
+ aViewData.ResetOldCursor();
+
+ if (nMovX != 0 && VALIDCOLROW(nCurX,nCurY))
+@@ -1048,15 +1060,20 @@ void ScTabView::MoveCursorRel( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode,
+ do
+ {
+ BYTE nColFlags = pDoc->GetColFlags( nCurX, nTab );
+- bHidden = (nColFlags & CR_HIDDEN) || pDoc->IsHorOverlapped( nCurX, nCurY, nTab );
+- if (bHidden)
++ bSkipCell = (nColFlags & CR_HIDDEN) || pDoc->IsHorOverlapped( nCurX, nCurY, nTab );
++ if (bSkipProtected && !bSkipCell)
++ bSkipCell = pDoc->HasAttrib(nCurX, nCurY, nTab, nCurX, nCurY, nTab, HASATTR_PROTECTED);
++ if (bSkipUnprotected && !bSkipCell)
++ bSkipCell = !pDoc->HasAttrib(nCurX, nCurY, nTab, nCurX, nCurY, nTab, HASATTR_PROTECTED);
++
++ if (bSkipCell)
+ {
+ if ( nCurX<=0 || nCurX>=MAXCOL )
+ {
+ if (bHFlip)
+ {
+ nCurX = nOldX;
+- bHidden = FALSE;
++ bSkipCell = FALSE;
+ }
+ else
+ {
+@@ -1069,7 +1086,8 @@ void ScTabView::MoveCursorRel( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode,
+ if (nMovX > 0) ++nCurX; else --nCurX;
+ }
+ }
+- while (bHidden);
++ while (bSkipCell);
++
+ if (pDoc->IsVerOverlapped( nCurX, nCurY, nTab ))
+ {
+ aViewData.SetOldCursor( nCurX,nCurY );
+@@ -1084,15 +1102,20 @@ void ScTabView::MoveCursorRel( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode,
+ do
+ {
+ BYTE nRowFlags = pDoc->GetRowFlags( nCurY, nTab );
+- bHidden = (nRowFlags & CR_HIDDEN) || pDoc->IsVerOverlapped( nCurX, nCurY, nTab );
+- if (bHidden)
++ bSkipCell = (nRowFlags & CR_HIDDEN) || pDoc->IsVerOverlapped( nCurX, nCurY, nTab );
++ if (bSkipProtected && !bSkipCell)
++ bSkipCell = pDoc->HasAttrib(nCurX, nCurY, nTab, nCurX, nCurY, nTab, HASATTR_PROTECTED);
++ if (bSkipUnprotected && !bSkipCell)
++ bSkipCell = !pDoc->HasAttrib(nCurX, nCurY, nTab, nCurX, nCurY, nTab, HASATTR_PROTECTED);
++
++ if (bSkipCell)
+ {
+ if ( nCurY<=0 || nCurY>=MAXROW )
+ {
+ if (bVFlip)
+ {
+ nCurY = nOldY;
+- bHidden = FALSE;
++ bSkipCell = FALSE;
+ }
+ else
+ {
+@@ -1105,7 +1128,8 @@ void ScTabView::MoveCursorRel( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode,
+ if (nMovY > 0) ++nCurY; else --nCurY;
+ }
+ }
+- while (bHidden);
++ while (bSkipCell);
++
+ if (pDoc->IsHorOverlapped( nCurX, nCurY, nTab ))
+ {
+ aViewData.SetOldCursor( nCurX,nCurY );
+diff --git sc/source/ui/view/tabvwsh3.cxx sc/source/ui/view/tabvwsh3.cxx
+index acfbb36..1f0743f 100644
+--- sc/source/ui/view/tabvwsh3.cxx
++++ sc/source/ui/view/tabvwsh3.cxx
+@@ -75,6 +75,8 @@
+ #include "autofmt.hxx"
+ #include "dwfunctr.hxx"
+ #include "shtabdlg.hxx"
++#include "tabprotection.hxx"
++#include "protectiondlg.hxx"
+
+ #include <svtools/ilstitem.hxx>
+ #define _SVSTDARR_ULONGS
+@@ -84,6 +86,10 @@
+ #include <svx/dialogs.hrc> //CHINA001
+ #include "scabstdlg.hxx" //CHINA001
+
++#include <memory>
++
++using ::std::auto_ptr;
++
+ #define IS_EDITMODE() GetViewData()->HasEditView( GetViewData()->GetActivePart() )
+ #define IS_AVAILABLE(WhichId,ppItem) \
+ (pReqArgs->GetItemState((WhichId), TRUE, ppItem ) == SFX_ITEM_SET)
+@@ -972,12 +978,13 @@ void ScTabViewShell::Execute( SfxRequest& rReq )
+ }
+ }
+
+- if (pDoc->IsDocProtected())
++ ScDocProtection* pProtect = pDoc->GetDocProtection();
++ if (pProtect && pProtect->isProtected())
+ {
+ BOOL bCancel = FALSE;
+ String aPassword;
+
+- if (pDoc->GetDocPassword().getLength())
++ if (pProtect->isProtectedWithPass())
+ {
+ String aText( ScResId(SCSTR_PASSWORD) );
+
+@@ -1027,89 +1034,84 @@ void ScTabViewShell::Execute( SfxRequest& rReq )
+
+
+ case FID_PROTECT_TABLE:
+- {
+- ScDocument* pDoc = GetViewData()->GetDocument();
+- SCTAB nTab = GetViewData()->GetTabNo();
+- SfxPasswordDialog* pDlg;
+- String aPassword;
+- BOOL bCancel = FALSE;
+- BOOL bOldProtection = pDoc->IsTabProtected(nTab);
+- BOOL bNewProtection = ! bOldProtection;
++ {
++ ScDocument* pDoc = GetViewData()->GetDocument();
++ SCTAB nTab = GetViewData()->GetTabNo();
++ bool bOldProtection = pDoc->IsTabProtected(nTab);
+
+- if( pReqArgs )
+- {
+- const SfxPoolItem* pItem;
+- if( IS_AVAILABLE( FID_PROTECT_TABLE, &pItem ) )
+- bNewProtection = ((const SfxBoolItem*)pItem)->GetValue();
+- if( bNewProtection == bOldProtection )
+- {
+- rReq.Ignore();
+- break;
+- }
++ if( pReqArgs )
++ {
++ const SfxPoolItem* pItem;
++ bool bNewProtection = !bOldProtection;
++ if( IS_AVAILABLE( FID_PROTECT_TABLE, &pItem ) )
++ bNewProtection = ((const SfxBoolItem*)pItem)->GetValue();
++ if( bNewProtection == bOldProtection )
++ {
++ rReq.Ignore();
++ break;
+ }
++ }
++
++ if (bOldProtection)
++ {
++ // Unprotect a protected sheet.
+
+- if ( bOldProtection)
++ ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
++ if (pProtect && pProtect->isProtectedWithPass())
++ {
++ String aText( ScResId(SCSTR_PASSWORDOPT) );
++ auto_ptr<SfxPasswordDialog> pDlg(new SfxPasswordDialog(GetDialogParent(), &aText));
++ pDlg->SetText( ScResId(SCSTR_UNPROTECTTAB) );
++ pDlg->SetMinLen( 0 );
++ pDlg->SetHelpId( FID_PROTECT_TABLE );
++ pDlg->SetEditHelpId( HID_PASSWD_TABLE );
++
++ if (pDlg->Execute() == RET_OK)
+ {
+- if (pDoc->GetTabPassword(nTab).getLength())
+- {
+- String aText( ScResId(SCSTR_PASSWORD) );
+-
+- pDlg = new SfxPasswordDialog( GetDialogParent(), &aText );
+- pDlg->SetText( ScResId(SCSTR_UNPROTECTTAB) );
+- pDlg->SetMinLen( 0 );
+- pDlg->SetHelpId( FID_PROTECT_TABLE );
+- pDlg->SetEditHelpId( HID_PASSWD_TABLE );
+-
+- if (pDlg->Execute() == RET_OK)
+- aPassword = pDlg->GetPassword();
+- else
+- bCancel = TRUE;
+-
+- delete pDlg;
+- }
++ String aPassword = pDlg->GetPassword();
++ Unprotect(nTab, aPassword);
+ }
+- else
+- {
+- String aText( ScResId(SCSTR_PASSWORDOPT) );
++ }
++ else
++ // this sheet is not password-protected.
++ Unprotect(nTab, String());
++
++ if (!pReqArgs)
++ {
++ rReq.AppendItem( SfxBoolItem(FID_PROTECT_TABLE, false) );
++ rReq.Done();
++ }
++ }
++ else
++ {
++ // Protect a current sheet.
+
+- pDlg = new SfxPasswordDialog( GetDialogParent(), &aText );
+- pDlg->SetText( ScResId(SCSTR_PROTECTTAB) );
+- pDlg->SetMinLen( 0 );
+- pDlg->SetHelpId( FID_PROTECT_TABLE );
+- pDlg->SetEditHelpId( HID_PASSWD_TABLE );
+- pDlg->ShowExtras( SHOWEXTRAS_CONFIRM );
++ auto_ptr<ScTableProtectionDlg> pDlg(new ScTableProtectionDlg(GetDialogParent()));
+
+- if (pDlg->Execute() == RET_OK)
+- aPassword = pDlg->GetPassword();
+- else
+- bCancel = TRUE;
++ ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
++ if (pProtect)
++ pDlg->SetDialogData(*pProtect);
+
+- delete pDlg;
+- }
++ if (pDlg->Execute() == RET_OK)
++ {
++ pScMod->InputEnterHandler();
+
+- if( !bCancel )
+- {
+- if ( bOldProtection )
+- Unprotect( nTab, aPassword );
+- else
++ ScTableProtection aNewProtect;
++ pDlg->WriteData(aNewProtect);
++ ProtectSheet(nTab, aNewProtect);
++ if (!pReqArgs)
+ {
+- pScMod->InputEnterHandler();
+-
+- Protect( nTab, aPassword );
++ rReq.AppendItem( SfxBoolItem(FID_PROTECT_TABLE, true) );
++ rReq.Done();
+ }
++ }
++ }
+
+- if( !pReqArgs )
+- {
+- rReq.AppendItem( SfxBoolItem( FID_PROTECT_TABLE, bNewProtection ) );
+- rReq.Done();
+- }
+- }
+-
+- TabChanged();
+- UpdateInputHandler(TRUE); // damit sofort wieder eingegeben werden kann
+- SelectionChanged();
+- }
+- break;
++ TabChanged();
++ UpdateInputHandler(true); // damit sofort wieder eingegeben werden kann
++ SelectionChanged();
++ }
++ break;
+
+ case SID_OPT_LOCALE_CHANGED :
+ { // locale changed, SYSTEM number formats changed => repaint cell contents
+diff --git sc/source/ui/view/tabvwshh.cxx sc/source/ui/view/tabvwshh.cxx
+index fb9408b..52c8fc4 100644
+--- sc/source/ui/view/tabvwshh.cxx
++++ sc/source/ui/view/tabvwshh.cxx
+@@ -43,6 +43,7 @@
+ #include <sfx2/request.hxx>
+ #include <basic/sbxcore.hxx>
+ #include <svtools/whiter.hxx>
++#include <vcl/msgbox.hxx>
+
+ #include "tabvwsh.hxx"
+ #include "client.hxx"
+@@ -50,6 +51,10 @@
+ #include "docsh.hxx"
+ #include "sc.hrc"
+ #include "drwlayer.hxx" // GetVisibleName
++#include "retypepassdlg.hxx"
++#include "tabprotection.hxx"
++
++#include <memory>
+
+ using namespace com::sun::star;
+
+@@ -270,6 +275,22 @@ BOOL ScTabViewShell::HasAccessibilityObjects()
+ return pAccessibilityBroadcaster != NULL;
+ }
+
++bool ScTabViewShell::ExecuteRetypePassDlg(ScPasswordHash eDesiredHash)
++{
++ using ::std::auto_ptr;
++
++ ScDocument* pDoc = GetViewData()->GetDocument();
++
++ auto_ptr<ScRetypePassDlg> pDlg(new ScRetypePassDlg(GetDialogParent()));
++ pDlg->SetData(*pDoc);
++ pDlg->SetDesiredHash(eDesiredHash);
++ if (pDlg->Execute() != RET_OK)
++ return false;
++
++ pDlg->WriteNewDataToDocument(*pDoc);
++ return true;
++}
++
+
+
+
+diff --git sc/source/ui/view/viewfun2.cxx sc/source/ui/view/viewfun2.cxx
+index 9a216b4..1970245 100644
+--- sc/source/ui/view/viewfun2.cxx
++++ sc/source/ui/view/viewfun2.cxx
+@@ -2150,7 +2150,7 @@ BOOL ScViewFunc::DeleteTables(const SvShorts &TheTabs, BOOL bRecord )
+ pUndoDoc->SetVisible( nTab, pDoc->IsVisible( nTab ) );
+
+ if ( pDoc->IsTabProtected( nTab ) )
+- pUndoDoc->SetTabProtection( nTab, TRUE, pDoc->GetTabPassword( nTab ) );
++ pUndoDoc->SetTabProtection(nTab, pDoc->GetTabProtection(nTab));
+
+ // Drawing-Layer muss sein Undo selbst in der Hand behalten !!!
+ // pUndoDoc->TransferDrawPage(pDoc, nTab,nTab);
+@@ -2565,7 +2565,7 @@ void ScViewFunc::MoveTable( USHORT nDestDocNo, SCTAB nDestTab, BOOL bCopy )
+ }
+
+ if ( nErrVal > 0 && pDoc->IsTabProtected( TheTabs[i] ) )
+- pDestDoc->SetTabProtection( nDestTab1, TRUE, pDoc->GetTabPassword( TheTabs[i] ) );
++ pDestDoc->SetTabProtection(nDestTab1, pDoc->GetTabProtection(TheTabs[i]));
+
+ nDestTab1++;
+ }
+diff --git sc/source/ui/view/viewfunc.cxx sc/source/ui/view/viewfunc.cxx
+index d0362e5..666b939 100644
+--- sc/source/ui/view/viewfunc.cxx
++++ sc/source/ui/view/viewfunc.cxx
+@@ -2396,6 +2396,36 @@ void ScViewFunc::ModifyCellSize( ScDirection eDir, BOOL bOptimal )
+ ShowAllCursors();
+ }
+
++void ScViewFunc::ProtectSheet( SCTAB nTab, const ScTableProtection& rProtect )
++{
++ if (nTab == TABLEID_DOC)
++ return;
++
++ ScMarkData& rMark = GetViewData()->GetMarkData();
++ ScDocShell* pDocSh = GetViewData()->GetDocShell();
++ ScDocument* pDoc = pDocSh->GetDocument();
++ ScDocFunc aFunc(*pDocSh);
++ bool bUndo(pDoc->IsUndoEnabled());
++
++ // modifying several tables is handled here
++
++ if (bUndo)
++ {
++ String aUndo = ScGlobal::GetRscString( STR_UNDO_PROTECT_TAB );
++ pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
++ }
++
++ SCTAB nCount = pDocSh->GetDocument()->GetTableCount();
++ for ( SCTAB i=0; i<nCount; i++ )
++ if ( rMark.GetTableSelect(i) )
++ aFunc.ProtectSheet(i, rProtect);
++
++ if (bUndo)
++ pDocSh->GetUndoManager()->LeaveListAction();
++
++ UpdateLayerLocks(); //! broadcast to all views
++}
++
+ void ScViewFunc::Protect( SCTAB nTab, const String& rPassword )
+ {
+ ScMarkData& rMark = GetViewData()->GetMarkData();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]