Avoid potential negative array index access to cached text.
[LibreOffice.git] / sc / source / core / tool / progress.cxx
blobae0b99b32f48ab5a253ccfc31eb4b4ff2dca226c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sfx2/app.hxx>
21 #include <sfx2/objsh.hxx>
22 #include <sfx2/progress.hxx>
23 #include <sfx2/docfile.hxx>
24 #include <sfx2/sfxsids.hrc>
25 #include <svl/eitem.hxx>
26 #include <svl/itemset.hxx>
27 #include <osl/diagnose.h>
29 #include <com/sun/star/frame/XModel.hpp>
31 #define SC_PROGRESS_CXX
32 #include <progress.hxx>
33 #include <document.hxx>
34 #include <docsh.hxx>
35 #include <globstr.hrc>
36 #include <scresid.hxx>
38 using namespace com::sun::star;
40 static ScProgress theDummyInterpretProgress;
41 SfxProgress* ScProgress::pGlobalProgress = nullptr;
42 sal_uInt64 ScProgress::nGlobalRange = 0;
43 sal_uInt64 ScProgress::nGlobalPercent = 0;
44 ScProgress* ScProgress::pInterpretProgress = &theDummyInterpretProgress;
45 sal_uInt64 ScProgress::nInterpretProgress = 0;
46 ScDocument* ScProgress::pInterpretDoc;
47 bool ScProgress::bIdleWasEnabled = false;
49 static bool lcl_IsHiddenDocument( const SfxObjectShell* pObjSh )
51 if (pObjSh)
53 SfxMedium* pMed = pObjSh->GetMedium();
54 if (pMed)
56 if (const SfxBoolItem* pItem = pMed->GetItemSet().GetItemIfSet(SID_HIDDEN);
57 pItem && pItem->GetValue())
58 return true;
61 return false;
64 static bool lcl_HasControllersLocked( const SfxObjectShell& rObjSh )
66 uno::Reference<frame::XModel> xModel( rObjSh.GetBaseModel() );
67 if (xModel.is())
68 return xModel->hasControllersLocked();
69 return false;
72 ScProgress::ScProgress(SfxObjectShell* pObjSh, const OUString& rText,
73 sal_uInt64 nRange, bool bWait)
74 : bEnabled(true)
77 if ( pGlobalProgress || SfxProgress::GetActiveProgress() )
79 if ( lcl_IsHiddenDocument(pObjSh) )
81 // loading a hidden document while a progress is active is possible - no error
82 pProgress = nullptr;
84 else
86 OSL_FAIL( "ScProgress: there can be only one!" );
87 pProgress = nullptr;
90 else if ( SfxGetpApp()->IsDowning() )
92 // This happens. E.g. when saving the clipboard-content as OLE when closing the app.
93 // In this case a SfxProgress would produce dirt in memory.
94 //TODO: Should that be this way ???
96 pProgress = nullptr;
98 else if ( pObjSh && ( pObjSh->GetCreateMode() == SfxObjectCreateMode::EMBEDDED ||
99 pObjSh->GetProgress() ||
100 lcl_HasControllersLocked(*pObjSh) ) )
102 // no own progress for embedded objects,
103 // no second progress if the document already has one
105 pProgress = nullptr;
107 else
109 pProgress.reset(new SfxProgress( pObjSh, rText, nRange, bWait ));
110 pGlobalProgress = pProgress.get();
111 nGlobalRange = nRange;
112 nGlobalPercent = 0;
116 ScProgress::ScProgress()
117 : bEnabled(true)
119 // DummyInterpret
122 ScProgress::~ScProgress()
124 if ( pProgress )
126 pProgress.reset();
127 pGlobalProgress = nullptr;
128 nGlobalRange = 0;
129 nGlobalPercent = 0;
133 void ScProgress::CreateInterpretProgress( ScDocument* pDoc, bool bWait )
135 if ( nInterpretProgress )
136 nInterpretProgress++;
137 else if ( pDoc->GetAutoCalc() )
139 nInterpretProgress = 1;
140 bIdleWasEnabled = pDoc->IsIdleEnabled();
141 pDoc->EnableIdle(false);
142 // Interpreter may be called in many circumstances, also if another
143 // progress bar is active, for example while adapting row heights.
144 // Keep the dummy interpret progress.
145 if ( !pGlobalProgress )
146 pInterpretProgress = new ScProgress( pDoc->GetDocumentShell(),
147 ScResId( STR_PROGRESS_CALCULATING ),
148 pDoc->GetFormulaCodeInTree()/MIN_NO_CODES_PER_PROGRESS_UPDATE, bWait );
149 pInterpretDoc = pDoc;
153 void ScProgress::DeleteInterpretProgress()
155 if ( !nInterpretProgress )
156 return;
158 /* Do not decrement 'nInterpretProgress', before 'pInterpretProgress'
159 is deleted. In rare cases, deletion of 'pInterpretProgress' causes
160 a refresh of the sheet window which may call CreateInterpretProgress
161 and DeleteInterpretProgress again (from Output::DrawStrings),
162 resulting in double deletion of 'pInterpretProgress'. */
163 if ( nInterpretProgress == 1 )
165 if ( pInterpretProgress != &theDummyInterpretProgress )
167 // move pointer to local temporary to avoid double deletion
168 ScProgress* pTmpProgress = pInterpretProgress;
169 pInterpretProgress = &theDummyInterpretProgress;
170 delete pTmpProgress;
172 if ( pInterpretDoc )
173 pInterpretDoc->EnableIdle(bIdleWasEnabled);
175 --nInterpretProgress;
178 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */