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-02-13 16:23:56.000000000 +0800 @@ -52,6 +52,7 @@ #include #include +#include #include "docfunc.hxx" @@ -59,6 +60,7 @@ #include "arealink.hxx" #include "attrib.hxx" +#include "dociter.hxx" #include "autoform.hxx" #include "cell.hxx" #include "detdata.hxx" @@ -1239,6 +1241,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; @@ -1300,52 +1311,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 +1327,259 @@ 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 + ::std::queue qIncreaseRange; + BOOL bInsertMerge = FALSE; + 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 ( nMergeStartX != nMergeTestStartX || nMergeStartY != nMergeTestStartY || + nMergeEndX != nMergeTestEndX || nMergeEndY != nMergeTestEndY ) + { + bCanDo = FALSE; + } + + if( !bCanDo ) + { + SCCOL nCol = -1; + SCROW nRow1 = -1; + SCROW nRow2 = -1; + + ScDocAttrIterator aIter( pDoc, i, nStartCol, nStartRow, nEndCol, nEndRow ); + const ScPatternAttr* pPattern = NULL; + const ScMergeAttr* pMergeFlag = NULL; + const ScMergeFlagAttr* pMergeFlagAttr = NULL; + while ( ( pPattern = aIter.GetNext( nCol, nRow1, nRow2 ) ) != NULL ) + { + pMergeFlag = (const ScMergeAttr*) &pPattern->GetItem(ATTR_MERGE); + pMergeFlagAttr = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG); + ScRange aRange(nCol, nRow1, i); + pDoc->ExtendOverlapped(aRange); + pDoc->ExtendMerge(aRange, TRUE, TRUE); + long nMergeWidthCount = aRange.aEnd.Col()-aRange.aStart.Col()+1; + long nMergeHeightCount = aRange.aEnd.Row()-aRange.aStart.Row()+1; + long nSelectWidthCount = rRange.aEnd.Col()-rRange.aStart.Col()+1; + long nSelectHeightCount = rRange.aEnd.Row()-rRange.aStart.Row()+1; + + nMergeTestStartX = aRange.aStart.Col(); + nMergeTestStartY = aRange.aStart.Row(); + nMergeTestEndX = aRange.aEnd.Col(); + nMergeTestEndY = aRange.aEnd.Row(); + + if ( eCmd == INS_INSROWS ) + { + nMergeTestStartX = 0; + nMergeTestEndX = MAXCOL; + } + if ( eCmd == INS_INSCOLS ) + { + nMergeTestStartY = 0; + nMergeTestEndY = MAXROW; + } + if ( eCmd == INS_CELLSDOWN ) + nMergeTestEndY = MAXROW; + if ( eCmd == INS_CELLSRIGHT ) + nMergeTestEndX = MAXCOL; + + nMergeStartX = nMergeTestStartX; + nMergeStartY = nMergeTestStartY; + nMergeEndX = nMergeTestEndX; + nMergeEndY = nMergeTestEndY; + pDoc->ExtendMerge( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i ); + pDoc->ExtendOverlapped( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i ); + + if( ( pMergeFlag && pMergeFlag->IsMerged() ) || ( pMergeFlagAttr && pMergeFlagAttr->IsOverlapped() ) ) + { + BOOL bInsertDown = FALSE; + BOOL bInsertRight = FALSE; + + if( nSelectWidthCount < nMergeWidthCount && nSelectHeightCount > nMergeHeightCount ) + { + bInsertDown = TRUE; + } + else if( nSelectWidthCount > nMergeWidthCount && nSelectHeightCount < nMergeHeightCount ) + { + bInsertRight = TRUE; + } + else if( nSelectWidthCount == nSelectHeightCount || ( nSelectWidthCount == nMergeWidthCount && nSelectHeightCount == nMergeHeightCount ) + || nSelectWidthCount > nMergeWidthCount || nSelectHeightCount > nMergeHeightCount ) + { + if ( nMergeStartX != nMergeTestStartX || nMergeStartY != nMergeTestStartY || + nMergeEndX != nMergeTestEndX || nMergeEndY != nMergeTestEndY ) + { + if( eCmd == INS_CELLSDOWN || eCmd == INS_CELLSRIGHT ) + { + bInsertMerge = FALSE; + break; + } + else if( ( nMergeTestStartY > nMergeStartY && eCmd == INS_INSROWS ) || ( nMergeTestStartX > nMergeStartX && eCmd == INS_INSCOLS ) ) + { + ScRange rScRange( nMergeTestStartX, nMergeTestStartY, i, nMergeTestEndX, nMergeTestEndY, i ); + SCCOL nStartX; + SCROW nStartY; + SCCOL nEndX; + SCROW nEndY; + if ( nMergeTestStartY > nMergeStartY && eCmd == INS_INSROWS ) + { + nStartX = nMergeTestStartX; + nStartY = nMergeTestStartY; + nEndX = nMergeTestEndX; + nEndY = nStartY; + } + else + { + nStartX = nMergeTestStartX; + nStartY = nMergeTestStartY; + nEndX = nStartX; + nEndY = nMergeTestEndY; + } + + ScDocAttrIterator aIter( pDoc, i, nStartX, nStartY, nEndX, nEndY ); + while ( ( pPattern = aIter.GetNext( nCol, nRow1, nRow2 ) ) != NULL ) + { + pMergeFlag = (const ScMergeAttr*) &pPattern->GetItem(ATTR_MERGE); + pMergeFlagAttr = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG); + ScRange aRange(nCol, nRow1, i); + pDoc->ExtendOverlapped(aRange); + pDoc->ExtendMerge(aRange, TRUE, TRUE); + if( ( pMergeFlag && pMergeFlag->IsMerged() ) || ( pMergeFlagAttr && pMergeFlagAttr->IsOverlapped() ) ) + { + ScRange aMergeRange( aRange.aStart.Col(),aRange.aStart.Row(), i ); + if( !rScRange.In( aMergeRange ) ) + { + qIncreaseRange.push( aRange ); + UnmergeCells( aRange, TRUE, TRUE ); + } + } + } + } + } + + if( nSelectWidthCount == nSelectHeightCount ) + { + if( eCmd == INS_INSROWS || eCmd == INS_CELLSDOWN ) + { + nStartRow = aRange.aStart.Row(); + nEndRow = aRange.aEnd.Row(); + + if( eCmd == INS_CELLSDOWN ) + nEndCol += (SCCOL)nMergeWidthCount-1; + else + { + nStartCol = 0; + nEndCol = MAXCOL; + } + } + else if( eCmd == INS_CELLSRIGHT || eCmd == INS_INSCOLS ) + { + + nStartCol = aRange.aStart.Col(); + nEndCol = aRange.aEnd.Col(); + if( eCmd == INS_CELLSRIGHT ) + { + nEndRow += nMergeHeightCount-1; + nPaintEndY = nEndRow; + } + else + { + nStartRow = 0; + nEndRow = MAXROW; + } + } + } + } + + if( ( bInsertDown && eCmd == INS_CELLSDOWN ) || ( bInsertRight && eCmd == INS_CELLSRIGHT ) ) + { + if (!bApi) + rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0); + return FALSE; + } + + ScRange aMergeRange( aRange.aStart.Col(),aRange.aStart.Row(), i ); + if( !rRange.In( aMergeRange ) ) + { + qIncreaseRange.push( aRange ); + UnmergeCells( aRange, TRUE, TRUE ); + } + + bInsertMerge = TRUE; + } + } + + if( !bInsertMerge ) + { + if (!bApi) + rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0); + rDocShell.GetUndoManager()->LeaveListAction(); + return FALSE; + } + } + else + { + long nSelectWidthCount = rRange.aEnd.Col()-rRange.aStart.Col()+1; + long nSelectHeightCount = rRange.aEnd.Row()-rRange.aStart.Row()+1; + if( nSelectWidthCount == nSelectHeightCount ) + { + SCCOL nExtendStartX = rRange.aStart.Col(); + SCROW nExtendStartY = rRange.aStart.Row(); + SCCOL nExtendEndX = rRange.aEnd.Col(); + SCROW nExtendEndY = rRange.aEnd.Row(); + pDoc->ExtendMerge( nExtendStartX, nExtendStartY, nExtendEndX, nExtendEndY, i ); + pDoc->ExtendOverlapped( nExtendStartX, nExtendStartY, nExtendEndX, nExtendEndY, i ); + if( eCmd == INS_INSROWS || eCmd == INS_CELLSDOWN ) + { + nStartRow = nExtendStartY; + nEndRow = nExtendEndY; + + if( eCmd == INS_CELLSDOWN ) + nEndCol = nExtendEndX; + else + { + nStartCol = 0; + nEndCol = MAXCOL; + } + } + else if( eCmd == INS_CELLSRIGHT || eCmd == INS_INSCOLS ) + { + + nStartCol = nExtendStartX; + nEndCol = nExtendEndX; + if( eCmd == INS_CELLSRIGHT ) + { + nEndRow = nExtendEndY; + nPaintEndY = nEndRow; + } + else + { + nStartRow = 0; + nEndRow = MAXROW; + } + } + } + } + } + } + } + switch (eCmd) { case INS_CELLSDOWN: @@ -1441,8 +1659,9 @@ SCTAB* pTabs = NULL; SCTAB* pScenarios = NULL; SCTAB nUndoPos = 0; - if ( bRecord ) - { + + if ( bRecord ) + { pTabs = new SCTAB[nSelCount]; pScenarios = new SCTAB[nSelCount]; nUndoPos = 0; @@ -1460,10 +1679,41 @@ 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.front(); + 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(); + } + + if( bInsertMerge ) + rDocShell.GetUndoManager()->LeaveListAction(); for( i=0; iGetUndoActionCount() ) + pMgr->Undo(); + + if( pViewSh ) + { + pViewSh->MarkRange( rRange, FALSE ); + pViewSh->SetCursor( nCursorCol, nCursorRow ); + } + + rDocShell.GetUndoManager()->LeaveListAction(); + } + 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; }