1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #ifndef INCLUDED_RECURSIONHELPER_HXX 29 #define INCLUDED_RECURSIONHELPER_HXX 30 31 #include "formularesult.hxx" 32 33 #include <list> 34 #include <stack> 35 #include <tools/solar.h> 36 37 class ScFormulaCell; 38 39 struct ScFormulaRecursionEntry 40 { 41 ScFormulaCell* pCell; 42 sal_Bool bOldRunning; 43 ScFormulaResult aPreviousResult; 44 ScFormulaRecursionEntry( ScFormulaCell* p, sal_Bool bR, 45 const ScFormulaResult & rRes ) : 46 pCell(p), bOldRunning(bR), aPreviousResult( rRes) 47 { 48 } 49 }; 50 51 typedef ::std::list< ScFormulaRecursionEntry > ScFormulaRecursionList; 52 53 class ScRecursionHelper 54 { 55 typedef ::std::stack< ScFormulaCell* > ScRecursionInIterationStack; 56 ScFormulaRecursionList aRecursionFormulas; 57 ScFormulaRecursionList::iterator aInsertPos; 58 ScFormulaRecursionList::iterator aLastIterationStart; 59 ScRecursionInIterationStack aRecursionInIterationStack; 60 sal_uInt16 nRecursionCount; 61 sal_uInt16 nIteration; 62 bool bInRecursionReturn; 63 bool bDoingRecursion; 64 bool bInIterationReturn; 65 bool bConverging; 66 67 void Init() 68 { 69 nRecursionCount = 0; 70 bInRecursionReturn = bDoingRecursion = bInIterationReturn = false; 71 aInsertPos = GetEnd(); 72 ResetIteration(); 73 } 74 void ResetIteration() 75 { 76 aLastIterationStart = GetEnd(); 77 nIteration = 0; 78 bConverging = false; 79 } 80 81 public: 82 83 ScRecursionHelper() { Init(); } 84 sal_uInt16 GetRecursionCount() const { return nRecursionCount; } 85 void IncRecursionCount() { ++nRecursionCount; } 86 void DecRecursionCount() { --nRecursionCount; } 87 /// A pure recursion return, no iteration. 88 bool IsInRecursionReturn() const { return bInRecursionReturn && 89 !bInIterationReturn; } 90 void SetInRecursionReturn( bool b ) 91 { 92 // Do not use IsInRecursionReturn() here, it decouples iteration. 93 if (b && !bInRecursionReturn) 94 aInsertPos = aRecursionFormulas.begin(); 95 bInRecursionReturn = b; 96 } 97 bool IsDoingRecursion() const { return bDoingRecursion; } 98 void SetDoingRecursion( bool b ) { bDoingRecursion = b; } 99 void Insert( ScFormulaCell* p, sal_Bool bOldRunning, 100 const ScFormulaResult & rRes ) 101 { 102 aRecursionFormulas.insert( aInsertPos, ScFormulaRecursionEntry( p, 103 bOldRunning, rRes)); 104 } 105 ScFormulaRecursionList::iterator GetStart() 106 { 107 return aRecursionFormulas.begin(); 108 } 109 ScFormulaRecursionList::iterator GetEnd() 110 { 111 return aRecursionFormulas.end(); 112 } 113 bool IsInIterationReturn() const { return bInIterationReturn; } 114 void SetInIterationReturn( bool b ) 115 { 116 // An iteration return is always coupled to a recursion return. 117 SetInRecursionReturn( b); 118 bInIterationReturn = b; 119 } 120 bool IsDoingIteration() const { return nIteration > 0; } 121 sal_uInt16 GetIteration() const { return nIteration; } 122 bool & GetConvergingReference() { return bConverging; } 123 void StartIteration() 124 { 125 SetInIterationReturn( false); 126 nIteration = 1; 127 bConverging = false; 128 aLastIterationStart = GetIterationStart(); 129 } 130 void ResumeIteration() 131 { 132 SetInIterationReturn( false); 133 aLastIterationStart = GetIterationStart(); 134 } 135 void IncIteration() { ++nIteration; } 136 void EndIteration() 137 { 138 aRecursionFormulas.erase( GetIterationStart(), GetIterationEnd()); 139 ResetIteration(); 140 } 141 ScFormulaRecursionList::iterator GetLastIterationStart() { return aLastIterationStart; } 142 ScFormulaRecursionList::iterator GetIterationStart() { return GetStart(); } 143 ScFormulaRecursionList::iterator GetIterationEnd() { return GetEnd(); } 144 /** Any return, recursion or iteration, iteration is always coupled with 145 recursion. */ 146 bool IsInReturn() const { return bInRecursionReturn; } 147 const ScFormulaRecursionList& GetList() const { return aRecursionFormulas; } 148 ScFormulaRecursionList& GetList() { return aRecursionFormulas; } 149 ScRecursionInIterationStack& GetRecursionInIterationStack() { return aRecursionInIterationStack; } 150 void Clear() 151 { 152 aRecursionFormulas.clear(); 153 while (!aRecursionInIterationStack.empty()) 154 aRecursionInIterationStack.pop(); 155 Init(); 156 } 157 }; 158 159 #endif // INCLUDED_RECURSIONHELPER_HXX 160