update dev300-m57
[ooovba.git] / applied_patches / 0140-calc-multi-range-copy-paste.diff
blobc17efcf415d73f094179fde68c2849844faa18f2
1 diff --git sc/inc/cell.hxx sc/inc/cell.hxx
2 index 5454907..b460a31 100644
3 --- sc/inc/cell.hxx
4 +++ sc/inc/cell.hxx
5 @@ -40,6 +40,7 @@
6 #include <tools/mempool.hxx>
7 #include <svtools/listener.hxx>
8 #include "global.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
22 new file mode 100644
23 index 0000000..1a46f4c
24 --- /dev/null
25 +++ sc/inc/clipparam.hxx
26 @@ -0,0 +1,90 @@
27 +/*************************************************************************
28 + *
29 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
30 + *
31 + * Copyright 2008 by Sun Microsystems, Inc.
32 + *
33 + * OpenOffice.org - a multi-platform office productivity suite
34 + *
35 + * $RCSfile: document.hxx,v $
36 + * $Revision: 1.115.36.9 $
37 + *
38 + * This file is part of OpenOffice.org.
39 + *
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.
43 + *
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).
49 + *
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.
54 + *
55 + ************************************************************************/
57 +#ifndef SC_CLIPPARAM_HXX
58 +#define SC_CLIPPARAM_HXX
60 +#include "rangelst.hxx"
61 +#include "rangenam.hxx"
63 +#include <vector>
65 +/**
66 + * This struct stores general clipboard parameters associated with a
67 + * ScDocument instance created in clipboard mode.
68 + */
69 +struct ScClipParam
71 + enum Direction { Unspecified, Column, Row };
73 + ScRangeList maRanges;
74 + Direction meDirection;
75 + bool mbCutMode;
77 + ScClipParam();
78 + explicit ScClipParam(const ScClipParam& r);
80 + bool isMultiRange() const;
82 + /**
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.
86 + */
87 + SCCOL getPasteColSize();
89 + /**
90 + * Same as the above method, but returns the row size of the compressed
91 + * range.
92 + */
93 + SCROW getPasteRowSize();
95 + /**
96 + * Return a single range that encompasses all individual ranges.
97 + */
98 + ScRange getWholeRange() const;
100 + void transpose();
103 +// ============================================================================
105 +struct ScClipRangeNameData
107 + ScRangeData::IndexMap maRangeMap;
108 + ::std::vector<ScRangeData*> mpRangeNames;
109 + bool mbReplace;
111 + ScClipRangeNameData();
112 + ~ScClipRangeNameData();
113 + void insert(sal_uInt16 nOldIndex, sal_uInt16 nNewIndex);
116 +#endif
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
121 @@ -35,6 +35,7 @@
122 #include "global.hxx"
123 #include "compressedarray.hxx"
124 #include "address.hxx"
125 +#include "rangenam.hxx"
126 #include <tools/solar.h>
128 #include <set>
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 --- sc/inc/document.hxx
138 +++ sc/inc/document.hxx
139 @@ -138,6 +138,8 @@ class ScAutoNameCache;
140 class ScTemporaryChartLock;
141 class ScLookupCache;
142 struct ScLookupCacheMapImpl;
143 +struct ScClipParam;
144 +struct ScClipRangeNameData;
145 class SfxUndoManager;
146 class ScFormulaParserPool;
148 @@ -286,6 +288,7 @@ private:
149 ScFieldEditEngine* pCacheFieldEditEngine;
151 ::std::auto_ptr<ScDocProtection> pDocProtection;
152 + ::std::auto_ptr<ScClipParam> mpClipParam;
154 ::std::auto_ptr<ScExternalRefManager> pExternalRefMgr;
155 String aDocName; // opt: Dokumentname
156 @@ -307,7 +310,6 @@ private:
158 sal_uInt32 nRangeOverflowType; // used in (xml) loading for overflow warnings
160 - ScRange aClipRange;
161 ScRange aEmbedRange;
162 ScAddress aCurTextWidthCalcPos;
163 ScAddress aOnlineSpellPos; // within whole document
164 @@ -357,7 +359,6 @@ private:
165 BOOL bForcedFormulaPending;
166 BOOL bCalculatingFormulaTree;
167 BOOL bIsClip;
168 - BOOL bCutMode;
169 BOOL bIsUndo;
170 BOOL bIsVisible; // set from view ctor
172 @@ -957,6 +958,9 @@ public:
173 BOOL bKeepScenarioFlags = FALSE,
174 BOOL bIncludeObjects = FALSE,
175 BOOL bCloneNoteCaptions = TRUE);
176 + void CopyToClip(const ScClipParam& rClipParam, ScDocument* pClipDoc,
177 + const ScMarkData* pMarks = NULL, bool bKeepScenarioFlags = false,
178 + bool bIncludeObjects = false, bool bCloneNoteCaptions = true);
179 void CopyTabToClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
180 SCTAB nTab, ScDocument* pClipDoc = NULL);
181 void CopyBlockFromClip( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
182 @@ -984,6 +988,12 @@ public:
183 BOOL bSkipAttrForEmpty = FALSE,
184 const ScRangeList * pDestRanges = NULL );
186 + void CopyMultiRangeFromClip(const ScAddress& rDestPos, const ScMarkData& rMark,
187 + sal_uInt16 nInsFlag, ScDocument* pClipDoc,
188 + bool bResetCut = true, bool bAsLink = false,
189 + bool bIncludeFiltered = true,
190 + bool bSkipAttrForEmpty = false);
192 void GetClipArea(SCCOL& nClipX, SCROW& nClipY, BOOL bIncludeFiltered);
193 void GetClipStart(SCCOL& nClipX, SCROW& nClipY);
195 @@ -993,6 +1003,9 @@ public:
197 SC_DLLPUBLIC void TransposeClip( ScDocument* pTransClip, USHORT nFlags, BOOL bAsLink );
199 + ScClipParam& GetClipParam();
200 + void SetClipParam(const ScClipParam& rParam);
202 void MixDocument( const ScRange& rRange, USHORT nFunction, BOOL bSkipEmpty,
203 ScDocument* pSrcDoc );
205 @@ -1692,6 +1705,23 @@ public:
207 private: // CLOOK-Impl-Methoden
209 + /**
210 + * Use this class as a locale variable to merge number formatter from
211 + * another document, and set NULL pointer to pFormatExchangeList when
212 + * done.
213 + */
214 + class NumFmtMergeHandler
216 + public:
217 + explicit NumFmtMergeHandler(ScDocument* pDoc, ScDocument* pSrcDoc);
218 + ~NumFmtMergeHandler();
220 + private:
221 + ScDocument* mpDoc;
222 + };
224 + void MergeNumberFormatter(ScDocument* pSrcDoc);
226 void ImplCreateOptions(); // bei Gelegenheit auf on-demand umstellen?
227 void ImplDeleteOptions();
229 @@ -1713,6 +1743,12 @@ private: // CLOOK-Impl-Methoden
230 void UpdateRefAreaLinks( UpdateRefMode eUpdateRefMode,
231 const ScRange& r, SCsCOL nDx, SCsROW nDy, SCsTAB nDz );
233 + void CopyRangeNamesToClip(ScDocument* pClipDoc, const ScRange& rClipRange, const ScMarkData* pMarks, bool bAllTabs);
234 + void CopyRangeNamesFromClip(ScDocument* pClipDoc, ScClipRangeNameData& rRangeNames);
235 + void UpdateRangeNamesInFormulas(
236 + ScClipRangeNameData& rRangeNames, const ScRangeList& rDestRanges, const ScMarkData& rMark,
237 + SCCOL nXw, SCROW nYw);
239 BOOL HasPartOfMerged( const ScRange& rRange );
241 std::map< SCTAB, ScSortParam > mSheetSortParams;
242 diff --git sc/inc/rangenam.hxx sc/inc/rangenam.hxx
243 index 8231cbd..ece1609 100644
244 --- sc/inc/rangenam.hxx
245 +++ sc/inc/rangenam.hxx
246 @@ -37,6 +37,8 @@
247 #include "formula/grammar.hxx"
248 #include "scdllapi.h"
250 +#include <map>
252 //------------------------------------------------------------------------
254 class ScDocument;
255 @@ -84,6 +86,8 @@ private:
256 friend class ScRangeName;
257 ScRangeData( USHORT nIndex );
258 public:
259 + typedef ::std::map<sal_uInt16, sal_uInt16> IndexMap;
261 SC_DLLPUBLIC ScRangeData( ScDocument* pDoc,
262 const String& rName,
263 const String& rSymbol,
264 @@ -150,6 +154,7 @@ public:
265 void ValidateTabRefs();
267 void ReplaceRangeNamesInUse( const ScIndexMap& rMap );
268 + void ReplaceRangeNamesInUse( const IndexMap& rMap );
270 static void MakeValidName( String& rName );
271 SC_DLLPUBLIC static BOOL IsNameValid( const String& rName, ScDocument* pDoc );
272 diff --git sc/inc/table.hxx sc/inc/table.hxx
273 index 734ad3c..b32bb64 100644
274 --- sc/inc/table.hxx
275 +++ sc/inc/table.hxx
276 @@ -292,6 +292,8 @@ public:
277 void DeleteArea(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, USHORT nDelFlag);
278 void CopyToClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScTable* pTable,
279 BOOL bKeepScenarioFlags, BOOL bCloneNoteCaptions);
280 + void CopyToClip(const ScRangeList& rRanges, ScTable* pTable,
281 + bool bKeepScenarioFlags, bool bCloneNoteCaptions);
282 void CopyFromClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SCsCOL nDx, SCsROW nDy,
283 USHORT nInsFlag, BOOL bAsLink, BOOL bSkipAttrForEmpty, ScTable* pTable);
284 void StartListeningInArea( SCCOL nCol1, SCROW nRow1,
285 @@ -406,6 +408,8 @@ public:
286 std::set<USHORT>& rIndexes) const;
287 void ReplaceRangeNamesInUse(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
288 const ScIndexMap& rMap );
289 + void ReplaceRangeNamesInUse(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
290 + const ScRangeData::IndexMap& rMap );
291 void Fill( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
292 ULONG nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd,
293 double nStepValue, double nMaxValue);
294 diff --git sc/source/core/data/cell2.cxx sc/source/core/data/cell2.cxx
295 index 7e29ed7..c0c17ce 100644
296 --- sc/source/core/data/cell2.cxx
297 +++ sc/source/core/data/cell2.cxx
298 @@ -1318,6 +1318,26 @@ void ScFormulaCell::ReplaceRangeNamesInUse( const ScIndexMap& rMap )
299 CompileTokenArray();
302 +void ScFormulaCell::ReplaceRangeNamesInUse( const ScRangeData::IndexMap& rMap )
304 + for( FormulaToken* p = pCode->First(); p; p = pCode->Next() )
306 + if( p->GetOpCode() == ocName )
308 + sal_uInt16 nIndex = p->GetIndex();
309 + ScRangeData::IndexMap::const_iterator itr = rMap.find(nIndex);
310 + sal_uInt16 nNewIndex = itr == rMap.end() ? nIndex : nNewIndex;
311 + if ( nIndex != nNewIndex )
313 + p->SetIndex( nNewIndex );
314 + bCompile = TRUE;
318 + if( bCompile )
319 + CompileTokenArray();
322 void ScFormulaCell::CompileDBFormula()
324 for( FormulaToken* p = pCode->First(); p; p = pCode->Next() )
325 diff --git sc/source/core/data/clipparam.cxx sc/source/core/data/clipparam.cxx
326 new file mode 100644
327 index 0000000..564b04d
328 --- /dev/null
329 +++ sc/source/core/data/clipparam.cxx
330 @@ -0,0 +1,200 @@
331 +/*************************************************************************
333 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
335 + * Copyright 2008 by Sun Microsystems, Inc.
337 + * OpenOffice.org - a multi-platform office productivity suite
339 + * $RCSfile: document.cxx,v $
340 + * $Revision: 1.90.36.8 $
342 + * This file is part of OpenOffice.org.
344 + * OpenOffice.org is free software: you can redistribute it and/or modify
345 + * it under the terms of the GNU Lesser General Public License version 3
346 + * only, as published by the Free Software Foundation.
348 + * OpenOffice.org is distributed in the hope that it will be useful,
349 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
350 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
351 + * GNU Lesser General Public License version 3 for more details
352 + * (a copy is included in the LICENSE file that accompanied this code).
354 + * You should have received a copy of the GNU Lesser General Public License
355 + * version 3 along with OpenOffice.org. If not, see
356 + * <http://www.openoffice.org/license.html>
357 + * for a copy of the LGPLv3 License.
359 + ************************************************************************/
361 +// MARKER(update_precomp.py): autogen include statement, do not remove
362 +#include "precompiled_sc.hxx"
364 +// INCLUDE ---------------------------------------------------------------
366 +#include "clipparam.hxx"
368 +using ::std::vector;
370 +ScClipParam::ScClipParam() :
371 + meDirection(Unspecified),
372 + mbCutMode(false)
376 +ScClipParam::ScClipParam(const ScClipParam& r) :
377 + maRanges(r.maRanges),
378 + meDirection(r.meDirection),
379 + mbCutMode(r.mbCutMode)
383 +bool ScClipParam::isMultiRange() const
385 + return maRanges.Count() > 1;
388 +SCCOL ScClipParam::getPasteColSize()
390 + if (!maRanges.Count())
391 + return 0;
393 + switch (meDirection)
395 + case ScClipParam::Column:
397 + SCCOL nColSize = 0;
398 + for (ScRangePtr p = maRanges.First(); p; p = maRanges.Next())
399 + nColSize += p->aEnd.Col() - p->aStart.Col() + 1;
400 + return nColSize;
402 + break;
403 + case ScClipParam::Row:
405 + // We assume that all ranges have identical column size.
406 + const ScRange& rRange = *maRanges.First();
407 + return rRange.aEnd.Col() - rRange.aStart.Col() + 1;
409 + break;
410 + case ScClipParam::Unspecified:
411 + default:
414 + return 0;
417 +SCROW ScClipParam::getPasteRowSize()
419 + if (!maRanges.Count())
420 + return 0;
422 + switch (meDirection)
424 + case ScClipParam::Column:
426 + // We assume that all ranges have identical row size.
427 + const ScRange& rRange = *maRanges.First();
428 + return rRange.aEnd.Row() - rRange.aStart.Row() + 1;
430 + break;
431 + case ScClipParam::Row:
433 + SCROW nRowSize = 0;
434 + for (ScRangePtr p = maRanges.First(); p; p = maRanges.Next())
435 + nRowSize += p->aEnd.Row() - p->aStart.Row() + 1;
436 + return nRowSize;
438 + break;
439 + case ScClipParam::Unspecified:
440 + default:
443 + return 0;
446 +ScRange ScClipParam::getWholeRange() const
448 + ScRange aWhole;
449 + bool bFirst = true;
450 + ScRangeList aRanges = maRanges;
451 + for (ScRange* p = aRanges.First(); p; p = aRanges.Next())
453 + if (bFirst)
454 + {
455 + aWhole = *p;
456 + bFirst = false;
457 + continue;
460 + if (aWhole.aStart.Col() > p->aStart.Col())
461 + aWhole.aStart.SetCol(p->aStart.Col());
463 + if (aWhole.aStart.Row() > p->aStart.Row())
464 + aWhole.aStart.SetRow(p->aStart.Row());
466 + if (aWhole.aEnd.Col() < p->aEnd.Col())
467 + aWhole.aEnd.SetCol(p->aEnd.Col());
469 + if (aWhole.aEnd.Row() < p->aEnd.Row())
470 + aWhole.aEnd.SetRow(p->aEnd.Row());
472 + return aWhole;
475 +void ScClipParam::transpose()
477 + switch (meDirection)
479 + case Column:
480 + meDirection = ScClipParam::Row;
481 + break;
482 + case Row:
483 + meDirection = ScClipParam::Column;
484 + break;
485 + case Unspecified:
486 + default:
490 + ScRangeList aNewRanges;
491 + if (maRanges.Count())
493 + ScRange* p = maRanges.First();
494 + SCCOL nColOrigin = p->aStart.Col();
495 + SCROW nRowOrigin = p->aStart.Row();
496 + for (; p; p = maRanges.Next())
498 + SCCOL nColDelta = p->aStart.Col() - nColOrigin;
499 + SCROW nRowDelta = p->aStart.Row() - nRowOrigin;
500 + SCCOL nCol1 = 0;
501 + SCCOL nCol2 = static_cast<SCCOL>(p->aEnd.Row() - p->aStart.Row());
502 + SCROW nRow1 = 0;
503 + SCROW nRow2 = static_cast<SCROW>(p->aEnd.Col() - p->aStart.Col());
504 + nCol1 += static_cast<SCCOL>(nRowDelta);
505 + nCol2 += static_cast<SCCOL>(nRowDelta);
506 + nRow1 += static_cast<SCROW>(nColDelta);
507 + nRow2 += static_cast<SCROW>(nColDelta);
508 + ScRange aNew(nCol1, nRow1, p->aStart.Tab(), nCol2, nRow2, p->aStart.Tab());
509 + aNewRanges.Append(aNew);
512 + maRanges = aNewRanges;
515 +// ============================================================================
517 +ScClipRangeNameData::ScClipRangeNameData() :
518 + mbReplace(false)
522 +ScClipRangeNameData::~ScClipRangeNameData()
526 +void ScClipRangeNameData::insert(sal_uInt16 nOldIndex, sal_uInt16 nNewIndex)
528 + maRangeMap.insert(
529 + ScRangeData::IndexMap::value_type(nOldIndex, nNewIndex));
531 diff --git sc/source/core/data/column.cxx sc/source/core/data/column.cxx
532 index 721a66f..555c3e8 100644
533 --- sc/source/core/data/column.cxx
534 +++ sc/source/core/data/column.cxx
535 @@ -1884,6 +1884,23 @@ void ScColumn::ReplaceRangeNamesInUse(SCROW nRow1, SCROW nRow2,
539 +void ScColumn::ReplaceRangeNamesInUse(SCROW nRow1, SCROW nRow2,
540 + const ScRangeData::IndexMap& rMap )
542 + if (pItems)
543 + for (SCSIZE i = 0; i < nCount; i++)
545 + if ((pItems[i].nRow >= nRow1) &&
546 + (pItems[i].nRow <= nRow2) &&
547 + (pItems[i].pCell->GetCellType() == CELLTYPE_FORMULA))
549 + SCROW nRow = pItems[i].nRow;
550 + ((ScFormulaCell*)pItems[i].pCell)->ReplaceRangeNamesInUse( rMap );
551 + if ( nRow != pItems[i].nRow )
552 + Search( nRow, i ); // Listener geloescht/eingefuegt?
557 void ScColumn::SetDirtyVar()
559 --- sc/source/core/data/documen2.cxx
560 +++ sc/source/core/data/documen2.cxx
561 @@ -95,6 +95,7 @@
562 #include "lookupcache.hxx"
563 #include "externalrefmgr.hxx"
564 #include "tabprotection.hxx"
565 +#include "clipparam.hxx"
566 #include "formulaparserpool.hxx"
568 // pImpl because including lookupcache.hxx in document.hxx isn't wanted, and
569 @@ -153,6 +154,7 @@ ScDocument::ScDocument( ScDocumentMode eMode,
570 pScriptTypeData( NULL ),
571 pCacheFieldEditEngine( NULL ),
572 pDocProtection( NULL ),
573 + mpClipParam( NULL ),
574 pViewOptions( NULL ),
575 pDocOptions( NULL ),
576 pExtDocOptions( NULL ),
577 @@ -181,7 +183,6 @@ ScDocument::ScDocument( ScDocumentMode eMode,
578 bForcedFormulaPending( FALSE ),
579 bCalculatingFormulaTree( FALSE ),
580 bIsClip( eMode == SCDOCMODE_CLIP ),
581 - bCutMode( FALSE ),
582 bIsUndo( eMode == SCDOCMODE_UNDO ),
583 bIsVisible( FALSE ),
584 bIsEmbedded( FALSE ),
585 @@ -978,23 +979,18 @@ ULONG ScDocument::TransferTab( ScDocument* pSrcDoc, SCTAB nSrcPos,
586 bOldAutoCalcSrc = pSrcDoc->GetAutoCalc();
587 pSrcDoc->SetAutoCalc( TRUE ); // falls was berechnet werden muss
589 - SvNumberFormatter* pThisFormatter = xPoolHelper->GetFormTable();
590 - SvNumberFormatter* pOtherFormatter = pSrcDoc->xPoolHelper->GetFormTable();
591 - if (pOtherFormatter && pOtherFormatter != pThisFormatter)
594 - SvNumberFormatterIndexTable* pExchangeList =
595 - pThisFormatter->MergeFormatter(*(pOtherFormatter));
596 - if (pExchangeList->Count() > 0)
597 - pFormatExchangeList = pExchangeList;
599 - nDestPos = Min(nDestPos, (SCTAB)(GetTableCount() - 1));
600 - { // scope for bulk broadcast
601 - ScBulkBroadcast aBulkBroadcast( pBASM);
602 - pSrcDoc->pTab[nSrcPos]->CopyToTable(0, 0, MAXCOL, MAXROW,
603 - ( bResultsOnly ? IDF_ALL & ~IDF_FORMULA : IDF_ALL),
604 - FALSE, pTab[nDestPos] );
605 + NumFmtMergeHandler aNumFmtMergeHdl(this, pSrcDoc);
607 + nDestPos = Min(nDestPos, (SCTAB)(GetTableCount() - 1));
608 + { // scope for bulk broadcast
609 + ScBulkBroadcast aBulkBroadcast( pBASM);
610 + pSrcDoc->pTab[nSrcPos]->CopyToTable(0, 0, MAXCOL, MAXROW,
611 + ( bResultsOnly ? IDF_ALL & ~IDF_FORMULA : IDF_ALL),
612 + FALSE, pTab[nDestPos] );
615 - pFormatExchangeList = NULL;
616 pTab[nDestPos]->SetTabNo(nDestPos);
618 if ( !bResultsOnly )
619 --- sc/source/core/data/documen3.cxx
620 +++ sc/source/core/data/documen3.cxx
621 @@ -79,6 +79,7 @@
622 #include "listenercalls.hxx"
623 #include "svtools/PasswordHelper.hxx"
624 #include "tabprotection.hxx"
625 +#include "clipparam.hxx"
626 #include "formulaparserpool.hxx"
628 #include <memory>
629 @@ -890,7 +891,7 @@ void ScDocument::UpdateReference( UpdateRefMode eUpdateRefMode,
631 ScDocument* pClipDoc = SC_MOD()->GetClipDoc();
632 if (pClipDoc)
633 - pClipDoc->bCutMode = FALSE;
634 + pClipDoc->GetClipParam().mbCutMode = false;
638 @@ -900,7 +901,10 @@ void ScDocument::UpdateTranspose( const ScAddress& rDestPos, ScDocument* pClipDo
640 DBG_ASSERT(pClipDoc->bIsClip, "UpdateTranspose: kein Clip");
642 - ScRange aSource = pClipDoc->aClipRange; // Tab wird noch angepasst
643 + ScRange aSource;
644 + ScClipParam& rClipParam = GetClipParam();
645 + if (rClipParam.maRanges.Count())
646 + aSource = *rClipParam.maRanges.First();
647 ScAddress aDest = rDestPos;
649 SCTAB nClipTab = 0;
650 diff --git sc/source/core/data/documen8.cxx sc/source/core/data/documen8.cxx
651 index 2e617d7..8cd34a1 100644
652 --- sc/source/core/data/documen8.cxx
653 +++ sc/source/core/data/documen8.cxx
654 @@ -318,20 +318,8 @@ void ScDocument::ModifyStyleSheet( SfxStyleSheetBase& rStyleSheet,
655 void ScDocument::CopyStdStylesFrom( ScDocument* pSrcDoc )
657 // #b5017505# number format exchange list has to be handled here, too
659 - SvNumberFormatter* pThisFormatter = xPoolHelper->GetFormTable();
660 - SvNumberFormatter* pOtherFormatter = pSrcDoc->xPoolHelper->GetFormTable();
661 - if (pOtherFormatter && pOtherFormatter != pThisFormatter)
663 - SvNumberFormatterIndexTable* pExchangeList =
664 - pThisFormatter->MergeFormatter(*(pOtherFormatter));
665 - if (pExchangeList->Count() > 0)
666 - pFormatExchangeList = pExchangeList;
669 + NumFmtMergeHandler aNumFmtMergeHdl(this, pSrcDoc);
670 xPoolHelper->GetStylePool()->CopyStdStylesFrom( pSrcDoc->xPoolHelper->GetStylePool() );
672 - pFormatExchangeList = NULL;
675 //------------------------------------------------------------------------
676 diff --git sc/source/core/data/document.cxx sc/source/core/data/document.cxx
677 index 4366571..e477781 100644
678 --- sc/source/core/data/document.cxx
679 +++ sc/source/core/data/document.cxx
680 @@ -94,6 +94,9 @@
681 #include "postit.hxx"
682 #include "externalrefmgr.hxx"
683 #include "tabprotection.hxx"
684 +#include "clipparam.hxx"
686 +#include <map>
688 namespace WritingMode2 = ::com::sun::star::text::WritingMode2;
690 @@ -1214,7 +1217,7 @@ void ScDocument::AddUndoTab( SCTAB nTab1, SCTAB nTab2, BOOL bColInfo, BOOL bRowI
691 void ScDocument::SetCutMode( BOOL bVal )
693 if (bIsClip)
694 - bCutMode = bVal;
695 + GetClipParam().mbCutMode = bVal;
696 else
698 DBG_ERROR("SetCutMode without bIsClip");
699 @@ -1225,7 +1228,7 @@ void ScDocument::SetCutMode( BOOL bVal )
700 BOOL ScDocument::IsCutMode()
702 if (bIsClip)
703 - return bCutMode;
704 + return GetClipParam().mbCutMode;
705 else
707 DBG_ERROR("IsCutMode ohne bIsClip");
708 @@ -1356,33 +1359,16 @@ void ScDocument::CopyToClip(SCCOL nCol1, SCROW nRow1,
709 pClipDoc = SC_MOD()->GetClipDoc();
712 + ScRange aClipRange(nCol1, nRow1, 0, nCol2, nRow2, 0);
713 + ScClipParam& rClipParam = pClipDoc->GetClipParam();
714 + rClipParam.maRanges.RemoveAll();
715 + rClipParam.maRanges.Append(aClipRange);
716 pClipDoc->aDocName = aDocName;
717 - pClipDoc->aClipRange = ScRange( nCol1,nRow1,0, nCol2,nRow2,0 );
718 pClipDoc->ResetClip( this, pMarks );
719 - USHORT i;
720 - SCTAB j;
722 - std::set<USHORT> aUsedNames; // indexes of named ranges that are used in the copied cells
723 - for (j = 0; j <= MAXTAB; j++)
724 - if (pTab[j] && pClipDoc->pTab[j])
725 - if ( bAllTabs || !pMarks || pMarks->GetTableSelect(j) )
726 - pTab[j]->FindRangeNamesInUse( nCol1, nRow1, nCol2, nRow2, aUsedNames );
727 + CopyRangeNamesToClip(pClipDoc, aClipRange, pMarks, bAllTabs);
729 - pClipDoc->pRangeName->FreeAll();
730 - for (i = 0; i < pRangeName->GetCount(); i++) //! DB-Bereiche Pivot-Bereiche auch !!!
732 - USHORT nIndex = ((ScRangeData*)((*pRangeName)[i]))->GetIndex();
733 - bool bInUse = ( aUsedNames.find(nIndex) != aUsedNames.end() );
734 - if (bInUse)
736 - ScRangeData* pData = new ScRangeData(*((*pRangeName)[i]));
737 - if (!pClipDoc->pRangeName->Insert(pData))
738 - delete pData;
739 - else
740 - pData->SetIndex(nIndex);
743 - for (j = 0; j <= MAXTAB; j++)
744 + for (SCTAB j = 0; j <= MAXTAB; j++)
745 if (pTab[j] && pClipDoc->pTab[j])
746 if ( bAllTabs || !pMarks || pMarks->GetTableSelect(j) )
748 @@ -1397,10 +1383,53 @@ void ScDocument::CopyToClip(SCCOL nCol1, SCROW nRow1,
752 - pClipDoc->bCutMode = bCut;
753 + pClipDoc->GetClipParam().mbCutMode = bCut;
757 +void ScDocument::CopyToClip(const ScClipParam& rClipParam,
758 + ScDocument* pClipDoc, const ScMarkData* pMarks,
759 + bool bKeepScenarioFlags, bool bIncludeObjects, bool bCloneNoteCaptions)
761 + if (bIsClip)
762 + return;
764 + if (!pClipDoc)
766 + DBG_ERROR("CopyToClip: no ClipDoc");
767 + pClipDoc = SC_MOD()->GetClipDoc();
770 + pClipDoc->aDocName = aDocName;
771 + pClipDoc->SetClipParam(rClipParam);
772 + pClipDoc->ResetClip(this, pMarks);
774 + ScRange aClipRange = rClipParam.getWholeRange();
775 + CopyRangeNamesToClip(pClipDoc, aClipRange, pMarks, false);
777 + for (SCTAB i = 0; i <= MAXTAB; ++i)
779 + if (!pTab[i] || !pClipDoc->pTab[i])
780 + continue;
782 + if (pMarks && !pMarks->GetTableSelect(i))
783 + continue;
785 + pTab[i]->CopyToClip(rClipParam.maRanges, pClipDoc->pTab[i], bKeepScenarioFlags, bCloneNoteCaptions);
787 + if (pDrawLayer && bIncludeObjects)
789 + // also copy drawing objects
790 + const ScRange aRange = rClipParam.getWholeRange();
791 + Rectangle aObjRect = GetMMRect(
792 + aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), aRange.aEnd.Row(), i);
793 + pDrawLayer->CopyToClip(pClipDoc, i, aObjRect);
797 + // Make sure to mark overlapped cells.
798 + pClipDoc->ExtendMerge(aClipRange, true);
801 void ScDocument::CopyTabToClip(SCCOL nCol1, SCROW nRow1,
802 SCCOL nCol2, SCROW nRow2,
803 @@ -1416,14 +1445,16 @@ void ScDocument::CopyTabToClip(SCCOL nCol1, SCROW nRow1,
804 pClipDoc = SC_MOD()->GetClipDoc();
807 + ScClipParam& rClipParam = pClipDoc->GetClipParam();
808 pClipDoc->aDocName = aDocName;
809 - pClipDoc->aClipRange = ScRange( nCol1,nRow1,0, nCol2,nRow2,0 );
810 + rClipParam.maRanges.RemoveAll();
811 + rClipParam.maRanges.Append(ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0));
812 pClipDoc->ResetClip( this, nTab );
814 if (pTab[nTab] && pClipDoc->pTab[nTab])
815 pTab[nTab]->CopyToClip(nCol1, nRow1, nCol2, nRow2, pClipDoc->pTab[nTab], FALSE, TRUE);
817 - pClipDoc->bCutMode = FALSE;
818 + pClipDoc->GetClipParam().mbCutMode = false;
822 @@ -1453,6 +1484,7 @@ void ScDocument::TransposeClip( ScDocument* pTransClip, USHORT nFlags, BOOL bAsL
824 // Daten
826 + ScRange aClipRange = GetClipParam().getWholeRange();
827 if ( ValidRow(aClipRange.aEnd.Row()-aClipRange.aStart.Row()) )
829 for (SCTAB i=0; i<=MAXTAB; i++)
830 @@ -1481,10 +1513,8 @@ void ScDocument::TransposeClip( ScDocument* pTransClip, USHORT nFlags, BOOL bAsL
834 - pTransClip->aClipRange = ScRange( 0, 0, aClipRange.aStart.Tab(),
835 - static_cast<SCCOL>(aClipRange.aEnd.Row() - aClipRange.aStart.Row()),
836 - static_cast<SCROW>(aClipRange.aEnd.Col() - aClipRange.aStart.Col()),
837 - aClipRange.aEnd.Tab() );
838 + pTransClip->SetClipParam(GetClipParam());
839 + pTransClip->GetClipParam().transpose();
841 else
843 @@ -1493,9 +1523,184 @@ void ScDocument::TransposeClip( ScDocument* pTransClip, USHORT nFlags, BOOL bAsL
845 // Dies passiert erst beim Einfuegen...
847 - bCutMode = FALSE;
848 + GetClipParam().mbCutMode = false;
851 +void ScDocument::CopyRangeNamesToClip(ScDocument* pClipDoc, const ScRange& rClipRange, const ScMarkData* pMarks, bool bAllTabs)
853 + std::set<USHORT> aUsedNames; // indexes of named ranges that are used in the copied cells
854 + for (SCTAB i = 0; i <= MAXTAB; ++i)
855 + if (pTab[i] && pClipDoc->pTab[i])
856 + if ( bAllTabs || !pMarks || pMarks->GetTableSelect(i) )
857 + pTab[i]->FindRangeNamesInUse(
858 + rClipRange.aStart.Col(), rClipRange.aStart.Row(),
859 + rClipRange.aEnd.Col(), rClipRange.aEnd.Row(), aUsedNames);
861 + pClipDoc->pRangeName->FreeAll();
862 + for (USHORT i = 0; i < pRangeName->GetCount(); i++) //! DB-Bereiche Pivot-Bereiche auch !!!
864 + USHORT nIndex = ((ScRangeData*)((*pRangeName)[i]))->GetIndex();
865 + bool bInUse = ( aUsedNames.find(nIndex) != aUsedNames.end() );
866 + if (bInUse)
868 + ScRangeData* pData = new ScRangeData(*((*pRangeName)[i]));
869 + if (!pClipDoc->pRangeName->Insert(pData))
870 + delete pData;
871 + else
872 + pData->SetIndex(nIndex);
877 +ScDocument::NumFmtMergeHandler::NumFmtMergeHandler(ScDocument* pDoc, ScDocument* pSrcDoc) :
878 + mpDoc(pDoc)
880 + mpDoc->MergeNumberFormatter(pSrcDoc);
883 +ScDocument::NumFmtMergeHandler::~NumFmtMergeHandler()
885 + mpDoc->pFormatExchangeList = NULL;
888 +void ScDocument::MergeNumberFormatter(ScDocument* pSrcDoc)
890 + SvNumberFormatter* pThisFormatter = xPoolHelper->GetFormTable();
891 + SvNumberFormatter* pOtherFormatter = pSrcDoc->xPoolHelper->GetFormTable();
892 + if (pOtherFormatter && pOtherFormatter != pThisFormatter)
894 + SvNumberFormatterIndexTable* pExchangeList =
895 + pThisFormatter->MergeFormatter(*(pOtherFormatter));
896 + if (pExchangeList->Count() > 0)
897 + pFormatExchangeList = pExchangeList;
901 +void ScDocument::CopyRangeNamesFromClip(ScDocument* pClipDoc, ScClipRangeNameData& rRangeNames)
903 + sal_uInt16 nClipRangeNameCount = pClipDoc->pRangeName->GetCount();
904 + ScClipRangeNameData aClipRangeNames;
906 + // array containing range names which might need update of indices
907 + aClipRangeNames.mpRangeNames.resize(nClipRangeNameCount, NULL);
909 + for (sal_uInt16 i = 0; i < nClipRangeNameCount; ++i) //! DB-Bereiche Pivot-Bereiche auch
911 + /* Copy only if the name doesn't exist in this document.
912 + If it exists we use the already existing name instead,
913 + another possibility could be to create new names if
914 + documents differ.
915 + A proper solution would ask the user how to proceed.
916 + The adjustment of the indices in the formulas is done later.
917 + */
918 + ScRangeData* pClipRangeData = (*pClipDoc->pRangeName)[i];
919 + USHORT k;
920 + if ( pRangeName->SearchName( pClipRangeData->GetName(), k ) )
922 + aClipRangeNames.mpRangeNames[i] = NULL; // range name not inserted
923 + USHORT nOldIndex = pClipRangeData->GetIndex();
924 + USHORT nNewIndex = ((*pRangeName)[k])->GetIndex();
925 + aClipRangeNames.insert(nOldIndex, nNewIndex);
926 + if ( !aClipRangeNames.mbReplace )
927 + aClipRangeNames.mbReplace = ( nOldIndex != nNewIndex );
929 + else
931 + ScRangeData* pData = new ScRangeData( *pClipRangeData );
932 + pData->SetDocument(this);
933 + if ( pRangeName->FindIndex( pData->GetIndex() ) )
934 + pData->SetIndex(0); // need new index, done in Insert
935 + if ( pRangeName->Insert( pData ) )
937 + aClipRangeNames.mpRangeNames[i] = pData;
938 + USHORT nOldIndex = pClipRangeData->GetIndex();
939 + USHORT nNewIndex = pData->GetIndex();
940 + aClipRangeNames.insert(nOldIndex, nNewIndex);
941 + if ( !aClipRangeNames.mbReplace )
942 + aClipRangeNames.mbReplace = ( nOldIndex != nNewIndex );
944 + else
945 + { // must be an overflow
946 + delete pData;
947 + aClipRangeNames.mpRangeNames[i] = NULL;
948 + aClipRangeNames.insert(pClipRangeData->GetIndex(), 0);
949 + aClipRangeNames.mbReplace = true;
953 + rRangeNames = aClipRangeNames;
956 +void ScDocument::UpdateRangeNamesInFormulas(
957 + ScClipRangeNameData& rRangeNames, const ScRangeList& rDestRanges, const ScMarkData& rMark,
958 + SCCOL nXw, SCROW nYw)
960 + // nXw and nYw are the extra width and height of the destination range
961 + // extended due to presence of merged cell(s).
963 + if (!rRangeNames.mbReplace)
964 + return;
966 + // first update all inserted named formulas if they contain other
967 + // range names and used indices changed
968 + sal_uInt16 nRangeNameCount = rRangeNames.mpRangeNames.size();
969 + for (sal_uInt16 i = 0; i < nRangeNameCount; ++i) //! DB-Bereiche Pivot-Bereiche auch
971 + if ( rRangeNames.mpRangeNames[i] )
972 + rRangeNames.mpRangeNames[i]->ReplaceRangeNamesInUse(rRangeNames.maRangeMap);
974 + // then update the formulas, they might need just the updated range names
975 + for (ULONG nRange = 0; nRange < rDestRanges.Count(); ++nRange)
977 + const ScRange* pRange = rDestRanges.GetObject( nRange);
978 + SCCOL nCol1 = pRange->aStart.Col();
979 + SCROW nRow1 = pRange->aStart.Row();
980 + SCCOL nCol2 = pRange->aEnd.Col();
981 + SCROW nRow2 = pRange->aEnd.Row();
983 + SCCOL nC1 = nCol1;
984 + SCROW nR1 = nRow1;
985 + SCCOL nC2 = nC1 + nXw;
986 + if (nC2 > nCol2)
987 + nC2 = nCol2;
988 + SCROW nR2 = nR1 + nYw;
989 + if (nR2 > nRow2)
990 + nR2 = nRow2;
991 + do
993 + do
995 + for (SCTAB k = 0; k <= MAXTAB; k++)
997 + if ( pTab[k] && rMark.GetTableSelect(k) )
998 + pTab[k]->ReplaceRangeNamesInUse(nC1, nR1,
999 + nC2, nR2, rRangeNames.maRangeMap);
1001 + nC1 = nC2 + 1;
1002 + nC2 = Min((SCCOL)(nC1 + nXw), nCol2);
1003 + } while (nC1 <= nCol2);
1004 + nC1 = nCol1;
1005 + nC2 = nC1 + nXw;
1006 + if (nC2 > nCol2)
1007 + nC2 = nCol2;
1008 + nR1 = nR2 + 1;
1009 + nR2 = Min((SCROW)(nR1 + nYw), nRow2);
1010 + } while (nR1 <= nRow2);
1014 +ScClipParam& ScDocument::GetClipParam()
1016 + if (!mpClipParam.get())
1017 + mpClipParam.reset(new ScClipParam);
1019 + return *mpClipParam;
1022 +void ScDocument::SetClipParam(const ScClipParam& rParam)
1024 + mpClipParam.reset(new ScClipParam(rParam));
1027 BOOL ScDocument::IsClipboardSource() const
1029 @@ -1595,7 +1800,7 @@ void ScDocument::CopyBlockFromClip( SCCOL nCol1, SCROW nRow1,
1030 && ppClipTab[nClipTab + nFollow + 1] )
1031 ++nFollow;
1033 - if ( pCBFCP->pClipDoc->bCutMode )
1034 + if ( pCBFCP->pClipDoc->GetClipParam().mbCutMode )
1036 BOOL bOldInserting = IsInsertingFromOtherDoc();
1037 SetInsertingFromOtherDoc( TRUE);
1038 @@ -1637,7 +1842,9 @@ void ScDocument::CopyNonFilteredFromClip( SCCOL nCol1, SCROW nRow1,
1039 pCBFCP->pClipDoc->GetRowFlagsArray( nFlagTab);
1041 SCROW nSourceRow = rClipStartRow;
1042 - SCROW nSourceEnd = pCBFCP->pClipDoc->aClipRange.aEnd.Row();
1043 + SCROW nSourceEnd = 0;
1044 + if (pCBFCP->pClipDoc->GetClipParam().maRanges.Count())
1045 + nSourceEnd = pCBFCP->pClipDoc->GetClipParam().maRanges.First()->aEnd.Row();
1046 SCROW nDestRow = nRow1;
1048 while ( nSourceRow <= nSourceEnd && nDestRow <= nRow2 )
1049 @@ -1683,67 +1890,11 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar
1050 BOOL bOldAutoCalc = GetAutoCalc();
1051 SetAutoCalc( FALSE ); // avoid multiple recalculations
1053 - SvNumberFormatter* pThisFormatter = xPoolHelper->GetFormTable();
1054 - SvNumberFormatter* pOtherFormatter = pClipDoc->xPoolHelper->GetFormTable();
1055 - if (pOtherFormatter && pOtherFormatter != pThisFormatter)
1057 - SvNumberFormatterIndexTable* pExchangeList =
1058 - pThisFormatter->MergeFormatter(*(pOtherFormatter));
1059 - if (pExchangeList->Count() > 0)
1060 - pFormatExchangeList = pExchangeList;
1062 + NumFmtMergeHandler aNumFmtMergeHdl(this, pClipDoc);
1064 - USHORT nClipRangeNames = pClipDoc->pRangeName->GetCount();
1065 - // array containing range names which might need update of indices
1066 - ScRangeData** pClipRangeNames = nClipRangeNames ? new ScRangeData* [nClipRangeNames] : NULL;
1067 - // the index mapping thereof
1068 - ScIndexMap aClipRangeMap( nClipRangeNames );
1069 - BOOL bRangeNameReplace = FALSE;
1070 + ScClipRangeNameData aClipRangeNames;
1071 + CopyRangeNamesFromClip(pClipDoc, aClipRangeNames);
1073 - for (USHORT i = 0; i < nClipRangeNames; i++) //! DB-Bereiche Pivot-Bereiche auch
1075 - /* Copy only if the name doesn't exist in this document.
1076 - If it exists we use the already existing name instead,
1077 - another possibility could be to create new names if
1078 - documents differ.
1079 - A proper solution would ask the user how to proceed.
1080 - The adjustment of the indices in the formulas is done later.
1081 - */
1082 - ScRangeData* pClipRangeData = (*pClipDoc->pRangeName)[i];
1083 - USHORT k;
1084 - if ( pRangeName->SearchName( pClipRangeData->GetName(), k ) )
1086 - pClipRangeNames[i] = NULL; // range name not inserted
1087 - USHORT nOldIndex = pClipRangeData->GetIndex();
1088 - USHORT nNewIndex = ((*pRangeName)[k])->GetIndex();
1089 - aClipRangeMap.SetPair( i, nOldIndex, nNewIndex );
1090 - if ( !bRangeNameReplace )
1091 - bRangeNameReplace = ( nOldIndex != nNewIndex );
1093 - else
1095 - ScRangeData* pData = new ScRangeData( *pClipRangeData );
1096 - pData->SetDocument(this);
1097 - if ( pRangeName->FindIndex( pData->GetIndex() ) )
1098 - pData->SetIndex(0); // need new index, done in Insert
1099 - if ( pRangeName->Insert( pData ) )
1101 - pClipRangeNames[i] = pData;
1102 - USHORT nOldIndex = pClipRangeData->GetIndex();
1103 - USHORT nNewIndex = pData->GetIndex();
1104 - aClipRangeMap.SetPair( i, nOldIndex, nNewIndex );
1105 - if ( !bRangeNameReplace )
1106 - bRangeNameReplace = ( nOldIndex != nNewIndex );
1108 - else
1109 - { // must be an overflow
1110 - delete pData;
1111 - pClipRangeNames[i] = NULL;
1112 - aClipRangeMap.SetPair( i, pClipRangeData->GetIndex(), 0 );
1113 - bRangeNameReplace = TRUE;
1117 SCCOL nAllCol1 = rDestRange.aStart.Col();
1118 SCROW nAllRow1 = rDestRange.aStart.Row();
1119 SCCOL nAllCol2 = rDestRange.aEnd.Col();
1120 @@ -1751,17 +1902,18 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar
1122 SCCOL nXw = 0;
1123 SCROW nYw = 0;
1124 + ScRange aClipRange = pClipDoc->GetClipParam().getWholeRange();
1125 for (SCTAB nTab = 0; nTab <= MAXTAB; nTab++) // find largest merge overlap
1126 if (pClipDoc->pTab[nTab]) // all sheets of the clipboard content
1128 - SCCOL nThisEndX = pClipDoc->aClipRange.aEnd.Col();
1129 - SCROW nThisEndY = pClipDoc->aClipRange.aEnd.Row();
1130 - pClipDoc->ExtendMerge( pClipDoc->aClipRange.aStart.Col(),
1131 - pClipDoc->aClipRange.aStart.Row(),
1132 + SCCOL nThisEndX = aClipRange.aEnd.Col();
1133 + SCROW nThisEndY = aClipRange.aEnd.Row();
1134 + pClipDoc->ExtendMerge( aClipRange.aStart.Col(),
1135 + aClipRange.aStart.Row(),
1136 nThisEndX, nThisEndY, nTab );
1137 // only extra value from ExtendMerge
1138 - nThisEndX = sal::static_int_cast<SCCOL>( nThisEndX - pClipDoc->aClipRange.aEnd.Col() );
1139 - nThisEndY = sal::static_int_cast<SCROW>( nThisEndY - pClipDoc->aClipRange.aEnd.Row() );
1140 + nThisEndX = sal::static_int_cast<SCCOL>( nThisEndX - aClipRange.aEnd.Col() );
1141 + nThisEndY = sal::static_int_cast<SCROW>( nThisEndY - aClipRange.aEnd.Row() );
1142 if ( nThisEndX > nXw )
1143 nXw = nThisEndX;
1144 if ( nThisEndY > nYw )
1145 @@ -1820,10 +1972,10 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar
1146 if (bDoDouble)
1147 ScColumn::bDoubleAlloc = TRUE;
1149 - SCCOL nClipStartCol = pClipDoc->aClipRange.aStart.Col();
1150 - SCROW nClipStartRow = pClipDoc->aClipRange.aStart.Row();
1151 + SCCOL nClipStartCol = aClipRange.aStart.Col();
1152 + SCROW nClipStartRow = aClipRange.aStart.Row();
1153 // WaE: commented because unused: SCCOL nClipEndCol = pClipDoc->aClipRange.aEnd.Col();
1154 - SCROW nClipEndRow = pClipDoc->aClipRange.aEnd.Row();
1155 + SCROW nClipEndRow = aClipRange.aEnd.Row();
1156 for (ULONG nRange = 0; nRange < pDestRanges->Count(); ++nRange)
1158 const ScRange* pRange = pDestRanges->GetObject( nRange);
1159 @@ -1874,7 +2026,7 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar
1160 nC2 = Min((SCCOL)(nC1 + nXw), nCol2);
1161 } while (nC1 <= nCol2);
1162 if (nClipStartRow > nClipEndRow)
1163 - nClipStartRow = pClipDoc->aClipRange.aStart.Row();
1164 + nClipStartRow = aClipRange.aStart.Row();
1165 nC1 = nCol1;
1166 nC2 = nC1 + nXw;
1167 if (nC2 > nCol2)
1168 @@ -1891,75 +2043,120 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar
1169 pTab[k]->DecRecalcLevel();
1171 bInsertingFromOtherDoc = FALSE;
1172 - pFormatExchangeList = NULL;
1173 - if ( bRangeNameReplace )
1175 - // first update all inserted named formulas if they contain other
1176 - // range names and used indices changed
1177 - for (USHORT i = 0; i < nClipRangeNames; i++) //! DB-Bereiche Pivot-Bereiche auch
1179 - if ( pClipRangeNames[i] )
1180 - pClipRangeNames[i]->ReplaceRangeNamesInUse( aClipRangeMap );
1182 - // then update the formulas, they might need the just updated range names
1183 - for (ULONG nRange = 0; nRange < pDestRanges->Count(); ++nRange)
1185 - const ScRange* pRange = pDestRanges->GetObject( nRange);
1186 - SCCOL nCol1 = pRange->aStart.Col();
1187 - SCROW nRow1 = pRange->aStart.Row();
1188 - SCCOL nCol2 = pRange->aEnd.Col();
1189 - SCROW nRow2 = pRange->aEnd.Row();
1191 - SCCOL nC1 = nCol1;
1192 - SCROW nR1 = nRow1;
1193 - SCCOL nC2 = nC1 + nXw;
1194 - if (nC2 > nCol2)
1195 - nC2 = nCol2;
1196 - SCROW nR2 = nR1 + nYw;
1197 - if (nR2 > nRow2)
1198 - nR2 = nRow2;
1199 - do
1201 - do
1203 - for (SCTAB k = 0; k <= MAXTAB; k++)
1205 - if ( pTab[k] && rMark.GetTableSelect(k) )
1206 - pTab[k]->ReplaceRangeNamesInUse(nC1, nR1,
1207 - nC2, nR2, aClipRangeMap );
1209 - nC1 = nC2 + 1;
1210 - nC2 = Min((SCCOL)(nC1 + nXw), nCol2);
1211 - } while (nC1 <= nCol2);
1212 - nC1 = nCol1;
1213 - nC2 = nC1 + nXw;
1214 - if (nC2 > nCol2)
1215 - nC2 = nCol2;
1216 - nR1 = nR2 + 1;
1217 - nR2 = Min((SCROW)(nR1 + nYw), nRow2);
1218 - } while (nR1 <= nRow2);
1221 - if ( pClipRangeNames )
1222 - delete [] pClipRangeNames;
1224 + UpdateRangeNamesInFormulas(aClipRangeNames, *pDestRanges, rMark, nXw, nYw);
1226 // Listener aufbauen nachdem alles inserted wurde
1227 StartListeningFromClip( nAllCol1, nAllRow1, nAllCol2, nAllRow2, rMark, nInsFlag );
1228 // nachdem alle Listener aufgebaut wurden, kann gebroadcastet werden
1229 BroadcastFromClip( nAllCol1, nAllRow1, nAllCol2, nAllRow2, rMark, nInsFlag );
1230 if (bResetCut)
1231 - pClipDoc->bCutMode = FALSE;
1232 + pClipDoc->GetClipParam().mbCutMode = false;
1233 SetAutoCalc( bOldAutoCalc );
1238 +void ScDocument::CopyMultiRangeFromClip(
1239 + const ScAddress& rDestPos, const ScMarkData& rMark, sal_uInt16 nInsFlag, ScDocument* pClipDoc,
1240 + bool bResetCut, bool bAsLink, bool /*bIncludeFiltered*/, bool bSkipAttrForEmpty)
1242 + if (bIsClip)
1243 + return;
1245 + if (!pClipDoc->bIsClip || !pClipDoc->GetTableCount())
1246 + // There is nothing in the clip doc to copy.
1247 + return;
1249 + BOOL bOldAutoCalc = GetAutoCalc();
1250 + SetAutoCalc( FALSE ); // avoid multiple recalculations
1252 + NumFmtMergeHandler aNumFmtMergeHdl(this, pClipDoc);
1254 + ScClipRangeNameData aClipRangeNames;
1255 + CopyRangeNamesFromClip(pClipDoc, aClipRangeNames);
1257 + SCCOL nCol1 = rDestPos.Col();
1258 + SCROW nRow1 = rDestPos.Row();
1259 + ScClipParam& rClipParam = pClipDoc->GetClipParam();
1261 + ScCopyBlockFromClipParams aCBFCP;
1262 + aCBFCP.pRefUndoDoc = NULL;
1263 + aCBFCP.pClipDoc = pClipDoc;
1264 + aCBFCP.nInsFlag = nInsFlag;
1265 + aCBFCP.bAsLink = bAsLink;
1266 + aCBFCP.bSkipAttrForEmpty = bSkipAttrForEmpty;
1267 + aCBFCP.nTabStart = MAXTAB;
1268 + aCBFCP.nTabEnd = 0;
1270 + SCCOL nCols = rClipParam.getPasteColSize();
1271 + SCROW nRows = rClipParam.getPasteRowSize();
1272 + for (SCTAB j = 0; j <= MAXTAB; ++j)
1273 + {
1274 + if (pTab[j] && rMark.GetTableSelect(j))
1276 + if ( j < aCBFCP.nTabStart )
1277 + aCBFCP.nTabStart = j;
1278 + aCBFCP.nTabEnd = j;
1279 + pTab[j]->IncRecalcLevel();
1283 + bInsertingFromOtherDoc = TRUE; // kein Broadcast/Listener aufbauen bei Insert
1285 + if (!bSkipAttrForEmpty)
1287 + sal_uInt16 nDelFlag = IDF_CONTENTS;
1288 + DeleteArea(nCol1, nRow1, nCol1+nCols-1, nRow1+nRows-1, rMark, nDelFlag);
1291 + for (ScRange* p = rClipParam.maRanges.First(); p; p = rClipParam.maRanges.Next())
1293 + SCsCOL nDx = static_cast<SCsCOL>(nCol1 - p->aStart.Col());
1294 + SCsROW nDy = static_cast<SCsROW>(nRow1 - p->aStart.Row());
1295 + SCCOL nCol2 = nCol1 + p->aEnd.Col() - p->aStart.Col();
1296 + SCROW nRow2 = nRow1 + p->aEnd.Row() - p->aStart.Row();
1298 + CopyBlockFromClip(nCol1, nRow1, nCol2, nRow2, rMark, nDx, nDy, &aCBFCP);
1300 + if (rClipParam.meDirection == ScClipParam::Column)
1301 + nCol1 += p->aEnd.Col() - p->aStart.Col() + 1;
1302 + if (rClipParam.meDirection == ScClipParam::Row)
1303 + nRow1 += p->aEnd.Row() - p->aStart.Row() + 1;
1306 + for (SCTAB i = 0; i <= MAXTAB; i++)
1307 + if (pTab[i] && rMark.GetTableSelect(i))
1308 + pTab[i]->DecRecalcLevel();
1310 + bInsertingFromOtherDoc = FALSE;
1312 + ScRange aDestRange(rDestPos.Col(), rDestPos.Row(), rDestPos.Tab(),
1313 + rDestPos.Col()+nCols-1, rDestPos.Row()+nRows-1, rDestPos.Tab());
1314 + ScRangeList aRanges;
1315 + aRanges.Append(aDestRange);
1316 + UpdateRangeNamesInFormulas(aClipRangeNames, aRanges, rMark, nCols-1, nRows-1);
1318 + // Listener aufbauen nachdem alles inserted wurde
1319 + StartListeningFromClip(aDestRange.aStart.Col(), aDestRange.aStart.Row(),
1320 + aDestRange.aEnd.Col(), aDestRange.aEnd.Row(), rMark, nInsFlag );
1321 + // nachdem alle Listener aufgebaut wurden, kann gebroadcastet werden
1322 + BroadcastFromClip(aDestRange.aStart.Col(), aDestRange.aStart.Row(),
1323 + aDestRange.aEnd.Col(), aDestRange.aEnd.Row(), rMark, nInsFlag );
1325 + if (bResetCut)
1326 + pClipDoc->GetClipParam().mbCutMode = false;
1327 + SetAutoCalc( bOldAutoCalc );
1330 void ScDocument::SetClipArea( const ScRange& rArea, BOOL bCut )
1332 if (bIsClip)
1334 - aClipRange = rArea;
1335 - bCutMode = bCut;
1336 + ScClipParam& rClipParam = GetClipParam();
1337 + rClipParam.maRanges.RemoveAll();
1338 + rClipParam.maRanges.Append(rArea);
1339 + rClipParam.mbCutMode = bCut;
1341 else
1343 @@ -1970,33 +2167,53 @@ void ScDocument::SetClipArea( const ScRange& rArea, BOOL bCut )
1345 void ScDocument::GetClipArea(SCCOL& nClipX, SCROW& nClipY, BOOL bIncludeFiltered)
1347 - if (bIsClip)
1349 - nClipX = aClipRange.aEnd.Col() - aClipRange.aStart.Col();
1350 + if (!bIsClip)
1351 + {
1352 + DBG_ERROR("GetClipArea: kein Clip");
1353 + return;
1356 - if ( bIncludeFiltered )
1357 - nClipY = aClipRange.aEnd.Row() - aClipRange.aStart.Row();
1358 - else
1360 - // count non-filtered rows
1361 - // count on first used table in clipboard
1362 - SCTAB nCountTab = 0;
1363 - while ( nCountTab < MAXTAB && !pTab[nCountTab] )
1364 - ++nCountTab;
1366 - SCROW nResult = GetRowFlagsArray( nCountTab).CountForCondition(
1367 - aClipRange.aStart.Row(), aClipRange.aEnd.Row(),
1368 - CR_FILTERED, 0);
1370 - if ( nResult > 0 )
1371 - nClipY = nResult - 1;
1372 - else
1373 - nClipY = 0; // always return at least 1 row
1375 + ScRangeList& rClipRanges = GetClipParam().maRanges;
1376 + if (!rClipRanges.Count())
1377 + // No clip range. Bail out.
1378 + return;
1380 + ScRangePtr p = rClipRanges.First();
1381 + SCCOL nStartCol = p->aStart.Col();
1382 + SCCOL nEndCol = p->aEnd.Col();
1383 + SCROW nStartRow = p->aStart.Row();
1384 + SCROW nEndRow = p->aEnd.Row();
1385 + for (p = rClipRanges.Next(); p; p = rClipRanges.Next())
1387 + if (p->aStart.Col() < nStartCol)
1388 + nStartCol = p->aStart.Col();
1389 + if (p->aStart.Row() < nStartRow)
1390 + nStartRow = p->aStart.Row();
1391 + if (p->aEnd.Col() > nEndCol)
1392 + nEndCol = p->aEnd.Col();
1393 + if (p->aEnd.Row() < nEndRow)
1394 + nEndRow = p->aEnd.Row();
1397 + nClipX = nEndCol - nStartCol;
1399 + if ( bIncludeFiltered )
1400 + nClipY = nEndRow - nStartRow;
1401 else
1403 - DBG_ERROR("GetClipArea: kein Clip");
1404 + // count non-filtered rows
1405 + // count on first used table in clipboard
1406 + SCTAB nCountTab = 0;
1407 + while ( nCountTab < MAXTAB && !pTab[nCountTab] )
1408 + ++nCountTab;
1410 + SCROW nResult = GetRowFlagsArray( nCountTab).CountForCondition(
1411 + nStartRow, nEndRow, CR_FILTERED, 0);
1413 + if ( nResult > 0 )
1414 + nClipY = nResult - 1;
1415 + else
1416 + nClipY = 0; // always return at least 1 row
1420 @@ -2005,8 +2222,12 @@ void ScDocument::GetClipStart(SCCOL& nClipX, SCROW& nClipY)
1422 if (bIsClip)
1424 - nClipX = aClipRange.aStart.Col();
1425 - nClipY = aClipRange.aStart.Row();
1426 + ScRangeList& rClipRanges = GetClipParam().maRanges;
1427 + if (rClipRanges.Count())
1429 + nClipX = rClipRanges.First()->aStart.Col();
1430 + nClipY = rClipRanges.First()->aStart.Row();
1433 else
1435 @@ -2022,8 +2243,12 @@ BOOL ScDocument::HasClipFilteredRows()
1436 while ( nCountTab < MAXTAB && !pTab[nCountTab] )
1437 ++nCountTab;
1439 - return GetRowFlagsArray( nCountTab).HasCondition( aClipRange.aStart.Row(),
1440 - aClipRange.aEnd.Row(), CR_FILTERED, CR_FILTERED);
1441 + ScRangeList& rClipRanges = GetClipParam().maRanges;
1442 + if (!rClipRanges.Count())
1443 + return false;
1445 + return GetRowFlagsArray( nCountTab).HasCondition( rClipRanges.First()->aStart.Row(),
1446 + rClipRanges.First()->aEnd.Row(), CR_FILTERED, CR_FILTERED);
1450 diff --git sc/source/core/data/makefile.mk sc/source/core/data/makefile.mk
1451 index 9dfc108..8440ee8 100644
1452 --- sc/source/core/data/makefile.mk
1453 +++ sc/source/core/data/makefile.mk
1454 @@ -56,6 +56,7 @@ SLOFILES = \
1455 $(SLO)$/bcaslot.obj \
1456 $(SLO)$/cell.obj \
1457 $(SLO)$/cell2.obj \
1458 + $(SLO)$/clipparam.obj \
1459 $(SLO)$/column.obj \
1460 $(SLO)$/column2.obj \
1461 $(SLO)$/column3.obj \
1462 diff --git sc/source/core/data/table1.cxx sc/source/core/data/table1.cxx
1463 index 460abe1..3b2d3c5 100644
1464 --- sc/source/core/data/table1.cxx
1465 +++ sc/source/core/data/table1.cxx
1466 @@ -1303,6 +1303,16 @@ void ScTable::ReplaceRangeNamesInUse(SCCOL nCol1, SCROW nRow1,
1470 +void ScTable::ReplaceRangeNamesInUse(SCCOL nCol1, SCROW nRow1,
1471 + SCCOL nCol2, SCROW nRow2,
1472 + const ScRangeData::IndexMap& rMap )
1474 + for (SCCOL i = nCol1; i <= nCol2 && (ValidCol(i)); i++)
1476 + aCol[i].ReplaceRangeNamesInUse( nRow1, nRow2, rMap );
1480 void ScTable::ExtendPrintArea( OutputDevice* pDev,
1481 SCCOL /* nStartCol */, SCROW nStartRow, SCCOL& rEndCol, SCROW nEndRow )
1483 diff --git sc/source/core/data/table2.cxx sc/source/core/data/table2.cxx
1484 index eec97e2..0ef9cbb 100644
1485 --- sc/source/core/data/table2.cxx
1486 +++ sc/source/core/data/table2.cxx
1487 @@ -367,6 +367,16 @@ void ScTable::CopyToClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1491 +void ScTable::CopyToClip(const ScRangeList& rRanges, ScTable* pTable,
1492 + bool bKeepScenarioFlags, bool bCloneNoteCaptions)
1494 + ScRangeList aRanges(rRanges);
1495 + for (ScRangePtr p = aRanges.First(); p; p = aRanges.Next())
1497 + CopyToClip(p->aStart.Col(), p->aStart.Row(), p->aEnd.Col(), p->aEnd.Row(),
1498 + pTable, bKeepScenarioFlags, bCloneNoteCaptions);
1502 void ScTable::CopyFromClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1503 SCsCOL nDx, SCsROW nDy, USHORT nInsFlag,
1504 diff --git sc/source/core/tool/rangenam.cxx sc/source/core/tool/rangenam.cxx
1505 index 6029663..d30a3d5 100644
1506 --- sc/source/core/tool/rangenam.cxx
1507 +++ sc/source/core/tool/rangenam.cxx
1508 @@ -585,6 +585,31 @@ void ScRangeData::ReplaceRangeNamesInUse( const ScIndexMap& rMap )
1512 +void ScRangeData::ReplaceRangeNamesInUse( const IndexMap& rMap )
1514 + bool bCompile = false;
1515 + for ( FormulaToken* p = pCode->First(); p; p = pCode->Next() )
1517 + if ( p->GetOpCode() == ocName )
1519 + const sal_uInt16 nOldIndex = p->GetIndex();
1520 + IndexMap::const_iterator itr = rMap.find(nOldIndex);
1521 + const sal_uInt16 nNewIndex = itr == rMap.end() ? nOldIndex : itr->second;
1522 + if ( nOldIndex != nNewIndex )
1524 + p->SetIndex( nNewIndex );
1525 + bCompile = true;
1529 + if ( bCompile )
1531 + ScCompiler aComp( pDoc, aPos, *pCode);
1532 + aComp.SetGrammar(pDoc->GetGrammar());
1533 + aComp.CompileTokenArray();
1538 void ScRangeData::ValidateTabRefs()
1540 diff --git sc/source/ui/inc/viewfunc.hxx sc/source/ui/inc/viewfunc.hxx
1541 index 17ad51a..f727fb4 100644
1542 --- sc/source/ui/inc/viewfunc.hxx
1543 +++ sc/source/ui/inc/viewfunc.hxx
1544 @@ -354,6 +354,11 @@ private:
1545 void PasteRTF( SCCOL nCol, SCROW nStartRow,
1546 const ::com::sun::star::uno::Reference<
1547 ::com::sun::star::datatransfer::XTransferable >& rxTransferable );
1548 + bool PasteMultiRangesFromClip( sal_uInt16 nFlags, ScDocument* pClipDoc, sal_uInt16 nFunction,
1549 + bool bSkipEmpty, bool bTranspos, bool bAsLink, bool bAllowDialogs,
1550 + InsCellCmd eMoveMode, sal_uInt16 nCondFlags, sal_uInt16 nUndoFlags );
1551 + void PostPasteFromClip(const ScRange& rPasteRange, const ScMarkData& rMark);
1553 USHORT GetOptimalColWidth( SCCOL nCol, SCTAB nTab, BOOL bFormula );
1555 void StartFormatArea();
1556 diff --git sc/source/ui/view/cellsh.cxx sc/source/ui/view/cellsh.cxx
1557 index ddfa8e9..e782dd2 100644
1558 --- sc/source/ui/view/cellsh.cxx
1559 +++ sc/source/ui/view/cellsh.cxx
1560 @@ -206,7 +206,6 @@ void ScCellShell::GetBlockState( SfxItemSet& rSet )
1561 break;
1563 case SID_COPY: // Kopieren
1564 - bDisable = (!bSimpleArea && eMarkType != SC_MARK_SIMPLE_FILTERED);
1565 // nur wegen Matrix nicht editierbar? Matrix nicht zerreissen
1566 //! schlaegt nicht zu, wenn geschuetzt UND Matrix, aber damit
1567 //! muss man leben.. wird in Copy-Routine abgefangen, sonst
1568 --- sc/source/ui/view/cellsh1.cxx
1569 +++ sc/source/ui/view/cellsh1.cxx
1570 @@ -104,6 +104,7 @@
1571 #include "dpsave.hxx"
1572 #include "dpgroup.hxx" // for ScDPNumGroupInfo
1573 #include "spellparam.hxx"
1574 +#include "clipparam.hxx"
1575 #include "postit.hxx"
1577 #include "globstr.hrc"
1578 @@ -2243,7 +2244,13 @@ void ScCellShell::PasteFromClipboard( ScViewData* pViewData, ScTabViewShell* pTa
1579 pTabViewShell->PasteFromSystem();
1580 else
1582 - pTabViewShell->PasteFromClip( IDF_ALL, pOwnClip->GetDocument(),
1583 + ScDocument* pClipDoc = pOwnClip->GetDocument();
1584 + sal_uInt16 nFlags = IDF_ALL;
1585 + if (pClipDoc->GetClipParam().isMultiRange())
1586 + // For multi-range paste, we paste values by default.
1587 + nFlags &= ~IDF_FORMULA;
1589 + pTabViewShell->PasteFromClip( nFlags, pClipDoc,
1590 PASTE_NOFUNC, FALSE, FALSE, FALSE, INS_NONE, IDF_NONE,
1591 bShowDialog ); // allow warning dialog
1593 diff --git sc/source/ui/view/tabvwsh4.cxx sc/source/ui/view/tabvwsh4.cxx
1594 index 4d3dfc1..0e76555 100644
1595 --- sc/source/ui/view/tabvwsh4.cxx
1596 +++ sc/source/ui/view/tabvwsh4.cxx
1597 @@ -1506,7 +1506,7 @@ BOOL ScTabViewShell::TabKeyInput(const KeyEvent& rKEvt)
1598 // #51889# Spezialfall: Copy/Cut bei Mehrfachselektion -> Fehlermeldung
1599 // (Slot ist disabled, SfxViewShell::KeyInput wuerde also kommentarlos verschluckt)
1600 KeyFuncType eFunc = aCode.GetFunction();
1601 - if ( eFunc == KEYFUNC_COPY || eFunc == KEYFUNC_CUT )
1602 + if ( eFunc == KEYFUNC_CUT )
1604 ScRange aDummy;
1605 ScMarkType eMarkType = GetViewData()->GetSimpleArea( aDummy );
1606 diff --git sc/source/ui/view/viewfun3.cxx sc/source/ui/view/viewfun3.cxx
1607 index 0a97b2a..31fca76 100644
1608 --- sc/source/ui/view/viewfun3.cxx
1609 +++ sc/source/ui/view/viewfun3.cxx
1610 @@ -210,6 +210,7 @@
1611 #include "drwtrans.hxx"
1612 #include "docuno.hxx"
1613 #include "undodat.hxx" // Amelia Wang
1614 +#include "clipparam.hxx"
1616 using namespace com::sun::star;
1618 @@ -310,10 +311,10 @@ BOOL ScViewFunc::CopyToClip( ScDocument* pClipDoc, BOOL bCut, BOOL bApi, BOOL bI
1620 ScRange aRange;
1621 ScMarkType eMarkType = GetViewData()->GetSimpleArea( aRange );
1622 + ScDocument* pDoc = GetViewData()->GetDocument();
1623 + ScMarkData& rMark = GetViewData()->GetMarkData();
1624 if ( eMarkType == SC_MARK_SIMPLE || eMarkType == SC_MARK_SIMPLE_FILTERED )
1626 - ScDocument* pDoc = GetViewData()->GetDocument();
1627 - ScMarkData& rMark = GetViewData()->GetMarkData();
1628 if ( !pDoc->HasSelectedBlockMatrixFragment(
1629 aRange.aStart.Col(), aRange.aStart.Row(),
1630 aRange.aEnd.Col(), aRange.aEnd.Row(),
1631 @@ -380,6 +381,122 @@ BOOL ScViewFunc::CopyToClip( ScDocument* pClipDoc, BOOL bCut, BOOL bApi, BOOL bI
1632 ErrorMessage(STR_MATRIXFRAGMENTERR);
1635 + else if (eMarkType == SC_MARK_MULTI)
1637 + bool bSuccess = false;
1638 + ScClipParam aClipParam;
1639 + aClipParam.mbCutMode = false;
1640 + rMark.FillRangeListWithMarks(&aClipParam.maRanges, false);
1642 + do
1644 + if (bCut)
1645 + // We con't support cutting of multi-selections.
1646 + break;
1648 + if (pClipDoc)
1649 + // TODO: What's this for?
1650 + break;
1652 + ::std::auto_ptr<ScDocument> pDocClip(new ScDocument(SCDOCMODE_CLIP));
1654 + // Check for geometrical feasibility of the ranges.
1655 + bool bValidRanges = true;
1656 + ScRangePtr p = aClipParam.maRanges.First();
1657 + SCCOL nPrevColDelta = 0;
1658 + SCROW nPrevRowDelta = 0;
1659 + SCCOL nPrevCol = p->aStart.Col();
1660 + SCROW nPrevRow = p->aStart.Row();
1661 + SCCOL nPrevColSize = p->aEnd.Col() - p->aStart.Col() + 1;
1662 + SCROW nPrevRowSize = p->aEnd.Row() - p->aStart.Row() + 1;
1663 + for (p = aClipParam.maRanges.Next(); p; p = aClipParam.maRanges.Next())
1665 + if (pDoc->HasSelectedBlockMatrixFragment(
1666 + p->aStart.Col(), p->aStart.Row(), p->aEnd.Col(), p->aEnd.Row(), rMark))
1667 + {
1668 + bValidRanges = false;
1669 + break;
1672 + SCCOL nColDelta = p->aStart.Col() - nPrevCol;
1673 + SCROW nRowDelta = p->aStart.Row() - nPrevRow;
1675 + if ((nColDelta && nRowDelta) || (nPrevColDelta && nRowDelta) || (nPrevRowDelta && nColDelta))
1677 + bValidRanges = false;
1678 + break;
1681 + if (aClipParam.meDirection == ScClipParam::Unspecified)
1683 + if (nColDelta)
1684 + aClipParam.meDirection = ScClipParam::Column;
1685 + if (nRowDelta)
1686 + aClipParam.meDirection = ScClipParam::Row;
1689 + SCCOL nColSize = p->aEnd.Col() - p->aStart.Col() + 1;
1690 + SCROW nRowSize = p->aEnd.Row() - p->aStart.Row() + 1;
1692 + if (aClipParam.meDirection == ScClipParam::Column && nRowSize != nPrevRowSize)
1694 + // column-oriented ranges must have identical row size.
1695 + bValidRanges = false;
1696 + break;
1698 + if (aClipParam.meDirection == ScClipParam::Row && nColSize != nPrevColSize)
1700 + // likewise, row-oriented ranges must have identical
1701 + // column size.
1702 + bValidRanges = false;
1703 + break;
1706 + nPrevCol = p->aStart.Col();
1707 + nPrevRow = p->aStart.Row();
1708 + nPrevColDelta = nColDelta;
1709 + nPrevRowDelta = nRowDelta;
1710 + nPrevColSize = nColSize;
1711 + nPrevRowSize = nRowSize;
1713 + if (!bValidRanges)
1714 + break;
1716 + pDoc->CopyToClip(aClipParam, pDocClip.get(), &rMark, false, bIncludeObjects);
1718 + ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
1719 + if ( pChangeTrack )
1720 + pChangeTrack->ResetLastCut(); // kein CutMode mehr
1723 + ScDocShell* pDocSh = GetViewData()->GetDocShell();
1724 + TransferableObjectDescriptor aObjDesc;
1725 + pDocSh->FillTransferableObjectDescriptor( aObjDesc );
1726 + aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
1727 + // maSize is set in ScTransferObj ctor
1729 + ScTransferObj* pTransferObj = new ScTransferObj( pDocClip.release(), aObjDesc );
1730 + uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
1732 + if ( ScGlobal::pDrawClipDocShellRef )
1734 + SfxObjectShellRef aPersistRef( &(*ScGlobal::pDrawClipDocShellRef) );
1735 + pTransferObj->SetDrawPersist( aPersistRef ); // keep persist for ole objects alive
1738 + pTransferObj->CopyToClipboard( GetActiveWin() ); // system clipboard
1739 + SC_MOD()->SetClipObject( pTransferObj, NULL ); // internal clipboard
1742 + bSuccess = true;
1744 + while (false);
1746 + if (!bSuccess && !bApi)
1747 + ErrorMessage(STR_NOMULTISELECT);
1749 + bDone = bSuccess;
1751 else
1753 if (!bApi)
1754 @@ -743,6 +860,52 @@ BOOL lcl_SelHasAttrib( ScDocument* pDoc, SCCOL nCol1, SCROW nRow1, SCCOL nCol2,
1756 // internes Paste
1758 +namespace {
1760 +class CursorSwitcher
1762 +public:
1763 + CursorSwitcher(ScViewFunc* pViewFunc) :
1764 + mpViewFunc(pViewFunc)
1766 + mpViewFunc->HideCursor();
1769 + ~CursorSwitcher()
1771 + mpViewFunc->ShowCursor();
1773 +private:
1774 + ScViewFunc* mpViewFunc;
1777 +bool lcl_checkDestRangeForOverwrite(const ScRange& rDestRange, const ScDocument* pDoc, const ScMarkData& rMark, Window* pParentWnd)
1779 + bool bIsEmpty = true;
1780 + SCTAB nTabCount = pDoc->GetTableCount();
1781 + for (SCTAB nTab=0; nTab < nTabCount && bIsEmpty; ++nTab)
1783 + if (!rMark.GetTableSelect(nTab))
1784 + continue;
1786 + bIsEmpty = pDoc->IsBlockEmpty(nTab, rDestRange.aStart.Col(), rDestRange.aStart.Row(),
1787 + rDestRange.aEnd.Col(), rDestRange.aEnd.Row());
1790 + if (!bIsEmpty)
1792 + ScReplaceWarnBox aBox(pParentWnd);
1793 + if (aBox.Execute() != RET_YES)
1795 + // changing the configuration is within the ScReplaceWarnBox
1796 + return false;
1799 + return true;
1804 BOOL ScViewFunc::PasteFromClip( USHORT nFlags, ScDocument* pClipDoc,
1805 USHORT nFunction, BOOL bSkipEmpty,
1806 BOOL bTranspose, BOOL bAsLink,
1807 @@ -768,6 +931,12 @@ BOOL ScViewFunc::PasteFromClip( USHORT nFlags, ScDocument* pClipDoc,
1808 // do not copy note captions into undo document
1809 nUndoFlags |= IDF_NOCAPTIONS;
1811 + ScClipParam& rClipParam = pClipDoc->GetClipParam();
1812 + if (rClipParam.isMultiRange())
1813 + return PasteMultiRangesFromClip(
1814 + nFlags, pClipDoc, nFunction, bSkipEmpty, bTranspose, bAsLink, bAllowDialogs,
1815 + eMoveMode, nContFlags, nUndoFlags);
1817 BOOL bCutMode = pClipDoc->IsCutMode(); // if transposing, take from original clipdoc
1818 BOOL bIncludeFiltered = bCutMode;
1820 @@ -996,23 +1165,8 @@ BOOL ScViewFunc::PasteFromClip( USHORT nFlags, ScDocument* pClipDoc,
1821 SC_MOD()->GetInputOptions().GetReplaceCellsWarn();
1822 if ( bAskIfNotEmpty )
1824 - BOOL bIsEmpty = TRUE;
1825 - SCTAB nTabCount = pDoc->GetTableCount();
1826 - for (SCTAB nTab=0; nTab<nTabCount && bIsEmpty; nTab++)
1827 - if ( aFilteredMark.GetTableSelect(nTab) &&
1828 - !pDoc->IsBlockEmpty( nTab, aUserRange.aStart.Col(), aUserRange.aStart.Row(),
1829 - aUserRange.aEnd.Col(), aUserRange.aEnd.Row() ) )
1830 - bIsEmpty = FALSE;
1832 - if ( !bIsEmpty )
1834 - ScReplaceWarnBox aBox( GetViewData()->GetDialogParent() );
1835 - if ( aBox.Execute() != RET_YES )
1837 - // changing the configuration is within the ScReplaceWarnBox
1838 - return FALSE;
1841 + if (!lcl_checkDestRangeForOverwrite(aUserRange, pDoc, aFilteredMark, GetViewData()->GetDialogParent()))
1842 + return false;
1846 @@ -1281,7 +1435,171 @@ BOOL ScViewFunc::PasteFromClip( USHORT nFlags, ScDocument* pClipDoc,
1847 // AdjustBlockHeight has already been called above
1849 aModificator.SetDocumentModified();
1850 - pDocSh->UpdateOle(GetViewData());
1851 + PostPasteFromClip(aUserRange, rMark);
1852 + return TRUE;
1855 +bool ScViewFunc::PasteMultiRangesFromClip(
1856 + sal_uInt16 nFlags, ScDocument* pClipDoc, sal_uInt16 nFunction,
1857 + bool bSkipEmpty, bool bTranspose, bool bAsLink, bool bAllowDialogs,
1858 + InsCellCmd eMoveMode, sal_uInt16 /*nContFlags*/, sal_uInt16 nUndoFlags)
1860 + ScViewData& rViewData = *GetViewData();
1861 + ScDocument* pDoc = rViewData.GetDocument();
1862 + ScDocShell* pDocSh = rViewData.GetDocShell();
1863 + ScMarkData aMark(rViewData.GetMarkData());
1864 + const ScAddress& rCurPos = rViewData.GetCurPos();
1865 + ScClipParam& rClipParam = pClipDoc->GetClipParam();
1866 + SCCOL nColSize = rClipParam.getPasteColSize();
1867 + SCROW nRowSize = rClipParam.getPasteRowSize();
1869 + if (bTranspose)
1871 + if (static_cast<SCROW>(rCurPos.Col()) + nRowSize-1 > static_cast<SCROW>(MAXCOL))
1873 + ErrorMessage(STR_PASTE_FULL);
1874 + return false;
1877 + ::std::auto_ptr<ScDocument> pTransClip(new ScDocument(SCDOCMODE_CLIP));
1878 + pClipDoc->TransposeClip(pTransClip.get(), nFlags, bAsLink);
1879 + pClipDoc = pTransClip.release();
1880 + SCCOL nTempColSize = nColSize;
1881 + nColSize = static_cast<SCCOL>(nRowSize);
1882 + nRowSize = static_cast<SCROW>(nTempColSize);
1885 + if (!ValidCol(rCurPos.Col()+nColSize-1) || !ValidRow(rCurPos.Row()+nRowSize-1))
1887 + ErrorMessage(STR_PASTE_FULL);
1888 + return false;
1891 + // Determine the first and last selected sheet numbers.
1892 + SCTAB nTab1 = aMark.GetFirstSelected();
1893 + SCTAB nTab2 = nTab1;
1894 + for (SCTAB i = nTab1+1; i <= MAXTAB; ++i)
1895 + if (aMark.GetTableSelect(i))
1896 + nTab2 = i;
1898 + ScDocShellModificator aModificator(*pDocSh);
1900 + // For multi-selection paste, we don't support cell duplication for larger
1901 + // destination range. In case the destination is marked, we reset it to
1902 + // the clip size.
1903 + ScRange aMarkedRange(rCurPos.Col(), rCurPos.Row(), nTab1,
1904 + rCurPos.Col()+nColSize-1, rCurPos.Row()+nRowSize-1, nTab2);
1906 + bool bAskIfNotEmpty =
1907 + bAllowDialogs && (nFlags & IDF_CONTENTS) &&
1908 + nFunction == PASTE_NOFUNC && SC_MOD()->GetInputOptions().GetReplaceCellsWarn();
1910 + if (bAskIfNotEmpty)
1912 + if (!lcl_checkDestRangeForOverwrite(aMarkedRange, pDoc, aMark, rViewData.GetDialogParent()))
1913 + return false;
1916 + aMark.SetMarkArea(aMarkedRange);
1917 + MarkRange(aMarkedRange);
1919 + bool bInsertCells = (eMoveMode != INS_NONE);
1920 + if (bInsertCells)
1922 + if (!InsertCells(eMoveMode, pDoc->IsUndoEnabled(), true))
1923 + return false;
1926 + ::std::auto_ptr<ScDocument> pUndoDoc;
1927 + if (pDoc->IsUndoEnabled())
1929 + pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1930 + pUndoDoc->InitUndoSelected(pDoc, aMark, false, false);
1931 + pDoc->CopyToDocument(aMarkedRange, IDF_ALL, false, pUndoDoc.get(), &aMark, true);
1934 + ::std::auto_ptr<ScDocument> pMixDoc;
1935 + if ( bSkipEmpty || nFunction )
1937 + if ( nFlags & IDF_CONTENTS )
1939 + pMixDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1940 + pMixDoc->InitUndoSelected(pDoc, aMark, false, false);
1941 + pDoc->CopyToDocument(aMarkedRange, IDF_CONTENTS, false, pMixDoc.get(), &aMark, true);
1945 + /* Make draw layer and start drawing undo.
1946 + - Needed before AdjustBlockHeight to track moved drawing objects.
1947 + - Needed before pDoc->CopyFromClip to track inserted note caption objects.
1948 + */
1949 + if (nFlags & IDF_OBJECTS)
1950 + pDocSh->MakeDrawLayer();
1951 + if (pDoc->IsUndoEnabled())
1952 + pDoc->BeginDrawUndo();
1954 + CursorSwitcher aCursorSwitch(this);
1955 + sal_uInt16 nNoObjFlags = nFlags & ~IDF_OBJECTS;
1956 + pDoc->CopyMultiRangeFromClip(rCurPos, aMark, nNoObjFlags, pClipDoc,
1957 + true, bAsLink, false, bSkipEmpty);
1959 + if (pMixDoc.get())
1960 + pDoc->MixDocument(aMarkedRange, nFunction, bSkipEmpty, pMixDoc.get());
1962 + AdjustBlockHeight(); // update row heights before pasting objects
1964 + if (nFlags & IDF_OBJECTS)
1966 + // Paste the drawing objects after the row heights have been updated.
1967 + pDoc->CopyMultiRangeFromClip(rCurPos, aMark, IDF_OBJECTS, pClipDoc,
1968 + true, false, false, true);
1971 + pDocSh->PostPaint(rCurPos.Col(), rCurPos.Row(), rCurPos.Tab(),
1972 + rCurPos.Col()+nColSize-1, rCurPos.Row()+nRowSize-1, rCurPos.Tab(),
1973 + PAINT_GRID);
1975 + if (pDoc->IsUndoEnabled())
1977 + SfxUndoManager* pUndoMgr = pDocSh->GetUndoManager();
1978 + String aUndo = ScGlobal::GetRscString(
1979 + pClipDoc->IsCutMode() ? STR_UNDO_CUT : STR_UNDO_COPY);
1980 + pUndoMgr->EnterListAction(aUndo, aUndo);
1982 + ScUndoPasteOptions aOptions; // store options for repeat
1983 + aOptions.nFunction = nFunction;
1984 + aOptions.bSkipEmpty = bSkipEmpty;
1985 + aOptions.bTranspose = bTranspose;
1986 + aOptions.bAsLink = bAsLink;
1987 + aOptions.eMoveMode = eMoveMode;
1989 + ScUndoPaste* pUndo = new ScUndoPaste(pDocSh,
1990 + aMarkedRange.aStart.Col(),
1991 + aMarkedRange.aStart.Row(),
1992 + aMarkedRange.aStart.Tab(),
1993 + aMarkedRange.aEnd.Col(),
1994 + aMarkedRange.aEnd.Row(),
1995 + aMarkedRange.aEnd.Tab(),
1996 + aMark, pUndoDoc.release(), NULL, nFlags|nUndoFlags, NULL, NULL, NULL, NULL, false, &aOptions);
1998 + if (bInsertCells)
1999 + pUndoMgr->AddUndoAction(new ScUndoWrapper(pUndo), true);
2000 + else
2001 + pUndoMgr->AddUndoAction(pUndo, false);
2003 + pUndoMgr->LeaveListAction();
2005 + aModificator.SetDocumentModified();
2006 + PostPasteFromClip(aMarkedRange, aMark);
2007 + return true;
2010 +void ScViewFunc::PostPasteFromClip(const ScRange& rPasteRange, const ScMarkData& rMark)
2012 + ScViewData* pViewData = GetViewData();
2013 + ScDocShell* pDocSh = pViewData->GetDocShell();
2014 + ScDocument* pDoc = pViewData->GetDocument();
2015 + pDocSh->UpdateOle(pViewData);
2017 SelectionChanged();
2019 @@ -1295,7 +1613,7 @@ BOOL ScViewFunc::PasteFromClip( USHORT nFlags, ScDocument* pClipDoc,
2021 if ( rMark.GetTableSelect( i ) )
2023 - ScRange aChangeRange( aUserRange );
2024 + ScRange aChangeRange(rPasteRange);
2025 aChangeRange.aStart.SetTab( i );
2026 aChangeRange.aEnd.SetTab( i );
2027 aChangeRanges.Append( aChangeRange );
2028 @@ -1303,8 +1621,6 @@ BOOL ScViewFunc::PasteFromClip( USHORT nFlags, ScDocument* pClipDoc,
2030 pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges );
2033 - return TRUE;