| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sc.hxx" |
| |
| |
| |
| // INCLUDE --------------------------------------------------------------- |
| |
| #include "scitems.hxx" |
| #include <editeng/eeitem.hxx> |
| |
| #include <sfx2/app.hxx> |
| #include <editeng/editobj.hxx> |
| #include <sfx2/linkmgr.hxx> |
| #include <svx/svdundo.hxx> |
| #include <sfx2/bindings.hxx> |
| #include <sfx2/printer.hxx> |
| #include <vcl/msgbox.hxx> |
| #include <vcl/sound.hxx> |
| #include <vcl/virdev.hxx> |
| #include <vcl/waitobj.hxx> |
| #include <svl/zforlist.hxx> |
| #include <svl/PasswordHelper.hxx> |
| |
| #include <basic/sbstar.hxx> |
| #include <com/sun/star/container/XNameContainer.hpp> |
| #include <com/sun/star/script/ModuleType.hpp> |
| #include <com/sun/star/script/XLibraryContainer.hpp> |
| #include <com/sun/star/script/vba/XVBAModuleInfo.hpp> |
| |
| #include <list> |
| |
| #include "docfunc.hxx" |
| |
| #include "sc.hrc" |
| |
| #include "arealink.hxx" |
| #include "attrib.hxx" |
| #include "dociter.hxx" |
| #include "autoform.hxx" |
| #include "cell.hxx" |
| #include "detdata.hxx" |
| #include "detfunc.hxx" |
| #include "docpool.hxx" |
| #include "docsh.hxx" |
| #include "drwlayer.hxx" |
| #include "editutil.hxx" |
| #include "globstr.hrc" |
| //CHINA001 #include "namecrea.hxx" // NAME_TOP etc. |
| #include "olinetab.hxx" |
| #include "patattr.hxx" |
| #include "rangenam.hxx" |
| #include "rangeutl.hxx" |
| #include "refundo.hxx" |
| #include "scresid.hxx" |
| #include "stlpool.hxx" |
| #include "stlsheet.hxx" |
| #include "tablink.hxx" |
| #include "tabvwsh.hxx" |
| #include "uiitems.hxx" |
| #include "undoblk.hxx" |
| #include "undocell.hxx" |
| #include "undodraw.hxx" |
| #include "undotab.hxx" |
| #include "waitoff.hxx" |
| #include "sizedev.hxx" |
| #include "scmod.hxx" |
| #include "inputhdl.hxx" |
| #include "inputwin.hxx" |
| #include "editable.hxx" |
| #include "compiler.hxx" |
| #include "scui_def.hxx" //CHINA001 |
| #include "tabprotection.hxx" |
| #include "clipparam.hxx" |
| #include "externalrefmgr.hxx" |
| |
| #include <memory> |
| #include <basic/basmgr.hxx> |
| #include <boost/scoped_ptr.hpp> |
| |
| using namespace com::sun::star; |
| using ::com::sun::star::uno::Sequence; |
| |
| // STATIC DATA ----------------------------------------------------------- |
| |
| //======================================================================== |
| |
| IMPL_LINK( ScDocFunc, NotifyDrawUndo, SdrUndoAction*, pUndoAction ) |
| { |
| // #i101118# if drawing layer collects the undo actions, add it there |
| ScDrawLayer* pDrawLayer = rDocShell.GetDocument()->GetDrawLayer(); |
| if( pDrawLayer && pDrawLayer->IsUndoAllowed() && pDrawLayer->IsRecording() ) |
| pDrawLayer->AddCalcUndo( pUndoAction ); |
| else |
| rDocShell.GetUndoManager()->AddUndoAction( new ScUndoDraw( pUndoAction, &rDocShell ) ); |
| rDocShell.SetDrawModified(); |
| |
| // the affected sheet isn't known, so all stream positions are invalidated |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| SCTAB nTabCount = pDoc->GetTableCount(); |
| for (SCTAB nTab=0; nTab<nTabCount; nTab++) |
| if (pDoc->IsStreamValid(nTab)) |
| pDoc->SetStreamValid(nTab, sal_False); |
| |
| return 0; |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| // Zeile ueber dem Range painten (fuer Linien nach AdjustRowHeight) |
| |
| void lcl_PaintAbove( ScDocShell& rDocShell, const ScRange& rRange ) |
| { |
| SCROW nRow = rRange.aStart.Row(); |
| if ( nRow > 0 ) |
| { |
| SCTAB nTab = rRange.aStart.Tab(); //! alle? |
| --nRow; |
| rDocShell.PostPaint( ScRange(0,nRow,nTab, MAXCOL,nRow,nTab), PAINT_GRID ); |
| } |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| sal_Bool ScDocFunc::AdjustRowHeight( const ScRange& rRange, sal_Bool bPaint ) |
| { |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| if ( pDoc->IsImportingXML() ) |
| { |
| // for XML import, all row heights are updated together after importing |
| return sal_False; |
| } |
| if ( !pDoc->IsAdjustHeightEnabled() ) |
| { |
| return sal_False; |
| } |
| |
| SCTAB nTab = rRange.aStart.Tab(); |
| SCROW nStartRow = rRange.aStart.Row(); |
| SCROW nEndRow = rRange.aEnd.Row(); |
| |
| ScSizeDeviceProvider aProv( &rDocShell ); |
| Fraction aOne(1,1); |
| |
| sal_Bool bChanged = pDoc->SetOptimalHeight( nStartRow, nEndRow, nTab, 0, aProv.GetDevice(), |
| aProv.GetPPTX(), aProv.GetPPTY(), aOne, aOne, sal_False ); |
| |
| if ( bPaint && bChanged ) |
| rDocShell.PostPaint( 0, nStartRow, nTab, MAXCOL, MAXROW, nTab, |
| PAINT_GRID | PAINT_LEFT ); |
| |
| return bChanged; |
| } |
| |
| |
| //------------------------------------------------------------------------ |
| |
| sal_Bool ScDocFunc::DetectiveAddPred(const ScAddress& rPos) |
| { |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| rDocShell.MakeDrawLayer(); |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| sal_Bool bUndo (pDoc->IsUndoEnabled()); |
| ScDrawLayer* pModel = pDoc->GetDrawLayer(); |
| SCCOL nCol = rPos.Col(); |
| SCROW nRow = rPos.Row(); |
| SCTAB nTab = rPos.Tab(); |
| |
| if (bUndo) |
| pModel->BeginCalcUndo(false); |
| sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).ShowPred( nCol, nRow ); |
| SdrUndoGroup* pUndo = NULL; |
| if (bUndo) |
| pUndo = pModel->GetCalcUndo(); |
| if (bDone) |
| { |
| ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_ADDPRED ); |
| pDoc->AddDetectiveOperation( aOperation ); |
| if (bUndo) |
| { |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoDetective( &rDocShell, pUndo, &aOperation ) ); |
| } |
| aModificator.SetDocumentModified(); |
| SfxBindings* pBindings = rDocShell.GetViewBindings(); |
| if (pBindings) |
| pBindings->Invalidate( SID_DETECTIVE_REFRESH ); |
| } |
| else |
| delete pUndo; |
| |
| return bDone; |
| } |
| |
| sal_Bool ScDocFunc::DetectiveDelPred(const ScAddress& rPos) |
| { |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| |
| sal_Bool bUndo(pDoc->IsUndoEnabled()); |
| ScDrawLayer* pModel = pDoc->GetDrawLayer(); |
| if (!pModel) |
| return sal_False; |
| |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| SCCOL nCol = rPos.Col(); |
| SCROW nRow = rPos.Row(); |
| SCTAB nTab = rPos.Tab(); |
| |
| if (bUndo) |
| pModel->BeginCalcUndo(false); |
| sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).DeletePred( nCol, nRow ); |
| SdrUndoGroup* pUndo = NULL; |
| if (bUndo) |
| pUndo = pModel->GetCalcUndo(); |
| if (bDone) |
| { |
| ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_DELPRED ); |
| pDoc->AddDetectiveOperation( aOperation ); |
| if (bUndo) |
| { |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoDetective( &rDocShell, pUndo, &aOperation ) ); |
| } |
| aModificator.SetDocumentModified(); |
| SfxBindings* pBindings = rDocShell.GetViewBindings(); |
| if (pBindings) |
| pBindings->Invalidate( SID_DETECTIVE_REFRESH ); |
| } |
| else |
| delete pUndo; |
| |
| return bDone; |
| } |
| |
| sal_Bool ScDocFunc::DetectiveAddSucc(const ScAddress& rPos) |
| { |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| rDocShell.MakeDrawLayer(); |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| |
| sal_Bool bUndo(pDoc->IsUndoEnabled()); |
| ScDrawLayer* pModel = pDoc->GetDrawLayer(); |
| SCCOL nCol = rPos.Col(); |
| SCROW nRow = rPos.Row(); |
| SCTAB nTab = rPos.Tab(); |
| |
| if (bUndo) |
| pModel->BeginCalcUndo(false); |
| sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).ShowSucc( nCol, nRow ); |
| SdrUndoGroup* pUndo = NULL; |
| if (bUndo) |
| pUndo = pModel->GetCalcUndo(); |
| if (bDone) |
| { |
| ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_ADDSUCC ); |
| pDoc->AddDetectiveOperation( aOperation ); |
| if (bUndo) |
| { |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoDetective( &rDocShell, pUndo, &aOperation ) ); |
| } |
| aModificator.SetDocumentModified(); |
| SfxBindings* pBindings = rDocShell.GetViewBindings(); |
| if (pBindings) |
| pBindings->Invalidate( SID_DETECTIVE_REFRESH ); |
| } |
| else |
| delete pUndo; |
| |
| return bDone; |
| } |
| |
| sal_Bool ScDocFunc::DetectiveDelSucc(const ScAddress& rPos) |
| { |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| |
| sal_Bool bUndo (pDoc->IsUndoEnabled()); |
| ScDrawLayer* pModel = pDoc->GetDrawLayer(); |
| if (!pModel) |
| return sal_False; |
| |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| SCCOL nCol = rPos.Col(); |
| SCROW nRow = rPos.Row(); |
| SCTAB nTab = rPos.Tab(); |
| |
| if (bUndo) |
| pModel->BeginCalcUndo(false); |
| sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).DeleteSucc( nCol, nRow ); |
| SdrUndoGroup* pUndo = NULL; |
| if (bUndo) |
| pUndo = pModel->GetCalcUndo(); |
| if (bDone) |
| { |
| ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_DELSUCC ); |
| pDoc->AddDetectiveOperation( aOperation ); |
| if (bUndo) |
| { |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoDetective( &rDocShell, pUndo, &aOperation ) ); |
| } |
| aModificator.SetDocumentModified(); |
| SfxBindings* pBindings = rDocShell.GetViewBindings(); |
| if (pBindings) |
| pBindings->Invalidate( SID_DETECTIVE_REFRESH ); |
| } |
| else |
| delete pUndo; |
| |
| return bDone; |
| } |
| |
| sal_Bool ScDocFunc::DetectiveAddError(const ScAddress& rPos) |
| { |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| rDocShell.MakeDrawLayer(); |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| |
| sal_Bool bUndo (pDoc->IsUndoEnabled()); |
| ScDrawLayer* pModel = pDoc->GetDrawLayer(); |
| SCCOL nCol = rPos.Col(); |
| SCROW nRow = rPos.Row(); |
| SCTAB nTab = rPos.Tab(); |
| |
| if (bUndo) |
| pModel->BeginCalcUndo(false); |
| sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).ShowError( nCol, nRow ); |
| SdrUndoGroup* pUndo = NULL; |
| if (bUndo) |
| pUndo = pModel->GetCalcUndo(); |
| if (bDone) |
| { |
| ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_ADDERROR ); |
| pDoc->AddDetectiveOperation( aOperation ); |
| if (bUndo) |
| { |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoDetective( &rDocShell, pUndo, &aOperation ) ); |
| } |
| aModificator.SetDocumentModified(); |
| SfxBindings* pBindings = rDocShell.GetViewBindings(); |
| if (pBindings) |
| pBindings->Invalidate( SID_DETECTIVE_REFRESH ); |
| } |
| else |
| delete pUndo; |
| |
| return bDone; |
| } |
| |
| sal_Bool ScDocFunc::DetectiveMarkInvalid(SCTAB nTab) |
| { |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| rDocShell.MakeDrawLayer(); |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| |
| sal_Bool bUndo (pDoc->IsUndoEnabled()); |
| ScDrawLayer* pModel = pDoc->GetDrawLayer(); |
| |
| Window* pWaitWin = rDocShell.GetActiveDialogParent(); |
| if (pWaitWin) |
| pWaitWin->EnterWait(); |
| if (bUndo) |
| pModel->BeginCalcUndo(false); |
| sal_Bool bOverflow; |
| sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).MarkInvalid( bOverflow ); |
| SdrUndoGroup* pUndo = NULL; |
| if (bUndo) |
| pUndo = pModel->GetCalcUndo(); |
| if (pWaitWin) |
| pWaitWin->LeaveWait(); |
| if (bDone) |
| { |
| if (pUndo && bUndo) |
| { |
| pUndo->SetComment( ScGlobal::GetRscString( STR_UNDO_DETINVALID ) ); |
| rDocShell.GetUndoManager()->AddUndoAction( pUndo ); |
| } |
| aModificator.SetDocumentModified(); |
| if ( bOverflow ) |
| { |
| InfoBox( NULL, |
| ScGlobal::GetRscString( STR_DETINVALID_OVERFLOW ) ).Execute(); |
| } |
| } |
| else |
| delete pUndo; |
| |
| return bDone; |
| } |
| |
| sal_Bool ScDocFunc::DetectiveDelAll(SCTAB nTab) |
| { |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| |
| sal_Bool bUndo (pDoc->IsUndoEnabled()); |
| ScDrawLayer* pModel = pDoc->GetDrawLayer(); |
| if (!pModel) |
| return sal_False; |
| |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| if (bUndo) |
| pModel->BeginCalcUndo(false); |
| sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).DeleteAll( SC_DET_DETECTIVE ); |
| SdrUndoGroup* pUndo = NULL; |
| if (bUndo) |
| pUndo = pModel->GetCalcUndo(); |
| if (bDone) |
| { |
| ScDetOpList* pOldList = pDoc->GetDetOpList(); |
| ScDetOpList* pUndoList = NULL; |
| if (bUndo) |
| pUndoList = pOldList ? new ScDetOpList(*pOldList) : NULL; |
| |
| pDoc->ClearDetectiveOperations(); |
| |
| if (bUndo) |
| { |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoDetective( &rDocShell, pUndo, NULL, pUndoList ) ); |
| } |
| aModificator.SetDocumentModified(); |
| SfxBindings* pBindings = rDocShell.GetViewBindings(); |
| if (pBindings) |
| pBindings->Invalidate( SID_DETECTIVE_REFRESH ); |
| } |
| else |
| delete pUndo; |
| |
| return bDone; |
| } |
| |
| sal_Bool ScDocFunc::DetectiveRefresh( sal_Bool bAutomatic ) |
| { |
| sal_Bool bDone = sal_False; |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| |
| sal_Bool bUndo (pDoc->IsUndoEnabled()); |
| ScDetOpList* pList = pDoc->GetDetOpList(); |
| if ( pList && pList->Count() ) |
| { |
| rDocShell.MakeDrawLayer(); |
| ScDrawLayer* pModel = pDoc->GetDrawLayer(); |
| if (bUndo) |
| pModel->BeginCalcUndo(false); |
| |
| // Loeschen auf allen Tabellen |
| |
| SCTAB nTabCount = pDoc->GetTableCount(); |
| for (SCTAB nTab=0; nTab<nTabCount; nTab++) |
| ScDetectiveFunc( pDoc,nTab ).DeleteAll( SC_DET_ARROWS ); // don't remove circles |
| |
| // Wiederholen |
| |
| sal_uInt16 nCount = pList->Count(); |
| for (sal_uInt16 i=0; i<nCount; i++) |
| { |
| ScDetOpData* pData = (*pList)[i]; |
| if (pData) |
| { |
| ScAddress aPos = pData->GetPos(); |
| ScDetectiveFunc aFunc( pDoc, aPos.Tab() ); |
| SCCOL nCol = aPos.Col(); |
| SCROW nRow = aPos.Row(); |
| switch (pData->GetOperation()) |
| { |
| case SCDETOP_ADDSUCC: |
| aFunc.ShowSucc( nCol, nRow ); |
| break; |
| case SCDETOP_DELSUCC: |
| aFunc.DeleteSucc( nCol, nRow ); |
| break; |
| case SCDETOP_ADDPRED: |
| aFunc.ShowPred( nCol, nRow ); |
| break; |
| case SCDETOP_DELPRED: |
| aFunc.DeletePred( nCol, nRow ); |
| break; |
| case SCDETOP_ADDERROR: |
| aFunc.ShowError( nCol, nRow ); |
| break; |
| default: |
| DBG_ERROR("falsche Op bei DetectiveRefresh"); |
| } |
| } |
| } |
| |
| if (bUndo) |
| { |
| SdrUndoGroup* pUndo = pModel->GetCalcUndo(); |
| if (pUndo) |
| { |
| pUndo->SetComment( ScGlobal::GetRscString( STR_UNDO_DETREFRESH ) ); |
| // wenn automatisch, an letzte Aktion anhaengen |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoDraw( pUndo, &rDocShell ), |
| bAutomatic ); |
| } |
| } |
| rDocShell.SetDrawModified(); |
| bDone = sal_True; |
| } |
| return bDone; |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| sal_Bool ScDocFunc::DeleteContents( const ScMarkData& rMark, sal_uInt16 nFlags, |
| sal_Bool bRecord, sal_Bool bApi ) |
| { |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| if ( !rMark.IsMarked() && !rMark.IsMultiMarked() ) |
| { |
| DBG_ERROR("ScDocFunc::DeleteContents ohne Markierung"); |
| return sal_False; |
| } |
| |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| |
| if (bRecord && !pDoc->IsUndoEnabled()) |
| bRecord = sal_False; |
| |
| ScEditableTester aTester( pDoc, rMark ); |
| if (!aTester.IsEditable()) |
| { |
| if (!bApi) |
| rDocShell.ErrorMessage(aTester.GetMessageId()); |
| return sal_False; |
| } |
| |
| ScRange aMarkRange; |
| sal_Bool bSimple = sal_False; |
| |
| ScMarkData aMultiMark = rMark; |
| aMultiMark.SetMarking(sal_False); // fuer MarkToMulti |
| |
| ScDocument* pUndoDoc = NULL; |
| sal_Bool bMulti = !bSimple && aMultiMark.IsMultiMarked(); |
| if (!bSimple) |
| { |
| aMultiMark.MarkToMulti(); |
| aMultiMark.GetMultiMarkArea( aMarkRange ); |
| } |
| ScRange aExtendedRange(aMarkRange); |
| if (!bSimple) |
| { |
| if ( pDoc->ExtendMerge( aExtendedRange, sal_True ) ) |
| bMulti = sal_False; |
| } |
| |
| // keine Objekte auf geschuetzten Tabellen |
| sal_Bool bObjects = sal_False; |
| if ( nFlags & IDF_OBJECTS ) |
| { |
| bObjects = sal_True; |
| SCTAB nTabCount = pDoc->GetTableCount(); |
| for (SCTAB nTab=0; nTab<nTabCount; nTab++) |
| if (aMultiMark.GetTableSelect(nTab) && pDoc->IsTabProtected(nTab)) |
| bObjects = sal_False; |
| } |
| |
| sal_uInt16 nExtFlags = 0; // extra flags are needed only if attributes are deleted |
| if ( nFlags & IDF_ATTRIB ) |
| rDocShell.UpdatePaintExt( nExtFlags, aMarkRange ); |
| |
| // Reihenfolge: |
| // 1) BeginDrawUndo |
| // 2) Objekte loeschen (DrawUndo wird gefuellt) |
| // 3) Inhalte fuer Undo kopieren und Undo-Aktion anlegen |
| // 4) Inhalte loeschen |
| |
| bool bDrawUndo = bObjects || (nFlags & IDF_NOTE); |
| if (bRecord && bDrawUndo) |
| pDoc->BeginDrawUndo(); |
| |
| if (bObjects) |
| { |
| if (bMulti) |
| pDoc->DeleteObjectsInSelection( aMultiMark ); |
| else |
| pDoc->DeleteObjectsInArea( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), |
| aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), |
| aMultiMark ); |
| } |
| |
| if ( bRecord ) |
| { |
| pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); |
| pUndoDoc->InitUndo( pDoc, aMarkRange.aStart.Tab(), aMarkRange.aEnd.Tab() ); |
| |
| // bei "Format/Standard" alle Attribute kopieren, weil CopyToDocument |
| // nur mit IDF_HARDATTR zu langsam ist: |
| sal_uInt16 nUndoDocFlags = nFlags; |
| if (nFlags & IDF_ATTRIB) |
| nUndoDocFlags |= IDF_ATTRIB; |
| if (nFlags & IDF_EDITATTR) // Edit-Engine-Attribute |
| nUndoDocFlags |= IDF_STRING; // -> Zellen werden geaendert |
| if (nFlags & IDF_NOTE) |
| nUndoDocFlags |= IDF_CONTENTS; // #68795# copy all cells with their notes |
| // note captions are handled in drawing undo |
| nUndoDocFlags |= IDF_NOCAPTIONS; |
| pDoc->CopyToDocument( aExtendedRange, nUndoDocFlags, bMulti, pUndoDoc, &aMultiMark ); |
| } |
| |
| //! HideAllCursors(); // falls Zusammenfassung aufgehoben wird |
| if (bSimple) |
| pDoc->DeleteArea( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), |
| aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), |
| aMultiMark, nFlags ); |
| else |
| { |
| pDoc->DeleteSelection( nFlags, aMultiMark ); |
| // aMultiMark.MarkToSimple(); |
| } |
| |
| // add undo action after drawing undo is complete (objects and note captions) |
| if( bRecord ) |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoDeleteContents( &rDocShell, aMultiMark, aExtendedRange, |
| pUndoDoc, bMulti, nFlags, bDrawUndo ) ); |
| |
| if (!AdjustRowHeight( aExtendedRange )) |
| rDocShell.PostPaint( aExtendedRange, PAINT_GRID, nExtFlags ); |
| else if (nExtFlags & SC_PF_LINES) |
| lcl_PaintAbove( rDocShell, aExtendedRange ); // fuer Linien ueber dem Bereich |
| |
| // rDocShell.UpdateOle(GetViewData()); //! an der View? |
| aModificator.SetDocumentModified(); |
| //! CellContentChanged(); |
| //! ShowAllCursors(); |
| |
| #if 0 |
| //! muss an der View bleiben !!!! |
| if ( nFlags & IDF_ATTRIB ) |
| { |
| if ( nFlags & IDF_CONTENTS ) |
| ForgetFormatArea(); |
| else |
| StartFormatArea(); // Attribute loeschen ist auch Attributierung |
| } |
| #endif |
| |
| return sal_True; |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| sal_Bool ScDocFunc::TransliterateText( const ScMarkData& rMark, sal_Int32 nType, |
| sal_Bool bRecord, sal_Bool bApi ) |
| { |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| if (bRecord && !pDoc->IsUndoEnabled()) |
| bRecord = sal_False; |
| |
| ScEditableTester aTester( pDoc, rMark ); |
| if (!aTester.IsEditable()) |
| { |
| if (!bApi) |
| rDocShell.ErrorMessage(aTester.GetMessageId()); |
| return sal_False; |
| } |
| |
| ScRange aMarkRange; |
| ScMarkData aMultiMark = rMark; |
| aMultiMark.SetMarking(sal_False); // for MarkToMulti |
| aMultiMark.MarkToMulti(); |
| aMultiMark.GetMultiMarkArea( aMarkRange ); |
| |
| if (bRecord) |
| { |
| SCTAB nStartTab = aMarkRange.aStart.Tab(); |
| SCTAB nTabCount = pDoc->GetTableCount(); |
| |
| ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); |
| pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab ); |
| for (SCTAB i=0; i<nTabCount; i++) |
| if (i != nStartTab && rMark.GetTableSelect(i)) |
| pUndoDoc->AddUndoTab( i, i ); |
| |
| ScRange aCopyRange = aMarkRange; |
| aCopyRange.aStart.SetTab(0); |
| aCopyRange.aEnd.SetTab(nTabCount-1); |
| pDoc->CopyToDocument( aCopyRange, IDF_CONTENTS, sal_True, pUndoDoc, &aMultiMark ); |
| |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoTransliterate( &rDocShell, aMultiMark, pUndoDoc, nType ) ); |
| } |
| |
| pDoc->TransliterateText( aMultiMark, nType ); |
| |
| if (!AdjustRowHeight( aMarkRange )) |
| rDocShell.PostPaint( aMarkRange, PAINT_GRID ); |
| |
| aModificator.SetDocumentModified(); |
| |
| return sal_True; |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| sal_Bool ScDocFunc::SetNormalString( const ScAddress& rPos, const String& rText, sal_Bool bApi ) |
| { |
| ScDocShellModificator aModificator( rDocShell ); |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| |
| sal_Bool bUndo(pDoc->IsUndoEnabled()); |
| ScEditableTester aTester( pDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() ); |
| if (!aTester.IsEditable()) |
| { |
| if (!bApi) |
| rDocShell.ErrorMessage(aTester.GetMessageId()); |
| return sal_False; |
| } |
| |
| SCTAB* pTabs = NULL; |
| ScBaseCell** ppOldCells = NULL; |
| sal_Bool* pHasFormat = NULL; |
| sal_uLong* pOldFormats = NULL; |
| ScBaseCell* pDocCell = pDoc->GetCell( rPos ); |
| sal_Bool bEditDeleted = (pDocCell && pDocCell->GetCellType() == CELLTYPE_EDIT); |
| if (bUndo) |
| { |
| pTabs = new SCTAB[1]; |
| pTabs[0] = rPos.Tab(); |
| ppOldCells = new ScBaseCell*[1]; |
| ppOldCells[0] = pDocCell ? pDocCell->CloneWithoutNote( *pDoc ) : 0; |
| |
| pHasFormat = new sal_Bool[1]; |
| pOldFormats = new sal_uLong[1]; |
| const SfxPoolItem* pItem; |
| const ScPatternAttr* pPattern = pDoc->GetPattern( rPos.Col(),rPos.Row(),rPos.Tab() ); |
| if ( SFX_ITEM_SET == pPattern->GetItemSet().GetItemState( |
| ATTR_VALUE_FORMAT,sal_False,&pItem) ) |
| { |
| pHasFormat[0] = sal_True; |
| pOldFormats[0] = ((const SfxUInt32Item*)pItem)->GetValue(); |
| } |
| else |
| pHasFormat[0] = sal_False; |
| } |
| |
| pDoc->SetString( rPos.Col(), rPos.Row(), rPos.Tab(), rText ); |
| |
| if (bUndo) |
| { |
| // wegen ChangeTracking darf UndoAction erst nach SetString angelegt werden |
| rDocShell.GetUndoManager()->AddUndoAction(new ScUndoEnterData( &rDocShell, rPos.Col(),rPos.Row(),rPos.Tab(), 1,pTabs, |
| ppOldCells, pHasFormat, pOldFormats, rText, NULL ) ); |
| } |
| |
| if ( bEditDeleted || pDoc->HasAttrib( ScRange(rPos), HASATTR_NEEDHEIGHT ) ) |
| AdjustRowHeight( ScRange(rPos) ); |
| |
| rDocShell.PostPaintCell( rPos ); |
| aModificator.SetDocumentModified(); |
| |
| // #107160# notify input handler here the same way as in PutCell |
| if (bApi) |
| NotifyInputHandler( rPos ); |
| |
| return sal_True; |
| } |
| |
| sal_Bool ScDocFunc::PutCell( const ScAddress& rPos, ScBaseCell* pNewCell, sal_Bool bApi ) |
| { |
| ScDocShellModificator aModificator( rDocShell ); |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| sal_Bool bUndo (pDoc->IsUndoEnabled()); |
| sal_Bool bXMLLoading(pDoc->IsImportingXML()); |
| |
| // #i925#; it is not neccessary to test whether the cell is editable on loading a XML document |
| if (!bXMLLoading) |
| { |
| ScEditableTester aTester( pDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() ); |
| if (!aTester.IsEditable()) |
| { |
| if (!bApi) |
| rDocShell.ErrorMessage(aTester.GetMessageId()); |
| pNewCell->Delete(); |
| return sal_False; |
| } |
| } |
| |
| sal_Bool bEditCell = ( pNewCell->GetCellType() == CELLTYPE_EDIT ); |
| ScBaseCell* pDocCell = pDoc->GetCell( rPos ); |
| sal_Bool bEditDeleted = (pDocCell && pDocCell->GetCellType() == CELLTYPE_EDIT); |
| sal_Bool bHeight = ( bEditDeleted || bEditCell || |
| pDoc->HasAttrib( ScRange(rPos), HASATTR_NEEDHEIGHT ) ); |
| |
| ScBaseCell* pUndoCell = (bUndo && pDocCell) ? pDocCell->CloneWithoutNote( *pDoc, rPos ) : 0; |
| ScBaseCell* pRedoCell = (bUndo && pNewCell) ? pNewCell->CloneWithoutNote( *pDoc, rPos ) : 0; |
| |
| pDoc->PutCell( rPos, pNewCell ); |
| |
| // wegen ChangeTracking darf UndoAction erst nach PutCell angelegt werden |
| if (bUndo) |
| { |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoPutCell( &rDocShell, rPos, pUndoCell, pRedoCell, bHeight ) ); |
| } |
| |
| if (bHeight) |
| AdjustRowHeight( ScRange(rPos) ); |
| |
| if (!bXMLLoading) |
| rDocShell.PostPaintCell( rPos ); |
| |
| aModificator.SetDocumentModified(); |
| |
| // #i925#; it is not neccessary to notify on loading a XML document |
| // #103934#; notify editline and cell in edit mode |
| if (bApi && !bXMLLoading) |
| NotifyInputHandler( rPos ); |
| |
| return sal_True; |
| } |
| |
| void ScDocFunc::NotifyInputHandler( const ScAddress& rPos ) |
| { |
| ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell(); |
| if ( pViewSh && pViewSh->GetViewData()->GetDocShell() == &rDocShell ) |
| { |
| ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl(); |
| if ( pInputHdl && pInputHdl->GetCursorPos() == rPos ) |
| { |
| sal_Bool bIsEditMode(pInputHdl->IsEditMode()); |
| |
| // set modified if in editmode, because so the string is not set in the InputWindow like in the cell |
| // (the cell shows the same like the InputWindow) |
| if (bIsEditMode) |
| pInputHdl->SetModified(); |
| pViewSh->UpdateInputHandler(sal_False, !bIsEditMode); |
| } |
| } |
| } |
| |
| struct ScMyRememberItem |
| { |
| sal_uInt16 nIndex; |
| SfxItemSet aItemSet; |
| |
| ScMyRememberItem(const SfxItemSet& rItemSet, sal_uInt16 nTempIndex) : |
| nIndex(nTempIndex), aItemSet(rItemSet) {} |
| }; |
| |
| typedef ::std::list<ScMyRememberItem*> ScMyRememberItemList; |
| |
| sal_Bool ScDocFunc::PutData( const ScAddress& rPos, ScEditEngineDefaulter& rEngine, sal_Bool bInterpret, sal_Bool bApi ) |
| { |
| // PutData ruft PutCell oder SetNormalString |
| |
| sal_Bool bRet = sal_False; |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| ScEditAttrTester aTester( &rEngine ); |
| sal_Bool bEditCell = aTester.NeedsObject(); |
| if ( bEditCell ) |
| { |
| // #i61702# With bLoseContent set, the content of rEngine isn't restored |
| // (used in loading XML, where after the removeActionLock call the API obejct's |
| // EditEngine isn't accessed again. |
| sal_Bool bLoseContent = pDoc->IsImportingXML(); |
| |
| sal_Bool bUpdateMode(rEngine.GetUpdateMode()); |
| if (bUpdateMode) |
| rEngine.SetUpdateMode(sal_False); |
| |
| ScMyRememberItemList aRememberItems; |
| ScMyRememberItem* pRememberItem = NULL; |
| |
| // All paragraph attributes must be removed before calling CreateTextObject, |
| // not only alignment, so the object doesn't contain the cell attributes as |
| // paragraph attributes. Before remove the attributes store they in a list to |
| // set they back to the EditEngine. |
| sal_uInt16 nCount = rEngine.GetParagraphCount(); |
| for (sal_uInt16 i=0; i<nCount; i++) |
| { |
| const SfxItemSet& rOld = rEngine.GetParaAttribs( i ); |
| if ( rOld.Count() ) |
| { |
| if ( !bLoseContent ) |
| { |
| pRememberItem = new ScMyRememberItem(rEngine.GetParaAttribs(i), i); |
| aRememberItems.push_back(pRememberItem); |
| } |
| rEngine.SetParaAttribs( i, SfxItemSet( *rOld.GetPool(), rOld.GetRanges() ) ); |
| } |
| } |
| |
| EditTextObject* pNewData = rEngine.CreateTextObject(); |
| bRet = PutCell( rPos, |
| new ScEditCell( pNewData, pDoc, rEngine.GetEditTextObjectPool() ), |
| bApi ); |
| delete pNewData; |
| |
| // Set the paragraph attributes back to the EditEngine. |
| if (!aRememberItems.empty()) |
| { |
| // ScMyRememberItem* pRememberItem = NULL; |
| ScMyRememberItemList::iterator aItr = aRememberItems.begin(); |
| while (aItr != aRememberItems.end()) |
| { |
| pRememberItem = *aItr; |
| rEngine.SetParaAttribs(pRememberItem->nIndex, pRememberItem->aItemSet); |
| delete pRememberItem; |
| aItr = aRememberItems.erase(aItr); |
| } |
| } |
| |
| // #i61702# if the content isn't accessed, there's no need to set the UpdateMode again |
| if ( bUpdateMode && !bLoseContent ) |
| rEngine.SetUpdateMode(sal_True); |
| } |
| else |
| { |
| String aText = rEngine.GetText(); |
| if ( bInterpret || !aText.Len() ) |
| bRet = SetNormalString( rPos, aText, bApi ); |
| else |
| bRet = PutCell( rPos, new ScStringCell( aText ), bApi ); |
| } |
| |
| if ( bRet && aTester.NeedsCellAttr() ) |
| { |
| const SfxItemSet& rEditAttr = aTester.GetAttribs(); |
| ScPatternAttr aPattern( pDoc->GetPool() ); |
| aPattern.GetFromEditItemSet( &rEditAttr ); |
| aPattern.DeleteUnchanged( pDoc->GetPattern( rPos.Col(), rPos.Row(), rPos.Tab() ) ); |
| aPattern.GetItemSet().ClearItem( ATTR_HOR_JUSTIFY ); // wasn't removed above if no edit object |
| if ( aPattern.GetItemSet().Count() > 0 ) |
| { |
| ScMarkData aMark; |
| aMark.SelectTable( rPos.Tab(), sal_True ); |
| aMark.SetMarkArea( ScRange( rPos ) ); |
| ApplyAttributes( aMark, aPattern, sal_True, bApi ); |
| } |
| } |
| |
| return bRet; |
| } |
| |
| |
| ScTokenArray* lcl_ScDocFunc_CreateTokenArrayXML( const String& rText, const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar ) |
| { |
| ScTokenArray* pCode = new ScTokenArray; |
| pCode->AddString( rText ); |
| if( (eGrammar == formula::FormulaGrammar::GRAM_EXTERNAL) && (rFormulaNmsp.Len() > 0) ) |
| pCode->AddString( rFormulaNmsp ); |
| return pCode; |
| } |
| |
| |
| ScBaseCell* ScDocFunc::InterpretEnglishString( const ScAddress& rPos, |
| const String& rText, const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar, short* pRetFormatType ) |
| { |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| ScBaseCell* pNewCell = NULL; |
| |
| if ( rText.Len() > 1 && rText.GetChar(0) == '=' ) |
| { |
| ScTokenArray* pCode; |
| if ( pDoc->IsImportingXML() ) |
| { // temporary formula string as string tokens |
| pCode = lcl_ScDocFunc_CreateTokenArrayXML( rText, rFormulaNmsp, eGrammar ); |
| pDoc->IncXMLImportedFormulaCount( rText.Len() ); |
| } |
| else |
| { |
| ScCompiler aComp( pDoc, rPos ); |
| aComp.SetGrammar(eGrammar); |
| pCode = aComp.CompileString( rText ); |
| } |
| pNewCell = new ScFormulaCell( pDoc, rPos, pCode, eGrammar, MM_NONE ); |
| delete pCode; // Zell-ctor hat das TokenArray kopiert |
| } |
| else if ( rText.Len() > 1 && rText.GetChar(0) == '\'' ) |
| { |
| // for bEnglish, "'" at the beginning is always interpreted as text |
| // marker and stripped |
| pNewCell = ScBaseCell::CreateTextCell( rText.Copy( 1 ), pDoc ); |
| } |
| else // (nur) auf englisches Zahlformat testen |
| { |
| SvNumberFormatter* pFormatter = pDoc->GetFormatTable(); |
| sal_uInt32 nEnglish = pFormatter->GetStandardIndex(LANGUAGE_ENGLISH_US); |
| double fVal; |
| if ( pFormatter->IsNumberFormat( rText, nEnglish, fVal ) ) |
| { |
| pNewCell = new ScValueCell( fVal ); |
| // return the format type from the English format, so a localized format can be created |
| if ( pRetFormatType ) |
| *pRetFormatType = pFormatter->GetType( nEnglish ); |
| } |
| else if ( rText.Len() ) |
| pNewCell = ScBaseCell::CreateTextCell( rText, pDoc ); |
| |
| // das (englische) Zahlformat wird nicht gesetzt |
| //! passendes lokales Format suchen und setzen??? |
| } |
| |
| return pNewCell; |
| } |
| |
| |
| sal_Bool ScDocFunc::SetCellText( const ScAddress& rPos, const String& rText, |
| sal_Bool bInterpret, sal_Bool bEnglish, sal_Bool bApi, |
| const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar ) |
| { |
| // SetCellText ruft PutCell oder SetNormalString |
| |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| ScBaseCell* pNewCell = NULL; |
| if ( bInterpret ) |
| { |
| if ( bEnglish ) |
| { |
| ::boost::scoped_ptr<ScExternalRefManager::ApiGuard> pExtRefGuard; |
| if (bApi) |
| pExtRefGuard.reset(new ScExternalRefManager::ApiGuard(pDoc)); |
| |
| // code moved to own method InterpretEnglishString because it is also used in |
| // ScCellRangeObj::setFormulaArray |
| |
| pNewCell = InterpretEnglishString( rPos, rText, rFormulaNmsp, eGrammar ); |
| } |
| // sonst Null behalten -> SetString mit lokalen Formeln/Zahlformat |
| } |
| else if ( rText.Len() ) |
| { |
| OSL_ENSURE( rFormulaNmsp.Len() == 0, "ScDocFunc::SetCellText - formula namespace, but do not interpret?" ); |
| pNewCell = ScBaseCell::CreateTextCell( rText, pDoc ); // immer Text |
| } |
| |
| if (pNewCell) |
| return PutCell( rPos, pNewCell, bApi ); |
| else |
| return SetNormalString( rPos, rText, bApi ); |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| bool ScDocFunc::ShowNote( const ScAddress& rPos, bool bShow ) |
| { |
| ScDocument& rDoc = *rDocShell.GetDocument(); |
| ScPostIt* pNote = rDoc.GetNote( rPos ); |
| if( !pNote || (bShow == pNote->IsCaptionShown()) ) return false; |
| |
| // move the caption to internal or hidden layer and create undo action |
| pNote->ShowCaption( rPos, bShow ); |
| if( rDoc.IsUndoEnabled() ) |
| rDocShell.GetUndoManager()->AddUndoAction( new ScUndoShowHideNote( rDocShell, rPos, bShow ) ); |
| |
| if (rDoc.IsStreamValid(rPos.Tab())) |
| rDoc.SetStreamValid(rPos.Tab(), sal_False); |
| |
| rDocShell.SetDocumentModified(); |
| |
| return true; |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| bool ScDocFunc::SetNoteText( const ScAddress& rPos, const String& rText, sal_Bool bApi ) |
| { |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| ScEditableTester aTester( pDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() ); |
| if (!aTester.IsEditable()) |
| { |
| if (!bApi) |
| rDocShell.ErrorMessage(aTester.GetMessageId()); |
| return false; |
| } |
| |
| String aNewText = rText; |
| aNewText.ConvertLineEnd(); //! ist das noetig ??? |
| |
| if( ScPostIt* pNote = (aNewText.Len() > 0) ? pDoc->GetOrCreateNote( rPos ) : pDoc->GetNote( rPos ) ) |
| pNote->SetText( rPos, aNewText ); |
| |
| //! Undo !!! |
| |
| if (pDoc->IsStreamValid(rPos.Tab())) |
| pDoc->SetStreamValid(rPos.Tab(), sal_False); |
| |
| rDocShell.PostPaintCell( rPos ); |
| aModificator.SetDocumentModified(); |
| |
| return true; |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| bool ScDocFunc::ReplaceNote( const ScAddress& rPos, const String& rNoteText, const String* pAuthor, const String* pDate, sal_Bool bApi ) |
| { |
| bool bDone = false; |
| |
| ScDocShellModificator aModificator( rDocShell ); |
| ScDocument& rDoc = *rDocShell.GetDocument(); |
| ScEditableTester aTester( &rDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() ); |
| if (aTester.IsEditable()) |
| { |
| ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer(); |
| ::svl::IUndoManager* pUndoMgr = (pDrawLayer && rDoc.IsUndoEnabled()) ? rDocShell.GetUndoManager() : 0; |
| |
| ScNoteData aOldData; |
| ScPostIt* pOldNote = rDoc.ReleaseNote( rPos ); |
| if( pOldNote ) |
| { |
| // ensure existing caption object before draw undo tracking starts |
| pOldNote->GetOrCreateCaption( rPos ); |
| // rescue note data for undo |
| aOldData = pOldNote->GetNoteData(); |
| } |
| |
| // collect drawing undo actions for deleting/inserting caption obejcts |
| if( pUndoMgr ) |
| pDrawLayer->BeginCalcUndo(false); |
| |
| // delete the note (creates drawing undo action for the caption object) |
| delete pOldNote; |
| |
| // create new note (creates drawing undo action for the new caption object) |
| ScNoteData aNewData; |
| if( ScPostIt* pNewNote = ScNoteUtil::CreateNoteFromString( rDoc, rPos, rNoteText, false, true ) ) |
| { |
| if( pAuthor ) pNewNote->SetAuthor( *pAuthor ); |
| if( pDate ) pNewNote->SetDate( *pDate ); |
| // rescue note data for undo |
| aNewData = pNewNote->GetNoteData(); |
| } |
| |
| // create the undo action |
| if( pUndoMgr && (aOldData.mpCaption || aNewData.mpCaption) ) |
| pUndoMgr->AddUndoAction( new ScUndoReplaceNote( rDocShell, rPos, aOldData, aNewData, pDrawLayer->GetCalcUndo() ) ); |
| |
| // repaint cell (to make note marker visible) |
| rDocShell.PostPaintCell( rPos ); |
| |
| if (rDoc.IsStreamValid(rPos.Tab())) |
| rDoc.SetStreamValid(rPos.Tab(), sal_False); |
| |
| aModificator.SetDocumentModified(); |
| bDone = true; |
| } |
| else if (!bApi) |
| { |
| rDocShell.ErrorMessage(aTester.GetMessageId()); |
| } |
| |
| return bDone; |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| sal_Bool ScDocFunc::ApplyAttributes( const ScMarkData& rMark, const ScPatternAttr& rPattern, |
| sal_Bool bRecord, sal_Bool bApi ) |
| { |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| if ( bRecord && !pDoc->IsUndoEnabled() ) |
| bRecord = sal_False; |
| |
| sal_Bool bImportingXML = pDoc->IsImportingXML(); |
| // Cell formats can still be set if the range isn't editable only because of matrix formulas. |
| // #i62483# When loading XML, the check can be skipped altogether. |
| sal_Bool bOnlyNotBecauseOfMatrix; |
| if ( !bImportingXML && !pDoc->IsSelectionEditable( rMark, &bOnlyNotBecauseOfMatrix ) |
| && !bOnlyNotBecauseOfMatrix ) |
| { |
| if (!bApi) |
| rDocShell.ErrorMessage(STR_PROTECTIONERR); |
| return sal_False; |
| } |
| |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| //! Umrandung |
| |
| ScRange aMultiRange; |
| sal_Bool bMulti = rMark.IsMultiMarked(); |
| if ( bMulti ) |
| rMark.GetMultiMarkArea( aMultiRange ); |
| else |
| rMark.GetMarkArea( aMultiRange ); |
| |
| if ( bRecord ) |
| { |
| ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); |
| pUndoDoc->InitUndo( pDoc, aMultiRange.aStart.Tab(), aMultiRange.aEnd.Tab() ); |
| pDoc->CopyToDocument( aMultiRange, IDF_ATTRIB, bMulti, pUndoDoc, &rMark ); |
| |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoSelectionAttr( |
| &rDocShell, rMark, |
| aMultiRange.aStart.Col(), aMultiRange.aStart.Row(), aMultiRange.aStart.Tab(), |
| aMultiRange.aEnd.Col(), aMultiRange.aEnd.Row(), aMultiRange.aEnd.Tab(), |
| pUndoDoc, bMulti, &rPattern ) ); |
| } |
| |
| // While loading XML it is not neccessary to ask HasAttrib. It needs too much time. |
| sal_uInt16 nExtFlags = 0; |
| if ( !bImportingXML ) |
| rDocShell.UpdatePaintExt( nExtFlags, aMultiRange ); // content before the change |
| pDoc->ApplySelectionPattern( rPattern, rMark ); |
| if ( !bImportingXML ) |
| rDocShell.UpdatePaintExt( nExtFlags, aMultiRange ); // content after the change |
| |
| if (!AdjustRowHeight( aMultiRange )) |
| rDocShell.PostPaint( aMultiRange, PAINT_GRID, nExtFlags ); |
| else if (nExtFlags & SC_PF_LINES) |
| lcl_PaintAbove( rDocShell, aMultiRange ); // fuer Linien ueber dem Bereich |
| |
| aModificator.SetDocumentModified(); |
| |
| return sal_True; |
| } |
| |
| |
| sal_Bool ScDocFunc::ApplyStyle( const ScMarkData& rMark, const String& rStyleName, |
| sal_Bool bRecord, sal_Bool bApi ) |
| { |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| if ( bRecord && !pDoc->IsUndoEnabled() ) |
| bRecord = sal_False; |
| |
| sal_Bool bImportingXML = pDoc->IsImportingXML(); |
| // Cell formats can still be set if the range isn't editable only because of matrix formulas. |
| // #i62483# When loading XML, the check can be skipped altogether. |
| sal_Bool bOnlyNotBecauseOfMatrix; |
| if ( !bImportingXML && !pDoc->IsSelectionEditable( rMark, &bOnlyNotBecauseOfMatrix ) |
| && !bOnlyNotBecauseOfMatrix ) |
| { |
| if (!bApi) |
| rDocShell.ErrorMessage(STR_PROTECTIONERR); |
| return sal_False; |
| } |
| |
| ScStyleSheet* pStyleSheet = (ScStyleSheet*) pDoc->GetStyleSheetPool()->Find( |
| rStyleName, SFX_STYLE_FAMILY_PARA ); |
| if (!pStyleSheet) |
| return sal_False; |
| |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| ScRange aMultiRange; |
| sal_Bool bMulti = rMark.IsMultiMarked(); |
| if ( bMulti ) |
| rMark.GetMultiMarkArea( aMultiRange ); |
| else |
| rMark.GetMarkArea( aMultiRange ); |
| |
| if ( bRecord ) |
| { |
| ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); |
| SCTAB nStartTab = aMultiRange.aStart.Tab(); |
| SCTAB nTabCount = pDoc->GetTableCount(); |
| pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab ); |
| for (SCTAB i=0; i<nTabCount; i++) |
| if (i != nStartTab && rMark.GetTableSelect(i)) |
| pUndoDoc->AddUndoTab( i, i ); |
| |
| ScRange aCopyRange = aMultiRange; |
| aCopyRange.aStart.SetTab(0); |
| aCopyRange.aEnd.SetTab(nTabCount-1); |
| pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, bMulti, pUndoDoc, &rMark ); |
| |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoSelectionStyle( |
| &rDocShell, rMark, aMultiRange, rStyleName, pUndoDoc ) ); |
| |
| } |
| |
| // sal_Bool bPaintExt = pDoc->HasAttrib( aMultiRange, HASATTR_PAINTEXT ); |
| // pDoc->ApplySelectionPattern( rPattern, rMark ); |
| |
| pDoc->ApplySelectionStyle( (ScStyleSheet&)*pStyleSheet, rMark ); |
| |
| // if (!bPaintExt) |
| // bPaintExt = pDoc->HasAttrib( aMultiRange, HASATTR_PAINTEXT ); |
| // sal_uInt16 nExtFlags = bPaintExt ? SC_PF_LINES : 0; |
| sal_uInt16 nExtFlags = 0; |
| if (!AdjustRowHeight( aMultiRange )) |
| rDocShell.PostPaint( aMultiRange, PAINT_GRID, nExtFlags ); |
| else if (nExtFlags & SC_PF_LINES) |
| lcl_PaintAbove( rDocShell, aMultiRange ); // fuer Linien ueber dem Bereich |
| |
| aModificator.SetDocumentModified(); |
| |
| return sal_True; |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| sal_Bool ScDocFunc::InsertCells( const ScRange& rRange, const ScMarkData* pTabMark, InsCellCmd eCmd, |
| sal_Bool bRecord, sal_Bool bApi, sal_Bool bPartOfPaste ) |
| { |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| SCCOL nStartCol = rRange.aStart.Col(); |
| SCROW nStartRow = rRange.aStart.Row(); |
| SCTAB nStartTab = rRange.aStart.Tab(); |
| SCCOL nEndCol = rRange.aEnd.Col(); |
| SCROW nEndRow = rRange.aEnd.Row(); |
| SCTAB nEndTab = rRange.aEnd.Tab(); |
| |
| if ( !ValidRow(nStartRow) || !ValidRow(nEndRow) ) |
| { |
| DBG_ERROR("invalid row in InsertCells"); |
| return sal_False; |
| } |
| |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| SCTAB nTabCount = pDoc->GetTableCount(); |
| SCCOL nPaintStartX = nStartCol; |
| SCROW nPaintStartY = nStartRow; |
| SCCOL nPaintEndX = nEndCol; |
| SCROW nPaintEndY = nEndRow; |
| sal_uInt16 nPaintFlags = PAINT_GRID; |
| sal_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 = sal_False; |
| |
| ScMarkData aMark; |
| if (pTabMark) |
| aMark = *pTabMark; |
| else |
| { |
| SCTAB nCount = 0; |
| for( i=0; i<nTabCount; i++ ) |
| { |
| if( !pDoc->IsScenario(i) ) |
| { |
| nCount++; |
| if( nCount == nEndTab+1 ) |
| { |
| aMark.SelectTable( i, sal_True ); |
| break; |
| } |
| } |
| } |
| } |
| |
| ScMarkData aFullMark( aMark ); // including scenario sheets |
| for( i=0; i<nTabCount; i++ ) |
| if( aMark.GetTableSelect( i ) ) |
| { |
| for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ ) |
| aFullMark.SelectTable( j, sal_True ); |
| } |
| |
| SCTAB nSelCount = aMark.GetSelectCount(); |
| |
| // zugehoerige Szenarien auch anpassen |
| // Test zusammengefasste |
| |
| SCCOL nMergeTestStartX = nStartCol; |
| SCROW nMergeTestStartY = nStartRow; |
| SCCOL nMergeTestEndX = nEndCol; |
| SCROW nMergeTestEndY = nEndRow; |
| |
| 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(); |
| nPaintEndX = nMergeTestEndX; |
| nPaintEndY = nMergeTestEndY; |
| } |
| |
| 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; |
| |
| sal_Bool bNeedRefresh = sal_False; |
| |
| SCCOL nEditTestEndX = (eCmd==INS_INSCOLS) ? MAXCOL : nMergeTestEndX; |
| SCROW nEditTestEndY = (eCmd==INS_INSROWS) ? MAXROW : nMergeTestEndY; |
| ScEditableTester aTester( pDoc, nMergeTestStartX, nMergeTestStartY, nEditTestEndX, nEditTestEndY, aMark ); |
| if (!aTester.IsEditable()) |
| { |
| if (!bApi) |
| rDocShell.ErrorMessage(aTester.GetMessageId()); |
| return sal_False; |
| } |
| |
| WaitObject aWait( rDocShell.GetActiveDialogParent() ); // wichtig wegen TrackFormulas bei UpdateReference |
| |
| ScDocument* pRefUndoDoc = NULL; |
| ScRefUndoData* pUndoData = NULL; |
| if ( bRecord ) |
| { |
| pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO ); |
| pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, sal_False, sal_False ); |
| |
| // pRefUndoDoc is filled in InsertCol / InsertRow |
| |
| pUndoData = new ScRefUndoData( pDoc ); |
| |
| 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 |
| sal_Bool bInsertMerge = sal_False; |
| std::vector<ScRange> qIncreaseRange; |
| String aUndo = ScGlobal::GetRscString( STR_UNDO_INSERTCELLS ); |
| if (bRecord) |
| rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo ); |
| |
| for( i=0; i<nTabCount; i++ ) |
| { |
| if( aMark.GetTableSelect(i) ) |
| { |
| if( pDoc->HasAttrib( nMergeTestStartX, nMergeTestStartY, i, nMergeTestEndX, nMergeTestEndY, i, HASATTR_MERGED | HASATTR_OVERLAPPED ) ) |
| { |
| if (eCmd==INS_CELLSRIGHT) |
| bNeedRefresh = sal_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 sal_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); |
| sal_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, sal_True, sal_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, sal_True, sal_True); |
| ScRange aMergeRange( aTestRange.aStart.Col(),aTestRange.aStart.Row(), i ); |
| if( !aExtendRange.In( aMergeRange ) ) |
| { |
| qIncreaseRange.push_back( aTestRange ); |
| bInsertMerge = sal_True; |
| } |
| } |
| } |
| else |
| { |
| ScRange aMergeRange( aRange.aStart.Col(),aRange.aStart.Row(), i ); |
| if( !aExtendRange.In( aMergeRange ) ) |
| { |
| qIncreaseRange.push_back( aRange ); |
| } |
| bInsertMerge = sal_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; |
| } |
| else |
| { |
| nStartRow = 0; |
| nEndRow = MAXROW; |
| } |
| } |
| |
| if( !qIncreaseRange.empty() ) |
| { |
| for( ::std::vector<ScRange>::const_iterator iIter( qIncreaseRange.begin()); iIter != qIncreaseRange.end(); iIter++ ) |
| { |
| ScRange aRange( *iIter ); |
| if( pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) ) |
| { |
| UnmergeCells( aRange, sal_True, sal_True ); |
| } |
| } |
| } |
| } |
| else |
| { |
| if (!bApi) |
| rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0); |
| rDocShell.GetUndoManager()->LeaveListAction(); |
| return sal_False; |
| } |
| } |
| } |
| } |
| |
| switch (eCmd) |
| { |
| case INS_CELLSDOWN: |
| bSuccess = pDoc->InsertRow( nStartCol, 0, nEndCol, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, &aFullMark ); |
| nPaintEndY = MAXROW; |
| break; |
| case INS_INSROWS: |
| bSuccess = pDoc->InsertRow( 0, 0, MAXCOL, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, &aFullMark ); |
| nPaintStartX = 0; |
| nPaintEndX = MAXCOL; |
| nPaintEndY = MAXROW; |
| nPaintFlags |= PAINT_LEFT; |
| break; |
| case INS_CELLSRIGHT: |
| bSuccess = pDoc->InsertCol( nStartRow, 0, nEndRow, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, &aFullMark ); |
| nPaintEndX = MAXCOL; |
| break; |
| case INS_INSCOLS: |
| bSuccess = pDoc->InsertCol( 0, 0, MAXROW, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, &aFullMark ); |
| nPaintStartY = 0; |
| nPaintEndY = MAXROW; |
| nPaintEndX = MAXCOL; |
| nPaintFlags |= PAINT_TOP; |
| break; |
| default: |
| DBG_ERROR("Falscher Code beim Einfuegen"); |
| bSuccess = sal_False; |
| break; |
| } |
| |
| if ( bSuccess ) |
| { |
| SCTAB* pTabs = NULL; |
| SCTAB* pScenarios = NULL; |
| SCTAB nUndoPos = 0; |
| |
| if ( bRecord ) |
| { |
| pTabs = new SCTAB[nSelCount]; |
| pScenarios = new SCTAB[nSelCount]; |
| nUndoPos = 0; |
| for( i=0; i<nTabCount; i++ ) |
| { |
| if( aMark.GetTableSelect( i ) ) |
| { |
| SCTAB nCount = 0; |
| for( SCTAB j=i+1; j<nTabCount && pDoc->IsScenario(j); j++ ) |
| nCount ++; |
| |
| pScenarios[nUndoPos] = nCount; |
| pTabs[nUndoPos] = i; |
| nUndoPos ++; |
| } |
| } |
| |
| 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<SCsCOL>(nEndRow-nStartRow+1)); |
| break; |
| case INS_CELLSRIGHT: |
| case INS_INSCOLS: |
| aRange.aEnd.IncCol(static_cast<SCsCOL>(nEndCol-nStartCol+1)); |
| break; |
| default: |
| break; |
| } |
| MergeCells(aRange, sal_False, sal_True, sal_True); |
| } |
| qIncreaseRange.pop_back(); |
| } |
| |
| if( bInsertMerge ) |
| rDocShell.GetUndoManager()->LeaveListAction(); |
| |
| for( i=0; i<nTabCount; i++ ) |
| { |
| if( aMark.GetTableSelect( i ) ) |
| { |
| if (bNeedRefresh) |
| pDoc->ExtendMerge( nMergeTestStartX, nMergeTestStartY, nMergeTestEndX, nMergeTestEndY, i, sal_True ); |
| else |
| pDoc->RefreshAutoFilter( nMergeTestStartX, nMergeTestStartY, nMergeTestEndX, nMergeTestEndY, i ); |
| |
| if ( eCmd == INS_INSROWS || eCmd == INS_INSCOLS ) |
| pDoc->UpdatePageBreaks( i ); |
| |
| sal_uInt16 nExtFlags = 0; |
| rDocShell.UpdatePaintExt( nExtFlags, nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i ); |
| |
| SCTAB nScenarioCount = 0; |
| |
| for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ ) |
| nScenarioCount ++; |
| |
| sal_Bool bAdjusted = ( eCmd == INS_INSROWS ) ? AdjustRowHeight(ScRange(0, nStartRow, i, MAXCOL, nEndRow, i+nScenarioCount )) : |
| AdjustRowHeight(ScRange(0, nPaintStartY, i, MAXCOL, nPaintEndY, i+nScenarioCount )); |
| if (bAdjusted) |
| { |
| // paint only what is not done by AdjustRowHeight |
| if (nPaintFlags & PAINT_TOP) |
| rDocShell.PostPaint( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount, PAINT_TOP ); |
| } |
| else |
| rDocShell.PostPaint( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount, nPaintFlags, nExtFlags ); |
| } |
| } |
| //aModificator.SetDocumentModified(); |
| } |
| else |
| { |
| if( bInsertMerge ) |
| { |
| while( !qIncreaseRange.empty() ) |
| { |
| ScRange aRange = qIncreaseRange.back(); |
| MergeCells(aRange, sal_False, sal_True, sal_True); |
| qIncreaseRange.pop_back(); |
| } |
| |
| if( pViewSh ) |
| { |
| pViewSh->MarkRange( rRange, sal_False ); |
| pViewSh->SetCursor( nCursorCol, nCursorRow ); |
| } |
| } |
| |
| rDocShell.GetUndoManager()->LeaveListAction(); |
| rDocShell.GetUndoManager()->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; |
| } |
| |
| sal_Bool ScDocFunc::DeleteCells( const ScRange& rRange, const ScMarkData* pTabMark, DelCellCmd eCmd, |
| sal_Bool bRecord, sal_Bool bApi ) |
| { |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| SCCOL nStartCol = rRange.aStart.Col(); |
| SCROW nStartRow = rRange.aStart.Row(); |
| SCTAB nStartTab = rRange.aStart.Tab(); |
| SCCOL nEndCol = rRange.aEnd.Col(); |
| SCROW nEndRow = rRange.aEnd.Row(); |
| SCTAB nEndTab = rRange.aEnd.Tab(); |
| |
| if ( !ValidRow(nStartRow) || !ValidRow(nEndRow) ) |
| { |
| DBG_ERROR("invalid row in DeleteCells"); |
| return sal_False; |
| } |
| |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| SCTAB nTabCount = pDoc->GetTableCount(); |
| SCCOL nPaintStartX = nStartCol; |
| SCROW nPaintStartY = nStartRow; |
| SCCOL nPaintEndX = nEndCol; |
| SCROW nPaintEndY = nEndRow; |
| sal_uInt16 nPaintFlags = PAINT_GRID; |
| SCTAB i; |
| |
| if (bRecord && !pDoc->IsUndoEnabled()) |
| bRecord = sal_False; |
| |
| ScMarkData aMark; |
| if (pTabMark) |
| aMark = *pTabMark; |
| else |
| { |
| SCTAB nCount = 0; |
| for( i=0; i<nTabCount; i++ ) |
| { |
| if( !pDoc->IsScenario(i) ) |
| { |
| nCount++; |
| if( nCount == nEndTab+1 ) |
| { |
| aMark.SelectTable( i, sal_True ); |
| break; |
| } |
| } |
| } |
| } |
| |
| ScMarkData aFullMark( aMark ); // including scenario sheets |
| for( i=0; i<nTabCount; i++ ) |
| if( aMark.GetTableSelect( i ) ) |
| { |
| for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ ) |
| aFullMark.SelectTable( j, sal_True ); |
| } |
| |
| SCTAB nSelCount = aMark.GetSelectCount(); |
| |
| SCCOL nUndoStartX = nStartCol; |
| SCROW nUndoStartY = nStartRow; |
| SCCOL nUndoEndX = nEndCol; |
| SCROW nUndoEndY = nEndRow; |
| |
| ScRange aExtendMergeRange( rRange ); |
| |
| if( rRange.aStart == rRange.aEnd && pDoc->HasAttrib(rRange, HASATTR_MERGED) ) |
| { |
| pDoc->ExtendMerge( aExtendMergeRange ); |
| pDoc->ExtendOverlapped( aExtendMergeRange ); |
| nUndoEndX = aExtendMergeRange.aEnd.Col(); |
| nUndoEndY = aExtendMergeRange.aEnd.Row(); |
| nPaintEndX = nUndoEndX; |
| nPaintEndY = nUndoEndY; |
| } |
| |
| if (eCmd==DEL_DELROWS) |
| { |
| nUndoStartX = 0; |
| nUndoEndX = MAXCOL; |
| } |
| if (eCmd==DEL_DELCOLS) |
| { |
| nUndoStartY = 0; |
| nUndoEndY = MAXROW; |
| } |
| // Test Zellschutz |
| |
| SCCOL nEditTestEndX = nUndoEndX; |
| if ( eCmd==DEL_DELCOLS || eCmd==DEL_CELLSLEFT ) |
| nEditTestEndX = MAXCOL; |
| SCROW nEditTestEndY = nUndoEndY; |
| if ( eCmd==DEL_DELROWS || eCmd==DEL_CELLSUP ) |
| nEditTestEndY = MAXROW; |
| ScEditableTester aTester( pDoc, nUndoStartX, nUndoStartY, nEditTestEndX, nEditTestEndY, aMark ); |
| if (!aTester.IsEditable()) |
| { |
| if (!bApi) |
| rDocShell.ErrorMessage(aTester.GetMessageId()); |
| return sal_False; |
| } |
| |
| // Test zusammengefasste |
| |
| SCCOL nMergeTestEndX = (eCmd==DEL_CELLSLEFT) ? MAXCOL : nUndoEndX; |
| SCROW nMergeTestEndY = (eCmd==DEL_CELLSUP) ? MAXROW : nUndoEndY; |
| SCCOL nExtendStartCol = nUndoStartX; |
| SCROW nExtendStartRow = nUndoStartY; |
| sal_Bool bNeedRefresh = sal_False; |
| |
| //Issue 8302 want to be able to insert into the middle of merged cells |
| //the patch comes from maoyg |
| ::std::vector<ScRange> qDecreaseRange; |
| sal_Bool bDeletingMerge = sal_False; |
| String aUndo = ScGlobal::GetRscString( STR_UNDO_DELETECELLS ); |
| if (bRecord) |
| rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo ); |
| |
| for( i=0; i<nTabCount; i++ ) |
| { |
| if( aMark.GetTableSelect(i) ) |
| { |
| if ( pDoc->HasAttrib( nUndoStartX, nUndoStartY, i, nMergeTestEndX, nMergeTestEndY, i, HASATTR_MERGED | HASATTR_OVERLAPPED )) |
| { |
| SCCOL nMergeStartX = nUndoStartX; |
| SCROW nMergeStartY = nUndoStartY; |
| SCCOL nMergeEndX = nMergeTestEndX; |
| SCROW nMergeEndY = nMergeTestEndY; |
| |
| pDoc->ExtendMerge( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i ); |
| pDoc->ExtendOverlapped( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i ); |
| if( ( eCmd == DEL_CELLSUP && ( nMergeStartX != nUndoStartX || nMergeEndX != nMergeTestEndX))|| |
| ( eCmd == DEL_CELLSLEFT && ( nMergeStartY != nUndoStartY || nMergeEndY != nMergeTestEndY))) |
| { |
| if (!bApi) |
| rDocShell.ErrorMessage(STR_MSSG_DELETECELLS_0); |
| rDocShell.GetUndoManager()->LeaveListAction(); |
| return sal_False; |
| } |
| |
| nExtendStartCol = nMergeStartX; |
| nExtendStartRow = nMergeStartY; |
| SCCOL nTestCol = -1; |
| SCROW nTestRow1 = -1; |
| SCROW nTestRow2 = -1; |
| |
| ScDocAttrIterator aTestIter( pDoc, i, nUndoStartX, nUndoStartY, nMergeTestEndX, nMergeTestEndY ); |
| ScRange aExtendRange( nUndoStartX, nUndoStartY, 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 ); |
| sal_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, sal_True, sal_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, sal_True, sal_True); |
| ScRange aMergeRange( aTestRange.aStart.Col(),aTestRange.aStart.Row(), i ); |
| if( !aExtendRange.In( aMergeRange ) ) |
| { |
| qDecreaseRange.push_back( aTestRange ); |
| bDeletingMerge = sal_True; |
| } |
| } |
| } |
| else |
| { |
| ScRange aMergeRange( aRange.aStart.Col(),aRange.aStart.Row(), i ); |
| if( !aExtendRange.In( aMergeRange ) ) |
| { |
| qDecreaseRange.push_back( aRange ); |
| } |
| bDeletingMerge = sal_True; |
| } |
| } |
| } |
| |
| if( bDeletingMerge ) |
| { |
| |
| if( eCmd == DEL_DELROWS || eCmd == DEL_CELLSUP ) |
| { |
| nStartRow = aExtendMergeRange.aStart.Row(); |
| nEndRow = aExtendMergeRange.aEnd.Row(); |
| bNeedRefresh = sal_True; |
| |
| if( eCmd == DEL_CELLSUP ) |
| { |
| nEndCol = aExtendMergeRange.aEnd.Col(); |
| } |
| else |
| { |
| nStartCol = 0; |
| nEndCol = MAXCOL; |
| } |
| } |
| else if( eCmd == DEL_CELLSLEFT || eCmd == DEL_DELCOLS ) |
| { |
| |
| nStartCol = aExtendMergeRange.aStart.Col(); |
| nEndCol = aExtendMergeRange.aEnd.Col(); |
| if( eCmd == DEL_CELLSLEFT ) |
| { |
| nEndRow = aExtendMergeRange.aEnd.Row(); |
| bNeedRefresh = sal_True; |
| } |
| else |
| { |
| nStartRow = 0; |
| nEndRow = MAXROW; |
| } |
| } |
| |
| if( !qDecreaseRange.empty() ) |
| { |
| for( ::std::vector<ScRange>::const_iterator iIter( qDecreaseRange.begin()); iIter != qDecreaseRange.end(); iIter++ ) |
| { |
| ScRange aRange( *iIter ); |
| if( pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) ) |
| { |
| UnmergeCells( aRange, sal_True, sal_True ); |
| } |
| } |
| } |
| } |
| else |
| { |
| if (!bApi) |
| rDocShell.ErrorMessage(STR_MSSG_DELETECELLS_0); |
| rDocShell.GetUndoManager()->LeaveListAction(); |
| return sal_False; |
| } |
| } |
| } |
| } |
| |
| // |
| // ausfuehren |
| // |
| |
| WaitObject aWait( rDocShell.GetActiveDialogParent() ); // wichtig wegen TrackFormulas bei UpdateReference |
| |
| ScDocument* pUndoDoc = NULL; |
| ScDocument* pRefUndoDoc = NULL; |
| ScRefUndoData* pUndoData = NULL; |
| if ( bRecord ) |
| { |
| // With the fix for #101329#, UpdateRef always puts cells into pRefUndoDoc at their old position, |
| // so it's no longer necessary to copy more than the deleted range into pUndoDoc. |
| |
| pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); |
| pUndoDoc->InitUndo( pDoc, 0, nTabCount-1, (eCmd==DEL_DELCOLS), (eCmd==DEL_DELROWS) ); |
| for( i=0; i<nTabCount; i++ ) |
| { |
| if( aMark.GetTableSelect( i ) ) |
| { |
| SCTAB nScenarioCount = 0; |
| |
| for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ ) |
| nScenarioCount ++; |
| |
| pDoc->CopyToDocument( nUndoStartX, nUndoStartY, i, nUndoEndX, nUndoEndY, i+nScenarioCount, |
| IDF_ALL | IDF_NOCAPTIONS, sal_False, pUndoDoc ); |
| } |
| } |
| |
| pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO ); |
| pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, sal_False, sal_False ); |
| |
| pUndoData = new ScRefUndoData( pDoc ); |
| |
| pDoc->BeginDrawUndo(); |
| } |
| |
| sal_uInt16 nExtFlags = 0; |
| for( i=0; i<nTabCount; i++ ) |
| { |
| if( aMark.GetTableSelect( i ) ) |
| rDocShell.UpdatePaintExt( nExtFlags, nStartCol, nStartRow, i, nEndCol, nEndRow, i ); |
| } |
| |
| sal_Bool bUndoOutline = sal_False; |
| switch (eCmd) |
| { |
| case DEL_CELLSUP: |
| pDoc->DeleteRow( nStartCol, 0, nEndCol, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, NULL, &aFullMark ); |
| nPaintEndY = MAXROW; |
| break; |
| case DEL_DELROWS: |
| pDoc->DeleteRow( 0, 0, MAXCOL, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, &bUndoOutline, &aFullMark ); |
| nPaintStartX = 0; |
| nPaintEndX = MAXCOL; |
| nPaintEndY = MAXROW; |
| nPaintFlags |= PAINT_LEFT; |
| break; |
| case DEL_CELLSLEFT: |
| pDoc->DeleteCol( nStartRow, 0, nEndRow, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, NULL, &aFullMark ); |
| nPaintEndX = MAXCOL; |
| break; |
| case DEL_DELCOLS: |
| pDoc->DeleteCol( 0, 0, MAXROW, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, &bUndoOutline, &aFullMark ); |
| nPaintStartY = 0; |
| nPaintEndY = MAXROW; |
| nPaintEndX = MAXCOL; |
| nPaintFlags |= PAINT_TOP; |
| break; |
| default: |
| DBG_ERROR("Falscher Code beim Loeschen"); |
| break; |
| } |
| |
| //! Test, ob Outline in Groesse geaendert |
| |
| if ( bRecord ) |
| { |
| for( i=0; i<nTabCount; i++ ) |
| if( aFullMark.GetTableSelect( i ) ) |
| pRefUndoDoc->DeleteAreaTab(nUndoStartX,nUndoStartY,nUndoEndX,nUndoEndY, i, IDF_ALL); |
| |
| // alle Tabellen anlegen, damit Formeln kopiert werden koennen: |
| pUndoDoc->AddUndoTab( 0, nTabCount-1, sal_False, sal_False ); |
| |
| // kopieren mit bColRowFlags=sal_False (#54194#) |
| pRefUndoDoc->CopyToDocument(0,0,0,MAXCOL,MAXROW,MAXTAB,IDF_FORMULA,sal_False,pUndoDoc,NULL,sal_False); |
| delete pRefUndoDoc; |
| |
| SCTAB* pTabs = new SCTAB[nSelCount]; |
| SCTAB* pScenarios = new SCTAB[nSelCount]; |
| SCTAB nUndoPos = 0; |
| |
| for( i=0; i<nTabCount; i++ ) |
| { |
| if( aMark.GetTableSelect( i ) ) |
| { |
| SCTAB nCount = 0; |
| for( SCTAB j=i+1; j<nTabCount && pDoc->IsScenario(j); j++ ) |
| nCount ++; |
| |
| pScenarios[nUndoPos] = nCount; |
| pTabs[nUndoPos] = i; |
| nUndoPos ++; |
| } |
| } |
| |
| if( !bDeletingMerge ) |
| { |
| rDocShell.GetUndoManager()->LeaveListAction(); |
| } |
| |
| rDocShell.GetUndoManager()->AddUndoAction( new ScUndoDeleteCells( |
| &rDocShell, ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ),nUndoPos, pTabs, pScenarios, |
| eCmd, pUndoDoc, pUndoData ) ); |
| } |
| |
| // #i8302 want to be able to insert into the middle of merged cells |
| // the patch comes from maoyg |
| |
| while( !qDecreaseRange.empty() ) |
| { |
| ScRange aRange = qDecreaseRange.back(); |
| |
| long nDecreaseRowCount = 0; |
| long nDecreaseColCount = 0; |
| if( eCmd == DEL_CELLSUP || eCmd == DEL_DELROWS ) |
| { |
| if( nStartRow >= aRange.aStart.Row() && nStartRow <= aRange.aEnd.Row() && nEndRow>= aRange.aStart.Row() && nEndRow <= aRange.aEnd.Row() ) |
| nDecreaseRowCount = nEndRow-nStartRow+1; |
| else if( nStartRow >= aRange.aStart.Row() && nStartRow <= aRange.aEnd.Row() && nEndRow >= aRange.aStart.Row() && nEndRow >= aRange.aEnd.Row() ) |
| nDecreaseRowCount = aRange.aEnd.Row()-nStartRow+1; |
| else if( nStartRow >= aRange.aStart.Row() && nStartRow >= aRange.aEnd.Row() && nEndRow>= aRange.aStart.Row() && nEndRow <= aRange.aEnd.Row() ) |
| nDecreaseRowCount = aRange.aEnd.Row()-nEndRow+1; |
| } |
| else if( eCmd == DEL_CELLSLEFT || eCmd == DEL_DELCOLS ) |
| { |
| if( nStartCol >= aRange.aStart.Col() && nStartCol <= aRange.aEnd.Col() && nEndCol>= aRange.aStart.Col() && nEndCol <= aRange.aEnd.Col() ) |
| nDecreaseColCount = nEndCol-nStartCol+1; |
| else if( nStartCol >= aRange.aStart.Col() && nStartCol <= aRange.aEnd.Col() && nEndCol >= aRange.aStart.Col() && nEndCol >= aRange.aEnd.Col() ) |
| nDecreaseColCount = aRange.aEnd.Col()-nStartCol+1; |
| else if( nStartCol >= aRange.aStart.Col() && nStartCol >= aRange.aEnd.Col() && nEndCol>= aRange.aStart.Col() && nEndCol <= aRange.aEnd.Col() ) |
| nDecreaseColCount = aRange.aEnd.Col()-nEndCol+1; |
| } |
| |
| switch (eCmd) |
| { |
| case DEL_CELLSUP: |
| case DEL_DELROWS: |
| aRange.aEnd.SetRow(static_cast<SCsCOL>( aRange.aEnd.Row()-nDecreaseRowCount)); |
| break; |
| case DEL_CELLSLEFT: |
| case DEL_DELCOLS: |
| aRange.aEnd.SetCol(static_cast<SCsCOL>( aRange.aEnd.Col()-nDecreaseColCount)); |
| break; |
| default: |
| break; |
| } |
| |
| if( !pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) ) |
| { |
| MergeCells( aRange, sal_False, sal_True, sal_True ); |
| } |
| qDecreaseRange.pop_back(); |
| } |
| |
| if( bDeletingMerge ) |
| rDocShell.GetUndoManager()->LeaveListAction(); |
| |
| if ( bNeedRefresh ) |
| { |
| // #i51445# old merge flag attributes must be deleted also for single cells, |
| // not only for whole columns/rows |
| |
| if ( eCmd==DEL_DELCOLS || eCmd==DEL_CELLSLEFT ) |
| nMergeTestEndX = MAXCOL; |
| if ( eCmd==DEL_DELROWS || eCmd==DEL_CELLSUP ) |
| nMergeTestEndY = MAXROW; |
| ScPatternAttr aPattern( pDoc->GetPool() ); |
| aPattern.GetItemSet().Put( ScMergeFlagAttr() ); |
| |
| pDoc->ApplyPatternArea( nExtendStartCol, nExtendStartRow, nMergeTestEndX, nMergeTestEndY, aMark, aPattern ); |
| |
| for( i=0; i<nTabCount; i++ ) |
| { |
| if( aMark.GetTableSelect( i ) ) |
| { |
| SCTAB nScenarioCount = 0; |
| |
| for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ ) |
| nScenarioCount ++; |
| |
| ScRange aMergedRange( nExtendStartCol, nExtendStartRow, i, nMergeTestEndX, nMergeTestEndY, i+nScenarioCount ); |
| pDoc->ExtendMerge( aMergedRange, sal_True ); |
| } |
| } |
| } |
| |
| for( i=0; i<nTabCount; i++ ) |
| { |
| if( aMark.GetTableSelect( i ) ) |
| { |
| if ( eCmd == DEL_DELCOLS || eCmd == DEL_DELROWS ) |
| pDoc->UpdatePageBreaks( i ); |
| |
| rDocShell.UpdatePaintExt( nExtFlags, nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i ); |
| |
| SCTAB nScenarioCount = 0; |
| |
| for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ ) |
| nScenarioCount ++; |
| |
| // ganze Zeilen loeschen: nichts anpassen |
| if ( eCmd == DEL_DELROWS || !AdjustRowHeight(ScRange( 0, nPaintStartY, i, MAXCOL, nPaintEndY, i+nScenarioCount )) ) |
| rDocShell.PostPaint( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount, nPaintFlags, nExtFlags ); |
| else |
| { |
| // paint only what is not done by AdjustRowHeight |
| if (nExtFlags & SC_PF_LINES) |
| lcl_PaintAbove( rDocShell, ScRange( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount) ); |
| if (nPaintFlags & PAINT_TOP) |
| rDocShell.PostPaint( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount, PAINT_TOP ); |
| } |
| } |
| } |
| aModificator.SetDocumentModified(); |
| |
| SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); |
| |
| return sal_True; |
| } |
| |
| sal_Bool ScDocFunc::MoveBlock( const ScRange& rSource, const ScAddress& rDestPos, |
| sal_Bool bCut, sal_Bool bRecord, sal_Bool bPaint, sal_Bool bApi ) |
| { |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| SCCOL nStartCol = rSource.aStart.Col(); |
| SCROW nStartRow = rSource.aStart.Row(); |
| SCTAB nStartTab = rSource.aStart.Tab(); |
| SCCOL nEndCol = rSource.aEnd.Col(); |
| SCROW nEndRow = rSource.aEnd.Row(); |
| SCTAB nEndTab = rSource.aEnd.Tab(); |
| SCCOL nDestCol = rDestPos.Col(); |
| SCROW nDestRow = rDestPos.Row(); |
| SCTAB nDestTab = rDestPos.Tab(); |
| |
| if ( !ValidRow(nStartRow) || !ValidRow(nEndRow) || !ValidRow(nDestRow) ) |
| { |
| DBG_ERROR("invalid row in MoveBlock"); |
| return sal_False; |
| } |
| |
| // zugehoerige Szenarien auch anpassen - nur wenn innerhalb einer Tabelle verschoben wird! |
| sal_Bool bScenariosAdded = sal_False; |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| if (bRecord && !pDoc->IsUndoEnabled()) |
| bRecord = sal_False; |
| |
| SCTAB nTabCount = pDoc->GetTableCount(); |
| if ( nDestTab == nStartTab && !pDoc->IsScenario(nEndTab) ) |
| while ( nEndTab+1 < nTabCount && pDoc->IsScenario(nEndTab+1) ) |
| { |
| ++nEndTab; |
| bScenariosAdded = sal_True; |
| } |
| |
| SCTAB nSrcTabCount = nEndTab-nStartTab+1; |
| SCTAB nDestEndTab = nDestTab+nSrcTabCount-1; |
| SCTAB nTab; |
| |
| ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP ); |
| |
| ScMarkData aSourceMark; |
| for (nTab=nStartTab; nTab<=nEndTab; nTab++) |
| aSourceMark.SelectTable( nTab, sal_True ); // Source selektieren |
| aSourceMark.SetMarkArea( rSource ); |
| |
| ScDocShellRef aDragShellRef; |
| if ( pDoc->HasOLEObjectsInArea( rSource ) ) |
| { |
| aDragShellRef = new ScDocShell; // DocShell needs a Ref immediately |
| aDragShellRef->DoInitNew(NULL); |
| } |
| ScDrawLayer::SetGlobalDrawPersist(aDragShellRef); |
| |
| ScClipParam aClipParam(ScRange(nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nStartTab), bCut); |
| pDoc->CopyToClip(aClipParam, pClipDoc, &aSourceMark, false, bScenariosAdded, true); |
| |
| ScDrawLayer::SetGlobalDrawPersist(NULL); |
| |
| SCCOL nOldEndCol = nEndCol; |
| SCROW nOldEndRow = nEndRow; |
| sal_Bool bClipOver = sal_False; |
| for (nTab=nStartTab; nTab<=nEndTab; nTab++) |
| { |
| SCCOL nTmpEndCol = nOldEndCol; |
| SCROW nTmpEndRow = nOldEndRow; |
| if (pDoc->ExtendMerge( nStartCol, nStartRow, nTmpEndCol, nTmpEndRow, nTab )) |
| bClipOver = sal_True; |
| if ( nTmpEndCol > nEndCol ) nEndCol = nTmpEndCol; |
| if ( nTmpEndRow > nEndRow ) nEndRow = nTmpEndRow; |
| } |
| |
| SCCOL nDestEndCol = nDestCol + ( nOldEndCol-nStartCol ); |
| SCROW nDestEndRow = nDestRow + ( nOldEndRow-nStartRow ); |
| |
| SCCOL nUndoEndCol = nDestCol + ( nEndCol-nStartCol ); // erweitert im Zielblock |
| SCROW nUndoEndRow = nDestRow + ( nEndRow-nStartRow ); |
| |
| sal_Bool bIncludeFiltered = bCut; |
| if ( !bIncludeFiltered ) |
| { |
| // adjust sizes to include only non-filtered rows |
| |
| SCCOL nClipX; |
| SCROW nClipY; |
| pClipDoc->GetClipArea( nClipX, nClipY, sal_False ); |
| SCROW nUndoAdd = nUndoEndRow - nDestEndRow; |
| nDestEndRow = nDestRow + nClipY; |
| nUndoEndRow = nDestEndRow + nUndoAdd; |
| } |
| |
| if (!ValidCol(nUndoEndCol) || !ValidRow(nUndoEndRow)) |
| { |
| if (!bApi) |
| rDocShell.ErrorMessage(STR_PASTE_FULL); |
| delete pClipDoc; |
| return sal_False; |
| } |
| |
| // Test auf Zellschutz |
| |
| ScEditableTester aTester; |
| for (nTab=nDestTab; nTab<=nDestEndTab; nTab++) |
| aTester.TestBlock( pDoc, nTab, nDestCol,nDestRow, nUndoEndCol,nUndoEndRow ); |
| if (bCut) |
| for (nTab=nStartTab; nTab<=nEndTab; nTab++) |
| aTester.TestBlock( pDoc, nTab, nStartCol,nStartRow, nEndCol,nEndRow ); |
| |
| if (!aTester.IsEditable()) |
| { |
| if (!bApi) |
| rDocShell.ErrorMessage(aTester.GetMessageId()); |
| delete pClipDoc; |
| return sal_False; |
| } |
| |
| // Test auf zusammengefasste - beim Verschieben erst nach dem Loeschen |
| |
| if (bClipOver && !bCut) |
| if (pDoc->HasAttrib( nDestCol,nDestRow,nDestTab, nUndoEndCol,nUndoEndRow,nDestEndTab, |
| HASATTR_MERGED | HASATTR_OVERLAPPED )) |
| { // "Zusammenfassen nicht verschachteln !" |
| if (!bApi) |
| rDocShell.ErrorMessage(STR_MSSG_MOVEBLOCKTO_0); |
| delete pClipDoc; |
| return sal_False; |
| } |
| |
| // Are there borders in the cells? (for painting) |
| |
| sal_uInt16 nSourceExt = 0; |
| rDocShell.UpdatePaintExt( nSourceExt, nStartCol,nStartRow,nStartTab, nEndCol,nEndRow,nEndTab ); |
| sal_uInt16 nDestExt = 0; |
| rDocShell.UpdatePaintExt( nDestExt, nDestCol,nDestRow,nDestTab, nDestEndCol,nDestEndRow,nDestEndTab ); |
| |
| // |
| // ausfuehren |
| // |
| |
| ScDocument* pUndoDoc = NULL; |
| ScDocument* pRefUndoDoc = NULL; |
| ScRefUndoData* pUndoData = NULL; |
| if (bRecord) |
| { |
| sal_Bool bWholeCols = ( nStartRow == 0 && nEndRow == MAXROW ); |
| sal_Bool bWholeRows = ( nStartCol == 0 && nEndCol == MAXCOL ); |
| sal_uInt16 nUndoFlags = (IDF_ALL & ~IDF_OBJECTS) | IDF_NOCAPTIONS; |
| |
| pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); |
| pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab, bWholeCols, bWholeRows ); |
| |
| if (bCut) |
| { |
| pDoc->CopyToDocument( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab, |
| nUndoFlags, sal_False, pUndoDoc ); |
| pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO ); |
| pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, sal_False, sal_False ); |
| } |
| |
| if ( nDestTab != nStartTab ) |
| pUndoDoc->AddUndoTab( nDestTab, nDestEndTab, bWholeCols, bWholeRows ); |
| pDoc->CopyToDocument( nDestCol, nDestRow, nDestTab, |
| nDestEndCol, nDestEndRow, nDestEndTab, |
| nUndoFlags, sal_False, pUndoDoc ); |
| |
| pUndoData = new ScRefUndoData( pDoc ); |
| |
| pDoc->BeginDrawUndo(); |
| } |
| |
| sal_Bool bSourceHeight = sal_False; // Hoehen angepasst? |
| if (bCut) |
| { |
| ScMarkData aDelMark; // only for tables |
| for (nTab=nStartTab; nTab<=nEndTab; nTab++) |
| { |
| pDoc->DeleteAreaTab( nStartCol,nStartRow, nOldEndCol,nOldEndRow, nTab, IDF_ALL ); |
| aDelMark.SelectTable( nTab, sal_True ); |
| } |
| pDoc->DeleteObjectsInArea( nStartCol,nStartRow, nOldEndCol,nOldEndRow, aDelMark ); |
| |
| // Test auf zusammengefasste |
| |
| if (bClipOver) |
| if (pDoc->HasAttrib( nDestCol,nDestRow,nDestTab, |
| nUndoEndCol,nUndoEndRow,nDestEndTab, |
| HASATTR_MERGED | HASATTR_OVERLAPPED )) |
| { |
| pDoc->CopyFromClip( rSource, aSourceMark, IDF_ALL, pRefUndoDoc, pClipDoc ); |
| for (nTab=nStartTab; nTab<=nEndTab; nTab++) |
| { |
| SCCOL nTmpEndCol = nEndCol; |
| SCROW nTmpEndRow = nEndRow; |
| pDoc->ExtendMerge( nStartCol, nStartRow, nTmpEndCol, nTmpEndRow, nTab, sal_True ); |
| } |
| |
| // Fehlermeldung erst nach dem Wiederherstellen des Inhalts |
| if (!bApi) // "Zusammenfassen nicht verschachteln !" |
| rDocShell.ErrorMessage(STR_MSSG_MOVEBLOCKTO_0); |
| |
| delete pUndoDoc; |
| delete pRefUndoDoc; |
| delete pUndoData; |
| delete pClipDoc; |
| return sal_False; |
| } |
| |
| bSourceHeight = AdjustRowHeight( rSource, sal_False ); |
| } |
| |
| ScRange aPasteDest( nDestCol, nDestRow, nDestTab, nDestEndCol, nDestEndRow, nDestEndTab ); |
| |
| ScMarkData aDestMark; |
| for (nTab=nDestTab; nTab<=nDestEndTab; nTab++) |
| aDestMark.SelectTable( nTab, sal_True ); // Destination selektieren |
| aDestMark.SetMarkArea( aPasteDest ); |
| |
| /* Do not copy cell notes and drawing objects here. While pasting, the |
| function ScDocument::UpdateReference() is called which calls |
| ScDrawLayer::MoveCells() which may move away inserted objects to wrong |
| positions (e.g. if source and destination range overlaps). Cell notes |
| and drawing objects are pasted below after doing all adjusting. */ |
| pDoc->CopyFromClip( aPasteDest, aDestMark, IDF_ALL & ~(IDF_NOTE | IDF_OBJECTS), |
| pRefUndoDoc, pClipDoc, sal_True, sal_False, bIncludeFiltered ); |
| |
| // skipped rows and merged cells don't mix |
| if ( !bIncludeFiltered && pClipDoc->HasClipFilteredRows() ) |
| UnmergeCells( aPasteDest, sal_False, sal_True ); |
| |
| VirtualDevice aVirtDev; |
| sal_Bool bDestHeight = AdjustRowHeight( |
| ScRange( 0,nDestRow,nDestTab, MAXCOL,nDestEndRow,nDestEndTab ), |
| sal_False ); |
| |
| /* Paste cell notes and drawing objects after adjusting formula references |
| and row heights. There are no cell notes or drawing objects, if the |
| clipdoc does not contain a drawing layer. |
| #i102056# Passing IDF_NOTE only would overwrite cell contents with |
| empty note cells, therefore the special modifier IDF_ADDNOTES is passed |
| here too which changes the behaviour of ScColumn::CopyFromClip() to not |
| touch existing cells. */ |
| if ( pClipDoc->GetDrawLayer() ) |
| pDoc->CopyFromClip( aPasteDest, aDestMark, IDF_NOTE | IDF_ADDNOTES | IDF_OBJECTS, |
| pRefUndoDoc, pClipDoc, sal_True, sal_False, bIncludeFiltered ); |
| |
| if (bRecord) |
| { |
| if (pRefUndoDoc) |
| { |
| // alle Tabellen anlegen, damit Formeln kopiert werden koennen: |
| pUndoDoc->AddUndoTab( 0, nTabCount-1, sal_False, sal_False ); |
| |
| pRefUndoDoc->DeleteArea( nDestCol, nDestRow, nDestEndCol, nDestEndRow, aSourceMark, IDF_ALL ); |
| // kopieren mit bColRowFlags=sal_False (#54194#) |
| pRefUndoDoc->CopyToDocument( 0, 0, 0, MAXCOL, MAXROW, MAXTAB, |
| IDF_FORMULA, sal_False, pUndoDoc, NULL, sal_False ); |
| delete pRefUndoDoc; |
| } |
| |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoDragDrop( &rDocShell, ScRange( |
| nStartCol, nStartRow, nStartTab, |
| nOldEndCol, nOldEndRow, nEndTab ), |
| ScAddress( nDestCol, nDestRow, nDestTab ), |
| bCut, pUndoDoc, pUndoData, bScenariosAdded ) ); |
| } |
| |
| SCCOL nDestPaintEndCol = nDestEndCol; |
| SCROW nDestPaintEndRow = nDestEndRow; |
| for (nTab=nDestTab; nTab<=nDestEndTab; nTab++) |
| { |
| SCCOL nTmpEndCol = nDestEndCol; |
| SCROW nTmpEndRow = nDestEndRow; |
| pDoc->ExtendMerge( nDestCol, nDestRow, nTmpEndCol, nTmpEndRow, nTab, sal_True ); |
| if (nTmpEndCol > nDestPaintEndCol) nDestPaintEndCol = nTmpEndCol; |
| if (nTmpEndRow > nDestPaintEndRow) nDestPaintEndRow = nTmpEndRow; |
| } |
| |
| if (bCut) |
| for (nTab=nStartTab; nTab<=nEndTab; nTab++) |
| pDoc->RefreshAutoFilter( nStartCol, nStartRow, nEndCol, nEndRow, nTab ); |
| |
| if (bPaint) |
| { |
| // Zielbereich: |
| |
| SCCOL nPaintStartX = nDestCol; |
| SCROW nPaintStartY = nDestRow; |
| SCCOL nPaintEndX = nDestPaintEndCol; |
| SCROW nPaintEndY = nDestPaintEndRow; |
| sal_uInt16 nFlags = PAINT_GRID; |
| |
| if ( nStartRow==0 && nEndRow==MAXROW ) // Breiten mitkopiert? |
| { |
| nPaintEndX = MAXCOL; |
| nPaintStartY = 0; |
| nPaintEndY = MAXROW; |
| nFlags |= PAINT_TOP; |
| } |
| if ( bDestHeight || ( nStartCol == 0 && nEndCol == MAXCOL ) ) |
| { |
| nPaintEndY = MAXROW; |
| nPaintStartX = 0; |
| nPaintEndX = MAXCOL; |
| nFlags |= PAINT_LEFT; |
| } |
| if ( bScenariosAdded ) |
| { |
| nPaintStartX = 0; |
| nPaintStartY = 0; |
| nPaintEndX = MAXCOL; |
| nPaintEndY = MAXROW; |
| } |
| |
| rDocShell.PostPaint( nPaintStartX,nPaintStartY,nDestTab, |
| nPaintEndX,nPaintEndY,nDestEndTab, nFlags, nSourceExt | nDestExt ); |
| |
| if ( bCut ) |
| { |
| // Quellbereich: |
| |
| nPaintStartX = nStartCol; |
| nPaintStartY = nStartRow; |
| nPaintEndX = nEndCol; |
| nPaintEndY = nEndRow; |
| nFlags = PAINT_GRID; |
| |
| if ( bSourceHeight ) |
| { |
| nPaintEndY = MAXROW; |
| nPaintStartX = 0; |
| nPaintEndX = MAXCOL; |
| nFlags |= PAINT_LEFT; |
| } |
| if ( bScenariosAdded ) |
| { |
| nPaintStartX = 0; |
| nPaintStartY = 0; |
| nPaintEndX = MAXCOL; |
| nPaintEndY = MAXROW; |
| } |
| |
| rDocShell.PostPaint( nPaintStartX,nPaintStartY,nStartTab, |
| nPaintEndX,nPaintEndY,nEndTab, nFlags, nSourceExt ); |
| } |
| } |
| |
| aModificator.SetDocumentModified(); |
| |
| SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); |
| |
| delete pClipDoc; |
| return sal_True; |
| } |
| |
| //------------------------------------------------------------------------ |
| uno::Reference< uno::XInterface > GetDocModuleObject( SfxObjectShell& rDocSh, String& sCodeName ) |
| { |
| uno::Reference< lang::XMultiServiceFactory> xSF(rDocSh.GetModel(), uno::UNO_QUERY); |
| uno::Reference< container::XNameAccess > xVBACodeNamedObjectAccess; |
| uno::Reference< uno::XInterface > xDocModuleApiObject; |
| if ( xSF.is() ) |
| { |
| xVBACodeNamedObjectAccess.set( xSF->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAObjectModuleObjectProvider"))), uno::UNO_QUERY ); |
| xDocModuleApiObject.set( xVBACodeNamedObjectAccess->getByName( sCodeName ), uno::UNO_QUERY ); |
| } |
| return xDocModuleApiObject; |
| |
| } |
| |
| script::ModuleInfo lcl_InitModuleInfo( SfxObjectShell& rDocSh, String& sModule ) |
| { |
| script::ModuleInfo sModuleInfo; |
| sModuleInfo.ModuleType = script::ModuleType::DOCUMENT; |
| sModuleInfo.ModuleObject = GetDocModuleObject( rDocSh, sModule ); |
| return sModuleInfo; |
| } |
| |
| void VBA_InsertModule( ScDocument& rDoc, SCTAB nTab, String& sModuleName, String& sSource ) |
| { |
| SfxObjectShell& rDocSh = *rDoc.GetDocumentShell(); |
| uno::Reference< script::XLibraryContainer > xLibContainer = rDocSh.GetBasicContainer(); |
| DBG_ASSERT( xLibContainer.is(), "No BasicContainer!" ); |
| |
| uno::Reference< container::XNameContainer > xLib; |
| if( xLibContainer.is() ) |
| { |
| String aLibName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) ); |
| if ( rDocSh.GetBasicManager() && rDocSh.GetBasicManager()->GetName().Len() ) |
| aLibName = rDocSh.GetBasicManager()->GetName(); |
| uno::Any aLibAny = xLibContainer->getByName( aLibName ); |
| aLibAny >>= xLib; |
| } |
| if( xLib.is() ) |
| { |
| // if the Module with codename exists then find a new name |
| sal_Int32 nNum = 0; |
| String genModuleName; |
| if ( sModuleName.Len() ) |
| sModuleName = sModuleName; |
| else |
| { |
| genModuleName = String::CreateFromAscii( "Sheet1" ); |
| nNum = 1; |
| } |
| while( xLib->hasByName( genModuleName ) ) |
| genModuleName = rtl::OUString::createFromAscii( "Sheet" ) + rtl::OUString::valueOf( ++nNum ); |
| |
| uno::Any aSourceAny; |
| rtl::OUString sTmpSource = sSource; |
| if ( sTmpSource.getLength() == 0 ) |
| sTmpSource = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Rem Attribute VBA_ModuleType=VBADocumentModule\nOption VBASupport 1\n" )); |
| aSourceAny <<= sTmpSource; |
| uno::Reference< script::vba::XVBAModuleInfo > xVBAModuleInfo( xLib, uno::UNO_QUERY ); |
| if ( xVBAModuleInfo.is() ) |
| { |
| rDoc.SetCodeName( nTab, genModuleName ); |
| script::ModuleInfo sModuleInfo = lcl_InitModuleInfo( rDocSh, genModuleName ); |
| xVBAModuleInfo->insertModuleInfo( genModuleName, sModuleInfo ); |
| xLib->insertByName( genModuleName, aSourceAny ); |
| } |
| |
| } |
| } |
| |
| void VBA_DeleteModule( ScDocShell& rDocSh, String& sModuleName ) |
| { |
| uno::Reference< script::XLibraryContainer > xLibContainer = rDocSh.GetBasicContainer(); |
| DBG_ASSERT( xLibContainer.is(), "No BasicContainer!" ); |
| |
| uno::Reference< container::XNameContainer > xLib; |
| if( xLibContainer.is() ) |
| { |
| String aLibName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) ); |
| if ( rDocSh.GetBasicManager() && rDocSh.GetBasicManager()->GetName().Len() ) |
| aLibName = rDocSh.GetBasicManager()->GetName(); |
| uno::Any aLibAny = xLibContainer->getByName( aLibName ); |
| aLibAny >>= xLib; |
| } |
| if( xLib.is() ) |
| { |
| uno::Reference< script::vba::XVBAModuleInfo > xVBAModuleInfo( xLib, uno::UNO_QUERY ); |
| if( xLib->hasByName( sModuleName ) ) |
| xLib->removeByName( sModuleName ); |
| if ( xVBAModuleInfo.is() ) |
| xVBAModuleInfo->removeModuleInfo( sModuleName ); |
| |
| } |
| } |
| |
| |
| sal_Bool ScDocFunc::InsertTable( SCTAB nTab, const String& rName, sal_Bool bRecord, sal_Bool bApi ) |
| { |
| sal_Bool bSuccess = sal_False; |
| WaitObject aWait( rDocShell.GetActiveDialogParent() ); |
| |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| |
| |
| // Strange loop, also basic is loaded too early ( InsertTable ) |
| // is called via the xml import for sheets in described in odf |
| sal_Bool bInsertDocModule = false; |
| |
| if( !rDocShell.GetDocument()->IsImportingXML() ) |
| { |
| bInsertDocModule = pDoc ? pDoc->IsInVBAMode() : false; |
| } |
| if ( bInsertDocModule || ( bRecord && !pDoc->IsUndoEnabled() ) ) |
| bRecord = sal_False; |
| |
| if (bRecord) |
| pDoc->BeginDrawUndo(); // InsertTab erzeugt ein SdrUndoNewPage |
| |
| SCTAB nTabCount = pDoc->GetTableCount(); |
| sal_Bool bAppend = ( nTab >= nTabCount ); |
| if ( bAppend ) |
| nTab = nTabCount; // wichtig fuer Undo |
| |
| if (pDoc->InsertTab( nTab, rName )) |
| { |
| String sCodeName; |
| if (bRecord) |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoInsertTab( &rDocShell, nTab, bAppend, rName)); |
| // Views updaten: |
| // Only insert vba modules if vba mode ( and not currently importing XML ) |
| if( bInsertDocModule ) |
| { |
| String sSource; |
| VBA_InsertModule( *pDoc, nTab, sCodeName, sSource ); |
| } |
| rDocShell.Broadcast( ScTablesHint( SC_TAB_INSERTED, nTab ) ); |
| |
| rDocShell.PostPaintExtras(); |
| aModificator.SetDocumentModified(); |
| SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); |
| bSuccess = sal_True; |
| } |
| else if (!bApi) |
| rDocShell.ErrorMessage(STR_TABINSERT_ERROR); |
| |
| return bSuccess; |
| } |
| |
| sal_Bool ScDocFunc::DeleteTable( SCTAB nTab, sal_Bool bRecord, sal_Bool /* bApi */ ) |
| { |
| WaitObject aWait( rDocShell.GetActiveDialogParent() ); |
| |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| sal_Bool bSuccess = sal_False; |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| sal_Bool bVbaEnabled = pDoc ? pDoc->IsInVBAMode() : false; |
| if (bRecord && !pDoc->IsUndoEnabled()) |
| bRecord = sal_False; |
| if ( bVbaEnabled ) |
| bRecord = sal_False; |
| sal_Bool bWasLinked = pDoc->IsLinked(nTab); |
| ScDocument* pUndoDoc = NULL; |
| ScRefUndoData* pUndoData = NULL; |
| if (bRecord) |
| { |
| pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); |
| SCTAB nCount = pDoc->GetTableCount(); |
| |
| pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_True ); // nur nTab mit Flags |
| pUndoDoc->AddUndoTab( 0, nCount-1 ); // alle Tabs fuer Referenzen |
| |
| pDoc->CopyToDocument(0,0,nTab, MAXCOL,MAXROW,nTab, IDF_ALL,sal_False, pUndoDoc ); |
| String aOldName; |
| pDoc->GetName( nTab, aOldName ); |
| pUndoDoc->RenameTab( nTab, aOldName, sal_False ); |
| if (bWasLinked) |
| pUndoDoc->SetLink( nTab, pDoc->GetLinkMode(nTab), pDoc->GetLinkDoc(nTab), |
| pDoc->GetLinkFlt(nTab), pDoc->GetLinkOpt(nTab), |
| pDoc->GetLinkTab(nTab), |
| pDoc->GetLinkRefreshDelay(nTab) ); |
| |
| if ( pDoc->IsScenario(nTab) ) |
| { |
| pUndoDoc->SetScenario( nTab, sal_True ); |
| String aComment; |
| Color aColor; |
| sal_uInt16 nScenFlags; |
| pDoc->GetScenarioData( nTab, aComment, aColor, nScenFlags ); |
| pUndoDoc->SetScenarioData( nTab, aComment, aColor, nScenFlags ); |
| sal_Bool bActive = pDoc->IsActiveScenario( nTab ); |
| pUndoDoc->SetActiveScenario( nTab, bActive ); |
| } |
| pUndoDoc->SetVisible( nTab, pDoc->IsVisible( nTab ) ); |
| pUndoDoc->SetTabBgColor( nTab, pDoc->GetTabBgColor(nTab) ); |
| pUndoDoc->SetSheetEvents( nTab, pDoc->GetSheetEvents( nTab ) ); |
| |
| // Drawing-Layer muss sein Undo selbst in der Hand behalten !!! |
| pDoc->BeginDrawUndo(); // DeleteTab erzeugt ein SdrUndoDelPage |
| |
| pUndoData = new ScRefUndoData( pDoc ); |
| } |
| |
| String sCodeName; |
| sal_Bool bHasCodeName = pDoc->GetCodeName( nTab, sCodeName ); |
| if (pDoc->DeleteTab( nTab, pUndoDoc )) |
| { |
| if (bRecord) |
| { |
| SvShorts theTabs; |
| theTabs.push_back(nTab); |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoDeleteTab( &rDocShell, theTabs, pUndoDoc, pUndoData )); |
| } |
| // Views updaten: |
| if( bVbaEnabled ) |
| { |
| if( bHasCodeName ) |
| { |
| VBA_DeleteModule( rDocShell, sCodeName ); |
| } |
| } |
| rDocShell.Broadcast( ScTablesHint( SC_TAB_DELETED, nTab ) ); |
| |
| if (bWasLinked) |
| { |
| rDocShell.UpdateLinks(); // Link-Manager updaten |
| SfxBindings* pBindings = rDocShell.GetViewBindings(); |
| if (pBindings) |
| pBindings->Invalidate(SID_LINKS); |
| } |
| |
| rDocShell.PostPaintExtras(); |
| aModificator.SetDocumentModified(); |
| |
| SfxApplication* pSfxApp = SFX_APP(); // Navigator |
| pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); |
| pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) ); |
| pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); |
| |
| bSuccess = sal_True; |
| } |
| else |
| { |
| delete pUndoDoc; |
| delete pUndoData; |
| } |
| return bSuccess; |
| } |
| |
| sal_Bool ScDocFunc::SetTableVisible( SCTAB nTab, sal_Bool bVisible, sal_Bool bApi ) |
| { |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| sal_Bool bUndo(pDoc->IsUndoEnabled()); |
| if ( pDoc->IsVisible( nTab ) == bVisible ) |
| return sal_True; // nichts zu tun - ok |
| |
| if ( !pDoc->IsDocEditable() ) |
| { |
| if (!bApi) |
| rDocShell.ErrorMessage(STR_PROTECTIONERR); |
| return sal_False; |
| } |
| |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| if ( !bVisible && !pDoc->IsImportingXML() ) // #i57869# allow hiding in any order for loading |
| { |
| // nicht alle Tabellen ausblenden |
| |
| sal_uInt16 nVisCount = 0; |
| SCTAB nCount = pDoc->GetTableCount(); |
| for (SCTAB i=0; i<nCount; i++) |
| if (pDoc->IsVisible(i)) |
| ++nVisCount; |
| |
| if (nVisCount <= 1) |
| { |
| if (!bApi) |
| rDocShell.ErrorMessage(STR_PROTECTIONERR); //! eigene Meldung? |
| return sal_False; |
| } |
| } |
| |
| pDoc->SetVisible( nTab, bVisible ); |
| if (bUndo) |
| rDocShell.GetUndoManager()->AddUndoAction( new ScUndoShowHideTab( &rDocShell, nTab, bVisible ) ); |
| |
| // Views updaten: |
| if (!bVisible) |
| rDocShell.Broadcast( ScTablesHint( SC_TAB_HIDDEN, nTab ) ); |
| |
| SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); |
| rDocShell.PostPaint(0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_EXTRAS); |
| aModificator.SetDocumentModified(); |
| |
| return sal_True; |
| } |
| |
| sal_Bool ScDocFunc::SetLayoutRTL( SCTAB nTab, sal_Bool bRTL, sal_Bool /* bApi */ ) |
| { |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| sal_Bool bUndo(pDoc->IsUndoEnabled()); |
| if ( pDoc->IsLayoutRTL( nTab ) == bRTL ) |
| return sal_True; // nothing to do - ok |
| |
| //! protection (sheet or document?) |
| |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| pDoc->SetLayoutRTL( nTab, bRTL ); |
| |
| if (bUndo) |
| { |
| rDocShell.GetUndoManager()->AddUndoAction( new ScUndoLayoutRTL( &rDocShell, nTab, bRTL ) ); |
| } |
| |
| rDocShell.PostPaint( 0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_ALL ); |
| aModificator.SetDocumentModified(); |
| |
| SfxBindings* pBindings = rDocShell.GetViewBindings(); |
| if (pBindings) |
| { |
| pBindings->Invalidate( FID_TAB_RTL ); |
| pBindings->Invalidate( SID_ATTR_SIZE ); |
| } |
| |
| return sal_True; |
| } |
| |
| //UNUSED2009-05 sal_Bool ScDocFunc::SetGrammar( formula::FormulaGrammar::Grammar eGrammar ) |
| //UNUSED2009-05 { |
| //UNUSED2009-05 ScDocument* pDoc = rDocShell.GetDocument(); |
| //UNUSED2009-05 |
| //UNUSED2009-05 if ( pDoc->GetGrammar() == eGrammar ) |
| //UNUSED2009-05 return sal_True; |
| //UNUSED2009-05 |
| //UNUSED2009-05 sal_Bool bUndo(pDoc->IsUndoEnabled()); |
| //UNUSED2009-05 ScDocShellModificator aModificator( rDocShell ); |
| //UNUSED2009-05 |
| //UNUSED2009-05 pDoc->SetGrammar( eGrammar ); |
| //UNUSED2009-05 |
| //UNUSED2009-05 if (bUndo) |
| //UNUSED2009-05 { |
| //UNUSED2009-05 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoSetGrammar( &rDocShell, eGrammar ) ); |
| //UNUSED2009-05 } |
| //UNUSED2009-05 |
| //UNUSED2009-05 rDocShell.PostPaint( 0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_ALL ); |
| //UNUSED2009-05 |
| //UNUSED2009-05 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell(); |
| //UNUSED2009-05 if (NULL != pViewSh) |
| //UNUSED2009-05 { |
| //UNUSED2009-05 pViewSh->UpdateInputHandler( sal_False, sal_False ); |
| //UNUSED2009-05 } |
| //UNUSED2009-05 |
| //UNUSED2009-05 aModificator.SetDocumentModified(); |
| //UNUSED2009-05 |
| //UNUSED2009-05 SfxBindings* pBindings = rDocShell.GetViewBindings(); |
| //UNUSED2009-05 if (pBindings) |
| //UNUSED2009-05 { |
| //UNUSED2009-05 // erAck: 2006-09-07T22:19+0200 commented out in CWS scr1c1 |
| //UNUSED2009-05 //pBindings->Invalidate( FID_TAB_USE_R1C1 ); |
| //UNUSED2009-05 } |
| //UNUSED2009-05 |
| //UNUSED2009-05 return sal_True; |
| //UNUSED2009-05 } |
| |
| sal_Bool ScDocFunc::RenameTable( SCTAB nTab, const String& rName, sal_Bool bRecord, sal_Bool bApi ) |
| { |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| if (bRecord && !pDoc->IsUndoEnabled()) |
| bRecord = sal_False; |
| if ( !pDoc->IsDocEditable() ) |
| { |
| if (!bApi) |
| rDocShell.ErrorMessage(STR_PROTECTIONERR); |
| return sal_False; |
| } |
| |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| sal_Bool bSuccess = sal_False; |
| String sOldName; |
| pDoc->GetName(nTab, sOldName); |
| if (pDoc->RenameTab( nTab, rName )) |
| { |
| if (bRecord) |
| { |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoRenameTab( &rDocShell, nTab, sOldName, rName)); |
| } |
| rDocShell.PostPaintExtras(); |
| aModificator.SetDocumentModified(); |
| SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); |
| |
| bSuccess = sal_True; |
| } |
| return bSuccess; |
| } |
| |
| bool ScDocFunc::SetTabBgColor( SCTAB nTab, const Color& rColor, bool bRecord, bool bApi ) |
| { |
| |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| if (bRecord && !pDoc->IsUndoEnabled()) |
| bRecord = false; |
| if ( !pDoc->IsDocEditable() || pDoc->IsTabProtected(nTab) ) |
| { |
| if (!bApi) |
| rDocShell.ErrorMessage(STR_PROTECTIONERR); //TODO Check to see what this string is... |
| return false; |
| } |
| |
| Color aOldTabBgColor; |
| aOldTabBgColor = pDoc->GetTabBgColor(nTab); |
| |
| bool bSuccess = false; |
| pDoc->SetTabBgColor(nTab, rColor); |
| if ( pDoc->GetTabBgColor(nTab) == rColor) |
| bSuccess = true; |
| if (bSuccess) |
| { |
| if (bRecord) |
| { |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoTabColor( &rDocShell, nTab, aOldTabBgColor, rColor)); |
| } |
| rDocShell.PostPaintExtras(); |
| ScDocShellModificator aModificator( rDocShell ); |
| aModificator.SetDocumentModified(); |
| SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); |
| |
| bSuccess = true; |
| } |
| return bSuccess; |
| } |
| |
| bool ScDocFunc::SetTabBgColor( |
| ScUndoTabColorInfo::List& rUndoTabColorList, bool bRecord, bool bApi ) |
| { |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| if (bRecord && !pDoc->IsUndoEnabled()) |
| bRecord = false; |
| |
| if ( !pDoc->IsDocEditable() ) |
| { |
| if (!bApi) |
| rDocShell.ErrorMessage(STR_PROTECTIONERR); //TODO Get a better String Error... |
| return false; |
| } |
| |
| sal_uInt16 nTab; |
| Color aNewTabBgColor; |
| bool bSuccess = true; |
| size_t nTabProtectCount = 0; |
| size_t nTabListCount = rUndoTabColorList.size(); |
| for ( size_t i = 0; i < nTabListCount; ++i ) |
| { |
| ScUndoTabColorInfo& rInfo = rUndoTabColorList[i]; |
| nTab = rInfo.mnTabId; |
| if ( !pDoc->IsTabProtected(nTab) ) |
| { |
| aNewTabBgColor = rInfo.maNewTabBgColor; |
| rInfo.maOldTabBgColor = pDoc->GetTabBgColor(nTab); |
| pDoc->SetTabBgColor(nTab, aNewTabBgColor); |
| if ( pDoc->GetTabBgColor(nTab) != aNewTabBgColor) |
| { |
| bSuccess = false; |
| break; |
| } |
| } |
| else |
| { |
| nTabProtectCount++; |
| } |
| } |
| |
| if ( nTabProtectCount == nTabListCount ) |
| { |
| if (!bApi) |
| rDocShell.ErrorMessage(STR_PROTECTIONERR); //TODO Get a better String Error... |
| return false; |
| } |
| |
| if (bSuccess) |
| { |
| if (bRecord) |
| { |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoTabColor( &rDocShell, rUndoTabColorList)); |
| } |
| rDocShell.PostPaintExtras(); |
| ScDocShellModificator aModificator( rDocShell ); |
| aModificator.SetDocumentModified(); |
| } |
| return bSuccess; |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| //! SetWidthOrHeight - noch doppelt zu ViewFunc !!!!!! |
| //! Probleme: |
| //! - Optimale Hoehe fuer Edit-Zellen ist unterschiedlich zwischen Drucker und Bildschirm |
| //! - Optimale Breite braucht Selektion, um evtl. nur selektierte Zellen zu beruecksichtigen |
| |
| sal_uInt16 lcl_GetOptimalColWidth( ScDocShell& rDocShell, SCCOL nCol, SCTAB nTab, sal_Bool bFormula ) |
| { |
| sal_uInt16 nTwips = 0; |
| |
| ScSizeDeviceProvider aProv(&rDocShell); |
| OutputDevice* pDev = aProv.GetDevice(); // has pixel MapMode |
| double nPPTX = aProv.GetPPTX(); |
| double nPPTY = aProv.GetPPTY(); |
| |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| Fraction aOne(1,1); |
| nTwips = pDoc->GetOptimalColWidth( nCol, nTab, pDev, nPPTX, nPPTY, aOne, aOne, |
| bFormula, NULL ); |
| |
| return nTwips; |
| } |
| |
| sal_Bool ScDocFunc::SetWidthOrHeight( sal_Bool bWidth, SCCOLROW nRangeCnt, SCCOLROW* pRanges, SCTAB nTab, |
| ScSizeMode eMode, sal_uInt16 nSizeTwips, |
| sal_Bool bRecord, sal_Bool bApi ) |
| { |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| if (!nRangeCnt) |
| return sal_True; |
| |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| if ( bRecord && !pDoc->IsUndoEnabled() ) |
| bRecord = sal_False; |
| |
| // import into read-only document is possible |
| if ( !pDoc->IsChangeReadOnlyEnabled() && !rDocShell.IsEditable() ) |
| { |
| if (!bApi) |
| rDocShell.ErrorMessage(STR_PROTECTIONERR); //! eigene Meldung? |
| return sal_False; |
| } |
| |
| sal_Bool bSuccess = sal_False; |
| SCCOLROW nStart = pRanges[0]; |
| SCCOLROW nEnd = pRanges[2*nRangeCnt-1]; |
| |
| sal_Bool bFormula = sal_False; |
| if ( eMode == SC_SIZE_OPTIMAL ) |
| { |
| //! Option "Formeln anzeigen" - woher nehmen? |
| } |
| |
| ScDocument* pUndoDoc = NULL; |
| ScOutlineTable* pUndoTab = NULL; |
| SCCOLROW* pUndoRanges = NULL; |
| |
| if ( bRecord ) |
| { |
| pDoc->BeginDrawUndo(); // Drawing Updates |
| |
| pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); |
| if (bWidth) |
| { |
| pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_False ); |
| pDoc->CopyToDocument( static_cast<SCCOL>(nStart), 0, nTab, static_cast<SCCOL>(nEnd), MAXROW, nTab, IDF_NONE, sal_False, pUndoDoc ); |
| } |
| else |
| { |
| pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_False, sal_True ); |
| pDoc->CopyToDocument( 0, static_cast<SCROW>(nStart), nTab, MAXCOL, static_cast<SCROW>(nEnd), nTab, IDF_NONE, sal_False, pUndoDoc ); |
| } |
| |
| pUndoRanges = new SCCOLROW[ 2*nRangeCnt ]; |
| memmove( pUndoRanges, pRanges, 2*nRangeCnt*sizeof(SCCOLROW) ); |
| |
| ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab ); |
| if (pTable) |
| pUndoTab = new ScOutlineTable( *pTable ); |
| } |
| |
| sal_Bool bShow = nSizeTwips > 0 || eMode != SC_SIZE_DIRECT; |
| sal_Bool bOutline = sal_False; |
| |
| pDoc->IncSizeRecalcLevel( nTab ); // nicht fuer jede Spalte einzeln |
| for (SCCOLROW nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++) |
| { |
| SCCOLROW nStartNo = *(pRanges++); |
| SCCOLROW nEndNo = *(pRanges++); |
| |
| if ( !bWidth ) // Hoehen immer blockweise |
| { |
| if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT ) |
| { |
| sal_Bool bAll = ( eMode==SC_SIZE_OPTIMAL ); |
| if (!bAll) |
| { |
| // fuer alle eingeblendeten CR_MANUALSIZE loeschen, |
| // dann SetOptimalHeight mit bShrink = FALSE |
| for (SCROW nRow=nStartNo; nRow<=nEndNo; nRow++) |
| { |
| sal_uInt8 nOld = pDoc->GetRowFlags(nRow,nTab); |
| SCROW nLastRow = -1; |
| bool bHidden = pDoc->RowHidden(nRow, nTab, nLastRow); |
| if ( !bHidden && ( nOld & CR_MANUALSIZE ) ) |
| pDoc->SetRowFlags( nRow, nTab, nOld & ~CR_MANUALSIZE ); |
| } |
| } |
| |
| ScSizeDeviceProvider aProv( &rDocShell ); |
| Fraction aOne(1,1); |
| pDoc->SetOptimalHeight( nStartNo, nEndNo, nTab, 0, aProv.GetDevice(), |
| aProv.GetPPTX(), aProv.GetPPTY(), aOne, aOne, bAll ); |
| |
| if (bAll) |
| pDoc->ShowRows( nStartNo, nEndNo, nTab, sal_True ); |
| |
| // Manual-Flag wird bei bAll=sal_True schon in SetOptimalHeight gesetzt |
| // (an bei Extra-Height, sonst aus). |
| } |
| else if ( eMode==SC_SIZE_DIRECT || eMode==SC_SIZE_ORIGINAL ) |
| { |
| if (nSizeTwips) |
| { |
| pDoc->SetRowHeightRange( nStartNo, nEndNo, nTab, nSizeTwips ); |
| pDoc->SetManualHeight( nStartNo, nEndNo, nTab, sal_True ); // height was set manually |
| } |
| if ( eMode != SC_SIZE_ORIGINAL ) |
| pDoc->ShowRows( nStartNo, nEndNo, nTab, nSizeTwips != 0 ); |
| } |
| else if ( eMode==SC_SIZE_SHOW ) |
| { |
| pDoc->ShowRows( nStartNo, nEndNo, nTab, sal_True ); |
| } |
| } |
| else // Spaltenbreiten |
| { |
| for (SCCOL nCol=static_cast<SCCOL>(nStartNo); nCol<=static_cast<SCCOL>(nEndNo); nCol++) |
| { |
| SCCOL nLastCol = -1; |
| if ( eMode != SC_SIZE_VISOPT || !pDoc->ColHidden(nCol, nTab, nLastCol) ) |
| { |
| sal_uInt16 nThisSize = nSizeTwips; |
| |
| if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT ) |
| nThisSize = nSizeTwips + |
| lcl_GetOptimalColWidth( rDocShell, nCol, nTab, bFormula ); |
| if ( nThisSize ) |
| pDoc->SetColWidth( nCol, nTab, nThisSize ); |
| |
| if ( eMode != SC_SIZE_ORIGINAL ) |
| pDoc->ShowCol( nCol, nTab, bShow ); |
| } |
| } |
| } |
| |
| // adjust outlines |
| |
| if ( eMode != SC_SIZE_ORIGINAL ) |
| { |
| if (bWidth) |
| bOutline = bOutline || pDoc->UpdateOutlineCol( |
| static_cast<SCCOL>(nStartNo), |
| static_cast<SCCOL>(nEndNo), nTab, bShow ); |
| else |
| bOutline = bOutline || pDoc->UpdateOutlineRow( |
| static_cast<SCROW>(nStartNo), |
| static_cast<SCROW>(nEndNo), nTab, bShow ); |
| } |
| } |
| pDoc->DecSizeRecalcLevel( nTab ); // nicht fuer jede Spalte einzeln |
| |
| if (!bOutline) |
| DELETEZ(pUndoTab); |
| |
| if (bRecord) |
| { |
| ScMarkData aMark; |
| aMark.SelectOneTable( nTab ); |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoWidthOrHeight( &rDocShell, aMark, |
| nStart, nTab, nEnd, nTab, |
| pUndoDoc, nRangeCnt, pUndoRanges, |
| pUndoTab, eMode, nSizeTwips, bWidth ) ); |
| } |
| |
| pDoc->UpdatePageBreaks( nTab ); |
| |
| rDocShell.PostPaint(0,0,nTab,MAXCOL,MAXROW,nTab,PAINT_ALL); |
| aModificator.SetDocumentModified(); |
| |
| return bSuccess; |
| } |
| |
| |
| sal_Bool ScDocFunc::InsertPageBreak( sal_Bool bColumn, const ScAddress& rPos, |
| sal_Bool bRecord, sal_Bool bSetModified, sal_Bool /* bApi */ ) |
| { |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| if (bRecord && !pDoc->IsUndoEnabled()) |
| bRecord = sal_False; |
| SCTAB nTab = rPos.Tab(); |
| SfxBindings* pBindings = rDocShell.GetViewBindings(); |
| |
| SCCOLROW nPos = bColumn ? static_cast<SCCOLROW>(rPos.Col()) : |
| static_cast<SCCOLROW>(rPos.Row()); |
| if (nPos == 0) |
| return sal_False; // erste Spalte / Zeile |
| |
| ScBreakType nBreak = bColumn ? |
| pDoc->HasColBreak(static_cast<SCCOL>(nPos), nTab) : |
| pDoc->HasRowBreak(static_cast<SCROW>(nPos), nTab); |
| if (nBreak & BREAK_MANUAL) |
| return true; |
| |
| if (bRecord) |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoPageBreak( &rDocShell, rPos.Col(), rPos.Row(), nTab, bColumn, sal_True ) ); |
| |
| if (bColumn) |
| pDoc->SetColBreak(static_cast<SCCOL>(nPos), nTab, false, true); |
| else |
| pDoc->SetRowBreak(static_cast<SCROW>(nPos), nTab, false, true); |
| |
| pDoc->InvalidatePageBreaks(nTab); |
| pDoc->UpdatePageBreaks( nTab ); |
| |
| if (pDoc->IsStreamValid(nTab)) |
| pDoc->SetStreamValid(nTab, sal_False); |
| |
| if (bColumn) |
| { |
| rDocShell.PostPaint( static_cast<SCCOL>(nPos)-1, 0, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID ); |
| if (pBindings) |
| { |
| pBindings->Invalidate( FID_INS_COLBRK ); |
| pBindings->Invalidate( FID_DEL_COLBRK ); |
| } |
| } |
| else |
| { |
| rDocShell.PostPaint( 0, static_cast<SCROW>(nPos)-1, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID ); |
| if (pBindings) |
| { |
| pBindings->Invalidate( FID_INS_ROWBRK ); |
| pBindings->Invalidate( FID_DEL_ROWBRK ); |
| } |
| } |
| if (pBindings) |
| pBindings->Invalidate( FID_DEL_MANUALBREAKS ); |
| |
| if (bSetModified) |
| aModificator.SetDocumentModified(); |
| |
| return sal_True; |
| } |
| |
| sal_Bool ScDocFunc::RemovePageBreak( sal_Bool bColumn, const ScAddress& rPos, |
| sal_Bool bRecord, sal_Bool bSetModified, sal_Bool /* bApi */ ) |
| { |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| if (bRecord && !pDoc->IsUndoEnabled()) |
| bRecord = sal_False; |
| SCTAB nTab = rPos.Tab(); |
| SfxBindings* pBindings = rDocShell.GetViewBindings(); |
| |
| SCCOLROW nPos = bColumn ? static_cast<SCCOLROW>(rPos.Col()) : |
| static_cast<SCCOLROW>(rPos.Row()); |
| |
| ScBreakType nBreak; |
| if (bColumn) |
| nBreak = pDoc->HasColBreak(static_cast<SCCOL>(nPos), nTab); |
| else |
| nBreak = pDoc->HasRowBreak(static_cast<SCROW>(nPos), nTab); |
| if ((nBreak & BREAK_MANUAL) == 0) |
| // There is no manual break. |
| return false; |
| |
| if (bRecord) |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoPageBreak( &rDocShell, rPos.Col(), rPos.Row(), nTab, bColumn, sal_False ) ); |
| |
| if (bColumn) |
| pDoc->RemoveColBreak(static_cast<SCCOL>(nPos), nTab, false, true); |
| else |
| pDoc->RemoveRowBreak(static_cast<SCROW>(nPos), nTab, false, true); |
| |
| pDoc->UpdatePageBreaks( nTab ); |
| |
| if (pDoc->IsStreamValid(nTab)) |
| pDoc->SetStreamValid(nTab, sal_False); |
| |
| if (bColumn) |
| { |
| rDocShell.PostPaint( static_cast<SCCOL>(nPos)-1, 0, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID ); |
| if (pBindings) |
| { |
| pBindings->Invalidate( FID_INS_COLBRK ); |
| pBindings->Invalidate( FID_DEL_COLBRK ); |
| } |
| } |
| else |
| { |
| rDocShell.PostPaint( 0, nPos-1, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID ); |
| if (pBindings) |
| { |
| pBindings->Invalidate( FID_INS_ROWBRK ); |
| pBindings->Invalidate( FID_DEL_ROWBRK ); |
| } |
| } |
| if (pBindings) |
| pBindings->Invalidate( FID_DEL_MANUALBREAKS ); |
| |
| if (bSetModified) |
| aModificator.SetDocumentModified(); |
| |
| return sal_True; |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| void ScDocFunc::ProtectSheet( SCTAB nTab, const ScTableProtection& rProtect ) |
| { |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| |
| pDoc->SetTabProtection(nTab, &rProtect); |
| if (pDoc->IsUndoEnabled()) |
| { |
| ScTableProtection* pProtect = pDoc->GetTabProtection(nTab); |
| DBG_ASSERT(pProtect, "ScDocFunc::Unprotect: ScTableProtection pointer is NULL!"); |
| if (pProtect) |
| { |
| ::std::auto_ptr<ScTableProtection> p(new ScTableProtection(*pProtect)); |
| p->setProtected(true); // just in case ... |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoTabProtect(&rDocShell, nTab, p) ); |
| |
| // ownership of auto_ptr now transferred to ScUndoTabProtect. |
| } |
| } |
| |
| rDocShell.PostPaintGridAll(); |
| ScDocShellModificator aModificator(rDocShell); |
| aModificator.SetDocumentModified(); |
| } |
| |
| sal_Bool ScDocFunc::Protect( SCTAB nTab, const String& rPassword, sal_Bool /*bApi*/ ) |
| { |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| if (nTab == TABLEID_DOC) |
| { |
| // document protection |
| ScDocProtection aProtection; |
| aProtection.setProtected(true); |
| aProtection.setPassword(rPassword); |
| pDoc->SetDocProtection(&aProtection); |
| if (pDoc->IsUndoEnabled()) |
| { |
| ScDocProtection* pProtect = pDoc->GetDocProtection(); |
| DBG_ASSERT(pProtect, "ScDocFunc::Unprotect: ScDocProtection pointer is NULL!"); |
| if (pProtect) |
| { |
| ::std::auto_ptr<ScDocProtection> p(new ScDocProtection(*pProtect)); |
| p->setProtected(true); // just in case ... |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoDocProtect(&rDocShell, p) ); |
| // ownership of auto_ptr is transferred to ScUndoDocProtect. |
| } |
| } |
| } |
| else |
| { |
| // sheet protection |
| |
| ScTableProtection aProtection; |
| aProtection.setProtected(true); |
| aProtection.setPassword(rPassword); |
| pDoc->SetTabProtection(nTab, &aProtection); |
| if (pDoc->IsUndoEnabled()) |
| { |
| ScTableProtection* pProtect = pDoc->GetTabProtection(nTab); |
| DBG_ASSERT(pProtect, "ScDocFunc::Unprotect: ScTableProtection pointer is NULL!"); |
| if (pProtect) |
| { |
| ::std::auto_ptr<ScTableProtection> p(new ScTableProtection(*pProtect)); |
| p->setProtected(true); // just in case ... |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoTabProtect(&rDocShell, nTab, p) ); |
| // ownership of auto_ptr now transferred to ScUndoTabProtect. |
| } |
| } |
| } |
| |
| rDocShell.PostPaintGridAll(); |
| ScDocShellModificator aModificator( rDocShell ); |
| aModificator.SetDocumentModified(); |
| |
| return true; |
| } |
| |
| sal_Bool ScDocFunc::Unprotect( SCTAB nTab, const String& rPassword, sal_Bool bApi ) |
| { |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| |
| if (nTab == TABLEID_DOC) |
| { |
| // document protection |
| |
| ScDocProtection* pDocProtect = pDoc->GetDocProtection(); |
| if (!pDocProtect || !pDocProtect->isProtected()) |
| // already unprotected (should not happen)! |
| return true; |
| |
| // save the protection state before unprotect (for undo). |
| ::std::auto_ptr<ScDocProtection> pProtectCopy(new ScDocProtection(*pDocProtect)); |
| |
| if (!pDocProtect->verifyPassword(rPassword)) |
| { |
| if (!bApi) |
| { |
| InfoBox aBox( rDocShell.GetActiveDialogParent(), String( ScResId( SCSTR_WRONGPASSWORD ) ) ); |
| aBox.Execute(); |
| } |
| return false; |
| } |
| |
| pDoc->SetDocProtection(NULL); |
| if (pDoc->IsUndoEnabled()) |
| { |
| pProtectCopy->setProtected(false); |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoDocProtect(&rDocShell, pProtectCopy) ); |
| // ownership of auto_ptr now transferred to ScUndoDocProtect. |
| } |
| } |
| else |
| { |
| // sheet protection |
| |
| ScTableProtection* pTabProtect = pDoc->GetTabProtection(nTab); |
| if (!pTabProtect || !pTabProtect->isProtected()) |
| // already unprotected (should not happen)! |
| return true; |
| |
| // save the protection state before unprotect (for undo). |
| ::std::auto_ptr<ScTableProtection> pProtectCopy(new ScTableProtection(*pTabProtect)); |
| if (!pTabProtect->verifyPassword(rPassword)) |
| { |
| if (!bApi) |
| { |
| InfoBox aBox( rDocShell.GetActiveDialogParent(), String( ScResId( SCSTR_WRONGPASSWORD ) ) ); |
| aBox.Execute(); |
| } |
| return false; |
| } |
| |
| pDoc->SetTabProtection(nTab, NULL); |
| if (pDoc->IsUndoEnabled()) |
| { |
| pProtectCopy->setProtected(false); |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoTabProtect(&rDocShell, nTab, pProtectCopy) ); |
| // ownership of auto_ptr now transferred to ScUndoTabProtect. |
| } |
| } |
| |
| rDocShell.PostPaintGridAll(); |
| ScDocShellModificator aModificator( rDocShell ); |
| aModificator.SetDocumentModified(); |
| |
| return true; |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| sal_Bool ScDocFunc::ClearItems( const ScMarkData& rMark, const sal_uInt16* pWhich, sal_Bool bApi ) |
| { |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| sal_Bool bUndo (pDoc->IsUndoEnabled()); |
| ScEditableTester aTester( pDoc, rMark ); |
| if (!aTester.IsEditable()) |
| { |
| if (!bApi) |
| rDocShell.ErrorMessage(aTester.GetMessageId()); |
| return sal_False; |
| } |
| |
| // #i12940# ClearItems is called (from setPropertyToDefault) directly with uno object's cached |
| // MarkData (GetMarkData), so rMark must be changed to multi selection for ClearSelectionItems |
| // here. |
| |
| ScRange aMarkRange; |
| ScMarkData aMultiMark = rMark; |
| aMultiMark.SetMarking(sal_False); // for MarkToMulti |
| aMultiMark.MarkToMulti(); |
| aMultiMark.GetMultiMarkArea( aMarkRange ); |
| |
| // if (bRecord) |
| if (bUndo) |
| { |
| SCTAB nStartTab = aMarkRange.aStart.Tab(); |
| SCTAB nEndTab = aMarkRange.aEnd.Tab(); |
| |
| ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); |
| pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab ); |
| pDoc->CopyToDocument( aMarkRange, IDF_ATTRIB, sal_True, pUndoDoc, (ScMarkData*)&aMultiMark ); |
| |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoClearItems( &rDocShell, aMultiMark, pUndoDoc, pWhich ) ); |
| } |
| |
| pDoc->ClearSelectionItems( pWhich, aMultiMark ); |
| |
| rDocShell.PostPaint( aMarkRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE ); |
| aModificator.SetDocumentModified(); |
| |
| //! Bindings-Invalidate etc.? |
| |
| return sal_True; |
| } |
| |
| sal_Bool ScDocFunc::ChangeIndent( const ScMarkData& rMark, sal_Bool bIncrement, sal_Bool bApi ) |
| { |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| sal_Bool bUndo(pDoc->IsUndoEnabled()); |
| ScEditableTester aTester( pDoc, rMark ); |
| if (!aTester.IsEditable()) |
| { |
| if (!bApi) |
| rDocShell.ErrorMessage(aTester.GetMessageId()); |
| return sal_False; |
| } |
| |
| ScRange aMarkRange; |
| rMark.GetMultiMarkArea( aMarkRange ); |
| |
| // if (bRecord) |
| if (bUndo) |
| { |
| SCTAB nStartTab = aMarkRange.aStart.Tab(); |
| SCTAB nTabCount = pDoc->GetTableCount(); |
| |
| ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); |
| pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab ); |
| for (SCTAB i=0; i<nTabCount; i++) |
| if (i != nStartTab && rMark.GetTableSelect(i)) |
| pUndoDoc->AddUndoTab( i, i ); |
| |
| ScRange aCopyRange = aMarkRange; |
| aCopyRange.aStart.SetTab(0); |
| aCopyRange.aEnd.SetTab(nTabCount-1); |
| pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, sal_True, pUndoDoc, (ScMarkData*)&rMark ); |
| |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoIndent( &rDocShell, rMark, pUndoDoc, bIncrement ) ); |
| } |
| |
| pDoc->ChangeSelectionIndent( bIncrement, rMark ); |
| |
| rDocShell.PostPaint( aMarkRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE ); |
| aModificator.SetDocumentModified(); |
| |
| SfxBindings* pBindings = rDocShell.GetViewBindings(); |
| if (pBindings) |
| { |
| pBindings->Invalidate( SID_ALIGNLEFT ); // ChangeIndent setzt auf links |
| pBindings->Invalidate( SID_ALIGNRIGHT ); |
| pBindings->Invalidate( SID_ALIGNBLOCK ); |
| pBindings->Invalidate( SID_ALIGNCENTERHOR ); |
| pBindings->Invalidate( SID_ATTR_LRSPACE ); |
| pBindings->Invalidate( SID_ATTR_PARA_ADJUST_LEFT ); |
| pBindings->Invalidate( SID_ATTR_PARA_ADJUST_RIGHT ); |
| pBindings->Invalidate( SID_ATTR_PARA_ADJUST_BLOCK ); |
| pBindings->Invalidate( SID_ATTR_PARA_ADJUST_CENTER); |
| // pseudo slots for Format menu |
| pBindings->Invalidate( SID_ALIGN_ANY_HDEFAULT ); |
| pBindings->Invalidate( SID_ALIGN_ANY_LEFT ); |
| pBindings->Invalidate( SID_ALIGN_ANY_HCENTER ); |
| pBindings->Invalidate( SID_ALIGN_ANY_RIGHT ); |
| pBindings->Invalidate( SID_ALIGN_ANY_JUSTIFIED ); |
| } |
| |
| return sal_True; |
| } |
| |
| sal_Bool ScDocFunc::AutoFormat( const ScRange& rRange, const ScMarkData* pTabMark, |
| sal_uInt16 nFormatNo, sal_Bool bRecord, sal_Bool bApi ) |
| { |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| sal_Bool bSuccess = sal_False; |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| SCCOL nStartCol = rRange.aStart.Col(); |
| SCROW nStartRow = rRange.aStart.Row(); |
| SCTAB nStartTab = rRange.aStart.Tab(); |
| SCCOL nEndCol = rRange.aEnd.Col(); |
| SCROW nEndRow = rRange.aEnd.Row(); |
| SCTAB nEndTab = rRange.aEnd.Tab(); |
| |
| if (bRecord && !pDoc->IsUndoEnabled()) |
| bRecord = sal_False; |
| ScMarkData aMark; |
| if (pTabMark) |
| aMark = *pTabMark; |
| else |
| { |
| for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++) |
| aMark.SelectTable( nTab, sal_True ); |
| } |
| |
| ScAutoFormat* pAutoFormat = ScGlobal::GetAutoFormat(); |
| ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark ); |
| if ( pAutoFormat && nFormatNo < pAutoFormat->GetCount() && aTester.IsEditable() ) |
| { |
| WaitObject aWait( rDocShell.GetActiveDialogParent() ); |
| |
| sal_Bool bSize = (*pAutoFormat)[nFormatNo]->GetIncludeWidthHeight(); |
| |
| SCTAB nTabCount = pDoc->GetTableCount(); |
| ScDocument* pUndoDoc = NULL; |
| if ( bRecord ) |
| { |
| pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); |
| pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab, bSize, bSize ); |
| for (SCTAB i=0; i<nTabCount; i++) |
| if (i != nStartTab && aMark.GetTableSelect(i)) |
| pUndoDoc->AddUndoTab( i, i, bSize, bSize ); |
| |
| ScRange aCopyRange = rRange; |
| aCopyRange.aStart.SetTab(0); |
| aCopyRange.aStart.SetTab(nTabCount-1); |
| pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, sal_False, pUndoDoc, &aMark ); |
| if (bSize) |
| { |
| pDoc->CopyToDocument( nStartCol,0,0, nEndCol,MAXROW,nTabCount-1, |
| IDF_NONE, sal_False, pUndoDoc, &aMark ); |
| pDoc->CopyToDocument( 0,nStartRow,0, MAXCOL,nEndRow,nTabCount-1, |
| IDF_NONE, sal_False, pUndoDoc, &aMark ); |
| } |
| pDoc->BeginDrawUndo(); |
| } |
| |
| pDoc->AutoFormat( nStartCol, nStartRow, nEndCol, nEndRow, nFormatNo, aMark ); |
| |
| if (bSize) |
| { |
| /* SCCOL nCols[2]; |
| nCols[0] = nStartCol; |
| nCols[1] = nEndCol; |
| SCROW nRows[2]; |
| nRows[0] = nStartRow; |
| nRows[1] = nEndRow; |
| */ |
| SCCOLROW nCols[2] = { nStartCol, nEndCol }; |
| SCCOLROW nRows[2] = { nStartRow, nEndRow }; |
| |
| for (SCTAB nTab=0; nTab<nTabCount; nTab++) |
| if (aMark.GetTableSelect(nTab)) |
| { |
| SetWidthOrHeight( sal_True, 1,nCols, nTab, SC_SIZE_VISOPT, STD_EXTRA_WIDTH, sal_False, sal_True); |
| SetWidthOrHeight( sal_False,1,nRows, nTab, SC_SIZE_VISOPT, 0, sal_False, sal_False); |
| rDocShell.PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, |
| PAINT_GRID | PAINT_LEFT | PAINT_TOP ); |
| } |
| } |
| else |
| { |
| for (SCTAB nTab=0; nTab<nTabCount; nTab++) |
| if (aMark.GetTableSelect(nTab)) |
| { |
| sal_Bool bAdj = AdjustRowHeight( ScRange(nStartCol, nStartRow, nTab, |
| nEndCol, nEndRow, nTab), sal_False ); |
| if (bAdj) |
| rDocShell.PostPaint( 0,nStartRow,nTab, MAXCOL,MAXROW,nTab, |
| PAINT_GRID | PAINT_LEFT ); |
| else |
| rDocShell.PostPaint( nStartCol, nStartRow, nTab, |
| nEndCol, nEndRow, nTab, PAINT_GRID ); |
| } |
| } |
| |
| if ( bRecord ) // Draw-Undo erst jetzt verfuegbar |
| { |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoAutoFormat( &rDocShell, rRange, pUndoDoc, aMark, bSize, nFormatNo ) ); |
| } |
| |
| aModificator.SetDocumentModified(); |
| } |
| else if (!bApi) |
| rDocShell.ErrorMessage(aTester.GetMessageId()); |
| |
| return bSuccess; |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| sal_Bool ScDocFunc::EnterMatrix( const ScRange& rRange, const ScMarkData* pTabMark, |
| const ScTokenArray* pTokenArray, const String& rString, sal_Bool bApi, sal_Bool bEnglish, |
| const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar ) |
| { |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| sal_Bool bSuccess = sal_False; |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| SCCOL nStartCol = rRange.aStart.Col(); |
| SCROW nStartRow = rRange.aStart.Row(); |
| SCTAB nStartTab = rRange.aStart.Tab(); |
| SCCOL nEndCol = rRange.aEnd.Col(); |
| SCROW nEndRow = rRange.aEnd.Row(); |
| SCTAB nEndTab = rRange.aEnd.Tab(); |
| |
| sal_Bool bUndo(pDoc->IsUndoEnabled()); |
| |
| ScMarkData aMark; |
| if (pTabMark) |
| aMark = *pTabMark; |
| else |
| { |
| for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++) |
| aMark.SelectTable( nTab, sal_True ); |
| } |
| |
| ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark ); |
| if ( aTester.IsEditable() ) |
| { |
| WaitObject aWait( rDocShell.GetActiveDialogParent() ); |
| |
| ScDocument* pUndoDoc = NULL; |
| // if (bRecord) // immer |
| if (bUndo) |
| { |
| //! auch bei Undo selektierte Tabellen beruecksichtigen |
| pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); |
| pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab ); |
| pDoc->CopyToDocument( rRange, IDF_ALL & ~IDF_NOTE, sal_False, pUndoDoc ); |
| } |
| |
| // use TokenArray if given, string (and flags) otherwise |
| if ( pTokenArray ) |
| { |
| pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow, |
| aMark, EMPTY_STRING, pTokenArray, eGrammar); |
| } |
| else if ( pDoc->IsImportingXML() ) |
| { |
| ScTokenArray* pCode = lcl_ScDocFunc_CreateTokenArrayXML( rString, rFormulaNmsp, eGrammar ); |
| pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow, |
| aMark, EMPTY_STRING, pCode, eGrammar); |
| delete pCode; |
| pDoc->IncXMLImportedFormulaCount( rString.Len() ); |
| } |
| else if (bEnglish) |
| { |
| ScCompiler aComp( pDoc, rRange.aStart); |
| aComp.SetGrammar(eGrammar); |
| ScTokenArray* pCode = aComp.CompileString( rString ); |
| pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow, |
| aMark, EMPTY_STRING, pCode, eGrammar); |
| delete pCode; |
| } |
| else |
| pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow, |
| aMark, rString, NULL, eGrammar); |
| |
| // if (bRecord) // immer |
| if (bUndo) |
| { |
| //! auch bei Undo selektierte Tabellen beruecksichtigen |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoEnterMatrix( &rDocShell, rRange, pUndoDoc, rString ) ); |
| } |
| |
| // Err522 beim Paint von DDE-Formeln werden jetzt beim Interpretieren abgefangen |
| rDocShell.PostPaint( nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab, PAINT_GRID ); |
| aModificator.SetDocumentModified(); |
| |
| bSuccess = sal_True; |
| } |
| else if (!bApi) |
| rDocShell.ErrorMessage(aTester.GetMessageId()); |
| |
| return bSuccess; |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| sal_Bool ScDocFunc::TabOp( const ScRange& rRange, const ScMarkData* pTabMark, |
| const ScTabOpParam& rParam, sal_Bool bRecord, sal_Bool bApi ) |
| { |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| sal_Bool bSuccess = sal_False; |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| SCCOL nStartCol = rRange.aStart.Col(); |
| SCROW nStartRow = rRange.aStart.Row(); |
| SCTAB nStartTab = rRange.aStart.Tab(); |
| SCCOL nEndCol = rRange.aEnd.Col(); |
| SCROW nEndRow = rRange.aEnd.Row(); |
| SCTAB nEndTab = rRange.aEnd.Tab(); |
| |
| if (bRecord && !pDoc->IsUndoEnabled()) |
| bRecord = sal_False; |
| |
| ScMarkData aMark; |
| if (pTabMark) |
| aMark = *pTabMark; |
| else |
| { |
| for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++) |
| aMark.SelectTable( nTab, sal_True ); |
| } |
| |
| ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark ); |
| if ( aTester.IsEditable() ) |
| { |
| WaitObject aWait( rDocShell.GetActiveDialogParent() ); |
| pDoc->SetDirty( rRange ); |
| if ( bRecord ) |
| { |
| //! auch bei Undo selektierte Tabellen beruecksichtigen |
| ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); |
| pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab ); |
| pDoc->CopyToDocument( rRange, IDF_ALL & ~IDF_NOTE, sal_False, pUndoDoc ); |
| |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoTabOp( &rDocShell, |
| nStartCol, nStartRow, nStartTab, |
| nEndCol, nEndRow, nEndTab, pUndoDoc, |
| rParam.aRefFormulaCell, |
| rParam.aRefFormulaEnd, |
| rParam.aRefRowCell, |
| rParam.aRefColCell, |
| rParam.nMode) ); |
| } |
| pDoc->InsertTableOp(rParam, nStartCol, nStartRow, nEndCol, nEndRow, aMark); |
| rDocShell.PostPaintGridAll(); |
| aModificator.SetDocumentModified(); |
| bSuccess = sal_True; |
| } |
| else if (!bApi) |
| rDocShell.ErrorMessage(aTester.GetMessageId()); |
| |
| return bSuccess; |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| inline ScDirection DirFromFillDir( FillDir eDir ) |
| { |
| if (eDir==FILL_TO_BOTTOM) |
| return DIR_BOTTOM; |
| else if (eDir==FILL_TO_RIGHT) |
| return DIR_RIGHT; |
| else if (eDir==FILL_TO_TOP) |
| return DIR_TOP; |
| else // if (eDir==FILL_TO_LEFT) |
| return DIR_LEFT; |
| } |
| |
| sal_Bool ScDocFunc::FillSimple( const ScRange& rRange, const ScMarkData* pTabMark, |
| FillDir eDir, sal_Bool bRecord, sal_Bool bApi ) |
| { |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| sal_Bool bSuccess = sal_False; |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| SCCOL nStartCol = rRange.aStart.Col(); |
| SCROW nStartRow = rRange.aStart.Row(); |
| SCTAB nStartTab = rRange.aStart.Tab(); |
| SCCOL nEndCol = rRange.aEnd.Col(); |
| SCROW nEndRow = rRange.aEnd.Row(); |
| SCTAB nEndTab = rRange.aEnd.Tab(); |
| |
| if (bRecord && !pDoc->IsUndoEnabled()) |
| bRecord = sal_False; |
| |
| ScMarkData aMark; |
| if (pTabMark) |
| aMark = *pTabMark; |
| else |
| { |
| for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++) |
| aMark.SelectTable( nTab, sal_True ); |
| } |
| |
| ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark ); |
| if ( aTester.IsEditable() ) |
| { |
| WaitObject aWait( rDocShell.GetActiveDialogParent() ); |
| |
| ScRange aSourceArea = rRange; |
| ScRange aDestArea = rRange; |
| |
| SCCOLROW nCount = 0; |
| switch (eDir) |
| { |
| case FILL_TO_BOTTOM: |
| nCount = aSourceArea.aEnd.Row()-aSourceArea.aStart.Row(); |
| aSourceArea.aEnd.SetRow( aSourceArea.aStart.Row() ); |
| break; |
| case FILL_TO_RIGHT: |
| nCount = aSourceArea.aEnd.Col()-aSourceArea.aStart.Col(); |
| aSourceArea.aEnd.SetCol( aSourceArea.aStart.Col() ); |
| break; |
| case FILL_TO_TOP: |
| nCount = aSourceArea.aEnd.Row()-aSourceArea.aStart.Row(); |
| aSourceArea.aStart.SetRow( aSourceArea.aEnd.Row() ); |
| break; |
| case FILL_TO_LEFT: |
| nCount = aSourceArea.aEnd.Col()-aSourceArea.aStart.Col(); |
| aSourceArea.aStart.SetCol( aSourceArea.aEnd.Col() ); |
| break; |
| } |
| |
| ScDocument* pUndoDoc = NULL; |
| if ( bRecord ) |
| { |
| SCTAB nTabCount = pDoc->GetTableCount(); |
| SCTAB nDestStartTab = aDestArea.aStart.Tab(); |
| |
| pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); |
| pUndoDoc->InitUndo( pDoc, nDestStartTab, nDestStartTab ); |
| for (SCTAB i=0; i<nTabCount; i++) |
| if (i != nDestStartTab && aMark.GetTableSelect(i)) |
| pUndoDoc->AddUndoTab( i, i ); |
| |
| ScRange aCopyRange = aDestArea; |
| aCopyRange.aStart.SetTab(0); |
| aCopyRange.aEnd.SetTab(nTabCount-1); |
| pDoc->CopyToDocument( aCopyRange, IDF_AUTOFILL, sal_False, pUndoDoc, &aMark ); |
| } |
| |
| pDoc->Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(), |
| aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aMark, |
| nCount, eDir, FILL_SIMPLE ); |
| AdjustRowHeight(rRange); |
| |
| if ( bRecord ) // Draw-Undo erst jetzt verfuegbar |
| { |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark, |
| eDir, FILL_SIMPLE, FILL_DAY, MAXDOUBLE, 1.0, 1e307, |
| pDoc->GetRangeName()->GetSharedMaxIndex()+1 ) ); |
| } |
| |
| rDocShell.PostPaintGridAll(); |
| // rDocShell.PostPaintDataChanged(); |
| aModificator.SetDocumentModified(); |
| |
| bSuccess = sal_True; |
| } |
| else if (!bApi) |
| rDocShell.ErrorMessage(aTester.GetMessageId()); |
| |
| return bSuccess; |
| } |
| |
| sal_Bool ScDocFunc::FillSeries( const ScRange& rRange, const ScMarkData* pTabMark, |
| FillDir eDir, FillCmd eCmd, FillDateCmd eDateCmd, |
| double fStart, double fStep, double fMax, |
| sal_Bool bRecord, sal_Bool bApi ) |
| { |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| sal_Bool bSuccess = sal_False; |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| SCCOL nStartCol = rRange.aStart.Col(); |
| SCROW nStartRow = rRange.aStart.Row(); |
| SCTAB nStartTab = rRange.aStart.Tab(); |
| SCCOL nEndCol = rRange.aEnd.Col(); |
| SCROW nEndRow = rRange.aEnd.Row(); |
| SCTAB nEndTab = rRange.aEnd.Tab(); |
| |
| if (bRecord && !pDoc->IsUndoEnabled()) |
| bRecord = sal_False; |
| |
| ScMarkData aMark; |
| if (pTabMark) |
| aMark = *pTabMark; |
| else |
| { |
| for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++) |
| aMark.SelectTable( nTab, sal_True ); |
| } |
| |
| ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark ); |
| if ( aTester.IsEditable() ) |
| { |
| WaitObject aWait( rDocShell.GetActiveDialogParent() ); |
| |
| ScRange aSourceArea = rRange; |
| ScRange aDestArea = rRange; |
| |
| SCSIZE nCount = pDoc->GetEmptyLinesInBlock( |
| aSourceArea.aStart.Col(), aSourceArea.aStart.Row(), aSourceArea.aStart.Tab(), |
| aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aSourceArea.aEnd.Tab(), |
| DirFromFillDir(eDir) ); |
| |
| // #27665# mindestens eine Zeile/Spalte als Quellbereich behalten: |
| SCSIZE nTotLines = ( eDir == FILL_TO_BOTTOM || eDir == FILL_TO_TOP ) ? |
| static_cast<SCSIZE>( aSourceArea.aEnd.Row() - aSourceArea.aStart.Row() + 1 ) : |
| static_cast<SCSIZE>( aSourceArea.aEnd.Col() - aSourceArea.aStart.Col() + 1 ); |
| if ( nCount >= nTotLines ) |
| nCount = nTotLines - 1; |
| |
| switch (eDir) |
| { |
| case FILL_TO_BOTTOM: |
| aSourceArea.aEnd.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aEnd.Row() - nCount ) ); |
| break; |
| case FILL_TO_RIGHT: |
| aSourceArea.aEnd.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aEnd.Col() - nCount ) ); |
| break; |
| case FILL_TO_TOP: |
| aSourceArea.aStart.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aStart.Row() + nCount ) ); |
| break; |
| case FILL_TO_LEFT: |
| aSourceArea.aStart.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aStart.Col() + nCount ) ); |
| break; |
| } |
| |
| ScDocument* pUndoDoc = NULL; |
| if ( bRecord ) |
| { |
| SCTAB nTabCount = pDoc->GetTableCount(); |
| SCTAB nDestStartTab = aDestArea.aStart.Tab(); |
| |
| pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); |
| pUndoDoc->InitUndo( pDoc, nDestStartTab, nDestStartTab ); |
| for (SCTAB i=0; i<nTabCount; i++) |
| if (i != nDestStartTab && aMark.GetTableSelect(i)) |
| pUndoDoc->AddUndoTab( i, i ); |
| |
| pDoc->CopyToDocument( |
| aDestArea.aStart.Col(), aDestArea.aStart.Row(), 0, |
| aDestArea.aEnd.Col(), aDestArea.aEnd.Row(), nTabCount-1, |
| IDF_AUTOFILL, sal_False, pUndoDoc, &aMark ); |
| } |
| |
| if (aDestArea.aStart.Col() <= aDestArea.aEnd.Col() && |
| aDestArea.aStart.Row() <= aDestArea.aEnd.Row()) |
| { |
| if ( fStart != MAXDOUBLE ) |
| { |
| SCCOL nValX = (eDir == FILL_TO_LEFT) ? aDestArea.aEnd.Col() : aDestArea.aStart.Col(); |
| SCROW nValY = (eDir == FILL_TO_TOP ) ? aDestArea.aEnd.Row() : aDestArea.aStart.Row(); |
| SCTAB nTab = aDestArea.aStart.Tab(); |
| pDoc->SetValue( nValX, nValY, nTab, fStart ); |
| } |
| pDoc->Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(), |
| aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aMark, |
| nCount, eDir, eCmd, eDateCmd, fStep, fMax ); |
| AdjustRowHeight(rRange); |
| |
| rDocShell.PostPaintGridAll(); |
| // rDocShell.PostPaintDataChanged(); |
| aModificator.SetDocumentModified(); |
| } |
| |
| if ( bRecord ) // Draw-Undo erst jetzt verfuegbar |
| { |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark, |
| eDir, eCmd, eDateCmd, fStart, fStep, fMax, |
| pDoc->GetRangeName()->GetSharedMaxIndex()+1 ) ); |
| } |
| |
| bSuccess = sal_True; |
| } |
| else if (!bApi) |
| rDocShell.ErrorMessage(aTester.GetMessageId()); |
| |
| return bSuccess; |
| } |
| |
| sal_Bool ScDocFunc::FillAuto( ScRange& rRange, const ScMarkData* pTabMark, |
| FillDir eDir, sal_uLong nCount, sal_Bool bRecord, sal_Bool bApi ) |
| { |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| SCCOL nStartCol = rRange.aStart.Col(); |
| SCROW nStartRow = rRange.aStart.Row(); |
| SCTAB nStartTab = rRange.aStart.Tab(); |
| SCCOL nEndCol = rRange.aEnd.Col(); |
| SCROW nEndRow = rRange.aEnd.Row(); |
| SCTAB nEndTab = rRange.aEnd.Tab(); |
| |
| if (bRecord && !pDoc->IsUndoEnabled()) |
| bRecord = sal_False; |
| |
| ScMarkData aMark; |
| if (pTabMark) |
| aMark = *pTabMark; |
| else |
| { |
| for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++) |
| aMark.SelectTable( nTab, sal_True ); |
| } |
| |
| ScRange aSourceArea = rRange; |
| ScRange aDestArea = rRange; |
| |
| FillCmd eCmd = FILL_AUTO; |
| FillDateCmd eDateCmd = FILL_DAY; |
| double fStep = 1.0; |
| double fMax = MAXDOUBLE; |
| |
| switch (eDir) |
| { |
| case FILL_TO_BOTTOM: |
| aDestArea.aEnd.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aEnd.Row() + nCount ) ); |
| break; |
| case FILL_TO_TOP: |
| if (nCount > sal::static_int_cast<sal_uLong>( aSourceArea.aStart.Row() )) |
| { |
| DBG_ERROR("FillAuto: Row < 0"); |
| nCount = aSourceArea.aStart.Row(); |
| } |
| aDestArea.aStart.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aStart.Row() - nCount ) ); |
| break; |
| case FILL_TO_RIGHT: |
| aDestArea.aEnd.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aEnd.Col() + nCount ) ); |
| break; |
| case FILL_TO_LEFT: |
| if (nCount > sal::static_int_cast<sal_uLong>( aSourceArea.aStart.Col() )) |
| { |
| DBG_ERROR("FillAuto: Col < 0"); |
| nCount = aSourceArea.aStart.Col(); |
| } |
| aDestArea.aStart.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aStart.Col() - nCount ) ); |
| break; |
| default: |
| DBG_ERROR("Falsche Richtung bei FillAuto"); |
| break; |
| } |
| |
| // Zellschutz testen |
| //! Quellbereich darf geschuetzt sein !!! |
| //! aber kein Matrixfragment enthalten !!! |
| |
| ScEditableTester aTester( pDoc, aDestArea ); |
| if ( !aTester.IsEditable() ) |
| { |
| if (!bApi) |
| rDocShell.ErrorMessage(aTester.GetMessageId()); |
| return sal_False; |
| } |
| |
| if ( pDoc->HasSelectedBlockMatrixFragment( nStartCol, nStartRow, |
| nEndCol, nEndRow, aMark ) ) |
| { |
| if (!bApi) |
| rDocShell.ErrorMessage(STR_MATRIXFRAGMENTERR); |
| return sal_False; |
| } |
| |
| WaitObject aWait( rDocShell.GetActiveDialogParent() ); |
| |
| ScDocument* pUndoDoc = NULL; |
| if ( bRecord ) |
| { |
| SCTAB nTabCount = pDoc->GetTableCount(); |
| SCTAB nDestStartTab = aDestArea.aStart.Tab(); |
| |
| pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); |
| pUndoDoc->InitUndo( pDoc, nDestStartTab, nDestStartTab ); |
| for (SCTAB i=0; i<nTabCount; i++) |
| if (i != nDestStartTab && aMark.GetTableSelect(i)) |
| pUndoDoc->AddUndoTab( i, i ); |
| |
| // do not clone note captions in undo document |
| pDoc->CopyToDocument( |
| aDestArea.aStart.Col(), aDestArea.aStart.Row(), 0, |
| aDestArea.aEnd.Col(), aDestArea.aEnd.Row(), nTabCount-1, |
| IDF_AUTOFILL, sal_False, pUndoDoc, &aMark ); |
| } |
| |
| pDoc->Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(), |
| aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aMark, |
| nCount, eDir, eCmd, eDateCmd, fStep, fMax ); |
| |
| AdjustRowHeight(aDestArea); |
| |
| if ( bRecord ) // Draw-Undo erst jetzt verfuegbar |
| { |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark, |
| eDir, eCmd, eDateCmd, MAXDOUBLE, fStep, fMax, |
| pDoc->GetRangeName()->GetSharedMaxIndex()+1 ) ); |
| } |
| |
| rDocShell.PostPaintGridAll(); |
| // rDocShell.PostPaintDataChanged(); |
| aModificator.SetDocumentModified(); |
| |
| rRange = aDestArea; // Zielbereich zurueckgeben (zum Markieren) |
| return sal_True; |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| sal_Bool ScDocFunc::MergeCells( const ScRange& rRange, sal_Bool bContents, sal_Bool bRecord, sal_Bool bApi ) |
| { |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| SCCOL nStartCol = rRange.aStart.Col(); |
| SCROW nStartRow = rRange.aStart.Row(); |
| SCCOL nEndCol = rRange.aEnd.Col(); |
| SCROW nEndRow = rRange.aEnd.Row(); |
| SCTAB nTab = rRange.aStart.Tab(); |
| |
| if (bRecord && !pDoc->IsUndoEnabled()) |
| bRecord = sal_False; |
| |
| ScEditableTester aTester( pDoc, nTab, nStartCol, nStartRow, nEndCol, nEndRow ); |
| if (!aTester.IsEditable()) |
| { |
| if (!bApi) |
| rDocShell.ErrorMessage(aTester.GetMessageId()); |
| return sal_False; |
| } |
| |
| if ( nStartCol == nEndCol && nStartRow == nEndRow ) |
| { |
| // nichts zu tun |
| return sal_True; |
| } |
| |
| if ( pDoc->HasAttrib( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab, |
| HASATTR_MERGED | HASATTR_OVERLAPPED ) ) |
| { |
| // "Zusammenfassen nicht verschachteln !" |
| if (!bApi) |
| rDocShell.ErrorMessage(STR_MSSG_MERGECELLS_0); |
| return sal_False; |
| } |
| |
| sal_Bool bNeedContents = bContents && |
| ( !pDoc->IsBlockEmpty( nTab, nStartCol,nStartRow+1, nStartCol,nEndRow, true ) || |
| !pDoc->IsBlockEmpty( nTab, nStartCol+1,nStartRow, nEndCol,nEndRow, true ) ); |
| |
| ScDocument* pUndoDoc = 0; |
| if (bRecord) |
| { |
| // test if the range contains other notes which also implies that we need an undo document |
| bool bHasNotes = false; |
| for( ScAddress aPos( nStartCol, nStartRow, nTab ); !bHasNotes && (aPos.Col() <= nEndCol); aPos.IncCol() ) |
| for( aPos.SetRow( nStartRow ); !bHasNotes && (aPos.Row() <= nEndRow); aPos.IncRow() ) |
| bHasNotes = ((aPos.Col() != nStartCol) || (aPos.Row() != nStartRow)) && (pDoc->GetNote( aPos ) != 0); |
| |
| if (bNeedContents || bHasNotes) |
| { |
| pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); |
| pUndoDoc->InitUndo( pDoc, nTab, nTab ); |
| // note captions are collected by drawing undo |
| pDoc->CopyToDocument( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab, |
| IDF_ALL|IDF_NOCAPTIONS, sal_False, pUndoDoc ); |
| } |
| if( bHasNotes ) |
| pDoc->BeginDrawUndo(); |
| } |
| |
| if (bNeedContents) |
| pDoc->DoMergeContents( nTab, nStartCol,nStartRow, nEndCol,nEndRow ); |
| pDoc->DoMerge( nTab, nStartCol,nStartRow, nEndCol,nEndRow ); |
| |
| if( bRecord ) |
| { |
| SdrUndoGroup* pDrawUndo = pDoc->GetDrawLayer() ? pDoc->GetDrawLayer()->GetCalcUndo() : 0; |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoMerge( &rDocShell, |
| nStartCol, nStartRow, nTab, |
| nEndCol, nEndRow, nTab, bNeedContents, pUndoDoc, pDrawUndo ) ); |
| } |
| |
| if ( !AdjustRowHeight( ScRange( 0,nStartRow,nTab, MAXCOL,nEndRow,nTab ) ) ) |
| rDocShell.PostPaint( nStartCol, nStartRow, nTab, |
| nEndCol, nEndRow, nTab, PAINT_GRID ); |
| if (bNeedContents) |
| pDoc->SetDirty( rRange ); |
| aModificator.SetDocumentModified(); |
| |
| SfxBindings* pBindings = rDocShell.GetViewBindings(); |
| if (pBindings) |
| { |
| pBindings->Invalidate( FID_MERGE_ON ); |
| pBindings->Invalidate( FID_MERGE_OFF ); |
| pBindings->Invalidate( FID_MERGE_TOGGLE ); |
| } |
| |
| return sal_True; |
| } |
| |
| sal_Bool ScDocFunc::UnmergeCells( const ScRange& rRange, sal_Bool bRecord, sal_Bool bApi ) |
| { |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| SCTAB nTab = rRange.aStart.Tab(); |
| |
| if (bRecord && !pDoc->IsUndoEnabled()) |
| bRecord = sal_False; |
| |
| if ( pDoc->HasAttrib( rRange, HASATTR_MERGED ) ) |
| { |
| ScRange aExtended = rRange; |
| pDoc->ExtendMerge( aExtended ); |
| ScRange aRefresh = aExtended; |
| pDoc->ExtendOverlapped( aRefresh ); |
| |
| if (bRecord) |
| { |
| ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); |
| pUndoDoc->InitUndo( pDoc, nTab, nTab ); |
| pDoc->CopyToDocument( aExtended, IDF_ATTRIB, sal_False, pUndoDoc ); |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoRemoveMerge( &rDocShell, rRange, pUndoDoc ) ); |
| } |
| |
| const SfxPoolItem& rDefAttr = pDoc->GetPool()->GetDefaultItem( ATTR_MERGE ); |
| ScPatternAttr aPattern( pDoc->GetPool() ); |
| aPattern.GetItemSet().Put( rDefAttr ); |
| pDoc->ApplyPatternAreaTab( rRange.aStart.Col(), rRange.aStart.Row(), |
| rRange.aEnd.Col(), rRange.aEnd.Row(), nTab, |
| aPattern ); |
| |
| pDoc->RemoveFlagsTab( aExtended.aStart.Col(), aExtended.aStart.Row(), |
| aExtended.aEnd.Col(), aExtended.aEnd.Row(), nTab, |
| SC_MF_HOR | SC_MF_VER ); |
| |
| pDoc->ExtendMerge( aRefresh, sal_True, sal_False ); |
| |
| if ( !AdjustRowHeight( aExtended ) ) |
| rDocShell.PostPaint( aExtended, PAINT_GRID ); |
| aModificator.SetDocumentModified(); |
| } |
| else if (!bApi) |
| Sound::Beep(); //! sal_False zurueck??? |
| |
| return sal_True; |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| sal_Bool ScDocFunc::ModifyRangeNames( const ScRangeName& rNewRanges, sal_Bool bApi ) |
| { |
| return SetNewRangeNames( new ScRangeName( rNewRanges ), bApi ); |
| } |
| |
| sal_Bool ScDocFunc::SetNewRangeNames( ScRangeName* pNewRanges, sal_Bool /* bApi */ ) // takes ownership of pNewRanges |
| { |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| DBG_ASSERT( pNewRanges, "pNewRanges is 0" ); |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| sal_Bool bUndo(pDoc->IsUndoEnabled()); |
| |
| if (bUndo) |
| { |
| ScRangeName* pOld = pDoc->GetRangeName(); |
| ScRangeName* pUndoRanges = new ScRangeName(*pOld); |
| ScRangeName* pRedoRanges = new ScRangeName(*pNewRanges); |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoRangeNames( &rDocShell, pUndoRanges, pRedoRanges ) ); |
| } |
| |
| // #i55926# While loading XML, formula cells only have a single string token, |
| // so CompileNameFormula would never find any name (index) tokens, and would |
| // unnecessarily loop through all cells. |
| sal_Bool bCompile = ( !pDoc->IsImportingXML() && pDoc->GetNamedRangesLockCount() == 0 ); |
| |
| if ( bCompile ) |
| pDoc->CompileNameFormula( sal_True ); // CreateFormulaString |
| pDoc->SetRangeName( pNewRanges ); // takes ownership |
| if ( bCompile ) |
| pDoc->CompileNameFormula( sal_False ); // CompileFormulaString |
| |
| aModificator.SetDocumentModified(); |
| |
| // #i114072# don't broadcast while loading a file |
| // (navigator and input line for other open documents would be notified) |
| if ( bCompile ) |
| SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) ); |
| |
| return sal_True; |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| void ScDocFunc::CreateOneName( ScRangeName& rList, |
| SCCOL nPosX, SCROW nPosY, SCTAB nTab, |
| SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, |
| sal_Bool& rCancel, sal_Bool bApi ) |
| { |
| if (rCancel) |
| return; |
| |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| if (!pDoc->HasValueData( nPosX, nPosY, nTab )) |
| { |
| String aName; |
| pDoc->GetString( nPosX, nPosY, nTab, aName ); |
| ScRangeData::MakeValidName(aName); |
| if (aName.Len()) |
| { |
| String aContent; |
| ScRange( nX1, nY1, nTab, nX2, nY2, nTab ).Format( aContent, SCR_ABS_3D, pDoc ); |
| |
| sal_Bool bInsert = sal_False; |
| sal_uInt16 nOldPos; |
| if (rList.SearchName( aName, nOldPos )) // vorhanden ? |
| { |
| ScRangeData* pOld = rList[nOldPos]; |
| String aOldStr; |
| pOld->GetSymbol( aOldStr ); |
| if (aOldStr != aContent) |
| { |
| if (bApi) |
| bInsert = sal_True; // per API nicht nachfragen |
| else |
| { |
| String aTemplate = ScGlobal::GetRscString( STR_CREATENAME_REPLACE ); |
| |
| String aMessage = aTemplate.GetToken( 0, '#' ); |
| aMessage += aName; |
| aMessage += aTemplate.GetToken( 1, '#' ); |
| |
| short nResult = QueryBox( rDocShell.GetActiveDialogParent(), |
| WinBits(WB_YES_NO_CANCEL | WB_DEF_YES), |
| aMessage ).Execute(); |
| if ( nResult == RET_YES ) |
| { |
| rList.AtFree(nOldPos); |
| bInsert = sal_True; |
| } |
| else if ( nResult == RET_CANCEL ) |
| rCancel = sal_True; |
| } |
| } |
| } |
| else |
| bInsert = sal_True; |
| |
| if (bInsert) |
| { |
| ScRangeData* pData = new ScRangeData( pDoc, aName, aContent, |
| ScAddress( nPosX, nPosY, nTab)); |
| if (!rList.Insert(pData)) |
| { |
| DBG_ERROR("nanu?"); |
| delete pData; |
| } |
| } |
| } |
| } |
| } |
| |
| sal_Bool ScDocFunc::CreateNames( const ScRange& rRange, sal_uInt16 nFlags, sal_Bool bApi ) |
| { |
| if (!nFlags) |
| return sal_False; // war nix |
| |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| sal_Bool bDone = sal_False; |
| SCCOL nStartCol = rRange.aStart.Col(); |
| SCROW nStartRow = rRange.aStart.Row(); |
| SCCOL nEndCol = rRange.aEnd.Col(); |
| SCROW nEndRow = rRange.aEnd.Row(); |
| SCTAB nTab = rRange.aStart.Tab(); |
| DBG_ASSERT(rRange.aEnd.Tab() == nTab, "CreateNames: mehrere Tabellen geht nicht"); |
| |
| sal_Bool bValid = sal_True; |
| if ( nFlags & ( NAME_TOP | NAME_BOTTOM ) ) |
| if ( nStartRow == nEndRow ) |
| bValid = sal_False; |
| if ( nFlags & ( NAME_LEFT | NAME_RIGHT ) ) |
| if ( nStartCol == nEndCol ) |
| bValid = sal_False; |
| |
| if (bValid) |
| { |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| ScRangeName* pNames = pDoc->GetRangeName(); |
| if (!pNames) |
| return sal_False; // soll nicht sein |
| ScRangeName aNewRanges( *pNames ); |
| |
| sal_Bool bTop = ( ( nFlags & NAME_TOP ) != 0 ); |
| sal_Bool bLeft = ( ( nFlags & NAME_LEFT ) != 0 ); |
| sal_Bool bBottom = ( ( nFlags & NAME_BOTTOM ) != 0 ); |
| sal_Bool bRight = ( ( nFlags & NAME_RIGHT ) != 0 ); |
| |
| SCCOL nContX1 = nStartCol; |
| SCROW nContY1 = nStartRow; |
| SCCOL nContX2 = nEndCol; |
| SCROW nContY2 = nEndRow; |
| |
| if ( bTop ) |
| ++nContY1; |
| if ( bLeft ) |
| ++nContX1; |
| if ( bBottom ) |
| --nContY2; |
| if ( bRight ) |
| --nContX2; |
| |
| sal_Bool bCancel = sal_False; |
| SCCOL i; |
| SCROW j; |
| |
| if ( bTop ) |
| for (i=nContX1; i<=nContX2; i++) |
| CreateOneName( aNewRanges, i,nStartRow,nTab, i,nContY1,i,nContY2, bCancel, bApi ); |
| if ( bLeft ) |
| for (j=nContY1; j<=nContY2; j++) |
| CreateOneName( aNewRanges, nStartCol,j,nTab, nContX1,j,nContX2,j, bCancel, bApi ); |
| if ( bBottom ) |
| for (i=nContX1; i<=nContX2; i++) |
| CreateOneName( aNewRanges, i,nEndRow,nTab, i,nContY1,i,nContY2, bCancel, bApi ); |
| if ( bRight ) |
| for (j=nContY1; j<=nContY2; j++) |
| CreateOneName( aNewRanges, nEndCol,j,nTab, nContX1,j,nContX2,j, bCancel, bApi ); |
| |
| if ( bTop && bLeft ) |
| CreateOneName( aNewRanges, nStartCol,nStartRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi ); |
| if ( bTop && bRight ) |
| CreateOneName( aNewRanges, nEndCol,nStartRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi ); |
| if ( bBottom && bLeft ) |
| CreateOneName( aNewRanges, nStartCol,nEndRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi ); |
| if ( bBottom && bRight ) |
| CreateOneName( aNewRanges, nEndCol,nEndRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi ); |
| |
| bDone = ModifyRangeNames( aNewRanges, bApi ); |
| |
| aModificator.SetDocumentModified(); |
| SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) ); |
| } |
| |
| return bDone; |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| sal_Bool ScDocFunc::InsertNameList( const ScAddress& rStartPos, sal_Bool bApi ) |
| { |
| ScDocShellModificator aModificator( rDocShell ); |
| |
| |
| sal_Bool bDone = sal_False; |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| const sal_Bool bRecord = pDoc->IsUndoEnabled(); |
| SCTAB nTab = rStartPos.Tab(); |
| ScDocument* pUndoDoc = NULL; |
| |
| ScRangeName* pList = pDoc->GetRangeName(); |
| sal_uInt16 nCount = pList->GetCount(); |
| sal_uInt16 nValidCount = 0; |
| sal_uInt16 i; |
| for (i=0; i<nCount; i++) |
| { |
| ScRangeData* pData = (*pList)[i]; |
| if ( !pData->HasType( RT_DATABASE ) && !pData->HasType( RT_SHARED ) ) |
| ++nValidCount; |
| } |
| |
| if (nValidCount) |
| { |
| SCCOL nStartCol = rStartPos.Col(); |
| SCROW nStartRow = rStartPos.Row(); |
| SCCOL nEndCol = nStartCol + 1; |
| SCROW nEndRow = nStartRow + static_cast<SCROW>(nValidCount) - 1; |
| |
| ScEditableTester aTester( pDoc, nTab, nStartCol,nStartRow, nEndCol,nEndRow ); |
| if (aTester.IsEditable()) |
| { |
| if (bRecord) |
| { |
| pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); |
| pUndoDoc->InitUndo( pDoc, nTab, nTab ); |
| pDoc->CopyToDocument( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab, |
| IDF_ALL, sal_False, pUndoDoc ); |
| |
| pDoc->BeginDrawUndo(); // wegen Hoehenanpassung |
| } |
| |
| ScRangeData** ppSortArray = new ScRangeData* [ nValidCount ]; |
| sal_uInt16 j = 0; |
| for (i=0; i<nCount; i++) |
| { |
| ScRangeData* pData = (*pList)[i]; |
| if ( !pData->HasType( RT_DATABASE ) && !pData->HasType( RT_SHARED ) ) |
| ppSortArray[j++] = pData; |
| } |
| #ifndef ICC |
| qsort( (void*)ppSortArray, nValidCount, sizeof(ScRangeData*), |
| &ScRangeData_QsortNameCompare ); |
| #else |
| qsort( (void*)ppSortArray, nValidCount, sizeof(ScRangeData*), |
| ICCQsortNameCompare ); |
| #endif |
| String aName; |
| rtl::OUStringBuffer aContent; |
| String aFormula; |
| SCROW nOutRow = nStartRow; |
| for (j=0; j<nValidCount; j++) |
| { |
| ScRangeData* pData = ppSortArray[j]; |
| pData->GetName(aName); |
| // relative Referenzen Excel-konform auf die linke Spalte anpassen: |
| pData->UpdateSymbol(aContent, ScAddress( nStartCol, nOutRow, nTab )); |
| aFormula = '='; |
| aFormula += aContent; |
| pDoc->PutCell( nStartCol,nOutRow,nTab, new ScStringCell( aName ) ); |
| pDoc->PutCell( nEndCol ,nOutRow,nTab, new ScStringCell( aFormula ) ); |
| ++nOutRow; |
| } |
| |
| delete [] ppSortArray; |
| |
| if (bRecord) |
| { |
| ScDocument* pRedoDoc = new ScDocument( SCDOCMODE_UNDO ); |
| pRedoDoc->InitUndo( pDoc, nTab, nTab ); |
| pDoc->CopyToDocument( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab, |
| IDF_ALL, sal_False, pRedoDoc ); |
| |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoListNames( &rDocShell, |
| ScRange( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab ), |
| pUndoDoc, pRedoDoc ) ); |
| } |
| |
| if (!AdjustRowHeight(ScRange(0,nStartRow,nTab,MAXCOL,nEndRow,nTab))) |
| rDocShell.PostPaint( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab, PAINT_GRID ); |
| //! rDocShell.UpdateOle(GetViewData()); |
| aModificator.SetDocumentModified(); |
| bDone = sal_True; |
| } |
| else if (!bApi) |
| rDocShell.ErrorMessage(aTester.GetMessageId()); |
| } |
| return bDone; |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| sal_Bool ScDocFunc::ResizeMatrix( const ScRange& rOldRange, const ScAddress& rNewEnd, sal_Bool bApi ) |
| { |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| SCCOL nStartCol = rOldRange.aStart.Col(); |
| SCROW nStartRow = rOldRange.aStart.Row(); |
| SCTAB nTab = rOldRange.aStart.Tab(); |
| |
| sal_Bool bUndo(pDoc->IsUndoEnabled()); |
| |
| sal_Bool bRet = sal_False; |
| |
| String aFormula; |
| pDoc->GetFormula( nStartCol, nStartRow, nTab, aFormula ); |
| if ( aFormula.GetChar(0) == '{' && aFormula.GetChar(aFormula.Len()-1) == '}' ) |
| { |
| String aUndo = ScGlobal::GetRscString( STR_UNDO_RESIZEMATRIX ); |
| if (bUndo) |
| rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo ); |
| |
| aFormula.Erase(0,1); |
| aFormula.Erase(aFormula.Len()-1,1); |
| |
| ScMarkData aMark; |
| aMark.SetMarkArea( rOldRange ); |
| aMark.SelectTable( nTab, sal_True ); |
| ScRange aNewRange( rOldRange.aStart, rNewEnd ); |
| |
| if ( DeleteContents( aMark, IDF_CONTENTS, sal_True, bApi ) ) |
| { |
| // GRAM_PODF_A1 for API compatibility. |
| bRet = EnterMatrix( aNewRange, &aMark, NULL, aFormula, bApi, sal_False, EMPTY_STRING, formula::FormulaGrammar::GRAM_PODF_A1 ); |
| if (!bRet) |
| { |
| // versuchen, alten Zustand wiederherzustellen |
| EnterMatrix( rOldRange, &aMark, NULL, aFormula, bApi, sal_False, EMPTY_STRING, formula::FormulaGrammar::GRAM_PODF_A1 ); |
| } |
| } |
| |
| if (bUndo) |
| rDocShell.GetUndoManager()->LeaveListAction(); |
| } |
| |
| return bRet; |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| sal_Bool ScDocFunc::InsertAreaLink( const String& rFile, const String& rFilter, |
| const String& rOptions, const String& rSource, |
| const ScRange& rDestRange, sal_uLong nRefresh, |
| sal_Bool bFitBlock, sal_Bool bApi ) |
| { |
| //! auch fuer ScViewFunc::InsertAreaLink benutzen! |
| |
| ScDocument* pDoc = rDocShell.GetDocument(); |
| sal_Bool bUndo (pDoc->IsUndoEnabled()); |
| |
| sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager(); |
| |
| // #i52120# if other area links exist at the same start position, |
| // remove them first (file format specifies only one link definition |
| // for a cell) |
| |
| sal_uInt16 nLinkCount = pLinkManager->GetLinks().Count(); |
| sal_uInt16 nRemoved = 0; |
| sal_uInt16 nLinkPos = 0; |
| while (nLinkPos<nLinkCount) |
| { |
| ::sfx2::SvBaseLink* pBase = *pLinkManager->GetLinks()[nLinkPos]; |
| if ( pBase->ISA(ScAreaLink) && |
| static_cast<ScAreaLink*>(pBase)->GetDestArea().aStart == rDestRange.aStart ) |
| { |
| if ( bUndo ) |
| { |
| if ( !nRemoved ) |
| { |
| // group all remove and the insert action |
| String aUndo = ScGlobal::GetRscString( STR_UNDO_INSERTAREALINK ); |
| rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo ); |
| } |
| |
| ScAreaLink* pOldArea = static_cast<ScAreaLink*>(pBase); |
| rDocShell.GetUndoManager()->AddUndoAction( |
| new ScUndoRemoveAreaLink( &rDocShell, |
| pOldArea->GetFile(), pOldArea->GetFilter(), pOldArea->GetOptions(), |
| pOldArea->GetSource(), pOldArea->GetDestArea(), pOldArea->GetRefreshDelay() ) ); |
| } |
| pLinkManager->Remove( pBase ); |
| nLinkCount = pLinkManager->GetLinks().Count(); |
| ++nRemoved; |
| } |
| else |
| ++nLinkPos; |
| } |
| |
| String aFilterName = rFilter; |
| String aNewOptions = rOptions; |
| if (!aFilterName.Len()) |
| ScDocumentLoader::GetFilterName( rFile, aFilterName, aNewOptions, sal_True, !bApi ); |
| |
| // remove application prefix from filter name here, so the filter options |
| // aren't reset when the filter name is changed in ScAreaLink::DataChanged |
| ScDocumentLoader::RemoveAppPrefix( aFilterName ); |
| |
| ScAreaLink* pLink = new ScAreaLink( &rDocShell, rFile, aFilterName, |
| aNewOptions, rSource, rDestRange, nRefresh ); |
| pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, rFile, &aFilterName, &rSource ); |
| |
| // Undo fuer den leeren Link |
| |
| if (bUndo) |
| { |
| rDocShell.GetUndoManager()->AddUndoAction( new ScUndoInsertAreaLink( &rDocShell, |
| rFile, aFilterName, aNewOptions, |
| rSource, rDestRange, nRefresh ) ); |
| if ( nRemoved ) |
| rDocShell.GetUndoManager()->LeaveListAction(); // undo for link update is still separate |
| } |
| |
| // Update hat sein eigenes Undo |
| if (pDoc->IsExecuteLinkEnabled()) |
| { |
| pLink->SetDoInsert(bFitBlock); // beim ersten Update ggf. nichts einfuegen |
| pLink->Update(); // kein SetInCreate -> Update ausfuehren |
| } |
| pLink->SetDoInsert(sal_True); // Default = sal_True |
| |
| SfxBindings* pBindings = rDocShell.GetViewBindings(); |
| if (pBindings) |
| pBindings->Invalidate( SID_LINKS ); |
| |
| SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); // Navigator |
| |
| return sal_True; |
| } |
| |
| |
| |
| |