xref: /trunk/main/sc/source/ui/docshell/docsh3.cxx (revision b3f79822)
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 <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
32 #include <com/sun/star/document/XDocumentProperties.hpp>
33 
34 #include "scitems.hxx"
35 #include "rangelst.hxx"
36 #include <editeng/flstitem.hxx>
37 #include <svx/pageitem.hxx>
38 #include <editeng/paperinf.hxx>
39 #include <svx/postattr.hxx>
40 #include <editeng/sizeitem.hxx>
41 #include <unotools/misccfg.hxx>
42 #include <sfx2/viewfrm.hxx>
43 #include <sfx2/app.hxx>
44 #include <sfx2/docfile.hxx>
45 #include <sfx2/printer.hxx>
46 #include <svtools/ctrltool.hxx>
47 #include <vcl/virdev.hxx>
48 #include <vcl/svapp.hxx>
49 #include <vcl/msgbox.hxx>
50 #include <unotools/localedatawrapper.hxx>
51 
52 #include "docsh.hxx"
53 #include "docshimp.hxx"
54 #include "scmod.hxx"
55 #include "tabvwsh.hxx"
56 #include "viewdata.hxx"
57 #include "docpool.hxx"
58 #include "stlpool.hxx"
59 #include "patattr.hxx"
60 #include "uiitems.hxx"
61 #include "hints.hxx"
62 #include "docoptio.hxx"
63 #include "viewopti.hxx"
64 #include "pntlock.hxx"
65 #include "chgtrack.hxx"
66 #include "docfunc.hxx"
67 #include "cell.hxx"
68 #include "chgviset.hxx"
69 #include "progress.hxx"
70 #include "redcom.hxx"
71 #include "sc.hrc"
72 #include "inputopt.hxx"
73 #include "drwlayer.hxx"
74 #include "inputhdl.hxx"
75 #include "conflictsdlg.hxx"
76 #include "globstr.hrc"
77 
78 #if DEBUG_CHANGETRACK
79 #include <stdio.h>
80 #endif // DEBUG_CHANGETRACK
81 
82 
83 //------------------------------------------------------------------
84 
85 //
86 //			Redraw - Benachrichtigungen
87 //
88 
89 
PostEditView(ScEditEngineDefaulter * pEditEngine,const ScAddress & rCursorPos)90 void ScDocShell::PostEditView( ScEditEngineDefaulter* pEditEngine, const ScAddress& rCursorPos )
91 {
92 //	Broadcast( ScEditViewHint( pEditEngine, rCursorPos ) );
93 
94 		//	Test: nur aktive ViewShell
95 
96 	ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
97 	if (pViewSh && pViewSh->GetViewData()->GetDocShell() == this)
98 	{
99 		ScEditViewHint aHint( pEditEngine, rCursorPos );
100 		pViewSh->Notify( *this, aHint );
101 	}
102 }
103 
PostDataChanged()104 void ScDocShell::PostDataChanged()
105 {
106 	Broadcast( SfxSimpleHint( FID_DATACHANGED ) );
107 	aDocument.ResetChanged( ScRange(0,0,0,MAXCOL,MAXROW,MAXTAB) );
108 
109 	SFX_APP()->Broadcast(SfxSimpleHint( FID_ANYDATACHANGED ));		// Navigator
110 	//!	Navigator direkt benachrichtigen!
111 }
112 
PostPaint(SCCOL nStartCol,SCROW nStartRow,SCTAB nStartTab,SCCOL nEndCol,SCROW nEndRow,SCTAB nEndTab,sal_uInt16 nPart,sal_uInt16 nExtFlags)113 void ScDocShell::PostPaint( SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab,
114 							SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab, sal_uInt16 nPart,
115 							sal_uInt16 nExtFlags )
116 {
117 	if (!ValidCol(nStartCol)) nStartCol = MAXCOL;
118 	if (!ValidRow(nStartRow)) nStartRow = MAXROW;
119 	if (!ValidCol(nEndCol)) nEndCol = MAXCOL;
120 	if (!ValidRow(nEndRow)) nEndRow = MAXROW;
121 
122 	if ( pPaintLockData )
123 	{
124         // #i54081# PAINT_EXTRAS still has to be brodcast because it changes the
125         // current sheet if it's invalid. All other flags added to pPaintLockData.
126         sal_uInt16 nLockPart = nPart & ~PAINT_EXTRAS;
127         if ( nLockPart )
128         {
129             //! nExtFlags ???
130             pPaintLockData->AddRange( ScRange( nStartCol, nStartRow, nStartTab,
131                                                nEndCol, nEndRow, nEndTab ), nLockPart );
132         }
133 
134         nPart &= PAINT_EXTRAS;  // for broadcasting
135         if ( !nPart )
136             return;
137 	}
138 
139 
140     if (nExtFlags & SC_PF_LINES)            // Platz fuer Linien beruecksichtigen
141 	{
142 											//! Abfrage auf versteckte Spalten/Zeilen!
143 		if (nStartCol>0) --nStartCol;
144 		if (nEndCol<MAXCOL) ++nEndCol;
145 		if (nStartRow>0) --nStartRow;
146 		if (nEndRow<MAXROW) ++nEndRow;
147 	}
148 
149 											// um zusammengefasste erweitern
150 	if (nExtFlags & SC_PF_TESTMERGE)
151 		aDocument.ExtendMerge( nStartCol, nStartRow, nEndCol, nEndRow, nStartTab );
152 
153 	if ( nStartCol != 0 || nEndCol != MAXCOL )
154 	{
155 		//	Extend to whole rows if SC_PF_WHOLEROWS is set, or rotated or non-left
156 		//	aligned cells are contained (see UpdatePaintExt).
157 		//	Special handling for RTL text (#i9731#) is unnecessary now with full
158 		//	support of right-aligned text.
159 
160 		if ( ( nExtFlags & SC_PF_WHOLEROWS ) ||
161 			 aDocument.HasAttrib( nStartCol,nStartRow,nStartTab,
162 								  MAXCOL,nEndRow,nEndTab, HASATTR_ROTATE | HASATTR_RIGHTORCENTER ) )
163 		{
164 			nStartCol = 0;
165 			nEndCol = MAXCOL;
166 		}
167 	}
168 
169 	Broadcast( ScPaintHint( ScRange( nStartCol, nStartRow, nStartTab,
170 									 nEndCol, nEndRow, nEndTab ), nPart ) );
171 
172 	if ( nPart & PAINT_GRID )
173 		aDocument.ResetChanged( ScRange(nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab) );
174 }
175 
PostPaint(const ScRange & rRange,sal_uInt16 nPart,sal_uInt16 nExtFlags)176 void ScDocShell::PostPaint( const ScRange& rRange, sal_uInt16 nPart, sal_uInt16 nExtFlags )
177 {
178 	PostPaint( rRange.aStart.Col(), rRange.aStart.Row(), rRange.aStart.Tab(),
179 			   rRange.aEnd.Col(),   rRange.aEnd.Row(),   rRange.aEnd.Tab(),
180 			   nPart, nExtFlags );
181 }
182 
PostPaintGridAll()183 void ScDocShell::PostPaintGridAll()
184 {
185 	PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID );
186 }
187 
PostPaintCell(SCCOL nCol,SCROW nRow,SCTAB nTab)188 void ScDocShell::PostPaintCell( SCCOL nCol, SCROW nRow, SCTAB nTab )
189 {
190 	PostPaint( nCol,nRow,nTab, nCol,nRow,nTab, PAINT_GRID, SC_PF_TESTMERGE );
191 }
192 
PostPaintCell(const ScAddress & rPos)193 void ScDocShell::PostPaintCell( const ScAddress& rPos )
194 {
195 	PostPaintCell( rPos.Col(), rPos.Row(), rPos.Tab() );
196 }
197 
PostPaintExtras()198 void ScDocShell::PostPaintExtras()
199 {
200 	PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_EXTRAS );
201 }
202 
UpdatePaintExt(sal_uInt16 & rExtFlags,const ScRange & rRange)203 void ScDocShell::UpdatePaintExt( sal_uInt16& rExtFlags, const ScRange& rRange )
204 {
205 	if ( ( rExtFlags & SC_PF_LINES ) == 0 && aDocument.HasAttrib( rRange, HASATTR_PAINTEXT ) )
206 	{
207 		//	If the range contains lines, shadow or conditional formats,
208 		//	set SC_PF_LINES to include one extra cell in all directions.
209 
210 		rExtFlags |= SC_PF_LINES;
211 	}
212 
213 	if ( ( rExtFlags & SC_PF_WHOLEROWS ) == 0 &&
214 		 ( rRange.aStart.Col() != 0 || rRange.aEnd.Col() != MAXCOL ) &&
215 		 aDocument.HasAttrib( rRange, HASATTR_ROTATE | HASATTR_RIGHTORCENTER ) )
216 	{
217 		//	If the range contains (logically) right- or center-aligned cells,
218 		//	or rotated cells, set SC_PF_WHOLEROWS to paint the whole rows.
219 		//	This test isn't needed after the cell changes, because it's also
220 		//	tested in PostPaint. UpdatePaintExt may later be changed to do this
221 		//	only if called before the changes.
222 
223 		rExtFlags |= SC_PF_WHOLEROWS;
224 	}
225 }
226 
UpdatePaintExt(sal_uInt16 & rExtFlags,SCCOL nStartCol,SCROW nStartRow,SCTAB nStartTab,SCCOL nEndCol,SCROW nEndRow,SCTAB nEndTab)227 void ScDocShell::UpdatePaintExt( sal_uInt16& rExtFlags, SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab,
228 												   SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab )
229 {
230 	UpdatePaintExt( rExtFlags, ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ) );
231 }
232 
233 //------------------------------------------------------------------
234 
LockPaint_Impl(sal_Bool bDoc)235 void ScDocShell::LockPaint_Impl(sal_Bool bDoc)
236 {
237 	if ( !pPaintLockData )
238 		pPaintLockData = new ScPaintLockData(0);	//! Modus...
239     pPaintLockData->IncLevel(bDoc);
240 }
241 
UnlockPaint_Impl(sal_Bool bDoc)242 void ScDocShell::UnlockPaint_Impl(sal_Bool bDoc)
243 {
244 	if ( pPaintLockData )
245 	{
246 		if ( pPaintLockData->GetLevel(bDoc) )
247 			pPaintLockData->DecLevel(bDoc);
248 		if (!pPaintLockData->GetLevel(!bDoc) && !pPaintLockData->GetLevel(bDoc))
249 		{
250 			//		Paint jetzt ausfuehren
251 
252 			ScPaintLockData* pPaint = pPaintLockData;
253 			pPaintLockData = NULL;						// nicht weitersammeln
254 
255 			ScRangeListRef xRangeList = pPaint->GetRangeList();
256 			if (xRangeList)
257 			{
258 				sal_uInt16 nParts = pPaint->GetParts();
259 				sal_uLong nCount = xRangeList->Count();
260 				for ( sal_uLong i=0; i<nCount; i++ )
261 				{
262 					//!	nExtFlags ???
263 					ScRange aRange = *xRangeList->GetObject(i);
264 					PostPaint( aRange.aStart.Col(), aRange.aStart.Row(), aRange.aStart.Tab(),
265 								aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aEnd.Tab(),
266 								nParts );
267 				}
268 			}
269 
270 			if ( pPaint->GetModified() )
271 				SetDocumentModified();
272 
273 			delete pPaint;
274 		}
275 	}
276 	else
277 	{
278 		DBG_ERROR("UnlockPaint ohne LockPaint");
279 	}
280 }
281 
LockDocument_Impl(sal_uInt16 nNew)282 void ScDocShell::LockDocument_Impl(sal_uInt16 nNew)
283 {
284 	if (!nDocumentLock)
285 	{
286 		ScDrawLayer* pDrawLayer = aDocument.GetDrawLayer();
287 		if (pDrawLayer)
288 			pDrawLayer->setLock(sal_True);
289 	}
290 	nDocumentLock = nNew;
291 }
292 
UnlockDocument_Impl(sal_uInt16 nNew)293 void ScDocShell::UnlockDocument_Impl(sal_uInt16 nNew)
294 {
295 	nDocumentLock = nNew;
296 	if (!nDocumentLock)
297 	{
298 		ScDrawLayer* pDrawLayer = aDocument.GetDrawLayer();
299 		if (pDrawLayer)
300 			pDrawLayer->setLock(sal_False);
301 	}
302 }
303 
GetLockCount() const304 sal_uInt16 ScDocShell::GetLockCount() const
305 {
306 	return nDocumentLock;
307 }
308 
SetLockCount(sal_uInt16 nNew)309 void ScDocShell::SetLockCount(sal_uInt16 nNew)
310 {
311 	if (nNew)					// setzen
312 	{
313 		if ( !pPaintLockData )
314 			pPaintLockData = new ScPaintLockData(0);	//! Modus...
315 		pPaintLockData->SetLevel(nNew-1, sal_True);
316 		LockDocument_Impl(nNew);
317 	}
318 	else if (pPaintLockData)	// loeschen
319 	{
320 		pPaintLockData->SetLevel(0, sal_True);	// bei Unlock sofort ausfuehren
321 		UnlockPaint_Impl(sal_True);					// jetzt
322 		UnlockDocument_Impl(0);
323 	}
324 }
325 
LockPaint()326 void ScDocShell::LockPaint()
327 {
328 	LockPaint_Impl(sal_False);
329 }
330 
UnlockPaint()331 void ScDocShell::UnlockPaint()
332 {
333 	UnlockPaint_Impl(sal_False);
334 }
335 
LockDocument()336 void ScDocShell::LockDocument()
337 {
338 	LockPaint_Impl(sal_True);
339 	LockDocument_Impl(nDocumentLock + 1);
340 }
341 
UnlockDocument()342 void ScDocShell::UnlockDocument()
343 {
344 	if (nDocumentLock)
345 	{
346 		UnlockPaint_Impl(sal_True);
347 		UnlockDocument_Impl(nDocumentLock - 1);
348 	}
349 	else
350 	{
351 		DBG_ERROR("UnlockDocument without LockDocument");
352 	}
353 }
354 
355 //------------------------------------------------------------------
356 
SetInplace(sal_Bool bInplace)357 void ScDocShell::SetInplace( sal_Bool bInplace )
358 {
359 	if (bIsInplace != bInplace)
360 	{
361 		bIsInplace = bInplace;
362 		CalcOutputFactor();
363 	}
364 }
365 
CalcOutputFactor()366 void ScDocShell::CalcOutputFactor()
367 {
368 	if (bIsInplace)
369 	{
370 		nPrtToScreenFactor = 1.0;			// passt sonst nicht zur inaktiven Darstellung
371 		return;
372 	}
373 
374 	sal_Bool bTextWysiwyg = SC_MOD()->GetInputOptions().GetTextWysiwyg();
375 	if (bTextWysiwyg)
376 	{
377 		nPrtToScreenFactor = 1.0;
378 		return;
379 	}
380 
381 	String aTestString = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(
382 			"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890123456789" ));
383 	long nPrinterWidth = 0;
384 	long nWindowWidth = 0;
385 	const ScPatternAttr* pPattern = (const ScPatternAttr*)&aDocument.GetPool()->
386 											GetDefaultItem(ATTR_PATTERN);
387 
388 	Font aDefFont;
389 	OutputDevice* pRefDev = GetRefDevice();
390 	MapMode aOldMode = pRefDev->GetMapMode();
391 	Font	aOldFont = pRefDev->GetFont();
392 
393 	pRefDev->SetMapMode(MAP_PIXEL);
394 	pPattern->GetFont(aDefFont, SC_AUTOCOL_BLACK, pRefDev);	// font color doesn't matter here
395 	pRefDev->SetFont(aDefFont);
396 	nPrinterWidth = pRefDev->PixelToLogic( Size( pRefDev->GetTextWidth(aTestString), 0 ), MAP_100TH_MM ).Width();
397 	pRefDev->SetFont(aOldFont);
398 	pRefDev->SetMapMode(aOldMode);
399 
400 	VirtualDevice aVirtWindow( *Application::GetDefaultDevice() );
401 	aVirtWindow.SetMapMode(MAP_PIXEL);
402 	pPattern->GetFont(aDefFont, SC_AUTOCOL_BLACK, &aVirtWindow);	// font color doesn't matter here
403 	aVirtWindow.SetFont(aDefFont);
404 	nWindowWidth = aVirtWindow.GetTextWidth(aTestString);
405 	nWindowWidth = (long) ( nWindowWidth / ScGlobal::nScreenPPTX * HMM_PER_TWIPS );
406 
407 	if (nPrinterWidth && nWindowWidth)
408 		nPrtToScreenFactor = nPrinterWidth / (double) nWindowWidth;
409 	else
410 	{
411 		DBG_ERROR("GetTextSize gibt 0 ??");
412 		nPrtToScreenFactor = 1.0;
413 	}
414 }
415 
GetOutputFactor() const416 double ScDocShell::GetOutputFactor() const
417 {
418 	return nPrtToScreenFactor;
419 }
420 
421 //---------------------------------------------------------------------
422 
InitOptions(bool bForLoading)423 void ScDocShell::InitOptions(bool bForLoading)      // called from InitNew and Load
424 {
425 	//	Einstellungen aus dem SpellCheckCfg kommen in Doc- und ViewOptions
426 
427 	sal_uInt16 nDefLang, nCjkLang, nCtlLang;
428     sal_Bool bAutoSpell;
429     ScModule::GetSpellSettings( nDefLang, nCjkLang, nCtlLang, bAutoSpell );
430 	ScModule* pScMod = SC_MOD();
431 
432 	ScDocOptions  aDocOpt  = pScMod->GetDocOptions();
433 	ScViewOptions aViewOpt = pScMod->GetViewOptions();
434 	aDocOpt.SetAutoSpell( bAutoSpell );
435 
436 	// zweistellige Jahreszahleneingabe aus Extras->Optionen->Allgemein->Sonstiges
437     aDocOpt.SetYear2000( sal::static_int_cast<sal_uInt16>( ::utl::MiscCfg().GetYear2000() ) );
438 
439     if (bForLoading)
440     {
441         // #i112123# No style:decimal-places attribute means automatic decimals, not the configured default,
442         // so it must not be taken from the global options.
443         // Calculation settings are handled separately in ScXMLBodyContext::EndElement.
444         aDocOpt.SetStdPrecision( SvNumberFormatter::UNLIMITED_PRECISION );
445     }
446 
447 	aDocument.SetDocOptions( aDocOpt );
448 	aDocument.SetViewOptions( aViewOpt );
449 
450 	//	Druck-Optionen werden jetzt direkt vor dem Drucken gesetzt
451 
452 	aDocument.SetLanguage( (LanguageType) nDefLang, (LanguageType) nCjkLang, (LanguageType) nCtlLang );
453 }
454 
455 //---------------------------------------------------------------------
456 
GetDocumentPrinter()457 Printer* ScDocShell::GetDocumentPrinter()		// fuer OLE
458 {
459 	return aDocument.GetPrinter();
460 }
461 
GetPrinter(sal_Bool bCreateIfNotExist)462 SfxPrinter* ScDocShell::GetPrinter(sal_Bool bCreateIfNotExist)
463 {
464 	return aDocument.GetPrinter(bCreateIfNotExist);
465 }
466 
UpdateFontList()467 void ScDocShell::UpdateFontList()
468 {
469     delete pImpl->pFontList;
470     // pImpl->pFontList = new FontList( GetPrinter(), Application::GetDefaultDevice() );
471     pImpl->pFontList = new FontList( GetRefDevice(), NULL, sal_False ); // sal_False or sal_True???
472     SvxFontListItem aFontListItem( pImpl->pFontList, SID_ATTR_CHAR_FONTLIST );
473 	PutItem( aFontListItem );
474 
475 	CalcOutputFactor();
476 }
477 
GetRefDevice()478 OutputDevice* ScDocShell::GetRefDevice()
479 {
480 	return aDocument.GetRefDevice();
481 }
482 
SetPrinter(SfxPrinter * pNewPrinter,sal_uInt16 nDiffFlags)483 sal_uInt16 ScDocShell::SetPrinter( SfxPrinter* pNewPrinter, sal_uInt16 nDiffFlags )
484 {
485     SfxPrinter *pOld = aDocument.GetPrinter( sal_False );
486     if ( pOld && pOld->IsPrinting() )
487         return SFX_PRINTERROR_BUSY;
488 
489 	if (nDiffFlags & SFX_PRINTER_PRINTER)
490 	{
491 		if ( aDocument.GetPrinter() != pNewPrinter )
492 		{
493 			aDocument.SetPrinter( pNewPrinter );
494 			aDocument.SetPrintOptions();
495 
496 			// MT: Use UpdateFontList: Will use Printer fonts only if needed!
497 			/*
498             delete pImpl->pFontList;
499             pImpl->pFontList = new FontList( pNewPrinter, Application::GetDefaultDevice() );
500             SvxFontListItem aFontListItem( pImpl->pFontList, SID_ATTR_CHAR_FONTLIST );
501 			PutItem( aFontListItem );
502 
503 			CalcOutputFactor();
504 			*/
505 			if ( SC_MOD()->GetInputOptions().GetTextWysiwyg() )
506 				UpdateFontList();
507 
508 			ScModule* pScMod = SC_MOD();
509 			SfxViewFrame *pFrame = SfxViewFrame::GetFirst( this );
510 			while (pFrame)
511 			{
512 				SfxViewShell* pSh = pFrame->GetViewShell();
513 				if (pSh && pSh->ISA(ScTabViewShell))
514 				{
515 					ScTabViewShell* pViewSh	= (ScTabViewShell*)pSh;
516 					ScInputHandler* pInputHdl = pScMod->GetInputHdl(pViewSh);
517 					if (pInputHdl)
518 						pInputHdl->UpdateRefDevice();
519 				}
520 				pFrame = SfxViewFrame::GetNext( *pFrame, this );
521 			}
522 		}
523 	}
524 	else if (nDiffFlags & SFX_PRINTER_JOBSETUP)
525 	{
526 		SfxPrinter* pOldPrinter = aDocument.GetPrinter();
527 		if (pOldPrinter)
528 		{
529 			pOldPrinter->SetJobSetup( pNewPrinter->GetJobSetup() );
530 
531 			//	#i6706# Call SetPrinter with the old printer again, so the drawing layer
532 			//	RefDevice is set (calling ReformatAllTextObjects and rebuilding charts),
533 			//	because the JobSetup (printer device settings) may affect text layout.
534 			aDocument.SetPrinter( pOldPrinter );
535 			CalcOutputFactor();							// also with the new settings
536 		}
537 	}
538 
539 	if (nDiffFlags & SFX_PRINTER_OPTIONS)
540 	{
541 		aDocument.SetPrintOptions();		//! aus neuem Printer ???
542 	}
543 
544 	if (nDiffFlags & (SFX_PRINTER_CHG_ORIENTATION | SFX_PRINTER_CHG_SIZE))
545 	{
546 		String aStyle = aDocument.GetPageStyle( GetCurTab() );
547 		ScStyleSheetPool* pStPl = aDocument.GetStyleSheetPool();
548 		SfxStyleSheet* pStyleSheet = (SfxStyleSheet*)pStPl->Find(aStyle, SFX_STYLE_FAMILY_PAGE);
549 		if (pStyleSheet)
550 		{
551 			SfxItemSet& rSet = pStyleSheet->GetItemSet();
552 
553 			if (nDiffFlags & SFX_PRINTER_CHG_ORIENTATION)
554 			{
555 				const SvxPageItem& rOldItem = (const SvxPageItem&)rSet.Get(ATTR_PAGE);
556 				sal_Bool bWasLand = rOldItem.IsLandscape();
557 				sal_Bool bNewLand = ( pNewPrinter->GetOrientation() == ORIENTATION_LANDSCAPE );
558 				if (bNewLand != bWasLand)
559 				{
560 					SvxPageItem aNewItem( rOldItem );
561 					aNewItem.SetLandscape( bNewLand );
562 					rSet.Put( aNewItem );
563 
564 					//	Groesse umdrehen
565 					Size aOldSize = ((const SvxSizeItem&)rSet.Get(ATTR_PAGE_SIZE)).GetSize();
566 					Size aNewSize(aOldSize.Height(),aOldSize.Width());
567 					SvxSizeItem aNewSItem(ATTR_PAGE_SIZE,aNewSize);
568 					rSet.Put( aNewSItem );
569 				}
570 			}
571 			if (nDiffFlags & SFX_PRINTER_CHG_SIZE)
572 			{
573 				SvxSizeItem	aPaperSizeItem( ATTR_PAGE_SIZE, SvxPaperInfo::GetPaperSize(pNewPrinter) );
574 				rSet.Put( aPaperSizeItem );
575 			}
576 		}
577 	}
578 
579 	PostPaint(0,0,0,MAXCOL,MAXROW,MAXTAB,PAINT_ALL);
580 
581 	return 0;
582 }
583 
584 //---------------------------------------------------------------------
585 
GetChangeAction(const ScAddress & rPos)586 ScChangeAction* ScDocShell::GetChangeAction( const ScAddress& rPos )
587 {
588 	ScChangeTrack* pTrack = GetDocument()->GetChangeTrack();
589 	if (!pTrack)
590 		return NULL;
591 
592 	SCTAB nTab = rPos.Tab();
593 
594 	const ScChangeAction* pFound = NULL;
595 	const ScChangeAction* pFoundContent = NULL;
596 	const ScChangeAction* pFoundMove = NULL;
597 	long nModified = 0;
598 	const ScChangeAction* pAction = pTrack->GetFirst();
599 	while (pAction)
600 	{
601 		ScChangeActionType eType = pAction->GetType();
602 		//!	ScViewUtil::IsActionShown( *pAction, *pSettings, *pDoc )...
603 		if ( pAction->IsVisible() && eType != SC_CAT_DELETE_TABS )
604 		{
605 			const ScBigRange& rBig = pAction->GetBigRange();
606 			if ( rBig.aStart.Tab() == nTab )
607 			{
608 				ScRange aRange = rBig.MakeRange();
609 
610 				if ( eType == SC_CAT_DELETE_ROWS )
611 					aRange.aEnd.SetRow( aRange.aStart.Row() );
612 				else if ( eType == SC_CAT_DELETE_COLS )
613 					aRange.aEnd.SetCol( aRange.aStart.Col() );
614 
615 				if ( aRange.In( rPos ) )
616 				{
617 					pFound = pAction;		// der letzte gewinnt
618 					switch ( pAction->GetType() )
619 					{
620 						case SC_CAT_CONTENT :
621 							pFoundContent = pAction;
622 						break;
623 						case SC_CAT_MOVE :
624 							pFoundMove = pAction;
625 						break;
626                         default:
627                         {
628                             // added to avoid warnings
629                         }
630 					}
631 					++nModified;
632 				}
633 			}
634 			if ( pAction->GetType() == SC_CAT_MOVE )
635 			{
636 				ScRange aRange =
637 					((const ScChangeActionMove*)pAction)->
638 					GetFromRange().MakeRange();
639 				if ( aRange.In( rPos ) )
640 				{
641 					pFound = pAction;
642 					++nModified;
643 				}
644 			}
645 		}
646 		pAction = pAction->GetNext();
647 	}
648 
649 	return (ScChangeAction*)pFound;
650 }
651 
SetChangeComment(ScChangeAction * pAction,const String & rComment)652 void ScDocShell::SetChangeComment( ScChangeAction* pAction, const String& rComment )
653 {
654 	if (pAction)
655 	{
656 		pAction->SetComment( rComment );
657 		//!	Undo ???
658 		SetDocumentModified();
659 
660 		//	Dialog-Notify
661 		ScChangeTrack* pTrack = GetDocument()->GetChangeTrack();
662 		if (pTrack)
663 		{
664 			sal_uLong nNumber = pAction->GetActionNumber();
665 			pTrack->NotifyModified( SC_CTM_CHANGE, nNumber, nNumber );
666 		}
667 	}
668 }
669 
ExecuteChangeCommentDialog(ScChangeAction * pAction,Window * pParent,sal_Bool bPrevNext)670 void ScDocShell::ExecuteChangeCommentDialog( ScChangeAction* pAction, Window* pParent,sal_Bool bPrevNext)
671 {
672 	if (!pAction) return;			// ohne Aktion ist nichts..
673 
674 	String aComment = pAction->GetComment();
675 	String aAuthor = pAction->GetUser();
676 
677 	DateTime aDT = pAction->GetDateTime();
678     String aDate = ScGlobal::pLocaleData->getDate( aDT );
679 	aDate += ' ';
680     aDate += ScGlobal::pLocaleData->getTime( aDT, sal_False, sal_False );
681 
682 	SfxItemSet aSet( GetPool(),
683 					  SID_ATTR_POSTIT_AUTHOR, SID_ATTR_POSTIT_AUTHOR,
684 					  SID_ATTR_POSTIT_DATE,   SID_ATTR_POSTIT_DATE,
685 					  SID_ATTR_POSTIT_TEXT,   SID_ATTR_POSTIT_TEXT,
686 					  0 );
687 
688 	aSet.Put( SvxPostItTextItem  ( aComment, SID_ATTR_POSTIT_TEXT ) );
689 	aSet.Put( SvxPostItAuthorItem( aAuthor,  SID_ATTR_POSTIT_AUTHOR ) );
690 	aSet.Put( SvxPostItDateItem  ( aDate,    SID_ATTR_POSTIT_DATE ) );
691 
692 	ScRedComDialog* pDlg = new ScRedComDialog( pParent, aSet,this,pAction,bPrevNext);
693 
694 	pDlg->Execute();
695 
696 	delete pDlg;
697 }
698 
699 //---------------------------------------------------------------------
700 
CompareDocument(ScDocument & rOtherDoc)701 void ScDocShell::CompareDocument( ScDocument& rOtherDoc )
702 {
703 	ScChangeTrack* pTrack = aDocument.GetChangeTrack();
704 	if ( pTrack && pTrack->GetFirst() )
705 	{
706 		//!	Changes vorhanden -> Nachfrage ob geloescht werden soll
707 	}
708 
709 	aDocument.EndChangeTracking();
710 	aDocument.StartChangeTracking();
711 
712 	String aOldUser;
713 	pTrack = aDocument.GetChangeTrack();
714 	if ( pTrack )
715 	{
716 		aOldUser = pTrack->GetUser();
717 
718 		//	check if comparing to same document
719 
720 		String aThisFile;
721 		const SfxMedium* pThisMed = GetMedium();
722 		if (pThisMed)
723 			aThisFile = pThisMed->GetName();
724 		String aOtherFile;
725 		SfxObjectShell* pOtherSh = rOtherDoc.GetDocumentShell();
726 		if (pOtherSh)
727 		{
728 			const SfxMedium* pOtherMed = pOtherSh->GetMedium();
729 			if (pOtherMed)
730 				aOtherFile = pOtherMed->GetName();
731 		}
732 		sal_Bool bSameDoc = ( aThisFile == aOtherFile && aThisFile.Len() );
733 		if ( !bSameDoc )
734 		{
735 			//	create change actions from comparing with the name of the user
736 			//	who last saved the document
737 			//	(only if comparing different documents)
738 
739             using namespace ::com::sun::star;
740             uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
741                 GetModel(), uno::UNO_QUERY_THROW);
742             uno::Reference<document::XDocumentProperties> xDocProps(
743                 xDPS->getDocumentProperties());
744             DBG_ASSERT(xDocProps.is(), "no DocumentProperties");
745             String aDocUser = xDocProps->getModifiedBy();
746 
747 			if ( aDocUser.Len() )
748 				pTrack->SetUser( aDocUser );
749 		}
750 	}
751 
752 	aDocument.CompareDocument( rOtherDoc );
753 
754 	pTrack = aDocument.GetChangeTrack();
755 	if ( pTrack )
756 		pTrack->SetUser( aOldUser );
757 
758 	PostPaintGridAll();
759 	SetDocumentModified();
760 }
761 
762 //---------------------------------------------------------------------
763 //
764 //				Merge (Aenderungen zusammenfuehren)
765 //
766 //---------------------------------------------------------------------
767 
lcl_Equal(const ScChangeAction * pA,const ScChangeAction * pB,sal_Bool bIgnore100Sec)768 inline sal_Bool lcl_Equal( const ScChangeAction* pA, const ScChangeAction* pB, sal_Bool bIgnore100Sec )
769 {
770 	return pA && pB &&
771         pA->GetActionNumber() == pB->GetActionNumber() &&
772         pA->GetType()		  == pB->GetType() &&
773         pA->GetUser()		  == pB->GetUser() &&
774         (bIgnore100Sec ?
775          pA->GetDateTimeUTC().IsEqualIgnore100Sec( pB->GetDateTimeUTC() ) :
776          pA->GetDateTimeUTC() == pB->GetDateTimeUTC());
777 	//	State nicht vergleichen, falls eine alte Aenderung akzeptiert wurde
778 }
779 
lcl_FindAction(ScDocument * pDoc,const ScChangeAction * pAction,ScDocument * pSearchDoc,const ScChangeAction * pFirstSearchAction,const ScChangeAction * pLastSearchAction,sal_Bool bIgnore100Sec)780 bool lcl_FindAction( ScDocument* pDoc, const ScChangeAction* pAction, ScDocument* pSearchDoc, const ScChangeAction* pFirstSearchAction, const ScChangeAction* pLastSearchAction, sal_Bool bIgnore100Sec )
781 {
782     if ( !pDoc || !pAction || !pSearchDoc || !pFirstSearchAction || !pLastSearchAction )
783     {
784         return false;
785     }
786 
787     sal_uLong nLastSearchAction = pLastSearchAction->GetActionNumber();
788     const ScChangeAction* pA = pFirstSearchAction;
789     while ( pA && pA->GetActionNumber() <= nLastSearchAction )
790     {
791 	    if ( pAction->GetType() == pA->GetType() &&
792              pAction->GetUser() == pA->GetUser() &&
793              (bIgnore100Sec ?
794                 pAction->GetDateTimeUTC().IsEqualIgnore100Sec( pA->GetDateTimeUTC() ) :
795                 pAction->GetDateTimeUTC() == pA->GetDateTimeUTC() ) &&
796              pAction->GetBigRange() == pA->GetBigRange() )
797         {
798             String aActionDesc;
799             pAction->GetDescription( aActionDesc, pDoc, sal_True );
800             String aADesc;
801             pA->GetDescription( aADesc, pSearchDoc, sal_True );
802             if ( aActionDesc.Equals( aADesc ) )
803             {
804                 DBG_ERROR( "lcl_FindAction(): found equal action!" );
805                 return true;
806             }
807         }
808         pA = pA->GetNext();
809     }
810 
811     return false;
812 }
813 
MergeDocument(ScDocument & rOtherDoc,bool bShared,bool bCheckDuplicates,sal_uLong nOffset,ScChangeActionMergeMap * pMergeMap,bool bInverseMap)814 void ScDocShell::MergeDocument( ScDocument& rOtherDoc, bool bShared, bool bCheckDuplicates, sal_uLong nOffset, ScChangeActionMergeMap* pMergeMap, bool bInverseMap )
815 {
816     ScTabViewShell* pViewSh = GetBestViewShell( sal_False );    //! Funktionen an die DocShell
817 	if (!pViewSh)
818 		return;
819 
820 	ScChangeTrack* pSourceTrack = rOtherDoc.GetChangeTrack();
821 	if (!pSourceTrack)
822 		return;				//!	nichts zu tun - Fehlermeldung?
823 
824 	ScChangeTrack* pThisTrack = aDocument.GetChangeTrack();
825 	if ( !pThisTrack )
826 	{	// anschalten
827 		aDocument.StartChangeTracking();
828 		pThisTrack = aDocument.GetChangeTrack();
829 		DBG_ASSERT(pThisTrack,"ChangeTracking nicht angeschaltet?");
830         if ( !bShared )
831         {
832             // #51138# visuelles RedLining einschalten
833             ScChangeViewSettings aChangeViewSet;
834             aChangeViewSet.SetShowChanges(sal_True);
835             aDocument.SetChangeViewSettings(aChangeViewSet);
836         }
837 	}
838 
839     // #97286# include 100th seconds in compare?
840     sal_Bool bIgnore100Sec = !pSourceTrack->IsTime100thSeconds() ||
841             !pThisTrack->IsTime100thSeconds();
842 
843 	//	gemeinsame Ausgangsposition suchen
844 	sal_uLong nFirstNewNumber = 0;
845 	const ScChangeAction* pSourceAction = pSourceTrack->GetFirst();
846 	const ScChangeAction* pThisAction = pThisTrack->GetFirst();
847     // skip identical actions
848     while ( lcl_Equal( pSourceAction, pThisAction, bIgnore100Sec ) )
849 	{
850 		nFirstNewNumber = pSourceAction->GetActionNumber() + 1;
851 		pSourceAction = pSourceAction->GetNext();
852 		pThisAction = pThisAction->GetNext();
853 	}
854 	//	pSourceAction und pThisAction zeigen jetzt auf die ersten "eigenen" Aktionen
855 	//	Die gemeinsamen Aktionen davor interessieren ueberhaupt nicht
856 
857 	//!	Abfrage, ob die Dokumente vor dem Change-Tracking gleich waren !!!
858 
859 
860 	const ScChangeAction* pFirstMergeAction = pSourceAction;
861     const ScChangeAction* pFirstSearchAction = pThisAction;
862 
863     // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong
864     const ScChangeAction* pLastSearchAction = pThisTrack->GetLast();
865 
866 	//	MergeChangeData aus den folgenden Aktionen erzeugen
867 	sal_uLong nNewActionCount = 0;
868 	const ScChangeAction* pCount = pSourceAction;
869 	while ( pCount )
870 	{
871         if ( bShared || !ScChangeTrack::MergeIgnore( *pCount, nFirstNewNumber ) )
872 			++nNewActionCount;
873 		pCount = pCount->GetNext();
874 	}
875 	if (!nNewActionCount)
876 		return;				//!	nichts zu tun - Fehlermeldung?
877 							//	ab hier kein return mehr
878 
879 	ScProgress aProgress( this,
880 					String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("...")),
881 					nNewActionCount );
882 
883 	sal_uLong nLastMergeAction = pSourceTrack->GetLast()->GetActionNumber();
884 	// UpdateReference-Undo, gueltige Referenzen fuer den letzten gemeinsamen Zustand
885     pSourceTrack->MergePrepare( (ScChangeAction*) pFirstMergeAction, bShared );
886 
887 	//	MergeChangeData an alle noch folgenden Aktionen in diesem Dokument anpassen
888 	//	-> Referenzen gueltig fuer dieses Dokument
889 	while ( pThisAction )
890 	{
891         // #i87049# [Collaboration] Conflict between delete row and insert content is not merged correctly
892         if ( !bShared || !ScChangeTrack::MergeIgnore( *pThisAction, nFirstNewNumber ) )
893         {
894             ScChangeActionType eType = pThisAction->GetType();
895 		    switch ( eType )
896 		    {
897 			    case SC_CAT_INSERT_COLS :
898 			    case SC_CAT_INSERT_ROWS :
899 			    case SC_CAT_INSERT_TABS :
900 				    pSourceTrack->AppendInsert( pThisAction->GetBigRange().MakeRange() );
901 			    break;
902 			    case SC_CAT_DELETE_COLS :
903 			    case SC_CAT_DELETE_ROWS :
904 			    case SC_CAT_DELETE_TABS :
905 			    {
906 				    const ScChangeActionDel* pDel = (const ScChangeActionDel*) pThisAction;
907 				    if ( pDel->IsTopDelete() && !pDel->IsTabDeleteCol() )
908 				    {	// deleted Table enthaelt deleted Cols, die nicht
909 					    sal_uLong nStart, nEnd;
910 					    pSourceTrack->AppendDeleteRange(
911 						    pDel->GetOverAllRange().MakeRange(), NULL, nStart, nEnd );
912 				    }
913 			    }
914 			    break;
915 			    case SC_CAT_MOVE :
916 			    {
917 				    const ScChangeActionMove* pMove = (const ScChangeActionMove*) pThisAction;
918 				    pSourceTrack->AppendMove( pMove->GetFromRange().MakeRange(),
919 					    pMove->GetBigRange().MakeRange(), NULL );
920 			    }
921 			    break;
922                 default:
923                 {
924                     // added to avoid warnings
925                 }
926 		    }
927         }
928 		pThisAction = pThisAction->GetNext();
929 	}
930 
931     LockPaint();    // #i73877# no repainting after each action
932 
933 	//	MergeChangeData in das aktuelle Dokument uebernehmen
934 	sal_Bool bHasRejected = sal_False;
935 	String aOldUser = pThisTrack->GetUser();
936 	pThisTrack->SetUseFixDateTime( sal_True );
937 	ScMarkData& rMarkData = pViewSh->GetViewData()->GetMarkData();
938 	ScMarkData aOldMarkData( rMarkData );
939 	pSourceAction = pFirstMergeAction;
940 	while ( pSourceAction && pSourceAction->GetActionNumber() <= nLastMergeAction )
941 	{
942         bool bMergeAction = false;
943         if ( bShared )
944         {
945             if ( !bCheckDuplicates || !lcl_FindAction( &rOtherDoc, pSourceAction, &aDocument, pFirstSearchAction, pLastSearchAction, bIgnore100Sec ) )
946             {
947                 bMergeAction = true;
948             }
949         }
950         else
951         {
952             if ( !ScChangeTrack::MergeIgnore( *pSourceAction, nFirstNewNumber ) )
953             {
954                 bMergeAction = true;
955             }
956         }
957 
958         if ( bMergeAction )
959 		{
960 			ScChangeActionType eSourceType = pSourceAction->GetType();
961             if ( !bShared && pSourceAction->IsDeletedIn() )
962 			{
963 				//! muss hier noch festgestellt werden, ob wirklich in
964 				//! _diesem_ Dokument geloescht?
965 
966 				//	liegt in einem Bereich, der in diesem Dokument geloescht wurde
967 				//	-> wird weggelassen
968 				//!	??? Loesch-Aktion rueckgaengig machen ???
969 				//!	??? Aktion irgendwo anders speichern  ???
970 #ifdef DBG_UTIL
971 				String aValue;
972 				if ( eSourceType == SC_CAT_CONTENT )
973 					((const ScChangeActionContent*)pSourceAction)->GetNewString( aValue );
974 				ByteString aError( aValue, gsl_getSystemTextEncoding() );
975 				aError += " weggelassen";
976 				DBG_ERROR( aError.GetBuffer() );
977 #endif
978 			}
979 			else
980 			{
981 				//!	Datum/Autor/Kommentar der Source-Aktion uebernehmen!
982 
983 				pThisTrack->SetUser( pSourceAction->GetUser() );
984 				pThisTrack->SetFixDateTimeUTC( pSourceAction->GetDateTimeUTC() );
985                 sal_uLong nOldActionMax = pThisTrack->GetActionMax();
986 
987                 bool bExecute = true;
988 				sal_uLong nReject = pSourceAction->GetRejectAction();
989                 if ( nReject )
990 				{
991                     if ( bShared )
992                     {
993                         if ( nReject >= nFirstNewNumber )
994                         {
995                             nReject += nOffset;
996                         }
997                         ScChangeAction* pOldAction = pThisTrack->GetAction( nReject );
998                         if ( pOldAction && pOldAction->IsVirgin() )
999                         {
1000                             pThisTrack->Reject( pOldAction );
1001                             bHasRejected = sal_True;
1002                             bExecute = false;
1003                         }
1004                     }
1005                     else
1006                     {
1007 					    //	alte Aktion (aus den gemeinsamen) ablehnen
1008 					    ScChangeAction* pOldAction = pThisTrack->GetAction( nReject );
1009 					    if (pOldAction && pOldAction->GetState() == SC_CAS_VIRGIN)
1010 					    {
1011 						    //!	was passiert bei Aktionen, die in diesem Dokument accepted worden sind???
1012 						    //!	Fehlermeldung oder was???
1013 						    //!	oder Reject-Aenderung normal ausfuehren
1014 
1015 						    pThisTrack->Reject(pOldAction);
1016 						    bHasRejected = sal_True;				// fuer Paint
1017 					    }
1018                         bExecute = false;
1019                     }
1020 				}
1021 
1022                 if ( bExecute )
1023 				{
1024 					//	normal ausfuehren
1025 					ScRange aSourceRange = pSourceAction->GetBigRange().MakeRange();
1026 					rMarkData.SelectOneTable( aSourceRange.aStart.Tab() );
1027 					switch ( eSourceType )
1028 					{
1029 						case SC_CAT_CONTENT:
1030 						{
1031 							//!	Test, ob es ganz unten im Dokument war, dann automatisches
1032 							//!	Zeilen-Einfuegen ???
1033 
1034 							DBG_ASSERT( aSourceRange.aStart == aSourceRange.aEnd, "huch?" );
1035 							ScAddress aPos = aSourceRange.aStart;
1036 							String aValue;
1037 							((const ScChangeActionContent*)pSourceAction)->GetNewString( aValue );
1038 							sal_uInt8 eMatrix = MM_NONE;
1039 							const ScBaseCell* pCell = ((const ScChangeActionContent*)pSourceAction)->GetNewCell();
1040                             if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA )
1041 								eMatrix = ((const ScFormulaCell*)pCell)->GetMatrixFlag();
1042 							switch ( eMatrix )
1043 							{
1044 								case MM_NONE :
1045 									pViewSh->EnterData( aPos.Col(), aPos.Row(), aPos.Tab(), aValue );
1046 								break;
1047 								case MM_FORMULA :
1048 								{
1049                                     SCCOL nCols;
1050                                     SCROW nRows;
1051                                     ((const ScFormulaCell*)pCell)->GetMatColsRows( nCols, nRows );
1052 									aSourceRange.aEnd.SetCol( aPos.Col() + nCols - 1 );
1053 									aSourceRange.aEnd.SetRow( aPos.Row() + nRows - 1 );
1054 									aValue.Erase( 0, 1 );
1055 									aValue.Erase( aValue.Len()-1, 1 );
1056                                     GetDocFunc().EnterMatrix( aSourceRange,
1057                                         NULL, NULL, aValue, sal_False, sal_False,
1058                                         EMPTY_STRING, formula::FormulaGrammar::GRAM_DEFAULT );
1059 								}
1060 								break;
1061 								case MM_REFERENCE :		// do nothing
1062 								break;
1063 								case MM_FAKE :
1064 									DBG_WARNING( "MergeDocument: MatrixFlag MM_FAKE" );
1065 									pViewSh->EnterData( aPos.Col(), aPos.Row(), aPos.Tab(), aValue );
1066 								break;
1067 								default:
1068 									DBG_ERROR( "MergeDocument: unknown MatrixFlag" );
1069 							}
1070 						}
1071 						break;
1072 						case SC_CAT_INSERT_TABS :
1073 						{
1074 							String aName;
1075 							aDocument.CreateValidTabName( aName );
1076 							GetDocFunc().InsertTable( aSourceRange.aStart.Tab(), aName, sal_True, sal_False );
1077 						}
1078 						break;
1079 						case SC_CAT_INSERT_ROWS:
1080 							GetDocFunc().InsertCells( aSourceRange, NULL, INS_INSROWS, sal_True, sal_False );
1081 						break;
1082 						case SC_CAT_INSERT_COLS:
1083 							GetDocFunc().InsertCells( aSourceRange, NULL, INS_INSCOLS, sal_True, sal_False );
1084 						break;
1085 						case SC_CAT_DELETE_TABS :
1086 							GetDocFunc().DeleteTable( aSourceRange.aStart.Tab(), sal_True, sal_False );
1087 						break;
1088 						case SC_CAT_DELETE_ROWS:
1089 						{
1090 							const ScChangeActionDel* pDel = (const ScChangeActionDel*) pSourceAction;
1091 							if ( pDel->IsTopDelete() )
1092 							{
1093 								aSourceRange = pDel->GetOverAllRange().MakeRange();
1094 								GetDocFunc().DeleteCells( aSourceRange, NULL, DEL_DELROWS, sal_True, sal_False );
1095 
1096                                 // #i101099# [Collaboration] Changes are not correctly shown
1097                                 if ( bShared )
1098                                 {
1099                                     ScChangeAction* pAct = pThisTrack->GetLast();
1100                         			if ( pAct && pAct->GetType() == eSourceType && pAct->IsDeletedIn() && !pSourceAction->IsDeletedIn() )
1101                                     {
1102                                         pAct->RemoveAllDeletedIn();
1103                                     }
1104                                 }
1105 							}
1106 						}
1107 						break;
1108 						case SC_CAT_DELETE_COLS:
1109 						{
1110 							const ScChangeActionDel* pDel = (const ScChangeActionDel*) pSourceAction;
1111 							if ( pDel->IsTopDelete() && !pDel->IsTabDeleteCol() )
1112 							{	// deleted Table enthaelt deleted Cols, die nicht
1113 								aSourceRange = pDel->GetOverAllRange().MakeRange();
1114 								GetDocFunc().DeleteCells( aSourceRange, NULL, DEL_DELCOLS, sal_True, sal_False );
1115 							}
1116 						}
1117 						break;
1118 						case SC_CAT_MOVE :
1119 						{
1120 							const ScChangeActionMove* pMove = (const ScChangeActionMove*) pSourceAction;
1121 							ScRange aFromRange( pMove->GetFromRange().MakeRange() );
1122 							GetDocFunc().MoveBlock( aFromRange,
1123 								aSourceRange.aStart, sal_True, sal_True, sal_False, sal_False );
1124 						}
1125 						break;
1126                         default:
1127                         {
1128                             // added to avoid warnings
1129                         }
1130 					}
1131 				}
1132 				const String& rComment = pSourceAction->GetComment();
1133 				if ( rComment.Len() )
1134 				{
1135 					ScChangeAction* pAct = pThisTrack->GetLast();
1136                     if ( pAct && pAct->GetActionNumber() > nOldActionMax )
1137 						pAct->SetComment( rComment );
1138 #ifdef DBG_UTIL
1139 					else
1140 						DBG_ERROR( "MergeDocument: wohin mit dem Kommentar?!?" );
1141 #endif
1142 				}
1143 
1144 				// Referenzen anpassen
1145 				pSourceTrack->MergeOwn( (ScChangeAction*) pSourceAction, nFirstNewNumber, bShared );
1146 
1147                 // merge action state
1148                 if ( bShared && !pSourceAction->IsRejected() )
1149                 {
1150                     ScChangeAction* pAct = pThisTrack->GetLast();
1151                     if ( pAct && pAct->GetActionNumber() > nOldActionMax )
1152                     {
1153                         pThisTrack->MergeActionState( pAct, pSourceAction );
1154                     }
1155                 }
1156 
1157                 // fill merge map
1158                 if ( bShared && pMergeMap )
1159                 {
1160                     ScChangeAction* pAct = pThisTrack->GetLast();
1161                     if ( pAct && pAct->GetActionNumber() > nOldActionMax )
1162                     {
1163                         sal_uLong nActionMax = pAct->GetActionNumber();
1164                         sal_uLong nActionCount = nActionMax - nOldActionMax;
1165                         sal_uLong nAction = nActionMax - nActionCount + 1;
1166                         sal_uLong nSourceAction = pSourceAction->GetActionNumber() - nActionCount + 1;
1167                         while ( nAction <= nActionMax )
1168                         {
1169                             if ( bInverseMap )
1170                             {
1171                                 (*pMergeMap)[ nAction++ ] = nSourceAction++;
1172                             }
1173                             else
1174                             {
1175                                 (*pMergeMap)[ nSourceAction++ ] = nAction++;
1176                             }
1177                         }
1178                     }
1179                 }
1180 			}
1181 			aProgress.SetStateCountDown( --nNewActionCount );
1182 		}
1183 		pSourceAction = pSourceAction->GetNext();
1184 	}
1185 
1186 	rMarkData = aOldMarkData;
1187 	pThisTrack->SetUser(aOldUser);
1188 	pThisTrack->SetUseFixDateTime( sal_False );
1189 
1190 	pSourceTrack->Clear();		//! der ist jetzt verhunzt
1191 
1192 	if (bHasRejected)
1193 		PostPaintGridAll();			// Reject() paintet nicht selber
1194 
1195     UnlockPaint();
1196 }
1197 
MergeSharedDocument(ScDocShell * pSharedDocShell)1198 bool ScDocShell::MergeSharedDocument( ScDocShell* pSharedDocShell )
1199 {
1200     if ( !pSharedDocShell )
1201     {
1202         return false;
1203     }
1204 
1205     ScChangeTrack* pThisTrack = aDocument.GetChangeTrack();
1206     if ( !pThisTrack )
1207     {
1208         return false;
1209     }
1210 
1211     ScDocument& rSharedDoc = *( pSharedDocShell->GetDocument() );
1212     ScChangeTrack* pSharedTrack = rSharedDoc.GetChangeTrack();
1213     if ( !pSharedTrack )
1214     {
1215         return false;
1216     }
1217 
1218 #if DEBUG_CHANGETRACK
1219     ::rtl::OUString aMessage = ::rtl::OUString::createFromAscii( "\nbefore merge:\n" );
1220     aMessage += pThisTrack->ToString();
1221     ::rtl::OString aMsg = ::rtl::OUStringToOString( aMessage, RTL_TEXTENCODING_UTF8 );
1222     OSL_ENSURE( false, aMsg.getStr() );
1223     //fprintf( stdout, "%s ", aMsg.getStr() );
1224     //fflush( stdout );
1225 #endif // DEBUG_CHANGETRACK
1226 
1227     // reset show changes
1228     ScChangeViewSettings aChangeViewSet;
1229     aChangeViewSet.SetShowChanges( sal_False );
1230     aDocument.SetChangeViewSettings( aChangeViewSet );
1231 
1232     // find first merge action in this document
1233     sal_Bool bIgnore100Sec = !pThisTrack->IsTime100thSeconds() || !pSharedTrack->IsTime100thSeconds();
1234     ScChangeAction* pThisAction = pThisTrack->GetFirst();
1235     ScChangeAction* pSharedAction = pSharedTrack->GetFirst();
1236     while ( lcl_Equal( pThisAction, pSharedAction, bIgnore100Sec ) )
1237     {
1238         pThisAction = pThisAction->GetNext();
1239         pSharedAction = pSharedAction->GetNext();
1240     }
1241 
1242     if ( pSharedAction )
1243     {
1244         if ( pThisAction )
1245         {
1246             // merge own changes into shared document
1247             sal_uLong nActStartShared = pSharedAction->GetActionNumber();
1248             sal_uLong nActEndShared = pSharedTrack->GetActionMax();
1249             ScDocument* pTmpDoc = new ScDocument;
1250             for ( sal_Int32 nIndex = 0; nIndex < aDocument.GetTableCount(); ++nIndex )
1251             {
1252                 String sTabName;
1253                 pTmpDoc->CreateValidTabName( sTabName );
1254                 pTmpDoc->InsertTab( SC_TAB_APPEND, sTabName );
1255             }
1256             aDocument.GetChangeTrack()->Clone( pTmpDoc );
1257             ScChangeActionMergeMap aOwnInverseMergeMap;
1258             pSharedDocShell->MergeDocument( *pTmpDoc, true, true, 0, &aOwnInverseMergeMap, true );
1259             delete pTmpDoc;
1260             sal_uLong nActStartOwn = nActEndShared + 1;
1261             sal_uLong nActEndOwn = pSharedTrack->GetActionMax();
1262 
1263             // find conflicts
1264             ScConflictsList aConflictsList;
1265             ScConflictsFinder aFinder( pSharedTrack, nActStartShared, nActEndShared, nActStartOwn, nActEndOwn, aConflictsList );
1266             if ( aFinder.Find() )
1267             {
1268                 ScConflictsListHelper::TransformConflictsList( aConflictsList, NULL, &aOwnInverseMergeMap );
1269                 bool bLoop = true;
1270                 while ( bLoop )
1271                 {
1272                     bLoop = false;
1273                     ScConflictsDlg aDlg( GetActiveDialogParent(), GetViewData(), &rSharedDoc, aConflictsList );
1274                     if ( aDlg.Execute() == RET_CANCEL )
1275                     {
1276                         QueryBox aBox( GetActiveDialogParent(), WinBits( WB_YES_NO | WB_DEF_YES ),
1277                             ScGlobal::GetRscString( STR_DOC_WILLNOTBESAVED ) );
1278                         if ( aBox.Execute() == RET_YES )
1279                         {
1280                             return false;
1281                         }
1282                         else
1283                         {
1284                             bLoop = true;
1285                         }
1286                     }
1287                 }
1288             }
1289 
1290             // undo own changes in shared document
1291             pSharedTrack->Undo( nActStartOwn, nActEndOwn );
1292 
1293             // clone change track for merging into own document
1294             pTmpDoc = new ScDocument;
1295             for ( sal_Int32 nIndex = 0; nIndex < aDocument.GetTableCount(); ++nIndex )
1296             {
1297                 String sTabName;
1298                 pTmpDoc->CreateValidTabName( sTabName );
1299                 pTmpDoc->InsertTab( SC_TAB_APPEND, sTabName );
1300             }
1301             pThisTrack->Clone( pTmpDoc );
1302 
1303             // undo own changes since last save in own document
1304             sal_uLong nStartShared = pThisAction->GetActionNumber();
1305             ScChangeAction* pAction = pThisTrack->GetLast();
1306             while ( pAction && pAction->GetActionNumber() >= nStartShared )
1307             {
1308                 pThisTrack->Reject( pAction, true );
1309                 pAction = pAction->GetPrev();
1310             }
1311 
1312             // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong
1313             pThisTrack->Undo( nStartShared, pThisTrack->GetActionMax(), true );
1314 
1315             // merge shared changes into own document
1316             ScChangeActionMergeMap aSharedMergeMap;
1317             MergeDocument( rSharedDoc, true, true, 0, &aSharedMergeMap );
1318             sal_uLong nEndShared = pThisTrack->GetActionMax();
1319 
1320             // resolve conflicts for shared non-content actions
1321             if ( !aConflictsList.empty() )
1322             {
1323                 ScConflictsListHelper::TransformConflictsList( aConflictsList, &aSharedMergeMap, NULL );
1324                 ScConflictsResolver aResolver( pThisTrack, aConflictsList );
1325                 pAction = pThisTrack->GetAction( nEndShared );
1326                 while ( pAction && pAction->GetActionNumber() >= nStartShared )
1327                 {
1328                     aResolver.HandleAction( pAction, true /*bIsSharedAction*/,
1329                         false /*bHandleContentAction*/, true /*bHandleNonContentAction*/ );
1330                     pAction = pAction->GetPrev();
1331                 }
1332             }
1333             nEndShared = pThisTrack->GetActionMax();
1334 
1335             // only show changes from shared document
1336             aChangeViewSet.SetShowChanges( sal_True );
1337             aChangeViewSet.SetShowAccepted( sal_True );
1338             aChangeViewSet.SetHasActionRange( true );
1339             aChangeViewSet.SetTheActionRange( nStartShared, nEndShared );
1340             aDocument.SetChangeViewSettings( aChangeViewSet );
1341 
1342             // merge own changes back into own document
1343             sal_uLong nStartOwn = nEndShared + 1;
1344             ScChangeActionMergeMap aOwnMergeMap;
1345             MergeDocument( *pTmpDoc, true, true, nEndShared - nStartShared + 1, &aOwnMergeMap );
1346             delete pTmpDoc;
1347             sal_uLong nEndOwn = pThisTrack->GetActionMax();
1348 
1349             // resolve conflicts for shared content actions and own actions
1350             if ( !aConflictsList.empty() )
1351             {
1352                 ScConflictsListHelper::TransformConflictsList( aConflictsList, NULL, &aOwnMergeMap );
1353                 ScConflictsResolver aResolver( pThisTrack, aConflictsList );
1354                 pAction = pThisTrack->GetAction( nEndShared );
1355                 while ( pAction && pAction->GetActionNumber() >= nStartShared )
1356                 {
1357                     aResolver.HandleAction( pAction, true /*bIsSharedAction*/,
1358                         true /*bHandleContentAction*/, false /*bHandleNonContentAction*/ );
1359                     pAction = pAction->GetPrev();
1360                 }
1361 
1362                 pAction = pThisTrack->GetAction( nEndOwn );
1363                 while ( pAction && pAction->GetActionNumber() >= nStartOwn )
1364                 {
1365                     aResolver.HandleAction( pAction, false /*bIsSharedAction*/,
1366                         true /*bHandleContentAction*/, true /*bHandleNonContentAction*/ );
1367                     pAction = pAction->GetPrev();
1368                 }
1369             }
1370             nEndOwn = pThisTrack->GetActionMax();
1371         }
1372         else
1373         {
1374             // merge shared changes into own document
1375             sal_uLong nStartShared = pThisTrack->GetActionMax() + 1;
1376             MergeDocument( rSharedDoc, true, true );
1377             sal_uLong nEndShared = pThisTrack->GetActionMax();
1378 
1379             // only show changes from shared document
1380             aChangeViewSet.SetShowChanges( sal_True );
1381             aChangeViewSet.SetShowAccepted( sal_True );
1382             aChangeViewSet.SetHasActionRange( true );
1383             aChangeViewSet.SetTheActionRange( nStartShared, nEndShared );
1384             aDocument.SetChangeViewSettings( aChangeViewSet );
1385         }
1386 
1387         // update view
1388         PostPaintExtras();
1389         PostPaintGridAll();
1390 
1391         InfoBox aInfoBox( GetActiveDialogParent(), ScGlobal::GetRscString( STR_DOC_UPDATED ) );
1392         aInfoBox.Execute();
1393     }
1394 
1395 #if DEBUG_CHANGETRACK
1396     aMessage = ::rtl::OUString::createFromAscii( "\nafter merge:\n" );
1397     aMessage += pThisTrack->ToString();
1398     aMsg = ::rtl::OUStringToOString( aMessage, RTL_TEXTENCODING_UTF8 );
1399     OSL_ENSURE( false, aMsg.getStr() );
1400     //fprintf( stdout, "%s ", aMsg.getStr() );
1401     //fflush( stdout );
1402 #endif // DEBUG_CHANGETRACK
1403 
1404     return ( pThisAction != NULL );
1405 }
1406