1 diff --git sc/inc/cell.hxx sc/inc/cell.hxx
2 index 5454907..b460a31 100644
6 #include <tools/mempool.hxx>
7 #include <svtools/listener.hxx>
9 +#include "rangenam.hxx"
10 #include "formula/grammar.hxx"
11 #include "tokenarray.hxx"
12 #include "formularesult.hxx"
13 @@ -462,6 +463,7 @@ public:
14 BOOL IsRangeNameInUse(USHORT nIndex) const;
15 void FindRangeNamesInUse(std::set<USHORT>& rIndexes) const;
16 void ReplaceRangeNamesInUse( const ScIndexMap& rMap );
17 + void ReplaceRangeNamesInUse( const ScRangeData::IndexMap& rMap );
18 BOOL IsSubTotal() const { return bSubTotal; }
19 BOOL IsChanged() const { return bChanged; }
20 void ResetChanged() { bChanged = FALSE; }
21 diff --git sc/inc/clipparam.hxx sc/inc/clipparam.hxx
23 index 0000000..1a46f4c
25 +++ sc/inc/clipparam.hxx
27 +/*************************************************************************
29 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
31 + * Copyright 2008 by Sun Microsystems, Inc.
33 + * OpenOffice.org - a multi-platform office productivity suite
35 + * $RCSfile: document.hxx,v $
36 + * $Revision: 1.115.36.9 $
38 + * This file is part of OpenOffice.org.
40 + * OpenOffice.org is free software: you can redistribute it and/or modify
41 + * it under the terms of the GNU Lesser General Public License version 3
42 + * only, as published by the Free Software Foundation.
44 + * OpenOffice.org is distributed in the hope that it will be useful,
45 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
46 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
47 + * GNU Lesser General Public License version 3 for more details
48 + * (a copy is included in the LICENSE file that accompanied this code).
50 + * You should have received a copy of the GNU Lesser General Public License
51 + * version 3 along with OpenOffice.org. If not, see
52 + * <http://www.openoffice.org/license.html>
53 + * for a copy of the LGPLv3 License.
55 + ************************************************************************/
57 +#ifndef SC_CLIPPARAM_HXX
58 +#define SC_CLIPPARAM_HXX
60 +#include "rangelst.hxx"
61 +#include "rangenam.hxx"
66 + * This struct stores general clipboard parameters associated with a
67 + * ScDocument instance created in clipboard mode.
71 + enum Direction { Unspecified, Column, Row };
73 + ScRangeList maRanges;
74 + Direction meDirection;
78 + explicit ScClipParam(const ScClipParam& r);
80 + bool isMultiRange() const;
83 + * Get the column size of a pasted range. Note that when the range is
84 + * non-contiguous, we first compress all individual ranges into a single
85 + * range, and the size of that compressed range is returned.
87 + SCCOL getPasteColSize();
90 + * Same as the above method, but returns the row size of the compressed
93 + SCROW getPasteRowSize();
96 + * Return a single range that encompasses all individual ranges.
98 + ScRange getWholeRange() const;
103 +// ============================================================================
105 +struct ScClipRangeNameData
107 + ScRangeData::IndexMap maRangeMap;
108 + ::std::vector<ScRangeData*> mpRangeNames;
111 + ScClipRangeNameData();
112 + ~ScClipRangeNameData();
113 + void insert(sal_uInt16 nOldIndex, sal_uInt16 nNewIndex);
117 diff --git sc/inc/column.hxx sc/inc/column.hxx
118 index 64ac9a0..5b17512 100644
119 --- sc/inc/column.hxx
120 +++ sc/inc/column.hxx
122 #include "global.hxx"
123 #include "compressedarray.hxx"
124 #include "address.hxx"
125 +#include "rangenam.hxx"
126 #include <tools/solar.h>
129 @@ -301,6 +302,7 @@ public:
130 BOOL IsRangeNameInUse(SCROW nRow1, SCROW nRow2, USHORT nIndex) const;
131 void FindRangeNamesInUse(SCROW nRow1, SCROW nRow2, std::set<USHORT>& rIndexes) const;
132 void ReplaceRangeNamesInUse( SCROW nRow1, SCROW nRow2, const ScIndexMap& rMap );
133 + void ReplaceRangeNamesInUse( SCROW nRow1, SCROW nRow2, const ScRangeData::IndexMap& rMap );
135 const SfxPoolItem* GetAttr( SCROW nRow, USHORT nWhich ) const;
136 const ScPatternAttr* GetPattern( SCROW nRow ) const;
137 diff --git sc/inc/document.hxx sc/inc/document.hxx
138 index f392382..87a9343 100644
139 --- sc/inc/document.hxx
140 +++ sc/inc/document.hxx
141 @@ -138,6 +138,8 @@ class ScAutoNameCache;
142 class ScTemporaryChartLock;
144 struct ScLookupCacheMapImpl;
146 +struct ScClipRangeNameData;
148 namespace com { namespace sun { namespace star {
150 @@ -286,6 +288,7 @@ private:
151 ScFieldEditEngine* pCacheFieldEditEngine;
153 ::std::auto_ptr<ScDocProtection> pDocProtection;
154 + ::std::auto_ptr<ScClipParam> mpClipParam;
156 ::std::auto_ptr<ScExternalRefManager> pExternalRefMgr;
157 String aDocName; // opt: Dokumentname
158 @@ -307,7 +310,6 @@ private:
160 sal_uInt32 nRangeOverflowType; // used in (xml) loading for overflow warnings
162 - ScRange aClipRange;
164 ScAddress aCurTextWidthCalcPos;
165 ScAddress aOnlineSpellPos; // within whole document
166 @@ -357,7 +359,6 @@ private:
167 BOOL bForcedFormulaPending;
168 BOOL bCalculatingFormulaTree;
172 BOOL bIsVisible; // set from view ctor
174 @@ -957,6 +958,9 @@ public:
175 BOOL bKeepScenarioFlags = FALSE,
176 BOOL bIncludeObjects = FALSE,
177 BOOL bCloneNoteCaptions = TRUE);
178 + void CopyToClip(const ScClipParam& rClipParam, ScDocument* pClipDoc,
179 + const ScMarkData* pMarks = NULL, bool bKeepScenarioFlags = false,
180 + bool bIncludeObjects = false, bool bCloneNoteCaptions = true);
181 void CopyTabToClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
182 SCTAB nTab, ScDocument* pClipDoc = NULL);
183 void CopyBlockFromClip( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
184 @@ -984,6 +988,12 @@ public:
185 BOOL bSkipAttrForEmpty = FALSE,
186 const ScRangeList * pDestRanges = NULL );
188 + void CopyMultiRangeFromClip(const ScAddress& rDestPos, const ScMarkData& rMark,
189 + sal_uInt16 nInsFlag, ScDocument* pClipDoc,
190 + bool bResetCut = true, bool bAsLink = false,
191 + bool bIncludeFiltered = true,
192 + bool bSkipAttrForEmpty = false);
194 void GetClipArea(SCCOL& nClipX, SCROW& nClipY, BOOL bIncludeFiltered);
195 void GetClipStart(SCCOL& nClipX, SCROW& nClipY);
197 @@ -993,6 +1003,9 @@ public:
199 SC_DLLPUBLIC void TransposeClip( ScDocument* pTransClip, USHORT nFlags, BOOL bAsLink );
201 + ScClipParam& GetClipParam();
202 + void SetClipParam(const ScClipParam& rParam);
204 void MixDocument( const ScRange& rRange, USHORT nFunction, BOOL bSkipEmpty,
205 ScDocument* pSrcDoc );
207 @@ -1692,6 +1705,23 @@ public:
209 private: // CLOOK-Impl-Methoden
212 + * Use this class as a locale variable to merge number formatter from
213 + * another document, and set NULL pointer to pFormatExchangeList when
216 + class NumFmtMergeHandler
219 + explicit NumFmtMergeHandler(ScDocument* pDoc, ScDocument* pSrcDoc);
220 + ~NumFmtMergeHandler();
226 + void MergeNumberFormatter(ScDocument* pSrcDoc);
228 void ImplCreateOptions(); // bei Gelegenheit auf on-demand umstellen?
229 void ImplDeleteOptions();
231 @@ -1713,6 +1743,12 @@ private: // CLOOK-Impl-Methoden
232 void UpdateRefAreaLinks( UpdateRefMode eUpdateRefMode,
233 const ScRange& r, SCsCOL nDx, SCsROW nDy, SCsTAB nDz );
235 + void CopyRangeNamesToClip(ScDocument* pClipDoc, const ScRange& rClipRange, const ScMarkData* pMarks, bool bAllTabs);
236 + void CopyRangeNamesFromClip(ScDocument* pClipDoc, ScClipRangeNameData& rRangeNames);
237 + void UpdateRangeNamesInFormulas(
238 + ScClipRangeNameData& rRangeNames, const ScRangeList& rDestRanges, const ScMarkData& rMark,
239 + SCCOL nXw, SCROW nYw);
241 BOOL HasPartOfMerged( const ScRange& rRange );
243 std::map< SCTAB, ScSortParam > mSheetSortParams;
244 diff --git sc/inc/rangenam.hxx sc/inc/rangenam.hxx
245 index 8231cbd..ece1609 100644
246 --- sc/inc/rangenam.hxx
247 +++ sc/inc/rangenam.hxx
249 #include "formula/grammar.hxx"
250 #include "scdllapi.h"
254 //------------------------------------------------------------------------
257 @@ -84,6 +86,8 @@ private:
258 friend class ScRangeName;
259 ScRangeData( USHORT nIndex );
261 + typedef ::std::map<sal_uInt16, sal_uInt16> IndexMap;
263 SC_DLLPUBLIC ScRangeData( ScDocument* pDoc,
265 const String& rSymbol,
266 @@ -150,6 +154,7 @@ public:
267 void ValidateTabRefs();
269 void ReplaceRangeNamesInUse( const ScIndexMap& rMap );
270 + void ReplaceRangeNamesInUse( const IndexMap& rMap );
272 static void MakeValidName( String& rName );
273 SC_DLLPUBLIC static BOOL IsNameValid( const String& rName, ScDocument* pDoc );
274 diff --git sc/inc/table.hxx sc/inc/table.hxx
275 index 734ad3c..b32bb64 100644
278 @@ -292,6 +292,8 @@ public:
279 void DeleteArea(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, USHORT nDelFlag);
280 void CopyToClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScTable* pTable,
281 BOOL bKeepScenarioFlags, BOOL bCloneNoteCaptions);
282 + void CopyToClip(const ScRangeList& rRanges, ScTable* pTable,
283 + bool bKeepScenarioFlags, bool bCloneNoteCaptions);
284 void CopyFromClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SCsCOL nDx, SCsROW nDy,
285 USHORT nInsFlag, BOOL bAsLink, BOOL bSkipAttrForEmpty, ScTable* pTable);
286 void StartListeningInArea( SCCOL nCol1, SCROW nRow1,
287 @@ -406,6 +408,8 @@ public:
288 std::set<USHORT>& rIndexes) const;
289 void ReplaceRangeNamesInUse(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
290 const ScIndexMap& rMap );
291 + void ReplaceRangeNamesInUse(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
292 + const ScRangeData::IndexMap& rMap );
293 void Fill( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
294 ULONG nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd,
295 double nStepValue, double nMaxValue);
296 diff --git sc/source/core/data/cell2.cxx sc/source/core/data/cell2.cxx
297 index 7e29ed7..c0c17ce 100644
298 --- sc/source/core/data/cell2.cxx
299 +++ sc/source/core/data/cell2.cxx
300 @@ -1318,6 +1318,26 @@ void ScFormulaCell::ReplaceRangeNamesInUse( const ScIndexMap& rMap )
304 +void ScFormulaCell::ReplaceRangeNamesInUse( const ScRangeData::IndexMap& rMap )
306 + for( FormulaToken* p = pCode->First(); p; p = pCode->Next() )
308 + if( p->GetOpCode() == ocName )
310 + sal_uInt16 nIndex = p->GetIndex();
311 + ScRangeData::IndexMap::const_iterator itr = rMap.find(nIndex);
312 + sal_uInt16 nNewIndex = itr == rMap.end() ? nIndex : nNewIndex;
313 + if ( nIndex != nNewIndex )
315 + p->SetIndex( nNewIndex );
321 + CompileTokenArray();
324 void ScFormulaCell::CompileDBFormula()
326 for( FormulaToken* p = pCode->First(); p; p = pCode->Next() )
327 diff --git sc/source/core/data/clipparam.cxx sc/source/core/data/clipparam.cxx
329 index 0000000..564b04d
331 +++ sc/source/core/data/clipparam.cxx
333 +/*************************************************************************
335 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
337 + * Copyright 2008 by Sun Microsystems, Inc.
339 + * OpenOffice.org - a multi-platform office productivity suite
341 + * $RCSfile: document.cxx,v $
342 + * $Revision: 1.90.36.8 $
344 + * This file is part of OpenOffice.org.
346 + * OpenOffice.org is free software: you can redistribute it and/or modify
347 + * it under the terms of the GNU Lesser General Public License version 3
348 + * only, as published by the Free Software Foundation.
350 + * OpenOffice.org is distributed in the hope that it will be useful,
351 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
352 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
353 + * GNU Lesser General Public License version 3 for more details
354 + * (a copy is included in the LICENSE file that accompanied this code).
356 + * You should have received a copy of the GNU Lesser General Public License
357 + * version 3 along with OpenOffice.org. If not, see
358 + * <http://www.openoffice.org/license.html>
359 + * for a copy of the LGPLv3 License.
361 + ************************************************************************/
363 +// MARKER(update_precomp.py): autogen include statement, do not remove
364 +#include "precompiled_sc.hxx"
366 +// INCLUDE ---------------------------------------------------------------
368 +#include "clipparam.hxx"
370 +using ::std::vector;
372 +ScClipParam::ScClipParam() :
373 + meDirection(Unspecified),
378 +ScClipParam::ScClipParam(const ScClipParam& r) :
379 + maRanges(r.maRanges),
380 + meDirection(r.meDirection),
381 + mbCutMode(r.mbCutMode)
385 +bool ScClipParam::isMultiRange() const
387 + return maRanges.Count() > 1;
390 +SCCOL ScClipParam::getPasteColSize()
392 + if (!maRanges.Count())
395 + switch (meDirection)
397 + case ScClipParam::Column:
399 + SCCOL nColSize = 0;
400 + for (ScRangePtr p = maRanges.First(); p; p = maRanges.Next())
401 + nColSize += p->aEnd.Col() - p->aStart.Col() + 1;
405 + case ScClipParam::Row:
407 + // We assume that all ranges have identical column size.
408 + const ScRange& rRange = *maRanges.First();
409 + return rRange.aEnd.Col() - rRange.aStart.Col() + 1;
412 + case ScClipParam::Unspecified:
419 +SCROW ScClipParam::getPasteRowSize()
421 + if (!maRanges.Count())
424 + switch (meDirection)
426 + case ScClipParam::Column:
428 + // We assume that all ranges have identical row size.
429 + const ScRange& rRange = *maRanges.First();
430 + return rRange.aEnd.Row() - rRange.aStart.Row() + 1;
433 + case ScClipParam::Row:
435 + SCROW nRowSize = 0;
436 + for (ScRangePtr p = maRanges.First(); p; p = maRanges.Next())
437 + nRowSize += p->aEnd.Row() - p->aStart.Row() + 1;
441 + case ScClipParam::Unspecified:
448 +ScRange ScClipParam::getWholeRange() const
451 + bool bFirst = true;
452 + ScRangeList aRanges = maRanges;
453 + for (ScRange* p = aRanges.First(); p; p = aRanges.Next())
462 + if (aWhole.aStart.Col() > p->aStart.Col())
463 + aWhole.aStart.SetCol(p->aStart.Col());
465 + if (aWhole.aStart.Row() > p->aStart.Row())
466 + aWhole.aStart.SetRow(p->aStart.Row());
468 + if (aWhole.aEnd.Col() < p->aEnd.Col())
469 + aWhole.aEnd.SetCol(p->aEnd.Col());
471 + if (aWhole.aEnd.Row() < p->aEnd.Row())
472 + aWhole.aEnd.SetRow(p->aEnd.Row());
477 +void ScClipParam::transpose()
479 + switch (meDirection)
482 + meDirection = ScClipParam::Row;
485 + meDirection = ScClipParam::Column;
492 + ScRangeList aNewRanges;
493 + if (maRanges.Count())
495 + ScRange* p = maRanges.First();
496 + SCCOL nColOrigin = p->aStart.Col();
497 + SCROW nRowOrigin = p->aStart.Row();
498 + for (; p; p = maRanges.Next())
500 + SCCOL nColDelta = p->aStart.Col() - nColOrigin;
501 + SCROW nRowDelta = p->aStart.Row() - nRowOrigin;
503 + SCCOL nCol2 = static_cast<SCCOL>(p->aEnd.Row() - p->aStart.Row());
505 + SCROW nRow2 = static_cast<SCROW>(p->aEnd.Col() - p->aStart.Col());
506 + nCol1 += static_cast<SCCOL>(nRowDelta);
507 + nCol2 += static_cast<SCCOL>(nRowDelta);
508 + nRow1 += static_cast<SCROW>(nColDelta);
509 + nRow2 += static_cast<SCROW>(nColDelta);
510 + ScRange aNew(nCol1, nRow1, p->aStart.Tab(), nCol2, nRow2, p->aStart.Tab());
511 + aNewRanges.Append(aNew);
514 + maRanges = aNewRanges;
517 +// ============================================================================
519 +ScClipRangeNameData::ScClipRangeNameData() :
524 +ScClipRangeNameData::~ScClipRangeNameData()
528 +void ScClipRangeNameData::insert(sal_uInt16 nOldIndex, sal_uInt16 nNewIndex)
531 + ScRangeData::IndexMap::value_type(nOldIndex, nNewIndex));
533 diff --git sc/source/core/data/column.cxx sc/source/core/data/column.cxx
534 index 721a66f..555c3e8 100644
535 --- sc/source/core/data/column.cxx
536 +++ sc/source/core/data/column.cxx
537 @@ -1884,6 +1884,23 @@ void ScColumn::ReplaceRangeNamesInUse(SCROW nRow1, SCROW nRow2,
541 +void ScColumn::ReplaceRangeNamesInUse(SCROW nRow1, SCROW nRow2,
542 + const ScRangeData::IndexMap& rMap )
545 + for (SCSIZE i = 0; i < nCount; i++)
547 + if ((pItems[i].nRow >= nRow1) &&
548 + (pItems[i].nRow <= nRow2) &&
549 + (pItems[i].pCell->GetCellType() == CELLTYPE_FORMULA))
551 + SCROW nRow = pItems[i].nRow;
552 + ((ScFormulaCell*)pItems[i].pCell)->ReplaceRangeNamesInUse( rMap );
553 + if ( nRow != pItems[i].nRow )
554 + Search( nRow, i ); // Listener geloescht/eingefuegt?
559 void ScColumn::SetDirtyVar()
561 diff --git sc/source/core/data/documen2.cxx sc/source/core/data/documen2.cxx
562 index db40577..8894d1b 100644
563 --- sc/source/core/data/documen2.cxx
564 +++ sc/source/core/data/documen2.cxx
566 #include "lookupcache.hxx"
567 #include "externalrefmgr.hxx"
568 #include "tabprotection.hxx"
569 +#include "clipparam.hxx"
571 // pImpl because including lookupcache.hxx in document.hxx isn't wanted, and
572 // dtor plus helpers are convenient.
573 @@ -153,6 +154,7 @@ ScDocument::ScDocument( ScDocumentMode eMode,
574 pScriptTypeData( NULL ),
575 pCacheFieldEditEngine( NULL ),
576 pDocProtection( NULL ),
577 + mpClipParam( NULL ),
578 pExternalRefMgr( NULL ),
579 pViewOptions( NULL ),
581 @@ -181,7 +183,6 @@ ScDocument::ScDocument( ScDocumentMode eMode,
582 bForcedFormulaPending( FALSE ),
583 bCalculatingFormulaTree( FALSE ),
584 bIsClip( eMode == SCDOCMODE_CLIP ),
586 bIsUndo( eMode == SCDOCMODE_UNDO ),
588 bIsEmbedded( FALSE ),
589 @@ -978,23 +979,18 @@ ULONG ScDocument::TransferTab( ScDocument* pSrcDoc, SCTAB nSrcPos,
590 bOldAutoCalcSrc = pSrcDoc->GetAutoCalc();
591 pSrcDoc->SetAutoCalc( TRUE ); // falls was berechnet werden muss
593 - SvNumberFormatter* pThisFormatter = xPoolHelper->GetFormTable();
594 - SvNumberFormatter* pOtherFormatter = pSrcDoc->xPoolHelper->GetFormTable();
595 - if (pOtherFormatter && pOtherFormatter != pThisFormatter)
598 - SvNumberFormatterIndexTable* pExchangeList =
599 - pThisFormatter->MergeFormatter(*(pOtherFormatter));
600 - if (pExchangeList->Count() > 0)
601 - pFormatExchangeList = pExchangeList;
603 - nDestPos = Min(nDestPos, (SCTAB)(GetTableCount() - 1));
604 - { // scope for bulk broadcast
605 - ScBulkBroadcast aBulkBroadcast( pBASM);
606 - pSrcDoc->pTab[nSrcPos]->CopyToTable(0, 0, MAXCOL, MAXROW,
607 - ( bResultsOnly ? IDF_ALL & ~IDF_FORMULA : IDF_ALL),
608 - FALSE, pTab[nDestPos] );
609 + NumFmtMergeHandler aNumFmtMergeHdl(this, pSrcDoc);
611 + nDestPos = Min(nDestPos, (SCTAB)(GetTableCount() - 1));
612 + { // scope for bulk broadcast
613 + ScBulkBroadcast aBulkBroadcast( pBASM);
614 + pSrcDoc->pTab[nSrcPos]->CopyToTable(0, 0, MAXCOL, MAXROW,
615 + ( bResultsOnly ? IDF_ALL & ~IDF_FORMULA : IDF_ALL),
616 + FALSE, pTab[nDestPos] );
619 - pFormatExchangeList = NULL;
620 pTab[nDestPos]->SetTabNo(nDestPos);
623 diff --git sc/source/core/data/documen3.cxx sc/source/core/data/documen3.cxx
624 index 6143b5b..03267f7 100644
625 --- sc/source/core/data/documen3.cxx
626 +++ sc/source/core/data/documen3.cxx
628 #include "listenercalls.hxx"
629 #include "svtools/PasswordHelper.hxx"
630 #include "tabprotection.hxx"
631 +#include "clipparam.hxx"
635 @@ -890,7 +891,7 @@ void ScDocument::UpdateReference( UpdateRefMode eUpdateRefMode,
637 ScDocument* pClipDoc = SC_MOD()->GetClipDoc();
639 - pClipDoc->bCutMode = FALSE;
640 + pClipDoc->GetClipParam().mbCutMode = false;
644 @@ -900,7 +901,10 @@ void ScDocument::UpdateTranspose( const ScAddress& rDestPos, ScDocument* pClipDo
646 DBG_ASSERT(pClipDoc->bIsClip, "UpdateTranspose: kein Clip");
648 - ScRange aSource = pClipDoc->aClipRange; // Tab wird noch angepasst
650 + ScClipParam& rClipParam = GetClipParam();
651 + if (rClipParam.maRanges.Count())
652 + aSource = *rClipParam.maRanges.First();
653 ScAddress aDest = rDestPos;
656 diff --git sc/source/core/data/documen8.cxx sc/source/core/data/documen8.cxx
657 index 2e617d7..8cd34a1 100644
658 --- sc/source/core/data/documen8.cxx
659 +++ sc/source/core/data/documen8.cxx
660 @@ -318,20 +318,8 @@ void ScDocument::ModifyStyleSheet( SfxStyleSheetBase& rStyleSheet,
661 void ScDocument::CopyStdStylesFrom( ScDocument* pSrcDoc )
663 // #b5017505# number format exchange list has to be handled here, too
665 - SvNumberFormatter* pThisFormatter = xPoolHelper->GetFormTable();
666 - SvNumberFormatter* pOtherFormatter = pSrcDoc->xPoolHelper->GetFormTable();
667 - if (pOtherFormatter && pOtherFormatter != pThisFormatter)
669 - SvNumberFormatterIndexTable* pExchangeList =
670 - pThisFormatter->MergeFormatter(*(pOtherFormatter));
671 - if (pExchangeList->Count() > 0)
672 - pFormatExchangeList = pExchangeList;
675 + NumFmtMergeHandler aNumFmtMergeHdl(this, pSrcDoc);
676 xPoolHelper->GetStylePool()->CopyStdStylesFrom( pSrcDoc->xPoolHelper->GetStylePool() );
678 - pFormatExchangeList = NULL;
681 //------------------------------------------------------------------------
682 diff --git sc/source/core/data/document.cxx sc/source/core/data/document.cxx
683 index 4366571..e477781 100644
684 --- sc/source/core/data/document.cxx
685 +++ sc/source/core/data/document.cxx
687 #include "postit.hxx"
688 #include "externalrefmgr.hxx"
689 #include "tabprotection.hxx"
690 +#include "clipparam.hxx"
694 namespace WritingMode2 = ::com::sun::star::text::WritingMode2;
696 @@ -1214,7 +1217,7 @@ void ScDocument::AddUndoTab( SCTAB nTab1, SCTAB nTab2, BOOL bColInfo, BOOL bRowI
697 void ScDocument::SetCutMode( BOOL bVal )
701 + GetClipParam().mbCutMode = bVal;
704 DBG_ERROR("SetCutMode without bIsClip");
705 @@ -1225,7 +1228,7 @@ void ScDocument::SetCutMode( BOOL bVal )
706 BOOL ScDocument::IsCutMode()
710 + return GetClipParam().mbCutMode;
713 DBG_ERROR("IsCutMode ohne bIsClip");
714 @@ -1356,33 +1359,16 @@ void ScDocument::CopyToClip(SCCOL nCol1, SCROW nRow1,
715 pClipDoc = SC_MOD()->GetClipDoc();
718 + ScRange aClipRange(nCol1, nRow1, 0, nCol2, nRow2, 0);
719 + ScClipParam& rClipParam = pClipDoc->GetClipParam();
720 + rClipParam.maRanges.RemoveAll();
721 + rClipParam.maRanges.Append(aClipRange);
722 pClipDoc->aDocName = aDocName;
723 - pClipDoc->aClipRange = ScRange( nCol1,nRow1,0, nCol2,nRow2,0 );
724 pClipDoc->ResetClip( this, pMarks );
728 - std::set<USHORT> aUsedNames; // indexes of named ranges that are used in the copied cells
729 - for (j = 0; j <= MAXTAB; j++)
730 - if (pTab[j] && pClipDoc->pTab[j])
731 - if ( bAllTabs || !pMarks || pMarks->GetTableSelect(j) )
732 - pTab[j]->FindRangeNamesInUse( nCol1, nRow1, nCol2, nRow2, aUsedNames );
733 + CopyRangeNamesToClip(pClipDoc, aClipRange, pMarks, bAllTabs);
735 - pClipDoc->pRangeName->FreeAll();
736 - for (i = 0; i < pRangeName->GetCount(); i++) //! DB-Bereiche Pivot-Bereiche auch !!!
738 - USHORT nIndex = ((ScRangeData*)((*pRangeName)[i]))->GetIndex();
739 - bool bInUse = ( aUsedNames.find(nIndex) != aUsedNames.end() );
742 - ScRangeData* pData = new ScRangeData(*((*pRangeName)[i]));
743 - if (!pClipDoc->pRangeName->Insert(pData))
746 - pData->SetIndex(nIndex);
749 - for (j = 0; j <= MAXTAB; j++)
750 + for (SCTAB j = 0; j <= MAXTAB; j++)
751 if (pTab[j] && pClipDoc->pTab[j])
752 if ( bAllTabs || !pMarks || pMarks->GetTableSelect(j) )
754 @@ -1397,10 +1383,53 @@ void ScDocument::CopyToClip(SCCOL nCol1, SCROW nRow1,
758 - pClipDoc->bCutMode = bCut;
759 + pClipDoc->GetClipParam().mbCutMode = bCut;
763 +void ScDocument::CopyToClip(const ScClipParam& rClipParam,
764 + ScDocument* pClipDoc, const ScMarkData* pMarks,
765 + bool bKeepScenarioFlags, bool bIncludeObjects, bool bCloneNoteCaptions)
772 + DBG_ERROR("CopyToClip: no ClipDoc");
773 + pClipDoc = SC_MOD()->GetClipDoc();
776 + pClipDoc->aDocName = aDocName;
777 + pClipDoc->SetClipParam(rClipParam);
778 + pClipDoc->ResetClip(this, pMarks);
780 + ScRange aClipRange = rClipParam.getWholeRange();
781 + CopyRangeNamesToClip(pClipDoc, aClipRange, pMarks, false);
783 + for (SCTAB i = 0; i <= MAXTAB; ++i)
785 + if (!pTab[i] || !pClipDoc->pTab[i])
788 + if (pMarks && !pMarks->GetTableSelect(i))
791 + pTab[i]->CopyToClip(rClipParam.maRanges, pClipDoc->pTab[i], bKeepScenarioFlags, bCloneNoteCaptions);
793 + if (pDrawLayer && bIncludeObjects)
795 + // also copy drawing objects
796 + const ScRange aRange = rClipParam.getWholeRange();
797 + Rectangle aObjRect = GetMMRect(
798 + aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), aRange.aEnd.Row(), i);
799 + pDrawLayer->CopyToClip(pClipDoc, i, aObjRect);
803 + // Make sure to mark overlapped cells.
804 + pClipDoc->ExtendMerge(aClipRange, true);
807 void ScDocument::CopyTabToClip(SCCOL nCol1, SCROW nRow1,
808 SCCOL nCol2, SCROW nRow2,
809 @@ -1416,14 +1445,16 @@ void ScDocument::CopyTabToClip(SCCOL nCol1, SCROW nRow1,
810 pClipDoc = SC_MOD()->GetClipDoc();
813 + ScClipParam& rClipParam = pClipDoc->GetClipParam();
814 pClipDoc->aDocName = aDocName;
815 - pClipDoc->aClipRange = ScRange( nCol1,nRow1,0, nCol2,nRow2,0 );
816 + rClipParam.maRanges.RemoveAll();
817 + rClipParam.maRanges.Append(ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0));
818 pClipDoc->ResetClip( this, nTab );
820 if (pTab[nTab] && pClipDoc->pTab[nTab])
821 pTab[nTab]->CopyToClip(nCol1, nRow1, nCol2, nRow2, pClipDoc->pTab[nTab], FALSE, TRUE);
823 - pClipDoc->bCutMode = FALSE;
824 + pClipDoc->GetClipParam().mbCutMode = false;
828 @@ -1453,6 +1484,7 @@ void ScDocument::TransposeClip( ScDocument* pTransClip, USHORT nFlags, BOOL bAsL
832 + ScRange aClipRange = GetClipParam().getWholeRange();
833 if ( ValidRow(aClipRange.aEnd.Row()-aClipRange.aStart.Row()) )
835 for (SCTAB i=0; i<=MAXTAB; i++)
836 @@ -1481,10 +1513,8 @@ void ScDocument::TransposeClip( ScDocument* pTransClip, USHORT nFlags, BOOL bAsL
840 - pTransClip->aClipRange = ScRange( 0, 0, aClipRange.aStart.Tab(),
841 - static_cast<SCCOL>(aClipRange.aEnd.Row() - aClipRange.aStart.Row()),
842 - static_cast<SCROW>(aClipRange.aEnd.Col() - aClipRange.aStart.Col()),
843 - aClipRange.aEnd.Tab() );
844 + pTransClip->SetClipParam(GetClipParam());
845 + pTransClip->GetClipParam().transpose();
849 @@ -1493,9 +1523,184 @@ void ScDocument::TransposeClip( ScDocument* pTransClip, USHORT nFlags, BOOL bAsL
851 // Dies passiert erst beim Einfuegen...
854 + GetClipParam().mbCutMode = false;
857 +void ScDocument::CopyRangeNamesToClip(ScDocument* pClipDoc, const ScRange& rClipRange, const ScMarkData* pMarks, bool bAllTabs)
859 + std::set<USHORT> aUsedNames; // indexes of named ranges that are used in the copied cells
860 + for (SCTAB i = 0; i <= MAXTAB; ++i)
861 + if (pTab[i] && pClipDoc->pTab[i])
862 + if ( bAllTabs || !pMarks || pMarks->GetTableSelect(i) )
863 + pTab[i]->FindRangeNamesInUse(
864 + rClipRange.aStart.Col(), rClipRange.aStart.Row(),
865 + rClipRange.aEnd.Col(), rClipRange.aEnd.Row(), aUsedNames);
867 + pClipDoc->pRangeName->FreeAll();
868 + for (USHORT i = 0; i < pRangeName->GetCount(); i++) //! DB-Bereiche Pivot-Bereiche auch !!!
870 + USHORT nIndex = ((ScRangeData*)((*pRangeName)[i]))->GetIndex();
871 + bool bInUse = ( aUsedNames.find(nIndex) != aUsedNames.end() );
874 + ScRangeData* pData = new ScRangeData(*((*pRangeName)[i]));
875 + if (!pClipDoc->pRangeName->Insert(pData))
878 + pData->SetIndex(nIndex);
883 +ScDocument::NumFmtMergeHandler::NumFmtMergeHandler(ScDocument* pDoc, ScDocument* pSrcDoc) :
886 + mpDoc->MergeNumberFormatter(pSrcDoc);
889 +ScDocument::NumFmtMergeHandler::~NumFmtMergeHandler()
891 + mpDoc->pFormatExchangeList = NULL;
894 +void ScDocument::MergeNumberFormatter(ScDocument* pSrcDoc)
896 + SvNumberFormatter* pThisFormatter = xPoolHelper->GetFormTable();
897 + SvNumberFormatter* pOtherFormatter = pSrcDoc->xPoolHelper->GetFormTable();
898 + if (pOtherFormatter && pOtherFormatter != pThisFormatter)
900 + SvNumberFormatterIndexTable* pExchangeList =
901 + pThisFormatter->MergeFormatter(*(pOtherFormatter));
902 + if (pExchangeList->Count() > 0)
903 + pFormatExchangeList = pExchangeList;
907 +void ScDocument::CopyRangeNamesFromClip(ScDocument* pClipDoc, ScClipRangeNameData& rRangeNames)
909 + sal_uInt16 nClipRangeNameCount = pClipDoc->pRangeName->GetCount();
910 + ScClipRangeNameData aClipRangeNames;
912 + // array containing range names which might need update of indices
913 + aClipRangeNames.mpRangeNames.resize(nClipRangeNameCount, NULL);
915 + for (sal_uInt16 i = 0; i < nClipRangeNameCount; ++i) //! DB-Bereiche Pivot-Bereiche auch
917 + /* Copy only if the name doesn't exist in this document.
918 + If it exists we use the already existing name instead,
919 + another possibility could be to create new names if
921 + A proper solution would ask the user how to proceed.
922 + The adjustment of the indices in the formulas is done later.
924 + ScRangeData* pClipRangeData = (*pClipDoc->pRangeName)[i];
926 + if ( pRangeName->SearchName( pClipRangeData->GetName(), k ) )
928 + aClipRangeNames.mpRangeNames[i] = NULL; // range name not inserted
929 + USHORT nOldIndex = pClipRangeData->GetIndex();
930 + USHORT nNewIndex = ((*pRangeName)[k])->GetIndex();
931 + aClipRangeNames.insert(nOldIndex, nNewIndex);
932 + if ( !aClipRangeNames.mbReplace )
933 + aClipRangeNames.mbReplace = ( nOldIndex != nNewIndex );
937 + ScRangeData* pData = new ScRangeData( *pClipRangeData );
938 + pData->SetDocument(this);
939 + if ( pRangeName->FindIndex( pData->GetIndex() ) )
940 + pData->SetIndex(0); // need new index, done in Insert
941 + if ( pRangeName->Insert( pData ) )
943 + aClipRangeNames.mpRangeNames[i] = pData;
944 + USHORT nOldIndex = pClipRangeData->GetIndex();
945 + USHORT nNewIndex = pData->GetIndex();
946 + aClipRangeNames.insert(nOldIndex, nNewIndex);
947 + if ( !aClipRangeNames.mbReplace )
948 + aClipRangeNames.mbReplace = ( nOldIndex != nNewIndex );
951 + { // must be an overflow
953 + aClipRangeNames.mpRangeNames[i] = NULL;
954 + aClipRangeNames.insert(pClipRangeData->GetIndex(), 0);
955 + aClipRangeNames.mbReplace = true;
959 + rRangeNames = aClipRangeNames;
962 +void ScDocument::UpdateRangeNamesInFormulas(
963 + ScClipRangeNameData& rRangeNames, const ScRangeList& rDestRanges, const ScMarkData& rMark,
964 + SCCOL nXw, SCROW nYw)
966 + // nXw and nYw are the extra width and height of the destination range
967 + // extended due to presence of merged cell(s).
969 + if (!rRangeNames.mbReplace)
972 + // first update all inserted named formulas if they contain other
973 + // range names and used indices changed
974 + sal_uInt16 nRangeNameCount = rRangeNames.mpRangeNames.size();
975 + for (sal_uInt16 i = 0; i < nRangeNameCount; ++i) //! DB-Bereiche Pivot-Bereiche auch
977 + if ( rRangeNames.mpRangeNames[i] )
978 + rRangeNames.mpRangeNames[i]->ReplaceRangeNamesInUse(rRangeNames.maRangeMap);
980 + // then update the formulas, they might need just the updated range names
981 + for (ULONG nRange = 0; nRange < rDestRanges.Count(); ++nRange)
983 + const ScRange* pRange = rDestRanges.GetObject( nRange);
984 + SCCOL nCol1 = pRange->aStart.Col();
985 + SCROW nRow1 = pRange->aStart.Row();
986 + SCCOL nCol2 = pRange->aEnd.Col();
987 + SCROW nRow2 = pRange->aEnd.Row();
991 + SCCOL nC2 = nC1 + nXw;
994 + SCROW nR2 = nR1 + nYw;
1001 + for (SCTAB k = 0; k <= MAXTAB; k++)
1003 + if ( pTab[k] && rMark.GetTableSelect(k) )
1004 + pTab[k]->ReplaceRangeNamesInUse(nC1, nR1,
1005 + nC2, nR2, rRangeNames.maRangeMap);
1008 + nC2 = Min((SCCOL)(nC1 + nXw), nCol2);
1009 + } while (nC1 <= nCol2);
1015 + nR2 = Min((SCROW)(nR1 + nYw), nRow2);
1016 + } while (nR1 <= nRow2);
1020 +ScClipParam& ScDocument::GetClipParam()
1022 + if (!mpClipParam.get())
1023 + mpClipParam.reset(new ScClipParam);
1025 + return *mpClipParam;
1028 +void ScDocument::SetClipParam(const ScClipParam& rParam)
1030 + mpClipParam.reset(new ScClipParam(rParam));
1033 BOOL ScDocument::IsClipboardSource() const
1035 @@ -1595,7 +1800,7 @@ void ScDocument::CopyBlockFromClip( SCCOL nCol1, SCROW nRow1,
1036 && ppClipTab[nClipTab + nFollow + 1] )
1039 - if ( pCBFCP->pClipDoc->bCutMode )
1040 + if ( pCBFCP->pClipDoc->GetClipParam().mbCutMode )
1042 BOOL bOldInserting = IsInsertingFromOtherDoc();
1043 SetInsertingFromOtherDoc( TRUE);
1044 @@ -1637,7 +1842,9 @@ void ScDocument::CopyNonFilteredFromClip( SCCOL nCol1, SCROW nRow1,
1045 pCBFCP->pClipDoc->GetRowFlagsArray( nFlagTab);
1047 SCROW nSourceRow = rClipStartRow;
1048 - SCROW nSourceEnd = pCBFCP->pClipDoc->aClipRange.aEnd.Row();
1049 + SCROW nSourceEnd = 0;
1050 + if (pCBFCP->pClipDoc->GetClipParam().maRanges.Count())
1051 + nSourceEnd = pCBFCP->pClipDoc->GetClipParam().maRanges.First()->aEnd.Row();
1052 SCROW nDestRow = nRow1;
1054 while ( nSourceRow <= nSourceEnd && nDestRow <= nRow2 )
1055 @@ -1683,67 +1890,11 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar
1056 BOOL bOldAutoCalc = GetAutoCalc();
1057 SetAutoCalc( FALSE ); // avoid multiple recalculations
1059 - SvNumberFormatter* pThisFormatter = xPoolHelper->GetFormTable();
1060 - SvNumberFormatter* pOtherFormatter = pClipDoc->xPoolHelper->GetFormTable();
1061 - if (pOtherFormatter && pOtherFormatter != pThisFormatter)
1063 - SvNumberFormatterIndexTable* pExchangeList =
1064 - pThisFormatter->MergeFormatter(*(pOtherFormatter));
1065 - if (pExchangeList->Count() > 0)
1066 - pFormatExchangeList = pExchangeList;
1068 + NumFmtMergeHandler aNumFmtMergeHdl(this, pClipDoc);
1070 - USHORT nClipRangeNames = pClipDoc->pRangeName->GetCount();
1071 - // array containing range names which might need update of indices
1072 - ScRangeData** pClipRangeNames = nClipRangeNames ? new ScRangeData* [nClipRangeNames] : NULL;
1073 - // the index mapping thereof
1074 - ScIndexMap aClipRangeMap( nClipRangeNames );
1075 - BOOL bRangeNameReplace = FALSE;
1076 + ScClipRangeNameData aClipRangeNames;
1077 + CopyRangeNamesFromClip(pClipDoc, aClipRangeNames);
1079 - for (USHORT i = 0; i < nClipRangeNames; i++) //! DB-Bereiche Pivot-Bereiche auch
1081 - /* Copy only if the name doesn't exist in this document.
1082 - If it exists we use the already existing name instead,
1083 - another possibility could be to create new names if
1085 - A proper solution would ask the user how to proceed.
1086 - The adjustment of the indices in the formulas is done later.
1088 - ScRangeData* pClipRangeData = (*pClipDoc->pRangeName)[i];
1090 - if ( pRangeName->SearchName( pClipRangeData->GetName(), k ) )
1092 - pClipRangeNames[i] = NULL; // range name not inserted
1093 - USHORT nOldIndex = pClipRangeData->GetIndex();
1094 - USHORT nNewIndex = ((*pRangeName)[k])->GetIndex();
1095 - aClipRangeMap.SetPair( i, nOldIndex, nNewIndex );
1096 - if ( !bRangeNameReplace )
1097 - bRangeNameReplace = ( nOldIndex != nNewIndex );
1101 - ScRangeData* pData = new ScRangeData( *pClipRangeData );
1102 - pData->SetDocument(this);
1103 - if ( pRangeName->FindIndex( pData->GetIndex() ) )
1104 - pData->SetIndex(0); // need new index, done in Insert
1105 - if ( pRangeName->Insert( pData ) )
1107 - pClipRangeNames[i] = pData;
1108 - USHORT nOldIndex = pClipRangeData->GetIndex();
1109 - USHORT nNewIndex = pData->GetIndex();
1110 - aClipRangeMap.SetPair( i, nOldIndex, nNewIndex );
1111 - if ( !bRangeNameReplace )
1112 - bRangeNameReplace = ( nOldIndex != nNewIndex );
1115 - { // must be an overflow
1117 - pClipRangeNames[i] = NULL;
1118 - aClipRangeMap.SetPair( i, pClipRangeData->GetIndex(), 0 );
1119 - bRangeNameReplace = TRUE;
1123 SCCOL nAllCol1 = rDestRange.aStart.Col();
1124 SCROW nAllRow1 = rDestRange.aStart.Row();
1125 SCCOL nAllCol2 = rDestRange.aEnd.Col();
1126 @@ -1751,17 +1902,18 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar
1130 + ScRange aClipRange = pClipDoc->GetClipParam().getWholeRange();
1131 for (SCTAB nTab = 0; nTab <= MAXTAB; nTab++) // find largest merge overlap
1132 if (pClipDoc->pTab[nTab]) // all sheets of the clipboard content
1134 - SCCOL nThisEndX = pClipDoc->aClipRange.aEnd.Col();
1135 - SCROW nThisEndY = pClipDoc->aClipRange.aEnd.Row();
1136 - pClipDoc->ExtendMerge( pClipDoc->aClipRange.aStart.Col(),
1137 - pClipDoc->aClipRange.aStart.Row(),
1138 + SCCOL nThisEndX = aClipRange.aEnd.Col();
1139 + SCROW nThisEndY = aClipRange.aEnd.Row();
1140 + pClipDoc->ExtendMerge( aClipRange.aStart.Col(),
1141 + aClipRange.aStart.Row(),
1142 nThisEndX, nThisEndY, nTab );
1143 // only extra value from ExtendMerge
1144 - nThisEndX = sal::static_int_cast<SCCOL>( nThisEndX - pClipDoc->aClipRange.aEnd.Col() );
1145 - nThisEndY = sal::static_int_cast<SCROW>( nThisEndY - pClipDoc->aClipRange.aEnd.Row() );
1146 + nThisEndX = sal::static_int_cast<SCCOL>( nThisEndX - aClipRange.aEnd.Col() );
1147 + nThisEndY = sal::static_int_cast<SCROW>( nThisEndY - aClipRange.aEnd.Row() );
1148 if ( nThisEndX > nXw )
1150 if ( nThisEndY > nYw )
1151 @@ -1820,10 +1972,10 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar
1153 ScColumn::bDoubleAlloc = TRUE;
1155 - SCCOL nClipStartCol = pClipDoc->aClipRange.aStart.Col();
1156 - SCROW nClipStartRow = pClipDoc->aClipRange.aStart.Row();
1157 + SCCOL nClipStartCol = aClipRange.aStart.Col();
1158 + SCROW nClipStartRow = aClipRange.aStart.Row();
1159 // WaE: commented because unused: SCCOL nClipEndCol = pClipDoc->aClipRange.aEnd.Col();
1160 - SCROW nClipEndRow = pClipDoc->aClipRange.aEnd.Row();
1161 + SCROW nClipEndRow = aClipRange.aEnd.Row();
1162 for (ULONG nRange = 0; nRange < pDestRanges->Count(); ++nRange)
1164 const ScRange* pRange = pDestRanges->GetObject( nRange);
1165 @@ -1874,7 +2026,7 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar
1166 nC2 = Min((SCCOL)(nC1 + nXw), nCol2);
1167 } while (nC1 <= nCol2);
1168 if (nClipStartRow > nClipEndRow)
1169 - nClipStartRow = pClipDoc->aClipRange.aStart.Row();
1170 + nClipStartRow = aClipRange.aStart.Row();
1174 @@ -1891,75 +2043,120 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar
1175 pTab[k]->DecRecalcLevel();
1177 bInsertingFromOtherDoc = FALSE;
1178 - pFormatExchangeList = NULL;
1179 - if ( bRangeNameReplace )
1181 - // first update all inserted named formulas if they contain other
1182 - // range names and used indices changed
1183 - for (USHORT i = 0; i < nClipRangeNames; i++) //! DB-Bereiche Pivot-Bereiche auch
1185 - if ( pClipRangeNames[i] )
1186 - pClipRangeNames[i]->ReplaceRangeNamesInUse( aClipRangeMap );
1188 - // then update the formulas, they might need the just updated range names
1189 - for (ULONG nRange = 0; nRange < pDestRanges->Count(); ++nRange)
1191 - const ScRange* pRange = pDestRanges->GetObject( nRange);
1192 - SCCOL nCol1 = pRange->aStart.Col();
1193 - SCROW nRow1 = pRange->aStart.Row();
1194 - SCCOL nCol2 = pRange->aEnd.Col();
1195 - SCROW nRow2 = pRange->aEnd.Row();
1197 - SCCOL nC1 = nCol1;
1198 - SCROW nR1 = nRow1;
1199 - SCCOL nC2 = nC1 + nXw;
1202 - SCROW nR2 = nR1 + nYw;
1209 - for (SCTAB k = 0; k <= MAXTAB; k++)
1211 - if ( pTab[k] && rMark.GetTableSelect(k) )
1212 - pTab[k]->ReplaceRangeNamesInUse(nC1, nR1,
1213 - nC2, nR2, aClipRangeMap );
1216 - nC2 = Min((SCCOL)(nC1 + nXw), nCol2);
1217 - } while (nC1 <= nCol2);
1223 - nR2 = Min((SCROW)(nR1 + nYw), nRow2);
1224 - } while (nR1 <= nRow2);
1227 - if ( pClipRangeNames )
1228 - delete [] pClipRangeNames;
1230 + UpdateRangeNamesInFormulas(aClipRangeNames, *pDestRanges, rMark, nXw, nYw);
1232 // Listener aufbauen nachdem alles inserted wurde
1233 StartListeningFromClip( nAllCol1, nAllRow1, nAllCol2, nAllRow2, rMark, nInsFlag );
1234 // nachdem alle Listener aufgebaut wurden, kann gebroadcastet werden
1235 BroadcastFromClip( nAllCol1, nAllRow1, nAllCol2, nAllRow2, rMark, nInsFlag );
1237 - pClipDoc->bCutMode = FALSE;
1238 + pClipDoc->GetClipParam().mbCutMode = false;
1239 SetAutoCalc( bOldAutoCalc );
1244 +void ScDocument::CopyMultiRangeFromClip(
1245 + const ScAddress& rDestPos, const ScMarkData& rMark, sal_uInt16 nInsFlag, ScDocument* pClipDoc,
1246 + bool bResetCut, bool bAsLink, bool /*bIncludeFiltered*/, bool bSkipAttrForEmpty)
1251 + if (!pClipDoc->bIsClip || !pClipDoc->GetTableCount())
1252 + // There is nothing in the clip doc to copy.
1255 + BOOL bOldAutoCalc = GetAutoCalc();
1256 + SetAutoCalc( FALSE ); // avoid multiple recalculations
1258 + NumFmtMergeHandler aNumFmtMergeHdl(this, pClipDoc);
1260 + ScClipRangeNameData aClipRangeNames;
1261 + CopyRangeNamesFromClip(pClipDoc, aClipRangeNames);
1263 + SCCOL nCol1 = rDestPos.Col();
1264 + SCROW nRow1 = rDestPos.Row();
1265 + ScClipParam& rClipParam = pClipDoc->GetClipParam();
1267 + ScCopyBlockFromClipParams aCBFCP;
1268 + aCBFCP.pRefUndoDoc = NULL;
1269 + aCBFCP.pClipDoc = pClipDoc;
1270 + aCBFCP.nInsFlag = nInsFlag;
1271 + aCBFCP.bAsLink = bAsLink;
1272 + aCBFCP.bSkipAttrForEmpty = bSkipAttrForEmpty;
1273 + aCBFCP.nTabStart = MAXTAB;
1274 + aCBFCP.nTabEnd = 0;
1276 + SCCOL nCols = rClipParam.getPasteColSize();
1277 + SCROW nRows = rClipParam.getPasteRowSize();
1278 + for (SCTAB j = 0; j <= MAXTAB; ++j)
1280 + if (pTab[j] && rMark.GetTableSelect(j))
1282 + if ( j < aCBFCP.nTabStart )
1283 + aCBFCP.nTabStart = j;
1284 + aCBFCP.nTabEnd = j;
1285 + pTab[j]->IncRecalcLevel();
1289 + bInsertingFromOtherDoc = TRUE; // kein Broadcast/Listener aufbauen bei Insert
1291 + if (!bSkipAttrForEmpty)
1293 + sal_uInt16 nDelFlag = IDF_CONTENTS;
1294 + DeleteArea(nCol1, nRow1, nCol1+nCols-1, nRow1+nRows-1, rMark, nDelFlag);
1297 + for (ScRange* p = rClipParam.maRanges.First(); p; p = rClipParam.maRanges.Next())
1299 + SCsCOL nDx = static_cast<SCsCOL>(nCol1 - p->aStart.Col());
1300 + SCsROW nDy = static_cast<SCsROW>(nRow1 - p->aStart.Row());
1301 + SCCOL nCol2 = nCol1 + p->aEnd.Col() - p->aStart.Col();
1302 + SCROW nRow2 = nRow1 + p->aEnd.Row() - p->aStart.Row();
1304 + CopyBlockFromClip(nCol1, nRow1, nCol2, nRow2, rMark, nDx, nDy, &aCBFCP);
1306 + if (rClipParam.meDirection == ScClipParam::Column)
1307 + nCol1 += p->aEnd.Col() - p->aStart.Col() + 1;
1308 + if (rClipParam.meDirection == ScClipParam::Row)
1309 + nRow1 += p->aEnd.Row() - p->aStart.Row() + 1;
1312 + for (SCTAB i = 0; i <= MAXTAB; i++)
1313 + if (pTab[i] && rMark.GetTableSelect(i))
1314 + pTab[i]->DecRecalcLevel();
1316 + bInsertingFromOtherDoc = FALSE;
1318 + ScRange aDestRange(rDestPos.Col(), rDestPos.Row(), rDestPos.Tab(),
1319 + rDestPos.Col()+nCols-1, rDestPos.Row()+nRows-1, rDestPos.Tab());
1320 + ScRangeList aRanges;
1321 + aRanges.Append(aDestRange);
1322 + UpdateRangeNamesInFormulas(aClipRangeNames, aRanges, rMark, nCols-1, nRows-1);
1324 + // Listener aufbauen nachdem alles inserted wurde
1325 + StartListeningFromClip(aDestRange.aStart.Col(), aDestRange.aStart.Row(),
1326 + aDestRange.aEnd.Col(), aDestRange.aEnd.Row(), rMark, nInsFlag );
1327 + // nachdem alle Listener aufgebaut wurden, kann gebroadcastet werden
1328 + BroadcastFromClip(aDestRange.aStart.Col(), aDestRange.aStart.Row(),
1329 + aDestRange.aEnd.Col(), aDestRange.aEnd.Row(), rMark, nInsFlag );
1332 + pClipDoc->GetClipParam().mbCutMode = false;
1333 + SetAutoCalc( bOldAutoCalc );
1336 void ScDocument::SetClipArea( const ScRange& rArea, BOOL bCut )
1340 - aClipRange = rArea;
1342 + ScClipParam& rClipParam = GetClipParam();
1343 + rClipParam.maRanges.RemoveAll();
1344 + rClipParam.maRanges.Append(rArea);
1345 + rClipParam.mbCutMode = bCut;
1349 @@ -1970,33 +2167,53 @@ void ScDocument::SetClipArea( const ScRange& rArea, BOOL bCut )
1351 void ScDocument::GetClipArea(SCCOL& nClipX, SCROW& nClipY, BOOL bIncludeFiltered)
1355 - nClipX = aClipRange.aEnd.Col() - aClipRange.aStart.Col();
1358 + DBG_ERROR("GetClipArea: kein Clip");
1362 - if ( bIncludeFiltered )
1363 - nClipY = aClipRange.aEnd.Row() - aClipRange.aStart.Row();
1366 - // count non-filtered rows
1367 - // count on first used table in clipboard
1368 - SCTAB nCountTab = 0;
1369 - while ( nCountTab < MAXTAB && !pTab[nCountTab] )
1372 - SCROW nResult = GetRowFlagsArray( nCountTab).CountForCondition(
1373 - aClipRange.aStart.Row(), aClipRange.aEnd.Row(),
1376 - if ( nResult > 0 )
1377 - nClipY = nResult - 1;
1379 - nClipY = 0; // always return at least 1 row
1381 + ScRangeList& rClipRanges = GetClipParam().maRanges;
1382 + if (!rClipRanges.Count())
1383 + // No clip range. Bail out.
1386 + ScRangePtr p = rClipRanges.First();
1387 + SCCOL nStartCol = p->aStart.Col();
1388 + SCCOL nEndCol = p->aEnd.Col();
1389 + SCROW nStartRow = p->aStart.Row();
1390 + SCROW nEndRow = p->aEnd.Row();
1391 + for (p = rClipRanges.Next(); p; p = rClipRanges.Next())
1393 + if (p->aStart.Col() < nStartCol)
1394 + nStartCol = p->aStart.Col();
1395 + if (p->aStart.Row() < nStartRow)
1396 + nStartRow = p->aStart.Row();
1397 + if (p->aEnd.Col() > nEndCol)
1398 + nEndCol = p->aEnd.Col();
1399 + if (p->aEnd.Row() < nEndRow)
1400 + nEndRow = p->aEnd.Row();
1403 + nClipX = nEndCol - nStartCol;
1405 + if ( bIncludeFiltered )
1406 + nClipY = nEndRow - nStartRow;
1409 - DBG_ERROR("GetClipArea: kein Clip");
1410 + // count non-filtered rows
1411 + // count on first used table in clipboard
1412 + SCTAB nCountTab = 0;
1413 + while ( nCountTab < MAXTAB && !pTab[nCountTab] )
1416 + SCROW nResult = GetRowFlagsArray( nCountTab).CountForCondition(
1417 + nStartRow, nEndRow, CR_FILTERED, 0);
1419 + if ( nResult > 0 )
1420 + nClipY = nResult - 1;
1422 + nClipY = 0; // always return at least 1 row
1426 @@ -2005,8 +2222,12 @@ void ScDocument::GetClipStart(SCCOL& nClipX, SCROW& nClipY)
1430 - nClipX = aClipRange.aStart.Col();
1431 - nClipY = aClipRange.aStart.Row();
1432 + ScRangeList& rClipRanges = GetClipParam().maRanges;
1433 + if (rClipRanges.Count())
1435 + nClipX = rClipRanges.First()->aStart.Col();
1436 + nClipY = rClipRanges.First()->aStart.Row();
1441 @@ -2022,8 +2243,12 @@ BOOL ScDocument::HasClipFilteredRows()
1442 while ( nCountTab < MAXTAB && !pTab[nCountTab] )
1445 - return GetRowFlagsArray( nCountTab).HasCondition( aClipRange.aStart.Row(),
1446 - aClipRange.aEnd.Row(), CR_FILTERED, CR_FILTERED);
1447 + ScRangeList& rClipRanges = GetClipParam().maRanges;
1448 + if (!rClipRanges.Count())
1451 + return GetRowFlagsArray( nCountTab).HasCondition( rClipRanges.First()->aStart.Row(),
1452 + rClipRanges.First()->aEnd.Row(), CR_FILTERED, CR_FILTERED);
1456 diff --git sc/source/core/data/makefile.mk sc/source/core/data/makefile.mk
1457 index 9dfc108..8440ee8 100644
1458 --- sc/source/core/data/makefile.mk
1459 +++ sc/source/core/data/makefile.mk
1460 @@ -56,6 +56,7 @@ SLOFILES = \
1461 $(SLO)$/bcaslot.obj \
1464 + $(SLO)$/clipparam.obj \
1465 $(SLO)$/column.obj \
1466 $(SLO)$/column2.obj \
1467 $(SLO)$/column3.obj \
1468 diff --git sc/source/core/data/table1.cxx sc/source/core/data/table1.cxx
1469 index 460abe1..3b2d3c5 100644
1470 --- sc/source/core/data/table1.cxx
1471 +++ sc/source/core/data/table1.cxx
1472 @@ -1303,6 +1303,16 @@ void ScTable::ReplaceRangeNamesInUse(SCCOL nCol1, SCROW nRow1,
1476 +void ScTable::ReplaceRangeNamesInUse(SCCOL nCol1, SCROW nRow1,
1477 + SCCOL nCol2, SCROW nRow2,
1478 + const ScRangeData::IndexMap& rMap )
1480 + for (SCCOL i = nCol1; i <= nCol2 && (ValidCol(i)); i++)
1482 + aCol[i].ReplaceRangeNamesInUse( nRow1, nRow2, rMap );
1486 void ScTable::ExtendPrintArea( OutputDevice* pDev,
1487 SCCOL /* nStartCol */, SCROW nStartRow, SCCOL& rEndCol, SCROW nEndRow )
1489 diff --git sc/source/core/data/table2.cxx sc/source/core/data/table2.cxx
1490 index eec97e2..0ef9cbb 100644
1491 --- sc/source/core/data/table2.cxx
1492 +++ sc/source/core/data/table2.cxx
1493 @@ -367,6 +367,16 @@ void ScTable::CopyToClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1497 +void ScTable::CopyToClip(const ScRangeList& rRanges, ScTable* pTable,
1498 + bool bKeepScenarioFlags, bool bCloneNoteCaptions)
1500 + ScRangeList aRanges(rRanges);
1501 + for (ScRangePtr p = aRanges.First(); p; p = aRanges.Next())
1503 + CopyToClip(p->aStart.Col(), p->aStart.Row(), p->aEnd.Col(), p->aEnd.Row(),
1504 + pTable, bKeepScenarioFlags, bCloneNoteCaptions);
1508 void ScTable::CopyFromClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1509 SCsCOL nDx, SCsROW nDy, USHORT nInsFlag,
1510 diff --git sc/source/core/tool/rangenam.cxx sc/source/core/tool/rangenam.cxx
1511 index 6029663..d30a3d5 100644
1512 --- sc/source/core/tool/rangenam.cxx
1513 +++ sc/source/core/tool/rangenam.cxx
1514 @@ -585,6 +585,31 @@ void ScRangeData::ReplaceRangeNamesInUse( const ScIndexMap& rMap )
1518 +void ScRangeData::ReplaceRangeNamesInUse( const IndexMap& rMap )
1520 + bool bCompile = false;
1521 + for ( FormulaToken* p = pCode->First(); p; p = pCode->Next() )
1523 + if ( p->GetOpCode() == ocName )
1525 + const sal_uInt16 nOldIndex = p->GetIndex();
1526 + IndexMap::const_iterator itr = rMap.find(nOldIndex);
1527 + const sal_uInt16 nNewIndex = itr == rMap.end() ? nOldIndex : itr->second;
1528 + if ( nOldIndex != nNewIndex )
1530 + p->SetIndex( nNewIndex );
1537 + ScCompiler aComp( pDoc, aPos, *pCode);
1538 + aComp.SetGrammar(pDoc->GetGrammar());
1539 + aComp.CompileTokenArray();
1544 void ScRangeData::ValidateTabRefs()
1546 diff --git sc/source/ui/inc/viewfunc.hxx sc/source/ui/inc/viewfunc.hxx
1547 index 17ad51a..f727fb4 100644
1548 --- sc/source/ui/inc/viewfunc.hxx
1549 +++ sc/source/ui/inc/viewfunc.hxx
1550 @@ -354,6 +354,11 @@ private:
1551 void PasteRTF( SCCOL nCol, SCROW nStartRow,
1552 const ::com::sun::star::uno::Reference<
1553 ::com::sun::star::datatransfer::XTransferable >& rxTransferable );
1554 + bool PasteMultiRangesFromClip( sal_uInt16 nFlags, ScDocument* pClipDoc, sal_uInt16 nFunction,
1555 + bool bSkipEmpty, bool bTranspos, bool bAsLink, bool bAllowDialogs,
1556 + InsCellCmd eMoveMode, sal_uInt16 nCondFlags, sal_uInt16 nUndoFlags );
1557 + void PostPasteFromClip(const ScRange& rPasteRange, const ScMarkData& rMark);
1559 USHORT GetOptimalColWidth( SCCOL nCol, SCTAB nTab, BOOL bFormula );
1561 void StartFormatArea();
1562 diff --git sc/source/ui/view/cellsh.cxx sc/source/ui/view/cellsh.cxx
1563 index ddfa8e9..e782dd2 100644
1564 --- sc/source/ui/view/cellsh.cxx
1565 +++ sc/source/ui/view/cellsh.cxx
1566 @@ -206,7 +206,6 @@ void ScCellShell::GetBlockState( SfxItemSet& rSet )
1569 case SID_COPY: // Kopieren
1570 - bDisable = (!bSimpleArea && eMarkType != SC_MARK_SIMPLE_FILTERED);
1571 // nur wegen Matrix nicht editierbar? Matrix nicht zerreissen
1572 //! schlaegt nicht zu, wenn geschuetzt UND Matrix, aber damit
1573 //! muss man leben.. wird in Copy-Routine abgefangen, sonst
1574 diff --git sc/source/ui/view/cellsh1.cxx sc/source/ui/view/cellsh1.cxx
1575 index e297ee8..dfb2928 100644
1576 --- sc/source/ui/view/cellsh1.cxx
1577 +++ sc/source/ui/view/cellsh1.cxx
1579 #include "dpsave.hxx"
1580 #include "dpgroup.hxx" // for ScDPNumGroupInfo
1581 #include "spellparam.hxx"
1582 +#include "clipparam.hxx"
1584 #include "globstr.hrc"
1585 #include "scui_def.hxx" //CHINA001
1586 @@ -2243,7 +2244,13 @@ void ScCellShell::PasteFromClipboard( ScViewData* pViewData, ScTabViewShell* pTa
1587 pTabViewShell->PasteFromSystem();
1590 - pTabViewShell->PasteFromClip( IDF_ALL, pOwnClip->GetDocument(),
1591 + ScDocument* pClipDoc = pOwnClip->GetDocument();
1592 + sal_uInt16 nFlags = IDF_ALL;
1593 + if (pClipDoc->GetClipParam().isMultiRange())
1594 + // For multi-range paste, we paste values by default.
1595 + nFlags &= ~IDF_FORMULA;
1597 + pTabViewShell->PasteFromClip( nFlags, pClipDoc,
1598 PASTE_NOFUNC, FALSE, FALSE, FALSE, INS_NONE, IDF_NONE,
1599 bShowDialog ); // allow warning dialog
1601 diff --git sc/source/ui/view/tabvwsh4.cxx sc/source/ui/view/tabvwsh4.cxx
1602 index 4d3dfc1..0e76555 100644
1603 --- sc/source/ui/view/tabvwsh4.cxx
1604 +++ sc/source/ui/view/tabvwsh4.cxx
1605 @@ -1506,7 +1506,7 @@ BOOL ScTabViewShell::TabKeyInput(const KeyEvent& rKEvt)
1606 // #51889# Spezialfall: Copy/Cut bei Mehrfachselektion -> Fehlermeldung
1607 // (Slot ist disabled, SfxViewShell::KeyInput wuerde also kommentarlos verschluckt)
1608 KeyFuncType eFunc = aCode.GetFunction();
1609 - if ( eFunc == KEYFUNC_COPY || eFunc == KEYFUNC_CUT )
1610 + if ( eFunc == KEYFUNC_CUT )
1613 ScMarkType eMarkType = GetViewData()->GetSimpleArea( aDummy );
1614 diff --git sc/source/ui/view/viewfun3.cxx sc/source/ui/view/viewfun3.cxx
1615 index 0a97b2a..31fca76 100644
1616 --- sc/source/ui/view/viewfun3.cxx
1617 +++ sc/source/ui/view/viewfun3.cxx
1619 #include "drwtrans.hxx"
1620 #include "docuno.hxx"
1621 #include "undodat.hxx" // Amelia Wang
1622 +#include "clipparam.hxx"
1624 using namespace com::sun::star;
1626 @@ -310,10 +311,10 @@ BOOL ScViewFunc::CopyToClip( ScDocument* pClipDoc, BOOL bCut, BOOL bApi, BOOL bI
1629 ScMarkType eMarkType = GetViewData()->GetSimpleArea( aRange );
1630 + ScDocument* pDoc = GetViewData()->GetDocument();
1631 + ScMarkData& rMark = GetViewData()->GetMarkData();
1632 if ( eMarkType == SC_MARK_SIMPLE || eMarkType == SC_MARK_SIMPLE_FILTERED )
1634 - ScDocument* pDoc = GetViewData()->GetDocument();
1635 - ScMarkData& rMark = GetViewData()->GetMarkData();
1636 if ( !pDoc->HasSelectedBlockMatrixFragment(
1637 aRange.aStart.Col(), aRange.aStart.Row(),
1638 aRange.aEnd.Col(), aRange.aEnd.Row(),
1639 @@ -380,6 +381,122 @@ BOOL ScViewFunc::CopyToClip( ScDocument* pClipDoc, BOOL bCut, BOOL bApi, BOOL bI
1640 ErrorMessage(STR_MATRIXFRAGMENTERR);
1643 + else if (eMarkType == SC_MARK_MULTI)
1645 + bool bSuccess = false;
1646 + ScClipParam aClipParam;
1647 + aClipParam.mbCutMode = false;
1648 + rMark.FillRangeListWithMarks(&aClipParam.maRanges, false);
1653 + // We con't support cutting of multi-selections.
1657 + // TODO: What's this for?
1660 + ::std::auto_ptr<ScDocument> pDocClip(new ScDocument(SCDOCMODE_CLIP));
1662 + // Check for geometrical feasibility of the ranges.
1663 + bool bValidRanges = true;
1664 + ScRangePtr p = aClipParam.maRanges.First();
1665 + SCCOL nPrevColDelta = 0;
1666 + SCROW nPrevRowDelta = 0;
1667 + SCCOL nPrevCol = p->aStart.Col();
1668 + SCROW nPrevRow = p->aStart.Row();
1669 + SCCOL nPrevColSize = p->aEnd.Col() - p->aStart.Col() + 1;
1670 + SCROW nPrevRowSize = p->aEnd.Row() - p->aStart.Row() + 1;
1671 + for (p = aClipParam.maRanges.Next(); p; p = aClipParam.maRanges.Next())
1673 + if (pDoc->HasSelectedBlockMatrixFragment(
1674 + p->aStart.Col(), p->aStart.Row(), p->aEnd.Col(), p->aEnd.Row(), rMark))
1676 + bValidRanges = false;
1680 + SCCOL nColDelta = p->aStart.Col() - nPrevCol;
1681 + SCROW nRowDelta = p->aStart.Row() - nPrevRow;
1683 + if ((nColDelta && nRowDelta) || (nPrevColDelta && nRowDelta) || (nPrevRowDelta && nColDelta))
1685 + bValidRanges = false;
1689 + if (aClipParam.meDirection == ScClipParam::Unspecified)
1692 + aClipParam.meDirection = ScClipParam::Column;
1694 + aClipParam.meDirection = ScClipParam::Row;
1697 + SCCOL nColSize = p->aEnd.Col() - p->aStart.Col() + 1;
1698 + SCROW nRowSize = p->aEnd.Row() - p->aStart.Row() + 1;
1700 + if (aClipParam.meDirection == ScClipParam::Column && nRowSize != nPrevRowSize)
1702 + // column-oriented ranges must have identical row size.
1703 + bValidRanges = false;
1706 + if (aClipParam.meDirection == ScClipParam::Row && nColSize != nPrevColSize)
1708 + // likewise, row-oriented ranges must have identical
1710 + bValidRanges = false;
1714 + nPrevCol = p->aStart.Col();
1715 + nPrevRow = p->aStart.Row();
1716 + nPrevColDelta = nColDelta;
1717 + nPrevRowDelta = nRowDelta;
1718 + nPrevColSize = nColSize;
1719 + nPrevRowSize = nRowSize;
1721 + if (!bValidRanges)
1724 + pDoc->CopyToClip(aClipParam, pDocClip.get(), &rMark, false, bIncludeObjects);
1726 + ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
1727 + if ( pChangeTrack )
1728 + pChangeTrack->ResetLastCut(); // kein CutMode mehr
1731 + ScDocShell* pDocSh = GetViewData()->GetDocShell();
1732 + TransferableObjectDescriptor aObjDesc;
1733 + pDocSh->FillTransferableObjectDescriptor( aObjDesc );
1734 + aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
1735 + // maSize is set in ScTransferObj ctor
1737 + ScTransferObj* pTransferObj = new ScTransferObj( pDocClip.release(), aObjDesc );
1738 + uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
1740 + if ( ScGlobal::pDrawClipDocShellRef )
1742 + SfxObjectShellRef aPersistRef( &(*ScGlobal::pDrawClipDocShellRef) );
1743 + pTransferObj->SetDrawPersist( aPersistRef ); // keep persist for ole objects alive
1746 + pTransferObj->CopyToClipboard( GetActiveWin() ); // system clipboard
1747 + SC_MOD()->SetClipObject( pTransferObj, NULL ); // internal clipboard
1754 + if (!bSuccess && !bApi)
1755 + ErrorMessage(STR_NOMULTISELECT);
1762 @@ -743,6 +860,52 @@ BOOL lcl_SelHasAttrib( ScDocument* pDoc, SCCOL nCol1, SCROW nRow1, SCCOL nCol2,
1768 +class CursorSwitcher
1771 + CursorSwitcher(ScViewFunc* pViewFunc) :
1772 + mpViewFunc(pViewFunc)
1774 + mpViewFunc->HideCursor();
1779 + mpViewFunc->ShowCursor();
1782 + ScViewFunc* mpViewFunc;
1785 +bool lcl_checkDestRangeForOverwrite(const ScRange& rDestRange, const ScDocument* pDoc, const ScMarkData& rMark, Window* pParentWnd)
1787 + bool bIsEmpty = true;
1788 + SCTAB nTabCount = pDoc->GetTableCount();
1789 + for (SCTAB nTab=0; nTab < nTabCount && bIsEmpty; ++nTab)
1791 + if (!rMark.GetTableSelect(nTab))
1794 + bIsEmpty = pDoc->IsBlockEmpty(nTab, rDestRange.aStart.Col(), rDestRange.aStart.Row(),
1795 + rDestRange.aEnd.Col(), rDestRange.aEnd.Row());
1800 + ScReplaceWarnBox aBox(pParentWnd);
1801 + if (aBox.Execute() != RET_YES)
1803 + // changing the configuration is within the ScReplaceWarnBox
1812 BOOL ScViewFunc::PasteFromClip( USHORT nFlags, ScDocument* pClipDoc,
1813 USHORT nFunction, BOOL bSkipEmpty,
1814 BOOL bTranspose, BOOL bAsLink,
1815 @@ -768,6 +931,12 @@ BOOL ScViewFunc::PasteFromClip( USHORT nFlags, ScDocument* pClipDoc,
1816 // do not copy note captions into undo document
1817 nUndoFlags |= IDF_NOCAPTIONS;
1819 + ScClipParam& rClipParam = pClipDoc->GetClipParam();
1820 + if (rClipParam.isMultiRange())
1821 + return PasteMultiRangesFromClip(
1822 + nFlags, pClipDoc, nFunction, bSkipEmpty, bTranspose, bAsLink, bAllowDialogs,
1823 + eMoveMode, nContFlags, nUndoFlags);
1825 BOOL bCutMode = pClipDoc->IsCutMode(); // if transposing, take from original clipdoc
1826 BOOL bIncludeFiltered = bCutMode;
1828 @@ -996,23 +1165,8 @@ BOOL ScViewFunc::PasteFromClip( USHORT nFlags, ScDocument* pClipDoc,
1829 SC_MOD()->GetInputOptions().GetReplaceCellsWarn();
1830 if ( bAskIfNotEmpty )
1832 - BOOL bIsEmpty = TRUE;
1833 - SCTAB nTabCount = pDoc->GetTableCount();
1834 - for (SCTAB nTab=0; nTab<nTabCount && bIsEmpty; nTab++)
1835 - if ( aFilteredMark.GetTableSelect(nTab) &&
1836 - !pDoc->IsBlockEmpty( nTab, aUserRange.aStart.Col(), aUserRange.aStart.Row(),
1837 - aUserRange.aEnd.Col(), aUserRange.aEnd.Row() ) )
1842 - ScReplaceWarnBox aBox( GetViewData()->GetDialogParent() );
1843 - if ( aBox.Execute() != RET_YES )
1845 - // changing the configuration is within the ScReplaceWarnBox
1849 + if (!lcl_checkDestRangeForOverwrite(aUserRange, pDoc, aFilteredMark, GetViewData()->GetDialogParent()))
1854 @@ -1281,7 +1435,171 @@ BOOL ScViewFunc::PasteFromClip( USHORT nFlags, ScDocument* pClipDoc,
1855 // AdjustBlockHeight has already been called above
1857 aModificator.SetDocumentModified();
1858 - pDocSh->UpdateOle(GetViewData());
1859 + PostPasteFromClip(aUserRange, rMark);
1863 +bool ScViewFunc::PasteMultiRangesFromClip(
1864 + sal_uInt16 nFlags, ScDocument* pClipDoc, sal_uInt16 nFunction,
1865 + bool bSkipEmpty, bool bTranspose, bool bAsLink, bool bAllowDialogs,
1866 + InsCellCmd eMoveMode, sal_uInt16 /*nContFlags*/, sal_uInt16 nUndoFlags)
1868 + ScViewData& rViewData = *GetViewData();
1869 + ScDocument* pDoc = rViewData.GetDocument();
1870 + ScDocShell* pDocSh = rViewData.GetDocShell();
1871 + ScMarkData aMark(rViewData.GetMarkData());
1872 + const ScAddress& rCurPos = rViewData.GetCurPos();
1873 + ScClipParam& rClipParam = pClipDoc->GetClipParam();
1874 + SCCOL nColSize = rClipParam.getPasteColSize();
1875 + SCROW nRowSize = rClipParam.getPasteRowSize();
1879 + if (static_cast<SCROW>(rCurPos.Col()) + nRowSize-1 > static_cast<SCROW>(MAXCOL))
1881 + ErrorMessage(STR_PASTE_FULL);
1885 + ::std::auto_ptr<ScDocument> pTransClip(new ScDocument(SCDOCMODE_CLIP));
1886 + pClipDoc->TransposeClip(pTransClip.get(), nFlags, bAsLink);
1887 + pClipDoc = pTransClip.release();
1888 + SCCOL nTempColSize = nColSize;
1889 + nColSize = static_cast<SCCOL>(nRowSize);
1890 + nRowSize = static_cast<SCROW>(nTempColSize);
1893 + if (!ValidCol(rCurPos.Col()+nColSize-1) || !ValidRow(rCurPos.Row()+nRowSize-1))
1895 + ErrorMessage(STR_PASTE_FULL);
1899 + // Determine the first and last selected sheet numbers.
1900 + SCTAB nTab1 = aMark.GetFirstSelected();
1901 + SCTAB nTab2 = nTab1;
1902 + for (SCTAB i = nTab1+1; i <= MAXTAB; ++i)
1903 + if (aMark.GetTableSelect(i))
1906 + ScDocShellModificator aModificator(*pDocSh);
1908 + // For multi-selection paste, we don't support cell duplication for larger
1909 + // destination range. In case the destination is marked, we reset it to
1911 + ScRange aMarkedRange(rCurPos.Col(), rCurPos.Row(), nTab1,
1912 + rCurPos.Col()+nColSize-1, rCurPos.Row()+nRowSize-1, nTab2);
1914 + bool bAskIfNotEmpty =
1915 + bAllowDialogs && (nFlags & IDF_CONTENTS) &&
1916 + nFunction == PASTE_NOFUNC && SC_MOD()->GetInputOptions().GetReplaceCellsWarn();
1918 + if (bAskIfNotEmpty)
1920 + if (!lcl_checkDestRangeForOverwrite(aMarkedRange, pDoc, aMark, rViewData.GetDialogParent()))
1924 + aMark.SetMarkArea(aMarkedRange);
1925 + MarkRange(aMarkedRange);
1927 + bool bInsertCells = (eMoveMode != INS_NONE);
1930 + if (!InsertCells(eMoveMode, pDoc->IsUndoEnabled(), true))
1934 + ::std::auto_ptr<ScDocument> pUndoDoc;
1935 + if (pDoc->IsUndoEnabled())
1937 + pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1938 + pUndoDoc->InitUndoSelected(pDoc, aMark, false, false);
1939 + pDoc->CopyToDocument(aMarkedRange, IDF_ALL, false, pUndoDoc.get(), &aMark, true);
1942 + ::std::auto_ptr<ScDocument> pMixDoc;
1943 + if ( bSkipEmpty || nFunction )
1945 + if ( nFlags & IDF_CONTENTS )
1947 + pMixDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1948 + pMixDoc->InitUndoSelected(pDoc, aMark, false, false);
1949 + pDoc->CopyToDocument(aMarkedRange, IDF_CONTENTS, false, pMixDoc.get(), &aMark, true);
1953 + /* Make draw layer and start drawing undo.
1954 + - Needed before AdjustBlockHeight to track moved drawing objects.
1955 + - Needed before pDoc->CopyFromClip to track inserted note caption objects.
1957 + if (nFlags & IDF_OBJECTS)
1958 + pDocSh->MakeDrawLayer();
1959 + if (pDoc->IsUndoEnabled())
1960 + pDoc->BeginDrawUndo();
1962 + CursorSwitcher aCursorSwitch(this);
1963 + sal_uInt16 nNoObjFlags = nFlags & ~IDF_OBJECTS;
1964 + pDoc->CopyMultiRangeFromClip(rCurPos, aMark, nNoObjFlags, pClipDoc,
1965 + true, bAsLink, false, bSkipEmpty);
1967 + if (pMixDoc.get())
1968 + pDoc->MixDocument(aMarkedRange, nFunction, bSkipEmpty, pMixDoc.get());
1970 + AdjustBlockHeight(); // update row heights before pasting objects
1972 + if (nFlags & IDF_OBJECTS)
1974 + // Paste the drawing objects after the row heights have been updated.
1975 + pDoc->CopyMultiRangeFromClip(rCurPos, aMark, IDF_OBJECTS, pClipDoc,
1976 + true, false, false, true);
1979 + pDocSh->PostPaint(rCurPos.Col(), rCurPos.Row(), rCurPos.Tab(),
1980 + rCurPos.Col()+nColSize-1, rCurPos.Row()+nRowSize-1, rCurPos.Tab(),
1983 + if (pDoc->IsUndoEnabled())
1985 + SfxUndoManager* pUndoMgr = pDocSh->GetUndoManager();
1986 + String aUndo = ScGlobal::GetRscString(
1987 + pClipDoc->IsCutMode() ? STR_UNDO_CUT : STR_UNDO_COPY);
1988 + pUndoMgr->EnterListAction(aUndo, aUndo);
1990 + ScUndoPasteOptions aOptions; // store options for repeat
1991 + aOptions.nFunction = nFunction;
1992 + aOptions.bSkipEmpty = bSkipEmpty;
1993 + aOptions.bTranspose = bTranspose;
1994 + aOptions.bAsLink = bAsLink;
1995 + aOptions.eMoveMode = eMoveMode;
1997 + ScUndoPaste* pUndo = new ScUndoPaste(pDocSh,
1998 + aMarkedRange.aStart.Col(),
1999 + aMarkedRange.aStart.Row(),
2000 + aMarkedRange.aStart.Tab(),
2001 + aMarkedRange.aEnd.Col(),
2002 + aMarkedRange.aEnd.Row(),
2003 + aMarkedRange.aEnd.Tab(),
2004 + aMark, pUndoDoc.release(), NULL, nFlags|nUndoFlags, NULL, NULL, NULL, NULL, false, &aOptions);
2007 + pUndoMgr->AddUndoAction(new ScUndoWrapper(pUndo), true);
2009 + pUndoMgr->AddUndoAction(pUndo, false);
2011 + pUndoMgr->LeaveListAction();
2013 + aModificator.SetDocumentModified();
2014 + PostPasteFromClip(aMarkedRange, aMark);
2018 +void ScViewFunc::PostPasteFromClip(const ScRange& rPasteRange, const ScMarkData& rMark)
2020 + ScViewData* pViewData = GetViewData();
2021 + ScDocShell* pDocSh = pViewData->GetDocShell();
2022 + ScDocument* pDoc = pViewData->GetDocument();
2023 + pDocSh->UpdateOle(pViewData);
2027 @@ -1295,7 +1613,7 @@ BOOL ScViewFunc::PasteFromClip( USHORT nFlags, ScDocument* pClipDoc,
2029 if ( rMark.GetTableSelect( i ) )
2031 - ScRange aChangeRange( aUserRange );
2032 + ScRange aChangeRange(rPasteRange);
2033 aChangeRange.aStart.SetTab( i );
2034 aChangeRange.aEnd.SetTab( i );
2035 aChangeRanges.Append( aChangeRange );
2036 @@ -1303,8 +1621,6 @@ BOOL ScViewFunc::PasteFromClip( USHORT nFlags, ScDocument* pClipDoc,
2038 pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges );