xref: /trunk/main/sc/source/ui/undo/undoblk.cxx (revision cdf0e10c)
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