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