summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/com/android/calculator2/Calculator.java5
-rw-r--r--src/com/android/calculator2/CalculatorExpr.java11
-rw-r--r--src/com/android/calculator2/CalculatorResult.java5
-rw-r--r--src/com/android/calculator2/Evaluator.java95
4 files changed, 73 insertions, 43 deletions
diff --git a/src/com/android/calculator2/Calculator.java b/src/com/android/calculator2/Calculator.java
index 5019fdf..39cb9de 100644
--- a/src/com/android/calculator2/Calculator.java
+++ b/src/com/android/calculator2/Calculator.java
@@ -731,8 +731,7 @@ public class Calculator extends Activity
private void removeHistoryFragment() {
final FragmentManager manager = getFragmentManager();
if (manager != null && !manager.isDestroyed()) {
- manager.popBackStackImmediate(HistoryFragment.TAG,
- FragmentManager.POP_BACK_STACK_INCLUSIVE);
+ manager.popBackStack(HistoryFragment.TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
// When HistoryFragment is hidden, the main Calculator is important for accessibility again.
@@ -1175,7 +1174,7 @@ public class Calculator extends Activity
mEvaluator.represerve();
} else {
// Add current result to history.
- mEvaluator.preserve(true);
+ mEvaluator.preserve(Evaluator.MAIN_INDEX, true);
}
if (animate) {
diff --git a/src/com/android/calculator2/CalculatorExpr.java b/src/com/android/calculator2/CalculatorExpr.java
index 18bb6cf..75ab1c9 100644
--- a/src/com/android/calculator2/CalculatorExpr.java
+++ b/src/com/android/calculator2/CalculatorExpr.java
@@ -373,7 +373,16 @@ class CalculatorExpr {
case CONSTANT:
return new Constant(in);
case PRE_EVAL:
- return new PreEval(in);
+ PreEval pe = new PreEval(in);
+ if (pe.mIndex == -1) {
+ // Database corrupted by earlier bug.
+ // Return a conspicuously wrong placeholder that won't lead to a crash.
+ Constant result = new Constant();
+ result.add(R.id.dec_point);
+ return result;
+ } else {
+ return pe;
+ }
default: throw new IOException("Bad save file format");
}
} else {
diff --git a/src/com/android/calculator2/CalculatorResult.java b/src/com/android/calculator2/CalculatorResult.java
index a8ab291..1eede10 100644
--- a/src/com/android/calculator2/CalculatorResult.java
+++ b/src/com/android/calculator2/CalculatorResult.java
@@ -64,8 +64,7 @@ public class CalculatorResult extends AlignedTextView implements MenuItem.OnMenu
private boolean mScrollable = false;
// A scrollable result is currently displayed.
private boolean mValid = false;
- // The result holds something valid; either a a number or an error
- // message.
+ // The result holds a valid number (not an error message).
// A suffix of "Pos" denotes a pixel offset. Zero represents a scroll position
// in which the decimal point is just barely visible on the right of the display.
private int mCurrentPos;// Position of right of display relative to decimal point, in pixels.
@@ -596,7 +595,7 @@ public class CalculatorResult extends AlignedTextView implements MenuItem.OnMenu
@Override
public void onError(long index, int resourceId) {
mStoreToMemoryRequested = false;
- mValid = true;
+ mValid = false;
setLongClickable(false);
mScrollable = false;
final String msg = getContext().getString(resourceId);
diff --git a/src/com/android/calculator2/Evaluator.java b/src/com/android/calculator2/Evaluator.java
index 7add5b5..ea6d8ff 100644
--- a/src/com/android/calculator2/Evaluator.java
+++ b/src/com/android/calculator2/Evaluator.java
@@ -352,10 +352,10 @@ public class Evaluator implements CalculatorExpr.ExprResolver {
mMainExpr.mDegreeMode = mSharedPrefs.getBoolean(KEY_PREF_DEGREE_MODE, false);
long savedIndex = mSharedPrefs.getLong(KEY_PREF_SAVED_INDEX, 0L);
long memoryIndex = mSharedPrefs.getLong(KEY_PREF_MEMORY_INDEX, 0L);
- if (savedIndex != 0) {
+ if (savedIndex != 0 && savedIndex != -1 /* Recover from old corruption */) {
setSavedIndexWhenEvaluated(savedIndex);
}
- if (memoryIndex != 0) {
+ if (memoryIndex != 0 && memoryIndex != -1) {
setMemoryIndexWhenEvaluated(memoryIndex, false /* no need to persist again */);
}
mSavedName = mSharedPrefs.getString(KEY_PREF_SAVED_NAME, "none");
@@ -392,6 +392,13 @@ public class Evaluator implements CalculatorExpr.ExprResolver {
}
/**
+ * Does the expression index refer to a transient and mutable expression?
+ */
+ private boolean isMutableIndex(long index) {
+ return index == MAIN_INDEX || index == HISTORY_MAIN_INDEX;
+ }
+
+ /**
* Result of initial asynchronous result computation.
* Represents either an error or a result computed to an initial evaluation precision.
*/
@@ -1416,35 +1423,37 @@ public class Evaluator implements CalculatorExpr.ExprResolver {
* index1 should correspond to an immutable expression, and should thus NOT
* be MAIN_INDEX. Index2 may be MAIN_INDEX. Both expressions are presumed
* to have been evaluated. The result is unevaluated.
+ * Can return null if evaluation resulted in an error (a very unlikely case).
*/
private ExprInfo sum(long index1, long index2) {
- ExprInfo expr1 = mExprs.get(index1);
- ExprInfo expr2 = mExprs.get(index2);
- // TODO: Consider not collapsing expr2, to save database space.
- // Note that this is a bit tricky, since our expressions can contain unbalanced lparens.
- CalculatorExpr result = new CalculatorExpr();
- result.append(getCollapsedExpr(index1));
- result.add(R.id.op_add);
- result.append(getCollapsedExpr(index2));
- ExprInfo resultEi = new ExprInfo(result, false /* dont care about degrees/radians */);
- resultEi.mLongTimeout = expr1.mLongTimeout || expr2.mLongTimeout;
- return resultEi;
+ return generalized_sum(index1, index2, R.id.op_add);
}
/**
* Return an ExprInfo corresponding to the subtraction of the value at the subtrahend index
* from value at the minuend index (minuend - subtrahend = result). Both are presumed to have
- * been previously evaluated. The result is unevaluated.
+ * been previously evaluated. The result is unevaluated. Can return null.
*/
private ExprInfo difference(long minuendIndex, long subtrahendIndex) {
- final CalculatorExpr resultExpr = new CalculatorExpr();
- resultExpr.append(getCollapsedExpr(minuendIndex));
- resultExpr.add(R.id.op_sub);
- resultExpr.append(getCollapsedExpr(subtrahendIndex));
- final ExprInfo result = new ExprInfo(resultExpr, false /* angular measure irrelevant */);
- result.mLongTimeout = mExprs.get(minuendIndex).mLongTimeout
- || mExprs.get(subtrahendIndex).mLongTimeout;
- return result;
+ return generalized_sum(minuendIndex, subtrahendIndex, R.id.op_sub);
+ }
+
+ private ExprInfo generalized_sum(long index1, long index2, int op) {
+ // TODO: Consider not collapsing expr2, to save database space.
+ // Note that this is a bit tricky, since our expressions can contain unbalanced lparens.
+ CalculatorExpr result = new CalculatorExpr();
+ CalculatorExpr collapsed1 = getCollapsedExpr(index1);
+ CalculatorExpr collapsed2 = getCollapsedExpr(index2);
+ if (collapsed1 == null || collapsed2 == null) {
+ return null;
+ }
+ result.append(collapsed1);
+ result.add(op);
+ result.append(collapsed2);
+ ExprInfo resultEi = new ExprInfo(result, false /* dont care about degrees/radians */);
+ resultEi.mLongTimeout = mExprs.get(index1).mLongTimeout
+ || mExprs.get(index2).mLongTimeout;
+ return resultEi;
}
/**
@@ -1471,13 +1480,14 @@ public class Evaluator implements CalculatorExpr.ExprResolver {
}
/**
- * Preserve a copy of the current main expression at a new index.
+ * Preserve a copy of the expression at old_index at a new index.
+ * This is useful only of old_index is MAIN_INDEX or HISTORY_MAIN_INDEX.
* This assumes that initial evaluation completed suceessfully.
* @param in_history use a positive index so the result appears in the history.
* @return the new index
*/
- public long preserve(boolean in_history) {
- ExprInfo ei = copy(MAIN_INDEX, true);
+ public long preserve(long old_index, boolean in_history) {
+ ExprInfo ei = copy(old_index, true);
if (ei.mResultString == null || ei.mResultString == ERRONEOUS_RESULT) {
throw new AssertionError("Preserving unevaluated expression");
}
@@ -1516,9 +1526,14 @@ public class Evaluator implements CalculatorExpr.ExprResolver {
* expression has been completed.
*/
private CalculatorExpr getCollapsedExpr(long index) {
- long real_index = (index == MAIN_INDEX) ? preserve(false) : index;
+ long real_index = isMutableIndex(index) ? preserve(index, false) : index;
final ExprInfo ei = mExprs.get(real_index);
final String rs = ei.mResultString;
+ // An error can occur here only under extremely unlikely conditions.
+ // Check anyway, and just refuse.
+ if (ei.mResultString == ERRONEOUS_RESULT) {
+ return null;
+ }
final int dotIndex = rs.indexOf('.');
final int leastDigOffset = getLsdOffset(ei.mVal.get(), rs, dotIndex);
return ei.mExpr.abbreviate(real_index,
@@ -1650,7 +1665,7 @@ public class Evaluator implements CalculatorExpr.ExprResolver {
|| mExprs.get(index).mResultString == ERRONEOUS_RESULT) {
return false;
}
- setSavedIndex((index == MAIN_INDEX) ? preserve(false) : index);
+ setSavedIndex(isMutableIndex(index) ? preserve(index, false) : index);
return true;
}
@@ -1659,7 +1674,7 @@ public class Evaluator implements CalculatorExpr.ExprResolver {
* The expression at index is presumed to have been evaluated.
*/
public void copyToMemory(long index) {
- setMemoryIndex((index == MAIN_INDEX) ? preserve(false) : index);
+ setMemoryIndex(isMutableIndex(index) ? preserve(index, false) : index);
}
/**
@@ -1668,9 +1683,11 @@ public class Evaluator implements CalculatorExpr.ExprResolver {
*/
public void addToMemory(long index) {
ExprInfo newEi = sum(mMemoryIndex, index);
- long newIndex = addToDB(false, newEi);
- mMemoryIndex = 0; // Invalidate while we're evaluating.
- setMemoryIndexWhenEvaluated(newIndex, true /* persist */);
+ if (newEi != null) {
+ long newIndex = addToDB(false, newEi);
+ mMemoryIndex = 0; // Invalidate while we're evaluating.
+ setMemoryIndexWhenEvaluated(newIndex, true /* persist */);
+ }
}
/**
@@ -1679,9 +1696,11 @@ public class Evaluator implements CalculatorExpr.ExprResolver {
*/
public void subtractFromMemory(long index) {
ExprInfo newEi = difference(mMemoryIndex, index);
- long newIndex = addToDB(false, newEi);
- mMemoryIndex = 0; // Invalidate while we're evaluating.
- setMemoryIndexWhenEvaluated(newIndex, true /* persist */);
+ if (newEi != null) {
+ long newIndex = addToDB(false, newEi);
+ mMemoryIndex = 0; // Invalidate while we're evaluating.
+ setMemoryIndexWhenEvaluated(newIndex, true /* persist */);
+ }
}
/**
@@ -1732,9 +1751,13 @@ public class Evaluator implements CalculatorExpr.ExprResolver {
* Append the expression at index as a pre-evaluated expression to the main expression.
*/
public void appendExpr(long index) {
+ ExprInfo ei = mExprs.get(index);
mChangedValue = true;
- mMainExpr.mLongTimeout |= mExprs.get(index).mLongTimeout;
- mMainExpr.mExpr.append(getCollapsedExpr(index));
+ mMainExpr.mLongTimeout |= ei.mLongTimeout;
+ CalculatorExpr collapsed = getCollapsedExpr(index);
+ if (collapsed != null) {
+ mMainExpr.mExpr.append(getCollapsedExpr(index));
+ }
}
/**