1 diff --git sc/source/ui/docshell/docfunc.cxx sc/source/ui/docshell/docfunc.cxx
2 index 123a716..fde95e5 100644
3 --- sc/source/ui/docshell/docfunc.cxx
4 +++ sc/source/ui/docshell/docfunc.cxx
7 #include "autoform.hxx"
9 +#include "cellmergeoption.hxx"
10 #include "detdata.hxx"
11 #include "detfunc.hxx"
12 #include "docpool.hxx"
14 #include "tabprotection.hxx"
19 using namespace com::sun::star;
20 using ::com::sun::star::uno::Sequence;
21 @@ -3974,86 +3976,110 @@ BOOL ScDocFunc::FillAuto( ScRange& rRange, const ScMarkData* pTabMark, FillDir e
23 //------------------------------------------------------------------------
25 -BOOL ScDocFunc::MergeCells( const ScRange& rRange, BOOL bContents, BOOL bRecord, BOOL bApi )
26 +BOOL ScDocFunc::MergeCells( const ScCellMergeOption& rOption, BOOL bContents, BOOL bRecord, BOOL bApi )
30 ScDocShellModificator aModificator( rDocShell );
32 - ScDocument* pDoc = rDocShell.GetDocument();
33 - SCCOL nStartCol = rRange.aStart.Col();
34 - SCROW nStartRow = rRange.aStart.Row();
35 - SCCOL nEndCol = rRange.aEnd.Col();
36 - SCROW nEndRow = rRange.aEnd.Row();
37 - SCTAB nTab = rRange.aStart.Tab();
38 + SCCOL nStartCol = rOption.mnStartCol;
39 + SCROW nStartRow = rOption.mnStartRow;
40 + SCCOL nEndCol = rOption.mnEndCol;
41 + SCROW nEndRow = rOption.mnEndRow;
42 + if ((nStartCol == nEndCol && nStartRow == nEndRow) || rOption.maTabs.empty())
44 + // Nothing to do. Bail out quick.
48 + ScDocument* pDoc = rDocShell.GetDocument();
49 + set<SCTAB>::const_iterator itrBeg = rOption.maTabs.begin(), itrEnd = rOption.maTabs.end();
50 + SCTAB nTab1 = *itrBeg, nTab2 = *rOption.maTabs.rbegin();
52 if (bRecord && !pDoc->IsUndoEnabled())
55 - ScEditableTester aTester( pDoc, nTab, nStartCol, nStartRow, nEndCol, nEndRow );
56 - if (!aTester.IsEditable())
59 - rDocShell.ErrorMessage(aTester.GetMessageId());
62 + for (set<SCTAB>::const_iterator itr = itrBeg; itr != itrEnd; ++itr)
64 + ScEditableTester aTester( pDoc, *itr, nStartCol, nStartRow, nEndCol, nEndRow );
65 + if (!aTester.IsEditable())
68 + rDocShell.ErrorMessage(aTester.GetMessageId());
72 - if ( nStartCol == nEndCol && nStartRow == nEndRow )
77 + if ( pDoc->HasAttrib( nStartCol, nStartRow, *itr, nEndCol, nEndRow, *itr,
78 + HASATTR_MERGED | HASATTR_OVERLAPPED ) )
80 + // "Zusammenfassen nicht verschachteln !"
82 + rDocShell.ErrorMessage(STR_MSSG_MERGECELLS_0);
87 - if ( pDoc->HasAttrib( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab,
88 - HASATTR_MERGED | HASATTR_OVERLAPPED ) )
90 - // "Zusammenfassen nicht verschachteln !"
92 - rDocShell.ErrorMessage(STR_MSSG_MERGECELLS_0);
95 + ScDocument* pUndoDoc = NULL;
96 + bool bNeedContentsUndo = false;
97 + for (set<SCTAB>::const_iterator itr = itrBeg; itr != itrEnd; ++itr)
100 + bool bNeedContents = bContents &&
101 + ( !pDoc->IsBlockEmpty( nTab, nStartCol,nStartRow+1, nStartCol,nEndRow, true ) ||
102 + !pDoc->IsBlockEmpty( nTab, nStartCol+1,nStartRow, nEndCol,nEndRow, true ) );
106 + // test if the range contains other notes which also implies that we need an undo document
107 + bool bHasNotes = false;
108 + for( ScAddress aPos( nStartCol, nStartRow, nTab ); !bHasNotes && (aPos.Col() <= nEndCol); aPos.IncCol() )
109 + for( aPos.SetRow( nStartRow ); !bHasNotes && (aPos.Row() <= nEndRow); aPos.IncRow() )
110 + bHasNotes = ((aPos.Col() != nStartCol) || (aPos.Row() != nStartRow)) && (pDoc->GetNote( aPos ) != 0);
112 - BOOL bNeedContents = bContents &&
113 - ( !pDoc->IsBlockEmpty( nTab, nStartCol,nStartRow+1, nStartCol,nEndRow, true ) ||
114 - !pDoc->IsBlockEmpty( nTab, nStartCol+1,nStartRow, nEndCol,nEndRow, true ) );
115 + if (bNeedContents || bHasNotes || rOption.mbCenter)
119 + pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
120 + pUndoDoc->InitUndo(pDoc, nTab1, nTab2);
122 + // note captions are collected by drawing undo
123 + pDoc->CopyToDocument( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab,
124 + IDF_ALL|IDF_NOCAPTIONS, FALSE, pUndoDoc );
127 + pDoc->BeginDrawUndo();
130 - ScDocument* pUndoDoc = 0;
133 - // test if the range contains other notes which also implies that we need an undo document
134 - bool bHasNotes = false;
135 - for( ScAddress aPos( nStartCol, nStartRow, nTab ); !bHasNotes && (aPos.Col() <= nEndCol); aPos.IncCol() )
136 - for( aPos.SetRow( nStartRow ); !bHasNotes && (aPos.Row() <= nEndRow); aPos.IncRow() )
137 - bHasNotes = ((aPos.Col() != nStartCol) || (aPos.Row() != nStartRow)) && (pDoc->GetNote( aPos ) != 0);
139 + pDoc->DoMergeContents( nTab, nStartCol,nStartRow, nEndCol,nEndRow );
140 + pDoc->DoMerge( nTab, nStartCol,nStartRow, nEndCol,nEndRow );
142 + if (rOption.mbCenter)
144 + pDoc->ApplyAttr( nStartCol, nStartRow, nTab, SvxHorJustifyItem( SVX_HOR_JUSTIFY_CENTER, ATTR_HOR_JUSTIFY ) );
145 + pDoc->ApplyAttr( nStartCol, nStartRow, nTab, SvxVerJustifyItem( SVX_VER_JUSTIFY_CENTER, ATTR_VER_JUSTIFY ) );
148 - if (bNeedContents || bHasNotes)
150 - pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
151 - pUndoDoc->InitUndo( pDoc, nTab, nTab );
152 - // note captions are collected by drawing undo
153 - pDoc->CopyToDocument( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab,
154 - IDF_ALL|IDF_NOCAPTIONS, FALSE, pUndoDoc );
157 - pDoc->BeginDrawUndo();
159 + if ( !AdjustRowHeight( ScRange( 0,nStartRow,nTab, MAXCOL,nEndRow,nTab ) ) )
160 + rDocShell.PostPaint( nStartCol, nStartRow, nTab,
161 + nEndCol, nEndRow, nTab, PAINT_GRID );
162 + if (bNeedContents || rOption.mbCenter)
164 + ScRange aRange(nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab);
165 + pDoc->SetDirty(aRange);
169 - pDoc->DoMergeContents( nTab, nStartCol,nStartRow, nEndCol,nEndRow );
170 - pDoc->DoMerge( nTab, nStartCol,nStartRow, nEndCol,nEndRow );
171 + bNeedContentsUndo |= bNeedContents;
177 - SdrUndoGroup* pDrawUndo = pDoc->GetDrawLayer() ? pDoc->GetDrawLayer()->GetCalcUndo() : 0;
178 + SdrUndoGroup* pDrawUndo = pDoc->GetDrawLayer() ? pDoc->GetDrawLayer()->GetCalcUndo() : NULL;
179 rDocShell.GetUndoManager()->AddUndoAction(
180 - new ScUndoMerge( &rDocShell,
181 - nStartCol, nStartRow, nTab,
182 - nEndCol, nEndRow, nTab, bNeedContents, pUndoDoc, pDrawUndo ) );
183 + new ScUndoMerge(&rDocShell, rOption, bNeedContentsUndo, pUndoDoc, pDrawUndo) );
186 - if ( !AdjustRowHeight( ScRange( 0,nStartRow,nTab, MAXCOL,nEndRow,nTab ) ) )
187 - rDocShell.PostPaint( nStartCol, nStartRow, nTab,
188 - nEndCol, nEndRow, nTab, PAINT_GRID );
190 - pDoc->SetDirty( rRange );
191 aModificator.SetDocumentModified();
193 SfxBindings* pBindings = rDocShell.GetViewBindings();
194 @@ -4069,49 +4095,81 @@ BOOL ScDocFunc::MergeCells( const ScRange& rRange, BOOL bContents, BOOL bRecord,
196 BOOL ScDocFunc::UnmergeCells( const ScRange& rRange, BOOL bRecord, BOOL bApi )
198 - ScDocShellModificator aModificator( rDocShell );
199 + ScCellMergeOption aOption(rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row());
200 + SCTAB nTab1 = rRange.aStart.Tab(), nTab2 = rRange.aEnd.Tab();
201 + for (SCTAB i = nTab1; i <= nTab2; ++i)
202 + aOption.maTabs.insert(i);
204 + return UnmergeCells(aOption, bRecord, bApi);
207 +bool ScDocFunc::UnmergeCells( const ScCellMergeOption& rOption, BOOL bRecord, BOOL bApi )
211 + if (rOption.maTabs.empty())
212 + // Nothing to unmerge.
215 + ScDocShellModificator aModificator( rDocShell );
216 ScDocument* pDoc = rDocShell.GetDocument();
217 - SCTAB nTab = rRange.aStart.Tab();
219 if (bRecord && !pDoc->IsUndoEnabled())
222 - if ( pDoc->HasAttrib( rRange, HASATTR_MERGED ) )
224 - ScRange aExtended = rRange;
225 - pDoc->ExtendMerge( aExtended );
226 - ScRange aRefresh = aExtended;
227 - pDoc->ExtendOverlapped( aRefresh );
228 + ScDocument* pUndoDoc = NULL;
229 + bool bBeep = false;
230 + for (set<SCTAB>::const_iterator itr = rOption.maTabs.begin(), itrEnd = rOption.maTabs.end();
231 + itr != itrEnd; ++itr)
234 + ScRange aRange = rOption.getSingleRange(nTab);
235 + if ( !pDoc->HasAttrib(aRange, HASATTR_MERGED) )
243 - ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
244 - pUndoDoc->InitUndo( pDoc, nTab, nTab );
245 - pDoc->CopyToDocument( aExtended, IDF_ATTRIB, FALSE, pUndoDoc );
246 - rDocShell.GetUndoManager()->AddUndoAction(
247 - new ScUndoRemoveMerge( &rDocShell, rRange, pUndoDoc ) );
249 + ScRange aExtended = aRange;
250 + pDoc->ExtendMerge(aExtended);
251 + ScRange aRefresh = aExtended;
252 + pDoc->ExtendOverlapped(aRefresh);
254 - const SfxPoolItem& rDefAttr = pDoc->GetPool()->GetDefaultItem( ATTR_MERGE );
255 - ScPatternAttr aPattern( pDoc->GetPool() );
256 - aPattern.GetItemSet().Put( rDefAttr );
257 - pDoc->ApplyPatternAreaTab( rRange.aStart.Col(), rRange.aStart.Row(),
258 - rRange.aEnd.Col(), rRange.aEnd.Row(), nTab,
264 + pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
265 + pUndoDoc->InitUndo(pDoc, *rOption.maTabs.begin(), *rOption.maTabs.rbegin());
267 + pDoc->CopyToDocument(aExtended, IDF_ATTRIB, FALSE, pUndoDoc);
270 - pDoc->RemoveFlagsTab( aExtended.aStart.Col(), aExtended.aStart.Row(),
271 - aExtended.aEnd.Col(), aExtended.aEnd.Row(), nTab,
272 - SC_MF_HOR | SC_MF_VER );
273 + const SfxPoolItem& rDefAttr = pDoc->GetPool()->GetDefaultItem( ATTR_MERGE );
274 + ScPatternAttr aPattern( pDoc->GetPool() );
275 + aPattern.GetItemSet().Put( rDefAttr );
276 + pDoc->ApplyPatternAreaTab( aRange.aStart.Col(), aRange.aStart.Row(),
277 + aRange.aEnd.Col(), aRange.aEnd.Row(), nTab,
280 - pDoc->ExtendMerge( aRefresh, TRUE, FALSE );
281 + pDoc->RemoveFlagsTab( aExtended.aStart.Col(), aExtended.aStart.Row(),
282 + aExtended.aEnd.Col(), aExtended.aEnd.Row(), nTab,
283 + SC_MF_HOR | SC_MF_VER );
285 - if ( !AdjustRowHeight( aExtended ) )
286 - rDocShell.PostPaint( aExtended, PAINT_GRID );
287 - aModificator.SetDocumentModified();
290 - Sound::Beep(); //! FALSE zurueck???
291 + pDoc->ExtendMerge( aRefresh, TRUE, FALSE );
293 + if ( !AdjustRowHeight( aExtended ) )
294 + rDocShell.PostPaint( aExtended, PAINT_GRID );
296 + if (bBeep && !bApi)
301 + rDocShell.GetUndoManager()->AddUndoAction(
302 + new ScUndoRemoveMerge( &rDocShell, rOption, pUndoDoc ) );
304 + aModificator.SetDocumentModified();
308 diff --git sc/source/ui/inc/cellmergeoption.hxx sc/source/ui/inc/cellmergeoption.hxx
310 index 0000000..2e2dff2
312 +++ sc/source/ui/inc/cellmergeoption.hxx
314 +/*************************************************************************
316 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
318 + * Copyright 2008 by Sun Microsystems, Inc.
320 + * OpenOffice.org - a multi-platform office productivity suite
322 + * $RCSfile: docfunc.hxx,v $
323 + * $Revision: 1.18.30.2 $
325 + * This file is part of OpenOffice.org.
327 + * OpenOffice.org is free software: you can redistribute it and/or modify
328 + * it under the terms of the GNU Lesser General Public License version 3
329 + * only, as published by the Free Software Foundation.
331 + * OpenOffice.org is distributed in the hope that it will be useful,
332 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
333 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
334 + * GNU Lesser General Public License version 3 for more details
335 + * (a copy is included in the LICENSE file that accompanied this code).
337 + * You should have received a copy of the GNU Lesser General Public License
338 + * version 3 along with OpenOffice.org. If not, see
339 + * <http://www.openoffice.org/license.html>
340 + * for a copy of the LGPLv3 License.
342 + ************************************************************************/
344 +#ifndef SC_CELLMERGEOPTION_HXX
345 +#define SC_CELLMERGEOPTION_HXX
347 +#include "address.hxx"
353 +struct ScCellMergeOption
355 + ::std::set<SCTAB> maTabs;
362 + explicit ScCellMergeOption();
363 + explicit ScCellMergeOption(SCCOL nStartCol, SCROW nStartRow,
364 + SCCOL nEndCol, SCROW nEndRow,
365 + bool bCenter = false);
366 + explicit ScCellMergeOption(const ScCellMergeOption& r);
368 + ScRange getSingleRange(SCTAB nTab) const;
369 + ScRange getFirstSingleRange() const;
374 diff --git sc/source/ui/inc/docfunc.hxx sc/source/ui/inc/docfunc.hxx
375 index 8490bab..9976230 100644
376 --- sc/source/ui/inc/docfunc.hxx
377 +++ sc/source/ui/inc/docfunc.hxx
378 @@ -49,6 +49,7 @@ class ScBaseCell;
381 class ScTableProtection;
382 +struct ScCellMergeOption;
384 // ---------------------------------------------------------------------------
386 @@ -172,9 +173,10 @@ public:
388 BOOL ResizeMatrix( const ScRange& rOldRange, const ScAddress& rNewEnd, BOOL bApi );
390 - BOOL MergeCells( const ScRange& rRange, BOOL bContents,
391 + BOOL MergeCells( const ScCellMergeOption& rOption, BOOL bContents,
392 BOOL bRecord, BOOL bApi );
393 - BOOL UnmergeCells( const ScRange& rRange, BOOL bRecord, BOOL bApi );
394 + BOOL UnmergeCells( const ScRange& rRange, BOOL bRecord, BOOL bApi );
395 + bool UnmergeCells( const ScCellMergeOption& rOption, BOOL bRecord, BOOL bApi );
397 BOOL SetNewRangeNames( ScRangeName* pNewRanges, BOOL bApi ); // takes ownership of pNewRanges
398 BOOL ModifyRangeNames( const ScRangeName& rNewRanges, BOOL bApi );
399 diff --git sc/source/ui/inc/undoblk.hxx sc/source/ui/inc/undoblk.hxx
400 index 31932fd..2320502 100644
401 --- sc/source/ui/inc/undoblk.hxx
402 +++ sc/source/ui/inc/undoblk.hxx
404 #include "markdata.hxx"
405 #include "viewutil.hxx"
406 #include "spellparam.hxx"
407 +#include "cellmergeoption.hxx"
411 @@ -454,10 +455,8 @@ class ScUndoMerge: public ScSimpleUndo
415 - ScUndoMerge( ScDocShell* pNewDocShell,
416 - SCCOL nStartX, SCROW nStartY, SCTAB nStartZ,
417 - SCCOL nEndX, SCROW nEndY, SCTAB nEndZ,
418 - bool bMergeContents, ScDocument* pUndoDoc, SdrUndoAction* pDrawUndo );
419 + ScUndoMerge( ScDocShell* pNewDocShell, const ScCellMergeOption& rOption,
420 + bool bMergeContents, ScDocument* pUndoDoc, SdrUndoAction* pDrawUndo);
421 virtual ~ScUndoMerge();
424 @@ -468,7 +467,7 @@ public:
425 virtual String GetComment() const;
429 + ScCellMergeOption maOption;
430 bool mbMergeContents; // Merge contents in Redo().
431 ScDocument* mpUndoDoc; // wenn Daten zusammengefasst
432 SdrUndoAction* mpDrawUndo;
433 @@ -920,7 +919,7 @@ class ScUndoRemoveMerge: public ScBlockUndo
436 ScUndoRemoveMerge( ScDocShell* pNewDocShell,
437 - const ScRange& rArea,
438 + const ScCellMergeOption& rOption,
439 ScDocument* pNewUndoDoc );
440 virtual ~ScUndoRemoveMerge();
442 @@ -932,6 +931,9 @@ public:
443 virtual String GetComment() const;
448 + ScCellMergeOption maOption;
449 ScDocument* pUndoDoc;
452 diff --git sc/source/ui/inc/viewfunc.hxx sc/source/ui/inc/viewfunc.hxx
453 index 1f5102e..051a705 100644
454 --- sc/source/ui/inc/viewfunc.hxx
455 +++ sc/source/ui/inc/viewfunc.hxx
456 @@ -242,7 +242,7 @@ public:
457 BOOL TestMergeCells();
458 BOOL TestRemoveMerge();
460 - BOOL MergeCells( BOOL bApi, BOOL& rDoContents, BOOL bRecord = TRUE );
461 + BOOL MergeCells( BOOL bApi, BOOL& rDoContents, BOOL bRecord = TRUE, BOOL bCenter = FALSE );
462 BOOL RemoveMerge( BOOL bRecord = TRUE );
464 void FillSimple( FillDir eDir, BOOL bRecord = TRUE );
465 diff --git sc/source/ui/undo/undoblk.cxx sc/source/ui/undo/undoblk.cxx
466 index 5b3e219..fe2c7bc 100644
467 --- sc/source/ui/undo/undoblk.cxx
468 +++ sc/source/ui/undo/undoblk.cxx
470 #include "undoolk.hxx"
475 // STATIC DATA -----------------------------------------------------------
477 @@ -2066,8 +2067,9 @@ BOOL __EXPORT ScUndoRemoveBreaks::CanRepeat(SfxRepeatTarget& rTarget) const
480 ScUndoRemoveMerge::ScUndoRemoveMerge( ScDocShell* pNewDocShell,
481 - const ScRange& rArea, ScDocument* pNewUndoDoc ) :
482 - ScBlockUndo( pNewDocShell, rArea, SC_UNDO_SIMPLE ),
483 + const ScCellMergeOption& rOption, ScDocument* pNewUndoDoc ) :
484 + ScBlockUndo( pNewDocShell, rOption.getFirstSingleRange(), SC_UNDO_SIMPLE ),
486 pUndoDoc( pNewUndoDoc )
489 @@ -2084,66 +2086,78 @@ String __EXPORT ScUndoRemoveMerge::GetComment() const
491 void __EXPORT ScUndoRemoveMerge::Undo()
495 - ScDocument* pDoc = pDocShell->GetDocument();
498 - ScRange aExtended = aBlockRange;
499 - pUndoDoc->ExtendMerge( aExtended );
503 - pDoc->DeleteAreaTab( aExtended, IDF_ATTRIB );
504 - pUndoDoc->CopyToDocument( aExtended, IDF_ATTRIB, FALSE, pDoc );
505 + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
507 - BOOL bDidPaint = FALSE;
508 - ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
511 - pViewShell->SetTabNo( aExtended.aStart.Tab() );
512 - bDidPaint = pViewShell->AdjustRowHeight( aExtended.aStart.Row(), aExtended.aEnd.Row() );
515 - ScUndoUtil::PaintMore( pDocShell, aExtended );
516 + ScDocument* pDoc = pDocShell->GetDocument();
517 + for (set<SCTAB>::const_iterator itr = maOption.maTabs.begin(), itrEnd = maOption.maTabs.end();
518 + itr != itrEnd; ++itr)
520 + // There is no need to extend merge area because it's already been extended.
521 + ScRange aRange = maOption.getSingleRange(*itr);
522 + pDoc->DeleteAreaTab(aRange, IDF_ATTRIB);
523 + pUndoDoc->CopyToDocument(aRange, IDF_ATTRIB, FALSE, pDoc);
525 + bool bDidPaint = false;
528 + pViewShell->SetTabNo(*itr);
529 + bDidPaint = pViewShell->AdjustRowHeight(maOption.mnStartRow, maOption.mnEndRow);
532 + ScUndoUtil::PaintMore(pDocShell, aRange);
538 void __EXPORT ScUndoRemoveMerge::Redo()
545 - SCTAB nTab = aBlockRange.aStart.Tab();
546 ScDocument* pDoc = pDocShell->GetDocument();
547 - ScRange aExtended = aBlockRange;
548 - pDoc->ExtendMerge( aExtended );
549 - ScRange aRefresh = aExtended;
550 - pDoc->ExtendOverlapped( aRefresh );
554 - const SfxPoolItem& rDefAttr = pDoc->GetPool()->GetDefaultItem( ATTR_MERGE );
555 - ScPatternAttr aPattern( pDoc->GetPool() );
556 - aPattern.GetItemSet().Put( rDefAttr );
557 - pDoc->ApplyPatternAreaTab( aBlockRange.aStart.Col(), aBlockRange.aStart.Row(),
558 - aBlockRange.aEnd.Col(), aBlockRange.aEnd.Row(), nTab,
561 - pDoc->RemoveFlagsTab( aExtended.aStart.Col(), aExtended.aStart.Row(),
562 - aExtended.aEnd.Col(), aExtended.aEnd.Row(), nTab,
563 - SC_MF_HOR | SC_MF_VER );
565 - pDoc->ExtendMerge( aRefresh, TRUE, FALSE );
568 + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
570 - BOOL bDidPaint = FALSE;
571 - ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
574 - pViewShell->SetTabNo( aExtended.aStart.Tab() );
575 - bDidPaint = pViewShell->AdjustRowHeight( aExtended.aStart.Row(), aExtended.aEnd.Row() );
578 - ScUndoUtil::PaintMore( pDocShell, aExtended );
579 + for (set<SCTAB>::const_iterator itr = maOption.maTabs.begin(), itrEnd = maOption.maTabs.end();
580 + itr != itrEnd; ++itr)
583 + // There is no need to extend merge area because it's already been extended.
584 + ScRange aRange = maOption.getSingleRange(nTab);
588 + const SfxPoolItem& rDefAttr = pDoc->GetPool()->GetDefaultItem( ATTR_MERGE );
589 + ScPatternAttr aPattern( pDoc->GetPool() );
590 + aPattern.GetItemSet().Put( rDefAttr );
591 + pDoc->ApplyPatternAreaTab( maOption.mnStartCol, maOption.mnStartRow,
592 + maOption.mnEndCol, maOption.mnEndRow, nTab,
595 + pDoc->RemoveFlagsTab( maOption.mnStartCol, maOption.mnStartRow,
596 + maOption.mnEndCol, maOption.mnEndRow, nTab,
597 + SC_MF_HOR | SC_MF_VER );
599 + pDoc->ExtendMerge(aRange, TRUE, FALSE);
603 + BOOL bDidPaint = FALSE;
606 + pViewShell->SetTabNo(nTab);
607 + bDidPaint = pViewShell->AdjustRowHeight(maOption.mnStartRow, maOption.mnEndRow);
610 + ScUndoUtil::PaintMore(pDocShell, aRange);
615 @@ -2159,6 +2173,13 @@ BOOL __EXPORT ScUndoRemoveMerge::CanRepeat(SfxRepeatTarget& rTarget) const
616 return (rTarget.ISA(ScTabViewTarget));
619 +void ScUndoRemoveMerge::SetCurTab()
621 + SCTAB nCurTab = pDocShell->GetCurTab();
622 + aBlockRange.aStart.SetTab(nCurTab);
623 + aBlockRange.aEnd.SetTab(nCurTab);
626 // -----------------------------------------------------------------------
628 // nur Umrandung setzen, per ScRangeList (StarOne)
629 diff --git sc/source/ui/undo/undoblk3.cxx sc/source/ui/undo/undoblk3.cxx
630 index 5521813..f3f006c 100644
631 --- sc/source/ui/undo/undoblk3.cxx
632 +++ sc/source/ui/undo/undoblk3.cxx
634 // INCLUDE -------------------------------------------------------------------
636 #include "scitems.hxx"
637 +#include <svx/algitem.hxx>
638 #include <svx/boxitem.hxx>
639 #include <svx/srchitem.hxx>
640 #include <svx/linkmgr.hxx>
641 @@ -814,14 +815,12 @@ BOOL __EXPORT ScUndoAutoFill::CanRepeat(SfxRepeatTarget& rTarget) const
643 //----------------------------------------------------------------------------
645 -ScUndoMerge::ScUndoMerge( ScDocShell* pNewDocShell,
646 - SCCOL nStartX, SCROW nStartY, SCTAB nStartZ,
647 - SCCOL nEndX, SCROW nEndY, SCTAB nEndZ,
648 - bool bMergeContents, ScDocument* pUndoDoc, SdrUndoAction* pDrawUndo )
649 +ScUndoMerge::ScUndoMerge( ScDocShell* pNewDocShell, const ScCellMergeOption& rOption,
650 + bool bMergeContents, ScDocument* pUndoDoc, SdrUndoAction* pDrawUndo )
652 : ScSimpleUndo( pNewDocShell ),
654 - maRange( nStartX, nStartY, nStartZ, nEndX, nEndY, nEndZ ),
656 mbMergeContents( bMergeContents ),
657 mpUndoDoc( pUndoDoc ),
658 mpDrawUndo( pDrawUndo )
659 @@ -850,51 +849,77 @@ String ScUndoMerge::GetComment() const
661 void ScUndoMerge::DoChange( bool bUndo ) const
663 - ScDocument* pDoc = pDocShell->GetDocument();
666 - ScUndoUtil::MarkSimpleBlock( pDocShell, maRange );
667 + if (maOption.maTabs.empty())
672 - // remove merge (contents are copied back below from undo document)
673 - pDoc->RemoveMerge( maRange.aStart.Col(), maRange.aStart.Row(), maRange.aStart.Tab() );
675 - // repeat merge, but do not remove note captions (will be done by drawing redo below)
676 -/*!*/ pDoc->DoMerge( maRange.aStart.Tab(),
677 - maRange.aStart.Col(), maRange.aStart.Row(),
678 - maRange.aEnd.Col(), maRange.aEnd.Row(), false );
679 + ScDocument* pDoc = pDocShell->GetDocument();
680 + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
682 - // undo -> copy back deleted contents
683 - if (bUndo && mpUndoDoc)
685 - pDoc->DeleteAreaTab( maRange, IDF_CONTENTS|IDF_NOCAPTIONS );
686 - mpUndoDoc->CopyToDocument( maRange, IDF_ALL|IDF_NOCAPTIONS, FALSE, pDoc );
688 + ScRange aCurRange = maOption.getSingleRange(pDocShell->GetCurTab());
689 + ScUndoUtil::MarkSimpleBlock(pDocShell, aCurRange);
691 + for (set<SCTAB>::const_iterator itr = maOption.maTabs.begin(), itrEnd = maOption.maTabs.end();
692 + itr != itrEnd; ++itr)
695 + ScRange aRange = maOption.getSingleRange(nTab);
697 - // redo -> merge contents again
698 - else if (!bUndo && mbMergeContents)
700 -/*!*/ pDoc->DoMergeContents( maRange.aStart.Tab(),
701 - maRange.aStart.Col(), maRange.aStart.Row(),
702 - maRange.aEnd.Col(), maRange.aEnd.Row() );
704 + // remove merge (contents are copied back below from undo document)
705 + pDoc->RemoveMerge( aRange.aStart.Col(), aRange.aStart.Row(), aRange.aStart.Tab() );
708 + // repeat merge, but do not remove note captions (will be done by drawing redo below)
709 + pDoc->DoMerge( aRange.aStart.Tab(),
710 + aRange.aStart.Col(), aRange.aStart.Row(),
711 + aRange.aEnd.Col(), aRange.aEnd.Row(), false );
713 + if (maOption.mbCenter)
715 + pDoc->ApplyAttr( aRange.aStart.Col(), aRange.aStart.Row(),
716 + aRange.aStart.Tab(),
717 + SvxHorJustifyItem( SVX_HOR_JUSTIFY_CENTER, ATTR_HOR_JUSTIFY ) );
718 + pDoc->ApplyAttr( aRange.aStart.Col(), aRange.aStart.Row(),
719 + aRange.aStart.Tab(),
720 + SvxVerJustifyItem( SVX_VER_JUSTIFY_CENTER, ATTR_VER_JUSTIFY ) );
724 + // undo -> copy back deleted contents
725 + if (bUndo && mpUndoDoc)
727 + pDoc->DeleteAreaTab( aRange, IDF_CONTENTS|IDF_NOCAPTIONS );
728 + mpUndoDoc->CopyToDocument( aRange, IDF_ALL|IDF_NOCAPTIONS, FALSE, pDoc );
731 + // redo -> merge contents again
732 + else if (!bUndo && mbMergeContents)
734 + pDoc->DoMergeContents( aRange.aStart.Tab(),
735 + aRange.aStart.Col(), aRange.aStart.Row(),
736 + aRange.aEnd.Col(), aRange.aEnd.Row() );
740 + DoSdrUndoAction( mpDrawUndo, pDoc );
742 + RedoSdrUndoAction( mpDrawUndo );
744 + bool bDidPaint = false;
747 + pViewShell->SetTabNo(nTab);
748 + bDidPaint = pViewShell->AdjustRowHeight(maOption.mnStartRow, maOption.mnEndRow);
752 + ScUndoUtil::PaintMore(pDocShell, aRange);
756 - DoSdrUndoAction( mpDrawUndo, pDoc );
758 - RedoSdrUndoAction( mpDrawUndo );
760 - BOOL bDidPaint = FALSE;
761 - ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
764 - pViewShell->SetTabNo( maRange.aStart.Tab() );
765 - bDidPaint = pViewShell->AdjustRowHeight( maRange.aStart.Row(), maRange.aEnd.Row() );
769 - ScUndoUtil::PaintMore( pDocShell, maRange );
771 - ShowTable( maRange );
772 + ShowTable(aCurRange);
776 diff --git sc/source/ui/unoobj/cellsuno.cxx sc/source/ui/unoobj/cellsuno.cxx
777 index c2eb810..d4cfb42 100644
778 --- sc/source/ui/unoobj/cellsuno.cxx
779 +++ sc/source/ui/unoobj/cellsuno.cxx
781 #include <com/sun/star/text/WritingMode2.hpp>
783 #include "autoform.hxx"
784 +#include "cellmergeoption.hxx"
785 #include "cellsuno.hxx"
786 #include "cursuno.hxx"
787 #include "textuno.hxx"
788 @@ -5404,10 +5405,14 @@ void SAL_CALL ScCellRangeObj::merge( sal_Bool bMerge ) throw(uno::RuntimeExcepti
791 ScDocFunc aFunc(*pDocSh);
792 + ScCellMergeOption aMergeOption(
793 + aRange.aStart.Col(), aRange.aStart.Row(),
794 + aRange.aEnd.Col(), aRange.aEnd.Row(), false);
795 + aMergeOption.maTabs.insert(aRange.aStart.Tab());
797 - aFunc.MergeCells( aRange, FALSE, TRUE, TRUE );
798 + aFunc.MergeCells( aMergeOption, FALSE, TRUE, TRUE );
800 - aFunc.UnmergeCells( aRange, TRUE, TRUE );
801 + aFunc.UnmergeCells( aMergeOption, TRUE, TRUE );
805 diff --git sc/source/ui/view/cellmergeoption.cxx sc/source/ui/view/cellmergeoption.cxx
807 index 0000000..ed6b8cb
809 +++ sc/source/ui/view/cellmergeoption.cxx
811 +/*************************************************************************
813 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
815 + * Copyright 2008 by Sun Microsystems, Inc.
817 + * OpenOffice.org - a multi-platform office productivity suite
819 + * $RCSfile: docfunc.hxx,v $
820 + * $Revision: 1.18.30.2 $
822 + * This file is part of OpenOffice.org.
824 + * OpenOffice.org is free software: you can redistribute it and/or modify
825 + * it under the terms of the GNU Lesser General Public License version 3
826 + * only, as published by the Free Software Foundation.
828 + * OpenOffice.org is distributed in the hope that it will be useful,
829 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
830 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
831 + * GNU Lesser General Public License version 3 for more details
832 + * (a copy is included in the LICENSE file that accompanied this code).
834 + * You should have received a copy of the GNU Lesser General Public License
835 + * version 3 along with OpenOffice.org. If not, see
836 + * <http://www.openoffice.org/license.html>
837 + * for a copy of the LGPLv3 License.
839 + ************************************************************************/
841 +#include "cellmergeoption.hxx"
842 +#include "address.hxx"
844 +ScCellMergeOption::ScCellMergeOption() :
853 +ScCellMergeOption::ScCellMergeOption(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, bool bCenter) :
854 + mnStartCol(nStartCol),
855 + mnStartRow(nStartRow),
862 +ScCellMergeOption::ScCellMergeOption(const ScCellMergeOption& r) :
864 + mnStartCol(r.mnStartCol),
865 + mnStartRow(r.mnStartRow),
866 + mnEndCol(r.mnEndCol),
867 + mnEndRow(r.mnEndRow),
868 + mbCenter(r.mbCenter)
872 +ScRange ScCellMergeOption::getSingleRange(SCTAB nTab) const
874 + return ScRange(mnStartCol, mnStartRow, nTab, mnEndCol, mnEndRow, nTab);
877 +ScRange ScCellMergeOption::getFirstSingleRange() const
880 + if (!maTabs.empty())
881 + nTab = *maTabs.begin();
883 + return getSingleRange(nTab);
885 diff --git sc/source/ui/view/cellsh3.cxx sc/source/ui/view/cellsh3.cxx
886 index 57309e3..c689fa1 100644
887 --- sc/source/ui/view/cellsh3.cxx
888 +++ sc/source/ui/view/cellsh3.cxx
889 @@ -772,6 +772,7 @@ void ScCellShell::Execute( SfxRequest& rReq )
891 // test whether to merge or to split
893 + BOOL bCenter = FALSE;
897 @@ -782,6 +783,7 @@ void ScCellShell::Execute( SfxRequest& rReq )
899 case FID_MERGE_TOGGLE:
902 SfxPoolItem* pItem = 0;
903 if( rBindings.QueryState( nSlot, pItem ) >= SFX_ITEM_DEFAULT )
904 bMerge = !static_cast< SfxBoolItem* >( pItem )->GetValue();
905 @@ -802,7 +804,7 @@ void ScCellShell::Execute( SfxRequest& rReq )
906 bMoveContents = ((const SfxBoolItem*)pItem)->GetValue();
909 - if (pTabViewShell->MergeCells( bApi, bMoveContents ))
910 + if (pTabViewShell->MergeCells( bApi, bMoveContents, TRUE, bCenter ))
912 if (!bApi && bMoveContents) // "ja" im Dialog geklickt
913 rReq.AppendItem( SfxBoolItem( nSlot, bMoveContents ) );
914 diff --git sc/source/ui/view/makefile.mk sc/source/ui/view/makefile.mk
915 index 48395f3..46b8122 100644
916 --- sc/source/ui/view/makefile.mk
917 +++ sc/source/ui/view/makefile.mk
918 @@ -100,6 +100,7 @@ SLOFILES = \
919 $(SLO)$/output3.obj \
920 $(SLO)$/gridmerg.obj \
921 $(SLO)$/invmerge.obj \
922 + $(SLO)$/cellmergeoption.obj \
924 $(SLO)$/olinewin.obj \
925 $(SLO)$/hintwin.obj \
926 diff --git sc/source/ui/view/viewfun2.cxx sc/source/ui/view/viewfun2.cxx
927 index c563b9a..d6fd25d 100644
928 --- sc/source/ui/view/viewfun2.cxx
929 +++ sc/source/ui/view/viewfun2.cxx
930 @@ -70,6 +70,7 @@ using namespace com::sun::star;
931 #include "attrib.hxx"
932 #include "autoform.hxx"
933 #include "cell.hxx" // EnterAutoSum
934 +#include "cellmergeoption.hxx"
935 #include "compiler.hxx"
936 #include "docfunc.hxx"
937 #include "docpool.hxx"
938 @@ -1087,7 +1088,7 @@ BOOL ScViewFunc::TestMergeCells() // Vorab-Test (fuer Menue)
940 //----------------------------------------------------------------------------
942 -BOOL ScViewFunc::MergeCells( BOOL bApi, BOOL& rDoContents, BOOL bRecord )
943 +BOOL ScViewFunc::MergeCells( BOOL bApi, BOOL& rDoContents, BOOL bRecord, BOOL bCenter )
945 // Editable- und Verschachtelungs-Abfrage muss vorneweg sein (auch in DocFunc),
946 // damit dann nicht die Inhalte-QueryBox kommt
947 @@ -1130,10 +1131,26 @@ BOOL ScViewFunc::MergeCells( BOOL bApi, BOOL& rDoContents, BOOL bRecord )
951 + // Check for the contents of all selected tables.
952 + bool bAskDialog = false;
953 + SCTAB nTabCount = pDoc->GetTableCount();
954 + ScCellMergeOption aMergeOption(nStartCol, nStartRow, nEndCol, nEndRow, bCenter);
955 + for (SCTAB i = 0; i < nTabCount; ++i)
957 + if (!rMark.GetTableSelect(i))
958 + // this table is not selected.
961 + aMergeOption.maTabs.insert(i);
963 + if (!pDoc->IsBlockEmpty(i, nStartCol, nStartRow+1, nStartCol, nEndRow) ||
964 + !pDoc->IsBlockEmpty(i, nStartCol+1, nStartRow, nEndCol, nEndRow))
970 - if ( !pDoc->IsBlockEmpty( nStartTab, nStartCol,nStartRow+1, nStartCol,nEndRow, true ) ||
971 - !pDoc->IsBlockEmpty( nStartTab, nStartCol+1,nStartRow, nEndCol,nEndRow, true ) )
976 @@ -1153,7 +1170,7 @@ BOOL ScViewFunc::MergeCells( BOOL bApi, BOOL& rDoContents, BOOL bRecord )
980 - bOk = pDocSh->GetDocFunc().MergeCells( aMarkRange, rDoContents, bRecord, bApi );
981 + bOk = pDocSh->GetDocFunc().MergeCells( aMergeOption, rDoContents, bRecord, bApi );
985 @@ -1189,6 +1206,32 @@ BOOL ScViewFunc::TestRemoveMerge()
987 //----------------------------------------------------------------------------
989 +static bool lcl_extendMergeRange(ScCellMergeOption& rOption, const ScRange& rRange)
991 + bool bExtended = false;
992 + if (rOption.mnStartCol > rRange.aStart.Col())
994 + rOption.mnStartCol = rRange.aStart.Col();
997 + if (rOption.mnStartRow > rRange.aStart.Row())
999 + rOption.mnStartRow = rRange.aStart.Row();
1002 + if (rOption.mnEndCol < rRange.aEnd.Col())
1004 + rOption.mnEndCol = rRange.aEnd.Col();
1007 + if (rOption.mnEndRow < rRange.aEnd.Row())
1009 + rOption.mnEndRow = rRange.aEnd.Row();
1015 BOOL ScViewFunc::RemoveMerge( BOOL bRecord )
1018 @@ -1200,12 +1243,39 @@ BOOL ScViewFunc::RemoveMerge( BOOL bRecord )
1020 else if (GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE)
1022 + ScDocument* pDoc = GetViewData()->GetDocument();
1023 ScRange aExtended( aRange );
1024 - GetViewData()->GetDocument()->ExtendMerge( aExtended );
1025 + pDoc->ExtendMerge( aExtended );
1026 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1027 + const ScMarkData& rMark = GetViewData()->GetMarkData();
1028 + SCTAB nTabCount = pDoc->GetTableCount();
1029 + ScCellMergeOption aOption(aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), aRange.aEnd.Row());
1030 + bool bExtended = false;
1033 + bExtended = false;
1034 + for (SCTAB i = 0; i < nTabCount; ++i)
1036 + if (!rMark.GetTableSelect(i))
1037 + // This table is not selected.
1040 + aOption.maTabs.insert(i);
1041 + aExtended.aStart.SetTab(i);
1042 + aExtended.aEnd.SetTab(i);
1043 + pDoc->ExtendMerge(aExtended);
1044 + pDoc->ExtendOverlapped(aExtended);
1046 + // Expand the current range to be inclusive of all merged
1047 + // areas on all sheets.
1048 + bExtended = lcl_extendMergeRange(aOption, aExtended);
1051 + while (bExtended);
1054 - BOOL bOk = pDocSh->GetDocFunc().UnmergeCells( aRange, bRecord, FALSE );
1055 + BOOL bOk = pDocSh->GetDocFunc().UnmergeCells(aOption, bRecord, FALSE );
1056 + aExtended = aOption.getFirstSingleRange();
1057 MarkRange( aExtended );
1060 diff --git sc/uiconfig/scalc/menubar/menubar.xml sc/uiconfig/scalc/menubar/menubar.xml
1061 index 118fac7..322d448 100644
1062 --- sc/uiconfig/scalc/menubar/menubar.xml
1063 +++ sc/uiconfig/scalc/menubar/menubar.xml
1064 @@ -218,7 +218,13 @@
1065 <menu:menuitem menu:id=".uno:SetTabBgColor"/>
1068 - <menu:menuitem menu:id=".uno:ToggleMergeCells"/>
1069 + <menu:menu menu:id=".uno:MergeCellsMenu">
1071 + <menu:menuitem menu:id=".uno:ToggleMergeCells"/>
1072 + <menu:menuitem menu:id=".uno:MergeCells"/>
1073 + <menu:menuitem menu:id=".uno:SplitCell"/>
1076 <menu:menuseparator/>
1077 <menu:menuitem menu:id=".uno:PageFormatDialog"/>
1078 <menu:menu menu:id=".uno:PrintRangesMenu">