1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: documen3.cxx,v $
10 * $Revision: 1.42.100.5 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
34 // INCLUDE ---------------------------------------------------------------
36 #include "scitems.hxx"
37 #include <svx/langitem.hxx>
38 #include <svx/srchitem.hxx>
39 #include <svx/linkmgr.hxx>
40 #include <sfx2/bindings.hxx>
41 #include <sfx2/objsh.hxx>
42 #include <svtools/zforlist.hxx>
43 #include <svtools/PasswordHelper.hxx>
44 #include <vcl/svapp.hxx>
45 #include "document.hxx"
49 #include "rangenam.hxx"
50 #include "dbcolect.hxx"
52 #include "docpool.hxx"
53 #include "poolhelp.hxx"
54 #include "autoform.hxx"
55 #include "rangelst.hxx"
56 #include "chartarr.hxx"
57 #include "chartlock.hxx"
58 #include "compiler.hxx"
59 #include "refupdat.hxx"
60 #include "docoptio.hxx"
61 #include "viewopti.hxx"
62 #include "scextopt.hxx"
64 #include "bcaslot.hxx"
65 #include "tablink.hxx"
66 #include "externalrefmgr.hxx"
67 #include "markdata.hxx"
68 #include "validat.hxx"
69 #include "dociter.hxx"
70 #include "detdata.hxx"
71 #include "detfunc.hxx"
72 #include "scmod.hxx" // SC_MOD
73 #include "inputopt.hxx" // GetExpandRefs
74 #include "chartlis.hxx"
75 #include "sc.hrc" // SID_LINK
77 #include "dpobject.hxx"
78 #include "unoguard.hxx"
79 #include "drwlayer.hxx"
80 #include "unoreflist.hxx"
81 #include "listenercalls.hxx"
82 #include "tabprotection.hxx"
83 #include "formulaparserpool.hxx"
84 #include "clipparam.hxx"
88 using namespace com::sun::star
;
89 using ::std::auto_ptr
;
91 //------------------------------------------------------------------------
93 ScRangeName
* ScDocument::GetRangeName()
98 void ScDocument::SetRangeName( ScRangeName
* pNewRangeName
)
102 pRangeName
= pNewRangeName
;
105 //UNUSED2008-05 ScRangeData* ScDocument::GetRangeAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab,
106 //UNUSED2008-05 BOOL bStartOnly) const
108 //UNUSED2008-05 if ( pRangeName )
109 //UNUSED2008-05 return pRangeName->GetRangeAtCursor( ScAddress( nCol, nRow, nTab ), bStartOnly );
111 //UNUSED2008-05 return NULL;
114 ScRangeData
* ScDocument::GetRangeAtBlock( const ScRange
& rBlock
, String
* pName
) const
116 ScRangeData
* pData
= NULL
;
119 pData
= pRangeName
->GetRangeAtBlock( rBlock
);
121 *pName
= pData
->GetName();
126 ScDBCollection
* ScDocument::GetDBCollection() const
128 return pDBCollection
;
131 void ScDocument::SetDBCollection( ScDBCollection
* pNewDBCollection
, BOOL bRemoveAutoFilter
)
133 if ( bRemoveAutoFilter
)
135 // remove auto filter attribute if new db data don't contain auto filter flag
136 // start position is also compared, so bRemoveAutoFilter must not be set from ref-undo!
140 USHORT nOldCount
= pDBCollection
->GetCount();
141 for (USHORT nOld
=0; nOld
<nOldCount
; nOld
++)
143 ScDBData
* pOldData
= (*pDBCollection
)[nOld
];
144 if ( pOldData
->HasAutoFilter() )
147 pOldData
->GetArea( aOldRange
);
150 USHORT nNewIndex
= 0;
151 if ( pNewDBCollection
&&
152 pNewDBCollection
->SearchName( pOldData
->GetName(), nNewIndex
) )
154 ScDBData
* pNewData
= (*pNewDBCollection
)[nNewIndex
];
155 if ( pNewData
->HasAutoFilter() )
158 pNewData
->GetArea( aNewRange
);
159 if ( aOldRange
.aStart
== aNewRange
.aStart
)
166 aOldRange
.aEnd
.SetRow( aOldRange
.aStart
.Row() );
167 RemoveFlagsTab( aOldRange
.aStart
.Col(), aOldRange
.aStart
.Row(),
168 aOldRange
.aEnd
.Col(), aOldRange
.aEnd
.Row(),
169 aOldRange
.aStart
.Tab(), SC_MF_AUTO
);
171 pShell
->Broadcast( ScPaintHint( aOldRange
, PAINT_GRID
) );
179 delete pDBCollection
;
180 pDBCollection
= pNewDBCollection
;
183 ScDBData
* ScDocument::GetDBAtCursor(SCCOL nCol
, SCROW nRow
, SCTAB nTab
, BOOL bStartOnly
) const
186 return pDBCollection
->GetDBAtCursor(nCol
, nRow
, nTab
, bStartOnly
);
191 ScDBData
* ScDocument::GetDBAtArea(SCTAB nTab
, SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
) const
194 return pDBCollection
->GetDBAtArea(nTab
, nCol1
, nRow1
, nCol2
, nRow2
);
199 ScDPCollection
* ScDocument::GetDPCollection()
202 pDPCollection
= new ScDPCollection(this);
203 return pDPCollection
;
206 ScDPObject
* ScDocument::GetDPAtCursor(SCCOL nCol
, SCROW nRow
, SCTAB nTab
) const
211 USHORT nCount
= pDPCollection
->GetCount();
212 ScAddress
aPos( nCol
, nRow
, nTab
);
213 for (USHORT i
=0; i
<nCount
; i
++)
214 if ( (*pDPCollection
)[i
]->GetOutRange().In( aPos
) )
215 return (*pDPCollection
)[i
];
220 ScDPObject
* ScDocument::GetDPAtBlock( const ScRange
& rBlock
) const
225 /* Walk the collection in reverse order to get something of an
226 * approximation of MS Excels 'most recent' effect. */
227 USHORT i
= pDPCollection
->GetCount();
229 if ( (*pDPCollection
)[i
]->GetOutRange().In( rBlock
) )
230 return (*pDPCollection
)[i
];
235 ScChartCollection
* ScDocument::GetChartCollection() const
237 return pChartCollection
;
240 void ScDocument::StopTemporaryChartLock()
242 if( apTemporaryChartLock
.get() )
243 apTemporaryChartLock
->StopLocking();
246 void ScDocument::SetChartListenerCollection(
247 ScChartListenerCollection
* pNewChartListenerCollection
,
248 BOOL bSetChartRangeLists
)
250 ScChartListenerCollection
* pOld
= pChartListenerCollection
;
251 pChartListenerCollection
= pNewChartListenerCollection
;
252 if ( pChartListenerCollection
)
255 pChartListenerCollection
->SetDiffDirty( *pOld
, bSetChartRangeLists
);
256 pChartListenerCollection
->StartAllListeners();
261 void ScDocument::SetScenario( SCTAB nTab
, BOOL bFlag
)
263 if (ValidTab(nTab
) && pTab
[nTab
])
264 pTab
[nTab
]->SetScenario(bFlag
);
267 BOOL
ScDocument::IsScenario( SCTAB nTab
) const
269 return ValidTab(nTab
) && pTab
[nTab
] &&pTab
[nTab
]->IsScenario();
270 //if (ValidTab(nTab) && pTab[nTab])
271 // return pTab[nTab]->IsScenario();
276 void ScDocument::SetScenarioData( SCTAB nTab
, const String
& rComment
,
277 const Color
& rColor
, USHORT nFlags
)
279 if (ValidTab(nTab
) && pTab
[nTab
] && pTab
[nTab
]->IsScenario())
281 pTab
[nTab
]->SetScenarioComment( rComment
);
282 pTab
[nTab
]->SetScenarioColor( rColor
);
283 pTab
[nTab
]->SetScenarioFlags( nFlags
);
287 void ScDocument::GetScenarioData( SCTAB nTab
, String
& rComment
,
288 Color
& rColor
, USHORT
& rFlags
) const
290 if (ValidTab(nTab
) && pTab
[nTab
] && pTab
[nTab
]->IsScenario())
292 pTab
[nTab
]->GetScenarioComment( rComment
);
293 rColor
= pTab
[nTab
]->GetScenarioColor();
294 rFlags
= pTab
[nTab
]->GetScenarioFlags();
298 void ScDocument::GetScenarioFlags( SCTAB nTab
, USHORT
& rFlags
) const
300 if (VALIDTAB(nTab
) && pTab
[nTab
] && pTab
[nTab
]->IsScenario())
301 rFlags
= pTab
[nTab
]->GetScenarioFlags();
304 BOOL
ScDocument::IsLinked( SCTAB nTab
) const
306 return ValidTab(nTab
) && pTab
[nTab
] && pTab
[nTab
]->IsLinked();
308 //if (ValidTab(nTab) && pTab[nTab])
309 // return pTab[nTab]->IsLinked();
313 formula::FormulaGrammar::AddressConvention
ScDocument::GetAddressConvention() const
315 return formula::FormulaGrammar::extractRefConvention(eGrammar
);
318 formula::FormulaGrammar::Grammar
ScDocument::GetGrammar() const
323 void ScDocument::SetGrammar( formula::FormulaGrammar::Grammar eGram
)
328 BOOL
ScDocument::GetLinkMode( SCTAB nTab
) const
330 if (ValidTab(nTab
) && pTab
[nTab
])
331 return pTab
[nTab
]->GetLinkMode();
335 const String
& ScDocument::GetLinkDoc( SCTAB nTab
) const
337 if (ValidTab(nTab
) && pTab
[nTab
])
338 return pTab
[nTab
]->GetLinkDoc();
342 const String
& ScDocument::GetLinkFlt( SCTAB nTab
) const
344 if (ValidTab(nTab
) && pTab
[nTab
])
345 return pTab
[nTab
]->GetLinkFlt();
349 const String
& ScDocument::GetLinkOpt( SCTAB nTab
) const
351 if (ValidTab(nTab
) && pTab
[nTab
])
352 return pTab
[nTab
]->GetLinkOpt();
356 const String
& ScDocument::GetLinkTab( SCTAB nTab
) const
358 if (ValidTab(nTab
) && pTab
[nTab
])
359 return pTab
[nTab
]->GetLinkTab();
363 ULONG
ScDocument::GetLinkRefreshDelay( SCTAB nTab
) const
365 if (ValidTab(nTab
) && pTab
[nTab
])
366 return pTab
[nTab
]->GetLinkRefreshDelay();
370 void ScDocument::SetLink( SCTAB nTab
, BYTE nMode
, const String
& rDoc
,
371 const String
& rFilter
, const String
& rOptions
,
372 const String
& rTabName
, ULONG nRefreshDelay
)
374 if (ValidTab(nTab
) && pTab
[nTab
])
375 pTab
[nTab
]->SetLink( nMode
, rDoc
, rFilter
, rOptions
, rTabName
, nRefreshDelay
);
378 BOOL
ScDocument::HasLink( const String
& rDoc
,
379 const String
& rFilter
, const String
& rOptions
) const
381 SCTAB nCount
= GetTableCount();
382 for (SCTAB i
=0; i
<nCount
; i
++)
383 if (pTab
[i
]->IsLinked()
384 && pTab
[i
]->GetLinkDoc() == rDoc
385 && pTab
[i
]->GetLinkFlt() == rFilter
386 && pTab
[i
]->GetLinkOpt() == rOptions
)
392 BOOL
ScDocument::LinkExternalTab( SCTAB
& rTab
, const String
& aDocTab
,
393 const String
& aFileName
, const String
& aTabName
)
397 DBG_ERRORFILE( "LinkExternalTab in Clipboard" );
401 String aFilterName
; // wird vom Loader gefuellt
402 String aOptions
; // Filter-Optionen
403 sal_uInt32 nLinkCnt
= pExtDocOptions
? pExtDocOptions
->GetDocSettings().mnLinkCnt
: 0;
404 ScDocumentLoader
aLoader( aFileName
, aFilterName
, aOptions
, nLinkCnt
+ 1 );
405 if ( aLoader
.IsError() )
407 ScDocument
* pSrcDoc
= aLoader
.GetDocument();
411 if ( pSrcDoc
->GetTable( aTabName
, nSrcTab
) )
413 if ( !InsertTab( SC_TAB_APPEND
, aDocTab
, TRUE
) )
415 DBG_ERRORFILE("can't insert external document table");
418 rTab
= GetTableCount() - 1;
419 // nicht neu einfuegen, nur Ergebnisse
420 TransferTab( pSrcDoc
, nSrcTab
, rTab
, FALSE
, TRUE
);
425 ULONG nRefreshDelay
= 0;
427 BOOL bWasThere
= HasLink( aFileName
, aFilterName
, aOptions
);
428 SetLink( rTab
, SC_LINK_VALUE
, aFileName
, aFilterName
, aOptions
, aTabName
, nRefreshDelay
);
429 if ( !bWasThere
) // Link pro Quelldokument nur einmal eintragen
431 ScTableLink
* pLink
= new ScTableLink( pShell
, aFileName
, aFilterName
, aOptions
, nRefreshDelay
);
432 pLink
->SetInCreate( TRUE
);
433 GetLinkManager()->InsertFileLink( *pLink
, OBJECT_CLIENT_FILE
, aFileName
,
436 pLink
->SetInCreate( FALSE
);
437 SfxBindings
* pBindings
= GetViewBindings();
439 pBindings
->Invalidate( SID_LINKS
);
444 ScExternalRefManager
* ScDocument::GetExternalRefManager() const
446 ScDocument
* pThis
= const_cast<ScDocument
*>(this);
447 if (!pExternalRefMgr
.get())
448 pThis
->pExternalRefMgr
.reset( new ScExternalRefManager( pThis
));
450 return pExternalRefMgr
.get();
453 bool ScDocument::IsInExternalReferenceMarking() const
455 return pExternalRefMgr
.get() && pExternalRefMgr
->isInReferenceMarking();
458 void ScDocument::MarkUsedExternalReferences()
460 if (!pExternalRefMgr
.get())
462 if (!pExternalRefMgr
->hasExternalData())
465 bool bAllMarked
= pExternalRefMgr
->markUsedByLinkListeners();
467 for (SCTAB nTab
= 0; !bAllMarked
&& nTab
< nMaxTableNumber
; ++nTab
)
470 bAllMarked
= pTab
[nTab
]->MarkUsedExternalReferences();
472 /* NOTE: Conditional formats and validation objects are marked when
473 * collecting them during export. */
476 ScFormulaParserPool
& ScDocument::GetFormulaParserPool() const
478 if( !mxFormulaParserPool
.get() )
479 mxFormulaParserPool
.reset( new ScFormulaParserPool( *this ) );
480 return *mxFormulaParserPool
;
483 ScOutlineTable
* ScDocument::GetOutlineTable( SCTAB nTab
, BOOL bCreate
)
485 ScOutlineTable
* pVal
= NULL
;
490 pVal
= pTab
[nTab
]->GetOutlineTable();
494 pTab
[nTab
]->StartOutlineTable();
495 pVal
= pTab
[nTab
]->GetOutlineTable();
502 BOOL
ScDocument::SetOutlineTable( SCTAB nTab
, const ScOutlineTable
* pNewOutline
)
504 return VALIDTAB(nTab
) && pTab
[nTab
] && pTab
[nTab
]->SetOutlineTable(pNewOutline
);
505 //if (VALIDTAB(nTab))
507 // return pTab[nTab]->SetOutlineTable(pNewOutline);
512 void ScDocument::DoAutoOutline( SCCOL nStartCol
, SCROW nStartRow
,
513 SCCOL nEndCol
, SCROW nEndRow
, SCTAB nTab
)
515 if (VALIDTAB(nTab
) && pTab
[nTab
])
516 pTab
[nTab
]->DoAutoOutline( nStartCol
, nStartRow
, nEndCol
, nEndRow
);
519 BOOL
ScDocument::TestRemoveSubTotals( SCTAB nTab
, const ScSubTotalParam
& rParam
)
521 return VALIDTAB(nTab
) && pTab
[nTab
] && pTab
[nTab
]->TestRemoveSubTotals( rParam
);
522 //if (VALIDTAB(nTab) && pTab[nTab] )
523 // return pTab[nTab]->TestRemoveSubTotals( rParam );
528 void ScDocument::RemoveSubTotals( SCTAB nTab
, ScSubTotalParam
& rParam
)
530 if ( VALIDTAB(nTab
) && pTab
[nTab
] )
531 pTab
[nTab
]->RemoveSubTotals( rParam
);
534 BOOL
ScDocument::DoSubTotals( SCTAB nTab
, ScSubTotalParam
& rParam
)
536 return VALIDTAB(nTab
) && pTab
[nTab
] && pTab
[nTab
]->DoSubTotals( rParam
);
537 //if (VALIDTAB(nTab))
539 // return pTab[nTab]->DoSubTotals( rParam );
544 BOOL
ScDocument::HasSubTotalCells( const ScRange
& rRange
)
546 ScCellIterator
aIter( this, rRange
);
547 ScBaseCell
* pCell
= aIter
.GetFirst();
550 if ( pCell
->GetCellType() == CELLTYPE_FORMULA
&& ((ScFormulaCell
*)pCell
)->IsSubTotal() )
553 pCell
= aIter
.GetNext();
555 return FALSE
; // none found
558 // kopiert aus diesem Dokument die Zellen von Positionen, an denen in pPosDoc
559 // auch Zellen stehen, nach pDestDoc
561 void ScDocument::CopyUpdated( ScDocument
* pPosDoc
, ScDocument
* pDestDoc
)
563 SCTAB nCount
= GetTableCount();
564 for (SCTAB nTab
=0; nTab
<nCount
; nTab
++)
565 if (pTab
[nTab
] && pPosDoc
->pTab
[nTab
] && pDestDoc
->pTab
[nTab
])
566 pTab
[nTab
]->CopyUpdated( pPosDoc
->pTab
[nTab
], pDestDoc
->pTab
[nTab
] );
569 void ScDocument::CopyScenario( SCTAB nSrcTab
, SCTAB nDestTab
, BOOL bNewScenario
)
571 if (ValidTab(nSrcTab
) && ValidTab(nDestTab
) && pTab
[nSrcTab
] && pTab
[nDestTab
])
573 // Flags fuer aktive Szenarios richtig setzen
574 // und aktuelle Werte in bisher aktive Szenarios zurueckschreiben
576 ScRangeList aRanges
= *pTab
[nSrcTab
]->GetScenarioRanges();
577 const ULONG nRangeCount
= aRanges
.Count();
579 // nDestTab ist die Zieltabelle
580 for ( SCTAB nTab
= nDestTab
+1;
581 nTab
<=MAXTAB
&& pTab
[nTab
] && pTab
[nTab
]->IsScenario();
584 if ( pTab
[nTab
]->IsActiveScenario() ) // auch wenn's dasselbe Szenario ist
586 BOOL bTouched
= FALSE
;
587 for ( ULONG nR
=0; nR
<nRangeCount
&& !bTouched
; nR
++)
589 const ScRange
* pRange
= aRanges
.GetObject(nR
);
590 if ( pTab
[nTab
]->HasScenarioRange( *pRange
) )
595 pTab
[nTab
]->SetActiveScenario(FALSE
);
596 if ( pTab
[nTab
]->GetScenarioFlags() & SC_SCENARIO_TWOWAY
)
597 pTab
[nTab
]->CopyScenarioFrom( pTab
[nDestTab
] );
602 pTab
[nSrcTab
]->SetActiveScenario(TRUE
); // da kommt's her...
603 if (!bNewScenario
) // Daten aus dem ausgewaehlten Szenario kopieren
605 BOOL bOldAutoCalc
= GetAutoCalc();
606 SetAutoCalc( FALSE
); // Mehrfachberechnungen vermeiden
607 pTab
[nSrcTab
]->CopyScenarioTo( pTab
[nDestTab
] );
609 SetAutoCalc( bOldAutoCalc
);
614 void ScDocument::MarkScenario( SCTAB nSrcTab
, SCTAB nDestTab
, ScMarkData
& rDestMark
,
615 BOOL bResetMark
, USHORT nNeededBits
) const
618 rDestMark
.ResetMark();
620 if (ValidTab(nSrcTab
) && pTab
[nSrcTab
])
621 pTab
[nSrcTab
]->MarkScenarioIn( rDestMark
, nNeededBits
);
623 rDestMark
.SetAreaTab( nDestTab
);
626 BOOL
ScDocument::HasScenarioRange( SCTAB nTab
, const ScRange
& rRange
) const
628 return ValidTab(nTab
) && pTab
[nTab
] && pTab
[nTab
]->HasScenarioRange( rRange
);
629 //if (ValidTab(nTab) && pTab[nTab])
630 // return pTab[nTab]->HasScenarioRange( rRange );
635 const ScRangeList
* ScDocument::GetScenarioRanges( SCTAB nTab
) const
637 if (ValidTab(nTab
) && pTab
[nTab
])
638 return pTab
[nTab
]->GetScenarioRanges();
643 BOOL
ScDocument::IsActiveScenario( SCTAB nTab
) const
645 return ValidTab(nTab
) && pTab
[nTab
] && pTab
[nTab
]->IsActiveScenario( );
646 //if (ValidTab(nTab) && pTab[nTab])
647 // return pTab[nTab]->IsActiveScenario();
652 void ScDocument::SetActiveScenario( SCTAB nTab
, BOOL bActive
)
654 if (ValidTab(nTab
) && pTab
[nTab
])
655 pTab
[nTab
]->SetActiveScenario( bActive
);
658 BOOL
ScDocument::TestCopyScenario( SCTAB nSrcTab
, SCTAB nDestTab
) const
660 if (ValidTab(nSrcTab
) && ValidTab(nDestTab
))
661 return pTab
[nSrcTab
]->TestCopyScenarioTo( pTab
[nDestTab
] );
663 DBG_ERROR("falsche Tabelle bei TestCopyScenario");
667 void ScDocument::AddUnoObject( SfxListener
& rObject
)
669 if (!pUnoBroadcaster
)
670 pUnoBroadcaster
= new SfxBroadcaster
;
672 rObject
.StartListening( *pUnoBroadcaster
);
675 void ScDocument::RemoveUnoObject( SfxListener
& rObject
)
679 rObject
.EndListening( *pUnoBroadcaster
);
681 if ( bInUnoBroadcast
)
683 // #107294# Broadcasts from ScDocument::BroadcastUno are the only way that
684 // uno object methods are called without holding a reference.
686 // If RemoveUnoObject is called from an object dtor in the finalizer thread
687 // while the main thread is calling BroadcastUno, the dtor thread must wait
688 // (or the object's Notify might try to access a deleted object).
689 // The SolarMutex can't be locked here because if a component is called from
690 // a VCL event, the main thread has the SolarMutex locked all the time.
692 // This check is done after calling EndListening, so a later BroadcastUno call
693 // won't touch this object.
695 vos::IMutex
& rSolarMutex
= Application::GetSolarMutex();
696 if ( rSolarMutex
.tryToAcquire() )
698 // BroadcastUno is always called with the SolarMutex locked, so if it
699 // can be acquired, this is within the same thread (should not happen)
700 DBG_ERRORFILE( "RemoveUnoObject called from BroadcastUno" );
701 rSolarMutex
.release();
705 // let the thread that called BroadcastUno continue
706 while ( bInUnoBroadcast
)
708 vos::OThread::yield();
715 DBG_ERROR("No Uno broadcaster");
719 void ScDocument::BroadcastUno( const SfxHint
&rHint
)
723 bInUnoBroadcast
= TRUE
;
724 pUnoBroadcaster
->Broadcast( rHint
);
725 bInUnoBroadcast
= FALSE
;
727 // During Broadcast notification, Uno objects can add to pUnoListenerCalls.
728 // The listener calls must be processed after completing the broadcast,
729 // because they can add or remove objects from pUnoBroadcaster.
731 if ( pUnoListenerCalls
&& rHint
.ISA( SfxSimpleHint
) &&
732 ((const SfxSimpleHint
&)rHint
).GetId() == SFX_HINT_DATACHANGED
&&
733 !bInUnoListenerCall
)
735 // Listener calls may lead to BroadcastUno calls again. The listener calls
736 // are not nested, instead the calls are collected in the list, and the
737 // outermost call executes them all.
739 ScChartLockGuard
aChartLockGuard(this);
740 bInUnoListenerCall
= TRUE
;
741 pUnoListenerCalls
->ExecuteAndClear();
742 bInUnoListenerCall
= FALSE
;
747 void ScDocument::AddUnoListenerCall( const uno::Reference
<util::XModifyListener
>& rListener
,
748 const lang::EventObject
& rEvent
)
750 DBG_ASSERT( bInUnoBroadcast
, "AddUnoListenerCall is supposed to be called from BroadcastUno only" );
752 if ( !pUnoListenerCalls
)
753 pUnoListenerCalls
= new ScUnoListenerCalls
;
754 pUnoListenerCalls
->Add( rListener
, rEvent
);
757 void ScDocument::BeginUnoRefUndo()
759 DBG_ASSERT( !pUnoRefUndoList
, "BeginUnoRefUndo twice" );
760 delete pUnoRefUndoList
;
762 pUnoRefUndoList
= new ScUnoRefList
;
765 ScUnoRefList
* ScDocument::EndUnoRefUndo()
767 ScUnoRefList
* pRet
= pUnoRefUndoList
;
768 pUnoRefUndoList
= NULL
;
769 return pRet
; // must be deleted by caller!
772 void ScDocument::AddUnoRefChange( sal_Int64 nId
, const ScRangeList
& rOldRanges
)
774 if ( pUnoRefUndoList
)
775 pUnoRefUndoList
->Add( nId
, rOldRanges
);
778 sal_Int64
ScDocument::GetNewUnoId()
780 return ++nUnoObjectId
;
783 void ScDocument::UpdateReference( UpdateRefMode eUpdateRefMode
,
784 SCCOL nCol1
, SCROW nRow1
, SCTAB nTab1
,
785 SCCOL nCol2
, SCROW nRow2
, SCTAB nTab2
,
786 SCsCOL nDx
, SCsROW nDy
, SCsTAB nDz
,
787 ScDocument
* pUndoDoc
, BOOL bIncludeDraw
)
789 PutInOrder( nCol1
, nCol2
);
790 PutInOrder( nRow1
, nRow2
);
791 PutInOrder( nTab1
, nTab2
);
792 if (VALIDTAB(nTab1
) && VALIDTAB(nTab2
))
794 BOOL bExpandRefsOld
= IsExpandRefs();
795 if ( eUpdateRefMode
== URM_INSDEL
&& (nDx
> 0 || nDy
> 0 || nDz
> 0) )
796 SetExpandRefs( SC_MOD()->GetInputOptions().GetExpandRefs() );
799 if ( eUpdateRefMode
== URM_COPY
)
806 ScRange
aRange( nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
807 xColNameRanges
->UpdateReference( eUpdateRefMode
, this, aRange
, nDx
, nDy
, nDz
);
808 xRowNameRanges
->UpdateReference( eUpdateRefMode
, this, aRange
, nDx
, nDy
, nDz
);
809 pDBCollection
->UpdateReference( eUpdateRefMode
, nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
, nDx
, nDy
, nDz
);
810 pRangeName
->UpdateReference( eUpdateRefMode
, aRange
, nDx
, nDy
, nDz
);
812 pDPCollection
->UpdateReference( eUpdateRefMode
, aRange
, nDx
, nDy
, nDz
);
813 UpdateChartRef( eUpdateRefMode
, nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
, nDx
, nDy
, nDz
);
814 UpdateRefAreaLinks( eUpdateRefMode
, aRange
, nDx
, nDy
, nDz
);
816 pCondFormList
->UpdateReference( eUpdateRefMode
, aRange
, nDx
, nDy
, nDz
);
817 if ( pValidationList
)
818 pValidationList
->UpdateReference( eUpdateRefMode
, aRange
, nDx
, nDy
, nDz
);
820 pDetOpList
->UpdateReference( this, eUpdateRefMode
, aRange
, nDx
, nDy
, nDz
);
821 if ( pUnoBroadcaster
)
822 pUnoBroadcaster
->Broadcast( ScUpdateRefHint(
823 eUpdateRefMode
, aRange
, nDx
, nDy
, nDz
) );
827 for ( ; i
<=iMax
; i
++)
829 pTab
[i
]->UpdateReference(
830 eUpdateRefMode
, nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
,
831 nDx
, nDy
, nDz
, pUndoDoc
, bIncludeDraw
);
841 theCol1
= aEmbedRange
.aStart
.Col();
842 theRow1
= aEmbedRange
.aStart
.Row();
843 theTab1
= aEmbedRange
.aStart
.Tab();
844 theCol2
= aEmbedRange
.aEnd
.Col();
845 theRow2
= aEmbedRange
.aEnd
.Row();
846 theTab2
= aEmbedRange
.aEnd
.Tab();
847 if ( ScRefUpdate::Update( this, eUpdateRefMode
, nCol1
,nRow1
,nTab1
, nCol2
,nRow2
,nTab2
,
848 nDx
,nDy
,nDz
, theCol1
,theRow1
,theTab1
, theCol2
,theRow2
,theTab2
) )
850 aEmbedRange
= ScRange( theCol1
,theRow1
,theTab1
, theCol2
,theRow2
,theTab2
);
853 SetExpandRefs( bExpandRefsOld
);
855 // #30428# after moving, no clipboard move ref-updates are possible
856 if ( eUpdateRefMode
!= URM_COPY
&& IsClipboardSource() )
858 ScDocument
* pClipDoc
= SC_MOD()->GetClipDoc();
860 pClipDoc
->GetClipParam().mbCutMode
= false;
865 void ScDocument::UpdateTranspose( const ScAddress
& rDestPos
, ScDocument
* pClipDoc
,
866 const ScMarkData
& rMark
, ScDocument
* pUndoDoc
)
868 DBG_ASSERT(pClipDoc
->bIsClip
, "UpdateTranspose: kein Clip");
871 ScClipParam
& rClipParam
= GetClipParam();
872 if (rClipParam
.maRanges
.Count())
873 aSource
= *rClipParam
.maRanges
.First();
874 ScAddress aDest
= rDestPos
;
877 for (SCTAB nDestTab
=0; nDestTab
<=MAXTAB
&& pTab
[nDestTab
]; nDestTab
++)
878 if (rMark
.GetTableSelect(nDestTab
))
880 while (!pClipDoc
->pTab
[nClipTab
]) nClipTab
= (nClipTab
+1) % (MAXTAB
+1);
881 aSource
.aStart
.SetTab( nClipTab
);
882 aSource
.aEnd
.SetTab( nClipTab
);
883 aDest
.SetTab( nDestTab
);
885 // wie UpdateReference
887 pRangeName
->UpdateTranspose( aSource
, aDest
); // vor den Zellen!
888 for (SCTAB i
=0; i
<=MAXTAB
; i
++)
890 pTab
[i
]->UpdateTranspose( aSource
, aDest
, pUndoDoc
);
892 nClipTab
= (nClipTab
+1) % (MAXTAB
+1);
896 void ScDocument::UpdateGrow( const ScRange
& rArea
, SCCOL nGrowX
, SCROW nGrowY
)
902 pRangeName
->UpdateGrow( rArea
, nGrowX
, nGrowY
);
904 for (SCTAB i
=0; i
<=MAXTAB
&& pTab
[i
]; i
++)
905 pTab
[i
]->UpdateGrow( rArea
, nGrowX
, nGrowY
);
908 void ScDocument::Fill(SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
, const ScMarkData
& rMark
,
909 ULONG nFillCount
, FillDir eFillDir
, FillCmd eFillCmd
, FillDateCmd eFillDateCmd
,
910 double nStepValue
, double nMaxValue
)
912 PutInOrder( nCol1
, nCol2
);
913 PutInOrder( nRow1
, nRow2
);
914 for (SCTAB i
=0; i
<= MAXTAB
; i
++)
916 if (rMark
.GetTableSelect(i
))
917 pTab
[i
]->Fill(nCol1
, nRow1
, nCol2
, nRow2
,
918 nFillCount
, eFillDir
, eFillCmd
, eFillDateCmd
,
919 nStepValue
, nMaxValue
);
922 String
ScDocument::GetAutoFillPreview( const ScRange
& rSource
, SCCOL nEndX
, SCROW nEndY
)
924 SCTAB nTab
= rSource
.aStart
.Tab();
926 return pTab
[nTab
]->GetAutoFillPreview( rSource
, nEndX
, nEndY
);
931 void ScDocument::AutoFormat( SCCOL nStartCol
, SCROW nStartRow
, SCCOL nEndCol
, SCROW nEndRow
,
932 USHORT nFormatNo
, const ScMarkData
& rMark
)
934 PutInOrder( nStartCol
, nEndCol
);
935 PutInOrder( nStartRow
, nEndRow
);
936 for (SCTAB i
=0; i
<= MAXTAB
; i
++)
938 if (rMark
.GetTableSelect(i
))
939 pTab
[i
]->AutoFormat( nStartCol
, nStartRow
, nEndCol
, nEndRow
, nFormatNo
);
942 void ScDocument::GetAutoFormatData(SCTAB nTab
, SCCOL nStartCol
, SCROW nStartRow
, SCCOL nEndCol
, SCROW nEndRow
,
943 ScAutoFormatData
& rData
)
949 PutInOrder(nStartCol
, nEndCol
);
950 PutInOrder(nStartRow
, nEndRow
);
951 pTab
[nTab
]->GetAutoFormatData(nStartCol
, nStartRow
, nEndCol
, nEndRow
, rData
);
957 void ScDocument::GetSearchAndReplaceStart( const SvxSearchItem
& rSearchItem
,
958 SCCOL
& rCol
, SCROW
& rRow
)
960 USHORT nCommand
= rSearchItem
.GetCommand();
961 BOOL bReplace
= ( nCommand
== SVX_SEARCHCMD_REPLACE
||
962 nCommand
== SVX_SEARCHCMD_REPLACE_ALL
);
963 if ( rSearchItem
.GetBackward() )
965 if ( rSearchItem
.GetRowDirection() )
967 if ( rSearchItem
.GetPattern() )
985 if ( rSearchItem
.GetPattern() )
1004 if ( rSearchItem
.GetRowDirection() )
1006 if ( rSearchItem
.GetPattern() )
1011 else if ( bReplace
)
1024 if ( rSearchItem
.GetPattern() )
1029 else if ( bReplace
)
1043 BOOL
ScDocument::SearchAndReplace(const SvxSearchItem
& rSearchItem
,
1044 SCCOL
& rCol
, SCROW
& rRow
, SCTAB
& rTab
,
1046 String
& rUndoStr
, ScDocument
* pUndoDoc
)
1048 //! getrennte Markierungen pro Tabelle verwalten !!!!!!!!!!!!!
1050 rMark
.MarkToMulti();
1052 BOOL bFound
= FALSE
;
1058 USHORT nCommand
= rSearchItem
.GetCommand();
1059 if ( nCommand
== SVX_SEARCHCMD_FIND_ALL
||
1060 nCommand
== SVX_SEARCHCMD_REPLACE_ALL
)
1062 for (nTab
= 0; nTab
<= MAXTAB
; nTab
++)
1065 if (rMark
.GetTableSelect(nTab
))
1069 bFound
|= pTab
[nTab
]->SearchAndReplace(
1070 rSearchItem
, nCol
, nRow
, rMark
, rUndoStr
, pUndoDoc
);
1074 // Markierung wird innen schon komplett gesetzt
1080 if (rSearchItem
.GetBackward())
1082 for (nTab
= rTab
; ((SCsTAB
)nTab
>= 0) && !bFound
; nTab
--)
1085 if (rMark
.GetTableSelect(nTab
))
1087 bFound
= pTab
[nTab
]->SearchAndReplace(
1088 rSearchItem
, nCol
, nRow
, rMark
, rUndoStr
, pUndoDoc
);
1096 ScDocument::GetSearchAndReplaceStart(
1097 rSearchItem
, nCol
, nRow
);
1103 for (nTab
= rTab
; (nTab
<= MAXTAB
) && !bFound
; nTab
++)
1106 if (rMark
.GetTableSelect(nTab
))
1108 bFound
= pTab
[nTab
]->SearchAndReplace(
1109 rSearchItem
, nCol
, nRow
, rMark
, rUndoStr
, pUndoDoc
);
1117 ScDocument::GetSearchAndReplaceStart(
1118 rSearchItem
, nCol
, nRow
);
1129 BOOL
ScDocument::UpdateOutlineCol( SCCOL nStartCol
, SCCOL nEndCol
, SCTAB nTab
, BOOL bShow
)
1131 if ( ValidTab(nTab
) && pTab
[nTab
] )
1132 return pTab
[nTab
]->UpdateOutlineCol( nStartCol
, nEndCol
, bShow
);
1134 DBG_ERROR("missing tab");
1138 BOOL
ScDocument::UpdateOutlineRow( SCROW nStartRow
, SCROW nEndRow
, SCTAB nTab
, BOOL bShow
)
1140 if ( ValidTab(nTab
) && pTab
[nTab
] )
1141 return pTab
[nTab
]->UpdateOutlineRow( nStartRow
, nEndRow
, bShow
);
1143 DBG_ERROR("missing tab");
1147 void ScDocument::Sort(SCTAB nTab
, const ScSortParam
& rSortParam
, BOOL bKeepQuery
)
1149 if ( ValidTab(nTab
) && pTab
[nTab
] )
1151 BOOL bOldDisableIdle
= IsIdleDisabled();
1152 DisableIdle( TRUE
);
1153 pTab
[nTab
]->Sort(rSortParam
, bKeepQuery
);
1154 DisableIdle( bOldDisableIdle
);
1158 SCSIZE
ScDocument::Query(SCTAB nTab
, const ScQueryParam
& rQueryParam
, BOOL bKeepSub
)
1160 if ( ValidTab(nTab
) && pTab
[nTab
] )
1161 return pTab
[nTab
]->Query((ScQueryParam
&)rQueryParam
, bKeepSub
);
1163 DBG_ERROR("missing tab");
1168 BOOL
ScDocument::ValidQuery( SCROW nRow
, SCTAB nTab
, const ScQueryParam
& rQueryParam
, BOOL
* pSpecial
)
1170 if ( ValidTab(nTab
) && pTab
[nTab
] )
1171 return pTab
[nTab
]->ValidQuery( nRow
, rQueryParam
, pSpecial
);
1173 DBG_ERROR("missing tab");
1178 void ScDocument::GetUpperCellString(SCCOL nCol
, SCROW nRow
, SCTAB nTab
, String
& rStr
)
1180 if ( ValidTab(nTab
) && pTab
[nTab
] )
1181 pTab
[nTab
]->GetUpperCellString( nCol
, nRow
, rStr
);
1186 BOOL
ScDocument::CreateQueryParam(SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
, SCTAB nTab
, ScQueryParam
& rQueryParam
)
1188 if ( ValidTab(nTab
) && pTab
[nTab
] )
1189 return pTab
[nTab
]->CreateQueryParam(nCol1
, nRow1
, nCol2
, nRow2
, rQueryParam
);
1191 DBG_ERROR("missing tab");
1195 BOOL
ScDocument::HasAutoFilter( SCCOL nCurCol
, SCROW nCurRow
, SCTAB nCurTab
)
1197 ScDBData
* pDBData
= GetDBAtCursor( nCurCol
, nCurRow
, nCurTab
);
1198 BOOL bHasAutoFilter
= ( pDBData
!= NULL
);
1202 if ( pDBData
->HasHeader() )
1208 ScQueryParam aParam
;
1209 pDBData
->GetQueryParam( aParam
);
1210 nRow
= aParam
.nRow1
;
1212 for ( nCol
=aParam
.nCol1
; nCol
<=aParam
.nCol2
&& bHasAutoFilter
; nCol
++ )
1214 nFlag
= ((ScMergeFlagAttr
*)
1215 GetAttr( nCol
, nRow
, nCurTab
, ATTR_MERGE_FLAG
))->
1218 if ( (nFlag
& SC_MF_AUTO
) == 0 )
1219 bHasAutoFilter
= FALSE
;
1223 bHasAutoFilter
= FALSE
;
1226 return bHasAutoFilter
;
1229 BOOL
ScDocument::HasColHeader( SCCOL nStartCol
, SCROW nStartRow
, SCCOL nEndCol
, SCROW nEndRow
,
1232 return VALIDTAB(nTab
) && pTab
[nTab
] && pTab
[nTab
]->HasColHeader( nStartCol
, nStartRow
, nEndCol
, nEndRow
);
1233 //if (VALIDTAB(nTab))
1235 // return pTab[nTab]->HasColHeader( nStartCol, nStartRow, nEndCol, nEndRow );
1240 BOOL
ScDocument::HasRowHeader( SCCOL nStartCol
, SCROW nStartRow
, SCCOL nEndCol
, SCROW nEndRow
,
1243 return VALIDTAB(nTab
) && pTab
[nTab
] && pTab
[nTab
]->HasRowHeader( nStartCol
, nStartRow
, nEndCol
, nEndRow
);
1244 //if (VALIDTAB(nTab))
1246 // return pTab[nTab]->HasRowHeader( nStartCol, nStartRow, nEndCol, nEndRow );
1251 void ScDocument::UpdateDynamicEndRow(ScDBData
& rDBData
) const
1256 rDBData
.GetArea(nTab
, nCol1
, nRow1
, nCol2
, nRow2
);
1257 SCCOL nCol1a
= nCol1
, nCol2a
= nCol2
;
1258 SCROW nRow1a
= nRow1
, nRow2a
= nRow2
;
1259 GetDataArea(nTab
, nCol1a
, nRow1a
, nCol2a
, nRow2a
, false);
1260 rDBData
.SetDynamicEndRow(nRow2a
);
1264 // GetFilterEntries - Eintraege fuer AutoFilter-Listbox
1267 BOOL
ScDocument::GetFilterEntries(
1268 SCCOL nCol
, SCROW nRow
, SCTAB nTab
, bool bFilter
, TypedScStrCollection
& rStrings
, bool& rHasDates
)
1270 if ( ValidTab(nTab
) && pTab
[nTab
] && pDBCollection
)
1272 ScDBData
* pDBData
= pDBCollection
->GetDBAtCursor(nCol
, nRow
, nTab
, FALSE
); //!??
1275 UpdateDynamicEndRow(*pDBData
);
1281 pDBData
->GetArea( nAreaTab
, nStartCol
, nStartRow
, nEndCol
, nEndRow
);
1282 if (pDBData
->HasHeader())
1285 ScQueryParam aParam
;
1286 pDBData
->GetQueryParam( aParam
);
1287 nEndRow
= aParam
.nDynamicEndRow
;
1288 rStrings
.SetCaseSensitive( aParam
.bCaseSens
);
1290 // return all filter entries, if a filter condition is connected with a boolean OR
1293 SCSIZE nEntryCount
= aParam
.GetEntryCount();
1294 for ( SCSIZE i
= 0; i
< nEntryCount
&& aParam
.GetEntry(i
).bDoQuery
; ++i
)
1296 ScQueryEntry
& rEntry
= aParam
.GetEntry(i
);
1297 if ( rEntry
.eConnect
!= SC_AND
)
1307 pTab
[nTab
]->GetFilteredFilterEntries( nCol
, nStartRow
, nEndRow
, aParam
, rStrings
, rHasDates
);
1311 pTab
[nTab
]->GetFilterEntries( nCol
, nStartRow
, nEndRow
, rStrings
, rHasDates
);
1322 // GetFilterEntriesArea - Eintraege fuer Filter-Dialog
1325 BOOL
ScDocument::GetFilterEntriesArea( SCCOL nCol
, SCROW nStartRow
, SCROW nEndRow
,
1326 SCTAB nTab
, TypedScStrCollection
& rStrings
, bool& rHasDates
)
1328 if ( ValidTab(nTab
) && pTab
[nTab
] )
1330 pTab
[nTab
]->GetFilterEntries( nCol
, nStartRow
, nEndRow
, rStrings
, rHasDates
);
1338 // GetDataEntries - Eintraege fuer Auswahlliste-Listbox (keine Zahlen / Formeln)
1341 BOOL
ScDocument::GetDataEntries( SCCOL nCol
, SCROW nRow
, SCTAB nTab
,
1342 TypedScStrCollection
& rStrings
, BOOL bLimit
)
1346 /* Try to generate the list from list validation. This part is skipped,
1347 if bLimit==TRUE, because in that case this function is called to get
1348 cell values for auto completion on input. */
1349 sal_uInt32 nValidation
= static_cast< const SfxUInt32Item
* >( GetAttr( nCol
, nRow
, nTab
, ATTR_VALIDDATA
) )->GetValue();
1352 const ScValidationData
* pData
= GetValidationEntry( nValidation
);
1353 if( pData
&& pData
->FillSelectionList( rStrings
, ScAddress( nCol
, nRow
, nTab
) ) )
1358 return ValidTab(nTab
) && pTab
[nTab
] && pTab
[nTab
]->GetDataEntries( nCol
, nRow
, rStrings
, bLimit
);
1359 //if (ValidTab(nTab) && pTab[nTab])
1360 // return pTab[nTab]->GetDataEntries( nCol, nRow, rStrings, bLimit );
1366 // GetFormulaEntries - Eintraege fuer Formel-AutoEingabe
1369 // Funktionen werden als 1 schon vom InputHandler eingefuegt
1370 #define SC_STRTYPE_NAMES 2
1371 #define SC_STRTYPE_DBNAMES 3
1372 #define SC_STRTYPE_HEADERS 4
1374 BOOL
ScDocument::GetFormulaEntries( TypedScStrCollection
& rStrings
)
1384 USHORT nRangeCount
= pRangeName
->GetCount();
1385 for ( i
=0; i
<nRangeCount
; i
++ )
1387 ScRangeData
* pData
= (*pRangeName
)[i
];
1390 TypedStrData
* pNew
= new TypedStrData( pData
->GetName(), 0.0, SC_STRTYPE_NAMES
);
1391 if ( !rStrings
.Insert(pNew
) )
1398 // Datenbank-Bereiche
1401 if ( pDBCollection
)
1403 USHORT nDBCount
= pDBCollection
->GetCount();
1404 for ( i
=0; i
<nDBCount
; i
++ )
1406 ScDBData
* pData
= (*pDBCollection
)[i
];
1409 TypedStrData
* pNew
= new TypedStrData( pData
->GetName(), 0.0, SC_STRTYPE_DBNAMES
);
1410 if ( !rStrings
.Insert(pNew
) )
1417 // Inhalte von Beschriftungsbereichen
1420 ScRangePairList
* pLists
[2];
1421 pLists
[0] = GetColNameRanges();
1422 pLists
[1] = GetRowNameRanges();
1423 for (USHORT nListNo
=0; nListNo
<2; nListNo
++)
1425 ScRangePairList
* pList
= pLists
[nListNo
];
1427 for ( ScRangePair
* pPair
= pList
->First(); pPair
; pPair
= pList
->Next() )
1429 ScRange aRange
= pPair
->GetRange(0);
1430 ScCellIterator
aIter( this, aRange
);
1431 for ( ScBaseCell
* pCell
= aIter
.GetFirst(); pCell
; pCell
= aIter
.GetNext() )
1432 if ( pCell
->HasStringData() )
1434 String aStr
= pCell
->GetStringData();
1435 TypedStrData
* pNew
= new TypedStrData( aStr
, 0.0, SC_STRTYPE_HEADERS
);
1436 if ( !rStrings
.Insert(pNew
) )
1446 BOOL
ScDocument::IsEmbedded() const
1451 void ScDocument::GetEmbedded( ScRange
& rRange
) const
1453 rRange
= aEmbedRange
;
1456 Rectangle
ScDocument::GetEmbeddedRect() const // 1/100 mm
1459 ScTable
* pTable
= pTab
[aEmbedRange
.aStart
.Tab()];
1462 DBG_ERROR("GetEmbeddedRect ohne Tabelle");
1468 for (i
=0; i
<aEmbedRange
.aStart
.Col(); i
++)
1469 aRect
.Left() += pTable
->GetColWidth(i
);
1470 aRect
.Top() += pTable
->GetRowHeight( 0, aEmbedRange
.aStart
.Row() - 1);
1471 aRect
.Right() = aRect
.Left();
1472 for (i
=aEmbedRange
.aStart
.Col(); i
<=aEmbedRange
.aEnd
.Col(); i
++)
1473 aRect
.Right() += pTable
->GetColWidth(i
);
1474 aRect
.Bottom() = aRect
.Top();
1475 aRect
.Bottom() += pTable
->GetRowHeight( aEmbedRange
.aStart
.Row(), aEmbedRange
.aEnd
.Row());
1477 aRect
.Left() = (long) ( aRect
.Left() * HMM_PER_TWIPS
);
1478 aRect
.Right() = (long) ( aRect
.Right() * HMM_PER_TWIPS
);
1479 aRect
.Top() = (long) ( aRect
.Top() * HMM_PER_TWIPS
);
1480 aRect
.Bottom() = (long) ( aRect
.Bottom() * HMM_PER_TWIPS
);
1485 void ScDocument::SetEmbedded( const ScRange
& rRange
)
1488 aEmbedRange
= rRange
;
1491 void ScDocument::ResetEmbedded()
1493 bIsEmbedded
= FALSE
;
1494 aEmbedRange
= ScRange();
1497 ScRange
ScDocument::GetRange( SCTAB nTab
, const Rectangle
& rMMRect
)
1499 ScTable
* pTable
= pTab
[nTab
];
1502 DBG_ERROR("GetRange ohne Tabelle");
1506 Rectangle aPosRect
= rMMRect
;
1507 if ( IsNegativePage( nTab
) )
1508 ScDrawLayer::MirrorRectRTL( aPosRect
); // always with positive (LTR) values
1516 nTwips
= (long) (aPosRect
.Left() / HMM_PER_TWIPS
);
1522 nAdd
= (long) pTable
->GetColWidth(nX1
);
1523 if (nSize
+nAdd
<= nTwips
+1 && nX1
<MAXCOL
)
1532 nTwips
= (long) (aPosRect
.Right() / HMM_PER_TWIPS
);
1538 nAdd
= (long) pTable
->GetColWidth(nX2
);
1539 if (nSize
+nAdd
< nTwips
&& nX2
<MAXCOL
)
1550 nTwips
= (long) (aPosRect
.Top() / HMM_PER_TWIPS
);
1554 for (SCROW i
= nY1
; i
<= MAXROW
&& !bEnd
; ++i
)
1556 if (pTable
->RowHidden(i
))
1560 nAdd
= static_cast<long>(pTable
->GetRowHeight(i
));
1561 if (nSize
+nAdd
<= nTwips
+1 && nY1
<MAXROW
)
1570 nY1
= MAXROW
; // all hidden down to the bottom
1572 nTwips
= (long) (aPosRect
.Bottom() / HMM_PER_TWIPS
);
1576 for (SCROW i
= nY2
; i
<= MAXROW
&& !bEnd
; ++i
)
1579 nAdd
= static_cast<long>(pTable
->GetRowHeight(i
));
1580 if (nSize
+nAdd
< nTwips
&& nY2
<MAXROW
)
1589 nY2
= MAXROW
; // all hidden down to the bottom
1591 return ScRange( nX1
,nY1
,nTab
, nX2
,nY2
,nTab
);
1594 void ScDocument::SetEmbedded( const Rectangle
& rRect
) // aus VisArea (1/100 mm)
1597 aEmbedRange
= GetRange( nVisibleTab
, rRect
);
1600 // VisArea auf Zellgrenzen anpassen
1602 void lcl_SnapHor( ScTable
* pTable
, long& rVal
, SCCOL
& rStartCol
)
1605 long nTwips
= (long) (rVal
/ HMM_PER_TWIPS
);
1607 while ( nCol
<MAXCOL
)
1609 long nAdd
= pTable
->GetColWidth(nCol
);
1610 if ( nSnap
+ nAdd
/2 < nTwips
|| nCol
< rStartCol
)
1618 rVal
= (long) ( nSnap
* HMM_PER_TWIPS
);
1622 void lcl_SnapVer( ScTable
* pTable
, long& rVal
, SCROW
& rStartRow
)
1625 long nTwips
= (long) (rVal
/ HMM_PER_TWIPS
);
1628 bool bFound
= false;
1629 for (SCROW i
= nRow
; i
<= MAXROW
; ++i
)
1632 if (pTable
->RowHidden(i
, NULL
, &nLastRow
))
1639 long nAdd
= pTable
->GetRowHeight(i
);
1640 if ( nSnap
+ nAdd
/2 < nTwips
|| nRow
< rStartRow
)
1652 nRow
= MAXROW
; // all hidden down to the bottom
1654 rVal
= (long) ( nSnap
* HMM_PER_TWIPS
);
1658 void ScDocument::SnapVisArea( Rectangle
& rRect
) const
1660 ScTable
* pTable
= pTab
[nVisibleTab
];
1663 DBG_ERROR("SetEmbedded ohne Tabelle");
1667 BOOL bNegativePage
= IsNegativePage( nVisibleTab
);
1668 if ( bNegativePage
)
1669 ScDrawLayer::MirrorRectRTL( rRect
); // calculate with positive (LTR) values
1672 lcl_SnapHor( pTable
, rRect
.Left(), nCol
);
1673 ++nCol
; // mindestens eine Spalte
1674 lcl_SnapHor( pTable
, rRect
.Right(), nCol
);
1677 lcl_SnapVer( pTable
, rRect
.Top(), nRow
);
1678 ++nRow
; // mindestens eine Zeile
1679 lcl_SnapVer( pTable
, rRect
.Bottom(), nRow
);
1681 if ( bNegativePage
)
1682 ScDrawLayer::MirrorRectRTL( rRect
); // back to real rectangle
1685 ScDocProtection
* ScDocument::GetDocProtection() const
1687 return pDocProtection
.get();
1690 void ScDocument::SetDocProtection(const ScDocProtection
* pProtect
)
1693 pDocProtection
.reset(new ScDocProtection(*pProtect
));
1695 pDocProtection
.reset(NULL
);
1698 BOOL
ScDocument::IsDocProtected() const
1700 return pDocProtection
.get() && pDocProtection
->isProtected();
1703 BOOL
ScDocument::IsDocEditable() const
1705 // import into read-only document is possible
1706 return !IsDocProtected() && ( bImportingXML
|| mbChangeReadOnlyEnabled
|| !pShell
|| !pShell
->IsReadOnly() );
1709 BOOL
ScDocument::IsTabProtected( SCTAB nTab
) const
1711 if (VALIDTAB(nTab
) && pTab
[nTab
])
1712 return pTab
[nTab
]->IsProtected();
1714 DBG_ERROR("Falsche Tabellennummer");
1718 ScTableProtection
* ScDocument::GetTabProtection( SCTAB nTab
) const
1720 if (VALIDTAB(nTab
) && pTab
[nTab
])
1721 return pTab
[nTab
]->GetProtection();
1726 void ScDocument::SetTabProtection(SCTAB nTab
, const ScTableProtection
* pProtect
)
1728 if (!ValidTab(nTab
))
1731 pTab
[nTab
]->SetProtection(pProtect
);
1734 void ScDocument::CopyTabProtection(SCTAB nTabSrc
, SCTAB nTabDest
)
1736 if (!ValidTab(nTabSrc
) || !ValidTab(nTabDest
))
1739 pTab
[nTabDest
]->SetProtection( pTab
[nTabSrc
]->GetProtection() );
1742 const ScDocOptions
& ScDocument::GetDocOptions() const
1744 DBG_ASSERT( pDocOptions
, "No DocOptions! :-(" );
1745 return *pDocOptions
;
1748 void ScDocument::SetDocOptions( const ScDocOptions
& rOpt
)
1750 DBG_ASSERT( pDocOptions
, "No DocOptions! :-(" );
1751 *pDocOptions
= rOpt
;
1753 xPoolHelper
->SetFormTableOpt(rOpt
);
1755 SetGrammar( rOpt
.GetFormulaSyntax() );
1757 // Update the separators.
1758 ScCompiler::UpdateSeparatorsNative(
1759 rOpt
.GetFormulaSepArg(), rOpt
.GetFormulaSepArrayCol(), rOpt
.GetFormulaSepArrayRow());
1762 const ScViewOptions
& ScDocument::GetViewOptions() const
1764 DBG_ASSERT( pViewOptions
, "No ViewOptions! :-(" );
1765 return *pViewOptions
;
1768 void ScDocument::SetViewOptions( const ScViewOptions
& rOpt
)
1770 DBG_ASSERT( pViewOptions
, "No ViewOptions! :-(" );
1771 *pViewOptions
= rOpt
;
1774 void ScDocument::GetLanguage( LanguageType
& rLatin
, LanguageType
& rCjk
, LanguageType
& rCtl
) const
1777 rCjk
= eCjkLanguage
;
1778 rCtl
= eCtlLanguage
;
1781 void ScDocument::SetLanguage( LanguageType eLatin
, LanguageType eCjk
, LanguageType eCtl
)
1784 eCjkLanguage
= eCjk
;
1785 eCtlLanguage
= eCtl
;
1786 if ( xPoolHelper
.isValid() )
1788 ScDocumentPool
* pPool
= xPoolHelper
->GetDocPool();
1789 pPool
->SetPoolDefaultItem( SvxLanguageItem( eLanguage
, ATTR_FONT_LANGUAGE
) );
1790 pPool
->SetPoolDefaultItem( SvxLanguageItem( eCjkLanguage
, ATTR_CJK_FONT_LANGUAGE
) );
1791 pPool
->SetPoolDefaultItem( SvxLanguageItem( eCtlLanguage
, ATTR_CTL_FONT_LANGUAGE
) );
1794 UpdateDrawLanguages(); // set edit engine defaults in drawing layer pool
1797 void ScDocument::SetDrawDefaults()
1799 bSetDrawDefaults
= TRUE
;
1800 UpdateDrawDefaults();
1803 Rectangle
ScDocument::GetMMRect( SCCOL nStartCol
, SCROW nStartRow
,
1804 SCCOL nEndCol
, SCROW nEndRow
, SCTAB nTab
)
1806 if (!ValidTab(nTab
) || !pTab
[nTab
])
1808 DBG_ERROR("GetMMRect: falsche Tabelle");
1809 return Rectangle(0,0,0,0);
1815 for (i
=0; i
<nStartCol
; i
++)
1816 aRect
.Left() += GetColWidth(i
,nTab
);
1817 aRect
.Top() += FastGetRowHeight( 0, nStartRow
-1, nTab
);
1819 aRect
.Right() = aRect
.Left();
1820 aRect
.Bottom() = aRect
.Top();
1822 for (i
=nStartCol
; i
<=nEndCol
; i
++)
1823 aRect
.Right() += GetColWidth(i
,nTab
);
1824 aRect
.Bottom() += FastGetRowHeight( nStartRow
, nEndRow
, nTab
);
1826 aRect
.Left() = (long)(aRect
.Left() * HMM_PER_TWIPS
);
1827 aRect
.Right() = (long)(aRect
.Right() * HMM_PER_TWIPS
);
1828 aRect
.Top() = (long)(aRect
.Top() * HMM_PER_TWIPS
);
1829 aRect
.Bottom() = (long)(aRect
.Bottom() * HMM_PER_TWIPS
);
1831 if ( IsNegativePage( nTab
) )
1832 ScDrawLayer::MirrorRectRTL( aRect
);
1837 void ScDocument::SetExtDocOptions( ScExtDocOptions
* pNewOptions
)
1839 delete pExtDocOptions
;
1840 pExtDocOptions
= pNewOptions
;
1843 void ScDocument::DoMergeContents( SCTAB nTab
, SCCOL nStartCol
, SCROW nStartRow
,
1844 SCCOL nEndCol
, SCROW nEndRow
)
1851 for (nRow
=nStartRow
; nRow
<=nEndRow
; nRow
++)
1852 for (nCol
=nStartCol
; nCol
<=nEndCol
; nCol
++)
1854 GetString(nCol
,nRow
,nTab
,aCellStr
);
1861 if (nCol
!= nStartCol
|| nRow
!= nStartRow
)
1862 SetString(nCol
,nRow
,nTab
,aEmpty
);
1865 SetString(nStartCol
,nStartRow
,nTab
,aTotal
);
1868 void ScDocument::DoMerge( SCTAB nTab
, SCCOL nStartCol
, SCROW nStartRow
,
1869 SCCOL nEndCol
, SCROW nEndRow
, bool bDeleteCaptions
)
1871 ScMergeAttr
aAttr( nEndCol
-nStartCol
+1, nEndRow
-nStartRow
+1 );
1872 ApplyAttr( nStartCol
, nStartRow
, nTab
, aAttr
);
1874 if ( nEndCol
> nStartCol
)
1875 ApplyFlagsTab( nStartCol
+1, nStartRow
, nEndCol
, nStartRow
, nTab
, SC_MF_HOR
);
1876 if ( nEndRow
> nStartRow
)
1877 ApplyFlagsTab( nStartCol
, nStartRow
+1, nStartCol
, nEndRow
, nTab
, SC_MF_VER
);
1878 if ( nEndCol
> nStartCol
&& nEndRow
> nStartRow
)
1879 ApplyFlagsTab( nStartCol
+1, nStartRow
+1, nEndCol
, nEndRow
, nTab
, SC_MF_HOR
| SC_MF_VER
);
1881 // remove all covered notes (removed captions are collected by drawing undo if active)
1882 USHORT nDelFlag
= IDF_NOTE
| (bDeleteCaptions
? 0 : IDF_NOCAPTIONS
);
1883 if( nStartCol
< nEndCol
)
1884 DeleteAreaTab( nStartCol
+ 1, nStartRow
, nEndCol
, nStartRow
, nTab
, nDelFlag
);
1885 if( nStartRow
< nEndRow
)
1886 DeleteAreaTab( nStartCol
, nStartRow
+ 1, nEndCol
, nEndRow
, nTab
, nDelFlag
);
1889 void ScDocument::RemoveMerge( SCCOL nCol
, SCROW nRow
, SCTAB nTab
)
1891 const ScMergeAttr
* pAttr
= (const ScMergeAttr
*)
1892 GetAttr( nCol
, nRow
, nTab
, ATTR_MERGE
);
1894 if ( pAttr
->GetColMerge() <= 1 && pAttr
->GetRowMerge() <= 1 )
1897 SCCOL nEndCol
= nCol
+ pAttr
->GetColMerge() - 1;
1898 SCROW nEndRow
= nRow
+ pAttr
->GetRowMerge() - 1;
1900 RemoveFlagsTab( nCol
, nRow
, nEndCol
, nEndRow
, nTab
, SC_MF_HOR
| SC_MF_VER
);
1902 const ScMergeAttr
* pDefAttr
= (const ScMergeAttr
*)
1903 &xPoolHelper
->GetDocPool()->GetDefaultItem( ATTR_MERGE
);
1904 ApplyAttr( nCol
, nRow
, nTab
, *pDefAttr
);
1907 void ScDocument::ExtendPrintArea( OutputDevice
* pDev
, SCTAB nTab
,
1908 SCCOL nStartCol
, SCROW nStartRow
, SCCOL
& rEndCol
, SCROW nEndRow
)
1910 if ( ValidTab(nTab
) && pTab
[nTab
] )
1911 pTab
[nTab
]->ExtendPrintArea( pDev
, nStartCol
, nStartRow
, rEndCol
, nEndRow
);
1914 void ScDocument::IncSizeRecalcLevel( SCTAB nTab
)
1916 if ( ValidTab(nTab
) && pTab
[nTab
] )
1917 pTab
[nTab
]->IncRecalcLevel();
1920 void ScDocument::DecSizeRecalcLevel( SCTAB nTab
)
1922 if ( ValidTab(nTab
) && pTab
[nTab
] )
1923 pTab
[nTab
]->DecRecalcLevel();