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