xref: /trunk/main/sc/source/ui/docshell/docfunc.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sc.hxx"
30 
31 
32 
33 // INCLUDE ---------------------------------------------------------------
34 
35 #include "scitems.hxx"
36 #include <editeng/eeitem.hxx>
37 
38 #include <sfx2/app.hxx>
39 #include <editeng/editobj.hxx>
40 #include <sfx2/linkmgr.hxx>
41 #include <svx/svdundo.hxx>
42 #include <sfx2/bindings.hxx>
43 #include <sfx2/printer.hxx>
44 #include <vcl/msgbox.hxx>
45 #include <vcl/sound.hxx>
46 #include <vcl/virdev.hxx>
47 #include <vcl/waitobj.hxx>
48 #include <svl/zforlist.hxx>
49 #include <svl/PasswordHelper.hxx>
50 
51 #include <basic/sbstar.hxx>
52 #include <com/sun/star/container/XNameContainer.hpp>
53 #include <com/sun/star/script/ModuleType.hpp>
54 #include <com/sun/star/script/XLibraryContainer.hpp>
55 #include <com/sun/star/script/vba/XVBAModuleInfo.hpp>
56 
57 #include <list>
58 
59 #include "docfunc.hxx"
60 
61 #include "sc.hrc"
62 
63 #include "arealink.hxx"
64 #include "attrib.hxx"
65 #include "dociter.hxx"
66 #include "autoform.hxx"
67 #include "cell.hxx"
68 #include "detdata.hxx"
69 #include "detfunc.hxx"
70 #include "docpool.hxx"
71 #include "docsh.hxx"
72 #include "drwlayer.hxx"
73 #include "editutil.hxx"
74 #include "globstr.hrc"
75 //CHINA001 #include "namecrea.hxx"      // NAME_TOP etc.
76 #include "olinetab.hxx"
77 #include "patattr.hxx"
78 #include "rangenam.hxx"
79 #include "rangeutl.hxx"
80 #include "refundo.hxx"
81 #include "scresid.hxx"
82 #include "stlpool.hxx"
83 #include "stlsheet.hxx"
84 #include "tablink.hxx"
85 #include "tabvwsh.hxx"
86 #include "uiitems.hxx"
87 #include "undoblk.hxx"
88 #include "undocell.hxx"
89 #include "undodraw.hxx"
90 #include "undotab.hxx"
91 #include "waitoff.hxx"
92 #include "sizedev.hxx"
93 #include "scmod.hxx"
94 #include "inputhdl.hxx"
95 #include "inputwin.hxx"
96 #include "editable.hxx"
97 #include "compiler.hxx"
98 #include "scui_def.hxx" //CHINA001
99 #include "tabprotection.hxx"
100 #include "clipparam.hxx"
101 #include "externalrefmgr.hxx"
102 
103 #include <memory>
104 #include <basic/basmgr.hxx>
105 #include <boost/scoped_ptr.hpp>
106 
107 using namespace com::sun::star;
108 using ::com::sun::star::uno::Sequence;
109 
110 // STATIC DATA -----------------------------------------------------------
111 
112 //========================================================================
113 
114 IMPL_LINK( ScDocFunc, NotifyDrawUndo, SdrUndoAction*, pUndoAction )
115 {
116     // #i101118# if drawing layer collects the undo actions, add it there
117     ScDrawLayer* pDrawLayer = rDocShell.GetDocument()->GetDrawLayer();
118     if( pDrawLayer && pDrawLayer->IsRecording() )
119         pDrawLayer->AddCalcUndo( pUndoAction );
120     else
121         rDocShell.GetUndoManager()->AddUndoAction( new ScUndoDraw( pUndoAction, &rDocShell ) );
122     rDocShell.SetDrawModified();
123 
124     // the affected sheet isn't known, so all stream positions are invalidated
125     ScDocument* pDoc = rDocShell.GetDocument();
126     SCTAB nTabCount = pDoc->GetTableCount();
127     for (SCTAB nTab=0; nTab<nTabCount; nTab++)
128         if (pDoc->IsStreamValid(nTab))
129             pDoc->SetStreamValid(nTab, sal_False);
130 
131     return 0;
132 }
133 
134 //------------------------------------------------------------------------
135 
136 //  Zeile ueber dem Range painten (fuer Linien nach AdjustRowHeight)
137 
138 void lcl_PaintAbove( ScDocShell& rDocShell, const ScRange& rRange )
139 {
140     SCROW nRow = rRange.aStart.Row();
141     if ( nRow > 0 )
142     {
143         SCTAB nTab = rRange.aStart.Tab();   //! alle?
144         --nRow;
145         rDocShell.PostPaint( ScRange(0,nRow,nTab, MAXCOL,nRow,nTab), PAINT_GRID );
146     }
147 }
148 
149 //------------------------------------------------------------------------
150 
151 sal_Bool ScDocFunc::AdjustRowHeight( const ScRange& rRange, sal_Bool bPaint )
152 {
153     ScDocument* pDoc = rDocShell.GetDocument();
154     if ( pDoc->IsImportingXML() )
155     {
156         //  for XML import, all row heights are updated together after importing
157         return sal_False;
158     }
159     if ( !pDoc->IsAdjustHeightEnabled() )
160     {
161         return sal_False;
162     }
163 
164     SCTAB nTab      = rRange.aStart.Tab();
165     SCROW nStartRow = rRange.aStart.Row();
166     SCROW nEndRow   = rRange.aEnd.Row();
167 
168     ScSizeDeviceProvider aProv( &rDocShell );
169     Fraction aOne(1,1);
170 
171     sal_Bool bChanged = pDoc->SetOptimalHeight( nStartRow, nEndRow, nTab, 0, aProv.GetDevice(),
172                                             aProv.GetPPTX(), aProv.GetPPTY(), aOne, aOne, sal_False );
173 
174     if ( bPaint && bChanged )
175         rDocShell.PostPaint( 0, nStartRow, nTab, MAXCOL, MAXROW, nTab,
176                                             PAINT_GRID | PAINT_LEFT );
177 
178     return bChanged;
179 }
180 
181 
182 //------------------------------------------------------------------------
183 
184 sal_Bool ScDocFunc::DetectiveAddPred(const ScAddress& rPos)
185 {
186     ScDocShellModificator aModificator( rDocShell );
187 
188     rDocShell.MakeDrawLayer();
189     ScDocument* pDoc = rDocShell.GetDocument();
190     sal_Bool bUndo (pDoc->IsUndoEnabled());
191     ScDrawLayer* pModel = pDoc->GetDrawLayer();
192     SCCOL nCol = rPos.Col();
193     SCROW nRow = rPos.Row();
194     SCTAB nTab = rPos.Tab();
195 
196     if (bUndo)
197         pModel->BeginCalcUndo();
198     sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).ShowPred( nCol, nRow );
199     SdrUndoGroup* pUndo = NULL;
200     if (bUndo)
201         pUndo = pModel->GetCalcUndo();
202     if (bDone)
203     {
204         ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_ADDPRED );
205         pDoc->AddDetectiveOperation( aOperation );
206         if (bUndo)
207         {
208             rDocShell.GetUndoManager()->AddUndoAction(
209                         new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
210         }
211         aModificator.SetDocumentModified();
212         SfxBindings* pBindings = rDocShell.GetViewBindings();
213         if (pBindings)
214             pBindings->Invalidate( SID_DETECTIVE_REFRESH );
215     }
216     else
217         delete pUndo;
218 
219     return bDone;
220 }
221 
222 sal_Bool ScDocFunc::DetectiveDelPred(const ScAddress& rPos)
223 {
224     ScDocument* pDoc = rDocShell.GetDocument();
225 
226     sal_Bool bUndo(pDoc->IsUndoEnabled());
227     ScDrawLayer* pModel = pDoc->GetDrawLayer();
228     if (!pModel)
229         return sal_False;
230 
231     ScDocShellModificator aModificator( rDocShell );
232 
233     SCCOL nCol = rPos.Col();
234     SCROW nRow = rPos.Row();
235     SCTAB nTab = rPos.Tab();
236 
237     if (bUndo)
238         pModel->BeginCalcUndo();
239     sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).DeletePred( nCol, nRow );
240     SdrUndoGroup* pUndo = NULL;
241     if (bUndo)
242         pUndo = pModel->GetCalcUndo();
243     if (bDone)
244     {
245         ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_DELPRED );
246         pDoc->AddDetectiveOperation( aOperation );
247         if (bUndo)
248         {
249             rDocShell.GetUndoManager()->AddUndoAction(
250                         new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
251         }
252         aModificator.SetDocumentModified();
253         SfxBindings* pBindings = rDocShell.GetViewBindings();
254         if (pBindings)
255             pBindings->Invalidate( SID_DETECTIVE_REFRESH );
256     }
257     else
258         delete pUndo;
259 
260     return bDone;
261 }
262 
263 sal_Bool ScDocFunc::DetectiveAddSucc(const ScAddress& rPos)
264 {
265     ScDocShellModificator aModificator( rDocShell );
266 
267     rDocShell.MakeDrawLayer();
268     ScDocument* pDoc = rDocShell.GetDocument();
269 
270     sal_Bool bUndo(pDoc->IsUndoEnabled());
271     ScDrawLayer* pModel = pDoc->GetDrawLayer();
272     SCCOL nCol = rPos.Col();
273     SCROW nRow = rPos.Row();
274     SCTAB nTab = rPos.Tab();
275 
276     if (bUndo)
277         pModel->BeginCalcUndo();
278     sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).ShowSucc( nCol, nRow );
279     SdrUndoGroup* pUndo = NULL;
280     if (bUndo)
281         pUndo = pModel->GetCalcUndo();
282     if (bDone)
283     {
284         ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_ADDSUCC );
285         pDoc->AddDetectiveOperation( aOperation );
286         if (bUndo)
287         {
288             rDocShell.GetUndoManager()->AddUndoAction(
289                         new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
290         }
291         aModificator.SetDocumentModified();
292         SfxBindings* pBindings = rDocShell.GetViewBindings();
293         if (pBindings)
294             pBindings->Invalidate( SID_DETECTIVE_REFRESH );
295     }
296     else
297         delete pUndo;
298 
299     return bDone;
300 }
301 
302 sal_Bool ScDocFunc::DetectiveDelSucc(const ScAddress& rPos)
303 {
304     ScDocument* pDoc = rDocShell.GetDocument();
305 
306     sal_Bool bUndo (pDoc->IsUndoEnabled());
307     ScDrawLayer* pModel = pDoc->GetDrawLayer();
308     if (!pModel)
309         return sal_False;
310 
311     ScDocShellModificator aModificator( rDocShell );
312 
313     SCCOL nCol = rPos.Col();
314     SCROW nRow = rPos.Row();
315     SCTAB nTab = rPos.Tab();
316 
317     if (bUndo)
318         pModel->BeginCalcUndo();
319     sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).DeleteSucc( nCol, nRow );
320     SdrUndoGroup* pUndo = NULL;
321     if (bUndo)
322         pUndo = pModel->GetCalcUndo();
323     if (bDone)
324     {
325         ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_DELSUCC );
326         pDoc->AddDetectiveOperation( aOperation );
327         if (bUndo)
328         {
329             rDocShell.GetUndoManager()->AddUndoAction(
330                         new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
331         }
332         aModificator.SetDocumentModified();
333         SfxBindings* pBindings = rDocShell.GetViewBindings();
334         if (pBindings)
335             pBindings->Invalidate( SID_DETECTIVE_REFRESH );
336     }
337     else
338         delete pUndo;
339 
340     return bDone;
341 }
342 
343 sal_Bool ScDocFunc::DetectiveAddError(const ScAddress& rPos)
344 {
345     ScDocShellModificator aModificator( rDocShell );
346 
347     rDocShell.MakeDrawLayer();
348     ScDocument* pDoc = rDocShell.GetDocument();
349 
350     sal_Bool bUndo (pDoc->IsUndoEnabled());
351     ScDrawLayer* pModel = pDoc->GetDrawLayer();
352     SCCOL nCol = rPos.Col();
353     SCROW nRow = rPos.Row();
354     SCTAB nTab = rPos.Tab();
355 
356     if (bUndo)
357         pModel->BeginCalcUndo();
358     sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).ShowError( nCol, nRow );
359     SdrUndoGroup* pUndo = NULL;
360     if (bUndo)
361         pUndo = pModel->GetCalcUndo();
362     if (bDone)
363     {
364         ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_ADDERROR );
365         pDoc->AddDetectiveOperation( aOperation );
366         if (bUndo)
367         {
368             rDocShell.GetUndoManager()->AddUndoAction(
369                         new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
370         }
371         aModificator.SetDocumentModified();
372         SfxBindings* pBindings = rDocShell.GetViewBindings();
373         if (pBindings)
374             pBindings->Invalidate( SID_DETECTIVE_REFRESH );
375     }
376     else
377         delete pUndo;
378 
379     return bDone;
380 }
381 
382 sal_Bool ScDocFunc::DetectiveMarkInvalid(SCTAB nTab)
383 {
384     ScDocShellModificator aModificator( rDocShell );
385 
386     rDocShell.MakeDrawLayer();
387     ScDocument* pDoc = rDocShell.GetDocument();
388 
389     sal_Bool bUndo (pDoc->IsUndoEnabled());
390     ScDrawLayer* pModel = pDoc->GetDrawLayer();
391 
392     Window* pWaitWin = rDocShell.GetActiveDialogParent();
393     if (pWaitWin)
394         pWaitWin->EnterWait();
395     if (bUndo)
396         pModel->BeginCalcUndo();
397     sal_Bool bOverflow;
398     sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).MarkInvalid( bOverflow );
399     SdrUndoGroup* pUndo = NULL;
400     if (bUndo)
401         pUndo = pModel->GetCalcUndo();
402     if (pWaitWin)
403         pWaitWin->LeaveWait();
404     if (bDone)
405     {
406         if (pUndo && bUndo)
407         {
408             pUndo->SetComment( ScGlobal::GetRscString( STR_UNDO_DETINVALID ) );
409             rDocShell.GetUndoManager()->AddUndoAction( pUndo );
410         }
411         aModificator.SetDocumentModified();
412         if ( bOverflow )
413         {
414             InfoBox( NULL,
415                     ScGlobal::GetRscString( STR_DETINVALID_OVERFLOW ) ).Execute();
416         }
417     }
418     else
419         delete pUndo;
420 
421     return bDone;
422 }
423 
424 sal_Bool ScDocFunc::DetectiveDelAll(SCTAB nTab)
425 {
426     ScDocument* pDoc = rDocShell.GetDocument();
427 
428     sal_Bool bUndo (pDoc->IsUndoEnabled());
429     ScDrawLayer* pModel = pDoc->GetDrawLayer();
430     if (!pModel)
431         return sal_False;
432 
433     ScDocShellModificator aModificator( rDocShell );
434 
435     if (bUndo)
436         pModel->BeginCalcUndo();
437     sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).DeleteAll( SC_DET_DETECTIVE );
438     SdrUndoGroup* pUndo = NULL;
439     if (bUndo)
440         pUndo = pModel->GetCalcUndo();
441     if (bDone)
442     {
443         ScDetOpList* pOldList = pDoc->GetDetOpList();
444         ScDetOpList* pUndoList = NULL;
445         if (bUndo)
446             pUndoList = pOldList ? new ScDetOpList(*pOldList) : NULL;
447 
448         pDoc->ClearDetectiveOperations();
449 
450         if (bUndo)
451         {
452             rDocShell.GetUndoManager()->AddUndoAction(
453                         new ScUndoDetective( &rDocShell, pUndo, NULL, pUndoList ) );
454         }
455         aModificator.SetDocumentModified();
456         SfxBindings* pBindings = rDocShell.GetViewBindings();
457         if (pBindings)
458             pBindings->Invalidate( SID_DETECTIVE_REFRESH );
459     }
460     else
461         delete pUndo;
462 
463     return bDone;
464 }
465 
466 sal_Bool ScDocFunc::DetectiveRefresh( sal_Bool bAutomatic )
467 {
468     sal_Bool bDone = sal_False;
469     ScDocument* pDoc = rDocShell.GetDocument();
470 
471     sal_Bool bUndo (pDoc->IsUndoEnabled());
472     ScDetOpList* pList = pDoc->GetDetOpList();
473     if ( pList && pList->Count() )
474     {
475         rDocShell.MakeDrawLayer();
476         ScDrawLayer* pModel = pDoc->GetDrawLayer();
477         if (bUndo)
478             pModel->BeginCalcUndo();
479 
480         //  Loeschen auf allen Tabellen
481 
482         SCTAB nTabCount = pDoc->GetTableCount();
483         for (SCTAB nTab=0; nTab<nTabCount; nTab++)
484             ScDetectiveFunc( pDoc,nTab ).DeleteAll( SC_DET_ARROWS );    // don't remove circles
485 
486         //  Wiederholen
487 
488         sal_uInt16 nCount = pList->Count();
489         for (sal_uInt16 i=0; i<nCount; i++)
490         {
491             ScDetOpData* pData = (*pList)[i];
492             if (pData)
493             {
494                 ScAddress aPos = pData->GetPos();
495                 ScDetectiveFunc aFunc( pDoc, aPos.Tab() );
496                 SCCOL nCol = aPos.Col();
497                 SCROW nRow = aPos.Row();
498                 switch (pData->GetOperation())
499                 {
500                     case SCDETOP_ADDSUCC:
501                         aFunc.ShowSucc( nCol, nRow );
502                         break;
503                     case SCDETOP_DELSUCC:
504                         aFunc.DeleteSucc( nCol, nRow );
505                         break;
506                     case SCDETOP_ADDPRED:
507                         aFunc.ShowPred( nCol, nRow );
508                         break;
509                     case SCDETOP_DELPRED:
510                         aFunc.DeletePred( nCol, nRow );
511                         break;
512                     case SCDETOP_ADDERROR:
513                         aFunc.ShowError( nCol, nRow );
514                         break;
515                     default:
516                         DBG_ERROR("falsche Op bei DetectiveRefresh");
517                 }
518             }
519         }
520 
521         if (bUndo)
522         {
523             SdrUndoGroup* pUndo = pModel->GetCalcUndo();
524             if (pUndo)
525             {
526                 pUndo->SetComment( ScGlobal::GetRscString( STR_UNDO_DETREFRESH ) );
527                 //  wenn automatisch, an letzte Aktion anhaengen
528                 rDocShell.GetUndoManager()->AddUndoAction(
529                                                 new ScUndoDraw( pUndo, &rDocShell ),
530                                                 bAutomatic );
531             }
532         }
533         rDocShell.SetDrawModified();
534         bDone = sal_True;
535     }
536     return bDone;
537 }
538 
539 //------------------------------------------------------------------------
540 
541 sal_Bool ScDocFunc::DeleteContents( const ScMarkData& rMark, sal_uInt16 nFlags,
542                                     sal_Bool bRecord, sal_Bool bApi )
543 {
544     ScDocShellModificator aModificator( rDocShell );
545 
546     if ( !rMark.IsMarked() && !rMark.IsMultiMarked() )
547     {
548         DBG_ERROR("ScDocFunc::DeleteContents ohne Markierung");
549         return sal_False;
550     }
551 
552     ScDocument* pDoc = rDocShell.GetDocument();
553 
554     if (bRecord && !pDoc->IsUndoEnabled())
555         bRecord = sal_False;
556 
557     ScEditableTester aTester( pDoc, rMark );
558     if (!aTester.IsEditable())
559     {
560         if (!bApi)
561             rDocShell.ErrorMessage(aTester.GetMessageId());
562         return sal_False;
563     }
564 
565     ScRange aMarkRange;
566     sal_Bool bSimple = sal_False;
567 
568     ScMarkData aMultiMark = rMark;
569     aMultiMark.SetMarking(sal_False);       // fuer MarkToMulti
570 
571     ScDocument* pUndoDoc = NULL;
572     sal_Bool bMulti = !bSimple && aMultiMark.IsMultiMarked();
573     if (!bSimple)
574     {
575         aMultiMark.MarkToMulti();
576         aMultiMark.GetMultiMarkArea( aMarkRange );
577     }
578     ScRange aExtendedRange(aMarkRange);
579     if (!bSimple)
580     {
581         if ( pDoc->ExtendMerge( aExtendedRange, sal_True ) )
582             bMulti = sal_False;
583     }
584 
585     // keine Objekte auf geschuetzten Tabellen
586     sal_Bool bObjects = sal_False;
587     if ( nFlags & IDF_OBJECTS )
588     {
589         bObjects = sal_True;
590         SCTAB nTabCount = pDoc->GetTableCount();
591         for (SCTAB nTab=0; nTab<nTabCount; nTab++)
592             if (aMultiMark.GetTableSelect(nTab) && pDoc->IsTabProtected(nTab))
593                 bObjects = sal_False;
594     }
595 
596     sal_uInt16 nExtFlags = 0;       // extra flags are needed only if attributes are deleted
597     if ( nFlags & IDF_ATTRIB )
598         rDocShell.UpdatePaintExt( nExtFlags, aMarkRange );
599 
600     //  Reihenfolge:
601     //  1) BeginDrawUndo
602     //  2) Objekte loeschen (DrawUndo wird gefuellt)
603     //  3) Inhalte fuer Undo kopieren und Undo-Aktion anlegen
604     //  4) Inhalte loeschen
605 
606     bool bDrawUndo = bObjects || (nFlags & IDF_NOTE);
607     if (bRecord && bDrawUndo)
608         pDoc->BeginDrawUndo();
609 
610     if (bObjects)
611     {
612         if (bMulti)
613             pDoc->DeleteObjectsInSelection( aMultiMark );
614         else
615             pDoc->DeleteObjectsInArea( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
616                                        aMarkRange.aEnd.Col(),   aMarkRange.aEnd.Row(),
617                                        aMultiMark );
618     }
619 
620     if ( bRecord )
621     {
622         pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
623         pUndoDoc->InitUndo( pDoc, aMarkRange.aStart.Tab(), aMarkRange.aEnd.Tab() );
624 
625         //  bei "Format/Standard" alle Attribute kopieren, weil CopyToDocument
626         //  nur mit IDF_HARDATTR zu langsam ist:
627         sal_uInt16 nUndoDocFlags = nFlags;
628         if (nFlags & IDF_ATTRIB)
629             nUndoDocFlags |= IDF_ATTRIB;
630         if (nFlags & IDF_EDITATTR)          // Edit-Engine-Attribute
631             nUndoDocFlags |= IDF_STRING;    // -> Zellen werden geaendert
632         if (nFlags & IDF_NOTE)
633             nUndoDocFlags |= IDF_CONTENTS;  // #68795# copy all cells with their notes
634         // note captions are handled in drawing undo
635         nUndoDocFlags |= IDF_NOCAPTIONS;
636         pDoc->CopyToDocument( aExtendedRange, nUndoDocFlags, bMulti, pUndoDoc, &aMultiMark );
637     }
638 
639 //! HideAllCursors();   // falls Zusammenfassung aufgehoben wird
640     if (bSimple)
641         pDoc->DeleteArea( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
642                           aMarkRange.aEnd.Col(),   aMarkRange.aEnd.Row(),
643                           aMultiMark, nFlags );
644     else
645     {
646         pDoc->DeleteSelection( nFlags, aMultiMark );
647 //       aMultiMark.MarkToSimple();
648     }
649 
650     // add undo action after drawing undo is complete (objects and note captions)
651     if( bRecord )
652         rDocShell.GetUndoManager()->AddUndoAction(
653             new ScUndoDeleteContents( &rDocShell, aMultiMark, aExtendedRange,
654                                       pUndoDoc, bMulti, nFlags, bDrawUndo ) );
655 
656     if (!AdjustRowHeight( aExtendedRange ))
657         rDocShell.PostPaint( aExtendedRange, PAINT_GRID, nExtFlags );
658     else if (nExtFlags & SC_PF_LINES)
659         lcl_PaintAbove( rDocShell, aExtendedRange );    // fuer Linien ueber dem Bereich
660 
661 //  rDocShell.UpdateOle(GetViewData());     //! an der View?
662     aModificator.SetDocumentModified();
663 //! CellContentChanged();
664 //! ShowAllCursors();
665 
666 #if 0
667     //! muss an der View bleiben !!!!
668     if ( nFlags & IDF_ATTRIB )
669     {
670         if ( nFlags & IDF_CONTENTS )
671             ForgetFormatArea();
672         else
673             StartFormatArea();              // Attribute loeschen ist auch Attributierung
674     }
675 #endif
676 
677     return sal_True;
678 }
679 
680 //------------------------------------------------------------------------
681 
682 sal_Bool ScDocFunc::TransliterateText( const ScMarkData& rMark, sal_Int32 nType,
683                                     sal_Bool bRecord, sal_Bool bApi )
684 {
685     ScDocShellModificator aModificator( rDocShell );
686 
687     ScDocument* pDoc = rDocShell.GetDocument();
688     if (bRecord && !pDoc->IsUndoEnabled())
689         bRecord = sal_False;
690 
691     ScEditableTester aTester( pDoc, rMark );
692     if (!aTester.IsEditable())
693     {
694         if (!bApi)
695             rDocShell.ErrorMessage(aTester.GetMessageId());
696         return sal_False;
697     }
698 
699     ScRange aMarkRange;
700     ScMarkData aMultiMark = rMark;
701     aMultiMark.SetMarking(sal_False);       // for MarkToMulti
702     aMultiMark.MarkToMulti();
703     aMultiMark.GetMultiMarkArea( aMarkRange );
704 
705     if (bRecord)
706     {
707         SCTAB nStartTab = aMarkRange.aStart.Tab();
708         SCTAB nTabCount = pDoc->GetTableCount();
709 
710         ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
711         pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab );
712         for (SCTAB i=0; i<nTabCount; i++)
713             if (i != nStartTab && rMark.GetTableSelect(i))
714                 pUndoDoc->AddUndoTab( i, i );
715 
716         ScRange aCopyRange = aMarkRange;
717         aCopyRange.aStart.SetTab(0);
718         aCopyRange.aEnd.SetTab(nTabCount-1);
719         pDoc->CopyToDocument( aCopyRange, IDF_CONTENTS, sal_True, pUndoDoc, &aMultiMark );
720 
721         rDocShell.GetUndoManager()->AddUndoAction(
722             new ScUndoTransliterate( &rDocShell, aMultiMark, pUndoDoc, nType ) );
723     }
724 
725     pDoc->TransliterateText( aMultiMark, nType );
726 
727     if (!AdjustRowHeight( aMarkRange ))
728         rDocShell.PostPaint( aMarkRange, PAINT_GRID );
729 
730     aModificator.SetDocumentModified();
731 
732     return sal_True;
733 }
734 
735 //------------------------------------------------------------------------
736 
737 sal_Bool ScDocFunc::SetNormalString( const ScAddress& rPos, const String& rText, sal_Bool bApi )
738 {
739     ScDocShellModificator aModificator( rDocShell );
740     ScDocument* pDoc = rDocShell.GetDocument();
741 
742     sal_Bool bUndo(pDoc->IsUndoEnabled());
743     ScEditableTester aTester( pDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() );
744     if (!aTester.IsEditable())
745     {
746         if (!bApi)
747             rDocShell.ErrorMessage(aTester.GetMessageId());
748         return sal_False;
749     }
750 
751     SCTAB* pTabs = NULL;
752     ScBaseCell** ppOldCells = NULL;
753     sal_Bool* pHasFormat = NULL;
754     sal_uLong* pOldFormats = NULL;
755     ScBaseCell* pDocCell = pDoc->GetCell( rPos );
756     sal_Bool bEditDeleted = (pDocCell && pDocCell->GetCellType() == CELLTYPE_EDIT);
757     if (bUndo)
758     {
759         pTabs = new SCTAB[1];
760         pTabs[0] = rPos.Tab();
761         ppOldCells  = new ScBaseCell*[1];
762         ppOldCells[0] = pDocCell ? pDocCell->CloneWithoutNote( *pDoc ) : 0;
763 
764         pHasFormat = new sal_Bool[1];
765         pOldFormats = new sal_uLong[1];
766         const SfxPoolItem* pItem;
767         const ScPatternAttr* pPattern = pDoc->GetPattern( rPos.Col(),rPos.Row(),rPos.Tab() );
768         if ( SFX_ITEM_SET == pPattern->GetItemSet().GetItemState(
769                                 ATTR_VALUE_FORMAT,sal_False,&pItem) )
770         {
771             pHasFormat[0] = sal_True;
772             pOldFormats[0] = ((const SfxUInt32Item*)pItem)->GetValue();
773         }
774         else
775             pHasFormat[0] = sal_False;
776     }
777 
778     pDoc->SetString( rPos.Col(), rPos.Row(), rPos.Tab(), rText );
779 
780     if (bUndo)
781     {
782         //  wegen ChangeTracking darf UndoAction erst nach SetString angelegt werden
783         rDocShell.GetUndoManager()->AddUndoAction(new ScUndoEnterData( &rDocShell, rPos.Col(),rPos.Row(),rPos.Tab(), 1,pTabs,
784                                      ppOldCells, pHasFormat, pOldFormats, rText, NULL ) );
785     }
786 
787     if ( bEditDeleted || pDoc->HasAttrib( ScRange(rPos), HASATTR_NEEDHEIGHT ) )
788         AdjustRowHeight( ScRange(rPos) );
789 
790     rDocShell.PostPaintCell( rPos );
791     aModificator.SetDocumentModified();
792 
793     // #107160# notify input handler here the same way as in PutCell
794     if (bApi)
795         NotifyInputHandler( rPos );
796 
797     return sal_True;
798 }
799 
800 sal_Bool ScDocFunc::PutCell( const ScAddress& rPos, ScBaseCell* pNewCell, sal_Bool bApi )
801 {
802     ScDocShellModificator aModificator( rDocShell );
803     ScDocument* pDoc = rDocShell.GetDocument();
804     sal_Bool bUndo (pDoc->IsUndoEnabled());
805     sal_Bool bXMLLoading(pDoc->IsImportingXML());
806 
807     // #i925#; it is not neccessary to test whether the cell is editable on loading a XML document
808     if (!bXMLLoading)
809     {
810         ScEditableTester aTester( pDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() );
811         if (!aTester.IsEditable())
812         {
813             if (!bApi)
814                 rDocShell.ErrorMessage(aTester.GetMessageId());
815             pNewCell->Delete();
816             return sal_False;
817         }
818     }
819 
820     sal_Bool bEditCell = ( pNewCell->GetCellType() == CELLTYPE_EDIT );
821     ScBaseCell* pDocCell = pDoc->GetCell( rPos );
822     sal_Bool bEditDeleted = (pDocCell && pDocCell->GetCellType() == CELLTYPE_EDIT);
823     sal_Bool bHeight = ( bEditDeleted || bEditCell ||
824                     pDoc->HasAttrib( ScRange(rPos), HASATTR_NEEDHEIGHT ) );
825 
826     ScBaseCell* pUndoCell = (bUndo && pDocCell) ? pDocCell->CloneWithoutNote( *pDoc, rPos ) : 0;
827     ScBaseCell* pRedoCell = (bUndo && pNewCell) ? pNewCell->CloneWithoutNote( *pDoc, rPos ) : 0;
828 
829     pDoc->PutCell( rPos, pNewCell );
830 
831     //  wegen ChangeTracking darf UndoAction erst nach PutCell angelegt werden
832     if (bUndo)
833     {
834         rDocShell.GetUndoManager()->AddUndoAction(
835                 new ScUndoPutCell( &rDocShell, rPos, pUndoCell, pRedoCell, bHeight ) );
836     }
837 
838     if (bHeight)
839         AdjustRowHeight( ScRange(rPos) );
840 
841     if (!bXMLLoading)
842         rDocShell.PostPaintCell( rPos );
843 
844     aModificator.SetDocumentModified();
845 
846     // #i925#; it is not neccessary to notify on loading a XML document
847     // #103934#; notify editline and cell in edit mode
848     if (bApi && !bXMLLoading)
849         NotifyInputHandler( rPos );
850 
851     return sal_True;
852 }
853 
854 void ScDocFunc::NotifyInputHandler( const ScAddress& rPos )
855 {
856     ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
857     if ( pViewSh && pViewSh->GetViewData()->GetDocShell() == &rDocShell )
858     {
859         ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl();
860         if ( pInputHdl && pInputHdl->GetCursorPos() == rPos )
861         {
862             sal_Bool bIsEditMode(pInputHdl->IsEditMode());
863 
864             // set modified if in editmode, because so the string is not set in the InputWindow like in the cell
865             // (the cell shows the same like the InputWindow)
866             if (bIsEditMode)
867                 pInputHdl->SetModified();
868             pViewSh->UpdateInputHandler(sal_False, !bIsEditMode);
869         }
870     }
871 }
872 
873         struct ScMyRememberItem
874         {
875             sal_uInt16      nIndex;
876             SfxItemSet  aItemSet;
877 
878             ScMyRememberItem(const SfxItemSet& rItemSet, sal_uInt16 nTempIndex) :
879                 nIndex(nTempIndex), aItemSet(rItemSet) {}
880         };
881 
882         typedef ::std::list<ScMyRememberItem*> ScMyRememberItemList;
883 
884 sal_Bool ScDocFunc::PutData( const ScAddress& rPos, ScEditEngineDefaulter& rEngine, sal_Bool bInterpret, sal_Bool bApi )
885 {
886     //  PutData ruft PutCell oder SetNormalString
887 
888     sal_Bool bRet = sal_False;
889     ScDocument* pDoc = rDocShell.GetDocument();
890     ScEditAttrTester aTester( &rEngine );
891     sal_Bool bEditCell = aTester.NeedsObject();
892     if ( bEditCell )
893     {
894         // #i61702# With bLoseContent set, the content of rEngine isn't restored
895         // (used in loading XML, where after the removeActionLock call the API obejct's
896         // EditEngine isn't accessed again.
897         sal_Bool bLoseContent = pDoc->IsImportingXML();
898 
899         sal_Bool bUpdateMode(rEngine.GetUpdateMode());
900         if (bUpdateMode)
901             rEngine.SetUpdateMode(sal_False);
902 
903         ScMyRememberItemList aRememberItems;
904         ScMyRememberItem* pRememberItem = NULL;
905 
906         //  All paragraph attributes must be removed before calling CreateTextObject,
907         //  not only alignment, so the object doesn't contain the cell attributes as
908         //  paragraph attributes. Before remove the attributes store they in a list to
909         //  set they back to the EditEngine.
910         sal_uInt16 nCount = rEngine.GetParagraphCount();
911         for (sal_uInt16 i=0; i<nCount; i++)
912         {
913             const SfxItemSet& rOld = rEngine.GetParaAttribs( i );
914             if ( rOld.Count() )
915             {
916                 if ( !bLoseContent )
917                 {
918                     pRememberItem = new ScMyRememberItem(rEngine.GetParaAttribs(i), i);
919                     aRememberItems.push_back(pRememberItem);
920                 }
921                 rEngine.SetParaAttribs( i, SfxItemSet( *rOld.GetPool(), rOld.GetRanges() ) );
922             }
923         }
924 
925         EditTextObject* pNewData = rEngine.CreateTextObject();
926         bRet = PutCell( rPos,
927                         new ScEditCell( pNewData, pDoc, rEngine.GetEditTextObjectPool() ),
928                         bApi );
929         delete pNewData;
930 
931         // Set the paragraph attributes back to the EditEngine.
932         if (!aRememberItems.empty())
933         {
934 //            ScMyRememberItem* pRememberItem = NULL;
935             ScMyRememberItemList::iterator aItr = aRememberItems.begin();
936             while (aItr != aRememberItems.end())
937             {
938                 pRememberItem = *aItr;
939                 rEngine.SetParaAttribs(pRememberItem->nIndex, pRememberItem->aItemSet);
940                 delete pRememberItem;
941                 aItr = aRememberItems.erase(aItr);
942             }
943         }
944 
945         // #i61702# if the content isn't accessed, there's no need to set the UpdateMode again
946         if ( bUpdateMode && !bLoseContent )
947             rEngine.SetUpdateMode(sal_True);
948     }
949     else
950     {
951         String aText = rEngine.GetText();
952         if ( bInterpret || !aText.Len() )
953             bRet = SetNormalString( rPos, aText, bApi );
954         else
955             bRet = PutCell( rPos, new ScStringCell( aText ), bApi );
956     }
957 
958     if ( bRet && aTester.NeedsCellAttr() )
959     {
960         const SfxItemSet& rEditAttr = aTester.GetAttribs();
961         ScPatternAttr aPattern( pDoc->GetPool() );
962         aPattern.GetFromEditItemSet( &rEditAttr );
963         aPattern.DeleteUnchanged( pDoc->GetPattern( rPos.Col(), rPos.Row(), rPos.Tab() ) );
964         aPattern.GetItemSet().ClearItem( ATTR_HOR_JUSTIFY );    // wasn't removed above if no edit object
965         if ( aPattern.GetItemSet().Count() > 0 )
966         {
967             ScMarkData aMark;
968             aMark.SelectTable( rPos.Tab(), sal_True );
969             aMark.SetMarkArea( ScRange( rPos ) );
970             ApplyAttributes( aMark, aPattern, sal_True, bApi );
971         }
972     }
973 
974     return bRet;
975 }
976 
977 
978 ScTokenArray* lcl_ScDocFunc_CreateTokenArrayXML( const String& rText, const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar )
979 {
980     ScTokenArray* pCode = new ScTokenArray;
981     pCode->AddString( rText );
982     if( (eGrammar == formula::FormulaGrammar::GRAM_EXTERNAL) && (rFormulaNmsp.Len() > 0) )
983         pCode->AddString( rFormulaNmsp );
984     return pCode;
985 }
986 
987 
988 ScBaseCell* ScDocFunc::InterpretEnglishString( const ScAddress& rPos,
989         const String& rText, const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar, short* pRetFormatType )
990 {
991     ScDocument* pDoc = rDocShell.GetDocument();
992     ScBaseCell* pNewCell = NULL;
993 
994     if ( rText.Len() > 1 && rText.GetChar(0) == '=' )
995     {
996         ScTokenArray* pCode;
997         if ( pDoc->IsImportingXML() )
998         {   // temporary formula string as string tokens
999             pCode = lcl_ScDocFunc_CreateTokenArrayXML( rText, rFormulaNmsp, eGrammar );
1000             pDoc->IncXMLImportedFormulaCount( rText.Len() );
1001         }
1002         else
1003         {
1004             ScCompiler aComp( pDoc, rPos );
1005             aComp.SetGrammar(eGrammar);
1006             pCode = aComp.CompileString( rText );
1007         }
1008         pNewCell = new ScFormulaCell( pDoc, rPos, pCode, eGrammar, MM_NONE );
1009         delete pCode;   // Zell-ctor hat das TokenArray kopiert
1010     }
1011     else if ( rText.Len() > 1 && rText.GetChar(0) == '\'' )
1012     {
1013         //  for bEnglish, "'" at the beginning is always interpreted as text
1014         //  marker and stripped
1015         pNewCell = ScBaseCell::CreateTextCell( rText.Copy( 1 ), pDoc );
1016     }
1017     else        // (nur) auf englisches Zahlformat testen
1018     {
1019         SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
1020         sal_uInt32 nEnglish = pFormatter->GetStandardIndex(LANGUAGE_ENGLISH_US);
1021         double fVal;
1022         if ( pFormatter->IsNumberFormat( rText, nEnglish, fVal ) )
1023         {
1024             pNewCell = new ScValueCell( fVal );
1025             // return the format type from the English format, so a localized format can be created
1026             if ( pRetFormatType )
1027                 *pRetFormatType = pFormatter->GetType( nEnglish );
1028         }
1029         else if ( rText.Len() )
1030             pNewCell = ScBaseCell::CreateTextCell( rText, pDoc );
1031 
1032         //  das (englische) Zahlformat wird nicht gesetzt
1033         //! passendes lokales Format suchen und setzen???
1034     }
1035 
1036     return pNewCell;
1037 }
1038 
1039 
1040 sal_Bool ScDocFunc::SetCellText( const ScAddress& rPos, const String& rText,
1041         sal_Bool bInterpret, sal_Bool bEnglish, sal_Bool bApi,
1042         const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar )
1043 {
1044     //  SetCellText ruft PutCell oder SetNormalString
1045 
1046     ScDocument* pDoc = rDocShell.GetDocument();
1047     ScBaseCell* pNewCell = NULL;
1048     if ( bInterpret )
1049     {
1050         if ( bEnglish )
1051         {
1052             ::boost::scoped_ptr<ScExternalRefManager::ApiGuard> pExtRefGuard;
1053             if (bApi)
1054                 pExtRefGuard.reset(new ScExternalRefManager::ApiGuard(pDoc));
1055 
1056             //  code moved to own method InterpretEnglishString because it is also used in
1057             //  ScCellRangeObj::setFormulaArray
1058 
1059             pNewCell = InterpretEnglishString( rPos, rText, rFormulaNmsp, eGrammar );
1060         }
1061         // sonst Null behalten -> SetString mit lokalen Formeln/Zahlformat
1062     }
1063     else if ( rText.Len() )
1064     {
1065         OSL_ENSURE( rFormulaNmsp.Len() == 0, "ScDocFunc::SetCellText - formula namespace, but do not interpret?" );
1066         pNewCell = ScBaseCell::CreateTextCell( rText, pDoc );   // immer Text
1067     }
1068 
1069     if (pNewCell)
1070         return PutCell( rPos, pNewCell, bApi );
1071     else
1072         return SetNormalString( rPos, rText, bApi );
1073 }
1074 
1075 //------------------------------------------------------------------------
1076 
1077 bool ScDocFunc::ShowNote( const ScAddress& rPos, bool bShow )
1078 {
1079     ScDocument& rDoc = *rDocShell.GetDocument();
1080     ScPostIt* pNote = rDoc.GetNote( rPos );
1081     if( !pNote || (bShow == pNote->IsCaptionShown()) ) return false;
1082 
1083     // move the caption to internal or hidden layer and create undo action
1084     pNote->ShowCaption( rPos, bShow );
1085     if( rDoc.IsUndoEnabled() )
1086         rDocShell.GetUndoManager()->AddUndoAction( new ScUndoShowHideNote( rDocShell, rPos, bShow ) );
1087 
1088     if (rDoc.IsStreamValid(rPos.Tab()))
1089         rDoc.SetStreamValid(rPos.Tab(), sal_False);
1090 
1091     rDocShell.SetDocumentModified();
1092 
1093     return true;
1094 }
1095 
1096 //------------------------------------------------------------------------
1097 
1098 bool ScDocFunc::SetNoteText( const ScAddress& rPos, const String& rText, sal_Bool bApi )
1099 {
1100     ScDocShellModificator aModificator( rDocShell );
1101 
1102     ScDocument* pDoc = rDocShell.GetDocument();
1103     ScEditableTester aTester( pDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() );
1104     if (!aTester.IsEditable())
1105     {
1106         if (!bApi)
1107             rDocShell.ErrorMessage(aTester.GetMessageId());
1108         return false;
1109     }
1110 
1111     String aNewText = rText;
1112     aNewText.ConvertLineEnd();      //! ist das noetig ???
1113 
1114     if( ScPostIt* pNote = (aNewText.Len() > 0) ? pDoc->GetOrCreateNote( rPos ) : pDoc->GetNote( rPos ) )
1115         pNote->SetText( rPos, aNewText );
1116 
1117     //! Undo !!!
1118 
1119     if (pDoc->IsStreamValid(rPos.Tab()))
1120         pDoc->SetStreamValid(rPos.Tab(), sal_False);
1121 
1122     rDocShell.PostPaintCell( rPos );
1123     aModificator.SetDocumentModified();
1124 
1125     return true;
1126 }
1127 
1128 //------------------------------------------------------------------------
1129 
1130 bool ScDocFunc::ReplaceNote( const ScAddress& rPos, const String& rNoteText, const String* pAuthor, const String* pDate, sal_Bool bApi )
1131 {
1132     bool bDone = false;
1133 
1134     ScDocShellModificator aModificator( rDocShell );
1135     ScDocument& rDoc = *rDocShell.GetDocument();
1136     ScEditableTester aTester( &rDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() );
1137     if (aTester.IsEditable())
1138     {
1139         ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
1140         ::svl::IUndoManager* pUndoMgr = (pDrawLayer && rDoc.IsUndoEnabled()) ? rDocShell.GetUndoManager() : 0;
1141 
1142         ScNoteData aOldData;
1143         ScPostIt* pOldNote = rDoc.ReleaseNote( rPos );
1144         if( pOldNote )
1145         {
1146             // ensure existing caption object before draw undo tracking starts
1147             pOldNote->GetOrCreateCaption( rPos );
1148             // rescue note data for undo
1149             aOldData = pOldNote->GetNoteData();
1150         }
1151 
1152         // collect drawing undo actions for deleting/inserting caption obejcts
1153         if( pUndoMgr )
1154             pDrawLayer->BeginCalcUndo();
1155 
1156         // delete the note (creates drawing undo action for the caption object)
1157         delete pOldNote;
1158 
1159         // create new note (creates drawing undo action for the new caption object)
1160         ScNoteData aNewData;
1161         if( ScPostIt* pNewNote = ScNoteUtil::CreateNoteFromString( rDoc, rPos, rNoteText, false, true ) )
1162         {
1163             if( pAuthor ) pNewNote->SetAuthor( *pAuthor );
1164             if( pDate ) pNewNote->SetDate( *pDate );
1165             // rescue note data for undo
1166             aNewData = pNewNote->GetNoteData();
1167         }
1168 
1169         // create the undo action
1170         if( pUndoMgr && (aOldData.mpCaption || aNewData.mpCaption) )
1171             pUndoMgr->AddUndoAction( new ScUndoReplaceNote( rDocShell, rPos, aOldData, aNewData, pDrawLayer->GetCalcUndo() ) );
1172 
1173         // repaint cell (to make note marker visible)
1174         rDocShell.PostPaintCell( rPos );
1175 
1176         if (rDoc.IsStreamValid(rPos.Tab()))
1177             rDoc.SetStreamValid(rPos.Tab(), sal_False);
1178 
1179         aModificator.SetDocumentModified();
1180         bDone = true;
1181     }
1182     else if (!bApi)
1183     {
1184         rDocShell.ErrorMessage(aTester.GetMessageId());
1185     }
1186 
1187     return bDone;
1188 }
1189 
1190 //------------------------------------------------------------------------
1191 
1192 sal_Bool ScDocFunc::ApplyAttributes( const ScMarkData& rMark, const ScPatternAttr& rPattern,
1193                                     sal_Bool bRecord, sal_Bool bApi )
1194 {
1195     ScDocument* pDoc = rDocShell.GetDocument();
1196     if ( bRecord && !pDoc->IsUndoEnabled() )
1197         bRecord = sal_False;
1198 
1199     sal_Bool bImportingXML = pDoc->IsImportingXML();
1200     // Cell formats can still be set if the range isn't editable only because of matrix formulas.
1201     // #i62483# When loading XML, the check can be skipped altogether.
1202     sal_Bool bOnlyNotBecauseOfMatrix;
1203     if ( !bImportingXML && !pDoc->IsSelectionEditable( rMark, &bOnlyNotBecauseOfMatrix )
1204             && !bOnlyNotBecauseOfMatrix )
1205     {
1206         if (!bApi)
1207             rDocShell.ErrorMessage(STR_PROTECTIONERR);
1208         return sal_False;
1209     }
1210 
1211     ScDocShellModificator aModificator( rDocShell );
1212 
1213     //! Umrandung
1214 
1215     ScRange aMultiRange;
1216     sal_Bool bMulti = rMark.IsMultiMarked();
1217     if ( bMulti )
1218         rMark.GetMultiMarkArea( aMultiRange );
1219     else
1220         rMark.GetMarkArea( aMultiRange );
1221 
1222     if ( bRecord )
1223     {
1224         ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1225         pUndoDoc->InitUndo( pDoc, aMultiRange.aStart.Tab(), aMultiRange.aEnd.Tab() );
1226         pDoc->CopyToDocument( aMultiRange, IDF_ATTRIB, bMulti, pUndoDoc, &rMark );
1227 
1228         rDocShell.GetUndoManager()->AddUndoAction(
1229             new ScUndoSelectionAttr(
1230                     &rDocShell, rMark,
1231                     aMultiRange.aStart.Col(), aMultiRange.aStart.Row(), aMultiRange.aStart.Tab(),
1232                     aMultiRange.aEnd.Col(), aMultiRange.aEnd.Row(), aMultiRange.aEnd.Tab(),
1233                     pUndoDoc, bMulti, &rPattern ) );
1234     }
1235 
1236     // While loading XML it is not neccessary to ask HasAttrib. It needs too much time.
1237     sal_uInt16 nExtFlags = 0;
1238     if ( !bImportingXML )
1239         rDocShell.UpdatePaintExt( nExtFlags, aMultiRange );     // content before the change
1240     pDoc->ApplySelectionPattern( rPattern, rMark );
1241     if ( !bImportingXML )
1242         rDocShell.UpdatePaintExt( nExtFlags, aMultiRange );     // content after the change
1243 
1244     if (!AdjustRowHeight( aMultiRange ))
1245         rDocShell.PostPaint( aMultiRange, PAINT_GRID, nExtFlags );
1246     else if (nExtFlags & SC_PF_LINES)
1247         lcl_PaintAbove( rDocShell, aMultiRange );   // fuer Linien ueber dem Bereich
1248 
1249     aModificator.SetDocumentModified();
1250 
1251     return sal_True;
1252 }
1253 
1254 
1255 sal_Bool ScDocFunc::ApplyStyle( const ScMarkData& rMark, const String& rStyleName,
1256                                     sal_Bool bRecord, sal_Bool bApi )
1257 {
1258     ScDocument* pDoc = rDocShell.GetDocument();
1259     if ( bRecord && !pDoc->IsUndoEnabled() )
1260         bRecord = sal_False;
1261 
1262     sal_Bool bImportingXML = pDoc->IsImportingXML();
1263     // Cell formats can still be set if the range isn't editable only because of matrix formulas.
1264     // #i62483# When loading XML, the check can be skipped altogether.
1265     sal_Bool bOnlyNotBecauseOfMatrix;
1266     if ( !bImportingXML && !pDoc->IsSelectionEditable( rMark, &bOnlyNotBecauseOfMatrix )
1267             && !bOnlyNotBecauseOfMatrix )
1268     {
1269         if (!bApi)
1270             rDocShell.ErrorMessage(STR_PROTECTIONERR);
1271         return sal_False;
1272     }
1273 
1274     ScStyleSheet* pStyleSheet = (ScStyleSheet*) pDoc->GetStyleSheetPool()->Find(
1275                                                 rStyleName, SFX_STYLE_FAMILY_PARA );
1276     if (!pStyleSheet)
1277         return sal_False;
1278 
1279     ScDocShellModificator aModificator( rDocShell );
1280 
1281     ScRange aMultiRange;
1282     sal_Bool bMulti = rMark.IsMultiMarked();
1283     if ( bMulti )
1284         rMark.GetMultiMarkArea( aMultiRange );
1285     else
1286         rMark.GetMarkArea( aMultiRange );
1287 
1288     if ( bRecord )
1289     {
1290         ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1291         SCTAB nStartTab = aMultiRange.aStart.Tab();
1292         SCTAB nTabCount = pDoc->GetTableCount();
1293         pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab );
1294         for (SCTAB i=0; i<nTabCount; i++)
1295             if (i != nStartTab && rMark.GetTableSelect(i))
1296                 pUndoDoc->AddUndoTab( i, i );
1297 
1298         ScRange aCopyRange = aMultiRange;
1299         aCopyRange.aStart.SetTab(0);
1300         aCopyRange.aEnd.SetTab(nTabCount-1);
1301         pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, bMulti, pUndoDoc, &rMark );
1302 
1303         rDocShell.GetUndoManager()->AddUndoAction(
1304             new ScUndoSelectionStyle(
1305                     &rDocShell, rMark, aMultiRange, rStyleName, pUndoDoc ) );
1306 
1307     }
1308 
1309 //  sal_Bool bPaintExt = pDoc->HasAttrib( aMultiRange, HASATTR_PAINTEXT );
1310 //  pDoc->ApplySelectionPattern( rPattern, rMark );
1311 
1312     pDoc->ApplySelectionStyle( (ScStyleSheet&)*pStyleSheet, rMark );
1313 
1314 //  if (!bPaintExt)
1315 //      bPaintExt = pDoc->HasAttrib( aMultiRange, HASATTR_PAINTEXT );
1316 //  sal_uInt16 nExtFlags = bPaintExt ? SC_PF_LINES : 0;
1317     sal_uInt16 nExtFlags = 0;
1318     if (!AdjustRowHeight( aMultiRange ))
1319         rDocShell.PostPaint( aMultiRange, PAINT_GRID, nExtFlags );
1320     else if (nExtFlags & SC_PF_LINES)
1321         lcl_PaintAbove( rDocShell, aMultiRange );   // fuer Linien ueber dem Bereich
1322 
1323     aModificator.SetDocumentModified();
1324 
1325     return sal_True;
1326 }
1327 
1328 //------------------------------------------------------------------------
1329 
1330 sal_Bool ScDocFunc::InsertCells( const ScRange& rRange, const ScMarkData* pTabMark, InsCellCmd eCmd,
1331                                 sal_Bool bRecord, sal_Bool bApi, sal_Bool bPartOfPaste )
1332 {
1333     ScDocShellModificator aModificator( rDocShell );
1334 
1335     SCCOL nStartCol = rRange.aStart.Col();
1336     SCROW nStartRow = rRange.aStart.Row();
1337     SCTAB nStartTab = rRange.aStart.Tab();
1338     SCCOL nEndCol = rRange.aEnd.Col();
1339     SCROW nEndRow = rRange.aEnd.Row();
1340     SCTAB nEndTab = rRange.aEnd.Tab();
1341 
1342     if ( !ValidRow(nStartRow) || !ValidRow(nEndRow) )
1343     {
1344         DBG_ERROR("invalid row in InsertCells");
1345         return sal_False;
1346     }
1347 
1348     ScDocument* pDoc = rDocShell.GetDocument();
1349     SCTAB nTabCount = pDoc->GetTableCount();
1350     SCCOL nPaintStartX = nStartCol;
1351     SCROW nPaintStartY = nStartRow;
1352     SCCOL nPaintEndX = nEndCol;
1353     SCROW nPaintEndY = nEndRow;
1354     sal_uInt16 nPaintFlags = PAINT_GRID;
1355     sal_Bool bSuccess;
1356     SCTAB i;
1357 
1358     ScTabViewShell* pViewSh = rDocShell.GetBestViewShell();  //preserve current cursor position
1359     SCCOL nCursorCol = 0;
1360     SCROW nCursorRow = 0;
1361     if( pViewSh )
1362     {
1363         nCursorCol = pViewSh->GetViewData()->GetCurX();
1364         nCursorRow = pViewSh->GetViewData()->GetCurY();
1365     }
1366 
1367     if (bRecord && !pDoc->IsUndoEnabled())
1368         bRecord = sal_False;
1369 
1370     ScMarkData aMark;
1371     if (pTabMark)
1372         aMark = *pTabMark;
1373     else
1374     {
1375         SCTAB nCount = 0;
1376         for( i=0; i<nTabCount; i++ )
1377         {
1378             if( !pDoc->IsScenario(i) )
1379             {
1380                 nCount++;
1381                 if( nCount == nEndTab+1 )
1382                 {
1383                     aMark.SelectTable( i, sal_True );
1384                     break;
1385                 }
1386             }
1387         }
1388     }
1389 
1390     ScMarkData aFullMark( aMark );          // including scenario sheets
1391     for( i=0; i<nTabCount; i++ )
1392         if( aMark.GetTableSelect( i ) )
1393         {
1394             for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
1395                 aFullMark.SelectTable( j, sal_True );
1396         }
1397 
1398     SCTAB nSelCount = aMark.GetSelectCount();
1399 
1400     //  zugehoerige Szenarien auch anpassen
1401     // Test zusammengefasste
1402 
1403     SCCOL nMergeTestStartX = nStartCol;
1404     SCROW nMergeTestStartY = nStartRow;
1405     SCCOL nMergeTestEndX = nEndCol;
1406     SCROW nMergeTestEndY = nEndRow;
1407 
1408     ScRange aExtendMergeRange( rRange );
1409 
1410     if( rRange.aStart == rRange.aEnd && pDoc->HasAttrib(rRange, HASATTR_MERGED) )
1411     {
1412         pDoc->ExtendMerge( aExtendMergeRange );
1413         pDoc->ExtendOverlapped( aExtendMergeRange );
1414         nMergeTestEndX = aExtendMergeRange.aEnd.Col();
1415         nMergeTestEndY = aExtendMergeRange.aEnd.Row();
1416         nPaintEndX = nMergeTestEndX;
1417         nPaintEndY = nMergeTestEndY;
1418     }
1419 
1420     if ( eCmd == INS_INSROWS )
1421     {
1422         nMergeTestStartX = 0;
1423         nMergeTestEndX = MAXCOL;
1424     }
1425     if ( eCmd == INS_INSCOLS )
1426     {
1427         nMergeTestStartY = 0;
1428         nMergeTestEndY = MAXROW;
1429     }
1430     if ( eCmd == INS_CELLSDOWN )
1431         nMergeTestEndY = MAXROW;
1432     if ( eCmd == INS_CELLSRIGHT )
1433         nMergeTestEndX = MAXCOL;
1434 
1435     sal_Bool bNeedRefresh = sal_False;
1436 
1437     SCCOL nEditTestEndX = (eCmd==INS_INSCOLS) ? MAXCOL : nMergeTestEndX;
1438     SCROW nEditTestEndY = (eCmd==INS_INSROWS) ? MAXROW : nMergeTestEndY;
1439     ScEditableTester aTester( pDoc, nMergeTestStartX, nMergeTestStartY, nEditTestEndX, nEditTestEndY, aMark );
1440     if (!aTester.IsEditable())
1441     {
1442         if (!bApi)
1443             rDocShell.ErrorMessage(aTester.GetMessageId());
1444         return sal_False;
1445     }
1446 
1447     WaitObject aWait( rDocShell.GetActiveDialogParent() );      // wichtig wegen TrackFormulas bei UpdateReference
1448 
1449     ScDocument* pRefUndoDoc = NULL;
1450     ScRefUndoData* pUndoData = NULL;
1451     if ( bRecord )
1452     {
1453         pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1454         pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, sal_False, sal_False );
1455 
1456         // pRefUndoDoc is filled in InsertCol / InsertRow
1457 
1458         pUndoData = new ScRefUndoData( pDoc );
1459 
1460         pDoc->BeginDrawUndo();
1461     }
1462 
1463     // #i8302 : we unmerge overwhelming ranges, before insertion all the actions are put in the same ListAction
1464     // the patch comes from mloiseleur and maoyg
1465     sal_Bool bInsertMerge = sal_False;
1466     std::vector<ScRange> qIncreaseRange;
1467     String aUndo = ScGlobal::GetRscString( STR_UNDO_INSERTCELLS );
1468     if (bRecord)
1469         rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo );
1470 
1471     for( i=0; i<nTabCount; i++ )
1472     {
1473         if( aMark.GetTableSelect(i) )
1474         {
1475             if( pDoc->HasAttrib( nMergeTestStartX, nMergeTestStartY, i, nMergeTestEndX, nMergeTestEndY, i, HASATTR_MERGED | HASATTR_OVERLAPPED ) )
1476             {
1477                 if (eCmd==INS_CELLSRIGHT)
1478                     bNeedRefresh = sal_True;
1479 
1480                 SCCOL nMergeStartX = nMergeTestStartX;
1481                 SCROW nMergeStartY = nMergeTestStartY;
1482                 SCCOL nMergeEndX   = nMergeTestEndX;
1483                 SCROW nMergeEndY   = nMergeTestEndY;
1484 
1485                 pDoc->ExtendMerge( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i );
1486                 pDoc->ExtendOverlapped( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i );
1487 
1488                 if(( eCmd == INS_CELLSDOWN && ( nMergeStartX != nMergeTestStartX || nMergeEndX != nMergeTestEndX )) ||
1489                     (eCmd == INS_CELLSRIGHT && ( nMergeStartY != nMergeTestStartY || nMergeEndY != nMergeTestEndY )) )
1490                 {
1491                     if (!bApi)
1492                         rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0);
1493                     rDocShell.GetUndoManager()->LeaveListAction();
1494                     return sal_False;
1495                 }
1496 
1497                 SCCOL nTestCol = -1;
1498                 SCROW nTestRow1 = -1;
1499                 SCROW nTestRow2 = -1;
1500 
1501                 ScDocAttrIterator aTestIter( pDoc, i, nMergeTestStartX, nMergeTestStartY, nMergeTestEndX, nMergeTestEndY );
1502                 ScRange aExtendRange( nMergeTestStartX, nMergeTestStartY, i, nMergeTestEndX, nMergeTestEndY, i );
1503                 const ScPatternAttr* pPattern = NULL;
1504                 const ScMergeAttr* pMergeFlag = NULL;
1505                 const ScMergeFlagAttr* pMergeFlagAttr = NULL;
1506                 while ( ( pPattern = aTestIter.GetNext( nTestCol, nTestRow1, nTestRow2 ) ) != NULL )
1507                 {
1508                     pMergeFlag = (const ScMergeAttr*) &pPattern->GetItem(ATTR_MERGE);
1509                     pMergeFlagAttr = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG);
1510                     sal_Int16 nNewFlags = pMergeFlagAttr->GetValue() & ( SC_MF_HOR | SC_MF_VER );
1511                     if( ( pMergeFlag && pMergeFlag->IsMerged() ) || nNewFlags == SC_MF_HOR || nNewFlags == SC_MF_VER )
1512                     {
1513                         ScRange aRange( nTestCol, nTestRow1, i );
1514                         pDoc->ExtendOverlapped(aRange);
1515                         pDoc->ExtendMerge(aRange, sal_True, sal_True);
1516 
1517                         if( nTestRow1 < nTestRow2 && nNewFlags == SC_MF_HOR )
1518                         {
1519                             for( SCROW nTestRow = nTestRow1; nTestRow <= nTestRow2; nTestRow++ )
1520                             {
1521                                 ScRange aTestRange( nTestCol, nTestRow, i );
1522                                 pDoc->ExtendOverlapped( aTestRange );
1523                                 pDoc->ExtendMerge( aTestRange, sal_True, sal_True);
1524                                 ScRange aMergeRange( aTestRange.aStart.Col(),aTestRange.aStart.Row(), i );
1525                                 if( !aExtendRange.In( aMergeRange ) )
1526                                 {
1527                                     qIncreaseRange.push_back( aTestRange );
1528                                     bInsertMerge = sal_True;
1529                                 }
1530                             }
1531                         }
1532                         else
1533                         {
1534                             ScRange aMergeRange( aRange.aStart.Col(),aRange.aStart.Row(), i );
1535                             if( !aExtendRange.In( aMergeRange ) )
1536                             {
1537                                 qIncreaseRange.push_back( aRange );
1538                             }
1539                             bInsertMerge = sal_True;
1540                         }
1541                     }
1542                 }
1543 
1544                 if( bInsertMerge )
1545                 {
1546                     if( eCmd == INS_INSROWS || eCmd == INS_CELLSDOWN )
1547                     {
1548                         nStartRow = aExtendMergeRange.aStart.Row();
1549                         nEndRow = aExtendMergeRange.aEnd.Row();
1550 
1551                         if( eCmd == INS_CELLSDOWN )
1552                             nEndCol = nMergeTestEndX;
1553                         else
1554                         {
1555                             nStartCol = 0;
1556                             nEndCol = MAXCOL;
1557                         }
1558                     }
1559                     else if( eCmd == INS_CELLSRIGHT || eCmd == INS_INSCOLS )
1560                     {
1561 
1562                         nStartCol = aExtendMergeRange.aStart.Col();
1563                         nEndCol = aExtendMergeRange.aEnd.Col();
1564                         if( eCmd == INS_CELLSRIGHT )
1565                         {
1566                             nEndRow = nMergeTestEndY;
1567                         }
1568                         else
1569                         {
1570                             nStartRow = 0;
1571                             nEndRow = MAXROW;
1572                         }
1573                     }
1574 
1575                     if( !qIncreaseRange.empty() )
1576                     {
1577                         for( ::std::vector<ScRange>::const_iterator iIter( qIncreaseRange.begin()); iIter != qIncreaseRange.end(); iIter++ )
1578                         {
1579                             ScRange aRange( *iIter );
1580                             if( pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) )
1581                             {
1582                                 UnmergeCells( aRange, sal_True, sal_True );
1583                             }
1584                         }
1585                     }
1586                 }
1587                 else
1588                 {
1589                     if (!bApi)
1590                         rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0);
1591                     rDocShell.GetUndoManager()->LeaveListAction();
1592                     return sal_False;
1593                 }
1594             }
1595         }
1596     }
1597 
1598     switch (eCmd)
1599     {
1600         case INS_CELLSDOWN:
1601             bSuccess = pDoc->InsertRow( nStartCol, 0, nEndCol, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, &aFullMark );
1602             nPaintEndY = MAXROW;
1603             break;
1604         case INS_INSROWS:
1605             bSuccess = pDoc->InsertRow( 0, 0, MAXCOL, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, &aFullMark );
1606             nPaintStartX = 0;
1607             nPaintEndX = MAXCOL;
1608             nPaintEndY = MAXROW;
1609             nPaintFlags |= PAINT_LEFT;
1610             break;
1611         case INS_CELLSRIGHT:
1612             bSuccess = pDoc->InsertCol( nStartRow, 0, nEndRow, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, &aFullMark );
1613             nPaintEndX = MAXCOL;
1614             break;
1615         case INS_INSCOLS:
1616             bSuccess = pDoc->InsertCol( 0, 0, MAXROW, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, &aFullMark );
1617             nPaintStartY = 0;
1618             nPaintEndY = MAXROW;
1619             nPaintEndX = MAXCOL;
1620             nPaintFlags |= PAINT_TOP;
1621             break;
1622         default:
1623             DBG_ERROR("Falscher Code beim Einfuegen");
1624             bSuccess = sal_False;
1625             break;
1626     }
1627 
1628     if ( bSuccess )
1629     {
1630         SCTAB* pTabs      = NULL;
1631         SCTAB* pScenarios = NULL;
1632         SCTAB  nUndoPos  = 0;
1633 
1634         if ( bRecord )
1635         {
1636             pTabs       = new SCTAB[nSelCount];
1637             pScenarios  = new SCTAB[nSelCount];
1638             nUndoPos    = 0;
1639             for( i=0; i<nTabCount; i++ )
1640             {
1641                 if( aMark.GetTableSelect( i ) )
1642                 {
1643                     SCTAB nCount = 0;
1644                     for( SCTAB j=i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
1645                         nCount ++;
1646 
1647                     pScenarios[nUndoPos] = nCount;
1648                     pTabs[nUndoPos] = i;
1649                     nUndoPos ++;
1650                 }
1651             }
1652 
1653             if( !bInsertMerge )
1654             {
1655                 rDocShell.GetUndoManager()->LeaveListAction();
1656             }
1657 
1658             rDocShell.GetUndoManager()->AddUndoAction( new ScUndoInsertCells(
1659                 &rDocShell, ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ),
1660                 nUndoPos, pTabs, pScenarios, eCmd, pRefUndoDoc, pUndoData, bPartOfPaste ) );
1661         }
1662 
1663         // #i8302 : we remerge growing ranges, with the new part inserted
1664 
1665         while( !qIncreaseRange.empty() )
1666         {
1667             ScRange aRange = qIncreaseRange.back();
1668             if( !pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) )
1669             {
1670                 switch (eCmd)
1671                 {
1672                     case INS_CELLSDOWN:
1673                     case INS_INSROWS:
1674                         aRange.aEnd.IncRow(static_cast<SCsCOL>(nEndRow-nStartRow+1));
1675                         break;
1676                     case INS_CELLSRIGHT:
1677                     case INS_INSCOLS:
1678                         aRange.aEnd.IncCol(static_cast<SCsCOL>(nEndCol-nStartCol+1));
1679                         break;
1680                     default:
1681                         break;
1682                 }
1683                 MergeCells(aRange, sal_False, sal_True, sal_True);
1684             }
1685             qIncreaseRange.pop_back();
1686         }
1687 
1688         if( bInsertMerge )
1689             rDocShell.GetUndoManager()->LeaveListAction();
1690 
1691         for( i=0; i<nTabCount; i++ )
1692         {
1693             if( aMark.GetTableSelect( i ) )
1694             {
1695                 if (bNeedRefresh)
1696                     pDoc->ExtendMerge( nMergeTestStartX, nMergeTestStartY, nMergeTestEndX, nMergeTestEndY, i, sal_True );
1697                 else
1698                     pDoc->RefreshAutoFilter( nMergeTestStartX, nMergeTestStartY, nMergeTestEndX, nMergeTestEndY, i );
1699 
1700                 if ( eCmd == INS_INSROWS || eCmd == INS_INSCOLS )
1701                     pDoc->UpdatePageBreaks( i );
1702 
1703                 sal_uInt16 nExtFlags = 0;
1704                 rDocShell.UpdatePaintExt( nExtFlags, nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i );
1705 
1706                 SCTAB nScenarioCount = 0;
1707 
1708                 for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
1709                     nScenarioCount ++;
1710 
1711                 sal_Bool bAdjusted = ( eCmd == INS_INSROWS ) ? AdjustRowHeight(ScRange(0, nStartRow, i, MAXCOL, nEndRow, i+nScenarioCount )) :
1712                                                            AdjustRowHeight(ScRange(0, nPaintStartY, i, MAXCOL, nPaintEndY, i+nScenarioCount ));
1713                 if (bAdjusted)
1714                 {
1715                     //  paint only what is not done by AdjustRowHeight
1716                     if (nPaintFlags & PAINT_TOP)
1717                         rDocShell.PostPaint( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount, PAINT_TOP );
1718                 }
1719                 else
1720                     rDocShell.PostPaint( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount, nPaintFlags, nExtFlags );
1721             }
1722         }
1723         //aModificator.SetDocumentModified();
1724     }
1725     else
1726     {
1727         if( bInsertMerge )
1728         {
1729             while( !qIncreaseRange.empty() )
1730             {
1731                 ScRange aRange = qIncreaseRange.back();
1732                 MergeCells(aRange, sal_False, sal_True, sal_True);
1733                 qIncreaseRange.pop_back();
1734             }
1735 
1736             if( pViewSh )
1737             {
1738                 pViewSh->MarkRange( rRange, sal_False );
1739                 pViewSh->SetCursor( nCursorCol, nCursorRow );
1740             }
1741         }
1742 
1743         rDocShell.GetUndoManager()->LeaveListAction();
1744         rDocShell.GetUndoManager()->RemoveLastUndoAction();
1745 
1746         delete pRefUndoDoc;
1747         delete pUndoData;
1748         if (!bApi)
1749             rDocShell.ErrorMessage(STR_INSERT_FULL);        // Spalte/Zeile voll
1750     }
1751 
1752     aModificator.SetDocumentModified();
1753 
1754     SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
1755     return bSuccess;
1756 }
1757 
1758 sal_Bool ScDocFunc::DeleteCells( const ScRange& rRange, const ScMarkData* pTabMark, DelCellCmd eCmd,
1759                              sal_Bool bRecord, sal_Bool bApi )
1760 {
1761     ScDocShellModificator aModificator( rDocShell );
1762 
1763     SCCOL nStartCol = rRange.aStart.Col();
1764     SCROW nStartRow = rRange.aStart.Row();
1765     SCTAB nStartTab = rRange.aStart.Tab();
1766     SCCOL nEndCol = rRange.aEnd.Col();
1767     SCROW nEndRow = rRange.aEnd.Row();
1768     SCTAB nEndTab = rRange.aEnd.Tab();
1769 
1770     if ( !ValidRow(nStartRow) || !ValidRow(nEndRow) )
1771     {
1772         DBG_ERROR("invalid row in DeleteCells");
1773         return sal_False;
1774     }
1775 
1776     ScDocument* pDoc = rDocShell.GetDocument();
1777     SCTAB nTabCount = pDoc->GetTableCount();
1778     SCCOL nPaintStartX = nStartCol;
1779     SCROW nPaintStartY = nStartRow;
1780     SCCOL nPaintEndX = nEndCol;
1781     SCROW nPaintEndY = nEndRow;
1782     sal_uInt16 nPaintFlags = PAINT_GRID;
1783     SCTAB i;
1784 
1785     if (bRecord && !pDoc->IsUndoEnabled())
1786         bRecord = sal_False;
1787 
1788     ScMarkData aMark;
1789     if (pTabMark)
1790         aMark = *pTabMark;
1791     else
1792     {
1793         SCTAB nCount = 0;
1794         for( i=0; i<nTabCount; i++ )
1795         {
1796             if( !pDoc->IsScenario(i) )
1797             {
1798                 nCount++;
1799                 if( nCount == nEndTab+1 )
1800                 {
1801                     aMark.SelectTable( i, sal_True );
1802                     break;
1803                 }
1804             }
1805         }
1806     }
1807 
1808     ScMarkData aFullMark( aMark );          // including scenario sheets
1809     for( i=0; i<nTabCount; i++ )
1810         if( aMark.GetTableSelect( i ) )
1811         {
1812             for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
1813                 aFullMark.SelectTable( j, sal_True );
1814         }
1815 
1816     SCTAB nSelCount = aMark.GetSelectCount();
1817 
1818     SCCOL nUndoStartX = nStartCol;
1819     SCROW nUndoStartY = nStartRow;
1820     SCCOL nUndoEndX = nEndCol;
1821     SCROW nUndoEndY = nEndRow;
1822 
1823     ScRange aExtendMergeRange( rRange );
1824 
1825     if( rRange.aStart == rRange.aEnd && pDoc->HasAttrib(rRange, HASATTR_MERGED) )
1826     {
1827         pDoc->ExtendMerge( aExtendMergeRange );
1828         pDoc->ExtendOverlapped( aExtendMergeRange );
1829         nUndoEndX = aExtendMergeRange.aEnd.Col();
1830         nUndoEndY = aExtendMergeRange.aEnd.Row();
1831         nPaintEndX = nUndoEndX;
1832         nPaintEndY = nUndoEndY;
1833     }
1834 
1835     if (eCmd==DEL_DELROWS)
1836     {
1837         nUndoStartX = 0;
1838         nUndoEndX = MAXCOL;
1839     }
1840     if (eCmd==DEL_DELCOLS)
1841     {
1842         nUndoStartY = 0;
1843         nUndoEndY = MAXROW;
1844     }
1845                     // Test Zellschutz
1846 
1847     SCCOL nEditTestEndX = nUndoEndX;
1848     if ( eCmd==DEL_DELCOLS || eCmd==DEL_CELLSLEFT )
1849         nEditTestEndX = MAXCOL;
1850     SCROW nEditTestEndY = nUndoEndY;
1851     if ( eCmd==DEL_DELROWS || eCmd==DEL_CELLSUP )
1852         nEditTestEndY = MAXROW;
1853     ScEditableTester aTester( pDoc, nUndoStartX, nUndoStartY, nEditTestEndX, nEditTestEndY, aMark );
1854     if (!aTester.IsEditable())
1855     {
1856         if (!bApi)
1857             rDocShell.ErrorMessage(aTester.GetMessageId());
1858         return sal_False;
1859     }
1860 
1861                     // Test zusammengefasste
1862 
1863     SCCOL nMergeTestEndX = (eCmd==DEL_CELLSLEFT) ? MAXCOL : nUndoEndX;
1864     SCROW nMergeTestEndY = (eCmd==DEL_CELLSUP)   ? MAXROW : nUndoEndY;
1865     SCCOL nExtendStartCol = nUndoStartX;
1866     SCROW nExtendStartRow = nUndoStartY;
1867     sal_Bool bNeedRefresh = sal_False;
1868 
1869     //Issue 8302 want to be able to insert into the middle of merged cells
1870     //the patch comes from maoyg
1871     ::std::vector<ScRange> qDecreaseRange;
1872     sal_Bool bDeletingMerge = sal_False;
1873     String aUndo = ScGlobal::GetRscString( STR_UNDO_DELETECELLS );
1874     if (bRecord)
1875         rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo );
1876 
1877     for( i=0; i<nTabCount; i++ )
1878     {
1879         if( aMark.GetTableSelect(i) )
1880         {
1881             if ( pDoc->HasAttrib( nUndoStartX, nUndoStartY, i, nMergeTestEndX, nMergeTestEndY, i, HASATTR_MERGED | HASATTR_OVERLAPPED ))
1882             {
1883                 SCCOL nMergeStartX = nUndoStartX;
1884                 SCROW nMergeStartY = nUndoStartY;
1885                 SCCOL nMergeEndX   = nMergeTestEndX;
1886                 SCROW nMergeEndY   = nMergeTestEndY;
1887 
1888                 pDoc->ExtendMerge( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i );
1889                 pDoc->ExtendOverlapped( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i );
1890                 if( ( eCmd == DEL_CELLSUP && ( nMergeStartX != nUndoStartX || nMergeEndX != nMergeTestEndX))||
1891                     ( eCmd == DEL_CELLSLEFT && ( nMergeStartY != nUndoStartY || nMergeEndY != nMergeTestEndY)))
1892                 {
1893                     if (!bApi)
1894                         rDocShell.ErrorMessage(STR_MSSG_DELETECELLS_0);
1895                     rDocShell.GetUndoManager()->LeaveListAction();
1896                     return sal_False;
1897                 }
1898 
1899                 nExtendStartCol = nMergeStartX;
1900                 nExtendStartRow = nMergeStartY;
1901                 SCCOL nTestCol = -1;
1902                 SCROW nTestRow1 = -1;
1903                 SCROW nTestRow2 = -1;
1904 
1905                 ScDocAttrIterator aTestIter( pDoc, i, nUndoStartX, nUndoStartY, nMergeTestEndX, nMergeTestEndY );
1906                 ScRange aExtendRange( nUndoStartX, nUndoStartY, i, nMergeTestEndX, nMergeTestEndY, i );
1907                 const ScPatternAttr* pPattern = NULL;
1908                 const ScMergeAttr* pMergeFlag = NULL;
1909                 const ScMergeFlagAttr* pMergeFlagAttr = NULL;
1910                 while ( ( pPattern = aTestIter.GetNext( nTestCol, nTestRow1, nTestRow2 ) ) != NULL )
1911                 {
1912                     pMergeFlag = (const ScMergeAttr*) &pPattern->GetItem( ATTR_MERGE );
1913                     pMergeFlagAttr = (const ScMergeFlagAttr*) &pPattern->GetItem( ATTR_MERGE_FLAG );
1914                     sal_Int16 nNewFlags = pMergeFlagAttr->GetValue() & ( SC_MF_HOR | SC_MF_VER );
1915                     if( ( pMergeFlag && pMergeFlag->IsMerged() ) || nNewFlags == SC_MF_HOR || nNewFlags == SC_MF_VER )
1916                     {
1917                         ScRange aRange( nTestCol, nTestRow1, i );
1918                         pDoc->ExtendOverlapped( aRange );
1919                         pDoc->ExtendMerge( aRange, sal_True, sal_True );
1920 
1921                         if( nTestRow1 < nTestRow2 && nNewFlags == SC_MF_HOR )
1922                         {
1923                             for( SCROW nTestRow = nTestRow1; nTestRow <= nTestRow2; nTestRow++ )
1924                             {
1925                                 ScRange aTestRange( nTestCol, nTestRow, i );
1926                                 pDoc->ExtendOverlapped( aTestRange );
1927                                 pDoc->ExtendMerge( aTestRange, sal_True, sal_True);
1928                                 ScRange aMergeRange( aTestRange.aStart.Col(),aTestRange.aStart.Row(), i );
1929                                 if( !aExtendRange.In( aMergeRange ) )
1930                                 {
1931                                     qDecreaseRange.push_back( aTestRange );
1932                                     bDeletingMerge = sal_True;
1933                                 }
1934                             }
1935                         }
1936                         else
1937                         {
1938                             ScRange aMergeRange( aRange.aStart.Col(),aRange.aStart.Row(), i );
1939                             if( !aExtendRange.In( aMergeRange ) )
1940                             {
1941                                 qDecreaseRange.push_back( aRange );
1942                             }
1943                             bDeletingMerge = sal_True;
1944                         }
1945                     }
1946                 }
1947 
1948                 if( bDeletingMerge )
1949                 {
1950 
1951                     if( eCmd == DEL_DELROWS || eCmd == DEL_CELLSUP )
1952                     {
1953                         nStartRow = aExtendMergeRange.aStart.Row();
1954                         nEndRow = aExtendMergeRange.aEnd.Row();
1955                         bNeedRefresh = sal_True;
1956 
1957                         if( eCmd == DEL_CELLSUP )
1958                         {
1959                             nEndCol = aExtendMergeRange.aEnd.Col();
1960                         }
1961                         else
1962                         {
1963                             nStartCol = 0;
1964                             nEndCol = MAXCOL;
1965                         }
1966                     }
1967                     else if( eCmd == DEL_CELLSLEFT || eCmd == DEL_DELCOLS )
1968                     {
1969 
1970                         nStartCol = aExtendMergeRange.aStart.Col();
1971                         nEndCol = aExtendMergeRange.aEnd.Col();
1972                         if( eCmd == DEL_CELLSLEFT )
1973                         {
1974                             nEndRow = aExtendMergeRange.aEnd.Row();
1975                             bNeedRefresh = sal_True;
1976                         }
1977                         else
1978                         {
1979                             nStartRow = 0;
1980                             nEndRow = MAXROW;
1981                         }
1982                     }
1983 
1984                     if( !qDecreaseRange.empty() )
1985                     {
1986                         for( ::std::vector<ScRange>::const_iterator iIter( qDecreaseRange.begin()); iIter != qDecreaseRange.end(); iIter++ )
1987                         {
1988                             ScRange aRange( *iIter );
1989                             if( pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) )
1990                             {
1991                                 UnmergeCells( aRange, sal_True, sal_True );
1992                             }
1993                         }
1994                     }
1995                 }
1996                 else
1997                 {
1998                     if (!bApi)
1999                         rDocShell.ErrorMessage(STR_MSSG_DELETECELLS_0);
2000                     rDocShell.GetUndoManager()->LeaveListAction();
2001                     return sal_False;
2002                 }
2003             }
2004         }
2005     }
2006 
2007     //
2008     //      ausfuehren
2009     //
2010 
2011     WaitObject aWait( rDocShell.GetActiveDialogParent() );      // wichtig wegen TrackFormulas bei UpdateReference
2012 
2013     ScDocument* pUndoDoc = NULL;
2014     ScDocument* pRefUndoDoc = NULL;
2015     ScRefUndoData* pUndoData = NULL;
2016     if ( bRecord )
2017     {
2018         // With the fix for #101329#, UpdateRef always puts cells into pRefUndoDoc at their old position,
2019         // so it's no longer necessary to copy more than the deleted range into pUndoDoc.
2020 
2021         pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2022         pUndoDoc->InitUndo( pDoc, 0, nTabCount-1, (eCmd==DEL_DELCOLS), (eCmd==DEL_DELROWS) );
2023         for( i=0; i<nTabCount; i++ )
2024         {
2025             if( aMark.GetTableSelect( i ) )
2026             {
2027                 SCTAB nScenarioCount = 0;
2028 
2029                 for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
2030                     nScenarioCount ++;
2031 
2032                 pDoc->CopyToDocument( nUndoStartX, nUndoStartY, i, nUndoEndX, nUndoEndY, i+nScenarioCount,
2033                     IDF_ALL | IDF_NOCAPTIONS, sal_False, pUndoDoc );
2034             }
2035         }
2036 
2037         pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2038         pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, sal_False, sal_False );
2039 
2040         pUndoData = new ScRefUndoData( pDoc );
2041 
2042         pDoc->BeginDrawUndo();
2043     }
2044 
2045     sal_uInt16 nExtFlags = 0;
2046     for( i=0; i<nTabCount; i++ )
2047     {
2048         if( aMark.GetTableSelect( i ) )
2049             rDocShell.UpdatePaintExt( nExtFlags, nStartCol, nStartRow, i, nEndCol, nEndRow, i );
2050     }
2051 
2052     sal_Bool bUndoOutline = sal_False;
2053     switch (eCmd)
2054     {
2055         case DEL_CELLSUP:
2056             pDoc->DeleteRow( nStartCol, 0, nEndCol, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, NULL, &aFullMark );
2057             nPaintEndY = MAXROW;
2058             break;
2059         case DEL_DELROWS:
2060             pDoc->DeleteRow( 0, 0, MAXCOL, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, &bUndoOutline, &aFullMark );
2061             nPaintStartX = 0;
2062             nPaintEndX = MAXCOL;
2063             nPaintEndY = MAXROW;
2064             nPaintFlags |= PAINT_LEFT;
2065             break;
2066         case DEL_CELLSLEFT:
2067             pDoc->DeleteCol( nStartRow, 0, nEndRow, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, NULL, &aFullMark );
2068             nPaintEndX = MAXCOL;
2069             break;
2070         case DEL_DELCOLS:
2071             pDoc->DeleteCol( 0, 0, MAXROW, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, &bUndoOutline, &aFullMark );
2072             nPaintStartY = 0;
2073             nPaintEndY = MAXROW;
2074             nPaintEndX = MAXCOL;
2075             nPaintFlags |= PAINT_TOP;
2076             break;
2077         default:
2078             DBG_ERROR("Falscher Code beim Loeschen");
2079             break;
2080     }
2081 
2082     //! Test, ob Outline in Groesse geaendert
2083 
2084     if ( bRecord )
2085     {
2086         for( i=0; i<nTabCount; i++ )
2087             if( aFullMark.GetTableSelect( i ) )
2088                 pRefUndoDoc->DeleteAreaTab(nUndoStartX,nUndoStartY,nUndoEndX,nUndoEndY, i, IDF_ALL);
2089 
2090             //  alle Tabellen anlegen, damit Formeln kopiert werden koennen:
2091         pUndoDoc->AddUndoTab( 0, nTabCount-1, sal_False, sal_False );
2092 
2093             //  kopieren mit bColRowFlags=sal_False (#54194#)
2094         pRefUndoDoc->CopyToDocument(0,0,0,MAXCOL,MAXROW,MAXTAB,IDF_FORMULA,sal_False,pUndoDoc,NULL,sal_False);
2095         delete pRefUndoDoc;
2096 
2097         SCTAB* pTabs      = new SCTAB[nSelCount];
2098         SCTAB* pScenarios = new SCTAB[nSelCount];
2099         SCTAB   nUndoPos  = 0;
2100 
2101         for( i=0; i<nTabCount; i++ )
2102         {
2103             if( aMark.GetTableSelect( i ) )
2104             {
2105                 SCTAB nCount = 0;
2106                 for( SCTAB j=i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
2107                     nCount ++;
2108 
2109                 pScenarios[nUndoPos] = nCount;
2110                 pTabs[nUndoPos] = i;
2111                 nUndoPos ++;
2112             }
2113         }
2114 
2115         if( !bDeletingMerge )
2116         {
2117             rDocShell.GetUndoManager()->LeaveListAction();
2118         }
2119 
2120         rDocShell.GetUndoManager()->AddUndoAction( new ScUndoDeleteCells(
2121             &rDocShell, ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ),nUndoPos, pTabs, pScenarios,
2122             eCmd, pUndoDoc, pUndoData ) );
2123     }
2124 
2125     // #i8302 want to be able to insert into the middle of merged cells
2126     // the patch comes from maoyg
2127 
2128     while( !qDecreaseRange.empty() )
2129     {
2130         ScRange aRange = qDecreaseRange.back();
2131 
2132         long nDecreaseRowCount = 0;
2133         long nDecreaseColCount = 0;
2134         if( eCmd == DEL_CELLSUP || eCmd == DEL_DELROWS )
2135         {
2136             if( nStartRow >= aRange.aStart.Row() && nStartRow <= aRange.aEnd.Row() && nEndRow>= aRange.aStart.Row() && nEndRow <= aRange.aEnd.Row() )
2137                 nDecreaseRowCount = nEndRow-nStartRow+1;
2138             else if( nStartRow >= aRange.aStart.Row() && nStartRow <= aRange.aEnd.Row() && nEndRow >= aRange.aStart.Row() && nEndRow >= aRange.aEnd.Row() )
2139                 nDecreaseRowCount = aRange.aEnd.Row()-nStartRow+1;
2140             else if( nStartRow >= aRange.aStart.Row() && nStartRow >= aRange.aEnd.Row() && nEndRow>= aRange.aStart.Row() && nEndRow <= aRange.aEnd.Row() )
2141                 nDecreaseRowCount = aRange.aEnd.Row()-nEndRow+1;
2142         }
2143         else if( eCmd == DEL_CELLSLEFT || eCmd == DEL_DELCOLS )
2144         {
2145             if( nStartCol >= aRange.aStart.Col() && nStartCol <= aRange.aEnd.Col() && nEndCol>= aRange.aStart.Col() && nEndCol <= aRange.aEnd.Col() )
2146                 nDecreaseColCount = nEndCol-nStartCol+1;
2147             else if( nStartCol >= aRange.aStart.Col() && nStartCol <= aRange.aEnd.Col() && nEndCol >= aRange.aStart.Col() && nEndCol >= aRange.aEnd.Col() )
2148                 nDecreaseColCount = aRange.aEnd.Col()-nStartCol+1;
2149             else if( nStartCol >= aRange.aStart.Col() && nStartCol >= aRange.aEnd.Col() && nEndCol>= aRange.aStart.Col() && nEndCol <= aRange.aEnd.Col() )
2150                 nDecreaseColCount = aRange.aEnd.Col()-nEndCol+1;
2151         }
2152 
2153         switch (eCmd)
2154         {
2155             case DEL_CELLSUP:
2156             case DEL_DELROWS:
2157                 aRange.aEnd.SetRow(static_cast<SCsCOL>( aRange.aEnd.Row()-nDecreaseRowCount));
2158                 break;
2159             case DEL_CELLSLEFT:
2160             case DEL_DELCOLS:
2161                 aRange.aEnd.SetCol(static_cast<SCsCOL>( aRange.aEnd.Col()-nDecreaseColCount));
2162                 break;
2163             default:
2164                 break;
2165         }
2166 
2167         if( !pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) )
2168         {
2169             MergeCells( aRange, sal_False, sal_True, sal_True );
2170         }
2171         qDecreaseRange.pop_back();
2172     }
2173 
2174     if( bDeletingMerge )
2175         rDocShell.GetUndoManager()->LeaveListAction();
2176 
2177     if ( bNeedRefresh )
2178     {
2179         // #i51445# old merge flag attributes must be deleted also for single cells,
2180         // not only for whole columns/rows
2181 
2182         if ( eCmd==DEL_DELCOLS || eCmd==DEL_CELLSLEFT )
2183             nMergeTestEndX = MAXCOL;
2184         if ( eCmd==DEL_DELROWS || eCmd==DEL_CELLSUP )
2185             nMergeTestEndY = MAXROW;
2186         ScPatternAttr aPattern( pDoc->GetPool() );
2187         aPattern.GetItemSet().Put( ScMergeFlagAttr() );
2188 
2189         pDoc->ApplyPatternArea( nExtendStartCol, nExtendStartRow, nMergeTestEndX, nMergeTestEndY, aMark, aPattern );
2190 
2191         for( i=0; i<nTabCount; i++ )
2192         {
2193             if( aMark.GetTableSelect( i ) )
2194             {
2195                 SCTAB nScenarioCount = 0;
2196 
2197                 for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
2198                     nScenarioCount ++;
2199 
2200                 ScRange aMergedRange( nExtendStartCol, nExtendStartRow, i, nMergeTestEndX, nMergeTestEndY, i+nScenarioCount );
2201                 pDoc->ExtendMerge( aMergedRange, sal_True );
2202             }
2203         }
2204     }
2205 
2206     for( i=0; i<nTabCount; i++ )
2207     {
2208         if( aMark.GetTableSelect( i ) )
2209         {
2210             if ( eCmd == DEL_DELCOLS || eCmd == DEL_DELROWS )
2211                 pDoc->UpdatePageBreaks( i );
2212 
2213             rDocShell.UpdatePaintExt( nExtFlags, nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i );
2214 
2215             SCTAB nScenarioCount = 0;
2216 
2217             for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
2218                 nScenarioCount ++;
2219 
2220             //  ganze Zeilen loeschen: nichts anpassen
2221             if ( eCmd == DEL_DELROWS || !AdjustRowHeight(ScRange( 0, nPaintStartY, i, MAXCOL, nPaintEndY, i+nScenarioCount )) )
2222                 rDocShell.PostPaint( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount, nPaintFlags,  nExtFlags );
2223             else
2224             {
2225                 //  paint only what is not done by AdjustRowHeight
2226                 if (nExtFlags & SC_PF_LINES)
2227                     lcl_PaintAbove( rDocShell, ScRange( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount) );
2228                 if (nPaintFlags & PAINT_TOP)
2229                     rDocShell.PostPaint( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount, PAINT_TOP );
2230             }
2231         }
2232     }
2233     aModificator.SetDocumentModified();
2234 
2235     SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
2236 
2237     return sal_True;
2238 }
2239 
2240 sal_Bool ScDocFunc::MoveBlock( const ScRange& rSource, const ScAddress& rDestPos,
2241                                 sal_Bool bCut, sal_Bool bRecord, sal_Bool bPaint, sal_Bool bApi )
2242 {
2243     ScDocShellModificator aModificator( rDocShell );
2244 
2245     SCCOL nStartCol = rSource.aStart.Col();
2246     SCROW nStartRow = rSource.aStart.Row();
2247     SCTAB nStartTab = rSource.aStart.Tab();
2248     SCCOL nEndCol = rSource.aEnd.Col();
2249     SCROW nEndRow = rSource.aEnd.Row();
2250     SCTAB nEndTab = rSource.aEnd.Tab();
2251     SCCOL nDestCol = rDestPos.Col();
2252     SCROW nDestRow = rDestPos.Row();
2253     SCTAB nDestTab = rDestPos.Tab();
2254 
2255     if ( !ValidRow(nStartRow) || !ValidRow(nEndRow) || !ValidRow(nDestRow) )
2256     {
2257         DBG_ERROR("invalid row in MoveBlock");
2258         return sal_False;
2259     }
2260 
2261     //  zugehoerige Szenarien auch anpassen - nur wenn innerhalb einer Tabelle verschoben wird!
2262     sal_Bool bScenariosAdded = sal_False;
2263     ScDocument* pDoc = rDocShell.GetDocument();
2264     if (bRecord && !pDoc->IsUndoEnabled())
2265         bRecord = sal_False;
2266 
2267     SCTAB nTabCount = pDoc->GetTableCount();
2268     if ( nDestTab == nStartTab && !pDoc->IsScenario(nEndTab) )
2269         while ( nEndTab+1 < nTabCount && pDoc->IsScenario(nEndTab+1) )
2270         {
2271             ++nEndTab;
2272             bScenariosAdded = sal_True;
2273         }
2274 
2275     SCTAB nSrcTabCount = nEndTab-nStartTab+1;
2276     SCTAB nDestEndTab = nDestTab+nSrcTabCount-1;
2277     SCTAB nTab;
2278 
2279     ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP );
2280 
2281     ScMarkData aSourceMark;
2282     for (nTab=nStartTab; nTab<=nEndTab; nTab++)
2283         aSourceMark.SelectTable( nTab, sal_True );      // Source selektieren
2284     aSourceMark.SetMarkArea( rSource );
2285 
2286     ScDocShellRef aDragShellRef;
2287     if ( pDoc->HasOLEObjectsInArea( rSource ) )
2288     {
2289         aDragShellRef = new ScDocShell;     // DocShell needs a Ref immediately
2290         aDragShellRef->DoInitNew(NULL);
2291     }
2292     ScDrawLayer::SetGlobalDrawPersist(aDragShellRef);
2293 
2294     ScClipParam aClipParam(ScRange(nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nStartTab), bCut);
2295     pDoc->CopyToClip(aClipParam, pClipDoc, &aSourceMark, false, bScenariosAdded, true);
2296 
2297     ScDrawLayer::SetGlobalDrawPersist(NULL);
2298 
2299     SCCOL nOldEndCol = nEndCol;
2300     SCROW nOldEndRow = nEndRow;
2301     sal_Bool bClipOver = sal_False;
2302     for (nTab=nStartTab; nTab<=nEndTab; nTab++)
2303     {
2304         SCCOL nTmpEndCol = nOldEndCol;
2305         SCROW nTmpEndRow = nOldEndRow;
2306         if (pDoc->ExtendMerge( nStartCol, nStartRow, nTmpEndCol, nTmpEndRow, nTab ))
2307             bClipOver = sal_True;
2308         if ( nTmpEndCol > nEndCol ) nEndCol = nTmpEndCol;
2309         if ( nTmpEndRow > nEndRow ) nEndRow = nTmpEndRow;
2310     }
2311 
2312     SCCOL nDestEndCol = nDestCol + ( nOldEndCol-nStartCol );
2313     SCROW nDestEndRow = nDestRow + ( nOldEndRow-nStartRow );
2314 
2315     SCCOL nUndoEndCol = nDestCol + ( nEndCol-nStartCol );       // erweitert im Zielblock
2316     SCROW nUndoEndRow = nDestRow + ( nEndRow-nStartRow );
2317 
2318     sal_Bool bIncludeFiltered = bCut;
2319     if ( !bIncludeFiltered )
2320     {
2321         //  adjust sizes to include only non-filtered rows
2322 
2323         SCCOL nClipX;
2324         SCROW nClipY;
2325         pClipDoc->GetClipArea( nClipX, nClipY, sal_False );
2326         SCROW nUndoAdd = nUndoEndRow - nDestEndRow;
2327         nDestEndRow = nDestRow + nClipY;
2328         nUndoEndRow = nDestEndRow + nUndoAdd;
2329     }
2330 
2331     if (!ValidCol(nUndoEndCol) || !ValidRow(nUndoEndRow))
2332     {
2333         if (!bApi)
2334             rDocShell.ErrorMessage(STR_PASTE_FULL);
2335         delete pClipDoc;
2336         return sal_False;
2337     }
2338 
2339     //  Test auf Zellschutz
2340 
2341     ScEditableTester aTester;
2342     for (nTab=nDestTab; nTab<=nDestEndTab; nTab++)
2343         aTester.TestBlock( pDoc, nTab, nDestCol,nDestRow, nUndoEndCol,nUndoEndRow );
2344     if (bCut)
2345         for (nTab=nStartTab; nTab<=nEndTab; nTab++)
2346             aTester.TestBlock( pDoc, nTab, nStartCol,nStartRow, nEndCol,nEndRow );
2347 
2348     if (!aTester.IsEditable())
2349     {
2350         if (!bApi)
2351             rDocShell.ErrorMessage(aTester.GetMessageId());
2352         delete pClipDoc;
2353         return sal_False;
2354     }
2355 
2356     //  Test auf zusammengefasste - beim Verschieben erst nach dem Loeschen
2357 
2358     if (bClipOver && !bCut)
2359         if (pDoc->HasAttrib( nDestCol,nDestRow,nDestTab, nUndoEndCol,nUndoEndRow,nDestEndTab,
2360                                 HASATTR_MERGED | HASATTR_OVERLAPPED ))
2361         {       // "Zusammenfassen nicht verschachteln !"
2362             if (!bApi)
2363                 rDocShell.ErrorMessage(STR_MSSG_MOVEBLOCKTO_0);
2364             delete pClipDoc;
2365             return sal_False;
2366         }
2367 
2368     //  Are there borders in the cells? (for painting)
2369 
2370     sal_uInt16 nSourceExt = 0;
2371     rDocShell.UpdatePaintExt( nSourceExt, nStartCol,nStartRow,nStartTab, nEndCol,nEndRow,nEndTab );
2372     sal_uInt16 nDestExt = 0;
2373     rDocShell.UpdatePaintExt( nDestExt, nDestCol,nDestRow,nDestTab, nDestEndCol,nDestEndRow,nDestEndTab );
2374 
2375     //
2376     //  ausfuehren
2377     //
2378 
2379     ScDocument* pUndoDoc = NULL;
2380     ScDocument* pRefUndoDoc = NULL;
2381     ScRefUndoData* pUndoData = NULL;
2382     if (bRecord)
2383     {
2384         sal_Bool bWholeCols = ( nStartRow == 0 && nEndRow == MAXROW );
2385         sal_Bool bWholeRows = ( nStartCol == 0 && nEndCol == MAXCOL );
2386         sal_uInt16 nUndoFlags = (IDF_ALL & ~IDF_OBJECTS) | IDF_NOCAPTIONS;
2387 
2388         pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2389         pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab, bWholeCols, bWholeRows );
2390 
2391         if (bCut)
2392         {
2393             pDoc->CopyToDocument( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab,
2394                                     nUndoFlags, sal_False, pUndoDoc );
2395             pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2396             pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, sal_False, sal_False );
2397         }
2398 
2399         if ( nDestTab != nStartTab )
2400             pUndoDoc->AddUndoTab( nDestTab, nDestEndTab, bWholeCols, bWholeRows );
2401         pDoc->CopyToDocument( nDestCol, nDestRow, nDestTab,
2402                                     nDestEndCol, nDestEndRow, nDestEndTab,
2403                                     nUndoFlags, sal_False, pUndoDoc );
2404 
2405         pUndoData = new ScRefUndoData( pDoc );
2406 
2407         pDoc->BeginDrawUndo();
2408     }
2409 
2410     sal_Bool bSourceHeight = sal_False;     // Hoehen angepasst?
2411     if (bCut)
2412     {
2413         ScMarkData aDelMark;    // only for tables
2414         for (nTab=nStartTab; nTab<=nEndTab; nTab++)
2415         {
2416             pDoc->DeleteAreaTab( nStartCol,nStartRow, nOldEndCol,nOldEndRow, nTab, IDF_ALL );
2417             aDelMark.SelectTable( nTab, sal_True );
2418         }
2419         pDoc->DeleteObjectsInArea( nStartCol,nStartRow, nOldEndCol,nOldEndRow, aDelMark );
2420 
2421         //  Test auf zusammengefasste
2422 
2423         if (bClipOver)
2424             if (pDoc->HasAttrib( nDestCol,nDestRow,nDestTab,
2425                                     nUndoEndCol,nUndoEndRow,nDestEndTab,
2426                                     HASATTR_MERGED | HASATTR_OVERLAPPED ))
2427             {
2428                 pDoc->CopyFromClip( rSource, aSourceMark, IDF_ALL, pRefUndoDoc, pClipDoc );
2429                 for (nTab=nStartTab; nTab<=nEndTab; nTab++)
2430                 {
2431                     SCCOL nTmpEndCol = nEndCol;
2432                     SCROW nTmpEndRow = nEndRow;
2433                     pDoc->ExtendMerge( nStartCol, nStartRow, nTmpEndCol, nTmpEndRow, nTab, sal_True );
2434                 }
2435 
2436                 //  Fehlermeldung erst nach dem Wiederherstellen des Inhalts
2437                 if (!bApi)      // "Zusammenfassen nicht verschachteln !"
2438                     rDocShell.ErrorMessage(STR_MSSG_MOVEBLOCKTO_0);
2439 
2440                 delete pUndoDoc;
2441                 delete pRefUndoDoc;
2442                 delete pUndoData;
2443                 delete pClipDoc;
2444                 return sal_False;
2445             }
2446 
2447         bSourceHeight = AdjustRowHeight( rSource, sal_False );
2448     }
2449 
2450     ScRange aPasteDest( nDestCol, nDestRow, nDestTab, nDestEndCol, nDestEndRow, nDestEndTab );
2451 
2452     ScMarkData aDestMark;
2453     for (nTab=nDestTab; nTab<=nDestEndTab; nTab++)
2454         aDestMark.SelectTable( nTab, sal_True );        // Destination selektieren
2455     aDestMark.SetMarkArea( aPasteDest );
2456 
2457     /*  Do not copy cell notes and drawing objects here. While pasting, the
2458         function ScDocument::UpdateReference() is called which calls
2459         ScDrawLayer::MoveCells() which may move away inserted objects to wrong
2460         positions (e.g. if source and destination range overlaps). Cell notes
2461         and drawing objects are pasted below after doing all adjusting. */
2462     pDoc->CopyFromClip( aPasteDest, aDestMark, IDF_ALL & ~(IDF_NOTE | IDF_OBJECTS),
2463                         pRefUndoDoc, pClipDoc, sal_True, sal_False, bIncludeFiltered );
2464 
2465     // skipped rows and merged cells don't mix
2466     if ( !bIncludeFiltered && pClipDoc->HasClipFilteredRows() )
2467         UnmergeCells( aPasteDest, sal_False, sal_True );
2468 
2469     VirtualDevice aVirtDev;
2470     sal_Bool bDestHeight = AdjustRowHeight(
2471                             ScRange( 0,nDestRow,nDestTab, MAXCOL,nDestEndRow,nDestEndTab ),
2472                             sal_False );
2473 
2474     /*  Paste cell notes and drawing objects after adjusting formula references
2475         and row heights. There are no cell notes or drawing objects, if the
2476         clipdoc does not contain a drawing layer.
2477         #i102056# Passing IDF_NOTE only would overwrite cell contents with
2478         empty note cells, therefore the special modifier IDF_ADDNOTES is passed
2479         here too which changes the behaviour of ScColumn::CopyFromClip() to not
2480         touch existing cells. */
2481     if ( pClipDoc->GetDrawLayer() )
2482         pDoc->CopyFromClip( aPasteDest, aDestMark, IDF_NOTE | IDF_ADDNOTES | IDF_OBJECTS,
2483                             pRefUndoDoc, pClipDoc, sal_True, sal_False, bIncludeFiltered );
2484 
2485     if (bRecord)
2486     {
2487         if (pRefUndoDoc)
2488         {
2489                 //  alle Tabellen anlegen, damit Formeln kopiert werden koennen:
2490             pUndoDoc->AddUndoTab( 0, nTabCount-1, sal_False, sal_False );
2491 
2492             pRefUndoDoc->DeleteArea( nDestCol, nDestRow, nDestEndCol, nDestEndRow, aSourceMark, IDF_ALL );
2493             //  kopieren mit bColRowFlags=sal_False (#54194#)
2494             pRefUndoDoc->CopyToDocument( 0, 0, 0, MAXCOL, MAXROW, MAXTAB,
2495                                             IDF_FORMULA, sal_False, pUndoDoc, NULL, sal_False );
2496             delete pRefUndoDoc;
2497         }
2498 
2499         rDocShell.GetUndoManager()->AddUndoAction(
2500             new ScUndoDragDrop( &rDocShell, ScRange(
2501                                     nStartCol, nStartRow, nStartTab,
2502                                     nOldEndCol, nOldEndRow, nEndTab ),
2503                                 ScAddress( nDestCol, nDestRow, nDestTab ),
2504                                 bCut, pUndoDoc, pUndoData, bScenariosAdded ) );
2505     }
2506 
2507     SCCOL nDestPaintEndCol = nDestEndCol;
2508     SCROW nDestPaintEndRow = nDestEndRow;
2509     for (nTab=nDestTab; nTab<=nDestEndTab; nTab++)
2510     {
2511         SCCOL nTmpEndCol = nDestEndCol;
2512         SCROW nTmpEndRow = nDestEndRow;
2513         pDoc->ExtendMerge( nDestCol, nDestRow, nTmpEndCol, nTmpEndRow, nTab, sal_True );
2514         if (nTmpEndCol > nDestPaintEndCol) nDestPaintEndCol = nTmpEndCol;
2515         if (nTmpEndRow > nDestPaintEndRow) nDestPaintEndRow = nTmpEndRow;
2516     }
2517 
2518     if (bCut)
2519         for (nTab=nStartTab; nTab<=nEndTab; nTab++)
2520             pDoc->RefreshAutoFilter( nStartCol, nStartRow, nEndCol, nEndRow, nTab );
2521 
2522     if (bPaint)
2523     {
2524             //  Zielbereich:
2525 
2526         SCCOL nPaintStartX = nDestCol;
2527         SCROW nPaintStartY = nDestRow;
2528         SCCOL nPaintEndX = nDestPaintEndCol;
2529         SCROW nPaintEndY = nDestPaintEndRow;
2530         sal_uInt16 nFlags = PAINT_GRID;
2531 
2532         if ( nStartRow==0 && nEndRow==MAXROW )      // Breiten mitkopiert?
2533         {
2534             nPaintEndX = MAXCOL;
2535             nPaintStartY = 0;
2536             nPaintEndY = MAXROW;
2537             nFlags |= PAINT_TOP;
2538         }
2539         if ( bDestHeight || ( nStartCol == 0 && nEndCol == MAXCOL ) )
2540         {
2541             nPaintEndY = MAXROW;
2542             nPaintStartX = 0;
2543             nPaintEndX = MAXCOL;
2544             nFlags |= PAINT_LEFT;
2545         }
2546         if ( bScenariosAdded )
2547         {
2548             nPaintStartX = 0;
2549             nPaintStartY = 0;
2550             nPaintEndX = MAXCOL;
2551             nPaintEndY = MAXROW;
2552         }
2553 
2554         rDocShell.PostPaint( nPaintStartX,nPaintStartY,nDestTab,
2555                             nPaintEndX,nPaintEndY,nDestEndTab, nFlags, nSourceExt | nDestExt );
2556 
2557         if ( bCut )
2558         {
2559                 //  Quellbereich:
2560 
2561             nPaintStartX = nStartCol;
2562             nPaintStartY = nStartRow;
2563             nPaintEndX = nEndCol;
2564             nPaintEndY = nEndRow;
2565             nFlags = PAINT_GRID;
2566 
2567             if ( bSourceHeight )
2568             {
2569                 nPaintEndY = MAXROW;
2570                 nPaintStartX = 0;
2571                 nPaintEndX = MAXCOL;
2572                 nFlags |= PAINT_LEFT;
2573             }
2574             if ( bScenariosAdded )
2575             {
2576                 nPaintStartX = 0;
2577                 nPaintStartY = 0;
2578                 nPaintEndX = MAXCOL;
2579                 nPaintEndY = MAXROW;
2580             }
2581 
2582             rDocShell.PostPaint( nPaintStartX,nPaintStartY,nStartTab,
2583                                 nPaintEndX,nPaintEndY,nEndTab, nFlags, nSourceExt );
2584         }
2585     }
2586 
2587     aModificator.SetDocumentModified();
2588 
2589     SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
2590 
2591     delete pClipDoc;
2592     return sal_True;
2593 }
2594 
2595 //------------------------------------------------------------------------
2596 uno::Reference< uno::XInterface > GetDocModuleObject( SfxObjectShell& rDocSh, String& sCodeName )
2597 {
2598     uno::Reference< lang::XMultiServiceFactory> xSF(rDocSh.GetModel(), uno::UNO_QUERY);
2599     uno::Reference< container::XNameAccess > xVBACodeNamedObjectAccess;
2600     uno::Reference< uno::XInterface > xDocModuleApiObject;
2601     if ( xSF.is() )
2602     {
2603         xVBACodeNamedObjectAccess.set( xSF->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAObjectModuleObjectProvider"))), uno::UNO_QUERY );
2604         xDocModuleApiObject.set( xVBACodeNamedObjectAccess->getByName( sCodeName ), uno::UNO_QUERY );
2605     }
2606     return xDocModuleApiObject;
2607 
2608 }
2609 
2610 script::ModuleInfo lcl_InitModuleInfo( SfxObjectShell& rDocSh, String& sModule )
2611 {
2612     script::ModuleInfo sModuleInfo;
2613     sModuleInfo.ModuleType = script::ModuleType::DOCUMENT;
2614     sModuleInfo.ModuleObject = GetDocModuleObject( rDocSh, sModule );
2615     return sModuleInfo;
2616 }
2617 
2618 void VBA_InsertModule( ScDocument& rDoc, SCTAB nTab, String& sModuleName, String& sSource )
2619 {
2620     SfxObjectShell& rDocSh = *rDoc.GetDocumentShell();
2621     uno::Reference< script::XLibraryContainer > xLibContainer = rDocSh.GetBasicContainer();
2622     DBG_ASSERT( xLibContainer.is(), "No BasicContainer!" );
2623 
2624     uno::Reference< container::XNameContainer > xLib;
2625     if( xLibContainer.is() )
2626     {
2627         String aLibName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) );
2628         if ( rDocSh.GetBasicManager() && rDocSh.GetBasicManager()->GetName().Len() )
2629             aLibName = rDocSh.GetBasicManager()->GetName();
2630         uno::Any aLibAny = xLibContainer->getByName( aLibName );
2631         aLibAny >>= xLib;
2632     }
2633     if( xLib.is() )
2634     {
2635         // if the Module with codename exists then find a new name
2636         sal_Int32 nNum = 0;
2637         String genModuleName;
2638         if ( sModuleName.Len() )
2639             sModuleName = sModuleName;
2640         else
2641         {
2642              genModuleName = String::CreateFromAscii( "Sheet1" );
2643              nNum = 1;
2644         }
2645         while( xLib->hasByName( genModuleName  ) )
2646             genModuleName = rtl::OUString::createFromAscii( "Sheet" ) + rtl::OUString::valueOf( ++nNum );
2647 
2648         uno::Any aSourceAny;
2649         rtl::OUString sTmpSource = sSource;
2650         if ( sTmpSource.getLength() == 0 )
2651             sTmpSource = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Rem Attribute VBA_ModuleType=VBADocumentModule\nOption VBASupport 1\n" ));
2652         aSourceAny <<= sTmpSource;
2653         uno::Reference< script::vba::XVBAModuleInfo > xVBAModuleInfo( xLib, uno::UNO_QUERY );
2654         if ( xVBAModuleInfo.is() )
2655         {
2656             rDoc.SetCodeName( nTab, genModuleName );
2657             script::ModuleInfo sModuleInfo = lcl_InitModuleInfo(  rDocSh, genModuleName );
2658             xVBAModuleInfo->insertModuleInfo( genModuleName, sModuleInfo );
2659             xLib->insertByName( genModuleName, aSourceAny );
2660         }
2661 
2662     }
2663 }
2664 
2665 void VBA_DeleteModule( ScDocShell& rDocSh, String& sModuleName )
2666 {
2667     uno::Reference< script::XLibraryContainer > xLibContainer = rDocSh.GetBasicContainer();
2668     DBG_ASSERT( xLibContainer.is(), "No BasicContainer!" );
2669 
2670     uno::Reference< container::XNameContainer > xLib;
2671     if( xLibContainer.is() )
2672     {
2673         String aLibName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) );
2674         if ( rDocSh.GetBasicManager() && rDocSh.GetBasicManager()->GetName().Len() )
2675             aLibName = rDocSh.GetBasicManager()->GetName();
2676         uno::Any aLibAny = xLibContainer->getByName( aLibName );
2677         aLibAny >>= xLib;
2678     }
2679     if( xLib.is() )
2680     {
2681         uno::Reference< script::vba::XVBAModuleInfo > xVBAModuleInfo( xLib, uno::UNO_QUERY );
2682         if( xLib->hasByName( sModuleName ) )
2683             xLib->removeByName( sModuleName );
2684         if ( xVBAModuleInfo.is() )
2685             xVBAModuleInfo->removeModuleInfo( sModuleName );
2686 
2687     }
2688 }
2689 
2690 
2691 sal_Bool ScDocFunc::InsertTable( SCTAB nTab, const String& rName, sal_Bool bRecord, sal_Bool bApi )
2692 {
2693     sal_Bool bSuccess = sal_False;
2694     WaitObject aWait( rDocShell.GetActiveDialogParent() );
2695 
2696     ScDocShellModificator aModificator( rDocShell );
2697 
2698     ScDocument* pDoc = rDocShell.GetDocument();
2699 
2700 
2701     // Strange loop, also basic is loaded too early ( InsertTable )
2702     // is called via the xml import for sheets in described in odf
2703     sal_Bool bInsertDocModule = false;
2704 
2705     if(  !rDocShell.GetDocument()->IsImportingXML() )
2706     {
2707         bInsertDocModule = pDoc ? pDoc->IsInVBAMode() : false;
2708     }
2709     if ( bInsertDocModule || ( bRecord && !pDoc->IsUndoEnabled() ) )
2710         bRecord = sal_False;
2711 
2712     if (bRecord)
2713         pDoc->BeginDrawUndo();                          //  InsertTab erzeugt ein SdrUndoNewPage
2714 
2715     SCTAB nTabCount = pDoc->GetTableCount();
2716     sal_Bool bAppend = ( nTab >= nTabCount );
2717     if ( bAppend )
2718         nTab = nTabCount;       // wichtig fuer Undo
2719 
2720     if (pDoc->InsertTab( nTab, rName ))
2721     {
2722         String sCodeName;
2723         if (bRecord)
2724             rDocShell.GetUndoManager()->AddUndoAction(
2725                         new ScUndoInsertTab( &rDocShell, nTab, bAppend, rName));
2726         //  Views updaten:
2727         // Only insert vba modules if vba mode ( and not currently importing XML )
2728         if( bInsertDocModule )
2729         {
2730             String sSource;
2731             VBA_InsertModule( *pDoc, nTab, sCodeName, sSource );
2732         }
2733         rDocShell.Broadcast( ScTablesHint( SC_TAB_INSERTED, nTab ) );
2734 
2735         rDocShell.PostPaintExtras();
2736         aModificator.SetDocumentModified();
2737         SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2738         bSuccess = sal_True;
2739     }
2740     else if (!bApi)
2741         rDocShell.ErrorMessage(STR_TABINSERT_ERROR);
2742 
2743     return bSuccess;
2744 }
2745 
2746 sal_Bool ScDocFunc::DeleteTable( SCTAB nTab, sal_Bool bRecord, sal_Bool /* bApi */ )
2747 {
2748     WaitObject aWait( rDocShell.GetActiveDialogParent() );
2749 
2750     ScDocShellModificator aModificator( rDocShell );
2751 
2752     sal_Bool bSuccess = sal_False;
2753     ScDocument* pDoc = rDocShell.GetDocument();
2754     sal_Bool bVbaEnabled = pDoc ? pDoc->IsInVBAMode() : false;
2755     if (bRecord && !pDoc->IsUndoEnabled())
2756         bRecord = sal_False;
2757     if ( bVbaEnabled )
2758         bRecord = sal_False;
2759     sal_Bool bWasLinked = pDoc->IsLinked(nTab);
2760     ScDocument* pUndoDoc = NULL;
2761     ScRefUndoData* pUndoData = NULL;
2762     if (bRecord)
2763     {
2764         pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2765         SCTAB nCount = pDoc->GetTableCount();
2766 
2767         pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_True );     // nur nTab mit Flags
2768         pUndoDoc->AddUndoTab( 0, nCount-1 );                    // alle Tabs fuer Referenzen
2769 
2770         pDoc->CopyToDocument(0,0,nTab, MAXCOL,MAXROW,nTab, IDF_ALL,sal_False, pUndoDoc );
2771         String aOldName;
2772         pDoc->GetName( nTab, aOldName );
2773         pUndoDoc->RenameTab( nTab, aOldName, sal_False );
2774         if (bWasLinked)
2775             pUndoDoc->SetLink( nTab, pDoc->GetLinkMode(nTab), pDoc->GetLinkDoc(nTab),
2776                                 pDoc->GetLinkFlt(nTab), pDoc->GetLinkOpt(nTab),
2777                                 pDoc->GetLinkTab(nTab),
2778                                 pDoc->GetLinkRefreshDelay(nTab) );
2779 
2780         if ( pDoc->IsScenario(nTab) )
2781         {
2782             pUndoDoc->SetScenario( nTab, sal_True );
2783             String aComment;
2784             Color  aColor;
2785             sal_uInt16 nScenFlags;
2786             pDoc->GetScenarioData( nTab, aComment, aColor, nScenFlags );
2787             pUndoDoc->SetScenarioData( nTab, aComment, aColor, nScenFlags );
2788             sal_Bool bActive = pDoc->IsActiveScenario( nTab );
2789             pUndoDoc->SetActiveScenario( nTab, bActive );
2790         }
2791         pUndoDoc->SetVisible( nTab, pDoc->IsVisible( nTab ) );
2792         pUndoDoc->SetTabBgColor( nTab, pDoc->GetTabBgColor(nTab) );
2793         pUndoDoc->SetSheetEvents( nTab, pDoc->GetSheetEvents( nTab ) );
2794 
2795         //  Drawing-Layer muss sein Undo selbst in der Hand behalten !!!
2796         pDoc->BeginDrawUndo();                          //  DeleteTab erzeugt ein SdrUndoDelPage
2797 
2798         pUndoData = new ScRefUndoData( pDoc );
2799     }
2800 
2801     String sCodeName;
2802     sal_Bool bHasCodeName = pDoc->GetCodeName( nTab, sCodeName );
2803     if (pDoc->DeleteTab( nTab, pUndoDoc ))
2804     {
2805         if (bRecord)
2806         {
2807             SvShorts theTabs;
2808             theTabs.push_back(nTab);
2809             rDocShell.GetUndoManager()->AddUndoAction(
2810                         new ScUndoDeleteTab( &rDocShell, theTabs, pUndoDoc, pUndoData ));
2811         }
2812         //  Views updaten:
2813         if( bVbaEnabled )
2814         {
2815             if( bHasCodeName )
2816             {
2817                 VBA_DeleteModule( rDocShell, sCodeName );
2818             }
2819         }
2820         rDocShell.Broadcast( ScTablesHint( SC_TAB_DELETED, nTab ) );
2821 
2822         if (bWasLinked)
2823         {
2824             rDocShell.UpdateLinks();                // Link-Manager updaten
2825             SfxBindings* pBindings = rDocShell.GetViewBindings();
2826             if (pBindings)
2827                 pBindings->Invalidate(SID_LINKS);
2828         }
2829 
2830         rDocShell.PostPaintExtras();
2831         aModificator.SetDocumentModified();
2832 
2833         SfxApplication* pSfxApp = SFX_APP();                                // Navigator
2834         pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2835         pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) );
2836         pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
2837 
2838         bSuccess = sal_True;
2839     }
2840     else
2841     {
2842         delete pUndoDoc;
2843         delete pUndoData;
2844     }
2845     return bSuccess;
2846 }
2847 
2848 sal_Bool ScDocFunc::SetTableVisible( SCTAB nTab, sal_Bool bVisible, sal_Bool bApi )
2849 {
2850     ScDocument* pDoc = rDocShell.GetDocument();
2851     sal_Bool bUndo(pDoc->IsUndoEnabled());
2852     if ( pDoc->IsVisible( nTab ) == bVisible )
2853         return sal_True;                                // nichts zu tun - ok
2854 
2855     if ( !pDoc->IsDocEditable() )
2856     {
2857         if (!bApi)
2858             rDocShell.ErrorMessage(STR_PROTECTIONERR);
2859         return sal_False;
2860     }
2861 
2862     ScDocShellModificator aModificator( rDocShell );
2863 
2864     if ( !bVisible && !pDoc->IsImportingXML() )     // #i57869# allow hiding in any order for loading
2865     {
2866         //  nicht alle Tabellen ausblenden
2867 
2868         sal_uInt16 nVisCount = 0;
2869         SCTAB nCount = pDoc->GetTableCount();
2870         for (SCTAB i=0; i<nCount; i++)
2871             if (pDoc->IsVisible(i))
2872                 ++nVisCount;
2873 
2874         if (nVisCount <= 1)
2875         {
2876             if (!bApi)
2877                 rDocShell.ErrorMessage(STR_PROTECTIONERR);  //! eigene Meldung?
2878             return sal_False;
2879         }
2880     }
2881 
2882     pDoc->SetVisible( nTab, bVisible );
2883     if (bUndo)
2884         rDocShell.GetUndoManager()->AddUndoAction( new ScUndoShowHideTab( &rDocShell, nTab, bVisible ) );
2885 
2886     //  Views updaten:
2887     if (!bVisible)
2888         rDocShell.Broadcast( ScTablesHint( SC_TAB_HIDDEN, nTab ) );
2889 
2890     SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2891     rDocShell.PostPaint(0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_EXTRAS);
2892     aModificator.SetDocumentModified();
2893 
2894     return sal_True;
2895 }
2896 
2897 sal_Bool ScDocFunc::SetLayoutRTL( SCTAB nTab, sal_Bool bRTL, sal_Bool /* bApi */ )
2898 {
2899     ScDocument* pDoc = rDocShell.GetDocument();
2900     sal_Bool bUndo(pDoc->IsUndoEnabled());
2901     if ( pDoc->IsLayoutRTL( nTab ) == bRTL )
2902         return sal_True;                                // nothing to do - ok
2903 
2904     //! protection (sheet or document?)
2905 
2906     ScDocShellModificator aModificator( rDocShell );
2907 
2908     pDoc->SetLayoutRTL( nTab, bRTL );
2909 
2910     if (bUndo)
2911     {
2912         rDocShell.GetUndoManager()->AddUndoAction( new ScUndoLayoutRTL( &rDocShell, nTab, bRTL ) );
2913     }
2914 
2915     rDocShell.PostPaint( 0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_ALL );
2916     aModificator.SetDocumentModified();
2917 
2918     SfxBindings* pBindings = rDocShell.GetViewBindings();
2919     if (pBindings)
2920     {
2921         pBindings->Invalidate( FID_TAB_RTL );
2922         pBindings->Invalidate( SID_ATTR_SIZE );
2923     }
2924 
2925     return sal_True;
2926 }
2927 
2928 //UNUSED2009-05 sal_Bool ScDocFunc::SetGrammar( formula::FormulaGrammar::Grammar eGrammar )
2929 //UNUSED2009-05 {
2930 //UNUSED2009-05     ScDocument* pDoc = rDocShell.GetDocument();
2931 //UNUSED2009-05
2932 //UNUSED2009-05     if ( pDoc->GetGrammar() == eGrammar )
2933 //UNUSED2009-05         return sal_True;
2934 //UNUSED2009-05
2935 //UNUSED2009-05     sal_Bool bUndo(pDoc->IsUndoEnabled());
2936 //UNUSED2009-05     ScDocShellModificator aModificator( rDocShell );
2937 //UNUSED2009-05
2938 //UNUSED2009-05     pDoc->SetGrammar( eGrammar );
2939 //UNUSED2009-05
2940 //UNUSED2009-05     if (bUndo)
2941 //UNUSED2009-05     {
2942 //UNUSED2009-05         rDocShell.GetUndoManager()->AddUndoAction( new ScUndoSetGrammar( &rDocShell, eGrammar ) );
2943 //UNUSED2009-05     }
2944 //UNUSED2009-05
2945 //UNUSED2009-05     rDocShell.PostPaint( 0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_ALL );
2946 //UNUSED2009-05
2947 //UNUSED2009-05     ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
2948 //UNUSED2009-05     if (NULL != pViewSh)
2949 //UNUSED2009-05     {
2950 //UNUSED2009-05         pViewSh->UpdateInputHandler( sal_False, sal_False );
2951 //UNUSED2009-05     }
2952 //UNUSED2009-05
2953 //UNUSED2009-05     aModificator.SetDocumentModified();
2954 //UNUSED2009-05
2955 //UNUSED2009-05     SfxBindings* pBindings = rDocShell.GetViewBindings();
2956 //UNUSED2009-05     if (pBindings)
2957 //UNUSED2009-05     {
2958 //UNUSED2009-05         // erAck: 2006-09-07T22:19+0200  commented out in CWS scr1c1
2959 //UNUSED2009-05         //pBindings->Invalidate( FID_TAB_USE_R1C1 );
2960 //UNUSED2009-05     }
2961 //UNUSED2009-05
2962 //UNUSED2009-05     return sal_True;
2963 //UNUSED2009-05 }
2964 
2965 sal_Bool ScDocFunc::RenameTable( SCTAB nTab, const String& rName, sal_Bool bRecord, sal_Bool bApi )
2966 {
2967     ScDocument* pDoc = rDocShell.GetDocument();
2968     if (bRecord && !pDoc->IsUndoEnabled())
2969         bRecord = sal_False;
2970     if ( !pDoc->IsDocEditable() )
2971     {
2972         if (!bApi)
2973             rDocShell.ErrorMessage(STR_PROTECTIONERR);
2974         return sal_False;
2975     }
2976 
2977     ScDocShellModificator aModificator( rDocShell );
2978 
2979     sal_Bool bSuccess = sal_False;
2980     String sOldName;
2981     pDoc->GetName(nTab, sOldName);
2982     if (pDoc->RenameTab( nTab, rName ))
2983     {
2984         if (bRecord)
2985         {
2986             rDocShell.GetUndoManager()->AddUndoAction(
2987                             new ScUndoRenameTab( &rDocShell, nTab, sOldName, rName));
2988         }
2989         rDocShell.PostPaintExtras();
2990         aModificator.SetDocumentModified();
2991         SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2992 
2993         bSuccess = sal_True;
2994     }
2995     return bSuccess;
2996 }
2997 
2998 bool ScDocFunc::SetTabBgColor( SCTAB nTab, const Color& rColor, bool bRecord, bool bApi )
2999 {
3000 
3001     ScDocument* pDoc = rDocShell.GetDocument();
3002     if (bRecord && !pDoc->IsUndoEnabled())
3003         bRecord = false;
3004     if ( !pDoc->IsDocEditable() || pDoc->IsTabProtected(nTab) )
3005     {
3006         if (!bApi)
3007             rDocShell.ErrorMessage(STR_PROTECTIONERR); //TODO Check to see what this string is...
3008         return false;
3009     }
3010 
3011     Color aOldTabBgColor;
3012     aOldTabBgColor = pDoc->GetTabBgColor(nTab);
3013 
3014     bool bSuccess = false;
3015     pDoc->SetTabBgColor(nTab, rColor);
3016     if ( pDoc->GetTabBgColor(nTab) == rColor)
3017         bSuccess = true;
3018     if (bSuccess)
3019     {
3020         if (bRecord)
3021         {
3022             rDocShell.GetUndoManager()->AddUndoAction(
3023                 new ScUndoTabColor( &rDocShell, nTab, aOldTabBgColor, rColor));
3024         }
3025         rDocShell.PostPaintExtras();
3026         ScDocShellModificator aModificator( rDocShell );
3027         aModificator.SetDocumentModified();
3028         SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
3029 
3030         bSuccess = true;
3031     }
3032     return bSuccess;
3033 }
3034 
3035 bool ScDocFunc::SetTabBgColor(
3036     ScUndoTabColorInfo::List& rUndoTabColorList, bool bRecord, bool bApi )
3037 {
3038     ScDocument* pDoc = rDocShell.GetDocument();
3039     if (bRecord && !pDoc->IsUndoEnabled())
3040         bRecord = false;
3041 
3042     if ( !pDoc->IsDocEditable() )
3043     {
3044         if (!bApi)
3045             rDocShell.ErrorMessage(STR_PROTECTIONERR); //TODO Get a better String Error...
3046         return false;
3047     }
3048 
3049     sal_uInt16 nTab;
3050     Color aNewTabBgColor;
3051     bool bSuccess = true;
3052     size_t nTabProtectCount = 0;
3053     size_t nTabListCount = rUndoTabColorList.size();
3054     for ( size_t i = 0; i < nTabListCount; ++i )
3055     {
3056         ScUndoTabColorInfo& rInfo = rUndoTabColorList[i];
3057         nTab = rInfo.mnTabId;
3058         if ( !pDoc->IsTabProtected(nTab) )
3059         {
3060             aNewTabBgColor = rInfo.maNewTabBgColor;
3061             rInfo.maOldTabBgColor = pDoc->GetTabBgColor(nTab);
3062             pDoc->SetTabBgColor(nTab, aNewTabBgColor);
3063             if ( pDoc->GetTabBgColor(nTab) != aNewTabBgColor)
3064             {
3065                 bSuccess = false;
3066                 break;
3067             }
3068         }
3069         else
3070         {
3071             nTabProtectCount++;
3072         }
3073     }
3074 
3075     if ( nTabProtectCount == nTabListCount )
3076     {
3077         if (!bApi)
3078             rDocShell.ErrorMessage(STR_PROTECTIONERR); //TODO Get a better String Error...
3079         return false;
3080     }
3081 
3082     if (bSuccess)
3083     {
3084         if (bRecord)
3085         {
3086             rDocShell.GetUndoManager()->AddUndoAction(
3087                 new ScUndoTabColor( &rDocShell, rUndoTabColorList));
3088         }
3089         rDocShell.PostPaintExtras();
3090         ScDocShellModificator aModificator( rDocShell );
3091         aModificator.SetDocumentModified();
3092     }
3093     return bSuccess;
3094 }
3095 
3096 //------------------------------------------------------------------------
3097 
3098 //! SetWidthOrHeight - noch doppelt zu ViewFunc !!!!!!
3099 //! Probleme:
3100 //! - Optimale Hoehe fuer Edit-Zellen ist unterschiedlich zwischen Drucker und Bildschirm
3101 //! - Optimale Breite braucht Selektion, um evtl. nur selektierte Zellen zu beruecksichtigen
3102 
3103 sal_uInt16 lcl_GetOptimalColWidth( ScDocShell& rDocShell, SCCOL nCol, SCTAB nTab, sal_Bool bFormula )
3104 {
3105     sal_uInt16 nTwips = 0;
3106 
3107     ScSizeDeviceProvider aProv(&rDocShell);
3108     OutputDevice* pDev = aProv.GetDevice();         // has pixel MapMode
3109     double nPPTX = aProv.GetPPTX();
3110     double nPPTY = aProv.GetPPTY();
3111 
3112     ScDocument* pDoc = rDocShell.GetDocument();
3113     Fraction aOne(1,1);
3114     nTwips = pDoc->GetOptimalColWidth( nCol, nTab, pDev, nPPTX, nPPTY, aOne, aOne,
3115                                         bFormula, NULL );
3116 
3117     return nTwips;
3118 }
3119 
3120 sal_Bool ScDocFunc::SetWidthOrHeight( sal_Bool bWidth, SCCOLROW nRangeCnt, SCCOLROW* pRanges, SCTAB nTab,
3121                                         ScSizeMode eMode, sal_uInt16 nSizeTwips,
3122                                         sal_Bool bRecord, sal_Bool bApi )
3123 {
3124     ScDocShellModificator aModificator( rDocShell );
3125 
3126     if (!nRangeCnt)
3127         return sal_True;
3128 
3129     ScDocument* pDoc = rDocShell.GetDocument();
3130     if ( bRecord && !pDoc->IsUndoEnabled() )
3131         bRecord = sal_False;
3132 
3133     // import into read-only document is possible
3134     if ( !pDoc->IsChangeReadOnlyEnabled() && !rDocShell.IsEditable() )
3135     {
3136         if (!bApi)
3137             rDocShell.ErrorMessage(STR_PROTECTIONERR);      //! eigene Meldung?
3138         return sal_False;
3139     }
3140 
3141     sal_Bool bSuccess = sal_False;
3142     SCCOLROW nStart = pRanges[0];
3143     SCCOLROW nEnd = pRanges[2*nRangeCnt-1];
3144 
3145     sal_Bool bFormula = sal_False;
3146     if ( eMode == SC_SIZE_OPTIMAL )
3147     {
3148         //! Option "Formeln anzeigen" - woher nehmen?
3149     }
3150 
3151     ScDocument*     pUndoDoc = NULL;
3152     ScOutlineTable* pUndoTab = NULL;
3153     SCCOLROW*       pUndoRanges = NULL;
3154 
3155     if ( bRecord )
3156     {
3157         pDoc->BeginDrawUndo();                          // Drawing Updates
3158 
3159         pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
3160         if (bWidth)
3161         {
3162             pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_False );
3163             pDoc->CopyToDocument( static_cast<SCCOL>(nStart), 0, nTab, static_cast<SCCOL>(nEnd), MAXROW, nTab, IDF_NONE, sal_False, pUndoDoc );
3164         }
3165         else
3166         {
3167             pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_False, sal_True );
3168             pDoc->CopyToDocument( 0, static_cast<SCROW>(nStart), nTab, MAXCOL, static_cast<SCROW>(nEnd), nTab, IDF_NONE, sal_False, pUndoDoc );
3169         }
3170 
3171         pUndoRanges = new SCCOLROW[ 2*nRangeCnt ];
3172         memmove( pUndoRanges, pRanges, 2*nRangeCnt*sizeof(SCCOLROW) );
3173 
3174         ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab );
3175         if (pTable)
3176             pUndoTab = new ScOutlineTable( *pTable );
3177     }
3178 
3179     sal_Bool bShow = nSizeTwips > 0 || eMode != SC_SIZE_DIRECT;
3180     sal_Bool bOutline = sal_False;
3181 
3182     pDoc->IncSizeRecalcLevel( nTab );       // nicht fuer jede Spalte einzeln
3183     for (SCCOLROW nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++)
3184     {
3185         SCCOLROW nStartNo = *(pRanges++);
3186         SCCOLROW nEndNo = *(pRanges++);
3187 
3188         if ( !bWidth )                      // Hoehen immer blockweise
3189         {
3190             if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
3191             {
3192                 sal_Bool bAll = ( eMode==SC_SIZE_OPTIMAL );
3193                 if (!bAll)
3194                 {
3195                     //  fuer alle eingeblendeten CR_MANUALSIZE loeschen,
3196                     //  dann SetOptimalHeight mit bShrink = FALSE
3197                     for (SCROW nRow=nStartNo; nRow<=nEndNo; nRow++)
3198                     {
3199                         sal_uInt8 nOld = pDoc->GetRowFlags(nRow,nTab);
3200                         SCROW nLastRow = -1;
3201                         bool bHidden = pDoc->RowHidden(nRow, nTab, nLastRow);
3202                         if ( !bHidden && ( nOld & CR_MANUALSIZE ) )
3203                             pDoc->SetRowFlags( nRow, nTab, nOld & ~CR_MANUALSIZE );
3204                     }
3205                 }
3206 
3207                 ScSizeDeviceProvider aProv( &rDocShell );
3208                 Fraction aOne(1,1);
3209                 pDoc->SetOptimalHeight( nStartNo, nEndNo, nTab, 0, aProv.GetDevice(),
3210                                         aProv.GetPPTX(), aProv.GetPPTY(), aOne, aOne, bAll );
3211 
3212                 if (bAll)
3213                     pDoc->ShowRows( nStartNo, nEndNo, nTab, sal_True );
3214 
3215                 //  Manual-Flag wird bei bAll=sal_True schon in SetOptimalHeight gesetzt
3216                 //  (an bei Extra-Height, sonst aus).
3217             }
3218             else if ( eMode==SC_SIZE_DIRECT || eMode==SC_SIZE_ORIGINAL )
3219             {
3220                 if (nSizeTwips)
3221                 {
3222                     pDoc->SetRowHeightRange( nStartNo, nEndNo, nTab, nSizeTwips );
3223                     pDoc->SetManualHeight( nStartNo, nEndNo, nTab, sal_True );          // height was set manually
3224                 }
3225                 if ( eMode != SC_SIZE_ORIGINAL )
3226                     pDoc->ShowRows( nStartNo, nEndNo, nTab, nSizeTwips != 0 );
3227             }
3228             else if ( eMode==SC_SIZE_SHOW )
3229             {
3230                 pDoc->ShowRows( nStartNo, nEndNo, nTab, sal_True );
3231             }
3232         }
3233         else                                // Spaltenbreiten
3234         {
3235             for (SCCOL nCol=static_cast<SCCOL>(nStartNo); nCol<=static_cast<SCCOL>(nEndNo); nCol++)
3236             {
3237                 SCCOL nLastCol = -1;
3238                 if ( eMode != SC_SIZE_VISOPT || !pDoc->ColHidden(nCol, nTab, nLastCol) )
3239                 {
3240                     sal_uInt16 nThisSize = nSizeTwips;
3241 
3242                     if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
3243                         nThisSize = nSizeTwips +
3244                                     lcl_GetOptimalColWidth( rDocShell, nCol, nTab, bFormula );
3245                     if ( nThisSize )
3246                         pDoc->SetColWidth( nCol, nTab, nThisSize );
3247 
3248                     if ( eMode != SC_SIZE_ORIGINAL )
3249                         pDoc->ShowCol( nCol, nTab, bShow );
3250                 }
3251             }
3252         }
3253 
3254                             //  adjust outlines
3255 
3256         if ( eMode != SC_SIZE_ORIGINAL )
3257         {
3258             if (bWidth)
3259                 bOutline = bOutline || pDoc->UpdateOutlineCol(
3260                         static_cast<SCCOL>(nStartNo),
3261                         static_cast<SCCOL>(nEndNo), nTab, bShow );
3262             else
3263                 bOutline = bOutline || pDoc->UpdateOutlineRow(
3264                         static_cast<SCROW>(nStartNo),
3265                         static_cast<SCROW>(nEndNo), nTab, bShow );
3266         }
3267     }
3268     pDoc->DecSizeRecalcLevel( nTab );       // nicht fuer jede Spalte einzeln
3269 
3270     if (!bOutline)
3271         DELETEZ(pUndoTab);
3272 
3273     if (bRecord)
3274     {
3275         ScMarkData aMark;
3276         aMark.SelectOneTable( nTab );
3277         rDocShell.GetUndoManager()->AddUndoAction(
3278             new ScUndoWidthOrHeight( &rDocShell, aMark,
3279                                      nStart, nTab, nEnd, nTab,
3280                                      pUndoDoc, nRangeCnt, pUndoRanges,
3281                                      pUndoTab, eMode, nSizeTwips, bWidth ) );
3282     }
3283 
3284     pDoc->UpdatePageBreaks( nTab );
3285 
3286     rDocShell.PostPaint(0,0,nTab,MAXCOL,MAXROW,nTab,PAINT_ALL);
3287     aModificator.SetDocumentModified();
3288 
3289     return bSuccess;
3290 }
3291 
3292 
3293 sal_Bool ScDocFunc::InsertPageBreak( sal_Bool bColumn, const ScAddress& rPos,
3294                                 sal_Bool bRecord, sal_Bool bSetModified, sal_Bool /* bApi */ )
3295 {
3296     ScDocShellModificator aModificator( rDocShell );
3297 
3298     ScDocument* pDoc = rDocShell.GetDocument();
3299     if (bRecord && !pDoc->IsUndoEnabled())
3300         bRecord = sal_False;
3301     SCTAB nTab = rPos.Tab();
3302     SfxBindings* pBindings = rDocShell.GetViewBindings();
3303 
3304     SCCOLROW nPos = bColumn ? static_cast<SCCOLROW>(rPos.Col()) :
3305         static_cast<SCCOLROW>(rPos.Row());
3306     if (nPos == 0)
3307         return sal_False;                   // erste Spalte / Zeile
3308 
3309     ScBreakType nBreak = bColumn ?
3310         pDoc->HasColBreak(static_cast<SCCOL>(nPos), nTab) :
3311         pDoc->HasRowBreak(static_cast<SCROW>(nPos), nTab);
3312     if (nBreak & BREAK_MANUAL)
3313         return true;
3314 
3315     if (bRecord)
3316         rDocShell.GetUndoManager()->AddUndoAction(
3317             new ScUndoPageBreak( &rDocShell, rPos.Col(), rPos.Row(), nTab, bColumn, sal_True ) );
3318 
3319     if (bColumn)
3320         pDoc->SetColBreak(static_cast<SCCOL>(nPos), nTab, false, true);
3321     else
3322         pDoc->SetRowBreak(static_cast<SCROW>(nPos), nTab, false, true);
3323 
3324     pDoc->InvalidatePageBreaks(nTab);
3325     pDoc->UpdatePageBreaks( nTab );
3326 
3327     if (pDoc->IsStreamValid(nTab))
3328         pDoc->SetStreamValid(nTab, sal_False);
3329 
3330     if (bColumn)
3331     {
3332         rDocShell.PostPaint( static_cast<SCCOL>(nPos)-1, 0, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID );
3333         if (pBindings)
3334         {
3335             pBindings->Invalidate( FID_INS_COLBRK );
3336             pBindings->Invalidate( FID_DEL_COLBRK );
3337         }
3338     }
3339     else
3340     {
3341         rDocShell.PostPaint( 0, static_cast<SCROW>(nPos)-1, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID );
3342         if (pBindings)
3343         {
3344             pBindings->Invalidate( FID_INS_ROWBRK );
3345             pBindings->Invalidate( FID_DEL_ROWBRK );
3346         }
3347     }
3348     if (pBindings)
3349         pBindings->Invalidate( FID_DEL_MANUALBREAKS );
3350 
3351     if (bSetModified)
3352         aModificator.SetDocumentModified();
3353 
3354     return sal_True;
3355 }
3356 
3357 sal_Bool ScDocFunc::RemovePageBreak( sal_Bool bColumn, const ScAddress& rPos,
3358                                 sal_Bool bRecord, sal_Bool bSetModified, sal_Bool /* bApi */ )
3359 {
3360     ScDocShellModificator aModificator( rDocShell );
3361 
3362     ScDocument* pDoc = rDocShell.GetDocument();
3363     if (bRecord && !pDoc->IsUndoEnabled())
3364         bRecord = sal_False;
3365     SCTAB nTab = rPos.Tab();
3366     SfxBindings* pBindings = rDocShell.GetViewBindings();
3367 
3368     SCCOLROW nPos = bColumn ? static_cast<SCCOLROW>(rPos.Col()) :
3369         static_cast<SCCOLROW>(rPos.Row());
3370 
3371     ScBreakType nBreak;
3372     if (bColumn)
3373         nBreak = pDoc->HasColBreak(static_cast<SCCOL>(nPos), nTab);
3374     else
3375         nBreak = pDoc->HasRowBreak(static_cast<SCROW>(nPos), nTab);
3376     if ((nBreak & BREAK_MANUAL) == 0)
3377         // There is no manual break.
3378         return false;
3379 
3380     if (bRecord)
3381         rDocShell.GetUndoManager()->AddUndoAction(
3382             new ScUndoPageBreak( &rDocShell, rPos.Col(), rPos.Row(), nTab, bColumn, sal_False ) );
3383 
3384     if (bColumn)
3385         pDoc->RemoveColBreak(static_cast<SCCOL>(nPos), nTab, false, true);
3386     else
3387         pDoc->RemoveRowBreak(static_cast<SCROW>(nPos), nTab, false, true);
3388 
3389     pDoc->UpdatePageBreaks( nTab );
3390 
3391     if (pDoc->IsStreamValid(nTab))
3392         pDoc->SetStreamValid(nTab, sal_False);
3393 
3394     if (bColumn)
3395     {
3396         rDocShell.PostPaint( static_cast<SCCOL>(nPos)-1, 0, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID );
3397         if (pBindings)
3398         {
3399             pBindings->Invalidate( FID_INS_COLBRK );
3400             pBindings->Invalidate( FID_DEL_COLBRK );
3401         }
3402     }
3403     else
3404     {
3405         rDocShell.PostPaint( 0, nPos-1, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID );
3406         if (pBindings)
3407         {
3408             pBindings->Invalidate( FID_INS_ROWBRK );
3409             pBindings->Invalidate( FID_DEL_ROWBRK );
3410         }
3411     }
3412     if (pBindings)
3413         pBindings->Invalidate( FID_DEL_MANUALBREAKS );
3414 
3415     if (bSetModified)
3416         aModificator.SetDocumentModified();
3417 
3418     return sal_True;
3419 }
3420 
3421 //------------------------------------------------------------------------
3422 
3423 void ScDocFunc::ProtectSheet( SCTAB nTab, const ScTableProtection& rProtect )
3424 {
3425     ScDocument* pDoc = rDocShell.GetDocument();
3426 
3427     pDoc->SetTabProtection(nTab, &rProtect);
3428     if (pDoc->IsUndoEnabled())
3429     {
3430         ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
3431         DBG_ASSERT(pProtect, "ScDocFunc::Unprotect: ScTableProtection pointer is NULL!");
3432         if (pProtect)
3433         {
3434             ::std::auto_ptr<ScTableProtection> p(new ScTableProtection(*pProtect));
3435             p->setProtected(true); // just in case ...
3436             rDocShell.GetUndoManager()->AddUndoAction(
3437                 new ScUndoTabProtect(&rDocShell, nTab, p) );
3438 
3439             // ownership of auto_ptr now transferred to ScUndoTabProtect.
3440         }
3441     }
3442 
3443     rDocShell.PostPaintGridAll();
3444     ScDocShellModificator aModificator(rDocShell);
3445     aModificator.SetDocumentModified();
3446 }
3447 
3448 sal_Bool ScDocFunc::Protect( SCTAB nTab, const String& rPassword, sal_Bool /*bApi*/ )
3449 {
3450     ScDocument* pDoc = rDocShell.GetDocument();
3451     if (nTab == TABLEID_DOC)
3452     {
3453         // document protection
3454         ScDocProtection aProtection;
3455         aProtection.setProtected(true);
3456         aProtection.setPassword(rPassword);
3457         pDoc->SetDocProtection(&aProtection);
3458         if (pDoc->IsUndoEnabled())
3459         {
3460             ScDocProtection* pProtect = pDoc->GetDocProtection();
3461             DBG_ASSERT(pProtect, "ScDocFunc::Unprotect: ScDocProtection pointer is NULL!");
3462             if (pProtect)
3463             {
3464                 ::std::auto_ptr<ScDocProtection> p(new ScDocProtection(*pProtect));
3465                 p->setProtected(true); // just in case ...
3466                 rDocShell.GetUndoManager()->AddUndoAction(
3467                     new ScUndoDocProtect(&rDocShell, p) );
3468                 // ownership of auto_ptr is transferred to ScUndoDocProtect.
3469             }
3470         }
3471     }
3472     else
3473     {
3474         // sheet protection
3475 
3476         ScTableProtection aProtection;
3477         aProtection.setProtected(true);
3478         aProtection.setPassword(rPassword);
3479         pDoc->SetTabProtection(nTab, &aProtection);
3480         if (pDoc->IsUndoEnabled())
3481         {
3482             ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
3483             DBG_ASSERT(pProtect, "ScDocFunc::Unprotect: ScTableProtection pointer is NULL!");
3484             if (pProtect)
3485             {
3486                 ::std::auto_ptr<ScTableProtection> p(new ScTableProtection(*pProtect));
3487                 p->setProtected(true); // just in case ...
3488                 rDocShell.GetUndoManager()->AddUndoAction(
3489                     new ScUndoTabProtect(&rDocShell, nTab, p) );
3490                 // ownership of auto_ptr now transferred to ScUndoTabProtect.
3491             }
3492         }
3493     }
3494 
3495     rDocShell.PostPaintGridAll();
3496     ScDocShellModificator aModificator( rDocShell );
3497     aModificator.SetDocumentModified();
3498 
3499     return true;
3500 }
3501 
3502 sal_Bool ScDocFunc::Unprotect( SCTAB nTab, const String& rPassword, sal_Bool bApi )
3503 {
3504     ScDocument* pDoc = rDocShell.GetDocument();
3505 
3506     if (nTab == TABLEID_DOC)
3507     {
3508         // document protection
3509 
3510         ScDocProtection* pDocProtect = pDoc->GetDocProtection();
3511         if (!pDocProtect || !pDocProtect->isProtected())
3512             // already unprotected (should not happen)!
3513             return true;
3514 
3515         // save the protection state before unprotect (for undo).
3516         ::std::auto_ptr<ScDocProtection> pProtectCopy(new ScDocProtection(*pDocProtect));
3517 
3518         if (!pDocProtect->verifyPassword(rPassword))
3519         {
3520             if (!bApi)
3521             {
3522                 InfoBox aBox( rDocShell.GetActiveDialogParent(), String( ScResId( SCSTR_WRONGPASSWORD ) ) );
3523                 aBox.Execute();
3524             }
3525             return false;
3526         }
3527 
3528         pDoc->SetDocProtection(NULL);
3529         if (pDoc->IsUndoEnabled())
3530         {
3531             pProtectCopy->setProtected(false);
3532             rDocShell.GetUndoManager()->AddUndoAction(
3533                 new ScUndoDocProtect(&rDocShell, pProtectCopy) );
3534             // ownership of auto_ptr now transferred to ScUndoDocProtect.
3535         }
3536     }
3537     else
3538     {
3539         // sheet protection
3540 
3541         ScTableProtection* pTabProtect = pDoc->GetTabProtection(nTab);
3542         if (!pTabProtect || !pTabProtect->isProtected())
3543             // already unprotected (should not happen)!
3544             return true;
3545 
3546         // save the protection state before unprotect (for undo).
3547         ::std::auto_ptr<ScTableProtection> pProtectCopy(new ScTableProtection(*pTabProtect));
3548         if (!pTabProtect->verifyPassword(rPassword))
3549         {
3550             if (!bApi)
3551             {
3552                 InfoBox aBox( rDocShell.GetActiveDialogParent(), String( ScResId( SCSTR_WRONGPASSWORD ) ) );
3553                 aBox.Execute();
3554             }
3555             return false;
3556         }
3557 
3558         pDoc->SetTabProtection(nTab, NULL);
3559         if (pDoc->IsUndoEnabled())
3560         {
3561             pProtectCopy->setProtected(false);
3562             rDocShell.GetUndoManager()->AddUndoAction(
3563                 new ScUndoTabProtect(&rDocShell, nTab, pProtectCopy) );
3564             // ownership of auto_ptr now transferred to ScUndoTabProtect.
3565         }
3566     }
3567 
3568     rDocShell.PostPaintGridAll();
3569     ScDocShellModificator aModificator( rDocShell );
3570     aModificator.SetDocumentModified();
3571 
3572     return true;
3573 }
3574 
3575 //------------------------------------------------------------------------
3576 
3577 sal_Bool ScDocFunc::ClearItems( const ScMarkData& rMark, const sal_uInt16* pWhich, sal_Bool bApi )
3578 {
3579     ScDocShellModificator aModificator( rDocShell );
3580 
3581     ScDocument* pDoc = rDocShell.GetDocument();
3582     sal_Bool bUndo (pDoc->IsUndoEnabled());
3583     ScEditableTester aTester( pDoc, rMark );
3584     if (!aTester.IsEditable())
3585     {
3586         if (!bApi)
3587             rDocShell.ErrorMessage(aTester.GetMessageId());
3588         return sal_False;
3589     }
3590 
3591     //  #i12940# ClearItems is called (from setPropertyToDefault) directly with uno object's cached
3592     //  MarkData (GetMarkData), so rMark must be changed to multi selection for ClearSelectionItems
3593     //  here.
3594 
3595     ScRange aMarkRange;
3596     ScMarkData aMultiMark = rMark;
3597     aMultiMark.SetMarking(sal_False);       // for MarkToMulti
3598     aMultiMark.MarkToMulti();
3599     aMultiMark.GetMultiMarkArea( aMarkRange );
3600 
3601 //  if (bRecord)
3602     if (bUndo)
3603     {
3604         SCTAB nStartTab = aMarkRange.aStart.Tab();
3605         SCTAB nEndTab = aMarkRange.aEnd.Tab();
3606 
3607         ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
3608         pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab );
3609         pDoc->CopyToDocument( aMarkRange, IDF_ATTRIB, sal_True, pUndoDoc, (ScMarkData*)&aMultiMark );
3610 
3611         rDocShell.GetUndoManager()->AddUndoAction(
3612             new ScUndoClearItems( &rDocShell, aMultiMark, pUndoDoc, pWhich ) );
3613     }
3614 
3615     pDoc->ClearSelectionItems( pWhich, aMultiMark );
3616 
3617     rDocShell.PostPaint( aMarkRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
3618     aModificator.SetDocumentModified();
3619 
3620     //! Bindings-Invalidate etc.?
3621 
3622     return sal_True;
3623 }
3624 
3625 sal_Bool ScDocFunc::ChangeIndent( const ScMarkData& rMark, sal_Bool bIncrement, sal_Bool bApi )
3626 {
3627     ScDocShellModificator aModificator( rDocShell );
3628 
3629     ScDocument* pDoc = rDocShell.GetDocument();
3630     sal_Bool bUndo(pDoc->IsUndoEnabled());
3631     ScEditableTester aTester( pDoc, rMark );
3632     if (!aTester.IsEditable())
3633     {
3634         if (!bApi)
3635             rDocShell.ErrorMessage(aTester.GetMessageId());
3636         return sal_False;
3637     }
3638 
3639     ScRange aMarkRange;
3640     rMark.GetMultiMarkArea( aMarkRange );
3641 
3642 //  if (bRecord)
3643     if (bUndo)
3644     {
3645         SCTAB nStartTab = aMarkRange.aStart.Tab();
3646         SCTAB nTabCount = pDoc->GetTableCount();
3647 
3648         ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
3649         pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab );
3650         for (SCTAB i=0; i<nTabCount; i++)
3651             if (i != nStartTab && rMark.GetTableSelect(i))
3652                 pUndoDoc->AddUndoTab( i, i );
3653 
3654         ScRange aCopyRange = aMarkRange;
3655         aCopyRange.aStart.SetTab(0);
3656         aCopyRange.aEnd.SetTab(nTabCount-1);
3657         pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, sal_True, pUndoDoc, (ScMarkData*)&rMark );
3658 
3659         rDocShell.GetUndoManager()->AddUndoAction(
3660             new ScUndoIndent( &rDocShell, rMark, pUndoDoc, bIncrement ) );
3661     }
3662 
3663     pDoc->ChangeSelectionIndent( bIncrement, rMark );
3664 
3665     rDocShell.PostPaint( aMarkRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
3666     aModificator.SetDocumentModified();
3667 
3668     SfxBindings* pBindings = rDocShell.GetViewBindings();
3669     if (pBindings)
3670     {
3671         pBindings->Invalidate( SID_ALIGNLEFT );         // ChangeIndent setzt auf links
3672         pBindings->Invalidate( SID_ALIGNRIGHT );
3673         pBindings->Invalidate( SID_ALIGNBLOCK );
3674         pBindings->Invalidate( SID_ALIGNCENTERHOR );
3675         // pseudo slots for Format menu
3676         pBindings->Invalidate( SID_ALIGN_ANY_HDEFAULT );
3677         pBindings->Invalidate( SID_ALIGN_ANY_LEFT );
3678         pBindings->Invalidate( SID_ALIGN_ANY_HCENTER );
3679         pBindings->Invalidate( SID_ALIGN_ANY_RIGHT );
3680         pBindings->Invalidate( SID_ALIGN_ANY_JUSTIFIED );
3681     }
3682 
3683     return sal_True;
3684 }
3685 
3686 sal_Bool ScDocFunc::AutoFormat( const ScRange& rRange, const ScMarkData* pTabMark,
3687                             sal_uInt16 nFormatNo, sal_Bool bRecord, sal_Bool bApi )
3688 {
3689     ScDocShellModificator aModificator( rDocShell );
3690 
3691     sal_Bool bSuccess = sal_False;
3692     ScDocument* pDoc = rDocShell.GetDocument();
3693     SCCOL nStartCol = rRange.aStart.Col();
3694     SCROW nStartRow = rRange.aStart.Row();
3695     SCTAB nStartTab = rRange.aStart.Tab();
3696     SCCOL nEndCol = rRange.aEnd.Col();
3697     SCROW nEndRow = rRange.aEnd.Row();
3698     SCTAB nEndTab = rRange.aEnd.Tab();
3699 
3700     if (bRecord && !pDoc->IsUndoEnabled())
3701         bRecord = sal_False;
3702     ScMarkData aMark;
3703     if (pTabMark)
3704         aMark = *pTabMark;
3705     else
3706     {
3707         for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
3708             aMark.SelectTable( nTab, sal_True );
3709     }
3710 
3711     ScAutoFormat* pAutoFormat = ScGlobal::GetAutoFormat();
3712     ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
3713     if ( pAutoFormat && nFormatNo < pAutoFormat->GetCount() && aTester.IsEditable() )
3714     {
3715         WaitObject aWait( rDocShell.GetActiveDialogParent() );
3716 
3717         sal_Bool bSize = (*pAutoFormat)[nFormatNo]->GetIncludeWidthHeight();
3718 
3719         SCTAB nTabCount = pDoc->GetTableCount();
3720         ScDocument* pUndoDoc = NULL;
3721         if ( bRecord )
3722         {
3723             pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
3724             pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab, bSize, bSize );
3725             for (SCTAB i=0; i<nTabCount; i++)
3726                 if (i != nStartTab && aMark.GetTableSelect(i))
3727                     pUndoDoc->AddUndoTab( i, i, bSize, bSize );
3728 
3729             ScRange aCopyRange = rRange;
3730             aCopyRange.aStart.SetTab(0);
3731             aCopyRange.aStart.SetTab(nTabCount-1);
3732             pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, sal_False, pUndoDoc, &aMark );
3733             if (bSize)
3734             {
3735                 pDoc->CopyToDocument( nStartCol,0,0, nEndCol,MAXROW,nTabCount-1,
3736                                                             IDF_NONE, sal_False, pUndoDoc, &aMark );
3737                 pDoc->CopyToDocument( 0,nStartRow,0, MAXCOL,nEndRow,nTabCount-1,
3738                                                             IDF_NONE, sal_False, pUndoDoc, &aMark );
3739             }
3740             pDoc->BeginDrawUndo();
3741         }
3742 
3743         pDoc->AutoFormat( nStartCol, nStartRow, nEndCol, nEndRow, nFormatNo, aMark );
3744 
3745         if (bSize)
3746         {
3747 /*          SCCOL nCols[2];
3748             nCols[0] = nStartCol;
3749             nCols[1] = nEndCol;
3750             SCROW nRows[2];
3751             nRows[0] = nStartRow;
3752             nRows[1] = nEndRow;
3753 */
3754             SCCOLROW nCols[2] = { nStartCol, nEndCol };
3755             SCCOLROW nRows[2] = { nStartRow, nEndRow };
3756 
3757             for (SCTAB nTab=0; nTab<nTabCount; nTab++)
3758                 if (aMark.GetTableSelect(nTab))
3759                 {
3760                     SetWidthOrHeight( sal_True, 1,nCols, nTab, SC_SIZE_VISOPT, STD_EXTRA_WIDTH, sal_False, sal_True);
3761                     SetWidthOrHeight( sal_False,1,nRows, nTab, SC_SIZE_VISOPT, 0, sal_False, sal_False);
3762                     rDocShell.PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab,
3763                                     PAINT_GRID | PAINT_LEFT | PAINT_TOP );
3764                 }
3765         }
3766         else
3767         {
3768             for (SCTAB nTab=0; nTab<nTabCount; nTab++)
3769                 if (aMark.GetTableSelect(nTab))
3770                 {
3771                     sal_Bool bAdj = AdjustRowHeight( ScRange(nStartCol, nStartRow, nTab,
3772                                                         nEndCol, nEndRow, nTab), sal_False );
3773                     if (bAdj)
3774                         rDocShell.PostPaint( 0,nStartRow,nTab, MAXCOL,MAXROW,nTab,
3775                                             PAINT_GRID | PAINT_LEFT );
3776                     else
3777                         rDocShell.PostPaint( nStartCol, nStartRow, nTab,
3778                                             nEndCol, nEndRow, nTab, PAINT_GRID );
3779                 }
3780         }
3781 
3782         if ( bRecord )      // Draw-Undo erst jetzt verfuegbar
3783         {
3784             rDocShell.GetUndoManager()->AddUndoAction(
3785                 new ScUndoAutoFormat( &rDocShell, rRange, pUndoDoc, aMark, bSize, nFormatNo ) );
3786         }
3787 
3788         aModificator.SetDocumentModified();
3789     }
3790     else if (!bApi)
3791         rDocShell.ErrorMessage(aTester.GetMessageId());
3792 
3793     return bSuccess;
3794 }
3795 
3796 //------------------------------------------------------------------------
3797 
3798 sal_Bool ScDocFunc::EnterMatrix( const ScRange& rRange, const ScMarkData* pTabMark,
3799         const ScTokenArray* pTokenArray, const String& rString, sal_Bool bApi, sal_Bool bEnglish,
3800         const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar )
3801 {
3802     ScDocShellModificator aModificator( rDocShell );
3803 
3804     sal_Bool bSuccess = sal_False;
3805     ScDocument* pDoc = rDocShell.GetDocument();
3806     SCCOL nStartCol = rRange.aStart.Col();
3807     SCROW nStartRow = rRange.aStart.Row();
3808     SCTAB nStartTab = rRange.aStart.Tab();
3809     SCCOL nEndCol = rRange.aEnd.Col();
3810     SCROW nEndRow = rRange.aEnd.Row();
3811     SCTAB nEndTab = rRange.aEnd.Tab();
3812 
3813     sal_Bool bUndo(pDoc->IsUndoEnabled());
3814 
3815     ScMarkData aMark;
3816     if (pTabMark)
3817         aMark = *pTabMark;
3818     else
3819     {
3820         for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
3821             aMark.SelectTable( nTab, sal_True );
3822     }
3823 
3824     ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
3825     if ( aTester.IsEditable() )
3826     {
3827         WaitObject aWait( rDocShell.GetActiveDialogParent() );
3828 
3829         ScDocument* pUndoDoc = NULL;
3830 //      if (bRecord)    // immer
3831         if (bUndo)
3832         {
3833             //! auch bei Undo selektierte Tabellen beruecksichtigen
3834             pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
3835             pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab );
3836             pDoc->CopyToDocument( rRange, IDF_ALL & ~IDF_NOTE, sal_False, pUndoDoc );
3837         }
3838 
3839         // use TokenArray if given, string (and flags) otherwise
3840         if ( pTokenArray )
3841         {
3842             pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow,
3843                     aMark, EMPTY_STRING, pTokenArray, eGrammar);
3844         }
3845         else if ( pDoc->IsImportingXML() )
3846         {
3847             ScTokenArray* pCode = lcl_ScDocFunc_CreateTokenArrayXML( rString, rFormulaNmsp, eGrammar );
3848             pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow,
3849                     aMark, EMPTY_STRING, pCode, eGrammar);
3850             delete pCode;
3851             pDoc->IncXMLImportedFormulaCount( rString.Len() );
3852         }
3853         else if (bEnglish)
3854         {
3855             ScCompiler aComp( pDoc, rRange.aStart);
3856             aComp.SetGrammar(eGrammar);
3857             ScTokenArray* pCode = aComp.CompileString( rString );
3858             pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow,
3859                     aMark, EMPTY_STRING, pCode, eGrammar);
3860             delete pCode;
3861         }
3862         else
3863             pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow,
3864                     aMark, rString, NULL, eGrammar);
3865 
3866 //      if (bRecord)    // immer
3867         if (bUndo)
3868         {
3869             //! auch bei Undo selektierte Tabellen beruecksichtigen
3870             rDocShell.GetUndoManager()->AddUndoAction(
3871                 new ScUndoEnterMatrix( &rDocShell, rRange, pUndoDoc, rString ) );
3872         }
3873 
3874         //  Err522 beim Paint von DDE-Formeln werden jetzt beim Interpretieren abgefangen
3875         rDocShell.PostPaint( nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab, PAINT_GRID );
3876         aModificator.SetDocumentModified();
3877 
3878         bSuccess = sal_True;
3879     }
3880     else if (!bApi)
3881         rDocShell.ErrorMessage(aTester.GetMessageId());
3882 
3883     return bSuccess;
3884 }
3885 
3886 //------------------------------------------------------------------------
3887 
3888 sal_Bool ScDocFunc::TabOp( const ScRange& rRange, const ScMarkData* pTabMark,
3889                             const ScTabOpParam& rParam, sal_Bool bRecord, sal_Bool bApi )
3890 {
3891     ScDocShellModificator aModificator( rDocShell );
3892 
3893     sal_Bool bSuccess = sal_False;
3894     ScDocument* pDoc = rDocShell.GetDocument();
3895     SCCOL nStartCol = rRange.aStart.Col();
3896     SCROW nStartRow = rRange.aStart.Row();
3897     SCTAB nStartTab = rRange.aStart.Tab();
3898     SCCOL nEndCol = rRange.aEnd.Col();
3899     SCROW nEndRow = rRange.aEnd.Row();
3900     SCTAB nEndTab = rRange.aEnd.Tab();
3901 
3902     if (bRecord && !pDoc->IsUndoEnabled())
3903         bRecord = sal_False;
3904 
3905     ScMarkData aMark;
3906     if (pTabMark)
3907         aMark = *pTabMark;
3908     else
3909     {
3910         for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
3911             aMark.SelectTable( nTab, sal_True );
3912     }
3913 
3914     ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
3915     if ( aTester.IsEditable() )
3916     {
3917         WaitObject aWait( rDocShell.GetActiveDialogParent() );
3918         pDoc->SetDirty( rRange );
3919         if ( bRecord )
3920         {
3921             //! auch bei Undo selektierte Tabellen beruecksichtigen
3922             ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
3923             pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab );
3924             pDoc->CopyToDocument( rRange, IDF_ALL & ~IDF_NOTE, sal_False, pUndoDoc );
3925 
3926             rDocShell.GetUndoManager()->AddUndoAction(
3927                     new ScUndoTabOp( &rDocShell,
3928                                      nStartCol, nStartRow, nStartTab,
3929                                      nEndCol, nEndRow, nEndTab, pUndoDoc,
3930                                      rParam.aRefFormulaCell,
3931                                      rParam.aRefFormulaEnd,
3932                                      rParam.aRefRowCell,
3933                                      rParam.aRefColCell,
3934                                      rParam.nMode) );
3935         }
3936         pDoc->InsertTableOp(rParam, nStartCol, nStartRow, nEndCol, nEndRow, aMark);
3937         rDocShell.PostPaintGridAll();
3938         aModificator.SetDocumentModified();
3939         bSuccess = sal_True;
3940     }
3941     else if (!bApi)
3942         rDocShell.ErrorMessage(aTester.GetMessageId());
3943 
3944     return bSuccess;
3945 }
3946 
3947 //------------------------------------------------------------------------
3948 
3949 inline ScDirection DirFromFillDir( FillDir eDir )
3950 {
3951     if (eDir==FILL_TO_BOTTOM)
3952         return DIR_BOTTOM;
3953     else if (eDir==FILL_TO_RIGHT)
3954         return DIR_RIGHT;
3955     else if (eDir==FILL_TO_TOP)
3956         return DIR_TOP;
3957     else // if (eDir==FILL_TO_LEFT)
3958         return DIR_LEFT;
3959 }
3960 
3961 sal_Bool ScDocFunc::FillSimple( const ScRange& rRange, const ScMarkData* pTabMark,
3962                             FillDir eDir, sal_Bool bRecord, sal_Bool bApi )
3963 {
3964     ScDocShellModificator aModificator( rDocShell );
3965 
3966     sal_Bool bSuccess = sal_False;
3967     ScDocument* pDoc = rDocShell.GetDocument();
3968     SCCOL nStartCol = rRange.aStart.Col();
3969     SCROW nStartRow = rRange.aStart.Row();
3970     SCTAB nStartTab = rRange.aStart.Tab();
3971     SCCOL nEndCol = rRange.aEnd.Col();
3972     SCROW nEndRow = rRange.aEnd.Row();
3973     SCTAB nEndTab = rRange.aEnd.Tab();
3974 
3975     if (bRecord && !pDoc->IsUndoEnabled())
3976         bRecord = sal_False;
3977 
3978     ScMarkData aMark;
3979     if (pTabMark)
3980         aMark = *pTabMark;
3981     else
3982     {
3983         for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
3984             aMark.SelectTable( nTab, sal_True );
3985     }
3986 
3987     ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
3988     if ( aTester.IsEditable() )
3989     {
3990         WaitObject aWait( rDocShell.GetActiveDialogParent() );
3991 
3992         ScRange aSourceArea = rRange;
3993         ScRange aDestArea   = rRange;
3994 
3995         SCCOLROW nCount = 0;
3996         switch (eDir)
3997         {
3998             case FILL_TO_BOTTOM:
3999                 nCount = aSourceArea.aEnd.Row()-aSourceArea.aStart.Row();
4000                 aSourceArea.aEnd.SetRow( aSourceArea.aStart.Row() );
4001                 break;
4002             case FILL_TO_RIGHT:
4003                 nCount = aSourceArea.aEnd.Col()-aSourceArea.aStart.Col();
4004                 aSourceArea.aEnd.SetCol( aSourceArea.aStart.Col() );
4005                 break;
4006             case FILL_TO_TOP:
4007                 nCount = aSourceArea.aEnd.Row()-aSourceArea.aStart.Row();
4008                 aSourceArea.aStart.SetRow( aSourceArea.aEnd.Row() );
4009                 break;
4010             case FILL_TO_LEFT:
4011                 nCount = aSourceArea.aEnd.Col()-aSourceArea.aStart.Col();
4012                 aSourceArea.aStart.SetCol( aSourceArea.aEnd.Col() );
4013                 break;
4014         }
4015 
4016         ScDocument* pUndoDoc = NULL;
4017         if ( bRecord )
4018         {
4019             SCTAB nTabCount = pDoc->GetTableCount();
4020             SCTAB nDestStartTab = aDestArea.aStart.Tab();
4021 
4022             pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
4023             pUndoDoc->InitUndo( pDoc, nDestStartTab, nDestStartTab );
4024             for (SCTAB i=0; i<nTabCount; i++)
4025                 if (i != nDestStartTab && aMark.GetTableSelect(i))
4026                     pUndoDoc->AddUndoTab( i, i );
4027 
4028             ScRange aCopyRange = aDestArea;
4029             aCopyRange.aStart.SetTab(0);
4030             aCopyRange.aEnd.SetTab(nTabCount-1);
4031             pDoc->CopyToDocument( aCopyRange, IDF_AUTOFILL, sal_False, pUndoDoc, &aMark );
4032         }
4033 
4034         pDoc->Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(),
4035                     aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aMark,
4036                     nCount, eDir, FILL_SIMPLE );
4037         AdjustRowHeight(rRange);
4038 
4039         if ( bRecord )      // Draw-Undo erst jetzt verfuegbar
4040         {
4041             rDocShell.GetUndoManager()->AddUndoAction(
4042                 new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark,
4043                                     eDir, FILL_SIMPLE, FILL_DAY, MAXDOUBLE, 1.0, 1e307,
4044                                     pDoc->GetRangeName()->GetSharedMaxIndex()+1 ) );
4045         }
4046 
4047         rDocShell.PostPaintGridAll();
4048 //      rDocShell.PostPaintDataChanged();
4049         aModificator.SetDocumentModified();
4050 
4051         bSuccess = sal_True;
4052     }
4053     else if (!bApi)
4054         rDocShell.ErrorMessage(aTester.GetMessageId());
4055 
4056     return bSuccess;
4057 }
4058 
4059 sal_Bool ScDocFunc::FillSeries( const ScRange& rRange, const ScMarkData* pTabMark,
4060                             FillDir eDir, FillCmd eCmd, FillDateCmd eDateCmd,
4061                             double fStart, double fStep, double fMax,
4062                             sal_Bool bRecord, sal_Bool bApi )
4063 {
4064     ScDocShellModificator aModificator( rDocShell );
4065 
4066     sal_Bool bSuccess = sal_False;
4067     ScDocument* pDoc = rDocShell.GetDocument();
4068     SCCOL nStartCol = rRange.aStart.Col();
4069     SCROW nStartRow = rRange.aStart.Row();
4070     SCTAB nStartTab = rRange.aStart.Tab();
4071     SCCOL nEndCol = rRange.aEnd.Col();
4072     SCROW nEndRow = rRange.aEnd.Row();
4073     SCTAB nEndTab = rRange.aEnd.Tab();
4074 
4075     if (bRecord && !pDoc->IsUndoEnabled())
4076         bRecord = sal_False;
4077 
4078     ScMarkData aMark;
4079     if (pTabMark)
4080         aMark = *pTabMark;
4081     else
4082     {
4083         for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
4084             aMark.SelectTable( nTab, sal_True );
4085     }
4086 
4087     ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
4088     if ( aTester.IsEditable() )
4089     {
4090         WaitObject aWait( rDocShell.GetActiveDialogParent() );
4091 
4092         ScRange aSourceArea = rRange;
4093         ScRange aDestArea   = rRange;
4094 
4095         SCSIZE nCount = pDoc->GetEmptyLinesInBlock(
4096                 aSourceArea.aStart.Col(), aSourceArea.aStart.Row(), aSourceArea.aStart.Tab(),
4097                 aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aSourceArea.aEnd.Tab(),
4098                 DirFromFillDir(eDir) );
4099 
4100         //  #27665# mindestens eine Zeile/Spalte als Quellbereich behalten:
4101         SCSIZE nTotLines = ( eDir == FILL_TO_BOTTOM || eDir == FILL_TO_TOP ) ?
4102             static_cast<SCSIZE>( aSourceArea.aEnd.Row() - aSourceArea.aStart.Row() + 1 ) :
4103             static_cast<SCSIZE>( aSourceArea.aEnd.Col() - aSourceArea.aStart.Col() + 1 );
4104         if ( nCount >= nTotLines )
4105             nCount = nTotLines - 1;
4106 
4107         switch (eDir)
4108         {
4109             case FILL_TO_BOTTOM:
4110                 aSourceArea.aEnd.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aEnd.Row() - nCount ) );
4111                 break;
4112             case FILL_TO_RIGHT:
4113                 aSourceArea.aEnd.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aEnd.Col() - nCount ) );
4114                 break;
4115             case FILL_TO_TOP:
4116                 aSourceArea.aStart.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aStart.Row() + nCount ) );
4117                 break;
4118             case FILL_TO_LEFT:
4119                 aSourceArea.aStart.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aStart.Col() + nCount ) );
4120                 break;
4121         }
4122 
4123         ScDocument* pUndoDoc = NULL;
4124         if ( bRecord )
4125         {
4126             SCTAB nTabCount = pDoc->GetTableCount();
4127             SCTAB nDestStartTab = aDestArea.aStart.Tab();
4128 
4129             pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
4130             pUndoDoc->InitUndo( pDoc, nDestStartTab, nDestStartTab );
4131             for (SCTAB i=0; i<nTabCount; i++)
4132                 if (i != nDestStartTab && aMark.GetTableSelect(i))
4133                     pUndoDoc->AddUndoTab( i, i );
4134 
4135             pDoc->CopyToDocument(
4136                 aDestArea.aStart.Col(), aDestArea.aStart.Row(), 0,
4137                 aDestArea.aEnd.Col(), aDestArea.aEnd.Row(), nTabCount-1,
4138                 IDF_AUTOFILL, sal_False, pUndoDoc, &aMark );
4139         }
4140 
4141         if (aDestArea.aStart.Col() <= aDestArea.aEnd.Col() &&
4142             aDestArea.aStart.Row() <= aDestArea.aEnd.Row())
4143         {
4144             if ( fStart != MAXDOUBLE )
4145             {
4146                 SCCOL nValX = (eDir == FILL_TO_LEFT) ? aDestArea.aEnd.Col() : aDestArea.aStart.Col();
4147                 SCROW nValY = (eDir == FILL_TO_TOP ) ? aDestArea.aEnd.Row() : aDestArea.aStart.Row();
4148                 SCTAB nTab = aDestArea.aStart.Tab();
4149                 pDoc->SetValue( nValX, nValY, nTab, fStart );
4150             }
4151             pDoc->Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(),
4152                         aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aMark,
4153                         nCount, eDir, eCmd, eDateCmd, fStep, fMax );
4154             AdjustRowHeight(rRange);
4155 
4156             rDocShell.PostPaintGridAll();
4157 //          rDocShell.PostPaintDataChanged();
4158             aModificator.SetDocumentModified();
4159         }
4160 
4161         if ( bRecord )      // Draw-Undo erst jetzt verfuegbar
4162         {
4163             rDocShell.GetUndoManager()->AddUndoAction(
4164                 new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark,
4165                                     eDir, eCmd, eDateCmd, fStart, fStep, fMax,
4166                                     pDoc->GetRangeName()->GetSharedMaxIndex()+1 ) );
4167         }
4168 
4169         bSuccess = sal_True;
4170     }
4171     else if (!bApi)
4172         rDocShell.ErrorMessage(aTester.GetMessageId());
4173 
4174     return bSuccess;
4175 }
4176 
4177 sal_Bool ScDocFunc::FillAuto( ScRange& rRange, const ScMarkData* pTabMark,
4178                             FillDir eDir, sal_uLong nCount, sal_Bool bRecord, sal_Bool bApi )
4179 {
4180     ScDocShellModificator aModificator( rDocShell );
4181 
4182     ScDocument* pDoc = rDocShell.GetDocument();
4183     SCCOL nStartCol = rRange.aStart.Col();
4184     SCROW nStartRow = rRange.aStart.Row();
4185     SCTAB nStartTab = rRange.aStart.Tab();
4186     SCCOL nEndCol = rRange.aEnd.Col();
4187     SCROW nEndRow = rRange.aEnd.Row();
4188     SCTAB nEndTab = rRange.aEnd.Tab();
4189 
4190     if (bRecord && !pDoc->IsUndoEnabled())
4191         bRecord = sal_False;
4192 
4193     ScMarkData aMark;
4194     if (pTabMark)
4195         aMark = *pTabMark;
4196     else
4197     {
4198         for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
4199             aMark.SelectTable( nTab, sal_True );
4200     }
4201 
4202     ScRange aSourceArea = rRange;
4203     ScRange aDestArea   = rRange;
4204 
4205     FillCmd     eCmd = FILL_AUTO;
4206     FillDateCmd eDateCmd = FILL_DAY;
4207     double      fStep = 1.0;
4208     double      fMax = MAXDOUBLE;
4209 
4210     switch (eDir)
4211     {
4212         case FILL_TO_BOTTOM:
4213             aDestArea.aEnd.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aEnd.Row() + nCount ) );
4214             break;
4215         case FILL_TO_TOP:
4216             if (nCount > sal::static_int_cast<sal_uLong>( aSourceArea.aStart.Row() ))
4217             {
4218                 DBG_ERROR("FillAuto: Row < 0");
4219                 nCount = aSourceArea.aStart.Row();
4220             }
4221             aDestArea.aStart.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aStart.Row() - nCount ) );
4222             break;
4223         case FILL_TO_RIGHT:
4224             aDestArea.aEnd.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aEnd.Col() + nCount ) );
4225             break;
4226         case FILL_TO_LEFT:
4227             if (nCount > sal::static_int_cast<sal_uLong>( aSourceArea.aStart.Col() ))
4228             {
4229                 DBG_ERROR("FillAuto: Col < 0");
4230                 nCount = aSourceArea.aStart.Col();
4231             }
4232             aDestArea.aStart.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aStart.Col() - nCount ) );
4233             break;
4234         default:
4235             DBG_ERROR("Falsche Richtung bei FillAuto");
4236             break;
4237     }
4238 
4239     //      Zellschutz testen
4240     //!     Quellbereich darf geschuetzt sein !!!
4241     //!     aber kein Matrixfragment enthalten !!!
4242 
4243     ScEditableTester aTester( pDoc, aDestArea );
4244     if ( !aTester.IsEditable() )
4245     {
4246         if (!bApi)
4247             rDocShell.ErrorMessage(aTester.GetMessageId());
4248         return sal_False;
4249     }
4250 
4251     if ( pDoc->HasSelectedBlockMatrixFragment( nStartCol, nStartRow,
4252             nEndCol, nEndRow, aMark ) )
4253     {
4254         if (!bApi)
4255             rDocShell.ErrorMessage(STR_MATRIXFRAGMENTERR);
4256         return sal_False;
4257     }
4258 
4259     WaitObject aWait( rDocShell.GetActiveDialogParent() );
4260 
4261     ScDocument* pUndoDoc = NULL;
4262     if ( bRecord )
4263     {
4264         SCTAB nTabCount = pDoc->GetTableCount();
4265         SCTAB nDestStartTab = aDestArea.aStart.Tab();
4266 
4267         pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
4268         pUndoDoc->InitUndo( pDoc, nDestStartTab, nDestStartTab );
4269         for (SCTAB i=0; i<nTabCount; i++)
4270             if (i != nDestStartTab && aMark.GetTableSelect(i))
4271                 pUndoDoc->AddUndoTab( i, i );
4272 
4273         // do not clone note captions in undo document
4274         pDoc->CopyToDocument(
4275             aDestArea.aStart.Col(), aDestArea.aStart.Row(), 0,
4276             aDestArea.aEnd.Col(), aDestArea.aEnd.Row(), nTabCount-1,
4277             IDF_AUTOFILL, sal_False, pUndoDoc, &aMark );
4278     }
4279 
4280     pDoc->Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(),
4281                 aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aMark,
4282                 nCount, eDir, eCmd, eDateCmd, fStep, fMax );
4283 
4284     AdjustRowHeight(aDestArea);
4285 
4286     if ( bRecord )      // Draw-Undo erst jetzt verfuegbar
4287     {
4288         rDocShell.GetUndoManager()->AddUndoAction(
4289             new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark,
4290                                 eDir, eCmd, eDateCmd, MAXDOUBLE, fStep, fMax,
4291                                 pDoc->GetRangeName()->GetSharedMaxIndex()+1 ) );
4292     }
4293 
4294     rDocShell.PostPaintGridAll();
4295 //  rDocShell.PostPaintDataChanged();
4296     aModificator.SetDocumentModified();
4297 
4298     rRange = aDestArea;         // Zielbereich zurueckgeben (zum Markieren)
4299     return sal_True;
4300 }
4301 
4302 //------------------------------------------------------------------------
4303 
4304 sal_Bool ScDocFunc::MergeCells( const ScRange& rRange, sal_Bool bContents, sal_Bool bRecord, sal_Bool bApi )
4305 {
4306     ScDocShellModificator aModificator( rDocShell );
4307 
4308     ScDocument* pDoc = rDocShell.GetDocument();
4309     SCCOL nStartCol = rRange.aStart.Col();
4310     SCROW nStartRow = rRange.aStart.Row();
4311     SCCOL nEndCol = rRange.aEnd.Col();
4312     SCROW nEndRow = rRange.aEnd.Row();
4313     SCTAB nTab = rRange.aStart.Tab();
4314 
4315     if (bRecord && !pDoc->IsUndoEnabled())
4316         bRecord = sal_False;
4317 
4318     ScEditableTester aTester( pDoc, nTab, nStartCol, nStartRow, nEndCol, nEndRow );
4319     if (!aTester.IsEditable())
4320     {
4321         if (!bApi)
4322             rDocShell.ErrorMessage(aTester.GetMessageId());
4323         return sal_False;
4324     }
4325 
4326     if ( nStartCol == nEndCol && nStartRow == nEndRow )
4327     {
4328         // nichts zu tun
4329         return sal_True;
4330     }
4331 
4332     if ( pDoc->HasAttrib( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab,
4333                             HASATTR_MERGED | HASATTR_OVERLAPPED ) )
4334     {
4335         // "Zusammenfassen nicht verschachteln !"
4336         if (!bApi)
4337             rDocShell.ErrorMessage(STR_MSSG_MERGECELLS_0);
4338         return sal_False;
4339     }
4340 
4341     sal_Bool bNeedContents = bContents &&
4342             ( !pDoc->IsBlockEmpty( nTab, nStartCol,nStartRow+1, nStartCol,nEndRow, true ) ||
4343               !pDoc->IsBlockEmpty( nTab, nStartCol+1,nStartRow, nEndCol,nEndRow, true ) );
4344 
4345     ScDocument* pUndoDoc = 0;
4346     if (bRecord)
4347     {
4348         // test if the range contains other notes which also implies that we need an undo document
4349         bool bHasNotes = false;
4350         for( ScAddress aPos( nStartCol, nStartRow, nTab ); !bHasNotes && (aPos.Col() <= nEndCol); aPos.IncCol() )
4351             for( aPos.SetRow( nStartRow ); !bHasNotes && (aPos.Row() <= nEndRow); aPos.IncRow() )
4352                 bHasNotes = ((aPos.Col() != nStartCol) || (aPos.Row() != nStartRow)) && (pDoc->GetNote( aPos ) != 0);
4353 
4354         if (bNeedContents || bHasNotes)
4355         {
4356             pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
4357             pUndoDoc->InitUndo( pDoc, nTab, nTab );
4358             // note captions are collected by drawing undo
4359             pDoc->CopyToDocument( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab,
4360                                     IDF_ALL|IDF_NOCAPTIONS, sal_False, pUndoDoc );
4361         }
4362         if( bHasNotes )
4363             pDoc->BeginDrawUndo();
4364     }
4365 
4366     if (bNeedContents)
4367         pDoc->DoMergeContents( nTab, nStartCol,nStartRow, nEndCol,nEndRow );
4368     pDoc->DoMerge( nTab, nStartCol,nStartRow, nEndCol,nEndRow );
4369 
4370     if( bRecord )
4371     {
4372         SdrUndoGroup* pDrawUndo = pDoc->GetDrawLayer() ? pDoc->GetDrawLayer()->GetCalcUndo() : 0;
4373         rDocShell.GetUndoManager()->AddUndoAction(
4374             new ScUndoMerge( &rDocShell,
4375                             nStartCol, nStartRow, nTab,
4376                             nEndCol, nEndRow, nTab, bNeedContents, pUndoDoc, pDrawUndo ) );
4377     }
4378 
4379     if ( !AdjustRowHeight( ScRange( 0,nStartRow,nTab, MAXCOL,nEndRow,nTab ) ) )
4380         rDocShell.PostPaint( nStartCol, nStartRow, nTab,
4381                                             nEndCol, nEndRow, nTab, PAINT_GRID );
4382     if (bNeedContents)
4383         pDoc->SetDirty( rRange );
4384     aModificator.SetDocumentModified();
4385 
4386     SfxBindings* pBindings = rDocShell.GetViewBindings();
4387     if (pBindings)
4388     {
4389         pBindings->Invalidate( FID_MERGE_ON );
4390         pBindings->Invalidate( FID_MERGE_OFF );
4391         pBindings->Invalidate( FID_MERGE_TOGGLE );
4392     }
4393 
4394     return sal_True;
4395 }
4396 
4397 sal_Bool ScDocFunc::UnmergeCells( const ScRange& rRange, sal_Bool bRecord, sal_Bool bApi )
4398 {
4399     ScDocShellModificator aModificator( rDocShell );
4400 
4401     ScDocument* pDoc = rDocShell.GetDocument();
4402     SCTAB nTab = rRange.aStart.Tab();
4403 
4404     if (bRecord && !pDoc->IsUndoEnabled())
4405         bRecord = sal_False;
4406 
4407     if ( pDoc->HasAttrib( rRange, HASATTR_MERGED ) )
4408     {
4409         ScRange aExtended = rRange;
4410         pDoc->ExtendMerge( aExtended );
4411         ScRange aRefresh = aExtended;
4412         pDoc->ExtendOverlapped( aRefresh );
4413 
4414         if (bRecord)
4415         {
4416             ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
4417             pUndoDoc->InitUndo( pDoc, nTab, nTab );
4418             pDoc->CopyToDocument( aExtended, IDF_ATTRIB, sal_False, pUndoDoc );
4419             rDocShell.GetUndoManager()->AddUndoAction(
4420                 new ScUndoRemoveMerge( &rDocShell, rRange, pUndoDoc ) );
4421         }
4422 
4423         const SfxPoolItem& rDefAttr = pDoc->GetPool()->GetDefaultItem( ATTR_MERGE );
4424         ScPatternAttr aPattern( pDoc->GetPool() );
4425         aPattern.GetItemSet().Put( rDefAttr );
4426         pDoc->ApplyPatternAreaTab( rRange.aStart.Col(), rRange.aStart.Row(),
4427                                     rRange.aEnd.Col(), rRange.aEnd.Row(), nTab,
4428                                     aPattern );
4429 
4430         pDoc->RemoveFlagsTab( aExtended.aStart.Col(), aExtended.aStart.Row(),
4431                                 aExtended.aEnd.Col(), aExtended.aEnd.Row(), nTab,
4432                                 SC_MF_HOR | SC_MF_VER );
4433 
4434         pDoc->ExtendMerge( aRefresh, sal_True, sal_False );
4435 
4436         if ( !AdjustRowHeight( aExtended ) )
4437             rDocShell.PostPaint( aExtended, PAINT_GRID );
4438         aModificator.SetDocumentModified();
4439     }
4440     else if (!bApi)
4441         Sound::Beep();      //! sal_False zurueck???
4442 
4443     return sal_True;
4444 }
4445 
4446 //------------------------------------------------------------------------
4447 
4448 sal_Bool ScDocFunc::ModifyRangeNames( const ScRangeName& rNewRanges, sal_Bool bApi )
4449 {
4450     return SetNewRangeNames( new ScRangeName( rNewRanges ), bApi );
4451 }
4452 
4453 sal_Bool ScDocFunc::SetNewRangeNames( ScRangeName* pNewRanges, sal_Bool /* bApi */ )     // takes ownership of pNewRanges
4454 {
4455     ScDocShellModificator aModificator( rDocShell );
4456 
4457     DBG_ASSERT( pNewRanges, "pNewRanges is 0" );
4458     ScDocument* pDoc = rDocShell.GetDocument();
4459     sal_Bool bUndo(pDoc->IsUndoEnabled());
4460 
4461     if (bUndo)
4462     {
4463         ScRangeName* pOld = pDoc->GetRangeName();
4464         ScRangeName* pUndoRanges = new ScRangeName(*pOld);
4465         ScRangeName* pRedoRanges = new ScRangeName(*pNewRanges);
4466         rDocShell.GetUndoManager()->AddUndoAction(
4467             new ScUndoRangeNames( &rDocShell, pUndoRanges, pRedoRanges ) );
4468     }
4469 
4470     // #i55926# While loading XML, formula cells only have a single string token,
4471     // so CompileNameFormula would never find any name (index) tokens, and would
4472     // unnecessarily loop through all cells.
4473     sal_Bool bCompile = ( !pDoc->IsImportingXML() && pDoc->GetNamedRangesLockCount() == 0 );
4474 
4475     if ( bCompile )
4476         pDoc->CompileNameFormula( sal_True );   // CreateFormulaString
4477     pDoc->SetRangeName( pNewRanges );       // takes ownership
4478     if ( bCompile )
4479         pDoc->CompileNameFormula( sal_False );  // CompileFormulaString
4480 
4481     aModificator.SetDocumentModified();
4482 
4483     // #i114072# don't broadcast while loading a file
4484     // (navigator and input line for other open documents would be notified)
4485     if ( bCompile )
4486         SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) );
4487 
4488     return sal_True;
4489 }
4490 
4491 //------------------------------------------------------------------------
4492 
4493 void ScDocFunc::CreateOneName( ScRangeName& rList,
4494                                 SCCOL nPosX, SCROW nPosY, SCTAB nTab,
4495                                 SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
4496                                 sal_Bool& rCancel, sal_Bool bApi )
4497 {
4498     if (rCancel)
4499         return;
4500 
4501     ScDocument* pDoc = rDocShell.GetDocument();
4502     if (!pDoc->HasValueData( nPosX, nPosY, nTab ))
4503     {
4504         String aName;
4505         pDoc->GetString( nPosX, nPosY, nTab, aName );
4506         ScRangeData::MakeValidName(aName);
4507         if (aName.Len())
4508         {
4509             String aContent;
4510             ScRange( nX1, nY1, nTab, nX2, nY2, nTab ).Format( aContent, SCR_ABS_3D, pDoc );
4511 
4512             sal_Bool bInsert = sal_False;
4513             sal_uInt16 nOldPos;
4514             if (rList.SearchName( aName, nOldPos ))         // vorhanden ?
4515             {
4516                 ScRangeData* pOld = rList[nOldPos];
4517                 String aOldStr;
4518                 pOld->GetSymbol( aOldStr );
4519                 if (aOldStr != aContent)
4520                 {
4521                     if (bApi)
4522                         bInsert = sal_True;     // per API nicht nachfragen
4523                     else
4524                     {
4525                         String aTemplate = ScGlobal::GetRscString( STR_CREATENAME_REPLACE );
4526 
4527                         String aMessage = aTemplate.GetToken( 0, '#' );
4528                         aMessage += aName;
4529                         aMessage += aTemplate.GetToken( 1, '#' );
4530 
4531                         short nResult = QueryBox( rDocShell.GetActiveDialogParent(),
4532                                                     WinBits(WB_YES_NO_CANCEL | WB_DEF_YES),
4533                                                     aMessage ).Execute();
4534                         if ( nResult == RET_YES )
4535                         {
4536                             rList.AtFree(nOldPos);
4537                             bInsert = sal_True;
4538                         }
4539                         else if ( nResult == RET_CANCEL )
4540                             rCancel = sal_True;
4541                     }
4542                 }
4543             }
4544             else
4545                 bInsert = sal_True;
4546 
4547             if (bInsert)
4548             {
4549                 ScRangeData* pData = new ScRangeData( pDoc, aName, aContent,
4550                         ScAddress( nPosX, nPosY, nTab));
4551                 if (!rList.Insert(pData))
4552                 {
4553                     DBG_ERROR("nanu?");
4554                     delete pData;
4555                 }
4556             }
4557         }
4558     }
4559 }
4560 
4561 sal_Bool ScDocFunc::CreateNames( const ScRange& rRange, sal_uInt16 nFlags, sal_Bool bApi )
4562 {
4563     if (!nFlags)
4564         return sal_False;       // war nix
4565 
4566     ScDocShellModificator aModificator( rDocShell );
4567 
4568     sal_Bool bDone = sal_False;
4569     SCCOL nStartCol = rRange.aStart.Col();
4570     SCROW nStartRow = rRange.aStart.Row();
4571     SCCOL nEndCol = rRange.aEnd.Col();
4572     SCROW nEndRow = rRange.aEnd.Row();
4573     SCTAB nTab = rRange.aStart.Tab();
4574     DBG_ASSERT(rRange.aEnd.Tab() == nTab, "CreateNames: mehrere Tabellen geht nicht");
4575 
4576     sal_Bool bValid = sal_True;
4577     if ( nFlags & ( NAME_TOP | NAME_BOTTOM ) )
4578         if ( nStartRow == nEndRow )
4579             bValid = sal_False;
4580     if ( nFlags & ( NAME_LEFT | NAME_RIGHT ) )
4581         if ( nStartCol == nEndCol )
4582             bValid = sal_False;
4583 
4584     if (bValid)
4585     {
4586         ScDocument* pDoc = rDocShell.GetDocument();
4587         ScRangeName* pNames = pDoc->GetRangeName();
4588         if (!pNames)
4589             return sal_False;   // soll nicht sein
4590         ScRangeName aNewRanges( *pNames );
4591 
4592         sal_Bool bTop    = ( ( nFlags & NAME_TOP ) != 0 );
4593         sal_Bool bLeft   = ( ( nFlags & NAME_LEFT ) != 0 );
4594         sal_Bool bBottom = ( ( nFlags & NAME_BOTTOM ) != 0 );
4595         sal_Bool bRight  = ( ( nFlags & NAME_RIGHT ) != 0 );
4596 
4597         SCCOL nContX1 = nStartCol;
4598         SCROW nContY1 = nStartRow;
4599         SCCOL nContX2 = nEndCol;
4600         SCROW nContY2 = nEndRow;
4601 
4602         if ( bTop )
4603             ++nContY1;
4604         if ( bLeft )
4605             ++nContX1;
4606         if ( bBottom )
4607             --nContY2;
4608         if ( bRight )
4609             --nContX2;
4610 
4611         sal_Bool bCancel = sal_False;
4612         SCCOL i;
4613         SCROW j;
4614 
4615         if ( bTop )
4616             for (i=nContX1; i<=nContX2; i++)
4617                 CreateOneName( aNewRanges, i,nStartRow,nTab, i,nContY1,i,nContY2, bCancel, bApi );
4618         if ( bLeft )
4619             for (j=nContY1; j<=nContY2; j++)
4620                 CreateOneName( aNewRanges, nStartCol,j,nTab, nContX1,j,nContX2,j, bCancel, bApi );
4621         if ( bBottom )
4622             for (i=nContX1; i<=nContX2; i++)
4623                 CreateOneName( aNewRanges, i,nEndRow,nTab, i,nContY1,i,nContY2, bCancel, bApi );
4624         if ( bRight )
4625             for (j=nContY1; j<=nContY2; j++)
4626                 CreateOneName( aNewRanges, nEndCol,j,nTab, nContX1,j,nContX2,j, bCancel, bApi );
4627 
4628         if ( bTop && bLeft )
4629             CreateOneName( aNewRanges, nStartCol,nStartRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
4630         if ( bTop && bRight )
4631             CreateOneName( aNewRanges, nEndCol,nStartRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
4632         if ( bBottom && bLeft )
4633             CreateOneName( aNewRanges, nStartCol,nEndRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
4634         if ( bBottom && bRight )
4635             CreateOneName( aNewRanges, nEndCol,nEndRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
4636 
4637         bDone = ModifyRangeNames( aNewRanges, bApi );
4638 
4639         aModificator.SetDocumentModified();
4640         SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) );
4641     }
4642 
4643     return bDone;
4644 }
4645 
4646 //------------------------------------------------------------------------
4647 
4648 sal_Bool ScDocFunc::InsertNameList( const ScAddress& rStartPos, sal_Bool bApi )
4649 {
4650     ScDocShellModificator aModificator( rDocShell );
4651 
4652 
4653     sal_Bool bDone = sal_False;
4654     ScDocument* pDoc = rDocShell.GetDocument();
4655     const sal_Bool bRecord = pDoc->IsUndoEnabled();
4656     SCTAB nTab = rStartPos.Tab();
4657     ScDocument* pUndoDoc = NULL;
4658 
4659     ScRangeName* pList = pDoc->GetRangeName();
4660     sal_uInt16 nCount = pList->GetCount();
4661     sal_uInt16 nValidCount = 0;
4662     sal_uInt16 i;
4663     for (i=0; i<nCount; i++)
4664     {
4665         ScRangeData* pData = (*pList)[i];
4666         if ( !pData->HasType( RT_DATABASE ) && !pData->HasType( RT_SHARED ) )
4667             ++nValidCount;
4668     }
4669 
4670     if (nValidCount)
4671     {
4672         SCCOL nStartCol = rStartPos.Col();
4673         SCROW nStartRow = rStartPos.Row();
4674         SCCOL nEndCol = nStartCol + 1;
4675         SCROW nEndRow = nStartRow + static_cast<SCROW>(nValidCount) - 1;
4676 
4677         ScEditableTester aTester( pDoc, nTab, nStartCol,nStartRow, nEndCol,nEndRow );
4678         if (aTester.IsEditable())
4679         {
4680             if (bRecord)
4681             {
4682                 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
4683                 pUndoDoc->InitUndo( pDoc, nTab, nTab );
4684                 pDoc->CopyToDocument( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab,
4685                                         IDF_ALL, sal_False, pUndoDoc );
4686 
4687                 pDoc->BeginDrawUndo();      // wegen Hoehenanpassung
4688             }
4689 
4690             ScRangeData** ppSortArray = new ScRangeData* [ nValidCount ];
4691             sal_uInt16 j = 0;
4692             for (i=0; i<nCount; i++)
4693             {
4694                 ScRangeData* pData = (*pList)[i];
4695                 if ( !pData->HasType( RT_DATABASE ) && !pData->HasType( RT_SHARED ) )
4696                     ppSortArray[j++] = pData;
4697             }
4698 #ifndef ICC
4699             qsort( (void*)ppSortArray, nValidCount, sizeof(ScRangeData*),
4700                 &ScRangeData_QsortNameCompare );
4701 #else
4702             qsort( (void*)ppSortArray, nValidCount, sizeof(ScRangeData*),
4703                 ICCQsortNameCompare );
4704 #endif
4705             String aName;
4706             rtl::OUStringBuffer aContent;
4707             String aFormula;
4708             SCROW nOutRow = nStartRow;
4709             for (j=0; j<nValidCount; j++)
4710             {
4711                 ScRangeData* pData = ppSortArray[j];
4712                 pData->GetName(aName);
4713                 // relative Referenzen Excel-konform auf die linke Spalte anpassen:
4714                 pData->UpdateSymbol(aContent, ScAddress( nStartCol, nOutRow, nTab ));
4715                 aFormula = '=';
4716                 aFormula += aContent;
4717                 pDoc->PutCell( nStartCol,nOutRow,nTab, new ScStringCell( aName ) );
4718                 pDoc->PutCell( nEndCol  ,nOutRow,nTab, new ScStringCell( aFormula ) );
4719                 ++nOutRow;
4720             }
4721 
4722             delete [] ppSortArray;
4723 
4724             if (bRecord)
4725             {
4726                 ScDocument* pRedoDoc = new ScDocument( SCDOCMODE_UNDO );
4727                 pRedoDoc->InitUndo( pDoc, nTab, nTab );
4728                 pDoc->CopyToDocument( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab,
4729                                         IDF_ALL, sal_False, pRedoDoc );
4730 
4731                 rDocShell.GetUndoManager()->AddUndoAction(
4732                     new ScUndoListNames( &rDocShell,
4733                                 ScRange( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab ),
4734                                 pUndoDoc, pRedoDoc ) );
4735             }
4736 
4737             if (!AdjustRowHeight(ScRange(0,nStartRow,nTab,MAXCOL,nEndRow,nTab)))
4738                 rDocShell.PostPaint( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab, PAINT_GRID );
4739 //!         rDocShell.UpdateOle(GetViewData());
4740             aModificator.SetDocumentModified();
4741             bDone = sal_True;
4742         }
4743         else if (!bApi)
4744             rDocShell.ErrorMessage(aTester.GetMessageId());
4745     }
4746     return bDone;
4747 }
4748 
4749 //------------------------------------------------------------------------
4750 
4751 sal_Bool ScDocFunc::ResizeMatrix( const ScRange& rOldRange, const ScAddress& rNewEnd, sal_Bool bApi )
4752 {
4753     ScDocument* pDoc = rDocShell.GetDocument();
4754     SCCOL nStartCol = rOldRange.aStart.Col();
4755     SCROW nStartRow = rOldRange.aStart.Row();
4756     SCTAB nTab = rOldRange.aStart.Tab();
4757 
4758     sal_Bool bUndo(pDoc->IsUndoEnabled());
4759 
4760     sal_Bool bRet = sal_False;
4761 
4762     String aFormula;
4763     pDoc->GetFormula( nStartCol, nStartRow, nTab, aFormula );
4764     if ( aFormula.GetChar(0) == '{' && aFormula.GetChar(aFormula.Len()-1) == '}' )
4765     {
4766         String aUndo = ScGlobal::GetRscString( STR_UNDO_RESIZEMATRIX );
4767         if (bUndo)
4768             rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo );
4769 
4770         aFormula.Erase(0,1);
4771         aFormula.Erase(aFormula.Len()-1,1);
4772 
4773         ScMarkData aMark;
4774         aMark.SetMarkArea( rOldRange );
4775         aMark.SelectTable( nTab, sal_True );
4776         ScRange aNewRange( rOldRange.aStart, rNewEnd );
4777 
4778         if ( DeleteContents( aMark, IDF_CONTENTS, sal_True, bApi ) )
4779         {
4780             // GRAM_PODF_A1 for API compatibility.
4781             bRet = EnterMatrix( aNewRange, &aMark, NULL, aFormula, bApi, sal_False, EMPTY_STRING, formula::FormulaGrammar::GRAM_PODF_A1 );
4782             if (!bRet)
4783             {
4784                 //  versuchen, alten Zustand wiederherzustellen
4785                 EnterMatrix( rOldRange, &aMark, NULL, aFormula, bApi, sal_False, EMPTY_STRING, formula::FormulaGrammar::GRAM_PODF_A1 );
4786             }
4787         }
4788 
4789         if (bUndo)
4790             rDocShell.GetUndoManager()->LeaveListAction();
4791     }
4792 
4793     return bRet;
4794 }
4795 
4796 //------------------------------------------------------------------------
4797 
4798 sal_Bool ScDocFunc::InsertAreaLink( const String& rFile, const String& rFilter,
4799                                 const String& rOptions, const String& rSource,
4800                                 const ScRange& rDestRange, sal_uLong nRefresh,
4801                                 sal_Bool bFitBlock, sal_Bool bApi )
4802 {
4803     //! auch fuer ScViewFunc::InsertAreaLink benutzen!
4804 
4805     ScDocument* pDoc = rDocShell.GetDocument();
4806     sal_Bool bUndo (pDoc->IsUndoEnabled());
4807 
4808     sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager();
4809 
4810     //  #i52120# if other area links exist at the same start position,
4811     //  remove them first (file format specifies only one link definition
4812     //  for a cell)
4813 
4814     sal_uInt16 nLinkCount = pLinkManager->GetLinks().Count();
4815     sal_uInt16 nRemoved = 0;
4816     sal_uInt16 nLinkPos = 0;
4817     while (nLinkPos<nLinkCount)
4818     {
4819         ::sfx2::SvBaseLink* pBase = *pLinkManager->GetLinks()[nLinkPos];
4820         if ( pBase->ISA(ScAreaLink) &&
4821              static_cast<ScAreaLink*>(pBase)->GetDestArea().aStart == rDestRange.aStart )
4822         {
4823             if ( bUndo )
4824             {
4825                 if ( !nRemoved )
4826                 {
4827                     // group all remove and the insert action
4828                     String aUndo = ScGlobal::GetRscString( STR_UNDO_INSERTAREALINK );
4829                     rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo );
4830                 }
4831 
4832                 ScAreaLink* pOldArea = static_cast<ScAreaLink*>(pBase);
4833                 rDocShell.GetUndoManager()->AddUndoAction(
4834                     new ScUndoRemoveAreaLink( &rDocShell,
4835                         pOldArea->GetFile(), pOldArea->GetFilter(), pOldArea->GetOptions(),
4836                         pOldArea->GetSource(), pOldArea->GetDestArea(), pOldArea->GetRefreshDelay() ) );
4837             }
4838             pLinkManager->Remove( pBase );
4839             nLinkCount = pLinkManager->GetLinks().Count();
4840             ++nRemoved;
4841         }
4842         else
4843             ++nLinkPos;
4844     }
4845 
4846     String aFilterName = rFilter;
4847     String aNewOptions = rOptions;
4848     if (!aFilterName.Len())
4849         ScDocumentLoader::GetFilterName( rFile, aFilterName, aNewOptions, sal_True, !bApi );
4850 
4851     //  remove application prefix from filter name here, so the filter options
4852     //  aren't reset when the filter name is changed in ScAreaLink::DataChanged
4853     ScDocumentLoader::RemoveAppPrefix( aFilterName );
4854 
4855     ScAreaLink* pLink = new ScAreaLink( &rDocShell, rFile, aFilterName,
4856                                         aNewOptions, rSource, rDestRange, nRefresh );
4857     pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, rFile, &aFilterName, &rSource );
4858 
4859     //  Undo fuer den leeren Link
4860 
4861     if (bUndo)
4862     {
4863         rDocShell.GetUndoManager()->AddUndoAction( new ScUndoInsertAreaLink( &rDocShell,
4864                                                     rFile, aFilterName, aNewOptions,
4865                                                     rSource, rDestRange, nRefresh ) );
4866         if ( nRemoved )
4867             rDocShell.GetUndoManager()->LeaveListAction();  // undo for link update is still separate
4868     }
4869 
4870     //  Update hat sein eigenes Undo
4871     if (pDoc->IsExecuteLinkEnabled())
4872     {
4873         pLink->SetDoInsert(bFitBlock);  // beim ersten Update ggf. nichts einfuegen
4874         pLink->Update();                // kein SetInCreate -> Update ausfuehren
4875     }
4876     pLink->SetDoInsert(sal_True);       // Default = sal_True
4877 
4878     SfxBindings* pBindings = rDocShell.GetViewBindings();
4879     if (pBindings)
4880         pBindings->Invalidate( SID_LINKS );
4881 
4882     SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );     // Navigator
4883 
4884     return sal_True;
4885 }
4886 
4887 
4888 
4889 
4890