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