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