diff --git a/apps/calculation/history_controller.cpp b/apps/calculation/history_controller.cpp index e09cac524..159c36e8a 100644 --- a/apps/calculation/history_controller.cpp +++ b/apps/calculation/history_controller.cpp @@ -1,5 +1,6 @@ #include "history_controller.h" #include "app.h" +#include #include using namespace Shared; @@ -206,6 +207,10 @@ KDCoordinate HistoryController::rowHeight(int j) { KDCoordinate result = calculation->memoizedHeight(expanded); if (result < 0) { result = HistoryViewCell::Height(calculation.pointer(), expanded); + if (result < 0) { + // Raise, because Height modified the calculation and failed. + Poincare::ExceptionCheckpoint::Raise(); + } calculation->setMemoizedHeight(expanded, result); } /* We might want to put an assertion here to check the memoization: diff --git a/apps/calculation/history_view_cell.cpp b/apps/calculation/history_view_cell.cpp index 3dff139a8..2f982053d 100644 --- a/apps/calculation/history_view_cell.cpp +++ b/apps/calculation/history_view_cell.cpp @@ -36,7 +36,16 @@ void HistoryViewCellDataSource::setSelectedSubviewType(SubviewType subviewType, KDCoordinate HistoryViewCell::Height(Calculation * calculation, bool expanded) { HistoryViewCell cell(nullptr); - cell.setCalculation(calculation, expanded); + bool didForceOutput = false; + cell.setCalculation(calculation, expanded, &didForceOutput); + if (didForceOutput) { + /* We could not compute the height of the calculation as it is (the display + * output was forced to another value during the height computation). + * Warning: the display output of calculation was actually changed, so it + * will cause problems if we already did some computations with another + * display value. */ + return -1; + } KDRect ellipsisFrame = KDRectZero; KDRect inputFrame = KDRectZero; KDRect outputFrame = KDRectZero; @@ -237,7 +246,8 @@ void HistoryViewCell::resetMemoization() { m_calculationCRC32 = 0; } -void HistoryViewCell::setCalculation(Calculation * calculation, bool expanded) { +void HistoryViewCell::setCalculation(Calculation * calculation, bool expanded, bool * didForceOutput) { + assert(!didForceOutput || *didForceOutput == false); uint32_t newCalculationCRC = Ion::crc32Byte((const uint8_t *)calculation, ((char *)calculation->next()) - ((char *) calculation)); if (newCalculationCRC == m_calculationCRC32 && m_calculationExpanded == expanded) { return; @@ -265,6 +275,9 @@ void HistoryViewCell::setCalculation(Calculation * calculation, bool expanded) { if (couldNotCreateExactLayout) { if (calculation->displayOutput(context) != ::Calculation::Calculation::DisplayOutput::ExactOnly) { calculation->forceDisplayOutput(::Calculation::Calculation::DisplayOutput::ApproximateOnly); + if (didForceOutput) { + *didForceOutput = true; + } } else { /* We should only display the exact result, but we cannot create it * -> raise an exception. */ @@ -287,6 +300,9 @@ void HistoryViewCell::setCalculation(Calculation * calculation, bool expanded) { /* Set the display output to ApproximateOnly, make room in the pool by * erasing the exact layout, and retry to create the approximate layout */ calculation->forceDisplayOutput(::Calculation::Calculation::DisplayOutput::ApproximateOnly); + if (didForceOutput) { + *didForceOutput = true; + } exactOutputLayout = Poincare::Layout(); couldNotCreateApproximateLayout = false; approximateOutputLayout = calculation->createApproximateOutputLayout(context, &couldNotCreateApproximateLayout); diff --git a/apps/calculation/history_view_cell.h b/apps/calculation/history_view_cell.h index 7bddbe434..abe2d6ac8 100644 --- a/apps/calculation/history_view_cell.h +++ b/apps/calculation/history_view_cell.h @@ -51,7 +51,7 @@ public: Poincare::Layout layout() const override; KDColor backgroundColor() const override { return m_even ? KDColorWhite : Palette::WallScreen; } void resetMemoization(); - void setCalculation(Calculation * calculation, bool expanded); + void setCalculation(Calculation * calculation, bool expanded, bool * didForceOutput = nullptr); int numberOfSubviews() const override { return 2 + displayedEllipsis(); } View * subviewAtIndex(int index) override; void layoutSubviews(bool force = false) override;