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