From 10af6ea64a35d3477ceed905b547531fd0faa973 Mon Sep 17 00:00:00 2001
From: Mike Kaganski <mike.kaganski@collabora.com>
Date: Thu, 3 Dec 2015 19:05:03 +1000
Subject: [PATCH] tdf#96206: Avoid scaling objects while copying to clipboard

... to prevent duplicating masters on slide copy-paste.
Also fixed a 10-year copy-paste error (pRefPage wasn't replaced
with pNPage).
Fixed argument evaluation order issue (aStream.GetEndOfData()
depends on Flush() but doesn't call it, so will return incorrect
result if called before aStream.GetBuffer()).
Replaced compare of hashes with results of stringify(),
because it removes useless overhead (hashes are calculated from
stringify() anyway, and are not cached anywhere).
Removed Flush() called from SvMemoryStream::GetBuffer(), because
it calls GetData(), which calls Flush() itself.

Change-Id: Ia46d4e9a017fc628d424949a9d229045a249a4ca
(cherry picked from commit 0b6c9ddce0478bbedc36e8531f31b154bbce661c)

tdf#96708: don't modify document while copying to clipboard

I.e., don't try to create auto-layout for clipboard pages which
don't contain one; don't resize objects to text.

Also, don't invalidate items that are equal to defaults,
because explicitly set items are not the same as absent items:
pasting an object without an item makes the property to inherit
new target's default, while when the item is present, the default
doesn't apply.

Also, don't consider selected state of the page while stringifying
- this makes selected page string to differ from not-selected
clipboard page.

Reviewed-on: https://gerrit.libreoffice.org/20871
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Andras Timar <andras.timar@collabora.com>
(cherry picked from commit 3b4059dc53ec764be5423517363223043d6dbfad)

Change-Id: I172e03e1a8c428e5fcae3a116cc9ad8de79f1a87

diff --git a/include/svx/svdmodel.hxx b/include/svx/svdmodel.hxx
index 4d56a44..cfdd489 100644
--- a/include/svx/svdmodel.hxx
+++ b/include/svx/svdmodel.hxx
@@ -200,14 +200,15 @@ protected:
     bool                bInfoChanged:1;
     bool                bPagNumsDirty:1;
     bool                bMPgNumsDirty:1;
-    bool                bPageNotValid:1;  // TRUE=Doc is only object container. Page is invalid.
+    bool                bPageNotValid:1;
+    bool                bTransportContainer:1;  // doc is temporary object container, no display (e.g. clipboard)
     bool                bSavePortable:1;  // save metafiles portably
     bool                bNoBitmapCaching:1;   // cache bitmaps for screen output
     bool                bReadOnly:1;
     bool                bTransparentTextFrames:1;
     bool                bSaveCompressed:1;
     bool                bSwapGraphics:1;
-    bool                bPasteResize:1; // Objects are beingresized due to Paste with different MapMode
+    bool                bPasteResize:1; // Objects are being resized due to Paste with different MapMode
     bool                bSaveOLEPreview:1;      // save preview metafile of OLE objects
     bool                bSaveNative:1;
     bool                bStarDrawPreviewMode:1;
@@ -284,6 +285,8 @@ private:
     ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > mxUnoModel;

 public:
+    SVX_DLLPRIVATE virtual bool IsCreatingDataObj() const { return false; }
+    bool     IsTransportContainer() const { return bTransportContainer; }
     bool     IsPasteResize() const        { return bPasteResize; }
     void     SetPasteResize(bool bOn) { bPasteResize=bOn; }
     TYPEINFO_OVERRIDE();
diff --git a/sd/inc/drawdoc.hxx b/sd/inc/drawdoc.hxx
index 1a3e359..39df03e 100644
--- a/sd/inc/drawdoc.hxx
+++ b/sd/inc/drawdoc.hxx
@@ -241,6 +241,7 @@ public:
     SAL_DLLPRIVATE void                SetAllocDocSh(bool bAlloc);

     SAL_DLLPRIVATE void                CreatingDataObj( SdTransferable* pTransferable ) { mpCreatingTransferable = pTransferable; }
+    SAL_DLLPRIVATE virtual bool        IsCreatingDataObj() const override { return mpCreatingTransferable != nullptr; }

     /** if the document does not contain at least one handout, one slide and one notes page with
         at least one master each this methods creates them.
diff --git a/sd/source/core/drawdoc2.cxx b/sd/source/core/drawdoc2.cxx
index eb83ade..3329521 100644
--- a/sd/source/core/drawdoc2.cxx
+++ b/sd/source/core/drawdoc2.cxx
@@ -850,6 +850,9 @@ LanguageType SdDrawDocument::GetLanguage( const sal_uInt16 nId ) const
 // Initiate WorkStartup
 IMPL_LINK_NOARG_TYPED(SdDrawDocument, WorkStartupHdl, Timer *, void)
 {
+    if (IsTransportContainer())
+        return;
+
     if( mpDocSh )
         mpDocSh->SetWaitCursor( true );

diff --git a/sd/source/core/drawdoc3.cxx b/sd/source/core/drawdoc3.cxx
index 3f966e8..d36cc52 100644
--- a/sd/source/core/drawdoc3.cxx
+++ b/sd/source/core/drawdoc3.cxx
@@ -51,6 +51,7 @@
 #include "strmname.h"
 #include "anminfo.hxx"
 #include "customshowlist.hxx"
+#include "sdxfer.hxx"

 #include "../ui/inc/unmovss.hxx"
 #include "../ui/inc/unchss.hxx"
@@ -110,7 +111,7 @@ void InsertBookmarkAsPage_FindDuplicateLayouts::operator()( SdDrawDocument& rDoc
         {
             // Ignore Layouts with "Default" these seem to be special - in the sense that there are lot of assumption all over Impress
             // about this
-            if( bRenameDuplicates && aTest != OUString( SdResId( STR_LAYOUT_DEFAULT_NAME ) ) && pTestPage->getHash() != pBMMPage->getHash() )
+            if( bRenameDuplicates && aTest != OUString( SdResId( STR_LAYOUT_DEFAULT_NAME ) ) && pTestPage->stringify() != pBMMPage->stringify() )
             {
                 pBookmarkDoc->RenameLayoutTemplate( pBMMPage->GetLayoutName(), OUString(pBMMPage->GetName())+=OUString("_") );
                 aLayout = pBMMPage->GetName();
@@ -438,17 +439,26 @@ bool SdDrawDocument::InsertBookmarkAsPage(
     sal_Int32 nNRight = pNPage->GetRgtBorder();
     sal_Int32 nNUpper = pNPage->GetUppBorder();
     sal_Int32 nNLower = pNPage->GetLwrBorder();
-    Orientation eNOrient = pRefPage->GetOrientation();
+    Orientation eNOrient = pNPage->GetOrientation();

     // Adapt page size and margins to those of the later pages?
     pRefPage = GetSdPage(nSdPageCount - 1, PK_STANDARD);

     if( bNoDialogs )
     {
-        if( rBookmarkList.empty() )
-            bScaleObjects = pRefPage->IsScaleObjects();
-        else
-            bScaleObjects = true;
+        // If this is clipboard, then no need to scale objects:
+        // this will make copied masters to differ from the originals,
+        // and thus InsertBookmarkAsPage_FindDuplicateLayouts will
+        // duplicate masters on insert to same document
+        bTransportContainer = (SD_MOD()->pTransferClip &&
+                               SD_MOD()->pTransferClip->GetWorkDocument() == this);
+        if (!bTransportContainer)
+        {
+            if (rBookmarkList.empty())
+                bScaleObjects = pRefPage->IsScaleObjects();
+            else
+                bScaleObjects = true;
+        }
     }
     else
     {
diff --git a/sd/source/core/sdpage2.cxx b/sd/source/core/sdpage2.cxx
index f3a1336..86bdd6d 100644
--- a/sd/source/core/sdpage2.cxx
+++ b/sd/source/core/sdpage2.cxx
@@ -560,7 +560,7 @@ void SdPage::setTransitionDuration ( double fTranstionDuration )
 OString SdPage::stringify() const
 {
     OStringBuffer aString(100);
-    aString.append((sal_Int32)mePageKind).append((sal_Int32)meAutoLayout).append(mbSelected).append((sal_Int32)mePresChange).append(mfTime).append(mbSoundOn).append(mbExcluded).
+    aString.append((sal_Int32)mePageKind).append((sal_Int32)meAutoLayout).append((sal_Int32)mePresChange).append(mfTime).append(mbSoundOn).append(mbExcluded).
              append(OUStringToOString( maLayoutName, RTL_TEXTENCODING_UTF8 )).
              append(OUStringToOString(maSoundFile, RTL_TEXTENCODING_UTF8 )).
              append(mbLoopSound).append(mbStopSound).
diff --git a/sd/source/ui/slidesorter/controller/SlsClipboard.cxx b/sd/source/ui/slidesorter/controller/SlsClipboard.cxx
index 7dfc356..015ff86 100644
--- a/sd/source/ui/slidesorter/controller/SlsClipboard.cxx
+++ b/sd/source/ui/slidesorter/controller/SlsClipboard.cxx
@@ -433,7 +433,6 @@ void Clipboard::CreateSlideTransferable (

         pDocument->CreatingDataObj (pTransferable);
         pTransferable->SetWorkDocument(pDocument->AllocSdDrawDocument());
-        pDocument->CreatingDataObj (NULL);
         TransferableObjectDescriptor aObjDesc;
         pTransferable->GetWorkDocument()->GetDocSh()
             ->FillTransferableObjectDescriptor (aObjDesc);
@@ -466,6 +465,8 @@ void Clipboard::CreateSlideTransferable (
         }
         else
             pTransferable->CopyToClipboard (pActionWindow);
+
+        pDocument->CreatingDataObj(nullptr);
     }
 }

diff --git a/sd/source/ui/slidesorter/inc/controller/SlideSorterController.hxx b/sd/source/ui/slidesorter/inc/controller/SlideSorterController.hxx
index 62818dc..4d38369 100644
--- a/sd/source/ui/slidesorter/inc/controller/SlideSorterController.hxx
+++ b/sd/source/ui/slidesorter/inc/controller/SlideSorterController.hxx
@@ -106,7 +106,8 @@ public:
     */
     model::SharedPageDescriptor GetPageAt (const Point& rPixelPosition);

-    PageSelector& GetPageSelector();
+    // Exported for unit test
+    SD_DLLPUBLIC PageSelector& GetPageSelector();
     FocusManager& GetFocusManager();
     controller::Clipboard& GetClipboard();

diff --git a/sd/source/ui/slidesorter/inc/controller/SlsPageSelector.hxx b/sd/source/ui/slidesorter/inc/controller/SlsPageSelector.hxx
index 9f2051c..a8408e7 100644
--- a/sd/source/ui/slidesorter/inc/controller/SlsPageSelector.hxx
+++ b/sd/source/ui/slidesorter/inc/controller/SlsPageSelector.hxx
@@ -27,6 +27,8 @@
 #include <memory>
 #include <boost/noncopyable.hpp>

+#include "sddllapi.h"
+
 class SdPage;

 namespace sd { namespace slidesorter {
@@ -55,7 +57,8 @@ class PageSelector : private ::boost::noncopyable
 public:
     PageSelector (SlideSorter& rSlideSorter);

-    void SelectAllPages();
+    // Exported for unit test
+    SD_DLLPUBLIC void SelectAllPages();
     void DeselectAllPages();

     /** Update the selection state of all page descriptors to be the same as
diff --git a/svl/source/items/itemset.cxx b/svl/source/items/itemset.cxx
index 4862706..7a84b25 100644
--- a/svl/source/items/itemset.cxx
+++ b/svl/source/items/itemset.cxx
@@ -1613,9 +1613,7 @@ sal_Int32 SfxItemSet::getHash() const
 OString SfxItemSet::stringify() const
 {
     SvMemoryStream aStream;
-    SfxItemSet aSet(*this);
-    aSet.InvalidateDefaultItems();
-    aSet.Store(aStream, true);
+    Store(aStream, true);
     aStream.Flush();
     return OString(
         static_cast<char const *>(aStream.GetData()), aStream.GetEndOfData());
diff --git a/svx/source/svdraw/svdmodel.cxx b/svx/source/svdraw/svdmodel.cxx
index 47c3c21..af29cf8 100644
--- a/svx/source/svdraw/svdmodel.cxx
+++ b/svx/source/svdraw/svdmodel.cxx
@@ -147,7 +147,7 @@ void SdrModel::ImpCtor(SfxItemPool* pPool, ::comphelper::IEmbeddedHelper* _pEmbe
     bInfoChanged=false;
     bPagNumsDirty=false;
     bMPgNumsDirty=false;
-    bPageNotValid=false;
+    bTransportContainer = false;
     bSavePortable=false;
     bSaveCompressed=false;
     bSaveNative=false;
diff --git a/svx/source/svdraw/svdoashp.cxx b/svx/source/svdraw/svdoashp.cxx
index 00cff5f..4b79721 100644
--- a/svx/source/svdraw/svdoashp.cxx
+++ b/svx/source/svdraw/svdoashp.cxx
@@ -1445,7 +1445,7 @@ const Rectangle& SdrObjCustomShape::GetLogicRect() const
 // state of the ResizeShapeToFitText flag to correctly set TextMinFrameWidth/Height
 void SdrObjCustomShape::AdaptTextMinSize()
 {
-    if(!pModel || !pModel->IsPasteResize())
+    if (!pModel || (!pModel->IsCreatingDataObj() && !pModel->IsPasteResize()))
     {
         const bool bResizeShapeToFitText(static_cast< const SdrOnOffItem& >(GetObjectItem(SDRATTR_TEXT_AUTOGROWHEIGHT)).GetValue());
         SfxItemSet aSet(
diff --git a/svx/source/svdraw/svdobj.cxx b/svx/source/svdraw/svdobj.cxx
index b6d3827..b9fb84e 100644
--- a/svx/source/svdraw/svdobj.cxx
+++ b/svx/source/svdraw/svdobj.cxx
@@ -1772,11 +1772,7 @@ OString SdrObject::stringify() const
             //append(maBLIPSizeRectangle).
             append(mnLayerID);

-    SvMemoryStream aStream;
-    SfxItemSet aSet(GetMergedItemSet());
-    aSet.InvalidateDefaultItems();
-    aSet.Store(aStream, true);
-    aString.append(static_cast<const char *>(aStream.GetBuffer()), aStream.GetEndOfData());
+    aString.append(GetMergedItemSet().stringify());

     return aString.makeStringAndClear();
 }
diff --git a/tools/source/stream/stream.cxx b/tools/source/stream/stream.cxx
index bb6d21e..17bdcd1 100644
--- a/tools/source/stream/stream.cxx
+++ b/tools/source/stream/stream.cxx
@@ -1723,7 +1723,6 @@ SvMemoryStream::~SvMemoryStream()

 const void* SvMemoryStream::GetBuffer()
 {
-    Flush();
     return GetData();
 }

--
2.6.2

