xref: /trunk/main/sc/source/ui/undo/undoblk.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sc.hxx"
30 
31 
32 
33 //------------------------------------------------------------------
34 
35 // INCLUDE ---------------------------------------------------------------
36 
37 #include "scitems.hxx"
38 #include <vcl/virdev.hxx>
39 #include <vcl/waitobj.hxx>
40 #include <editeng/boxitem.hxx>
41 #include <sfx2/app.hxx>
42 
43 #include "undoblk.hxx"
44 #include "undoutil.hxx"
45 #include "document.hxx"
46 #include "patattr.hxx"
47 #include "docsh.hxx"
48 #include "tabvwsh.hxx"
49 #include "rangenam.hxx"
50 #include "rangeutl.hxx"
51 #include "dbcolect.hxx"
52 #include "stlpool.hxx"
53 #include "stlsheet.hxx"
54 #include "globstr.hrc"
55 #include "global.hxx"
56 #include "target.hxx"
57 #include "docpool.hxx"
58 #include "docfunc.hxx"
59 #include "attrib.hxx"
60 #include "chgtrack.hxx"
61 #include "transobj.hxx"
62 #include "refundo.hxx"
63 #include "undoolk.hxx"
64 #include "clipparam.hxx"
65 #include "sc.hrc"
66 
67 
68 // STATIC DATA -----------------------------------------------------------
69 
70 TYPEINIT1(ScUndoInsertCells,        SfxUndoAction);
71 TYPEINIT1(ScUndoDeleteCells,        SfxUndoAction);
72 TYPEINIT1(ScUndoDeleteMulti,        SfxUndoAction);
73 TYPEINIT1(ScUndoCut,                ScBlockUndo);
74 TYPEINIT1(ScUndoPaste,              SfxUndoAction);
75 TYPEINIT1(ScUndoDragDrop,           SfxUndoAction);
76 TYPEINIT1(ScUndoListNames,          SfxUndoAction);
77 TYPEINIT1(ScUndoUseScenario,        SfxUndoAction);
78 TYPEINIT1(ScUndoSelectionStyle,     SfxUndoAction);
79 TYPEINIT1(ScUndoEnterMatrix,        ScBlockUndo);
80 TYPEINIT1(ScUndoIndent,             ScBlockUndo);
81 TYPEINIT1(ScUndoTransliterate,      ScBlockUndo);
82 TYPEINIT1(ScUndoClearItems,         ScBlockUndo);
83 TYPEINIT1(ScUndoRemoveBreaks,       SfxUndoAction);
84 TYPEINIT1(ScUndoRemoveMerge,        ScBlockUndo);
85 TYPEINIT1(ScUndoBorder,             ScBlockUndo);
86 
87 
88 
89 // To Do:
90 /*A*/   // SetOptimalHeight auf Dokument, wenn keine View
91 /*B*/   // gelinkte Tabellen
92 /*C*/   // ScArea
93 //?     // spaeter mal pruefen
94 
95 
96 // -----------------------------------------------------------------------
97 //
98 //      Zellen einfuegen
99 //      Zeilen einfuegen
100 //      einzeln oder Block
101 //
102 
103 ScUndoInsertCells::ScUndoInsertCells( ScDocShell* pNewDocShell,
104                                 const ScRange& rRange, SCTAB nNewCount, SCTAB* pNewTabs, SCTAB* pNewScenarios,
105                                 InsCellCmd eNewCmd, ScDocument* pUndoDocument, ScRefUndoData* pRefData,
106                                 sal_Bool bNewPartOfPaste ) :
107     ScMoveUndo( pNewDocShell, pUndoDocument, pRefData, SC_UNDO_REFLAST ),
108     aEffRange( rRange ),
109     nCount( nNewCount ),
110     pTabs( pNewTabs ),
111     pScenarios( pNewScenarios ),
112     eCmd( eNewCmd ),
113     bPartOfPaste( bNewPartOfPaste ),
114     pPasteUndo( NULL )
115 {
116     if (eCmd == INS_INSROWS)            // ganze Zeilen?
117     {
118         aEffRange.aStart.SetCol(0);
119         aEffRange.aEnd.SetCol(MAXCOL);
120     }
121 
122     if (eCmd == INS_INSCOLS)            // ganze Spalten?
123     {
124         aEffRange.aStart.SetRow(0);
125         aEffRange.aEnd.SetRow(MAXROW);
126     }
127 
128     SetChangeTrack();
129 }
130 
131 __EXPORT ScUndoInsertCells::~ScUndoInsertCells()
132 {
133     delete pPasteUndo;
134     delete []pTabs;
135     delete []pScenarios;
136 }
137 
138 String __EXPORT ScUndoInsertCells::GetComment() const
139 {
140     return ScGlobal::GetRscString( pPasteUndo ? STR_UNDO_PASTE : STR_UNDO_INSERTCELLS );
141 }
142 
143 sal_Bool ScUndoInsertCells::Merge( SfxUndoAction* pNextAction )
144 {
145     //  If a paste undo action has already been added, append (detective) action there.
146     if ( pPasteUndo )
147         return pPasteUndo->Merge( pNextAction );
148 
149     if ( bPartOfPaste && pNextAction->ISA( ScUndoWrapper ) )
150     {
151         ScUndoWrapper* pWrapper = (ScUndoWrapper*)pNextAction;
152         SfxUndoAction* pWrappedAction = pWrapper->GetWrappedUndo();
153         if ( pWrappedAction && pWrappedAction->ISA( ScUndoPaste ) )
154         {
155             //  Store paste action if this is part of paste with inserting cells.
156             //  A list action isn't used because Repeat wouldn't work (insert wrong cells).
157 
158             pPasteUndo = pWrappedAction;
159             pWrapper->ForgetWrappedUndo();      // pWrapper is deleted by UndoManager
160             return sal_True;
161         }
162     }
163 
164     //  Call base class for detective handling
165     return ScMoveUndo::Merge( pNextAction );
166 }
167 
168 void ScUndoInsertCells::SetChangeTrack()
169 {
170     ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack();
171     if ( pChangeTrack )
172     {
173         pChangeTrack->AppendInsert( aEffRange );
174         nEndChangeAction = pChangeTrack->GetActionMax();
175     }
176     else
177         nEndChangeAction = 0;
178 }
179 
180 void ScUndoInsertCells::DoChange( const sal_Bool bUndo )
181 {
182     ScDocument* pDoc = pDocShell->GetDocument();
183     SCTAB i;
184 
185     if ( bUndo )
186     {
187         ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
188         if ( pChangeTrack )
189             pChangeTrack->Undo( nEndChangeAction, nEndChangeAction );
190     }
191     else
192         SetChangeTrack();
193 
194     // refresh of merged cells has to be after inserting/deleting
195 
196     switch (eCmd)
197     {
198         case INS_INSROWS:
199         case INS_CELLSDOWN:
200             for( i=0; i<nCount; i++ )
201             {
202                 if (bUndo)
203                     pDoc->DeleteRow( aEffRange.aStart.Col(), pTabs[i], aEffRange.aEnd.Col(), pTabs[i]+pScenarios[i],
204                     aEffRange.aStart.Row(), static_cast<SCSIZE>(aEffRange.aEnd.Row()-aEffRange.aStart.Row()+1));
205                 else
206                     pDoc->InsertRow( aEffRange.aStart.Col(), pTabs[i], aEffRange.aEnd.Col(), pTabs[i]+pScenarios[i],
207                     aEffRange.aStart.Row(), static_cast<SCSIZE>(aEffRange.aEnd.Row()-aEffRange.aStart.Row()+1));
208             }
209             break;
210         case INS_INSCOLS:
211         case INS_CELLSRIGHT:
212             for( i=0; i<nCount; i++ )
213             {
214                 if (bUndo)
215                     pDoc->DeleteCol( aEffRange.aStart.Row(), pTabs[i], aEffRange.aEnd.Row(), pTabs[i]+pScenarios[i],
216                     aEffRange.aStart.Col(), static_cast<SCSIZE>(aEffRange.aEnd.Col()-aEffRange.aStart.Col()+1));
217                 else
218                     pDoc->InsertCol( aEffRange.aStart.Row(), pTabs[i], aEffRange.aEnd.Row(), pTabs[i]+pScenarios[i],
219                     aEffRange.aStart.Col(), static_cast<SCSIZE>(aEffRange.aEnd.Col()-aEffRange.aStart.Col()+1));
220             }
221             break;
222         default:
223         {
224             // added to avoid warnings
225         }
226     }
227 
228     ScRange aWorkRange( aEffRange );
229     if ( eCmd == INS_CELLSRIGHT )                   // only "shift right" requires refresh of the moved area
230         aWorkRange.aEnd.SetCol(MAXCOL);
231     for( i=0; i<nCount; i++ )
232     {
233         if ( pDoc->HasAttrib( aWorkRange.aStart.Col(), aWorkRange.aStart.Row(), pTabs[i],
234             aWorkRange.aEnd.Col(), aWorkRange.aEnd.Row(), pTabs[i], HASATTR_MERGED ) )
235         {
236             SCCOL nEndCol = aWorkRange.aEnd.Col();
237             SCROW nEndRow = aWorkRange.aEnd.Row();
238             pDoc->ExtendMerge( aWorkRange.aStart.Col(), aWorkRange.aStart.Row(), nEndCol, nEndRow, pTabs[i], sal_True );
239         }
240     }
241 
242 //? Undo fuer herausgeschobene Attribute ?
243 
244     sal_uInt16 nPaint = PAINT_GRID;
245     ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
246     switch (eCmd)
247     {
248         case INS_INSROWS:
249             nPaint |= PAINT_LEFT;
250             aWorkRange.aEnd.SetRow(MAXROW);
251             break;
252         case INS_CELLSDOWN:
253             for( i=0; i<nCount; i++ )
254             {
255                 aWorkRange.aEnd.SetRow(MAXROW);
256                 if ( pDocShell->AdjustRowHeight( aWorkRange.aStart.Row(), aWorkRange.aEnd.Row(), pTabs[i] ))
257                 {
258                     aWorkRange.aStart.SetCol(0);
259                     aWorkRange.aEnd.SetCol(MAXCOL);
260                     nPaint |= PAINT_LEFT;
261                 }
262             }
263             break;
264         case INS_INSCOLS:
265             nPaint |= PAINT_TOP;                // obere Leiste
266         case INS_CELLSRIGHT:
267             for( i=0; i<nCount; i++ )
268             {
269                 aWorkRange.aEnd.SetCol(MAXCOL);     // bis ganz nach rechts
270                 if ( pDocShell->AdjustRowHeight( aWorkRange.aStart.Row(), aWorkRange.aEnd.Row(), pTabs[i]) )
271                 {                                   // AdjustDraw zeichnet PAINT_TOP nicht,
272                     aWorkRange.aStart.SetCol(0);    // daher so geloest
273                     aWorkRange.aEnd.SetRow(MAXROW);
274                     nPaint |= PAINT_LEFT;
275                 }
276             }
277             break;
278         default:
279         {
280             // added to avoid warnings
281         }
282     }
283 
284     for( i=0; i<nCount; i++ )
285     {
286         pDocShell->PostPaint( aWorkRange.aStart.Col(), aWorkRange.aStart.Row(), pTabs[i],
287             aWorkRange.aEnd.Col(), aWorkRange.aEnd.Row(), pTabs[i]+pScenarios[i], nPaint );
288     }
289     pDocShell->PostDataChanged();
290     if (pViewShell)
291         pViewShell->CellContentChanged();
292 }
293 
294 void __EXPORT ScUndoInsertCells::Undo()
295 {
296     if ( pPasteUndo )
297         pPasteUndo->Undo();     // undo paste first
298 
299     WaitObject aWait( pDocShell->GetActiveDialogParent() );     // wichtig wegen TrackFormulas bei UpdateReference
300     BeginUndo();
301     DoChange( sal_True );
302     EndUndo();
303 }
304 
305 void __EXPORT ScUndoInsertCells::Redo()
306 {
307     WaitObject aWait( pDocShell->GetActiveDialogParent() );     // wichtig wegen TrackFormulas bei UpdateReference
308     BeginRedo();
309     DoChange( sal_False );
310     EndRedo();
311 
312     if ( pPasteUndo )
313         pPasteUndo->Redo();     // redo paste last
314 }
315 
316 void __EXPORT ScUndoInsertCells::Repeat(SfxRepeatTarget& rTarget)
317 {
318     if (rTarget.ISA(ScTabViewTarget))
319     {
320         if ( pPasteUndo )
321         {
322             //  #94115# Repeat for paste with inserting cells is handled completely
323             //  by the Paste undo action
324 
325             pPasteUndo->Repeat( rTarget );
326         }
327         else
328             ((ScTabViewTarget&)rTarget).GetViewShell()->InsertCells( eCmd, sal_True );
329     }
330 }
331 
332 sal_Bool __EXPORT ScUndoInsertCells::CanRepeat(SfxRepeatTarget& rTarget) const
333 {
334     return (rTarget.ISA(ScTabViewTarget));
335 }
336 
337 
338 // -----------------------------------------------------------------------
339 //
340 //      Zellen loeschen
341 //      Zeilen loeschen
342 //      einzeln oder Block
343 //
344 
345 ScUndoDeleteCells::ScUndoDeleteCells( ScDocShell* pNewDocShell,
346                                 const ScRange& rRange, SCTAB nNewCount, SCTAB* pNewTabs, SCTAB* pNewScenarios,
347                                 DelCellCmd eNewCmd, ScDocument* pUndoDocument, ScRefUndoData* pRefData ) :
348     ScMoveUndo( pNewDocShell, pUndoDocument, pRefData, SC_UNDO_REFLAST ),
349     aEffRange( rRange ),
350     nCount( nNewCount ),
351     pTabs( pNewTabs ),
352     pScenarios( pNewScenarios ),
353     eCmd( eNewCmd )
354 {
355     if (eCmd == DEL_DELROWS)            // gaze Zeilen?
356     {
357         aEffRange.aStart.SetCol(0);
358         aEffRange.aEnd.SetCol(MAXCOL);
359     }
360 
361     if (eCmd == DEL_DELCOLS)            // ganze Spalten?
362     {
363         aEffRange.aStart.SetRow(0);
364         aEffRange.aEnd.SetRow(MAXROW);
365     }
366 
367     SetChangeTrack();
368 }
369 
370 __EXPORT ScUndoDeleteCells::~ScUndoDeleteCells()
371 {
372     delete []pTabs;
373     delete []pScenarios;
374 }
375 
376 String __EXPORT ScUndoDeleteCells::GetComment() const
377 {
378     return ScGlobal::GetRscString( STR_UNDO_DELETECELLS ); // "Loeschen"
379 }
380 
381 void ScUndoDeleteCells::SetChangeTrack()
382 {
383     ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack();
384     if ( pChangeTrack )
385         pChangeTrack->AppendDeleteRange( aEffRange, pRefUndoDoc,
386             nStartChangeAction, nEndChangeAction );
387     else
388         nStartChangeAction = nEndChangeAction = 0;
389 }
390 
391 void ScUndoDeleteCells::DoChange( const sal_Bool bUndo )
392 {
393     ScDocument* pDoc = pDocShell->GetDocument();
394     SCTAB i;
395 
396     if ( bUndo )
397     {
398         ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
399         if ( pChangeTrack )
400             pChangeTrack->Undo( nStartChangeAction, nEndChangeAction );
401     }
402     else
403         SetChangeTrack();
404 
405     // Ausfuehren
406     switch (eCmd)
407     {
408         case DEL_DELROWS:
409         case DEL_CELLSUP:
410             for( i=0; i<nCount; i++ )
411             {
412                 if (bUndo)
413                     pDoc->InsertRow( aEffRange.aStart.Col(), pTabs[i], aEffRange.aEnd.Col(), pTabs[i]+pScenarios[i],
414                     aEffRange.aStart.Row(), static_cast<SCSIZE>(aEffRange.aEnd.Row()-aEffRange.aStart.Row()+1));
415                 else
416                     pDoc->DeleteRow( aEffRange.aStart.Col(), pTabs[i], aEffRange.aEnd.Col(), pTabs[i]+pScenarios[i],
417                     aEffRange.aStart.Row(), static_cast<SCSIZE>(aEffRange.aEnd.Row()-aEffRange.aStart.Row()+1));
418             }
419             break;
420         case DEL_DELCOLS:
421         case DEL_CELLSLEFT:
422             for( i=0; i<nCount; i++ )
423             {
424                 if (bUndo)
425                     pDoc->InsertCol( aEffRange.aStart.Row(), pTabs[i], aEffRange.aEnd.Row(), pTabs[i]+pScenarios[i],
426                     aEffRange.aStart.Col(), static_cast<SCSIZE>(aEffRange.aEnd.Col()-aEffRange.aStart.Col()+1));
427                 else
428                     pDoc->DeleteCol( aEffRange.aStart.Row(), pTabs[i], aEffRange.aEnd.Row(), pTabs[i]+pScenarios[i],
429                     aEffRange.aStart.Col(), static_cast<SCSIZE>(aEffRange.aEnd.Col()-aEffRange.aStart.Col()+1));
430             }
431             break;
432         default:
433         {
434             // added to avoid warnings
435         }
436     }
437 
438     // bei Undo Referenzen wiederherstellen
439     for( i=0; i<nCount && bUndo; i++ )
440     {
441         pRefUndoDoc->CopyToDocument( aEffRange.aStart.Col(), aEffRange.aStart.Row(), pTabs[i], aEffRange.aEnd.Col(), aEffRange.aEnd.Row(), pTabs[i]+pScenarios[i],
442             IDF_ALL | IDF_NOCAPTIONS, sal_False, pDoc );
443     }
444 
445     ScRange aWorkRange( aEffRange );
446     if ( eCmd == DEL_CELLSLEFT )        // only "shift left" requires refresh of the moved area
447         aWorkRange.aEnd.SetCol(MAXCOL);
448 
449     for( i=0; i<nCount; i++ )
450     {
451         if ( pDoc->HasAttrib( aWorkRange.aStart.Col(), aWorkRange.aStart.Row(), pTabs[i],
452             aWorkRange.aEnd.Col(), aWorkRange.aEnd.Row(), pTabs[i], HASATTR_MERGED | HASATTR_OVERLAPPED ) )
453         {
454             // #i51445# old merge flag attributes must be deleted also for single cells,
455             // not only for whole columns/rows
456 
457             if ( !bUndo )
458             {
459                 if ( eCmd==DEL_DELCOLS || eCmd==DEL_CELLSLEFT )
460                     aWorkRange.aEnd.SetCol(MAXCOL);
461                 if ( eCmd==DEL_DELROWS || eCmd==DEL_CELLSUP )
462                     aWorkRange.aEnd.SetRow(MAXROW);
463                 ScMarkData aMarkData;
464                 aMarkData.SelectOneTable( aWorkRange.aStart.Tab() );
465                 ScPatternAttr aPattern( pDoc->GetPool() );
466                 aPattern.GetItemSet().Put( ScMergeFlagAttr() );
467                 pDoc->ApplyPatternArea( aWorkRange.aStart.Col(), aWorkRange.aStart.Row(),
468                     aWorkRange.aEnd.Col(),   aWorkRange.aEnd.Row(),
469                     aMarkData, aPattern );
470             }
471 
472             SCCOL nEndCol = aWorkRange.aEnd.Col();
473             SCROW nEndRow = aWorkRange.aEnd.Row();
474             pDoc->ExtendMerge( aWorkRange.aStart.Col(), aWorkRange.aStart.Row(), nEndCol, nEndRow, pTabs[i], sal_True );
475         }
476     }
477 
478     // Zeichnen
479     sal_uInt16 nPaint = PAINT_GRID;
480     switch (eCmd)
481     {
482         case DEL_DELROWS:
483             nPaint |= PAINT_LEFT;
484             aWorkRange.aEnd.SetRow(MAXROW);
485             break;
486         case DEL_CELLSUP:
487             for( i=0; i<nCount; i++ )
488             {
489                 aWorkRange.aEnd.SetRow(MAXROW);
490                 if ( pDocShell->AdjustRowHeight( aWorkRange.aStart.Row(), aWorkRange.aEnd.Row(), pTabs[i] ))
491                 {
492                     aWorkRange.aStart.SetCol(0);
493                     aWorkRange.aEnd.SetCol(MAXCOL);
494                     nPaint |= PAINT_LEFT;
495                 }
496             }
497             break;
498         case DEL_DELCOLS:
499             nPaint |= PAINT_TOP;                // obere Leiste
500         case DEL_CELLSLEFT:
501             for( i=0; i<nCount; i++ )
502             {
503                 aWorkRange.aEnd.SetCol(MAXCOL);     // bis ganz nach rechts
504                 if ( pDocShell->AdjustRowHeight( aWorkRange.aStart.Row(), aWorkRange.aEnd.Row(), pTabs[i] ) )
505                 {
506                     aWorkRange.aStart.SetCol(0);
507                     aWorkRange.aEnd.SetRow(MAXROW);
508                     nPaint |= PAINT_LEFT;
509                 }
510             }
511             break;
512         default:
513         {
514             // added to avoid warnings
515         }
516     }
517 
518     for( i=0; i<nCount; i++ )
519     {
520         pDocShell->PostPaint( aWorkRange.aStart.Col(), aWorkRange.aStart.Row(), pTabs[i],
521             aWorkRange.aEnd.Col(), aWorkRange.aEnd.Row(), pTabs[i]+pScenarios[i], nPaint, SC_PF_LINES );
522     }
523     // Markierung erst nach EndUndo
524 
525     pDocShell->PostDataChanged();
526     //  CellContentChanged kommt mit der Markierung
527 }
528 
529 void __EXPORT ScUndoDeleteCells::Undo()
530 {
531     WaitObject aWait( pDocShell->GetActiveDialogParent() );     // wichtig wegen TrackFormulas bei UpdateReference
532     BeginUndo();
533     DoChange( sal_True );
534     EndUndo();
535     SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
536 
537     // Markierung erst nach EndUndo
538     ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
539     if (pViewShell)
540     {
541         for( SCTAB i=0; i<nCount; i++ )
542         {
543             pViewShell->MarkRange( ScRange(aEffRange.aStart.Col(), aEffRange.aStart.Row(), pTabs[i], aEffRange.aEnd.Col(), aEffRange.aEnd.Row(), pTabs[i]+pScenarios[i]) );
544         }
545     }
546 }
547 
548 void __EXPORT ScUndoDeleteCells::Redo()
549 {
550     WaitObject aWait( pDocShell->GetActiveDialogParent() );     // wichtig wegen TrackFormulas bei UpdateReference
551     BeginRedo();
552     DoChange( sal_False);
553     EndRedo();
554     SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
555 
556     ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
557     if (pViewShell)
558         pViewShell->DoneBlockMode();            // aktuelle weg
559 }
560 
561 void __EXPORT ScUndoDeleteCells::Repeat(SfxRepeatTarget& rTarget)
562 {
563     if (rTarget.ISA(ScTabViewTarget))
564         ((ScTabViewTarget&)rTarget).GetViewShell()->DeleteCells( eCmd, sal_True );
565 }
566 
567 sal_Bool __EXPORT ScUndoDeleteCells::CanRepeat(SfxRepeatTarget& rTarget) const
568 {
569     return (rTarget.ISA(ScTabViewTarget));
570 }
571 
572 
573 // -----------------------------------------------------------------------
574 //
575 //      Zellen loeschen auf Mehrfachselektion
576 //
577 
578 ScUndoDeleteMulti::ScUndoDeleteMulti( ScDocShell* pNewDocShell,
579                                         sal_Bool bNewRows, sal_Bool bNeedsRefresh, SCTAB nNewTab,
580                                         const SCCOLROW* pRng, SCCOLROW nRngCnt,
581                                         ScDocument* pUndoDocument, ScRefUndoData* pRefData ) :
582     ScMoveUndo( pNewDocShell, pUndoDocument, pRefData, SC_UNDO_REFLAST ),
583     bRows( bNewRows ),
584     bRefresh( bNeedsRefresh ),
585     nTab( nNewTab ),
586     nRangeCnt( nRngCnt )
587 {
588     pRanges = new SCCOLROW[ 2 * nRangeCnt ];
589     memcpy(pRanges,pRng,nRangeCnt*2*sizeof(SCCOLROW));
590     SetChangeTrack();
591 }
592 
593 __EXPORT ScUndoDeleteMulti::~ScUndoDeleteMulti()
594 {
595     delete [] pRanges;
596 }
597 
598 String __EXPORT ScUndoDeleteMulti::GetComment() const
599 {
600     return ScGlobal::GetRscString( STR_UNDO_DELETECELLS );  // wie DeleteCells
601 }
602 
603 void ScUndoDeleteMulti::DoChange() const
604 {
605     SCCOL nStartCol;
606     SCROW nStartRow;
607     sal_uInt16 nPaint;
608     if (bRows)
609     {
610         nStartCol = 0;
611         nStartRow = static_cast<SCROW>(pRanges[0]);
612         nPaint = PAINT_GRID | PAINT_LEFT;
613     }
614     else
615     {
616         nStartCol = static_cast<SCCOL>(pRanges[0]);
617         nStartRow = 0;
618         nPaint = PAINT_GRID | PAINT_TOP;
619     }
620 
621     if ( bRefresh )
622     {
623         ScDocument* pDoc = pDocShell->GetDocument();
624         SCCOL nEndCol = MAXCOL;
625         SCROW nEndRow = MAXROW;
626         pDoc->RemoveFlagsTab( nStartCol, nStartRow, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER );
627         pDoc->ExtendMerge( nStartCol, nStartRow, nEndCol, nEndRow, nTab, sal_True );
628     }
629 
630     pDocShell->PostPaint( nStartCol, nStartRow, nTab, MAXCOL, MAXROW, nTab, nPaint );
631     pDocShell->PostDataChanged();
632     ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
633     if (pViewShell)
634         pViewShell->CellContentChanged();
635 
636     ShowTable( nTab );
637 }
638 
639 void ScUndoDeleteMulti::SetChangeTrack()
640 {
641     ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack();
642     if ( pChangeTrack )
643     {
644         nStartChangeAction = pChangeTrack->GetActionMax() + 1;
645         ScRange aRange( 0, 0, nTab, 0, 0, nTab );
646         if ( bRows )
647             aRange.aEnd.SetCol( MAXCOL );
648         else
649             aRange.aEnd.SetRow( MAXROW );
650         // rueckwaerts loeschen
651         SCCOLROW* pOneRange = &pRanges[2*nRangeCnt];
652         for ( SCCOLROW nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++ )
653         {
654             SCCOLROW nEnd = *(--pOneRange);
655             SCCOLROW nStart = *(--pOneRange);
656             if ( bRows )
657             {
658                 aRange.aStart.SetRow( nStart );
659                 aRange.aEnd.SetRow( nEnd );
660             }
661             else
662             {
663                 aRange.aStart.SetCol( static_cast<SCCOL>(nStart) );
664                 aRange.aEnd.SetCol( static_cast<SCCOL>(nEnd) );
665             }
666             sal_uLong nDummyStart;
667             pChangeTrack->AppendDeleteRange( aRange, pRefUndoDoc,
668                 nDummyStart, nEndChangeAction );
669         }
670     }
671     else
672         nStartChangeAction = nEndChangeAction = 0;
673 }
674 
675 void __EXPORT ScUndoDeleteMulti::Undo()
676 {
677     WaitObject aWait( pDocShell->GetActiveDialogParent() );     // wichtig wegen TrackFormulas bei UpdateReference
678     BeginUndo();
679 
680     ScDocument* pDoc = pDocShell->GetDocument();
681     SCCOLROW* pOneRange;
682     SCCOLROW nRangeNo;
683 
684     //  rueckwaerts geloescht -> vorwaerts einfuegen
685     pOneRange = pRanges;
686     for (nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++)
687     {
688         SCCOLROW nStart = *(pOneRange++);
689         SCCOLROW nEnd = *(pOneRange++);
690         if (bRows)
691             pDoc->InsertRow( 0,nTab, MAXCOL,nTab, nStart,static_cast<SCSIZE>(nEnd-nStart+1) );
692         else
693             pDoc->InsertCol( 0,nTab, MAXROW,nTab, static_cast<SCCOL>(nStart), static_cast<SCSIZE>(nEnd-nStart+1) );
694     }
695 
696     pOneRange = pRanges;
697     for (nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++)
698     {
699         SCCOLROW nStart = *(pOneRange++);
700         SCCOLROW nEnd = *(pOneRange++);
701         if (bRows)
702             pRefUndoDoc->CopyToDocument( 0,nStart,nTab, MAXCOL,nEnd,nTab, IDF_ALL,sal_False,pDoc );
703         else
704             pRefUndoDoc->CopyToDocument( static_cast<SCCOL>(nStart),0,nTab,
705                     static_cast<SCCOL>(nEnd),MAXROW,nTab, IDF_ALL,sal_False,pDoc );
706     }
707 
708     ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
709     if ( pChangeTrack )
710         pChangeTrack->Undo( nStartChangeAction, nEndChangeAction );
711 
712     DoChange();
713 
714     //! Markierung wieder einzeichnen
715     //! geht im Moment nicht, da keine Daten fuer Markierung vorhanden!
716 
717     EndUndo();
718     SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
719 }
720 
721 void __EXPORT ScUndoDeleteMulti::Redo()
722 {
723     WaitObject aWait( pDocShell->GetActiveDialogParent() );     // wichtig wegen TrackFormulas bei UpdateReference
724     BeginRedo();
725 
726     ScDocument* pDoc = pDocShell->GetDocument();
727 
728     // rueckwaerts loeschen
729     SCCOLROW* pOneRange = &pRanges[2*nRangeCnt];
730     for (SCCOLROW nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++)
731     {
732         SCCOLROW nEnd = *(--pOneRange);
733         SCCOLROW nStart = *(--pOneRange);
734         if (bRows)
735             pDoc->DeleteRow( 0,nTab, MAXCOL,nTab, nStart,static_cast<SCSIZE>(nEnd-nStart+1) );
736         else
737             pDoc->DeleteCol( 0,nTab, MAXROW,nTab, static_cast<SCCOL>(nStart), static_cast<SCSIZE>(nEnd-nStart+1) );
738     }
739 
740     SetChangeTrack();
741 
742     DoChange();
743 
744 //! Markierung loeschen, derzeit unnoetig (s.o.)
745 //! ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
746 //! if (pViewShell)
747 //!     DoneBlockMode();
748 
749     EndRedo();
750     SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
751 }
752 
753 void __EXPORT ScUndoDeleteMulti::Repeat(SfxRepeatTarget& rTarget)
754 {
755     //  DeleteCells, falls einfache Selektion
756     if (rTarget.ISA(ScTabViewTarget))
757         ((ScTabViewTarget&)rTarget).GetViewShell()->DeleteCells( DEL_DELROWS, sal_True );
758 }
759 
760 sal_Bool __EXPORT ScUndoDeleteMulti::CanRepeat(SfxRepeatTarget& rTarget) const
761 {
762     return (rTarget.ISA(ScTabViewTarget));
763 }
764 
765 
766 // -----------------------------------------------------------------------
767 //
768 //      Ausschneiden (Cut)
769 //
770 
771 ScUndoCut::ScUndoCut( ScDocShell* pNewDocShell,
772                 ScRange aRange, ScAddress aOldEnd, const ScMarkData& rMark,
773                 ScDocument* pNewUndoDoc ) :
774     ScBlockUndo( pNewDocShell, ScRange(aRange.aStart, aOldEnd), SC_UNDO_AUTOHEIGHT ),
775     aMarkData( rMark ),
776     pUndoDoc( pNewUndoDoc ),
777     aExtendedRange( aRange )
778 {
779     SetChangeTrack();
780 }
781 
782 __EXPORT ScUndoCut::~ScUndoCut()
783 {
784     delete pUndoDoc;
785 }
786 
787 String __EXPORT ScUndoCut::GetComment() const
788 {
789     return ScGlobal::GetRscString( STR_UNDO_CUT ); // "Ausschneiden"
790 }
791 
792 void ScUndoCut::SetChangeTrack()
793 {
794     ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack();
795     if ( pChangeTrack )
796         pChangeTrack->AppendContentRange( aBlockRange, pUndoDoc,
797             nStartChangeAction, nEndChangeAction, SC_CACM_CUT );
798     else
799         nStartChangeAction = nEndChangeAction = 0;
800 }
801 
802 void ScUndoCut::DoChange( const sal_Bool bUndo )
803 {
804     ScDocument* pDoc = pDocShell->GetDocument();
805     sal_uInt16 nExtFlags = 0;
806 
807     // do not undo/redo objects and note captions, they are handled via drawing undo
808     sal_uInt16 nUndoFlags = (IDF_ALL & ~IDF_OBJECTS) | IDF_NOCAPTIONS;
809 
810     if (bUndo)  // nur bei Undo
811     {
812         //  all sheets - CopyToDocument skips those that don't exist in pUndoDoc
813         SCTAB nTabCount = pDoc->GetTableCount();
814         ScRange aCopyRange = aExtendedRange;
815         aCopyRange.aStart.SetTab(0);
816         aCopyRange.aEnd.SetTab(nTabCount-1);
817         pUndoDoc->CopyToDocument( aCopyRange, nUndoFlags, sal_False, pDoc );
818         ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
819         if ( pChangeTrack )
820             pChangeTrack->Undo( nStartChangeAction, nEndChangeAction );
821     }
822     else        // nur bei Redo
823     {
824         pDocShell->UpdatePaintExt( nExtFlags, aExtendedRange );
825         pDoc->DeleteArea( aBlockRange.aStart.Col(), aBlockRange.aStart.Row(),
826                           aBlockRange.aEnd.Col(), aBlockRange.aEnd.Row(), aMarkData, nUndoFlags );
827         SetChangeTrack();
828     }
829 
830     ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
831     if ( !( (pViewShell) && pViewShell->AdjustBlockHeight() ) )
832 /*A*/   pDocShell->PostPaint( aExtendedRange, PAINT_GRID, nExtFlags );
833 
834     if ( !bUndo )                               //   draw redo after updating row heights
835         RedoSdrUndoAction( pDrawUndo );         //! include in ScBlockUndo?
836 
837     pDocShell->PostDataChanged();
838     if (pViewShell)
839         pViewShell->CellContentChanged();
840 }
841 
842 void __EXPORT ScUndoCut::Undo()
843 {
844     BeginUndo();
845     DoChange( sal_True );
846     EndUndo();
847 }
848 
849 void __EXPORT ScUndoCut::Redo()
850 {
851     BeginRedo();
852     ScDocument* pDoc = pDocShell->GetDocument();
853     EnableDrawAdjust( pDoc, sal_False );                //! include in ScBlockUndo?
854     DoChange( sal_False );
855     EnableDrawAdjust( pDoc, sal_True );                 //! include in ScBlockUndo?
856     EndRedo();
857 }
858 
859 void __EXPORT ScUndoCut::Repeat(SfxRepeatTarget& rTarget)
860 {
861     if (rTarget.ISA(ScTabViewTarget))
862         ((ScTabViewTarget&)rTarget).GetViewShell()->CutToClip( NULL, sal_True );
863 }
864 
865 sal_Bool __EXPORT ScUndoCut::CanRepeat(SfxRepeatTarget& rTarget) const
866 {
867     return (rTarget.ISA(ScTabViewTarget));
868 }
869 
870 
871 // -----------------------------------------------------------------------
872 //
873 //      Einfuegen (Paste)
874 //
875 
876 ScUndoPaste::ScUndoPaste( ScDocShell* pNewDocShell,
877                 SCCOL nStartX, SCROW nStartY, SCTAB nStartZ,
878                 SCCOL nEndX, SCROW nEndY, SCTAB nEndZ,
879                 const ScMarkData& rMark,
880                 ScDocument* pNewUndoDoc, ScDocument* pNewRedoDoc,
881                 sal_uInt16 nNewFlags,
882                 ScRefUndoData* pRefData,
883                 void* /* pFill1 */, void* /* pFill2 */, void* /* pFill3 */,
884                 sal_Bool bRedoIsFilled, const ScUndoPasteOptions* pOptions ) :
885     ScBlockUndo( pNewDocShell, ScRange( nStartX, nStartY, nStartZ, nEndX, nEndY, nEndZ ), SC_UNDO_SIMPLE ),
886     aMarkData( rMark ),
887     pUndoDoc( pNewUndoDoc ),
888     pRedoDoc( pNewRedoDoc ),
889     nFlags( nNewFlags ),
890     pRefUndoData( pRefData ),
891     pRefRedoData( NULL ),
892     bRedoFilled( bRedoIsFilled )
893 {
894     //  pFill1,pFill2,pFill3 are there so the ctor calls for simple paste (without cutting)
895     //  don't have to be changed and branched for 641.
896     //  They can be removed later.
897 
898     if ( !aMarkData.IsMarked() )                // no cell marked:
899         aMarkData.SetMarkArea( aBlockRange );   //  mark paste block
900 
901     if ( pRefUndoData )
902         pRefUndoData->DeleteUnchanged( pDocShell->GetDocument() );
903 
904     if ( pOptions )
905         aPasteOptions = *pOptions;      // used only for Repeat
906 
907     SetChangeTrack();
908 }
909 
910 __EXPORT ScUndoPaste::~ScUndoPaste()
911 {
912     delete pUndoDoc;
913     delete pRedoDoc;
914     delete pRefUndoData;
915     delete pRefRedoData;
916 }
917 
918 String __EXPORT ScUndoPaste::GetComment() const
919 {
920     return ScGlobal::GetRscString( STR_UNDO_PASTE ); // "Einfuegen"
921 }
922 
923 void ScUndoPaste::SetChangeTrack()
924 {
925     ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack();
926     if ( pChangeTrack && (nFlags & IDF_CONTENTS) )
927         pChangeTrack->AppendContentRange( aBlockRange, pUndoDoc,
928             nStartChangeAction, nEndChangeAction, SC_CACM_PASTE );
929     else
930         nStartChangeAction = nEndChangeAction = 0;
931 }
932 
933 void ScUndoPaste::DoChange( const sal_Bool bUndo )
934 {
935     ScDocument* pDoc = pDocShell->GetDocument();
936 
937     //  RefUndoData for redo is created before first undo
938     //  (with DeleteUnchanged after the DoUndo call)
939     sal_Bool bCreateRedoData = ( bUndo && pRefUndoData && !pRefRedoData );
940     if ( bCreateRedoData )
941         pRefRedoData = new ScRefUndoData( pDoc );
942 
943     ScRefUndoData* pWorkRefData = bUndo ? pRefUndoData : pRefRedoData;
944 
945         //  fuer Undo immer alle oder keine Inhalte sichern
946     sal_uInt16 nUndoFlags = IDF_NONE;
947     if (nFlags & IDF_CONTENTS)
948         nUndoFlags |= IDF_CONTENTS;
949     if (nFlags & IDF_ATTRIB)
950         nUndoFlags |= IDF_ATTRIB;
951 
952     // do not undo/redo objects and note captions, they are handled via drawing undo
953     (nUndoFlags &= ~IDF_OBJECTS) |= IDF_NOCAPTIONS;
954 
955     sal_Bool bPaintAll = sal_False;
956 
957     ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
958 
959     // marking is in ScBlockUndo...
960     ScUndoUtil::MarkSimpleBlock( pDocShell, aBlockRange );
961 
962     SCTAB nTabCount = pDoc->GetTableCount();
963     if ( bUndo && !bRedoFilled )
964     {
965         if (!pRedoDoc)
966         {
967             sal_Bool bColInfo = ( aBlockRange.aStart.Row()==0 && aBlockRange.aEnd.Row()==MAXROW );
968             sal_Bool bRowInfo = ( aBlockRange.aStart.Col()==0 && aBlockRange.aEnd.Col()==MAXCOL );
969 
970             pRedoDoc = new ScDocument( SCDOCMODE_UNDO );
971             pRedoDoc->InitUndoSelected( pDoc, aMarkData, bColInfo, bRowInfo );
972         }
973         //  read "redo" data from the document in the first undo
974         //  all sheets - CopyToDocument skips those that don't exist in pRedoDoc
975         ScRange aCopyRange = aBlockRange;
976         aCopyRange.aStart.SetTab(0);
977         aCopyRange.aEnd.SetTab(nTabCount-1);
978         pDoc->CopyToDocument( aCopyRange, nUndoFlags, sal_False, pRedoDoc );
979         bRedoFilled = sal_True;
980     }
981 
982     sal_uInt16 nExtFlags = 0;
983     pDocShell->UpdatePaintExt( nExtFlags, aBlockRange );
984 
985     aMarkData.MarkToMulti();
986     pDoc->DeleteSelection( nUndoFlags, aMarkData );
987     aMarkData.MarkToSimple();
988 
989     SCTAB nFirstSelected = aMarkData.GetFirstSelected();
990     ScRange aTabSelectRange = aBlockRange;
991     SCTAB nTab;
992 
993     if ( !bUndo && pRedoDoc )       // Redo: UndoToDocument before handling RefData
994     {
995         aTabSelectRange.aStart.SetTab( nFirstSelected );
996         aTabSelectRange.aEnd.SetTab( nFirstSelected );
997         pRedoDoc->UndoToDocument( aTabSelectRange, nUndoFlags, sal_False, pDoc );
998         for (nTab=0; nTab<nTabCount; nTab++)
999             if (nTab != nFirstSelected && aMarkData.GetTableSelect(nTab))
1000             {
1001                 aTabSelectRange.aStart.SetTab( nTab );
1002                 aTabSelectRange.aEnd.SetTab( nTab );
1003                 pRedoDoc->CopyToDocument( aTabSelectRange, nUndoFlags, sal_False, pDoc );
1004             }
1005     }
1006 
1007     if (pWorkRefData)
1008     {
1009         pWorkRefData->DoUndo( pDoc, sal_True );     // sal_True = bSetChartRangeLists for SetChartListenerCollection
1010         if ( pDoc->RefreshAutoFilter( 0,0, MAXCOL,MAXROW, aBlockRange.aStart.Tab() ) )
1011             bPaintAll = sal_True;
1012     }
1013 
1014     if ( bCreateRedoData && pRefRedoData )
1015         pRefRedoData->DeleteUnchanged( pDoc );
1016 
1017     if (bUndo)      // Undo: UndoToDocument after handling RefData
1018     {
1019         aTabSelectRange.aStart.SetTab( nFirstSelected );
1020         aTabSelectRange.aEnd.SetTab( nFirstSelected );
1021         pUndoDoc->UndoToDocument( aTabSelectRange, nUndoFlags, sal_False, pDoc );
1022         for (nTab=0; nTab<nTabCount; nTab++)
1023             if (nTab != nFirstSelected && aMarkData.GetTableSelect(nTab))
1024             {
1025                 aTabSelectRange.aStart.SetTab( nTab );
1026                 aTabSelectRange.aEnd.SetTab( nTab );
1027                 pUndoDoc->UndoToDocument( aTabSelectRange, nUndoFlags, sal_False, pDoc );
1028             }
1029     }
1030 
1031     if ( bUndo )
1032     {
1033         ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
1034         if ( pChangeTrack )
1035             pChangeTrack->Undo( nStartChangeAction, nEndChangeAction );
1036     }
1037     else
1038         SetChangeTrack();
1039 
1040     ScRange aDrawRange( aBlockRange );
1041     pDoc->ExtendMerge( aDrawRange, sal_True );      // only needed for single sheet (text/rtf etc.)
1042     sal_uInt16 nPaint = PAINT_GRID;
1043     if (bPaintAll)
1044     {
1045         aDrawRange.aStart.SetCol(0);
1046         aDrawRange.aStart.SetRow(0);
1047         aDrawRange.aEnd.SetCol(MAXCOL);
1048         aDrawRange.aEnd.SetRow(MAXROW);
1049         nPaint |= PAINT_TOP | PAINT_LEFT;
1050 /*A*/   if (pViewShell)
1051             pViewShell->AdjustBlockHeight(sal_False);
1052     }
1053     else
1054     {
1055         if ( aBlockRange.aStart.Row() == 0 && aBlockRange.aEnd.Row() == MAXROW )    // ganze Spalte
1056         {
1057             nPaint |= PAINT_TOP;
1058             aDrawRange.aEnd.SetCol(MAXCOL);
1059         }
1060         if ( aBlockRange.aStart.Col() == 0 && aBlockRange.aEnd.Col() == MAXCOL )    // ganze Zeile
1061         {
1062             nPaint |= PAINT_LEFT;
1063             aDrawRange.aEnd.SetRow(MAXROW);
1064         }
1065 /*A*/   if ((pViewShell) && pViewShell->AdjustBlockHeight(sal_False))
1066         {
1067             aDrawRange.aStart.SetCol(0);
1068             aDrawRange.aStart.SetRow(0);
1069             aDrawRange.aEnd.SetCol(MAXCOL);
1070             aDrawRange.aEnd.SetRow(MAXROW);
1071             nPaint |= PAINT_LEFT;
1072         }
1073         pDocShell->UpdatePaintExt( nExtFlags, aDrawRange );
1074     }
1075 
1076     if ( !bUndo )                               //   draw redo after updating row heights
1077         RedoSdrUndoAction( pDrawUndo );         //! include in ScBlockUndo?
1078 
1079     pDocShell->PostPaint( aDrawRange, nPaint, nExtFlags );
1080 
1081     pDocShell->PostDataChanged();
1082     if (pViewShell)
1083         pViewShell->CellContentChanged();
1084 }
1085 
1086 void __EXPORT ScUndoPaste::Undo()
1087 {
1088     BeginUndo();
1089     DoChange( sal_True );
1090     ShowTable( aBlockRange );
1091     EndUndo();
1092     SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
1093 }
1094 
1095 void __EXPORT ScUndoPaste::Redo()
1096 {
1097     BeginRedo();
1098     ScDocument* pDoc = pDocShell->GetDocument();
1099     EnableDrawAdjust( pDoc, sal_False );                //! include in ScBlockUndo?
1100     DoChange( sal_False );
1101     EnableDrawAdjust( pDoc, sal_True );                 //! include in ScBlockUndo?
1102     EndRedo();
1103     SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
1104 }
1105 
1106 void __EXPORT ScUndoPaste::Repeat(SfxRepeatTarget& rTarget)
1107 {
1108     if (rTarget.ISA(ScTabViewTarget))
1109     {
1110         ScTabViewShell* pViewSh = ((ScTabViewTarget&)rTarget).GetViewShell();
1111         ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pViewSh->GetActiveWin() );
1112         if (pOwnClip)
1113         {
1114             // #129384# keep a reference in case the clipboard is changed during PasteFromClip
1115             com::sun::star::uno::Reference<com::sun::star::datatransfer::XTransferable> aOwnClipRef( pOwnClip );
1116             pViewSh->PasteFromClip( nFlags, pOwnClip->GetDocument(),
1117                                     aPasteOptions.nFunction, aPasteOptions.bSkipEmpty, aPasteOptions.bTranspose,
1118                                     aPasteOptions.bAsLink, aPasteOptions.eMoveMode, IDF_NONE,
1119                                     sal_True );     // allow warning dialog
1120         }
1121     }
1122 }
1123 
1124 sal_Bool __EXPORT ScUndoPaste::CanRepeat(SfxRepeatTarget& rTarget) const
1125 {
1126     return (rTarget.ISA(ScTabViewTarget));
1127 }
1128 
1129 
1130 // -----------------------------------------------------------------------
1131 //
1132 //      Verschieben/Kopieren (Drag & Drop)
1133 //
1134 
1135 ScUndoDragDrop::ScUndoDragDrop( ScDocShell* pNewDocShell,
1136                     const ScRange& rRange, ScAddress aNewDestPos, sal_Bool bNewCut,
1137                     ScDocument* pUndoDocument, ScRefUndoData* pRefData, sal_Bool bScenario ) :
1138     ScMoveUndo( pNewDocShell, pUndoDocument, pRefData, SC_UNDO_REFFIRST ),
1139     aSrcRange( rRange ),
1140     bCut( bNewCut ),
1141     bKeepScenarioFlags( bScenario )
1142 {
1143     ScAddress aDestEnd(aNewDestPos);
1144     aDestEnd.IncRow(aSrcRange.aEnd.Row() - aSrcRange.aStart.Row());
1145     aDestEnd.IncCol(aSrcRange.aEnd.Col() - aSrcRange.aStart.Col());
1146     aDestEnd.IncTab(aSrcRange.aEnd.Tab() - aSrcRange.aStart.Tab());
1147 
1148     sal_Bool bIncludeFiltered = bCut;
1149     if ( !bIncludeFiltered )
1150     {
1151         // find number of non-filtered rows
1152         SCROW nPastedCount = pDocShell->GetDocument()->CountNonFilteredRows(
1153             aSrcRange.aStart.Row(), aSrcRange.aEnd.Row(), aSrcRange.aStart.Tab());
1154 
1155         if ( nPastedCount == 0 )
1156             nPastedCount = 1;
1157         aDestEnd.SetRow( aNewDestPos.Row() + nPastedCount - 1 );
1158     }
1159 
1160     aDestRange.aStart = aNewDestPos;
1161     aDestRange.aEnd = aDestEnd;
1162 
1163     SetChangeTrack();
1164 }
1165 
1166 __EXPORT ScUndoDragDrop::~ScUndoDragDrop()
1167 {
1168 }
1169 
1170 String __EXPORT ScUndoDragDrop::GetComment() const
1171 {   // "Verschieben" : "Kopieren"
1172     return bCut ?
1173         ScGlobal::GetRscString( STR_UNDO_MOVE ) :
1174         ScGlobal::GetRscString( STR_UNDO_COPY );
1175 }
1176 
1177 void ScUndoDragDrop::SetChangeTrack()
1178 {
1179     ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack();
1180     if ( pChangeTrack )
1181     {
1182         if ( bCut )
1183         {
1184             nStartChangeAction = pChangeTrack->GetActionMax() + 1;
1185             pChangeTrack->AppendMove( aSrcRange, aDestRange, pRefUndoDoc );
1186             nEndChangeAction = pChangeTrack->GetActionMax();
1187         }
1188         else
1189             pChangeTrack->AppendContentRange( aDestRange, pRefUndoDoc,
1190                 nStartChangeAction, nEndChangeAction );
1191     }
1192     else
1193         nStartChangeAction = nEndChangeAction = 0;
1194 }
1195 
1196 void ScUndoDragDrop::PaintArea( ScRange aRange, sal_uInt16 nExtFlags ) const
1197 {
1198     sal_uInt16 nPaint = PAINT_GRID;
1199     ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
1200     ScDocument* pDoc = pDocShell->GetDocument();
1201 
1202     if (pViewShell)
1203     {
1204         VirtualDevice aVirtDev;
1205         ScViewData* pViewData = pViewShell->GetViewData();
1206 
1207         if ( pDoc->SetOptimalHeight( aRange.aStart.Row(), aRange.aEnd.Row(),
1208                                      aRange.aStart.Tab(), 0, &aVirtDev,
1209                                      pViewData->GetPPTX(),  pViewData->GetPPTY(),
1210                                      pViewData->GetZoomX(), pViewData->GetZoomY(),
1211                                      sal_False ) )
1212         {
1213             aRange.aStart.SetCol(0);
1214             aRange.aEnd.SetCol(MAXCOL);
1215             aRange.aEnd.SetRow(MAXROW);
1216             nPaint |= PAINT_LEFT;
1217         }
1218     }
1219 
1220     if ( bKeepScenarioFlags )
1221     {
1222         //  Szenarien mitkopiert -> auch Szenario-Rahmen painten
1223         aRange.aStart.SetCol(0);
1224         aRange.aStart.SetRow(0);
1225         aRange.aEnd.SetCol(MAXCOL);
1226         aRange.aEnd.SetRow(MAXROW);
1227     }
1228 
1229     //  column/row info (width/height) included if whole columns/rows were copied
1230     if ( aSrcRange.aStart.Col() == 0 && aSrcRange.aEnd.Col() == MAXCOL )
1231     {
1232         nPaint |= PAINT_LEFT;
1233         aRange.aEnd.SetRow(MAXROW);
1234     }
1235     if ( aSrcRange.aStart.Row() == 0 && aSrcRange.aEnd.Row() == MAXROW )
1236     {
1237         nPaint |= PAINT_TOP;
1238         aRange.aEnd.SetCol(MAXCOL);
1239     }
1240 
1241     pDocShell->PostPaint( aRange, nPaint, nExtFlags );
1242 }
1243 
1244 
1245 void ScUndoDragDrop::DoUndo( ScRange aRange ) const
1246 {
1247     ScDocument* pDoc = pDocShell->GetDocument();
1248 
1249     ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
1250     if ( pChangeTrack )
1251         pChangeTrack->Undo( nStartChangeAction, nEndChangeAction );
1252 
1253 //? DB-Areas vor Daten, damit bei ExtendMerge die Autofilter-Knoepfe stimmen
1254 
1255     ScRange aPaintRange = aRange;
1256     pDoc->ExtendMerge( aPaintRange );           // before deleting
1257 
1258     sal_uInt16 nExtFlags = 0;
1259     pDocShell->UpdatePaintExt( nExtFlags, aPaintRange );
1260 
1261     // do not undo objects and note captions, they are handled via drawing undo
1262     sal_uInt16 nUndoFlags = (IDF_ALL & ~IDF_OBJECTS) | IDF_NOCAPTIONS;
1263 
1264     pDoc->DeleteAreaTab( aRange, nUndoFlags );
1265     pRefUndoDoc->CopyToDocument( aRange, nUndoFlags, sal_False, pDoc );
1266     if ( pDoc->HasAttrib( aRange, HASATTR_MERGED ) )
1267         pDoc->ExtendMerge( aRange, sal_True );
1268 
1269     aPaintRange.aEnd.SetCol( Max( aPaintRange.aEnd.Col(), aRange.aEnd.Col() ) );
1270     aPaintRange.aEnd.SetRow( Max( aPaintRange.aEnd.Row(), aRange.aEnd.Row() ) );
1271 
1272     pDocShell->UpdatePaintExt( nExtFlags, aPaintRange );
1273     PaintArea( aPaintRange, nExtFlags );
1274 }
1275 
1276 void __EXPORT ScUndoDragDrop::Undo()
1277 {
1278     BeginUndo();
1279     DoUndo(aDestRange);
1280     if (bCut)
1281         DoUndo(aSrcRange);
1282     EndUndo();
1283     SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
1284 }
1285 
1286 void __EXPORT ScUndoDragDrop::Redo()
1287 {
1288     BeginRedo();
1289 
1290     ScDocument* pDoc = pDocShell->GetDocument();
1291     ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP );
1292 
1293     EnableDrawAdjust( pDoc, sal_False );                //! include in ScBlockUndo?
1294 
1295     // do not undo/redo objects and note captions, they are handled via drawing undo
1296     sal_uInt16 nRedoFlags = (IDF_ALL & ~IDF_OBJECTS) | IDF_NOCAPTIONS;
1297 
1298     /*  TODO: Redoing note captions is quite tricky due to the fact that a
1299         helper clip document is used. While (re-)pasting the contents to the
1300         destination area, the original pointers to the captions created while
1301         dropping have to be restored. A simple CopyFromClip() would create new
1302         caption objects that are not tracked by drawing undo, and the captions
1303         restored by drawing redo would live without cell note objects pointing
1304         to them. So, first, CopyToClip() and CopyFromClip() are called without
1305         cloning the caption objects. This leads to cell notes pointing to the
1306         wrong captions from source area that will be removed by drawing redo
1307         later. Second, the pointers to the new captions have to be restored.
1308         Sadly, currently these pointers are not stored anywhere but in the list
1309         of drawing undo actions. */
1310 
1311     SCTAB nTab;
1312     ScMarkData aSourceMark;
1313     for (nTab=aSrcRange.aStart.Tab(); nTab<=aSrcRange.aEnd.Tab(); nTab++)
1314         aSourceMark.SelectTable( nTab, sal_True );
1315 
1316     // do not clone objects and note captions into clipdoc (see above)
1317     ScClipParam aClipParam(aSrcRange, bCut);
1318     pDoc->CopyToClip(aClipParam, pClipDoc, &aSourceMark, false, bKeepScenarioFlags, false, false);
1319 
1320     if (bCut)
1321     {
1322         ScRange aSrcPaintRange = aSrcRange;
1323         pDoc->ExtendMerge( aSrcPaintRange );            // before deleting
1324         sal_uInt16 nExtFlags = 0;
1325         pDocShell->UpdatePaintExt( nExtFlags, aSrcPaintRange );
1326         pDoc->DeleteAreaTab( aSrcRange, nRedoFlags );
1327         PaintArea( aSrcPaintRange, nExtFlags );
1328     }
1329 
1330     ScMarkData aDestMark;
1331     for (nTab=aDestRange.aStart.Tab(); nTab<=aDestRange.aEnd.Tab(); nTab++)
1332         aDestMark.SelectTable( nTab, sal_True );
1333 
1334     sal_Bool bIncludeFiltered = bCut;
1335     // TODO: restore old note captions instead of cloning new captions...
1336     pDoc->CopyFromClip( aDestRange, aDestMark, IDF_ALL & ~IDF_OBJECTS, NULL, pClipDoc, sal_True, sal_False, bIncludeFiltered );
1337 
1338     if (bCut)
1339         for (nTab=aSrcRange.aStart.Tab(); nTab<=aSrcRange.aEnd.Tab(); nTab++)
1340             pDoc->RefreshAutoFilter( aSrcRange.aStart.Col(), aSrcRange.aStart.Row(),
1341                                      aSrcRange.aEnd.Col(),   aSrcRange.aEnd.Row(), nTab );
1342 
1343     // skipped rows and merged cells don't mix
1344     if ( !bIncludeFiltered && pClipDoc->HasClipFilteredRows() )
1345         pDocShell->GetDocFunc().UnmergeCells( aDestRange, sal_False, sal_True );
1346 
1347     for (nTab=aDestRange.aStart.Tab(); nTab<=aDestRange.aEnd.Tab(); nTab++)
1348     {
1349         SCCOL nEndCol = aDestRange.aEnd.Col();
1350         SCROW nEndRow = aDestRange.aEnd.Row();
1351         pDoc->ExtendMerge( aDestRange.aStart.Col(), aDestRange.aStart.Row(),
1352                             nEndCol, nEndRow, nTab, sal_True );
1353         PaintArea( ScRange( aDestRange.aStart.Col(), aDestRange.aStart.Row(), nTab,
1354                             nEndCol, nEndRow, nTab ), 0 );
1355     }
1356 
1357     SetChangeTrack();
1358 
1359     delete pClipDoc;
1360     ShowTable( aDestRange.aStart.Tab() );
1361 
1362     RedoSdrUndoAction( pDrawUndo );             //! include in ScBlockUndo?
1363     EnableDrawAdjust( pDoc, sal_True );             //! include in ScBlockUndo?
1364 
1365     EndRedo();
1366     SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
1367 }
1368 
1369 void __EXPORT ScUndoDragDrop::Repeat(SfxRepeatTarget& /* rTarget */)
1370 {
1371 }
1372 
1373 sal_Bool __EXPORT ScUndoDragDrop::CanRepeat(SfxRepeatTarget& /* rTarget */) const
1374 {
1375     return sal_False;           // geht nicht
1376 }
1377 
1378 
1379 // -----------------------------------------------------------------------
1380 //
1381 //      Liste der Bereichsnamen einfuegen
1382 //      (Einfuegen|Name|Einfuegen =>[Liste])
1383 //
1384 
1385 ScUndoListNames::ScUndoListNames( ScDocShell* pNewDocShell, const ScRange& rRange,
1386                 ScDocument* pNewUndoDoc, ScDocument* pNewRedoDoc ) :
1387     ScBlockUndo( pNewDocShell, rRange, SC_UNDO_AUTOHEIGHT ),
1388     pUndoDoc( pNewUndoDoc ),
1389     pRedoDoc( pNewRedoDoc )
1390 {
1391 }
1392 
1393 __EXPORT ScUndoListNames::~ScUndoListNames()
1394 {
1395     delete pUndoDoc;
1396     delete pRedoDoc;
1397 }
1398 
1399 String __EXPORT ScUndoListNames::GetComment() const
1400 {
1401     return ScGlobal::GetRscString( STR_UNDO_LISTNAMES );
1402 }
1403 
1404 void ScUndoListNames::DoChange( ScDocument* pSrcDoc ) const
1405 {
1406     ScDocument* pDoc = pDocShell->GetDocument();
1407 
1408     pDoc->DeleteAreaTab( aBlockRange, IDF_ALL );
1409     pSrcDoc->CopyToDocument( aBlockRange, IDF_ALL, sal_False, pDoc );
1410     pDocShell->PostPaint( aBlockRange, PAINT_GRID );
1411     pDocShell->PostDataChanged();
1412     ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
1413     if (pViewShell)
1414         pViewShell->CellContentChanged();
1415 }
1416 
1417 void __EXPORT ScUndoListNames::Undo()
1418 {
1419     BeginUndo();
1420     DoChange(pUndoDoc);
1421     EndUndo();
1422 }
1423 
1424 void __EXPORT ScUndoListNames::Redo()
1425 {
1426     BeginRedo();
1427     DoChange(pRedoDoc);
1428     EndRedo();
1429 }
1430 
1431 void __EXPORT ScUndoListNames::Repeat(SfxRepeatTarget& rTarget)
1432 {
1433     if (rTarget.ISA(ScTabViewTarget))
1434         ((ScTabViewTarget&)rTarget).GetViewShell()->InsertNameList();
1435 }
1436 
1437 sal_Bool __EXPORT ScUndoListNames::CanRepeat(SfxRepeatTarget& rTarget) const
1438 {
1439     return (rTarget.ISA(ScTabViewTarget));
1440 }
1441 
1442 
1443 // -----------------------------------------------------------------------
1444 //
1445 //      Szenario anwenden
1446 //      (Extras|Szenarien)
1447 //
1448 
1449 ScUndoUseScenario::ScUndoUseScenario( ScDocShell* pNewDocShell,
1450                         const ScMarkData& rMark,
1451 /*C*/                   const ScArea& rDestArea,
1452                               ScDocument* pNewUndoDoc,
1453                         const String& rNewName ) :
1454     ScSimpleUndo( pNewDocShell ),
1455     pUndoDoc( pNewUndoDoc ),
1456     aMarkData( rMark ),
1457     aName( rNewName )
1458 {
1459     aRange.aStart.SetCol(rDestArea.nColStart);
1460     aRange.aStart.SetRow(rDestArea.nRowStart);
1461     aRange.aStart.SetTab(rDestArea.nTab);
1462     aRange.aEnd.SetCol(rDestArea.nColEnd);
1463     aRange.aEnd.SetRow(rDestArea.nRowEnd);
1464     aRange.aEnd.SetTab(rDestArea.nTab);
1465 }
1466 
1467 __EXPORT ScUndoUseScenario::~ScUndoUseScenario()
1468 {
1469     delete pUndoDoc;
1470 }
1471 
1472 String __EXPORT ScUndoUseScenario::GetComment() const
1473 {
1474     return ScGlobal::GetRscString( STR_UNDO_USESCENARIO );
1475 }
1476 
1477 void __EXPORT ScUndoUseScenario::Undo()
1478 {
1479     BeginUndo();
1480 
1481     ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
1482     if (pViewShell)
1483     {
1484         pViewShell->DoneBlockMode();
1485         pViewShell->InitOwnBlockMode();
1486     }
1487 
1488     ScDocument* pDoc = pDocShell->GetDocument();
1489     pDoc->DeleteSelection( IDF_ALL, aMarkData );
1490     pUndoDoc->CopyToDocument( aRange, IDF_ALL, sal_True, pDoc, &aMarkData );
1491 
1492     //  Szenario-Tabellen
1493     sal_Bool bFrame = sal_False;
1494     SCTAB nTab = aRange.aStart.Tab();
1495     SCTAB nEndTab = nTab;
1496     while ( pUndoDoc->HasTable(nEndTab+1) && pUndoDoc->IsScenario(nEndTab+1) )
1497         ++nEndTab;
1498     for (SCTAB i = nTab+1; i<=nEndTab; i++)
1499     {
1500         //  Flags immer
1501         String aComment;
1502         Color  aColor;
1503         sal_uInt16 nScenFlags;
1504         pUndoDoc->GetScenarioData( i, aComment, aColor, nScenFlags );
1505         pDoc->SetScenarioData( i, aComment, aColor, nScenFlags );
1506         sal_Bool bActive = pUndoDoc->IsActiveScenario( i );
1507         pDoc->SetActiveScenario( i, bActive );
1508         //  Bei Zurueckkopier-Szenarios auch Inhalte
1509         if ( nScenFlags & SC_SCENARIO_TWOWAY )
1510         {
1511             pDoc->DeleteAreaTab( 0,0, MAXCOL,MAXROW, i, IDF_ALL );
1512             pUndoDoc->CopyToDocument( 0,0,i, MAXCOL,MAXROW,i, IDF_ALL,sal_False, pDoc );
1513         }
1514         if ( nScenFlags & SC_SCENARIO_SHOWFRAME )
1515             bFrame = sal_True;
1516     }
1517 
1518     //  Wenn sichtbare Rahmen, dann alles painten
1519     if (bFrame)
1520         pDocShell->PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID | PAINT_EXTRAS );
1521     else
1522         pDocShell->PostPaint( aRange, PAINT_GRID | PAINT_EXTRAS );
1523     pDocShell->PostDataChanged();
1524     if (pViewShell)
1525         pViewShell->CellContentChanged();
1526 
1527     ShowTable( aRange.aStart.Tab() );
1528 
1529     EndUndo();
1530 }
1531 
1532 void __EXPORT ScUndoUseScenario::Redo()
1533 {
1534     SCTAB nTab = aRange.aStart.Tab();
1535     BeginRedo();
1536 
1537     ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
1538     if (pViewShell)
1539     {
1540         pViewShell->SetTabNo( nTab );
1541         pViewShell->DoneBlockMode();
1542         pViewShell->InitOwnBlockMode();
1543     }
1544 
1545     pDocShell->UseScenario( nTab, aName, sal_False );
1546 
1547     EndRedo();
1548 }
1549 
1550 void __EXPORT ScUndoUseScenario::Repeat(SfxRepeatTarget& rTarget)
1551 {
1552     if (rTarget.ISA(ScTabViewTarget))
1553     {
1554         String aTemp = aName;
1555         ((ScTabViewTarget&)rTarget).GetViewShell()->UseScenario(aTemp);
1556     }
1557 }
1558 
1559 sal_Bool __EXPORT ScUndoUseScenario::CanRepeat(SfxRepeatTarget& rTarget) const
1560 {
1561     if (rTarget.ISA(ScTabViewTarget))
1562     {
1563         ScViewData* pViewData = ((ScTabViewTarget&)rTarget).GetViewShell()->GetViewData();
1564         return !pViewData->GetDocument()->IsScenario( pViewData->GetTabNo() );
1565     }
1566     return sal_False;
1567 }
1568 
1569 
1570 // -----------------------------------------------------------------------
1571 //
1572 //      Vorlage anwenden
1573 //      (Format|Vorlagenkatalog)
1574 //
1575 
1576 ScUndoSelectionStyle::ScUndoSelectionStyle( ScDocShell* pNewDocShell,
1577                                       const ScMarkData& rMark,
1578                                       const ScRange& rRange,
1579                                       const String& rName,
1580                                             ScDocument* pNewUndoDoc ) :
1581     ScSimpleUndo( pNewDocShell ),
1582     aMarkData( rMark ),
1583     pUndoDoc( pNewUndoDoc ),
1584     aStyleName( rName ),
1585     aRange( rRange )
1586 {
1587     aMarkData.MarkToMulti();
1588 }
1589 
1590 __EXPORT ScUndoSelectionStyle::~ScUndoSelectionStyle()
1591 {
1592     delete pUndoDoc;
1593 }
1594 
1595 String __EXPORT ScUndoSelectionStyle::GetComment() const
1596 {
1597     return ScGlobal::GetRscString( STR_UNDO_APPLYCELLSTYLE );
1598 }
1599 
1600 void ScUndoSelectionStyle::DoChange( const sal_Bool bUndo )
1601 {
1602     ScDocument* pDoc = pDocShell->GetDocument();
1603 
1604     SetViewMarkData( aMarkData );
1605 
1606     ScRange aWorkRange( aRange );
1607     if ( pDoc->HasAttrib( aWorkRange, HASATTR_MERGED ) )        // zusammengefasste Zellen?
1608         pDoc->ExtendMerge( aWorkRange, sal_True );
1609 
1610     sal_uInt16 nExtFlags = 0;
1611     pDocShell->UpdatePaintExt( nExtFlags, aWorkRange );
1612 
1613     if (bUndo)      // bei Undo alte Daten wieder reinschubsen
1614     {
1615         SCTAB nTabCount = pDoc->GetTableCount();
1616         ScRange aCopyRange = aWorkRange;
1617         aCopyRange.aStart.SetTab(0);
1618         aCopyRange.aEnd.SetTab(nTabCount-1);
1619         pUndoDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, sal_True, pDoc, &aMarkData );
1620     }
1621     else            // bei Redo Style wieder zuweisen
1622     {
1623         ScStyleSheetPool* pStlPool = pDoc->GetStyleSheetPool();
1624         ScStyleSheet* pStyleSheet =
1625             (ScStyleSheet*) pStlPool->Find( aStyleName, SFX_STYLE_FAMILY_PARA );
1626         if (!pStyleSheet)
1627         {
1628             DBG_ERROR("StyleSheet not found");
1629             return;
1630         }
1631         pDoc->ApplySelectionStyle( *pStyleSheet, aMarkData );
1632     }
1633 
1634     pDocShell->UpdatePaintExt( nExtFlags, aWorkRange );
1635 
1636     ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
1637     if ( !( (pViewShell) && pViewShell->AdjustBlockHeight() ) )
1638 /*A*/   pDocShell->PostPaint( aWorkRange, PAINT_GRID | PAINT_EXTRAS, nExtFlags );
1639 
1640     ShowTable( aWorkRange.aStart.Tab() );
1641 }
1642 
1643 void __EXPORT ScUndoSelectionStyle::Undo()
1644 {
1645     BeginUndo();
1646     DoChange( sal_True );
1647     EndUndo();
1648 }
1649 
1650 void __EXPORT ScUndoSelectionStyle::Redo()
1651 {
1652     BeginRedo();
1653     DoChange( sal_False );
1654     EndRedo();
1655 }
1656 
1657 void __EXPORT ScUndoSelectionStyle::Repeat(SfxRepeatTarget& rTarget)
1658 {
1659     if (rTarget.ISA(ScTabViewTarget))
1660     {
1661         ScDocument* pDoc = pDocShell->GetDocument();
1662         ScStyleSheetPool* pStlPool = pDoc->GetStyleSheetPool();
1663         ScStyleSheet* pStyleSheet = (ScStyleSheet*) pStlPool->
1664                                             Find( aStyleName, SFX_STYLE_FAMILY_PARA );
1665         if (!pStyleSheet)
1666         {
1667             DBG_ERROR("StyleSheet not found");
1668             return;
1669         }
1670 
1671         ScTabViewShell& rViewShell = *((ScTabViewTarget&)rTarget).GetViewShell();
1672         rViewShell.SetStyleSheetToMarked( pStyleSheet, sal_True );
1673     }
1674 }
1675 
1676 sal_Bool __EXPORT ScUndoSelectionStyle::CanRepeat(SfxRepeatTarget& rTarget) const
1677 {
1678     return (rTarget.ISA(ScTabViewTarget));
1679 }
1680 
1681 sal_uInt16 __EXPORT ScUndoSelectionStyle::GetId() const
1682 {
1683     return STR_UNDO_APPLYCELLSTYLE;
1684 }
1685 
1686 
1687 // -----------------------------------------------------------------------
1688 //
1689 //      Matrix-Formel eingeben
1690 //
1691 
1692 ScUndoEnterMatrix::ScUndoEnterMatrix( ScDocShell* pNewDocShell, const ScRange& rArea,
1693                                       ScDocument* pNewUndoDoc, const String& rForm ) :
1694     ScBlockUndo( pNewDocShell, rArea, SC_UNDO_SIMPLE ),
1695     pUndoDoc( pNewUndoDoc ),
1696     aFormula( rForm )
1697 {
1698     SetChangeTrack();
1699 }
1700 
1701 __EXPORT ScUndoEnterMatrix::~ScUndoEnterMatrix()
1702 {
1703     delete pUndoDoc;
1704 }
1705 
1706 String __EXPORT ScUndoEnterMatrix::GetComment() const
1707 {
1708     return ScGlobal::GetRscString( STR_UNDO_ENTERMATRIX );
1709 }
1710 
1711 void ScUndoEnterMatrix::SetChangeTrack()
1712 {
1713     ScDocument* pDoc = pDocShell->GetDocument();
1714     ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
1715     if ( pChangeTrack )
1716         pChangeTrack->AppendContentRange( aBlockRange, pUndoDoc,
1717             nStartChangeAction, nEndChangeAction );
1718     else
1719         nStartChangeAction = nEndChangeAction = 0;
1720 }
1721 
1722 void __EXPORT ScUndoEnterMatrix::Undo()
1723 {
1724     BeginUndo();
1725 
1726     ScDocument* pDoc = pDocShell->GetDocument();
1727 
1728     pDoc->DeleteAreaTab( aBlockRange, IDF_ALL & ~IDF_NOTE );
1729     pUndoDoc->CopyToDocument( aBlockRange, IDF_ALL & ~IDF_NOTE, sal_False, pDoc );
1730     pDocShell->PostPaint( aBlockRange, PAINT_GRID );
1731     pDocShell->PostDataChanged();
1732     ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
1733     if (pViewShell)
1734         pViewShell->CellContentChanged();
1735 
1736     ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
1737     if ( pChangeTrack )
1738         pChangeTrack->Undo( nStartChangeAction, nEndChangeAction );
1739 
1740     EndUndo();
1741 }
1742 
1743 void __EXPORT ScUndoEnterMatrix::Redo()
1744 {
1745     BeginRedo();
1746 
1747     ScDocument* pDoc = pDocShell->GetDocument();
1748 
1749     ScMarkData aDestMark;
1750     aDestMark.SelectOneTable( aBlockRange.aStart.Tab() );
1751     aDestMark.SetMarkArea( aBlockRange );
1752 
1753     pDoc->InsertMatrixFormula( aBlockRange.aStart.Col(), aBlockRange.aStart.Row(),
1754                                aBlockRange.aEnd.Col(),   aBlockRange.aEnd.Row(),
1755                                aDestMark, aFormula );
1756 //  pDocShell->PostPaint( aBlockRange, PAINT_GRID );    // nicht noetig ???
1757 
1758     SetChangeTrack();
1759 
1760     EndRedo();
1761 }
1762 
1763 void __EXPORT ScUndoEnterMatrix::Repeat(SfxRepeatTarget& rTarget)
1764 {
1765     if (rTarget.ISA(ScTabViewTarget))
1766     {
1767         String aTemp = aFormula;
1768         ((ScTabViewTarget&)rTarget).GetViewShell()->EnterMatrix(aTemp);
1769     }
1770 }
1771 
1772 sal_Bool __EXPORT ScUndoEnterMatrix::CanRepeat(SfxRepeatTarget& rTarget) const
1773 {
1774     return (rTarget.ISA(ScTabViewTarget));
1775 }
1776 
1777 // -----------------------------------------------------------------------
1778 //
1779 //      Einzug vermindern / erhoehen
1780 //
1781 
1782 ScRange lcl_GetMultiMarkRange( const ScMarkData& rMark )
1783 {
1784     DBG_ASSERT( rMark.IsMultiMarked(), "wrong mark type" );
1785 
1786     ScRange aRange;
1787     rMark.GetMultiMarkArea( aRange );
1788     return aRange;
1789 }
1790 
1791 ScUndoIndent::ScUndoIndent( ScDocShell* pNewDocShell, const ScMarkData& rMark,
1792                             ScDocument* pNewUndoDoc, sal_Bool bIncrement ) :
1793     ScBlockUndo( pNewDocShell, lcl_GetMultiMarkRange(rMark), SC_UNDO_AUTOHEIGHT ),
1794     aMarkData( rMark ),
1795     pUndoDoc( pNewUndoDoc ),
1796     bIsIncrement( bIncrement )
1797 {
1798 }
1799 
1800 __EXPORT ScUndoIndent::~ScUndoIndent()
1801 {
1802     delete pUndoDoc;
1803 }
1804 
1805 String __EXPORT ScUndoIndent::GetComment() const
1806 {
1807     sal_uInt16 nId = bIsIncrement ? STR_UNDO_INC_INDENT : STR_UNDO_DEC_INDENT;
1808     return ScGlobal::GetRscString( nId );
1809 }
1810 
1811 void __EXPORT ScUndoIndent::Undo()
1812 {
1813     BeginUndo();
1814 
1815     ScDocument* pDoc = pDocShell->GetDocument();
1816     SCTAB nTabCount = pDoc->GetTableCount();
1817     ScRange aCopyRange = aBlockRange;
1818     aCopyRange.aStart.SetTab(0);
1819     aCopyRange.aEnd.SetTab(nTabCount-1);
1820     pUndoDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, sal_True, pDoc, &aMarkData );
1821     pDocShell->PostPaint( aBlockRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
1822 
1823     EndUndo();
1824 }
1825 
1826 void __EXPORT ScUndoIndent::Redo()
1827 {
1828     BeginRedo();
1829 
1830     ScDocument* pDoc = pDocShell->GetDocument();
1831     pDoc->ChangeSelectionIndent( bIsIncrement, aMarkData );
1832     pDocShell->PostPaint( aBlockRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
1833 
1834     EndRedo();
1835 }
1836 
1837 void __EXPORT ScUndoIndent::Repeat(SfxRepeatTarget& rTarget)
1838 {
1839     if (rTarget.ISA(ScTabViewTarget))
1840         ((ScTabViewTarget&)rTarget).GetViewShell()->ChangeIndent( bIsIncrement );
1841 }
1842 
1843 sal_Bool __EXPORT ScUndoIndent::CanRepeat(SfxRepeatTarget& rTarget) const
1844 {
1845     return (rTarget.ISA(ScTabViewTarget));
1846 }
1847 
1848 // -----------------------------------------------------------------------
1849 //
1850 //      Transliteration for cells
1851 //
1852 
1853 ScUndoTransliterate::ScUndoTransliterate( ScDocShell* pNewDocShell, const ScMarkData& rMark,
1854                             ScDocument* pNewUndoDoc, sal_Int32 nType ) :
1855     ScBlockUndo( pNewDocShell, lcl_GetMultiMarkRange(rMark), SC_UNDO_AUTOHEIGHT ),
1856     aMarkData( rMark ),
1857     pUndoDoc( pNewUndoDoc ),
1858     nTransliterationType( nType )
1859 {
1860 }
1861 
1862 __EXPORT ScUndoTransliterate::~ScUndoTransliterate()
1863 {
1864     delete pUndoDoc;
1865 }
1866 
1867 String __EXPORT ScUndoTransliterate::GetComment() const
1868 {
1869     return ScGlobal::GetRscString( STR_UNDO_TRANSLITERATE );
1870 }
1871 
1872 void __EXPORT ScUndoTransliterate::Undo()
1873 {
1874     BeginUndo();
1875 
1876     ScDocument* pDoc = pDocShell->GetDocument();
1877     SCTAB nTabCount = pDoc->GetTableCount();
1878     ScRange aCopyRange = aBlockRange;
1879     aCopyRange.aStart.SetTab(0);
1880     aCopyRange.aEnd.SetTab(nTabCount-1);
1881     pUndoDoc->CopyToDocument( aCopyRange, IDF_CONTENTS, sal_True, pDoc, &aMarkData );
1882     pDocShell->PostPaint( aBlockRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
1883 
1884     EndUndo();
1885 }
1886 
1887 void __EXPORT ScUndoTransliterate::Redo()
1888 {
1889     BeginRedo();
1890 
1891     ScDocument* pDoc = pDocShell->GetDocument();
1892     pDoc->TransliterateText( aMarkData, nTransliterationType );
1893     pDocShell->PostPaint( aBlockRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
1894 
1895     EndRedo();
1896 }
1897 
1898 void __EXPORT ScUndoTransliterate::Repeat(SfxRepeatTarget& rTarget)
1899 {
1900     if (rTarget.ISA(ScTabViewTarget))
1901         ((ScTabViewTarget&)rTarget).GetViewShell()->TransliterateText( nTransliterationType );
1902 }
1903 
1904 sal_Bool __EXPORT ScUndoTransliterate::CanRepeat(SfxRepeatTarget& rTarget) const
1905 {
1906     return (rTarget.ISA(ScTabViewTarget));
1907 }
1908 
1909 // -----------------------------------------------------------------------
1910 //
1911 //      einzelne Items per Which-IDs aus Bereich loeschen
1912 //
1913 
1914 ScUndoClearItems::ScUndoClearItems( ScDocShell* pNewDocShell, const ScMarkData& rMark,
1915                             ScDocument* pNewUndoDoc, const sal_uInt16* pW ) :
1916     ScBlockUndo( pNewDocShell, lcl_GetMultiMarkRange(rMark), SC_UNDO_AUTOHEIGHT ),
1917     aMarkData( rMark ),
1918     pUndoDoc( pNewUndoDoc ),
1919     pWhich( NULL )
1920 {
1921     DBG_ASSERT( pW, "ScUndoClearItems: Which-Pointer ist 0" );
1922 
1923     sal_uInt16 nCount = 0;
1924     while ( pW[nCount] )
1925         ++nCount;
1926     pWhich = new sal_uInt16[nCount+1];
1927     for (sal_uInt16 i=0; i<=nCount; i++)
1928         pWhich[i] = pW[i];
1929 }
1930 
1931 __EXPORT ScUndoClearItems::~ScUndoClearItems()
1932 {
1933     delete pUndoDoc;
1934     delete pWhich;
1935 }
1936 
1937 String __EXPORT ScUndoClearItems::GetComment() const
1938 {
1939     return ScGlobal::GetRscString( STR_UNDO_DELETECONTENTS );
1940 }
1941 
1942 void __EXPORT ScUndoClearItems::Undo()
1943 {
1944     BeginUndo();
1945 
1946     ScDocument* pDoc = pDocShell->GetDocument();
1947     pUndoDoc->CopyToDocument( aBlockRange, IDF_ATTRIB, sal_True, pDoc, &aMarkData );
1948     pDocShell->PostPaint( aBlockRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
1949 
1950     EndUndo();
1951 }
1952 
1953 void __EXPORT ScUndoClearItems::Redo()
1954 {
1955     BeginRedo();
1956 
1957     ScDocument* pDoc = pDocShell->GetDocument();
1958     pDoc->ClearSelectionItems( pWhich, aMarkData );
1959     pDocShell->PostPaint( aBlockRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
1960 
1961     EndRedo();
1962 }
1963 
1964 void __EXPORT ScUndoClearItems::Repeat(SfxRepeatTarget& rTarget)
1965 {
1966     if (rTarget.ISA(ScTabViewTarget))
1967     {
1968         ScViewData* pViewData = ((ScTabViewTarget&)rTarget).GetViewShell()->GetViewData();
1969         ScDocFunc aFunc(*pViewData->GetDocShell());
1970         aFunc.ClearItems( pViewData->GetMarkData(), pWhich, sal_False );
1971     }
1972 }
1973 
1974 sal_Bool __EXPORT ScUndoClearItems::CanRepeat(SfxRepeatTarget& rTarget) const
1975 {
1976     return (rTarget.ISA(ScTabViewTarget));
1977 }
1978 
1979 // -----------------------------------------------------------------------
1980 //
1981 //      Alle Umbrueche einer Tabelle loeschen
1982 //
1983 
1984 ScUndoRemoveBreaks::ScUndoRemoveBreaks( ScDocShell* pNewDocShell,
1985                                     SCTAB nNewTab, ScDocument* pNewUndoDoc ) :
1986     ScSimpleUndo( pNewDocShell ),
1987     nTab( nNewTab ),
1988     pUndoDoc( pNewUndoDoc )
1989 {
1990 }
1991 
1992 __EXPORT ScUndoRemoveBreaks::~ScUndoRemoveBreaks()
1993 {
1994     delete pUndoDoc;
1995 }
1996 
1997 String __EXPORT ScUndoRemoveBreaks::GetComment() const
1998 {
1999     return ScGlobal::GetRscString( STR_UNDO_REMOVEBREAKS );
2000 }
2001 
2002 void __EXPORT ScUndoRemoveBreaks::Undo()
2003 {
2004     BeginUndo();
2005 
2006     ScDocument* pDoc = pDocShell->GetDocument();
2007     ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
2008 
2009     pUndoDoc->CopyToDocument( 0,0,nTab, MAXCOL,MAXROW,nTab, IDF_NONE, sal_False, pDoc );
2010     if (pViewShell)
2011         pViewShell->UpdatePageBreakData( sal_True );
2012     pDocShell->PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID );
2013 
2014     EndUndo();
2015 }
2016 
2017 void __EXPORT ScUndoRemoveBreaks::Redo()
2018 {
2019     BeginRedo();
2020 
2021     ScDocument* pDoc = pDocShell->GetDocument();
2022     ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
2023 
2024     pDoc->RemoveManualBreaks(nTab);
2025     pDoc->UpdatePageBreaks(nTab);
2026     if (pViewShell)
2027         pViewShell->UpdatePageBreakData( sal_True );
2028     pDocShell->PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID );
2029 
2030     EndRedo();
2031 }
2032 
2033 void __EXPORT ScUndoRemoveBreaks::Repeat(SfxRepeatTarget& rTarget)
2034 {
2035     if (rTarget.ISA(ScTabViewTarget))
2036     {
2037         ScTabViewShell& rViewShell = *((ScTabViewTarget&)rTarget).GetViewShell();
2038         rViewShell.RemoveManualBreaks();
2039     }
2040 }
2041 
2042 sal_Bool __EXPORT ScUndoRemoveBreaks::CanRepeat(SfxRepeatTarget& rTarget) const
2043 {
2044     return (rTarget.ISA(ScTabViewTarget));
2045 }
2046 
2047 // -----------------------------------------------------------------------
2048 //
2049 //      Zusammenfassung aufheben (fuer einen ganzen Bereich)
2050 //
2051 
2052 ScUndoRemoveMerge::ScUndoRemoveMerge( ScDocShell* pNewDocShell,
2053                                        const ScRange& rArea, ScDocument* pNewUndoDoc ) :
2054     ScBlockUndo( pNewDocShell, rArea, SC_UNDO_SIMPLE ),
2055     pUndoDoc( pNewUndoDoc )
2056 {
2057 }
2058 
2059 __EXPORT ScUndoRemoveMerge::~ScUndoRemoveMerge()
2060 {
2061     delete pUndoDoc;
2062 }
2063 
2064 String __EXPORT ScUndoRemoveMerge::GetComment() const
2065 {
2066     return ScGlobal::GetRscString( STR_UNDO_REMERGE );  // "Zusammenfassung aufheben"
2067 }
2068 
2069 void __EXPORT ScUndoRemoveMerge::Undo()
2070 {
2071     BeginUndo();
2072 
2073     ScDocument* pDoc = pDocShell->GetDocument();
2074 
2075     ScRange aExtended = aBlockRange;
2076     pUndoDoc->ExtendMerge( aExtended );
2077 
2078     pDoc->DeleteAreaTab( aExtended, IDF_ATTRIB );
2079     pUndoDoc->CopyToDocument( aExtended, IDF_ATTRIB, sal_False, pDoc );
2080 
2081     sal_Bool bDidPaint = sal_False;
2082     ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
2083     if ( pViewShell )
2084     {
2085         pViewShell->SetTabNo( aExtended.aStart.Tab() );
2086         bDidPaint = pViewShell->AdjustRowHeight( aExtended.aStart.Row(), aExtended.aEnd.Row() );
2087     }
2088     if (!bDidPaint)
2089         ScUndoUtil::PaintMore( pDocShell, aExtended );
2090 
2091     EndUndo();
2092 }
2093 
2094 void __EXPORT ScUndoRemoveMerge::Redo()
2095 {
2096     BeginRedo();
2097 
2098     SCTAB nTab = aBlockRange.aStart.Tab();
2099     ScDocument* pDoc = pDocShell->GetDocument();
2100     ScRange aExtended = aBlockRange;
2101     pDoc->ExtendMerge( aExtended );
2102     ScRange aRefresh = aExtended;
2103     pDoc->ExtendOverlapped( aRefresh );
2104 
2105     //  ausfuehren
2106 
2107     const SfxPoolItem& rDefAttr = pDoc->GetPool()->GetDefaultItem( ATTR_MERGE );
2108     ScPatternAttr aPattern( pDoc->GetPool() );
2109     aPattern.GetItemSet().Put( rDefAttr );
2110     pDoc->ApplyPatternAreaTab( aBlockRange.aStart.Col(), aBlockRange.aStart.Row(),
2111                                 aBlockRange.aEnd.Col(), aBlockRange.aEnd.Row(), nTab,
2112                                 aPattern );
2113 
2114     pDoc->RemoveFlagsTab( aExtended.aStart.Col(), aExtended.aStart.Row(),
2115                             aExtended.aEnd.Col(), aExtended.aEnd.Row(), nTab,
2116                             SC_MF_HOR | SC_MF_VER );
2117 
2118     pDoc->ExtendMerge( aRefresh, sal_True, sal_False );
2119 
2120     //  Paint
2121 
2122     sal_Bool bDidPaint = sal_False;
2123     ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
2124     if ( pViewShell )
2125     {
2126         pViewShell->SetTabNo( aExtended.aStart.Tab() );
2127         bDidPaint = pViewShell->AdjustRowHeight( aExtended.aStart.Row(), aExtended.aEnd.Row() );
2128     }
2129     if (!bDidPaint)
2130         ScUndoUtil::PaintMore( pDocShell, aExtended );
2131 
2132     EndRedo();
2133 }
2134 
2135 void __EXPORT ScUndoRemoveMerge::Repeat(SfxRepeatTarget& rTarget)
2136 {
2137     if (rTarget.ISA(ScTabViewTarget))
2138         ((ScTabViewTarget&)rTarget).GetViewShell()->RemoveMerge();
2139 }
2140 
2141 sal_Bool __EXPORT ScUndoRemoveMerge::CanRepeat(SfxRepeatTarget& rTarget) const
2142 {
2143     return (rTarget.ISA(ScTabViewTarget));
2144 }
2145 
2146 // -----------------------------------------------------------------------
2147 //
2148 //      nur Umrandung setzen, per ScRangeList (StarOne)
2149 //
2150 
2151 ScRange lcl_TotalRange( const ScRangeList& rRanges )
2152 {
2153     ScRange aTotal;
2154     sal_uLong nCount = rRanges.Count();
2155     for (sal_uLong i=0; i<nCount; i++)
2156     {
2157         ScRange aRange = *rRanges.GetObject(i);
2158         if (i==0)
2159             aTotal = aRange;
2160         else
2161         {
2162             if (aRange.aStart.Col() < aTotal.aStart.Col())
2163                 aTotal.aStart.SetCol(aRange.aStart.Col());
2164             if (aRange.aStart.Row() < aTotal.aStart.Row())
2165                 aTotal.aStart.SetRow(aRange.aStart.Row());
2166             if (aRange.aStart.Tab() < aTotal.aStart.Tab())
2167                 aTotal.aStart.SetTab(aRange.aStart.Tab());
2168             if (aRange.aEnd.Col() > aTotal.aEnd.Col())
2169                 aTotal.aEnd.SetCol(aRange.aEnd.Col());
2170             if (aRange.aEnd.Row() > aTotal.aEnd.Row())
2171                 aTotal.aEnd.SetRow(aRange.aEnd.Row());
2172             if (aRange.aEnd.Tab() > aTotal.aEnd.Tab())
2173                 aTotal.aEnd.SetTab(aRange.aEnd.Tab());
2174         }
2175     }
2176     return aTotal;
2177 }
2178 
2179 ScUndoBorder::ScUndoBorder( ScDocShell* pNewDocShell,
2180                             const ScRangeList& rRangeList, ScDocument* pNewUndoDoc,
2181                             const SvxBoxItem& rNewOuter, const SvxBoxInfoItem& rNewInner ) :
2182     ScBlockUndo( pNewDocShell, lcl_TotalRange(rRangeList), SC_UNDO_SIMPLE ),
2183     pUndoDoc( pNewUndoDoc )
2184 {
2185     pRanges = new ScRangeList(rRangeList);
2186     pOuter = new SvxBoxItem(rNewOuter);
2187     pInner = new SvxBoxInfoItem(rNewInner);
2188 }
2189 
2190 __EXPORT ScUndoBorder::~ScUndoBorder()
2191 {
2192     delete pUndoDoc;
2193     delete pRanges;
2194     delete pOuter;
2195     delete pInner;
2196 }
2197 
2198 String __EXPORT ScUndoBorder::GetComment() const
2199 {
2200     return ScGlobal::GetRscString( STR_UNDO_SELATTRLINES );     //! eigener String?
2201 }
2202 
2203 void __EXPORT ScUndoBorder::Undo()
2204 {
2205     BeginUndo();
2206 
2207     ScDocument* pDoc = pDocShell->GetDocument();
2208     ScMarkData aMarkData;
2209     aMarkData.MarkFromRangeList( *pRanges, sal_False );
2210     pUndoDoc->CopyToDocument( aBlockRange, IDF_ATTRIB, sal_True, pDoc, &aMarkData );
2211     pDocShell->PostPaint( aBlockRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
2212 
2213     EndUndo();
2214 }
2215 
2216 void __EXPORT ScUndoBorder::Redo()
2217 {
2218     BeginRedo();
2219 
2220     ScDocument* pDoc = pDocShell->GetDocument();        //! Funktion an docfunc aufrufen
2221     sal_uLong nCount = pRanges->Count();
2222     sal_uLong i;
2223     for (i=0; i<nCount; i++)
2224     {
2225         ScRange aRange = *pRanges->GetObject(i);
2226         SCTAB nTab = aRange.aStart.Tab();
2227 
2228         ScMarkData aMark;
2229         aMark.SetMarkArea( aRange );
2230         aMark.SelectTable( nTab, sal_True );
2231 
2232         pDoc->ApplySelectionFrame( aMark, pOuter, pInner );
2233     }
2234     for (i=0; i<nCount; i++)
2235         pDocShell->PostPaint( *pRanges->GetObject(i), PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
2236 
2237     EndRedo();
2238 }
2239 
2240 void __EXPORT ScUndoBorder::Repeat(SfxRepeatTarget& /* rTarget */)
2241 {
2242     //! spaeter (wenn die Funktion aus cellsuno nach docfunc gewandert ist)
2243 }
2244 
2245 sal_Bool __EXPORT ScUndoBorder::CanRepeat(SfxRepeatTarget& /* rTarget */) const
2246 {
2247     return sal_False;   // s.o.
2248 }
2249 
2250 
2251 
2252 
2253