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