Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : */
9 :
10 : #include <document.hxx>
11 : #include <clipcontext.hxx>
12 : #include <formulacell.hxx>
13 : #include <clipparam.hxx>
14 : #include <table.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>
23 :
24 : #include "dociter.hxx"
25 : #include "patattr.hxx"
26 : #include <svl/whiter.hxx>
27 : #include <editeng/colritem.hxx>
28 : #include "scitems.hxx"
29 :
30 : // Add totally brand-new methods to this source file.
31 :
32 17 : bool ScDocument::IsMerged( const ScAddress& rPos ) const
33 : {
34 17 : const ScTable* pTab = FetchTable(rPos.Tab());
35 17 : if (!pTab)
36 0 : return false;
37 :
38 17 : return pTab->IsMerged(rPos.Col(), rPos.Row());
39 : }
40 :
41 2 : void ScDocument::DeleteBeforeCopyFromClip(
42 : sc::CopyFromClipContext& rCxt, const ScMarkData& rMark, sc::ColumnSpanSet& rBroadcastSpans )
43 : {
44 2 : SCTAB nClipTab = 0;
45 2 : const TableContainer& rClipTabs = rCxt.getClipDoc()->maTabs;
46 2 : SCTAB nClipTabCount = rClipTabs.size();
47 :
48 4 : for (SCTAB nTab = rCxt.getTabStart(); nTab <= rCxt.getTabEnd(); ++nTab)
49 : {
50 2 : ScTable* pTab = FetchTable(nTab);
51 2 : if (!pTab)
52 0 : continue;
53 :
54 2 : if (!rMark.GetTableSelect(nTab))
55 0 : continue;
56 :
57 4 : while (!rClipTabs[nClipTab])
58 0 : nClipTab = (nClipTab+1) % nClipTabCount;
59 :
60 2 : pTab->DeleteBeforeCopyFromClip(rCxt, *rClipTabs[nClipTab], rBroadcastSpans);
61 :
62 2 : nClipTab = (nClipTab+1) % nClipTabCount;
63 : }
64 2 : }
65 :
66 77 : bool ScDocument::CopyOneCellFromClip(
67 : sc::CopyFromClipContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
68 : {
69 77 : ScDocument* pClipDoc = rCxt.getClipDoc();
70 77 : if (pClipDoc->GetClipParam().mbCutMode)
71 : // We don't handle cut and paste or moving of cells here.
72 16 : return false;
73 :
74 61 : ScRange aClipRange = pClipDoc->GetClipParam().getWholeRange();
75 61 : if (aClipRange.aStart.Row() != aClipRange.aEnd.Row())
76 : // The source is not really a single row. Bail out.
77 49 : return false;
78 :
79 12 : SCCOL nSrcColSize = aClipRange.aEnd.Col() - aClipRange.aStart.Col() + 1;
80 12 : SCCOL nDestColSize = nCol2 - nCol1 + 1;
81 12 : if (nDestColSize < nSrcColSize)
82 0 : return false;
83 :
84 12 : ScAddress aSrcPos = aClipRange.aStart;
85 :
86 29 : for (SCCOL nCol = aClipRange.aStart.Col(); nCol <= aClipRange.aEnd.Col(); ++nCol)
87 : {
88 17 : ScAddress aTestPos = aSrcPos;
89 17 : aTestPos.SetCol(nCol);
90 17 : if (pClipDoc->IsMerged(aTestPos))
91 : // We don't handle merged source cell for this.
92 0 : return false;
93 : }
94 :
95 12 : ScTable* pSrcTab = pClipDoc->FetchTable(aSrcPos.Tab());
96 12 : if (!pSrcTab)
97 0 : return false;
98 :
99 12 : rCxt.setSingleCellColumnSize(nSrcColSize);
100 :
101 29 : for (SCCOL nColOffset = 0; nColOffset < nSrcColSize; ++nColOffset, aSrcPos.IncCol())
102 : {
103 17 : const ScPatternAttr* pAttr = pClipDoc->GetPattern(aSrcPos);
104 17 : rCxt.setSingleCellPattern(nColOffset, pAttr);
105 :
106 17 : if ((rCxt.getInsertFlag() & (IDF_NOTE | IDF_ADDNOTES)) != IDF_NONE)
107 17 : rCxt.setSingleCellNote(nColOffset, pClipDoc->GetNote(aSrcPos));
108 :
109 17 : ScColumn& rSrcCol = pSrcTab->aCol[aSrcPos.Col()];
110 : // Determine the script type of the copied single cell.
111 17 : rSrcCol.UpdateScriptTypes(aSrcPos.Row(), aSrcPos.Row());
112 17 : rCxt.setSingleCell(aSrcPos, rSrcCol);
113 : }
114 :
115 : // All good. Proceed with the pasting.
116 :
117 12 : SCTAB nTabEnd = rCxt.getTabEnd();
118 24 : for (SCTAB i = rCxt.getTabStart(); i <= nTabEnd && i < static_cast<SCTAB>(maTabs.size()); ++i)
119 : {
120 12 : maTabs[i]->CopyOneCellFromClip(rCxt, nCol1, nRow1, nCol2, nRow2);
121 12 : if (rCxt.getInsertFlag() & IDF_ATTRIB)
122 28 : for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
123 : {
124 34 : maTabs[i]->CopyConditionalFormat(nCol1, nRow, nCol2, nRow, nCol1 - aClipRange.aStart.Col(),
125 51 : nRow - aClipRange.aStart.Row(), pSrcTab);
126 : }
127 : }
128 :
129 12 : return true;
130 : }
131 :
132 0 : void ScDocument::SetValues( const ScAddress& rPos, const std::vector<double>& rVals )
133 : {
134 0 : ScTable* pTab = FetchTable(rPos.Tab());
135 0 : if (!pTab)
136 0 : return;
137 :
138 0 : pTab->SetValues(rPos.Col(), rPos.Row(), rVals);
139 : }
140 :
141 0 : void ScDocument::TransferCellValuesTo( const ScAddress& rTopPos, size_t nLen, sc::CellValues& rDest )
142 : {
143 0 : ScTable* pTab = FetchTable(rTopPos.Tab());
144 0 : if (!pTab)
145 0 : return;
146 :
147 0 : pTab->TransferCellValuesTo(rTopPos.Col(), rTopPos.Row(), nLen, rDest);
148 : }
149 :
150 0 : void ScDocument::CopyCellValuesFrom( const ScAddress& rTopPos, const sc::CellValues& rSrc )
151 : {
152 0 : ScTable* pTab = FetchTable(rTopPos.Tab());
153 0 : if (!pTab)
154 0 : return;
155 :
156 0 : pTab->CopyCellValuesFrom(rTopPos.Col(), rTopPos.Row(), rSrc);
157 : }
158 :
159 0 : std::set<Color> ScDocument::GetDocColors()
160 : {
161 0 : std::set<Color> aDocColors;
162 0 : ScDocumentPool *pPool = GetPool();
163 0 : const sal_uInt16 pAttribs[] = {ATTR_BACKGROUND, ATTR_FONT_COLOR};
164 0 : for (size_t i=0; i<SAL_N_ELEMENTS( pAttribs ); i++)
165 : {
166 0 : const sal_uInt16 nAttrib = pAttribs[i];
167 0 : const sal_uInt32 nCount = pPool->GetItemCount2(nAttrib);
168 0 : for (sal_uInt32 j=0; j<nCount; j++)
169 : {
170 0 : const SvxColorItem *pItem = static_cast<const SvxColorItem*>(pPool->GetItem2(nAttrib, j));
171 0 : if (pItem == 0)
172 0 : continue;
173 0 : Color aColor( pItem->GetValue() );
174 0 : if (COL_AUTO != aColor.GetColor())
175 0 : aDocColors.insert(aColor);
176 : }
177 : }
178 0 : return aDocColors;
179 : }
180 :
181 768 : void ScDocument::SetCalcConfig( const ScCalcConfig& rConfig )
182 : {
183 768 : maCalcConfig = rConfig;
184 768 : }
185 :
186 2 : void ScDocument::ConvertFormulaToValue( const ScRange& rRange, sc::TableValues* pUndo )
187 : {
188 2 : sc::EndListeningContext aCxt(*this);
189 :
190 4 : for (SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); ++nTab)
191 : {
192 2 : ScTable* pTab = FetchTable(nTab);
193 2 : if (!pTab)
194 0 : continue;
195 :
196 : pTab->ConvertFormulaToValue(
197 4 : aCxt, rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row(),
198 6 : pUndo);
199 : }
200 :
201 2 : aCxt.purgeEmptyBroadcasters();
202 2 : }
203 :
204 4 : void ScDocument::SwapNonEmpty( sc::TableValues& rValues )
205 : {
206 4 : const ScRange& rRange = rValues.getRange();
207 4 : if (!rRange.IsValid())
208 4 : return;
209 :
210 4 : boost::shared_ptr<sc::ColumnBlockPositionSet> pPosSet(new sc::ColumnBlockPositionSet(*this));
211 8 : sc::StartListeningContext aStartCxt(*this, pPosSet);
212 8 : sc::EndListeningContext aEndCxt(*this, pPosSet);
213 :
214 8 : for (SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); ++nTab)
215 : {
216 4 : ScTable* pTab = FetchTable(nTab);
217 4 : if (!pTab)
218 0 : continue;
219 :
220 4 : pTab->SwapNonEmpty(rValues, aStartCxt, aEndCxt);
221 : }
222 :
223 8 : aEndCxt.purgeEmptyBroadcasters();
224 : }
225 :
226 32 : void ScDocument::PreprocessRangeNameUpdate()
227 : {
228 32 : sc::EndListeningContext aEndListenCxt(*this);
229 64 : sc::CompileFormulaContext aCompileCxt(this);
230 :
231 32 : TableContainer::iterator it = maTabs.begin(), itEnd = maTabs.end();
232 102 : for (; it != itEnd; ++it)
233 : {
234 70 : ScTable* p = *it;
235 70 : p->PreprocessRangeNameUpdate(aEndListenCxt, aCompileCxt);
236 32 : }
237 32 : }
238 :
239 9 : void ScDocument::PreprocessDBDataUpdate()
240 : {
241 9 : sc::EndListeningContext aEndListenCxt(*this);
242 18 : sc::CompileFormulaContext aCompileCxt(this);
243 :
244 9 : TableContainer::iterator it = maTabs.begin(), itEnd = maTabs.end();
245 20 : for (; it != itEnd; ++it)
246 : {
247 11 : ScTable* p = *it;
248 11 : p->PreprocessDBDataUpdate(aEndListenCxt, aCompileCxt);
249 9 : }
250 9 : }
251 :
252 41 : void ScDocument::CompileHybridFormula()
253 : {
254 41 : sc::StartListeningContext aStartListenCxt(*this);
255 82 : sc::CompileFormulaContext aCompileCxt(this);
256 41 : TableContainer::iterator it = maTabs.begin(), itEnd = maTabs.end();
257 122 : for (; it != itEnd; ++it)
258 : {
259 81 : ScTable* p = *it;
260 81 : p->CompileHybridFormula(aStartListenCxt, aCompileCxt);
261 41 : }
262 41 : }
263 :
264 1000 : void ScDocument::SharePooledResources( ScDocument* pSrcDoc )
265 : {
266 1000 : xPoolHelper = pSrcDoc->xPoolHelper;
267 1000 : mpCellStringPool = pSrcDoc->mpCellStringPool;
268 1000 : }
269 :
270 46 : void ScDocument::UpdateScriptTypes( const ScAddress& rPos, SCCOL nColSize, SCROW nRowSize )
271 : {
272 46 : ScTable* pTab = FetchTable(rPos.Tab());
273 46 : if (!pTab)
274 46 : return;
275 :
276 46 : pTab->UpdateScriptTypes(rPos.Col(), rPos.Row(), rPos.Col()+nColSize-1, rPos.Row()+nRowSize-1);
277 : }
278 :
279 29 : bool ScDocument::HasUniformRowHeight( SCTAB nTab, SCROW nRow1, SCROW nRow2 ) const
280 : {
281 29 : const ScTable* pTab = FetchTable(nTab);
282 29 : if (!pTab)
283 0 : return false;
284 :
285 29 : return pTab->HasUniformRowHeight(nRow1, nRow2);
286 : }
287 :
288 5 : void ScDocument::UnshareFormulaCells( SCTAB nTab, SCCOL nCol, std::vector<SCROW>& rRows )
289 : {
290 5 : ScTable* pTab = FetchTable(nTab);
291 5 : if (!pTab)
292 5 : return;
293 :
294 5 : pTab->UnshareFormulaCells(nCol, rRows);
295 : }
296 :
297 5 : void ScDocument::RegroupFormulaCells( SCTAB nTab, SCCOL nCol )
298 : {
299 5 : ScTable* pTab = FetchTable(nTab);
300 5 : if (!pTab)
301 5 : return;
302 :
303 5 : pTab->RegroupFormulaCells(nCol);
304 : }
305 :
306 6 : void ScDocument::CollectAllAreaListeners(
307 : std::vector<SvtListener*>& rListener, const ScRange& rRange, sc::AreaOverlapType eType )
308 : {
309 6 : if (!pBASM)
310 6 : return;
311 :
312 6 : std::vector<sc::AreaListener> aAL = pBASM->GetAllListeners(rRange, eType);
313 6 : std::vector<sc::AreaListener>::iterator it = aAL.begin(), itEnd = aAL.end();
314 7 : for (; it != itEnd; ++it)
315 7 : rListener.push_back(it->mpListener);
316 : }
317 :
318 0 : bool ScDocument::HasFormulaCell( const ScRange& rRange ) const
319 : {
320 0 : if (!rRange.IsValid())
321 0 : return false;
322 :
323 0 : for (SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); ++nTab)
324 : {
325 0 : const ScTable* pTab = FetchTable(nTab);
326 0 : if (!pTab)
327 0 : continue;
328 :
329 0 : if (pTab->HasFormulaCell(rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row()))
330 0 : return true;
331 : }
332 :
333 0 : return false;
334 : }
335 :
336 36 : void ScDocument::EndListeningIntersectedGroup(
337 : sc::EndListeningContext& rCxt, const ScAddress& rPos, std::vector<ScAddress>* pGroupPos )
338 : {
339 36 : ScTable* pTab = FetchTable(rPos.Tab());
340 36 : if (!pTab)
341 36 : return;
342 :
343 36 : pTab->EndListeningIntersectedGroup(rCxt, rPos.Col(), rPos.Row(), pGroupPos);
344 : }
345 :
346 324 : void ScDocument::EndListeningIntersectedGroups(
347 : sc::EndListeningContext& rCxt, const ScRange& rRange, std::vector<ScAddress>* pGroupPos )
348 : {
349 648 : for (SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); ++nTab)
350 : {
351 324 : ScTable* pTab = FetchTable(nTab);
352 324 : if (!pTab)
353 0 : continue;
354 :
355 : pTab->EndListeningIntersectedGroups(
356 648 : rCxt, rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row(),
357 972 : pGroupPos);
358 : }
359 324 : }
360 :
361 50 : void ScDocument::EndListeningGroups( const std::vector<ScAddress>& rPosArray )
362 : {
363 50 : sc::EndListeningContext aCxt(*this);
364 50 : std::vector<ScAddress>::const_iterator it = rPosArray.begin(), itEnd = rPosArray.end();
365 56 : for (; it != itEnd; ++it)
366 : {
367 6 : const ScAddress& rPos = *it;
368 6 : ScTable* pTab = FetchTable(rPos.Tab());
369 6 : if (!pTab)
370 50 : return;
371 :
372 6 : pTab->EndListeningGroup(aCxt, rPos.Col(), rPos.Row());
373 : }
374 :
375 50 : aCxt.purgeEmptyBroadcasters();
376 : }
377 :
378 340 : void ScDocument::SetNeedsListeningGroups( const std::vector<ScAddress>& rPosArray )
379 : {
380 340 : std::vector<ScAddress>::const_iterator it = rPosArray.begin(), itEnd = rPosArray.end();
381 412 : for (; it != itEnd; ++it)
382 : {
383 72 : const ScAddress& rPos = *it;
384 72 : ScTable* pTab = FetchTable(rPos.Tab());
385 72 : if (!pTab)
386 0 : return;
387 :
388 72 : pTab->SetNeedsListeningGroup(rPos.Col(), rPos.Row());
389 : }
390 : }
391 :
392 : namespace {
393 :
394 1212 : class StartNeededListenersHandler : std::unary_function<ScTable*, void>
395 : {
396 : boost::shared_ptr<sc::StartListeningContext> mpCxt;
397 : public:
398 404 : StartNeededListenersHandler( ScDocument& rDoc ) : mpCxt(new sc::StartListeningContext(rDoc)) {}
399 :
400 491 : void operator() (ScTable* p)
401 : {
402 491 : if (p)
403 491 : p->StartListeners(*mpCxt, false);
404 491 : }
405 : };
406 :
407 : }
408 :
409 404 : void ScDocument::StartNeededListeners()
410 : {
411 404 : std::for_each(maTabs.begin(), maTabs.end(), StartNeededListenersHandler(*this));
412 404 : }
413 :
414 762 : void ScDocument::StartAllListeners( const ScRange& rRange )
415 : {
416 762 : boost::shared_ptr<sc::ColumnBlockPositionSet> pPosSet(new sc::ColumnBlockPositionSet(*this));
417 1524 : sc::StartListeningContext aStartCxt(*this, pPosSet);
418 1524 : sc::EndListeningContext aEndCxt(*this, pPosSet);
419 :
420 1688 : for (SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); ++nTab)
421 : {
422 926 : ScTable* pTab = FetchTable(nTab);
423 926 : if (!pTab)
424 160 : continue;
425 :
426 : pTab->StartListeningFormulaCells(
427 : aStartCxt, aEndCxt,
428 766 : rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row());
429 762 : }
430 762 : }
431 :
432 0 : void ScDocument::EndAllListeners( const ScRange& rRange )
433 : {
434 0 : sc::EndListeningContext aEndCxt(*this);
435 :
436 0 : for (SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); ++nTab)
437 : {
438 0 : ScTable* pTab = FetchTable(nTab);
439 0 : if (!pTab)
440 0 : continue;
441 :
442 : pTab->EndListeningFormulaCells(
443 : aEndCxt,
444 0 : rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row());
445 0 : }
446 156 : }
447 :
448 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|