merge the formfield patch from ooo-build
[ooovba.git] / sc / source / ui / docshell / docfunc.cxx
blobcf9c070c187a43b3739c19164aa4836b5e5d123f
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: docfunc.cxx,v $
10 * $Revision: 1.70.100.10 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
36 // INCLUDE ---------------------------------------------------------------
38 #include "scitems.hxx"
39 #include <svx/eeitem.hxx>
41 #include <sfx2/app.hxx>
42 #include <svx/editobj.hxx>
43 #include <svx/linkmgr.hxx>
44 #include <svx/svdundo.hxx>
45 #include <sfx2/bindings.hxx>
46 #include <sfx2/printer.hxx>
47 #include <vcl/msgbox.hxx>
48 #include <vcl/sound.hxx>
49 #include <vcl/virdev.hxx>
50 #include <vcl/waitobj.hxx>
51 #include <svtools/zforlist.hxx>
52 #include <svtools/PasswordHelper.hxx>
54 #include <basic/sbstar.hxx>
55 #include <com/sun/star/container/XNameContainer.hpp>
56 #include <com/sun/star/script/XLibraryContainer.hpp>
57 #include <com/sun/star/script/ModuleInfo.hpp>
58 #include <com/sun/star/script/ModuleType.hpp>
60 #include <list>
62 #include "docfunc.hxx"
64 #include "sc.hrc"
66 #include "arealink.hxx"
67 #include "attrib.hxx"
68 #include "dociter.hxx"
69 #include "autoform.hxx"
70 #include "cell.hxx"
71 #include "cellmergeoption.hxx"
72 #include "detdata.hxx"
73 #include "detfunc.hxx"
74 #include "docpool.hxx"
75 #include "docsh.hxx"
76 #include "drwlayer.hxx"
77 #include "editutil.hxx"
78 #include "globstr.hrc"
79 //CHINA001 #include "namecrea.hxx" // NAME_TOP etc.
80 #include "olinetab.hxx"
81 #include "patattr.hxx"
82 #include "rangenam.hxx"
83 #include "rangeutl.hxx"
84 #include "refundo.hxx"
85 #include "scresid.hxx"
86 #include "stlpool.hxx"
87 #include "stlsheet.hxx"
88 #include "tablink.hxx"
89 #include "tabvwsh.hxx"
90 #include "uiitems.hxx"
91 #include "undoblk.hxx"
92 #include "undocell.hxx"
93 #include "undodraw.hxx"
94 #include "undotab.hxx"
95 #include "waitoff.hxx"
96 #include "sizedev.hxx"
97 #include "scmod.hxx"
98 #include "inputhdl.hxx"
99 #include "inputwin.hxx"
100 #include "editable.hxx"
101 #include "compiler.hxx"
102 #include "scui_def.hxx" //CHINA001
103 #include "tabprotection.hxx"
104 #include "clipparam.hxx"
106 #include <memory>
107 #include <set>
109 using namespace com::sun::star;
110 using ::com::sun::star::uno::Sequence;
111 using ::std::vector;
114 // STATIC DATA -----------------------------------------------------------
116 //========================================================================
118 IMPL_LINK( ScDocFunc, NotifyDrawUndo, SdrUndoAction*, pUndoAction )
120 // #i101118# if drawing layer collects the undo actions, add it there
121 ScDrawLayer* pDrawLayer = rDocShell.GetDocument()->GetDrawLayer();
122 if( pDrawLayer && pDrawLayer->IsRecording() )
123 pDrawLayer->AddCalcUndo( pUndoAction );
124 else
125 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoDraw( pUndoAction, &rDocShell ) );
126 rDocShell.SetDrawModified();
128 // the affected sheet isn't known, so all stream positions are invalidated
129 ScDocument* pDoc = rDocShell.GetDocument();
130 SCTAB nTabCount = pDoc->GetTableCount();
131 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
132 if (pDoc->IsStreamValid(nTab))
133 pDoc->SetStreamValid(nTab, FALSE);
135 return 0;
138 //------------------------------------------------------------------------
140 // Zeile ueber dem Range painten (fuer Linien nach AdjustRowHeight)
142 void lcl_PaintAbove( ScDocShell& rDocShell, const ScRange& rRange )
144 SCROW nRow = rRange.aStart.Row();
145 if ( nRow > 0 )
147 SCTAB nTab = rRange.aStart.Tab(); //! alle?
148 --nRow;
149 rDocShell.PostPaint( ScRange(0,nRow,nTab, MAXCOL,nRow,nTab), PAINT_GRID );
153 //------------------------------------------------------------------------
155 BOOL ScDocFunc::AdjustRowHeight( const ScRange& rRange, BOOL bPaint )
157 ScDocument* pDoc = rDocShell.GetDocument();
158 if ( pDoc->IsImportingXML() )
160 // for XML import, all row heights are updated together after importing
161 return FALSE;
163 if ( !pDoc->IsAdjustHeightEnabled() )
165 return FALSE;
168 SCTAB nTab = rRange.aStart.Tab();
169 SCROW nStartRow = rRange.aStart.Row();
170 SCROW nEndRow = rRange.aEnd.Row();
172 ScSizeDeviceProvider aProv( &rDocShell );
173 Fraction aOne(1,1);
175 BOOL bChanged = pDoc->SetOptimalHeight( nStartRow, nEndRow, nTab, 0, aProv.GetDevice(),
176 aProv.GetPPTX(), aProv.GetPPTY(), aOne, aOne, FALSE );
178 if ( bPaint && bChanged )
179 rDocShell.PostPaint( 0, nStartRow, nTab, MAXCOL, MAXROW, nTab,
180 PAINT_GRID | PAINT_LEFT );
182 return bChanged;
186 //------------------------------------------------------------------------
188 BOOL ScDocFunc::DetectiveAddPred(const ScAddress& rPos)
190 ScDocShellModificator aModificator( rDocShell );
192 rDocShell.MakeDrawLayer();
193 ScDocument* pDoc = rDocShell.GetDocument();
194 BOOL bUndo (pDoc->IsUndoEnabled());
195 ScDrawLayer* pModel = pDoc->GetDrawLayer();
196 SCCOL nCol = rPos.Col();
197 SCROW nRow = rPos.Row();
198 SCTAB nTab = rPos.Tab();
200 if (bUndo)
201 pModel->BeginCalcUndo();
202 BOOL bDone = ScDetectiveFunc( pDoc,nTab ).ShowPred( nCol, nRow );
203 SdrUndoGroup* pUndo = NULL;
204 if (bUndo)
205 pUndo = pModel->GetCalcUndo();
206 if (bDone)
208 ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_ADDPRED );
209 pDoc->AddDetectiveOperation( aOperation );
210 if (bUndo)
212 rDocShell.GetUndoManager()->AddUndoAction(
213 new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
215 aModificator.SetDocumentModified();
216 SfxBindings* pBindings = rDocShell.GetViewBindings();
217 if (pBindings)
218 pBindings->Invalidate( SID_DETECTIVE_REFRESH );
220 else
221 delete pUndo;
223 return bDone;
226 BOOL ScDocFunc::DetectiveDelPred(const ScAddress& rPos)
228 ScDocument* pDoc = rDocShell.GetDocument();
230 BOOL bUndo(pDoc->IsUndoEnabled());
231 ScDrawLayer* pModel = pDoc->GetDrawLayer();
232 if (!pModel)
233 return FALSE;
235 ScDocShellModificator aModificator( rDocShell );
237 SCCOL nCol = rPos.Col();
238 SCROW nRow = rPos.Row();
239 SCTAB nTab = rPos.Tab();
241 if (bUndo)
242 pModel->BeginCalcUndo();
243 BOOL bDone = ScDetectiveFunc( pDoc,nTab ).DeletePred( nCol, nRow );
244 SdrUndoGroup* pUndo = NULL;
245 if (bUndo)
246 pUndo = pModel->GetCalcUndo();
247 if (bDone)
249 ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_DELPRED );
250 pDoc->AddDetectiveOperation( aOperation );
251 if (bUndo)
253 rDocShell.GetUndoManager()->AddUndoAction(
254 new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
256 aModificator.SetDocumentModified();
257 SfxBindings* pBindings = rDocShell.GetViewBindings();
258 if (pBindings)
259 pBindings->Invalidate( SID_DETECTIVE_REFRESH );
261 else
262 delete pUndo;
264 return bDone;
267 BOOL ScDocFunc::DetectiveAddSucc(const ScAddress& rPos)
269 ScDocShellModificator aModificator( rDocShell );
271 rDocShell.MakeDrawLayer();
272 ScDocument* pDoc = rDocShell.GetDocument();
274 BOOL bUndo(pDoc->IsUndoEnabled());
275 ScDrawLayer* pModel = pDoc->GetDrawLayer();
276 SCCOL nCol = rPos.Col();
277 SCROW nRow = rPos.Row();
278 SCTAB nTab = rPos.Tab();
280 if (bUndo)
281 pModel->BeginCalcUndo();
282 BOOL bDone = ScDetectiveFunc( pDoc,nTab ).ShowSucc( nCol, nRow );
283 SdrUndoGroup* pUndo = NULL;
284 if (bUndo)
285 pUndo = pModel->GetCalcUndo();
286 if (bDone)
288 ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_ADDSUCC );
289 pDoc->AddDetectiveOperation( aOperation );
290 if (bUndo)
292 rDocShell.GetUndoManager()->AddUndoAction(
293 new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
295 aModificator.SetDocumentModified();
296 SfxBindings* pBindings = rDocShell.GetViewBindings();
297 if (pBindings)
298 pBindings->Invalidate( SID_DETECTIVE_REFRESH );
300 else
301 delete pUndo;
303 return bDone;
306 BOOL ScDocFunc::DetectiveDelSucc(const ScAddress& rPos)
308 ScDocument* pDoc = rDocShell.GetDocument();
310 BOOL bUndo (pDoc->IsUndoEnabled());
311 ScDrawLayer* pModel = pDoc->GetDrawLayer();
312 if (!pModel)
313 return FALSE;
315 ScDocShellModificator aModificator( rDocShell );
317 SCCOL nCol = rPos.Col();
318 SCROW nRow = rPos.Row();
319 SCTAB nTab = rPos.Tab();
321 if (bUndo)
322 pModel->BeginCalcUndo();
323 BOOL bDone = ScDetectiveFunc( pDoc,nTab ).DeleteSucc( nCol, nRow );
324 SdrUndoGroup* pUndo = NULL;
325 if (bUndo)
326 pUndo = pModel->GetCalcUndo();
327 if (bDone)
329 ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_DELSUCC );
330 pDoc->AddDetectiveOperation( aOperation );
331 if (bUndo)
333 rDocShell.GetUndoManager()->AddUndoAction(
334 new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
336 aModificator.SetDocumentModified();
337 SfxBindings* pBindings = rDocShell.GetViewBindings();
338 if (pBindings)
339 pBindings->Invalidate( SID_DETECTIVE_REFRESH );
341 else
342 delete pUndo;
344 return bDone;
347 BOOL ScDocFunc::DetectiveAddError(const ScAddress& rPos)
349 ScDocShellModificator aModificator( rDocShell );
351 rDocShell.MakeDrawLayer();
352 ScDocument* pDoc = rDocShell.GetDocument();
354 BOOL bUndo (pDoc->IsUndoEnabled());
355 ScDrawLayer* pModel = pDoc->GetDrawLayer();
356 SCCOL nCol = rPos.Col();
357 SCROW nRow = rPos.Row();
358 SCTAB nTab = rPos.Tab();
360 if (bUndo)
361 pModel->BeginCalcUndo();
362 BOOL bDone = ScDetectiveFunc( pDoc,nTab ).ShowError( nCol, nRow );
363 SdrUndoGroup* pUndo = NULL;
364 if (bUndo)
365 pUndo = pModel->GetCalcUndo();
366 if (bDone)
368 ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_ADDERROR );
369 pDoc->AddDetectiveOperation( aOperation );
370 if (bUndo)
372 rDocShell.GetUndoManager()->AddUndoAction(
373 new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
375 aModificator.SetDocumentModified();
376 SfxBindings* pBindings = rDocShell.GetViewBindings();
377 if (pBindings)
378 pBindings->Invalidate( SID_DETECTIVE_REFRESH );
380 else
381 delete pUndo;
383 return bDone;
386 BOOL ScDocFunc::DetectiveMarkInvalid(SCTAB nTab)
388 ScDocShellModificator aModificator( rDocShell );
390 rDocShell.MakeDrawLayer();
391 ScDocument* pDoc = rDocShell.GetDocument();
393 BOOL bUndo (pDoc->IsUndoEnabled());
394 ScDrawLayer* pModel = pDoc->GetDrawLayer();
396 Window* pWaitWin = rDocShell.GetActiveDialogParent();
397 if (pWaitWin)
398 pWaitWin->EnterWait();
399 if (bUndo)
400 pModel->BeginCalcUndo();
401 BOOL bOverflow;
402 BOOL bDone = ScDetectiveFunc( pDoc,nTab ).MarkInvalid( bOverflow );
403 SdrUndoGroup* pUndo = NULL;
404 if (bUndo)
405 pUndo = pModel->GetCalcUndo();
406 if (pWaitWin)
407 pWaitWin->LeaveWait();
408 if (bDone)
410 if (pUndo && bUndo)
412 pUndo->SetComment( ScGlobal::GetRscString( STR_UNDO_DETINVALID ) );
413 rDocShell.GetUndoManager()->AddUndoAction( pUndo );
415 aModificator.SetDocumentModified();
416 if ( bOverflow )
418 InfoBox( NULL,
419 ScGlobal::GetRscString( STR_DETINVALID_OVERFLOW ) ).Execute();
422 else
423 delete pUndo;
425 return bDone;
428 BOOL ScDocFunc::DetectiveDelAll(SCTAB nTab)
430 ScDocument* pDoc = rDocShell.GetDocument();
432 BOOL bUndo (pDoc->IsUndoEnabled());
433 ScDrawLayer* pModel = pDoc->GetDrawLayer();
434 if (!pModel)
435 return FALSE;
437 ScDocShellModificator aModificator( rDocShell );
439 if (bUndo)
440 pModel->BeginCalcUndo();
441 BOOL bDone = ScDetectiveFunc( pDoc,nTab ).DeleteAll( SC_DET_DETECTIVE );
442 SdrUndoGroup* pUndo = NULL;
443 if (bUndo)
444 pUndo = pModel->GetCalcUndo();
445 if (bDone)
447 ScDetOpList* pOldList = pDoc->GetDetOpList();
448 ScDetOpList* pUndoList = NULL;
449 if (bUndo)
450 pUndoList = pOldList ? new ScDetOpList(*pOldList) : NULL;
452 pDoc->ClearDetectiveOperations();
454 if (bUndo)
456 rDocShell.GetUndoManager()->AddUndoAction(
457 new ScUndoDetective( &rDocShell, pUndo, NULL, pUndoList ) );
459 aModificator.SetDocumentModified();
460 SfxBindings* pBindings = rDocShell.GetViewBindings();
461 if (pBindings)
462 pBindings->Invalidate( SID_DETECTIVE_REFRESH );
464 else
465 delete pUndo;
467 return bDone;
470 BOOL ScDocFunc::DetectiveRefresh( BOOL bAutomatic )
472 BOOL bDone = FALSE;
473 ScDocument* pDoc = rDocShell.GetDocument();
475 BOOL bUndo (pDoc->IsUndoEnabled());
476 ScDetOpList* pList = pDoc->GetDetOpList();
477 if ( pList && pList->Count() )
479 rDocShell.MakeDrawLayer();
480 ScDrawLayer* pModel = pDoc->GetDrawLayer();
481 if (bUndo)
482 pModel->BeginCalcUndo();
484 // Loeschen auf allen Tabellen
486 SCTAB nTabCount = pDoc->GetTableCount();
487 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
488 ScDetectiveFunc( pDoc,nTab ).DeleteAll( SC_DET_ARROWS ); // don't remove circles
490 // Wiederholen
492 USHORT nCount = pList->Count();
493 for (USHORT i=0; i<nCount; i++)
495 ScDetOpData* pData = (*pList)[i];
496 if (pData)
498 ScAddress aPos = pData->GetPos();
499 ScDetectiveFunc aFunc( pDoc, aPos.Tab() );
500 SCCOL nCol = aPos.Col();
501 SCROW nRow = aPos.Row();
502 switch (pData->GetOperation())
504 case SCDETOP_ADDSUCC:
505 aFunc.ShowSucc( nCol, nRow );
506 break;
507 case SCDETOP_DELSUCC:
508 aFunc.DeleteSucc( nCol, nRow );
509 break;
510 case SCDETOP_ADDPRED:
511 aFunc.ShowPred( nCol, nRow );
512 break;
513 case SCDETOP_DELPRED:
514 aFunc.DeletePred( nCol, nRow );
515 break;
516 case SCDETOP_ADDERROR:
517 aFunc.ShowError( nCol, nRow );
518 break;
519 default:
520 DBG_ERROR("falsche Op bei DetectiveRefresh");
525 if (bUndo)
527 SdrUndoGroup* pUndo = pModel->GetCalcUndo();
528 if (pUndo)
530 pUndo->SetComment( ScGlobal::GetRscString( STR_UNDO_DETREFRESH ) );
531 // wenn automatisch, an letzte Aktion anhaengen
532 rDocShell.GetUndoManager()->AddUndoAction(
533 new ScUndoDraw( pUndo, &rDocShell ),
534 bAutomatic );
537 rDocShell.SetDrawModified();
538 bDone = TRUE;
540 return bDone;
543 static void lcl_collectAllPredOrSuccRanges(
544 const ScRangeList& rSrcRanges, vector<ScSharedTokenRef>& rRefTokens, ScDocShell& rDocShell,
545 bool bPred)
547 ScDocument* pDoc = rDocShell.GetDocument();
548 vector<ScSharedTokenRef> aRefTokens;
549 ScRangeList aSrcRanges(rSrcRanges);
550 ScRange* p = aSrcRanges.First();
551 if (!p)
552 return;
553 ScDetectiveFunc aDetFunc(pDoc, p->aStart.Tab());
554 ScRangeList aDestRanges;
555 for (; p; p = aSrcRanges.Next())
557 if (bPred)
559 aDetFunc.GetAllPreds(
560 p->aStart.Col(), p->aStart.Row(), p->aEnd.Col(), p->aEnd.Row(), aRefTokens);
562 else
564 aDetFunc.GetAllSuccs(
565 p->aStart.Col(), p->aStart.Row(), p->aEnd.Col(), p->aEnd.Row(), aRefTokens);
568 rRefTokens.swap(aRefTokens);
571 void ScDocFunc::DetectiveCollectAllPreds(const ScRangeList& rSrcRanges, vector<ScSharedTokenRef>& rRefTokens)
573 lcl_collectAllPredOrSuccRanges(rSrcRanges, rRefTokens, rDocShell, true);
576 void ScDocFunc::DetectiveCollectAllSuccs(const ScRangeList& rSrcRanges, vector<ScSharedTokenRef>& rRefTokens)
578 lcl_collectAllPredOrSuccRanges(rSrcRanges, rRefTokens, rDocShell, false);
581 //------------------------------------------------------------------------
583 BOOL ScDocFunc::DeleteContents( const ScMarkData& rMark, USHORT nFlags,
584 BOOL bRecord, BOOL bApi )
586 ScDocShellModificator aModificator( rDocShell );
588 if ( !rMark.IsMarked() && !rMark.IsMultiMarked() )
590 DBG_ERROR("ScDocFunc::DeleteContents ohne Markierung");
591 return FALSE;
594 ScDocument* pDoc = rDocShell.GetDocument();
596 if (bRecord && !pDoc->IsUndoEnabled())
597 bRecord = FALSE;
599 ScEditableTester aTester( pDoc, rMark );
600 if (!aTester.IsEditable())
602 if (!bApi)
603 rDocShell.ErrorMessage(aTester.GetMessageId());
604 return FALSE;
607 ScRange aMarkRange;
608 BOOL bSimple = FALSE;
610 ScMarkData aMultiMark = rMark;
611 aMultiMark.SetMarking(FALSE); // fuer MarkToMulti
613 ScDocument* pUndoDoc = NULL;
614 BOOL bMulti = !bSimple && aMultiMark.IsMultiMarked();
615 if (!bSimple)
617 aMultiMark.MarkToMulti();
618 aMultiMark.GetMultiMarkArea( aMarkRange );
620 ScRange aExtendedRange(aMarkRange);
621 if (!bSimple)
623 if ( pDoc->ExtendMerge( aExtendedRange, TRUE ) )
624 bMulti = FALSE;
627 // keine Objekte auf geschuetzten Tabellen
628 BOOL bObjects = FALSE;
629 if ( nFlags & IDF_OBJECTS )
631 bObjects = TRUE;
632 SCTAB nTabCount = pDoc->GetTableCount();
633 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
634 if (aMultiMark.GetTableSelect(nTab) && pDoc->IsTabProtected(nTab))
635 bObjects = FALSE;
638 USHORT nExtFlags = 0; // extra flags are needed only if attributes are deleted
639 if ( nFlags & IDF_ATTRIB )
640 rDocShell.UpdatePaintExt( nExtFlags, aMarkRange );
642 // Reihenfolge:
643 // 1) BeginDrawUndo
644 // 2) Objekte loeschen (DrawUndo wird gefuellt)
645 // 3) Inhalte fuer Undo kopieren und Undo-Aktion anlegen
646 // 4) Inhalte loeschen
648 bool bDrawUndo = bObjects || (nFlags & IDF_NOTE);
649 if (bRecord && bDrawUndo)
650 pDoc->BeginDrawUndo();
652 if (bObjects)
654 if (bMulti)
655 pDoc->DeleteObjectsInSelection( aMultiMark );
656 else
657 pDoc->DeleteObjectsInArea( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
658 aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(),
659 aMultiMark );
662 if ( bRecord )
664 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
665 pUndoDoc->InitUndo( pDoc, aMarkRange.aStart.Tab(), aMarkRange.aEnd.Tab() );
667 // bei "Format/Standard" alle Attribute kopieren, weil CopyToDocument
668 // nur mit IDF_HARDATTR zu langsam ist:
669 USHORT nUndoDocFlags = nFlags;
670 if (nFlags & IDF_ATTRIB)
671 nUndoDocFlags |= IDF_ATTRIB;
672 if (nFlags & IDF_EDITATTR) // Edit-Engine-Attribute
673 nUndoDocFlags |= IDF_STRING; // -> Zellen werden geaendert
674 if (nFlags & IDF_NOTE)
675 nUndoDocFlags |= IDF_CONTENTS; // #68795# copy all cells with their notes
676 // note captions are handled in drawing undo
677 nUndoDocFlags |= IDF_NOCAPTIONS;
678 pDoc->CopyToDocument( aExtendedRange, nUndoDocFlags, bMulti, pUndoDoc, &aMultiMark );
681 //! HideAllCursors(); // falls Zusammenfassung aufgehoben wird
682 if (bSimple)
683 pDoc->DeleteArea( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
684 aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(),
685 aMultiMark, nFlags );
686 else
688 pDoc->DeleteSelection( nFlags, aMultiMark );
689 // aMultiMark.MarkToSimple();
692 // add undo action after drawing undo is complete (objects and note captions)
693 if( bRecord )
694 rDocShell.GetUndoManager()->AddUndoAction(
695 new ScUndoDeleteContents( &rDocShell, aMultiMark, aExtendedRange,
696 pUndoDoc, bMulti, nFlags, bDrawUndo ) );
698 if (!AdjustRowHeight( aExtendedRange ))
699 rDocShell.PostPaint( aExtendedRange, PAINT_GRID, nExtFlags );
700 else if (nExtFlags & SC_PF_LINES)
701 lcl_PaintAbove( rDocShell, aExtendedRange ); // fuer Linien ueber dem Bereich
703 // rDocShell.UpdateOle(GetViewData()); //! an der View?
704 aModificator.SetDocumentModified();
705 //! CellContentChanged();
706 //! ShowAllCursors();
708 #if 0
709 //! muss an der View bleiben !!!!
710 if ( nFlags & IDF_ATTRIB )
712 if ( nFlags & IDF_CONTENTS )
713 ForgetFormatArea();
714 else
715 StartFormatArea(); // Attribute loeschen ist auch Attributierung
717 #endif
719 return TRUE;
722 //------------------------------------------------------------------------
724 BOOL ScDocFunc::TransliterateText( const ScMarkData& rMark, sal_Int32 nType,
725 BOOL bRecord, BOOL bApi )
727 ScDocShellModificator aModificator( rDocShell );
729 ScDocument* pDoc = rDocShell.GetDocument();
730 if (bRecord && !pDoc->IsUndoEnabled())
731 bRecord = FALSE;
733 ScEditableTester aTester( pDoc, rMark );
734 if (!aTester.IsEditable())
736 if (!bApi)
737 rDocShell.ErrorMessage(aTester.GetMessageId());
738 return FALSE;
741 ScRange aMarkRange;
742 ScMarkData aMultiMark = rMark;
743 aMultiMark.SetMarking(FALSE); // for MarkToMulti
744 aMultiMark.MarkToMulti();
745 aMultiMark.GetMultiMarkArea( aMarkRange );
747 if (bRecord)
749 SCTAB nStartTab = aMarkRange.aStart.Tab();
750 SCTAB nTabCount = pDoc->GetTableCount();
752 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
753 pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab );
754 for (SCTAB i=0; i<nTabCount; i++)
755 if (i != nStartTab && rMark.GetTableSelect(i))
756 pUndoDoc->AddUndoTab( i, i );
758 ScRange aCopyRange = aMarkRange;
759 aCopyRange.aStart.SetTab(0);
760 aCopyRange.aEnd.SetTab(nTabCount-1);
761 pDoc->CopyToDocument( aCopyRange, IDF_CONTENTS, TRUE, pUndoDoc, &aMultiMark );
763 rDocShell.GetUndoManager()->AddUndoAction(
764 new ScUndoTransliterate( &rDocShell, aMultiMark, pUndoDoc, nType ) );
767 pDoc->TransliterateText( aMultiMark, nType );
769 if (!AdjustRowHeight( aMarkRange ))
770 rDocShell.PostPaint( aMarkRange, PAINT_GRID );
772 aModificator.SetDocumentModified();
774 return TRUE;
777 //------------------------------------------------------------------------
779 BOOL ScDocFunc::SetNormalString( const ScAddress& rPos, const String& rText, BOOL bApi )
781 ScDocShellModificator aModificator( rDocShell );
782 ScDocument* pDoc = rDocShell.GetDocument();
784 BOOL bUndo(pDoc->IsUndoEnabled());
785 ScEditableTester aTester( pDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() );
786 if (!aTester.IsEditable())
788 if (!bApi)
789 rDocShell.ErrorMessage(aTester.GetMessageId());
790 return FALSE;
793 SCTAB* pTabs = NULL;
794 ScBaseCell** ppOldCells = NULL;
795 BOOL* pHasFormat = NULL;
796 ULONG* pOldFormats = NULL;
797 ScBaseCell* pDocCell = pDoc->GetCell( rPos );
798 BOOL bEditDeleted = (pDocCell && pDocCell->GetCellType() == CELLTYPE_EDIT);
799 if (bUndo)
801 pTabs = new SCTAB[1];
802 pTabs[0] = rPos.Tab();
803 ppOldCells = new ScBaseCell*[1];
804 ppOldCells[0] = pDocCell ? pDocCell->CloneWithoutNote( *pDoc ) : 0;
806 pHasFormat = new BOOL[1];
807 pOldFormats = new ULONG[1];
808 const SfxPoolItem* pItem;
809 const ScPatternAttr* pPattern = pDoc->GetPattern( rPos.Col(),rPos.Row(),rPos.Tab() );
810 if ( SFX_ITEM_SET == pPattern->GetItemSet().GetItemState(
811 ATTR_VALUE_FORMAT,FALSE,&pItem) )
813 pHasFormat[0] = TRUE;
814 pOldFormats[0] = ((const SfxUInt32Item*)pItem)->GetValue();
816 else
817 pHasFormat[0] = FALSE;
820 pDoc->SetString( rPos.Col(), rPos.Row(), rPos.Tab(), rText );
822 if (bUndo)
824 // wegen ChangeTracking darf UndoAction erst nach SetString angelegt werden
825 rDocShell.GetUndoManager()->AddUndoAction(new ScUndoEnterData( &rDocShell, rPos.Col(),rPos.Row(),rPos.Tab(), 1,pTabs,
826 ppOldCells, pHasFormat, pOldFormats, rText, NULL ) );
829 if ( bEditDeleted || pDoc->HasAttrib( ScRange(rPos), HASATTR_NEEDHEIGHT ) )
830 AdjustRowHeight( ScRange(rPos) );
832 rDocShell.PostPaintCell( rPos );
833 aModificator.SetDocumentModified();
835 // #107160# notify input handler here the same way as in PutCell
836 if (bApi)
837 NotifyInputHandler( rPos );
839 return TRUE;
842 BOOL ScDocFunc::PutCell( const ScAddress& rPos, ScBaseCell* pNewCell, BOOL bApi )
844 ScDocShellModificator aModificator( rDocShell );
845 ScDocument* pDoc = rDocShell.GetDocument();
846 BOOL bUndo (pDoc->IsUndoEnabled());
847 BOOL bXMLLoading(pDoc->IsImportingXML());
849 // #i925#; it is not neccessary to test whether the cell is editable on loading a XML document
850 if (!bXMLLoading)
852 ScEditableTester aTester( pDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() );
853 if (!aTester.IsEditable())
855 if (!bApi)
856 rDocShell.ErrorMessage(aTester.GetMessageId());
857 pNewCell->Delete();
858 return FALSE;
862 BOOL bEditCell = ( pNewCell->GetCellType() == CELLTYPE_EDIT );
863 ScBaseCell* pDocCell = pDoc->GetCell( rPos );
864 BOOL bEditDeleted = (pDocCell && pDocCell->GetCellType() == CELLTYPE_EDIT);
865 BOOL bHeight = ( bEditDeleted || bEditCell ||
866 pDoc->HasAttrib( ScRange(rPos), HASATTR_NEEDHEIGHT ) );
868 ScBaseCell* pUndoCell = (bUndo && pDocCell) ? pDocCell->CloneWithoutNote( *pDoc, rPos ) : 0;
869 ScBaseCell* pRedoCell = (bUndo && pNewCell) ? pNewCell->CloneWithoutNote( *pDoc, rPos ) : 0;
871 pDoc->PutCell( rPos, pNewCell );
873 // wegen ChangeTracking darf UndoAction erst nach PutCell angelegt werden
874 if (bUndo)
876 rDocShell.GetUndoManager()->AddUndoAction(
877 new ScUndoPutCell( &rDocShell, rPos, pUndoCell, pRedoCell, bHeight ) );
880 if (bHeight)
881 AdjustRowHeight( ScRange(rPos) );
883 if (!bXMLLoading)
884 rDocShell.PostPaintCell( rPos );
886 aModificator.SetDocumentModified();
888 // #i925#; it is not neccessary to notify on loading a XML document
889 // #103934#; notify editline and cell in edit mode
890 if (bApi && !bXMLLoading)
891 NotifyInputHandler( rPos );
893 return TRUE;
896 void ScDocFunc::NotifyInputHandler( const ScAddress& /* rPos */ )
898 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
899 if ( pViewSh && pViewSh->GetViewData()->GetDocShell() == &rDocShell )
901 ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl();
902 if ( pInputHdl )
904 sal_Bool bIsEditMode(pInputHdl->IsEditMode());
906 // set modified if in editmode, because so the string is not set in the InputWindow like in the cell
907 // (the cell shows the same like the InputWindow)
908 if (bIsEditMode)
909 pInputHdl->SetModified();
910 pViewSh->UpdateInputHandler(FALSE, !bIsEditMode);
915 struct ScMyRememberItem
917 USHORT nIndex;
918 SfxItemSet aItemSet;
920 ScMyRememberItem(const SfxItemSet& rItemSet, USHORT nTempIndex) :
921 nIndex(nTempIndex), aItemSet(rItemSet) {}
924 typedef ::std::list<ScMyRememberItem*> ScMyRememberItemList;
926 BOOL ScDocFunc::PutData( const ScAddress& rPos, ScEditEngineDefaulter& rEngine, BOOL bInterpret, BOOL bApi )
928 // PutData ruft PutCell oder SetNormalString
930 BOOL bRet = FALSE;
931 ScDocument* pDoc = rDocShell.GetDocument();
932 ScEditAttrTester aTester( &rEngine );
933 BOOL bEditCell = aTester.NeedsObject();
934 if ( bEditCell )
936 // #i61702# With bLoseContent set, the content of rEngine isn't restored
937 // (used in loading XML, where after the removeActionLock call the API obejct's
938 // EditEngine isn't accessed again.
939 sal_Bool bLoseContent = pDoc->IsImportingXML();
941 sal_Bool bUpdateMode(rEngine.GetUpdateMode());
942 if (bUpdateMode)
943 rEngine.SetUpdateMode(sal_False);
945 ScMyRememberItemList aRememberItems;
946 ScMyRememberItem* pRememberItem = NULL;
948 // All paragraph attributes must be removed before calling CreateTextObject,
949 // not only alignment, so the object doesn't contain the cell attributes as
950 // paragraph attributes. Before remove the attributes store they in a list to
951 // set they back to the EditEngine.
952 USHORT nCount = rEngine.GetParagraphCount();
953 for (USHORT i=0; i<nCount; i++)
955 const SfxItemSet& rOld = rEngine.GetParaAttribs( i );
956 if ( rOld.Count() )
958 if ( !bLoseContent )
960 pRememberItem = new ScMyRememberItem(rEngine.GetParaAttribs(i), i);
961 aRememberItems.push_back(pRememberItem);
963 rEngine.SetParaAttribs( i, SfxItemSet( *rOld.GetPool(), rOld.GetRanges() ) );
967 EditTextObject* pNewData = rEngine.CreateTextObject();
968 bRet = PutCell( rPos,
969 new ScEditCell( pNewData, pDoc, rEngine.GetEditTextObjectPool() ),
970 bApi );
971 delete pNewData;
973 // Set the paragraph attributes back to the EditEngine.
974 if (!aRememberItems.empty())
976 // ScMyRememberItem* pRememberItem = NULL;
977 ScMyRememberItemList::iterator aItr = aRememberItems.begin();
978 while (aItr != aRememberItems.end())
980 pRememberItem = *aItr;
981 rEngine.SetParaAttribs(pRememberItem->nIndex, pRememberItem->aItemSet);
982 delete pRememberItem;
983 aItr = aRememberItems.erase(aItr);
987 // #i61702# if the content isn't accessed, there's no need to set the UpdateMode again
988 if ( bUpdateMode && !bLoseContent )
989 rEngine.SetUpdateMode(sal_True);
991 else
993 String aText = rEngine.GetText();
994 if ( bInterpret || !aText.Len() )
995 bRet = SetNormalString( rPos, aText, bApi );
996 else
997 bRet = PutCell( rPos, new ScStringCell( aText ), bApi );
1000 if ( bRet && aTester.NeedsCellAttr() )
1002 const SfxItemSet& rEditAttr = aTester.GetAttribs();
1003 ScPatternAttr aPattern( pDoc->GetPool() );
1004 aPattern.GetFromEditItemSet( &rEditAttr );
1005 aPattern.DeleteUnchanged( pDoc->GetPattern( rPos.Col(), rPos.Row(), rPos.Tab() ) );
1006 aPattern.GetItemSet().ClearItem( ATTR_HOR_JUSTIFY ); // wasn't removed above if no edit object
1007 if ( aPattern.GetItemSet().Count() > 0 )
1009 ScMarkData aMark;
1010 aMark.SelectTable( rPos.Tab(), TRUE );
1011 aMark.SetMarkArea( ScRange( rPos ) );
1012 ApplyAttributes( aMark, aPattern, TRUE, bApi );
1016 return bRet;
1020 ScTokenArray* lcl_ScDocFunc_CreateTokenArrayXML( const String& rText, const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar )
1022 ScTokenArray* pCode = new ScTokenArray;
1023 pCode->AddString( rText );
1024 if( (eGrammar == formula::FormulaGrammar::GRAM_EXTERNAL) && (rFormulaNmsp.Len() > 0) )
1025 pCode->AddString( rFormulaNmsp );
1026 return pCode;
1030 ScBaseCell* ScDocFunc::InterpretEnglishString( const ScAddress& rPos,
1031 const String& rText, const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar )
1033 ScDocument* pDoc = rDocShell.GetDocument();
1034 ScBaseCell* pNewCell = NULL;
1036 if ( rText.Len() > 1 && rText.GetChar(0) == '=' )
1038 ScTokenArray* pCode;
1039 if ( pDoc->IsImportingXML() )
1040 { // temporary formula string as string tokens
1041 pCode = lcl_ScDocFunc_CreateTokenArrayXML( rText, rFormulaNmsp, eGrammar );
1042 pDoc->IncXMLImportedFormulaCount( rText.Len() );
1044 else
1046 ScCompiler aComp( pDoc, rPos );
1047 aComp.SetGrammar(eGrammar);
1048 pCode = aComp.CompileString( rText );
1050 pNewCell = new ScFormulaCell( pDoc, rPos, pCode, eGrammar, MM_NONE );
1051 delete pCode; // Zell-ctor hat das TokenArray kopiert
1053 else if ( rText.Len() > 1 && rText.GetChar(0) == '\'' )
1055 // for bEnglish, "'" at the beginning is always interpreted as text
1056 // marker and stripped
1057 pNewCell = ScBaseCell::CreateTextCell( rText.Copy( 1 ), pDoc );
1059 else // (nur) auf englisches Zahlformat testen
1061 SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
1062 sal_uInt32 nEnglish = pFormatter->GetStandardIndex(LANGUAGE_ENGLISH_US);
1063 double fVal;
1064 if ( pFormatter->IsNumberFormat( rText, nEnglish, fVal ) )
1065 pNewCell = new ScValueCell( fVal );
1066 else if ( rText.Len() )
1067 pNewCell = ScBaseCell::CreateTextCell( rText, pDoc );
1069 // das (englische) Zahlformat wird nicht gesetzt
1070 //! passendes lokales Format suchen und setzen???
1073 return pNewCell;
1077 BOOL ScDocFunc::SetCellText( const ScAddress& rPos, const String& rText,
1078 BOOL bInterpret, BOOL bEnglish, BOOL bApi,
1079 const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar )
1081 // SetCellText ruft PutCell oder SetNormalString
1083 ScDocument* pDoc = rDocShell.GetDocument();
1084 ScBaseCell* pNewCell = NULL;
1085 if ( bInterpret )
1087 if ( bEnglish )
1089 // code moved to own method InterpretEnglishString because it is also used in
1090 // ScCellRangeObj::setFormulaArray
1092 pNewCell = InterpretEnglishString( rPos, rText, rFormulaNmsp, eGrammar );
1094 // sonst Null behalten -> SetString mit lokalen Formeln/Zahlformat
1096 else if ( rText.Len() )
1098 OSL_ENSURE( rFormulaNmsp.Len() == 0, "ScDocFunc::SetCellText - formula namespace, but do not interpret?" );
1099 pNewCell = ScBaseCell::CreateTextCell( rText, pDoc ); // immer Text
1102 if (pNewCell)
1103 return PutCell( rPos, pNewCell, bApi );
1104 else
1105 return SetNormalString( rPos, rText, bApi );
1108 //------------------------------------------------------------------------
1110 bool ScDocFunc::ShowNote( const ScAddress& rPos, bool bShow )
1112 ScDocument& rDoc = *rDocShell.GetDocument();
1113 ScPostIt* pNote = rDoc.GetNote( rPos );
1114 if( !pNote || (bShow == pNote->IsCaptionShown()) ) return false;
1116 // move the caption to internal or hidden layer and create undo action
1117 pNote->ShowCaption( rPos, bShow );
1118 if( rDoc.IsUndoEnabled() )
1119 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoShowHideNote( rDocShell, rPos, bShow ) );
1121 if (rDoc.IsStreamValid(rPos.Tab()))
1122 rDoc.SetStreamValid(rPos.Tab(), FALSE);
1124 rDocShell.SetDocumentModified();
1126 return true;
1129 //------------------------------------------------------------------------
1131 bool ScDocFunc::SetNoteText( const ScAddress& rPos, const String& rText, BOOL bApi )
1133 ScDocShellModificator aModificator( rDocShell );
1135 ScDocument* pDoc = rDocShell.GetDocument();
1136 ScEditableTester aTester( pDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() );
1137 if (!aTester.IsEditable())
1139 if (!bApi)
1140 rDocShell.ErrorMessage(aTester.GetMessageId());
1141 return false;
1144 String aNewText = rText;
1145 aNewText.ConvertLineEnd(); //! ist das noetig ???
1147 if( ScPostIt* pNote = (aNewText.Len() > 0) ? pDoc->GetOrCreateNote( rPos ) : pDoc->GetNote( rPos ) )
1148 pNote->SetText( rPos, aNewText );
1150 //! Undo !!!
1152 if (pDoc->IsStreamValid(rPos.Tab()))
1153 pDoc->SetStreamValid(rPos.Tab(), FALSE);
1155 rDocShell.PostPaintCell( rPos );
1156 aModificator.SetDocumentModified();
1158 return true;
1161 //------------------------------------------------------------------------
1163 bool ScDocFunc::ReplaceNote( const ScAddress& rPos, const String& rNoteText, const String* pAuthor, const String* pDate, BOOL bApi )
1165 bool bDone = false;
1167 ScDocShellModificator aModificator( rDocShell );
1168 ScDocument& rDoc = *rDocShell.GetDocument();
1169 ScEditableTester aTester( &rDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() );
1170 if (aTester.IsEditable())
1172 ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
1173 SfxUndoManager* pUndoMgr = (pDrawLayer && rDoc.IsUndoEnabled()) ? rDocShell.GetUndoManager() : 0;
1175 ScNoteData aOldData;
1176 ScPostIt* pOldNote = rDoc.ReleaseNote( rPos );
1177 if( pOldNote )
1179 // ensure existing caption object before draw undo tracking starts
1180 pOldNote->GetOrCreateCaption( rPos );
1181 // rescue note data for undo
1182 aOldData = pOldNote->GetNoteData();
1185 // collect drawing undo actions for deleting/inserting caption obejcts
1186 if( pUndoMgr )
1187 pDrawLayer->BeginCalcUndo();
1189 // delete the note (creates drawing undo action for the caption object)
1190 delete pOldNote;
1192 // create new note (creates drawing undo action for the new caption object)
1193 ScNoteData aNewData;
1194 if( ScPostIt* pNewNote = ScNoteUtil::CreateNoteFromString( rDoc, rPos, rNoteText, false, true ) )
1196 if( pAuthor ) pNewNote->SetAuthor( *pAuthor );
1197 if( pDate ) pNewNote->SetDate( *pDate );
1198 // rescue note data for undo
1199 aNewData = pNewNote->GetNoteData();
1202 // create the undo action
1203 if( pUndoMgr && (aOldData.mpCaption || aNewData.mpCaption) )
1204 pUndoMgr->AddUndoAction( new ScUndoReplaceNote( rDocShell, rPos, aOldData, aNewData, pDrawLayer->GetCalcUndo() ) );
1206 // repaint cell (to make note marker visible)
1207 rDocShell.PostPaintCell( rPos );
1209 if (rDoc.IsStreamValid(rPos.Tab()))
1210 rDoc.SetStreamValid(rPos.Tab(), FALSE);
1212 aModificator.SetDocumentModified();
1213 bDone = true;
1215 else if (!bApi)
1217 rDocShell.ErrorMessage(aTester.GetMessageId());
1220 return bDone;
1223 //------------------------------------------------------------------------
1225 BOOL ScDocFunc::ApplyAttributes( const ScMarkData& rMark, const ScPatternAttr& rPattern,
1226 BOOL bRecord, BOOL bApi )
1228 ScDocument* pDoc = rDocShell.GetDocument();
1229 if ( bRecord && !pDoc->IsUndoEnabled() )
1230 bRecord = FALSE;
1232 BOOL bImportingXML = pDoc->IsImportingXML();
1233 // Cell formats can still be set if the range isn't editable only because of matrix formulas.
1234 // #i62483# When loading XML, the check can be skipped altogether.
1235 BOOL bOnlyNotBecauseOfMatrix;
1236 if ( !bImportingXML && !pDoc->IsSelectionEditable( rMark, &bOnlyNotBecauseOfMatrix )
1237 && !bOnlyNotBecauseOfMatrix )
1239 if (!bApi)
1240 rDocShell.ErrorMessage(STR_PROTECTIONERR);
1241 return FALSE;
1244 ScDocShellModificator aModificator( rDocShell );
1246 //! Umrandung
1248 ScRange aMultiRange;
1249 BOOL bMulti = rMark.IsMultiMarked();
1250 if ( bMulti )
1251 rMark.GetMultiMarkArea( aMultiRange );
1252 else
1253 rMark.GetMarkArea( aMultiRange );
1255 if ( bRecord )
1257 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1258 pUndoDoc->InitUndo( pDoc, aMultiRange.aStart.Tab(), aMultiRange.aEnd.Tab() );
1259 pDoc->CopyToDocument( aMultiRange, IDF_ATTRIB, bMulti, pUndoDoc, &rMark );
1261 rDocShell.GetUndoManager()->AddUndoAction(
1262 new ScUndoSelectionAttr(
1263 &rDocShell, rMark,
1264 aMultiRange.aStart.Col(), aMultiRange.aStart.Row(), aMultiRange.aStart.Tab(),
1265 aMultiRange.aEnd.Col(), aMultiRange.aEnd.Row(), aMultiRange.aEnd.Tab(),
1266 pUndoDoc, bMulti, &rPattern ) );
1269 // While loading XML it is not neccessary to ask HasAttrib. It needs too much time.
1270 USHORT nExtFlags = 0;
1271 if ( !bImportingXML )
1272 rDocShell.UpdatePaintExt( nExtFlags, aMultiRange ); // content before the change
1273 pDoc->ApplySelectionPattern( rPattern, rMark );
1274 if ( !bImportingXML )
1275 rDocShell.UpdatePaintExt( nExtFlags, aMultiRange ); // content after the change
1277 if (!AdjustRowHeight( aMultiRange ))
1278 rDocShell.PostPaint( aMultiRange, PAINT_GRID, nExtFlags );
1279 else if (nExtFlags & SC_PF_LINES)
1280 lcl_PaintAbove( rDocShell, aMultiRange ); // fuer Linien ueber dem Bereich
1282 aModificator.SetDocumentModified();
1284 return TRUE;
1288 BOOL ScDocFunc::ApplyStyle( const ScMarkData& rMark, const String& rStyleName,
1289 BOOL bRecord, BOOL bApi )
1291 ScDocument* pDoc = rDocShell.GetDocument();
1292 if ( bRecord && !pDoc->IsUndoEnabled() )
1293 bRecord = FALSE;
1295 BOOL bImportingXML = pDoc->IsImportingXML();
1296 // Cell formats can still be set if the range isn't editable only because of matrix formulas.
1297 // #i62483# When loading XML, the check can be skipped altogether.
1298 BOOL bOnlyNotBecauseOfMatrix;
1299 if ( !bImportingXML && !pDoc->IsSelectionEditable( rMark, &bOnlyNotBecauseOfMatrix )
1300 && !bOnlyNotBecauseOfMatrix )
1302 if (!bApi)
1303 rDocShell.ErrorMessage(STR_PROTECTIONERR);
1304 return FALSE;
1307 ScStyleSheet* pStyleSheet = (ScStyleSheet*) pDoc->GetStyleSheetPool()->Find(
1308 rStyleName, SFX_STYLE_FAMILY_PARA );
1309 if (!pStyleSheet)
1310 return FALSE;
1312 ScDocShellModificator aModificator( rDocShell );
1314 ScRange aMultiRange;
1315 BOOL bMulti = rMark.IsMultiMarked();
1316 if ( bMulti )
1317 rMark.GetMultiMarkArea( aMultiRange );
1318 else
1319 rMark.GetMarkArea( aMultiRange );
1321 if ( bRecord )
1323 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1324 SCTAB nStartTab = aMultiRange.aStart.Tab();
1325 SCTAB nTabCount = pDoc->GetTableCount();
1326 pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab );
1327 for (SCTAB i=0; i<nTabCount; i++)
1328 if (i != nStartTab && rMark.GetTableSelect(i))
1329 pUndoDoc->AddUndoTab( i, i );
1331 ScRange aCopyRange = aMultiRange;
1332 aCopyRange.aStart.SetTab(0);
1333 aCopyRange.aEnd.SetTab(nTabCount-1);
1334 pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, bMulti, pUndoDoc, &rMark );
1336 rDocShell.GetUndoManager()->AddUndoAction(
1337 new ScUndoSelectionStyle(
1338 &rDocShell, rMark, aMultiRange, rStyleName, pUndoDoc ) );
1342 // BOOL bPaintExt = pDoc->HasAttrib( aMultiRange, HASATTR_PAINTEXT );
1343 // pDoc->ApplySelectionPattern( rPattern, rMark );
1345 pDoc->ApplySelectionStyle( (ScStyleSheet&)*pStyleSheet, rMark );
1347 // if (!bPaintExt)
1348 // bPaintExt = pDoc->HasAttrib( aMultiRange, HASATTR_PAINTEXT );
1349 // USHORT nExtFlags = bPaintExt ? SC_PF_LINES : 0;
1350 USHORT nExtFlags = 0;
1351 if (!AdjustRowHeight( aMultiRange ))
1352 rDocShell.PostPaint( aMultiRange, PAINT_GRID, nExtFlags );
1353 else if (nExtFlags & SC_PF_LINES)
1354 lcl_PaintAbove( rDocShell, aMultiRange ); // fuer Linien ueber dem Bereich
1356 aModificator.SetDocumentModified();
1358 return TRUE;
1361 //------------------------------------------------------------------------
1363 BOOL ScDocFunc::InsertCells( const ScRange& rRange, const ScMarkData* pTabMark, InsCellCmd eCmd,
1364 BOOL bRecord, BOOL bApi, BOOL bPartOfPaste )
1366 ScDocShellModificator aModificator( rDocShell );
1368 SCCOL nStartCol = rRange.aStart.Col();
1369 SCROW nStartRow = rRange.aStart.Row();
1370 SCTAB nStartTab = rRange.aStart.Tab();
1371 SCCOL nEndCol = rRange.aEnd.Col();
1372 SCROW nEndRow = rRange.aEnd.Row();
1373 SCTAB nEndTab = rRange.aEnd.Tab();
1375 if ( !ValidRow(nStartRow) || !ValidRow(nEndRow) )
1377 DBG_ERROR("invalid row in InsertCells");
1378 return FALSE;
1381 ScDocument* pDoc = rDocShell.GetDocument();
1382 SCTAB nTabCount = pDoc->GetTableCount();
1383 SCCOL nPaintStartX = nStartCol;
1384 SCROW nPaintStartY = nStartRow;
1385 SCCOL nPaintEndX = nEndCol;
1386 SCROW nPaintEndY = nEndRow;
1387 USHORT nPaintFlags = PAINT_GRID;
1388 BOOL bSuccess;
1389 SCTAB i;
1391 ScTabViewShell* pViewSh = rDocShell.GetBestViewShell(); //preserve current cursor position
1392 SCCOL nCursorCol = 0;
1393 SCROW nCursorRow = 0;
1394 if( pViewSh )
1396 nCursorCol = pViewSh->GetViewData()->GetCurX();
1397 nCursorRow = pViewSh->GetViewData()->GetCurY();
1400 if (bRecord && !pDoc->IsUndoEnabled())
1401 bRecord = FALSE;
1403 ScMarkData aMark;
1404 if (pTabMark)
1405 aMark = *pTabMark;
1406 else
1408 SCTAB nCount = 0;
1409 for( i=0; i<nTabCount; i++ )
1411 if( !pDoc->IsScenario(i) )
1413 nCount++;
1414 if( nCount == nEndTab+1 )
1416 aMark.SelectTable( i, TRUE );
1417 break;
1423 ScMarkData aFullMark( aMark ); // including scenario sheets
1424 for( i=0; i<nTabCount; i++ )
1425 if( aMark.GetTableSelect( i ) )
1427 for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
1428 aFullMark.SelectTable( j, TRUE );
1431 SCTAB nSelCount = aMark.GetSelectCount();
1433 // zugehoerige Szenarien auch anpassen
1434 // Test zusammengefasste
1436 SCCOL nMergeTestStartX = nStartCol;
1437 SCROW nMergeTestStartY = nStartRow;
1438 SCCOL nMergeTestEndX = nEndCol;
1439 SCROW nMergeTestEndY = nEndRow;
1441 ScRange aExtendMergeRange( rRange );
1443 if( rRange.aStart == rRange.aEnd && pDoc->HasAttrib(rRange, HASATTR_MERGED) )
1445 pDoc->ExtendMerge( aExtendMergeRange );
1446 pDoc->ExtendOverlapped( aExtendMergeRange );
1447 nMergeTestEndX = aExtendMergeRange.aEnd.Col();
1448 nMergeTestEndY = aExtendMergeRange.aEnd.Row();
1449 nPaintEndX = nMergeTestEndX;
1450 nPaintEndY = nMergeTestEndY;
1453 if ( eCmd == INS_INSROWS )
1455 nMergeTestStartX = 0;
1456 nMergeTestEndX = MAXCOL;
1458 if ( eCmd == INS_INSCOLS )
1460 nMergeTestStartY = 0;
1461 nMergeTestEndY = MAXROW;
1463 if ( eCmd == INS_CELLSDOWN )
1464 nMergeTestEndY = MAXROW;
1465 if ( eCmd == INS_CELLSRIGHT )
1466 nMergeTestEndX = MAXCOL;
1468 BOOL bNeedRefresh = FALSE;
1470 SCCOL nEditTestEndX = (eCmd==INS_INSCOLS) ? MAXCOL : nMergeTestEndX;
1471 SCROW nEditTestEndY = (eCmd==INS_INSROWS) ? MAXROW : nMergeTestEndY;
1472 ScEditableTester aTester( pDoc, nMergeTestStartX, nMergeTestStartY, nEditTestEndX, nEditTestEndY, aMark );
1473 if (!aTester.IsEditable())
1475 if (!bApi)
1476 rDocShell.ErrorMessage(aTester.GetMessageId());
1477 return FALSE;
1480 WaitObject aWait( rDocShell.GetActiveDialogParent() ); // wichtig wegen TrackFormulas bei UpdateReference
1482 ScDocument* pRefUndoDoc = NULL;
1483 ScRefUndoData* pUndoData = NULL;
1484 if ( bRecord )
1486 pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1487 pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, FALSE, FALSE );
1489 // pRefUndoDoc is filled in InsertCol / InsertRow
1491 pUndoData = new ScRefUndoData( pDoc );
1493 pDoc->BeginDrawUndo();
1496 // #i8302 : we unmerge overwhelming ranges, before insertion all the actions are put in the same ListAction
1497 // the patch comes from mloiseleur and maoyg
1498 BOOL bInsertMerge = FALSE;
1499 std::vector<ScRange> qIncreaseRange;
1500 String aUndo = ScGlobal::GetRscString( STR_UNDO_INSERTCELLS );
1501 if (bRecord)
1502 rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo );
1504 for( i=0; i<nTabCount; i++ )
1506 if( aMark.GetTableSelect(i) )
1508 if( pDoc->HasAttrib( nMergeTestStartX, nMergeTestStartY, i, nMergeTestEndX, nMergeTestEndY, i, HASATTR_MERGED | HASATTR_OVERLAPPED ) )
1510 if (eCmd==INS_CELLSRIGHT)
1511 bNeedRefresh = TRUE;
1513 SCCOL nMergeStartX = nMergeTestStartX;
1514 SCROW nMergeStartY = nMergeTestStartY;
1515 SCCOL nMergeEndX = nMergeTestEndX;
1516 SCROW nMergeEndY = nMergeTestEndY;
1518 pDoc->ExtendMerge( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i );
1519 pDoc->ExtendOverlapped( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i );
1521 if(( eCmd == INS_CELLSDOWN && ( nMergeStartX != nMergeTestStartX || nMergeEndX != nMergeTestEndX )) ||
1522 (eCmd == INS_CELLSRIGHT && ( nMergeStartY != nMergeTestStartY || nMergeEndY != nMergeTestEndY )) )
1524 if (!bApi)
1525 rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0);
1526 rDocShell.GetUndoManager()->LeaveListAction();
1527 return FALSE;
1530 SCCOL nTestCol = -1;
1531 SCROW nTestRow1 = -1;
1532 SCROW nTestRow2 = -1;
1534 ScDocAttrIterator aTestIter( pDoc, i, nMergeTestStartX, nMergeTestStartY, nMergeTestEndX, nMergeTestEndY );
1535 ScRange aExtendRange( nMergeTestStartX, nMergeTestStartY, i, nMergeTestEndX, nMergeTestEndY, i );
1536 const ScPatternAttr* pPattern = NULL;
1537 const ScMergeAttr* pMergeFlag = NULL;
1538 const ScMergeFlagAttr* pMergeFlagAttr = NULL;
1539 while ( ( pPattern = aTestIter.GetNext( nTestCol, nTestRow1, nTestRow2 ) ) != NULL )
1541 pMergeFlag = (const ScMergeAttr*) &pPattern->GetItem(ATTR_MERGE);
1542 pMergeFlagAttr = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG);
1543 INT16 nNewFlags = pMergeFlagAttr->GetValue() & ( SC_MF_HOR | SC_MF_VER );
1544 if( ( pMergeFlag && pMergeFlag->IsMerged() ) || nNewFlags == SC_MF_HOR || nNewFlags == SC_MF_VER )
1546 ScRange aRange( nTestCol, nTestRow1, i );
1547 pDoc->ExtendOverlapped(aRange);
1548 pDoc->ExtendMerge(aRange, TRUE, TRUE);
1550 if( nTestRow1 < nTestRow2 && nNewFlags == SC_MF_HOR )
1552 for( SCROW nTestRow = nTestRow1; nTestRow <= nTestRow2; nTestRow++ )
1554 ScRange aTestRange( nTestCol, nTestRow, i );
1555 pDoc->ExtendOverlapped( aTestRange );
1556 pDoc->ExtendMerge( aTestRange, TRUE, TRUE);
1557 ScRange aMergeRange( aTestRange.aStart.Col(),aTestRange.aStart.Row(), i );
1558 if( !aExtendRange.In( aMergeRange ) )
1560 qIncreaseRange.push_back( aTestRange );
1561 bInsertMerge = TRUE;
1565 else
1567 ScRange aMergeRange( aRange.aStart.Col(),aRange.aStart.Row(), i );
1568 if( !aExtendRange.In( aMergeRange ) )
1570 qIncreaseRange.push_back( aRange );
1572 bInsertMerge = TRUE;
1577 if( bInsertMerge )
1579 if( eCmd == INS_INSROWS || eCmd == INS_CELLSDOWN )
1581 nStartRow = aExtendMergeRange.aStart.Row();
1582 nEndRow = aExtendMergeRange.aEnd.Row();
1584 if( eCmd == INS_CELLSDOWN )
1585 nEndCol = nMergeTestEndX;
1586 else
1588 nStartCol = 0;
1589 nEndCol = MAXCOL;
1592 else if( eCmd == INS_CELLSRIGHT || eCmd == INS_INSCOLS )
1595 nStartCol = aExtendMergeRange.aStart.Col();
1596 nEndCol = aExtendMergeRange.aEnd.Col();
1597 if( eCmd == INS_CELLSRIGHT )
1599 nEndRow = nMergeTestEndY;
1601 else
1603 nStartRow = 0;
1604 nEndRow = MAXROW;
1608 if( !qIncreaseRange.empty() )
1610 for( ::std::vector<ScRange>::const_iterator iIter( qIncreaseRange.begin()); iIter != qIncreaseRange.end(); iIter++ )
1612 ScRange aRange( *iIter );
1613 if( pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) )
1615 UnmergeCells( aRange, TRUE, TRUE );
1620 else
1622 if (!bApi)
1623 rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0);
1624 rDocShell.GetUndoManager()->LeaveListAction();
1625 return FALSE;
1631 switch (eCmd)
1633 case INS_CELLSDOWN:
1634 bSuccess = pDoc->InsertRow( nStartCol, 0, nEndCol, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, &aFullMark );
1635 nPaintEndY = MAXROW;
1636 break;
1637 case INS_INSROWS:
1638 bSuccess = pDoc->InsertRow( 0, 0, MAXCOL, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, &aFullMark );
1639 nPaintStartX = 0;
1640 nPaintEndX = MAXCOL;
1641 nPaintEndY = MAXROW;
1642 nPaintFlags |= PAINT_LEFT;
1643 break;
1644 case INS_CELLSRIGHT:
1645 bSuccess = pDoc->InsertCol( nStartRow, 0, nEndRow, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, &aFullMark );
1646 nPaintEndX = MAXCOL;
1647 break;
1648 case INS_INSCOLS:
1649 bSuccess = pDoc->InsertCol( 0, 0, MAXROW, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, &aFullMark );
1650 nPaintStartY = 0;
1651 nPaintEndY = MAXROW;
1652 nPaintEndX = MAXCOL;
1653 nPaintFlags |= PAINT_TOP;
1654 break;
1655 default:
1656 DBG_ERROR("Falscher Code beim Einfuegen");
1657 bSuccess = FALSE;
1658 break;
1661 if ( bSuccess )
1663 SCTAB* pTabs = NULL;
1664 SCTAB* pScenarios = NULL;
1665 SCTAB nUndoPos = 0;
1667 if ( bRecord )
1669 pTabs = new SCTAB[nSelCount];
1670 pScenarios = new SCTAB[nSelCount];
1671 nUndoPos = 0;
1672 for( i=0; i<nTabCount; i++ )
1674 if( aMark.GetTableSelect( i ) )
1676 SCTAB nCount = 0;
1677 for( SCTAB j=i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
1678 nCount ++;
1680 pScenarios[nUndoPos] = nCount;
1681 pTabs[nUndoPos] = i;
1682 nUndoPos ++;
1686 if( !bInsertMerge )
1688 rDocShell.GetUndoManager()->LeaveListAction();
1691 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoInsertCells(
1692 &rDocShell, ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ),
1693 nUndoPos, pTabs, pScenarios, eCmd, pRefUndoDoc, pUndoData, bPartOfPaste ) );
1696 // #i8302 : we remerge growing ranges, with the new part inserted
1698 while( !qIncreaseRange.empty() )
1700 ScRange aRange = qIncreaseRange.back();
1701 if( !pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) )
1703 switch (eCmd)
1705 case INS_CELLSDOWN:
1706 case INS_INSROWS:
1707 aRange.aEnd.IncRow(static_cast<SCsCOL>(nEndRow-nStartRow+1));
1708 break;
1709 case INS_CELLSRIGHT:
1710 case INS_INSCOLS:
1711 aRange.aEnd.IncCol(static_cast<SCsCOL>(nEndCol-nStartCol+1));
1712 break;
1713 default:
1714 break;
1716 ScCellMergeOption aMergeOption(
1717 aRange.aStart.Col(), aRange.aStart.Row(),
1718 aRange.aEnd.Col(), aRange.aEnd.Row() );
1719 aMergeOption.maTabs.insert(aRange.aStart.Tab());
1720 MergeCells(aMergeOption, FALSE, TRUE, TRUE);
1722 qIncreaseRange.pop_back();
1725 if( bInsertMerge )
1726 rDocShell.GetUndoManager()->LeaveListAction();
1728 for( i=0; i<nTabCount; i++ )
1730 if( aMark.GetTableSelect( i ) )
1732 if (bNeedRefresh)
1733 pDoc->ExtendMerge( nMergeTestStartX, nMergeTestStartY, nMergeTestEndX, nMergeTestEndY, i, TRUE );
1734 else
1735 pDoc->RefreshAutoFilter( nMergeTestStartX, nMergeTestStartY, nMergeTestEndX, nMergeTestEndY, i );
1737 if ( eCmd == INS_INSROWS || eCmd == INS_INSCOLS )
1738 pDoc->UpdatePageBreaks( i );
1740 USHORT nExtFlags = 0;
1741 rDocShell.UpdatePaintExt( nExtFlags, nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i );
1743 SCTAB nScenarioCount = 0;
1745 for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
1746 nScenarioCount ++;
1748 BOOL bAdjusted = ( eCmd == INS_INSROWS ) ? AdjustRowHeight(ScRange(0, nStartRow, i, MAXCOL, nEndRow, i+nScenarioCount )) :
1749 AdjustRowHeight(ScRange(0, nPaintStartY, i, MAXCOL, nPaintEndY, i+nScenarioCount ));
1750 if (bAdjusted)
1752 // paint only what is not done by AdjustRowHeight
1753 if (nPaintFlags & PAINT_TOP)
1754 rDocShell.PostPaint( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount, PAINT_TOP );
1756 else
1757 rDocShell.PostPaint( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount, nPaintFlags, nExtFlags );
1760 //aModificator.SetDocumentModified();
1762 else
1764 if( bInsertMerge )
1766 while( !qIncreaseRange.empty() )
1768 ScRange aRange = qIncreaseRange.back();
1769 ScCellMergeOption aMergeOption(
1770 aRange.aStart.Col(), aRange.aStart.Row(),
1771 aRange.aEnd.Col(), aRange.aEnd.Row() );
1772 MergeCells(aMergeOption, FALSE, TRUE, TRUE);
1773 qIncreaseRange.pop_back();
1776 if( pViewSh )
1778 pViewSh->MarkRange( rRange, FALSE );
1779 pViewSh->SetCursor( nCursorCol, nCursorRow );
1783 rDocShell.GetUndoManager()->LeaveListAction();
1784 SfxUndoManager* pMgr = rDocShell.GetUndoManager();
1785 pMgr->RemoveLastUndoAction();
1787 delete pRefUndoDoc;
1788 delete pUndoData;
1789 if (!bApi)
1790 rDocShell.ErrorMessage(STR_INSERT_FULL); // Spalte/Zeile voll
1793 aModificator.SetDocumentModified();
1795 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
1796 return bSuccess;
1799 BOOL ScDocFunc::DeleteCells( const ScRange& rRange, const ScMarkData* pTabMark, DelCellCmd eCmd,
1800 BOOL bRecord, BOOL bApi )
1802 ScDocShellModificator aModificator( rDocShell );
1804 SCCOL nStartCol = rRange.aStart.Col();
1805 SCROW nStartRow = rRange.aStart.Row();
1806 SCTAB nStartTab = rRange.aStart.Tab();
1807 SCCOL nEndCol = rRange.aEnd.Col();
1808 SCROW nEndRow = rRange.aEnd.Row();
1809 SCTAB nEndTab = rRange.aEnd.Tab();
1811 if ( !ValidRow(nStartRow) || !ValidRow(nEndRow) )
1813 DBG_ERROR("invalid row in DeleteCells");
1814 return FALSE;
1817 ScDocument* pDoc = rDocShell.GetDocument();
1818 SCTAB nTabCount = pDoc->GetTableCount();
1819 SCCOL nPaintStartX = nStartCol;
1820 SCROW nPaintStartY = nStartRow;
1821 SCCOL nPaintEndX = nEndCol;
1822 SCROW nPaintEndY = nEndRow;
1823 USHORT nPaintFlags = PAINT_GRID;
1824 SCTAB i;
1826 if (bRecord && !pDoc->IsUndoEnabled())
1827 bRecord = FALSE;
1829 ScMarkData aMark;
1830 if (pTabMark)
1831 aMark = *pTabMark;
1832 else
1834 SCTAB nCount = 0;
1835 for( i=0; i<nTabCount; i++ )
1837 if( !pDoc->IsScenario(i) )
1839 nCount++;
1840 if( nCount == nEndTab+1 )
1842 aMark.SelectTable( i, TRUE );
1843 break;
1849 ScMarkData aFullMark( aMark ); // including scenario sheets
1850 for( i=0; i<nTabCount; i++ )
1851 if( aMark.GetTableSelect( i ) )
1853 for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
1854 aFullMark.SelectTable( j, TRUE );
1857 SCTAB nSelCount = aMark.GetSelectCount();
1859 SCCOL nUndoStartX = nStartCol;
1860 SCROW nUndoStartY = nStartRow;
1861 SCCOL nUndoEndX = nEndCol;
1862 SCROW nUndoEndY = nEndRow;
1864 ScRange aExtendMergeRange( rRange );
1866 if( rRange.aStart == rRange.aEnd && pDoc->HasAttrib(rRange, HASATTR_MERGED) )
1868 pDoc->ExtendMerge( aExtendMergeRange );
1869 pDoc->ExtendOverlapped( aExtendMergeRange );
1870 nUndoEndX = aExtendMergeRange.aEnd.Col();
1871 nUndoEndY = aExtendMergeRange.aEnd.Row();
1872 nPaintEndX = nUndoEndX;
1873 nPaintEndY = nUndoEndY;
1876 if (eCmd==DEL_DELROWS)
1878 nUndoStartX = 0;
1879 nUndoEndX = MAXCOL;
1881 if (eCmd==DEL_DELCOLS)
1883 nUndoStartY = 0;
1884 nUndoEndY = MAXROW;
1886 // Test Zellschutz
1888 SCCOL nEditTestEndX = nUndoEndX;
1889 if ( eCmd==DEL_DELCOLS || eCmd==DEL_CELLSLEFT )
1890 nEditTestEndX = MAXCOL;
1891 SCROW nEditTestEndY = nUndoEndY;
1892 if ( eCmd==DEL_DELROWS || eCmd==DEL_CELLSUP )
1893 nEditTestEndY = MAXROW;
1894 ScEditableTester aTester( pDoc, nUndoStartX, nUndoStartY, nEditTestEndX, nEditTestEndY, aMark );
1895 if (!aTester.IsEditable())
1897 if (!bApi)
1898 rDocShell.ErrorMessage(aTester.GetMessageId());
1899 return FALSE;
1902 // Test zusammengefasste
1904 SCCOL nMergeTestEndX = (eCmd==DEL_CELLSLEFT) ? MAXCOL : nUndoEndX;
1905 SCROW nMergeTestEndY = (eCmd==DEL_CELLSUP) ? MAXROW : nUndoEndY;
1906 SCCOL nExtendStartCol = nUndoStartX;
1907 SCROW nExtendStartRow = nUndoStartY;
1908 BOOL bNeedRefresh = FALSE;
1910 //Issue 8302 want to be able to insert into the middle of merged cells
1911 //the patch comes from maoyg
1912 ::std::vector<ScRange> qDecreaseRange;
1913 BOOL bDeletingMerge = FALSE;
1914 String aUndo = ScGlobal::GetRscString( STR_UNDO_DELETECELLS );
1915 if (bRecord)
1916 rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo );
1918 for( i=0; i<nTabCount; i++ )
1920 if( aMark.GetTableSelect(i) )
1922 if ( pDoc->HasAttrib( nUndoStartX, nUndoStartY, i, nMergeTestEndX, nMergeTestEndY, i, HASATTR_MERGED | HASATTR_OVERLAPPED ))
1924 SCCOL nMergeStartX = nUndoStartX;
1925 SCROW nMergeStartY = nUndoStartY;
1926 SCCOL nMergeEndX = nMergeTestEndX;
1927 SCROW nMergeEndY = nMergeTestEndY;
1929 pDoc->ExtendMerge( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i );
1930 pDoc->ExtendOverlapped( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i );
1931 if( ( eCmd == DEL_CELLSUP && ( nMergeStartX != nUndoStartX || nMergeEndX != nMergeTestEndX))||
1932 ( eCmd == DEL_CELLSLEFT && ( nMergeStartY != nUndoStartY || nMergeEndY != nMergeTestEndY)))
1934 if (!bApi)
1935 rDocShell.ErrorMessage(STR_MSSG_DELETECELLS_0);
1936 rDocShell.GetUndoManager()->LeaveListAction();
1937 return FALSE;
1940 nExtendStartCol = nMergeStartX;
1941 nExtendStartRow = nMergeStartY;
1942 SCCOL nTestCol = -1;
1943 SCROW nTestRow1 = -1;
1944 SCROW nTestRow2 = -1;
1946 ScDocAttrIterator aTestIter( pDoc, i, nUndoStartX, nUndoStartY, nMergeTestEndX, nMergeTestEndY );
1947 ScRange aExtendRange( nUndoStartX, nUndoStartY, i, nMergeTestEndX, nMergeTestEndY, i );
1948 const ScPatternAttr* pPattern = NULL;
1949 const ScMergeAttr* pMergeFlag = NULL;
1950 const ScMergeFlagAttr* pMergeFlagAttr = NULL;
1951 while ( ( pPattern = aTestIter.GetNext( nTestCol, nTestRow1, nTestRow2 ) ) != NULL )
1953 pMergeFlag = (const ScMergeAttr*) &pPattern->GetItem( ATTR_MERGE );
1954 pMergeFlagAttr = (const ScMergeFlagAttr*) &pPattern->GetItem( ATTR_MERGE_FLAG );
1955 INT16 nNewFlags = pMergeFlagAttr->GetValue() & ( SC_MF_HOR | SC_MF_VER );
1956 if( ( pMergeFlag && pMergeFlag->IsMerged() ) || nNewFlags == SC_MF_HOR || nNewFlags == SC_MF_VER )
1958 ScRange aRange( nTestCol, nTestRow1, i );
1959 pDoc->ExtendOverlapped( aRange );
1960 pDoc->ExtendMerge( aRange, TRUE, TRUE );
1962 if( nTestRow1 < nTestRow2 && nNewFlags == SC_MF_HOR )
1964 for( SCROW nTestRow = nTestRow1; nTestRow <= nTestRow2; nTestRow++ )
1966 ScRange aTestRange( nTestCol, nTestRow, i );
1967 pDoc->ExtendOverlapped( aTestRange );
1968 pDoc->ExtendMerge( aTestRange, TRUE, TRUE);
1969 ScRange aMergeRange( aTestRange.aStart.Col(),aTestRange.aStart.Row(), i );
1970 if( !aExtendRange.In( aMergeRange ) )
1972 qDecreaseRange.push_back( aTestRange );
1973 bDeletingMerge = TRUE;
1977 else
1979 ScRange aMergeRange( aRange.aStart.Col(),aRange.aStart.Row(), i );
1980 if( !aExtendRange.In( aMergeRange ) )
1982 qDecreaseRange.push_back( aRange );
1984 bDeletingMerge = TRUE;
1989 if( bDeletingMerge )
1992 if( eCmd == DEL_DELROWS || eCmd == DEL_CELLSUP )
1994 nStartRow = aExtendMergeRange.aStart.Row();
1995 nEndRow = aExtendMergeRange.aEnd.Row();
1996 bNeedRefresh = TRUE;
1998 if( eCmd == DEL_CELLSUP )
2000 nEndCol = aExtendMergeRange.aEnd.Col();
2002 else
2004 nStartCol = 0;
2005 nEndCol = MAXCOL;
2008 else if( eCmd == DEL_CELLSLEFT || eCmd == DEL_DELCOLS )
2011 nStartCol = aExtendMergeRange.aStart.Col();
2012 nEndCol = aExtendMergeRange.aEnd.Col();
2013 if( eCmd == DEL_CELLSLEFT )
2015 nEndRow = aExtendMergeRange.aEnd.Row();
2016 bNeedRefresh = TRUE;
2018 else
2020 nStartRow = 0;
2021 nEndRow = MAXROW;
2025 if( !qDecreaseRange.empty() )
2027 for( ::std::vector<ScRange>::const_iterator iIter( qDecreaseRange.begin()); iIter != qDecreaseRange.end(); iIter++ )
2029 ScRange aRange( *iIter );
2030 if( pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) )
2032 UnmergeCells( aRange, TRUE, TRUE );
2037 else
2039 if (!bApi)
2040 rDocShell.ErrorMessage(STR_MSSG_DELETECELLS_0);
2041 rDocShell.GetUndoManager()->LeaveListAction();
2042 return FALSE;
2049 // ausfuehren
2052 WaitObject aWait( rDocShell.GetActiveDialogParent() ); // wichtig wegen TrackFormulas bei UpdateReference
2054 ScDocument* pUndoDoc = NULL;
2055 ScDocument* pRefUndoDoc = NULL;
2056 ScRefUndoData* pUndoData = NULL;
2057 if ( bRecord )
2059 // With the fix for #101329#, UpdateRef always puts cells into pRefUndoDoc at their old position,
2060 // so it's no longer necessary to copy more than the deleted range into pUndoDoc.
2062 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2063 pUndoDoc->InitUndo( pDoc, 0, nTabCount-1, (eCmd==DEL_DELCOLS), (eCmd==DEL_DELROWS) );
2064 for( i=0; i<nTabCount; i++ )
2066 if( aMark.GetTableSelect( i ) )
2068 SCTAB nScenarioCount = 0;
2070 for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
2071 nScenarioCount ++;
2073 pDoc->CopyToDocument( nUndoStartX, nUndoStartY, i, nUndoEndX, nUndoEndY, i+nScenarioCount,
2074 IDF_ALL | IDF_NOCAPTIONS, FALSE, pUndoDoc );
2078 pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2079 pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, FALSE, FALSE );
2081 pUndoData = new ScRefUndoData( pDoc );
2083 pDoc->BeginDrawUndo();
2086 USHORT nExtFlags = 0;
2087 for( i=0; i<nTabCount; i++ )
2089 if( aMark.GetTableSelect( i ) )
2090 rDocShell.UpdatePaintExt( nExtFlags, nStartCol, nStartRow, i, nEndCol, nEndRow, i );
2093 BOOL bUndoOutline = FALSE;
2094 switch (eCmd)
2096 case DEL_CELLSUP:
2097 pDoc->DeleteRow( nStartCol, 0, nEndCol, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, NULL, &aFullMark );
2098 nPaintEndY = MAXROW;
2099 break;
2100 case DEL_DELROWS:
2101 pDoc->DeleteRow( 0, 0, MAXCOL, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, &bUndoOutline, &aFullMark );
2102 nPaintStartX = 0;
2103 nPaintEndX = MAXCOL;
2104 nPaintEndY = MAXROW;
2105 nPaintFlags |= PAINT_LEFT;
2106 break;
2107 case DEL_CELLSLEFT:
2108 pDoc->DeleteCol( nStartRow, 0, nEndRow, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, NULL, &aFullMark );
2109 nPaintEndX = MAXCOL;
2110 break;
2111 case DEL_DELCOLS:
2112 pDoc->DeleteCol( 0, 0, MAXROW, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, &bUndoOutline, &aFullMark );
2113 nPaintStartY = 0;
2114 nPaintEndY = MAXROW;
2115 nPaintEndX = MAXCOL;
2116 nPaintFlags |= PAINT_TOP;
2117 break;
2118 default:
2119 DBG_ERROR("Falscher Code beim Loeschen");
2120 break;
2123 //! Test, ob Outline in Groesse geaendert
2125 if ( bRecord )
2127 for( i=0; i<nTabCount; i++ )
2128 if( aFullMark.GetTableSelect( i ) )
2129 pRefUndoDoc->DeleteAreaTab(nUndoStartX,nUndoStartY,nUndoEndX,nUndoEndY, i, IDF_ALL);
2131 // alle Tabellen anlegen, damit Formeln kopiert werden koennen:
2132 pUndoDoc->AddUndoTab( 0, nTabCount-1, FALSE, FALSE );
2134 // kopieren mit bColRowFlags=FALSE (#54194#)
2135 pRefUndoDoc->CopyToDocument(0,0,0,MAXCOL,MAXROW,MAXTAB,IDF_FORMULA,FALSE,pUndoDoc,NULL,FALSE);
2136 delete pRefUndoDoc;
2138 SCTAB* pTabs = new SCTAB[nSelCount];
2139 SCTAB* pScenarios = new SCTAB[nSelCount];
2140 SCTAB nUndoPos = 0;
2142 for( i=0; i<nTabCount; i++ )
2144 if( aMark.GetTableSelect( i ) )
2146 SCTAB nCount = 0;
2147 for( SCTAB j=i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
2148 nCount ++;
2150 pScenarios[nUndoPos] = nCount;
2151 pTabs[nUndoPos] = i;
2152 nUndoPos ++;
2156 if( !bDeletingMerge )
2158 rDocShell.GetUndoManager()->LeaveListAction();
2161 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoDeleteCells(
2162 &rDocShell, ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ),nUndoPos, pTabs, pScenarios,
2163 eCmd, pUndoDoc, pUndoData ) );
2166 // #i8302 want to be able to insert into the middle of merged cells
2167 // the patch comes from maoyg
2169 while( !qDecreaseRange.empty() )
2171 ScRange aRange = qDecreaseRange.back();
2173 long nDecreaseRowCount = 0;
2174 long nDecreaseColCount = 0;
2175 if( eCmd == DEL_CELLSUP || eCmd == DEL_DELROWS )
2177 if( nStartRow >= aRange.aStart.Row() && nStartRow <= aRange.aEnd.Row() && nEndRow>= aRange.aStart.Row() && nEndRow <= aRange.aEnd.Row() )
2178 nDecreaseRowCount = nEndRow-nStartRow+1;
2179 else if( nStartRow >= aRange.aStart.Row() && nStartRow <= aRange.aEnd.Row() && nEndRow >= aRange.aStart.Row() && nEndRow >= aRange.aEnd.Row() )
2180 nDecreaseRowCount = aRange.aEnd.Row()-nStartRow+1;
2181 else if( nStartRow >= aRange.aStart.Row() && nStartRow >= aRange.aEnd.Row() && nEndRow>= aRange.aStart.Row() && nEndRow <= aRange.aEnd.Row() )
2182 nDecreaseRowCount = aRange.aEnd.Row()-nEndRow+1;
2184 else if( eCmd == DEL_CELLSLEFT || eCmd == DEL_DELCOLS )
2186 if( nStartCol >= aRange.aStart.Col() && nStartCol <= aRange.aEnd.Col() && nEndCol>= aRange.aStart.Col() && nEndCol <= aRange.aEnd.Col() )
2187 nDecreaseColCount = nEndCol-nStartCol+1;
2188 else if( nStartCol >= aRange.aStart.Col() && nStartCol <= aRange.aEnd.Col() && nEndCol >= aRange.aStart.Col() && nEndCol >= aRange.aEnd.Col() )
2189 nDecreaseColCount = aRange.aEnd.Col()-nStartCol+1;
2190 else if( nStartCol >= aRange.aStart.Col() && nStartCol >= aRange.aEnd.Col() && nEndCol>= aRange.aStart.Col() && nEndCol <= aRange.aEnd.Col() )
2191 nDecreaseColCount = aRange.aEnd.Col()-nEndCol+1;
2194 switch (eCmd)
2196 case DEL_CELLSUP:
2197 case DEL_DELROWS:
2198 aRange.aEnd.SetRow(static_cast<SCsCOL>( aRange.aEnd.Row()-nDecreaseRowCount));
2199 break;
2200 case DEL_CELLSLEFT:
2201 case DEL_DELCOLS:
2202 aRange.aEnd.SetCol(static_cast<SCsCOL>( aRange.aEnd.Col()-nDecreaseColCount));
2203 break;
2204 default:
2205 break;
2208 if( !pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) )
2210 ScCellMergeOption aMergeOption(
2211 aRange.aStart.Col(), aRange.aStart.Row(),
2212 aRange.aEnd.Col(), aRange.aEnd.Row() );
2213 MergeCells( aMergeOption, FALSE, TRUE, TRUE );
2215 qDecreaseRange.pop_back();
2218 if( bDeletingMerge )
2219 rDocShell.GetUndoManager()->LeaveListAction();
2221 if ( bNeedRefresh )
2223 // #i51445# old merge flag attributes must be deleted also for single cells,
2224 // not only for whole columns/rows
2226 if ( eCmd==DEL_DELCOLS || eCmd==DEL_CELLSLEFT )
2227 nMergeTestEndX = MAXCOL;
2228 if ( eCmd==DEL_DELROWS || eCmd==DEL_CELLSUP )
2229 nMergeTestEndY = MAXROW;
2230 ScPatternAttr aPattern( pDoc->GetPool() );
2231 aPattern.GetItemSet().Put( ScMergeFlagAttr() );
2233 pDoc->ApplyPatternArea( nExtendStartCol, nExtendStartRow, nMergeTestEndX, nMergeTestEndY, aMark, aPattern );
2235 for( i=0; i<nTabCount; i++ )
2237 if( aMark.GetTableSelect( i ) )
2239 SCTAB nScenarioCount = 0;
2241 for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
2242 nScenarioCount ++;
2244 ScRange aMergedRange( nExtendStartCol, nExtendStartRow, i, nMergeTestEndX, nMergeTestEndY, i+nScenarioCount );
2245 pDoc->ExtendMerge( aMergedRange, TRUE );
2250 for( i=0; i<nTabCount; i++ )
2252 if( aMark.GetTableSelect( i ) )
2254 if ( eCmd == DEL_DELCOLS || eCmd == DEL_DELROWS )
2255 pDoc->UpdatePageBreaks( i );
2257 rDocShell.UpdatePaintExt( nExtFlags, nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i );
2259 SCTAB nScenarioCount = 0;
2261 for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
2262 nScenarioCount ++;
2264 // ganze Zeilen loeschen: nichts anpassen
2265 if ( eCmd == DEL_DELROWS || !AdjustRowHeight(ScRange( 0, nPaintStartY, i, MAXCOL, nPaintEndY, i+nScenarioCount )) )
2266 rDocShell.PostPaint( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount, nPaintFlags, nExtFlags );
2267 else
2269 // paint only what is not done by AdjustRowHeight
2270 if (nExtFlags & SC_PF_LINES)
2271 lcl_PaintAbove( rDocShell, ScRange( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount) );
2272 if (nPaintFlags & PAINT_TOP)
2273 rDocShell.PostPaint( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount, PAINT_TOP );
2277 aModificator.SetDocumentModified();
2279 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
2281 return TRUE;
2284 BOOL ScDocFunc::MoveBlock( const ScRange& rSource, const ScAddress& rDestPos,
2285 BOOL bCut, BOOL bRecord, BOOL bPaint, BOOL bApi )
2287 ScDocShellModificator aModificator( rDocShell );
2289 SCCOL nStartCol = rSource.aStart.Col();
2290 SCROW nStartRow = rSource.aStart.Row();
2291 SCTAB nStartTab = rSource.aStart.Tab();
2292 SCCOL nEndCol = rSource.aEnd.Col();
2293 SCROW nEndRow = rSource.aEnd.Row();
2294 SCTAB nEndTab = rSource.aEnd.Tab();
2295 SCCOL nDestCol = rDestPos.Col();
2296 SCROW nDestRow = rDestPos.Row();
2297 SCTAB nDestTab = rDestPos.Tab();
2299 if ( !ValidRow(nStartRow) || !ValidRow(nEndRow) || !ValidRow(nDestRow) )
2301 DBG_ERROR("invalid row in MoveBlock");
2302 return FALSE;
2305 // zugehoerige Szenarien auch anpassen - nur wenn innerhalb einer Tabelle verschoben wird!
2306 BOOL bScenariosAdded = FALSE;
2307 ScDocument* pDoc = rDocShell.GetDocument();
2308 if (bRecord && !pDoc->IsUndoEnabled())
2309 bRecord = FALSE;
2311 SCTAB nTabCount = pDoc->GetTableCount();
2312 if ( nDestTab == nStartTab && !pDoc->IsScenario(nEndTab) )
2313 while ( nEndTab+1 < nTabCount && pDoc->IsScenario(nEndTab+1) )
2315 ++nEndTab;
2316 bScenariosAdded = TRUE;
2319 SCTAB nSrcTabCount = nEndTab-nStartTab+1;
2320 SCTAB nDestEndTab = nDestTab+nSrcTabCount-1;
2321 SCTAB nTab;
2323 ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP );
2325 ScMarkData aSourceMark;
2326 for (nTab=nStartTab; nTab<=nEndTab; nTab++)
2327 aSourceMark.SelectTable( nTab, TRUE ); // Source selektieren
2328 aSourceMark.SetMarkArea( rSource );
2330 ScDocShellRef aDragShellRef;
2331 if ( pDoc->HasOLEObjectsInArea( rSource ) )
2333 aDragShellRef = new ScDocShell; // DocShell needs a Ref immediately
2334 aDragShellRef->DoInitNew(NULL);
2336 ScDrawLayer::SetGlobalDrawPersist(aDragShellRef);
2338 ScClipParam aClipParam(ScRange(nStartCol, nStartRow, 0, nEndCol, nEndRow, 0), bCut);
2339 pDoc->CopyToClip(aClipParam, pClipDoc, &aSourceMark, false, bScenariosAdded, true);
2341 ScDrawLayer::SetGlobalDrawPersist(NULL);
2343 SCCOL nOldEndCol = nEndCol;
2344 SCROW nOldEndRow = nEndRow;
2345 BOOL bClipOver = FALSE;
2346 for (nTab=nStartTab; nTab<=nEndTab; nTab++)
2348 SCCOL nTmpEndCol = nOldEndCol;
2349 SCROW nTmpEndRow = nOldEndRow;
2350 if (pDoc->ExtendMerge( nStartCol, nStartRow, nTmpEndCol, nTmpEndRow, nTab ))
2351 bClipOver = TRUE;
2352 if ( nTmpEndCol > nEndCol ) nEndCol = nTmpEndCol;
2353 if ( nTmpEndRow > nEndRow ) nEndRow = nTmpEndRow;
2356 SCCOL nDestEndCol = nDestCol + ( nOldEndCol-nStartCol );
2357 SCROW nDestEndRow = nDestRow + ( nOldEndRow-nStartRow );
2359 SCCOL nUndoEndCol = nDestCol + ( nEndCol-nStartCol ); // erweitert im Zielblock
2360 SCROW nUndoEndRow = nDestRow + ( nEndRow-nStartRow );
2362 BOOL bIncludeFiltered = bCut;
2363 if ( !bIncludeFiltered )
2365 // adjust sizes to include only non-filtered rows
2367 SCCOL nClipX;
2368 SCROW nClipY;
2369 pClipDoc->GetClipArea( nClipX, nClipY, FALSE );
2370 SCROW nUndoAdd = nUndoEndRow - nDestEndRow;
2371 nDestEndRow = nDestRow + nClipY;
2372 nUndoEndRow = nDestEndRow + nUndoAdd;
2375 if (!ValidCol(nUndoEndCol) || !ValidRow(nUndoEndRow))
2377 if (!bApi)
2378 rDocShell.ErrorMessage(STR_PASTE_FULL);
2379 delete pClipDoc;
2380 return FALSE;
2383 // Test auf Zellschutz
2385 ScEditableTester aTester;
2386 for (nTab=nDestTab; nTab<=nDestEndTab; nTab++)
2387 aTester.TestBlock( pDoc, nTab, nDestCol,nDestRow, nUndoEndCol,nUndoEndRow );
2388 if (bCut)
2389 for (nTab=nStartTab; nTab<=nEndTab; nTab++)
2390 aTester.TestBlock( pDoc, nTab, nStartCol,nStartRow, nEndCol,nEndRow );
2392 if (!aTester.IsEditable())
2394 if (!bApi)
2395 rDocShell.ErrorMessage(aTester.GetMessageId());
2396 delete pClipDoc;
2397 return FALSE;
2400 // Test auf zusammengefasste - beim Verschieben erst nach dem Loeschen
2402 if (bClipOver && !bCut)
2403 if (pDoc->HasAttrib( nDestCol,nDestRow,nDestTab, nUndoEndCol,nUndoEndRow,nDestEndTab,
2404 HASATTR_MERGED | HASATTR_OVERLAPPED ))
2405 { // "Zusammenfassen nicht verschachteln !"
2406 if (!bApi)
2407 rDocShell.ErrorMessage(STR_MSSG_MOVEBLOCKTO_0);
2408 delete pClipDoc;
2409 return FALSE;
2412 // Are there borders in the cells? (for painting)
2414 USHORT nSourceExt = 0;
2415 rDocShell.UpdatePaintExt( nSourceExt, nStartCol,nStartRow,nStartTab, nEndCol,nEndRow,nEndTab );
2416 USHORT nDestExt = 0;
2417 rDocShell.UpdatePaintExt( nDestExt, nDestCol,nDestRow,nDestTab, nDestEndCol,nDestEndRow,nDestEndTab );
2420 // ausfuehren
2423 ScDocument* pUndoDoc = NULL;
2424 ScDocument* pRefUndoDoc = NULL;
2425 ScRefUndoData* pUndoData = NULL;
2426 if (bRecord)
2428 BOOL bWholeCols = ( nStartRow == 0 && nEndRow == MAXROW );
2429 BOOL bWholeRows = ( nStartCol == 0 && nEndCol == MAXCOL );
2430 USHORT nUndoFlags = (IDF_ALL & ~IDF_OBJECTS) | IDF_NOCAPTIONS;
2432 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2433 pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab, bWholeCols, bWholeRows );
2435 if (bCut)
2437 pDoc->CopyToDocument( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab,
2438 nUndoFlags, FALSE, pUndoDoc );
2439 pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2440 pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, FALSE, FALSE );
2443 if ( nDestTab != nStartTab )
2444 pUndoDoc->AddUndoTab( nDestTab, nDestEndTab, bWholeCols, bWholeRows );
2445 pDoc->CopyToDocument( nDestCol, nDestRow, nDestTab,
2446 nDestEndCol, nDestEndRow, nDestEndTab,
2447 nUndoFlags, FALSE, pUndoDoc );
2449 pUndoData = new ScRefUndoData( pDoc );
2451 pDoc->BeginDrawUndo();
2454 BOOL bSourceHeight = FALSE; // Hoehen angepasst?
2455 if (bCut)
2457 ScMarkData aDelMark; // only for tables
2458 for (nTab=nStartTab; nTab<=nEndTab; nTab++)
2460 pDoc->DeleteAreaTab( nStartCol,nStartRow, nOldEndCol,nOldEndRow, nTab, IDF_ALL );
2461 aDelMark.SelectTable( nTab, TRUE );
2463 pDoc->DeleteObjectsInArea( nStartCol,nStartRow, nOldEndCol,nOldEndRow, aDelMark );
2465 // Test auf zusammengefasste
2467 if (bClipOver)
2468 if (pDoc->HasAttrib( nDestCol,nDestRow,nDestTab,
2469 nUndoEndCol,nUndoEndRow,nDestEndTab,
2470 HASATTR_MERGED | HASATTR_OVERLAPPED ))
2472 pDoc->CopyFromClip( rSource, aSourceMark, IDF_ALL, pRefUndoDoc, pClipDoc );
2473 for (nTab=nStartTab; nTab<=nEndTab; nTab++)
2475 SCCOL nTmpEndCol = nEndCol;
2476 SCROW nTmpEndRow = nEndRow;
2477 pDoc->ExtendMerge( nStartCol, nStartRow, nTmpEndCol, nTmpEndRow, nTab, TRUE );
2480 // Fehlermeldung erst nach dem Wiederherstellen des Inhalts
2481 if (!bApi) // "Zusammenfassen nicht verschachteln !"
2482 rDocShell.ErrorMessage(STR_MSSG_MOVEBLOCKTO_0);
2484 delete pUndoDoc;
2485 delete pRefUndoDoc;
2486 delete pUndoData;
2487 delete pClipDoc;
2488 return FALSE;
2491 bSourceHeight = AdjustRowHeight( rSource, FALSE );
2494 ScRange aPasteDest( nDestCol, nDestRow, nDestTab, nDestEndCol, nDestEndRow, nDestEndTab );
2496 ScMarkData aDestMark;
2497 for (nTab=nDestTab; nTab<=nDestEndTab; nTab++)
2498 aDestMark.SelectTable( nTab, TRUE ); // Destination selektieren
2499 aDestMark.SetMarkArea( aPasteDest );
2501 /* Do not copy cell notes and drawing objects here. While pasting, the
2502 function ScDocument::UpdateReference() is called which calls
2503 ScDrawLayer::MoveCells() which may move away inserted objects to wrong
2504 positions (e.g. if source and destination range overlaps). Cell notes
2505 and drawing objects are pasted below after doing all adjusting. */
2506 pDoc->CopyFromClip( aPasteDest, aDestMark, IDF_ALL & ~(IDF_NOTE | IDF_OBJECTS),
2507 pRefUndoDoc, pClipDoc, TRUE, FALSE, bIncludeFiltered );
2509 // skipped rows and merged cells don't mix
2510 if ( !bIncludeFiltered && pClipDoc->HasClipFilteredRows() )
2511 UnmergeCells( aPasteDest, FALSE, TRUE );
2513 VirtualDevice aVirtDev;
2514 BOOL bDestHeight = AdjustRowHeight(
2515 ScRange( 0,nDestRow,nDestTab, MAXCOL,nDestEndRow,nDestEndTab ),
2516 FALSE );
2518 /* Paste cell notes and drawing objects after adjusting formula references
2519 and row heights. There are no cell notes or drawing objects, if the
2520 clipdoc does not contain a drawing layer.
2521 #i102056# Passing IDF_NOTE only would overwrite cell contents with
2522 empty note cells, therefore the special modifier IDF_ADDNOTES is passed
2523 here too which changes the behaviour of ScColumn::CopyFromClip() to not
2524 touch existing cells. */
2525 if ( pClipDoc->GetDrawLayer() )
2526 pDoc->CopyFromClip( aPasteDest, aDestMark, IDF_NOTE | IDF_ADDNOTES | IDF_OBJECTS,
2527 pRefUndoDoc, pClipDoc, TRUE, FALSE, bIncludeFiltered );
2529 if (bRecord)
2531 if (pRefUndoDoc)
2533 // alle Tabellen anlegen, damit Formeln kopiert werden koennen:
2534 pUndoDoc->AddUndoTab( 0, nTabCount-1, FALSE, FALSE );
2536 pRefUndoDoc->DeleteArea( nDestCol, nDestRow, nDestEndCol, nDestEndRow, aSourceMark, IDF_ALL );
2537 // kopieren mit bColRowFlags=FALSE (#54194#)
2538 pRefUndoDoc->CopyToDocument( 0, 0, 0, MAXCOL, MAXROW, MAXTAB,
2539 IDF_FORMULA, FALSE, pUndoDoc, NULL, FALSE );
2540 delete pRefUndoDoc;
2543 rDocShell.GetUndoManager()->AddUndoAction(
2544 new ScUndoDragDrop( &rDocShell, ScRange(
2545 nStartCol, nStartRow, nStartTab,
2546 nOldEndCol, nOldEndRow, nEndTab ),
2547 ScAddress( nDestCol, nDestRow, nDestTab ),
2548 bCut, pUndoDoc, pUndoData, bScenariosAdded ) );
2551 SCCOL nDestPaintEndCol = nDestEndCol;
2552 SCROW nDestPaintEndRow = nDestEndRow;
2553 for (nTab=nDestTab; nTab<=nDestEndTab; nTab++)
2555 SCCOL nTmpEndCol = nDestEndCol;
2556 SCROW nTmpEndRow = nDestEndRow;
2557 pDoc->ExtendMerge( nDestCol, nDestRow, nTmpEndCol, nTmpEndRow, nTab, TRUE );
2558 if (nTmpEndCol > nDestPaintEndCol) nDestPaintEndCol = nTmpEndCol;
2559 if (nTmpEndRow > nDestPaintEndRow) nDestPaintEndRow = nTmpEndRow;
2562 if (bCut)
2563 for (nTab=nStartTab; nTab<=nEndTab; nTab++)
2564 pDoc->RefreshAutoFilter( nStartCol, nStartRow, nEndCol, nEndRow, nTab );
2566 if (bPaint)
2568 // Zielbereich:
2570 SCCOL nPaintStartX = nDestCol;
2571 SCROW nPaintStartY = nDestRow;
2572 SCCOL nPaintEndX = nDestPaintEndCol;
2573 SCROW nPaintEndY = nDestPaintEndRow;
2574 USHORT nFlags = PAINT_GRID;
2576 if ( nStartRow==0 && nEndRow==MAXROW ) // Breiten mitkopiert?
2578 nPaintEndX = MAXCOL;
2579 nPaintStartY = 0;
2580 nPaintEndY = MAXROW;
2581 nFlags |= PAINT_TOP;
2583 if ( bDestHeight || ( nStartCol == 0 && nEndCol == MAXCOL ) )
2585 nPaintEndY = MAXROW;
2586 nPaintStartX = 0;
2587 nPaintEndX = MAXCOL;
2588 nFlags |= PAINT_LEFT;
2590 if ( bScenariosAdded )
2592 nPaintStartX = 0;
2593 nPaintStartY = 0;
2594 nPaintEndX = MAXCOL;
2595 nPaintEndY = MAXROW;
2598 rDocShell.PostPaint( nPaintStartX,nPaintStartY,nDestTab,
2599 nPaintEndX,nPaintEndY,nDestEndTab, nFlags, nSourceExt | nDestExt );
2601 if ( bCut )
2603 // Quellbereich:
2605 nPaintStartX = nStartCol;
2606 nPaintStartY = nStartRow;
2607 nPaintEndX = nEndCol;
2608 nPaintEndY = nEndRow;
2609 nFlags = PAINT_GRID;
2611 if ( bSourceHeight )
2613 nPaintEndY = MAXROW;
2614 nPaintStartX = 0;
2615 nPaintEndX = MAXCOL;
2616 nFlags |= PAINT_LEFT;
2618 if ( bScenariosAdded )
2620 nPaintStartX = 0;
2621 nPaintStartY = 0;
2622 nPaintEndX = MAXCOL;
2623 nPaintEndY = MAXROW;
2626 rDocShell.PostPaint( nPaintStartX,nPaintStartY,nStartTab,
2627 nPaintEndX,nPaintEndY,nEndTab, nFlags, nSourceExt );
2631 aModificator.SetDocumentModified();
2633 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
2635 delete pClipDoc;
2636 return TRUE;
2639 //------------------------------------------------------------------------
2640 uno::Reference< uno::XInterface > GetDocModuleObject( SfxObjectShell& rDocSh, String& sCodeName )
2642 uno::Reference< lang::XMultiServiceFactory> xSF(rDocSh.GetModel(), uno::UNO_QUERY);
2643 uno::Reference< container::XNameAccess > xVBACodeNamedObjectAccess;
2644 uno::Reference< uno::XInterface > xDocModuleApiObject;
2645 if ( xSF.is() )
2647 xVBACodeNamedObjectAccess.set( xSF->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAObjectModuleObjectProvider"))), uno::UNO_QUERY );
2648 xDocModuleApiObject.set( xVBACodeNamedObjectAccess->getByName( sCodeName ), uno::UNO_QUERY );
2650 return xDocModuleApiObject;
2654 script::ModuleInfo lcl_InitModuleInfo( SfxObjectShell& rDocSh, String& sModule, String& sSource )
2656 ::rtl::OUString aModName( sModule );
2657 ::rtl::OUString sVbaOption( RTL_CONSTASCII_USTRINGPARAM( "Rem Attribute VBA_ModuleType=VBADocumentModule\nOption VBASupport 1\n" ));
2658 script::ModuleInfo sModuleInfo;
2659 sModuleInfo.ModuleName = aModName;
2660 if ( sSource.Len() > 0 )
2661 sModuleInfo.ModuleSource = sSource;
2662 else
2663 sModuleInfo.ModuleSource = sVbaOption;
2664 sModuleInfo.ModuleType = script::ModuleType::Document;
2665 sModuleInfo.ModuleObject = GetDocModuleObject( rDocSh, sModule );
2666 return sModuleInfo;
2669 void lcl_InsertModule( ScDocShell& rDocSh, SCTAB nTab, String& sModuleName, String& sSource )
2671 SFX_APP()->EnterBasicCall();
2672 script::ModuleInfo sModuleInfo = lcl_InitModuleInfo( rDocSh, sModuleName, sSource );
2673 uno::Reference< script::XLibraryContainer > xLibContainer = rDocSh.GetBasicContainer();
2674 DBG_ASSERT( xLibContainer.is(), "No BasicContainer!" );
2676 uno::Reference< container::XNameContainer > xLib;
2677 if( xLibContainer.is() )
2679 String aLibName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) );
2680 uno::Any aLibAny = xLibContainer->getByName( aLibName );
2681 aLibAny >>= xLib;
2683 if( xLib.is() )
2685 // if the Module with codename exists then find a new name
2686 sal_Int32 nNum = 1;
2687 sModuleInfo.ModuleName = sModuleName;
2688 while( xLib->hasByName( sModuleInfo.ModuleName ) )
2690 sModuleInfo.ModuleName = rtl::OUString::createFromAscii( "Sheet" ) + rtl::OUString::valueOf( nNum );
2691 nNum += 1;
2693 uno::Any aSourceAny;
2694 aSourceAny <<= sModuleInfo;
2695 xLib->insertByName( sModuleInfo.ModuleName, aSourceAny );
2696 ScDocument* pDoc = rDocSh.GetDocument();
2697 String sCodeName( sModuleInfo.ModuleName );
2698 pDoc->SetCodeName( nTab, sCodeName );
2700 SFX_APP()->LeaveBasicCall();
2703 void lcl_DeleteModule( ScDocShell& rDocSh, String& sModuleName )
2705 SFX_APP()->EnterBasicCall();
2706 uno::Reference< script::XLibraryContainer > xLibContainer = rDocSh.GetBasicContainer();
2707 DBG_ASSERT( xLibContainer.is(), "No BasicContainer!" );
2709 uno::Reference< container::XNameContainer > xLib;
2710 if( xLibContainer.is() )
2712 String aLibName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) );
2713 uno::Any aLibAny = xLibContainer->getByName( aLibName );
2714 aLibAny >>= xLib;
2716 if( xLib.is() )
2718 if( xLib->hasByName( sModuleName ) )
2720 xLib->removeByName( sModuleName );
2723 SFX_APP()->LeaveBasicCall();
2727 BOOL ScDocFunc::InsertTable( SCTAB nTab, const String& rName, BOOL bRecord, BOOL bApi )
2729 BOOL bSuccess = FALSE;
2730 WaitObject aWait( rDocShell.GetActiveDialogParent() );
2732 ScDocShellModificator aModificator( rDocShell );
2734 ScDocument* pDoc = rDocShell.GetDocument();
2735 // Strange loop, also basic is loaded too early ( InsertTable )
2736 // is called via the xml import for sheets in described in odf
2737 BOOL bInsertDocModule = false;
2739 if( !rDocShell.GetDocument()->IsImportingXML() )
2741 StarBASIC* pStarBASIC = rDocShell.GetBasic();
2742 bInsertDocModule = pStarBASIC ? pStarBASIC->isVBAEnabled() : false;
2744 if ( bInsertDocModule || ( bRecord && !pDoc->IsUndoEnabled() ) )
2745 bRecord = FALSE;
2747 if (bRecord)
2748 pDoc->BeginDrawUndo(); // InsertTab erzeugt ein SdrUndoNewPage
2750 SCTAB nTabCount = pDoc->GetTableCount();
2751 BOOL bAppend = ( nTab >= nTabCount );
2752 if ( bAppend )
2753 nTab = nTabCount; // wichtig fuer Undo
2755 if (pDoc->InsertTab( nTab, rName ))
2757 String sCodeName;
2758 if (bRecord)
2759 rDocShell.GetUndoManager()->AddUndoAction(
2760 new ScUndoInsertTab( &rDocShell, nTab, bAppend, rName));
2761 // Views updaten:
2762 // Only insert vba modules if vba mode ( and not currently importing XML )
2763 if( bInsertDocModule )
2765 if ( sCodeName.Len() == 0 )
2766 sCodeName = rName;
2767 String sSource;
2768 lcl_InsertModule( rDocShell, nTab, sCodeName, sSource );
2770 rDocShell.Broadcast( ScTablesHint( SC_TAB_INSERTED, nTab ) );
2772 rDocShell.PostPaintExtras();
2773 aModificator.SetDocumentModified();
2774 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2775 bSuccess = TRUE;
2777 else if (!bApi)
2778 rDocShell.ErrorMessage(STR_TABINSERT_ERROR);
2780 return bSuccess;
2783 BOOL ScDocFunc::DeleteTable( SCTAB nTab, BOOL bRecord, BOOL /* bApi */ )
2785 WaitObject aWait( rDocShell.GetActiveDialogParent() );
2787 ScDocShellModificator aModificator( rDocShell );
2789 BOOL bSuccess = FALSE;
2790 ScDocument* pDoc = rDocShell.GetDocument();
2791 StarBASIC* pStarBASIC = rDocShell.GetBasic();
2792 BOOL bVbaEnabled = pStarBASIC->isVBAEnabled();
2793 if (bRecord && !pDoc->IsUndoEnabled())
2794 bRecord = FALSE;
2795 if ( bVbaEnabled )
2796 bRecord = FALSE;
2797 BOOL bWasLinked = pDoc->IsLinked(nTab);
2798 ScDocument* pUndoDoc = NULL;
2799 ScRefUndoData* pUndoData = NULL;
2800 if (bRecord)
2802 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2803 SCTAB nCount = pDoc->GetTableCount();
2805 pUndoDoc->InitUndo( pDoc, nTab, nTab, TRUE, TRUE ); // nur nTab mit Flags
2806 pUndoDoc->AddUndoTab( 0, nCount-1 ); // alle Tabs fuer Referenzen
2808 pDoc->CopyToDocument(0,0,nTab, MAXCOL,MAXROW,nTab, IDF_ALL,FALSE, pUndoDoc );
2809 String aOldName;
2810 pDoc->GetName( nTab, aOldName );
2811 pUndoDoc->RenameTab( nTab, aOldName, FALSE );
2812 if (bWasLinked)
2813 pUndoDoc->SetLink( nTab, pDoc->GetLinkMode(nTab), pDoc->GetLinkDoc(nTab),
2814 pDoc->GetLinkFlt(nTab), pDoc->GetLinkOpt(nTab),
2815 pDoc->GetLinkTab(nTab),
2816 pDoc->GetLinkRefreshDelay(nTab) );
2818 if ( pDoc->IsScenario(nTab) )
2820 pUndoDoc->SetScenario( nTab, TRUE );
2821 String aComment;
2822 Color aColor;
2823 USHORT nScenFlags;
2824 pDoc->GetScenarioData( nTab, aComment, aColor, nScenFlags );
2825 pUndoDoc->SetScenarioData( nTab, aComment, aColor, nScenFlags );
2826 BOOL bActive = pDoc->IsActiveScenario( nTab );
2827 pUndoDoc->SetActiveScenario( nTab, bActive );
2829 pUndoDoc->SetVisible( nTab, pDoc->IsVisible( nTab ) );
2831 // Drawing-Layer muss sein Undo selbst in der Hand behalten !!!
2832 pDoc->BeginDrawUndo(); // DeleteTab erzeugt ein SdrUndoDelPage
2834 pUndoData = new ScRefUndoData( pDoc );
2837 String sCodeName;
2838 BOOL bHasCodeName = pDoc->GetCodeName( nTab, sCodeName );
2839 if (pDoc->DeleteTab( nTab, pUndoDoc ))
2841 if (bRecord)
2843 SvShorts theTabs;
2844 theTabs.Insert(nTab,theTabs.Count());
2845 rDocShell.GetUndoManager()->AddUndoAction(
2846 new ScUndoDeleteTab( &rDocShell, theTabs, pUndoDoc, pUndoData ));
2848 // Views updaten:
2849 if( bVbaEnabled )
2851 if( bHasCodeName )
2853 lcl_DeleteModule( rDocShell, sCodeName );
2856 rDocShell.Broadcast( ScTablesHint( SC_TAB_DELETED, nTab ) );
2858 if (bWasLinked)
2860 rDocShell.UpdateLinks(); // Link-Manager updaten
2861 SfxBindings* pBindings = rDocShell.GetViewBindings();
2862 if (pBindings)
2863 pBindings->Invalidate(SID_LINKS);
2866 rDocShell.PostPaintExtras();
2867 aModificator.SetDocumentModified();
2869 SfxApplication* pSfxApp = SFX_APP(); // Navigator
2870 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2871 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) );
2872 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
2874 bSuccess = TRUE;
2876 else
2878 delete pUndoDoc;
2879 delete pUndoData;
2881 return bSuccess;
2884 BOOL ScDocFunc::SetTableVisible( SCTAB nTab, BOOL bVisible, BOOL bApi )
2886 ScDocument* pDoc = rDocShell.GetDocument();
2887 BOOL bUndo(pDoc->IsUndoEnabled());
2888 if ( pDoc->IsVisible( nTab ) == bVisible )
2889 return TRUE; // nichts zu tun - ok
2891 if ( !pDoc->IsDocEditable() )
2893 if (!bApi)
2894 rDocShell.ErrorMessage(STR_PROTECTIONERR);
2895 return FALSE;
2898 ScDocShellModificator aModificator( rDocShell );
2900 if ( !bVisible && !pDoc->IsImportingXML() ) // #i57869# allow hiding in any order for loading
2902 // nicht alle Tabellen ausblenden
2904 USHORT nVisCount = 0;
2905 SCTAB nCount = pDoc->GetTableCount();
2906 for (SCTAB i=0; i<nCount; i++)
2907 if (pDoc->IsVisible(i))
2908 ++nVisCount;
2910 if (nVisCount <= 1)
2912 if (!bApi)
2913 rDocShell.ErrorMessage(STR_PROTECTIONERR); //! eigene Meldung?
2914 return FALSE;
2918 pDoc->SetVisible( nTab, bVisible );
2919 if (bUndo)
2920 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoShowHideTab( &rDocShell, nTab, bVisible ) );
2922 // Views updaten:
2923 if (!bVisible)
2924 rDocShell.Broadcast( ScTablesHint( SC_TAB_HIDDEN, nTab ) );
2926 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2927 rDocShell.PostPaint(0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_EXTRAS);
2928 aModificator.SetDocumentModified();
2930 return TRUE;
2933 BOOL ScDocFunc::SetLayoutRTL( SCTAB nTab, BOOL bRTL, BOOL /* bApi */ )
2935 ScDocument* pDoc = rDocShell.GetDocument();
2936 BOOL bUndo(pDoc->IsUndoEnabled());
2937 if ( pDoc->IsLayoutRTL( nTab ) == bRTL )
2938 return TRUE; // nothing to do - ok
2940 //! protection (sheet or document?)
2942 ScDocShellModificator aModificator( rDocShell );
2944 pDoc->SetLayoutRTL( nTab, bRTL );
2946 if (bUndo)
2948 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoLayoutRTL( &rDocShell, nTab, bRTL ) );
2951 rDocShell.PostPaint( 0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_ALL );
2952 aModificator.SetDocumentModified();
2954 SfxBindings* pBindings = rDocShell.GetViewBindings();
2955 if (pBindings)
2957 pBindings->Invalidate( FID_TAB_RTL );
2958 pBindings->Invalidate( SID_ATTR_SIZE );
2961 return TRUE;
2964 //UNUSED2009-05 BOOL ScDocFunc::SetGrammar( formula::FormulaGrammar::Grammar eGrammar )
2965 //UNUSED2009-05 {
2966 //UNUSED2009-05 ScDocument* pDoc = rDocShell.GetDocument();
2967 //UNUSED2009-05
2968 //UNUSED2009-05 if ( pDoc->GetGrammar() == eGrammar )
2969 //UNUSED2009-05 return TRUE;
2970 //UNUSED2009-05
2971 //UNUSED2009-05 BOOL bUndo(pDoc->IsUndoEnabled());
2972 //UNUSED2009-05 ScDocShellModificator aModificator( rDocShell );
2973 //UNUSED2009-05
2974 //UNUSED2009-05 pDoc->SetGrammar( eGrammar );
2975 //UNUSED2009-05
2976 //UNUSED2009-05 if (bUndo)
2977 //UNUSED2009-05 {
2978 //UNUSED2009-05 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoSetGrammar( &rDocShell, eGrammar ) );
2979 //UNUSED2009-05 }
2980 //UNUSED2009-05
2981 //UNUSED2009-05 rDocShell.PostPaint( 0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_ALL );
2982 //UNUSED2009-05
2983 //UNUSED2009-05 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
2984 //UNUSED2009-05 if (NULL != pViewSh)
2985 //UNUSED2009-05 {
2986 //UNUSED2009-05 pViewSh->UpdateInputHandler( FALSE, FALSE );
2987 //UNUSED2009-05 }
2988 //UNUSED2009-05
2989 //UNUSED2009-05 aModificator.SetDocumentModified();
2990 //UNUSED2009-05
2991 //UNUSED2009-05 SfxBindings* pBindings = rDocShell.GetViewBindings();
2992 //UNUSED2009-05 if (pBindings)
2993 //UNUSED2009-05 {
2994 //UNUSED2009-05 // erAck: 2006-09-07T22:19+0200 commented out in CWS scr1c1
2995 //UNUSED2009-05 //pBindings->Invalidate( FID_TAB_USE_R1C1 );
2996 //UNUSED2009-05 }
2997 //UNUSED2009-05
2998 //UNUSED2009-05 return TRUE;
2999 //UNUSED2009-05 }
3001 BOOL ScDocFunc::RenameTable( SCTAB nTab, const String& rName, BOOL bRecord, BOOL bApi )
3003 ScDocument* pDoc = rDocShell.GetDocument();
3004 if (bRecord && !pDoc->IsUndoEnabled())
3005 bRecord = FALSE;
3006 if ( !pDoc->IsDocEditable() )
3008 if (!bApi)
3009 rDocShell.ErrorMessage(STR_PROTECTIONERR);
3010 return FALSE;
3013 ScDocShellModificator aModificator( rDocShell );
3015 BOOL bSuccess = FALSE;
3016 String sOldName;
3017 pDoc->GetName(nTab, sOldName);
3018 if (pDoc->RenameTab( nTab, rName ))
3020 if (bRecord)
3022 rDocShell.GetUndoManager()->AddUndoAction(
3023 new ScUndoRenameTab( &rDocShell, nTab, sOldName, rName));
3025 rDocShell.PostPaintExtras();
3026 aModificator.SetDocumentModified();
3027 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
3029 bSuccess = TRUE;
3031 return bSuccess;
3034 BOOL ScDocFunc::SetTabBgColor( SCTAB nTab, const Color& rColor, BOOL bRecord, BOOL bApi )
3037 ScDocument* pDoc = rDocShell.GetDocument();
3038 if (bRecord && !pDoc->IsUndoEnabled())
3039 bRecord = FALSE;
3040 if ( !pDoc->IsDocEditable() || pDoc->IsTabProtected(nTab) )
3042 if (!bApi)
3043 rDocShell.ErrorMessage(STR_PROTECTIONERR); //TODO Check to see what this string is...
3044 return FALSE;
3047 ScViewData* pViewData = rDocShell.GetViewData();
3049 Color aOldTabBgColor;
3050 aOldTabBgColor = pViewData->GetTabBgColor(nTab);
3052 BOOL bSuccess = FALSE;
3053 pViewData->SetTabBgColor(rColor, nTab);
3054 if ( pViewData->GetTabBgColor( nTab ) == rColor)
3055 bSuccess = TRUE;
3056 if (bSuccess)
3058 if (bRecord)
3060 rDocShell.GetUndoManager()->AddUndoAction(
3061 new ScUndoSetTabBgColor( &rDocShell, nTab, aOldTabBgColor, rColor));
3063 rDocShell.PostPaintExtras();
3064 ScDocShellModificator aModificator( rDocShell );
3065 aModificator.SetDocumentModified();
3066 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
3068 bSuccess = TRUE;
3070 return bSuccess;
3073 BOOL ScDocFunc::SetTabBgColor( ScUndoSetTabBgColorInfoList* rUndoSetTabBgColorInfoList, BOOL bRecord, BOOL bApi )
3075 ScDocument* pDoc = rDocShell.GetDocument();
3076 if (bRecord && !pDoc->IsUndoEnabled())
3077 bRecord = FALSE;
3078 if ( !pDoc->IsDocEditable() )
3080 if (!bApi)
3081 rDocShell.ErrorMessage(STR_PROTECTIONERR); //TODO Get a better String Error...
3082 return FALSE;
3085 ScViewData* pViewData = rDocShell.GetViewData();
3086 USHORT nTab;
3087 Color aNewTabBgColor;
3088 ScUndoSetTabBgColorInfo* rUndoSetTabBgColorInfo;
3089 BOOL bSuccess = TRUE;
3090 USHORT nTabProtectCount = 0;
3091 for ( USHORT i=0; i < rUndoSetTabBgColorInfoList->Count(); i++ )
3093 rUndoSetTabBgColorInfo = rUndoSetTabBgColorInfoList->GetObject(i);
3094 nTab = rUndoSetTabBgColorInfo->nTabId;
3095 if ( !pDoc->IsTabProtected(nTab) )
3097 aNewTabBgColor = rUndoSetTabBgColorInfo->aNewTabBgColor;
3098 rUndoSetTabBgColorInfo->aOldTabBgColor = pViewData->GetTabBgColor(nTab);
3099 pViewData->SetTabBgColor(aNewTabBgColor, nTab);
3100 if ( pViewData->GetTabBgColor( nTab ) != aNewTabBgColor)
3102 bSuccess = FALSE;
3103 break;
3106 else
3108 nTabProtectCount++;
3111 if ( nTabProtectCount == rUndoSetTabBgColorInfoList->Count() )
3113 if (!bApi)
3114 rDocShell.ErrorMessage(STR_PROTECTIONERR); //TODO Get a better String Error...
3115 return FALSE;
3117 if (bSuccess)
3119 if (bRecord)
3121 rDocShell.GetUndoManager()->AddUndoAction(
3122 new ScUndoSetTabBgColor( &rDocShell, rUndoSetTabBgColorInfoList));
3124 rDocShell.PostPaintExtras();
3125 ScDocShellModificator aModificator( rDocShell );
3126 aModificator.SetDocumentModified();
3127 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
3129 return bSuccess;
3132 //------------------------------------------------------------------------
3134 //! SetWidthOrHeight - noch doppelt zu ViewFunc !!!!!!
3135 //! Probleme:
3136 //! - Optimale Hoehe fuer Edit-Zellen ist unterschiedlich zwischen Drucker und Bildschirm
3137 //! - Optimale Breite braucht Selektion, um evtl. nur selektierte Zellen zu beruecksichtigen
3139 USHORT lcl_GetOptimalColWidth( ScDocShell& rDocShell, SCCOL nCol, SCTAB nTab, BOOL bFormula )
3141 USHORT nTwips = 0;
3143 ScSizeDeviceProvider aProv(&rDocShell);
3144 OutputDevice* pDev = aProv.GetDevice(); // has pixel MapMode
3145 double nPPTX = aProv.GetPPTX();
3146 double nPPTY = aProv.GetPPTY();
3148 ScDocument* pDoc = rDocShell.GetDocument();
3149 Fraction aOne(1,1);
3150 nTwips = pDoc->GetOptimalColWidth( nCol, nTab, pDev, nPPTX, nPPTY, aOne, aOne,
3151 bFormula, NULL );
3153 return nTwips;
3156 BOOL ScDocFunc::SetWidthOrHeight( BOOL bWidth, SCCOLROW nRangeCnt, SCCOLROW* pRanges, SCTAB nTab,
3157 ScSizeMode eMode, USHORT nSizeTwips,
3158 BOOL bRecord, BOOL bApi )
3160 if (!nRangeCnt)
3161 return TRUE;
3163 ScDocument* pDoc = rDocShell.GetDocument();
3164 if ( bRecord && !pDoc->IsUndoEnabled() )
3165 bRecord = FALSE;
3167 // import into read-only document is possible
3168 if ( !pDoc->IsChangeReadOnlyEnabled() && !rDocShell.IsEditable() )
3170 if (!bApi)
3171 rDocShell.ErrorMessage(STR_PROTECTIONERR); //! eigene Meldung?
3172 return FALSE;
3175 BOOL bSuccess = FALSE;
3176 SCCOLROW nStart = pRanges[0];
3177 SCCOLROW nEnd = pRanges[2*nRangeCnt-1];
3179 BOOL bFormula = FALSE;
3180 if ( eMode == SC_SIZE_OPTIMAL )
3182 //! Option "Formeln anzeigen" - woher nehmen?
3185 ScDocument* pUndoDoc = NULL;
3186 ScOutlineTable* pUndoTab = NULL;
3187 SCCOLROW* pUndoRanges = NULL;
3189 if ( bRecord )
3191 pDoc->BeginDrawUndo(); // Drawing Updates
3193 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
3194 if (bWidth)
3196 pUndoDoc->InitUndo( pDoc, nTab, nTab, TRUE, FALSE );
3197 pDoc->CopyToDocument( static_cast<SCCOL>(nStart), 0, nTab, static_cast<SCCOL>(nEnd), MAXROW, nTab, IDF_NONE, FALSE, pUndoDoc );
3199 else
3201 pUndoDoc->InitUndo( pDoc, nTab, nTab, FALSE, TRUE );
3202 pDoc->CopyToDocument( 0, static_cast<SCROW>(nStart), nTab, MAXCOL, static_cast<SCROW>(nEnd), nTab, IDF_NONE, FALSE, pUndoDoc );
3205 pUndoRanges = new SCCOLROW[ 2*nRangeCnt ];
3206 memmove( pUndoRanges, pRanges, 2*nRangeCnt*sizeof(SCCOLROW) );
3208 ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab );
3209 if (pTable)
3210 pUndoTab = new ScOutlineTable( *pTable );
3213 BOOL bShow = nSizeTwips > 0 || eMode != SC_SIZE_DIRECT;
3214 BOOL bOutline = FALSE;
3216 pDoc->IncSizeRecalcLevel( nTab ); // nicht fuer jede Spalte einzeln
3217 for (SCCOLROW nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++)
3219 SCCOLROW nStartNo = *(pRanges++);
3220 SCCOLROW nEndNo = *(pRanges++);
3222 if ( !bWidth ) // Hoehen immer blockweise
3224 if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
3226 BOOL bAll = ( eMode==SC_SIZE_OPTIMAL );
3227 if (!bAll)
3229 // fuer alle eingeblendeten CR_MANUALSIZE loeschen,
3230 // dann SetOptimalHeight mit bShrink = FALSE
3231 for (SCROW nRow=nStartNo; nRow<=nEndNo; nRow++)
3233 BYTE nOld = pDoc->GetRowFlags(nRow,nTab);
3234 SCROW nLastRow = -1;
3235 bool bHidden = pDoc->RowHidden(nRow, nTab, nLastRow);
3236 if ( !bHidden && ( nOld & CR_MANUALSIZE ) )
3237 pDoc->SetRowFlags( nRow, nTab, nOld & ~CR_MANUALSIZE );
3241 ScSizeDeviceProvider aProv( &rDocShell );
3242 Fraction aOne(1,1);
3243 pDoc->SetOptimalHeight( nStartNo, nEndNo, nTab, 0, aProv.GetDevice(),
3244 aProv.GetPPTX(), aProv.GetPPTY(), aOne, aOne, bAll );
3246 if (bAll)
3247 pDoc->ShowRows( nStartNo, nEndNo, nTab, TRUE );
3249 // Manual-Flag wird bei bAll=TRUE schon in SetOptimalHeight gesetzt
3250 // (an bei Extra-Height, sonst aus).
3252 else if ( eMode==SC_SIZE_DIRECT || eMode==SC_SIZE_ORIGINAL )
3254 if (nSizeTwips)
3256 pDoc->SetRowHeightRange( nStartNo, nEndNo, nTab, nSizeTwips );
3257 pDoc->SetManualHeight( nStartNo, nEndNo, nTab, TRUE ); // height was set manually
3259 if ( eMode != SC_SIZE_ORIGINAL )
3260 pDoc->ShowRows( nStartNo, nEndNo, nTab, nSizeTwips != 0 );
3262 else if ( eMode==SC_SIZE_SHOW )
3264 pDoc->ShowRows( nStartNo, nEndNo, nTab, TRUE );
3267 else // Spaltenbreiten
3269 for (SCCOL nCol=static_cast<SCCOL>(nStartNo); nCol<=static_cast<SCCOL>(nEndNo); nCol++)
3271 SCCOL nLastCol = -1;
3272 if ( eMode != SC_SIZE_VISOPT || !pDoc->ColHidden(nCol, nTab, nLastCol) )
3274 USHORT nThisSize = nSizeTwips;
3276 if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
3277 nThisSize = nSizeTwips +
3278 lcl_GetOptimalColWidth( rDocShell, nCol, nTab, bFormula );
3279 if ( nThisSize )
3280 pDoc->SetColWidth( nCol, nTab, nThisSize );
3282 if ( eMode != SC_SIZE_ORIGINAL )
3283 pDoc->ShowCol( nCol, nTab, bShow );
3288 // adjust outlines
3290 if ( eMode != SC_SIZE_ORIGINAL )
3292 if (bWidth)
3293 bOutline = bOutline || pDoc->UpdateOutlineCol(
3294 static_cast<SCCOL>(nStartNo),
3295 static_cast<SCCOL>(nEndNo), nTab, bShow );
3296 else
3297 bOutline = bOutline || pDoc->UpdateOutlineRow(
3298 static_cast<SCROW>(nStartNo),
3299 static_cast<SCROW>(nEndNo), nTab, bShow );
3302 pDoc->DecSizeRecalcLevel( nTab ); // nicht fuer jede Spalte einzeln
3304 if (!bOutline)
3305 DELETEZ(pUndoTab);
3307 if (bRecord)
3309 ScMarkData aMark;
3310 aMark.SelectOneTable( nTab );
3311 rDocShell.GetUndoManager()->AddUndoAction(
3312 new ScUndoWidthOrHeight( &rDocShell, aMark,
3313 nStart, nTab, nEnd, nTab,
3314 pUndoDoc, nRangeCnt, pUndoRanges,
3315 pUndoTab, eMode, nSizeTwips, bWidth ) );
3318 pDoc->UpdatePageBreaks( nTab );
3320 rDocShell.PostPaint(0,0,nTab,MAXCOL,MAXROW,nTab,PAINT_ALL);
3322 return bSuccess;
3326 BOOL ScDocFunc::InsertPageBreak( BOOL bColumn, const ScAddress& rPos,
3327 BOOL bRecord, BOOL bSetModified, BOOL /* bApi */ )
3329 ScDocShellModificator aModificator( rDocShell );
3331 ScDocument* pDoc = rDocShell.GetDocument();
3332 if (bRecord && !pDoc->IsUndoEnabled())
3333 bRecord = FALSE;
3334 SCTAB nTab = rPos.Tab();
3335 SfxBindings* pBindings = rDocShell.GetViewBindings();
3337 SCCOLROW nPos = bColumn ? static_cast<SCCOLROW>(rPos.Col()) :
3338 static_cast<SCCOLROW>(rPos.Row());
3339 if (nPos == 0)
3340 return FALSE; // erste Spalte / Zeile
3342 ScBreakType nBreak = bColumn ?
3343 pDoc->HasColBreak(static_cast<SCCOL>(nPos), nTab) :
3344 pDoc->HasRowBreak(static_cast<SCROW>(nPos), nTab);
3345 if (nBreak & BREAK_MANUAL)
3346 return true;
3348 if (bRecord)
3349 rDocShell.GetUndoManager()->AddUndoAction(
3350 new ScUndoPageBreak( &rDocShell, rPos.Col(), rPos.Row(), nTab, bColumn, TRUE ) );
3352 if (bColumn)
3353 pDoc->SetColBreak(static_cast<SCCOL>(nPos), nTab, false, true);
3354 else
3355 pDoc->SetRowBreak(static_cast<SCROW>(nPos), nTab, false, true);
3357 pDoc->InvalidatePageBreaks(nTab);
3358 pDoc->UpdatePageBreaks( nTab );
3360 if (bColumn)
3362 rDocShell.PostPaint( static_cast<SCCOL>(nPos)-1, 0, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID );
3363 if (pBindings)
3365 pBindings->Invalidate( FID_INS_COLBRK );
3366 pBindings->Invalidate( FID_DEL_COLBRK );
3369 else
3371 rDocShell.PostPaint( 0, static_cast<SCROW>(nPos)-1, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID );
3372 if (pBindings)
3374 pBindings->Invalidate( FID_INS_ROWBRK );
3375 pBindings->Invalidate( FID_DEL_ROWBRK );
3378 if (pBindings)
3379 pBindings->Invalidate( FID_DEL_MANUALBREAKS );
3381 if (bSetModified)
3382 aModificator.SetDocumentModified();
3384 return TRUE;
3387 BOOL ScDocFunc::RemovePageBreak( BOOL bColumn, const ScAddress& rPos,
3388 BOOL bRecord, BOOL bSetModified, BOOL /* bApi */ )
3390 ScDocShellModificator aModificator( rDocShell );
3392 ScDocument* pDoc = rDocShell.GetDocument();
3393 if (bRecord && !pDoc->IsUndoEnabled())
3394 bRecord = FALSE;
3395 SCTAB nTab = rPos.Tab();
3396 SfxBindings* pBindings = rDocShell.GetViewBindings();
3398 SCCOLROW nPos = bColumn ? static_cast<SCCOLROW>(rPos.Col()) :
3399 static_cast<SCCOLROW>(rPos.Row());
3401 ScBreakType nBreak;
3402 if (bColumn)
3403 nBreak = pDoc->HasColBreak(static_cast<SCCOL>(nPos), nTab);
3404 else
3405 nBreak = pDoc->HasRowBreak(static_cast<SCROW>(nPos), nTab);
3406 if ((nBreak & BREAK_MANUAL) == 0)
3407 // There is no manual break.
3408 return false;
3410 if (bRecord)
3411 rDocShell.GetUndoManager()->AddUndoAction(
3412 new ScUndoPageBreak( &rDocShell, rPos.Col(), rPos.Row(), nTab, bColumn, FALSE ) );
3414 if (bColumn)
3415 pDoc->RemoveColBreak(static_cast<SCCOL>(nPos), nTab, false, true);
3416 else
3417 pDoc->RemoveRowBreak(static_cast<SCROW>(nPos), nTab, false, true);
3419 pDoc->UpdatePageBreaks( nTab );
3421 if (bColumn)
3423 rDocShell.PostPaint( static_cast<SCCOL>(nPos)-1, 0, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID );
3424 if (pBindings)
3426 pBindings->Invalidate( FID_INS_COLBRK );
3427 pBindings->Invalidate( FID_DEL_COLBRK );
3430 else
3432 rDocShell.PostPaint( 0, nPos-1, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID );
3433 if (pBindings)
3435 pBindings->Invalidate( FID_INS_ROWBRK );
3436 pBindings->Invalidate( FID_DEL_ROWBRK );
3439 if (pBindings)
3440 pBindings->Invalidate( FID_DEL_MANUALBREAKS );
3442 if (bSetModified)
3443 aModificator.SetDocumentModified();
3445 return TRUE;
3448 //------------------------------------------------------------------------
3450 void ScDocFunc::ProtectSheet( SCTAB nTab, const ScTableProtection& rProtect )
3452 ScDocument* pDoc = rDocShell.GetDocument();
3454 pDoc->SetTabProtection(nTab, &rProtect);
3455 if (pDoc->IsUndoEnabled())
3457 ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
3458 DBG_ASSERT(pProtect, "ScDocFunc::Unprotect: ScTableProtection pointer is NULL!");
3459 if (pProtect)
3461 ::std::auto_ptr<ScTableProtection> p(new ScTableProtection(*pProtect));
3462 p->setProtected(true); // just in case ...
3463 rDocShell.GetUndoManager()->AddUndoAction(
3464 new ScUndoTabProtect(&rDocShell, nTab, p) );
3466 // ownership of auto_ptr now transferred to ScUndoTabProtect.
3470 rDocShell.PostPaintGridAll();
3471 ScDocShellModificator aModificator(rDocShell);
3472 aModificator.SetDocumentModified();
3475 BOOL ScDocFunc::Protect( SCTAB nTab, const String& rPassword, BOOL /*bApi*/ )
3477 ScDocument* pDoc = rDocShell.GetDocument();
3478 if (nTab == TABLEID_DOC)
3480 // document protection
3481 ScDocProtection aProtection;
3482 aProtection.setProtected(true);
3483 aProtection.setPassword(rPassword);
3484 pDoc->SetDocProtection(&aProtection);
3485 if (pDoc->IsUndoEnabled())
3487 ScDocProtection* pProtect = pDoc->GetDocProtection();
3488 DBG_ASSERT(pProtect, "ScDocFunc::Unprotect: ScDocProtection pointer is NULL!");
3489 if (pProtect)
3491 ::std::auto_ptr<ScDocProtection> p(new ScDocProtection(*pProtect));
3492 p->setProtected(true); // just in case ...
3493 rDocShell.GetUndoManager()->AddUndoAction(
3494 new ScUndoDocProtect(&rDocShell, p) );
3495 // ownership of auto_ptr is transferred to ScUndoDocProtect.
3499 else
3501 // sheet protection
3503 ScTableProtection aProtection;
3504 aProtection.setProtected(true);
3505 aProtection.setPassword(rPassword);
3506 pDoc->SetTabProtection(nTab, &aProtection);
3507 if (pDoc->IsUndoEnabled())
3509 ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
3510 DBG_ASSERT(pProtect, "ScDocFunc::Unprotect: ScTableProtection pointer is NULL!");
3511 if (pProtect)
3513 ::std::auto_ptr<ScTableProtection> p(new ScTableProtection(*pProtect));
3514 p->setProtected(true); // just in case ...
3515 rDocShell.GetUndoManager()->AddUndoAction(
3516 new ScUndoTabProtect(&rDocShell, nTab, p) );
3517 // ownership of auto_ptr now transferred to ScUndoTabProtect.
3522 rDocShell.PostPaintGridAll();
3523 ScDocShellModificator aModificator( rDocShell );
3524 aModificator.SetDocumentModified();
3526 return true;
3529 BOOL ScDocFunc::Unprotect( SCTAB nTab, const String& rPassword, BOOL bApi )
3531 ScDocument* pDoc = rDocShell.GetDocument();
3533 if (nTab == TABLEID_DOC)
3535 // document protection
3537 ScDocProtection* pDocProtect = pDoc->GetDocProtection();
3538 if (!pDocProtect || !pDocProtect->isProtected())
3539 // already unprotected (should not happen)!
3540 return true;
3542 // save the protection state before unprotect (for undo).
3543 ::std::auto_ptr<ScDocProtection> pProtectCopy(new ScDocProtection(*pDocProtect));
3545 if (!pDocProtect->verifyPassword(rPassword))
3547 if (!bApi)
3549 InfoBox aBox( rDocShell.GetActiveDialogParent(), String( ScResId( SCSTR_WRONGPASSWORD ) ) );
3550 aBox.Execute();
3552 return false;
3555 pDoc->SetDocProtection(NULL);
3556 if (pDoc->IsUndoEnabled())
3558 pProtectCopy->setProtected(false);
3559 rDocShell.GetUndoManager()->AddUndoAction(
3560 new ScUndoDocProtect(&rDocShell, pProtectCopy) );
3561 // ownership of auto_ptr now transferred to ScUndoDocProtect.
3564 else
3566 // sheet protection
3568 ScTableProtection* pTabProtect = pDoc->GetTabProtection(nTab);
3569 if (!pTabProtect || !pTabProtect->isProtected())
3570 // already unprotected (should not happen)!
3571 return true;
3573 // save the protection state before unprotect (for undo).
3574 ::std::auto_ptr<ScTableProtection> pProtectCopy(new ScTableProtection(*pTabProtect));
3575 if (!pTabProtect->verifyPassword(rPassword))
3577 if (!bApi)
3579 InfoBox aBox( rDocShell.GetActiveDialogParent(), String( ScResId( SCSTR_WRONGPASSWORD ) ) );
3580 aBox.Execute();
3582 return false;
3585 pDoc->SetTabProtection(nTab, NULL);
3586 if (pDoc->IsUndoEnabled())
3588 pProtectCopy->setProtected(false);
3589 rDocShell.GetUndoManager()->AddUndoAction(
3590 new ScUndoTabProtect(&rDocShell, nTab, pProtectCopy) );
3591 // ownership of auto_ptr now transferred to ScUndoTabProtect.
3595 rDocShell.PostPaintGridAll();
3596 ScDocShellModificator aModificator( rDocShell );
3597 aModificator.SetDocumentModified();
3599 return true;
3602 //------------------------------------------------------------------------
3604 BOOL ScDocFunc::ClearItems( const ScMarkData& rMark, const USHORT* pWhich, BOOL bApi )
3606 ScDocShellModificator aModificator( rDocShell );
3608 ScDocument* pDoc = rDocShell.GetDocument();
3609 BOOL bUndo (pDoc->IsUndoEnabled());
3610 ScEditableTester aTester( pDoc, rMark );
3611 if (!aTester.IsEditable())
3613 if (!bApi)
3614 rDocShell.ErrorMessage(aTester.GetMessageId());
3615 return FALSE;
3618 // #i12940# ClearItems is called (from setPropertyToDefault) directly with uno object's cached
3619 // MarkData (GetMarkData), so rMark must be changed to multi selection for ClearSelectionItems
3620 // here.
3622 ScRange aMarkRange;
3623 ScMarkData aMultiMark = rMark;
3624 aMultiMark.SetMarking(FALSE); // for MarkToMulti
3625 aMultiMark.MarkToMulti();
3626 aMultiMark.GetMultiMarkArea( aMarkRange );
3628 // if (bRecord)
3629 if (bUndo)
3631 SCTAB nStartTab = aMarkRange.aStart.Tab();
3632 SCTAB nEndTab = aMarkRange.aEnd.Tab();
3634 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
3635 pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab );
3636 pDoc->CopyToDocument( aMarkRange, IDF_ATTRIB, TRUE, pUndoDoc, (ScMarkData*)&aMultiMark );
3638 rDocShell.GetUndoManager()->AddUndoAction(
3639 new ScUndoClearItems( &rDocShell, aMultiMark, pUndoDoc, pWhich ) );
3642 pDoc->ClearSelectionItems( pWhich, aMultiMark );
3644 rDocShell.PostPaint( aMarkRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
3645 aModificator.SetDocumentModified();
3647 //! Bindings-Invalidate etc.?
3649 return TRUE;
3652 BOOL ScDocFunc::ChangeIndent( const ScMarkData& rMark, BOOL bIncrement, BOOL bApi )
3654 ScDocShellModificator aModificator( rDocShell );
3656 ScDocument* pDoc = rDocShell.GetDocument();
3657 BOOL bUndo(pDoc->IsUndoEnabled());
3658 ScEditableTester aTester( pDoc, rMark );
3659 if (!aTester.IsEditable())
3661 if (!bApi)
3662 rDocShell.ErrorMessage(aTester.GetMessageId());
3663 return FALSE;
3666 ScRange aMarkRange;
3667 rMark.GetMultiMarkArea( aMarkRange );
3669 // if (bRecord)
3670 if (bUndo)
3672 SCTAB nStartTab = aMarkRange.aStart.Tab();
3673 SCTAB nTabCount = pDoc->GetTableCount();
3675 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
3676 pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab );
3677 for (SCTAB i=0; i<nTabCount; i++)
3678 if (i != nStartTab && rMark.GetTableSelect(i))
3679 pUndoDoc->AddUndoTab( i, i );
3681 ScRange aCopyRange = aMarkRange;
3682 aCopyRange.aStart.SetTab(0);
3683 aCopyRange.aEnd.SetTab(nTabCount-1);
3684 pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, TRUE, pUndoDoc, (ScMarkData*)&rMark );
3686 rDocShell.GetUndoManager()->AddUndoAction(
3687 new ScUndoIndent( &rDocShell, rMark, pUndoDoc, bIncrement ) );
3690 pDoc->ChangeSelectionIndent( bIncrement, rMark );
3692 rDocShell.PostPaint( aMarkRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
3693 aModificator.SetDocumentModified();
3695 SfxBindings* pBindings = rDocShell.GetViewBindings();
3696 if (pBindings)
3698 pBindings->Invalidate( SID_ALIGNLEFT ); // ChangeIndent setzt auf links
3699 pBindings->Invalidate( SID_ALIGNRIGHT );
3700 pBindings->Invalidate( SID_ALIGNBLOCK );
3701 pBindings->Invalidate( SID_ALIGNCENTERHOR );
3702 // pseudo slots for Format menu
3703 pBindings->Invalidate( SID_ALIGN_ANY_HDEFAULT );
3704 pBindings->Invalidate( SID_ALIGN_ANY_LEFT );
3705 pBindings->Invalidate( SID_ALIGN_ANY_HCENTER );
3706 pBindings->Invalidate( SID_ALIGN_ANY_RIGHT );
3707 pBindings->Invalidate( SID_ALIGN_ANY_JUSTIFIED );
3710 return TRUE;
3713 BOOL ScDocFunc::AutoFormat( const ScRange& rRange, const ScMarkData* pTabMark,
3714 USHORT nFormatNo, BOOL bRecord, BOOL bApi )
3716 ScDocShellModificator aModificator( rDocShell );
3718 BOOL bSuccess = FALSE;
3719 ScDocument* pDoc = rDocShell.GetDocument();
3720 SCCOL nStartCol = rRange.aStart.Col();
3721 SCROW nStartRow = rRange.aStart.Row();
3722 SCTAB nStartTab = rRange.aStart.Tab();
3723 SCCOL nEndCol = rRange.aEnd.Col();
3724 SCROW nEndRow = rRange.aEnd.Row();
3725 SCTAB nEndTab = rRange.aEnd.Tab();
3727 if (bRecord && !pDoc->IsUndoEnabled())
3728 bRecord = FALSE;
3729 ScMarkData aMark;
3730 if (pTabMark)
3731 aMark = *pTabMark;
3732 else
3734 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
3735 aMark.SelectTable( nTab, TRUE );
3738 ScAutoFormat* pAutoFormat = ScGlobal::GetAutoFormat();
3739 ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
3740 if ( pAutoFormat && nFormatNo < pAutoFormat->GetCount() && aTester.IsEditable() )
3742 WaitObject aWait( rDocShell.GetActiveDialogParent() );
3744 BOOL bSize = (*pAutoFormat)[nFormatNo]->GetIncludeWidthHeight();
3746 SCTAB nTabCount = pDoc->GetTableCount();
3747 ScDocument* pUndoDoc = NULL;
3748 if ( bRecord )
3750 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
3751 pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab, bSize, bSize );
3752 for (SCTAB i=0; i<nTabCount; i++)
3753 if (i != nStartTab && aMark.GetTableSelect(i))
3754 pUndoDoc->AddUndoTab( i, i, bSize, bSize );
3756 ScRange aCopyRange = rRange;
3757 aCopyRange.aStart.SetTab(0);
3758 aCopyRange.aStart.SetTab(nTabCount-1);
3759 pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, FALSE, pUndoDoc, &aMark );
3760 if (bSize)
3762 pDoc->CopyToDocument( nStartCol,0,0, nEndCol,MAXROW,nTabCount-1,
3763 IDF_NONE, FALSE, pUndoDoc, &aMark );
3764 pDoc->CopyToDocument( 0,nStartRow,0, MAXCOL,nEndRow,nTabCount-1,
3765 IDF_NONE, FALSE, pUndoDoc, &aMark );
3767 pDoc->BeginDrawUndo();
3770 pDoc->AutoFormat( nStartCol, nStartRow, nEndCol, nEndRow, nFormatNo, aMark );
3772 if (bSize)
3774 /* SCCOL nCols[2];
3775 nCols[0] = nStartCol;
3776 nCols[1] = nEndCol;
3777 SCROW nRows[2];
3778 nRows[0] = nStartRow;
3779 nRows[1] = nEndRow;
3781 SCCOLROW nCols[2] = { nStartCol, nEndCol };
3782 SCCOLROW nRows[2] = { nStartRow, nEndRow };
3784 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
3785 if (aMark.GetTableSelect(nTab))
3787 SetWidthOrHeight( TRUE, 1,nCols, nTab, SC_SIZE_VISOPT, STD_EXTRA_WIDTH, FALSE, TRUE);
3788 SetWidthOrHeight( FALSE,1,nRows, nTab, SC_SIZE_VISOPT, 0, FALSE, FALSE);
3789 rDocShell.PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab,
3790 PAINT_GRID | PAINT_LEFT | PAINT_TOP );
3793 else
3795 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
3796 if (aMark.GetTableSelect(nTab))
3798 BOOL bAdj = AdjustRowHeight( ScRange(nStartCol, nStartRow, nTab,
3799 nEndCol, nEndRow, nTab), FALSE );
3800 if (bAdj)
3801 rDocShell.PostPaint( 0,nStartRow,nTab, MAXCOL,MAXROW,nTab,
3802 PAINT_GRID | PAINT_LEFT );
3803 else
3804 rDocShell.PostPaint( nStartCol, nStartRow, nTab,
3805 nEndCol, nEndRow, nTab, PAINT_GRID );
3809 if ( bRecord ) // Draw-Undo erst jetzt verfuegbar
3811 rDocShell.GetUndoManager()->AddUndoAction(
3812 new ScUndoAutoFormat( &rDocShell, rRange, pUndoDoc, aMark, bSize, nFormatNo ) );
3815 aModificator.SetDocumentModified();
3817 else if (!bApi)
3818 rDocShell.ErrorMessage(aTester.GetMessageId());
3820 return bSuccess;
3823 //------------------------------------------------------------------------
3825 BOOL ScDocFunc::EnterMatrix( const ScRange& rRange, const ScMarkData* pTabMark,
3826 const ScTokenArray* pTokenArray, const String& rString, BOOL bApi, BOOL bEnglish,
3827 const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar )
3829 ScDocShellModificator aModificator( rDocShell );
3831 BOOL bSuccess = FALSE;
3832 ScDocument* pDoc = rDocShell.GetDocument();
3833 SCCOL nStartCol = rRange.aStart.Col();
3834 SCROW nStartRow = rRange.aStart.Row();
3835 SCTAB nStartTab = rRange.aStart.Tab();
3836 SCCOL nEndCol = rRange.aEnd.Col();
3837 SCROW nEndRow = rRange.aEnd.Row();
3838 SCTAB nEndTab = rRange.aEnd.Tab();
3840 BOOL bUndo(pDoc->IsUndoEnabled());
3842 ScMarkData aMark;
3843 if (pTabMark)
3844 aMark = *pTabMark;
3845 else
3847 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
3848 aMark.SelectTable( nTab, TRUE );
3851 ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
3852 if ( aTester.IsEditable() )
3854 WaitObject aWait( rDocShell.GetActiveDialogParent() );
3856 ScDocument* pUndoDoc = NULL;
3857 // if (bRecord) // immer
3858 if (bUndo)
3860 //! auch bei Undo selektierte Tabellen beruecksichtigen
3861 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
3862 pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab );
3863 pDoc->CopyToDocument( rRange, IDF_ALL & ~IDF_NOTE, FALSE, pUndoDoc );
3866 // use TokenArray if given, string (and flags) otherwise
3867 if ( pTokenArray )
3869 pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow,
3870 aMark, EMPTY_STRING, pTokenArray, eGrammar);
3872 else if ( pDoc->IsImportingXML() )
3874 ScTokenArray* pCode = lcl_ScDocFunc_CreateTokenArrayXML( rString, rFormulaNmsp, eGrammar );
3875 pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow,
3876 aMark, EMPTY_STRING, pCode, eGrammar);
3877 delete pCode;
3878 pDoc->IncXMLImportedFormulaCount( rString.Len() );
3880 else if (bEnglish)
3882 ScCompiler aComp( pDoc, rRange.aStart);
3883 aComp.SetGrammar(eGrammar);
3884 ScTokenArray* pCode = aComp.CompileString( rString );
3885 pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow,
3886 aMark, EMPTY_STRING, pCode, eGrammar);
3887 delete pCode;
3889 else
3890 pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow,
3891 aMark, rString, NULL, eGrammar);
3893 // if (bRecord) // immer
3894 if (bUndo)
3896 //! auch bei Undo selektierte Tabellen beruecksichtigen
3897 rDocShell.GetUndoManager()->AddUndoAction(
3898 new ScUndoEnterMatrix( &rDocShell, rRange, pUndoDoc, rString ) );
3901 // Err522 beim Paint von DDE-Formeln werden jetzt beim Interpretieren abgefangen
3902 rDocShell.PostPaint( nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab, PAINT_GRID );
3903 aModificator.SetDocumentModified();
3905 bSuccess = TRUE;
3907 else if (!bApi)
3908 rDocShell.ErrorMessage(aTester.GetMessageId());
3910 return bSuccess;
3913 //------------------------------------------------------------------------
3915 BOOL ScDocFunc::TabOp( const ScRange& rRange, const ScMarkData* pTabMark,
3916 const ScTabOpParam& rParam, BOOL bRecord, BOOL bApi )
3918 ScDocShellModificator aModificator( rDocShell );
3920 BOOL bSuccess = FALSE;
3921 ScDocument* pDoc = rDocShell.GetDocument();
3922 SCCOL nStartCol = rRange.aStart.Col();
3923 SCROW nStartRow = rRange.aStart.Row();
3924 SCTAB nStartTab = rRange.aStart.Tab();
3925 SCCOL nEndCol = rRange.aEnd.Col();
3926 SCROW nEndRow = rRange.aEnd.Row();
3927 SCTAB nEndTab = rRange.aEnd.Tab();
3929 if (bRecord && !pDoc->IsUndoEnabled())
3930 bRecord = FALSE;
3932 ScMarkData aMark;
3933 if (pTabMark)
3934 aMark = *pTabMark;
3935 else
3937 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
3938 aMark.SelectTable( nTab, TRUE );
3941 ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
3942 if ( aTester.IsEditable() )
3944 WaitObject aWait( rDocShell.GetActiveDialogParent() );
3945 pDoc->SetDirty( rRange );
3946 if ( bRecord )
3948 //! auch bei Undo selektierte Tabellen beruecksichtigen
3949 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
3950 pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab );
3951 pDoc->CopyToDocument( rRange, IDF_ALL & ~IDF_NOTE, FALSE, pUndoDoc );
3953 rDocShell.GetUndoManager()->AddUndoAction(
3954 new ScUndoTabOp( &rDocShell,
3955 nStartCol, nStartRow, nStartTab,
3956 nEndCol, nEndRow, nEndTab, pUndoDoc,
3957 rParam.aRefFormulaCell,
3958 rParam.aRefFormulaEnd,
3959 rParam.aRefRowCell,
3960 rParam.aRefColCell,
3961 rParam.nMode) );
3963 pDoc->InsertTableOp(rParam, nStartCol, nStartRow, nEndCol, nEndRow, aMark);
3964 rDocShell.PostPaintGridAll();
3965 aModificator.SetDocumentModified();
3966 bSuccess = TRUE;
3968 else if (!bApi)
3969 rDocShell.ErrorMessage(aTester.GetMessageId());
3971 return bSuccess;
3974 //------------------------------------------------------------------------
3976 inline ScDirection DirFromFillDir( FillDir eDir )
3978 if (eDir==FILL_TO_BOTTOM)
3979 return DIR_BOTTOM;
3980 else if (eDir==FILL_TO_RIGHT)
3981 return DIR_RIGHT;
3982 else if (eDir==FILL_TO_TOP)
3983 return DIR_TOP;
3984 else // if (eDir==FILL_TO_LEFT)
3985 return DIR_LEFT;
3988 BOOL ScDocFunc::FillSimple( const ScRange& rRange, const ScMarkData* pTabMark,
3989 FillDir eDir, BOOL bRecord, BOOL bApi )
3991 ScDocShellModificator aModificator( rDocShell );
3993 BOOL bSuccess = FALSE;
3994 ScDocument* pDoc = rDocShell.GetDocument();
3995 SCCOL nStartCol = rRange.aStart.Col();
3996 SCROW nStartRow = rRange.aStart.Row();
3997 SCTAB nStartTab = rRange.aStart.Tab();
3998 SCCOL nEndCol = rRange.aEnd.Col();
3999 SCROW nEndRow = rRange.aEnd.Row();
4000 SCTAB nEndTab = rRange.aEnd.Tab();
4002 if (bRecord && !pDoc->IsUndoEnabled())
4003 bRecord = FALSE;
4005 ScMarkData aMark;
4006 if (pTabMark)
4007 aMark = *pTabMark;
4008 else
4010 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
4011 aMark.SelectTable( nTab, TRUE );
4014 ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
4015 if ( aTester.IsEditable() )
4017 WaitObject aWait( rDocShell.GetActiveDialogParent() );
4019 ScRange aSourceArea = rRange;
4020 ScRange aDestArea = rRange;
4022 SCCOLROW nCount = 0;
4023 switch (eDir)
4025 case FILL_TO_BOTTOM:
4026 nCount = aSourceArea.aEnd.Row()-aSourceArea.aStart.Row();
4027 aSourceArea.aEnd.SetRow( aSourceArea.aStart.Row() );
4028 break;
4029 case FILL_TO_RIGHT:
4030 nCount = aSourceArea.aEnd.Col()-aSourceArea.aStart.Col();
4031 aSourceArea.aEnd.SetCol( aSourceArea.aStart.Col() );
4032 break;
4033 case FILL_TO_TOP:
4034 nCount = aSourceArea.aEnd.Row()-aSourceArea.aStart.Row();
4035 aSourceArea.aStart.SetRow( aSourceArea.aEnd.Row() );
4036 break;
4037 case FILL_TO_LEFT:
4038 nCount = aSourceArea.aEnd.Col()-aSourceArea.aStart.Col();
4039 aSourceArea.aStart.SetCol( aSourceArea.aEnd.Col() );
4040 break;
4043 ScDocument* pUndoDoc = NULL;
4044 if ( bRecord )
4046 SCTAB nTabCount = pDoc->GetTableCount();
4047 SCTAB nDestStartTab = aDestArea.aStart.Tab();
4049 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
4050 pUndoDoc->InitUndo( pDoc, nDestStartTab, nDestStartTab );
4051 for (SCTAB i=0; i<nTabCount; i++)
4052 if (i != nDestStartTab && aMark.GetTableSelect(i))
4053 pUndoDoc->AddUndoTab( i, i );
4055 ScRange aCopyRange = aDestArea;
4056 aCopyRange.aStart.SetTab(0);
4057 aCopyRange.aEnd.SetTab(nTabCount-1);
4058 pDoc->CopyToDocument( aCopyRange, IDF_AUTOFILL, FALSE, pUndoDoc, &aMark );
4061 pDoc->Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(),
4062 aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aMark,
4063 nCount, eDir, FILL_SIMPLE );
4064 AdjustRowHeight(rRange);
4066 if ( bRecord ) // Draw-Undo erst jetzt verfuegbar
4068 rDocShell.GetUndoManager()->AddUndoAction(
4069 new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark,
4070 eDir, FILL_SIMPLE, FILL_DAY, MAXDOUBLE, 1.0, 1e307,
4071 pDoc->GetRangeName()->GetSharedMaxIndex()+1 ) );
4074 rDocShell.PostPaintGridAll();
4075 // rDocShell.PostPaintDataChanged();
4076 aModificator.SetDocumentModified();
4078 bSuccess = TRUE;
4080 else if (!bApi)
4081 rDocShell.ErrorMessage(aTester.GetMessageId());
4083 return bSuccess;
4086 BOOL ScDocFunc::FillSeries( const ScRange& rRange, const ScMarkData* pTabMark,
4087 FillDir eDir, FillCmd eCmd, FillDateCmd eDateCmd,
4088 double fStart, double fStep, double fMax,
4089 BOOL bRecord, BOOL bApi )
4091 ScDocShellModificator aModificator( rDocShell );
4093 BOOL bSuccess = FALSE;
4094 ScDocument* pDoc = rDocShell.GetDocument();
4095 SCCOL nStartCol = rRange.aStart.Col();
4096 SCROW nStartRow = rRange.aStart.Row();
4097 SCTAB nStartTab = rRange.aStart.Tab();
4098 SCCOL nEndCol = rRange.aEnd.Col();
4099 SCROW nEndRow = rRange.aEnd.Row();
4100 SCTAB nEndTab = rRange.aEnd.Tab();
4102 if (bRecord && !pDoc->IsUndoEnabled())
4103 bRecord = FALSE;
4105 ScMarkData aMark;
4106 if (pTabMark)
4107 aMark = *pTabMark;
4108 else
4110 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
4111 aMark.SelectTable( nTab, TRUE );
4114 ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
4115 if ( aTester.IsEditable() )
4117 WaitObject aWait( rDocShell.GetActiveDialogParent() );
4119 ScRange aSourceArea = rRange;
4120 ScRange aDestArea = rRange;
4122 SCSIZE nCount = pDoc->GetEmptyLinesInBlock(
4123 aSourceArea.aStart.Col(), aSourceArea.aStart.Row(), aSourceArea.aStart.Tab(),
4124 aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aSourceArea.aEnd.Tab(),
4125 DirFromFillDir(eDir) );
4127 // #27665# mindestens eine Zeile/Spalte als Quellbereich behalten:
4128 SCSIZE nTotLines = ( eDir == FILL_TO_BOTTOM || eDir == FILL_TO_TOP ) ?
4129 static_cast<SCSIZE>( aSourceArea.aEnd.Row() - aSourceArea.aStart.Row() + 1 ) :
4130 static_cast<SCSIZE>( aSourceArea.aEnd.Col() - aSourceArea.aStart.Col() + 1 );
4131 if ( nCount >= nTotLines )
4132 nCount = nTotLines - 1;
4134 switch (eDir)
4136 case FILL_TO_BOTTOM:
4137 aSourceArea.aEnd.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aEnd.Row() - nCount ) );
4138 break;
4139 case FILL_TO_RIGHT:
4140 aSourceArea.aEnd.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aEnd.Col() - nCount ) );
4141 break;
4142 case FILL_TO_TOP:
4143 aSourceArea.aStart.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aStart.Row() + nCount ) );
4144 break;
4145 case FILL_TO_LEFT:
4146 aSourceArea.aStart.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aStart.Col() + nCount ) );
4147 break;
4150 ScDocument* pUndoDoc = NULL;
4151 if ( bRecord )
4153 SCTAB nTabCount = pDoc->GetTableCount();
4154 SCTAB nDestStartTab = aDestArea.aStart.Tab();
4156 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
4157 pUndoDoc->InitUndo( pDoc, nDestStartTab, nDestStartTab );
4158 for (SCTAB i=0; i<nTabCount; i++)
4159 if (i != nDestStartTab && aMark.GetTableSelect(i))
4160 pUndoDoc->AddUndoTab( i, i );
4162 pDoc->CopyToDocument(
4163 aDestArea.aStart.Col(), aDestArea.aStart.Row(), 0,
4164 aDestArea.aEnd.Col(), aDestArea.aEnd.Row(), nTabCount-1,
4165 IDF_AUTOFILL, FALSE, pUndoDoc, &aMark );
4168 if (aDestArea.aStart.Col() <= aDestArea.aEnd.Col() &&
4169 aDestArea.aStart.Row() <= aDestArea.aEnd.Row())
4171 if ( fStart != MAXDOUBLE )
4173 SCCOL nValX = (eDir == FILL_TO_LEFT) ? aDestArea.aEnd.Col() : aDestArea.aStart.Col();
4174 SCROW nValY = (eDir == FILL_TO_TOP ) ? aDestArea.aEnd.Row() : aDestArea.aStart.Row();
4175 SCTAB nTab = aDestArea.aStart.Tab();
4176 pDoc->SetValue( nValX, nValY, nTab, fStart );
4178 pDoc->Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(),
4179 aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aMark,
4180 nCount, eDir, eCmd, eDateCmd, fStep, fMax );
4181 AdjustRowHeight(rRange);
4183 rDocShell.PostPaintGridAll();
4184 // rDocShell.PostPaintDataChanged();
4185 aModificator.SetDocumentModified();
4188 if ( bRecord ) // Draw-Undo erst jetzt verfuegbar
4190 rDocShell.GetUndoManager()->AddUndoAction(
4191 new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark,
4192 eDir, eCmd, eDateCmd, fStart, fStep, fMax,
4193 pDoc->GetRangeName()->GetSharedMaxIndex()+1 ) );
4196 bSuccess = TRUE;
4198 else if (!bApi)
4199 rDocShell.ErrorMessage(aTester.GetMessageId());
4201 return bSuccess;
4204 BOOL ScDocFunc::FillAuto( ScRange& rRange, const ScMarkData* pTabMark,
4205 FillDir eDir, ULONG nCount, BOOL bRecord, BOOL bApi )
4207 double fStep = 1.0;
4208 double fMax = MAXDOUBLE;
4209 return FillAuto( rRange, pTabMark, eDir, FILL_AUTO, FILL_DAY, nCount, fStep, fMax, bRecord, bApi );
4212 BOOL ScDocFunc::FillAuto( ScRange& rRange, const ScMarkData* pTabMark, FillDir eDir, FillCmd eCmd, FillDateCmd eDateCmd, ULONG nCount, double fStep, double fMax, BOOL bRecord, BOOL bApi )
4214 ScDocShellModificator aModificator( rDocShell );
4216 ScDocument* pDoc = rDocShell.GetDocument();
4217 SCCOL nStartCol = rRange.aStart.Col();
4218 SCROW nStartRow = rRange.aStart.Row();
4219 SCTAB nStartTab = rRange.aStart.Tab();
4220 SCCOL nEndCol = rRange.aEnd.Col();
4221 SCROW nEndRow = rRange.aEnd.Row();
4222 SCTAB nEndTab = rRange.aEnd.Tab();
4224 if (bRecord && !pDoc->IsUndoEnabled())
4225 bRecord = FALSE;
4227 ScMarkData aMark;
4228 if (pTabMark)
4229 aMark = *pTabMark;
4230 else
4232 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
4233 aMark.SelectTable( nTab, TRUE );
4236 ScRange aSourceArea = rRange;
4237 ScRange aDestArea = rRange;
4240 switch (eDir)
4242 case FILL_TO_BOTTOM:
4243 aDestArea.aEnd.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aEnd.Row() + nCount ) );
4244 break;
4245 case FILL_TO_TOP:
4246 if (nCount > sal::static_int_cast<ULONG>( aSourceArea.aStart.Row() ))
4248 DBG_ERROR("FillAuto: Row < 0");
4249 nCount = aSourceArea.aStart.Row();
4251 aDestArea.aStart.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aStart.Row() - nCount ) );
4252 break;
4253 case FILL_TO_RIGHT:
4254 aDestArea.aEnd.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aEnd.Col() + nCount ) );
4255 break;
4256 case FILL_TO_LEFT:
4257 if (nCount > sal::static_int_cast<ULONG>( aSourceArea.aStart.Col() ))
4259 DBG_ERROR("FillAuto: Col < 0");
4260 nCount = aSourceArea.aStart.Col();
4262 aDestArea.aStart.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aStart.Col() - nCount ) );
4263 break;
4264 default:
4265 DBG_ERROR("Falsche Richtung bei FillAuto");
4266 break;
4269 // Zellschutz testen
4270 //! Quellbereich darf geschuetzt sein !!!
4271 //! aber kein Matrixfragment enthalten !!!
4273 ScEditableTester aTester( pDoc, aDestArea );
4274 if ( !aTester.IsEditable() )
4276 if (!bApi)
4277 rDocShell.ErrorMessage(aTester.GetMessageId());
4278 return FALSE;
4281 if ( pDoc->HasSelectedBlockMatrixFragment( nStartCol, nStartRow,
4282 nEndCol, nEndRow, aMark ) )
4284 if (!bApi)
4285 rDocShell.ErrorMessage(STR_MATRIXFRAGMENTERR);
4286 return FALSE;
4289 WaitObject aWait( rDocShell.GetActiveDialogParent() );
4291 ScDocument* pUndoDoc = NULL;
4292 if ( bRecord )
4294 SCTAB nTabCount = pDoc->GetTableCount();
4295 SCTAB nDestStartTab = aDestArea.aStart.Tab();
4297 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
4298 pUndoDoc->InitUndo( pDoc, nDestStartTab, nDestStartTab );
4299 for (SCTAB i=0; i<nTabCount; i++)
4300 if (i != nDestStartTab && aMark.GetTableSelect(i))
4301 pUndoDoc->AddUndoTab( i, i );
4303 // do not clone note captions in undo document
4304 pDoc->CopyToDocument(
4305 aDestArea.aStart.Col(), aDestArea.aStart.Row(), 0,
4306 aDestArea.aEnd.Col(), aDestArea.aEnd.Row(), nTabCount-1,
4307 IDF_AUTOFILL, FALSE, pUndoDoc, &aMark );
4310 pDoc->Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(),
4311 aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aMark,
4312 nCount, eDir, eCmd, eDateCmd, fStep, fMax );
4314 AdjustRowHeight(aDestArea);
4316 if ( bRecord ) // Draw-Undo erst jetzt verfuegbar
4318 rDocShell.GetUndoManager()->AddUndoAction(
4319 new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark,
4320 eDir, eCmd, eDateCmd, MAXDOUBLE, fStep, fMax,
4321 pDoc->GetRangeName()->GetSharedMaxIndex()+1 ) );
4324 rDocShell.PostPaintGridAll();
4325 // rDocShell.PostPaintDataChanged();
4326 aModificator.SetDocumentModified();
4328 rRange = aDestArea; // Zielbereich zurueckgeben (zum Markieren)
4329 return TRUE;
4332 //------------------------------------------------------------------------
4334 BOOL ScDocFunc::MergeCells( const ScCellMergeOption& rOption, BOOL bContents, BOOL bRecord, BOOL bApi )
4336 using ::std::set;
4338 ScDocShellModificator aModificator( rDocShell );
4340 SCCOL nStartCol = rOption.mnStartCol;
4341 SCROW nStartRow = rOption.mnStartRow;
4342 SCCOL nEndCol = rOption.mnEndCol;
4343 SCROW nEndRow = rOption.mnEndRow;
4344 if ((nStartCol == nEndCol && nStartRow == nEndRow) || rOption.maTabs.empty())
4346 // Nothing to do. Bail out quick.
4347 return TRUE;
4350 ScDocument* pDoc = rDocShell.GetDocument();
4351 set<SCTAB>::const_iterator itrBeg = rOption.maTabs.begin(), itrEnd = rOption.maTabs.end();
4352 SCTAB nTab1 = *itrBeg, nTab2 = *rOption.maTabs.rbegin();
4354 if (bRecord && !pDoc->IsUndoEnabled())
4355 bRecord = FALSE;
4357 for (set<SCTAB>::const_iterator itr = itrBeg; itr != itrEnd; ++itr)
4359 ScEditableTester aTester( pDoc, *itr, nStartCol, nStartRow, nEndCol, nEndRow );
4360 if (!aTester.IsEditable())
4362 if (!bApi)
4363 rDocShell.ErrorMessage(aTester.GetMessageId());
4364 return FALSE;
4367 if ( pDoc->HasAttrib( nStartCol, nStartRow, *itr, nEndCol, nEndRow, *itr,
4368 HASATTR_MERGED | HASATTR_OVERLAPPED ) )
4370 // "Zusammenfassen nicht verschachteln !"
4371 if (!bApi)
4372 rDocShell.ErrorMessage(STR_MSSG_MERGECELLS_0);
4373 return FALSE;
4377 ScDocument* pUndoDoc = NULL;
4378 bool bNeedContentsUndo = false;
4379 for (set<SCTAB>::const_iterator itr = itrBeg; itr != itrEnd; ++itr)
4381 SCTAB nTab = *itr;
4382 bool bNeedContents = bContents &&
4383 ( !pDoc->IsBlockEmpty( nTab, nStartCol,nStartRow+1, nStartCol,nEndRow, true ) ||
4384 !pDoc->IsBlockEmpty( nTab, nStartCol+1,nStartRow, nEndCol,nEndRow, true ) );
4386 if (bRecord)
4388 // test if the range contains other notes which also implies that we need an undo document
4389 bool bHasNotes = false;
4390 for( ScAddress aPos( nStartCol, nStartRow, nTab ); !bHasNotes && (aPos.Col() <= nEndCol); aPos.IncCol() )
4391 for( aPos.SetRow( nStartRow ); !bHasNotes && (aPos.Row() <= nEndRow); aPos.IncRow() )
4392 bHasNotes = ((aPos.Col() != nStartCol) || (aPos.Row() != nStartRow)) && (pDoc->GetNote( aPos ) != 0);
4394 if (bNeedContents || bHasNotes || rOption.mbCenter)
4396 if (!pUndoDoc)
4398 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
4399 pUndoDoc->InitUndo(pDoc, nTab1, nTab2);
4401 // note captions are collected by drawing undo
4402 pDoc->CopyToDocument( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab,
4403 IDF_ALL|IDF_NOCAPTIONS, FALSE, pUndoDoc );
4405 if( bHasNotes )
4406 pDoc->BeginDrawUndo();
4409 if (bNeedContents)
4410 pDoc->DoMergeContents( nTab, nStartCol,nStartRow, nEndCol,nEndRow );
4411 pDoc->DoMerge( nTab, nStartCol,nStartRow, nEndCol,nEndRow );
4413 if (rOption.mbCenter)
4415 pDoc->ApplyAttr( nStartCol, nStartRow, nTab, SvxHorJustifyItem( SVX_HOR_JUSTIFY_CENTER, ATTR_HOR_JUSTIFY ) );
4416 pDoc->ApplyAttr( nStartCol, nStartRow, nTab, SvxVerJustifyItem( SVX_VER_JUSTIFY_CENTER, ATTR_VER_JUSTIFY ) );
4419 if ( !AdjustRowHeight( ScRange( 0,nStartRow,nTab, MAXCOL,nEndRow,nTab ) ) )
4420 rDocShell.PostPaint( nStartCol, nStartRow, nTab,
4421 nEndCol, nEndRow, nTab, PAINT_GRID );
4422 if (bNeedContents || rOption.mbCenter)
4424 ScRange aRange(nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab);
4425 pDoc->SetDirty(aRange);
4428 bNeedContentsUndo |= bNeedContents;
4431 if (pUndoDoc)
4433 SdrUndoGroup* pDrawUndo = pDoc->GetDrawLayer() ? pDoc->GetDrawLayer()->GetCalcUndo() : NULL;
4434 rDocShell.GetUndoManager()->AddUndoAction(
4435 new ScUndoMerge(&rDocShell, rOption, bNeedContentsUndo, pUndoDoc, pDrawUndo) );
4438 aModificator.SetDocumentModified();
4440 SfxBindings* pBindings = rDocShell.GetViewBindings();
4441 if (pBindings)
4443 pBindings->Invalidate( FID_MERGE_ON );
4444 pBindings->Invalidate( FID_MERGE_OFF );
4445 pBindings->Invalidate( FID_MERGE_TOGGLE );
4448 return TRUE;
4451 BOOL ScDocFunc::UnmergeCells( const ScRange& rRange, BOOL bRecord, BOOL bApi )
4453 ScCellMergeOption aOption(rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row());
4454 SCTAB nTab1 = rRange.aStart.Tab(), nTab2 = rRange.aEnd.Tab();
4455 for (SCTAB i = nTab1; i <= nTab2; ++i)
4456 aOption.maTabs.insert(i);
4458 return UnmergeCells(aOption, bRecord, bApi);
4461 bool ScDocFunc::UnmergeCells( const ScCellMergeOption& rOption, BOOL bRecord, BOOL bApi )
4463 using ::std::set;
4465 if (rOption.maTabs.empty())
4466 // Nothing to unmerge.
4467 return true;
4469 ScDocShellModificator aModificator( rDocShell );
4470 ScDocument* pDoc = rDocShell.GetDocument();
4472 if (bRecord && !pDoc->IsUndoEnabled())
4473 bRecord = FALSE;
4475 ScDocument* pUndoDoc = NULL;
4476 bool bBeep = false;
4477 for (set<SCTAB>::const_iterator itr = rOption.maTabs.begin(), itrEnd = rOption.maTabs.end();
4478 itr != itrEnd; ++itr)
4480 SCTAB nTab = *itr;
4481 ScRange aRange = rOption.getSingleRange(nTab);
4482 if ( !pDoc->HasAttrib(aRange, HASATTR_MERGED) )
4484 bBeep = true;
4485 continue;
4488 ScRange aExtended = aRange;
4489 pDoc->ExtendMerge(aExtended);
4490 ScRange aRefresh = aExtended;
4491 pDoc->ExtendOverlapped(aRefresh);
4493 if (bRecord)
4495 if (!pUndoDoc)
4497 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
4498 pUndoDoc->InitUndo(pDoc, *rOption.maTabs.begin(), *rOption.maTabs.rbegin());
4500 pDoc->CopyToDocument(aExtended, IDF_ATTRIB, FALSE, pUndoDoc);
4503 const SfxPoolItem& rDefAttr = pDoc->GetPool()->GetDefaultItem( ATTR_MERGE );
4504 ScPatternAttr aPattern( pDoc->GetPool() );
4505 aPattern.GetItemSet().Put( rDefAttr );
4506 pDoc->ApplyPatternAreaTab( aRange.aStart.Col(), aRange.aStart.Row(),
4507 aRange.aEnd.Col(), aRange.aEnd.Row(), nTab,
4508 aPattern );
4510 pDoc->RemoveFlagsTab( aExtended.aStart.Col(), aExtended.aStart.Row(),
4511 aExtended.aEnd.Col(), aExtended.aEnd.Row(), nTab,
4512 SC_MF_HOR | SC_MF_VER );
4514 pDoc->ExtendMerge( aRefresh, TRUE, FALSE );
4516 if ( !AdjustRowHeight( aExtended ) )
4517 rDocShell.PostPaint( aExtended, PAINT_GRID );
4519 if (bBeep && !bApi)
4520 Sound::Beep();
4522 if (bRecord)
4524 rDocShell.GetUndoManager()->AddUndoAction(
4525 new ScUndoRemoveMerge( &rDocShell, rOption, pUndoDoc ) );
4527 aModificator.SetDocumentModified();
4529 return TRUE;
4532 //------------------------------------------------------------------------
4534 BOOL ScDocFunc::ModifyRangeNames( const ScRangeName& rNewRanges, BOOL bApi )
4536 return SetNewRangeNames( new ScRangeName( rNewRanges ), bApi );
4539 BOOL ScDocFunc::SetNewRangeNames( ScRangeName* pNewRanges, BOOL /* bApi */ ) // takes ownership of pNewRanges
4541 ScDocShellModificator aModificator( rDocShell );
4543 DBG_ASSERT( pNewRanges, "pNewRanges is 0" );
4544 ScDocument* pDoc = rDocShell.GetDocument();
4545 BOOL bUndo(pDoc->IsUndoEnabled());
4547 if (bUndo)
4549 ScRangeName* pOld = pDoc->GetRangeName();
4550 ScRangeName* pUndoRanges = new ScRangeName(*pOld);
4551 ScRangeName* pRedoRanges = new ScRangeName(*pNewRanges);
4552 rDocShell.GetUndoManager()->AddUndoAction(
4553 new ScUndoRangeNames( &rDocShell, pUndoRanges, pRedoRanges ) );
4556 // #i55926# While loading XML, formula cells only have a single string token,
4557 // so CompileNameFormula would never find any name (index) tokens, and would
4558 // unnecessarily loop through all cells.
4559 BOOL bCompile = ( !pDoc->IsImportingXML() && pDoc->GetNamedRangesLockCount() == 0 );
4561 if ( bCompile )
4562 pDoc->CompileNameFormula( TRUE ); // CreateFormulaString
4563 pDoc->SetRangeName( pNewRanges ); // takes ownership
4564 if ( bCompile )
4565 pDoc->CompileNameFormula( FALSE ); // CompileFormulaString
4567 aModificator.SetDocumentModified();
4568 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) );
4570 return TRUE;
4573 //------------------------------------------------------------------------
4575 void ScDocFunc::CreateOneName( ScRangeName& rList,
4576 SCCOL nPosX, SCROW nPosY, SCTAB nTab,
4577 SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
4578 BOOL& rCancel, BOOL bApi )
4580 if (rCancel)
4581 return;
4583 ScDocument* pDoc = rDocShell.GetDocument();
4584 if (!pDoc->HasValueData( nPosX, nPosY, nTab ))
4586 String aName;
4587 pDoc->GetString( nPosX, nPosY, nTab, aName );
4588 ScRangeData::MakeValidName(aName);
4589 if (aName.Len())
4591 String aContent;
4592 ScRange( nX1, nY1, nTab, nX2, nY2, nTab ).Format( aContent, SCR_ABS_3D, pDoc );
4594 BOOL bInsert = FALSE;
4595 USHORT nOldPos;
4596 if (rList.SearchName( aName, nOldPos )) // vorhanden ?
4598 ScRangeData* pOld = rList[nOldPos];
4599 String aOldStr;
4600 pOld->GetSymbol( aOldStr );
4601 if (aOldStr != aContent)
4603 if (bApi)
4604 bInsert = TRUE; // per API nicht nachfragen
4605 else
4607 String aTemplate = ScGlobal::GetRscString( STR_CREATENAME_REPLACE );
4609 String aMessage = aTemplate.GetToken( 0, '#' );
4610 aMessage += aName;
4611 aMessage += aTemplate.GetToken( 1, '#' );
4613 short nResult = QueryBox( rDocShell.GetActiveDialogParent(),
4614 WinBits(WB_YES_NO_CANCEL | WB_DEF_YES),
4615 aMessage ).Execute();
4616 if ( nResult == RET_YES )
4618 rList.AtFree(nOldPos);
4619 bInsert = TRUE;
4621 else if ( nResult == RET_CANCEL )
4622 rCancel = TRUE;
4626 else
4627 bInsert = TRUE;
4629 if (bInsert)
4631 ScRangeData* pData = new ScRangeData( pDoc, aName, aContent,
4632 ScAddress( nPosX, nPosY, nTab));
4633 if (!rList.Insert(pData))
4635 DBG_ERROR("nanu?");
4636 delete pData;
4643 BOOL ScDocFunc::CreateNames( const ScRange& rRange, USHORT nFlags, BOOL bApi )
4645 if (!nFlags)
4646 return FALSE; // war nix
4648 ScDocShellModificator aModificator( rDocShell );
4650 BOOL bDone = FALSE;
4651 SCCOL nStartCol = rRange.aStart.Col();
4652 SCROW nStartRow = rRange.aStart.Row();
4653 SCCOL nEndCol = rRange.aEnd.Col();
4654 SCROW nEndRow = rRange.aEnd.Row();
4655 SCTAB nTab = rRange.aStart.Tab();
4656 DBG_ASSERT(rRange.aEnd.Tab() == nTab, "CreateNames: mehrere Tabellen geht nicht");
4658 BOOL bValid = TRUE;
4659 if ( nFlags & ( NAME_TOP | NAME_BOTTOM ) )
4660 if ( nStartRow == nEndRow )
4661 bValid = FALSE;
4662 if ( nFlags & ( NAME_LEFT | NAME_RIGHT ) )
4663 if ( nStartCol == nEndCol )
4664 bValid = FALSE;
4666 if (bValid)
4668 ScDocument* pDoc = rDocShell.GetDocument();
4669 ScRangeName* pNames = pDoc->GetRangeName();
4670 if (!pNames)
4671 return FALSE; // soll nicht sein
4672 ScRangeName aNewRanges( *pNames );
4674 BOOL bTop = ( ( nFlags & NAME_TOP ) != 0 );
4675 BOOL bLeft = ( ( nFlags & NAME_LEFT ) != 0 );
4676 BOOL bBottom = ( ( nFlags & NAME_BOTTOM ) != 0 );
4677 BOOL bRight = ( ( nFlags & NAME_RIGHT ) != 0 );
4679 SCCOL nContX1 = nStartCol;
4680 SCROW nContY1 = nStartRow;
4681 SCCOL nContX2 = nEndCol;
4682 SCROW nContY2 = nEndRow;
4684 if ( bTop )
4685 ++nContY1;
4686 if ( bLeft )
4687 ++nContX1;
4688 if ( bBottom )
4689 --nContY2;
4690 if ( bRight )
4691 --nContX2;
4693 BOOL bCancel = FALSE;
4694 SCCOL i;
4695 SCROW j;
4697 if ( bTop )
4698 for (i=nContX1; i<=nContX2; i++)
4699 CreateOneName( aNewRanges, i,nStartRow,nTab, i,nContY1,i,nContY2, bCancel, bApi );
4700 if ( bLeft )
4701 for (j=nContY1; j<=nContY2; j++)
4702 CreateOneName( aNewRanges, nStartCol,j,nTab, nContX1,j,nContX2,j, bCancel, bApi );
4703 if ( bBottom )
4704 for (i=nContX1; i<=nContX2; i++)
4705 CreateOneName( aNewRanges, i,nEndRow,nTab, i,nContY1,i,nContY2, bCancel, bApi );
4706 if ( bRight )
4707 for (j=nContY1; j<=nContY2; j++)
4708 CreateOneName( aNewRanges, nEndCol,j,nTab, nContX1,j,nContX2,j, bCancel, bApi );
4710 if ( bTop && bLeft )
4711 CreateOneName( aNewRanges, nStartCol,nStartRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
4712 if ( bTop && bRight )
4713 CreateOneName( aNewRanges, nEndCol,nStartRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
4714 if ( bBottom && bLeft )
4715 CreateOneName( aNewRanges, nStartCol,nEndRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
4716 if ( bBottom && bRight )
4717 CreateOneName( aNewRanges, nEndCol,nEndRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
4719 bDone = ModifyRangeNames( aNewRanges, bApi );
4721 aModificator.SetDocumentModified();
4722 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) );
4725 return bDone;
4728 //------------------------------------------------------------------------
4730 BOOL ScDocFunc::InsertNameList( const ScAddress& rStartPos, BOOL bApi )
4732 ScDocShellModificator aModificator( rDocShell );
4735 BOOL bDone = FALSE;
4736 ScDocument* pDoc = rDocShell.GetDocument();
4737 const BOOL bRecord = pDoc->IsUndoEnabled();
4738 SCTAB nTab = rStartPos.Tab();
4739 ScDocument* pUndoDoc = NULL;
4741 ScRangeName* pList = pDoc->GetRangeName();
4742 USHORT nCount = pList->GetCount();
4743 USHORT nValidCount = 0;
4744 USHORT i;
4745 for (i=0; i<nCount; i++)
4747 ScRangeData* pData = (*pList)[i];
4748 if ( !pData->HasType( RT_DATABASE ) && !pData->HasType( RT_SHARED ) )
4749 ++nValidCount;
4752 if (nValidCount)
4754 SCCOL nStartCol = rStartPos.Col();
4755 SCROW nStartRow = rStartPos.Row();
4756 SCCOL nEndCol = nStartCol + 1;
4757 SCROW nEndRow = nStartRow + static_cast<SCROW>(nValidCount) - 1;
4759 ScEditableTester aTester( pDoc, nTab, nStartCol,nStartRow, nEndCol,nEndRow );
4760 if (aTester.IsEditable())
4762 if (bRecord)
4764 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
4765 pUndoDoc->InitUndo( pDoc, nTab, nTab );
4766 pDoc->CopyToDocument( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab,
4767 IDF_ALL, FALSE, pUndoDoc );
4769 pDoc->BeginDrawUndo(); // wegen Hoehenanpassung
4772 ScRangeData** ppSortArray = new ScRangeData* [ nValidCount ];
4773 USHORT j = 0;
4774 for (i=0; i<nCount; i++)
4776 ScRangeData* pData = (*pList)[i];
4777 if ( !pData->HasType( RT_DATABASE ) && !pData->HasType( RT_SHARED ) )
4778 ppSortArray[j++] = pData;
4780 #ifndef ICC
4781 qsort( (void*)ppSortArray, nValidCount, sizeof(ScRangeData*),
4782 &ScRangeData_QsortNameCompare );
4783 #else
4784 qsort( (void*)ppSortArray, nValidCount, sizeof(ScRangeData*),
4785 ICCQsortNameCompare );
4786 #endif
4787 String aName;
4788 rtl::OUStringBuffer aContent;
4789 String aFormula;
4790 SCROW nOutRow = nStartRow;
4791 for (j=0; j<nValidCount; j++)
4793 ScRangeData* pData = ppSortArray[j];
4794 pData->GetName(aName);
4795 // relative Referenzen Excel-konform auf die linke Spalte anpassen:
4796 pData->UpdateSymbol(aContent, ScAddress( nStartCol, nOutRow, nTab ));
4797 aFormula = '=';
4798 aFormula += aContent;
4799 pDoc->PutCell( nStartCol,nOutRow,nTab, new ScStringCell( aName ) );
4800 pDoc->PutCell( nEndCol ,nOutRow,nTab, new ScStringCell( aFormula ) );
4801 ++nOutRow;
4804 delete [] ppSortArray;
4806 if (bRecord)
4808 ScDocument* pRedoDoc = new ScDocument( SCDOCMODE_UNDO );
4809 pRedoDoc->InitUndo( pDoc, nTab, nTab );
4810 pDoc->CopyToDocument( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab,
4811 IDF_ALL, FALSE, pRedoDoc );
4813 rDocShell.GetUndoManager()->AddUndoAction(
4814 new ScUndoListNames( &rDocShell,
4815 ScRange( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab ),
4816 pUndoDoc, pRedoDoc ) );
4819 if (!AdjustRowHeight(ScRange(0,nStartRow,nTab,MAXCOL,nEndRow,nTab)))
4820 rDocShell.PostPaint( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab, PAINT_GRID );
4821 //! rDocShell.UpdateOle(GetViewData());
4822 aModificator.SetDocumentModified();
4823 bDone = TRUE;
4825 else if (!bApi)
4826 rDocShell.ErrorMessage(aTester.GetMessageId());
4828 return bDone;
4831 //------------------------------------------------------------------------
4833 BOOL ScDocFunc::ResizeMatrix( const ScRange& rOldRange, const ScAddress& rNewEnd, BOOL bApi )
4835 ScDocument* pDoc = rDocShell.GetDocument();
4836 SCCOL nStartCol = rOldRange.aStart.Col();
4837 SCROW nStartRow = rOldRange.aStart.Row();
4838 SCTAB nTab = rOldRange.aStart.Tab();
4840 BOOL bUndo(pDoc->IsUndoEnabled());
4842 BOOL bRet = FALSE;
4844 String aFormula;
4845 pDoc->GetFormula( nStartCol, nStartRow, nTab, aFormula );
4846 if ( aFormula.GetChar(0) == '{' && aFormula.GetChar(aFormula.Len()-1) == '}' )
4848 String aUndo = ScGlobal::GetRscString( STR_UNDO_RESIZEMATRIX );
4849 if (bUndo)
4850 rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo );
4852 aFormula.Erase(0,1);
4853 aFormula.Erase(aFormula.Len()-1,1);
4855 ScMarkData aMark;
4856 aMark.SetMarkArea( rOldRange );
4857 aMark.SelectTable( nTab, TRUE );
4858 ScRange aNewRange( rOldRange.aStart, rNewEnd );
4860 if ( DeleteContents( aMark, IDF_CONTENTS, TRUE, bApi ) )
4862 // GRAM_PODF_A1 for API compatibility.
4863 bRet = EnterMatrix( aNewRange, &aMark, NULL, aFormula, bApi, FALSE, EMPTY_STRING, formula::FormulaGrammar::GRAM_PODF_A1 );
4864 if (!bRet)
4866 // versuchen, alten Zustand wiederherzustellen
4867 EnterMatrix( rOldRange, &aMark, NULL, aFormula, bApi, FALSE, EMPTY_STRING, formula::FormulaGrammar::GRAM_PODF_A1 );
4871 if (bUndo)
4872 rDocShell.GetUndoManager()->LeaveListAction();
4875 return bRet;
4878 //------------------------------------------------------------------------
4880 BOOL ScDocFunc::InsertAreaLink( const String& rFile, const String& rFilter,
4881 const String& rOptions, const String& rSource,
4882 const ScRange& rDestRange, ULONG nRefresh,
4883 BOOL bFitBlock, BOOL bApi )
4885 //! auch fuer ScViewFunc::InsertAreaLink benutzen!
4887 ScDocument* pDoc = rDocShell.GetDocument();
4888 BOOL bUndo (pDoc->IsUndoEnabled());
4890 SvxLinkManager* pLinkManager = pDoc->GetLinkManager();
4892 // #i52120# if other area links exist at the same start position,
4893 // remove them first (file format specifies only one link definition
4894 // for a cell)
4896 USHORT nLinkCount = pLinkManager->GetLinks().Count();
4897 USHORT nRemoved = 0;
4898 USHORT nLinkPos = 0;
4899 while (nLinkPos<nLinkCount)
4901 ::sfx2::SvBaseLink* pBase = *pLinkManager->GetLinks()[nLinkPos];
4902 if ( pBase->ISA(ScAreaLink) &&
4903 static_cast<ScAreaLink*>(pBase)->GetDestArea().aStart == rDestRange.aStart )
4905 if ( bUndo )
4907 if ( !nRemoved )
4909 // group all remove and the insert action
4910 String aUndo = ScGlobal::GetRscString( STR_UNDO_INSERTAREALINK );
4911 rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo );
4914 ScAreaLink* pOldArea = static_cast<ScAreaLink*>(pBase);
4915 rDocShell.GetUndoManager()->AddUndoAction(
4916 new ScUndoRemoveAreaLink( &rDocShell,
4917 pOldArea->GetFile(), pOldArea->GetFilter(), pOldArea->GetOptions(),
4918 pOldArea->GetSource(), pOldArea->GetDestArea(), pOldArea->GetRefreshDelay() ) );
4920 pLinkManager->Remove( pBase );
4921 nLinkCount = pLinkManager->GetLinks().Count();
4922 ++nRemoved;
4924 else
4925 ++nLinkPos;
4928 String aFilterName = rFilter;
4929 String aNewOptions = rOptions;
4930 if (!aFilterName.Len())
4931 ScDocumentLoader::GetFilterName( rFile, aFilterName, aNewOptions, TRUE, !bApi );
4933 // remove application prefix from filter name here, so the filter options
4934 // aren't reset when the filter name is changed in ScAreaLink::DataChanged
4935 ScDocumentLoader::RemoveAppPrefix( aFilterName );
4937 ScAreaLink* pLink = new ScAreaLink( &rDocShell, rFile, aFilterName,
4938 aNewOptions, rSource, rDestRange, nRefresh );
4939 pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, rFile, &aFilterName, &rSource );
4941 // Undo fuer den leeren Link
4943 if (bUndo)
4945 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoInsertAreaLink( &rDocShell,
4946 rFile, aFilterName, aNewOptions,
4947 rSource, rDestRange, nRefresh ) );
4948 if ( nRemoved )
4949 rDocShell.GetUndoManager()->LeaveListAction(); // undo for link update is still separate
4952 // Update hat sein eigenes Undo
4954 pLink->SetDoInsert(bFitBlock); // beim ersten Update ggf. nichts einfuegen
4955 pLink->Update(); // kein SetInCreate -> Update ausfuehren
4956 pLink->SetDoInsert(TRUE); // Default = TRUE
4958 SfxBindings* pBindings = rDocShell.GetViewBindings();
4959 if (pBindings)
4960 pBindings->Invalidate( SID_LINKS );
4962 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); // Navigator
4964 return TRUE;