[ooo-build-commit] Branch 'ooo/master' - sc/inc sc/source

Jan Holesovsky kendy at kemper.freedesktop.org
Wed Jul 1 17:16:01 PDT 2009


 sc/inc/document.hxx                          |   17 
 sc/inc/sc.hrc                                |    7 
 sc/inc/scextopt.hxx                          |    2 
 sc/inc/table.hxx                             |   13 
 sc/inc/tabprotection.hxx                     |  180 ++++++++
 sc/source/core/data/documen2.cxx             |    3 
 sc/source/core/data/documen3.cxx             |   44 +-
 sc/source/core/data/document.cxx             |   19 
 sc/source/core/data/makefile.mk              |    2 
 sc/source/core/data/table1.cxx               |    3 
 sc/source/core/data/table2.cxx               |   12 
 sc/source/core/data/table5.cxx               |   21 +
 sc/source/core/data/tabprotection.cxx        |  465 ++++++++++++++++++++++
 sc/source/filter/excel/excdoc.cxx            |   65 ++-
 sc/source/filter/excel/excimp8.cxx           |   13 
 sc/source/filter/excel/excrecds.cxx          |   31 +
 sc/source/filter/excel/impop.cxx             |   48 +-
 sc/source/filter/excel/read.cxx              |   11 
 sc/source/filter/excel/xeroot.cxx            |   44 ++
 sc/source/filter/excel/xestream.cxx          |  323 +++++++++++++++
 sc/source/filter/excel/xicontent.cxx         |  192 +++++++++
 sc/source/filter/excel/xilink.cxx            |    1 
 sc/source/filter/excel/xiroot.cxx            |   26 +
 sc/source/filter/excel/xistream.cxx          |   17 
 sc/source/filter/excel/xlroot.cxx            |   14 
 sc/source/filter/inc/excimp8.hxx             |    2 
 sc/source/filter/inc/excrecds.hxx            |   17 
 sc/source/filter/inc/imp_op.hxx              |    6 
 sc/source/filter/inc/xcl97rec.hxx            |  196 ++++++++-
 sc/source/filter/inc/xeroot.hxx              |    5 
 sc/source/filter/inc/xestream.hxx            |  114 ++---
 sc/source/filter/inc/xetable.hxx             |    2 
 sc/source/filter/inc/xicontent.hxx           |   61 +++
 sc/source/filter/inc/xiroot.hxx              |   16 
 sc/source/filter/inc/xistream.hxx            |    5 
 sc/source/filter/inc/xlroot.hxx              |    4 
 sc/source/filter/starcalc/scflt.cxx          |   16 
 sc/source/filter/xcl97/XclExpChangeTrack.cxx |    1 
 sc/source/filter/xcl97/makefile.mk           |    1 
 sc/source/filter/xcl97/xcl97rec.cxx          |  358 +++++++++++++++--
 sc/source/filter/xml/xmlbodyi.cxx            |   13 
 sc/source/filter/xml/xmlexprt.cxx            |   13 
 sc/source/filter/xml/xmlsubti.cxx            |   16 
 sc/source/ui/docshell/docfunc.cxx            |  194 ++++++---
 sc/source/ui/docshell/docsh.cxx              |   54 ++
 sc/source/ui/docshell/docsh5.cxx             |    2 
 sc/source/ui/inc/docfunc.hxx                 |    4 
 sc/source/ui/inc/protectiondlg.hrc           |   47 ++
 sc/source/ui/inc/protectiondlg.hxx           |   85 ++++
 sc/source/ui/inc/retypepassdlg.hrc           |   74 +++
 sc/source/ui/inc/retypepassdlg.hxx           |  177 ++++++++
 sc/source/ui/inc/tabvwsh.hxx                 |    3 
 sc/source/ui/inc/undotab.hxx                 |   46 +-
 sc/source/ui/inc/viewfunc.hxx                |    3 
 sc/source/ui/miscdlgs/makefile.mk            |   16 
 sc/source/ui/miscdlgs/protectiondlg.cxx      |  164 ++++++++
 sc/source/ui/miscdlgs/protectiondlg.src      |  130 ++++++
 sc/source/ui/miscdlgs/retypepassdlg.cxx      |  547 +++++++++++++++++++++++++++
 sc/source/ui/miscdlgs/retypepassdlg.src      |  316 +++++++++++++++
 sc/source/ui/undo/undotab.cxx                |  309 +++++++++------
 sc/source/ui/unoobj/warnpassword.cxx         |    1 
 sc/source/ui/view/gridwin.cxx                |   40 +
 sc/source/ui/view/scextopt.cxx               |    4 
 sc/source/ui/view/select.cxx                 |   23 +
 sc/source/ui/view/tabview3.cxx               |   42 +-
 sc/source/ui/view/tabvwsh3.cxx               |  212 +++++++---
 sc/source/ui/view/tabvwshh.cxx               |   21 +
 sc/source/ui/view/viewfun2.cxx               |    4 
 sc/source/ui/view/viewfunc.cxx               |   30 +
 69 files changed, 4380 insertions(+), 587 deletions(-)

New commits:
commit 0671b11c48b86b03b235751695bf6e05a18505d1
Author: Release Engineers <releng at openoffice.org>
Date:   Wed Jul 1 08:58:41 2009 +0000

    CWS-TOOLING: integrate CWS scsheetprotection02
    2009-06-18 16:48:14 +0200 kohei  r273124 : #i102906# Fix a crasher when loading an xls document with unsupported
    encrytpion.
    2009-06-15 14:02:00 +0200 dr  r272982 : #i10000# compiler warnings
    2009-04-13 23:06:21 +0200 kohei  r270740 : Renamed SetData() to SetDataFromDocument(), in order to resolve name clash
    with the method of the same name in class Window.  This caused a compiler
    warning on Solaris Intel.
    2009-04-13 04:09:59 +0200 kohei  r270729 : CWS-TOOLING: rebase CWS scsheetprotection02 to trunk at 270723 (milestone: DEV300:m46)
    2009-02-23 16:13:45 +0100 kohei  r268361 : added tabprotection.obj to the exception file list.  Apparently the older
    versions of boost::shared_ptr rely on C++ exceptions for its implementation.
    2009-02-18 19:59:05 +0100 kohei  r268253 : Switched to using ::boost::shared_ptr to wrap a pimpl class, because using
    ::std::auto_ptr in this header breaks the build on win32.  The MSVC
    implementation of ::std::auto_ptr has some weird quirks...
    2009-02-17 21:47:13 +0100 kohei  r268192 : fixed linkage issue due to library split.
    2009-02-17 04:50:34 +0100 kohei  r267842 : CWS-TOOLING: rebase CWS scsheetprotection02 to trunk at 267171 (milestone: DEV300:m41)
    2009-02-17 02:36:10 +0100 kohei  r267841 : reverted the last commit, to re-surrect the removed src files.
    2009-02-03 22:02:34 +0100 kohei  r267342 : removed the src files to prevent them from being entered into the translation
    process.  The dialogs that need the strings are not yet enabled in the code,
    so their removal will not cause any harm.
    2009-01-14 12:24:29 +0100 dr  r266280 : #i10000# wntmsci12 compiler warnings #4
    2009-01-14 09:35:46 +0100 dr  r266267 : #i10000# wntmsci12 compiler warnings #3
    2009-01-13 15:42:07 +0100 dr  r266231 : #i10000# wntmsci12 compiler warnings #2
    2009-01-13 13:18:28 +0100 dr  r266216 : #i10000# wntmsci12 compiler warnings
    2009-01-07 03:59:11 +0100 kohei  r265943 : remove the fscking compiler warnings.
    2009-01-06 15:55:32 +0100 kohei  r265925 : removed compiler warnings that caused the buildbot build to fail....
    2009-01-05 23:24:59 +0100 kohei  r265888 : Undoing my own local build fix to work around the libmoz... issue.
    2008-12-30 21:39:58 +0100 kohei  r265833 : Duh!  Sheet protection was supposed to be disabled. :-/
    2008-12-23 20:25:55 +0100 kohei  r265792 : recovered the code block that was accidentally removed during cws rebase.
    2008-12-23 19:03:19 +0100 kohei  r265791 : fixed breakage in ods export filter due to rebase to m38.
    2008-12-23 16:41:49 +0100 kohei  r265787 : CWS-TOOLING: rebase CWS scsheetprotection02 to trunk at 265758 (milestone: DEV300:m38)
    2008-12-23 05:37:47 +0100 kohei  r265768 : deliberately forget document and sheet passwords when importing from or
    exporting to excel, to emulate the current behavior.
    2008-12-23 05:12:59 +0100 kohei  r265767 : removed commented-out unused method ScDocument::SetAutoFilterFlags().
    2008-12-23 05:05:19 +0100 kohei  r265766 : removed one duplicate method and made associated changes with the removal,
    and a little more code cleanup.
    2008-12-23 04:24:58 +0100 kohei  r265765 : a typo in in-line comment
    2008-12-23 04:23:08 +0100 kohei  r265764 : remove fprintf statement that blatantly prints out document encryption
    password to stdout.  not a good practice.
    2008-12-23 04:14:21 +0100 kohei  r265763 : we actually don't want to clear all options, because if we do, then
    we would no longer be able to select any cells on a protected sheet.
    2008-12-23 04:07:10 +0100 kohei  r265762 : * minor code cleanup (indentation inconsistencies & use of tab)
    * fixed unprotecting a sheet with password to make it work again.
    2008-12-23 03:22:50 +0100 kohei  r265761 : reverted all the new functionalities to the existing ones, while keeping the new code in
    as much as I could.
    2008-12-22 23:11:08 +0100 kohei  r265760 : in xls export filter, renamed two unknown records into records of known name.
    2008-12-22 22:34:50 +0100 kohei  r265759 : temporarily disable password capability on file export for MS Excel 97.
    2008-12-22 17:01:21 +0100 kohei  r265754 : CWS-TOOLING: rebase CWS scsheetprotection02 to trunk at 264807 (milestone: DEV300:m37)
    2008-11-26 03:12:58 +0100 kohei  r264335 : recovered a method that was actually used.
    2008-11-25 21:51:10 +0100 kohei  r264334 : CWS-TOOLING: rebase CWS scsheetprotection02 to trunk at 264325 (milestone: DEV300:m36)
    2008-10-08 19:57:35 +0200 kohei  r262094 : changed description string to make it less technical.
    2008-10-01 05:56:58 +0200 kohei  r261986 : migrated from the cvs-based cws.
    2008-10-01 05:55:19 +0200 kohei  r261985 : migrated from the cvs-based cws.
    2008-10-01 05:55:00 +0200 kohei  r261984 : migrated from the cvs-based cws.

diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index b4aa59b..4070837 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -90,6 +90,7 @@ class ScDBData;
 class ScDetOpData;
 class ScDetOpList;
 class ScDocOptions;
+class ScDocProtection;
 class ScDocumentPool;
 class ScDrawLayer;
 class ScExtDocOptions;
@@ -108,6 +109,7 @@ class ScRangeName;
 class ScStyleSheet;
 class ScStyleSheetPool;
 class ScTable;
+class ScTableProtection;
 class ScTokenArray;
 class ScValidationData;
 class ScValidationDataList;
@@ -286,7 +288,7 @@ private:
 
     ScFieldEditEngine*	pCacheFieldEditEngine;
 
-    com::sun::star::uno::Sequence<sal_Int8>	aProtectPass;
+    ::std::auto_ptr<ScDocProtection> pDocProtection;
 
     ::std::auto_ptr<ScExternalRefManager> pExternalRefMgr;
     String              aDocName;                       // opt: Dokumentname
@@ -350,7 +352,6 @@ private:
 
     ScLkUpdMode			eLinkMode;
 
-    BOOL				bProtected;
     BOOL				bAutoCalc;						// Automatisch Berechnen
     BOOL				bAutoCalcShellDisabled;			// in/von/fuer ScDocShell disabled
     // ob noch ForcedFormulas berechnet werden muessen,
@@ -530,13 +531,14 @@ public:
     SC_DLLPUBLIC inline SCTAB	GetTableCount() const { return nMaxTableNumber; }
     SvNumberFormatterIndexTable* GetFormatExchangeList() const { return pFormatExchangeList; }
 
-    SC_DLLPUBLIC void			SetDocProtection( BOOL bProtect, const com::sun::star::uno::Sequence <sal_Int8>& aPass );
-    SC_DLLPUBLIC void			SetTabProtection( SCTAB nTab, BOOL bProtect, const com::sun::star::uno::Sequence <sal_Int8>& aPass );
+    SC_DLLPUBLIC ScDocProtection* GetDocProtection() const;
+    SC_DLLPUBLIC void            SetDocProtection(const ScDocProtection* pProtect);
     SC_DLLPUBLIC BOOL			IsDocProtected() const;
     BOOL			IsDocEditable() const;
     SC_DLLPUBLIC 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;
+    SC_DLLPUBLIC    ScTableProtection* GetTabProtection( SCTAB nTab ) const;
+    SC_DLLPUBLIC void SetTabProtection(SCTAB nTab, const ScTableProtection* pProtect);
+    void            CopyTabProtection(SCTAB nTabSrc, SCTAB nTabDest);
 
     void			LockTable(SCTAB nTab);
     void			UnlockTable(SCTAB nTab);
@@ -1475,7 +1477,8 @@ public:
 
 
 private:
-//UNUSED2008-05  void				SetAutoFilterFlags();
+    ScDocument(const ScDocument& r); // disabled with no definition
+
     void				FindMaxRotCol( SCTAB nTab, RowInfo* pRowInfo, SCSIZE nArrCount,
                                         SCCOL nX1, SCCOL nX2 ) const;
 
diff --git a/sc/inc/sc.hrc b/sc/inc/sc.hrc
index 79211b8..554d96f 100644
--- a/sc/inc/sc.hrc
+++ b/sc/inc/sc.hrc
@@ -1631,7 +1631,12 @@
 #define RID_SCDLG_CONFLICTS             (SC_DIALOGS_START + 145)
 #define RID_SCDLG_SHAREDOCUMENT         (SC_DIALOGS_START + 146)
 
-#define SC_DIALOGS_END          (SC_DIALOGS_START + 150)
+#define RID_SCDLG_TABPROTECTION         (SC_DIALOGS_START + 147)
+#define RID_SCDLG_DOCPROTECTION         (SC_DIALOGS_START + 148)
+#define RID_SCDLG_RETYPEPASS            (SC_DIALOGS_START + 149)
+#define RID_SCDLG_RETYPEPASS_INPUT      (SC_DIALOGS_START + 150)
+
+#define SC_DIALOGS_END          (SC_DIALOGS_START + 151)
 
 #ifndef STD_MASKCOLOR
 #define STD_MASKCOLOR Color { Red = 0xFF00; Green = 0x0000; Blue = 0xFF00; }
diff --git a/sc/inc/scextopt.hxx b/sc/inc/scextopt.hxx
index 4aa9444..d9e654e 100644
--- a/sc/inc/scextopt.hxx
+++ b/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 a/sc/inc/table.hxx b/sc/inc/table.hxx
index ba4b022..083a6d5 100644
--- a/sc/inc/table.hxx
+++ b/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,9 @@ 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(const ScTableProtection* pProtect);
+    ScTableProtection* GetProtection();
 
     Size			GetPageSize() const;
     void			SetPageSize( const Size& rSize );
diff --git a/sc/inc/tabprotection.hxx b/sc/inc/tabprotection.hxx
new file mode 100644
index 0000000..fc38a1b
--- /dev/null
+++ b/sc/inc/tabprotection.hxx
@@ -0,0 +1,180 @@
+/*************************************************************************
+ *
+ * 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: tabprotection.hxx,v $
+ * $Revision: 1.1.4.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.
+ *
+ ************************************************************************/
+
+#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 <boost/shared_ptr.hpp>
+
+#define ENABLE_SHEET_PROTECTION 0
+
+class ScDocument;
+class ScTableProtectionImpl;
+
+enum ScPasswordHash
+{
+    PASSHASH_OOO = 0,
+    PASSHASH_XL
+};
+
+class ScPassHashHelper
+{
+public:
+    /** 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 compatible with the specified hash type, then it
+        returns false. */
+    static bool needsPassHashRegen(const ScDocument& rDoc, ScPasswordHash eHash);
+
+private:
+    ScPassHashHelper();
+    ~ScPassHashHelper();
+};
+
+// ============================================================================
+
+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 SC_DLLPUBLIC 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:
+    ::boost::shared_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 SC_DLLPUBLIC 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:
+    ::boost::shared_ptr<ScTableProtectionImpl> mpImpl;
+};
+
+
+#endif
diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx
index 9f236e0..d5d4438 100644
--- a/sc/source/core/data/documen2.cxx
+++ b/sc/source/core/data/documen2.cxx
@@ -94,6 +94,7 @@
 #include "recursionhelper.hxx"
 #include "lookupcache.hxx"
 #include "externalrefmgr.hxx"
+#include "tabprotection.hxx"
 
 // pImpl because including lookupcache.hxx in document.hxx isn't wanted, and
 // dtor plus helpers are convenient.
@@ -152,6 +153,7 @@ ScDocument::ScDocument( ScDocumentMode	eMode,
         pChangeViewSettings( NULL ),
         pScriptTypeData( NULL ),
         pCacheFieldEditEngine( NULL ),
+        pDocProtection( NULL ),
         pExternalRefMgr( NULL ),
         pViewOptions( NULL ),
         pDocOptions( NULL ),
@@ -175,7 +177,6 @@ ScDocument::ScDocument( ScDocumentMode	eMode,
         nHardRecalcState(0),
         nVisibleTab( 0 ),
         eLinkMode(LM_UNKNOWN),
-        bProtected( FALSE ),
         bAutoCalc( eMode == SCDOCMODE_DOCUMENT ),
         bAutoCalcShellDisabled( FALSE ),
         bForcedFormulaPending( FALSE ),
diff --git a/sc/source/core/data/documen3.cxx b/sc/source/core/data/documen3.cxx
index f40768a..6143b5b 100644
--- a/sc/source/core/data/documen3.cxx
+++ b/sc/source/core/data/documen3.cxx
@@ -77,6 +77,8 @@
 #include "drwlayer.hxx"
 #include "unoreflist.hxx"
 #include "listenercalls.hxx"
+#include "svtools/PasswordHelper.hxx"
+#include "tabprotection.hxx"
 
 #include <memory>
 
@@ -1701,28 +1703,28 @@ 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(const ScDocProtection* pProtect)
 {
-    if (VALIDTAB(nTab))
-        if (pTab[nTab])
-            pTab[nTab]->SetProtection( bProtect, rPasswd );
+    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
@@ -1734,18 +1736,28 @@ 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, const ScTableProtection* pProtect)
 {
-    if (VALIDTAB(nTab) && pTab[nTab])
-        return pTab[nTab]->GetPassword();
+    if (!ValidTab(nTab))
+        return;
 
-    DBG_ERROR("Falsche Tabellennummer");
-    return aProtectPass;
+    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 a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 8efa79d..60a75f2 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -93,6 +93,7 @@
 #include "bcaslot.hxx"
 #include "postit.hxx"
 #include "externalrefmgr.hxx"
+#include "tabprotection.hxx"
 
 namespace WritingMode2 = ::com::sun::star::text::WritingMode2;
 
@@ -4104,24 +4105,6 @@ BOOL ScDocument::RefreshAutoFilter( SCCOL nStartCol, SCROW nStartRow,
 }
 
 
-//UNUSED2008-05  void ScDocument::SetAutoFilterFlags()
-//UNUSED2008-05  {
-//UNUSED2008-05      USHORT nCount = pDBCollection->GetCount();
-//UNUSED2008-05      for (USHORT i=0; i<nCount; i++)
-//UNUSED2008-05      {
-//UNUSED2008-05          ScDBData* pData = (*pDBCollection)[i];
-//UNUSED2008-05          SCTAB nDBTab;
-//UNUSED2008-05          SCCOL nDBStartCol;
-//UNUSED2008-05          SCROW nDBStartRow;
-//UNUSED2008-05          SCCOL nDBEndCol;
-//UNUSED2008-05          SCROW nDBEndRow;
-//UNUSED2008-05          pData->GetArea( nDBTab, nDBStartCol,nDBStartRow, nDBEndCol,nDBEndRow );
-//UNUSED2008-05          pData->SetAutoFilter( HasAttrib( nDBStartCol,nDBStartRow,nDBTab,
-//UNUSED2008-05                                  nDBEndCol,nDBStartRow,nDBTab, HASATTR_AUTOFILTER ) );
-//UNUSED2008-05      }
-//UNUSED2008-05  }
-
-
 BOOL ScDocument::IsHorOverlapped( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
 {
     const ScMergeFlagAttr* pAttr = (const ScMergeFlagAttr*)
diff --git a/sc/source/core/data/makefile.mk b/sc/source/core/data/makefile.mk
index 7129198..71d7ba6 100644
--- a/sc/source/core/data/makefile.mk
+++ b/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
@@ -128,6 +129,7 @@ EXCEPTIONSFILES= \
     $(SLO)$/global2.obj \
     $(SLO)$/table1.obj \
     $(SLO)$/table3.obj \
+    $(SLO)$/tabprotection.obj \
     $(SLO)$/postit.obj \
     $(SLO)$/documen3.obj \
     $(SLO)$/documen5.obj \
diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx
index d624d4a..680281c 100644
--- a/sc/source/core/data/table1.cxx
+++ b/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 a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index e84d3e4..d33d90b 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -292,7 +292,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 ) );
@@ -318,7 +318,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 );
@@ -361,7 +361,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);
     }
@@ -406,7 +406,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 ) );
@@ -1457,7 +1457,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)
         {
@@ -1524,7 +1524,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)
         {
diff --git a/sc/source/core/data/table5.cxx b/sc/source/core/data/table5.cxx
index 073808d..2865d4b 100644
--- a/sc/source/core/data/table5.cxx
+++ b/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,24 @@ void ScTable::SetPageSize( const Size& rSize )
         bPageSizeValid = FALSE;
 }
 
+BOOL ScTable::IsProtected() const
+{
+    return pTabProtection.get() && pTabProtection->isProtected();
+}
+
+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 a/sc/source/core/data/tabprotection.cxx b/sc/source/core/data/tabprotection.cxx
new file mode 100644
index 0000000..2b4ece2
--- /dev/null
+++ b/sc/source/core/data/tabprotection.cxx
@@ -0,0 +1,465 @@
+/*************************************************************************
+ *
+ * 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: tabprotection.cxx,v $
+ * $Revision: 1.1.4.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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sc.hxx"
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "tabprotection.hxx"
+#include "tools/debug.hxx"
+#include "svtools/PasswordHelper.hxx"
+#include "document.hxx"
+
+#define DEBUG_TAB_PROTECTION 0
+
+using namespace ::com::sun::star;
+using ::com::sun::star::uno::Sequence;
+using ::rtl::OUString;
+
+// ============================================================================
+
+bool ScPassHashHelper::needsPassHashRegen(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;
+}
+
+// ============================================================================
+
+ScPassHashProtectable::~ScPassHashProtectable()
+{
+}
+
+// ============================================================================
+
+static sal_uInt16 lcl_getXLHashFromChar(const sal_Char* szPassword)
+{
+    sal_uInt16 cchPassword = static_cast< sal_uInt16 >( 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) :
+    ScPassHashProtectable(),
+    mpImpl(new ScTableProtectionImpl(*r.mpImpl))
+{
+}
+
+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) :
+    ScPassHashProtectable(),
+    mpImpl(new ScTableProtectionImpl(*r.mpImpl))
+{
+}
+
+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 a/sc/source/filter/excel/excdoc.cxx b/sc/source/filter/excel/excdoc.cxx
index 7cd9ba8..bbc8cb4 100644
--- a/sc/source/filter/excel/excdoc.cxx
+++ b/sc/source/filter/excel/excdoc.cxx
@@ -68,11 +68,11 @@
 #include "convuno.hxx"
 #include "patattr.hxx"
 #include "docoptio.hxx"
+#include "tabprotection.hxx"
 
 #include "excdoc.hxx"
 #include "namebuff.hxx"
 
-#include "xcl97dum.hxx"
 #include "xcl97rec.hxx"
 #include "xcl97esc.hxx"
 #include "xetable.hxx"
@@ -118,7 +118,7 @@ static void lcl_AddCalcPr( XclExpRecordList<>& aRecList, ExcTable& self )
     aRecList.AppendNewRecord( new XclRefmode( rDoc ) );
     aRecList.AppendNewRecord( new XclIteration( rDoc ) );
     aRecList.AppendNewRecord( new XclDelta( rDoc ) );
-    aRecList.AppendNewRecord( new ExcDummy8_02 );
+    aRecList.AppendNewRecord( new XclExpBoolRecord(0x005F, true) ); // SAVERECALC
     aRecList.AppendNewRecord( new XclExpXmlEndSingleElementRecord() );  // XML_calcPr
 }
 
@@ -209,7 +209,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() )
@@ -219,7 +228,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
@@ -239,12 +249,22 @@ 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)) );
+#if ENABLE_SHEET_PROTECTION
+        Add( new XclExpPassHash(pProtect->getPasswordHash(PASSHASH_XL)) );
+#endif
+    }
 
     if( GetBiff() == EXC_BIFF8 )
-        Add( new ExcDummy8_040 );
+    {
+        Add( new XclExpProt4Rev );
+        Add( new XclExpProt4RevPass );
+    }
 
     // document protection options
     if( GetOutput() == EXC_OUTPUT_BINARY )
@@ -255,6 +275,12 @@ void ExcTable::FillAsHeader( ExcBoundsheetList& rBoundsheetList )
 
     Add( new XclExpXmlStartSingleElementRecord( XML_workbookPr ) );
 
+    if ( GetBiff() == EXC_BIFF8 )
+    {
+        Add( new XclExpBoolRecord(0x0040, false) ); // BACKUP
+        Add( new XclExpBoolRecord(0x008D, false) ); // HIDEOBJ
+    }
+
     if( GetBiff() <= EXC_BIFF5 )
     {
         Add( new ExcDummy_040 );
@@ -263,9 +289,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
         // OOXTODO: The following /workbook/workbookPr attributes are mapped
         //          to various BIFF records that are not currently supported:
         //
@@ -361,10 +389,14 @@ void ExcTable::FillAsHeader( ExcBoundsheetList& rBoundsheetList )
         if( GetOutput() != EXC_OUTPUT_BINARY )
             lcl_AddCalcPr( aRecList, *this );
 
+        Add( new XclExpRecalcId );
+
         // MSODRAWINGGROUP per-document data
         Add( new XclMsodrawinggroup( rR, ESCHER_DggContainer ) );
         // Shared string table: SST, EXTSST
         aRecList.AppendRecord( CreateRecord( EXC_ID_SST ) );
+
+        Add( new XclExpBookExt );
     }
 
     Add( new ExcEof );
@@ -425,8 +457,16 @@ 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)) );
+#if ENABLE_SHEET_PROTECTION
+        Add( new XclExpPassHash(pTabProtect->getPasswordHash(PASSHASH_XL)) );
+#endif
+    }
 
     // local link table: EXTERNCOUNT, EXTERNSHEET
     if( eBiff <= EXC_BIFF5 )
@@ -467,6 +507,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 a/sc/source/filter/excel/excimp8.cxx b/sc/source/filter/excel/excimp8.cxx
index 9e2e007..59545af 100644
--- a/sc/source/filter/excel/excimp8.cxx
+++ b/sc/source/filter/excel/excimp8.cxx
@@ -160,12 +160,6 @@ void ImportExcel8::Iteration( void )
 }
 
 
-void ImportExcel8:: WinProtection( void )
-{
-    if( aIn.ReaduInt16() != 0 )
-        GetExtDocOptions().GetDocSettings().mbWinProtected = true;
-}
-
 void ImportExcel8::Boundsheet( void )
 {
     UINT8			nLen;
@@ -249,6 +243,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);
@@ -295,6 +294,8 @@ void ImportExcel8::PostDocLoad( void )
         pExcRoot->pAutoFilterBuffer->Apply();
 
     GetWebQueryBuffer().Apply();    //! test if extant
+    GetSheetProtectBuffer().Apply();
+    GetDocProtectBuffer().Apply();
 
     ImportExcel::PostDocLoad();
 
diff --git a/sc/source/filter/excel/excrecds.cxx b/sc/source/filter/excel/excrecds.cxx
index 5509d09..a2158ee 100644
--- a/sc/source/filter/excel/excrecds.cxx
+++ b/sc/source/filter/excel/excrecds.cxx
@@ -100,6 +100,7 @@
 
 #include <oox/core/tokens.hxx>
 
+using ::com::sun::star::uno::Sequence;
 
 
 using ::rtl::OString;
@@ -432,7 +433,9 @@ ExcBundlesheetBase::ExcBundlesheetBase() :
 void ExcBundlesheetBase::UpdateStreamPos( XclExpStream& rStrm )
 {
     rStrm.SetSvStreamPos( nOwnPos );
+    rStrm.DisableEncryption();
     rStrm << static_cast<sal_uInt32>(nStrPos);
+    rStrm.EnableEncryption();
 }
 
 
@@ -532,7 +535,7 @@ void XclExpWsbool::SaveXml( XclExpXmlStream& rStrm )
 // XclExpWindowProtection ===============================================================
 
 XclExpWindowProtection::XclExpWindowProtection(bool bValue) :
-    XclExpBoolRecord(EXC_ID_WINDOWPROTECT,bValue)
+    XclExpBoolRecord(EXC_ID_WINDOWPROTECT, bValue)
 {
 }
 
@@ -545,13 +548,35 @@ void XclExpWindowProtection::SaveXml( XclExpXmlStream& rStrm )
 
 // 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 a/sc/source/filter/excel/impop.cxx b/sc/source/filter/excel/impop.cxx
index 2611c51..b936e00 100644
--- a/sc/source/filter/excel/impop.cxx
+++ b/sc/source/filter/excel/impop.cxx
@@ -84,6 +84,7 @@
 #include "xiview.hxx"
 #include "xilink.hxx"
 #include "xiescher.hxx"
+#include "xicontent.hxx"
 
 #include "excimp8.hxx"
 #include "excform.hxx"
@@ -418,14 +419,12 @@ void ImportExcel::Eof( void )
 }
 
 
-BOOL ImportExcel::Password( void )
+void ImportExcel::SheetPassword( void )
 {
-    // POST: return = TRUE, wenn Password <> 0
-    UINT16 nPasswd;
-
-    aIn >> nPasswd;
+    if (GetRoot().GetBiff() != EXC_BIFF8)
+        return;
 
-    return nPasswd != 0x0000;
+    GetRoot().GetSheetProtectBuffer().ReadPasswordHash( aIn, GetCurrScTab() );
 }
 
 
@@ -439,6 +438,15 @@ void ImportExcel::Externsheet( void )
 }
 
 
+void ImportExcel:: WinProtection( void )
+{
+    if (GetRoot().GetBiff() != EXC_BIFF8)
+        return;
+
+    GetRoot().GetDocProtectBuffer().ReadWinProtect( aIn );
+}
+
+
 void ImportExcel::Columndefault( void )
 {// Default Cell Attributes
     UINT16	nColMic, nColMac;
@@ -570,27 +578,33 @@ 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 );
-    }
+    if (GetRoot().GetBiff() != EXC_BIFF8)
+        return;
+
+    GetRoot().GetSheetProtectBuffer().ReadProtect( aIn, GetCurrScTab() );
 }
 
 void ImportExcel::DocProtect( void )
 {
-    if( aIn.ReaduInt16() )
-    {
-        uno::Sequence<sal_Int8> aEmptyPass;
-        GetDoc().SetDocProtection( TRUE, aEmptyPass );
-    }
+    if (GetRoot().GetBiff() != EXC_BIFF8)
+        return;
+
+    GetRoot().GetDocProtectBuffer().ReadDocProtect( aIn );
 }
 
+void ImportExcel::DocPasssword( void )
+{
+    if (GetRoot().GetBiff() != EXC_BIFF8)
+        return;
+
+    GetRoot().GetDocProtectBuffer().ReadPasswordHash( aIn );
+}
 
 void ImportExcel::Codepage( void )
 {
+    maStrm.EnableDecryption();
     SetCodePage( maStrm.ReaduInt16() );
 }
 
diff --git a/sc/source/filter/excel/read.cxx b/sc/source/filter/excel/read.cxx
index dbc65e9..da460a2 100644
--- a/sc/source/filter/excel/read.cxx
+++ b/sc/source/filter/excel/read.cxx
@@ -354,7 +354,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]
@@ -469,7 +469,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:
@@ -596,7 +596,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;
@@ -895,6 +895,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 );
@@ -1039,7 +1040,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   ]
@@ -1055,6 +1057,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 a/sc/source/filter/excel/xeroot.cxx b/sc/source/filter/excel/xeroot.cxx
index abe1da2..600a928 100644
--- a/sc/source/filter/excel/xeroot.cxx
+++ b/sc/source/filter/excel/xeroot.cxx
@@ -31,7 +31,11 @@
 // MARKER(update_precomp.py): autogen include statement, do not remove
 #include "precompiled_sc.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 "xecontent.hxx"
 #include "xltracer.hxx"
 #include "xehelper.hxx"
@@ -42,8 +46,10 @@
 #include "xepivot.hxx"
 #include "xeroot.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 a/sc/source/filter/excel/xestream.cxx b/sc/source/filter/excel/xestream.cxx
index ffb8622..82221b6 100644
--- a/sc/source/filter/excel/xestream.cxx
+++ b/sc/source/filter/excel/xestream.cxx
@@ -1,7 +1,7 @@
 /*************************************************************************
  *
  * 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
@@ -51,6 +51,8 @@
 #include <oox/core/tokens.hxx>
 #include <formula/grammar.hxx>
 
+#define DEBUG_XL_ENCRYPTION 0
+
 using ::com::sun::star::beans::PropertyValue;
 using ::com::sun::star::io::XOutputStream;
 using ::com::sun::star::io::XStream;
@@ -63,7 +65,10 @@ using ::com::sun::star::uno::UNO_QUERY;
 using ::rtl::OString;
 using ::rtl::OUString;
 using ::utl::OStreamWrapper;
+using ::std::vector;
+
 using namespace formula;
+
 // ============================================================================
 
 XclExpStream::XclExpStream( SvStream& rOutStrm, const XclExpRoot& rRoot, sal_uInt16 nMaxRecSize ) :
@@ -92,16 +97,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;
@@ -113,6 +121,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;
@@ -127,9 +215,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;
@@ -265,6 +365,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" );
@@ -356,6 +476,193 @@ 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_uInt32 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 = static_cast< sal_uInt16 >( 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_uInt32 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!!");
+        bRet = bRet; // to remove a silly compiler warning.
+
+        sal_Size nRet = rStrm.Write(&aBytes[nPos], nEncBytes);
+        DBG_ASSERT(nRet == nEncBytes, "XclExpBiff8Encrypter::EncryptBytes: fail to write to stream!!");
+        nRet = nRet; // to remove a silly compiler warning.
+
+        nStrmPos = rStrm.Tell();
+        nBlockOffset = GetOffsetInBlock(nStrmPos);
+        nBlockPos = GetBlockPos(nStrmPos);
+        if (nBlockOffset == 0)
+            maCodec.InitCipher(nBlockPos);
+
+        nBytesLeft -= nEncBytes;
+        nPos += nEncBytes;
+    }
+    mnOldPos = nStrmPos;
+}
+
 rtl::OUString XclXmlUtils::GetStreamName( const char* sStreamDir, const char* sStream, sal_Int32 nId )
 {
     rtl::OUStringBuffer sBuf;
@@ -417,8 +724,8 @@ static ScAddress lcl_ToAddress( const XclAddress& rAddress )
 {
     ScAddress aAddress;
 
-    // For some reason, ScRange::Format() returns omits row numbers if 
-    // the row is >= MAXROW or the column is >= MAXCOL, and Excel doesn't 
+    // For some reason, ScRange::Format() returns omits row numbers if
+    // the row is >= MAXROW or the column is >= MAXCOL, and Excel doesn't
     // like "A:IV" (i.e. no row numbers).  Prevent this.
     aAddress.SetRow( std::min<sal_Int32>( rAddress.mnRow, MAXROW-1 ) );
     aAddress.SetCol( static_cast<sal_Int16>(std::min<sal_Int32>( rAddress.mnCol, MAXCOL-1 )) );
@@ -649,12 +956,12 @@ sax_fastparser::FSHelperPtr& XclExpXmlStream::WriteFontData( const XclFontData&
     return rStream;
 }
 
-sax_fastparser::FSHelperPtr XclExpXmlStream::CreateOutputStream ( 
+sax_fastparser::FSHelperPtr XclExpXmlStream::CreateOutputStream (
     const OUString& sFullStream,
     const OUString& sRelativeStream,
-    const Reference< XOutputStream >& xParentRelation, 
-    const char* sContentType, 
-    const char* sRelationshipType, 
+    const Reference< XOutputStream >& xParentRelation,
+    const char* sContentType,
+    const char* sRelationshipType,
     ::rtl::OUString* pRelationshipId )
 {
     OUString sRelationshipId;
diff --git a/sc/source/filter/excel/xicontent.cxx b/sc/source/filter/excel/xicontent.cxx
index d4c5ba5..24c1999 100644
--- a/sc/source/filter/excel/xicontent.cxx
+++ b/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 ========================================================
 
@@ -1089,12 +1096,191 @@ ErrCode XclImpDecryptHelper::ReadFilepass( XclImpStream& rStrm )
         case EXC_BIFF8: xDecr = lclReadFilepass8( rStrm );  break;
         default:        DBG_ERROR_BIFF();
     };
+
+    if (!xDecr.is())
+        return EXC_ENCR_ERROR_UNSUPP_CRYPT;
+
     // set decrypter at import stream
     rStrm.SetDecrypter( xDecr );
-    // remember encryption for export
-    rStrm.GetRoot().GetExtDocOptions().GetDocSettings().mbEncrypted = true;
 
-    return xDecr.is() ? xDecr->GetError() : EXC_ENCR_ERROR_UNSUPP_CRYPT;
+    // 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->GetError();
+}
+
+// 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 ENABLE_SHEET_PROTECTION
+    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);
+    }
+#endif
+
+    // 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);
+
+#if ENABLE_SHEET_PROTECTION
+        // 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);
+        }
+#endif
+
+        // 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 a/sc/source/filter/excel/xilink.cxx b/sc/source/filter/excel/xilink.cxx
index 16a3edf..2c24263 100644
--- a/sc/source/filter/excel/xilink.cxx
+++ b/sc/source/filter/excel/xilink.cxx
@@ -263,6 +263,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 a/sc/source/filter/excel/xiroot.cxx b/sc/source/filter/excel/xiroot.cxx
index d5d1119..55ba4bd 100644
--- a/sc/source/filter/excel/xiroot.cxx
+++ b/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() ) );
@@ -232,6 +235,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;
@@ -255,5 +270,16 @@ 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;
+    }
+    return mrImpData.maPassw;
+}
+
 // ============================================================================
 
diff --git a/sc/source/filter/excel/xistream.cxx b/sc/source/filter/excel/xistream.cxx
index b7f0d38..e7780c0 100644
--- a/sc/source/filter/excel/xistream.cxx
+++ b/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 a/sc/source/filter/excel/xlroot.cxx b/sc/source/filter/excel/xlroot.cxx
index bdc75df..8f5ddad 100644
--- a/sc/source/filter/excel/xlroot.cxx
+++ b/sc/source/filter/excel/xlroot.cxx
@@ -92,8 +92,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() )
@@ -199,17 +198,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 a/sc/source/filter/inc/excimp8.hxx b/sc/source/filter/inc/excimp8.hxx
index 06850ba..fadad41 100644
--- a/sc/source/filter/inc/excimp8.hxx
+++ b/sc/source/filter/inc/excimp8.hxx
@@ -61,7 +61,6 @@ class ImportExcel8 : public ImportExcel
         void                    Precision( void );              // 0x0E
         void					Delta( void );					// 0x10
         void					Iteration( void );				// 0x11
-        void					WinProtection(	void );         // 0x19
         void					Boundsheet( void );				// 0x85
         void					FilterMode( void );				// 0x9B
         void					AutoFilterInfo( void );			// 0x9D
@@ -73,6 +72,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 a/sc/source/filter/inc/excrecds.hxx b/sc/source/filter/inc/excrecds.hxx
index 1686f2f..c56bc1f 100644
--- a/sc/source/filter/inc/excrecds.hxx
+++ b/sc/source/filter/inc/excrecds.hxx
@@ -246,10 +246,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 a/sc/source/filter/inc/imp_op.hxx b/sc/source/filter/inc/imp_op.hxx
index 2d58a6a..444ce2e 100644
--- a/sc/source/filter/inc/imp_op.hxx
+++ b/sc/source/filter/inc/imp_op.hxx
@@ -135,9 +135,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					Columndefault( void );			// 0x20
     void					Array25( void );				// 0x21
     void					Rec1904( void );				// 0x22
diff --git a/sc/source/filter/inc/xcl97rec.hxx b/sc/source/filter/inc/xcl97rec.hxx
index cc257e0..c2b8784 100644
--- a/sc/source/filter/inc/xcl97rec.hxx
+++ b/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;
 };
 
 
@@ -464,23 +460,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
 {
@@ -544,5 +541,162 @@ public:
     virtual void                SaveXml( XclExpXmlStream& rStrm );
 };
 
+// ============================================================================
+
+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 XclExpRecalcId : public XclExpDummyRecord
+{
+public:
+    explicit XclExpRecalcId();
+};
+
+// ============================================================================
+
+class XclExpBookExt : public XclExpDummyRecord
+{
+public:
+    explicit XclExpBookExt();
+};
+
 
 #endif // _XCL97REC_HXX
diff --git a/sc/source/filter/inc/xeroot.hxx b/sc/source/filter/inc/xeroot.hxx
index 7e97e92..f4e1d25 100644
--- a/sc/source/filter/inc/xeroot.hxx
+++ b/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 a/sc/source/filter/inc/xestream.hxx b/sc/source/filter/inc/xestream.hxx
index b3e4e8c..1267e0e 100644
--- a/sc/source/filter/inc/xestream.hxx
+++ b/sc/source/filter/inc/xestream.hxx
@@ -43,6 +43,9 @@
 #include "xlstream.hxx"
 #include "xestring.hxx"
 
+#include <svx/mscodec.hxx>
+#include <vector>
+
 /* ============================================================================
 Output stream class for Excel export
 - CONTINUE record handling
@@ -50,6 +53,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
@@ -108,14 +113,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 );
@@ -158,6 +163,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 );
@@ -180,6 +193,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.
@@ -197,64 +213,50 @@ 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;
+};
 
 // ----------------------------------------------------------------------------
 
diff --git a/sc/source/filter/inc/xetable.hxx b/sc/source/filter/inc/xetable.hxx
index 2c03a30..3da59d2 100644
--- a/sc/source/filter/inc/xetable.hxx
+++ b/sc/source/filter/inc/xetable.hxx
@@ -1088,7 +1088,5 @@ private:
     XclExpDvalRef       mxDval;             /// Data validation with DVAL and DV records.
 };
 
-// ============================================================================
-
 #endif
 
diff --git a/sc/source/filter/inc/xicontent.hxx b/sc/source/filter/inc/xicontent.hxx
index 48f6917..07b237a 100644
--- a/sc/source/filter/inc/xicontent.hxx
+++ b/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 a/sc/source/filter/inc/xiroot.hxx b/sc/source/filter/inc/xiroot.hxx
index dfa2ca0..915f961 100644
--- a/sc/source/filter/inc/xiroot.hxx
+++ b/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 a/sc/source/filter/inc/xistream.hxx b/sc/source/filter/inc/xistream.hxx
index aa1cae8..ccaaccd 100644
--- a/sc/source/filter/inc/xistream.hxx
+++ b/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 a/sc/source/filter/inc/xlroot.hxx b/sc/source/filter/inc/xlroot.hxx
index 4c917eb..4705829 100644
--- a/sc/source/filter/inc/xlroot.hxx
+++ b/sc/source/filter/inc/xlroot.hxx
@@ -92,7 +92,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).
@@ -116,7 +115,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,
@@ -184,8 +182,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 a/sc/source/filter/starcalc/scflt.cxx b/sc/source/filter/starcalc/scflt.cxx
index 0c11551..831e837 100644
--- a/sc/source/filter/starcalc/scflt.cxx
+++ b/sc/source/filter/starcalc/scflt.cxx
@@ -81,6 +81,7 @@
 #include "postit.hxx"
 #include "globstr.hrc"
 #include "ftools.hxx"
+#include "tabprotection.hxx"
 
 #include "fprogressbar.hxx"
 
@@ -1087,9 +1088,11 @@ 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);
+
+    ScDocProtection aProtection;
+    aProtection.setProtected(static_cast<bool>(SheetProtect.Protect));
+    aProtection.setPassword(SC10TOSTRING(SheetProtect.PassWord));
+    pDoc->SetDocProtection(&aProtection);
 }
 
 
@@ -1441,10 +1444,11 @@ void Sc10Import::LoadTables()
 
         //rStream.Read(&TabProtect, sizeof(TabProtect));
         lcl_ReadTabProtect(rStream, TabProtect);
-        uno::Sequence<sal_Int8> aPass;
-        SvPasswordHelper::GetHashPassword(aPass, SC10TOSTRING( TabProtect.PassWord ));
 
-        pDoc->SetTabProtection( static_cast<SCTAB>(Tab), TabProtect.Protect, aPass);
+        ScTableProtection aProtection;
+        aProtection.setProtected(static_cast<bool>(TabProtect.Protect));
+        aProtection.setPassword(SC10TOSTRING(TabProtect.PassWord));
+        pDoc->SetTabProtection(static_cast<SCTAB>(Tab), &aProtection);
 
         rStream >> TabNo;
 
diff --git a/sc/source/filter/xcl97/XclExpChangeTrack.cxx b/sc/source/filter/xcl97/XclExpChangeTrack.cxx
index c9440e9..efb224c 100644
--- a/sc/source/filter/xcl97/XclExpChangeTrack.cxx
+++ b/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 a/sc/source/filter/xcl97/makefile.mk b/sc/source/filter/xcl97/makefile.mk
index c40209d..58e2b8c 100644
--- a/sc/source/filter/xcl97/makefile.mk
+++ b/sc/source/filter/xcl97/makefile.mk
@@ -51,7 +51,6 @@ VISIBILITY_HIDDEN=TRUE
 # --- Files --------------------------------------------------------
 
 SLOFILES =									\
-        $(SLO)$/xcl97dum.obj				\
         $(SLO)$/xcl97esc.obj				\
         $(SLO)$/xcl97rec.obj				\
         $(SLO)$/XclImpChangeTrack.obj		\
diff --git a/sc/source/filter/xcl97/xcl97rec.cxx b/sc/source/filter/xcl97/xcl97rec.cxx
index 1291998..97bd958 100644
--- a/sc/source/filter/xcl97/xcl97rec.cxx
+++ b/sc/source/filter/xcl97/xcl97rec.cxx
@@ -78,6 +78,7 @@
 #include "scextopt.hxx"
 #include "docoptio.hxx"
 #include "patattr.hxx"
+#include "tabprotection.hxx"
 
 #include <oox/core/tokens.hxx>
 
@@ -135,9 +136,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 )
     {
@@ -182,7 +183,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" );
@@ -190,23 +191,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 )
     {
@@ -232,7 +221,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" );
@@ -240,16 +229,6 @@ void XclMsodrawing::SaveCont( XclExpStream& rStrm )
 }
 
 
-UINT16 XclMsodrawing::GetNum() const
-{
-    return 0x00EC;
-}
-
-
-sal_Size XclMsodrawing::GetLen() const
-{
-    return GetDataLen();
-}
 
 
 // --- class XclObjList ----------------------------------------------
@@ -887,6 +866,7 @@ ExcBof8_Base::ExcBof8_Base()
 
 void ExcBof8_Base::SaveCont( XclExpStream& rStrm )
 {
+    rStrm.DisableEncryption();
     rStrm	<< nVers << nDocType << nRupBuild << nRupYear
             << nFileHistory << nLowestBiffVer;
 }
@@ -946,7 +926,10 @@ void ExcBundlesheet8::SaveCont( XclExpStream& rStrm )
 {
     nOwnPos = rStrm.GetSvStreamPos();
     // write dummy position, real position comes later
-    rStrm << sal_uInt32( 0 ) << nGrbit << GetName();
+    rStrm.DisableEncryption();
+    rStrm << sal_uInt32(0);
+    rStrm.EnableEncryption();
+    rStrm << nGrbit << GetName();
 }
 
 
@@ -1254,33 +1237,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;
 
-const BYTE* XclProtection::GetData( void ) const
-{
-    return pMyData;
+    for (int i = 0; aTable[i].nMask != 0x0000; ++i)
+    {
+        if ( pProtect->isOptionEnabled(aTable[i].eOption) )
+            mnOptions |= aTable[i].nMask;
+    }
 }
 
+void XclExpSheetProtectOptions::WriteBody( XclExpStream& rStrm )
+{
+    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;
+}
 
+// ============================================================================
 
 
 
@@ -1385,8 +1408,253 @@ void XclDelta::SaveXml( XclExpXmlStream& rStrm )
             FSEND );
 }
 
+// ============================================================================
+
+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 nDataRecalcId[] = {
+    0xC1, 0x01, 0x00, 0x00, 0x54, 0x8D, 0x01, 0x00
+};
+
+XclExpRecalcId::XclExpRecalcId() :
+    XclExpDummyRecord(0x01C1, nDataRecalcId, sizeof(nDataRecalcId))
+{
+}
+
+// ============================================================================
+
+static const sal_uInt8 nDataBookExt[] = {
+    0x63, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+    0x02
+};
+
+XclExpBookExt::XclExpBookExt() :
+    XclExpDummyRecord(0x0863, nDataBookExt, sizeof(nDataBookExt))
+{
+}
 
+// ============================================================================
 
 XclRefmode::XclRefmode( const ScDocument& rDoc ) :
     XclExpBoolRecord( 0x000F, rDoc.GetAddressConvention() != formula::FormulaGrammar::CONV_XL_R1C1 )
diff --git a/sc/source/filter/xml/xmlbodyi.cxx b/sc/source/filter/xml/xmlbodyi.cxx
index f2dc908..1a190e3 100644
--- a/sc/source/filter/xml/xmlbodyi.cxx
+++ b/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,7 +63,10 @@
 #include <sal/types.h>
 #include <tools/debug.hxx>
 
+#include <memory>
+
 using rtl::OUString;
+
 using namespace com::sun::star;
 using namespace xmloff::token;
 
@@ -281,10 +285,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 a/sc/source/filter/xml/xmlexprt.cxx b/sc/source/filter/xml/xmlexprt.cxx
index 172e0ae..ef4fa69 100644
--- a/sc/source/filter/xml/xmlexprt.cxx
+++ b/sc/source/filter/xml/xmlexprt.cxx
@@ -69,6 +69,7 @@
 #include "postit.hxx"
 #include "externalrefmgr.hxx"
 #include "editutil.hxx"
+#include "tabprotection.hxx"
 
 #include <xmloff/xmltoken.hxx>
 #include <xmloff/xmlnmspe.hxx>
@@ -1469,7 +1470,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());
     }
@@ -1543,7 +1548,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());
                     }
diff --git a/sc/source/filter/xml/xmlsubti.cxx b/sc/source/filter/xml/xmlsubti.cxx
index 939c795..6464ee6 100644
--- a/sc/source/filter/xml/xmlsubti.cxx
+++ b/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;
@@ -616,13 +621,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 a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx
index 1a56661..c52e8d6 100644
--- a/sc/source/ui/docshell/docfunc.cxx
+++ b/sc/source/ui/docshell/docfunc.cxx
@@ -93,7 +93,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 -----------------------------------------------------------
 
@@ -3126,103 +3131,156 @@ 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 )
-    {
-        if (pDoc->IsDocProtected())
-            aOldPassword = pDoc->GetDocPassword();
-    }
-    else
+    ScDocument* pDoc = rDocShell.GetDocument();
+
+    pDoc->SetTabProtection(nTab, &rProtect);
+    if (pDoc->IsUndoEnabled())
     {
-        if (pDoc->IsTabProtected(nTab))
-            aOldPassword = pDoc->GetTabPassword(nTab);
-    }
+        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) );
 
-    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 )
-    {
-        uno::Sequence<sal_Int8> aPass;
-        if (rPassword.Len())
-            SvPasswordHelper::GetHashPassword(aPass, rPassword);
-
-        if (bUndo)
+    if (nTab == TABLEID_DOC)
+    {
+        // document protection
+        ScDocProtection aProtection;
+        aProtection.setProtected(true);
+        aProtection.setPassword(rPassword);
+        pDoc->SetDocProtection(&aProtection);
+        if (pDoc->IsUndoEnabled())
         {
-            rDocShell.GetUndoManager()->AddUndoAction(
-                        new ScUndoProtect( &rDocShell, nTab, TRUE, aPass ) );
+            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 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();
+        ScTableProtection aProtection;
+        aProtection.setProtected(true);
+        aProtection.setPassword(rPassword);
+        pDoc->SetTabProtection(nTab, &aProtection);
+        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 ScUndoDocProtect.
+        }
     }
-    else if (!bApi)
+    else
     {
-//!		rDocShell.ErrorMessage(...);
+        // sheet protection
+
+        ScTableProtection* pTabProtect = pDoc->GetTabProtection(nTab);
+        if (!pTabProtect || !pTabProtect->isProtected())
+            // already unprotected (should not happen)!
+            return true;
 
-        InfoBox aBox( rDocShell.GetActiveDialogParent(), String( ScResId( SCSTR_WRONGPASSWORD ) ) );
-        aBox.Execute();
+        // 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.
+        }
     }
 
-    return bOk;
+    rDocShell.PostPaintGridAll();
+    ScDocShellModificator aModificator( rDocShell );
+    aModificator.SetDocumentModified();
+
+    return true;
 }
 
 //------------------------------------------------------------------------
diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx
index 381a79c..8cb9ad8 100644
--- a/sc/source/ui/docshell/docsh.cxx
+++ b/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"
@@ -1327,6 +1322,16 @@ BOOL __EXPORT ScDocShell::SaveAs( SfxMedium& rMedium )
 {
     RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "nn93723", "ScDocShell::SaveAs" );
 
+#if ENABLE_SHEET_PROTECTION
+    ScTabViewShell* pViewShell = GetBestViewShell();
+    if (pViewShell && ScPassHashHelper::needsPassHashRegen(aDocument, PASSHASH_OOO))
+    {
+        if (!pViewShell->ExecuteRetypePassDlg(PASSHASH_OOO))
+            // password re-type cancelled.  Don't save the document.
+            return false;
+    }
+#endif
+
     ScRefreshTimerProtector( aDocument.GetRefreshTimerControlAddress() );
 
     PrepareSaveGuard aPrepareGuard( *this);
@@ -1792,7 +1797,6 @@ void ScDocShell::AsciiSave( SvStream& rStream, const ScImportOptions& rAsciiOpt
     rStream.SetNumberFormatInt( nOldNumberFormatInt );
 }
 
-
 BOOL __EXPORT ScDocShell::ConvertTo( SfxMedium &rMed )
 {
     RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "nn93723", "ScDocShell::ConvertTo" );
@@ -1846,15 +1850,39 @@ BOOL __EXPORT ScDocShell::ConvertTo( SfxMedium &rMed )
                 aDocument.SetExtDocOptions( pExtDocOpt = new ScExtDocOptions );
             pViewShell->GetViewData()->WriteExtOptions( *pExtDocOpt );
 
-            /*  #115980 #If the imported document contained an encrypted password -
-                determine if we should save without it. */
-            ScExtDocSettings& rDocSett = pExtDocOpt->GetDocSettings();
-            if( rDocSett.mbEncrypted )
+#if ENABLE_SHEET_PROTECTION
+            bool bNeedRetypePassDlg = ScPassHashHelper::needsPassHashRegen(aDocument, PASSHASH_XL);
+            if (bNeedRetypePassDlg && !pViewShell->ExecuteRetypePassDlg(PASSHASH_XL))
+            {
+                SetError( ERRCODE_ABORT );
+                return false;
+            }
+#else
+
+            do
             {
+                SfxItemSet* pSet = rMed.GetItemSet();
+                if (!pSet)
+                    break;
+                                                                                              
+                const SfxPoolItem* pItem = NULL;
+                if (SFX_ITEM_SET != pSet->GetItemState(SID_PASSWORD, sal_True, &pItem))
+                    // password is not set.
+                    break;
+
+                /*  #115980 #If the imported document contained an encrypted password -
+                    determine if we should save without it. */
                 bDoSave = ScWarnPassword::WarningOnPassword( rMed );
-                // #i42858# warn only on time
-                rDocSett.mbEncrypted = false;
+
+                if (bDoSave)
+                {
+                    // #i42858# warn only one time
+                    pSet->ClearItem(SID_PASSWORD);
+                }
             }
+            while (false);
+
+#endif            
         }
 
         if( bDoSave )
diff --git a/sc/source/ui/docshell/docsh5.cxx b/sc/source/ui/docshell/docsh5.cxx
index fef6618..e288b74 100644
--- a/sc/source/ui/docshell/docsh5.cxx
+++ b/sc/source/ui/docshell/docsh5.cxx
@@ -827,7 +827,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 a/sc/source/ui/inc/docfunc.hxx b/sc/source/ui/inc/docfunc.hxx
index 2995e81..beaa918 100644
--- a/sc/source/ui/inc/docfunc.hxx
+++ b/sc/source/ui/inc/docfunc.hxx
@@ -47,7 +47,7 @@ class ScRangeName;
 class ScBaseCell;
 class ScTokenArray;
 struct ScTabOpParam;
-
+class ScTableProtection;
 
 // ---------------------------------------------------------------------------
 
@@ -135,6 +135,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 a/sc/source/ui/inc/protectiondlg.hrc b/sc/source/ui/inc/protectiondlg.hrc
new file mode 100644
index 0000000..63cb9bf
--- /dev/null
+++ b/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 a/sc/source/ui/inc/protectiondlg.hxx b/sc/source/ui/inc/protectiondlg.hxx
new file mode 100644
index 0000000..263931f
--- /dev/null
+++ b/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 a/sc/source/ui/inc/retypepassdlg.hrc b/sc/source/ui/inc/retypepassdlg.hrc
new file mode 100644
index 0000000..2bd8d00
--- /dev/null
+++ b/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 a/sc/source/ui/inc/retypepassdlg.hxx b/sc/source/ui/inc/retypepassdlg.hxx
new file mode 100644
index 0000000..657773d
--- /dev/null
+++ b/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 SetDataFromDocument(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(size_t 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 a/sc/source/ui/inc/tabvwsh.hxx b/sc/source/ui/inc/tabvwsh.hxx
index 4e63d1c..f629097 100644
--- a/sc/source/ui/inc/tabvwsh.hxx
+++ b/sc/source/ui/inc/tabvwsh.hxx
@@ -39,6 +39,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 a/sc/source/ui/inc/undotab.hxx b/sc/source/ui/inc/undotab.hxx
index 6b3fc6a..f9e5764 100644
--- a/sc/source/ui/inc/undotab.hxx
+++ b/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 a/sc/source/ui/inc/viewfunc.hxx b/sc/source/ui/inc/viewfunc.hxx
index 48ddd43..072f832 100644
--- a/sc/source/ui/inc/viewfunc.hxx
+++ b/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 a/sc/source/ui/miscdlgs/makefile.mk b/sc/source/ui/miscdlgs/makefile.mk
index 988b288..66e1f33 100644
--- a/sc/source/ui/miscdlgs/makefile.mk
+++ b/sc/source/ui/miscdlgs/makefile.mk
@@ -78,7 +78,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        \
@@ -87,7 +89,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 = \
@@ -96,7 +100,9 @@ SRC1FILES = \
     highred.src					\
     linkarea.src                \
     conflictsdlg.src            \
-    sharedocdlg.src
+    sharedocdlg.src \
+    protectiondlg.src \
+    retypepassdlg.src
 
 LIB1TARGET = $(SLB)$/$(TARGET).lib
 
@@ -116,7 +122,9 @@ LIB1OBJFILES =  \
     $(SLO)$/redcom.obj			\
     $(SLO)$/warnbox.obj         \
     $(SLO)$/conflictsdlg.obj    \
-    $(SLO)$/sharedocdlg.obj
+    $(SLO)$/sharedocdlg.obj \
+    $(SLO)$/protectiondlg.obj \
+    $(SLO)$/retypepassdlg.obj
 
 # --- Tagets -------------------------------------------------------
 
diff --git a/sc/source/ui/miscdlgs/protectiondlg.cxx b/sc/source/ui/miscdlgs/protectiondlg.cxx
new file mode 100644
index 0000000..a5116ef
--- /dev/null
+++ b/sc/source/ui/miscdlgs/protectiondlg.cxx
@@ -0,0 +1,164 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sc.hxx"
+
+#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 a/sc/source/ui/miscdlgs/protectiondlg.src b/sc/source/ui/miscdlgs/protectiondlg.src
new file mode 100644
index 0000000..14a1c85
--- /dev/null
+++ b/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 a/sc/source/ui/miscdlgs/retypepassdlg.cxx b/sc/source/ui/miscdlgs/retypepassdlg.cxx
new file mode 100644
index 0000000..84a008f
--- /dev/null
+++ b/sc/source/ui/miscdlgs/retypepassdlg.cxx
@@ -0,0 +1,547 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sc.hxx"
+
+#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::SetDataFromDocument(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());
+
+    size_t nTabCount = static_cast<size_t>(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, static_cast< SCTAB >( 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(size_t 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, static_cast< SCTAB >( 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*, EMPTYARG )
+{
+    CheckPasswordInput();
+    return 0;
+}
+
+IMPL_LINK( ScRetypePassInputDlg, PasswordModifyHdl, Edit*, EMPTYARG )
+{
+    CheckPasswordInput();
+    return 0;
+}
diff --git a/sc/source/ui/miscdlgs/retypepassdlg.src b/sc/source/ui/miscdlgs/retypepassdlg.src
new file mode 100644
index 0000000..60ccfec
--- /dev/null
+++ b/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 password that cannot be exported.  Please re-type your password to be able to export your document." ;
+    };
+
+    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 a/sc/source/ui/undo/undotab.cxx b/sc/source/ui/undo/undotab.cxx
index 8eba3b1..af43a67 100644
--- a/sc/source/ui/undo/undotab.cxx
+++ b/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,96 +1169,153 @@ 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();
     if (pViewShell)
     {
         pViewShell->UpdateLayerLocks();
-        pViewShell->UpdateInputHandler(TRUE);	// damit sofort wieder eingegeben werden kann
+        pViewShell->UpdateInputHandler(TRUE);   // damit sofort wieder eingegeben werden kann
     }
 
     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
+    //  gippsnich
 }
 
-BOOL __EXPORT ScUndoProtect::CanRepeat(SfxRepeatTarget& /* rTarget */) const
+BOOL ScUndoDocProtect::CanRepeat(SfxRepeatTarget& /* rTarget */) const
 {
-    return FALSE;		// gippsnich
+    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)
 {
-    USHORT nId;
-    if ( nTab == TABLEID_DOC )
-        nId = bProtect ? STR_UNDO_PROTECT_DOC : STR_UNDO_UNPROTECT_DOC;
+}
+
+ScUndoTabProtect::~ScUndoTabProtect()
+{
+}
+
+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( formula::FormulaGrammar::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 a/sc/source/ui/unoobj/warnpassword.cxx b/sc/source/ui/unoobj/warnpassword.cxx
index a3a981e..1dac2f7 100644
--- a/sc/source/ui/unoobj/warnpassword.cxx
+++ b/sc/source/ui/unoobj/warnpassword.cxx
@@ -95,3 +95,4 @@ bool ScWarnPassword::WarningOnPassword( SfxMedium& rMedium )
     }
     return bReturn;
 }
+
diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx
index b08b068..8af1d2a 100644
--- a/sc/source/ui/view/gridwin.cxx
+++ b/sc/source/ui/view/gridwin.cxx
@@ -119,6 +119,7 @@
 #include "drwlayer.hxx"
 #include "attrib.hxx"
 #include "validat.hxx"
+#include "tabprotection.hxx"
 
 // #114409#
 #include <vcl/salbtype.hxx>		// FRound
@@ -2027,8 +2028,9 @@ 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() );
@@ -2070,16 +2072,34 @@ void __EXPORT ScGridWindow::MouseButtonUp( const MouseEvent& rMEvt )
             return;
         }
 
-        //	edit cell contents
-        pViewData->GetViewShell()->UpdateInputHandler();
-        pScMod->SetInputMode( SC_INPUT_TABLE );
-        if (pViewData->HasEditView(eWhich))
+        // 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 )
         {
-            //	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 );
+            //  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 a/sc/source/ui/view/scextopt.cxx b/sc/source/ui/view/scextopt.cxx
index 8ac6382..586f934 100644
--- a/sc/source/ui/view/scextopt.cxx
+++ b/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 a/sc/source/ui/view/select.cxx b/sc/source/ui/view/select.cxx
index 9eaf100..85547b6 100644
--- a/sc/source/ui/view/select.cxx
+++ b/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();
     ScTabViewShell* pViewShell = pViewData->GetViewShell();
     bool bRefMode = ( pViewShell ? pViewShell->IsRefInputMode() : false );
@@ -375,7 +396,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 &&
@@ -511,7 +531,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 a/sc/source/ui/view/tabview3.cxx b/sc/source/ui/view/tabview3.cxx
index 4c48695..1696bbb 100644
--- a/sc/source/ui/view/tabview3.cxx
+++ b/sc/source/ui/view/tabview3.cxx
@@ -79,6 +79,7 @@
 #include "AccessibilityHints.hxx"
 #include "rangeutl.hxx"
 #include "client.hxx"
+#include "tabprotection.hxx"
 
 #include <com/sun/star/chart2/data/HighlightedRange.hpp>
 
@@ -946,6 +947,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;
@@ -965,7 +977,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))
@@ -974,15 +986,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
                     {
@@ -995,7 +1012,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 );
@@ -1010,15 +1028,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
                     {
@@ -1031,7 +1054,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 a/sc/source/ui/view/tabvwsh3.cxx b/sc/source/ui/view/tabvwsh3.cxx
index a9250c9..d6b06c4 100644
--- a/sc/source/ui/view/tabvwsh3.cxx
+++ b/sc/source/ui/view/tabvwsh3.cxx
@@ -1,7 +1,7 @@
 /*************************************************************************
  *
  * 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
@@ -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
@@ -85,6 +87,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)
@@ -1009,12 +1015,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) );
 
@@ -1064,89 +1071,164 @@ void ScTabViewShell::Execute( SfxRequest& rReq )
 
 
         case FID_PROTECT_TABLE:
+        {
+            ScDocument* pDoc = GetViewData()->GetDocument();
+            SCTAB		nTab = GetViewData()->GetTabNo();
+            bool        bOldProtection = pDoc->IsTabProtected(nTab);
+
+#if ENABLE_SHEET_PROTECTION
+
+            if( pReqArgs )
             {
-                ScDocument* 		pDoc = GetViewData()->GetDocument();
-                SCTAB				nTab = GetViewData()->GetTabNo();
-                SfxPasswordDialog*	pDlg;
-                String				aPassword;
-                BOOL				bCancel = FALSE;
-                BOOL				bOldProtection = pDoc->IsTabProtected(nTab);
-                BOOL				bNewProtection = ! bOldProtection;
+                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( pReqArgs )
+            if (bOldProtection)
+            {
+                // Unprotect a protected sheet.
+
+                ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
+                if (pProtect && pProtect->isProtectedWithPass())
                 {
-                    const SfxPoolItem* pItem;
-                    if( IS_AVAILABLE( FID_PROTECT_TABLE, &pItem ) )
-                        bNewProtection = ((const SfxBoolItem*)pItem)->GetValue();
-                    if( bNewProtection == bOldProtection )
+                    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)
                     {
-                        rReq.Ignore();
-                        break;
+                        String aPassword = pDlg->GetPassword();
+                        Unprotect(nTab, aPassword);
                     }
                 }
+                else
+                    // this sheet is not password-protected.
+                    Unprotect(nTab, String());
 
-                    if ( bOldProtection)
-                    {
-                        if (pDoc->GetTabPassword(nTab).getLength())
-                        {
-                            String  aText( ScResId(SCSTR_PASSWORD) );
+                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_UNPROTECTTAB) );
-                            pDlg->SetMinLen( 0 );
-                            pDlg->SetHelpId( FID_PROTECT_TABLE );
-                            pDlg->SetEditHelpId( HID_PASSWD_TABLE );
+                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;
-                        }
-                    }
-                    else
-                    {
-                        String aText( ScResId(SCSTR_PASSWORDOPT) );
+                if (pDlg->Execute() == RET_OK)
+                {
+                    pScMod->InputEnterHandler();
 
-                        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 );
+                    ScTableProtection aNewProtect;
+                    pDlg->WriteData(aNewProtect);
+                    ProtectSheet(nTab, aNewProtect);
+                    if (!pReqArgs)
+                    {
+                        rReq.AppendItem( SfxBoolItem(FID_PROTECT_TABLE, true) );
+                        rReq.Done();
+                    }
+                }
+            }
+#else
+            auto_ptr<SfxPasswordDialog> pDlg;
+            String				aPassword;
+            BOOL				bCancel = FALSE;
+            bool                bNewProtection = ! bOldProtection;
 
-                        if (pDlg->Execute() == RET_OK)
-                            aPassword = pDlg->GetPassword();
-                        else
-                            bCancel = TRUE;
+            if( pReqArgs )
+            {
+                const SfxPoolItem* pItem;
+                if( IS_AVAILABLE( FID_PROTECT_TABLE, &pItem ) )
+                    bNewProtection = ((const SfxBoolItem*)pItem)->GetValue();
+                if( bNewProtection == bOldProtection )
+                {
+                    rReq.Ignore();
+                    break;
+                }
+            }
 
-                        delete pDlg;
-                    }
+            if ( bOldProtection)
+            {
+                // Unprotect a protected sheet.
 
-                if( !bCancel )
+                ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
+                if (pProtect && pProtect->isProtectedWithPass())
                 {
-                    if ( bOldProtection )
-                        Unprotect( nTab, aPassword );
+                    String aText( ScResId(SCSTR_PASSWORDOPT) );
+                    pDlg.reset(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
-                    {
-                        pScMod->InputEnterHandler();
+                        bCancel = TRUE;
+                }
 
-                        Protect( nTab, aPassword );
-                    }
+                if (!pReqArgs)
+                {
+                    rReq.AppendItem( SfxBoolItem(FID_PROTECT_TABLE, false) );
+                    rReq.Done();
+                }
+            }
+            else
+            {
+                String aText( ScResId(SCSTR_PASSWORDOPT) );
 
-                    if( !pReqArgs )
-                    {
-                        rReq.AppendItem( SfxBoolItem( FID_PROTECT_TABLE, bNewProtection ) );
-                        rReq.Done();
-                    }
+                pDlg.reset(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 );
+
+                if (pDlg->Execute() == RET_OK)
+                    aPassword = pDlg->GetPassword();
+                else
+                    bCancel = TRUE;
+            }
+
+            if( !bCancel )
+            {
+                if ( bOldProtection )
+                    Unprotect( nTab, aPassword );
+                else
+                {
+                    pScMod->InputEnterHandler();
+
+                    Protect( nTab, aPassword );
                 }
 
-                TabChanged();
-                UpdateInputHandler(TRUE);	// damit sofort wieder eingegeben werden kann
-                SelectionChanged();
+                if( !pReqArgs )
+                {
+                    rReq.AppendItem( SfxBoolItem( FID_PROTECT_TABLE, bNewProtection ) );
+                    rReq.Done();
+                }
             }
-            break;
+#endif
+            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 a/sc/source/ui/view/tabvwshh.cxx b/sc/source/ui/view/tabvwshh.cxx
index 5de767a..2f9f21f 100644
--- a/sc/source/ui/view/tabvwshh.cxx
+++ b/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->SetDataFromDocument(*pDoc);
+    pDlg->SetDesiredHash(eDesiredHash);
+    if (pDlg->Execute() != RET_OK)
+        return false;
+
+    pDlg->WriteNewDataToDocument(*pDoc);
+    return true;
+}
+
 
 
 
diff --git a/sc/source/ui/view/viewfun2.cxx b/sc/source/ui/view/viewfun2.cxx
index 1f91ce7..681f51c 100644
--- a/sc/source/ui/view/viewfun2.cxx
+++ b/sc/source/ui/view/viewfun2.cxx
@@ -2197,7 +2197,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);
@@ -2612,7 +2612,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 a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx
index f8a83cf..da65f46 100644
--- a/sc/source/ui/view/viewfunc.cxx
+++ b/sc/source/ui/view/viewfunc.cxx
@@ -2546,6 +2546,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();


More information about the ooo-build-commit mailing list