File: | home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx |
Warning: | line 2848, column 44 The right operand of '+' is a garbage value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ | |||
2 | /* | |||
3 | * This file is part of the LibreOffice project. | |||
4 | * | |||
5 | * This Source Code Form is subject to the terms of the Mozilla Public | |||
6 | * License, v. 2.0. If a copy of the MPL was not distributed with this | |||
7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. | |||
8 | * | |||
9 | * This file incorporates work covered by the following license notice: | |||
10 | * | |||
11 | * Licensed to the Apache Software Foundation (ASF) under one or more | |||
12 | * contributor license agreements. See the NOTICE file distributed | |||
13 | * with this work for additional information regarding copyright | |||
14 | * ownership. The ASF licenses this file to you under the Apache | |||
15 | * License, Version 2.0 (the "License"); you may not use this file | |||
16 | * except in compliance with the License. You may obtain a copy of | |||
17 | * the License at http://www.apache.org/licenses/LICENSE-2.0 . | |||
18 | */ | |||
19 | ||||
20 | #include <scitems.hxx> | |||
21 | ||||
22 | #include <editeng/boxitem.hxx> | |||
23 | #include <editeng/editobj.hxx> | |||
24 | #include <o3tl/safeint.hxx> | |||
25 | #include <svx/sdrundomanager.hxx> | |||
26 | #include <svx/svditer.hxx> | |||
27 | #include <sfx2/objsh.hxx> | |||
28 | #include <sfx2/viewsh.hxx> | |||
29 | #include <sfx2/docfile.hxx> | |||
30 | #include <svl/poolcach.hxx> | |||
31 | #include <svl/zforlist.hxx> | |||
32 | #include <unotools/charclass.hxx> | |||
33 | #include <unotools/transliterationwrapper.hxx> | |||
34 | #include <tools/urlobj.hxx> | |||
35 | #include <sal/log.hxx> | |||
36 | ||||
37 | #include <com/sun/star/text/WritingMode2.hpp> | |||
38 | #include <com/sun/star/script/vba/XVBACompatibility.hpp> | |||
39 | #include <com/sun/star/sheet/TablePageBreakData.hpp> | |||
40 | #include <com/sun/star/lang/NotInitializedException.hpp> | |||
41 | ||||
42 | #include <document.hxx> | |||
43 | #include <table.hxx> | |||
44 | #include <column.hxx> | |||
45 | #include <attrib.hxx> | |||
46 | #include <attarray.hxx> | |||
47 | #include <patattr.hxx> | |||
48 | #include <rangenam.hxx> | |||
49 | #include <poolhelp.hxx> | |||
50 | #include <docpool.hxx> | |||
51 | #include <stlpool.hxx> | |||
52 | #include <stlsheet.hxx> | |||
53 | #include <globstr.hrc> | |||
54 | #include <scresid.hxx> | |||
55 | #include <dbdata.hxx> | |||
56 | #include <chartlis.hxx> | |||
57 | #include <rangelst.hxx> | |||
58 | #include <markdata.hxx> | |||
59 | #include <drwlayer.hxx> | |||
60 | #include <validat.hxx> | |||
61 | #include <prnsave.hxx> | |||
62 | #include <chgtrack.hxx> | |||
63 | #include <hints.hxx> | |||
64 | #include <detdata.hxx> | |||
65 | #include <dpobject.hxx> | |||
66 | #include <detfunc.hxx> | |||
67 | #include <scmod.hxx> | |||
68 | #include <dociter.hxx> | |||
69 | #include <progress.hxx> | |||
70 | #include <autonamecache.hxx> | |||
71 | #include <bcaslot.hxx> | |||
72 | #include <postit.hxx> | |||
73 | #include <clipparam.hxx> | |||
74 | #include <defaultsoptions.hxx> | |||
75 | #include <editutil.hxx> | |||
76 | #include <stringutil.hxx> | |||
77 | #include <formulaiter.hxx> | |||
78 | #include <formulacell.hxx> | |||
79 | #include <clipcontext.hxx> | |||
80 | #include <listenercontext.hxx> | |||
81 | #include <scopetools.hxx> | |||
82 | #include <refupdatecontext.hxx> | |||
83 | #include <formulagroup.hxx> | |||
84 | #include <tokenstringcontext.hxx> | |||
85 | #include <compressedarray.hxx> | |||
86 | #include <docsh.hxx> | |||
87 | #include <brdcst.hxx> | |||
88 | #include <recursionhelper.hxx> | |||
89 | ||||
90 | #include <formula/vectortoken.hxx> | |||
91 | ||||
92 | #include <limits> | |||
93 | #include <memory> | |||
94 | #include <utility> | |||
95 | ||||
96 | #include <comphelper/lok.hxx> | |||
97 | #include <LibreOfficeKit/LibreOfficeKitEnums.h> | |||
98 | ||||
99 | #include <vcl/uitest/logger.hxx> | |||
100 | #include <vcl/uitest/eventdescription.hxx> | |||
101 | ||||
102 | #include <mtvelements.hxx> | |||
103 | #include <sfx2/lokhelper.hxx> | |||
104 | ||||
105 | using ::editeng::SvxBorderLine; | |||
106 | using namespace ::com::sun::star; | |||
107 | ||||
108 | namespace WritingMode2 = ::com::sun::star::text::WritingMode2; | |||
109 | using ::com::sun::star::uno::Sequence; | |||
110 | using ::com::sun::star::sheet::TablePageBreakData; | |||
111 | using ::std::set; | |||
112 | ||||
113 | namespace { | |||
114 | ||||
115 | std::pair<SCTAB,SCTAB> getMarkedTableRange(const std::vector<ScTableUniquePtr>& rTables, const ScMarkData& rMark) | |||
116 | { | |||
117 | SCTAB nTabStart = MAXTAB; | |||
118 | SCTAB nTabEnd = 0; | |||
119 | SCTAB nMax = static_cast<SCTAB>(rTables.size()); | |||
120 | for (const auto& rTab : rMark) | |||
121 | { | |||
122 | if (rTab >= nMax) | |||
123 | break; | |||
124 | ||||
125 | if (!rTables[rTab]) | |||
126 | continue; | |||
127 | ||||
128 | if (rTab < nTabStart) | |||
129 | nTabStart = rTab; | |||
130 | nTabEnd = rTab; | |||
131 | } | |||
132 | ||||
133 | return std::pair<SCTAB,SCTAB>(nTabStart,nTabEnd); | |||
134 | } | |||
135 | ||||
136 | void collectUIInformation(const std::map<OUString, OUString>& aParameters, const OUString& rAction) | |||
137 | { | |||
138 | EventDescription aDescription; | |||
139 | aDescription.aID = "grid_window"; | |||
140 | aDescription.aAction = rAction; | |||
141 | aDescription.aParameters = aParameters; | |||
142 | aDescription.aParent = "MainWindow"; | |||
143 | aDescription.aKeyWord = "ScGridWinUIObject"; | |||
144 | ||||
145 | UITestLogger::getInstance().logEvent(aDescription); | |||
146 | } | |||
147 | ||||
148 | struct ScDefaultAttr | |||
149 | { | |||
150 | const ScPatternAttr* pAttr; | |||
151 | SCROW nFirst; | |||
152 | SCSIZE nCount; | |||
153 | explicit ScDefaultAttr(const ScPatternAttr* pPatAttr) : pAttr(pPatAttr), nFirst(0), nCount(0) {} | |||
154 | }; | |||
155 | ||||
156 | struct ScLessDefaultAttr | |||
157 | { | |||
158 | bool operator() (const ScDefaultAttr& rValue1, const ScDefaultAttr& rValue2) const | |||
159 | { | |||
160 | return rValue1.pAttr < rValue2.pAttr; | |||
161 | } | |||
162 | }; | |||
163 | ||||
164 | } | |||
165 | ||||
166 | typedef std::set<ScDefaultAttr, ScLessDefaultAttr> ScDefaultAttrSet; | |||
167 | ||||
168 | void ScDocument::MakeTable( SCTAB nTab,bool _bNeedsNameCheck ) | |||
169 | { | |||
170 | if ( !(ValidTab(nTab) && ( nTab >= static_cast<SCTAB>(maTabs.size()) ||!maTabs[nTab])) ) | |||
171 | return; | |||
172 | ||||
173 | // Get Custom prefix | |||
174 | const ScDefaultsOptions& rOpt = SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule ::Calc)) )->GetDefaultsOptions(); | |||
175 | OUString aString = rOpt.GetInitTabPrefix() + OUString::number(nTab+1); | |||
176 | if ( _bNeedsNameCheck ) | |||
177 | CreateValidTabName( aString ); // no doubles | |||
178 | if (nTab < static_cast<SCTAB>(maTabs.size())) | |||
179 | { | |||
180 | maTabs[nTab].reset( new ScTable(*this, nTab, aString) ); | |||
181 | } | |||
182 | else | |||
183 | { | |||
184 | while(nTab > static_cast<SCTAB>(maTabs.size())) | |||
185 | maTabs.push_back(nullptr); | |||
186 | maTabs.emplace_back( new ScTable(*this, nTab, aString) ); | |||
187 | } | |||
188 | maTabs[nTab]->SetLoadingMedium(bLoadingMedium); | |||
189 | } | |||
190 | ||||
191 | bool ScDocument::HasTable( SCTAB nTab ) const | |||
192 | { | |||
193 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size())) | |||
194 | if (maTabs[nTab]) | |||
195 | return true; | |||
196 | ||||
197 | return false; | |||
198 | } | |||
199 | ||||
200 | bool ScDocument::GetHashCode( SCTAB nTab, sal_Int64& rHashCode ) const | |||
201 | { | |||
202 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size())) | |||
203 | { | |||
204 | if (maTabs[nTab]) | |||
205 | { | |||
206 | rHashCode = maTabs[nTab]->GetHashCode(); | |||
207 | return true; | |||
208 | } | |||
209 | } | |||
210 | return false; | |||
211 | } | |||
212 | ||||
213 | bool ScDocument::GetName( SCTAB nTab, OUString& rName ) const | |||
214 | { | |||
215 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size())) | |||
216 | { | |||
217 | if (maTabs[nTab]) | |||
218 | { | |||
219 | rName = maTabs[nTab]->GetName(); | |||
220 | return true; | |||
221 | } | |||
222 | } | |||
223 | rName.clear(); | |||
224 | return false; | |||
225 | } | |||
226 | ||||
227 | OUString ScDocument::GetCopyTabName( SCTAB nTab ) const | |||
228 | { | |||
229 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabNames.size())) | |||
230 | return maTabNames[nTab]; | |||
231 | return OUString(); | |||
232 | } | |||
233 | ||||
234 | bool ScDocument::SetCodeName( SCTAB nTab, const OUString& rName ) | |||
235 | { | |||
236 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size())) | |||
237 | { | |||
238 | if (maTabs[nTab]) | |||
239 | { | |||
240 | maTabs[nTab]->SetCodeName( rName ); | |||
241 | return true; | |||
242 | } | |||
243 | } | |||
244 | SAL_WARN("sc", "can't set code name " << rName )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "sc")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "can't set code name " << rName) == 1) { :: sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sc"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "244" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "can't set code name " << rName) , 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "can't set code name " << rName; ::sal::detail ::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sc"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "244" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "can't set code name " << rName) == 1) { :: sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sc"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "244" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "can't set code name " << rName) , 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "can't set code name " << rName; ::sal::detail ::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sc"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "244" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | |||
245 | return false; | |||
246 | } | |||
247 | ||||
248 | bool ScDocument::GetCodeName( SCTAB nTab, OUString& rName ) const | |||
249 | { | |||
250 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size())) | |||
251 | if (maTabs[nTab]) | |||
252 | { | |||
253 | rName = maTabs[nTab]->GetCodeName(); | |||
254 | return true; | |||
255 | } | |||
256 | rName.clear(); | |||
257 | return false; | |||
258 | } | |||
259 | ||||
260 | bool ScDocument::GetTable( const OUString& rName, SCTAB& rTab ) const | |||
261 | { | |||
262 | OUString aUpperName; | |||
263 | static OUString aCacheName, aCacheUpperName; | |||
264 | ||||
265 | assert(!IsThreadedGroupCalcInProgress())(static_cast <bool> (!IsThreadedGroupCalcInProgress()) ? void (0) : __assert_fail ("!IsThreadedGroupCalcInProgress()" , "/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" , 265, __extension__ __PRETTY_FUNCTION__)); | |||
266 | if (aCacheName != rName) | |||
267 | { | |||
268 | aCacheName = rName; | |||
269 | // surprisingly slow ... | |||
270 | aCacheUpperName = ScGlobal::getCharClassPtr()->uppercase(rName); | |||
271 | } | |||
272 | aUpperName = aCacheUpperName; | |||
273 | ||||
274 | for (SCTAB i=0; i< static_cast<SCTAB>(maTabs.size()); i++) | |||
275 | if (maTabs[i]) | |||
276 | { | |||
277 | if (aUpperName == maTabs[i]->GetUpperName()) | |||
278 | { | |||
279 | rTab = i; | |||
280 | return true; | |||
281 | } | |||
282 | } | |||
283 | rTab = 0; | |||
284 | return false; | |||
285 | } | |||
286 | ||||
287 | std::vector<OUString> ScDocument::GetAllTableNames() const | |||
288 | { | |||
289 | std::vector<OUString> aNames; | |||
290 | aNames.reserve(maTabs.size()); | |||
291 | for (const auto& a : maTabs) | |||
292 | { | |||
293 | // Positions need to be preserved for ScCompiler and address convention | |||
294 | // context, so still push an empty string for NULL tabs. | |||
295 | OUString aName; | |||
296 | if (a) | |||
297 | { | |||
298 | const ScTable& rTab = *a; | |||
299 | aName = rTab.GetName(); | |||
300 | } | |||
301 | aNames.push_back(aName); | |||
302 | } | |||
303 | ||||
304 | return aNames; | |||
305 | } | |||
306 | ||||
307 | ScDBData* ScDocument::GetAnonymousDBData(SCTAB nTab) | |||
308 | { | |||
309 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab]) | |||
310 | return maTabs[nTab]->GetAnonymousDBData(); | |||
311 | return nullptr; | |||
312 | } | |||
313 | ||||
314 | SCTAB ScDocument::GetTableCount() const | |||
315 | { | |||
316 | return static_cast<SCTAB>(maTabs.size()); | |||
317 | } | |||
318 | ||||
319 | void ScDocument::SetAnonymousDBData(SCTAB nTab, std::unique_ptr<ScDBData> pDBData) | |||
320 | { | |||
321 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab]) | |||
322 | maTabs[nTab]->SetAnonymousDBData(std::move(pDBData)); | |||
323 | } | |||
324 | ||||
325 | void ScDocument::SetAnonymousDBData( std::unique_ptr<ScDBData> pDBData ) | |||
326 | { | |||
327 | mpAnonymousDBData = std::move(pDBData); | |||
328 | } | |||
329 | ||||
330 | ScDBData* ScDocument::GetAnonymousDBData() | |||
331 | { | |||
332 | return mpAnonymousDBData.get(); | |||
333 | } | |||
334 | ||||
335 | bool ScDocument::ValidTabName( const OUString& rName ) | |||
336 | { | |||
337 | if (rName.isEmpty()) | |||
338 | return false; | |||
339 | sal_Int32 nLen = rName.getLength(); | |||
340 | ||||
341 | #if 1 | |||
342 | // Restrict sheet names to what Excel accepts. | |||
343 | /* TODO: We may want to remove this restriction for full ODFF compliance. | |||
344 | * Merely loading and calculating ODF documents using these characters in | |||
345 | * sheet names is not affected by this, but all sheet name editing and | |||
346 | * copying functionality is, maybe falling back to "Sheet4" or similar. */ | |||
347 | for (sal_Int32 i = 0; i < nLen; ++i) | |||
348 | { | |||
349 | const sal_Unicode c = rName[i]; | |||
350 | switch (c) | |||
351 | { | |||
352 | case ':': | |||
353 | case '\\': | |||
354 | case '/': | |||
355 | case '?': | |||
356 | case '*': | |||
357 | case '[': | |||
358 | case ']': | |||
359 | // these characters are not allowed to match XL's convention. | |||
360 | return false; | |||
361 | case '\'': | |||
362 | if (i == 0 || i == nLen - 1) | |||
363 | // single quote is not allowed at the first or last | |||
364 | // character position. | |||
365 | return false; | |||
366 | break; | |||
367 | } | |||
368 | } | |||
369 | #endif | |||
370 | ||||
371 | return true; | |||
372 | } | |||
373 | ||||
374 | bool ScDocument::ValidNewTabName( const OUString& rName ) const | |||
375 | { | |||
376 | bool bValid = ValidTabName(rName); | |||
377 | if (!bValid) | |||
378 | return false; | |||
379 | OUString aUpperName = ScGlobal::getCharClassPtr()->uppercase(rName); | |||
380 | for (const auto& a : maTabs) | |||
381 | { | |||
382 | if (!a) | |||
383 | continue; | |||
384 | const OUString& rOldName = a->GetUpperName(); | |||
385 | bValid = rOldName != aUpperName; | |||
386 | if (!bValid) | |||
387 | break; | |||
388 | } | |||
389 | return bValid; | |||
390 | } | |||
391 | ||||
392 | void ScDocument::CreateValidTabName(OUString& rName) const | |||
393 | { | |||
394 | if ( !ValidTabName(rName) ) | |||
395 | { | |||
396 | // Find new one | |||
397 | ||||
398 | // Get Custom prefix | |||
399 | const ScDefaultsOptions& rOpt = SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule ::Calc)) )->GetDefaultsOptions(); | |||
400 | const OUString& aStrTable = rOpt.GetInitTabPrefix(); | |||
401 | ||||
402 | bool bOk = false; | |||
403 | ||||
404 | // First test if the prefix is valid, if so only avoid doubles | |||
405 | bool bPrefix = ValidTabName( aStrTable ); | |||
406 | OSL_ENSURE(bPrefix, "Invalid Table Name")do { if (true && (!(bPrefix))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "406" ": "), "%s", "Invalid Table Name"); } } while (false ); | |||
407 | SCTAB nDummy; | |||
408 | ||||
409 | for ( SCTAB i = static_cast<SCTAB>(maTabs.size())+1; !bOk ; i++ ) | |||
410 | { | |||
411 | rName = aStrTable + OUString::number(static_cast<sal_Int32>(i)); | |||
412 | if (bPrefix) | |||
413 | bOk = ValidNewTabName( rName ); | |||
414 | else | |||
415 | bOk = !GetTable( rName, nDummy ); | |||
416 | } | |||
417 | } | |||
418 | else | |||
419 | { | |||
420 | // testing the supplied Name | |||
421 | ||||
422 | if ( !ValidNewTabName(rName) ) | |||
423 | { | |||
424 | SCTAB i = 1; | |||
425 | OUStringBuffer aName; | |||
426 | do | |||
427 | { | |||
428 | i++; | |||
429 | aName = rName; | |||
430 | aName.append('_'); | |||
431 | aName.append(static_cast<sal_Int32>(i)); | |||
432 | } | |||
433 | while (!ValidNewTabName(aName.toString()) && (i < MAXTAB+1)); | |||
434 | rName = aName.makeStringAndClear(); | |||
435 | } | |||
436 | } | |||
437 | } | |||
438 | ||||
439 | void ScDocument::CreateValidTabNames(std::vector<OUString>& aNames, SCTAB nCount) const | |||
440 | { | |||
441 | aNames.clear();//ensure that the vector is empty | |||
442 | ||||
443 | // Get Custom prefix | |||
444 | const ScDefaultsOptions& rOpt = SC_MOD()( static_cast<ScModule*>(SfxApplication::GetModule(SfxToolsModule ::Calc)) )->GetDefaultsOptions(); | |||
445 | const OUString& aStrTable = rOpt.GetInitTabPrefix(); | |||
446 | ||||
447 | OUStringBuffer rName; | |||
448 | ||||
449 | // First test if the prefix is valid, if so only avoid doubles | |||
450 | bool bPrefix = ValidTabName( aStrTable ); | |||
451 | OSL_ENSURE(bPrefix, "Invalid Table Name")do { if (true && (!(bPrefix))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "451" ": "), "%s", "Invalid Table Name"); } } while (false ); | |||
452 | SCTAB nDummy; | |||
453 | SCTAB i = static_cast<SCTAB>(maTabs.size())+1; | |||
454 | ||||
455 | for (SCTAB j = 0; j < nCount; ++j) | |||
456 | { | |||
457 | bool bOk = false; | |||
458 | while(!bOk) | |||
459 | { | |||
460 | rName = aStrTable; | |||
461 | rName.append(static_cast<sal_Int32>(i)); | |||
462 | if (bPrefix) | |||
463 | bOk = ValidNewTabName( rName.toString() ); | |||
464 | else | |||
465 | bOk = !GetTable( rName.toString(), nDummy ); | |||
466 | i++; | |||
467 | } | |||
468 | aNames.push_back(rName.makeStringAndClear()); | |||
469 | } | |||
470 | } | |||
471 | ||||
472 | void ScDocument::AppendTabOnLoad(const OUString& rName) | |||
473 | { | |||
474 | SCTAB nTabCount = static_cast<SCTAB>(maTabs.size()); | |||
475 | if (!ValidTab(nTabCount)) | |||
476 | // max table count reached. No more tables. | |||
477 | return; | |||
478 | ||||
479 | OUString aName = rName; | |||
480 | CreateValidTabName(aName); | |||
481 | maTabs.emplace_back( new ScTable(*this, nTabCount, aName) ); | |||
482 | } | |||
483 | ||||
484 | void ScDocument::SetTabNameOnLoad(SCTAB nTab, const OUString& rName) | |||
485 | { | |||
486 | if (!ValidTab(nTab) || static_cast<SCTAB>(maTabs.size()) <= nTab) | |||
487 | return; | |||
488 | ||||
489 | if (!ValidTabName(rName)) | |||
490 | return; | |||
491 | ||||
492 | maTabs[nTab]->SetName(rName); | |||
493 | } | |||
494 | ||||
495 | void ScDocument::InvalidateStreamOnSave() | |||
496 | { | |||
497 | for (const auto& a : maTabs) | |||
498 | { | |||
499 | if (a) | |||
500 | a->SetStreamValid(false); | |||
501 | } | |||
502 | } | |||
503 | ||||
504 | bool ScDocument::InsertTab( | |||
505 | SCTAB nPos, const OUString& rName, bool bExternalDocument, bool bUndoDeleteTab ) | |||
506 | { | |||
507 | SCTAB nTabCount = static_cast<SCTAB>(maTabs.size()); | |||
508 | bool bValid = ValidTab(nTabCount); | |||
509 | if ( !bExternalDocument ) // else test rName == "'Doc'!Tab" first | |||
510 | bValid = (bValid && ValidNewTabName(rName)); | |||
511 | if (bValid) | |||
512 | { | |||
513 | if (nPos == SC_TAB_APPEND || nPos >= nTabCount) | |||
514 | { | |||
515 | nPos = maTabs.size(); | |||
516 | maTabs.emplace_back( new ScTable(*this, nTabCount, rName) ); | |||
517 | if ( bExternalDocument ) | |||
518 | maTabs[nTabCount]->SetVisible( false ); | |||
519 | } | |||
520 | else | |||
521 | { | |||
522 | if (ValidTab(nPos) && (nPos < nTabCount)) | |||
523 | { | |||
524 | sc::RefUpdateInsertTabContext aCxt( *this, nPos, 1); | |||
525 | ||||
526 | ScRange aRange( 0,0,nPos, MaxCol(),MaxRow(),MAXTAB ); | |||
527 | xColNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,1 ); | |||
528 | xRowNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,1 ); | |||
529 | if (pRangeName) | |||
530 | pRangeName->UpdateInsertTab(aCxt); | |||
531 | pDBCollection->UpdateReference( | |||
532 | URM_INSDEL, 0,0,nPos, MaxCol(),MaxRow(),MAXTAB, 0,0,1 ); | |||
533 | if (pDPCollection) | |||
534 | pDPCollection->UpdateReference( URM_INSDEL, aRange, 0,0,1 ); | |||
535 | if (pDetOpList) | |||
536 | pDetOpList->UpdateReference( this, URM_INSDEL, aRange, 0,0,1 ); | |||
537 | UpdateChartRef( URM_INSDEL, 0,0,nPos, MaxCol(),MaxRow(),MAXTAB, 0,0,1 ); | |||
538 | UpdateRefAreaLinks( URM_INSDEL, aRange, 0,0,1 ); | |||
539 | if ( pUnoBroadcaster ) | |||
540 | pUnoBroadcaster->Broadcast( ScUpdateRefHint( URM_INSDEL, aRange, 0,0,1 ) ); | |||
541 | ||||
542 | for (const auto& a : maTabs) | |||
543 | { | |||
544 | if (a) | |||
545 | a->UpdateInsertTab(aCxt); | |||
546 | } | |||
547 | maTabs.emplace(maTabs.begin() + nPos, new ScTable(*this, nPos, rName)); | |||
548 | ||||
549 | // UpdateBroadcastAreas must be called between UpdateInsertTab, | |||
550 | // which ends listening, and StartAllListeners, to not modify | |||
551 | // areas that are to be inserted by starting listeners. | |||
552 | UpdateBroadcastAreas( URM_INSDEL, aRange, 0,0,1); | |||
553 | for (const auto& a : maTabs) | |||
554 | { | |||
555 | if (a) | |||
556 | a->UpdateCompile(); | |||
557 | } | |||
558 | ||||
559 | StartAllListeners(); | |||
560 | ||||
561 | if (pValidationList) | |||
562 | { | |||
563 | ScMutationGuard aGuard(*this, ScMutationGuardFlags::CORE); | |||
564 | pValidationList->UpdateInsertTab(aCxt); | |||
565 | } | |||
566 | ||||
567 | bValid = true; | |||
568 | } | |||
569 | else | |||
570 | bValid = false; | |||
571 | } | |||
572 | } | |||
573 | ||||
574 | if (bValid) | |||
575 | { | |||
576 | sc::SetFormulaDirtyContext aCxt; | |||
577 | aCxt.mbClearTabDeletedFlag = bUndoDeleteTab; | |||
578 | aCxt.mnTabDeletedStart = nPos; | |||
579 | aCxt.mnTabDeletedEnd = nPos; | |||
580 | SetAllFormulasDirty(aCxt); | |||
581 | ||||
582 | if (comphelper::LibreOfficeKit::isActive() && GetDrawLayer()) | |||
583 | { | |||
584 | ScModelObj* pModel = comphelper::getUnoTunnelImplementation<ScModelObj>(this->GetDocumentShell()->GetModel()); | |||
585 | SfxLokHelper::notifyDocumentSizeChangedAllViews(pModel); | |||
586 | } | |||
587 | } | |||
588 | ||||
589 | return bValid; | |||
590 | } | |||
591 | ||||
592 | bool ScDocument::InsertTabs( SCTAB nPos, const std::vector<OUString>& rNames, | |||
593 | bool bNamesValid ) | |||
594 | { | |||
595 | SCTAB nNewSheets = static_cast<SCTAB>(rNames.size()); | |||
596 | SCTAB nTabCount = static_cast<SCTAB>(maTabs.size()); | |||
597 | bool bValid = bNamesValid || ValidTab(nTabCount+nNewSheets); | |||
598 | ||||
599 | if (bValid) | |||
600 | { | |||
601 | if (nPos == SC_TAB_APPEND || nPos >= nTabCount) | |||
602 | { | |||
603 | for ( SCTAB i = 0; i < nNewSheets; ++i ) | |||
604 | { | |||
605 | maTabs.emplace_back( new ScTable(*this, nTabCount + i, rNames.at(i)) ); | |||
606 | } | |||
607 | } | |||
608 | else | |||
609 | { | |||
610 | if (ValidTab(nPos) && (nPos < nTabCount)) | |||
611 | { | |||
612 | sc::RefUpdateInsertTabContext aCxt( *this, nPos, nNewSheets); | |||
613 | ScRange aRange( 0,0,nPos, MaxCol(),MaxRow(),MAXTAB ); | |||
614 | xColNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,nNewSheets ); | |||
615 | xRowNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,nNewSheets ); | |||
616 | if (pRangeName) | |||
617 | pRangeName->UpdateInsertTab(aCxt); | |||
618 | pDBCollection->UpdateReference( | |||
619 | URM_INSDEL, 0,0,nPos, MaxCol(),MaxRow(),MAXTAB, 0,0,nNewSheets ); | |||
620 | if (pDPCollection) | |||
621 | pDPCollection->UpdateReference( URM_INSDEL, aRange, 0,0,nNewSheets ); | |||
622 | if (pDetOpList) | |||
623 | pDetOpList->UpdateReference( this, URM_INSDEL, aRange, 0,0,nNewSheets ); | |||
624 | UpdateChartRef( URM_INSDEL, 0,0,nPos, MaxCol(),MaxRow(),MAXTAB, 0,0,nNewSheets ); | |||
625 | UpdateRefAreaLinks( URM_INSDEL, aRange, 0,0, nNewSheets ); | |||
626 | if ( pUnoBroadcaster ) | |||
627 | pUnoBroadcaster->Broadcast( ScUpdateRefHint( URM_INSDEL, aRange, 0,0,nNewSheets ) ); | |||
628 | ||||
629 | for (const auto& a : maTabs) | |||
630 | { | |||
631 | if (a) | |||
632 | a->UpdateInsertTab(aCxt); | |||
633 | } | |||
634 | for (SCTAB i = 0; i < nNewSheets; ++i) | |||
635 | { | |||
636 | maTabs.emplace(maTabs.begin() + nPos + i, new ScTable(*this, nPos + i, rNames.at(i)) ); | |||
637 | } | |||
638 | ||||
639 | // UpdateBroadcastAreas must be called between UpdateInsertTab, | |||
640 | // which ends listening, and StartAllListeners, to not modify | |||
641 | // areas that are to be inserted by starting listeners. | |||
642 | UpdateBroadcastAreas( URM_INSDEL, aRange, 0,0,nNewSheets); | |||
643 | for (const auto& a : maTabs) | |||
644 | { | |||
645 | if (a) | |||
646 | a->UpdateCompile(); | |||
647 | } | |||
648 | ||||
649 | StartAllListeners(); | |||
650 | ||||
651 | if (pValidationList) | |||
652 | { | |||
653 | ScMutationGuard aGuard(*this, ScMutationGuardFlags::CORE); | |||
654 | pValidationList->UpdateInsertTab(aCxt); | |||
655 | } | |||
656 | ||||
657 | bValid = true; | |||
658 | } | |||
659 | else | |||
660 | bValid = false; | |||
661 | } | |||
662 | } | |||
663 | ||||
664 | if (bValid) | |||
665 | { | |||
666 | sc::SetFormulaDirtyContext aCxt; | |||
667 | SetAllFormulasDirty(aCxt); | |||
668 | } | |||
669 | ||||
670 | return bValid; | |||
671 | } | |||
672 | ||||
673 | bool ScDocument::DeleteTab( SCTAB nTab ) | |||
674 | { | |||
675 | bool bValid = false; | |||
676 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size())) | |||
677 | { | |||
678 | if (maTabs[nTab]) | |||
679 | { | |||
680 | SCTAB nTabCount = static_cast<SCTAB>(maTabs.size()); | |||
681 | if (nTabCount > 1) | |||
682 | { | |||
683 | sc::AutoCalcSwitch aACSwitch(*this, false); | |||
684 | sc::RefUpdateDeleteTabContext aCxt( *this, nTab, 1); | |||
685 | ||||
686 | ScRange aRange( 0, 0, nTab, MaxCol(), MaxRow(), nTab ); | |||
687 | DelBroadcastAreasInRange( aRange ); | |||
688 | ||||
689 | // #i8180# remove database ranges etc. that are on the deleted tab | |||
690 | // (restored in undo with ScRefUndoData) | |||
691 | ||||
692 | xColNameRanges->DeleteOnTab( nTab ); | |||
693 | xRowNameRanges->DeleteOnTab( nTab ); | |||
694 | pDBCollection->DeleteOnTab( nTab ); | |||
695 | if (pDPCollection) | |||
696 | pDPCollection->DeleteOnTab( nTab ); | |||
697 | if (pDetOpList) | |||
698 | pDetOpList->DeleteOnTab( nTab ); | |||
699 | DeleteAreaLinksOnTab( nTab ); | |||
700 | ||||
701 | // normal reference update | |||
702 | ||||
703 | aRange.aEnd.SetTab( static_cast<SCTAB>(maTabs.size())-1 ); | |||
704 | xColNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,-1 ); | |||
705 | xRowNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,-1 ); | |||
706 | if (pRangeName) | |||
707 | pRangeName->UpdateDeleteTab(aCxt); | |||
708 | pDBCollection->UpdateReference( | |||
709 | URM_INSDEL, 0,0,nTab, MaxCol(),MaxRow(),MAXTAB, 0,0,-1 ); | |||
710 | if (pDPCollection) | |||
711 | pDPCollection->UpdateReference( URM_INSDEL, aRange, 0,0,-1 ); | |||
712 | if (pDetOpList) | |||
713 | pDetOpList->UpdateReference( this, URM_INSDEL, aRange, 0,0,-1 ); | |||
714 | UpdateChartRef( URM_INSDEL, 0,0,nTab, MaxCol(),MaxRow(),MAXTAB, 0,0,-1 ); | |||
715 | UpdateRefAreaLinks( URM_INSDEL, aRange, 0,0,-1 ); | |||
716 | if (pValidationList) | |||
717 | { | |||
718 | ScMutationGuard aGuard(*this, ScMutationGuardFlags::CORE); | |||
719 | pValidationList->UpdateDeleteTab(aCxt); | |||
720 | } | |||
721 | if ( pUnoBroadcaster ) | |||
722 | pUnoBroadcaster->Broadcast( ScUpdateRefHint( URM_INSDEL, aRange, 0,0,-1 ) ); | |||
723 | ||||
724 | for (auto & pTab : maTabs) | |||
725 | if (pTab) | |||
726 | pTab->UpdateDeleteTab(aCxt); | |||
727 | ||||
728 | maTabs.erase(maTabs.begin() + nTab); | |||
729 | // UpdateBroadcastAreas must be called between UpdateDeleteTab, | |||
730 | // which ends listening, and StartAllListeners, to not modify | |||
731 | // areas that are to be inserted by starting listeners. | |||
732 | UpdateBroadcastAreas( URM_INSDEL, aRange, 0,0,-1); | |||
733 | for (const auto& a : maTabs) | |||
734 | { | |||
735 | if (a) | |||
736 | a->UpdateCompile(); | |||
737 | } | |||
738 | // Excel-Filter deletes some Tables while loading, Listeners will | |||
739 | // only be triggered after the loading is done. | |||
740 | if ( !bInsertingFromOtherDoc ) | |||
741 | { | |||
742 | StartAllListeners(); | |||
743 | ||||
744 | sc::SetFormulaDirtyContext aFormulaDirtyCxt; | |||
745 | SetAllFormulasDirty(aFormulaDirtyCxt); | |||
746 | } | |||
747 | ||||
748 | if (comphelper::LibreOfficeKit::isActive()) | |||
749 | { | |||
750 | ScModelObj* pModel = comphelper::getUnoTunnelImplementation<ScModelObj>(this->GetDocumentShell()->GetModel()); | |||
751 | SfxLokHelper::notifyDocumentSizeChangedAllViews(pModel); | |||
752 | } | |||
753 | ||||
754 | bValid = true; | |||
755 | } | |||
756 | } | |||
757 | } | |||
758 | return bValid; | |||
759 | } | |||
760 | ||||
761 | bool ScDocument::DeleteTabs( SCTAB nTab, SCTAB nSheets ) | |||
762 | { | |||
763 | bool bValid = false; | |||
764 | if (ValidTab(nTab) && (nTab + nSheets) <= static_cast<SCTAB>(maTabs.size())) | |||
765 | { | |||
766 | if (maTabs[nTab]) | |||
767 | { | |||
768 | SCTAB nTabCount = static_cast<SCTAB>(maTabs.size()); | |||
769 | if (nTabCount > nSheets) | |||
770 | { | |||
771 | sc::AutoCalcSwitch aACSwitch(*this, false); | |||
772 | sc::RefUpdateDeleteTabContext aCxt( *this, nTab, nSheets); | |||
773 | ||||
774 | for (SCTAB aTab = 0; aTab < nSheets; ++aTab) | |||
775 | { | |||
776 | ScRange aRange( 0, 0, nTab, MaxCol(), MaxRow(), nTab + aTab ); | |||
777 | DelBroadcastAreasInRange( aRange ); | |||
778 | ||||
779 | // #i8180# remove database ranges etc. that are on the deleted tab | |||
780 | // (restored in undo with ScRefUndoData) | |||
781 | ||||
782 | xColNameRanges->DeleteOnTab( nTab + aTab ); | |||
783 | xRowNameRanges->DeleteOnTab( nTab + aTab ); | |||
784 | pDBCollection->DeleteOnTab( nTab + aTab ); | |||
785 | if (pDPCollection) | |||
786 | pDPCollection->DeleteOnTab( nTab + aTab ); | |||
787 | if (pDetOpList) | |||
788 | pDetOpList->DeleteOnTab( nTab + aTab ); | |||
789 | DeleteAreaLinksOnTab( nTab + aTab ); | |||
790 | } | |||
791 | ||||
792 | if (pRangeName) | |||
793 | pRangeName->UpdateDeleteTab(aCxt); | |||
794 | ||||
795 | // normal reference update | |||
796 | ||||
797 | ScRange aRange( 0, 0, nTab, MaxCol(), MaxRow(), nTabCount - 1 ); | |||
798 | xColNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,-1*nSheets ); | |||
799 | xRowNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,-1*nSheets ); | |||
800 | pDBCollection->UpdateReference( | |||
801 | URM_INSDEL, 0,0,nTab, MaxCol(),MaxRow(),MAXTAB, 0,0,-1*nSheets ); | |||
802 | if (pDPCollection) | |||
803 | pDPCollection->UpdateReference( URM_INSDEL, aRange, 0,0,-1*nSheets ); | |||
804 | if (pDetOpList) | |||
805 | pDetOpList->UpdateReference( this, URM_INSDEL, aRange, 0,0,-1*nSheets ); | |||
806 | UpdateChartRef( URM_INSDEL, 0,0,nTab, MaxCol(),MaxRow(),MAXTAB, 0,0,-1*nSheets ); | |||
807 | UpdateRefAreaLinks( URM_INSDEL, aRange, 0,0,-1*nSheets ); | |||
808 | if (pValidationList) | |||
809 | { | |||
810 | ScMutationGuard aGuard(*this, ScMutationGuardFlags::CORE); | |||
811 | pValidationList->UpdateDeleteTab(aCxt); | |||
812 | } | |||
813 | if ( pUnoBroadcaster ) | |||
814 | pUnoBroadcaster->Broadcast( ScUpdateRefHint( URM_INSDEL, aRange, 0,0,-1*nSheets ) ); | |||
815 | ||||
816 | for (auto & pTab : maTabs) | |||
817 | if (pTab) | |||
818 | pTab->UpdateDeleteTab(aCxt); | |||
819 | ||||
820 | maTabs.erase(maTabs.begin() + nTab, maTabs.begin() + nTab + nSheets); | |||
821 | // UpdateBroadcastAreas must be called between UpdateDeleteTab, | |||
822 | // which ends listening, and StartAllListeners, to not modify | |||
823 | // areas that are to be inserted by starting listeners. | |||
824 | UpdateBroadcastAreas( URM_INSDEL, aRange, 0,0,-1*nSheets); | |||
825 | for (const auto& a : maTabs) | |||
826 | { | |||
827 | if (a) | |||
828 | a->UpdateCompile(); | |||
829 | } | |||
830 | // Excel-Filter deletes some Tables while loading, Listeners will | |||
831 | // only be triggered after the loading is done. | |||
832 | if ( !bInsertingFromOtherDoc ) | |||
833 | { | |||
834 | StartAllListeners(); | |||
835 | ||||
836 | sc::SetFormulaDirtyContext aFormulaDirtyCxt; | |||
837 | SetAllFormulasDirty(aFormulaDirtyCxt); | |||
838 | } | |||
839 | ||||
840 | if (comphelper::LibreOfficeKit::isActive()) | |||
841 | { | |||
842 | ScModelObj* pModel = comphelper::getUnoTunnelImplementation<ScModelObj>(this->GetDocumentShell()->GetModel()); | |||
843 | SfxLokHelper::notifyDocumentSizeChangedAllViews(pModel); | |||
844 | } | |||
845 | ||||
846 | bValid = true; | |||
847 | } | |||
848 | } | |||
849 | } | |||
850 | return bValid; | |||
851 | } | |||
852 | ||||
853 | bool ScDocument::RenameTab( SCTAB nTab, const OUString& rName, bool bExternalDocument ) | |||
854 | { | |||
855 | bool bValid = false; | |||
856 | SCTAB i; | |||
857 | if (ValidTab(nTab)) | |||
858 | { | |||
859 | if (maTabs[nTab]) | |||
860 | { | |||
861 | if ( bExternalDocument ) | |||
862 | bValid = true; // composed name | |||
863 | else | |||
864 | bValid = ValidTabName(rName); | |||
865 | for (i=0; (i< static_cast<SCTAB>(maTabs.size())) && bValid; i++) | |||
866 | if (maTabs[i] && (i != nTab)) | |||
867 | { | |||
868 | OUString aOldName = maTabs[i]->GetName(); | |||
869 | bValid = !ScGlobal::GetpTransliteration()->isEqual( rName, aOldName ); | |||
870 | } | |||
871 | if (bValid) | |||
872 | { | |||
873 | // #i75258# update charts before renaming, so they can get their live data objects. | |||
874 | // Once the charts are live, the sheet can be renamed without problems. | |||
875 | if ( pChartListenerCollection ) | |||
876 | pChartListenerCollection->UpdateChartsContainingTab( nTab ); | |||
877 | maTabs[nTab]->SetName(rName); | |||
878 | ||||
879 | // If formulas refer to the renamed sheet, the TokenArray remains valid, | |||
880 | // but the XML stream must be re-generated. | |||
881 | for (const auto& a : maTabs) | |||
882 | { | |||
883 | if (a) | |||
884 | a->SetStreamValid( false ); | |||
885 | } | |||
886 | ||||
887 | if (comphelper::LibreOfficeKit::isActive() && GetDrawLayer()) | |||
888 | { | |||
889 | ScModelObj* pModel = comphelper::getUnoTunnelImplementation<ScModelObj>(this->GetDocumentShell()->GetModel()); | |||
890 | SfxLokHelper::notifyDocumentSizeChangedAllViews(pModel); | |||
891 | } | |||
892 | } | |||
893 | } | |||
894 | } | |||
895 | ||||
896 | collectUIInformation({{"NewName", rName}}, "Rename_Sheet"); | |||
897 | ||||
898 | return bValid; | |||
899 | } | |||
900 | ||||
901 | void ScDocument::SetVisible( SCTAB nTab, bool bVisible ) | |||
902 | { | |||
903 | if (ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size())) | |||
904 | if (maTabs[nTab]) | |||
905 | maTabs[nTab]->SetVisible(bVisible); | |||
906 | } | |||
907 | ||||
908 | bool ScDocument::IsVisible( SCTAB nTab ) const | |||
909 | { | |||
910 | if (ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size())) | |||
911 | if (maTabs[nTab]) | |||
912 | return maTabs[nTab]->IsVisible(); | |||
913 | ||||
914 | return false; | |||
915 | } | |||
916 | ||||
917 | bool ScDocument::IsStreamValid( SCTAB nTab ) const | |||
918 | { | |||
919 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab] ) | |||
920 | return maTabs[nTab]->IsStreamValid(); | |||
921 | ||||
922 | return false; | |||
923 | } | |||
924 | ||||
925 | void ScDocument::SetStreamValid( SCTAB nTab, bool bSet, bool bIgnoreLock ) | |||
926 | { | |||
927 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab] ) | |||
928 | maTabs[nTab]->SetStreamValid( bSet, bIgnoreLock ); | |||
929 | } | |||
930 | ||||
931 | void ScDocument::LockStreamValid( bool bLock ) | |||
932 | { | |||
933 | mbStreamValidLocked = bLock; | |||
934 | } | |||
935 | ||||
936 | bool ScDocument::IsPendingRowHeights( SCTAB nTab ) const | |||
937 | { | |||
938 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab] ) | |||
939 | return maTabs[nTab]->IsPendingRowHeights(); | |||
940 | ||||
941 | return false; | |||
942 | } | |||
943 | ||||
944 | void ScDocument::SetPendingRowHeights( SCTAB nTab, bool bSet ) | |||
945 | { | |||
946 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab] ) | |||
947 | maTabs[nTab]->SetPendingRowHeights( bSet ); | |||
948 | } | |||
949 | ||||
950 | void ScDocument::SetLayoutRTL( SCTAB nTab, bool bRTL ) | |||
951 | { | |||
952 | if ( !(ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab]) ) | |||
953 | return; | |||
954 | ||||
955 | if ( bImportingXML ) | |||
956 | { | |||
957 | // #i57869# only set the LoadingRTL flag, the real setting (including mirroring) | |||
958 | // is applied in SetImportingXML(false). This is so the shapes can be loaded in | |||
959 | // normal LTR mode. | |||
960 | ||||
961 | maTabs[nTab]->SetLoadingRTL( bRTL ); | |||
962 | return; | |||
963 | } | |||
964 | ||||
965 | maTabs[nTab]->SetLayoutRTL( bRTL ); // only sets the flag | |||
966 | maTabs[nTab]->SetDrawPageSize(); | |||
967 | ||||
968 | // mirror existing objects: | |||
969 | ||||
970 | if (!mpDrawLayer) | |||
971 | return; | |||
972 | ||||
973 | SdrPage* pPage = mpDrawLayer->GetPage(static_cast<sal_uInt16>(nTab)); | |||
974 | OSL_ENSURE(pPage,"Page ?")do { if (true && (!(pPage))) { sal_detail_logFormat(( SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "974" ": "), "%s", "Page ?"); } } while (false); | |||
975 | if (!pPage) | |||
976 | return; | |||
977 | ||||
978 | SdrObjListIter aIter( pPage, SdrIterMode::DeepNoGroups ); | |||
979 | SdrObject* pObject = aIter.Next(); | |||
980 | while (pObject) | |||
981 | { | |||
982 | // objects with ScDrawObjData are re-positioned in SetPageSize, | |||
983 | // don't mirror again | |||
984 | ScDrawObjData* pData = ScDrawLayer::GetObjData( pObject ); | |||
985 | if ( !pData ) | |||
986 | mpDrawLayer->MirrorRTL( pObject ); | |||
987 | ||||
988 | pObject->SetContextWritingMode( bRTL ? WritingMode2::RL_TB : WritingMode2::LR_TB ); | |||
989 | ||||
990 | pObject = aIter.Next(); | |||
991 | } | |||
992 | } | |||
993 | ||||
994 | bool ScDocument::IsLayoutRTL( SCTAB nTab ) const | |||
995 | { | |||
996 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab] ) | |||
997 | return maTabs[nTab]->IsLayoutRTL(); | |||
998 | ||||
999 | return false; | |||
1000 | } | |||
1001 | ||||
1002 | bool ScDocument::IsNegativePage( SCTAB nTab ) const | |||
1003 | { | |||
1004 | // Negative page area is always used for RTL layout. | |||
1005 | // The separate method is used to find all RTL handling of drawing objects. | |||
1006 | return IsLayoutRTL( nTab ); | |||
1007 | } | |||
1008 | ||||
1009 | /* ---------------------------------------------------------------------------- | |||
1010 | used search area: | |||
1011 | ||||
1012 | GetCellArea - Only Data | |||
1013 | GetTableArea - Data / Attributes | |||
1014 | GetPrintArea - intended for character objects, | |||
1015 | sweeps attributes all the way to bottom / right | |||
1016 | ---------------------------------------------------------------------------- */ | |||
1017 | ||||
1018 | bool ScDocument::GetCellArea( SCTAB nTab, SCCOL& rEndCol, SCROW& rEndRow ) const | |||
1019 | { | |||
1020 | if (ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size())) | |||
1021 | if (maTabs[nTab]) | |||
1022 | return maTabs[nTab]->GetCellArea( rEndCol, rEndRow ); | |||
1023 | ||||
1024 | rEndCol = 0; | |||
1025 | rEndRow = 0; | |||
1026 | return false; | |||
1027 | } | |||
1028 | ||||
1029 | bool ScDocument::GetTableArea( SCTAB nTab, SCCOL& rEndCol, SCROW& rEndRow ) const | |||
1030 | { | |||
1031 | if (ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size())) | |||
1032 | if (maTabs[nTab]) | |||
1033 | return maTabs[nTab]->GetTableArea( rEndCol, rEndRow ); | |||
1034 | ||||
1035 | rEndCol = 0; | |||
1036 | rEndRow = 0; | |||
1037 | return false; | |||
1038 | } | |||
1039 | ||||
1040 | bool ScDocument::ShrinkToDataArea(SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow) const | |||
1041 | { | |||
1042 | if (!ValidTab(nTab) || nTab >= static_cast<SCTAB> (maTabs.size()) || !maTabs[nTab]) | |||
1043 | return false; | |||
1044 | ||||
1045 | SCCOL nCol1, nCol2; | |||
1046 | SCROW nRow1, nRow2; | |||
1047 | maTabs[nTab]->GetFirstDataPos(nCol1, nRow1); | |||
1048 | maTabs[nTab]->GetLastDataPos(nCol2, nRow2); | |||
1049 | ||||
1050 | if (nCol1 > nCol2 || nRow1 > nRow2) | |||
1051 | // invalid range. | |||
1052 | return false; | |||
1053 | ||||
1054 | // Make sure the area only shrinks, and doesn't grow. | |||
1055 | if (rStartCol < nCol1) | |||
1056 | rStartCol = nCol1; | |||
1057 | if (nCol2 < rEndCol) | |||
1058 | rEndCol = nCol2; | |||
1059 | if (rStartRow < nRow1) | |||
1060 | rStartRow = nRow1; | |||
1061 | if (nRow2 < rEndRow) | |||
1062 | rEndRow = nRow2; | |||
1063 | ||||
1064 | if (rStartCol > rEndCol || rStartRow > rEndRow) | |||
1065 | // invalid range. | |||
1066 | return false; | |||
1067 | ||||
1068 | return true; // success! | |||
1069 | } | |||
1070 | ||||
1071 | bool ScDocument::ShrinkToUsedDataArea( bool& o_bShrunk, SCTAB nTab, SCCOL& rStartCol, | |||
1072 | SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly, | |||
1073 | bool bStickyTopRow, bool bStickyLeftCol, bool bConsiderCellNotes, | |||
1074 | bool bConsiderCellDrawObjects ) const | |||
1075 | { | |||
1076 | if (!ValidTab(nTab) || nTab >= static_cast<SCTAB> (maTabs.size()) || !maTabs[nTab]) | |||
1077 | { | |||
1078 | o_bShrunk = false; | |||
1079 | return false; | |||
1080 | } | |||
1081 | return maTabs[nTab]->ShrinkToUsedDataArea( o_bShrunk, rStartCol, rStartRow, rEndCol, rEndRow, | |||
1082 | bColumnsOnly, bStickyTopRow, bStickyLeftCol, bConsiderCellNotes, bConsiderCellDrawObjects ); | |||
1083 | } | |||
1084 | ||||
1085 | SCROW ScDocument::GetLastDataRow( SCTAB nTab, SCCOL nCol1, SCCOL nCol2, SCROW nLastRow ) const | |||
1086 | { | |||
1087 | const ScTable* pTab = FetchTable(nTab); | |||
1088 | if (!pTab) | |||
1089 | return -1; | |||
1090 | ||||
1091 | return pTab->GetLastDataRow(nCol1, nCol2, nLastRow); | |||
1092 | } | |||
1093 | ||||
1094 | // connected area | |||
1095 | ||||
1096 | void ScDocument::GetDataArea( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow, | |||
1097 | SCCOL& rEndCol, SCROW& rEndRow, bool bIncludeOld, bool bOnlyDown ) const | |||
1098 | { | |||
1099 | if (ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab]) | |||
1100 | maTabs[nTab]->GetDataArea( rStartCol, rStartRow, rEndCol, rEndRow, bIncludeOld, bOnlyDown ); | |||
1101 | } | |||
1102 | ||||
1103 | bool ScDocument::GetDataAreaSubrange(ScRange& rRange) const | |||
1104 | { | |||
1105 | SCTAB nTab = rRange.aStart.Tab(); | |||
1106 | if (nTab != rRange.aEnd.Tab()) | |||
1107 | return true; | |||
1108 | ||||
1109 | if (ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab]) | |||
1110 | return maTabs[nTab]->GetDataAreaSubrange(rRange); | |||
1111 | ||||
1112 | return true; | |||
1113 | } | |||
1114 | ||||
1115 | void ScDocument::LimitChartArea( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow, | |||
1116 | SCCOL& rEndCol, SCROW& rEndRow ) | |||
1117 | { | |||
1118 | if (ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size())) | |||
1119 | if (maTabs[nTab]) | |||
1120 | maTabs[nTab]->LimitChartArea( rStartCol, rStartRow, rEndCol, rEndRow ); | |||
1121 | } | |||
1122 | ||||
1123 | void ScDocument::LimitChartIfAll( ScRangeListRef& rRangeList ) | |||
1124 | { | |||
1125 | ScRangeListRef aNew = new ScRangeList; | |||
1126 | if (rRangeList.is()) | |||
1127 | { | |||
1128 | for ( size_t i = 0, nCount = rRangeList->size(); i < nCount; i++ ) | |||
1129 | { | |||
1130 | ScRange aRange( (*rRangeList)[i] ); | |||
1131 | if ( ( aRange.aStart.Col() == 0 && aRange.aEnd.Col() == MaxCol() ) || | |||
1132 | ( aRange.aStart.Row() == 0 && aRange.aEnd.Row() == MaxRow() ) ) | |||
1133 | { | |||
1134 | SCCOL nStartCol = aRange.aStart.Col(); | |||
1135 | SCROW nStartRow = aRange.aStart.Row(); | |||
1136 | SCCOL nEndCol = aRange.aEnd.Col(); | |||
1137 | SCROW nEndRow = aRange.aEnd.Row(); | |||
1138 | SCTAB nTab = aRange.aStart.Tab(); | |||
1139 | if ( nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab]) | |||
1140 | maTabs[nTab]->LimitChartArea(nStartCol, nStartRow, nEndCol, nEndRow); | |||
1141 | aRange.aStart.SetCol( nStartCol ); | |||
1142 | aRange.aStart.SetRow( nStartRow ); | |||
1143 | aRange.aEnd.SetCol( nEndCol ); | |||
1144 | aRange.aEnd.SetRow( nEndRow ); | |||
1145 | } | |||
1146 | aNew->push_back(aRange); | |||
1147 | } | |||
1148 | } | |||
1149 | else | |||
1150 | { | |||
1151 | OSL_FAIL("LimitChartIfAll: Ref==0")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "1151" ": "), "%s", "LimitChartIfAll: Ref==0"); } } while (false); | |||
1152 | } | |||
1153 | rRangeList = aNew; | |||
1154 | } | |||
1155 | ||||
1156 | static void lcl_GetFirstTabRange( SCTAB& rTabRangeStart, SCTAB& rTabRangeEnd, const ScMarkData* pTabMark, SCTAB aMaxTab ) | |||
1157 | { | |||
1158 | // without ScMarkData, leave start/end unchanged | |||
1159 | if ( !pTabMark ) | |||
1160 | return; | |||
1161 | ||||
1162 | for (SCTAB nTab=0; nTab< aMaxTab; ++nTab) | |||
1163 | if (pTabMark->GetTableSelect(nTab)) | |||
1164 | { | |||
1165 | // find first range of consecutive selected sheets | |||
1166 | rTabRangeStart = pTabMark->GetFirstSelected(); | |||
1167 | while ( nTab+1 < aMaxTab && pTabMark->GetTableSelect(nTab+1) ) | |||
1168 | ++nTab; | |||
1169 | rTabRangeEnd = nTab; | |||
1170 | return; | |||
1171 | } | |||
1172 | } | |||
1173 | ||||
1174 | static bool lcl_GetNextTabRange( SCTAB& rTabRangeStart, SCTAB& rTabRangeEnd, const ScMarkData* pTabMark, SCTAB aMaxTab ) | |||
1175 | { | |||
1176 | if ( pTabMark ) | |||
1177 | { | |||
1178 | // find next range of consecutive selected sheets after rTabRangeEnd | |||
1179 | for (SCTAB nTab=rTabRangeEnd+1; nTab< aMaxTab; ++nTab) | |||
1180 | if (pTabMark->GetTableSelect(nTab)) | |||
1181 | { | |||
1182 | rTabRangeStart = nTab; | |||
1183 | while ( nTab+1 < aMaxTab && pTabMark->GetTableSelect(nTab+1) ) | |||
1184 | ++nTab; | |||
1185 | rTabRangeEnd = nTab; | |||
1186 | return true; | |||
1187 | } | |||
1188 | } | |||
1189 | return false; | |||
1190 | } | |||
1191 | ||||
1192 | bool ScDocument::CanInsertRow( const ScRange& rRange ) const | |||
1193 | { | |||
1194 | SCCOL nStartCol = rRange.aStart.Col(); | |||
1195 | SCROW nStartRow = rRange.aStart.Row(); | |||
1196 | SCTAB nStartTab = rRange.aStart.Tab(); | |||
1197 | SCCOL nEndCol = rRange.aEnd.Col(); | |||
1198 | SCROW nEndRow = rRange.aEnd.Row(); | |||
1199 | SCTAB nEndTab = rRange.aEnd.Tab(); | |||
1200 | PutInOrder( nStartCol, nEndCol ); | |||
1201 | PutInOrder( nStartRow, nEndRow ); | |||
1202 | PutInOrder( nStartTab, nEndTab ); | |||
1203 | SCSIZE nSize = static_cast<SCSIZE>(nEndRow - nStartRow + 1); | |||
1204 | ||||
1205 | bool bTest = true; | |||
1206 | for (SCTAB i=nStartTab; i<=nEndTab && bTest && i < static_cast<SCTAB>(maTabs.size()); i++) | |||
1207 | if (maTabs[i]) | |||
1208 | bTest &= maTabs[i]->TestInsertRow( nStartCol, nEndCol, nStartRow, nSize ); | |||
1209 | ||||
1210 | return bTest; | |||
1211 | } | |||
1212 | ||||
1213 | namespace { | |||
1214 | ||||
1215 | struct SetDirtyIfPostponedHandler | |||
1216 | { | |||
1217 | void operator() (const ScTableUniquePtr & p) | |||
1218 | { | |||
1219 | if (p) | |||
1220 | p->SetDirtyIfPostponed(); | |||
1221 | } | |||
1222 | }; | |||
1223 | ||||
1224 | struct BroadcastRecalcOnRefMoveHandler | |||
1225 | { | |||
1226 | void operator() (const ScTableUniquePtr & p) | |||
1227 | { | |||
1228 | if (p) | |||
1229 | p->BroadcastRecalcOnRefMove(); | |||
1230 | } | |||
1231 | }; | |||
1232 | ||||
1233 | struct BroadcastRecalcOnRefMoveGuard | |||
1234 | { | |||
1235 | explicit BroadcastRecalcOnRefMoveGuard( ScDocument* pDoc ) : | |||
1236 | aSwitch( *pDoc, false), | |||
1237 | aBulk( pDoc->GetBASM(), SfxHintId::ScDataChanged) | |||
1238 | { | |||
1239 | } | |||
1240 | ||||
1241 | private: | |||
1242 | sc::AutoCalcSwitch aSwitch; // first for ctor/dtor order, destroy second | |||
1243 | ScBulkBroadcast aBulk; // second for ctor/dtor order, destroy first | |||
1244 | }; | |||
1245 | ||||
1246 | } | |||
1247 | ||||
1248 | bool ScDocument::InsertRow( SCCOL nStartCol, SCTAB nStartTab, | |||
1249 | SCCOL nEndCol, SCTAB nEndTab, | |||
1250 | SCROW nStartRow, SCSIZE nSize, ScDocument* pRefUndoDoc, | |||
1251 | const ScMarkData* pTabMark ) | |||
1252 | { | |||
1253 | SCTAB i; | |||
1254 | ||||
1255 | PutInOrder( nStartCol, nEndCol ); | |||
1256 | PutInOrder( nStartTab, nEndTab ); | |||
1257 | if ( pTabMark ) | |||
1258 | { | |||
1259 | nStartTab = 0; | |||
1260 | nEndTab = static_cast<SCTAB>(maTabs.size()) -1; | |||
1261 | } | |||
1262 | ||||
1263 | bool bTest = true; | |||
1264 | bool bRet = false; | |||
1265 | bool bOldAutoCalc = GetAutoCalc(); | |||
1266 | SetAutoCalc( false ); // avoid multiple calculations | |||
1267 | for ( i = nStartTab; i <= nEndTab && bTest && i < static_cast<SCTAB>(maTabs.size()); i++) | |||
1268 | if (maTabs[i] && (!pTabMark || pTabMark->GetTableSelect(i))) | |||
1269 | bTest &= maTabs[i]->TestInsertRow(nStartCol, nEndCol, nStartRow, nSize); | |||
1270 | if (bTest) | |||
1271 | { | |||
1272 | // UpdateBroadcastAreas have to be called before UpdateReference, so that entries | |||
1273 | // aren't shifted that would be rebuild at UpdateReference | |||
1274 | ||||
1275 | // handle chunks of consecutive selected sheets together | |||
1276 | SCTAB nTabRangeStart = nStartTab; | |||
1277 | SCTAB nTabRangeEnd = nEndTab; | |||
1278 | lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ); | |||
1279 | ScRange aShiftedRange(nStartCol, nStartRow, nTabRangeStart, nEndCol, MaxRow(), nTabRangeEnd); | |||
1280 | sc::EndListeningContext aEndListenCxt(*this); | |||
1281 | ||||
1282 | std::vector<ScAddress> aGroupPos; | |||
1283 | do | |||
1284 | { | |||
1285 | aShiftedRange.aStart.SetTab(nTabRangeStart); | |||
1286 | aShiftedRange.aEnd.SetTab(nTabRangeEnd); | |||
1287 | ||||
1288 | // Collect all formula groups that will get split by the shifting, | |||
1289 | // and end all their listening. Record the position of the top | |||
1290 | // cell of the topmost group, and the position of the bottom cell | |||
1291 | // of the bottommost group. | |||
1292 | EndListeningIntersectedGroups(aEndListenCxt, aShiftedRange, &aGroupPos); | |||
1293 | ||||
1294 | UpdateBroadcastAreas(URM_INSDEL, aShiftedRange, 0, static_cast<SCROW>(nSize), 0); | |||
1295 | } | |||
1296 | while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) ); | |||
1297 | ||||
1298 | lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ); | |||
1299 | ||||
1300 | sc::RefUpdateContext aCxt(*this); | |||
1301 | aCxt.meMode = URM_INSDEL; | |||
1302 | aCxt.maRange = aShiftedRange; | |||
1303 | aCxt.mnRowDelta = nSize; | |||
1304 | do | |||
1305 | { | |||
1306 | aCxt.maRange.aStart.SetTab(nTabRangeStart); | |||
1307 | aCxt.maRange.aEnd.SetTab(nTabRangeEnd); | |||
1308 | UpdateReference(aCxt, pRefUndoDoc, false); // without drawing objects | |||
1309 | } | |||
1310 | while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) ); | |||
1311 | ||||
1312 | // UpdateReference should have set "needs listening" flags to those | |||
1313 | // whose references have been modified. We also need to set this flag | |||
1314 | // to those that were in the groups that got split by shifting. | |||
1315 | SetNeedsListeningGroups(aGroupPos); | |||
1316 | ||||
1317 | for (i=nStartTab; i<=nEndTab && i < static_cast<SCTAB>(maTabs.size()); i++) | |||
1318 | if (maTabs[i] && (!pTabMark || pTabMark->GetTableSelect(i))) | |||
1319 | maTabs[i]->InsertRow( nStartCol, nEndCol, nStartRow, nSize ); | |||
1320 | ||||
1321 | // UpdateRef for drawing layer must be after inserting, | |||
1322 | // when the new row heights are known. | |||
1323 | for (i=nStartTab; i<=nEndTab && i < static_cast<SCTAB>(maTabs.size()); i++) | |||
1324 | if (maTabs[i] && (!pTabMark || pTabMark->GetTableSelect(i))) | |||
1325 | maTabs[i]->UpdateDrawRef( URM_INSDEL, | |||
1326 | nStartCol, nStartRow, nStartTab, nEndCol, MaxRow(), nEndTab, | |||
1327 | 0, static_cast<SCROW>(nSize), 0 ); | |||
1328 | ||||
1329 | if ( pChangeTrack && pChangeTrack->IsInDeleteUndo() ) | |||
1330 | { // A new Listening is needed when references to deleted ranges are restored, | |||
1331 | // previous Listeners were removed in FormulaCell UpdateReference. | |||
1332 | StartAllListeners(); | |||
1333 | } | |||
1334 | else | |||
1335 | { // Listeners have been removed in UpdateReference | |||
1336 | StartNeededListeners(); | |||
1337 | ||||
1338 | // At least all cells using range names pointing relative to the | |||
1339 | // moved range must be recalculated, and all cells marked postponed | |||
1340 | // dirty. | |||
1341 | for (const auto& a : maTabs) | |||
1342 | { | |||
1343 | if (a) | |||
1344 | a->SetDirtyIfPostponed(); | |||
1345 | } | |||
1346 | ||||
1347 | { | |||
1348 | BroadcastRecalcOnRefMoveGuard g(this); | |||
1349 | std::for_each(maTabs.begin(), maTabs.end(), BroadcastRecalcOnRefMoveHandler()); | |||
1350 | } | |||
1351 | } | |||
1352 | bRet = true; | |||
1353 | } | |||
1354 | SetAutoCalc( bOldAutoCalc ); | |||
1355 | if ( bRet && pChartListenerCollection ) | |||
1356 | pChartListenerCollection->UpdateDirtyCharts(); | |||
1357 | return bRet; | |||
1358 | } | |||
1359 | ||||
1360 | bool ScDocument::InsertRow( const ScRange& rRange ) | |||
1361 | { | |||
1362 | return InsertRow( rRange.aStart.Col(), rRange.aStart.Tab(), | |||
1363 | rRange.aEnd.Col(), rRange.aEnd.Tab(), | |||
1364 | rRange.aStart.Row(), static_cast<SCSIZE>(rRange.aEnd.Row()-rRange.aStart.Row()+1) ); | |||
1365 | } | |||
1366 | ||||
1367 | void ScDocument::DeleteRow( SCCOL nStartCol, SCTAB nStartTab, | |||
1368 | SCCOL nEndCol, SCTAB nEndTab, | |||
1369 | SCROW nStartRow, SCSIZE nSize, | |||
1370 | ScDocument* pRefUndoDoc, bool* pUndoOutline, | |||
1371 | const ScMarkData* pTabMark ) | |||
1372 | { | |||
1373 | SCTAB i; | |||
1374 | ||||
1375 | PutInOrder( nStartCol, nEndCol ); | |||
1376 | PutInOrder( nStartTab, nEndTab ); | |||
1377 | if ( pTabMark ) | |||
1378 | { | |||
1379 | nStartTab = 0; | |||
1380 | nEndTab = static_cast<SCTAB>(maTabs.size())-1; | |||
1381 | } | |||
1382 | ||||
1383 | sc::AutoCalcSwitch aACSwitch(*this, false); // avoid multiple calculations | |||
1384 | ||||
1385 | // handle chunks of consecutive selected sheets together | |||
1386 | SCTAB nTabRangeStart = nStartTab; | |||
1387 | SCTAB nTabRangeEnd = nEndTab; | |||
1388 | lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ); | |||
1389 | do | |||
1390 | { | |||
1391 | if ( ValidRow(nStartRow+nSize) ) | |||
1392 | { | |||
1393 | DelBroadcastAreasInRange( ScRange( | |||
1394 | ScAddress( nStartCol, nStartRow, nTabRangeStart ), | |||
1395 | ScAddress( nEndCol, nStartRow+nSize-1, nTabRangeEnd ) ) ); | |||
1396 | UpdateBroadcastAreas( URM_INSDEL, ScRange( | |||
1397 | ScAddress( nStartCol, nStartRow+nSize, nTabRangeStart ), | |||
1398 | ScAddress( nEndCol, MaxRow(), nTabRangeEnd )), 0, -static_cast<SCROW>(nSize), 0 ); | |||
1399 | } | |||
1400 | else | |||
1401 | DelBroadcastAreasInRange( ScRange( | |||
1402 | ScAddress( nStartCol, nStartRow, nTabRangeStart ), | |||
1403 | ScAddress( nEndCol, MaxRow(), nTabRangeEnd ) ) ); | |||
1404 | } | |||
1405 | while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) ); | |||
1406 | ||||
1407 | sc::RefUpdateContext aCxt(*this); | |||
1408 | const bool bLastRowIncluded = (static_cast<SCROW>(nStartRow + nSize) == GetSheetLimits().GetMaxRowCount() && ValidRow(nStartRow)); | |||
1409 | if ( ValidRow(nStartRow+nSize) || bLastRowIncluded ) | |||
1410 | { | |||
1411 | lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ); | |||
1412 | aCxt.meMode = URM_INSDEL; | |||
1413 | aCxt.mnRowDelta = -static_cast<SCROW>(nSize); | |||
1414 | if (bLastRowIncluded) | |||
1415 | { | |||
1416 | // Last row is included, shift a virtually non-existent row in. | |||
1417 | aCxt.maRange = ScRange( nStartCol, GetSheetLimits().GetMaxRowCount(), nTabRangeStart, nEndCol, GetSheetLimits().GetMaxRowCount(), nTabRangeEnd); | |||
1418 | } | |||
1419 | else | |||
1420 | { | |||
1421 | aCxt.maRange = ScRange( nStartCol, nStartRow+nSize, nTabRangeStart, nEndCol, MaxRow(), nTabRangeEnd); | |||
1422 | } | |||
1423 | do | |||
1424 | { | |||
1425 | UpdateReference(aCxt, pRefUndoDoc, true, false); | |||
1426 | } | |||
1427 | while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) ); | |||
1428 | } | |||
1429 | ||||
1430 | if (pUndoOutline) | |||
1431 | *pUndoOutline = false; | |||
1432 | ||||
1433 | // Keep track of the positions of all formula groups that have been joined | |||
1434 | // during row deletion. | |||
1435 | std::vector<ScAddress> aGroupPos; | |||
1436 | ||||
1437 | for ( i = nStartTab; i <= nEndTab && i < static_cast<SCTAB>(maTabs.size()); i++) | |||
1438 | if (maTabs[i] && (!pTabMark || pTabMark->GetTableSelect(i))) | |||
1439 | maTabs[i]->DeleteRow(aCxt.maRegroupCols, nStartCol, nEndCol, nStartRow, nSize, pUndoOutline, &aGroupPos); | |||
1440 | ||||
1441 | // Newly joined groups have some of their members still listening. We | |||
1442 | // need to make sure none of them are listening. | |||
1443 | EndListeningGroups(aGroupPos); | |||
1444 | ||||
1445 | // Mark all joined groups for group listening. | |||
1446 | SetNeedsListeningGroups(aGroupPos); | |||
1447 | ||||
1448 | if ( ValidRow(nStartRow+nSize) || bLastRowIncluded ) | |||
1449 | { | |||
1450 | // Listeners have been removed in UpdateReference | |||
1451 | StartNeededListeners(); | |||
1452 | ||||
1453 | // At least all cells using range names pointing relative to the moved | |||
1454 | // range must be recalculated, and all cells marked postponed dirty. | |||
1455 | for (const auto& a : maTabs) | |||
1456 | { | |||
1457 | if (a) | |||
1458 | a->SetDirtyIfPostponed(); | |||
1459 | } | |||
1460 | ||||
1461 | { | |||
1462 | BroadcastRecalcOnRefMoveGuard g(this); | |||
1463 | std::for_each(maTabs.begin(), maTabs.end(), BroadcastRecalcOnRefMoveHandler()); | |||
1464 | } | |||
1465 | } | |||
1466 | ||||
1467 | if (pChartListenerCollection) | |||
1468 | pChartListenerCollection->UpdateDirtyCharts(); | |||
1469 | } | |||
1470 | ||||
1471 | void ScDocument::DeleteRow( const ScRange& rRange ) | |||
1472 | { | |||
1473 | DeleteRow( rRange.aStart.Col(), rRange.aStart.Tab(), | |||
1474 | rRange.aEnd.Col(), rRange.aEnd.Tab(), | |||
1475 | rRange.aStart.Row(), static_cast<SCSIZE>(rRange.aEnd.Row()-rRange.aStart.Row()+1) ); | |||
1476 | } | |||
1477 | ||||
1478 | bool ScDocument::CanInsertCol( const ScRange& rRange ) const | |||
1479 | { | |||
1480 | SCCOL nStartCol = rRange.aStart.Col(); | |||
1481 | SCROW nStartRow = rRange.aStart.Row(); | |||
1482 | SCTAB nStartTab = rRange.aStart.Tab(); | |||
1483 | SCCOL nEndCol = rRange.aEnd.Col(); | |||
1484 | SCROW nEndRow = rRange.aEnd.Row(); | |||
1485 | SCTAB nEndTab = rRange.aEnd.Tab(); | |||
1486 | PutInOrder( nStartCol, nEndCol ); | |||
1487 | PutInOrder( nStartRow, nEndRow ); | |||
1488 | PutInOrder( nStartTab, nEndTab ); | |||
1489 | SCSIZE nSize = static_cast<SCSIZE>(nEndCol - nStartCol + 1); | |||
1490 | ||||
1491 | bool bTest = true; | |||
1492 | for (SCTAB i=nStartTab; i<=nEndTab && bTest && i < static_cast<SCTAB>(maTabs.size()); i++) | |||
1493 | if (maTabs[i]) | |||
1494 | bTest &= maTabs[i]->TestInsertCol( nStartRow, nEndRow, nSize ); | |||
1495 | ||||
1496 | return bTest; | |||
1497 | } | |||
1498 | ||||
1499 | bool ScDocument::InsertCol( SCROW nStartRow, SCTAB nStartTab, | |||
1500 | SCROW nEndRow, SCTAB nEndTab, | |||
1501 | SCCOL nStartCol, SCSIZE nSize, ScDocument* pRefUndoDoc, | |||
1502 | const ScMarkData* pTabMark ) | |||
1503 | { | |||
1504 | SCTAB i; | |||
1505 | ||||
1506 | PutInOrder( nStartRow, nEndRow ); | |||
1507 | PutInOrder( nStartTab, nEndTab ); | |||
1508 | if ( pTabMark ) | |||
1509 | { | |||
1510 | nStartTab = 0; | |||
1511 | nEndTab = static_cast<SCTAB>(maTabs.size())-1; | |||
1512 | } | |||
1513 | ||||
1514 | bool bTest = true; | |||
1515 | bool bRet = false; | |||
1516 | bool bOldAutoCalc = GetAutoCalc(); | |||
1517 | SetAutoCalc( false ); // avoid multiple calculations | |||
1518 | for ( i = nStartTab; i <= nEndTab && bTest && i < static_cast<SCTAB>(maTabs.size()); i++) | |||
1519 | if (maTabs[i] && (!pTabMark || pTabMark->GetTableSelect(i))) | |||
1520 | bTest &= maTabs[i]->TestInsertCol( nStartRow, nEndRow, nSize ); | |||
1521 | if (bTest) | |||
1522 | { | |||
1523 | // handle chunks of consecutive selected sheets together | |||
1524 | SCTAB nTabRangeStart = nStartTab; | |||
1525 | SCTAB nTabRangeEnd = nEndTab; | |||
1526 | lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ); | |||
1527 | do | |||
1528 | { | |||
1529 | UpdateBroadcastAreas( URM_INSDEL, ScRange( | |||
1530 | ScAddress( nStartCol, nStartRow, nTabRangeStart ), | |||
1531 | ScAddress( MaxCol(), nEndRow, nTabRangeEnd )), static_cast<SCCOL>(nSize), 0, 0 ); | |||
1532 | } | |||
1533 | while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) ); | |||
1534 | ||||
1535 | lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ); | |||
1536 | ||||
1537 | sc::RefUpdateContext aCxt(*this); | |||
1538 | aCxt.meMode = URM_INSDEL; | |||
1539 | aCxt.maRange = ScRange(nStartCol, nStartRow, nTabRangeStart, MaxCol(), nEndRow, nTabRangeEnd); | |||
1540 | aCxt.mnColDelta = nSize; | |||
1541 | do | |||
1542 | { | |||
1543 | UpdateReference(aCxt, pRefUndoDoc, true, false); | |||
1544 | } | |||
1545 | while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) ); | |||
1546 | ||||
1547 | for (i=nStartTab; i<=nEndTab && i < static_cast<SCTAB>(maTabs.size()); i++) | |||
1548 | if (maTabs[i] && (!pTabMark || pTabMark->GetTableSelect(i))) | |||
1549 | maTabs[i]->InsertCol(aCxt.maRegroupCols, nStartCol, nStartRow, nEndRow, nSize); | |||
1550 | ||||
1551 | if ( pChangeTrack && pChangeTrack->IsInDeleteUndo() ) | |||
1552 | { // A new Listening is needed when references to deleted ranges are restored, | |||
1553 | // previous Listeners were removed in FormulaCell UpdateReference. | |||
1554 | StartAllListeners(); | |||
1555 | } | |||
1556 | else | |||
1557 | { | |||
1558 | // Listeners have been removed in UpdateReference | |||
1559 | StartNeededListeners(); | |||
1560 | // At least all cells using range names pointing relative to the | |||
1561 | // moved range must be recalculated, and all cells marked postponed | |||
1562 | // dirty. | |||
1563 | std::for_each(maTabs.begin(), maTabs.end(), SetDirtyIfPostponedHandler()); | |||
1564 | // Cells containing functions such as CELL, COLUMN or ROW may have | |||
1565 | // changed their values on relocation. Broadcast them. | |||
1566 | { | |||
1567 | BroadcastRecalcOnRefMoveGuard g(this); | |||
1568 | std::for_each(maTabs.begin(), maTabs.end(), BroadcastRecalcOnRefMoveHandler()); | |||
1569 | } | |||
1570 | } | |||
1571 | bRet = true; | |||
1572 | } | |||
1573 | SetAutoCalc( bOldAutoCalc ); | |||
1574 | if ( bRet && pChartListenerCollection ) | |||
1575 | pChartListenerCollection->UpdateDirtyCharts(); | |||
1576 | return bRet; | |||
1577 | } | |||
1578 | ||||
1579 | bool ScDocument::InsertCol( const ScRange& rRange ) | |||
1580 | { | |||
1581 | return InsertCol( rRange.aStart.Row(), rRange.aStart.Tab(), | |||
1582 | rRange.aEnd.Row(), rRange.aEnd.Tab(), | |||
1583 | rRange.aStart.Col(), static_cast<SCSIZE>(rRange.aEnd.Col()-rRange.aStart.Col()+1) ); | |||
1584 | } | |||
1585 | ||||
1586 | void ScDocument::DeleteCol(SCROW nStartRow, SCTAB nStartTab, SCROW nEndRow, SCTAB nEndTab, | |||
1587 | SCCOL nStartCol, SCSIZE nSize, ScDocument* pRefUndoDoc, | |||
1588 | bool* pUndoOutline, const ScMarkData* pTabMark ) | |||
1589 | { | |||
1590 | SCTAB i; | |||
1591 | ||||
1592 | PutInOrder( nStartRow, nEndRow ); | |||
1593 | PutInOrder( nStartTab, nEndTab ); | |||
1594 | if ( pTabMark ) | |||
1595 | { | |||
1596 | nStartTab = 0; | |||
1597 | nEndTab = static_cast<SCTAB>(maTabs.size())-1; | |||
1598 | } | |||
1599 | ||||
1600 | sc::AutoCalcSwitch aACSwitch(*this, false); // avoid multiple calculations | |||
1601 | ||||
1602 | // handle chunks of consecutive selected sheets together | |||
1603 | SCTAB nTabRangeStart = nStartTab; | |||
1604 | SCTAB nTabRangeEnd = nEndTab; | |||
1605 | lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ); | |||
1606 | do | |||
1607 | { | |||
1608 | if ( ValidCol(sal::static_int_cast<SCCOL>(nStartCol+nSize)) ) | |||
1609 | { | |||
1610 | DelBroadcastAreasInRange( ScRange( | |||
1611 | ScAddress( nStartCol, nStartRow, nTabRangeStart ), | |||
1612 | ScAddress( sal::static_int_cast<SCCOL>(nStartCol+nSize-1), nEndRow, nTabRangeEnd ) ) ); | |||
1613 | UpdateBroadcastAreas( URM_INSDEL, ScRange( | |||
1614 | ScAddress( sal::static_int_cast<SCCOL>(nStartCol+nSize), nStartRow, nTabRangeStart ), | |||
1615 | ScAddress( MaxCol(), nEndRow, nTabRangeEnd )), -static_cast<SCCOL>(nSize), 0, 0 ); | |||
1616 | } | |||
1617 | else | |||
1618 | DelBroadcastAreasInRange( ScRange( | |||
1619 | ScAddress( nStartCol, nStartRow, nTabRangeStart ), | |||
1620 | ScAddress( MaxCol(), nEndRow, nTabRangeEnd ) ) ); | |||
1621 | } | |||
1622 | while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) ); | |||
1623 | ||||
1624 | sc::RefUpdateContext aCxt(*this); | |||
1625 | const bool bLastColIncluded = (nStartCol + nSize == MAXCOLCOUNT && ValidCol(nStartCol)); | |||
1626 | if ( ValidCol(sal::static_int_cast<SCCOL>(nStartCol+nSize)) || bLastColIncluded ) | |||
1627 | { | |||
1628 | lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ); | |||
1629 | aCxt.meMode = URM_INSDEL; | |||
1630 | aCxt.mnColDelta = -static_cast<SCCOL>(nSize); | |||
1631 | if (bLastColIncluded) | |||
1632 | { | |||
1633 | // Last column is included, shift a virtually non-existent column in. | |||
1634 | aCxt.maRange = ScRange( MAXCOLCOUNT, nStartRow, nTabRangeStart, MAXCOLCOUNT, nEndRow, nTabRangeEnd); | |||
1635 | } | |||
1636 | else | |||
1637 | { | |||
1638 | aCxt.maRange = ScRange( sal::static_int_cast<SCCOL>(nStartCol+nSize), nStartRow, nTabRangeStart, | |||
1639 | MaxCol(), nEndRow, nTabRangeEnd); | |||
1640 | } | |||
1641 | do | |||
1642 | { | |||
1643 | UpdateReference(aCxt, pRefUndoDoc, true, false); | |||
1644 | } | |||
1645 | while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) ); | |||
1646 | } | |||
1647 | ||||
1648 | if (pUndoOutline) | |||
1649 | *pUndoOutline = false; | |||
1650 | ||||
1651 | for (i = nStartTab; i <= nEndTab && i < static_cast<SCTAB>(maTabs.size()); ++i) | |||
1652 | { | |||
1653 | if (maTabs[i] && (!pTabMark || pTabMark->GetTableSelect(i))) | |||
1654 | maTabs[i]->DeleteCol(aCxt.maRegroupCols, nStartCol, nStartRow, nEndRow, nSize, pUndoOutline); | |||
1655 | } | |||
1656 | ||||
1657 | if ( ValidCol(sal::static_int_cast<SCCOL>(nStartCol+nSize)) || bLastColIncluded ) | |||
1658 | { | |||
1659 | // Listeners have been removed in UpdateReference | |||
1660 | StartNeededListeners(); | |||
1661 | ||||
1662 | // At least all cells using range names pointing relative to the moved | |||
1663 | // range must be recalculated, and all cells marked postponed dirty. | |||
1664 | for (const auto& a : maTabs) | |||
1665 | { | |||
1666 | if (a) | |||
1667 | a->SetDirtyIfPostponed(); | |||
1668 | } | |||
1669 | ||||
1670 | { | |||
1671 | BroadcastRecalcOnRefMoveGuard g(this); | |||
1672 | std::for_each(maTabs.begin(), maTabs.end(), BroadcastRecalcOnRefMoveHandler()); | |||
1673 | } | |||
1674 | } | |||
1675 | ||||
1676 | if (pChartListenerCollection) | |||
1677 | pChartListenerCollection->UpdateDirtyCharts(); | |||
1678 | } | |||
1679 | ||||
1680 | void ScDocument::DeleteCol( const ScRange& rRange ) | |||
1681 | { | |||
1682 | DeleteCol( rRange.aStart.Row(), rRange.aStart.Tab(), | |||
1683 | rRange.aEnd.Row(), rRange.aEnd.Tab(), | |||
1684 | rRange.aStart.Col(), static_cast<SCSIZE>(rRange.aEnd.Col()-rRange.aStart.Col()+1) ); | |||
1685 | } | |||
1686 | ||||
1687 | // for Area-Links: Insert/delete cells, when the range is changed. | |||
1688 | // (without Paint) | |||
1689 | ||||
1690 | static void lcl_GetInsDelRanges( const ScRange& rOld, const ScRange& rNew, | |||
1691 | ScRange& rColRange, bool& rInsCol, bool& rDelCol, | |||
1692 | ScRange& rRowRange, bool& rInsRow, bool& rDelRow ) | |||
1693 | { | |||
1694 | OSL_ENSURE( rOld.aStart == rNew.aStart, "FitBlock: Beginning is different" )do { if (true && (!(rOld.aStart == rNew.aStart))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "1694" ": "), "%s", "FitBlock: Beginning is different"); } } while (false); | |||
1695 | ||||
1696 | rInsCol = rDelCol = rInsRow = rDelRow = false; | |||
1697 | ||||
1698 | SCCOL nStartX = rOld.aStart.Col(); | |||
1699 | SCROW nStartY = rOld.aStart.Row(); | |||
1700 | SCCOL nOldEndX = rOld.aEnd.Col(); | |||
1701 | SCROW nOldEndY = rOld.aEnd.Row(); | |||
1702 | SCCOL nNewEndX = rNew.aEnd.Col(); | |||
1703 | SCROW nNewEndY = rNew.aEnd.Row(); | |||
1704 | SCTAB nTab = rOld.aStart.Tab(); | |||
1705 | ||||
1706 | // if more rows, columns are inserted/deleted at the old height. | |||
1707 | bool bGrowY = ( nNewEndY > nOldEndY ); | |||
1708 | SCROW nColEndY = bGrowY ? nOldEndY : nNewEndY; | |||
1709 | SCCOL nRowEndX = bGrowY ? nNewEndX : nOldEndX; | |||
1710 | ||||
1711 | // Columns | |||
1712 | ||||
1713 | if ( nNewEndX > nOldEndX ) // Insert columns | |||
1714 | { | |||
1715 | rColRange = ScRange( nOldEndX+1, nStartY, nTab, nNewEndX, nColEndY, nTab ); | |||
1716 | rInsCol = true; | |||
1717 | } | |||
1718 | else if ( nNewEndX < nOldEndX ) // Delete columns | |||
1719 | { | |||
1720 | rColRange = ScRange( nNewEndX+1, nStartY, nTab, nOldEndX, nColEndY, nTab ); | |||
1721 | rDelCol = true; | |||
1722 | } | |||
1723 | ||||
1724 | // Rows | |||
1725 | ||||
1726 | if ( nNewEndY > nOldEndY ) // Insert rows | |||
1727 | { | |||
1728 | rRowRange = ScRange( nStartX, nOldEndY+1, nTab, nRowEndX, nNewEndY, nTab ); | |||
1729 | rInsRow = true; | |||
1730 | } | |||
1731 | else if ( nNewEndY < nOldEndY ) // Delete rows | |||
1732 | { | |||
1733 | rRowRange = ScRange( nStartX, nNewEndY+1, nTab, nRowEndX, nOldEndY, nTab ); | |||
1734 | rDelRow = true; | |||
1735 | } | |||
1736 | } | |||
1737 | ||||
1738 | bool ScDocument::HasPartOfMerged( const ScRange& rRange ) | |||
1739 | { | |||
1740 | bool bPart = false; | |||
1741 | SCTAB nTab = rRange.aStart.Tab(); | |||
1742 | ||||
1743 | SCCOL nStartX = rRange.aStart.Col(); | |||
1744 | SCROW nStartY = rRange.aStart.Row(); | |||
1745 | SCCOL nEndX = rRange.aEnd.Col(); | |||
1746 | SCROW nEndY = rRange.aEnd.Row(); | |||
1747 | ||||
1748 | if (HasAttrib( nStartX, nStartY, nTab, nEndX, nEndY, nTab, | |||
1749 | HasAttrFlags::Merged | HasAttrFlags::Overlapped )) | |||
1750 | { | |||
1751 | ExtendMerge( nStartX, nStartY, nEndX, nEndY, nTab ); | |||
1752 | ExtendOverlapped( nStartX, nStartY, nEndX, nEndY, nTab ); | |||
1753 | ||||
1754 | bPart = ( nStartX != rRange.aStart.Col() || nEndX != rRange.aEnd.Col() || | |||
1755 | nStartY != rRange.aStart.Row() || nEndY != rRange.aEnd.Row() ); | |||
1756 | } | |||
1757 | return bPart; | |||
1758 | } | |||
1759 | ||||
1760 | size_t ScDocument::GetFormulaHash( const ScAddress& rPos ) const | |||
1761 | { | |||
1762 | SCTAB nTab = rPos.Tab(); | |||
1763 | if (!ValidTab(nTab) || o3tl::make_unsigned(nTab) >= maTabs.size() || !maTabs[nTab]) | |||
1764 | return 0; | |||
1765 | ||||
1766 | return maTabs[nTab]->GetFormulaHash(rPos.Col(), rPos.Row()); | |||
1767 | } | |||
1768 | ||||
1769 | ScFormulaVectorState ScDocument::GetFormulaVectorState( const ScAddress& rPos ) const | |||
1770 | { | |||
1771 | SCTAB nTab = rPos.Tab(); | |||
1772 | if (!ValidTab(nTab) || o3tl::make_unsigned(nTab) >= maTabs.size() || !maTabs[nTab]) | |||
1773 | return FormulaVectorUnknown; | |||
1774 | ||||
1775 | return maTabs[nTab]->GetFormulaVectorState(rPos.Col(), rPos.Row()); | |||
1776 | } | |||
1777 | ||||
1778 | formula::FormulaTokenRef ScDocument::ResolveStaticReference( const ScAddress& rPos ) | |||
1779 | { | |||
1780 | SCTAB nTab = rPos.Tab(); | |||
1781 | if (!TableExists(nTab)) | |||
1782 | return formula::FormulaTokenRef(); | |||
1783 | ||||
1784 | return maTabs[nTab]->ResolveStaticReference(rPos.Col(), rPos.Row()); | |||
1785 | } | |||
1786 | ||||
1787 | formula::FormulaTokenRef ScDocument::ResolveStaticReference( const ScRange& rRange ) | |||
1788 | { | |||
1789 | SCTAB nTab = rRange.aStart.Tab(); | |||
1790 | if (nTab != rRange.aEnd.Tab() || !TableExists(nTab)) | |||
1791 | return formula::FormulaTokenRef(); | |||
1792 | ||||
1793 | return maTabs[nTab]->ResolveStaticReference( | |||
1794 | rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row()); | |||
1795 | } | |||
1796 | ||||
1797 | formula::VectorRefArray ScDocument::FetchVectorRefArray( const ScAddress& rPos, SCROW nLength ) | |||
1798 | { | |||
1799 | SCTAB nTab = rPos.Tab(); | |||
1800 | if (!TableExists(nTab)) | |||
1801 | return formula::VectorRefArray(); | |||
1802 | ||||
1803 | return maTabs[nTab]->FetchVectorRefArray(rPos.Col(), rPos.Row(), rPos.Row()+nLength-1); | |||
1804 | } | |||
1805 | ||||
1806 | #ifdef DBG_UTIL | |||
1807 | void ScDocument::AssertNoInterpretNeeded( const ScAddress& rPos, SCROW nLength ) | |||
1808 | { | |||
1809 | SCTAB nTab = rPos.Tab(); | |||
1810 | assert(TableExists(nTab))(static_cast <bool> (TableExists(nTab)) ? void (0) : __assert_fail ("TableExists(nTab)", "/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" , 1810, __extension__ __PRETTY_FUNCTION__)); | |||
1811 | return maTabs[nTab]->AssertNoInterpretNeeded(rPos.Col(), rPos.Row(), rPos.Row()+nLength-1); | |||
1812 | } | |||
1813 | #endif | |||
1814 | ||||
1815 | void ScDocument::UnlockAdjustHeight() | |||
1816 | { | |||
1817 | assert(nAdjustHeightLock > 0)(static_cast <bool> (nAdjustHeightLock > 0) ? void ( 0) : __assert_fail ("nAdjustHeightLock > 0", "/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" , 1817, __extension__ __PRETTY_FUNCTION__)); | |||
1818 | if(nAdjustHeightLock > 0) | |||
1819 | --nAdjustHeightLock; | |||
1820 | } | |||
1821 | ||||
1822 | bool ScDocument::HandleRefArrayForParallelism( const ScAddress& rPos, SCROW nLength, const ScFormulaCellGroupRef& mxGroup ) | |||
1823 | { | |||
1824 | SCTAB nTab = rPos.Tab(); | |||
1825 | if (!TableExists(nTab)) | |||
1826 | return false; | |||
1827 | ||||
1828 | return maTabs[nTab]->HandleRefArrayForParallelism(rPos.Col(), rPos.Row(), rPos.Row()+nLength-1, mxGroup); | |||
1829 | } | |||
1830 | ||||
1831 | bool ScDocument::CanFitBlock( const ScRange& rOld, const ScRange& rNew ) | |||
1832 | { | |||
1833 | if ( rOld == rNew ) | |||
1834 | return true; | |||
1835 | ||||
1836 | bool bOk = true; | |||
1837 | bool bInsCol,bDelCol,bInsRow,bDelRow; | |||
1838 | ScRange aColRange,aRowRange; | |||
1839 | lcl_GetInsDelRanges( rOld, rNew, aColRange,bInsCol,bDelCol, aRowRange,bInsRow,bDelRow ); | |||
1840 | ||||
1841 | if ( bInsCol && !CanInsertCol( aColRange ) ) // Cells at the edge ? | |||
1842 | bOk = false; | |||
1843 | if ( bInsRow && !CanInsertRow( aRowRange ) ) // Cells at the edge ? | |||
1844 | bOk = false; | |||
1845 | ||||
1846 | if ( bInsCol || bDelCol ) | |||
1847 | { | |||
1848 | aColRange.aEnd.SetCol(MaxCol()); | |||
1849 | if ( HasPartOfMerged(aColRange) ) | |||
1850 | bOk = false; | |||
1851 | } | |||
1852 | if ( bInsRow || bDelRow ) | |||
1853 | { | |||
1854 | aRowRange.aEnd.SetRow(MaxRow()); | |||
1855 | if ( HasPartOfMerged(aRowRange) ) | |||
1856 | bOk = false; | |||
1857 | } | |||
1858 | ||||
1859 | return bOk; | |||
1860 | } | |||
1861 | ||||
1862 | void ScDocument::FitBlock( const ScRange& rOld, const ScRange& rNew, bool bClear ) | |||
1863 | { | |||
1864 | if (bClear) | |||
1865 | DeleteAreaTab( rOld, InsertDeleteFlags::ALL ); | |||
1866 | ||||
1867 | bool bInsCol,bDelCol,bInsRow,bDelRow; | |||
1868 | ScRange aColRange,aRowRange; | |||
1869 | lcl_GetInsDelRanges( rOld, rNew, aColRange,bInsCol,bDelCol, aRowRange,bInsRow,bDelRow ); | |||
1870 | ||||
1871 | if ( bInsCol ) | |||
1872 | InsertCol( aColRange ); // First insert columns | |||
1873 | if ( bInsRow ) | |||
1874 | InsertRow( aRowRange ); | |||
1875 | ||||
1876 | if ( bDelRow ) | |||
1877 | DeleteRow( aRowRange ); // First delete rows | |||
1878 | if ( bDelCol ) | |||
1879 | DeleteCol( aColRange ); | |||
1880 | ||||
1881 | // Expand references to inserted rows | |||
1882 | ||||
1883 | if ( bInsCol || bInsRow ) | |||
1884 | { | |||
1885 | ScRange aGrowSource = rOld; | |||
1886 | aGrowSource.aEnd.SetCol(std::min( rOld.aEnd.Col(), rNew.aEnd.Col() )); | |||
1887 | aGrowSource.aEnd.SetRow(std::min( rOld.aEnd.Row(), rNew.aEnd.Row() )); | |||
1888 | SCCOL nGrowX = bInsCol ? ( rNew.aEnd.Col() - rOld.aEnd.Col() ) : 0; | |||
1889 | SCROW nGrowY = bInsRow ? ( rNew.aEnd.Row() - rOld.aEnd.Row() ) : 0; | |||
1890 | UpdateGrow( aGrowSource, nGrowX, nGrowY ); | |||
1891 | } | |||
1892 | } | |||
1893 | ||||
1894 | void ScDocument::DeleteArea( | |||
1895 | SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, const ScMarkData& rMark, | |||
1896 | InsertDeleteFlags nDelFlag, bool bBroadcast, sc::ColumnSpanSet* pBroadcastSpans ) | |||
1897 | { | |||
1898 | sc::AutoCalcSwitch aACSwitch(*this, false); | |||
1899 | ||||
1900 | PutInOrder( nCol1, nCol2 ); | |||
1901 | PutInOrder( nRow1, nRow2 ); | |||
1902 | ||||
1903 | std::vector<ScAddress> aGroupPos; | |||
1904 | // Destroy and reconstruct listeners only if content is affected. | |||
1905 | bool bDelContent = ((nDelFlag & ~InsertDeleteFlags::CONTENTS) != nDelFlag); | |||
1906 | if (bDelContent) | |||
1907 | { | |||
1908 | // Record the positions of top and/or bottom formula groups that intersect | |||
1909 | // the area borders. | |||
1910 | sc::EndListeningContext aCxt(*this); | |||
1911 | ScRange aRange(nCol1, nRow1, 0, nCol2, nRow2, 0); | |||
1912 | for (SCTAB i = 0; i < static_cast<SCTAB>(maTabs.size()); i++) | |||
1913 | { | |||
1914 | if (rMark.GetTableSelect(i)) | |||
1915 | { | |||
1916 | aRange.aStart.SetTab(i); | |||
1917 | aRange.aEnd.SetTab(i); | |||
1918 | ||||
1919 | EndListeningIntersectedGroups(aCxt, aRange, &aGroupPos); | |||
1920 | } | |||
1921 | } | |||
1922 | aCxt.purgeEmptyBroadcasters(); | |||
1923 | } | |||
1924 | ||||
1925 | for (SCTAB i = 0; i < static_cast<SCTAB>(maTabs.size()); i++) | |||
1926 | if (maTabs[i]) | |||
1927 | if ( rMark.GetTableSelect(i) || bIsUndo ) | |||
1928 | maTabs[i]->DeleteArea(nCol1, nRow1, nCol2, nRow2, nDelFlag, bBroadcast, pBroadcastSpans); | |||
1929 | ||||
1930 | if (!bDelContent) | |||
1931 | return; | |||
1932 | ||||
1933 | // Re-start listeners on those top bottom groups that have been split. | |||
1934 | SetNeedsListeningGroups(aGroupPos); | |||
1935 | StartNeededListeners(); | |||
1936 | ||||
1937 | // If formula groups were split their listeners were destroyed and may | |||
1938 | // need to be notified now that they're restored, ScTable::DeleteArea() | |||
1939 | // couldn't do that. | |||
1940 | if (aGroupPos.empty()) | |||
1941 | return; | |||
1942 | ||||
1943 | ScRange aRange(nCol1, nRow1, 0, nCol2, nRow2, 0); | |||
1944 | for (SCTAB i = 0; i < static_cast<SCTAB>(maTabs.size()); i++) | |||
1945 | { | |||
1946 | if (rMark.GetTableSelect(i)) | |||
1947 | { | |||
1948 | aRange.aStart.SetTab(i); | |||
1949 | aRange.aEnd.SetTab(i); | |||
1950 | SetDirty( aRange, true); | |||
1951 | } | |||
1952 | } | |||
1953 | } | |||
1954 | ||||
1955 | void ScDocument::DeleteAreaTab(SCCOL nCol1, SCROW nRow1, | |||
1956 | SCCOL nCol2, SCROW nRow2, | |||
1957 | SCTAB nTab, InsertDeleteFlags nDelFlag) | |||
1958 | { | |||
1959 | PutInOrder( nCol1, nCol2 ); | |||
1960 | PutInOrder( nRow1, nRow2 ); | |||
1961 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
1962 | { | |||
1963 | bool bOldAutoCalc = GetAutoCalc(); | |||
1964 | SetAutoCalc( false ); // avoid multiple calculations | |||
1965 | maTabs[nTab]->DeleteArea(nCol1, nRow1, nCol2, nRow2, nDelFlag); | |||
1966 | SetAutoCalc( bOldAutoCalc ); | |||
1967 | } | |||
1968 | } | |||
1969 | ||||
1970 | void ScDocument::DeleteAreaTab( const ScRange& rRange, InsertDeleteFlags nDelFlag ) | |||
1971 | { | |||
1972 | for ( SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); nTab++ ) | |||
1973 | DeleteAreaTab( rRange.aStart.Col(), rRange.aStart.Row(), | |||
1974 | rRange.aEnd.Col(), rRange.aEnd.Row(), | |||
1975 | nTab, nDelFlag ); | |||
1976 | } | |||
1977 | ||||
1978 | void ScDocument::InitUndoSelected(const ScDocument& rSrcDoc, const ScMarkData& rTabSelection, | |||
1979 | bool bColInfo, bool bRowInfo ) | |||
1980 | { | |||
1981 | if (bIsUndo) | |||
1982 | { | |||
1983 | Clear(); | |||
1984 | ||||
1985 | SharePooledResources(&rSrcDoc); | |||
1986 | ||||
1987 | for (SCTAB nTab = 0; nTab <= rTabSelection.GetLastSelected(); nTab++) | |||
1988 | if ( rTabSelection.GetTableSelect( nTab ) ) | |||
1989 | { | |||
1990 | ScTableUniquePtr pTable(new ScTable(*this, nTab, OUString(), bColInfo, bRowInfo)); | |||
1991 | if (nTab < static_cast<SCTAB>(maTabs.size())) | |||
1992 | maTabs[nTab] = std::move(pTable); | |||
1993 | else | |||
1994 | maTabs.push_back(std::move(pTable)); | |||
1995 | } | |||
1996 | else | |||
1997 | { | |||
1998 | if (nTab < static_cast<SCTAB>(maTabs.size())) | |||
1999 | maTabs[nTab]=nullptr; | |||
2000 | else | |||
2001 | maTabs.push_back(nullptr); | |||
2002 | } | |||
2003 | } | |||
2004 | else | |||
2005 | { | |||
2006 | OSL_FAIL("InitUndo")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "2006" ": "), "%s", "InitUndo"); } } while (false); | |||
2007 | } | |||
2008 | } | |||
2009 | ||||
2010 | void ScDocument::InitUndo( const ScDocument& rSrcDoc, SCTAB nTab1, SCTAB nTab2, | |||
2011 | bool bColInfo, bool bRowInfo ) | |||
2012 | { | |||
2013 | if (!bIsUndo) | |||
2014 | { | |||
2015 | OSL_FAIL("InitUndo")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "2015" ": "), "%s", "InitUndo"); } } while (false); | |||
2016 | return; | |||
2017 | } | |||
2018 | ||||
2019 | Clear(); | |||
2020 | ||||
2021 | // Undo document shares its pooled resources with the source document. | |||
2022 | SharePooledResources(&rSrcDoc); | |||
2023 | ||||
2024 | if (rSrcDoc.mpShell->GetMedium()) | |||
2025 | maFileURL = rSrcDoc.mpShell->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DecodeMechanism::ToIUri); | |||
2026 | ||||
2027 | if ( nTab2 >= static_cast<SCTAB>(maTabs.size())) | |||
2028 | maTabs.resize(nTab2 + 1); | |||
2029 | for (SCTAB nTab = nTab1; nTab <= nTab2; nTab++) | |||
2030 | { | |||
2031 | maTabs[nTab].reset(new ScTable(*this, nTab, OUString(), bColInfo, bRowInfo)); | |||
2032 | } | |||
2033 | } | |||
2034 | ||||
2035 | void ScDocument::AddUndoTab( SCTAB nTab1, SCTAB nTab2, bool bColInfo, bool bRowInfo ) | |||
2036 | { | |||
2037 | if (!bIsUndo) | |||
2038 | { | |||
2039 | OSL_FAIL("AddUndoTab")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "2039" ": "), "%s", "AddUndoTab"); } } while (false); | |||
2040 | return; | |||
2041 | } | |||
2042 | ||||
2043 | if (nTab2 >= static_cast<SCTAB>(maTabs.size())) | |||
2044 | { | |||
2045 | maTabs.resize(nTab2+1); | |||
2046 | } | |||
2047 | ||||
2048 | for (SCTAB nTab = nTab1; nTab <= nTab2; nTab++) | |||
2049 | if (!maTabs[nTab]) | |||
2050 | { | |||
2051 | maTabs[nTab].reset( new ScTable(*this, nTab, OUString(), bColInfo, bRowInfo) ); | |||
2052 | } | |||
2053 | } | |||
2054 | ||||
2055 | void ScDocument::SetCutMode( bool bVal ) | |||
2056 | { | |||
2057 | if (bIsClip) | |||
2058 | GetClipParam().mbCutMode = bVal; | |||
2059 | else | |||
2060 | { | |||
2061 | OSL_FAIL("SetCutMode without bIsClip")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "2061" ": "), "%s", "SetCutMode without bIsClip"); } } while (false); | |||
2062 | } | |||
2063 | } | |||
2064 | ||||
2065 | bool ScDocument::IsCutMode() | |||
2066 | { | |||
2067 | if (bIsClip) | |||
2068 | return GetClipParam().mbCutMode; | |||
2069 | else | |||
2070 | { | |||
2071 | OSL_FAIL("IsCutMode without bIsClip")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "2071" ": "), "%s", "IsCutMode without bIsClip"); } } while (false); | |||
2072 | return false; | |||
2073 | } | |||
2074 | } | |||
2075 | ||||
2076 | void ScDocument::CopyToDocument(SCCOL nCol1, SCROW nRow1, SCTAB nTab1, | |||
2077 | SCCOL nCol2, SCROW nRow2, SCTAB nTab2, | |||
2078 | InsertDeleteFlags nFlags, bool bOnlyMarked, ScDocument& rDestDoc, | |||
2079 | const ScMarkData* pMarks, bool bColRowFlags ) | |||
2080 | { | |||
2081 | if (ValidTab(nTab1) && ValidTab(nTab2)) | |||
2082 | { | |||
2083 | ScRange aThisRange(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2); | |||
2084 | CopyToDocument(aThisRange, nFlags, bOnlyMarked, rDestDoc, pMarks, bColRowFlags); | |||
2085 | } | |||
2086 | } | |||
2087 | ||||
2088 | void ScDocument::UndoToDocument(SCCOL nCol1, SCROW nRow1, SCTAB nTab1, | |||
2089 | SCCOL nCol2, SCROW nRow2, SCTAB nTab2, | |||
2090 | InsertDeleteFlags nFlags, bool bOnlyMarked, ScDocument& rDestDoc) | |||
2091 | { | |||
2092 | PutInOrder( nCol1, nCol2 ); | |||
2093 | PutInOrder( nRow1, nRow2 ); | |||
2094 | PutInOrder( nTab1, nTab2 ); | |||
2095 | if (!(ValidTab(nTab1) && ValidTab(nTab2))) | |||
2096 | return; | |||
2097 | ||||
2098 | sc::AutoCalcSwitch aACSwitch(rDestDoc, false); // avoid multiple calculations | |||
2099 | ||||
2100 | if (nTab1 > 0) | |||
2101 | CopyToDocument(0, 0, 0, MaxCol(), MaxRow(), nTab1-1, InsertDeleteFlags::FORMULA, false, rDestDoc); | |||
2102 | ||||
2103 | sc::CopyToDocContext aCxt(rDestDoc); | |||
2104 | assert( nTab2 < static_cast<SCTAB>(maTabs.size()) && nTab2 < static_cast<SCTAB>(rDestDoc.maTabs.size()))(static_cast <bool> (nTab2 < static_cast<SCTAB> (maTabs.size()) && nTab2 < static_cast<SCTAB> (rDestDoc.maTabs.size())) ? void (0) : __assert_fail ("nTab2 < static_cast<SCTAB>(maTabs.size()) && nTab2 < static_cast<SCTAB>(rDestDoc.maTabs.size())" , "/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" , 2104, __extension__ __PRETTY_FUNCTION__)); | |||
2105 | for (SCTAB i = nTab1; i <= nTab2; i++) | |||
2106 | { | |||
2107 | if (maTabs[i] && rDestDoc.maTabs[i]) | |||
2108 | maTabs[i]->UndoToTable(aCxt, nCol1, nRow1, nCol2, nRow2, nFlags, | |||
2109 | bOnlyMarked, rDestDoc.maTabs[i].get()); | |||
2110 | } | |||
2111 | ||||
2112 | if (nTab2 < MAXTAB) | |||
2113 | CopyToDocument(0, 0, nTab2+1, MaxCol(), MaxRow(), MAXTAB, InsertDeleteFlags::FORMULA, false, rDestDoc); | |||
2114 | } | |||
2115 | ||||
2116 | void ScDocument::CopyToDocument(const ScRange& rRange, | |||
2117 | InsertDeleteFlags nFlags, bool bOnlyMarked, ScDocument& rDestDoc, | |||
2118 | const ScMarkData* pMarks, bool bColRowFlags) | |||
2119 | { | |||
2120 | ScRange aNewRange = rRange; | |||
2121 | aNewRange.PutInOrder(); | |||
2122 | ||||
2123 | if (rDestDoc.aDocName.isEmpty()) | |||
2124 | rDestDoc.aDocName = aDocName; | |||
2125 | ||||
2126 | sc::AutoCalcSwitch aACSwitch(rDestDoc, false); // avoid multiple calculations | |||
2127 | ||||
2128 | sc::CopyToDocContext aCxt(rDestDoc); | |||
2129 | aCxt.setStartListening(false); | |||
2130 | ||||
2131 | SCTAB nMinSizeBothTabs = static_cast<SCTAB>(std::min(maTabs.size(), rDestDoc.maTabs.size())); | |||
2132 | for (SCTAB i = aNewRange.aStart.Tab(); i <= aNewRange.aEnd.Tab() && i < nMinSizeBothTabs; i++) | |||
2133 | { | |||
2134 | ScTable* pTab = FetchTable(i); | |||
2135 | ScTable* pDestTab = rDestDoc.FetchTable(i); | |||
2136 | if (!pTab || !pDestTab) | |||
2137 | continue; | |||
2138 | ||||
2139 | pTab->CopyToTable( | |||
2140 | aCxt, aNewRange.aStart.Col(), aNewRange.aStart.Row(), aNewRange.aEnd.Col(), aNewRange.aEnd.Row(), | |||
2141 | nFlags, bOnlyMarked, pDestTab, pMarks, false, bColRowFlags, | |||
2142 | /*bGlobalNamesToLocal*/false, /*bCopyCaptions*/true); | |||
2143 | } | |||
2144 | ||||
2145 | rDestDoc.StartAllListeners(aNewRange); | |||
2146 | } | |||
2147 | ||||
2148 | void ScDocument::UndoToDocument(const ScRange& rRange, | |||
2149 | InsertDeleteFlags nFlags, bool bOnlyMarked, ScDocument& rDestDoc) | |||
2150 | { | |||
2151 | sc::AutoCalcSwitch aAutoCalcSwitch(*this, false); | |||
2152 | ||||
2153 | ScRange aNewRange = rRange; | |||
2154 | aNewRange.PutInOrder(); | |||
2155 | SCTAB nTab1 = aNewRange.aStart.Tab(); | |||
2156 | SCTAB nTab2 = aNewRange.aEnd.Tab(); | |||
2157 | ||||
2158 | sc::CopyToDocContext aCxt(rDestDoc); | |||
2159 | if (nTab1 > 0) | |||
2160 | CopyToDocument(0, 0, 0, MaxCol(), MaxRow(), nTab1-1, InsertDeleteFlags::FORMULA, false, rDestDoc); | |||
2161 | ||||
2162 | SCTAB nMinSizeBothTabs = static_cast<SCTAB>(std::min(maTabs.size(), rDestDoc.maTabs.size())); | |||
2163 | for (SCTAB i = nTab1; i <= nTab2 && i < nMinSizeBothTabs; i++) | |||
2164 | { | |||
2165 | if (maTabs[i] && rDestDoc.maTabs[i]) | |||
2166 | maTabs[i]->UndoToTable(aCxt, aNewRange.aStart.Col(), aNewRange.aStart.Row(), | |||
2167 | aNewRange.aEnd.Col(), aNewRange.aEnd.Row(), | |||
2168 | nFlags, bOnlyMarked, rDestDoc.maTabs[i].get()); | |||
2169 | } | |||
2170 | ||||
2171 | if (nTab2 < static_cast<SCTAB>(maTabs.size())) | |||
2172 | CopyToDocument(0, 0 , nTab2+1, MaxCol(), MaxRow(), maTabs.size(), InsertDeleteFlags::FORMULA, false, rDestDoc); | |||
2173 | } | |||
2174 | ||||
2175 | void ScDocument::CopyToClip(const ScClipParam& rClipParam, | |||
2176 | ScDocument* pClipDoc, const ScMarkData* pMarks, | |||
2177 | bool bKeepScenarioFlags, bool bIncludeObjects ) | |||
2178 | { | |||
2179 | OSL_ENSURE( pMarks, "CopyToClip: ScMarkData fails" )do { if (true && (!(pMarks))) { sal_detail_logFormat( (SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "2179" ": "), "%s", "CopyToClip: ScMarkData fails"); } } while (false); | |||
2180 | ||||
2181 | if (bIsClip) | |||
2182 | return; | |||
2183 | ||||
2184 | if (!pClipDoc) | |||
2185 | { | |||
2186 | SAL_WARN("sc", "CopyToClip: no ClipDoc")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "sc")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "CopyToClip: no ClipDoc") == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sc"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "2186" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "CopyToClip: no ClipDoc"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "CopyToClip: no ClipDoc"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("sc"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "2186" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "CopyToClip: no ClipDoc") == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sc"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "2186" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "CopyToClip: no ClipDoc"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "CopyToClip: no ClipDoc"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("sc"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "2186" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | |||
2187 | pClipDoc = ScModule::GetClipDoc(); | |||
2188 | } | |||
2189 | ||||
2190 | if (mpShell->GetMedium()) | |||
2191 | { | |||
2192 | pClipDoc->maFileURL = mpShell->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DecodeMechanism::ToIUri); | |||
2193 | // for unsaved files use the title name and adjust during save of file | |||
2194 | if (pClipDoc->maFileURL.isEmpty()) | |||
2195 | pClipDoc->maFileURL = mpShell->GetName(); | |||
2196 | } | |||
2197 | else | |||
2198 | { | |||
2199 | pClipDoc->maFileURL = mpShell->GetName(); | |||
2200 | } | |||
2201 | ||||
2202 | //init maTabNames | |||
2203 | for (const auto& rxTab : maTabs) | |||
2204 | { | |||
2205 | if( rxTab ) | |||
2206 | { | |||
2207 | OUString aTabName = rxTab->GetName(); | |||
2208 | pClipDoc->maTabNames.push_back(aTabName); | |||
2209 | } | |||
2210 | else | |||
2211 | pClipDoc->maTabNames.emplace_back(); | |||
2212 | } | |||
2213 | ||||
2214 | pClipDoc->aDocName = aDocName; | |||
2215 | pClipDoc->SetClipParam(rClipParam); | |||
2216 | ScRange aClipRange = rClipParam.getWholeRange(); | |||
2217 | SCTAB nEndTab = static_cast<SCTAB>(maTabs.size()); | |||
2218 | ||||
2219 | pClipDoc->ResetClip(this, pMarks); | |||
2220 | ||||
2221 | sc::CopyToClipContext aCxt(*pClipDoc, bKeepScenarioFlags); | |||
2222 | CopyRangeNamesToClip(pClipDoc, aClipRange, pMarks); | |||
2223 | ||||
2224 | for (SCTAB i = 0; i < nEndTab; ++i) | |||
2225 | { | |||
2226 | if (!maTabs[i] || i >= static_cast<SCTAB>(pClipDoc->maTabs.size()) || !pClipDoc->maTabs[i]) | |||
2227 | continue; | |||
2228 | ||||
2229 | if ( pMarks && !pMarks->GetTableSelect(i) ) | |||
2230 | continue; | |||
2231 | ||||
2232 | maTabs[i]->CopyToClip(aCxt, rClipParam.maRanges, pClipDoc->maTabs[i].get()); | |||
2233 | ||||
2234 | if (mpDrawLayer && bIncludeObjects) | |||
2235 | { | |||
2236 | // also copy drawing objects | |||
2237 | tools::Rectangle aObjRect = GetMMRect( | |||
2238 | aClipRange.aStart.Col(), aClipRange.aStart.Row(), aClipRange.aEnd.Col(), aClipRange.aEnd.Row(), i); | |||
2239 | mpDrawLayer->CopyToClip(pClipDoc, i, aObjRect); | |||
2240 | } | |||
2241 | } | |||
2242 | ||||
2243 | // Make sure to mark overlapped cells. | |||
2244 | pClipDoc->ExtendMerge(aClipRange, true); | |||
2245 | } | |||
2246 | ||||
2247 | void ScDocument::CopyStaticToDocument(const ScRange& rSrcRange, SCTAB nDestTab, ScDocument& rDestDoc) | |||
2248 | { | |||
2249 | ScTable* pSrcTab = rSrcRange.aStart.Tab() < static_cast<SCTAB>(maTabs.size()) ? maTabs[rSrcRange.aStart.Tab()].get() : nullptr; | |||
2250 | ScTable* pDestTab = nDestTab < static_cast<SCTAB>(rDestDoc.maTabs.size()) ? rDestDoc.maTabs[nDestTab].get() : nullptr; | |||
2251 | ||||
2252 | if (!pSrcTab || !pDestTab) | |||
2253 | return; | |||
2254 | ||||
2255 | rDestDoc.GetFormatTable()->MergeFormatter(*GetFormatTable()); | |||
2256 | SvNumberFormatterMergeMap aMap = rDestDoc.GetFormatTable()->ConvertMergeTableToMap(); | |||
2257 | ||||
2258 | pSrcTab->CopyStaticToDocument( | |||
2259 | rSrcRange.aStart.Col(), rSrcRange.aStart.Row(), rSrcRange.aEnd.Col(), rSrcRange.aEnd.Row(), | |||
2260 | aMap, pDestTab); | |||
2261 | } | |||
2262 | ||||
2263 | void ScDocument::CopyCellToDocument( const ScAddress& rSrcPos, const ScAddress& rDestPos, ScDocument& rDestDoc ) | |||
2264 | { | |||
2265 | if (!TableExists(rSrcPos.Tab()) || !rDestDoc.TableExists(rDestPos.Tab())) | |||
2266 | return; | |||
2267 | ||||
2268 | ScTable& rSrcTab = *maTabs[rSrcPos.Tab()]; | |||
2269 | ScTable& rDestTab = *rDestDoc.maTabs[rDestPos.Tab()]; | |||
2270 | ||||
2271 | rSrcTab.CopyCellToDocument(rSrcPos.Col(), rSrcPos.Row(), rDestPos.Col(), rDestPos.Row(), rDestTab); | |||
2272 | } | |||
2273 | ||||
2274 | void ScDocument::CopyTabToClip(SCCOL nCol1, SCROW nRow1, | |||
2275 | SCCOL nCol2, SCROW nRow2, | |||
2276 | SCTAB nTab, ScDocument* pClipDoc) | |||
2277 | { | |||
2278 | if (bIsClip) | |||
2279 | return; | |||
2280 | ||||
2281 | if (!pClipDoc) | |||
2282 | { | |||
2283 | SAL_WARN("sc", "CopyTabToClip: no ClipDoc")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "sc")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "CopyTabToClip: no ClipDoc") == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sc"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "2283" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "CopyTabToClip: no ClipDoc"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "CopyTabToClip: no ClipDoc"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("sc"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "2283" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "CopyTabToClip: no ClipDoc") == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sc"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "2283" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "CopyTabToClip: no ClipDoc"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "CopyTabToClip: no ClipDoc"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("sc"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "2283" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | |||
2284 | pClipDoc = ScModule::GetClipDoc(); | |||
2285 | } | |||
2286 | ||||
2287 | if (mpShell->GetMedium()) | |||
2288 | { | |||
2289 | pClipDoc->maFileURL = mpShell->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DecodeMechanism::ToIUri); | |||
2290 | // for unsaved files use the title name and adjust during save of file | |||
2291 | if (pClipDoc->maFileURL.isEmpty()) | |||
2292 | pClipDoc->maFileURL = mpShell->GetName(); | |||
2293 | } | |||
2294 | else | |||
2295 | { | |||
2296 | pClipDoc->maFileURL = mpShell->GetName(); | |||
2297 | } | |||
2298 | ||||
2299 | //init maTabNames | |||
2300 | for (const auto& rxTab : maTabs) | |||
2301 | { | |||
2302 | if( rxTab ) | |||
2303 | { | |||
2304 | OUString aTabName = rxTab->GetName(); | |||
2305 | pClipDoc->maTabNames.push_back(aTabName); | |||
2306 | } | |||
2307 | else | |||
2308 | pClipDoc->maTabNames.emplace_back(); | |||
2309 | } | |||
2310 | ||||
2311 | PutInOrder( nCol1, nCol2 ); | |||
2312 | PutInOrder( nRow1, nRow2 ); | |||
2313 | ||||
2314 | ScClipParam& rClipParam = pClipDoc->GetClipParam(); | |||
2315 | pClipDoc->aDocName = aDocName; | |||
2316 | rClipParam.maRanges.RemoveAll(); | |||
2317 | rClipParam.maRanges.push_back(ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0)); | |||
2318 | pClipDoc->ResetClip( this, nTab ); | |||
2319 | ||||
2320 | sc::CopyToClipContext aCxt(*pClipDoc, false); | |||
2321 | if (nTab < static_cast<SCTAB>(maTabs.size()) && nTab < static_cast<SCTAB>(pClipDoc->maTabs.size())) | |||
2322 | if (maTabs[nTab] && pClipDoc->maTabs[nTab]) | |||
2323 | maTabs[nTab]->CopyToClip(aCxt, nCol1, nRow1, nCol2, nRow2, pClipDoc->maTabs[nTab].get()); | |||
2324 | ||||
2325 | pClipDoc->GetClipParam().mbCutMode = false; | |||
2326 | } | |||
2327 | ||||
2328 | void ScDocument::TransposeClip( ScDocument* pTransClip, InsertDeleteFlags nFlags, bool bAsLink ) | |||
2329 | { | |||
2330 | OSL_ENSURE( bIsClip && pTransClip && pTransClip->bIsClip,do { if (true && (!(bIsClip && pTransClip && pTransClip->bIsClip))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "2331" ": "), "%s", "TransposeClip with wrong Document") ; } } while (false) | |||
2331 | "TransposeClip with wrong Document" )do { if (true && (!(bIsClip && pTransClip && pTransClip->bIsClip))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "2331" ": "), "%s", "TransposeClip with wrong Document") ; } } while (false); | |||
2332 | ||||
2333 | // initialize | |||
2334 | // -> pTransClip has to be deleted before the original document! | |||
2335 | ||||
2336 | pTransClip->ResetClip(this, nullptr); // all | |||
2337 | ||||
2338 | // Take over range | |||
2339 | ||||
2340 | if (pRangeName) | |||
2341 | { | |||
2342 | pTransClip->GetRangeName()->clear(); | |||
2343 | for (const auto& rEntry : *pRangeName) | |||
2344 | { | |||
2345 | sal_uInt16 nIndex = rEntry.second->GetIndex(); | |||
2346 | ScRangeData* pData = new ScRangeData(*rEntry.second); | |||
2347 | if (pTransClip->pRangeName->insert(pData)) | |||
2348 | pData->SetIndex(nIndex); | |||
2349 | } | |||
2350 | } | |||
2351 | ||||
2352 | // The data | |||
2353 | ||||
2354 | ScRange aClipRange = GetClipParam().getWholeRange(); | |||
2355 | if ( ValidRow(aClipRange.aEnd.Row()-aClipRange.aStart.Row()) ) | |||
2356 | { | |||
2357 | for (SCTAB i=0; i< static_cast<SCTAB>(maTabs.size()); i++) | |||
2358 | if (maTabs[i]) | |||
2359 | { | |||
2360 | OSL_ENSURE( pTransClip->maTabs[i], "TransposeClip: Table not there" )do { if (true && (!(pTransClip->maTabs[i]))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "2360" ": "), "%s", "TransposeClip: Table not there"); } } while (false); | |||
2361 | maTabs[i]->TransposeClip( aClipRange.aStart.Col(), aClipRange.aStart.Row(), | |||
2362 | aClipRange.aEnd.Col(), aClipRange.aEnd.Row(), | |||
2363 | pTransClip->maTabs[i].get(), nFlags, bAsLink ); | |||
2364 | ||||
2365 | if ( mpDrawLayer && ( nFlags & InsertDeleteFlags::OBJECTS ) ) | |||
2366 | { | |||
2367 | // Drawing objects are copied to the new area without transposing. | |||
2368 | // CopyFromClip is used to adjust the objects to the transposed block's | |||
2369 | // cell range area. | |||
2370 | // (mpDrawLayer in the original clipboard document is set only if there | |||
2371 | // are drawing objects to copy) | |||
2372 | ||||
2373 | pTransClip->InitDrawLayer(); | |||
2374 | tools::Rectangle aSourceRect = GetMMRect( aClipRange.aStart.Col(), aClipRange.aStart.Row(), | |||
2375 | aClipRange.aEnd.Col(), aClipRange.aEnd.Row(), i ); | |||
2376 | tools::Rectangle aDestRect = pTransClip->GetMMRect( 0, 0, | |||
2377 | static_cast<SCCOL>(aClipRange.aEnd.Row() - aClipRange.aStart.Row()), | |||
2378 | static_cast<SCROW>(aClipRange.aEnd.Col() - aClipRange.aStart.Col()), i ); | |||
2379 | pTransClip->mpDrawLayer->CopyFromClip( mpDrawLayer.get(), i, aSourceRect, ScAddress(0,0,i), aDestRect ); | |||
2380 | } | |||
2381 | } | |||
2382 | ||||
2383 | pTransClip->SetClipParam(GetClipParam()); | |||
2384 | pTransClip->GetClipParam().transpose(); | |||
2385 | } | |||
2386 | else | |||
2387 | { | |||
2388 | SAL_WARN("sc", "TransposeClip: Too big")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "sc")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "TransposeClip: Too big") == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sc"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "2388" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "TransposeClip: Too big"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "TransposeClip: Too big"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("sc"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "2388" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "TransposeClip: Too big") == 1) { ::sal_detail_log ( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sc"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "2388" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "TransposeClip: Too big"), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "TransposeClip: Too big"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN ), ("sc"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "2388" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | |||
2389 | } | |||
2390 | ||||
2391 | // This happens only when inserting... | |||
2392 | ||||
2393 | GetClipParam().mbCutMode = false; | |||
2394 | } | |||
2395 | ||||
2396 | namespace { | |||
2397 | ||||
2398 | void copyUsedNamesToClip(ScRangeName* pClipRangeName, ScRangeName* pRangeName, | |||
2399 | const sc::UpdatedRangeNames::NameIndicesType& rUsedNames) | |||
2400 | { | |||
2401 | pClipRangeName->clear(); | |||
2402 | for (const auto& rEntry : *pRangeName) //TODO: also DB and Pivot regions!!! | |||
2403 | { | |||
2404 | sal_uInt16 nIndex = rEntry.second->GetIndex(); | |||
2405 | bool bInUse = (rUsedNames.count(nIndex) > 0); | |||
2406 | if (!bInUse) | |||
2407 | continue; | |||
2408 | ||||
2409 | ScRangeData* pData = new ScRangeData(*rEntry.second); | |||
2410 | if (pClipRangeName->insert(pData)) | |||
2411 | pData->SetIndex(nIndex); | |||
2412 | } | |||
2413 | } | |||
2414 | ||||
2415 | } | |||
2416 | ||||
2417 | void ScDocument::CopyRangeNamesToClip(ScDocument* pClipDoc, const ScRange& rClipRange, const ScMarkData* pMarks) | |||
2418 | { | |||
2419 | if (!pRangeName || pRangeName->empty()) | |||
2420 | return; | |||
2421 | ||||
2422 | sc::UpdatedRangeNames aUsedNames; // indexes of named ranges that are used in the copied cells | |||
2423 | SCTAB nMinSizeBothTabs = static_cast<SCTAB>(std::min(maTabs.size(), pClipDoc->maTabs.size())); | |||
2424 | for (SCTAB i = 0; i < nMinSizeBothTabs; ++i) | |||
2425 | if (maTabs[i] && pClipDoc->maTabs[i]) | |||
2426 | if ( !pMarks || pMarks->GetTableSelect(i) ) | |||
2427 | maTabs[i]->FindRangeNamesInUse( | |||
2428 | rClipRange.aStart.Col(), rClipRange.aStart.Row(), | |||
2429 | rClipRange.aEnd.Col(), rClipRange.aEnd.Row(), aUsedNames); | |||
2430 | ||||
2431 | /* TODO: handle also sheet-local names */ | |||
2432 | sc::UpdatedRangeNames::NameIndicesType aUsedGlobalNames( aUsedNames.getUpdatedNames(-1)); | |||
2433 | copyUsedNamesToClip(pClipDoc->GetRangeName(), pRangeName.get(), aUsedGlobalNames); | |||
2434 | } | |||
2435 | ||||
2436 | ScDocument::NumFmtMergeHandler::NumFmtMergeHandler(ScDocument& rDoc, const ScDocument& rSrcDoc) | |||
2437 | : mrDoc(rDoc) | |||
2438 | { | |||
2439 | mrDoc.MergeNumberFormatter(rSrcDoc); | |||
2440 | } | |||
2441 | ||||
2442 | ScDocument::NumFmtMergeHandler::~NumFmtMergeHandler() | |||
2443 | { | |||
2444 | ScMutationGuard aGuard(mrDoc, ScMutationGuardFlags::CORE); | |||
2445 | mrDoc.pFormatExchangeList = nullptr; | |||
2446 | } | |||
2447 | ||||
2448 | void ScDocument::PrepareFormulaCalc() | |||
2449 | { | |||
2450 | ScMutationGuard aGuard(*this, ScMutationGuardFlags::CORE); | |||
2451 | mpFormulaGroupCxt.reset(); | |||
2452 | } | |||
2453 | ||||
2454 | SvtBroadcaster* ScDocument::GetBroadcaster( const ScAddress& rPos ) | |||
2455 | { | |||
2456 | ScTable* pTab = FetchTable(rPos.Tab()); | |||
2457 | if (!pTab) | |||
2458 | return nullptr; | |||
2459 | ||||
2460 | return pTab->GetBroadcaster(rPos.Col(), rPos.Row()); | |||
2461 | } | |||
2462 | ||||
2463 | const SvtBroadcaster* ScDocument::GetBroadcaster( const ScAddress& rPos ) const | |||
2464 | { | |||
2465 | const ScTable* pTab = FetchTable(rPos.Tab()); | |||
2466 | if (!pTab) | |||
2467 | return nullptr; | |||
2468 | ||||
2469 | return pTab->GetBroadcaster(rPos.Col(), rPos.Row()); | |||
2470 | } | |||
2471 | ||||
2472 | void ScDocument::DeleteBroadcasters( sc::ColumnBlockPosition& rBlockPos, const ScAddress& rTopPos, SCROW nLength ) | |||
2473 | { | |||
2474 | ScTable* pTab = FetchTable(rTopPos.Tab()); | |||
2475 | if (!pTab || nLength <= 0) | |||
2476 | return; | |||
2477 | ||||
2478 | pTab->DeleteBroadcasters(rBlockPos, rTopPos.Col(), rTopPos.Row(), rTopPos.Row()+nLength-1); | |||
2479 | } | |||
2480 | ||||
2481 | #if DUMP_COLUMN_STORAGE0 | |||
2482 | void ScDocument::DumpColumnStorage( SCTAB nTab, SCCOL nCol ) const | |||
2483 | { | |||
2484 | const ScTable* pTab = FetchTable(nTab); | |||
2485 | if (!pTab) | |||
2486 | return; | |||
2487 | ||||
2488 | pTab->DumpColumnStorage(nCol); | |||
2489 | } | |||
2490 | #endif | |||
2491 | ||||
2492 | #if DEBUG_AREA_BROADCASTER0 | |||
2493 | void ScDocument::DumpAreaBroadcasters() const | |||
2494 | { | |||
2495 | if (pBASM) | |||
2496 | pBASM->Dump(); | |||
2497 | } | |||
2498 | #endif | |||
2499 | ||||
2500 | bool ScDocument::TableExists( SCTAB nTab ) const | |||
2501 | { | |||
2502 | return ValidTab(nTab) && o3tl::make_unsigned(nTab) < maTabs.size() && maTabs[nTab]; | |||
2503 | } | |||
2504 | ||||
2505 | ScTable* ScDocument::FetchTable( SCTAB nTab ) | |||
2506 | { | |||
2507 | if (!TableExists(nTab)) | |||
2508 | return nullptr; | |||
2509 | ||||
2510 | return maTabs[nTab].get(); | |||
2511 | } | |||
2512 | ||||
2513 | const ScTable* ScDocument::FetchTable( SCTAB nTab ) const | |||
2514 | { | |||
2515 | if (!TableExists(nTab)) | |||
2516 | return nullptr; | |||
2517 | ||||
2518 | return maTabs[nTab].get(); | |||
2519 | } | |||
2520 | ||||
2521 | ScColumnsRange ScDocument::GetColumnsRange( SCTAB nTab, SCCOL nColBegin, SCCOL nColEnd) const | |||
2522 | { | |||
2523 | if (!TableExists(nTab)) | |||
2524 | { | |||
2525 | std::vector<std::unique_ptr<ScColumn, o3tl::default_delete<ScColumn>>> aEmptyVector; | |||
2526 | return ScColumnsRange(ScColumnsRange::Iterator(aEmptyVector.begin()), | |||
2527 | ScColumnsRange::Iterator(aEmptyVector.end())); | |||
2528 | } | |||
2529 | ||||
2530 | return maTabs[nTab]->GetColumnsRange(nColBegin, nColEnd); | |||
2531 | } | |||
2532 | ||||
2533 | void ScDocument::MergeNumberFormatter(const ScDocument& rSrcDoc) | |||
2534 | { | |||
2535 | SvNumberFormatter* pThisFormatter = mxPoolHelper->GetFormTable(); | |||
2536 | SvNumberFormatter* pOtherFormatter = rSrcDoc.mxPoolHelper->GetFormTable(); | |||
2537 | if (pOtherFormatter && pOtherFormatter != pThisFormatter) | |||
2538 | { | |||
2539 | SvNumberFormatterIndexTable* pExchangeList = | |||
2540 | pThisFormatter->MergeFormatter(*pOtherFormatter); | |||
2541 | if (!pExchangeList->empty()) | |||
2542 | { | |||
2543 | ScMutationGuard aGuard(*this, ScMutationGuardFlags::CORE); | |||
2544 | pFormatExchangeList = pExchangeList; | |||
2545 | } | |||
2546 | } | |||
2547 | } | |||
2548 | ||||
2549 | ScClipParam& ScDocument::GetClipParam() | |||
2550 | { | |||
2551 | if (!mpClipParam) | |||
2552 | mpClipParam.reset(new ScClipParam); | |||
2553 | ||||
2554 | return *mpClipParam; | |||
2555 | } | |||
2556 | ||||
2557 | void ScDocument::SetClipParam(const ScClipParam& rParam) | |||
2558 | { | |||
2559 | mpClipParam.reset(new ScClipParam(rParam)); | |||
2560 | } | |||
2561 | ||||
2562 | bool ScDocument::IsClipboardSource() const | |||
2563 | { | |||
2564 | if (bIsClip || mpShell == nullptr || mpShell->IsLoading()) | |||
2565 | return false; | |||
2566 | ||||
2567 | ScDocument* pClipDoc = ScModule::GetClipDoc(); | |||
2568 | return pClipDoc && pClipDoc->bIsClip && pClipDoc->mxPoolHelper.is() && mxPoolHelper.is() && | |||
2569 | mxPoolHelper->GetDocPool() == pClipDoc->mxPoolHelper->GetDocPool(); | |||
2570 | } | |||
2571 | ||||
2572 | void ScDocument::StartListeningFromClip( SCCOL nCol1, SCROW nRow1, | |||
2573 | SCCOL nCol2, SCROW nRow2, | |||
2574 | const ScMarkData& rMark, InsertDeleteFlags nInsFlag ) | |||
2575 | { | |||
2576 | if (!(nInsFlag & InsertDeleteFlags::CONTENTS)) | |||
2577 | return; | |||
2578 | ||||
2579 | auto pSet = std::make_shared<sc::ColumnBlockPositionSet>(*this); | |||
2580 | ||||
2581 | sc::StartListeningContext aStartCxt(*this, pSet); | |||
2582 | sc::EndListeningContext aEndCxt(*this, pSet, nullptr); | |||
2583 | ||||
2584 | SCTAB nMax = static_cast<SCTAB>(maTabs.size()); | |||
2585 | for (const auto& rTab : rMark) | |||
2586 | { | |||
2587 | if (rTab >= nMax) | |||
2588 | break; | |||
2589 | if (maTabs[rTab]) | |||
2590 | maTabs[rTab]->StartListeningFormulaCells(aStartCxt, aEndCxt, nCol1, nRow1, nCol2, nRow2); | |||
2591 | } | |||
2592 | } | |||
2593 | ||||
2594 | void ScDocument::SetDirtyFromClip( | |||
2595 | SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, const ScMarkData& rMark, | |||
2596 | InsertDeleteFlags nInsFlag, sc::ColumnSpanSet& rBroadcastSpans ) | |||
2597 | { | |||
2598 | if (nInsFlag & InsertDeleteFlags::CONTENTS) | |||
2599 | { | |||
2600 | SCTAB nMax = static_cast<SCTAB>(maTabs.size()); | |||
2601 | for (const auto& rTab : rMark) | |||
2602 | { | |||
2603 | if (rTab >= nMax) | |||
2604 | break; | |||
2605 | if (maTabs[rTab]) | |||
2606 | maTabs[rTab]->SetDirtyFromClip(nCol1, nRow1, nCol2, nRow2, rBroadcastSpans); | |||
2607 | } | |||
2608 | } | |||
2609 | } | |||
2610 | ||||
2611 | bool ScDocument::InitColumnBlockPosition( sc::ColumnBlockPosition& rBlockPos, SCTAB nTab, SCCOL nCol ) | |||
2612 | { | |||
2613 | if (!TableExists(nTab)) | |||
2614 | return false; | |||
2615 | ||||
2616 | return maTabs[nTab]->InitColumnBlockPosition(rBlockPos, nCol); | |||
2617 | } | |||
2618 | ||||
2619 | void ScDocument::CopyBlockFromClip( | |||
2620 | sc::CopyFromClipContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, | |||
2621 | const ScMarkData& rMark, SCCOL nDx, SCROW nDy ) | |||
2622 | { | |||
2623 | TableContainer& rClipTabs = rCxt.getClipDoc()->maTabs; | |||
2624 | SCTAB nTabEnd = rCxt.getTabEnd(); | |||
2625 | SCTAB nClipTab = 0; | |||
2626 | for (SCTAB i = rCxt.getTabStart(); i <= nTabEnd && i < static_cast<SCTAB>(maTabs.size()); i++) | |||
2627 | { | |||
2628 | if (maTabs[i] && rMark.GetTableSelect(i) ) | |||
2629 | { | |||
2630 | while (!rClipTabs[nClipTab]) nClipTab = (nClipTab+1) % static_cast<SCTAB>(rClipTabs.size()); | |||
2631 | ||||
2632 | maTabs[i]->CopyFromClip( | |||
2633 | rCxt, nCol1, nRow1, nCol2, nRow2, nDx, nDy, rClipTabs[nClipTab].get()); | |||
2634 | ||||
2635 | if (rCxt.getClipDoc()->mpDrawLayer && (rCxt.getInsertFlag() & InsertDeleteFlags::OBJECTS)) | |||
2636 | { | |||
2637 | // also copy drawing objects | |||
2638 | ||||
2639 | // drawing layer must be created before calling CopyFromClip | |||
2640 | // (ScDocShell::MakeDrawLayer also does InitItems etc.) | |||
2641 | OSL_ENSURE( mpDrawLayer, "CopyBlockFromClip: No drawing layer" )do { if (true && (!(mpDrawLayer))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "2641" ": "), "%s", "CopyBlockFromClip: No drawing layer" ); } } while (false); | |||
2642 | if ( mpDrawLayer ) | |||
2643 | { | |||
2644 | // For GetMMRect, the row heights in the target document must already be valid | |||
2645 | // (copied in an extra step before pasting, or updated after pasting cells, but | |||
2646 | // before pasting objects). | |||
2647 | ||||
2648 | tools::Rectangle aSourceRect = rCxt.getClipDoc()->GetMMRect( | |||
2649 | nCol1-nDx, nRow1-nDy, nCol2-nDx, nRow2-nDy, nClipTab ); | |||
2650 | tools::Rectangle aDestRect = GetMMRect( nCol1, nRow1, nCol2, nRow2, i ); | |||
2651 | mpDrawLayer->CopyFromClip(rCxt.getClipDoc()->mpDrawLayer.get(), nClipTab, aSourceRect, | |||
2652 | ScAddress( nCol1, nRow1, i ), aDestRect ); | |||
2653 | } | |||
2654 | } | |||
2655 | ||||
2656 | nClipTab = (nClipTab+1) % static_cast<SCTAB>(rClipTabs.size()); | |||
2657 | } | |||
2658 | } | |||
2659 | if (!(rCxt.getInsertFlag() & InsertDeleteFlags::CONTENTS)) | |||
2660 | return; | |||
2661 | ||||
2662 | nClipTab = 0; | |||
2663 | for (SCTAB i = rCxt.getTabStart(); i <= nTabEnd && i < static_cast<SCTAB>(maTabs.size()); i++) | |||
2664 | { | |||
2665 | if (maTabs[i] && rMark.GetTableSelect(i) ) | |||
2666 | { | |||
2667 | while (!rClipTabs[nClipTab]) nClipTab = (nClipTab+1) % static_cast<SCTAB>(rClipTabs.size()); | |||
2668 | SCTAB nDz = i - nClipTab; | |||
2669 | ||||
2670 | // ranges of consecutive selected tables (in clipboard and dest. doc) | |||
2671 | // must be handled in one UpdateReference call | |||
2672 | SCTAB nFollow = 0; | |||
2673 | while ( i + nFollow < nTabEnd | |||
2674 | && rMark.GetTableSelect( i + nFollow + 1 ) | |||
2675 | && nClipTab + nFollow < MAXTAB | |||
2676 | && rClipTabs[(nClipTab + nFollow + 1) % static_cast<SCTAB>(rClipTabs.size())] ) | |||
2677 | ++nFollow; | |||
2678 | ||||
2679 | sc::RefUpdateContext aRefCxt(*this); | |||
2680 | aRefCxt.maRange = ScRange(nCol1, nRow1, i, nCol2, nRow2, i+nFollow); | |||
2681 | aRefCxt.mnColDelta = nDx; | |||
2682 | aRefCxt.mnRowDelta = nDy; | |||
2683 | aRefCxt.mnTabDelta = nDz; | |||
2684 | aRefCxt.setBlockPositionReference(rCxt.getBlockPositionSet()); // share mdds position caching | |||
2685 | if (rCxt.getClipDoc()->GetClipParam().mbCutMode) | |||
2686 | { | |||
2687 | // Update references only if cut originates from the same | |||
2688 | // document we are pasting into. | |||
2689 | if (rCxt.getClipDoc()->GetPool() == GetPool()) | |||
2690 | { | |||
2691 | bool bOldInserting = IsInsertingFromOtherDoc(); | |||
2692 | SetInsertingFromOtherDoc( true); | |||
2693 | aRefCxt.meMode = URM_MOVE; | |||
2694 | UpdateReference(aRefCxt, rCxt.getUndoDoc(), false); | |||
2695 | ||||
2696 | // For URM_MOVE group listeners may have been removed, | |||
2697 | // re-establish them. | |||
2698 | if (!aRefCxt.maRegroupCols.empty()) | |||
2699 | { | |||
2700 | /* TODO: holding the ColumnSet in a shared_ptr at | |||
2701 | * RefUpdateContext would eliminate the need of | |||
2702 | * copying it here. */ | |||
2703 | auto pColSet = std::make_shared<sc::ColumnSet>( aRefCxt.maRegroupCols); | |||
2704 | StartNeededListeners( pColSet); | |||
2705 | } | |||
2706 | ||||
2707 | SetInsertingFromOtherDoc( bOldInserting); | |||
2708 | } | |||
2709 | } | |||
2710 | else | |||
2711 | { | |||
2712 | aRefCxt.meMode = URM_COPY; | |||
2713 | UpdateReference(aRefCxt, rCxt.getUndoDoc(), false); | |||
2714 | } | |||
2715 | ||||
2716 | nClipTab = (nClipTab+nFollow+1) % static_cast<SCTAB>(rClipTabs.size()); | |||
2717 | i = sal::static_int_cast<SCTAB>( i + nFollow ); | |||
2718 | } | |||
2719 | } | |||
2720 | } | |||
2721 | ||||
2722 | void ScDocument::CopyNonFilteredFromClip( | |||
2723 | sc::CopyFromClipContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, | |||
2724 | const ScMarkData& rMark, SCCOL nDx, SCROW & rClipStartRow ) | |||
2725 | { | |||
2726 | // call CopyBlockFromClip for ranges of consecutive non-filtered rows | |||
2727 | // nCol1/nRow1 etc. is in target doc | |||
2728 | ||||
2729 | // filtered state is taken from first used table in clipboard (as in GetClipArea) | |||
2730 | SCTAB nFlagTab = 0; | |||
2731 | TableContainer& rClipTabs = rCxt.getClipDoc()->maTabs; | |||
2732 | while ( nFlagTab < static_cast<SCTAB>(rClipTabs.size()) && !rClipTabs[nFlagTab] ) | |||
2733 | ++nFlagTab; | |||
2734 | ||||
2735 | SCROW nSourceRow = rClipStartRow; | |||
2736 | SCROW nSourceEnd = 0; | |||
2737 | if (!rCxt.getClipDoc()->GetClipParam().maRanges.empty()) | |||
2738 | nSourceEnd = rCxt.getClipDoc()->GetClipParam().maRanges.front().aEnd.Row(); | |||
2739 | SCROW nDestRow = nRow1; | |||
2740 | ||||
2741 | while ( nSourceRow <= nSourceEnd && nDestRow <= nRow2 ) | |||
2742 | { | |||
2743 | // skip filtered rows | |||
2744 | nSourceRow = rCxt.getClipDoc()->FirstNonFilteredRow(nSourceRow, nSourceEnd, nFlagTab); | |||
2745 | ||||
2746 | if ( nSourceRow <= nSourceEnd ) | |||
2747 | { | |||
2748 | // look for more non-filtered rows following | |||
2749 | SCROW nLastRow = nSourceRow; | |||
2750 | (void)rCxt.getClipDoc()->RowFiltered(nSourceRow, nFlagTab, nullptr, &nLastRow); | |||
2751 | SCROW nFollow = nLastRow - nSourceRow; | |||
2752 | ||||
2753 | if (nFollow > nSourceEnd - nSourceRow) | |||
2754 | nFollow = nSourceEnd - nSourceRow; | |||
2755 | if (nFollow > nRow2 - nDestRow) | |||
2756 | nFollow = nRow2 - nDestRow; | |||
2757 | ||||
2758 | SCROW nNewDy = nDestRow - nSourceRow; | |||
2759 | CopyBlockFromClip( | |||
2760 | rCxt, nCol1, nDestRow, nCol2, nDestRow + nFollow, rMark, nDx, nNewDy); | |||
2761 | ||||
2762 | nSourceRow += nFollow + 1; | |||
2763 | nDestRow += nFollow + 1; | |||
2764 | } | |||
2765 | } | |||
2766 | rClipStartRow = nSourceRow; | |||
2767 | } | |||
2768 | ||||
2769 | namespace { | |||
2770 | ||||
2771 | class BroadcastAction : public sc::ColumnSpanSet::ColumnAction | |||
2772 | { | |||
2773 | ScDocument& mrDoc; | |||
2774 | ScColumn* mpCol; | |||
2775 | ||||
2776 | public: | |||
2777 | explicit BroadcastAction( ScDocument& rDoc ) : mrDoc(rDoc), mpCol(nullptr) {} | |||
2778 | ||||
2779 | virtual void startColumn( ScColumn* pCol ) override | |||
2780 | { | |||
2781 | mpCol = pCol; | |||
2782 | } | |||
2783 | ||||
2784 | virtual void execute( SCROW nRow1, SCROW nRow2, bool bVal ) override | |||
2785 | { | |||
2786 | if (!bVal) | |||
2787 | return; | |||
2788 | ||||
2789 | assert(mpCol)(static_cast <bool> (mpCol) ? void (0) : __assert_fail ( "mpCol", "/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" , 2789, __extension__ __PRETTY_FUNCTION__)); | |||
2790 | ScRange aRange(mpCol->GetCol(), nRow1, mpCol->GetTab()); | |||
2791 | aRange.aEnd.SetRow(nRow2); | |||
2792 | mrDoc.BroadcastCells(aRange, SfxHintId::ScDataChanged); | |||
2793 | }; | |||
2794 | }; | |||
2795 | ||||
2796 | } | |||
2797 | ||||
2798 | void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMark, | |||
2799 | InsertDeleteFlags nInsFlag, | |||
2800 | ScDocument* pRefUndoDoc, ScDocument* pClipDoc, bool bResetCut, | |||
2801 | bool bAsLink, bool bIncludeFiltered, bool bSkipAttrForEmpty, | |||
2802 | const ScRangeList * pDestRanges ) | |||
2803 | { | |||
2804 | if (bIsClip) | |||
| ||||
2805 | return; | |||
2806 | ||||
2807 | if (!pClipDoc) | |||
2808 | { | |||
2809 | OSL_FAIL("CopyFromClip: no ClipDoc")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "2809" ": "), "%s", "CopyFromClip: no ClipDoc"); } } while (false); | |||
2810 | pClipDoc = ScModule::GetClipDoc(); | |||
2811 | } | |||
2812 | ||||
2813 | if (!pClipDoc->bIsClip || !pClipDoc->GetTableCount()) | |||
2814 | return; | |||
2815 | ||||
2816 | sc::AutoCalcSwitch aACSwitch(*this, false); // temporarily turn off auto calc. | |||
2817 | ||||
2818 | NumFmtMergeHandler aNumFmtMergeHdl(*this, *pClipDoc); | |||
2819 | ||||
2820 | SCCOL nAllCol1 = rDestRange.aStart.Col(); | |||
2821 | SCROW nAllRow1 = rDestRange.aStart.Row(); | |||
2822 | SCCOL nAllCol2 = rDestRange.aEnd.Col(); | |||
2823 | SCROW nAllRow2 = rDestRange.aEnd.Row(); | |||
2824 | ||||
2825 | SCCOL nXw = 0; | |||
2826 | SCROW nYw = 0; | |||
2827 | ScRange aClipRange = pClipDoc->GetClipParam().getWholeRange(); | |||
2828 | for (SCTAB nTab = 0; nTab < static_cast<SCTAB>(pClipDoc->maTabs.size()); nTab++) // find largest merge overlap | |||
2829 | if (pClipDoc->maTabs[nTab]) // all sheets of the clipboard content | |||
2830 | { | |||
2831 | SCCOL nThisEndX = aClipRange.aEnd.Col(); | |||
2832 | SCROW nThisEndY = aClipRange.aEnd.Row(); | |||
2833 | pClipDoc->ExtendMerge( aClipRange.aStart.Col(), | |||
2834 | aClipRange.aStart.Row(), | |||
2835 | nThisEndX, nThisEndY, nTab ); | |||
2836 | // only extra value from ExtendMerge | |||
2837 | nThisEndX = sal::static_int_cast<SCCOL>( nThisEndX - aClipRange.aEnd.Col() ); | |||
2838 | nThisEndY = sal::static_int_cast<SCROW>( nThisEndY - aClipRange.aEnd.Row() ); | |||
2839 | if ( nThisEndX > nXw ) | |||
2840 | nXw = nThisEndX; | |||
2841 | if ( nThisEndY > nYw ) | |||
2842 | nYw = nThisEndY; | |||
2843 | } | |||
2844 | ||||
2845 | SCCOL nDestAddX; | |||
2846 | SCROW nDestAddY; | |||
2847 | pClipDoc->GetClipArea( nDestAddX, nDestAddY, bIncludeFiltered ); | |||
2848 | nXw = sal::static_int_cast<SCCOL>( nXw + nDestAddX ); | |||
| ||||
2849 | nYw = sal::static_int_cast<SCROW>( nYw + nDestAddY ); // ClipArea, plus ExtendMerge value | |||
2850 | ||||
2851 | /* Decide which contents to delete before copying. Delete all | |||
2852 | contents if nInsFlag contains any real content flag. | |||
2853 | #i102056# Notes are pasted from clipboard in a second pass, | |||
2854 | together with the special flag InsertDeleteFlags::ADDNOTES that states to not | |||
2855 | overwrite/delete existing cells but to insert the notes into | |||
2856 | these cells. In this case, just delete old notes from the | |||
2857 | destination area. */ | |||
2858 | InsertDeleteFlags nDelFlag = InsertDeleteFlags::NONE; | |||
2859 | if ( (nInsFlag & (InsertDeleteFlags::CONTENTS | InsertDeleteFlags::ADDNOTES)) == (InsertDeleteFlags::NOTE | InsertDeleteFlags::ADDNOTES) ) | |||
2860 | nDelFlag |= InsertDeleteFlags::NOTE; | |||
2861 | else if ( nInsFlag & InsertDeleteFlags::CONTENTS ) | |||
2862 | nDelFlag |= InsertDeleteFlags::CONTENTS; | |||
2863 | ||||
2864 | if (nInsFlag & InsertDeleteFlags::ATTRIB) | |||
2865 | nDelFlag |= InsertDeleteFlags::ATTRIB; | |||
2866 | ||||
2867 | sc::CopyFromClipContext aCxt(*this, pRefUndoDoc, pClipDoc, nInsFlag, bAsLink, bSkipAttrForEmpty); | |||
2868 | std::pair<SCTAB,SCTAB> aTabRanges = getMarkedTableRange(maTabs, rMark); | |||
2869 | aCxt.setTabRange(aTabRanges.first, aTabRanges.second); | |||
2870 | aCxt.setDeleteFlag(nDelFlag); | |||
2871 | ||||
2872 | ScRangeList aLocalRangeList; | |||
2873 | if (!pDestRanges) | |||
2874 | { | |||
2875 | aLocalRangeList.push_back( rDestRange); | |||
2876 | pDestRanges = &aLocalRangeList; | |||
2877 | } | |||
2878 | ||||
2879 | bInsertingFromOtherDoc = true; // No Broadcast/Listener created at Insert | |||
2880 | ||||
2881 | sc::ColumnSpanSet aBroadcastSpans; | |||
2882 | ||||
2883 | SCCOL nClipStartCol = aClipRange.aStart.Col(); | |||
2884 | SCROW nClipStartRow = aClipRange.aStart.Row(); | |||
2885 | SCROW nClipEndRow = aClipRange.aEnd.Row(); | |||
2886 | for ( size_t nRange = 0; nRange < pDestRanges->size(); ++nRange ) | |||
2887 | { | |||
2888 | const ScRange & rRange = (*pDestRanges)[nRange]; | |||
2889 | SCCOL nCol1 = rRange.aStart.Col(); | |||
2890 | SCROW nRow1 = rRange.aStart.Row(); | |||
2891 | SCCOL nCol2 = rRange.aEnd.Col(); | |||
2892 | SCROW nRow2 = rRange.aEnd.Row(); | |||
2893 | ||||
2894 | if (bSkipAttrForEmpty) | |||
2895 | { | |||
2896 | // Delete cells in the destination only if their corresponding clip cells are not empty. | |||
2897 | aCxt.setDestRange(nCol1, nRow1, nCol2, nRow2); | |||
2898 | DeleteBeforeCopyFromClip(aCxt, rMark, aBroadcastSpans); | |||
2899 | } | |||
2900 | else | |||
2901 | DeleteArea(nCol1, nRow1, nCol2, nRow2, rMark, nDelFlag, false, &aBroadcastSpans); | |||
2902 | ||||
2903 | if (CopyOneCellFromClip(aCxt, nCol1, nRow1, nCol2, nRow2)) | |||
2904 | continue; | |||
2905 | ||||
2906 | SCCOL nC1 = nCol1; | |||
2907 | SCROW nR1 = nRow1; | |||
2908 | SCCOL nC2 = nC1 + nXw; | |||
2909 | if (nC2 > nCol2) | |||
2910 | nC2 = nCol2; | |||
2911 | SCROW nR2 = nR1 + nYw; | |||
2912 | if (nR2 > nRow2) | |||
2913 | nR2 = nRow2; | |||
2914 | ||||
2915 | const SCCOLROW nThreshold = 8192; | |||
2916 | bool bPreallocatePattern = ((nInsFlag & InsertDeleteFlags::ATTRIB) && (nRow2 - nRow1 > nThreshold)); | |||
2917 | std::vector< SCTAB > vTables; | |||
2918 | ||||
2919 | if (bPreallocatePattern) | |||
2920 | { | |||
2921 | for (SCTAB i = aCxt.getTabStart(); i <= aCxt.getTabEnd(); ++i) | |||
2922 | if (maTabs[i] && rMark.GetTableSelect( i ) ) | |||
2923 | vTables.push_back( i ); | |||
2924 | } | |||
2925 | ||||
2926 | do | |||
2927 | { | |||
2928 | // Pasting is done column-wise, when pasting to a filtered | |||
2929 | // area this results in partitioning and we have to | |||
2930 | // remember and reset the start row for each column until | |||
2931 | // it can be advanced for the next chunk of unfiltered | |||
2932 | // rows. | |||
2933 | SCROW nSaveClipStartRow = nClipStartRow; | |||
2934 | do | |||
2935 | { | |||
2936 | nClipStartRow = nSaveClipStartRow; | |||
2937 | SCCOL nDx = nC1 - nClipStartCol; | |||
2938 | SCROW nDy = nR1 - nClipStartRow; | |||
2939 | if ( bIncludeFiltered ) | |||
2940 | { | |||
2941 | CopyBlockFromClip( | |||
2942 | aCxt, nC1, nR1, nC2, nR2, rMark, nDx, nDy); | |||
2943 | nClipStartRow += nR2 - nR1 + 1; | |||
2944 | } | |||
2945 | else | |||
2946 | { | |||
2947 | CopyNonFilteredFromClip( | |||
2948 | aCxt, nC1, nR1, nC2, nR2, rMark, nDx, nClipStartRow); | |||
2949 | } | |||
2950 | nC1 = nC2 + 1; | |||
2951 | nC2 = std::min(static_cast<SCCOL>(nC1 + nXw), nCol2); | |||
2952 | } while (nC1 <= nCol2); | |||
2953 | if (nClipStartRow > nClipEndRow) | |||
2954 | nClipStartRow = aClipRange.aStart.Row(); | |||
2955 | nC1 = nCol1; | |||
2956 | nC2 = nC1 + nXw; | |||
2957 | if (nC2 > nCol2) | |||
2958 | nC2 = nCol2; | |||
2959 | ||||
2960 | // Preallocate pattern memory once if further chunks are to be pasted. | |||
2961 | if (bPreallocatePattern && (nR2+1) <= nRow2) | |||
2962 | { | |||
2963 | SCROW nR3 = nR2 + 1; | |||
2964 | for (SCTAB nTab : vTables) | |||
2965 | { | |||
2966 | for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol) | |||
2967 | { | |||
2968 | // Pattern count of the first chunk pasted. | |||
2969 | SCSIZE nChunk = GetPatternCount( nTab, nCol, nR1, nR2); | |||
2970 | // If it is only one pattern per chunk and chunks are | |||
2971 | // pasted consecutively then it will get its range | |||
2972 | // enlarged for each chunk and no further allocation | |||
2973 | // happens. For non-consecutive chunks we're out of | |||
2974 | // luck in this case. | |||
2975 | if (nChunk > 1) | |||
2976 | { | |||
2977 | SCSIZE nNeeded = nChunk * (nRow2 - nR3 + 1) / (nYw + 1); | |||
2978 | SCSIZE nRemain = GetPatternCount( nTab, nCol, nR3, nRow2); | |||
2979 | if (nNeeded > nRemain) | |||
2980 | { | |||
2981 | SCSIZE nCurr = GetPatternCount( nTab, nCol); | |||
2982 | ReservePatternCount( nTab, nCol, nCurr + nNeeded); | |||
2983 | } | |||
2984 | } | |||
2985 | } | |||
2986 | } | |||
2987 | bPreallocatePattern = false; | |||
2988 | } | |||
2989 | ||||
2990 | nR1 = nR2 + 1; | |||
2991 | nR2 = std::min(static_cast<SCROW>(nR1 + nYw), nRow2); | |||
2992 | } while (nR1 <= nRow2); | |||
2993 | } | |||
2994 | ||||
2995 | bInsertingFromOtherDoc = false; | |||
2996 | ||||
2997 | // Create Listener after everything has been inserted | |||
2998 | StartListeningFromClip( nAllCol1, nAllRow1, nAllCol2, nAllRow2, rMark, nInsFlag ); | |||
2999 | ||||
3000 | { | |||
3001 | ScBulkBroadcast aBulkBroadcast( GetBASM(), SfxHintId::ScDataChanged); | |||
3002 | ||||
3003 | // Set all formula cells dirty, and collect non-empty non-formula cell | |||
3004 | // positions so that we can broadcast on them below. | |||
3005 | SetDirtyFromClip(nAllCol1, nAllRow1, nAllCol2, nAllRow2, rMark, nInsFlag, aBroadcastSpans); | |||
3006 | ||||
3007 | BroadcastAction aAction(*this); | |||
3008 | aBroadcastSpans.executeColumnAction(*this, aAction); | |||
3009 | } | |||
3010 | ||||
3011 | if (bResetCut) | |||
3012 | pClipDoc->GetClipParam().mbCutMode = false; | |||
3013 | } | |||
3014 | ||||
3015 | void ScDocument::CopyMultiRangeFromClip( | |||
3016 | const ScAddress& rDestPos, const ScMarkData& rMark, InsertDeleteFlags nInsFlag, ScDocument* pClipDoc, | |||
3017 | bool bResetCut, bool bAsLink, bool /*bIncludeFiltered*/, bool bSkipAttrForEmpty) | |||
3018 | { | |||
3019 | if (bIsClip) | |||
3020 | return; | |||
3021 | ||||
3022 | if (!pClipDoc->bIsClip || !pClipDoc->GetTableCount()) | |||
3023 | // There is nothing in the clip doc to copy. | |||
3024 | return; | |||
3025 | ||||
3026 | // Right now, we don't allow pasting into filtered rows, so we don't even handle it here. | |||
3027 | ||||
3028 | sc::AutoCalcSwitch aACSwitch(*this, false); // turn of auto calc temporarily. | |||
3029 | NumFmtMergeHandler aNumFmtMergeHdl(*this, *pClipDoc); | |||
3030 | ||||
3031 | ScRange aDestRange; | |||
3032 | rMark.GetMarkArea(aDestRange); | |||
3033 | ||||
3034 | bInsertingFromOtherDoc = true; // No Broadcast/Listener created at Insert | |||
3035 | ||||
3036 | SCCOL nCol1 = rDestPos.Col(); | |||
3037 | SCROW nRow1 = rDestPos.Row(); | |||
3038 | ScClipParam& rClipParam = pClipDoc->GetClipParam(); | |||
3039 | ||||
3040 | sc::ColumnSpanSet aBroadcastSpans; | |||
3041 | ||||
3042 | if (!bSkipAttrForEmpty) | |||
3043 | { | |||
3044 | // Do the deletion first. | |||
3045 | SCCOL nColSize = rClipParam.getPasteColSize(); | |||
3046 | SCROW nRowSize = rClipParam.getPasteRowSize(); | |||
3047 | ||||
3048 | DeleteArea(nCol1, nRow1, nCol1+nColSize-1, nRow1+nRowSize-1, rMark, InsertDeleteFlags::CONTENTS, false, &aBroadcastSpans); | |||
3049 | } | |||
3050 | ||||
3051 | sc::CopyFromClipContext aCxt(*this, nullptr, pClipDoc, nInsFlag, bAsLink, bSkipAttrForEmpty); | |||
3052 | std::pair<SCTAB,SCTAB> aTabRanges = getMarkedTableRange(maTabs, rMark); | |||
3053 | aCxt.setTabRange(aTabRanges.first, aTabRanges.second); | |||
3054 | ||||
3055 | for (size_t i = 0, n = rClipParam.maRanges.size(); i < n; ++i) | |||
3056 | { | |||
3057 | const ScRange & rRange = rClipParam.maRanges[i]; | |||
3058 | ||||
3059 | SCROW nRowCount = rRange.aEnd.Row() - rRange.aStart.Row() + 1; | |||
3060 | SCCOL nDx = static_cast<SCCOL>(nCol1 - rRange.aStart.Col()); | |||
3061 | SCROW nDy = static_cast<SCROW>(nRow1 - rRange.aStart.Row()); | |||
3062 | SCCOL nCol2 = nCol1 + rRange.aEnd.Col() - rRange.aStart.Col(); | |||
3063 | SCROW nEndRow = nRow1 + nRowCount - 1; | |||
3064 | ||||
3065 | CopyBlockFromClip(aCxt, nCol1, nRow1, nCol2, nEndRow, rMark, nDx, nDy); | |||
3066 | ||||
3067 | switch (rClipParam.meDirection) | |||
3068 | { | |||
3069 | case ScClipParam::Row: | |||
3070 | // Begin row for the next range being pasted. | |||
3071 | nRow1 += nRowCount; | |||
3072 | break; | |||
3073 | case ScClipParam::Column: | |||
3074 | nCol1 += rRange.aEnd.Col() - rRange.aStart.Col() + 1; | |||
3075 | break; | |||
3076 | default: | |||
3077 | ; | |||
3078 | } | |||
3079 | } | |||
3080 | ||||
3081 | bInsertingFromOtherDoc = false; | |||
3082 | ||||
3083 | // Create Listener after everything has been inserted | |||
3084 | StartListeningFromClip(aDestRange.aStart.Col(), aDestRange.aStart.Row(), | |||
3085 | aDestRange.aEnd.Col(), aDestRange.aEnd.Row(), rMark, nInsFlag ); | |||
3086 | ||||
3087 | { | |||
3088 | ScBulkBroadcast aBulkBroadcast( GetBASM(), SfxHintId::ScDataChanged); | |||
3089 | ||||
3090 | // Set formula cells dirty and collect non-formula cells. | |||
3091 | SetDirtyFromClip( | |||
3092 | aDestRange.aStart.Col(), aDestRange.aStart.Row(), aDestRange.aEnd.Col(), aDestRange.aEnd.Row(), | |||
3093 | rMark, nInsFlag, aBroadcastSpans); | |||
3094 | ||||
3095 | BroadcastAction aAction(*this); | |||
3096 | aBroadcastSpans.executeColumnAction(*this, aAction); | |||
3097 | } | |||
3098 | ||||
3099 | if (bResetCut) | |||
3100 | pClipDoc->GetClipParam().mbCutMode = false; | |||
3101 | } | |||
3102 | ||||
3103 | void ScDocument::SetClipArea( const ScRange& rArea, bool bCut ) | |||
3104 | { | |||
3105 | if (bIsClip) | |||
3106 | { | |||
3107 | ScClipParam& rClipParam = GetClipParam(); | |||
3108 | rClipParam.maRanges.RemoveAll(); | |||
3109 | rClipParam.maRanges.push_back(rArea); | |||
3110 | rClipParam.mbCutMode = bCut; | |||
3111 | } | |||
3112 | else | |||
3113 | { | |||
3114 | OSL_FAIL("SetClipArea: No Clip")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "3114" ": "), "%s", "SetClipArea: No Clip"); } } while ( false); | |||
3115 | } | |||
3116 | } | |||
3117 | ||||
3118 | void ScDocument::GetClipArea(SCCOL& nClipX, SCROW& nClipY, bool bIncludeFiltered) | |||
3119 | { | |||
3120 | if (!bIsClip) | |||
3121 | { | |||
3122 | OSL_FAIL("GetClipArea: No Clip")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "3122" ": "), "%s", "GetClipArea: No Clip"); } } while ( false); | |||
3123 | return; | |||
3124 | } | |||
3125 | ||||
3126 | ScRangeList& rClipRanges = GetClipParam().maRanges; | |||
3127 | if (rClipRanges.empty()) | |||
3128 | // No clip range. Bail out. | |||
3129 | return; | |||
3130 | ||||
3131 | ScRange const & rRange = rClipRanges.front(); | |||
3132 | SCCOL nStartCol = rRange.aStart.Col(); | |||
3133 | SCCOL nEndCol = rRange.aEnd.Col(); | |||
3134 | SCROW nStartRow = rRange.aStart.Row(); | |||
3135 | SCROW nEndRow = rRange.aEnd.Row(); | |||
3136 | for ( size_t i = 1, n = rClipRanges.size(); i < n; ++i ) | |||
3137 | { | |||
3138 | ScRange const & rRange2 = rClipRanges[ i ]; | |||
3139 | if (rRange2.aStart.Col() < nStartCol) | |||
3140 | nStartCol = rRange2.aStart.Col(); | |||
3141 | if (rRange2.aStart.Row() < nStartRow) | |||
3142 | nStartRow = rRange2.aStart.Row(); | |||
3143 | if (rRange2.aEnd.Col() > nEndCol) | |||
3144 | nEndCol = rRange2.aEnd.Col(); | |||
3145 | if (rRange2.aEnd.Row() < nEndRow) | |||
3146 | nEndRow = rRange2.aEnd.Row(); | |||
3147 | } | |||
3148 | ||||
3149 | nClipX = nEndCol - nStartCol; | |||
3150 | ||||
3151 | if ( bIncludeFiltered ) | |||
3152 | nClipY = nEndRow - nStartRow; | |||
3153 | else | |||
3154 | { | |||
3155 | // count non-filtered rows | |||
3156 | // count on first used table in clipboard | |||
3157 | SCTAB nCountTab = 0; | |||
3158 | while ( nCountTab < static_cast<SCTAB>(maTabs.size()) && !maTabs[nCountTab] ) | |||
3159 | ++nCountTab; | |||
3160 | ||||
3161 | SCROW nResult = CountNonFilteredRows(nStartRow, nEndRow, nCountTab); | |||
3162 | ||||
3163 | if ( nResult > 0 ) | |||
3164 | nClipY = nResult - 1; | |||
3165 | else | |||
3166 | nClipY = 0; // always return at least 1 row | |||
3167 | } | |||
3168 | } | |||
3169 | ||||
3170 | void ScDocument::GetClipStart(SCCOL& nClipX, SCROW& nClipY) | |||
3171 | { | |||
3172 | if (bIsClip) | |||
3173 | { | |||
3174 | ScRangeList& rClipRanges = GetClipParam().maRanges; | |||
3175 | if ( !rClipRanges.empty() ) | |||
3176 | { | |||
3177 | nClipX = rClipRanges.front().aStart.Col(); | |||
3178 | nClipY = rClipRanges.front().aStart.Row(); | |||
3179 | } | |||
3180 | } | |||
3181 | else | |||
3182 | { | |||
3183 | OSL_FAIL("GetClipStart: No Clip")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "3183" ": "), "%s", "GetClipStart: No Clip"); } } while ( false); | |||
3184 | } | |||
3185 | } | |||
3186 | ||||
3187 | bool ScDocument::HasClipFilteredRows() | |||
3188 | { | |||
3189 | // count on first used table in clipboard | |||
3190 | SCTAB nCountTab = 0; | |||
3191 | while ( nCountTab < static_cast<SCTAB>(maTabs.size()) && !maTabs[nCountTab] ) | |||
3192 | ++nCountTab; | |||
3193 | ||||
3194 | ScRangeList& rClipRanges = GetClipParam().maRanges; | |||
3195 | if ( rClipRanges.empty() ) | |||
3196 | return false; | |||
3197 | ||||
3198 | for ( size_t i = 0, n = rClipRanges.size(); i < n; ++i ) | |||
3199 | { | |||
3200 | ScRange & rRange = rClipRanges[ i ]; | |||
3201 | bool bAnswer = maTabs[nCountTab]->HasFilteredRows(rRange.aStart.Row(), rRange.aEnd.Row()); | |||
3202 | if (bAnswer) | |||
3203 | return true; | |||
3204 | } | |||
3205 | return false; | |||
3206 | } | |||
3207 | ||||
3208 | void ScDocument::MixDocument( const ScRange& rRange, ScPasteFunc nFunction, bool bSkipEmpty, | |||
3209 | ScDocument& rSrcDoc ) | |||
3210 | { | |||
3211 | SCTAB nTab1 = rRange.aStart.Tab(); | |||
3212 | SCTAB nTab2 = rRange.aEnd.Tab(); | |||
3213 | sc::MixDocContext aCxt(*this); | |||
3214 | SCTAB nMinSizeBothTabs = static_cast<SCTAB>(std::min(maTabs.size(), rSrcDoc.maTabs.size())); | |||
3215 | for (SCTAB i = nTab1; i <= nTab2 && i < nMinSizeBothTabs; i++) | |||
3216 | { | |||
3217 | ScTable* pTab = FetchTable(i); | |||
3218 | const ScTable* pSrcTab = rSrcDoc.FetchTable(i); | |||
3219 | if (!pTab || !pSrcTab) | |||
3220 | continue; | |||
3221 | ||||
3222 | pTab->MixData( | |||
3223 | aCxt, rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row(), | |||
3224 | nFunction, bSkipEmpty, pSrcTab); | |||
3225 | } | |||
3226 | } | |||
3227 | ||||
3228 | void ScDocument::FillTab( const ScRange& rSrcArea, const ScMarkData& rMark, | |||
3229 | InsertDeleteFlags nFlags, ScPasteFunc nFunction, | |||
3230 | bool bSkipEmpty, bool bAsLink ) | |||
3231 | { | |||
3232 | InsertDeleteFlags nDelFlags = nFlags; | |||
3233 | if (nDelFlags & InsertDeleteFlags::CONTENTS) | |||
3234 | nDelFlags |= InsertDeleteFlags::CONTENTS; // Either all contents or delete nothing! | |||
3235 | ||||
3236 | SCTAB nSrcTab = rSrcArea.aStart.Tab(); | |||
3237 | ||||
3238 | if (ValidTab(nSrcTab) && nSrcTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nSrcTab]) | |||
3239 | { | |||
3240 | SCCOL nStartCol = rSrcArea.aStart.Col(); | |||
3241 | SCROW nStartRow = rSrcArea.aStart.Row(); | |||
3242 | SCCOL nEndCol = rSrcArea.aEnd.Col(); | |||
3243 | SCROW nEndRow = rSrcArea.aEnd.Row(); | |||
3244 | ScDocumentUniquePtr pMixDoc; | |||
3245 | bool bDoMix = ( bSkipEmpty || nFunction != ScPasteFunc::NONE ) && ( nFlags & InsertDeleteFlags::CONTENTS ); | |||
3246 | ||||
3247 | bool bOldAutoCalc = GetAutoCalc(); | |||
3248 | SetAutoCalc( false ); // avoid multiple calculations | |||
3249 | ||||
3250 | sc::CopyToDocContext aCxt(*this); | |||
3251 | sc::MixDocContext aMixDocCxt(*this); | |||
3252 | ||||
3253 | SCTAB nCount = static_cast<SCTAB>(maTabs.size()); | |||
3254 | for (const SCTAB& i : rMark) | |||
3255 | { | |||
3256 | if (i >= nCount) | |||
3257 | break; | |||
3258 | if (i != nSrcTab && maTabs[i]) | |||
3259 | { | |||
3260 | if (bDoMix) | |||
3261 | { | |||
3262 | if (!pMixDoc) | |||
3263 | { | |||
3264 | pMixDoc.reset(new ScDocument(SCDOCMODE_UNDO)); | |||
3265 | pMixDoc->InitUndo( *this, i, i ); | |||
3266 | } | |||
3267 | else | |||
3268 | pMixDoc->AddUndoTab( i, i ); | |||
3269 | ||||
3270 | // context used for copying content to the temporary mix document. | |||
3271 | sc::CopyToDocContext aMixCxt(*pMixDoc); | |||
3272 | maTabs[i]->CopyToTable(aMixCxt, nStartCol,nStartRow, nEndCol,nEndRow, | |||
3273 | InsertDeleteFlags::CONTENTS, false, pMixDoc->maTabs[i].get(), | |||
3274 | /*pMarkData*/nullptr, /*bAsLink*/false, /*bColRowFlags*/true, | |||
3275 | /*bGlobalNamesToLocal*/false, /*bCopyCaptions*/true ); | |||
3276 | } | |||
3277 | maTabs[i]->DeleteArea( nStartCol,nStartRow, nEndCol,nEndRow, nDelFlags); | |||
3278 | maTabs[nSrcTab]->CopyToTable(aCxt, nStartCol,nStartRow, nEndCol,nEndRow, | |||
3279 | nFlags, false, maTabs[i].get(), nullptr, bAsLink, | |||
3280 | /*bColRowFlags*/true, /*bGlobalNamesToLocal*/false, /*bCopyCaptions*/true ); | |||
3281 | ||||
3282 | if (bDoMix) | |||
3283 | maTabs[i]->MixData(aMixDocCxt, nStartCol,nStartRow, nEndCol,nEndRow, | |||
3284 | nFunction, bSkipEmpty, pMixDoc->maTabs[i].get() ); | |||
3285 | } | |||
3286 | } | |||
3287 | ||||
3288 | SetAutoCalc( bOldAutoCalc ); | |||
3289 | } | |||
3290 | else | |||
3291 | { | |||
3292 | OSL_FAIL("wrong table")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "3292" ": "), "%s", "wrong table"); } } while (false); | |||
3293 | } | |||
3294 | } | |||
3295 | ||||
3296 | void ScDocument::FillTabMarked( SCTAB nSrcTab, const ScMarkData& rMark, | |||
3297 | InsertDeleteFlags nFlags, ScPasteFunc nFunction, | |||
3298 | bool bSkipEmpty, bool bAsLink ) | |||
3299 | { | |||
3300 | InsertDeleteFlags nDelFlags = nFlags; | |||
3301 | if (nDelFlags & InsertDeleteFlags::CONTENTS) | |||
3302 | nDelFlags |= InsertDeleteFlags::CONTENTS; // Either all contents or delete nothing! | |||
3303 | ||||
3304 | if (ValidTab(nSrcTab) && nSrcTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nSrcTab]) | |||
3305 | { | |||
3306 | ScDocumentUniquePtr pMixDoc; | |||
3307 | bool bDoMix = ( bSkipEmpty || nFunction != ScPasteFunc::NONE ) && ( nFlags & InsertDeleteFlags::CONTENTS ); | |||
3308 | ||||
3309 | bool bOldAutoCalc = GetAutoCalc(); | |||
3310 | SetAutoCalc( false ); // avoid multiple calculations | |||
3311 | ||||
3312 | ScRange aArea; | |||
3313 | rMark.GetMultiMarkArea( aArea ); | |||
3314 | SCCOL nStartCol = aArea.aStart.Col(); | |||
3315 | SCROW nStartRow = aArea.aStart.Row(); | |||
3316 | SCCOL nEndCol = aArea.aEnd.Col(); | |||
3317 | SCROW nEndRow = aArea.aEnd.Row(); | |||
3318 | ||||
3319 | sc::CopyToDocContext aCxt(*this); | |||
3320 | sc::MixDocContext aMixDocCxt(*this); | |||
3321 | SCTAB nCount = static_cast<SCTAB>(maTabs.size()); | |||
3322 | for (const SCTAB& i : rMark) | |||
3323 | { | |||
3324 | if (i >= nCount) | |||
3325 | break; | |||
3326 | if ( i != nSrcTab && maTabs[i] ) | |||
3327 | { | |||
3328 | if (bDoMix) | |||
3329 | { | |||
3330 | if (!pMixDoc) | |||
3331 | { | |||
3332 | pMixDoc.reset(new ScDocument(SCDOCMODE_UNDO)); | |||
3333 | pMixDoc->InitUndo( *this, i, i ); | |||
3334 | } | |||
3335 | else | |||
3336 | pMixDoc->AddUndoTab( i, i ); | |||
3337 | ||||
3338 | sc::CopyToDocContext aMixCxt(*pMixDoc); | |||
3339 | maTabs[i]->CopyToTable(aMixCxt, nStartCol,nStartRow, nEndCol,nEndRow, | |||
3340 | InsertDeleteFlags::CONTENTS, true, pMixDoc->maTabs[i].get(), &rMark, | |||
3341 | /*bAsLink*/false, /*bColRowFlags*/true, /*bGlobalNamesToLocal*/false, | |||
3342 | /*bCopyCaptions*/true ); | |||
3343 | } | |||
3344 | ||||
3345 | maTabs[i]->DeleteSelection( nDelFlags, rMark ); | |||
3346 | maTabs[nSrcTab]->CopyToTable(aCxt, nStartCol,nStartRow, nEndCol,nEndRow, | |||
3347 | nFlags, true, maTabs[i].get(), &rMark, bAsLink, | |||
3348 | /*bColRowFlags*/true, /*bGlobalNamesToLocal*/false, /*bCopyCaptions*/true ); | |||
3349 | ||||
3350 | if (bDoMix) | |||
3351 | maTabs[i]->MixMarked(aMixDocCxt, rMark, nFunction, bSkipEmpty, pMixDoc->maTabs[i].get()); | |||
3352 | } | |||
3353 | } | |||
3354 | ||||
3355 | SetAutoCalc( bOldAutoCalc ); | |||
3356 | } | |||
3357 | else | |||
3358 | { | |||
3359 | OSL_FAIL("wrong table")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "3359" ": "), "%s", "wrong table"); } } while (false); | |||
3360 | } | |||
3361 | } | |||
3362 | ||||
3363 | bool ScDocument::SetString( SCCOL nCol, SCROW nRow, SCTAB nTab, const OUString& rString, | |||
3364 | const ScSetStringParam* pParam ) | |||
3365 | { | |||
3366 | ScTable* pTab = FetchTable(nTab); | |||
3367 | if (!pTab) | |||
3368 | return false; | |||
3369 | ||||
3370 | const ScFormulaCell* pCurCellFormula = pTab->GetFormulaCell(nCol, nRow); | |||
3371 | if (pCurCellFormula && pCurCellFormula->IsShared()) | |||
3372 | { | |||
3373 | // In case setting this string affects an existing formula group, end | |||
3374 | // its listening to purge then empty cell broadcasters. Affected | |||
3375 | // remaining split group listeners will be set up again via | |||
3376 | // ScColumn::DetachFormulaCell() and | |||
3377 | // ScColumn::StartListeningUnshared(). | |||
3378 | ||||
3379 | sc::EndListeningContext aCxt(*this); | |||
3380 | ScAddress aPos(nCol, nRow, nTab); | |||
3381 | EndListeningIntersectedGroup(aCxt, aPos, nullptr); | |||
3382 | aCxt.purgeEmptyBroadcasters(); | |||
3383 | } | |||
3384 | ||||
3385 | return pTab->SetString(nCol, nRow, nTab, rString, pParam); | |||
3386 | } | |||
3387 | ||||
3388 | bool ScDocument::SetString( | |||
3389 | const ScAddress& rPos, const OUString& rString, const ScSetStringParam* pParam ) | |||
3390 | { | |||
3391 | return SetString(rPos.Col(), rPos.Row(), rPos.Tab(), rString, pParam); | |||
3392 | } | |||
3393 | ||||
3394 | bool ScDocument::SetEditText( const ScAddress& rPos, std::unique_ptr<EditTextObject> pEditText ) | |||
3395 | { | |||
3396 | if (!TableExists(rPos.Tab())) | |||
3397 | { | |||
3398 | return false; | |||
3399 | } | |||
3400 | ||||
3401 | return maTabs[rPos.Tab()]->SetEditText(rPos.Col(), rPos.Row(), std::move(pEditText)); | |||
3402 | } | |||
3403 | ||||
3404 | void ScDocument::SetEditText( const ScAddress& rPos, const EditTextObject& rEditText, const SfxItemPool* pEditPool ) | |||
3405 | { | |||
3406 | if (!TableExists(rPos.Tab())) | |||
3407 | return; | |||
3408 | ||||
3409 | maTabs[rPos.Tab()]->SetEditText(rPos.Col(), rPos.Row(), rEditText, pEditPool); | |||
3410 | } | |||
3411 | ||||
3412 | void ScDocument::SetEditText( const ScAddress& rPos, const OUString& rStr ) | |||
3413 | { | |||
3414 | if (!TableExists(rPos.Tab())) | |||
3415 | return; | |||
3416 | ||||
3417 | ScFieldEditEngine& rEngine = GetEditEngine(); | |||
3418 | rEngine.SetTextCurrentDefaults(rStr); | |||
3419 | maTabs[rPos.Tab()]->SetEditText(rPos.Col(), rPos.Row(), rEngine.CreateTextObject()); | |||
3420 | } | |||
3421 | ||||
3422 | SCROW ScDocument::GetFirstEditTextRow( const ScRange& rRange ) const | |||
3423 | { | |||
3424 | const ScTable* pTab = FetchTable(rRange.aStart.Tab()); | |||
3425 | if (!pTab) | |||
3426 | return -1; | |||
3427 | ||||
3428 | return pTab->GetFirstEditTextRow(rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row()); | |||
3429 | } | |||
3430 | ||||
3431 | void ScDocument::SetTextCell( const ScAddress& rPos, const OUString& rStr ) | |||
3432 | { | |||
3433 | if (!TableExists(rPos.Tab())) | |||
3434 | return; | |||
3435 | ||||
3436 | if (ScStringUtil::isMultiline(rStr)) | |||
3437 | { | |||
3438 | ScFieldEditEngine& rEngine = GetEditEngine(); | |||
3439 | rEngine.SetTextCurrentDefaults(rStr); | |||
3440 | maTabs[rPos.Tab()]->SetEditText(rPos.Col(), rPos.Row(), rEngine.CreateTextObject()); | |||
3441 | } | |||
3442 | else | |||
3443 | { | |||
3444 | ScSetStringParam aParam; | |||
3445 | aParam.setTextInput(); | |||
3446 | maTabs[rPos.Tab()]->SetString(rPos.Col(), rPos.Row(), rPos.Tab(), rStr, &aParam); | |||
3447 | } | |||
3448 | } | |||
3449 | ||||
3450 | void ScDocument::SetEmptyCell( const ScAddress& rPos ) | |||
3451 | { | |||
3452 | if (!TableExists(rPos.Tab())) | |||
3453 | return; | |||
3454 | ||||
3455 | maTabs[rPos.Tab()]->SetEmptyCell(rPos.Col(), rPos.Row()); | |||
3456 | } | |||
3457 | ||||
3458 | void ScDocument::SetValue( SCCOL nCol, SCROW nRow, SCTAB nTab, const double& rVal ) | |||
3459 | { | |||
3460 | SetValue(ScAddress(nCol, nRow, nTab), rVal); | |||
3461 | } | |||
3462 | ||||
3463 | void ScDocument::SetValue( const ScAddress& rPos, double fVal ) | |||
3464 | { | |||
3465 | ScTable* pTab = FetchTable(rPos.Tab()); | |||
3466 | if (!pTab) | |||
3467 | return; | |||
3468 | ||||
3469 | const ScFormulaCell* pCurCellFormula = pTab->GetFormulaCell(rPos.Col(), rPos.Row()); | |||
3470 | if (pCurCellFormula && pCurCellFormula->IsShared()) | |||
3471 | { | |||
3472 | // In case setting this value affects an existing formula group, end | |||
3473 | // its listening to purge then empty cell broadcasters. Affected | |||
3474 | // remaining split group listeners will be set up again via | |||
3475 | // ScColumn::DetachFormulaCell() and | |||
3476 | // ScColumn::StartListeningUnshared(). | |||
3477 | ||||
3478 | sc::EndListeningContext aCxt(*this); | |||
3479 | EndListeningIntersectedGroup(aCxt, rPos, nullptr); | |||
3480 | aCxt.purgeEmptyBroadcasters(); | |||
3481 | } | |||
3482 | ||||
3483 | pTab->SetValue(rPos.Col(), rPos.Row(), fVal); | |||
3484 | } | |||
3485 | ||||
3486 | OUString ScDocument::GetString( SCCOL nCol, SCROW nRow, SCTAB nTab, const ScInterpreterContext* pContext ) const | |||
3487 | { | |||
3488 | if (TableExists(nTab)) | |||
3489 | { | |||
3490 | OUString aStr; | |||
3491 | maTabs[nTab]->GetString(nCol, nRow, aStr, pContext); | |||
3492 | return aStr; | |||
3493 | } | |||
3494 | else | |||
3495 | return EMPTY_OUSTRINGScGlobal::GetEmptyOUString(); | |||
3496 | } | |||
3497 | ||||
3498 | OUString ScDocument::GetString( const ScAddress& rPos, const ScInterpreterContext* pContext ) const | |||
3499 | { | |||
3500 | if (!TableExists(rPos.Tab())) | |||
3501 | return EMPTY_OUSTRINGScGlobal::GetEmptyOUString(); | |||
3502 | ||||
3503 | OUString aStr; | |||
3504 | maTabs[rPos.Tab()]->GetString(rPos.Col(), rPos.Row(), aStr, pContext); | |||
3505 | return aStr; | |||
3506 | } | |||
3507 | ||||
3508 | double* ScDocument::GetValueCell( const ScAddress& rPos ) | |||
3509 | { | |||
3510 | if (!TableExists(rPos.Tab())) | |||
3511 | return nullptr; | |||
3512 | ||||
3513 | return maTabs[rPos.Tab()]->GetValueCell(rPos.Col(), rPos.Row()); | |||
3514 | } | |||
3515 | ||||
3516 | svl::SharedString ScDocument::GetSharedString( const ScAddress& rPos ) const | |||
3517 | { | |||
3518 | if (!TableExists(rPos.Tab())) | |||
3519 | return svl::SharedString(); | |||
3520 | ||||
3521 | return maTabs[rPos.Tab()]->GetSharedString(rPos.Col(), rPos.Row()); | |||
3522 | } | |||
3523 | ||||
3524 | std::shared_ptr<sc::FormulaGroupContext>& ScDocument::GetFormulaGroupContext() | |||
3525 | { | |||
3526 | ScMutationGuard aGuard(*this, ScMutationGuardFlags::CORE); | |||
3527 | if (!mpFormulaGroupCxt) | |||
3528 | mpFormulaGroupCxt = std::make_shared<sc::FormulaGroupContext>(); | |||
3529 | ||||
3530 | return mpFormulaGroupCxt; | |||
3531 | } | |||
3532 | ||||
3533 | void ScDocument::DiscardFormulaGroupContext() | |||
3534 | { | |||
3535 | assert(!IsThreadedGroupCalcInProgress())(static_cast <bool> (!IsThreadedGroupCalcInProgress()) ? void (0) : __assert_fail ("!IsThreadedGroupCalcInProgress()" , "/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" , 3535, __extension__ __PRETTY_FUNCTION__)); | |||
3536 | if( !mbFormulaGroupCxtBlockDiscard ) | |||
3537 | mpFormulaGroupCxt.reset(); | |||
3538 | } | |||
3539 | ||||
3540 | void ScDocument::GetInputString( SCCOL nCol, SCROW nRow, SCTAB nTab, OUString& rString ) | |||
3541 | { | |||
3542 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
3543 | maTabs[nTab]->GetInputString( nCol, nRow, rString ); | |||
3544 | else | |||
3545 | rString.clear(); | |||
3546 | } | |||
3547 | ||||
3548 | FormulaError ScDocument::GetStringForFormula( const ScAddress& rPos, OUString& rString ) | |||
3549 | { | |||
3550 | // Used in formulas (add-in parameters etc), so it must use the same semantics as | |||
3551 | // ScInterpreter::GetCellString: always format values as numbers. | |||
3552 | // The return value is the error code. | |||
3553 | ||||
3554 | ScRefCellValue aCell(*this, rPos); | |||
3555 | if (aCell.isEmpty()) | |||
3556 | { | |||
3557 | rString = EMPTY_OUSTRINGScGlobal::GetEmptyOUString(); | |||
3558 | return FormulaError::NONE; | |||
3559 | } | |||
3560 | ||||
3561 | FormulaError nErr = FormulaError::NONE; | |||
3562 | OUString aStr; | |||
3563 | SvNumberFormatter* pFormatter = GetFormatTable(); | |||
3564 | switch (aCell.meType) | |||
3565 | { | |||
3566 | case CELLTYPE_STRING: | |||
3567 | case CELLTYPE_EDIT: | |||
3568 | aStr = aCell.getString(this); | |||
3569 | break; | |||
3570 | case CELLTYPE_FORMULA: | |||
3571 | { | |||
3572 | ScFormulaCell* pFCell = aCell.mpFormula; | |||
3573 | nErr = pFCell->GetErrCode(); | |||
3574 | if (pFCell->IsValue()) | |||
3575 | { | |||
3576 | double fVal = pFCell->GetValue(); | |||
3577 | sal_uInt32 nIndex = pFormatter->GetStandardFormat( | |||
3578 | SvNumFormatType::NUMBER, | |||
3579 | ScGlobal::eLnge); | |||
3580 | pFormatter->GetInputLineString(fVal, nIndex, aStr); | |||
3581 | } | |||
3582 | else | |||
3583 | aStr = pFCell->GetString().getString(); | |||
3584 | } | |||
3585 | break; | |||
3586 | case CELLTYPE_VALUE: | |||
3587 | { | |||
3588 | double fVal = aCell.mfValue; | |||
3589 | sal_uInt32 nIndex = pFormatter->GetStandardFormat( | |||
3590 | SvNumFormatType::NUMBER, | |||
3591 | ScGlobal::eLnge); | |||
3592 | pFormatter->GetInputLineString(fVal, nIndex, aStr); | |||
3593 | } | |||
3594 | break; | |||
3595 | default: | |||
3596 | ; | |||
3597 | } | |||
3598 | ||||
3599 | rString = aStr; | |||
3600 | return nErr; | |||
3601 | } | |||
3602 | ||||
3603 | void ScDocument::GetValue( SCCOL nCol, SCROW nRow, SCTAB nTab, double& rValue ) const | |||
3604 | { | |||
3605 | if (TableExists(nTab)) | |||
3606 | rValue = maTabs[nTab]->GetValue( nCol, nRow ); | |||
3607 | else | |||
3608 | rValue = 0.0; | |||
3609 | } | |||
3610 | ||||
3611 | const EditTextObject* ScDocument::GetEditText( const ScAddress& rPos ) const | |||
3612 | { | |||
3613 | SCTAB nTab = rPos.Tab(); | |||
3614 | if (!TableExists(nTab)) | |||
3615 | return nullptr; | |||
3616 | ||||
3617 | return maTabs[nTab]->GetEditText(rPos.Col(), rPos.Row()); | |||
3618 | } | |||
3619 | ||||
3620 | void ScDocument::RemoveEditTextCharAttribs( const ScAddress& rPos, const ScPatternAttr& rAttr ) | |||
3621 | { | |||
3622 | if (!TableExists(rPos.Tab())) | |||
3623 | return; | |||
3624 | ||||
3625 | return maTabs[rPos.Tab()]->RemoveEditTextCharAttribs(rPos.Col(), rPos.Row(), rAttr); | |||
3626 | } | |||
3627 | ||||
3628 | double ScDocument::GetValue( const ScAddress& rPos ) const | |||
3629 | { | |||
3630 | SCTAB nTab = rPos.Tab(); | |||
3631 | if ( nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
3632 | return maTabs[nTab]->GetValue(rPos.Col(), rPos.Row()); | |||
3633 | return 0.0; | |||
3634 | } | |||
3635 | ||||
3636 | double ScDocument::GetValue( SCCOL nCol, SCROW nRow, SCTAB nTab ) const | |||
3637 | { | |||
3638 | ScAddress aAdr(nCol, nRow, nTab); return GetValue(aAdr); | |||
3639 | } | |||
3640 | ||||
3641 | void ScDocument::GetNumberFormat( SCCOL nCol, SCROW nRow, SCTAB nTab, | |||
3642 | sal_uInt32& rFormat ) const | |||
3643 | { | |||
3644 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size())) | |||
3645 | if (maTabs[nTab]) | |||
3646 | { | |||
3647 | rFormat = maTabs[nTab]->GetNumberFormat( nCol, nRow ); | |||
3648 | return ; | |||
3649 | } | |||
3650 | rFormat = 0; | |||
3651 | } | |||
3652 | ||||
3653 | sal_uInt32 ScDocument::GetNumberFormat( const ScRange& rRange ) const | |||
3654 | { | |||
3655 | SCTAB nTab1 = rRange.aStart.Tab(), nTab2 = rRange.aEnd.Tab(); | |||
3656 | SCCOL nCol1 = rRange.aStart.Col(), nCol2 = rRange.aEnd.Col(); | |||
3657 | SCROW nRow1 = rRange.aStart.Row(), nRow2 = rRange.aEnd.Row(); | |||
3658 | ||||
3659 | if (!TableExists(nTab1) || !TableExists(nTab2)) | |||
3660 | return 0; | |||
3661 | ||||
3662 | sal_uInt32 nFormat = 0; | |||
3663 | bool bFirstItem = true; | |||
3664 | for (SCTAB nTab = nTab1; nTab <= nTab2 && nTab < static_cast<SCTAB>(maTabs.size()) ; ++nTab) | |||
3665 | for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol) | |||
3666 | { | |||
3667 | sal_uInt32 nThisFormat = maTabs[nTab]->GetNumberFormat(nCol, nRow1, nRow2); | |||
3668 | if (bFirstItem) | |||
3669 | { | |||
3670 | nFormat = nThisFormat; | |||
3671 | bFirstItem = false; | |||
3672 | } | |||
3673 | else if (nThisFormat != nFormat) | |||
3674 | return 0; | |||
3675 | } | |||
3676 | ||||
3677 | return nFormat; | |||
3678 | } | |||
3679 | ||||
3680 | sal_uInt32 ScDocument::GetNumberFormat( const ScInterpreterContext& rContext, const ScAddress& rPos ) const | |||
3681 | { | |||
3682 | SCTAB nTab = rPos.Tab(); | |||
3683 | if (!TableExists(nTab)) | |||
3684 | return 0; | |||
3685 | ||||
3686 | return maTabs[nTab]->GetNumberFormat( rContext, rPos ); | |||
3687 | } | |||
3688 | ||||
3689 | void ScDocument::SetNumberFormat( const ScAddress& rPos, sal_uInt32 nNumberFormat ) | |||
3690 | { | |||
3691 | assert(!IsThreadedGroupCalcInProgress())(static_cast <bool> (!IsThreadedGroupCalcInProgress()) ? void (0) : __assert_fail ("!IsThreadedGroupCalcInProgress()" , "/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" , 3691, __extension__ __PRETTY_FUNCTION__)); | |||
3692 | SCTAB nTab = rPos.Tab(); | |||
3693 | if (!TableExists(nTab)) | |||
3694 | return; | |||
3695 | ||||
3696 | maTabs[nTab]->SetNumberFormat(rPos.Col(), rPos.Row(), nNumberFormat); | |||
3697 | } | |||
3698 | ||||
3699 | void ScDocument::GetNumberFormatInfo( const ScInterpreterContext& rContext, SvNumFormatType& nType, sal_uInt32& nIndex, | |||
3700 | const ScAddress& rPos ) const | |||
3701 | { | |||
3702 | SCTAB nTab = rPos.Tab(); | |||
3703 | if ( nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
3704 | { | |||
3705 | nIndex = maTabs[nTab]->GetNumberFormat( rContext, rPos ); | |||
3706 | nType = rContext.GetNumberFormatType( nIndex ); | |||
3707 | } | |||
3708 | else | |||
3709 | { | |||
3710 | nType = SvNumFormatType::UNDEFINED; | |||
3711 | nIndex = 0; | |||
3712 | } | |||
3713 | } | |||
3714 | ||||
3715 | void ScDocument::GetFormula( SCCOL nCol, SCROW nRow, SCTAB nTab, OUString& rFormula ) const | |||
3716 | { | |||
3717 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
3718 | maTabs[nTab]->GetFormula( nCol, nRow, rFormula ); | |||
3719 | else | |||
3720 | rFormula.clear(); | |||
3721 | } | |||
3722 | ||||
3723 | const ScFormulaCell* ScDocument::GetFormulaCell( const ScAddress& rPos ) const | |||
3724 | { | |||
3725 | if (!TableExists(rPos.Tab())) | |||
3726 | return nullptr; | |||
3727 | ||||
3728 | return maTabs[rPos.Tab()]->GetFormulaCell(rPos.Col(), rPos.Row()); | |||
3729 | } | |||
3730 | ||||
3731 | ScFormulaCell* ScDocument::GetFormulaCell( const ScAddress& rPos ) | |||
3732 | { | |||
3733 | if (!TableExists(rPos.Tab())) | |||
3734 | return nullptr; | |||
3735 | ||||
3736 | return maTabs[rPos.Tab()]->GetFormulaCell(rPos.Col(), rPos.Row()); | |||
3737 | } | |||
3738 | ||||
3739 | CellType ScDocument::GetCellType( const ScAddress& rPos ) const | |||
3740 | { | |||
3741 | SCTAB nTab = rPos.Tab(); | |||
3742 | if ( nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
3743 | return maTabs[nTab]->GetCellType( rPos ); | |||
3744 | return CELLTYPE_NONE; | |||
3745 | } | |||
3746 | ||||
3747 | void ScDocument::GetCellType( SCCOL nCol, SCROW nRow, SCTAB nTab, | |||
3748 | CellType& rCellType ) const | |||
3749 | { | |||
3750 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab]) | |||
3751 | rCellType = maTabs[nTab]->GetCellType( nCol, nRow ); | |||
3752 | else | |||
3753 | rCellType = CELLTYPE_NONE; | |||
3754 | } | |||
3755 | ||||
3756 | bool ScDocument::HasStringData( SCCOL nCol, SCROW nRow, SCTAB nTab ) const | |||
3757 | { | |||
3758 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] | |||
3759 | && nCol < maTabs[nTab]->GetAllocatedColumnsCount()) | |||
3760 | return maTabs[nTab]->HasStringData( nCol, nRow ); | |||
3761 | else | |||
3762 | return false; | |||
3763 | } | |||
3764 | ||||
3765 | bool ScDocument::HasValueData( SCCOL nCol, SCROW nRow, SCTAB nTab ) const | |||
3766 | { | |||
3767 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] | |||
3768 | && nCol < maTabs[nTab]->GetAllocatedColumnsCount()) | |||
3769 | return maTabs[nTab]->HasValueData( nCol, nRow ); | |||
3770 | else | |||
3771 | return false; | |||
3772 | } | |||
3773 | ||||
3774 | bool ScDocument::HasValueData( const ScAddress& rPos ) const | |||
3775 | { | |||
3776 | return HasValueData(rPos.Col(), rPos.Row(), rPos.Tab()); | |||
3777 | } | |||
3778 | ||||
3779 | bool ScDocument::HasStringCells( const ScRange& rRange ) const | |||
3780 | { | |||
3781 | // true, if String- or Edit cells in range | |||
3782 | ||||
3783 | SCCOL nStartCol = rRange.aStart.Col(); | |||
3784 | SCROW nStartRow = rRange.aStart.Row(); | |||
3785 | SCTAB nStartTab = rRange.aStart.Tab(); | |||
3786 | SCCOL nEndCol = rRange.aEnd.Col(); | |||
3787 | SCROW nEndRow = rRange.aEnd.Row(); | |||
3788 | SCTAB nEndTab = rRange.aEnd.Tab(); | |||
3789 | ||||
3790 | for ( SCTAB nTab=nStartTab; nTab<=nEndTab && nTab < static_cast<SCTAB>(maTabs.size()); nTab++ ) | |||
3791 | if ( maTabs[nTab] && maTabs[nTab]->HasStringCells( nStartCol, nStartRow, nEndCol, nEndRow ) ) | |||
3792 | return true; | |||
3793 | ||||
3794 | return false; | |||
3795 | } | |||
3796 | ||||
3797 | bool ScDocument::HasSelectionData( SCCOL nCol, SCROW nRow, SCTAB nTab ) const | |||
3798 | { | |||
3799 | sal_uInt32 nValidation = GetAttr( nCol, nRow, nTab, ATTR_VALIDDATA )->GetValue(); | |||
3800 | if( nValidation ) | |||
3801 | { | |||
3802 | const ScValidationData* pData = GetValidationEntry( nValidation ); | |||
3803 | if( pData && pData->HasSelectionList() ) | |||
3804 | return true; | |||
3805 | } | |||
3806 | return HasStringCells( ScRange( nCol, 0, nTab, nCol, MaxRow(), nTab ) ); | |||
3807 | } | |||
3808 | ||||
3809 | bool ScDocument::HasValidationData( SCCOL nCol, SCROW nRow, SCTAB nTab ) const | |||
3810 | { | |||
3811 | sal_uInt32 nValidation = GetAttr( nCol, nRow, nTab, ATTR_VALIDDATA )->GetValue(); | |||
3812 | if( nValidation ) | |||
3813 | { | |||
3814 | const ScValidationData* pData = GetValidationEntry( nValidation ); | |||
3815 | if( pData && pData->GetDataMode() != ScValidationMode::SC_VALID_ANY ) | |||
3816 | return true; | |||
3817 | } | |||
3818 | return false; | |||
3819 | } | |||
3820 | ||||
3821 | void ScDocument::CheckVectorizationState() | |||
3822 | { | |||
3823 | bool bOldAutoCalc = GetAutoCalc(); | |||
3824 | bAutoCalc = false; // no multiple calculations | |||
3825 | ||||
3826 | for (const auto& a : maTabs) | |||
3827 | { | |||
3828 | if (a) | |||
3829 | a->CheckVectorizationState(); | |||
3830 | } | |||
3831 | ||||
3832 | SetAutoCalc(bOldAutoCalc); | |||
3833 | } | |||
3834 | ||||
3835 | void ScDocument::SetAllFormulasDirty( const sc::SetFormulaDirtyContext& rCxt ) | |||
3836 | { | |||
3837 | bool bOldAutoCalc = GetAutoCalc(); | |||
3838 | bAutoCalc = false; // no multiple calculations | |||
3839 | { // scope for bulk broadcast | |||
3840 | ScBulkBroadcast aBulkBroadcast( GetBASM(), SfxHintId::ScDataChanged); | |||
3841 | for (const auto& a : maTabs) | |||
3842 | { | |||
3843 | if (a) | |||
3844 | a->SetAllFormulasDirty(rCxt); | |||
3845 | } | |||
3846 | } | |||
3847 | ||||
3848 | // Although Charts are also set to dirty in Tracking without AutoCalc | |||
3849 | // if all formulas are dirty, the charts can no longer be caught | |||
3850 | // (#45205#) - that is why all Charts have to be explicitly handled again | |||
3851 | if (pChartListenerCollection) | |||
3852 | pChartListenerCollection->SetDirty(); | |||
3853 | ||||
3854 | SetAutoCalc( bOldAutoCalc ); | |||
3855 | } | |||
3856 | ||||
3857 | void ScDocument::SetDirty( const ScRange& rRange, bool bIncludeEmptyCells ) | |||
3858 | { | |||
3859 | bool bOldAutoCalc = GetAutoCalc(); | |||
3860 | bAutoCalc = false; // no multiple calculations | |||
3861 | { // scope for bulk broadcast | |||
3862 | ScBulkBroadcast aBulkBroadcast( GetBASM(), SfxHintId::ScDataChanged); | |||
3863 | SCTAB nTab2 = rRange.aEnd.Tab(); | |||
3864 | for (SCTAB i=rRange.aStart.Tab(); i<=nTab2 && i < static_cast<SCTAB>(maTabs.size()); i++) | |||
3865 | if (maTabs[i]) maTabs[i]->SetDirty( rRange, | |||
3866 | (bIncludeEmptyCells ? ScColumn::BROADCAST_BROADCASTERS : ScColumn::BROADCAST_DATA_POSITIONS)); | |||
3867 | ||||
3868 | /* TODO: this now also notifies conditional formatting and does a UNO | |||
3869 | * broadcast, which wasn't done here before. Is that an actually | |||
3870 | * desired side effect, or should we come up with a method that | |||
3871 | * doesn't? */ | |||
3872 | if (bIncludeEmptyCells) | |||
3873 | BroadcastCells( rRange, SfxHintId::ScDataChanged, false); | |||
3874 | } | |||
3875 | SetAutoCalc( bOldAutoCalc ); | |||
3876 | } | |||
3877 | ||||
3878 | void ScDocument::SetTableOpDirty( const ScRange& rRange ) | |||
3879 | { | |||
3880 | bool bOldAutoCalc = GetAutoCalc(); | |||
3881 | bAutoCalc = false; // no multiple recalculation | |||
3882 | SCTAB nTab2 = rRange.aEnd.Tab(); | |||
3883 | for (SCTAB i=rRange.aStart.Tab(); i<=nTab2 && i < static_cast<SCTAB>(maTabs.size()); i++) | |||
3884 | if (maTabs[i]) maTabs[i]->SetTableOpDirty( rRange ); | |||
3885 | SetAutoCalc( bOldAutoCalc ); | |||
3886 | } | |||
3887 | ||||
3888 | void ScDocument::InterpretDirtyCells( const ScRangeList& rRanges ) | |||
3889 | { | |||
3890 | if (!GetAutoCalc()) | |||
3891 | return; | |||
3892 | ||||
3893 | PrepareFormulaCalc(); | |||
3894 | ||||
3895 | for (size_t nPos=0, nRangeCount = rRanges.size(); nPos < nRangeCount; nPos++) | |||
3896 | { | |||
3897 | const ScRange& rRange = rRanges[nPos]; | |||
3898 | for (SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); ++nTab) | |||
3899 | { | |||
3900 | ScTable* pTab = FetchTable(nTab); | |||
3901 | if (!pTab) | |||
3902 | return; | |||
3903 | ||||
3904 | pTab->InterpretDirtyCells( | |||
3905 | rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row()); | |||
3906 | } | |||
3907 | } | |||
3908 | ||||
3909 | ScMutationGuard aGuard(*this, ScMutationGuardFlags::CORE); | |||
3910 | mpFormulaGroupCxt.reset(); | |||
3911 | } | |||
3912 | ||||
3913 | void ScDocument::AddTableOpFormulaCell( ScFormulaCell* pCell ) | |||
3914 | { | |||
3915 | if (m_TableOpList.empty()) | |||
3916 | return; | |||
3917 | ||||
3918 | ScInterpreterTableOpParams *const p = m_TableOpList.back(); | |||
3919 | if ( p->bCollectNotifications ) | |||
3920 | { | |||
3921 | if ( p->bRefresh ) | |||
3922 | { // refresh pointers only | |||
3923 | p->aNotifiedFormulaCells.push_back( pCell ); | |||
3924 | } | |||
3925 | else | |||
3926 | { // init both, address and pointer | |||
3927 | p->aNotifiedFormulaCells.push_back( pCell ); | |||
3928 | p->aNotifiedFormulaPos.push_back( pCell->aPos ); | |||
3929 | } | |||
3930 | } | |||
3931 | } | |||
3932 | ||||
3933 | void ScDocument::CalcAll() | |||
3934 | { | |||
3935 | PrepareFormulaCalc(); | |||
3936 | ClearLookupCaches(); // Ensure we don't deliver zombie data. | |||
3937 | sc::AutoCalcSwitch aSwitch(*this, true); | |||
3938 | for (const auto& a : maTabs) | |||
3939 | { | |||
3940 | if (a) | |||
3941 | a->SetDirtyVar(); | |||
3942 | } | |||
3943 | for (const auto& a : maTabs) | |||
3944 | { | |||
3945 | if (a) | |||
3946 | a->CalcAll(); | |||
3947 | } | |||
3948 | ClearFormulaTree(); | |||
3949 | ||||
3950 | // In eternal hard recalc state caches were not added as listeners, | |||
3951 | // invalidate them so the next non-CalcAll() normal lookup will not be | |||
3952 | // presented with outdated data. | |||
3953 | if (GetHardRecalcState() == HardRecalcState::ETERNAL) | |||
3954 | ClearLookupCaches(); | |||
3955 | } | |||
3956 | ||||
3957 | void ScDocument::CompileAll() | |||
3958 | { | |||
3959 | sc::CompileFormulaContext aCxt(*this); | |||
3960 | for (const auto& a : maTabs) | |||
3961 | { | |||
3962 | if (a) | |||
3963 | a->CompileAll(aCxt); | |||
3964 | } | |||
3965 | ||||
3966 | sc::SetFormulaDirtyContext aFormulaDirtyCxt; | |||
3967 | SetAllFormulasDirty(aFormulaDirtyCxt); | |||
3968 | } | |||
3969 | ||||
3970 | void ScDocument::CompileXML() | |||
3971 | { | |||
3972 | bool bOldAutoCalc = GetAutoCalc(); | |||
3973 | SetAutoCalc( false ); | |||
3974 | ScProgress aProgress( GetDocumentShell(), ScResId( | |||
3975 | STR_PROGRESS_CALCULATINGreinterpret_cast<char const *>("STR_PROGRESS_CALCULATING" "\004" u8"calculating") ), GetXMLImportedFormulaCount(), true ); | |||
3976 | ||||
3977 | sc::CompileFormulaContext aCxt(*this); | |||
3978 | ||||
3979 | // set AutoNameCache to speed up automatic name lookup | |||
3980 | OSL_ENSURE( !pAutoNameCache, "AutoNameCache already set" )do { if (true && (!(!pAutoNameCache))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "3980" ": "), "%s", "AutoNameCache already set"); } } while (false); | |||
3981 | pAutoNameCache.reset( new ScAutoNameCache( *this ) ); | |||
3982 | ||||
3983 | if (pRangeName) | |||
3984 | pRangeName->CompileUnresolvedXML(aCxt); | |||
3985 | ||||
3986 | std::for_each(maTabs.begin(), maTabs.end(), | |||
3987 | [&](ScTableUniquePtr & pTab) | |||
3988 | { | |||
3989 | if (pTab) | |||
3990 | pTab->CompileXML(aCxt, aProgress); | |||
3991 | } | |||
3992 | ); | |||
3993 | StartAllListeners(); | |||
3994 | ||||
3995 | pAutoNameCache.reset(); // valid only during CompileXML, where cell contents don't change | |||
3996 | ||||
3997 | if ( pValidationList ) | |||
3998 | { | |||
3999 | ScMutationGuard aGuard(*this, ScMutationGuardFlags::CORE); | |||
4000 | pValidationList->CompileXML(); | |||
4001 | } | |||
4002 | ||||
4003 | // Track all formula cells that were appended to the FormulaTrack during | |||
4004 | // import or CompileXML(). | |||
4005 | TrackFormulas(); | |||
4006 | ||||
4007 | SetAutoCalc( bOldAutoCalc ); | |||
4008 | } | |||
4009 | ||||
4010 | bool ScDocument::CompileErrorCells(FormulaError nErrCode) | |||
4011 | { | |||
4012 | bool bCompiled = false; | |||
4013 | sc::CompileFormulaContext aCxt(*this); | |||
4014 | for (const auto& a : maTabs) | |||
4015 | { | |||
4016 | if (!a) | |||
4017 | continue; | |||
4018 | ||||
4019 | if (a->CompileErrorCells(aCxt, nErrCode)) | |||
4020 | bCompiled = true; | |||
4021 | } | |||
4022 | ||||
4023 | return bCompiled; | |||
4024 | } | |||
4025 | ||||
4026 | void ScDocument::CalcAfterLoad( bool bStartListening ) | |||
4027 | { | |||
4028 | if (bIsClip) // Excel data is loaded from the Clipboard to a Clip-Doc | |||
4029 | return; // the calculation is then only performed when inserting into the real document | |||
4030 | ||||
4031 | bCalcingAfterLoad = true; | |||
4032 | sc::CompileFormulaContext aCxt(*this); | |||
4033 | { | |||
4034 | for (const auto& a : maTabs) | |||
4035 | { | |||
4036 | if (a) | |||
4037 | a->CalcAfterLoad(aCxt, bStartListening); | |||
4038 | } | |||
4039 | for (const auto& a : maTabs) | |||
4040 | { | |||
4041 | if (a) | |||
4042 | a->SetDirtyAfterLoad(); | |||
4043 | } | |||
4044 | } | |||
4045 | bCalcingAfterLoad = false; | |||
4046 | ||||
4047 | SetDetectiveDirty(false); // No real changes yet | |||
4048 | ||||
4049 | // #i112436# If formula cells are already dirty, they don't broadcast further changes. | |||
4050 | // So the source ranges of charts must be interpreted even if they are not visible, | |||
4051 | // similar to ScMyShapeResizer::CreateChartListener for loading own files (i104899). | |||
4052 | if (pChartListenerCollection) | |||
4053 | { | |||
4054 | const ScChartListenerCollection::ListenersType& rListeners = pChartListenerCollection->getListeners(); | |||
4055 | for (auto const& it : rListeners) | |||
4056 | { | |||
4057 | const ScChartListener *const p = it.second.get(); | |||
4058 | InterpretDirtyCells(*p->GetRangeList()); | |||
4059 | } | |||
4060 | } | |||
4061 | } | |||
4062 | ||||
4063 | FormulaError ScDocument::GetErrCode( const ScAddress& rPos ) const | |||
4064 | { | |||
4065 | SCTAB nTab = rPos.Tab(); | |||
4066 | if ( nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4067 | return maTabs[nTab]->GetErrCode( rPos ); | |||
4068 | return FormulaError::NONE; | |||
4069 | } | |||
4070 | ||||
4071 | void ScDocument::ResetChanged( const ScRange& rRange ) | |||
4072 | { | |||
4073 | SCTAB nTabSize = static_cast<SCTAB>(maTabs.size()); | |||
4074 | SCTAB nTab1 = rRange.aStart.Tab(); | |||
4075 | SCTAB nTab2 = rRange.aEnd.Tab(); | |||
4076 | for (SCTAB nTab = nTab1; nTab1 <= nTab2 && nTab < nTabSize; ++nTab) | |||
4077 | if (maTabs[nTab]) | |||
4078 | maTabs[nTab]->ResetChanged(rRange); | |||
4079 | } | |||
4080 | ||||
4081 | // Column widths / Row heights -------------------------------------- | |||
4082 | ||||
4083 | void ScDocument::SetColWidth( SCCOL nCol, SCTAB nTab, sal_uInt16 nNewWidth ) | |||
4084 | { | |||
4085 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4086 | maTabs[nTab]->SetColWidth( nCol, nNewWidth ); | |||
4087 | } | |||
4088 | ||||
4089 | void ScDocument::SetColWidthOnly( SCCOL nCol, SCTAB nTab, sal_uInt16 nNewWidth ) | |||
4090 | { | |||
4091 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4092 | maTabs[nTab]->SetColWidthOnly( nCol, nNewWidth ); | |||
4093 | } | |||
4094 | ||||
4095 | void ScDocument::SetRowHeight( SCROW nRow, SCTAB nTab, sal_uInt16 nNewHeight ) | |||
4096 | { | |||
4097 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4098 | maTabs[nTab]->SetRowHeight( nRow, nNewHeight ); | |||
4099 | } | |||
4100 | ||||
4101 | void ScDocument::SetRowHeightRange( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_uInt16 nNewHeight ) | |||
4102 | { | |||
4103 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4104 | maTabs[nTab]->SetRowHeightRange | |||
4105 | ( nStartRow, nEndRow, nNewHeight, 1.0 ); | |||
4106 | } | |||
4107 | ||||
4108 | void ScDocument::SetRowHeightOnly( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_uInt16 nNewHeight ) | |||
4109 | { | |||
4110 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4111 | maTabs[nTab]->SetRowHeightOnly( nStartRow, nEndRow, nNewHeight ); | |||
4112 | } | |||
4113 | ||||
4114 | void ScDocument::SetManualHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bManual ) | |||
4115 | { | |||
4116 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4117 | maTabs[nTab]->SetManualHeight( nStartRow, nEndRow, bManual ); | |||
4118 | } | |||
4119 | ||||
4120 | sal_uInt16 ScDocument::GetColWidth( SCCOL nCol, SCTAB nTab, bool bHiddenAsZero ) const | |||
4121 | { | |||
4122 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4123 | return maTabs[nTab]->GetColWidth( nCol, bHiddenAsZero ); | |||
4124 | OSL_FAIL("wrong table number")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "4124" ": "), "%s", "wrong table number"); } } while (false ); | |||
4125 | return 0; | |||
4126 | } | |||
4127 | ||||
4128 | sal_uLong ScDocument::GetColWidth( SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab ) const | |||
4129 | { | |||
4130 | const ScTable* pTab = FetchTable(nTab); | |||
4131 | if (!pTab) | |||
4132 | return 0; | |||
4133 | ||||
4134 | return pTab->GetColWidth(nStartCol, nEndCol); | |||
4135 | } | |||
4136 | ||||
4137 | sal_uInt16 ScDocument::GetOriginalWidth( SCCOL nCol, SCTAB nTab ) const | |||
4138 | { | |||
4139 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4140 | return maTabs[nTab]->GetOriginalWidth( nCol ); | |||
4141 | OSL_FAIL("wrong table number")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "4141" ": "), "%s", "wrong table number"); } } while (false ); | |||
4142 | return 0; | |||
4143 | } | |||
4144 | ||||
4145 | sal_uInt16 ScDocument::GetCommonWidth( SCCOL nEndCol, SCTAB nTab ) const | |||
4146 | { | |||
4147 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4148 | return maTabs[nTab]->GetCommonWidth( nEndCol ); | |||
4149 | OSL_FAIL("Wrong table number")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "4149" ": "), "%s", "Wrong table number"); } } while (false ); | |||
4150 | return 0; | |||
4151 | } | |||
4152 | ||||
4153 | sal_uInt16 ScDocument::GetOriginalHeight( SCROW nRow, SCTAB nTab ) const | |||
4154 | { | |||
4155 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4156 | return maTabs[nTab]->GetOriginalHeight( nRow ); | |||
4157 | OSL_FAIL("Wrong table number")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "4157" ": "), "%s", "Wrong table number"); } } while (false ); | |||
4158 | return 0; | |||
4159 | } | |||
4160 | ||||
4161 | sal_uInt16 ScDocument::GetRowHeight( SCROW nRow, SCTAB nTab, bool bHiddenAsZero ) const | |||
4162 | { | |||
4163 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4164 | return maTabs[nTab]->GetRowHeight( nRow, nullptr, nullptr, bHiddenAsZero ); | |||
4165 | OSL_FAIL("Wrong sheet number")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "4165" ": "), "%s", "Wrong sheet number"); } } while (false ); | |||
4166 | return 0; | |||
4167 | } | |||
4168 | ||||
4169 | sal_uInt16 ScDocument::GetRowHeight( SCROW nRow, SCTAB nTab, SCROW* pStartRow, SCROW* pEndRow ) const | |||
4170 | { | |||
4171 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4172 | return maTabs[nTab]->GetRowHeight( nRow, pStartRow, pEndRow ); | |||
4173 | OSL_FAIL("Wrong sheet number")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "4173" ": "), "%s", "Wrong sheet number"); } } while (false ); | |||
4174 | return 0; | |||
4175 | } | |||
4176 | ||||
4177 | sal_uLong ScDocument::GetRowHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bHiddenAsZero ) const | |||
4178 | { | |||
4179 | if (nStartRow == nEndRow) | |||
4180 | return GetRowHeight( nStartRow, nTab, bHiddenAsZero ); // faster for a single row | |||
4181 | ||||
4182 | // check bounds because this method replaces former for(i=start;i<=end;++i) loops | |||
4183 | if (nStartRow > nEndRow) | |||
4184 | return 0; | |||
4185 | ||||
4186 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4187 | return maTabs[nTab]->GetRowHeight( nStartRow, nEndRow, bHiddenAsZero ); | |||
4188 | ||||
4189 | OSL_FAIL("wrong sheet number")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "4189" ": "), "%s", "wrong sheet number"); } } while (false ); | |||
4190 | return 0; | |||
4191 | } | |||
4192 | ||||
4193 | SCROW ScDocument::GetRowForHeight( SCTAB nTab, sal_uLong nHeight ) const | |||
4194 | { | |||
4195 | return maTabs[nTab]->GetRowForHeight(nHeight); | |||
4196 | } | |||
4197 | ||||
4198 | sal_uLong ScDocument::GetScaledRowHeight( SCROW nStartRow, SCROW nEndRow, | |||
4199 | SCTAB nTab, double fScale, const sal_uLong* pnMaxHeight ) const | |||
4200 | { | |||
4201 | // faster for a single row | |||
4202 | if (nStartRow == nEndRow) | |||
4203 | return static_cast<sal_uLong>(GetRowHeight( nStartRow, nTab) * fScale); | |||
4204 | ||||
4205 | // check bounds because this method replaces former for(i=start;i<=end;++i) loops | |||
4206 | if (nStartRow > nEndRow) | |||
4207 | return 0; | |||
4208 | ||||
4209 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4210 | return maTabs[nTab]->GetScaledRowHeight( nStartRow, nEndRow, fScale, pnMaxHeight ); | |||
4211 | ||||
4212 | OSL_FAIL("wrong sheet number")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "4212" ": "), "%s", "wrong sheet number"); } } while (false ); | |||
4213 | return 0; | |||
4214 | } | |||
4215 | ||||
4216 | SCROW ScDocument::GetHiddenRowCount( SCROW nRow, SCTAB nTab ) const | |||
4217 | { | |||
4218 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4219 | return maTabs[nTab]->GetHiddenRowCount( nRow ); | |||
4220 | OSL_FAIL("wrong table number")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "4220" ": "), "%s", "wrong table number"); } } while (false ); | |||
4221 | return 0; | |||
4222 | } | |||
4223 | ||||
4224 | sal_uLong ScDocument::GetColOffset( SCCOL nCol, SCTAB nTab, bool bHiddenAsZero ) const | |||
4225 | { | |||
4226 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4227 | return maTabs[nTab]->GetColOffset( nCol, bHiddenAsZero ); | |||
4228 | OSL_FAIL("wrong table number")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "4228" ": "), "%s", "wrong table number"); } } while (false ); | |||
4229 | return 0; | |||
4230 | } | |||
4231 | ||||
4232 | sal_uLong ScDocument::GetRowOffset( SCROW nRow, SCTAB nTab, bool bHiddenAsZero ) const | |||
4233 | { | |||
4234 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4235 | return maTabs[nTab]->GetRowOffset( nRow, bHiddenAsZero ); | |||
4236 | OSL_FAIL("wrong table number")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "4236" ": "), "%s", "wrong table number"); } } while (false ); | |||
4237 | return 0; | |||
4238 | } | |||
4239 | ||||
4240 | sal_uInt16 ScDocument::GetOptimalColWidth( SCCOL nCol, SCTAB nTab, OutputDevice* pDev, | |||
4241 | double nPPTX, double nPPTY, | |||
4242 | const Fraction& rZoomX, const Fraction& rZoomY, | |||
4243 | bool bFormula, const ScMarkData* pMarkData, | |||
4244 | const ScColWidthParam* pParam ) | |||
4245 | { | |||
4246 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4247 | return maTabs[nTab]->GetOptimalColWidth( nCol, pDev, nPPTX, nPPTY, | |||
4248 | rZoomX, rZoomY, bFormula, pMarkData, pParam ); | |||
4249 | OSL_FAIL("wrong table number")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "4249" ": "), "%s", "wrong table number"); } } while (false ); | |||
4250 | return 0; | |||
4251 | } | |||
4252 | ||||
4253 | long ScDocument::GetNeededSize( SCCOL nCol, SCROW nRow, SCTAB nTab, | |||
4254 | OutputDevice* pDev, | |||
4255 | double nPPTX, double nPPTY, | |||
4256 | const Fraction& rZoomX, const Fraction& rZoomY, | |||
4257 | bool bWidth, bool bTotalSize, bool bInPrintTwips ) | |||
4258 | { | |||
4259 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4260 | return maTabs[nTab]->GetNeededSize | |||
4261 | ( nCol, nRow, pDev, nPPTX, nPPTY, rZoomX, rZoomY, bWidth, bTotalSize, bInPrintTwips ); | |||
4262 | OSL_FAIL("wrong table number")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "4262" ": "), "%s", "wrong table number"); } } while (false ); | |||
4263 | return 0; | |||
4264 | } | |||
4265 | ||||
4266 | bool ScDocument::SetOptimalHeight( sc::RowHeightContext& rCxt, SCROW nStartRow, SCROW nEndRow, SCTAB nTab ) | |||
4267 | { | |||
4268 | ScTable* pTab = FetchTable(nTab); | |||
4269 | if (!pTab) | |||
4270 | return false; | |||
4271 | ||||
4272 | return pTab->SetOptimalHeight(rCxt, nStartRow, nEndRow); | |||
4273 | } | |||
4274 | ||||
4275 | void ScDocument::UpdateAllRowHeights( sc::RowHeightContext& rCxt, const ScMarkData* pTabMark ) | |||
4276 | { | |||
4277 | // one progress across all (selected) sheets | |||
4278 | ||||
4279 | sal_uLong nCellCount = 0; | |||
4280 | for ( SCTAB nTab=0; nTab< static_cast<SCTAB>(maTabs.size()); nTab++ ) | |||
4281 | if ( maTabs[nTab] && ( !pTabMark || pTabMark->GetTableSelect(nTab) ) ) | |||
4282 | nCellCount += maTabs[nTab]->GetWeightedCount(); | |||
4283 | ||||
4284 | ScProgress aProgress( GetDocumentShell(), ScResId(STR_PROGRESS_HEIGHTINGreinterpret_cast<char const *>("STR_PROGRESS_HEIGHTING" "\004" u8"Adapt row height")), nCellCount, true ); | |||
4285 | ||||
4286 | sal_uLong nProgressStart = 0; | |||
4287 | for ( SCTAB nTab=0; nTab< static_cast<SCTAB>(maTabs.size()); nTab++ ) | |||
4288 | if ( maTabs[nTab] && ( !pTabMark || pTabMark->GetTableSelect(nTab) ) ) | |||
4289 | { | |||
4290 | maTabs[nTab]->SetOptimalHeightOnly(rCxt, 0, MaxRow(), &aProgress, nProgressStart); | |||
4291 | maTabs[nTab]->SetDrawPageSize(); | |||
4292 | nProgressStart += maTabs[nTab]->GetWeightedCount(); | |||
4293 | } | |||
4294 | } | |||
4295 | ||||
4296 | // Column/Row - Flags ---------------------------------------------- | |||
4297 | ||||
4298 | void ScDocument::ShowCol(SCCOL nCol, SCTAB nTab, bool bShow) | |||
4299 | { | |||
4300 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4301 | maTabs[nTab]->ShowCol( nCol, bShow ); | |||
4302 | } | |||
4303 | ||||
4304 | void ScDocument::ShowRow(SCROW nRow, SCTAB nTab, bool bShow) | |||
4305 | { | |||
4306 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4307 | maTabs[nTab]->ShowRow( nRow, bShow ); | |||
4308 | } | |||
4309 | ||||
4310 | void ScDocument::ShowRows(SCROW nRow1, SCROW nRow2, SCTAB nTab, bool bShow) | |||
4311 | { | |||
4312 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4313 | maTabs[nTab]->ShowRows( nRow1, nRow2, bShow ); | |||
4314 | } | |||
4315 | ||||
4316 | void ScDocument::SetRowFlags( SCROW nRow, SCTAB nTab, CRFlags nNewFlags ) | |||
4317 | { | |||
4318 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4319 | maTabs[nTab]->SetRowFlags( nRow, nNewFlags ); | |||
4320 | } | |||
4321 | ||||
4322 | void ScDocument::SetRowFlags( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, CRFlags nNewFlags ) | |||
4323 | { | |||
4324 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4325 | maTabs[nTab]->SetRowFlags( nStartRow, nEndRow, nNewFlags ); | |||
4326 | } | |||
4327 | ||||
4328 | CRFlags ScDocument::GetColFlags( SCCOL nCol, SCTAB nTab ) const | |||
4329 | { | |||
4330 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4331 | return maTabs[nTab]->GetColFlags( nCol ); | |||
4332 | OSL_FAIL("wrong table number")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "4332" ": "), "%s", "wrong table number"); } } while (false ); | |||
4333 | return CRFlags::NONE; | |||
4334 | } | |||
4335 | ||||
4336 | CRFlags ScDocument::GetRowFlags( SCROW nRow, SCTAB nTab ) const | |||
4337 | { | |||
4338 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4339 | return maTabs[nTab]->GetRowFlags( nRow ); | |||
4340 | OSL_FAIL("wrong table number")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "4340" ": "), "%s", "wrong table number"); } } while (false ); | |||
4341 | return CRFlags::NONE; | |||
4342 | } | |||
4343 | ||||
4344 | void ScDocument::GetAllRowBreaks(set<SCROW>& rBreaks, SCTAB nTab, bool bPage, bool bManual) const | |||
4345 | { | |||
4346 | if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab]) | |||
4347 | return; | |||
4348 | maTabs[nTab]->GetAllRowBreaks(rBreaks, bPage, bManual); | |||
4349 | } | |||
4350 | ||||
4351 | void ScDocument::GetAllColBreaks(set<SCCOL>& rBreaks, SCTAB nTab, bool bPage, bool bManual) const | |||
4352 | { | |||
4353 | if (!ValidTab(nTab) || !maTabs[nTab]) | |||
4354 | return; | |||
4355 | ||||
4356 | maTabs[nTab]->GetAllColBreaks(rBreaks, bPage, bManual); | |||
4357 | } | |||
4358 | ||||
4359 | ScBreakType ScDocument::HasRowBreak(SCROW nRow, SCTAB nTab) const | |||
4360 | { | |||
4361 | ScBreakType nType = ScBreakType::NONE; | |||
4362 | if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab] || !ValidRow(nRow)) | |||
4363 | return nType; | |||
4364 | ||||
4365 | if (maTabs[nTab]->HasRowPageBreak(nRow)) | |||
4366 | nType |= ScBreakType::Page; | |||
4367 | ||||
4368 | if (maTabs[nTab]->HasRowManualBreak(nRow)) | |||
4369 | nType |= ScBreakType::Manual; | |||
4370 | ||||
4371 | return nType; | |||
4372 | } | |||
4373 | ||||
4374 | ScBreakType ScDocument::HasColBreak(SCCOL nCol, SCTAB nTab) const | |||
4375 | { | |||
4376 | ScBreakType nType = ScBreakType::NONE; | |||
4377 | if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab] || !ValidCol(nCol)) | |||
4378 | return nType; | |||
4379 | ||||
4380 | if (maTabs[nTab]->HasColPageBreak(nCol)) | |||
4381 | nType |= ScBreakType::Page; | |||
4382 | ||||
4383 | if (maTabs[nTab]->HasColManualBreak(nCol)) | |||
4384 | nType |= ScBreakType::Manual; | |||
4385 | ||||
4386 | return nType; | |||
4387 | } | |||
4388 | ||||
4389 | void ScDocument::SetRowBreak(SCROW nRow, SCTAB nTab, bool bPage, bool bManual) | |||
4390 | { | |||
4391 | if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab] || !ValidRow(nRow)) | |||
4392 | return; | |||
4393 | ||||
4394 | maTabs[nTab]->SetRowBreak(nRow, bPage, bManual); | |||
4395 | } | |||
4396 | ||||
4397 | void ScDocument::SetColBreak(SCCOL nCol, SCTAB nTab, bool bPage, bool bManual) | |||
4398 | { | |||
4399 | if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab] || !ValidCol(nCol)) | |||
4400 | return; | |||
4401 | ||||
4402 | maTabs[nTab]->SetColBreak(nCol, bPage, bManual); | |||
4403 | } | |||
4404 | ||||
4405 | void ScDocument::RemoveRowBreak(SCROW nRow, SCTAB nTab, bool bPage, bool bManual) | |||
4406 | { | |||
4407 | if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab] || !ValidRow(nRow)) | |||
4408 | return; | |||
4409 | ||||
4410 | maTabs[nTab]->RemoveRowBreak(nRow, bPage, bManual); | |||
4411 | } | |||
4412 | ||||
4413 | void ScDocument::RemoveColBreak(SCCOL nCol, SCTAB nTab, bool bPage, bool bManual) | |||
4414 | { | |||
4415 | if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab] || !ValidCol(nCol)) | |||
4416 | return; | |||
4417 | ||||
4418 | maTabs[nTab]->RemoveColBreak(nCol, bPage, bManual); | |||
4419 | } | |||
4420 | ||||
4421 | Sequence<TablePageBreakData> ScDocument::GetRowBreakData(SCTAB nTab) const | |||
4422 | { | |||
4423 | if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab]) | |||
4424 | return Sequence<TablePageBreakData>(); | |||
4425 | ||||
4426 | return maTabs[nTab]->GetRowBreakData(); | |||
4427 | } | |||
4428 | ||||
4429 | bool ScDocument::RowHidden(SCROW nRow, SCTAB nTab, SCROW* pFirstRow, SCROW* pLastRow) const | |||
4430 | { | |||
4431 | if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab]) | |||
4432 | return false; | |||
4433 | ||||
4434 | return maTabs[nTab]->RowHidden(nRow, pFirstRow, pLastRow); | |||
4435 | } | |||
4436 | ||||
4437 | bool ScDocument::HasHiddenRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const | |||
4438 | { | |||
4439 | if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab]) | |||
4440 | return false; | |||
4441 | ||||
4442 | return maTabs[nTab]->HasHiddenRows(nStartRow, nEndRow); | |||
4443 | } | |||
4444 | ||||
4445 | bool ScDocument::ColHidden(SCCOL nCol, SCTAB nTab, SCCOL* pFirstCol, SCCOL* pLastCol) const | |||
4446 | { | |||
4447 | if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab]) | |||
4448 | { | |||
4449 | if (pFirstCol) | |||
4450 | *pFirstCol = nCol; | |||
4451 | if (pLastCol) | |||
4452 | *pLastCol = nCol; | |||
4453 | return false; | |||
4454 | } | |||
4455 | ||||
4456 | return maTabs[nTab]->ColHidden(nCol, pFirstCol, pLastCol); | |||
4457 | } | |||
4458 | ||||
4459 | void ScDocument::SetRowHidden(SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bHidden) | |||
4460 | { | |||
4461 | if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab]) | |||
4462 | return; | |||
4463 | ||||
4464 | maTabs[nTab]->SetRowHidden(nStartRow, nEndRow, bHidden); | |||
4465 | } | |||
4466 | ||||
4467 | void ScDocument::SetColHidden(SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab, bool bHidden) | |||
4468 | { | |||
4469 | if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab]) | |||
4470 | return; | |||
4471 | ||||
4472 | maTabs[nTab]->SetColHidden(nStartCol, nEndCol, bHidden); | |||
4473 | } | |||
4474 | ||||
4475 | SCROW ScDocument::FirstVisibleRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const | |||
4476 | { | |||
4477 | if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab]) | |||
4478 | return ::std::numeric_limits<SCROW>::max(); | |||
4479 | ||||
4480 | return maTabs[nTab]->FirstVisibleRow(nStartRow, nEndRow); | |||
4481 | } | |||
4482 | ||||
4483 | SCROW ScDocument::LastVisibleRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const | |||
4484 | { | |||
4485 | if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab]) | |||
4486 | return ::std::numeric_limits<SCROW>::max(); | |||
4487 | ||||
4488 | return maTabs[nTab]->LastVisibleRow(nStartRow, nEndRow); | |||
4489 | } | |||
4490 | ||||
4491 | SCROW ScDocument::CountVisibleRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const | |||
4492 | { | |||
4493 | if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab]) | |||
4494 | return 0; | |||
4495 | ||||
4496 | return maTabs[nTab]->CountVisibleRows(nStartRow, nEndRow); | |||
4497 | } | |||
4498 | ||||
4499 | bool ScDocument::RowFiltered(SCROW nRow, SCTAB nTab, SCROW* pFirstRow, SCROW* pLastRow) const | |||
4500 | { | |||
4501 | if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab]) | |||
4502 | return false; | |||
4503 | ||||
4504 | return maTabs[nTab]->RowFiltered(nRow, pFirstRow, pLastRow); | |||
4505 | } | |||
4506 | ||||
4507 | bool ScDocument::HasFilteredRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const | |||
4508 | { | |||
4509 | if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab]) | |||
4510 | return false; | |||
4511 | ||||
4512 | return maTabs[nTab]->HasFilteredRows(nStartRow, nEndRow); | |||
4513 | } | |||
4514 | ||||
4515 | bool ScDocument::ColFiltered(SCCOL nCol, SCTAB nTab) const | |||
4516 | { | |||
4517 | if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab]) | |||
4518 | return false; | |||
4519 | ||||
4520 | return maTabs[nTab]->ColFiltered(nCol); | |||
4521 | } | |||
4522 | ||||
4523 | void ScDocument::SetRowFiltered(SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bFiltered) | |||
4524 | { | |||
4525 | if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab]) | |||
4526 | return; | |||
4527 | ||||
4528 | maTabs[nTab]->SetRowFiltered(nStartRow, nEndRow, bFiltered); | |||
4529 | } | |||
4530 | ||||
4531 | SCROW ScDocument::FirstNonFilteredRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const | |||
4532 | { | |||
4533 | if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab]) | |||
4534 | return ::std::numeric_limits<SCROW>::max(); | |||
4535 | ||||
4536 | return maTabs[nTab]->FirstNonFilteredRow(nStartRow, nEndRow); | |||
4537 | } | |||
4538 | ||||
4539 | SCROW ScDocument::LastNonFilteredRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const | |||
4540 | { | |||
4541 | if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab]) | |||
4542 | return ::std::numeric_limits<SCROW>::max(); | |||
4543 | ||||
4544 | return maTabs[nTab]->LastNonFilteredRow(nStartRow, nEndRow); | |||
4545 | } | |||
4546 | ||||
4547 | SCROW ScDocument::CountNonFilteredRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const | |||
4548 | { | |||
4549 | if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab]) | |||
4550 | return 0; | |||
4551 | ||||
4552 | return maTabs[nTab]->CountNonFilteredRows(nStartRow, nEndRow); | |||
4553 | } | |||
4554 | ||||
4555 | bool ScDocument::IsManualRowHeight(SCROW nRow, SCTAB nTab) const | |||
4556 | { | |||
4557 | if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab]) | |||
4558 | return false; | |||
4559 | ||||
4560 | return maTabs[nTab]->IsManualRowHeight(nRow); | |||
4561 | } | |||
4562 | ||||
4563 | void ScDocument::SyncColRowFlags() | |||
4564 | { | |||
4565 | for (const auto& a : maTabs) | |||
4566 | { | |||
4567 | if (a) | |||
4568 | a->SyncColRowFlags(); | |||
4569 | } | |||
4570 | } | |||
4571 | ||||
4572 | SCROW ScDocument::GetLastFlaggedRow( SCTAB nTab ) const | |||
4573 | { | |||
4574 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4575 | return maTabs[nTab]->GetLastFlaggedRow(); | |||
4576 | return 0; | |||
4577 | } | |||
4578 | ||||
4579 | SCCOL ScDocument::GetLastChangedCol( SCTAB nTab ) const | |||
4580 | { | |||
4581 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4582 | return maTabs[nTab]->GetLastChangedCol(); | |||
4583 | return 0; | |||
4584 | } | |||
4585 | ||||
4586 | SCROW ScDocument::GetLastChangedRow( SCTAB nTab ) const | |||
4587 | { | |||
4588 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4589 | return maTabs[nTab]->GetLastChangedRow(); | |||
4590 | return 0; | |||
4591 | } | |||
4592 | ||||
4593 | SCCOL ScDocument::GetNextDifferentChangedCol( SCTAB nTab, SCCOL nStart) const | |||
4594 | { | |||
4595 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4596 | { | |||
4597 | CRFlags nStartFlags = maTabs[nTab]->GetColFlags(nStart); | |||
4598 | sal_uInt16 nStartWidth = maTabs[nTab]->GetOriginalWidth(nStart); | |||
4599 | for (SCCOL nCol : maTabs[nTab]->GetColumnsRange( nStart + 1, MaxCol())) | |||
4600 | { | |||
4601 | if (((nStartFlags & CRFlags::ManualBreak) != (maTabs[nTab]->GetColFlags(nCol) & CRFlags::ManualBreak)) || | |||
4602 | (nStartWidth != maTabs[nTab]->GetOriginalWidth(nCol)) || | |||
4603 | ((nStartFlags & CRFlags::Hidden) != (maTabs[nTab]->GetColFlags(nCol) & CRFlags::Hidden)) ) | |||
4604 | return nCol; | |||
4605 | } | |||
4606 | return MaxCol()+1; | |||
4607 | } | |||
4608 | return 0; | |||
4609 | } | |||
4610 | ||||
4611 | SCROW ScDocument::GetNextDifferentChangedRow( SCTAB nTab, SCROW nStart) const | |||
4612 | { | |||
4613 | if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab]) | |||
4614 | return 0; | |||
4615 | ||||
4616 | const ScBitMaskCompressedArray<SCROW, CRFlags>* pRowFlagsArray = maTabs[nTab]->GetRowFlagsArray(); | |||
4617 | if (!pRowFlagsArray) | |||
4618 | return 0; | |||
4619 | ||||
4620 | if (!maTabs[nTab]->mpRowHeights || !maTabs[nTab]->mpHiddenRows) | |||
4621 | return 0; | |||
4622 | ||||
4623 | size_t nIndex; // ignored | |||
4624 | SCROW nFlagsEndRow; | |||
4625 | SCROW nHiddenEndRow; | |||
4626 | SCROW nHeightEndRow; | |||
4627 | CRFlags nFlags; | |||
4628 | bool bHidden; | |||
4629 | sal_uInt16 nHeight; | |||
4630 | CRFlags nStartFlags = nFlags = pRowFlagsArray->GetValue( nStart, nIndex, nFlagsEndRow); | |||
4631 | bool bStartHidden = bHidden = maTabs[nTab]->RowHidden( nStart, nullptr, &nHiddenEndRow); | |||
4632 | sal_uInt16 nStartHeight = nHeight = maTabs[nTab]->GetRowHeight( nStart, nullptr, &nHeightEndRow, false); | |||
4633 | SCROW nRow; | |||
4634 | while ((nRow = std::min( nHiddenEndRow, std::min( nFlagsEndRow, nHeightEndRow)) + 1) <= MaxRow()) | |||
4635 | { | |||
4636 | if (nFlagsEndRow < nRow) | |||
4637 | nFlags = pRowFlagsArray->GetValue( nRow, nIndex, nFlagsEndRow); | |||
4638 | if (nHiddenEndRow < nRow) | |||
4639 | bHidden = maTabs[nTab]->RowHidden( nRow, nullptr, &nHiddenEndRow); | |||
4640 | if (nHeightEndRow < nRow) | |||
4641 | nHeight = maTabs[nTab]->GetRowHeight( nRow, nullptr, &nHeightEndRow, false); | |||
4642 | ||||
4643 | if (((nStartFlags & CRFlags::ManualBreak) != (nFlags & CRFlags::ManualBreak)) || | |||
4644 | ((nStartFlags & CRFlags::ManualSize) != (nFlags & CRFlags::ManualSize)) || | |||
4645 | (bStartHidden != bHidden) || | |||
4646 | (nStartHeight != nHeight)) | |||
4647 | return nRow; | |||
4648 | } | |||
4649 | ||||
4650 | return MaxRow()+1; | |||
4651 | } | |||
4652 | ||||
4653 | void ScDocument::GetColDefault( SCTAB nTab, SCCOL nCol, SCROW nLastRow, SCROW& nDefault) | |||
4654 | { | |||
4655 | nDefault = 0; | |||
4656 | ScDocAttrIterator aDocAttrItr(*this, nTab, nCol, 0, nCol, nLastRow); | |||
4657 | SCCOL nColumn; | |||
4658 | SCROW nStartRow; | |||
4659 | SCROW nEndRow; | |||
4660 | const ScPatternAttr* pAttr = aDocAttrItr.GetNext(nColumn, nStartRow, nEndRow); | |||
4661 | if (nEndRow >= nLastRow) | |||
4662 | return; | |||
4663 | ||||
4664 | ScDefaultAttrSet aSet; | |||
4665 | ScDefaultAttrSet::iterator aItr = aSet.end(); | |||
4666 | while (pAttr) | |||
4667 | { | |||
4668 | ScDefaultAttr aAttr(pAttr); | |||
4669 | aItr = aSet.find(aAttr); | |||
4670 | if (aItr == aSet.end()) | |||
4671 | { | |||
4672 | aAttr.nCount = static_cast<SCSIZE>(nEndRow - nStartRow + 1); | |||
4673 | aAttr.nFirst = nStartRow; | |||
4674 | aSet.insert(aAttr); | |||
4675 | } | |||
4676 | else | |||
4677 | { | |||
4678 | aAttr.nCount = aItr->nCount + static_cast<SCSIZE>(nEndRow - nStartRow + 1); | |||
4679 | aAttr.nFirst = aItr->nFirst; | |||
4680 | aSet.erase(aItr); | |||
4681 | aSet.insert(aAttr); | |||
4682 | } | |||
4683 | pAttr = aDocAttrItr.GetNext(nColumn, nStartRow, nEndRow); | |||
4684 | } | |||
4685 | ScDefaultAttrSet::iterator aDefaultItr = aSet.begin(); | |||
4686 | aItr = aDefaultItr; | |||
4687 | ++aItr; | |||
4688 | while (aItr != aSet.end()) | |||
4689 | { | |||
4690 | // for entries with equal count, use the one with the lowest start row, | |||
4691 | // don't use the random order of pointer comparisons | |||
4692 | if ( aItr->nCount > aDefaultItr->nCount || | |||
4693 | ( aItr->nCount == aDefaultItr->nCount && aItr->nFirst < aDefaultItr->nFirst ) ) | |||
4694 | aDefaultItr = aItr; | |||
4695 | ++aItr; | |||
4696 | } | |||
4697 | nDefault = aDefaultItr->nFirst; | |||
4698 | } | |||
4699 | ||||
4700 | void ScDocument::StripHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2, SCTAB nTab ) | |||
4701 | { | |||
4702 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4703 | maTabs[nTab]->StripHidden( rX1, rY1, rX2, rY2 ); | |||
4704 | } | |||
4705 | ||||
4706 | void ScDocument::ExtendHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2, SCTAB nTab ) | |||
4707 | { | |||
4708 | if ( ValidTab(nTab) && maTabs[nTab] ) | |||
4709 | maTabs[nTab]->ExtendHidden( rX1, rY1, rX2, rY2 ); | |||
4710 | } | |||
4711 | ||||
4712 | // Attribute ---------------------------------------------------------- | |||
4713 | ||||
4714 | const SfxPoolItem* ScDocument::GetAttr( SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt16 nWhich ) const | |||
4715 | { | |||
4716 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && | |||
4717 | nCol < maTabs[nTab]->GetAllocatedColumnsCount()) | |||
4718 | { | |||
4719 | const SfxPoolItem* pTemp = maTabs[nTab]->GetAttr( nCol, nRow, nWhich ); | |||
4720 | if (pTemp) | |||
4721 | return pTemp; | |||
4722 | else | |||
4723 | { | |||
4724 | OSL_FAIL( "Attribute Null" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "4724" ": "), "%s", "Attribute Null"); } } while (false); | |||
4725 | } | |||
4726 | } | |||
4727 | return &mxPoolHelper->GetDocPool()->GetDefaultItem( nWhich ); | |||
4728 | } | |||
4729 | ||||
4730 | const SfxPoolItem* ScDocument::GetAttr( const ScAddress& rPos, sal_uInt16 nWhich ) const | |||
4731 | { | |||
4732 | return GetAttr(rPos.Col(), rPos.Row(), rPos.Tab(), nWhich); | |||
4733 | } | |||
4734 | ||||
4735 | const ScPatternAttr* ScDocument::GetPattern( SCCOL nCol, SCROW nRow, SCTAB nTab ) const | |||
4736 | { | |||
4737 | if (TableExists(nTab)) | |||
4738 | return maTabs[nTab]->GetPattern( nCol, nRow ); | |||
4739 | return nullptr; | |||
4740 | } | |||
4741 | ||||
4742 | const ScPatternAttr* ScDocument::GetPattern( const ScAddress& rPos ) const | |||
4743 | { | |||
4744 | if (TableExists(rPos.Tab())) | |||
4745 | return maTabs[rPos.Tab()]->GetPattern(rPos.Col(), rPos.Row()); | |||
4746 | ||||
4747 | return nullptr; | |||
4748 | } | |||
4749 | ||||
4750 | const ScPatternAttr* ScDocument::GetMostUsedPattern( SCCOL nCol, SCROW nStartRow, SCROW nEndRow, SCTAB nTab ) const | |||
4751 | { | |||
4752 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4753 | return maTabs[nTab]->GetMostUsedPattern( nCol, nStartRow, nEndRow ); | |||
4754 | return nullptr; | |||
4755 | } | |||
4756 | ||||
4757 | void ScDocument::ApplyAttr( SCCOL nCol, SCROW nRow, SCTAB nTab, const SfxPoolItem& rAttr ) | |||
4758 | { | |||
4759 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4760 | maTabs[nTab]->ApplyAttr( nCol, nRow, rAttr ); | |||
4761 | } | |||
4762 | ||||
4763 | void ScDocument::ApplyPattern( SCCOL nCol, SCROW nRow, SCTAB nTab, const ScPatternAttr& rAttr ) | |||
4764 | { | |||
4765 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4766 | maTabs[nTab]->ApplyPattern( nCol, nRow, rAttr ); | |||
4767 | } | |||
4768 | ||||
4769 | void ScDocument::ApplyPatternArea( SCCOL nStartCol, SCROW nStartRow, | |||
4770 | SCCOL nEndCol, SCROW nEndRow, | |||
4771 | const ScMarkData& rMark, | |||
4772 | const ScPatternAttr& rAttr, | |||
4773 | ScEditDataArray* pDataArray, | |||
4774 | bool* const pIsChanged ) | |||
4775 | { | |||
4776 | SCTAB nMax = static_cast<SCTAB>(maTabs.size()); | |||
4777 | for (const auto& rTab : rMark) | |||
4778 | { | |||
4779 | if (rTab >= nMax) | |||
4780 | break; | |||
4781 | if (maTabs[rTab]) | |||
4782 | maTabs[rTab]->ApplyPatternArea( nStartCol, nStartRow, nEndCol, nEndRow, rAttr, pDataArray, pIsChanged ); | |||
4783 | } | |||
4784 | } | |||
4785 | ||||
4786 | void ScDocument::ApplyPatternAreaTab( SCCOL nStartCol, SCROW nStartRow, | |||
4787 | SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, const ScPatternAttr& rAttr ) | |||
4788 | { | |||
4789 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size())) | |||
4790 | if (maTabs[nTab]) | |||
4791 | maTabs[nTab]->ApplyPatternArea( nStartCol, nStartRow, nEndCol, nEndRow, rAttr ); | |||
4792 | } | |||
4793 | ||||
4794 | void ScDocument::ApplyPatternIfNumberformatIncompatible( const ScRange& rRange, | |||
4795 | const ScMarkData& rMark, const ScPatternAttr& rPattern, SvNumFormatType nNewType ) | |||
4796 | { | |||
4797 | SCTAB nMax = static_cast<SCTAB>(maTabs.size()); | |||
4798 | for (const auto& rTab : rMark) | |||
4799 | { | |||
4800 | if (rTab >= nMax) | |||
4801 | break; | |||
4802 | if (maTabs[rTab]) | |||
4803 | maTabs[rTab]->ApplyPatternIfNumberformatIncompatible( rRange, rPattern, nNewType ); | |||
4804 | } | |||
4805 | } | |||
4806 | ||||
4807 | void ScDocument::AddCondFormatData( const ScRangeList& rRange, SCTAB nTab, sal_uInt32 nIndex ) | |||
4808 | { | |||
4809 | if(o3tl::make_unsigned(nTab) >= maTabs.size()) | |||
4810 | return; | |||
4811 | ||||
4812 | if(!maTabs[nTab]) | |||
4813 | return; | |||
4814 | ||||
4815 | maTabs[nTab]->AddCondFormatData(rRange, nIndex); | |||
4816 | } | |||
4817 | ||||
4818 | void ScDocument::RemoveCondFormatData( const ScRangeList& rRange, SCTAB nTab, sal_uInt32 nIndex ) | |||
4819 | { | |||
4820 | if(o3tl::make_unsigned(nTab) >= maTabs.size()) | |||
4821 | return; | |||
4822 | ||||
4823 | if(!maTabs[nTab]) | |||
4824 | return; | |||
4825 | ||||
4826 | maTabs[nTab]->RemoveCondFormatData(rRange, nIndex); | |||
4827 | } | |||
4828 | ||||
4829 | void ScDocument::ApplyStyle( SCCOL nCol, SCROW nRow, SCTAB nTab, const ScStyleSheet& rStyle) | |||
4830 | { | |||
4831 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size())) | |||
4832 | if (maTabs[nTab]) | |||
4833 | maTabs[nTab]->ApplyStyle( nCol, nRow, &rStyle ); | |||
4834 | } | |||
4835 | ||||
4836 | void ScDocument::ApplyStyleArea( SCCOL nStartCol, SCROW nStartRow, | |||
4837 | SCCOL nEndCol, SCROW nEndRow, | |||
4838 | const ScMarkData& rMark, | |||
4839 | const ScStyleSheet& rStyle) | |||
4840 | { | |||
4841 | SCTAB nMax = static_cast<SCTAB>(maTabs.size()); | |||
4842 | for (const auto& rTab : rMark) | |||
4843 | { | |||
4844 | if (rTab >= nMax) | |||
4845 | break; | |||
4846 | if (maTabs[rTab]) | |||
4847 | maTabs[rTab]->ApplyStyleArea( nStartCol, nStartRow, nEndCol, nEndRow, rStyle ); | |||
4848 | } | |||
4849 | } | |||
4850 | ||||
4851 | void ScDocument::ApplyStyleAreaTab( SCCOL nStartCol, SCROW nStartRow, | |||
4852 | SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, const ScStyleSheet& rStyle) | |||
4853 | { | |||
4854 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size())) | |||
4855 | if (maTabs[nTab]) | |||
4856 | maTabs[nTab]->ApplyStyleArea( nStartCol, nStartRow, nEndCol, nEndRow, rStyle ); | |||
4857 | } | |||
4858 | ||||
4859 | void ScDocument::ApplySelectionStyle(const ScStyleSheet& rStyle, const ScMarkData& rMark) | |||
4860 | { | |||
4861 | // ApplySelectionStyle needs multi mark | |||
4862 | if ( rMark.IsMarked() && !rMark.IsMultiMarked() ) | |||
4863 | { | |||
4864 | ScRange aRange; | |||
4865 | rMark.GetMarkArea( aRange ); | |||
4866 | ApplyStyleArea( aRange.aStart.Col(), aRange.aStart.Row(), | |||
4867 | aRange.aEnd.Col(), aRange.aEnd.Row(), rMark, rStyle ); | |||
4868 | } | |||
4869 | else | |||
4870 | { | |||
4871 | SCTAB nMax = static_cast<SCTAB>(maTabs.size()); | |||
4872 | for (const auto& rTab : rMark) | |||
4873 | { | |||
4874 | if (rTab >= nMax) | |||
4875 | break; | |||
4876 | if ( maTabs[rTab] ) | |||
4877 | maTabs[rTab]->ApplySelectionStyle( rStyle, rMark ); | |||
4878 | } | |||
4879 | } | |||
4880 | } | |||
4881 | ||||
4882 | void ScDocument::ApplySelectionLineStyle( const ScMarkData& rMark, | |||
4883 | const SvxBorderLine* pLine, bool bColorOnly ) | |||
4884 | { | |||
4885 | if ( bColorOnly && !pLine ) | |||
4886 | return; | |||
4887 | ||||
4888 | SCTAB nMax = static_cast<SCTAB>(maTabs.size()); | |||
4889 | for (const auto& rTab : rMark) | |||
4890 | { | |||
4891 | if (rTab >= nMax) | |||
4892 | break; | |||
4893 | if (maTabs[rTab]) | |||
4894 | maTabs[rTab]->ApplySelectionLineStyle( rMark, pLine, bColorOnly ); | |||
4895 | } | |||
4896 | } | |||
4897 | ||||
4898 | const ScStyleSheet* ScDocument::GetStyle( SCCOL nCol, SCROW nRow, SCTAB nTab ) const | |||
4899 | { | |||
4900 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
4901 | return maTabs[nTab]->GetStyle(nCol, nRow); | |||
4902 | else | |||
4903 | return nullptr; | |||
4904 | } | |||
4905 | ||||
4906 | const ScStyleSheet* ScDocument::GetSelectionStyle( const ScMarkData& rMark ) const | |||
4907 | { | |||
4908 | bool bEqual = true; | |||
4909 | bool bFound; | |||
4910 | ||||
4911 | const ScStyleSheet* pStyle = nullptr; | |||
4912 | const ScStyleSheet* pNewStyle; | |||
4913 | ||||
4914 | if ( rMark.IsMultiMarked() ) | |||
4915 | { | |||
4916 | SCTAB nMax = static_cast<SCTAB>(maTabs.size()); | |||
4917 | for (const auto& rTab : rMark) | |||
4918 | { | |||
4919 | if (rTab >= nMax) | |||
4920 | break; | |||
4921 | ||||
4922 | if (maTabs[rTab]) | |||
4923 | { | |||
4924 | pNewStyle = maTabs[rTab]->GetSelectionStyle( rMark, bFound ); | |||
4925 | if (bFound) | |||
4926 | { | |||
4927 | if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) ) | |||
4928 | bEqual = false; // different | |||
4929 | pStyle = pNewStyle; | |||
4930 | } | |||
4931 | } | |||
4932 | } | |||
4933 | } | |||
4934 | if ( rMark.IsMarked() ) | |||
4935 | { | |||
4936 | ScRange aRange; | |||
4937 | rMark.GetMarkArea( aRange ); | |||
4938 | for (SCTAB i=aRange.aStart.Tab(); i<=aRange.aEnd.Tab() && bEqual && i < static_cast<SCTAB>(maTabs.size()); i++) | |||
4939 | if (maTabs[i] && rMark.GetTableSelect(i)) | |||
4940 | { | |||
4941 | pNewStyle = maTabs[i]->GetAreaStyle( bFound, | |||
4942 | aRange.aStart.Col(), aRange.aStart.Row(), | |||
4943 | aRange.aEnd.Col(), aRange.aEnd.Row() ); | |||
4944 | if (bFound) | |||
4945 | { | |||
4946 | if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) ) | |||
4947 | bEqual = false; // different | |||
4948 | pStyle = pNewStyle; | |||
4949 | } | |||
4950 | } | |||
4951 | } | |||
4952 | ||||
4953 | return bEqual ? pStyle : nullptr; | |||
4954 | } | |||
4955 | ||||
4956 | void ScDocument::StyleSheetChanged( const SfxStyleSheetBase* pStyleSheet, bool bRemoved, | |||
4957 | OutputDevice* pDev, | |||
4958 | double nPPTX, double nPPTY, | |||
4959 | const Fraction& rZoomX, const Fraction& rZoomY ) | |||
4960 | { | |||
4961 | for (const auto& a : maTabs) | |||
4962 | { | |||
4963 | if (a) | |||
4964 | a->StyleSheetChanged | |||
4965 | ( pStyleSheet, bRemoved, pDev, nPPTX, nPPTY, rZoomX, rZoomY ); | |||
4966 | } | |||
4967 | ||||
4968 | if ( pStyleSheet && pStyleSheet->GetName() == ScResId(STR_STYLENAME_STANDARD_CELLreinterpret_cast<char const *>("STR_STYLENAME_STANDARD" "\004" u8"Default Cell Style")) ) | |||
4969 | { | |||
4970 | // update attributes for all note objects | |||
4971 | ScDetectiveFunc::UpdateAllComments( *this ); | |||
4972 | } | |||
4973 | else if ( pStyleSheet && pStyleSheet->GetName() == ScResId(STR_STYLENAME_STANDARD_PAGEreinterpret_cast<char const *>("STR_STYLENAME_STANDARD" "\004" u8"Default Page Style")) ) | |||
4974 | { | |||
4975 | // update attributes for all note objects | |||
4976 | ScDetectiveFunc::UpdateAllComments( *this ); | |||
4977 | } | |||
4978 | } | |||
4979 | ||||
4980 | bool ScDocument::IsStyleSheetUsed( const ScStyleSheet& rStyle ) const | |||
4981 | { | |||
4982 | if ( bStyleSheetUsageInvalid || rStyle.GetUsage() == ScStyleSheet::Usage::UNKNOWN ) | |||
4983 | { | |||
4984 | SfxStyleSheetIterator aIter( mxPoolHelper->GetStylePool(), | |||
4985 | SfxStyleFamily::Para ); | |||
4986 | for ( const SfxStyleSheetBase* pStyle = aIter.First(); pStyle; | |||
4987 | pStyle = aIter.Next() ) | |||
4988 | { | |||
4989 | if (pStyle->isScStyleSheet()) | |||
4990 | { | |||
4991 | const ScStyleSheet* pScStyle = static_cast<const ScStyleSheet*>( pStyle ); | |||
4992 | pScStyle->SetUsage( ScStyleSheet::Usage::NOTUSED ); | |||
4993 | } | |||
4994 | } | |||
4995 | ||||
4996 | bool bIsUsed = false; | |||
4997 | ||||
4998 | for (const auto& a : maTabs) | |||
4999 | { | |||
5000 | if (a && a->IsStyleSheetUsed( rStyle ) ) | |||
5001 | bIsUsed = true; | |||
5002 | } | |||
5003 | ||||
5004 | bStyleSheetUsageInvalid = false; | |||
5005 | ||||
5006 | return bIsUsed; | |||
5007 | } | |||
5008 | ||||
5009 | return rStyle.GetUsage() == ScStyleSheet::Usage::USED; | |||
5010 | } | |||
5011 | ||||
5012 | bool ScDocument::ApplyFlagsTab( SCCOL nStartCol, SCROW nStartRow, | |||
5013 | SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, ScMF nFlags ) | |||
5014 | { | |||
5015 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size())) | |||
5016 | if (maTabs[nTab]) | |||
5017 | return maTabs[nTab]->ApplyFlags( nStartCol, nStartRow, nEndCol, nEndRow, nFlags ); | |||
5018 | ||||
5019 | OSL_FAIL("ApplyFlags: wrong table")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "5019" ": "), "%s", "ApplyFlags: wrong table"); } } while (false); | |||
5020 | return false; | |||
5021 | } | |||
5022 | ||||
5023 | bool ScDocument::RemoveFlagsTab( SCCOL nStartCol, SCROW nStartRow, | |||
5024 | SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, ScMF nFlags ) | |||
5025 | { | |||
5026 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size())) | |||
5027 | if (maTabs[nTab]) | |||
5028 | return maTabs[nTab]->RemoveFlags( nStartCol, nStartRow, nEndCol, nEndRow, nFlags ); | |||
5029 | ||||
5030 | OSL_FAIL("RemoveFlags: wrong table")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "5030" ": "), "%s", "RemoveFlags: wrong table"); } } while (false); | |||
5031 | return false; | |||
5032 | } | |||
5033 | ||||
5034 | const ScPatternAttr* ScDocument::SetPattern( SCCOL nCol, SCROW nRow, SCTAB nTab, std::unique_ptr<ScPatternAttr> pAttr ) | |||
5035 | { | |||
5036 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size())) | |||
5037 | if (maTabs[nTab]) | |||
5038 | return maTabs[nTab]->SetPattern( nCol, nRow, std::move(pAttr) ); | |||
5039 | return nullptr; | |||
5040 | } | |||
5041 | ||||
5042 | void ScDocument::SetPattern( SCCOL nCol, SCROW nRow, SCTAB nTab, const ScPatternAttr& rAttr ) | |||
5043 | { | |||
5044 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size())) | |||
5045 | if (maTabs[nTab]) | |||
5046 | maTabs[nTab]->SetPattern( nCol, nRow, rAttr ); | |||
5047 | } | |||
5048 | ||||
5049 | void ScDocument::SetPattern( const ScAddress& rPos, const ScPatternAttr& rAttr ) | |||
5050 | { | |||
5051 | SCTAB nTab = rPos.Tab(); | |||
5052 | if ( nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab]) | |||
5053 | maTabs[nTab]->SetPattern( rPos, rAttr ); | |||
5054 | } | |||
5055 | ||||
5056 | std::unique_ptr<ScPatternAttr> ScDocument::CreateSelectionPattern( const ScMarkData& rMark, bool bDeep ) | |||
5057 | { | |||
5058 | ScMergePatternState aState; | |||
5059 | ||||
5060 | if ( rMark.IsMultiMarked() ) // multi selection | |||
5061 | { | |||
5062 | SCTAB nMax = static_cast<SCTAB>(maTabs.size()); | |||
5063 | for (const auto& rTab : rMark) | |||
5064 | { | |||
5065 | if (rTab >= nMax) | |||
5066 | break; | |||
5067 | if (maTabs[rTab]) | |||
5068 | maTabs[rTab]->MergeSelectionPattern( aState, rMark, bDeep ); | |||
5069 | } | |||
5070 | } | |||
5071 | if ( rMark.IsMarked() ) // single selection | |||
5072 | { | |||
5073 | ScRange aRange; | |||
5074 | rMark.GetMarkArea(aRange); | |||
5075 | SCTAB nMax = static_cast<SCTAB>(maTabs.size()); | |||
5076 | for (const auto& rTab : rMark) | |||
5077 | { | |||
5078 | if (rTab >= nMax) | |||
5079 | break; | |||
5080 | if (maTabs[rTab]) | |||
5081 | maTabs[rTab]->MergePatternArea( aState, | |||
5082 | aRange.aStart.Col(), aRange.aStart.Row(), | |||
5083 | aRange.aEnd.Col(), aRange.aEnd.Row(), bDeep ); | |||
5084 | } | |||
5085 | } | |||
5086 | ||||
5087 | OSL_ENSURE( aState.pItemSet, "SelectionPattern Null" )do { if (true && (!(aState.pItemSet))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "5087" ": "), "%s", "SelectionPattern Null"); } } while ( false); | |||
5088 | if (aState.pItemSet) | |||
5089 | { | |||
5090 | std::unique_ptr<ScPatternAttr> pPattern(new ScPatternAttr( std::move(aState.pItemSet) )); | |||
5091 | if (aState.mbValidPatternId) | |||
5092 | pPattern->SetKey(aState.mnPatternId); | |||
5093 | ||||
5094 | return pPattern; | |||
5095 | } | |||
5096 | else | |||
5097 | return std::unique_ptr<ScPatternAttr>(new ScPatternAttr( GetPool() )); // empty | |||
5098 | } | |||
5099 | ||||
5100 | const ScPatternAttr* ScDocument::GetSelectionPattern( const ScMarkData& rMark ) | |||
5101 | { | |||
5102 | pSelectionAttr = CreateSelectionPattern( rMark ); | |||
5103 | return pSelectionAttr.get(); | |||
5104 | } | |||
5105 | ||||
5106 | void ScDocument::GetSelectionFrame( const ScMarkData& rMark, | |||
5107 | SvxBoxItem& rLineOuter, | |||
5108 | SvxBoxInfoItem& rLineInner ) | |||
5109 | { | |||
5110 | rLineOuter.SetLine(nullptr, SvxBoxItemLine::TOP); | |||
5111 | rLineOuter.SetLine(nullptr, SvxBoxItemLine::BOTTOM); | |||
5112 | rLineOuter.SetLine(nullptr, SvxBoxItemLine::LEFT); | |||
5113 | rLineOuter.SetLine(nullptr, SvxBoxItemLine::RIGHT); | |||
5114 | rLineOuter.SetAllDistances(0); | |||
5115 | ||||
5116 | rLineInner.SetLine(nullptr, SvxBoxInfoItemLine::HORI); | |||
5117 | rLineInner.SetLine(nullptr, SvxBoxInfoItemLine::VERT); | |||
5118 | rLineInner.SetTable(true); | |||
5119 | rLineInner.SetDist(true); | |||
5120 | rLineInner.SetMinDist(false); | |||
5121 | ||||
5122 | ScLineFlags aFlags; | |||
5123 | ||||
5124 | if( rMark.IsMultiMarked() ) | |||
5125 | { | |||
5126 | ScRangeList aRangeList; | |||
5127 | rMark.FillRangeListWithMarks( &aRangeList, false ); | |||
5128 | size_t nRangeCount = aRangeList.size(); | |||
5129 | bool bMultipleRows = false, bMultipleCols = false; | |||
5130 | for( size_t nRangeIdx = 0; nRangeIdx < nRangeCount; ++nRangeIdx ) | |||
5131 | { | |||
5132 | const ScRange & rRange = aRangeList[ nRangeIdx ]; | |||
5133 | bMultipleRows = ( bMultipleRows || ( rRange.aStart.Row() != rRange.aEnd.Row() ) ); | |||
5134 | bMultipleCols = ( bMultipleCols || ( rRange.aStart.Col() != rRange.aEnd.Col() ) ); | |||
5135 | SCTAB nMax = static_cast<SCTAB>(maTabs.size()); | |||
5136 | for (const auto& rTab : rMark) | |||
5137 | { | |||
5138 | if (rTab >= nMax) | |||
5139 | break; | |||
5140 | ||||
5141 | if (maTabs[rTab]) | |||
5142 | maTabs[rTab]->MergeBlockFrame( &rLineOuter, &rLineInner, aFlags, | |||
5143 | rRange.aStart.Col(), rRange.aStart.Row(), | |||
5144 | rRange.aEnd.Col(), rRange.aEnd.Row() ); | |||
5145 | } | |||
5146 | } | |||
5147 | rLineInner.EnableHor( bMultipleRows ); | |||
5148 | rLineInner.EnableVer( bMultipleCols ); | |||
5149 | } | |||
5150 | else if( rMark.IsMarked() ) | |||
5151 | { | |||
5152 | ScRange aRange; | |||
5153 | rMark.GetMarkArea(aRange); | |||
5154 | rLineInner.EnableHor( aRange.aStart.Row() != aRange.aEnd.Row() ); | |||
5155 | rLineInner.EnableVer( aRange.aStart.Col() != aRange.aEnd.Col() ); | |||
5156 | SCTAB nMax = static_cast<SCTAB>(maTabs.size()); | |||
5157 | for (const auto& rTab : rMark) | |||
5158 | { | |||
5159 | if (rTab >= nMax) | |||
5160 | break; | |||
5161 | ||||
5162 | if (maTabs[rTab]) | |||
5163 | maTabs[rTab]->MergeBlockFrame( &rLineOuter, &rLineInner, aFlags, | |||
5164 | aRange.aStart.Col(), aRange.aStart.Row(), | |||
5165 | aRange.aEnd.Col(), aRange.aEnd.Row() ); | |||
5166 | } | |||
5167 | } | |||
5168 | ||||
5169 | // Evaluate don't care Status | |||
5170 | ||||
5171 | rLineInner.SetValid( SvxBoxInfoItemValidFlags::LEFT, ( aFlags.nLeft != SC_LINE_DONTCARE2 ) ); | |||
5172 | rLineInner.SetValid( SvxBoxInfoItemValidFlags::RIGHT, ( aFlags.nRight != SC_LINE_DONTCARE2 ) ); | |||
5173 | rLineInner.SetValid( SvxBoxInfoItemValidFlags::TOP, ( aFlags.nTop != SC_LINE_DONTCARE2 ) ); | |||
5174 | rLineInner.SetValid( SvxBoxInfoItemValidFlags::BOTTOM, ( aFlags.nBottom != SC_LINE_DONTCARE2 ) ); | |||
5175 | rLineInner.SetValid( SvxBoxInfoItemValidFlags::HORI, ( aFlags.nHori != SC_LINE_DONTCARE2 ) ); | |||
5176 | rLineInner.SetValid( SvxBoxInfoItemValidFlags::VERT, ( aFlags.nVert != SC_LINE_DONTCARE2 ) ); | |||
5177 | } | |||
5178 | ||||
5179 | bool ScDocument::HasAttrib( SCCOL nCol1, SCROW nRow1, SCTAB nTab1, | |||
5180 | SCCOL nCol2, SCROW nRow2, SCTAB nTab2, HasAttrFlags nMask ) const | |||
5181 | { | |||
5182 | if ( nMask & HasAttrFlags::Rotate ) | |||
5183 | { | |||
5184 | // Is attribute used in document? | |||
5185 | // (as in fillinfo) | |||
5186 | ||||
5187 | ScDocumentPool* pPool = mxPoolHelper->GetDocPool(); | |||
5188 | ||||
5189 | bool bAnyItem = false; | |||
5190 | for (const SfxPoolItem* pItem : pPool->GetItemSurrogates(ATTR_ROTATE_VALUE)) | |||
5191 | { | |||
5192 | // 90 or 270 degrees is former SvxOrientationItem - only look for other values | |||
5193 | // (see ScPatternAttr::GetCellOrientation) | |||
5194 | sal_Int32 nAngle = static_cast<const ScRotateValueItem*>(pItem)->GetValue(); | |||
5195 | if ( nAngle != 0 && nAngle != 9000 && nAngle != 27000 ) | |||
5196 | { | |||
5197 | bAnyItem = true; | |||
5198 | break; | |||
5199 | } | |||
5200 | } | |||
5201 | if (!bAnyItem) | |||
5202 | nMask &= ~HasAttrFlags::Rotate; | |||
5203 | } | |||
5204 | ||||
5205 | if (nMask == HasAttrFlags::NONE) | |||
5206 | return false; | |||
5207 | ||||
5208 | bool bFound = false; | |||
5209 | for (SCTAB i=nTab1; i<=nTab2 && !bFound && i < static_cast<SCTAB>(maTabs.size()); i++) | |||
5210 | if (maTabs[i]) | |||
5211 | { | |||
5212 | if ( nMask & HasAttrFlags::RightOrCenter ) | |||
5213 | { | |||
5214 | // On a RTL sheet, don't start to look for the default left value | |||
5215 | // (which is then logically right), instead always assume true. | |||
5216 | // That way, ScAttrArray::HasAttrib doesn't have to handle RTL sheets. | |||
5217 | ||||
5218 | if ( IsLayoutRTL(i) ) | |||
5219 | bFound = true; | |||
5220 | } | |||
5221 | ||||
5222 | if ( !bFound ) | |||
5223 | bFound = maTabs[i]->HasAttrib( nCol1, nRow1, nCol2, nRow2, nMask ); | |||
5224 | } | |||
5225 | ||||
5226 | return bFound; | |||
5227 | } | |||
5228 | ||||
5229 | bool ScDocument::HasAttrib( const ScRange& rRange, HasAttrFlags nMask ) const | |||
5230 | { | |||
5231 | return HasAttrib( rRange.aStart.Col(), rRange.aStart.Row(), rRange.aStart.Tab(), | |||
5232 | rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aEnd.Tab(), | |||
5233 | nMask ); | |||
5234 | } | |||
5235 | ||||
5236 | void ScDocument::FindMaxRotCol( SCTAB nTab, RowInfo* pRowInfo, SCSIZE nArrCount, | |||
5237 | SCCOL nX1, SCCOL nX2 ) const | |||
5238 | { | |||
5239 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
5240 | maTabs[nTab]->FindMaxRotCol( pRowInfo, nArrCount, nX1, nX2 ); | |||
5241 | else | |||
5242 | { | |||
5243 | OSL_FAIL("FindMaxRotCol: wrong table")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "5243" ": "), "%s", "FindMaxRotCol: wrong table"); } } while (false); | |||
5244 | } | |||
5245 | } | |||
5246 | ||||
5247 | void ScDocument::GetBorderLines( SCCOL nCol, SCROW nRow, SCTAB nTab, | |||
5248 | const SvxBorderLine** ppLeft, const SvxBorderLine** ppTop, | |||
5249 | const SvxBorderLine** ppRight, const SvxBorderLine** ppBottom ) const | |||
5250 | { | |||
5251 | //TODO: consider page limits for printing !!!!! | |||
5252 | ||||
5253 | const SvxBoxItem* pThisAttr = GetEffItem( nCol, nRow, nTab, ATTR_BORDER ); | |||
5254 | OSL_ENSURE(pThisAttr,"where is the attribute?")do { if (true && (!(pThisAttr))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "5254" ": "), "%s", "where is the attribute?"); } } while (false); | |||
5255 | ||||
5256 | const SvxBorderLine* pLeftLine = pThisAttr->GetLeft(); | |||
5257 | const SvxBorderLine* pTopLine = pThisAttr->GetTop(); | |||
5258 | const SvxBorderLine* pRightLine = pThisAttr->GetRight(); | |||
5259 | const SvxBorderLine* pBottomLine = pThisAttr->GetBottom(); | |||
5260 | ||||
5261 | if ( nCol > 0 ) | |||
5262 | { | |||
5263 | const SvxBorderLine* pOther = GetEffItem( nCol-1, nRow, nTab, ATTR_BORDER )->GetRight(); | |||
5264 | if ( ScHasPriority( pOther, pLeftLine ) ) | |||
5265 | pLeftLine = pOther; | |||
5266 | } | |||
5267 | if ( nRow > 0 ) | |||
5268 | { | |||
5269 | const SvxBorderLine* pOther = GetEffItem( nCol, nRow-1, nTab, ATTR_BORDER )->GetBottom(); | |||
5270 | if ( ScHasPriority( pOther, pTopLine ) ) | |||
5271 | pTopLine = pOther; | |||
5272 | } | |||
5273 | if ( nCol < MaxCol() ) | |||
5274 | { | |||
5275 | const SvxBorderLine* pOther = GetEffItem( nCol+1, nRow, nTab, ATTR_BORDER )->GetLeft(); | |||
5276 | if ( ScHasPriority( pOther, pRightLine ) ) | |||
5277 | pRightLine = pOther; | |||
5278 | } | |||
5279 | if ( nRow < MaxRow() ) | |||
5280 | { | |||
5281 | const SvxBorderLine* pOther = GetEffItem( nCol, nRow+1, nTab, ATTR_BORDER )->GetTop(); | |||
5282 | if ( ScHasPriority( pOther, pBottomLine ) ) | |||
5283 | pBottomLine = pOther; | |||
5284 | } | |||
5285 | ||||
5286 | if (ppLeft) | |||
5287 | *ppLeft = pLeftLine; | |||
5288 | if (ppTop) | |||
5289 | *ppTop = pTopLine; | |||
5290 | if (ppRight) | |||
5291 | *ppRight = pRightLine; | |||
5292 | if (ppBottom) | |||
5293 | *ppBottom = pBottomLine; | |||
5294 | } | |||
5295 | ||||
5296 | bool ScDocument::IsBlockEmpty( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow, | |||
5297 | SCCOL nEndCol, SCROW nEndRow, bool bIgnoreNotes ) const | |||
5298 | { | |||
5299 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size())) | |||
5300 | if (maTabs[nTab]) | |||
5301 | return maTabs[nTab]->IsBlockEmpty( nStartCol, nStartRow, nEndCol, nEndRow, bIgnoreNotes ); | |||
5302 | ||||
5303 | OSL_FAIL("wrong table number")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "5303" ": "), "%s", "wrong table number"); } } while (false ); | |||
5304 | return false; | |||
5305 | } | |||
5306 | ||||
5307 | void ScDocument::LockTable(SCTAB nTab) | |||
5308 | { | |||
5309 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
5310 | maTabs[nTab]->LockTable(); | |||
5311 | else | |||
5312 | { | |||
5313 | OSL_FAIL("wrong table number")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "5313" ": "), "%s", "wrong table number"); } } while (false ); | |||
5314 | } | |||
5315 | } | |||
5316 | ||||
5317 | void ScDocument::UnlockTable(SCTAB nTab) | |||
5318 | { | |||
5319 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
5320 | maTabs[nTab]->UnlockTable(); | |||
5321 | else | |||
5322 | { | |||
5323 | OSL_FAIL("wrong table number")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "5323" ": "), "%s", "wrong table number"); } } while (false ); | |||
5324 | } | |||
5325 | } | |||
5326 | ||||
5327 | bool ScDocument::IsBlockEditable( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow, | |||
5328 | SCCOL nEndCol, SCROW nEndRow, | |||
5329 | bool* pOnlyNotBecauseOfMatrix /* = NULL */, | |||
5330 | bool bNoMatrixAtAll ) const | |||
5331 | { | |||
5332 | // import into read-only document is possible | |||
5333 | if (!bImportingXML && !mbChangeReadOnlyEnabled && mpShell && mpShell->IsReadOnly()) | |||
5334 | { | |||
5335 | if ( pOnlyNotBecauseOfMatrix ) | |||
5336 | *pOnlyNotBecauseOfMatrix = false; | |||
5337 | return false; | |||
5338 | } | |||
5339 | ||||
5340 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size())) | |||
5341 | if (maTabs[nTab]) | |||
5342 | return maTabs[nTab]->IsBlockEditable( nStartCol, nStartRow, nEndCol, | |||
5343 | nEndRow, pOnlyNotBecauseOfMatrix, bNoMatrixAtAll ); | |||
5344 | ||||
5345 | OSL_FAIL("wrong table number")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "5345" ": "), "%s", "wrong table number"); } } while (false ); | |||
5346 | if ( pOnlyNotBecauseOfMatrix ) | |||
5347 | *pOnlyNotBecauseOfMatrix = false; | |||
5348 | return false; | |||
5349 | } | |||
5350 | ||||
5351 | bool ScDocument::IsSelectionEditable( const ScMarkData& rMark, | |||
5352 | bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) const | |||
5353 | { | |||
5354 | // import into read-only document is possible | |||
5355 | if ( !bImportingXML && !mbChangeReadOnlyEnabled && mpShell && mpShell->IsReadOnly() ) | |||
5356 | { | |||
5357 | if ( pOnlyNotBecauseOfMatrix ) | |||
5358 | *pOnlyNotBecauseOfMatrix = false; | |||
5359 | return false; | |||
5360 | } | |||
5361 | ||||
5362 | ScRange aRange; | |||
5363 | rMark.GetMarkArea(aRange); | |||
5364 | ||||
5365 | bool bOk = true; | |||
5366 | bool bMatrix = ( pOnlyNotBecauseOfMatrix != nullptr ); | |||
5367 | SCTAB nMax = static_cast<SCTAB>(maTabs.size()); | |||
5368 | for (const auto& rTab : rMark) | |||
5369 | { | |||
5370 | if (rTab >= nMax) | |||
5371 | break; | |||
5372 | ||||
5373 | if ( maTabs[rTab] ) | |||
5374 | { | |||
5375 | if (rMark.IsMarked()) | |||
5376 | { | |||
5377 | if ( !maTabs[rTab]->IsBlockEditable( aRange.aStart.Col(), | |||
5378 | aRange.aStart.Row(), aRange.aEnd.Col(), | |||
5379 | aRange.aEnd.Row(), pOnlyNotBecauseOfMatrix ) ) | |||
5380 | { | |||
5381 | bOk = false; | |||
5382 | if ( pOnlyNotBecauseOfMatrix ) | |||
5383 | bMatrix = *pOnlyNotBecauseOfMatrix; | |||
5384 | } | |||
5385 | } | |||
5386 | if (rMark.IsMultiMarked()) | |||
5387 | { | |||
5388 | if ( !maTabs[rTab]->IsSelectionEditable( rMark, pOnlyNotBecauseOfMatrix ) ) | |||
5389 | { | |||
5390 | bOk = false; | |||
5391 | if ( pOnlyNotBecauseOfMatrix ) | |||
5392 | bMatrix = *pOnlyNotBecauseOfMatrix; | |||
5393 | } | |||
5394 | } | |||
5395 | } | |||
5396 | ||||
5397 | if (!bOk && !bMatrix) | |||
5398 | break; | |||
5399 | } | |||
5400 | ||||
5401 | if ( pOnlyNotBecauseOfMatrix ) | |||
5402 | *pOnlyNotBecauseOfMatrix = ( !bOk && bMatrix ); | |||
5403 | ||||
5404 | return bOk; | |||
5405 | } | |||
5406 | ||||
5407 | bool ScDocument::HasSelectedBlockMatrixFragment( SCCOL nStartCol, SCROW nStartRow, | |||
5408 | SCCOL nEndCol, SCROW nEndRow, | |||
5409 | const ScMarkData& rMark ) const | |||
5410 | { | |||
5411 | bool bOk = true; | |||
5412 | SCTAB nMax = static_cast<SCTAB>(maTabs.size()); | |||
5413 | for (const auto& rTab : rMark) | |||
5414 | { | |||
5415 | if (rTab >= nMax) | |||
5416 | break; | |||
5417 | ||||
5418 | if (maTabs[rTab] && maTabs[rTab]->HasBlockMatrixFragment( nStartCol, nStartRow, nEndCol, nEndRow )) | |||
5419 | bOk = false; | |||
5420 | ||||
5421 | if (!bOk) | |||
5422 | break; | |||
5423 | } | |||
5424 | ||||
5425 | return !bOk; | |||
5426 | } | |||
5427 | ||||
5428 | bool ScDocument::GetMatrixFormulaRange( const ScAddress& rCellPos, ScRange& rMatrix ) | |||
5429 | { | |||
5430 | // if rCell is part of a matrix formula, return its complete range | |||
5431 | ||||
5432 | ScFormulaCell* pFCell = GetFormulaCell(rCellPos); | |||
5433 | if (!pFCell) | |||
5434 | // not a formula cell. Bail out. | |||
5435 | return false; | |||
5436 | ||||
5437 | ScAddress aOrigin = rCellPos; | |||
5438 | if (!pFCell->GetMatrixOrigin(*this, aOrigin)) | |||
5439 | // Failed to get the address of the matrix origin. | |||
5440 | return false; | |||
5441 | ||||
5442 | if (aOrigin != rCellPos) | |||
5443 | { | |||
5444 | pFCell = GetFormulaCell(aOrigin); | |||
5445 | if (!pFCell) | |||
5446 | // The matrix origin cell is not a formula cell !? Something is up... | |||
5447 | return false; | |||
5448 | } | |||
5449 | ||||
5450 | SCCOL nSizeX; | |||
5451 | SCROW nSizeY; | |||
5452 | pFCell->GetMatColsRows(nSizeX, nSizeY); | |||
5453 | if (nSizeX <= 0 || nSizeY <= 0) | |||
5454 | { | |||
5455 | // GetMatrixEdge computes also dimensions of the matrix | |||
5456 | // if not already done (may occur if document is loaded | |||
5457 | // from old file format). | |||
5458 | // Needs an "invalid" initialized address. | |||
5459 | aOrigin.SetInvalid(); | |||
5460 | pFCell->GetMatrixEdge(*this, aOrigin); | |||
5461 | pFCell->GetMatColsRows(nSizeX, nSizeY); | |||
5462 | } | |||
5463 | ||||
5464 | if (nSizeX <= 0 || nSizeY <= 0) | |||
5465 | // Matrix size is still invalid. Give up. | |||
5466 | return false; | |||
5467 | ||||
5468 | ScAddress aEnd( aOrigin.Col() + nSizeX - 1, | |||
5469 | aOrigin.Row() + nSizeY - 1, | |||
5470 | aOrigin.Tab() ); | |||
5471 | ||||
5472 | rMatrix.aStart = aOrigin; | |||
5473 | rMatrix.aEnd = aEnd; | |||
5474 | ||||
5475 | return true; | |||
5476 | } | |||
5477 | ||||
5478 | void ScDocument::ExtendOverlapped( SCCOL& rStartCol, SCROW& rStartRow, | |||
5479 | SCCOL nEndCol, SCROW nEndRow, SCTAB nTab ) const | |||
5480 | { | |||
5481 | if ( ValidColRow(rStartCol,rStartRow) && ValidColRow(nEndCol,nEndRow) && ValidTab(nTab) ) | |||
5482 | { | |||
5483 | if (nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab]) | |||
5484 | { | |||
5485 | SCCOL nCol; | |||
5486 | SCCOL nOldCol = rStartCol; | |||
5487 | SCROW nOldRow = rStartRow; | |||
5488 | for (nCol=nOldCol; nCol<=nEndCol; nCol++) | |||
5489 | while (GetAttr(nCol,rStartRow,nTab,ATTR_MERGE_FLAG)->IsVerOverlapped()) | |||
5490 | --rStartRow; | |||
5491 | ||||
5492 | //TODO: pass on ? | |||
5493 | ||||
5494 | ScAttrArray* pAttrArray = maTabs[nTab]->aCol[nOldCol].pAttrArray.get(); | |||
5495 | SCSIZE nIndex; | |||
5496 | if ( pAttrArray->Count() ) | |||
5497 | pAttrArray->Search( nOldRow, nIndex ); | |||
5498 | else | |||
5499 | nIndex = 0; | |||
5500 | SCROW nAttrPos = nOldRow; | |||
5501 | while (nAttrPos<=nEndRow) | |||
5502 | { | |||
5503 | OSL_ENSURE( nIndex < pAttrArray->Count(), "Wrong index in AttrArray" )do { if (true && (!(nIndex < pAttrArray->Count( )))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "5503" ": "), "%s", "Wrong index in AttrArray"); } } while (false); | |||
5504 | ||||
5505 | bool bHorOverlapped; | |||
5506 | if ( pAttrArray->Count() ) | |||
5507 | bHorOverlapped = pAttrArray->mvData[nIndex].pPattern->GetItem(ATTR_MERGE_FLAG).IsHorOverlapped(); | |||
5508 | else | |||
5509 | bHorOverlapped = GetDefPattern()->GetItem(ATTR_MERGE_FLAG).IsHorOverlapped(); | |||
5510 | if ( bHorOverlapped ) | |||
5511 | { | |||
5512 | SCROW nEndRowSeg = (pAttrArray->Count()) ? pAttrArray->mvData[nIndex].nEndRow : MaxRow(); | |||
5513 | SCROW nLoopEndRow = std::min( nEndRow, nEndRowSeg ); | |||
5514 | for (SCROW nAttrRow = nAttrPos; nAttrRow <= nLoopEndRow; nAttrRow++) | |||
5515 | { | |||
5516 | SCCOL nTempCol = nOldCol; | |||
5517 | do | |||
5518 | --nTempCol; | |||
5519 | while (GetAttr(nTempCol,nAttrRow,nTab,ATTR_MERGE_FLAG)->IsHorOverlapped()); | |||
5520 | if (nTempCol < rStartCol) | |||
5521 | rStartCol = nTempCol; | |||
5522 | } | |||
5523 | } | |||
5524 | if ( pAttrArray->Count() ) | |||
5525 | { | |||
5526 | nAttrPos = pAttrArray->mvData[nIndex].nEndRow + 1; | |||
5527 | ++nIndex; | |||
5528 | } | |||
5529 | else | |||
5530 | nAttrPos = MaxRow() + 1; | |||
5531 | } | |||
5532 | } | |||
5533 | } | |||
5534 | else | |||
5535 | { | |||
5536 | OSL_FAIL("ExtendOverlapped: invalid range")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "5536" ": "), "%s", "ExtendOverlapped: invalid range"); } } while (false); | |||
5537 | } | |||
5538 | } | |||
5539 | ||||
5540 | void ScDocument::ExtendMergeSel( SCCOL nStartCol, SCROW nStartRow, | |||
5541 | SCCOL& rEndCol, SCROW& rEndRow, | |||
5542 | const ScMarkData& rMark, bool bRefresh ) | |||
5543 | { | |||
5544 | // use all selected sheets from rMark | |||
5545 | ||||
5546 | SCCOL nOldEndCol = rEndCol; | |||
5547 | SCROW nOldEndRow = rEndRow; | |||
5548 | ||||
5549 | SCTAB nMax = static_cast<SCTAB>(maTabs.size()); | |||
5550 | for (const auto& rTab : rMark) | |||
5551 | { | |||
5552 | if (rTab >= nMax) | |||
5553 | break; | |||
5554 | ||||
5555 | if ( maTabs[rTab] ) | |||
5556 | { | |||
5557 | SCCOL nThisEndCol = nOldEndCol; | |||
5558 | SCROW nThisEndRow = nOldEndRow; | |||
5559 | ExtendMerge( nStartCol, nStartRow, nThisEndCol, nThisEndRow, rTab, bRefresh ); | |||
5560 | if ( nThisEndCol > rEndCol ) | |||
5561 | rEndCol = nThisEndCol; | |||
5562 | if ( nThisEndRow > rEndRow ) | |||
5563 | rEndRow = nThisEndRow; | |||
5564 | } | |||
5565 | } | |||
5566 | } | |||
5567 | ||||
5568 | bool ScDocument::ExtendMerge( SCCOL nStartCol, SCROW nStartRow, | |||
5569 | SCCOL& rEndCol, SCROW& rEndRow, | |||
5570 | SCTAB nTab, bool bRefresh ) | |||
5571 | { | |||
5572 | bool bFound = false; | |||
5573 | if ( ValidColRow(nStartCol,nStartRow) && ValidColRow(rEndCol,rEndRow) && ValidTab(nTab) ) | |||
5574 | { | |||
5575 | if (nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab]) | |||
5576 | bFound = maTabs[nTab]->ExtendMerge( nStartCol, nStartRow, rEndCol, rEndRow, bRefresh ); | |||
5577 | ||||
5578 | if (bRefresh) | |||
5579 | RefreshAutoFilter( nStartCol, nStartRow, rEndCol, rEndRow, nTab ); | |||
5580 | } | |||
5581 | else | |||
5582 | { | |||
5583 | OSL_FAIL("ExtendMerge: invalid range")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "5583" ": "), "%s", "ExtendMerge: invalid range"); } } while (false); | |||
5584 | } | |||
5585 | ||||
5586 | return bFound; | |||
5587 | } | |||
5588 | ||||
5589 | bool ScDocument::ExtendMerge( ScRange& rRange, bool bRefresh ) | |||
5590 | { | |||
5591 | bool bFound = false; | |||
5592 | SCTAB nStartTab = rRange.aStart.Tab(); | |||
5593 | SCTAB nEndTab = rRange.aEnd.Tab(); | |||
5594 | SCCOL nEndCol = rRange.aEnd.Col(); | |||
5595 | SCROW nEndRow = rRange.aEnd.Row(); | |||
5596 | ||||
5597 | PutInOrder( nStartTab, nEndTab ); | |||
5598 | for (SCTAB nTab = nStartTab; nTab <= nEndTab && nTab < static_cast<SCTAB>(maTabs.size()); nTab++ ) | |||
5599 | { | |||
5600 | SCCOL nExtendCol = rRange.aEnd.Col(); | |||
5601 | SCROW nExtendRow = rRange.aEnd.Row(); | |||
5602 | if (ExtendMerge( rRange.aStart.Col(), rRange.aStart.Row(), | |||
5603 | nExtendCol, nExtendRow, | |||
5604 | nTab, bRefresh ) ) | |||
5605 | { | |||
5606 | bFound = true; | |||
5607 | if (nExtendCol > nEndCol) nEndCol = nExtendCol; | |||
5608 | if (nExtendRow > nEndRow) nEndRow = nExtendRow; | |||
5609 | } | |||
5610 | } | |||
5611 | ||||
5612 | rRange.aEnd.SetCol(nEndCol); | |||
5613 | rRange.aEnd.SetRow(nEndRow); | |||
5614 | ||||
5615 | return bFound; | |||
5616 | } | |||
5617 | ||||
5618 | void ScDocument::ExtendTotalMerge( ScRange& rRange ) const | |||
5619 | { | |||
5620 | // Extend range to merged cells without including any new non-overlapped cells | |||
5621 | ScRange aExt = rRange; | |||
5622 | // ExtendMerge() is non-const, but called without refresh. | |||
5623 | if (!const_cast<ScDocument*>(this)->ExtendMerge( aExt )) | |||
5624 | return; | |||
5625 | ||||
5626 | if ( aExt.aEnd.Row() > rRange.aEnd.Row() ) | |||
5627 | { | |||
5628 | ScRange aTest = aExt; | |||
5629 | aTest.aStart.SetRow( rRange.aEnd.Row() + 1 ); | |||
5630 | if ( HasAttrib( aTest, HasAttrFlags::NotOverlapped ) ) | |||
5631 | aExt.aEnd.SetRow(rRange.aEnd.Row()); | |||
5632 | } | |||
5633 | if ( aExt.aEnd.Col() > rRange.aEnd.Col() ) | |||
5634 | { | |||
5635 | ScRange aTest = aExt; | |||
5636 | aTest.aStart.SetCol( rRange.aEnd.Col() + 1 ); | |||
5637 | if ( HasAttrib( aTest, HasAttrFlags::NotOverlapped ) ) | |||
5638 | aExt.aEnd.SetCol(rRange.aEnd.Col()); | |||
5639 | } | |||
5640 | ||||
5641 | rRange = aExt; | |||
5642 | } | |||
5643 | ||||
5644 | void ScDocument::ExtendOverlapped( ScRange& rRange ) const | |||
5645 | { | |||
5646 | SCTAB nStartTab = rRange.aStart.Tab(); | |||
5647 | SCTAB nEndTab = rRange.aEnd.Tab(); | |||
5648 | SCCOL nStartCol = rRange.aStart.Col(); | |||
5649 | SCROW nStartRow = rRange.aStart.Row(); | |||
5650 | ||||
5651 | PutInOrder( nStartTab, nEndTab ); | |||
5652 | for (SCTAB nTab = nStartTab; nTab <= nEndTab && nTab < static_cast<SCTAB>(maTabs.size()); nTab++ ) | |||
5653 | { | |||
5654 | SCCOL nExtendCol = rRange.aStart.Col(); | |||
5655 | SCROW nExtendRow = rRange.aStart.Row(); | |||
5656 | ExtendOverlapped( nExtendCol, nExtendRow, | |||
5657 | rRange.aEnd.Col(), rRange.aEnd.Row(), nTab ); | |||
5658 | if (nExtendCol < nStartCol) | |||
5659 | { | |||
5660 | nStartCol = nExtendCol; | |||
5661 | } | |||
5662 | if (nExtendRow < nStartRow) | |||
5663 | { | |||
5664 | nStartRow = nExtendRow; | |||
5665 | } | |||
5666 | } | |||
5667 | ||||
5668 | rRange.aStart.SetCol(nStartCol); | |||
5669 | rRange.aStart.SetRow(nStartRow); | |||
5670 | } | |||
5671 | ||||
5672 | bool ScDocument::RefreshAutoFilter( SCCOL nStartCol, SCROW nStartRow, | |||
5673 | SCCOL nEndCol, SCROW nEndRow, SCTAB nTab ) | |||
5674 | { | |||
5675 | SCTAB nDBTab; | |||
5676 | SCCOL nDBStartCol; | |||
5677 | SCROW nDBStartRow; | |||
5678 | SCCOL nDBEndCol; | |||
5679 | SCROW nDBEndRow; | |||
5680 | ||||
5681 | // Delete Autofilter | |||
5682 | ||||
5683 | bool bChange = RemoveFlagsTab( nStartCol,nStartRow, nEndCol,nEndRow, nTab, ScMF::Auto ); | |||
5684 | ||||
5685 | // Set Autofilter | |||
5686 | ||||
5687 | const ScDBData* pData = nullptr; | |||
5688 | ScDBCollection::NamedDBs& rDBs = pDBCollection->getNamedDBs(); | |||
5689 | for (const auto& rxDB : rDBs) | |||
5690 | { | |||
5691 | if (rxDB->HasAutoFilter()) | |||
5692 | { | |||
5693 | rxDB->GetArea(nDBTab, nDBStartCol,nDBStartRow, nDBEndCol,nDBEndRow); | |||
5694 | if ( nDBTab==nTab && nDBStartRow<=nEndRow && nDBEndRow>=nStartRow && | |||
5695 | nDBStartCol<=nEndCol && nDBEndCol>=nStartCol ) | |||
5696 | { | |||
5697 | if (ApplyFlagsTab( nDBStartCol,nDBStartRow, nDBEndCol,nDBStartRow, | |||
5698 | nDBTab, ScMF::Auto )) | |||
5699 | bChange = true; | |||
5700 | } | |||
5701 | } | |||
5702 | } | |||
5703 | if (nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab]) | |||
5704 | pData = maTabs[nTab]->GetAnonymousDBData(); | |||
5705 | else | |||
5706 | pData=nullptr; | |||
5707 | if (pData && pData->HasAutoFilter()) | |||
5708 | { | |||
5709 | pData->GetArea( nDBTab, nDBStartCol,nDBStartRow, nDBEndCol,nDBEndRow ); | |||
5710 | if ( nDBTab==nTab && nDBStartRow<=nEndRow && nDBEndRow>=nStartRow && | |||
5711 | nDBStartCol<=nEndCol && nDBEndCol>=nStartCol ) | |||
5712 | { | |||
5713 | if (ApplyFlagsTab( nDBStartCol,nDBStartRow, nDBEndCol,nDBStartRow, | |||
5714 | nDBTab, ScMF::Auto )) | |||
5715 | bChange = true; | |||
5716 | } | |||
5717 | } | |||
5718 | return bChange; | |||
5719 | } | |||
5720 | ||||
5721 | void ScDocument::SkipOverlapped( SCCOL& rCol, SCROW& rRow, SCTAB nTab ) const | |||
5722 | { | |||
5723 | while (IsHorOverlapped(rCol, rRow, nTab)) | |||
5724 | --rCol; | |||
5725 | while (IsVerOverlapped(rCol, rRow, nTab)) | |||
5726 | --rRow; | |||
5727 | } | |||
5728 | ||||
5729 | bool ScDocument::IsHorOverlapped( SCCOL nCol, SCROW nRow, SCTAB nTab ) const | |||
5730 | { | |||
5731 | const ScMergeFlagAttr* pAttr = GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG ); | |||
5732 | if (pAttr) | |||
5733 | return pAttr->IsHorOverlapped(); | |||
5734 | else | |||
5735 | { | |||
5736 | OSL_FAIL("Overlapped: Attr==0")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "5736" ": "), "%s", "Overlapped: Attr==0"); } } while (false ); | |||
5737 | return false; | |||
5738 | } | |||
5739 | } | |||
5740 | ||||
5741 | bool ScDocument::IsVerOverlapped( SCCOL nCol, SCROW nRow, SCTAB nTab ) const | |||
5742 | { | |||
5743 | const ScMergeFlagAttr* pAttr = GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG ); | |||
5744 | if (pAttr) | |||
5745 | return pAttr->IsVerOverlapped(); | |||
5746 | else | |||
5747 | { | |||
5748 | OSL_FAIL("Overlapped: Attr==0")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "5748" ": "), "%s", "Overlapped: Attr==0"); } } while (false ); | |||
5749 | return false; | |||
5750 | } | |||
5751 | } | |||
5752 | ||||
5753 | void ScDocument::ApplySelectionFrame( const ScMarkData& rMark, | |||
5754 | const SvxBoxItem& rLineOuter, | |||
5755 | const SvxBoxInfoItem* pLineInner ) | |||
5756 | { | |||
5757 | ScRangeList aRangeList; | |||
5758 | rMark.FillRangeListWithMarks( &aRangeList, false ); | |||
5759 | size_t nRangeCount = aRangeList.size(); | |||
5760 | SCTAB nMax = static_cast<SCTAB>(maTabs.size()); | |||
5761 | for (const auto& rTab : rMark) | |||
5762 | { | |||
5763 | if (rTab >= nMax) | |||
5764 | break; | |||
5765 | ||||
5766 | if (maTabs[rTab]) | |||
5767 | { | |||
5768 | for ( size_t j=0; j < nRangeCount; j++ ) | |||
5769 | { | |||
5770 | const ScRange & rRange = aRangeList[ j ]; | |||
5771 | maTabs[rTab]->ApplyBlockFrame( rLineOuter, pLineInner, | |||
5772 | rRange.aStart.Col(), rRange.aStart.Row(), | |||
5773 | rRange.aEnd.Col(), rRange.aEnd.Row() ); | |||
5774 | } | |||
5775 | } | |||
5776 | } | |||
5777 | if (!rLineOuter.IsRemoveAdjacentCellBorder()) | |||
5778 | return; | |||
5779 | ||||
5780 | SvxBoxItem aTmp0(rLineOuter); | |||
5781 | aTmp0.SetLine( nullptr, SvxBoxItemLine::TOP ); | |||
5782 | aTmp0.SetLine( nullptr, SvxBoxItemLine::BOTTOM ); | |||
5783 | aTmp0.SetLine( nullptr, SvxBoxItemLine::LEFT ); | |||
5784 | aTmp0.SetLine( nullptr, SvxBoxItemLine::RIGHT ); | |||
5785 | SvxBoxItem aLeft( aTmp0 ); | |||
5786 | SvxBoxItem aRight( aTmp0 ); | |||
5787 | SvxBoxItem aTop( aTmp0 ); | |||
5788 | SvxBoxItem aBottom( aTmp0 ); | |||
5789 | ||||
5790 | SvxBoxInfoItem aTmp1( *pLineInner ); | |||
5791 | aTmp1.SetTable( false ); | |||
5792 | aTmp1.SetLine( nullptr, SvxBoxInfoItemLine::HORI ); | |||
5793 | aTmp1.SetLine( nullptr, SvxBoxInfoItemLine::VERT ); | |||
5794 | aTmp1.SetValid( SvxBoxInfoItemValidFlags::ALL, false ); | |||
5795 | aTmp1.SetValid( SvxBoxInfoItemValidFlags::DISTANCE ); | |||
5796 | SvxBoxInfoItem aLeftInfo( aTmp1 ); | |||
5797 | SvxBoxInfoItem aRightInfo( aTmp1 ); | |||
5798 | SvxBoxInfoItem aTopInfo( aTmp1 ); | |||
5799 | SvxBoxInfoItem aBottomInfo( aTmp1 ); | |||
5800 | ||||
5801 | if (pLineInner->IsValid( SvxBoxInfoItemValidFlags::TOP ) && !rLineOuter.GetTop()) | |||
5802 | aTopInfo.SetValid( SvxBoxInfoItemValidFlags::BOTTOM ); | |||
5803 | ||||
5804 | if (pLineInner->IsValid( SvxBoxInfoItemValidFlags::BOTTOM ) && !rLineOuter.GetBottom()) | |||
5805 | aBottomInfo.SetValid( SvxBoxInfoItemValidFlags::TOP ); | |||
5806 | ||||
5807 | if (pLineInner->IsValid( SvxBoxInfoItemValidFlags::LEFT ) && !rLineOuter.GetLeft()) | |||
5808 | aLeftInfo.SetValid( SvxBoxInfoItemValidFlags::RIGHT ); | |||
5809 | ||||
5810 | if (pLineInner->IsValid( SvxBoxInfoItemValidFlags::RIGHT ) && !rLineOuter.GetRight()) | |||
5811 | aRightInfo.SetValid( SvxBoxInfoItemValidFlags::LEFT ); | |||
5812 | ||||
5813 | const ScRangeList& rRangeListTopEnvelope = rMark.GetTopEnvelope(); | |||
5814 | const ScRangeList& rRangeListBottomEnvelope = rMark.GetBottomEnvelope(); | |||
5815 | const ScRangeList& rRangeListLeftEnvelope = rMark.GetLeftEnvelope(); | |||
5816 | const ScRangeList& rRangeListRightEnvelope = rMark.GetRightEnvelope(); | |||
5817 | ||||
5818 | for (const auto& rTab : rMark) | |||
5819 | { | |||
5820 | if (rTab >= nMax) | |||
5821 | break; | |||
5822 | ||||
5823 | if ( maTabs[rTab] ) | |||
5824 | { | |||
5825 | size_t nEnvelopeRangeCount = rRangeListTopEnvelope.size(); | |||
5826 | for ( size_t j=0; j < nEnvelopeRangeCount; j++ ) | |||
5827 | { | |||
5828 | const ScRange & rRange = rRangeListTopEnvelope[ j ]; | |||
5829 | maTabs[rTab]->ApplyBlockFrame( aTop, &aTopInfo, | |||
5830 | rRange.aStart.Col(), rRange.aStart.Row(), | |||
5831 | rRange.aEnd.Col(), rRange.aEnd.Row() ); | |||
5832 | } | |||
5833 | nEnvelopeRangeCount = rRangeListBottomEnvelope.size(); | |||
5834 | for ( size_t j=0; j < nEnvelopeRangeCount; j++ ) | |||
5835 | { | |||
5836 | const ScRange & rRange = rRangeListBottomEnvelope[ j ]; | |||
5837 | maTabs[rTab]->ApplyBlockFrame( aBottom, &aBottomInfo, | |||
5838 | rRange.aStart.Col(), rRange.aStart.Row(), | |||
5839 | rRange.aEnd.Col(), rRange.aEnd.Row() ); | |||
5840 | } | |||
5841 | nEnvelopeRangeCount = rRangeListLeftEnvelope.size(); | |||
5842 | for ( size_t j=0; j < nEnvelopeRangeCount; j++ ) | |||
5843 | { | |||
5844 | const ScRange & rRange = rRangeListLeftEnvelope[ j ]; | |||
5845 | maTabs[rTab]->ApplyBlockFrame( aLeft, &aLeftInfo, | |||
5846 | rRange.aStart.Col(), rRange.aStart.Row(), | |||
5847 | rRange.aEnd.Col(), rRange.aEnd.Row() ); | |||
5848 | } | |||
5849 | nEnvelopeRangeCount = rRangeListRightEnvelope.size(); | |||
5850 | for ( size_t j=0; j < nEnvelopeRangeCount; j++ ) | |||
5851 | { | |||
5852 | const ScRange & rRange = rRangeListRightEnvelope[ j ]; | |||
5853 | maTabs[rTab]->ApplyBlockFrame( aRight, &aRightInfo, | |||
5854 | rRange.aStart.Col(), rRange.aStart.Row(), | |||
5855 | rRange.aEnd.Col(), rRange.aEnd.Row() ); | |||
5856 | } | |||
5857 | } | |||
5858 | } | |||
5859 | } | |||
5860 | ||||
5861 | void ScDocument::ApplyFrameAreaTab(const ScRange& rRange, | |||
5862 | const SvxBoxItem& rLineOuter, | |||
5863 | const SvxBoxInfoItem& rLineInner) | |||
5864 | { | |||
5865 | SCTAB nStartTab = rRange.aStart.Tab(); | |||
5866 | SCTAB nEndTab = rRange.aStart.Tab(); | |||
5867 | for (SCTAB nTab=nStartTab; nTab<=nEndTab && nTab < static_cast<SCTAB>(maTabs.size()); nTab++) | |||
5868 | if (maTabs[nTab]) | |||
5869 | maTabs[nTab]->ApplyBlockFrame(rLineOuter, &rLineInner, | |||
5870 | rRange.aStart.Col(), rRange.aStart.Row(), | |||
5871 | rRange.aEnd.Col(), rRange.aEnd.Row()); | |||
5872 | } | |||
5873 | ||||
5874 | void ScDocument::ApplySelectionPattern( const ScPatternAttr& rAttr, const ScMarkData& rMark, ScEditDataArray* pDataArray, bool* const pIsChanged ) | |||
5875 | { | |||
5876 | const SfxItemSet* pSet = &rAttr.GetItemSet(); | |||
5877 | bool bSet = false; | |||
5878 | sal_uInt16 i; | |||
5879 | for (i=ATTR_PATTERN_START; i<=ATTR_PATTERN_END && !bSet; i++) | |||
5880 | if (pSet->GetItemState(i) == SfxItemState::SET) | |||
5881 | bSet = true; | |||
5882 | ||||
5883 | if (!bSet) | |||
5884 | return; | |||
5885 | ||||
5886 | // ApplySelectionCache needs multi mark | |||
5887 | if ( rMark.IsMarked() && !rMark.IsMultiMarked() ) | |||
5888 | { | |||
5889 | ScRange aRange; | |||
5890 | rMark.GetMarkArea( aRange ); | |||
5891 | ApplyPatternArea( aRange.aStart.Col(), aRange.aStart.Row(), | |||
5892 | aRange.aEnd.Col(), aRange.aEnd.Row(), rMark, rAttr, pDataArray, pIsChanged ); | |||
5893 | } | |||
5894 | else | |||
5895 | { | |||
5896 | SfxItemPoolCache aCache( mxPoolHelper->GetDocPool(), pSet ); | |||
5897 | SCTAB nMax = static_cast<SCTAB>(maTabs.size()); | |||
5898 | for (const auto& rTab : rMark) | |||
5899 | { | |||
5900 | if (rTab >= nMax) | |||
5901 | break; | |||
5902 | if (maTabs[rTab]) | |||
5903 | maTabs[rTab]->ApplySelectionCache( &aCache, rMark, pDataArray, pIsChanged ); | |||
5904 | } | |||
5905 | } | |||
5906 | } | |||
5907 | ||||
5908 | void ScDocument::ChangeSelectionIndent( bool bIncrement, const ScMarkData& rMark ) | |||
5909 | { | |||
5910 | SCTAB nMax = static_cast<SCTAB>(maTabs.size()); | |||
5911 | for (const auto& rTab : rMark) | |||
5912 | { | |||
5913 | if (rTab >= nMax) | |||
5914 | break; | |||
5915 | if (maTabs[rTab]) | |||
5916 | maTabs[rTab]->ChangeSelectionIndent( bIncrement, rMark ); | |||
5917 | } | |||
5918 | } | |||
5919 | ||||
5920 | void ScDocument::ClearSelectionItems( const sal_uInt16* pWhich, const ScMarkData& rMark ) | |||
5921 | { | |||
5922 | SCTAB nMax = static_cast<SCTAB>(maTabs.size()); | |||
5923 | for (const auto& rTab : rMark) | |||
5924 | { | |||
5925 | if (rTab >= nMax) | |||
5926 | break; | |||
5927 | if (maTabs[rTab]) | |||
5928 | maTabs[rTab]->ClearSelectionItems( pWhich, rMark ); | |||
5929 | } | |||
5930 | } | |||
5931 | ||||
5932 | void ScDocument::DeleteSelection( InsertDeleteFlags nDelFlag, const ScMarkData& rMark, bool bBroadcast ) | |||
5933 | { | |||
5934 | sc::AutoCalcSwitch aACSwitch(*this, false); | |||
5935 | ||||
5936 | std::vector<ScAddress> aGroupPos; | |||
5937 | // Destroy and reconstruct listeners only if content is affected. | |||
5938 | bool bDelContent = ((nDelFlag & ~InsertDeleteFlags::CONTENTS) != nDelFlag); | |||
5939 | if (bDelContent) | |||
5940 | { | |||
5941 | // Record the positions of top and/or bottom formula groups that | |||
5942 | // intersect the area borders. | |||
5943 | sc::EndListeningContext aCxt(*this); | |||
5944 | ScRangeList aRangeList; | |||
5945 | rMark.FillRangeListWithMarks( &aRangeList, false); | |||
5946 | for (size_t i = 0; i < aRangeList.size(); ++i) | |||
5947 | { | |||
5948 | const ScRange & rRange = aRangeList[i]; | |||
5949 | EndListeningIntersectedGroups( aCxt, rRange, &aGroupPos); | |||
5950 | } | |||
5951 | aCxt.purgeEmptyBroadcasters(); | |||
5952 | } | |||
5953 | ||||
5954 | SCTAB nMax = static_cast<SCTAB>(maTabs.size()); | |||
5955 | for (const auto& rTab : rMark) | |||
5956 | { | |||
5957 | if (rTab >= nMax) | |||
5958 | break; | |||
5959 | if (maTabs[rTab]) | |||
5960 | maTabs[rTab]->DeleteSelection(nDelFlag, rMark, bBroadcast); | |||
5961 | } | |||
5962 | ||||
5963 | if (!bDelContent) | |||
5964 | return; | |||
5965 | ||||
5966 | // Re-start listeners on those top bottom groups that have been split. | |||
5967 | SetNeedsListeningGroups(aGroupPos); | |||
5968 | StartNeededListeners(); | |||
5969 | ||||
5970 | // If formula groups were split their listeners were destroyed and may | |||
5971 | // need to be notified now that they're restored, | |||
5972 | // ScTable::DeleteSelection() couldn't do that. | |||
5973 | if (aGroupPos.empty()) | |||
5974 | return; | |||
5975 | ||||
5976 | ScRangeList aRangeList; | |||
5977 | rMark.FillRangeListWithMarks( &aRangeList, false); | |||
5978 | for (size_t i = 0; i < aRangeList.size(); ++i) | |||
5979 | { | |||
5980 | SetDirty( aRangeList[i], true); | |||
5981 | } | |||
5982 | //Notify listeners on top and bottom of the group that has been split | |||
5983 | for (size_t i = 0; i < aGroupPos.size(); ++i) { | |||
5984 | ScFormulaCell *pFormulaCell = GetFormulaCell(aGroupPos[i]); | |||
5985 | if (pFormulaCell) | |||
5986 | pFormulaCell->SetDirty(true); | |||
5987 | } | |||
5988 | } | |||
5989 | ||||
5990 | void ScDocument::DeleteSelectionTab( | |||
5991 | SCTAB nTab, InsertDeleteFlags nDelFlag, const ScMarkData& rMark ) | |||
5992 | { | |||
5993 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab]) | |||
5994 | { | |||
5995 | sc::AutoCalcSwitch aACSwitch(*this, false); | |||
5996 | ||||
5997 | std::vector<ScAddress> aGroupPos; | |||
5998 | // Destroy and reconstruct listeners only if content is affected. | |||
5999 | bool bDelContent = ((nDelFlag & ~InsertDeleteFlags::CONTENTS) != nDelFlag); | |||
6000 | if (bDelContent) | |||
6001 | { | |||
6002 | // Record the positions of top and/or bottom formula groups that | |||
6003 | // intersect the area borders. | |||
6004 | sc::EndListeningContext aCxt(*this); | |||
6005 | ScRangeList aRangeList; | |||
6006 | rMark.FillRangeListWithMarks( &aRangeList, false); | |||
6007 | for (size_t i = 0; i < aRangeList.size(); ++i) | |||
6008 | { | |||
6009 | const ScRange & rRange = aRangeList[i]; | |||
6010 | if (rRange.aStart.Tab() <= nTab && nTab <= rRange.aEnd.Tab()) | |||
6011 | { | |||
6012 | ScRange aRange( rRange); | |||
6013 | aRange.aStart.SetTab( nTab); | |||
6014 | aRange.aEnd.SetTab( nTab); | |||
6015 | EndListeningIntersectedGroups( aCxt, aRange, &aGroupPos); | |||
6016 | } | |||
6017 | } | |||
6018 | aCxt.purgeEmptyBroadcasters(); | |||
6019 | } | |||
6020 | ||||
6021 | maTabs[nTab]->DeleteSelection(nDelFlag, rMark); | |||
6022 | ||||
6023 | if (bDelContent) | |||
6024 | { | |||
6025 | // Re-start listeners on those top bottom groups that have been split. | |||
6026 | SetNeedsListeningGroups(aGroupPos); | |||
6027 | StartNeededListeners(); | |||
6028 | ||||
6029 | // If formula groups were split their listeners were destroyed and may | |||
6030 | // need to be notified now that they're restored, | |||
6031 | // ScTable::DeleteSelection() couldn't do that. | |||
6032 | if (!aGroupPos.empty()) | |||
6033 | { | |||
6034 | ScRangeList aRangeList; | |||
6035 | rMark.FillRangeListWithMarks( &aRangeList, false); | |||
6036 | for (size_t i = 0; i < aRangeList.size(); ++i) | |||
6037 | { | |||
6038 | const ScRange & rRange = aRangeList[i]; | |||
6039 | if (rRange.aStart.Tab() <= nTab && nTab <= rRange.aEnd.Tab()) | |||
6040 | { | |||
6041 | ScRange aRange( rRange); | |||
6042 | aRange.aStart.SetTab( nTab); | |||
6043 | aRange.aEnd.SetTab( nTab); | |||
6044 | SetDirty( aRange, true); | |||
6045 | } | |||
6046 | } | |||
6047 | } | |||
6048 | } | |||
6049 | } | |||
6050 | else | |||
6051 | { | |||
6052 | OSL_FAIL("wrong table")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "6052" ": "), "%s", "wrong table"); } } while (false); | |||
6053 | } | |||
6054 | } | |||
6055 | ||||
6056 | ScPatternAttr* ScDocument::GetDefPattern() const | |||
6057 | { | |||
6058 | return const_cast<ScPatternAttr*>(&mxPoolHelper->GetDocPool()->GetDefaultItem(ATTR_PATTERN)); | |||
6059 | } | |||
6060 | ||||
6061 | ScDocumentPool* ScDocument::GetPool() | |||
6062 | { | |||
6063 | return mxPoolHelper->GetDocPool(); | |||
6064 | } | |||
6065 | ||||
6066 | ScStyleSheetPool* ScDocument::GetStyleSheetPool() const | |||
6067 | { | |||
6068 | return mxPoolHelper->GetStylePool(); | |||
6069 | } | |||
6070 | ||||
6071 | SCSIZE ScDocument::GetEmptyLinesInBlock( SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab, | |||
6072 | SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab, ScDirection eDir ) | |||
6073 | { | |||
6074 | PutInOrder(nStartCol, nEndCol); | |||
6075 | PutInOrder(nStartRow, nEndRow); | |||
6076 | PutInOrder(nStartTab, nEndTab); | |||
6077 | if (ValidTab(nStartTab) && nStartTab < static_cast<SCTAB>(maTabs.size())) | |||
6078 | { | |||
6079 | if (maTabs[nStartTab]) | |||
6080 | return maTabs[nStartTab]->GetEmptyLinesInBlock(nStartCol, nStartRow, nEndCol, nEndRow, eDir); | |||
6081 | else | |||
6082 | return 0; | |||
6083 | } | |||
6084 | else | |||
6085 | return 0; | |||
6086 | } | |||
6087 | ||||
6088 | void ScDocument::FindAreaPos( SCCOL& rCol, SCROW& rRow, SCTAB nTab, ScMoveDirection eDirection ) const | |||
6089 | { | |||
6090 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab]) | |||
6091 | maTabs[nTab]->FindAreaPos( rCol, rRow, eDirection ); | |||
6092 | } | |||
6093 | ||||
6094 | void ScDocument::GetNextPos( SCCOL& rCol, SCROW& rRow, SCTAB nTab, SCCOL nMovX, SCROW nMovY, | |||
6095 | bool bMarked, bool bUnprotected, const ScMarkData& rMark, SCCOL nTabStartCol ) const | |||
6096 | { | |||
6097 | OSL_ENSURE( !nMovX || !nMovY, "GetNextPos: only X or Y" )do { if (true && (!(!nMovX || !nMovY))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "6097" ": "), "%s", "GetNextPos: only X or Y"); } } while (false); | |||
6098 | ||||
6099 | ScMarkData aCopyMark = rMark; | |||
6100 | aCopyMark.SetMarking(false); | |||
6101 | aCopyMark.MarkToMulti(); | |||
6102 | ||||
6103 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab]) | |||
6104 | maTabs[nTab]->GetNextPos( rCol, rRow, nMovX, nMovY, bMarked, bUnprotected, aCopyMark, nTabStartCol ); | |||
6105 | } | |||
6106 | ||||
6107 | // Data operations | |||
6108 | ||||
6109 | void ScDocument::UpdStlShtPtrsFrmNms() | |||
6110 | { | |||
6111 | ScDocumentPool* pPool = mxPoolHelper->GetDocPool(); | |||
6112 | ||||
6113 | for (const SfxPoolItem* pItem : pPool->GetItemSurrogates(ATTR_PATTERN)) | |||
6114 | { | |||
6115 | auto pPattern = const_cast<ScPatternAttr*>(dynamic_cast<const ScPatternAttr*>(pItem)); | |||
6116 | if (pPattern) | |||
6117 | pPattern->UpdateStyleSheet(*this); | |||
6118 | } | |||
6119 | const_cast<ScPatternAttr&>(pPool->GetDefaultItem(ATTR_PATTERN)).UpdateStyleSheet(*this); | |||
6120 | } | |||
6121 | ||||
6122 | void ScDocument::StylesToNames() | |||
6123 | { | |||
6124 | ScDocumentPool* pPool = mxPoolHelper->GetDocPool(); | |||
6125 | ||||
6126 | for (const SfxPoolItem* pItem : pPool->GetItemSurrogates(ATTR_PATTERN)) | |||
6127 | { | |||
6128 | auto pPattern = const_cast<ScPatternAttr*>(dynamic_cast<const ScPatternAttr*>(pItem)); | |||
6129 | if (pPattern) | |||
6130 | pPattern->StyleToName(); | |||
6131 | } | |||
6132 | const_cast<ScPatternAttr&>(pPool->GetDefaultItem(ATTR_PATTERN)).StyleToName(); | |||
6133 | } | |||
6134 | ||||
6135 | sal_uLong ScDocument::GetCellCount() const | |||
6136 | { | |||
6137 | sal_uLong nCellCount = 0; | |||
6138 | ||||
6139 | for (const auto& a : maTabs) | |||
6140 | { | |||
6141 | if (a) | |||
6142 | nCellCount += a->GetCellCount(); | |||
6143 | } | |||
6144 | ||||
6145 | return nCellCount; | |||
6146 | } | |||
6147 | ||||
6148 | sal_uLong ScDocument::GetFormulaGroupCount() const | |||
6149 | { | |||
6150 | sal_uLong nFormulaGroupCount = 0; | |||
6151 | ||||
6152 | ScFormulaGroupIterator aIter( *const_cast<ScDocument*>(this) ); | |||
6153 | for ( sc::FormulaGroupEntry* ptr = aIter.first(); ptr; ptr = aIter.next()) | |||
6154 | { | |||
6155 | nFormulaGroupCount++; | |||
6156 | } | |||
6157 | ||||
6158 | return nFormulaGroupCount; | |||
6159 | } | |||
6160 | ||||
6161 | sal_uLong ScDocument::GetCodeCount() const | |||
6162 | { | |||
6163 | sal_uLong nCodeCount = 0; | |||
6164 | ||||
6165 | for (const auto& a : maTabs) | |||
6166 | { | |||
6167 | if (a) | |||
6168 | nCodeCount += a->GetCodeCount(); | |||
6169 | } | |||
6170 | ||||
6171 | return nCodeCount; | |||
6172 | } | |||
6173 | ||||
6174 | void ScDocument::PageStyleModified( SCTAB nTab, const OUString& rNewName ) | |||
6175 | { | |||
6176 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
6177 | maTabs[nTab]->PageStyleModified( rNewName ); | |||
6178 | } | |||
6179 | ||||
6180 | void ScDocument::SetPageStyle( SCTAB nTab, const OUString& rName ) | |||
6181 | { | |||
6182 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
6183 | maTabs[nTab]->SetPageStyle( rName ); | |||
6184 | } | |||
6185 | ||||
6186 | OUString ScDocument::GetPageStyle( SCTAB nTab ) const | |||
6187 | { | |||
6188 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
6189 | return maTabs[nTab]->GetPageStyle(); | |||
6190 | ||||
6191 | return OUString(); | |||
6192 | } | |||
6193 | ||||
6194 | void ScDocument::SetPageSize( SCTAB nTab, const Size& rSize ) | |||
6195 | { | |||
6196 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
6197 | maTabs[nTab]->SetPageSize( rSize ); | |||
6198 | } | |||
6199 | ||||
6200 | Size ScDocument::GetPageSize( SCTAB nTab ) const | |||
6201 | { | |||
6202 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
6203 | return maTabs[nTab]->GetPageSize(); | |||
6204 | ||||
6205 | OSL_FAIL("invalid tab")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "6205" ": "), "%s", "invalid tab"); } } while (false); | |||
6206 | return Size(); | |||
6207 | } | |||
6208 | ||||
6209 | void ScDocument::SetRepeatArea( SCTAB nTab, SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCROW nEndRow ) | |||
6210 | { | |||
6211 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
6212 | maTabs[nTab]->SetRepeatArea( nStartCol, nEndCol, nStartRow, nEndRow ); | |||
6213 | } | |||
6214 | ||||
6215 | void ScDocument::InvalidatePageBreaks(SCTAB nTab) | |||
6216 | { | |||
6217 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab]) | |||
6218 | maTabs[nTab]->InvalidatePageBreaks(); | |||
6219 | } | |||
6220 | ||||
6221 | void ScDocument::UpdatePageBreaks( SCTAB nTab, const ScRange* pUserArea ) | |||
6222 | { | |||
6223 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
6224 | maTabs[nTab]->UpdatePageBreaks( pUserArea ); | |||
6225 | } | |||
6226 | ||||
6227 | void ScDocument::RemoveManualBreaks( SCTAB nTab ) | |||
6228 | { | |||
6229 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
6230 | maTabs[nTab]->RemoveManualBreaks(); | |||
6231 | } | |||
6232 | ||||
6233 | bool ScDocument::HasManualBreaks( SCTAB nTab ) const | |||
6234 | { | |||
6235 | if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) | |||
6236 | return maTabs[nTab]->HasManualBreaks(); | |||
6237 | ||||
6238 | OSL_FAIL("invalid tab")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "6238" ": "), "%s", "invalid tab"); } } while (false); | |||
6239 | return false; | |||
6240 | } | |||
6241 | ||||
6242 | void ScDocument::GetDocStat( ScDocStat& rDocStat ) | |||
6243 | { | |||
6244 | rDocStat.nTableCount = GetTableCount(); | |||
6245 | rDocStat.aDocName = aDocName; | |||
6246 | rDocStat.nFormulaCount = GetFormulaGroupCount(); | |||
6247 | rDocStat.nCellCount = GetCellCount(); | |||
6248 | } | |||
6249 | ||||
6250 | bool ScDocument::HasPrintRange() | |||
6251 | { | |||
6252 | bool bResult = false; | |||
6253 | ||||
6254 | for (const auto& a : maTabs) | |||
6255 | { | |||
6256 | if (!a) | |||
6257 | continue; | |||
6258 | bResult = a->IsPrintEntireSheet() || (a->GetPrintRangeCount() > 0); | |||
6259 | if (bResult) | |||
6260 | break; | |||
6261 | } | |||
6262 | ||||
6263 | return bResult; | |||
6264 | } | |||
6265 | ||||
6266 | bool ScDocument::IsPrintEntireSheet( SCTAB nTab ) const | |||
6267 | { | |||
6268 | return (ValidTab(nTab) ) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->IsPrintEntireSheet(); | |||
6269 | } | |||
6270 | ||||
6271 | sal_uInt16 ScDocument::GetPrintRangeCount( SCTAB nTab ) | |||
6272 | { | |||
6273 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab]) | |||
6274 | return maTabs[nTab]->GetPrintRangeCount(); | |||
6275 | ||||
6276 | return 0; | |||
6277 | } | |||
6278 | ||||
6279 | const ScRange* ScDocument::GetPrintRange( SCTAB nTab, sal_uInt16 nPos ) | |||
6280 | { | |||
6281 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab]) | |||
6282 | return maTabs[nTab]->GetPrintRange(nPos); | |||
6283 | ||||
6284 | return nullptr; | |||
6285 | } | |||
6286 | ||||
6287 | const ScRange* ScDocument::GetRepeatColRange( SCTAB nTab ) | |||
6288 | { | |||
6289 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab]) | |||
6290 | return maTabs[nTab]->GetRepeatColRange(); | |||
6291 | ||||
6292 | return nullptr; | |||
6293 | } | |||
6294 | ||||
6295 | const ScRange* ScDocument::GetRepeatRowRange( SCTAB nTab ) | |||
6296 | { | |||
6297 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab]) | |||
6298 | return maTabs[nTab]->GetRepeatRowRange(); | |||
6299 | ||||
6300 | return nullptr; | |||
6301 | } | |||
6302 | ||||
6303 | void ScDocument::ClearPrintRanges( SCTAB nTab ) | |||
6304 | { | |||
6305 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab]) | |||
6306 | maTabs[nTab]->ClearPrintRanges(); | |||
6307 | } | |||
6308 | ||||
6309 | void ScDocument::AddPrintRange( SCTAB nTab, const ScRange& rNew ) | |||
6310 | { | |||
6311 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab]) | |||
6312 | maTabs[nTab]->AddPrintRange( rNew ); | |||
6313 | } | |||
6314 | ||||
6315 | void ScDocument::SetPrintEntireSheet( SCTAB nTab ) | |||
6316 | { | |||
6317 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab]) | |||
6318 | maTabs[nTab]->SetPrintEntireSheet(); | |||
6319 | } | |||
6320 | ||||
6321 | void ScDocument::SetRepeatColRange( SCTAB nTab, std::unique_ptr<ScRange> pNew ) | |||
6322 | { | |||
6323 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab]) | |||
6324 | maTabs[nTab]->SetRepeatColRange( std::move(pNew) ); | |||
6325 | } | |||
6326 | ||||
6327 | void ScDocument::SetRepeatRowRange( SCTAB nTab, std::unique_ptr<ScRange> pNew ) | |||
6328 | { | |||
6329 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab]) | |||
6330 | maTabs[nTab]->SetRepeatRowRange( std::move(pNew) ); | |||
6331 | } | |||
6332 | ||||
6333 | std::unique_ptr<ScPrintRangeSaver> ScDocument::CreatePrintRangeSaver() const | |||
6334 | { | |||
6335 | const SCTAB nCount = static_cast<SCTAB>(maTabs.size()); | |||
6336 | std::unique_ptr<ScPrintRangeSaver> pNew(new ScPrintRangeSaver( nCount )); | |||
6337 | for (SCTAB i=0; i<nCount; i++) | |||
6338 | if (maTabs[i]) | |||
6339 | maTabs[i]->FillPrintSaver( pNew->GetTabData(i) ); | |||
6340 | return pNew; | |||
6341 | } | |||
6342 | ||||
6343 | void ScDocument::RestorePrintRanges( const ScPrintRangeSaver& rSaver ) | |||
6344 | { | |||
6345 | const SCTAB nCount = rSaver.GetTabCount(); | |||
6346 | const SCTAB maxIndex = std::min(nCount, static_cast<SCTAB>(maTabs.size())); | |||
6347 | for (SCTAB i=0; i<maxIndex; i++) | |||
6348 | if (maTabs[i]) | |||
6349 | maTabs[i]->RestorePrintRanges( rSaver.GetTabData(i) ); | |||
6350 | } | |||
6351 | ||||
6352 | bool ScDocument::NeedPageResetAfterTab( SCTAB nTab ) const | |||
6353 | { | |||
6354 | // The page number count restarts at a sheet, if another template is set at | |||
6355 | // the preceding one (only compare names) and if a pagenumber is specified (not 0) | |||
6356 | ||||
6357 | if ( nTab + 1 < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab+1] ) | |||
6358 | { | |||
6359 | const OUString & rNew = maTabs[nTab+1]->GetPageStyle(); | |||
6360 | if ( rNew != maTabs[nTab]->GetPageStyle() ) | |||
6361 | { | |||
6362 | SfxStyleSheetBase* pStyle = mxPoolHelper->GetStylePool()->Find( rNew, SfxStyleFamily::Page ); | |||
6363 | if ( pStyle ) | |||
6364 | { | |||
6365 | const SfxItemSet& rSet = pStyle->GetItemSet(); | |||
6366 | sal_uInt16 nFirst = rSet.Get(ATTR_PAGE_FIRSTPAGENO).GetValue(); | |||
6367 | if ( nFirst != 0 ) | |||
6368 | return true; // Specify page number in new template | |||
6369 | } | |||
6370 | } | |||
6371 | } | |||
6372 | ||||
6373 | return false; // otherwise not | |||
6374 | } | |||
6375 | ||||
6376 | SfxUndoManager* ScDocument::GetUndoManager() | |||
6377 | { | |||
6378 | if (!mpUndoManager) | |||
6379 | { | |||
6380 | // to support enhanced text edit for draw objects, use an SdrUndoManager | |||
6381 | ScMutationGuard aGuard(*this, ScMutationGuardFlags::CORE); | |||
6382 | ||||
6383 | SdrUndoManager* pUndoManager = new SdrUndoManager; | |||
6384 | pUndoManager->SetDocShell(GetDocumentShell()); | |||
6385 | mpUndoManager = pUndoManager; | |||
6386 | } | |||
6387 | ||||
6388 | return mpUndoManager; | |||
6389 | } | |||
6390 | ||||
6391 | ScRowBreakIterator* ScDocument::GetRowBreakIterator(SCTAB nTab) const | |||
6392 | { | |||
6393 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab]) | |||
6394 | return new ScRowBreakIterator(maTabs[nTab]->maRowPageBreaks); | |||
6395 | return nullptr; | |||
6396 | } | |||
6397 | ||||
6398 | void ScDocument::AddSubTotalCell(ScFormulaCell* pCell) | |||
6399 | { | |||
6400 | maSubTotalCells.insert(pCell); | |||
6401 | } | |||
6402 | ||||
6403 | void ScDocument::RemoveSubTotalCell(ScFormulaCell* pCell) | |||
6404 | { | |||
6405 | maSubTotalCells.erase(pCell); | |||
6406 | } | |||
6407 | ||||
6408 | namespace { | |||
6409 | ||||
6410 | bool lcl_hasDirtyRange(const ScDocument& rDoc, ScFormulaCell* pCell, const ScRange& rDirtyRange) | |||
6411 | { | |||
6412 | ScDetectiveRefIter aRefIter(rDoc, pCell); | |||
6413 | ScRange aRange; | |||
6414 | while (aRefIter.GetNextRef(aRange)) | |||
6415 | { | |||
6416 | if (aRange.Intersects(rDirtyRange)) | |||
6417 | return true; | |||
6418 | } | |||
6419 | return false; | |||
6420 | } | |||
6421 | ||||
6422 | } | |||
6423 | ||||
6424 | void ScDocument::SetSubTotalCellsDirty(const ScRange& rDirtyRange) | |||
6425 | { | |||
6426 | // to update the list by skipping cells that no longer contain subtotal function. | |||
6427 | set<ScFormulaCell*> aNewSet; | |||
6428 | ||||
6429 | bool bOldRecalc = GetAutoCalc(); | |||
6430 | SetAutoCalc(false); | |||
6431 | for (ScFormulaCell* pCell : maSubTotalCells) | |||
6432 | { | |||
6433 | if (pCell->IsSubTotal()) | |||
6434 | { | |||
6435 | aNewSet.insert(pCell); | |||
6436 | if (lcl_hasDirtyRange(*this, pCell, rDirtyRange)) | |||
6437 | pCell->SetDirty(); | |||
6438 | } | |||
6439 | } | |||
6440 | ||||
6441 | SetAutoCalc(bOldRecalc); | |||
6442 | maSubTotalCells.swap(aNewSet); // update the list. | |||
6443 | } | |||
6444 | ||||
6445 | sal_uInt16 ScDocument::GetTextWidth( const ScAddress& rPos ) const | |||
6446 | { | |||
6447 | SCTAB nTab = rPos.Tab(); | |||
6448 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab]) | |||
6449 | return maTabs[nTab]->GetTextWidth(rPos.Col(), rPos.Row()); | |||
6450 | ||||
6451 | return 0; | |||
6452 | } | |||
6453 | ||||
6454 | SvtScriptType ScDocument::GetScriptType( const ScAddress& rPos ) const | |||
6455 | { | |||
6456 | SCTAB nTab = rPos.Tab(); | |||
6457 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab]) | |||
6458 | return maTabs[nTab]->GetScriptType(rPos.Col(), rPos.Row()); | |||
6459 | ||||
6460 | return SvtScriptType::NONE; | |||
6461 | } | |||
6462 | ||||
6463 | void ScDocument::SetScriptType( const ScAddress& rPos, SvtScriptType nType ) | |||
6464 | { | |||
6465 | SCTAB nTab = rPos.Tab(); | |||
6466 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab]) | |||
6467 | maTabs[nTab]->SetScriptType(rPos.Col(), rPos.Row(), nType); | |||
6468 | } | |||
6469 | ||||
6470 | void ScDocument::EnableUndo( bool bVal ) | |||
6471 | { | |||
6472 | // The undo manager increases lock count every time undo is disabled. | |||
6473 | // Because of this, we shouldn't disable undo unless it's currently | |||
6474 | // enabled, or else re-enabling it may not actually re-enable undo unless | |||
6475 | // the lock count becomes zero. | |||
6476 | ||||
6477 | if (bVal != GetUndoManager()->IsUndoEnabled()) | |||
6478 | { | |||
6479 | GetUndoManager()->EnableUndo(bVal); | |||
6480 | if( mpDrawLayer ) mpDrawLayer->EnableUndo(bVal); | |||
6481 | } | |||
6482 | ||||
6483 | mbUndoEnabled = bVal; | |||
6484 | } | |||
6485 | ||||
6486 | void ScDocument::EnableUserInteraction( bool bVal ) | |||
6487 | { | |||
6488 | mbUserInteractionEnabled = bVal; | |||
6489 | } | |||
6490 | ||||
6491 | bool ScDocument::IsInVBAMode() const | |||
6492 | { | |||
6493 | if (!mpShell) | |||
6494 | return false; | |||
6495 | ||||
6496 | try | |||
6497 | { | |||
6498 | uno::Reference<script::vba::XVBACompatibility> xVBA( | |||
6499 | mpShell->GetBasicContainer(), uno::UNO_QUERY); | |||
6500 | ||||
6501 | return xVBA.is() && xVBA->getVBACompatibilityMode(); | |||
6502 | } | |||
6503 | catch (const lang::NotInitializedException&) {} | |||
6504 | ||||
6505 | return false; | |||
6506 | } | |||
6507 | ||||
6508 | ScPostIt* ScDocument::GetNote(const ScAddress& rPos) | |||
6509 | { | |||
6510 | return GetNote(rPos.Col(), rPos.Row(), rPos.Tab()); | |||
6511 | } | |||
6512 | ||||
6513 | ScPostIt* ScDocument::GetNote(SCCOL nCol, SCROW nRow, SCTAB nTab) | |||
6514 | { | |||
6515 | if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && | |||
6516 | nCol < maTabs[nTab]->GetAllocatedColumnsCount()) | |||
6517 | return maTabs[nTab]->aCol[nCol].GetCellNote(nRow); | |||
6518 | else | |||
6519 | return nullptr; | |||
6520 | ||||
6521 | } | |||
6522 | ||||
6523 | void ScDocument::SetNote(const ScAddress& rPos, std::unique_ptr<ScPostIt> pNote) | |||
6524 | { | |||
6525 | return SetNote(rPos.Col(), rPos.Row(), rPos.Tab(), std::move(pNote)); | |||
6526 | } | |||
6527 | ||||
6528 | void ScDocument::SetNote(SCCOL nCol, SCROW nRow, SCTAB nTab, std::unique_ptr<ScPostIt> pNote) | |||
6529 | { | |||
6530 | return maTabs[nTab]->CreateColumnIfNotExists(nCol).SetCellNote(nRow, std::move(pNote)); | |||
6531 | } | |||
6532 | ||||
6533 | bool ScDocument::HasNote(const ScAddress& rPos) const | |||
6534 | { | |||
6535 | return HasNote(rPos.Col(), rPos.Row(), rPos.Tab()); | |||
6536 | } | |||
6537 | ||||
6538 | bool ScDocument::HasNote(SCCOL nCol, SCROW nRow, SCTAB nTab) const | |||
6539 | { | |||
6540 | if (!ValidColRow(nCol, nRow)) | |||
6541 | return false; | |||
6542 | ||||
6543 | const ScTable* pTab = FetchTable(nTab); | |||
6544 | if (!pTab) | |||
6545 | return false; | |||
6546 | ||||
6547 | if (nCol >= pTab->GetAllocatedColumnsCount()) | |||
6548 | return false; | |||
6549 | ||||
6550 | const ScPostIt* pNote = pTab->aCol[nCol].GetCellNote(nRow); | |||
6551 | return pNote != nullptr; | |||
6552 | } | |||
6553 | ||||
6554 | bool ScDocument::HasColNotes(SCCOL nCol, SCTAB nTab) const | |||
6555 | { | |||
6556 | if (!ValidCol(nCol)) | |||
6557 | return false; | |||
6558 | ||||
6559 | const ScTable* pTab = FetchTable(nTab); | |||
6560 | if (!pTab) | |||
6561 | return false; | |||
6562 | ||||
6563 | return pTab->aCol[nCol].HasCellNotes(); | |||
6564 | } | |||
6565 | ||||
6566 | bool ScDocument::HasTabNotes(SCTAB nTab) const | |||
6567 | { | |||
6568 | const ScTable* pTab = FetchTable(nTab); | |||
6569 | ||||
6570 | if ( !pTab ) | |||
6571 | return false; | |||
6572 | ||||
6573 | for (SCCOL nCol=0, nColSize = pTab->aCol.size(); nCol < nColSize; ++nCol) | |||
6574 | if ( HasColNotes(nCol, nTab) ) | |||
6575 | return true; | |||
6576 | ||||
6577 | return false; | |||
6578 | } | |||
6579 | ||||
6580 | bool ScDocument::HasNotes() const | |||
6581 | { | |||
6582 | for (SCTAB i = 0; i <= MAXTAB; ++i) | |||
6583 | { | |||
6584 | if (HasTabNotes(i)) | |||
6585 | return true; | |||
6586 | } | |||
6587 | return false; | |||
6588 | } | |||
6589 | ||||
6590 | std::unique_ptr<ScPostIt> ScDocument::ReleaseNote(const ScAddress& rPos) | |||
6591 | { | |||
6592 | ScTable* pTab = FetchTable(rPos.Tab()); | |||
6593 | if (!pTab) | |||
6594 | return nullptr; | |||
6595 | ||||
6596 | return pTab->ReleaseNote(rPos.Col(), rPos.Row()); | |||
6597 | } | |||
6598 | ||||
6599 | ScPostIt* ScDocument::GetOrCreateNote(const ScAddress& rPos) | |||
6600 | { | |||
6601 | if (HasNote(rPos)) | |||
6602 | return GetNote(rPos); | |||
6603 | else | |||
6604 | return CreateNote(rPos); | |||
6605 | } | |||
6606 | ScPostIt* ScDocument::CreateNote(const ScAddress& rPos) | |||
6607 | { | |||
6608 | ScPostIt* pPostIt = new ScPostIt(*this, rPos); | |||
6609 | SetNote(rPos, std::unique_ptr<ScPostIt>(pPostIt)); | |||
6610 | return pPostIt; | |||
6611 | } | |||
6612 | ||||
6613 | size_t ScDocument::GetNoteCount( SCTAB nTab, SCCOL nCol ) const | |||
6614 | { | |||
6615 | const ScTable* pTab = FetchTable(nTab); | |||
6616 | if (!pTab) | |||
6617 | return 0; | |||
6618 | ||||
6619 | return pTab->GetNoteCount(nCol); | |||
6620 | } | |||
6621 | ||||
6622 | void ScDocument::CreateAllNoteCaptions() | |||
6623 | { | |||
6624 | for (const auto& a : maTabs) | |||
6625 | { | |||
6626 | if (a) | |||
6627 | a->CreateAllNoteCaptions(); | |||
6628 | } | |||
6629 | } | |||
6630 | ||||
6631 | void ScDocument::ForgetNoteCaptions( const ScRangeList& rRanges, bool bPreserveData ) | |||
6632 | { | |||
6633 | for (size_t i = 0, n = rRanges.size(); i < n; ++i) | |||
6634 | { | |||
6635 | const ScRange & rRange = rRanges[i]; | |||
6636 | const ScAddress& s = rRange.aStart; | |||
6637 | const ScAddress& e = rRange.aEnd; | |||
6638 | for (SCTAB nTab = s.Tab(); nTab <= e.Tab(); ++nTab) | |||
6639 | { | |||
6640 | ScTable* pTab = FetchTable(nTab); | |||
6641 | if (!pTab) | |||
6642 | continue; | |||
6643 | ||||
6644 | pTab->ForgetNoteCaptions(s.Col(), s.Row(), e.Col(), e.Row(), bPreserveData); | |||
6645 | } | |||
6646 | } | |||
6647 | } | |||
6648 | ||||
6649 | CommentCaptionState ScDocument::GetAllNoteCaptionsState( const ScRangeList& rRanges ) | |||
6650 | { | |||
6651 | CommentCaptionState aTmpState = CommentCaptionState::ALLHIDDEN; | |||
6652 | CommentCaptionState aState = CommentCaptionState::ALLHIDDEN; | |||
6653 | bool bFirstControl = true; | |||
6654 | std::vector<sc::NoteEntry> aNotes; | |||
6655 | ||||
6656 | for (size_t i = 0, n = rRanges.size(); i < n; ++i) | |||
6657 | { | |||
6658 | const ScRange & rRange = rRanges[i]; | |||
6659 | ||||
6660 | for( SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); ++nTab ) | |||
6661 | { | |||
6662 | aState = maTabs[nTab]->GetAllNoteCaptionsState( rRange, aNotes ); | |||
6663 | ||||
6664 | if (aState == CommentCaptionState::MIXED) | |||
6665 | return aState; | |||
6666 | ||||
6667 | if (bFirstControl) // it is possible that a range is ALLSHOWN, another range is ALLHIDDEN, | |||
6668 | { // we have to detect that situation as mixed. | |||
6669 | aTmpState = aState; | |||
6670 | bFirstControl = false; | |||
6671 | } | |||
6672 | else if(aTmpState != aState) | |||
6673 | { | |||
6674 | aState = CommentCaptionState::MIXED; | |||
6675 | return aState; | |||
6676 | } | |||
6677 | } | |||
6678 | } | |||
6679 | return aState; | |||
6680 | } | |||
6681 | ||||
6682 | ScAddress ScDocument::GetNotePosition( size_t nIndex ) const | |||
6683 | { | |||
6684 | for (size_t nTab = 0; nTab < maTabs.size(); ++nTab) | |||
6685 | { | |||
6686 | for (SCCOL nCol : GetColumnsRange(nTab, 0, MaxCol())) | |||
6687 | { | |||
6688 | size_t nColNoteCount = GetNoteCount(nTab, nCol); | |||
6689 | if (!nColNoteCount) | |||
6690 | continue; | |||
6691 | ||||
6692 | if (nIndex >= nColNoteCount) | |||
6693 | { | |||
6694 | nIndex -= nColNoteCount; | |||
6695 | continue; | |||
6696 | } | |||
6697 | ||||
6698 | SCROW nRow = GetNotePosition(nTab, nCol, nIndex); | |||
6699 | if (nRow >= 0) | |||
6700 | return ScAddress(nCol, nRow, nTab); | |||
6701 | ||||
6702 | OSL_FAIL("note not found")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "6702" ": "), "%s", "note not found"); } } while (false); | |||
6703 | return ScAddress::INITIALIZE_INVALID; | |||
6704 | } | |||
6705 | } | |||
6706 | ||||
6707 | OSL_FAIL("note not found")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "6707" ": "), "%s", "note not found"); } } while (false); | |||
6708 | return ScAddress::INITIALIZE_INVALID; | |||
6709 | } | |||
6710 | ||||
6711 | ScAddress ScDocument::GetNotePosition( size_t nIndex, SCTAB nTab ) const | |||
6712 | { | |||
6713 | for (SCCOL nCol : GetColumnsRange(nTab, 0, MaxCol())) | |||
6714 | { | |||
6715 | size_t nColNoteCount = GetNoteCount(nTab, nCol); | |||
6716 | if (!nColNoteCount) | |||
6717 | continue; | |||
6718 | ||||
6719 | if (nIndex >= nColNoteCount) | |||
6720 | { | |||
6721 | nIndex -= nColNoteCount; | |||
6722 | continue; | |||
6723 | } | |||
6724 | ||||
6725 | SCROW nRow = GetNotePosition(nTab, nCol, nIndex); | |||
6726 | if (nRow >= 0) | |||
6727 | return ScAddress(nCol, nRow, nTab); | |||
6728 | ||||
6729 | OSL_FAIL("note not found")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "6729" ": "), "%s", "note not found"); } } while (false); | |||
6730 | return ScAddress::INITIALIZE_INVALID; | |||
6731 | } | |||
6732 | ||||
6733 | OSL_FAIL("note not found")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" ":" "6733" ": "), "%s", "note not found"); } } while (false); | |||
6734 | return ScAddress::INITIALIZE_INVALID; | |||
6735 | } | |||
6736 | ||||
6737 | SCROW ScDocument::GetNotePosition( SCTAB nTab, SCCOL nCol, size_t nIndex ) const | |||
6738 | { | |||
6739 | const ScTable* pTab = FetchTable(nTab); | |||
6740 | if (!pTab) | |||
6741 | return -1; | |||
6742 | ||||
6743 | return pTab->GetNotePosition(nCol, nIndex); | |||
6744 | } | |||
6745 | ||||
6746 | void ScDocument::GetAllNoteEntries( std::vector<sc::NoteEntry>& rNotes ) const | |||
6747 | { | |||
6748 | for (const auto & pTab : maTabs) | |||
6749 | { | |||
6750 | if (!pTab) | |||
6751 | continue; | |||
6752 | ||||
6753 | pTab->GetAllNoteEntries(rNotes); | |||
6754 | } | |||
6755 | } | |||
6756 | ||||
6757 | void ScDocument::GetAllNoteEntries( SCTAB nTab, std::vector<sc::NoteEntry>& rNotes ) const | |||
6758 | { | |||
6759 | const ScTable* pTab = FetchTable(nTab); | |||
6760 | if (!pTab) | |||
6761 | return; | |||
6762 | ||||
6763 | return pTab->GetAllNoteEntries( rNotes ); | |||
6764 | } | |||
6765 | ||||
6766 | void ScDocument::GetNotesInRange( const ScRangeList& rRangeList, std::vector<sc::NoteEntry>& rNotes ) const | |||
6767 | { | |||
6768 | for( size_t i = 0; i < rRangeList.size(); ++i) | |||
6769 | { | |||
6770 | const ScRange & rRange = rRangeList[i]; | |||
6771 | for( SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); ++nTab ) | |||
6772 | { | |||
6773 | maTabs[nTab]->GetNotesInRange( rRange, rNotes ); | |||
6774 | } | |||
6775 | } | |||
6776 | } | |||
6777 | ||||
6778 | void ScDocument::GetUnprotectedCells( ScRangeList& rRangeList, SCTAB nTab ) const | |||
6779 | { | |||
6780 | maTabs[nTab]->GetUnprotectedCells( rRangeList ); | |||
6781 | } | |||
6782 | ||||
6783 | bool ScDocument::ContainsNotesInRange( const ScRangeList& rRangeList ) const | |||
6784 | { | |||
6785 | for( size_t i = 0; i < rRangeList.size(); ++i) | |||
6786 | { | |||
6787 | const ScRange & rRange = rRangeList[i]; | |||
6788 | for( SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); ++nTab ) | |||
6789 | { | |||
6790 | bool bContainsNote = maTabs[nTab]->ContainsNotesInRange( rRange ); | |||
6791 | if(bContainsNote) | |||
6792 | return true; | |||
6793 | } | |||
6794 | } | |||
6795 | ||||
6796 | return false; | |||
6797 | } | |||
6798 | ||||
6799 | void ScDocument::SetAutoNameCache( std::unique_ptr<ScAutoNameCache> pCache ) | |||
6800 | { | |||
6801 | pAutoNameCache = std::move(pCache); | |||
6802 | } | |||
6803 | ||||
6804 | thread_local ScDocumentThreadSpecific ScDocument::maThreadSpecific; | |||
6805 | ||||
6806 | ScRecursionHelper& ScDocument::GetRecursionHelper() | |||
6807 | { | |||
6808 | if (!IsThreadedGroupCalcInProgress()) | |||
6809 | { | |||
6810 | if (!maNonThreaded.xRecursionHelper) | |||
6811 | maNonThreaded.xRecursionHelper = std::make_unique<ScRecursionHelper>(); | |||
6812 | return *maNonThreaded.xRecursionHelper; | |||
6813 | } | |||
6814 | else | |||
6815 | { | |||
6816 | if (!maThreadSpecific.xRecursionHelper) | |||
6817 | maThreadSpecific.xRecursionHelper = std::make_unique<ScRecursionHelper>(); | |||
6818 | return *maThreadSpecific.xRecursionHelper; | |||
6819 | } | |||
6820 | } | |||
6821 | ||||
6822 | void ScDocumentThreadSpecific::SetupFromNonThreadedData(const ScDocumentThreadSpecific& /*rNonThreadedData*/) | |||
6823 | { | |||
6824 | // What about the recursion helper? | |||
6825 | // Copy the lookup cache? | |||
6826 | } | |||
6827 | ||||
6828 | void ScDocumentThreadSpecific::MergeBackIntoNonThreadedData(ScDocumentThreadSpecific& /*rNonThreadedData*/) | |||
6829 | { | |||
6830 | // What about recursion helper and lookup cache? | |||
6831 | } | |||
6832 | ||||
6833 | ScDocumentThreadSpecific::ScDocumentThreadSpecific() | |||
6834 | : pContext(nullptr) | |||
6835 | {} | |||
6836 | ||||
6837 | ScDocumentThreadSpecific::~ScDocumentThreadSpecific() {} | |||
6838 | ||||
6839 | void ScDocument::SetupFromNonThreadedContext(ScInterpreterContext& /*threadedContext*/, int /*threadNumber*/) | |||
6840 | { | |||
6841 | // lookup cache is now only in pooled ScInterpreterContext's | |||
6842 | } | |||
6843 | ||||
6844 | void ScDocument::MergeBackIntoNonThreadedContext(ScInterpreterContext& threadedContext, int /*threadNumber*/) | |||
6845 | { | |||
6846 | // Move data from a context used by a calculation thread to the main thread's context. | |||
6847 | // Called from the main thread after the calculation thread has already finished. | |||
6848 | assert(!IsThreadedGroupCalcInProgress())(static_cast <bool> (!IsThreadedGroupCalcInProgress()) ? void (0) : __assert_fail ("!IsThreadedGroupCalcInProgress()" , "/home/maarten/src/libreoffice/core/sc/source/core/data/document.cxx" , 6848, __extension__ __PRETTY_FUNCTION__)); | |||
6849 | maInterpreterContext.maDelayedSetNumberFormat.insert( | |||
6850 | maInterpreterContext.maDelayedSetNumberFormat.end(), | |||
6851 | std::make_move_iterator(threadedContext.maDelayedSetNumberFormat.begin()), | |||
6852 | std::make_move_iterator(threadedContext.maDelayedSetNumberFormat.end())); | |||
6853 | // lookup cache is now only in pooled ScInterpreterContext's | |||
6854 | } | |||
6855 | ||||
6856 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |