[Libreoffice-commits] .: Branch 'libreoffice-3-5' - 2 commits - sc/inc sc/qa sc/source

Markus Mohrhard mmohrhard at kemper.freedesktop.org
Fri Jan 6 16:44:40 PST 2012


 sc/inc/document.hxx                      |   12 -
 sc/inc/externalrefmgr.hxx                |   30 ++++
 sc/inc/globstr.hrc                       |    4 
 sc/inc/rangenam.hxx                      |    1 
 sc/inc/tokenarray.hxx                    |   15 ++
 sc/qa/unit/ucalc.cxx                     |    2 
 sc/source/core/data/cell.cxx             |   14 ++
 sc/source/core/data/documen2.cxx         |   24 ++-
 sc/source/core/data/document.cxx         |  195 +++++++++++--------------------
 sc/source/core/tool/rangenam.cxx         |    9 +
 sc/source/core/tool/reftokenhelper.cxx   |    5 
 sc/source/core/tool/token.cxx            |  174 +++++++++++++++++++++++++++
 sc/source/ui/docshell/docsh.cxx          |   31 ++--
 sc/source/ui/docshell/externalrefmgr.cxx |   86 +++++++++++++
 sc/source/ui/inc/namemgrtable.hxx        |    4 
 sc/source/ui/namedlg/namedlg.cxx         |    2 
 sc/source/ui/namedlg/namemgrtable.cxx    |    7 -
 sc/source/ui/namedlg/namepast.cxx        |    5 
 sc/source/ui/src/globstr.src             |    8 +
 sc/source/ui/view/viewfun2.cxx           |    5 
 20 files changed, 473 insertions(+), 160 deletions(-)

New commits:
commit 34b417914e041e93ddbf6035b855658d3b947636
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Thu Jan 5 17:26:25 2012 +0000

    handle relative refs in name dialogs correctly

diff --git a/sc/inc/rangenam.hxx b/sc/inc/rangenam.hxx
index 4b4f8d9..0e8de43 100644
--- a/sc/inc/rangenam.hxx
+++ b/sc/inc/rangenam.hxx
@@ -135,6 +135,7 @@ public:
     sal_uInt32      GetUnoType() const;
     SC_DLLPUBLIC void GetSymbol( String& rSymbol, const formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_DEFAULT ) const;
     SC_DLLPUBLIC void GetSymbol( rtl::OUString& rSymbol, const formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_DEFAULT ) const;
+    SC_DLLPUBLIC void GetSymbol( rtl::OUString& rSymbol, const ScAddress& rPos, const formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_DEFAULT ) const;
     void            UpdateSymbol( rtl::OUStringBuffer& rBuffer, const ScAddress&,
                                     const formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_DEFAULT );
     void            UpdateReference( UpdateRefMode eUpdateRefMode,
diff --git a/sc/source/core/tool/rangenam.cxx b/sc/source/core/tool/rangenam.cxx
index a471512..8ebcc76 100644
--- a/sc/source/core/tool/rangenam.cxx
+++ b/sc/source/core/tool/rangenam.cxx
@@ -277,6 +277,15 @@ void ScRangeData::GetSymbol( OUString& rSymbol, const FormulaGrammar::Grammar eG
     rSymbol = aStr;
 }
 
+void ScRangeData::GetSymbol( OUString& rSymbol, const ScAddress& rPos, const FormulaGrammar::Grammar eGrammar ) const
+{
+    String aStr;
+    ScCompiler aComp(pDoc, rPos, *pCode);
+    aComp.SetGrammar(eGrammar);
+    aComp.CreateStringFromTokenArray( aStr );
+    rSymbol = aStr;
+}
+
 void ScRangeData::UpdateSymbol( rtl::OUStringBuffer& rBuffer, const ScAddress& rPos,
                                 const FormulaGrammar::Grammar eGrammar )
 {
diff --git a/sc/source/ui/inc/namemgrtable.hxx b/sc/source/ui/inc/namemgrtable.hxx
index 3023e29..3646164 100644
--- a/sc/source/ui/inc/namemgrtable.hxx
+++ b/sc/source/ui/inc/namemgrtable.hxx
@@ -31,6 +31,7 @@
 #include <vcl/ctrl.hxx>
 
 #include "scresid.hxx"
+#include "address.hxx"
 
 #include <vector>
 #include <boost/ptr_container/ptr_map.hpp>
@@ -71,6 +72,7 @@ private:
     // otherwise opening the dialog with a lot of range names is extremelly slow because
     // we would calculate all formula strings during opening
     std::map<SvLBoxEntry*, bool> maCalculatedFormulaEntries;
+    const ScAddress maPos;
 
     void GetLine(ScRangeNameLine& aLine, SvLBoxEntry* pEntry);
     void Init();
@@ -78,7 +80,7 @@ private:
     const ScRangeData* findRangeData(const ScRangeNameLine& rLine);
 
 public:
-    ScRangeManagerTable( Window* pParent, boost::ptr_map<rtl::OUString, ScRangeName>& aTabRangeNames );
+    ScRangeManagerTable( Window* pParent, boost::ptr_map<rtl::OUString, ScRangeName>& aTabRangeNames, const ScAddress& rPos );
     virtual ~ScRangeManagerTable();
 
     void addEntry( const ScRangeNameLine& rLine, bool bSetCurEntry = true );
diff --git a/sc/source/ui/namedlg/namedlg.cxx b/sc/source/ui/namedlg/namedlg.cxx
index a485986..56c50e8 100644
--- a/sc/source/ui/namedlg/namedlg.cxx
+++ b/sc/source/ui/namedlg/namedlg.cxx
@@ -144,7 +144,7 @@ void ScNameDlg::Init()
     //init UI
     maFtInfo.SetStyle(WB_VCENTER);
 
-    mpRangeManagerTable = new ScRangeManagerTable(&maNameMgrCtrl, maRangeMap);
+    mpRangeManagerTable = new ScRangeManagerTable(&maNameMgrCtrl, maRangeMap, maCursorPos);
     mpRangeManagerTable->SetSelectHdl( LINK( this, ScNameDlg, SelectionChangedHdl_Impl ) );
     mpRangeManagerTable->SetDeselectHdl( LINK( this, ScNameDlg, SelectionChangedHdl_Impl ) );
 
diff --git a/sc/source/ui/namedlg/namemgrtable.cxx b/sc/source/ui/namedlg/namemgrtable.cxx
index 7f8eb6b..b9164d3 100644
--- a/sc/source/ui/namedlg/namemgrtable.cxx
+++ b/sc/source/ui/namedlg/namemgrtable.cxx
@@ -57,11 +57,12 @@ String createEntryString(const ScRangeNameLine& rLine)
     return aRet;
 }
 
-ScRangeManagerTable::ScRangeManagerTable( Window* pWindow, boost::ptr_map<rtl::OUString, ScRangeName>& rRangeMap ):
+ScRangeManagerTable::ScRangeManagerTable( Window* pWindow, boost::ptr_map<rtl::OUString, ScRangeName>& rRangeMap, const ScAddress& rPos ):
     SvTabListBox( pWindow, WB_SORT | WB_HSCROLL | WB_CLIPCHILDREN | WB_TABSTOP ),
     maHeaderBar( pWindow, WB_BUTTONSTYLE | WB_BOTTOMBORDER ),
     maGlobalString( ScGlobal::GetRscString(STR_GLOBAL_SCOPE)),
-    mrRangeMap( rRangeMap )
+    mrRangeMap( rRangeMap ),
+    maPos( rPos )
 {
     Size aBoxSize( pWindow->GetOutputSizePixel() );
 
@@ -172,7 +173,7 @@ void ScRangeManagerTable::CheckForFormulaString()
             GetLine( aLine, pEntry);
             const ScRangeData* pData = findRangeData( aLine );
             rtl::OUString aFormulaString;
-            pData->GetSymbol(aFormulaString);
+            pData->GetSymbol(aFormulaString, maPos);
             SetEntryText(aFormulaString, pEntry, 1);
             maCalculatedFormulaEntries.insert( std::pair<SvLBoxEntry*, bool>(pEntry, true) );
         }
diff --git a/sc/source/ui/namedlg/namepast.cxx b/sc/source/ui/namedlg/namepast.cxx
index 4193955..68a406f 100644
--- a/sc/source/ui/namedlg/namepast.cxx
+++ b/sc/source/ui/namedlg/namepast.cxx
@@ -38,6 +38,7 @@
 #include "docsh.hxx"
 #include "miscdlgs.hrc"
 #include "rangenam.hxx"
+#include "viewdata.hxx"
 
 
 //==================================================================
@@ -62,7 +63,9 @@ ScNamePasteDlg::ScNamePasteDlg( Window * pParent, ScDocShell* pShell, bool )
         aRangeMap.insert(aTemp, new ScRangeName(*itr->second));
     }
 
-    mpTable = new ScRangeManagerTable(&maCtrl, aRangeMap);
+    ScViewData* pViewData = pShell->GetViewData();
+    ScAddress aPos(pViewData->GetCurX(), pViewData->GetCurY(), pViewData->GetTabNo());
+    mpTable = new ScRangeManagerTable(&maCtrl, aRangeMap, aPos);
 
     maBtnPaste.SetClickHdl( LINK( this, ScNamePasteDlg, ButtonHdl) );
     maBtnPasteAll.SetClickHdl( LINK( this, ScNamePasteDlg, ButtonHdl));
commit 12e9d6aaf7b228fcec19200ba18a27070617413a
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Wed Jan 4 15:31:18 2012 +0100

    improve copy/paste between different documents
    
    Absolute sheet refs are transformed to external references pointing to
    the old document

diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index d39940f..83ad4a1 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -242,6 +242,7 @@ private:
     ScValidationDataList* pValidationList;              // validity
     SvNumberFormatterIndexTable*    pFormatExchangeList;    // for application of number formats
     TableContainer maTabs;
+    std::vector<rtl::OUString> maTabNames;               // for undo document, we need the information tab name <-> index
     mutable ScRangeName* pRangeName;
     ScDBCollection*     pDBCollection;
     ScDPCollection*     pDPCollection;
@@ -280,8 +281,9 @@ private:
     mutable ::std::auto_ptr< ScFormulaParserPool >
                         mxFormulaParserPool;            /// Pool for all external formula parsers used by this document.
 
-    rtl::OUString              aDocName;                       // optional: name of document
-    rtl::OUString              aDocCodeName;                       // optional: name of document (twice?)
+    rtl::OUString       aDocName;                       // optional: name of document
+    rtl::OUString       aDocCodeName;                       // optional: name of document (twice?)
+    rtl::OUString       maFileURL;      // file URL for copy & paste
     ScRangePairListRef  xColNameRanges;
     ScRangePairListRef  xRowNameRanges;
 
@@ -432,6 +434,7 @@ public:
     void            SetName( const rtl::OUString& r ) { aDocName = r; }
     const rtl::OUString&   GetCodeName() const { return aDocCodeName; }
     void                SetCodeName( const rtl::OUString& r ) { aDocCodeName = r; }
+    const rtl::OUString& GetFileURL() const { return maFileURL; }
 
     void            GetDocStat( ScDocStat& rDocStat );
 
@@ -533,6 +536,7 @@ public:
     SC_DLLPUBLIC bool GetCodeName( SCTAB nTab, rtl::OUString& rName ) const;
     SC_DLLPUBLIC bool SetCodeName( SCTAB nTab, const rtl::OUString& rName );
     SC_DLLPUBLIC bool GetTable( const rtl::OUString& rName, SCTAB& rTab ) const;
+    rtl::OUString   GetCopyTabName(SCTAB nTab) const;
 
     SC_DLLPUBLIC void SetAnonymousDBData(SCTAB nTab, ScDBData* pDBData);
     SC_DLLPUBLIC ScDBData* GetAnonymousDBData(SCTAB nTab);
@@ -1860,10 +1864,6 @@ private: // CLOOK-Impl-methods
 
     void    CopyRangeNamesToClip(ScDocument* pClipDoc, const ScRange& rClipRange, const ScMarkData* pMarks, bool bAllTabs);
     void    CopyRangeNamesToClip(ScDocument* pClipDoc, const ScRange& rClipRange, SCTAB nTab);
-    void    CopyRangeNamesFromClip(ScDocument* pClipDoc, ScClipRangeNameData& rRangeNames);
-    void    UpdateRangeNamesInFormulas(
-        ScClipRangeNameData& rRangeNames, const ScRangeList& rDestRanges, const ScMarkData& rMark,
-        SCCOL nXw, SCROW nYw);
 
     bool    HasPartOfMerged( const ScRange& rRange );
 
diff --git a/sc/inc/externalrefmgr.hxx b/sc/inc/externalrefmgr.hxx
index e39ac2e..c44c8f1 100644
--- a/sc/inc/externalrefmgr.hxx
+++ b/sc/inc/externalrefmgr.hxx
@@ -33,9 +33,11 @@
 #include "address.hxx"
 #include "sfx2/objsh.hxx"
 #include "sfx2/lnkbase.hxx"
+#include "sfx2/event.hxx"
 #include "tools/time.hxx"
 #include "vcl/timer.hxx"
 #include "svl/zforlist.hxx"
+#include "svl/lstner.hxx"
 #include "scmatrix.hxx"
 #include "rangelst.hxx"
 #include "formula/token.hxx"
@@ -46,6 +48,7 @@
 #include <vector>
 #include <list>
 #include <set>
+#include <iostream>
 #include <formula/ExternalReferenceHelper.hxx>
 
 class ScDocument;
@@ -353,7 +356,7 @@ private:
     mutable DocDataType maDocs;
 };
 
-class SC_DLLPUBLIC ScExternalRefManager : public formula::ExternalReferenceHelper
+class SC_DLLPUBLIC ScExternalRefManager : public formula::ExternalReferenceHelper, SfxListener
 {
 public:
 
@@ -426,6 +429,7 @@ public:
         ::rtl::OUString maRelativeName;
         ::rtl::OUString maFilterName;
         ::rtl::OUString maFilterOptions;
+        bool bUnsaved;
 
         void maybeCreateRealFileName(const String& rOwnDocName);
     };
@@ -673,6 +677,23 @@ public:
      */
     bool isFileLoadable(const ::rtl::OUString& rFile) const;
 
+    /**
+     * If in maUnsavedDocShells move it to maDocShells and create a correct
+     * external reference entry
+     *
+     * @param Pointer to the newly saved DocumentShell
+     */
+    void transformUnsavedRefToSavedRef( SfxObjectShell* pShell );
+
+    virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
+
+    /**
+     * If we still contain unsaved files we should warn the user before saving
+     *
+     * @return true if the document still contains references to an unsaved file
+     */
+    bool containsUnsavedReferences() { return !maUnsavedDocShells.empty(); }
+
 private:
     ScExternalRefManager();
     ScExternalRefManager(const ScExternalRefManager&);
@@ -749,6 +770,7 @@ private:
 
     sal_uInt32 getMappedNumberFormat(sal_uInt16 nFileId, sal_uInt32 nNumFmt, const ScDocument* pSrcDoc);
 
+
 private:
     /** cache of referenced ranges and names from source documents. */
     ScExternalRefCache maRefCache;
@@ -761,6 +783,12 @@ private:
      */
     DocShellMap maDocShells;
 
+    /**
+     * DocShells to unsaved but referenced documents. If not empty ask before saving!
+     * Move to maDocShells if document referenced here is saved
+     */
+    DocShellMap maUnsavedDocShells;
+
     /** list of source documents that are managed by the link manager. */
     LinkedDocMap maLinkedDocs;
 
diff --git a/sc/inc/globstr.hrc b/sc/inc/globstr.hrc
index 2363aaf..48f4015 100644
--- a/sc/inc/globstr.hrc
+++ b/sc/inc/globstr.hrc
@@ -599,8 +599,10 @@
 #define STR_ERR_NAME_EXISTS         463
 #define STR_ERR_NAME_INVALID        464
 
+#define STR_UNSAVED_EXT_REF         465
+#define STR_CLOSE_WITH_UNSAVED_REFS 466
 
-#define STR_COUNT                   465
+#define STR_COUNT                   467
 
 
 #endif
diff --git a/sc/inc/tokenarray.hxx b/sc/inc/tokenarray.hxx
index b2f4565..48bf4c5 100644
--- a/sc/inc/tokenarray.hxx
+++ b/sc/inc/tokenarray.hxx
@@ -95,6 +95,21 @@ public:
     void            ReadjustRelative3DReferences(
                                 const ScAddress& rOldPos,
                                 const ScAddress& rNewPos );
+
+    /**
+     * Make all absolute references external references pointing to the old document
+     *
+     * @param pOldDoc old document
+     * @param pNewDoc new document
+     * @param rPos position of the cell to determine if the reference is in the copied area
+     * @param bRangeName set for range names, range names have special handling for absolute sheet ref + relative col/row ref
+     */
+    void ReadjustAbsolute3DReferences( const ScDocument* pOldDoc, const ScDocument* pNewDoc, const ScAddress& rPos, bool bRangeName = false );
+
+    /**
+     * Make all absolute references pointing to the copied range if the range is copied too
+     */
+    void AdjustAbsoluteRefs( const ScDocument* pOldDoc, const ScAddress& rOldPos, const ScAddress& rNewPos, bool bRangeName = false );
 };
 
 #endif // SC_TOKENARRAY_HXX
diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index 724dced..5471c47 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -2746,8 +2746,8 @@ void Test::testCopyPaste()
     //check values after copying
     rtl::OUString aString;
     m_pDoc->GetValue(1,1,1, aValue);
-    CPPUNIT_ASSERT_MESSAGE("copied formula should return 2", aValue == 2);
     m_pDoc->GetFormula(1,1,1, aString);
+    CPPUNIT_ASSERT_MESSAGE("copied formula should return 2", aValue == 2);
     CPPUNIT_ASSERT_MESSAGE("formula string was not copied correctly", aString == aFormulaString);
     m_pDoc->GetValue(0,1,1, aValue);
     CPPUNIT_ASSERT_MESSAGE("copied value should be 1", aValue == 1);
diff --git a/sc/source/core/data/cell.cxx b/sc/source/core/data/cell.cxx
index 6cc8209..155f4bd 100644
--- a/sc/source/core/data/cell.cxx
+++ b/sc/source/core/data/cell.cxx
@@ -179,6 +179,13 @@ void adjustRangeName(ScToken* pToken, ScDocument& rNewDoc, const ScDocument* pOl
     {
         bNewGlobal = bOldGlobal;
         pRangeData = new ScRangeData(*pOldRangeData, &rNewDoc);
+        ScTokenArray* pRangeNameToken = pRangeData->GetCode();
+        if (rNewDoc.GetPool() != const_cast<ScDocument*>(pOldDoc)->GetPool())
+        {
+            pRangeNameToken->ReadjustAbsolute3DReferences(pOldDoc, &rNewDoc, pRangeData->GetPos(), true);
+            pRangeNameToken->AdjustAbsoluteRefs(pOldDoc, aOldPos, aNewPos, true);
+        }
+
         bool bInserted;
         if (bNewGlobal)
             bInserted = rNewDoc.GetRangeName()->insert(pRangeData);
@@ -881,6 +888,13 @@ ScFormulaCell::ScFormulaCell( const ScFormulaCell& rCell, ScDocument& rDoc, cons
                     adjustDBRange(pToken, rDoc, rCell.pDocument);
             }
         }
+
+        if (pDocument->GetPool() != rCell.pDocument->GetPool())
+        {
+            pCode->ReadjustAbsolute3DReferences( rCell.pDocument, &rDoc, rCell.aPos);
+        }
+
+        pCode->AdjustAbsoluteRefs( rCell.pDocument, rCell.aPos, aPos );
     }
 
     if( !bCompile )
diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx
index 37005ee..aa99070 100644
--- a/sc/source/core/data/documen2.cxx
+++ b/sc/source/core/data/documen2.cxx
@@ -41,6 +41,7 @@
 #include <svx/svdobj.hxx>
 #include <sfx2/bindings.hxx>
 #include <sfx2/objsh.hxx>
+#include <sfx2/docfile.hxx>
 #include <sfx2/printer.hxx>
 #include <svl/zforlist.hxx>
 #include <svl/zformat.hxx>
@@ -48,6 +49,7 @@
 #include <comphelper/processfactory.hxx>
 #include <svl/PasswordHelper.hxx>
 #include <tools/tenccvt.hxx>
+#include <tools/urlobj.hxx>
 #include <rtl/crc.h>
 #include <basic/basmgr.hxx>
 
@@ -920,8 +922,21 @@ sal_uLong ScDocument::TransferTab( ScDocument* pSrcDoc, SCTAB nSrcPos,
                                 bool bResultsOnly )
 {
     sal_uLong nRetVal = 1;                      // 0 => Fehler 1 = ok
-                                            // 2 => RefBox, 3 => NameBox
+                                            // 3 => NameBox
                                             // 4 => beides
+
+    if (pSrcDoc->pShell->GetMedium())
+    {
+        pSrcDoc->maFileURL = pSrcDoc->pShell->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DECODE_TO_IURI);
+        // for unsaved files use the title name and adjust during save of file
+        if (pSrcDoc->maFileURL.isEmpty())
+            pSrcDoc->maFileURL = pSrcDoc->pShell->GetName();
+    }
+    else
+    {
+        pSrcDoc->maFileURL = pSrcDoc->pShell->GetName();
+    }
+
     bool bValid = true;
     if (bInsertNew)             // neu einfuegen
     {
@@ -1046,15 +1061,8 @@ sal_uLong ScDocument::TransferTab( ScDocument* pSrcDoc, SCTAB nSrcPos,
             maTabs[nDestPos]->UpdateReference(URM_COPY, 0, 0, nDestPos,
                                                      MAXCOL, MAXROW, nDestPos,
                                                      0, 0, nDz, NULL);
-            // Test for outside absolute references for info box
-            bool bIsAbsRef = pSrcDoc->maTabs[nSrcPos]->TestTabRefAbs(nSrcPos);
             // Readjust self-contained absolute references to this sheet
             maTabs[nDestPos]->TestTabRefAbs(nSrcPos);
-            if (bIsAbsRef)
-            {
-                nRetVal += 1;
-                    // InfoBox AbsoluteRefs sind moeglicherweise nicht mehr korrekt!!
-            }
             if (bNamesLost)
             {
                 nRetVal += 2;
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index efb003b..eb03a74 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -42,12 +42,14 @@
 #include <svx/svdocapt.hxx>
 #include <sfx2/app.hxx>
 #include <sfx2/objsh.hxx>
+#include <sfx2/docfile.hxx>
 #include <svl/poolcach.hxx>
 #include <unotools/saveopt.hxx>
 #include <svl/zforlist.hxx>
 #include <unotools/charclass.hxx>
 #include <unotools/transliterationwrapper.hxx>
 #include <tools/tenccvt.hxx>
+#include <tools/urlobj.hxx>
 
 #include <com/sun/star/text/WritingMode2.hpp>
 #include <com/sun/star/script/vba/XVBACompatibility.hpp>
@@ -97,6 +99,9 @@
 #include <map>
 #include <limits>
 
+#include <rtl/oustringostreaminserter.hxx>
+#include <iostream>
+
 using ::editeng::SvxBorderLine;
 using namespace ::com::sun::star;
 
@@ -180,6 +185,14 @@ bool ScDocument::GetName( SCTAB nTab, rtl::OUString& rName ) const
     return false;
 }
 
+rtl::OUString ScDocument::GetCopyTabName( SCTAB nTab ) const
+{
+    if (nTab < static_cast<SCTAB>(maTabNames.size()))
+        return maTabNames[nTab];
+    else
+        return rtl::OUString();
+}
+
 bool ScDocument::SetCodeName( SCTAB nTab, const rtl::OUString& rName )
 {
     if (VALIDTAB(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
@@ -1675,6 +1688,7 @@ void ScDocument::InitUndoSelected( ScDocument* pSrcDoc, const ScMarkData& rTabSe
 
         xPoolHelper = pSrcDoc->xPoolHelper;
 
+
         rtl::OUString aString;
         for (SCTAB nTab = 0; nTab <= rTabSelection.GetLastSelected(); nTab++)
             if ( rTabSelection.GetTableSelect( nTab ) )
@@ -1694,9 +1708,9 @@ void ScDocument::InitUndoSelected( ScDocument* pSrcDoc, const ScMarkData& rTabSe
             }
     }
     else
-        {
+    {
         OSL_FAIL("InitUndo");
-        }
+    }
 }
 
 
@@ -1708,6 +1722,12 @@ void ScDocument::InitUndo( ScDocument* pSrcDoc, SCTAB nTab1, SCTAB nTab2,
         Clear();
 
         xPoolHelper = pSrcDoc->xPoolHelper;
+        if (pSrcDoc->pShell->GetMedium())
+        {
+            maFileURL = pSrcDoc->pShell->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DECODE_TO_IURI);
+            std::cout << "SfxMedium: " << maFileURL << std::endl;
+            std::cout << "GetName: " << rtl::OUString(pSrcDoc->pShell->GetName()) << std::endl;
+        }
 
         rtl::OUString aString;
         if ( nTab2 >= static_cast<SCTAB>(maTabs.size()))
@@ -1893,6 +1913,31 @@ void ScDocument::CopyToClip(const ScClipParam& rClipParam,
         pClipDoc = SC_MOD()->GetClipDoc();
     }
 
+    if (pShell->GetMedium())
+    {
+        pClipDoc->maFileURL = pShell->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DECODE_TO_IURI);
+        // for unsaved files use the title name and adjust during save of file
+        if (pClipDoc->maFileURL.isEmpty())
+            pClipDoc->maFileURL = pShell->GetName();
+    }
+    else
+    {
+        pClipDoc->maFileURL = pShell->GetName();
+    }
+
+    //init maTabNames
+    for (TableContainer::iterator itr = maTabs.begin(); itr != maTabs.end(); ++itr)
+    {
+        if( *itr )
+        {
+            rtl::OUString aTabName;
+            (*itr)->GetName(aTabName);
+            pClipDoc->maTabNames.push_back(aTabName);
+        }
+        else
+            pClipDoc->maTabNames.push_back(rtl::OUString());
+    }
+
     pClipDoc->aDocName = aDocName;
     pClipDoc->SetClipParam(rClipParam);
     ScRange aClipRange = rClipParam.getWholeRange();
@@ -1943,6 +1988,31 @@ void ScDocument::CopyTabToClip(SCCOL nCol1, SCROW nRow1,
 {
     if (!bIsClip)
     {
+        if (pShell->GetMedium())
+        {
+            pClipDoc->maFileURL = pShell->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DECODE_TO_IURI);
+            // for unsaved files use the title name and adjust during save of file
+            if (pClipDoc->maFileURL.isEmpty())
+                pClipDoc->maFileURL = pShell->GetName();
+        }
+        else
+        {
+            pClipDoc->maFileURL = pShell->GetName();
+        }
+
+        //init maTabNames
+        for (TableContainer::iterator itr = maTabs.begin(); itr != maTabs.end(); ++itr)
+        {
+            if( *itr )
+            {
+                rtl::OUString aTabName;
+                (*itr)->GetName(aTabName);
+                pClipDoc->maTabNames.push_back(aTabName);
+            }
+            else
+                pClipDoc->maTabNames.push_back(rtl::OUString());
+        }
+
         PutInOrder( nCol1, nCol2 );
         PutInOrder( nRow1, nRow2 );
         if (!pClipDoc)
@@ -2114,116 +2184,6 @@ void ScDocument::MergeNumberFormatter(ScDocument* pSrcDoc)
     }
 }
 
-void ScDocument::CopyRangeNamesFromClip(ScDocument* pClipDoc, ScClipRangeNameData& rRangeNames)
-{
-    if (!pClipDoc->pRangeName)
-        return;
-
-    ScClipRangeNameData aClipRangeNames;
-
-    ScRangeName::const_iterator itr = pClipDoc->pRangeName->begin();
-    ScRangeName::const_iterator itrEnd = pClipDoc->pRangeName->end();
-    for (; itr != itrEnd; ++itr)        //! DB-Bereiche Pivot-Bereiche auch
-    {
-        /*  Copy only if the name doesn't exist in this document.
-            If it exists we use the already existing name instead,
-            another possibility could be to create new names if
-            documents differ.
-            A proper solution would ask the user how to proceed.
-            The adjustment of the indices in the formulas is done later.
-        */
-        const ScRangeData* pExistingData = GetRangeName()->findByUpperName(itr->first);
-        if (pExistingData)
-        {
-            sal_uInt16 nOldIndex = itr->second->GetIndex();
-            sal_uInt16 nNewIndex = pExistingData->GetIndex();
-            aClipRangeNames.insert(nOldIndex, nNewIndex);
-            if ( !aClipRangeNames.mbReplace )
-                aClipRangeNames.mbReplace = ( nOldIndex != nNewIndex );
-        }
-        else
-        {
-            ScRangeData* pData = new ScRangeData( *itr->second );
-            pData->SetDocument(this);
-            if ( pRangeName->findByIndex( pData->GetIndex() ) )
-                pData->SetIndex(0);     // need new index, done in Insert
-            if ( pRangeName->insert(pData) )
-            {
-                aClipRangeNames.mpRangeNames.push_back(pData);
-                sal_uInt16 nOldIndex = itr->second->GetIndex();
-                sal_uInt16 nNewIndex = pData->GetIndex();
-                aClipRangeNames.insert(nOldIndex, nNewIndex);
-                if ( !aClipRangeNames.mbReplace )
-                    aClipRangeNames.mbReplace = ( nOldIndex != nNewIndex );
-            }
-            else
-            {   // must be an overflow
-                pData = NULL;
-                aClipRangeNames.insert(itr->second->GetIndex(), 0);
-                aClipRangeNames.mbReplace = true;
-            }
-        }
-    }
-    rRangeNames = aClipRangeNames;
-}
-
-void ScDocument::UpdateRangeNamesInFormulas(
-    ScClipRangeNameData& rRangeNames, const ScRangeList& rDestRanges, const ScMarkData& rMark,
-    SCCOL nXw, SCROW nYw)
-{
-    // nXw and nYw are the extra width and height of the destination range
-    // extended due to presence of merged cell(s).
-
-    if (!rRangeNames.mbReplace)
-        return;
-
-    // first update all inserted named formulas if they contain other
-    // range names and used indices changed
-    for (size_t i = 0, n = rRangeNames.mpRangeNames.size(); i < n; ++i)        //! DB-Bereiche Pivot-Bereiche auch
-    {
-        rRangeNames.mpRangeNames[i]->ReplaceRangeNamesInUse(rRangeNames.maRangeMap);
-    }
-    // then update the formulas, they might need just the updated range names
-    for ( size_t nRange = 0, n = rDestRanges.size(); nRange < n; ++nRange )
-    {
-        const ScRange* pRange = rDestRanges[nRange];
-        SCCOL nCol1 = pRange->aStart.Col();
-        SCROW nRow1 = pRange->aStart.Row();
-        SCCOL nCol2 = pRange->aEnd.Col();
-        SCROW nRow2 = pRange->aEnd.Row();
-
-        SCCOL nC1 = nCol1;
-        SCROW nR1 = nRow1;
-        SCCOL nC2 = nC1 + nXw;
-        if (nC2 > nCol2)
-            nC2 = nCol2;
-        SCROW nR2 = nR1 + nYw;
-        if (nR2 > nRow2)
-            nR2 = nRow2;
-        do
-        {
-            do
-            {
-                ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
-                for (; itr != itrEnd; ++itr)
-                {
-                    if ( maTabs[*itr] )
-                        maTabs[*itr]->ReplaceRangeNamesInUse(nC1, nR1,
-                            nC2, nR2, rRangeNames.maRangeMap);
-                }
-                nC1 = nC2 + 1;
-                nC2 = Min((SCCOL)(nC1 + nXw), nCol2);
-            } while (nC1 <= nCol2);
-            nC1 = nCol1;
-            nC2 = nC1 + nXw;
-            if (nC2 > nCol2)
-                nC2 = nCol2;
-            nR1 = nR2 + 1;
-            nR2 = Min((SCROW)(nR1 + nYw), nRow2);
-        } while (nR1 <= nRow2);
-    }
-}
-
 ScClipParam& ScDocument::GetClipParam()
 {
     if (!mpClipParam.get())
@@ -2428,9 +2388,6 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar
 
             NumFmtMergeHandler aNumFmtMergeHdl(this, pClipDoc);
 
-            ScClipRangeNameData aClipRangeNames;
-            CopyRangeNamesFromClip(pClipDoc, aClipRangeNames);
-
             SCCOL nAllCol1 = rDestRange.aStart.Col();
             SCROW nAllRow1 = rDestRange.aStart.Row();
             SCCOL nAllCol2 = rDestRange.aEnd.Col();
@@ -2587,8 +2544,6 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar
 
             bInsertingFromOtherDoc = false;
 
-            UpdateRangeNamesInFormulas(aClipRangeNames, *pDestRanges, rMark, nXw, nYw);
-
             // Listener aufbauen nachdem alles inserted wurde
             StartListeningFromClip( nAllCol1, nAllRow1, nAllCol2, nAllRow2, rMark, nInsFlag );
             // nachdem alle Listener aufgebaut wurden, kann gebroadcastet werden
@@ -2631,9 +2586,6 @@ void ScDocument::CopyMultiRangeFromClip(
 
     NumFmtMergeHandler aNumFmtMergeHdl(this, pClipDoc);
 
-    ScClipRangeNameData aClipRangeNames;
-    CopyRangeNamesFromClip(pClipDoc, aClipRangeNames);
-
     SCCOL nCol1 = rDestPos.Col();
     SCROW nRow1 = rDestPos.Row();
     ScClipParam& rClipParam = pClipDoc->GetClipParam();
@@ -2728,9 +2680,6 @@ void ScDocument::CopyMultiRangeFromClip(
 
     ScRangeList aRanges;
     aRanges.Append(aDestRange);
-    SCCOL nCols = aDestRange.aEnd.Col() - aDestRange.aStart.Col() + 1;
-    SCROW nRows = aDestRange.aEnd.Row() - aDestRange.aStart.Row() + 1;
-    UpdateRangeNamesInFormulas(aClipRangeNames, aRanges, rMark, nCols-1, nRows-1);
 
     // Listener aufbauen nachdem alles inserted wurde
     StartListeningFromClip(aDestRange.aStart.Col(), aDestRange.aStart.Row(),
diff --git a/sc/source/core/tool/reftokenhelper.cxx b/sc/source/core/tool/reftokenhelper.cxx
index 7528257..2a32e12 100644
--- a/sc/source/core/tool/reftokenhelper.cxx
+++ b/sc/source/core/tool/reftokenhelper.cxx
@@ -136,6 +136,9 @@ void ScRefTokenHelper::compileRangeRepresentation(
         rRefTokens.clear();
 }
 
+namespace {
+
+//may return a relative address
 void singleRefToAddr(const ScSingleRefData& rRef, ScAddress& rAddr)
 {
     rAddr.SetCol(rRef.nCol);
@@ -143,6 +146,8 @@ void singleRefToAddr(const ScSingleRefData& rRef, ScAddress& rAddr)
     rAddr.SetTab(rRef.nTab);
 }
 
+}
+
 bool ScRefTokenHelper::getRangeFromToken(ScRange& rRange, const ScTokenRef& pToken, bool bExternal)
 {
     StackVar eType = pToken->GetType();
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index 1178022..68de154 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -37,9 +37,12 @@
 #include <string.h>
 #include <tools/mempool.hxx>
 #include <osl/diagnose.h>
+#include <sfx2/docfile.hxx>
 
 #include "token.hxx"
 #include "tokenarray.hxx"
+#include "reftokenhelper.hxx"
+#include "clipparam.hxx"
 #include "compiler.hxx"
 #include <formula/compiler.hrc>
 #include "rechead.hxx"
@@ -1815,5 +1818,176 @@ void ScTokenArray::ReadjustRelative3DReferences( const ScAddress& rOldPos,
     }
 }
 
+namespace {
+
+void GetExternalTableData(const ScDocument* pOldDoc, const ScDocument* pNewDoc, const SCTAB nTab, rtl::OUString& rTabName, sal_uInt16& rFileId)
+{
+    rtl::OUString aFileName = pOldDoc->GetFileURL();;
+    rFileId = pNewDoc->GetExternalRefManager()->getExternalFileId(aFileName);
+    rTabName = pOldDoc->GetCopyTabName(nTab);
+    if (rTabName.isEmpty())
+        pOldDoc->GetName(nTab, rTabName);
+}
+
+bool IsInCopyRange( const ScRange& rRange, const ScDocument* pClipDoc )
+{
+    ScClipParam& rClipParam = const_cast<ScDocument*>(pClipDoc)->GetClipParam();
+    return rClipParam.maRanges.In(rRange);
+}
+
+bool SkipReference(ScToken* pToken, const ScAddress& rPos, const ScDocument* pOldDoc, bool bRangeName)
+{
+    ScRange aRange;
+
+    pToken->CalcAbsIfRel(rPos);
+    if (!ScRefTokenHelper::getRangeFromToken(aRange, pToken))
+        return true;
+
+    if (bRangeName && aRange.aStart.Tab() == rPos.Tab())
+    {
+        switch (pToken->GetType())
+        {
+            case svDoubleRef:
+                {
+                    ScSingleRefData& rRef = pToken->GetSingleRef2();
+                    if (rRef.IsColRel() || rRef.IsRowRel())
+                        return true;
+                } // fall through
+            case svSingleRef:
+                {
+                    ScSingleRefData& rRef = pToken->GetSingleRef();
+                    if (rRef.IsColRel() || rRef.IsRowRel())
+                        return true;
+                }
+                break;
+            default:
+                break;
+        }
+    }
+
+    if (IsInCopyRange(aRange, pOldDoc))
+        return true;
+
+    return false;
+}
+
+void AdjustSingleRefData( ScSingleRefData& rRef, const ScAddress& rOldPos, const ScAddress& rNewPos)
+{
+    SCsCOL nCols = rNewPos.Col() - rOldPos.Col();
+    SCsROW nRows = rNewPos.Row() - rOldPos.Row();
+    SCsTAB nTabs = rNewPos.Tab() - rOldPos.Tab();
+
+    if (!rRef.IsColRel())
+        rRef.nCol += nCols;
+
+    if (!rRef.IsRowRel())
+        rRef.nRow += nRows;
+
+    if (!rRef.IsTabRel())
+        rRef.nTab += nTabs;
+}
+
+}
+
+void ScTokenArray::ReadjustAbsolute3DReferences( const ScDocument* pOldDoc, const ScDocument* pNewDoc, const ScAddress& rPos, bool bRangeName )
+{
+    for ( sal_uInt16 j=0; j<nLen; ++j )
+    {
+        switch ( pCode[j]->GetType() )
+        {
+            case svDoubleRef :
+            {
+                if (SkipReference(static_cast<ScToken*>(pCode[j]), rPos, pOldDoc, bRangeName))
+                    continue;
+
+                ScComplexRefData& rRef = static_cast<ScToken*>(pCode[j])->GetDoubleRef();
+                ScSingleRefData& rRef2 = rRef.Ref2;
+                ScSingleRefData& rRef1 = rRef.Ref1;
+
+                if ( (rRef2.IsFlag3D() && !rRef2.IsTabRel()) || (rRef1.IsFlag3D() && !rRef1.IsTabRel()) )
+                {
+                    rtl::OUString aTabName;
+                    sal_uInt16 nFileId;
+                    GetExternalTableData(pOldDoc, pNewDoc, rRef1.nTab, aTabName, nFileId);
+                    pCode[j]->DecRef();
+                    ScExternalDoubleRefToken* pToken = new ScExternalDoubleRefToken(nFileId, aTabName, rRef);
+                    pToken->IncRef();
+                    pCode[j] = pToken;
+                }
+            }
+            break;
+            case svSingleRef :
+            {
+                if (SkipReference(static_cast<ScToken*>(pCode[j]), rPos, pOldDoc, bRangeName))
+                    continue;
+
+                ScSingleRefData& rRef = static_cast<ScToken*>(pCode[j])->GetSingleRef();
+
+                if ( rRef.IsFlag3D() && !rRef.IsTabRel() )
+                {
+                    rtl::OUString aTabName;
+                    sal_uInt16 nFileId;
+                    GetExternalTableData(pOldDoc, pNewDoc, rRef.nTab, aTabName, nFileId);
+                    //replace with ScExternalSingleRefToken and adjust references
+                    pCode[j]->DecRef();
+                    ScExternalSingleRefToken* pToken = new ScExternalSingleRefToken(nFileId, aTabName, rRef);
+                    pToken->IncRef();
+                    pCode[j] = pToken;
+                }
+            }
+            break;
+            default:
+            {
+                // added to avoid warnings
+            }
+        }
+    }
+}
+
+void ScTokenArray::AdjustAbsoluteRefs( const ScDocument* pOldDoc, const ScAddress& rOldPos, const ScAddress& rNewPos, bool bRangeName)
+{
+    for ( sal_uInt16 j=0; j<nLen; ++j )
+    {
+        switch ( pCode[j]->GetType() )
+        {
+            case svDoubleRef :
+            {
+                if (!SkipReference(static_cast<ScToken*>(pCode[j]), rOldPos, pOldDoc, false))
+                    continue;
+
+                ScComplexRefData& rRef = static_cast<ScToken*>(pCode[j])->GetDoubleRef();
+                ScSingleRefData& rRef2 = rRef.Ref2;
+                ScSingleRefData& rRef1 = rRef.Ref1;
+
+                // for range names only adjust if all parts are absolute
+                if (!bRangeName || !(rRef1.IsColRel() || rRef1.IsRowRel() || rRef1.IsTabRel()))
+                    AdjustSingleRefData( rRef1, rOldPos, rNewPos );
+                if (!bRangeName || !(rRef2.IsColRel() || rRef2.IsRowRel() || rRef2.IsTabRel()))
+                    AdjustSingleRefData( rRef2, rOldPos, rNewPos );
+
+            }
+            break;
+            case svSingleRef :
+            {
+                if (!SkipReference(static_cast<ScToken*>(pCode[j]), rOldPos, pOldDoc, false))
+                    continue;
+
+                ScSingleRefData& rRef = static_cast<ScToken*>(pCode[j])->GetSingleRef();
+
+                // for range names only adjust if all parts are absolute
+                if (!bRangeName || !(rRef.IsColRel() || rRef.IsRowRel() || rRef.IsTabRel()))
+                    AdjustSingleRefData( rRef, rOldPos, rNewPos );
+
+
+            }
+            break;
+            default:
+            {
+                // added to avoid warnings
+            }
+        }
+    }
+}
+
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx
index 9fa5769..8f4f3fc 100644
--- a/sc/source/ui/docshell/docsh.cxx
+++ b/sc/source/ui/docshell/docsh.cxx
@@ -913,11 +913,25 @@ void ScDocShell::Notify( SfxBroadcaster&, const SfxHint& rHint )
                         if ( !bSuccess )
                             SetError( ERRCODE_IO_ABORT, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); // this error code will produce no error message, but will break the further saving process
                     }
+
+
                     if (pSheetSaveData)
                         pSheetSaveData->SetInSupportedSave(true);
                 }
                 break;
             case SFX_EVENT_SAVEASDOC:
+                {
+                    if ( GetDocument()->GetExternalRefManager()->containsUnsavedReferences() )
+                    {
+                        WarningBox aBox( GetActiveDialogParent(), WinBits( WB_YES_NO ),
+                                ScGlobal::GetRscString( STR_UNSAVED_EXT_REF ) );
+
+                        if( RET_NO == aBox.Execute())
+                        {
+                            SetError( ERRCODE_IO_ABORT, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); // this error code will produce no error message, but will break the further saving process
+                        }
+                    }
+                } // fall through
             case SFX_EVENT_SAVETODOC:
                 // #i108978# If no event is sent before saving, there will also be no "...DONE" event,
                 // and SAVE/SAVEAS can't be distinguished from SAVETO. So stream copying is only enabled
@@ -926,21 +940,11 @@ void ScDocShell::Notify( SfxBroadcaster&, const SfxHint& rHint )
                     pSheetSaveData->SetInSupportedSave(true);
                 break;
             case SFX_EVENT_SAVEDOCDONE:
+            case SFX_EVENT_SAVEASDOCDONE:
                 {
-                    if ( IsDocShared() && !SC_MOD()->IsInSharedDocSaving() )
-                    {
-                    }
+                    // new positions are used after "save" and "save as", but not "save to"
                     UseSheetSaveEntries();      // use positions from saved file for next saving
-                    if (pSheetSaveData)
-                        pSheetSaveData->SetInSupportedSave(false);
-                }
-                break;
-            case SFX_EVENT_SAVEASDOCDONE:
-                // new positions are used after "save" and "save as", but not "save to"
-                UseSheetSaveEntries();      // use positions from saved file for next saving
-                if (pSheetSaveData)
-                    pSheetSaveData->SetInSupportedSave(false);
-                break;
+                } // fall through
             case SFX_EVENT_SAVETODOCDONE:
                 // only reset the flag, don't use the new positions
                 if (pSheetSaveData)
@@ -1567,6 +1571,7 @@ sal_Bool ScDocShell::SaveAs( SfxMedium& rMedium )
             return false;
     }
 
+
     ScRefreshTimerProtector( aDocument.GetRefreshTimerControlAddress() );
 
     PrepareSaveGuard aPrepareGuard( *this);
diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx
index 6d23ab9..83881a5 100644
--- a/sc/source/ui/docshell/externalrefmgr.cxx
+++ b/sc/source/ui/docshell/externalrefmgr.cxx
@@ -44,6 +44,7 @@
 #include "viewdata.hxx"
 #include "tabvwsh.hxx"
 #include "sc.hrc"
+#include "globstr.hrc"
 
 #include "sfx2/app.hxx"
 #include "sfx2/docfilt.hxx"
@@ -61,6 +62,7 @@
 #include "tools/urlobj.hxx"
 #include "unotools/ucbhelper.hxx"
 #include "unotools/localfilehelper.hxx"
+#include "vcl/msgbox.hxx"
 
 #include <memory>
 #include <algorithm>
@@ -2092,7 +2094,7 @@ const ScDocument* ScExternalRefManager::getInMemorySrcDocument(sal_uInt16 nFileI
     while (pShell)
     {
         SfxMedium* pMedium = pShell->GetMedium();
-        if (pMedium)
+        if (pMedium && pMedium->GetName().Len())
         {
             OUString aName = pMedium->GetName();
             // TODO: We should make the case sensitivity platform dependent.
@@ -2103,6 +2105,21 @@ const ScDocument* ScExternalRefManager::getInMemorySrcDocument(sal_uInt16 nFileI
                 break;
             }
         }
+        else
+        {
+            // handle unsaved documents here
+            OUString aName = pShell->GetName();
+            if (pFileName->equalsIgnoreAsciiCase(aName))
+            {
+                // Found !
+                SrcShell aSrcDoc;
+                aSrcDoc.maShell = pShell;
+                maUnsavedDocShells.insert(DocShellMap::value_type(nFileId, aSrcDoc));
+                StartListening(*pShell);
+                pSrcDoc = pShell->GetDocument();
+                break;
+            }
+        }
         pShell = static_cast<ScDocShell*>(SfxObjectShell::GetNext(*pShell, &aType, false));
     }
 
@@ -2127,6 +2144,17 @@ const ScDocument* ScExternalRefManager::getSrcDocument(sal_uInt16 nFileId)
         return static_cast<ScDocShell*>(p)->GetDocument();
     }
 
+    itrEnd = maUnsavedDocShells.end();
+    itr = maUnsavedDocShells.find(nFileId);
+    if (itr != itrEnd)
+    {
+        //document is unsaved document
+
+        SfxObjectShell* p = itr->second.maShell;
+        itr->second.maLastAccess = Time( Time::SYSTEM );
+        return static_cast<ScDocShell*>(p)->GetDocument();
+    }
+
     const OUString* pFile = getExternalFileName(nFileId);
     if (!pFile)
         // no file name associated with this ID.
@@ -2341,6 +2369,17 @@ bool ScExternalRefManager::isOwnDocument(const OUString& rFile) const
 
 void ScExternalRefManager::convertToAbsName(OUString& rFile) const
 {
+    // unsaved documents have no AbsName
+    TypeId aType(TYPE(ScDocShell));
+    ScDocShell* pShell = static_cast<ScDocShell*>(SfxObjectShell::GetFirst(&aType, false));
+    while (pShell)
+    {
+        if (rFile == rtl::OUString(pShell->GetName()))
+            return;
+
+        pShell = static_cast<ScDocShell*>(SfxObjectShell::GetNext(*pShell, &aType, false));
+    }
+
     SfxObjectShell* pDocShell = mpDoc->GetDocumentShell();
     rFile = ScGlobal::GetAbsDocName(rFile, pDocShell);
 }
@@ -2644,6 +2683,51 @@ sal_uInt32 ScExternalRefManager::getMappedNumberFormat(sal_uInt16 nFileId, sal_u
     return nNumFmt;
 }
 
+void ScExternalRefManager::transformUnsavedRefToSavedRef( SfxObjectShell* pShell )
+{
+    DocShellMap::iterator itr = maUnsavedDocShells.begin();
+    while( itr != maUnsavedDocShells.end() )
+    {
+        if (&(itr->second.maShell) == pShell)
+        {
+            // found that the shell is marked as unsaved
+            rtl::OUString aFileURL = pShell->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DECODE_TO_IURI);
+            switchSrcFile(itr->first, aFileURL, rtl::OUString());
+            EndListening(*pShell);
+            maUnsavedDocShells.erase(itr++);
+        }
+    }
+}
+
+void ScExternalRefManager::Notify( SfxBroadcaster&, const SfxHint& rHint )
+{
+    if ( rHint.ISA( SfxEventHint ) )
+    {
+        sal_uLong nEventId = ((SfxEventHint&)rHint).GetEventId();
+        switch ( nEventId )
+        {
+            case SFX_EVENT_PREPARECLOSEDOC:
+                {
+                    SfxObjectShell* pObjShell = static_cast<const SfxEventHint&>( rHint ).GetObjShell();
+                    ScDocShell* pDocShell = static_cast< ScDocShell* >( pObjShell );
+                    WarningBox aBox(  pDocShell->GetActiveDialogParent(), WinBits( WB_OK ),
+                                        ScGlobal::GetRscString( STR_CLOSE_WITH_UNSAVED_REFS ) );
+                    aBox.Execute();
+                }
+                break;
+            case SFX_EVENT_SAVEDOCDONE:
+            case SFX_EVENT_SAVEASDOCDONE:
+                {
+                    SfxObjectShell* pObjShell = static_cast<const SfxEventHint&>( rHint ).GetObjShell();
+                    transformUnsavedRefToSavedRef(pObjShell);
+                }
+                break;
+            default:
+                break;
+        }
+    }
+}
+
 IMPL_LINK(ScExternalRefManager, TimeOutHdl, AutoTimer*, pTimer)
 {
     if (pTimer == &maSrcDocTimer)
diff --git a/sc/source/ui/src/globstr.src b/sc/source/ui/src/globstr.src
index 464f141..a5a1e6a 100644
--- a/sc/source/ui/src/globstr.src
+++ b/sc/source/ui/src/globstr.src
@@ -1851,5 +1851,13 @@ Resource RID_GLOBSTR
     {
         Text [ en-US ] = "Invalid name. Only use letters, numbers and underscore.";
     };
+    String STR_UNSAVED_EXT_REF
+    {
+        Text [ en-US ] = "This Document contains external references to unsaved documents.\n\nDo you want to continue?";
+    };
+    String STR_CLOSE_WITH_UNSAVED_REFS
+    {
+        Text [ en-US ] = "This Document is referenced by another document and not yet saved. Closing it without saving will result in data loss.";
+    };
 };
 
diff --git a/sc/source/ui/view/viewfun2.cxx b/sc/source/ui/view/viewfun2.cxx
index cfa027e..e2c950c 100644
--- a/sc/source/ui/view/viewfun2.cxx
+++ b/sc/source/ui/view/viewfun2.cxx
@@ -89,6 +89,7 @@
 #include "docuno.hxx"
 #include "charthelper.hxx"
 #include "tabbgcolor.hxx"
+#include "clipparam.hxx"
 
 #include <basic/sbstar.hxx>
 #include <com/sun/star/container/XNameContainer.hpp>
@@ -2562,6 +2563,7 @@ void ScViewFunc::MoveTable(
         if(nDestTab==SC_TAB_APPEND)
             nDestTab=pDestDoc->GetTableCount();
         SCTAB nDestTab1=nDestTab;
+        ScClipParam aParam;
         for( sal_uInt16 j=0; j<TheTabs.size(); ++j, ++nDestTab1 )
         {   // insert sheets first and update all references
             rtl::OUString aName;
@@ -2576,7 +2578,10 @@ void ScViewFunc::MoveTable(
                 nErrVal = 0;        // total error
                 break;  // for
             }
+            ScRange aRange( 0, 0, TheTabs[j], MAXCOL, MAXROW, TheTabs[j] );
+            aParam.maRanges.Append(aRange);
         }
+        pDoc->SetClipParam(aParam);
         if ( nErrVal > 0 )
         {
             nDestTab1 = nDestTab;


More information about the Libreoffice-commits mailing list