diff -uNr old/sc/source/ui/docshell/docfunc.cxx new/sc/source/ui/docshell/docfunc.cxx --- old/sc/source/ui/docshell/docfunc.cxx 2008-11-19 15:45:04.000000000 +0800 +++ new/sc/source/ui/docshell/docfunc.cxx 2009-03-03 12:00:56.000000000 +0800 @@ -59,6 +59,7 @@ #include "arealink.hxx" #include "attrib.hxx" +#include "dociter.hxx" #include "autoform.hxx" #include "cell.hxx" #include "detdata.hxx" @@ -1239,6 +1240,15 @@ BOOL bSuccess; SCTAB i; + ScTabViewShell* pViewSh = rDocShell.GetBestViewShell(); //preserve current cursor position + SCCOL nCursorCol = 0; + SCROW nCursorRow = 0; + if( pViewSh ) + { + nCursorCol = pViewSh->GetViewData()->GetCurX(); + nCursorRow = pViewSh->GetViewData()->GetCurY(); + } + if (bRecord && !pDoc->IsUndoEnabled()) bRecord = FALSE; @@ -1272,22 +1282,31 @@ SCCOL nMergeTestEndX = nEndCol; SCROW nMergeTestEndY = nEndRow; - if (eCmd==INS_INSROWS) + ScRange aExtendMergeRange( rRange ); + + if( rRange.aStart == rRange.aEnd && pDoc->HasAttrib(rRange, HASATTR_MERGED) ) + { + pDoc->ExtendMerge( aExtendMergeRange ); + pDoc->ExtendOverlapped( aExtendMergeRange ); + nMergeTestEndX = aExtendMergeRange.aEnd.Col(); + nMergeTestEndY = aExtendMergeRange.aEnd.Row(); + } + + if ( eCmd == INS_INSROWS ) { nMergeTestStartX = 0; nMergeTestEndX = MAXCOL; } - if (eCmd==INS_INSCOLS) + if ( eCmd == INS_INSCOLS ) { nMergeTestStartY = 0; nMergeTestEndY = MAXROW; } - if (eCmd==INS_CELLSDOWN) + if ( eCmd == INS_CELLSDOWN ) nMergeTestEndY = MAXROW; - if (eCmd==INS_CELLSRIGHT) + if ( eCmd == INS_CELLSRIGHT ) nMergeTestEndX = MAXCOL; - BOOL bCanDo = TRUE; BOOL bNeedRefresh = FALSE; SCCOL nEditTestEndX = (eCmd==INS_INSCOLS) ? MAXCOL : nMergeTestEndX; @@ -1300,52 +1319,6 @@ return FALSE; } - for( i=0; iHasAttrib( nMergeTestStartX,nMergeTestStartY, i, nMergeTestEndX, nMergeTestEndY, i, - HASATTR_MERGED | HASATTR_OVERLAPPED )) - { - if (eCmd==INS_CELLSRIGHT) - bNeedRefresh = TRUE; - - SCCOL nMergeStartX = nMergeTestStartX; - SCROW nMergeStartY = nMergeTestStartY; - SCCOL nMergeEndX = nMergeTestEndX; - SCROW nMergeEndY = nMergeTestEndY; - - pDoc->ExtendMerge( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i ); - pDoc->ExtendOverlapped( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i ); - if ( nMergeStartX != nMergeTestStartX || nMergeStartY != nMergeTestStartY || - nMergeEndX != nMergeTestEndX || nMergeEndY != nMergeTestEndY ) - bCanDo = FALSE; - - //! ? nur Start testen ? - - if (!bCanDo) - if ( eCmd==INS_INSCOLS || eCmd==INS_INSROWS ) - if ( nMergeStartX == nMergeTestStartX && nMergeStartY == nMergeTestStartY ) - { - bCanDo = TRUE; - } - } - - if (!bCanDo) - { - //! auf Verschieben (Drag&Drop) zurueckfuehren !!! - // "Kann nicht in zusammengefasste Bereiche einfuegen" - if (!bApi) - rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0); - return FALSE; - } - } - } - - // - // ausfuehren - // - WaitObject aWait( rDocShell.GetActiveDialogParent() ); // wichtig wegen TrackFormulas bei UpdateReference ScDocument* pRefUndoDoc = NULL; @@ -1362,6 +1335,142 @@ pDoc->BeginDrawUndo(); } + // #i8302 : we unmerge overwhelming ranges, before insertion all the actions are put in the same ListAction + // the patch comes from mloiseleur and maoyg + BOOL bInsertMerge = FALSE; + std::vector qIncreaseRange; + String aUndo = ScGlobal::GetRscString( STR_UNDO_INSERTCELLS ); + if (bRecord) + rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo ); + + for( i=0; iHasAttrib( nMergeTestStartX, nMergeTestStartY, i, nMergeTestEndX, nMergeTestEndY, i, HASATTR_MERGED | HASATTR_OVERLAPPED ) ) + { + if (eCmd==INS_CELLSRIGHT) + bNeedRefresh = TRUE; + + SCCOL nMergeStartX = nMergeTestStartX; + SCROW nMergeStartY = nMergeTestStartY; + SCCOL nMergeEndX = nMergeTestEndX; + SCROW nMergeEndY = nMergeTestEndY; + + pDoc->ExtendMerge( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i ); + pDoc->ExtendOverlapped( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i ); + + if(( eCmd == INS_CELLSDOWN && ( nMergeStartX != nMergeTestStartX || nMergeEndX != nMergeTestEndX ))|| + eCmd == INS_CELLSRIGHT && ( nMergeStartY != nMergeTestStartY || nMergeEndY != nMergeTestEndY ) ) + { + if (!bApi) + rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0); + rDocShell.GetUndoManager()->LeaveListAction(); + return FALSE; + } + + SCCOL nTestCol = -1; + SCROW nTestRow1 = -1; + SCROW nTestRow2 = -1; + + ScDocAttrIterator aTestIter( pDoc, i, nMergeTestStartX, nMergeTestStartY, nMergeTestEndX, nMergeTestEndY ); + ScRange aExtendRange( nMergeTestStartX, nMergeTestStartY, i, nMergeTestEndX, nMergeTestEndY, i ); + const ScPatternAttr* pPattern = NULL; + const ScMergeAttr* pMergeFlag = NULL; + const ScMergeFlagAttr* pMergeFlagAttr = NULL; + while ( ( pPattern = aTestIter.GetNext( nTestCol, nTestRow1, nTestRow2 ) ) != NULL ) + { + pMergeFlag = (const ScMergeAttr*) &pPattern->GetItem(ATTR_MERGE); + pMergeFlagAttr = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG); + INT16 nNewFlags = pMergeFlagAttr->GetValue() & ( SC_MF_HOR | SC_MF_VER ); + if( ( pMergeFlag && pMergeFlag->IsMerged() ) || nNewFlags == SC_MF_HOR || nNewFlags == SC_MF_VER ) + { + ScRange aRange( nTestCol, nTestRow1, i ); + pDoc->ExtendOverlapped(aRange); + pDoc->ExtendMerge(aRange, TRUE, TRUE); + + if( nTestRow1 < nTestRow2 && nNewFlags == SC_MF_HOR ) + { + for( SCROW nTestRow = nTestRow1; nTestRow <= nTestRow2; nTestRow++ ) + { + ScRange aTestRange( nTestCol, nTestRow, i ); + pDoc->ExtendOverlapped( aTestRange ); + pDoc->ExtendMerge( aTestRange, TRUE, TRUE); + ScRange aMergeRange( aTestRange.aStart.Col(),aTestRange.aStart.Row(), i ); + if( !aExtendRange.In( aMergeRange ) ) + { + qIncreaseRange.push_back( aTestRange ); + bInsertMerge = TRUE; + } + } + } + else + { + ScRange aMergeRange( aRange.aStart.Col(),aRange.aStart.Row(), i ); + if( !aExtendRange.In( aMergeRange ) ) + { + qIncreaseRange.push_back( aRange ); + } + bInsertMerge = TRUE; + } + } + } + + if( bInsertMerge ) + { + if( eCmd == INS_INSROWS || eCmd == INS_CELLSDOWN ) + { + nStartRow = aExtendMergeRange.aStart.Row(); + nEndRow = aExtendMergeRange.aEnd.Row(); + + if( eCmd == INS_CELLSDOWN ) + nEndCol = nMergeTestEndX; + else + { + nStartCol = 0; + nEndCol = MAXCOL; + } + } + else if( eCmd == INS_CELLSRIGHT || eCmd == INS_INSCOLS ) + { + + nStartCol = aExtendMergeRange.aStart.Col(); + nEndCol = aExtendMergeRange.aEnd.Col(); + if( eCmd == INS_CELLSRIGHT ) + { + nEndRow = nMergeTestEndY; + nPaintEndY = nEndRow; + } + else + { + nStartRow = 0; + nEndRow = MAXROW; + } + } + + if( !qIncreaseRange.empty() ) + { + for( ::std::vector::const_iterator iIter( qIncreaseRange.begin()); iIter != qIncreaseRange.end(); iIter++ ) + { + ScRange aRange( *iIter ); + if( pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) ) + { + UnmergeCells( aRange, TRUE, TRUE ); + } + } + } + } + else + { + if (!bApi) + rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0); + rDocShell.GetUndoManager()->LeaveListAction(); + return FALSE; + } + } + } + } + switch (eCmd) { case INS_CELLSDOWN: @@ -1441,8 +1550,9 @@ SCTAB* pTabs = NULL; SCTAB* pScenarios = NULL; SCTAB nUndoPos = 0; - if ( bRecord ) - { + + if ( bRecord ) + { pTabs = new SCTAB[nSelCount]; pScenarios = new SCTAB[nSelCount]; nUndoPos = 0; @@ -1450,7 +1560,6 @@ { if( aMark.GetTableSelect( i ) ) { - SCTAB nCount = 0; for( SCTAB j=i+1; jIsScenario(j); j++ ) nCount ++; @@ -1460,10 +1569,44 @@ nUndoPos ++; } } - rDocShell.GetUndoManager()->AddUndoAction( new ScUndoInsertCells( + + if( !bInsertMerge ) + { + rDocShell.GetUndoManager()->LeaveListAction(); + } + + rDocShell.GetUndoManager()->AddUndoAction( new ScUndoInsertCells( &rDocShell, ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ), nUndoPos, pTabs, pScenarios, eCmd, pRefUndoDoc, pUndoData, bPartOfPaste ) ); - } + } + + // #i8302 : we remerge growing ranges, with the new part inserted + + while( !qIncreaseRange.empty() ) + { + ScRange aRange = qIncreaseRange.back(); + if( !pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) ) + { + switch (eCmd) + { + case INS_CELLSDOWN: + case INS_INSROWS: + aRange.aEnd.IncRow(static_cast(nEndRow-nStartRow+1)); + break; + case INS_CELLSRIGHT: + case INS_INSCOLS: + aRange.aEnd.IncCol(static_cast(nEndCol-nStartCol+1)); + break; + default: + break; + } + MergeCells(aRange, FALSE, TRUE, TRUE); + } + qIncreaseRange.pop_back(); + } + + if( bInsertMerge ) + rDocShell.GetUndoManager()->LeaveListAction(); for( i=0; iMarkRange( rRange, FALSE ); + pViewSh->SetCursor( nCursorCol, nCursorRow ); + } + } + + rDocShell.GetUndoManager()->LeaveListAction(); + SfxUndoManager* pMgr = rDocShell.GetUndoManager(); + pMgr->RemoveLastUndoAction(); + delete pRefUndoDoc; delete pUndoData; if (!bApi) rDocShell.ErrorMessage(STR_INSERT_FULL); // Spalte/Zeile voll } + + aModificator.SetDocumentModified(); + + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); return bSuccess; }