1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <document.hxx>
11 #include <clipcontext.hxx>
12 #include <formulacell.hxx>
13 #include <clipparam.hxx>
15 #include <tokenarray.hxx>
16 #include <editutil.hxx>
17 #include <listenercontext.hxx>
18 #include <tokenstringcontext.hxx>
19 #include <poolhelp.hxx>
20 #include <bcaslot.hxx>
21 #include <cellvalues.hxx>
22 #include <docpool.hxx>
24 #include "dociter.hxx"
25 #include "patattr.hxx"
26 #include <svl/whiter.hxx>
27 #include <editeng/colritem.hxx>
28 #include "scitems.hxx"
30 // Add totally brand-new methods to this source file.
32 bool ScDocument::IsMerged( const ScAddress
& rPos
) const
34 const ScTable
* pTab
= FetchTable(rPos
.Tab());
38 return pTab
->IsMerged(rPos
.Col(), rPos
.Row());
41 void ScDocument::DeleteBeforeCopyFromClip(
42 sc::CopyFromClipContext
& rCxt
, const ScMarkData
& rMark
, sc::ColumnSpanSet
& rBroadcastSpans
)
45 const TableContainer
& rClipTabs
= rCxt
.getClipDoc()->maTabs
;
46 SCTAB nClipTabCount
= rClipTabs
.size();
48 for (SCTAB nTab
= rCxt
.getTabStart(); nTab
<= rCxt
.getTabEnd(); ++nTab
)
50 ScTable
* pTab
= FetchTable(nTab
);
54 if (!rMark
.GetTableSelect(nTab
))
57 while (!rClipTabs
[nClipTab
])
58 nClipTab
= (nClipTab
+1) % nClipTabCount
;
60 pTab
->DeleteBeforeCopyFromClip(rCxt
, *rClipTabs
[nClipTab
], rBroadcastSpans
);
62 nClipTab
= (nClipTab
+1) % nClipTabCount
;
66 bool ScDocument::CopyOneCellFromClip(
67 sc::CopyFromClipContext
& rCxt
, SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
)
69 ScDocument
* pClipDoc
= rCxt
.getClipDoc();
70 if (pClipDoc
->GetClipParam().mbCutMode
)
71 // We don't handle cut and paste or moving of cells here.
74 ScRange aClipRange
= pClipDoc
->GetClipParam().getWholeRange();
75 if (aClipRange
.aStart
.Row() != aClipRange
.aEnd
.Row())
76 // The source is not really a single row. Bail out.
79 SCCOL nSrcColSize
= aClipRange
.aEnd
.Col() - aClipRange
.aStart
.Col() + 1;
80 SCCOL nDestColSize
= nCol2
- nCol1
+ 1;
81 if (nDestColSize
< nSrcColSize
)
84 ScAddress aSrcPos
= aClipRange
.aStart
;
86 for (SCCOL nCol
= aClipRange
.aStart
.Col(); nCol
<= aClipRange
.aEnd
.Col(); ++nCol
)
88 ScAddress aTestPos
= aSrcPos
;
89 aTestPos
.SetCol(nCol
);
90 if (pClipDoc
->IsMerged(aTestPos
))
91 // We don't handle merged source cell for this.
95 ScTable
* pSrcTab
= pClipDoc
->FetchTable(aSrcPos
.Tab());
99 rCxt
.setSingleCellColumnSize(nSrcColSize
);
101 for (SCCOL nColOffset
= 0; nColOffset
< nSrcColSize
; ++nColOffset
, aSrcPos
.IncCol())
103 const ScPatternAttr
* pAttr
= pClipDoc
->GetPattern(aSrcPos
);
104 rCxt
.setSingleCellPattern(nColOffset
, pAttr
);
106 if ((rCxt
.getInsertFlag() & (IDF_NOTE
| IDF_ADDNOTES
)) != IDF_NONE
)
107 rCxt
.setSingleCellNote(nColOffset
, pClipDoc
->GetNote(aSrcPos
));
109 ScColumn
& rSrcCol
= pSrcTab
->aCol
[aSrcPos
.Col()];
110 // Determine the script type of the copied single cell.
111 rSrcCol
.UpdateScriptTypes(aSrcPos
.Row(), aSrcPos
.Row());
112 rCxt
.setSingleCell(aSrcPos
, rSrcCol
);
115 // All good. Proceed with the pasting.
117 SCTAB nTabEnd
= rCxt
.getTabEnd();
118 for (SCTAB i
= rCxt
.getTabStart(); i
<= nTabEnd
&& i
< static_cast<SCTAB
>(maTabs
.size()); ++i
)
120 maTabs
[i
]->CopyOneCellFromClip(rCxt
, nCol1
, nRow1
, nCol2
, nRow2
);
121 if (rCxt
.getInsertFlag() & IDF_ATTRIB
)
122 for (SCROW nRow
= nRow1
; nRow
<= nRow2
; ++nRow
)
124 maTabs
[i
]->CopyConditionalFormat(nCol1
, nRow
, nCol2
, nRow
, nCol1
- aClipRange
.aStart
.Col(),
125 nRow
- aClipRange
.aStart
.Row(), pSrcTab
);
132 void ScDocument::SetValues( const ScAddress
& rPos
, const std::vector
<double>& rVals
)
134 ScTable
* pTab
= FetchTable(rPos
.Tab());
138 pTab
->SetValues(rPos
.Col(), rPos
.Row(), rVals
);
141 void ScDocument::TransferCellValuesTo( const ScAddress
& rTopPos
, size_t nLen
, sc::CellValues
& rDest
)
143 ScTable
* pTab
= FetchTable(rTopPos
.Tab());
147 pTab
->TransferCellValuesTo(rTopPos
.Col(), rTopPos
.Row(), nLen
, rDest
);
150 void ScDocument::CopyCellValuesFrom( const ScAddress
& rTopPos
, const sc::CellValues
& rSrc
)
152 ScTable
* pTab
= FetchTable(rTopPos
.Tab());
156 pTab
->CopyCellValuesFrom(rTopPos
.Col(), rTopPos
.Row(), rSrc
);
159 std::set
<Color
> ScDocument::GetDocColors()
161 std::set
<Color
> aDocColors
;
162 ScDocumentPool
*pPool
= GetPool();
163 const sal_uInt16 pAttribs
[] = {ATTR_BACKGROUND
, ATTR_FONT_COLOR
};
164 for (size_t i
=0; i
<SAL_N_ELEMENTS( pAttribs
); i
++)
166 const sal_uInt16 nAttrib
= pAttribs
[i
];
167 const sal_uInt32 nCount
= pPool
->GetItemCount2(nAttrib
);
168 for (sal_uInt32 j
=0; j
<nCount
; j
++)
170 const SvxColorItem
*pItem
= static_cast<const SvxColorItem
*>(pPool
->GetItem2(nAttrib
, j
));
173 Color
aColor( pItem
->GetValue() );
174 if (COL_AUTO
!= aColor
.GetColor())
175 aDocColors
.insert(aColor
);
181 void ScDocument::SetCalcConfig( const ScCalcConfig
& rConfig
)
183 maCalcConfig
= rConfig
;
186 void ScDocument::ConvertFormulaToValue( const ScRange
& rRange
, sc::TableValues
* pUndo
)
188 sc::EndListeningContext
aCxt(*this);
190 for (SCTAB nTab
= rRange
.aStart
.Tab(); nTab
<= rRange
.aEnd
.Tab(); ++nTab
)
192 ScTable
* pTab
= FetchTable(nTab
);
196 pTab
->ConvertFormulaToValue(
197 aCxt
, rRange
.aStart
.Col(), rRange
.aStart
.Row(), rRange
.aEnd
.Col(), rRange
.aEnd
.Row(),
201 aCxt
.purgeEmptyBroadcasters();
204 void ScDocument::SwapNonEmpty( sc::TableValues
& rValues
)
206 const ScRange
& rRange
= rValues
.getRange();
207 if (!rRange
.IsValid())
210 boost::shared_ptr
<sc::ColumnBlockPositionSet
> pPosSet(new sc::ColumnBlockPositionSet(*this));
211 sc::StartListeningContext
aStartCxt(*this, pPosSet
);
212 sc::EndListeningContext
aEndCxt(*this, pPosSet
);
214 for (SCTAB nTab
= rRange
.aStart
.Tab(); nTab
<= rRange
.aEnd
.Tab(); ++nTab
)
216 ScTable
* pTab
= FetchTable(nTab
);
220 pTab
->SwapNonEmpty(rValues
, aStartCxt
, aEndCxt
);
223 aEndCxt
.purgeEmptyBroadcasters();
226 void ScDocument::PreprocessRangeNameUpdate()
228 sc::EndListeningContext
aEndListenCxt(*this);
229 sc::CompileFormulaContext
aCompileCxt(this);
231 TableContainer::iterator it
= maTabs
.begin(), itEnd
= maTabs
.end();
232 for (; it
!= itEnd
; ++it
)
235 p
->PreprocessRangeNameUpdate(aEndListenCxt
, aCompileCxt
);
239 void ScDocument::PreprocessDBDataUpdate()
241 sc::EndListeningContext
aEndListenCxt(*this);
242 sc::CompileFormulaContext
aCompileCxt(this);
244 TableContainer::iterator it
= maTabs
.begin(), itEnd
= maTabs
.end();
245 for (; it
!= itEnd
; ++it
)
248 p
->PreprocessDBDataUpdate(aEndListenCxt
, aCompileCxt
);
252 void ScDocument::CompileHybridFormula()
254 sc::StartListeningContext
aStartListenCxt(*this);
255 sc::CompileFormulaContext
aCompileCxt(this);
256 TableContainer::iterator it
= maTabs
.begin(), itEnd
= maTabs
.end();
257 for (; it
!= itEnd
; ++it
)
260 p
->CompileHybridFormula(aStartListenCxt
, aCompileCxt
);
264 void ScDocument::SharePooledResources( ScDocument
* pSrcDoc
)
266 xPoolHelper
= pSrcDoc
->xPoolHelper
;
267 mpCellStringPool
= pSrcDoc
->mpCellStringPool
;
270 void ScDocument::UpdateScriptTypes( const ScAddress
& rPos
, SCCOL nColSize
, SCROW nRowSize
)
272 ScTable
* pTab
= FetchTable(rPos
.Tab());
276 pTab
->UpdateScriptTypes(rPos
.Col(), rPos
.Row(), rPos
.Col()+nColSize
-1, rPos
.Row()+nRowSize
-1);
279 bool ScDocument::HasUniformRowHeight( SCTAB nTab
, SCROW nRow1
, SCROW nRow2
) const
281 const ScTable
* pTab
= FetchTable(nTab
);
285 return pTab
->HasUniformRowHeight(nRow1
, nRow2
);
288 void ScDocument::UnshareFormulaCells( SCTAB nTab
, SCCOL nCol
, std::vector
<SCROW
>& rRows
)
290 ScTable
* pTab
= FetchTable(nTab
);
294 pTab
->UnshareFormulaCells(nCol
, rRows
);
297 void ScDocument::RegroupFormulaCells( SCTAB nTab
, SCCOL nCol
)
299 ScTable
* pTab
= FetchTable(nTab
);
303 pTab
->RegroupFormulaCells(nCol
);
306 void ScDocument::CollectAllAreaListeners(
307 std::vector
<SvtListener
*>& rListener
, const ScRange
& rRange
, sc::AreaOverlapType eType
)
312 std::vector
<sc::AreaListener
> aAL
= pBASM
->GetAllListeners(rRange
, eType
);
313 std::vector
<sc::AreaListener
>::iterator it
= aAL
.begin(), itEnd
= aAL
.end();
314 for (; it
!= itEnd
; ++it
)
315 rListener
.push_back(it
->mpListener
);
318 bool ScDocument::HasFormulaCell( const ScRange
& rRange
) const
320 if (!rRange
.IsValid())
323 for (SCTAB nTab
= rRange
.aStart
.Tab(); nTab
<= rRange
.aEnd
.Tab(); ++nTab
)
325 const ScTable
* pTab
= FetchTable(nTab
);
329 if (pTab
->HasFormulaCell(rRange
.aStart
.Col(), rRange
.aStart
.Row(), rRange
.aEnd
.Col(), rRange
.aEnd
.Row()))
336 void ScDocument::EndListeningIntersectedGroup(
337 sc::EndListeningContext
& rCxt
, const ScAddress
& rPos
, std::vector
<ScAddress
>* pGroupPos
)
339 ScTable
* pTab
= FetchTable(rPos
.Tab());
343 pTab
->EndListeningIntersectedGroup(rCxt
, rPos
.Col(), rPos
.Row(), pGroupPos
);
346 void ScDocument::EndListeningIntersectedGroups(
347 sc::EndListeningContext
& rCxt
, const ScRange
& rRange
, std::vector
<ScAddress
>* pGroupPos
)
349 for (SCTAB nTab
= rRange
.aStart
.Tab(); nTab
<= rRange
.aEnd
.Tab(); ++nTab
)
351 ScTable
* pTab
= FetchTable(nTab
);
355 pTab
->EndListeningIntersectedGroups(
356 rCxt
, rRange
.aStart
.Col(), rRange
.aStart
.Row(), rRange
.aEnd
.Col(), rRange
.aEnd
.Row(),
361 void ScDocument::EndListeningGroups( const std::vector
<ScAddress
>& rPosArray
)
363 sc::EndListeningContext
aCxt(*this);
364 std::vector
<ScAddress
>::const_iterator it
= rPosArray
.begin(), itEnd
= rPosArray
.end();
365 for (; it
!= itEnd
; ++it
)
367 const ScAddress
& rPos
= *it
;
368 ScTable
* pTab
= FetchTable(rPos
.Tab());
372 pTab
->EndListeningGroup(aCxt
, rPos
.Col(), rPos
.Row());
375 aCxt
.purgeEmptyBroadcasters();
378 void ScDocument::SetNeedsListeningGroups( const std::vector
<ScAddress
>& rPosArray
)
380 std::vector
<ScAddress
>::const_iterator it
= rPosArray
.begin(), itEnd
= rPosArray
.end();
381 for (; it
!= itEnd
; ++it
)
383 const ScAddress
& rPos
= *it
;
384 ScTable
* pTab
= FetchTable(rPos
.Tab());
388 pTab
->SetNeedsListeningGroup(rPos
.Col(), rPos
.Row());
394 class StartNeededListenersHandler
: std::unary_function
<ScTable
*, void>
396 boost::shared_ptr
<sc::StartListeningContext
> mpCxt
;
398 StartNeededListenersHandler( ScDocument
& rDoc
) : mpCxt(new sc::StartListeningContext(rDoc
)) {}
400 void operator() (ScTable
* p
)
403 p
->StartListeners(*mpCxt
, false);
409 void ScDocument::StartNeededListeners()
411 std::for_each(maTabs
.begin(), maTabs
.end(), StartNeededListenersHandler(*this));
414 void ScDocument::StartAllListeners( const ScRange
& rRange
)
416 boost::shared_ptr
<sc::ColumnBlockPositionSet
> pPosSet(new sc::ColumnBlockPositionSet(*this));
417 sc::StartListeningContext
aStartCxt(*this, pPosSet
);
418 sc::EndListeningContext
aEndCxt(*this, pPosSet
);
420 for (SCTAB nTab
= rRange
.aStart
.Tab(); nTab
<= rRange
.aEnd
.Tab(); ++nTab
)
422 ScTable
* pTab
= FetchTable(nTab
);
426 pTab
->StartListeningFormulaCells(
428 rRange
.aStart
.Col(), rRange
.aStart
.Row(), rRange
.aEnd
.Col(), rRange
.aEnd
.Row());
432 void ScDocument::EndAllListeners( const ScRange
& rRange
)
434 sc::EndListeningContext
aEndCxt(*this);
436 for (SCTAB nTab
= rRange
.aStart
.Tab(); nTab
<= rRange
.aEnd
.Tab(); ++nTab
)
438 ScTable
* pTab
= FetchTable(nTab
);
442 pTab
->EndListeningFormulaCells(
444 rRange
.aStart
.Col(), rRange
.aStart
.Row(), rRange
.aEnd
.Col(), rRange
.aEnd
.Row());
448 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */