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