- Format all files.

This commit is contained in:
Daniel Belcher 2019-05-02 12:30:54 -07:00
commit 0df371f5a3
234 changed files with 12650 additions and 11851 deletions

View file

@ -124,15 +124,15 @@ bool CalcInput::TryAddDigit(unsigned int value, uint32_t radix, bool isIntegerMo
else if (radix == 10)
{
// If value length is at least the max, we know we can't add another digit.
if(pNumSec->value.size() < maxNumStr.size())
if (pNumSec->value.size() < maxNumStr.size())
{
// Compare value to substring of maxNumStr of value.size() length.
// If cmpResult > 0:
// eg. max is "127", and the current number is "20". first digit itself says we are out.
// eg. max is "127", and the current number is "20". first digit itself says we are out.
// Additional digit is not possible
// If cmpResult < 0:
// Success case. eg. max is "127", and current number is say "11". The second digit '1' being <
// Success case. eg. max is "127", and current number is say "11". The second digit '1' being <
// corresponding digit '2', means all digits are possible to append, like 119 will still be < 127
// If cmpResult == 0:
@ -151,7 +151,7 @@ bool CalcInput::TryAddDigit(unsigned int value, uint32_t radix, bool isIntegerMo
}
else if (pNumSec->IsNegative() && chDigit <= lastChar + 1)
{
// Negative value case, eg. max is "127", and current number is "-12". Then 8 is also valid, as the range
// Negative value case, eg. max is "127", and current number is "-12". Then 8 is also valid, as the range
// is always from -(max+1)...max in signed mode
allowExtraDigit = true;
}

View file

@ -33,9 +33,7 @@ bool IsDigitOpCode(OpCode opCode)
// was never inout, we need to revert the state changes made as a result of this test
bool IsGuiSettingOpCode(OpCode opCode)
{
if (IsOpInRange(opCode, IDM_HEX, IDM_BIN) ||
IsOpInRange(opCode, IDM_QWORD, IDM_BYTE) ||
IsOpInRange(opCode, IDM_DEG, IDM_GRAD))
if (IsOpInRange(opCode, IDM_HEX, IDM_BIN) || IsOpInRange(opCode, IDM_QWORD, IDM_BYTE) || IsOpInRange(opCode, IDM_DEG, IDM_GRAD))
{
return true;
}

View file

@ -11,7 +11,8 @@ constexpr int ASCII_0 = 48;
using namespace std;
using namespace CalcEngine;
namespace {
namespace
{
void IFT(ResultCode hr)
{
if (FAILED(hr))
@ -38,11 +39,8 @@ void CHistoryCollector::ReinitHistory()
// Constructor
// Can throw Out of memory error
CHistoryCollector::CHistoryCollector(ICalcDisplay *pCalcDisplay, std::shared_ptr<IHistoryDisplay> pHistoryDisplay, wchar_t decimalSymbol) :
m_pHistoryDisplay(pHistoryDisplay),
m_pCalcDisplay(pCalcDisplay),
m_iCurLineHistStart(-1),
m_decimalSymbol(decimalSymbol)
CHistoryCollector::CHistoryCollector(ICalcDisplay* pCalcDisplay, std::shared_ptr<IHistoryDisplay> pHistoryDisplay, wchar_t decimalSymbol)
: m_pHistoryDisplay(pHistoryDisplay), m_pCalcDisplay(pCalcDisplay), m_iCurLineHistStart(-1), m_decimalSymbol(decimalSymbol)
{
ReinitHistory();
}
@ -302,7 +300,8 @@ void CHistoryCollector::CompleteHistoryLine(wstring_view numStr)
{
if (nullptr != m_pCalcDisplay)
{
m_pCalcDisplay->SetExpressionDisplay(std::make_shared<CalculatorVector<std::pair<std::wstring, int>>>(), std::make_shared<CalculatorVector<std::shared_ptr<IExpressionCommand>>>());
m_pCalcDisplay->SetExpressionDisplay(std::make_shared<CalculatorVector<std::pair<std::wstring, int>>>(),
std::make_shared<CalculatorVector<std::shared_ptr<IExpressionCommand>>>());
}
if (nullptr != m_pHistoryDisplay)
@ -323,14 +322,14 @@ void CHistoryCollector::ClearHistoryLine(wstring_view errStr)
{
if (nullptr != m_pCalcDisplay)
{
m_pCalcDisplay->SetExpressionDisplay(std::make_shared<CalculatorVector<std::pair<std::wstring, int>>>(), std::make_shared<CalculatorVector<std::shared_ptr<IExpressionCommand>>>());
m_pCalcDisplay->SetExpressionDisplay(std::make_shared<CalculatorVector<std::pair<std::wstring, int>>>(),
std::make_shared<CalculatorVector<std::shared_ptr<IExpressionCommand>>>());
}
m_iCurLineHistStart = -1; // It will get recomputed at the first Opnd
ReinitHistory();
}
}
// Adds the given string psz to the globally maintained current equation string at the end.
// Also returns the 0 based index in the string just added. Can throw out of memory error
int CHistoryCollector::IchAddSzToEquationSz(wstring_view str, int icommandIndex)
@ -392,14 +391,13 @@ void CHistoryCollector::SetExpressionDisplay()
{
m_pCalcDisplay->SetExpressionDisplay(m_spTokens, m_spCommands);
}
}
int CHistoryCollector::AddCommand(_In_ const std::shared_ptr<IExpressionCommand> & spCommand)
int CHistoryCollector::AddCommand(_In_ const std::shared_ptr<IExpressionCommand>& spCommand)
{
if (m_spCommands == nullptr)
{
m_spCommands = std::make_shared <CalculatorVector<std::shared_ptr<IExpressionCommand>>>();
m_spCommands = std::make_shared<CalculatorVector<std::shared_ptr<IExpressionCommand>>>();
}
if (FAILED(m_spCommands->Append(spCommand)))

View file

@ -7,20 +7,15 @@ using namespace std;
namespace CalcEngine
{
Number::Number() noexcept :
Number(1, 0, { 0 })
{}
Number::Number() noexcept : Number(1, 0, { 0 })
{
}
Number::Number(int32_t sign, int32_t exp, vector<uint32_t> const& mantissa) noexcept :
m_sign{ sign },
m_exp{ exp },
m_mantissa{ mantissa }
{}
Number::Number(int32_t sign, int32_t exp, vector<uint32_t> const& mantissa) noexcept : m_sign{ sign }, m_exp{ exp }, m_mantissa{ mantissa }
{
}
Number::Number(PNUMBER p) noexcept :
m_sign{ p->sign },
m_exp{ p->exp },
m_mantissa{}
Number::Number(PNUMBER p) noexcept : m_sign{ p->sign }, m_exp{ p->exp }, m_mantissa{}
{
m_mantissa.reserve(p->cdigit);
copy(p->mant, p->mant + p->cdigit, back_inserter(m_mantissa));
@ -33,7 +28,7 @@ namespace CalcEngine
ret->exp = this->Exp();
ret->cdigit = static_cast<int32_t>(this->Mantissa().size());
MANTTYPE *ptrRet = ret->mant;
MANTTYPE* ptrRet = ret->mant;
for (auto const& digit : this->Mantissa())
{
*ptrRet++ = digit;
@ -59,6 +54,6 @@ namespace CalcEngine
bool Number::IsZero() const
{
return all_of(m_mantissa.begin(), m_mantissa.end(), [](auto &&i) { return i == 0; });
return all_of(m_mantissa.begin(), m_mantissa.end(), [](auto&& i) { return i == 0; });
}
}

View file

@ -7,10 +7,9 @@ using namespace std;
namespace CalcEngine
{
Rational::Rational() noexcept :
m_p{},
m_q{ 1, 0, { 1 } }
{}
Rational::Rational() noexcept : m_p{}, m_q{ 1, 0, { 1 } }
{
}
Rational::Rational(Number const& n) noexcept
{
@ -24,10 +23,9 @@ namespace CalcEngine
m_q = Number(1, qExp, { 1 });
}
Rational::Rational(Number const& p, Number const& q) noexcept :
m_p{ p },
m_q{ q }
{}
Rational::Rational(Number const& p, Number const& q) noexcept : m_p{ p }, m_q{ q }
{
}
Rational::Rational(int32_t i)
{
@ -60,10 +58,9 @@ namespace CalcEngine
m_q = Number{ temp.Q() };
}
Rational::Rational(PRAT prat) noexcept :
m_p{ Number{prat->pp} },
m_q{ Number{prat->pq} }
{}
Rational::Rational(PRAT prat) noexcept : m_p{ Number{ prat->pp } }, m_q{ Number{ prat->pq } }
{
}
PRAT Rational::ToPRAT() const
{
@ -353,7 +350,8 @@ namespace CalcEngine
/// Calculate the remainder after division, the sign of a result will match the sign of lhs.
/// </summary>
/// <remarks>
/// This function has the same behavior as the standard C/C++ operator '%', to calculate the modulus after division instead, use <see cref="Rational::operator%"/> instead.
/// This function has the same behavior as the standard C/C++ operator '%', to calculate the modulus after division instead, use <see
/// cref="Rational::operator%"/> instead.
/// </remarks>
Rational operator%(Rational lhs, Rational const& rhs)
{

View file

@ -58,42 +58,43 @@ void CCalcEngine::InitialOneTimeOnlySetup(CalculationManager::IResourceProvider&
// CCalcEngine::CCalcEngine
//
//////////////////////////////////////////////////
CCalcEngine::CCalcEngine(bool fPrecedence, bool fIntegerMode, CalculationManager::IResourceProvider* const pResourceProvider, __in_opt ICalcDisplay *pCalcDisplay, __in_opt shared_ptr<IHistoryDisplay> pHistoryDisplay) :
m_fPrecedence(fPrecedence),
m_fIntegerMode(fIntegerMode),
m_pCalcDisplay(pCalcDisplay),
m_resourceProvider(pResourceProvider),
m_nOpCode(0),
m_nPrevOpCode(0),
m_bChangeOp(false),
m_bRecord(false),
m_bSetCalcState(false),
m_input(DEFAULT_DEC_SEPARATOR),
m_nFE(FMT_FLOAT),
m_memoryValue{ make_unique<Rational>() },
m_holdVal{},
m_currentVal{},
m_lastVal{},
m_parenVals{},
m_precedenceVals{},
m_bError(false),
m_bInv(false),
m_bNoPrevEqu(true),
m_radix(DEFAULT_RADIX),
m_precision(DEFAULT_PRECISION),
m_cIntDigitsSav(DEFAULT_MAX_DIGITS),
m_decGrouping(),
m_numberString(DEFAULT_NUMBER_STR),
m_nTempCom(0),
m_openParenCount(0),
m_nOp(),
m_nPrecOp(),
m_precedenceOpCount(0),
m_nLastCom(0),
m_angletype(ANGLE_DEG),
m_numwidth(QWORD_WIDTH),
m_HistoryCollector(pCalcDisplay, pHistoryDisplay, DEFAULT_DEC_SEPARATOR),
m_groupSeparator(DEFAULT_GRP_SEPARATOR)
CCalcEngine::CCalcEngine(bool fPrecedence, bool fIntegerMode, CalculationManager::IResourceProvider* const pResourceProvider,
__in_opt ICalcDisplay* pCalcDisplay, __in_opt shared_ptr<IHistoryDisplay> pHistoryDisplay)
: m_fPrecedence(fPrecedence)
, m_fIntegerMode(fIntegerMode)
, m_pCalcDisplay(pCalcDisplay)
, m_resourceProvider(pResourceProvider)
, m_nOpCode(0)
, m_nPrevOpCode(0)
, m_bChangeOp(false)
, m_bRecord(false)
, m_bSetCalcState(false)
, m_input(DEFAULT_DEC_SEPARATOR)
, m_nFE(FMT_FLOAT)
, m_memoryValue{ make_unique<Rational>() }
, m_holdVal{}
, m_currentVal{}
, m_lastVal{}
, m_parenVals{}
, m_precedenceVals{}
, m_bError(false)
, m_bInv(false)
, m_bNoPrevEqu(true)
, m_radix(DEFAULT_RADIX)
, m_precision(DEFAULT_PRECISION)
, m_cIntDigitsSav(DEFAULT_MAX_DIGITS)
, m_decGrouping()
, m_numberString(DEFAULT_NUMBER_STR)
, m_nTempCom(0)
, m_openParenCount(0)
, m_nOp()
, m_nPrecOp()
, m_precedenceOpCount(0)
, m_nLastCom(0)
, m_angletype(ANGLE_DEG)
, m_numwidth(QWORD_WIDTH)
, m_HistoryCollector(pCalcDisplay, pHistoryDisplay, DEFAULT_DEC_SEPARATOR)
, m_groupSeparator(DEFAULT_GRP_SEPARATOR)
{
InitChopNumbers();

View file

@ -20,16 +20,16 @@
using namespace std;
using namespace CalcEngine;
namespace {
namespace
{
// NPrecedenceOfOp
//
// returns a virtual number for precedence for the operator. We expect binary operator only, otherwise the lowest number
// 0 is returned. Higher the number, higher the precedence of the operator.
int NPrecedenceOfOp(int nopCode)
{
static uint8_t rgbPrec[] = { 0,0, IDC_OR,0, IDC_XOR,0, IDC_AND,1,
IDC_ADD,2, IDC_SUB,2, IDC_RSHF,3, IDC_LSHF,3,
IDC_MOD,3, IDC_DIV,3, IDC_MUL,3, IDC_PWR,4, IDC_ROOT, 4 };
static uint8_t rgbPrec[] = { 0, 0, IDC_OR, 0, IDC_XOR, 0, IDC_AND, 1, IDC_ADD, 2, IDC_SUB, 2, IDC_RSHF,
3, IDC_LSHF, 3, IDC_MOD, 3, IDC_DIV, 3, IDC_MUL, 3, IDC_PWR, 4, IDC_ROOT, 4 };
unsigned int iPrec;
iPrec = 0;
@ -42,7 +42,6 @@ namespace {
iPrec = 0;
}
return rgbPrec[iPrec + 1];
}
}
@ -90,7 +89,7 @@ void CCalcEngine::ProcessCommand(OpCode wParam)
void CCalcEngine::ProcessCommandWorker(OpCode wParam)
{
int nx, ni;
int nx, ni;
// Save the last command. Some commands are not saved in this manor, these
// commands are:
@ -125,18 +124,13 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
// Toggle Record/Display mode if appropriate.
if (m_bRecord)
{
if (IsOpInRange(wParam, IDC_AND, IDC_MMINUS) ||
IsOpInRange(wParam, IDC_OPENP, IDC_CLOSEP) ||
IsOpInRange(wParam, IDM_HEX, IDM_BIN) ||
IsOpInRange(wParam, IDM_QWORD, IDM_BYTE) ||
IsOpInRange(wParam, IDM_DEG, IDM_GRAD) ||
IsOpInRange(wParam, IDC_BINEDITSTART, IDC_BINEDITSTART + 63) ||
(IDC_INV == wParam) ||
(IDC_SIGN == wParam && 10 != m_radix))
if (IsOpInRange(wParam, IDC_AND, IDC_MMINUS) || IsOpInRange(wParam, IDC_OPENP, IDC_CLOSEP) || IsOpInRange(wParam, IDM_HEX, IDM_BIN)
|| IsOpInRange(wParam, IDM_QWORD, IDM_BYTE) || IsOpInRange(wParam, IDM_DEG, IDM_GRAD)
|| IsOpInRange(wParam, IDC_BINEDITSTART, IDC_BINEDITSTART + 63) || (IDC_INV == wParam) || (IDC_SIGN == wParam && 10 != m_radix))
{
m_bRecord = false;
m_currentVal = m_input.ToRational(m_radix, m_precision);
DisplayNum(); // Causes 3.000 to shrink to 3. on first op.
DisplayNum(); // Causes 3.000 to shrink to 3. on first op.
}
}
else
@ -241,9 +235,9 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
else
{
/* do the last operation and then if the precedence array is not
* empty or the top is not the '(' demarcator then pop the top
* of the array and recheck precedence against the new operator
*/
* empty or the top is not the '(' demarcator then pop the top
* of the array and recheck precedence against the new operator
*/
m_currentVal = DoOperation(m_nOpCode, m_currentVal, m_lastVal);
m_nPrevOpCode = m_nOpCode;
@ -272,7 +266,6 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
m_HistoryCollector.PopLastOpndStart();
goto DoPrecedenceCheckAgain;
}
}
}
@ -337,11 +330,9 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
/* reset the m_bInv flag and indicators if it is set
and have been used */
if (m_bInv &&
((wParam == IDC_CHOP) ||
(wParam == IDC_SIN) || (wParam == IDC_COS) || (wParam == IDC_TAN) ||
(wParam == IDC_LN) || (wParam == IDC_DMS) || (wParam == IDC_DEGREES) ||
(wParam == IDC_SINH) || (wParam == IDC_COSH) || (wParam == IDC_TANH)))
if (m_bInv
&& ((wParam == IDC_CHOP) || (wParam == IDC_SIN) || (wParam == IDC_COS) || (wParam == IDC_TAN) || (wParam == IDC_LN) || (wParam == IDC_DMS)
|| (wParam == IDC_DEGREES) || (wParam == IDC_SINH) || (wParam == IDC_COSH) || (wParam == IDC_TANH)))
{
m_bInv = false;
}
@ -386,13 +377,13 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
m_nPrevOpCode = 0;
m_bNoPrevEqu = true;
/* clear the parenthesis status box indicator, this will not be
cleared for CENTR */
if (nullptr != m_pCalcDisplay)
{
m_pCalcDisplay->SetParenthesisNumber(0);
m_pCalcDisplay->SetExpressionDisplay(make_shared<CalculatorVector<pair<wstring, int>>>(), make_shared<CalculatorVector<shared_ptr<IExpressionCommand>>>());
m_pCalcDisplay->SetExpressionDisplay(make_shared<CalculatorVector<pair<wstring, int>>>(),
make_shared<CalculatorVector<shared_ptr<IExpressionCommand>>>());
}
m_HistoryCollector.ClearHistoryLine(wstring());
@ -435,7 +426,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
// automatic closing of all the parenthesis to get a meaningful result as well as ensure data integrity
m_nTempCom = m_nLastCom; // Put back this last saved command to the prev state so ) can be handled properly
ProcessCommand(IDC_CLOSEP);
m_nLastCom = m_nTempCom; // Actually this is IDC_CLOSEP
m_nLastCom = m_nTempCom; // Actually this is IDC_CLOSEP
m_nTempCom = (int)wParam; // put back in the state where last op seen was IDC_CLOSEP, and current op is IDC_EQU
}
@ -485,7 +476,8 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
m_HistoryCollector.CompleteHistoryLine(groupedString);
if (nullptr != m_pCalcDisplay)
{
m_pCalcDisplay->SetExpressionDisplay(make_shared<CalculatorVector<pair<wstring, int>>>(), make_shared<CalculatorVector<shared_ptr<IExpressionCommand>>>());
m_pCalcDisplay->SetExpressionDisplay(make_shared<CalculatorVector<pair<wstring, int>>>(),
make_shared<CalculatorVector<shared_ptr<IExpressionCommand>>>());
}
}
@ -749,7 +741,6 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
m_bInv = !m_bInv;
break;
}
}
// Helper function to resolve one item on the precedence stack.
@ -758,8 +749,8 @@ void CCalcEngine::ResolveHighestPrecedenceOperation()
// Is there a valid operation around?
if (m_nOpCode)
{
// If this is the first EQU in a string, set m_holdVal=m_currentVal
// Otherwise let m_currentVal=m_holdVal. This keeps m_currentVal constant
// If this is the first EQU in a string, set m_holdVal=m_currentVal
// Otherwise let m_currentVal=m_holdVal. This keeps m_currentVal constant
// through all EQUs in a row.
if (m_bNoPrevEqu)
{
@ -814,7 +805,6 @@ void CCalcEngine::CheckAndAddLastBinOpToHistory(bool addToHistory)
// So erase the last operand
m_HistoryCollector.RemoveLastOpndFromHistory();
}
}
else if (m_HistoryCollector.FOpndAddedToHistory() && !m_bError)
{
@ -823,8 +813,7 @@ void CCalcEngine::CheckAndAddLastBinOpToHistory(bool addToHistory)
// Let us make a current value =. So in case of 4 SQRT (or a equation under braces) and then a new equation is started, we can just form
// a useful equation of sqrt(4) = 2 and continue a new equation from now on. But no point in doing this for things like
// MR, SUM etc. All you will get is 5 = 5 kind of no useful equation.
if ((IsUnaryOpCode(m_nLastCom) || IDC_SIGN == m_nLastCom || IDC_CLOSEP == m_nLastCom) &&
0 == m_openParenCount)
if ((IsUnaryOpCode(m_nLastCom) || IDC_SIGN == m_nLastCom || IDC_CLOSEP == m_nLastCom) && 0 == m_openParenCount)
{
if (addToHistory)
{
@ -864,7 +853,7 @@ void CCalcEngine::DisplayAnnounceBinaryOperator()
// we have this separate table to get its localized name and for its Inv function if it exists.
struct FunctionNameElement
{
wstring degreeString; // Used by default if there are no rad or grad specific strings.
wstring degreeString; // Used by default if there are no rad or grad specific strings.
wstring inverseDegreeString; // Will fall back to degreeString if empty
wstring radString;
@ -877,9 +866,8 @@ struct FunctionNameElement
};
// Table for each unary operator
static const std::unordered_map<int, FunctionNameElement> unaryOperatorStringTable =
{
{ IDC_CHOP, { L"", SIDS_FRAC} },
static const std::unordered_map<int, FunctionNameElement> unaryOperatorStringTable = {
{ IDC_CHOP, { L"", SIDS_FRAC } },
{ IDC_SIN, { SIDS_SIND, SIDS_ASIND, SIDS_SINR, SIDS_ASINR, SIDS_SING, SIDS_ASING } },
{ IDC_COS, { SIDS_COSD, SIDS_ACOSD, SIDS_COSR, SIDS_ACOSR, SIDS_COSG, SIDS_ACOSG } },
@ -889,7 +877,7 @@ static const std::unordered_map<int, FunctionNameElement> unaryOperatorStringTab
{ IDC_COSH, { L"", SIDS_ACOSH } },
{ IDC_TANH, { L"", SIDS_ATANH } },
{ IDC_LN , { L"", SIDS_POWE } },
{ IDC_LN, { L"", SIDS_POWE } },
{ IDC_SQR, { SIDS_SQR } },
{ IDC_CUB, { SIDS_CUBE } },
{ IDC_FAC, { SIDS_FACT } },

View file

@ -25,7 +25,6 @@ constexpr uint32_t MAX_GROUPING_SIZE = 16;
constexpr wstring_view c_decPreSepStr = L"[+-]?(\\d*)[";
constexpr wstring_view c_decPostSepStr = L"]?(\\d*)(?:e[+-]?(\\d*))?$";
/****************************************************************************\
* void DisplayNum(void)
*
@ -37,15 +36,16 @@ constexpr wstring_view c_decPostSepStr = L"]?(\\d*)(?:e[+-]?(\\d*))?$";
//
// State of calc last time DisplayNum was called
//
typedef struct {
typedef struct
{
Rational value;
int32_t precision;
uint32_t radix;
int nFE;
NUM_WIDTH numwidth;
bool fIntMath;
bool bRecord;
bool bUseSep;
int nFE;
NUM_WIDTH numwidth;
bool fIntMath;
bool bRecord;
bool bUseSep;
} LASTDISP;
LASTDISP gldPrevious = { 0, -1, 0, -1, (NUM_WIDTH)-1, false, false, false };
@ -66,7 +66,7 @@ CalcEngine::Rational CCalcEngine::TruncateNumForIntMath(CalcEngine::Rational con
if (result < 0)
{
// if negative make positive by doing a twos complement
result = -(result) - 1;
result = -(result)-1;
result ^= m_chopNumbers[m_numwidth];
}
@ -84,15 +84,8 @@ void CCalcEngine::DisplayNum(void)
// something important has changed since the last time DisplayNum was
// called.
//
if (m_bRecord ||
gldPrevious.value != m_currentVal ||
gldPrevious.precision != m_precision ||
gldPrevious.radix != m_radix ||
gldPrevious.nFE != (int)m_nFE ||
gldPrevious.bUseSep != true ||
gldPrevious.numwidth != m_numwidth ||
gldPrevious.fIntMath != m_fIntegerMode ||
gldPrevious.bRecord != m_bRecord)
if (m_bRecord || gldPrevious.value != m_currentVal || gldPrevious.precision != m_precision || gldPrevious.radix != m_radix || gldPrevious.nFE != (int)m_nFE
|| gldPrevious.bUseSep != true || gldPrevious.numwidth != m_numwidth || gldPrevious.fIntMath != m_fIntegerMode || gldPrevious.bRecord != m_bRecord)
{
gldPrevious.precision = m_precision;
gldPrevious.radix = m_radix;

View file

@ -54,7 +54,7 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
uint64_t w64Bits = result.ToUInt64_t();
uint64_t msb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1;
w64Bits <<= 1; // LShift by 1
w64Bits <<= 1; // LShift by 1
w64Bits |= msb; // Set the prev Msb as the current Lsb
result = w64Bits;
@ -168,9 +168,9 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
case IDC_DEGREES:
ProcessCommand(IDC_INV);
// This case falls through to IDC_DMS case because in the old Win32 Calc,
// This case falls through to IDC_DMS case because in the old Win32 Calc,
// the degrees functionality was achieved as 'Inv' of 'dms' operation,
// so setting the IDC_INV command first and then performing 'dms' operation as global variables m_bInv, m_bRecord
// so setting the IDC_INV command first and then performing 'dms' operation as global variables m_bInv, m_bRecord
// are set properly through ProcessCommand(IDC_INV)
[[fallthrough]];
case IDC_DMS:
@ -202,7 +202,7 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
}
break;
}
} // end switch( op )
} // end switch( op )
}
catch (uint32_t nErrCode)
{
@ -226,4 +226,3 @@ void CCalcEngine::DisplayError(uint32_t nError)
m_HistoryCollector.ClearHistoryLine(errorString);
}

View file

@ -126,7 +126,7 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa
}
else
{
//other modes, use modrat (modulus after division)
// other modes, use modrat (modulus after division)
result = Mod(result, temp);
}
}

View file

@ -64,7 +64,7 @@ int32_t CCalcEngine::DwWordBitWidthFromeNumWidth(NUM_WIDTH /*numwidth*/)
uint32_t CCalcEngine::NRadixFromRadixType(RADIX_TYPE radixtype)
{
static constexpr uint32_t rgnRadish[4] = { 16, 10, 8, 2 }; /* Number bases in the same order as radixtype */
static constexpr uint32_t rgnRadish[4] = { 16, 10, 8, 2 }; /* Number bases in the same order as radixtype */
uint32_t radix = 10;
// convert special bases into symbolic values

View file

@ -7,11 +7,12 @@
using namespace std;
using namespace CalculationManager;
CalculatorHistory::CalculatorHistory(size_t maxSize) :
m_maxHistorySize(maxSize)
{}
CalculatorHistory::CalculatorHistory(size_t maxSize) : m_maxHistorySize(maxSize)
{
}
unsigned int CalculatorHistory::AddToHistory(_In_ shared_ptr<CalculatorVector <pair<wstring, int>>> const &tokens, _In_ shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> const &commands, _In_ wstring_view result)
unsigned int CalculatorHistory::AddToHistory(_In_ shared_ptr<CalculatorVector<pair<wstring, int>>> const& tokens,
_In_ shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> const& commands, _In_ wstring_view result)
{
unsigned int addedIndex;
wstring generatedExpression;
@ -31,8 +32,7 @@ unsigned int CalculatorHistory::AddToHistory(_In_ shared_ptr<CalculatorVector <p
return addedIndex;
}
unsigned int CalculatorHistory::AddItem(_In_ shared_ptr<HISTORYITEM> const &spHistoryItem)
unsigned int CalculatorHistory::AddItem(_In_ shared_ptr<HISTORYITEM> const& spHistoryItem)
{
if (m_historyItems.size() >= m_maxHistorySize)
{

View file

@ -15,10 +15,10 @@ namespace CalculationManager
struct HISTORYITEMVECTOR
{
std::shared_ptr<CalculatorVector <std::pair<std::wstring, int>>> spTokens;
std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> spTokens;
std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> spCommands;
std::wstring expression;
std::wstring result;
std::wstring expression;
std::wstring result;
};
struct HISTORYITEM
@ -26,19 +26,21 @@ namespace CalculationManager
HISTORYITEMVECTOR historyItemVector;
};
class CalculatorHistory :
public IHistoryDisplay
class CalculatorHistory : public IHistoryDisplay
{
public:
CalculatorHistory(const size_t maxSize);
unsigned int AddToHistory(_In_ std::shared_ptr<CalculatorVector <std::pair<std::wstring, int>>> const &spTokens, _In_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const &spCommands, std::wstring_view result);
unsigned int AddToHistory(_In_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const& spTokens,
_In_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const& spCommands, std::wstring_view result);
std::vector<std::shared_ptr<HISTORYITEM>> const& GetHistory();
std::shared_ptr<HISTORYITEM> const& GetHistoryItem(unsigned int uIdx);
void ClearHistory();
unsigned int AddItem(_In_ std::shared_ptr<HISTORYITEM> const &spHistoryItem);
unsigned int AddItem(_In_ std::shared_ptr<HISTORYITEM> const& spHistoryItem);
bool RemoveItem(unsigned int uIdx);
size_t MaxHistorySize() const { return m_maxHistorySize; }
size_t MaxHistorySize() const
{
return m_maxHistorySize;
}
~CalculatorHistory(void);
private:

View file

@ -14,25 +14,21 @@ static constexpr size_t SERIALIZED_NUMBER_MINSIZE = 3;
// Converts Memory Command enum value to unsigned char,
// while ignoring Warning C4309: 'conversion' : truncation of constant value
#define MEMORY_COMMAND_TO_UNSIGNED_CHAR(c)\
__pragma(warning(push))\
__pragma(warning(disable: 4309))\
static_cast<unsigned char>(c)\
__pragma(warning(pop))
#define MEMORY_COMMAND_TO_UNSIGNED_CHAR(c) __pragma(warning(push)) __pragma(warning(disable : 4309)) static_cast<unsigned char>(c) __pragma(warning(pop))
namespace CalculationManager
{
CalculatorManager::CalculatorManager(_In_ ICalcDisplay* displayCallback, _In_ IResourceProvider* resourceProvider) :
m_displayCallback(displayCallback),
m_currentCalculatorEngine(nullptr),
m_resourceProvider(resourceProvider),
m_inHistoryItemLoadMode(false),
m_persistedPrimaryValue(),
m_isExponentialFormat(false),
m_currentDegreeMode(Command::CommandNULL),
m_savedDegreeMode(Command::CommandDEG),
m_pStdHistory(new CalculatorHistory(MAX_HISTORY_ITEMS)),
m_pSciHistory(new CalculatorHistory(MAX_HISTORY_ITEMS))
CalculatorManager::CalculatorManager(_In_ ICalcDisplay* displayCallback, _In_ IResourceProvider* resourceProvider)
: m_displayCallback(displayCallback)
, m_currentCalculatorEngine(nullptr)
, m_resourceProvider(resourceProvider)
, m_inHistoryItemLoadMode(false)
, m_persistedPrimaryValue()
, m_isExponentialFormat(false)
, m_currentDegreeMode(Command::CommandNULL)
, m_savedDegreeMode(Command::CommandDEG)
, m_pStdHistory(new CalculatorHistory(MAX_HISTORY_ITEMS))
, m_pSciHistory(new CalculatorHistory(MAX_HISTORY_ITEMS))
{
CCalcEngine::InitialOneTimeOnlySetup(*m_resourceProvider);
}
@ -89,7 +85,8 @@ namespace CalculationManager
/// Used to set the expression display value on ViewModel
/// </summary>
/// <param name="expressionString">wstring representing expression to be displayed</param>
void CalculatorManager::SetExpressionDisplay(_Inout_ shared_ptr<CalculatorVector<pair<wstring, int>>> const &tokens, _Inout_ shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> const &commands)
void CalculatorManager::SetExpressionDisplay(_Inout_ shared_ptr<CalculatorVector<pair<wstring, int>>> const& tokens,
_Inout_ shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> const& commands)
{
if (!m_inHistoryItemLoadMode)
{
@ -165,7 +162,8 @@ namespace CalculationManager
{
if (!m_standardCalculatorEngine)
{
m_standardCalculatorEngine = make_unique<CCalcEngine>(false /* Respect Order of Operations */, false /* Set to Integer Mode */, m_resourceProvider, this, m_pStdHistory);
m_standardCalculatorEngine =
make_unique<CCalcEngine>(false /* Respect Order of Operations */, false /* Set to Integer Mode */, m_resourceProvider, this, m_pStdHistory);
}
m_currentCalculatorEngine = m_standardCalculatorEngine.get();
@ -183,7 +181,8 @@ namespace CalculationManager
{
if (!m_scientificCalculatorEngine)
{
m_scientificCalculatorEngine = make_unique<CCalcEngine>(true /* Respect Order of Operations */, false /* Set to Integer Mode */, m_resourceProvider, this, m_pSciHistory);
m_scientificCalculatorEngine =
make_unique<CCalcEngine>(true /* Respect Order of Operations */, false /* Set to Integer Mode */, m_resourceProvider, this, m_pSciHistory);
}
m_currentCalculatorEngine = m_scientificCalculatorEngine.get();
@ -198,9 +197,10 @@ namespace CalculationManager
/// </summary>
void CalculatorManager::SetProgrammerMode()
{
if(!m_programmerCalculatorEngine)
if (!m_programmerCalculatorEngine)
{
m_programmerCalculatorEngine = make_unique<CCalcEngine>(true /* Respect Order of Operations */, true /* Set to Integer Mode */, m_resourceProvider, this, nullptr);
m_programmerCalculatorEngine =
make_unique<CCalcEngine>(true /* Respect Order of Operations */, true /* Set to Integer Mode */, m_resourceProvider, this, nullptr);
}
m_currentCalculatorEngine = m_programmerCalculatorEngine.get();
@ -209,7 +209,6 @@ namespace CalculationManager
m_currentCalculatorEngine->ChangePrecision(static_cast<int>(CalculatorPrecision::ProgrammerModePrecision));
}
/// <summary>
/// Send command to the Calc Engine
/// Cast Command Enum to OpCode.
@ -220,8 +219,8 @@ namespace CalculationManager
{
// When the expression line is cleared, we save the current state, which includes,
// primary display, memory, and degree mode
if (command == Command::CommandCLEAR || command == Command::CommandEQU
|| command == Command::ModeBasic || command == Command::ModeScientific || command == Command::ModeProgrammer)
if (command == Command::CommandCLEAR || command == Command::CommandEQU || command == Command::ModeBasic || command == Command::ModeScientific
|| command == Command::ModeProgrammer)
{
switch (command)
{
@ -361,7 +360,7 @@ namespace CalculationManager
/// DeSerialize the primary display from vector of long
/// </summary>
/// <param name = "serializedPrimaryDisplay">Serialized Rational of primary display</param>
void CalculatorManager::DeSerializePrimaryDisplay(const vector<long> &serializedPrimaryDisplay)
void CalculatorManager::DeSerializePrimaryDisplay(const vector<long>& serializedPrimaryDisplay)
{
if (serializedPrimaryDisplay.empty())
{
@ -404,7 +403,7 @@ namespace CalculationManager
/// DeSerialize the Memory from vector of long
/// </summary>
/// <param name = "serializedMemory">Serialized Rational of memory</param>
void CalculatorManager::DeSerializeMemory(const vector<long> &serializedMemory)
void CalculatorManager::DeSerializeMemory(const vector<long>& serializedMemory)
{
vector<long>::const_iterator itr = serializedMemory.begin();
while (itr != serializedMemory.end())
@ -435,8 +434,8 @@ namespace CalculationManager
for (auto commandItr = serializedData.begin(); commandItr != serializedData.end(); ++commandItr)
{
if (*commandItr >= MEMORY_COMMAND_TO_UNSIGNED_CHAR(MemoryCommand::MemorizeNumber) &&
*commandItr <= MEMORY_COMMAND_TO_UNSIGNED_CHAR(MemoryCommand::MemorizedNumberClearAll))
if (*commandItr >= MEMORY_COMMAND_TO_UNSIGNED_CHAR(MemoryCommand::MemorizeNumber)
&& *commandItr <= MEMORY_COMMAND_TO_UNSIGNED_CHAR(MemoryCommand::MemorizedNumberClearAll))
{
// MemoryCommands(which have values above 255) are pushed on m_savedCommands upon casting to unsigned char.
// SerializeCommands uses m_savedCommands, which is then used in DeSerializeCommands.
@ -622,10 +621,10 @@ namespace CalculationManager
}
/// <summary>
/// Helper function that selects a memory from the vector and set it to CCalcEngine
/// Saved RAT number needs to be copied and passed in, as CCalcEngine destroyed the passed in RAT
/// </summary>
/// <param name="indexOfMemory">Index of the target memory</param>
/// Helper function that selects a memory from the vector and set it to CCalcEngine
/// Saved RAT number needs to be copied and passed in, as CCalcEngine destroyed the passed in RAT
/// </summary>
/// <param name="indexOfMemory">Index of the target memory</param>
void CalculatorManager::MemorizedNumberSelect(_In_ unsigned int indexOfMemory)
{
if (m_currentCalculatorEngine->FInErrorState())
@ -673,9 +672,7 @@ namespace CalculationManager
vector<shared_ptr<HISTORYITEM>> const& CalculatorManager::GetHistoryItems(_In_ CALCULATOR_MODE mode)
{
return (mode == CM_STD) ?
m_pStdHistory->GetHistory() :
m_pSciHistory->GetHistory();
return (mode == CM_STD) ? m_pStdHistory->GetHistory() : m_pSciHistory->GetHistory();
}
shared_ptr<HISTORYITEM> const& CalculatorManager::GetHistoryItem(_In_ unsigned int uIdx)

View file

@ -91,7 +91,8 @@ namespace CalculationManager
// ICalcDisplay
void SetPrimaryDisplay(_In_ const std::wstring& displayString, _In_ bool isError) override;
void SetIsInError(bool isError) override;
void SetExpressionDisplay(_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const &tokens, _Inout_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const &commands) override;
void SetExpressionDisplay(_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const& tokens,
_Inout_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const& commands) override;
void SetMemorizedNumbers(_In_ const std::vector<std::wstring>& memorizedNumbers) override;
void OnHistoryItemAdded(_In_ unsigned int addedItemIndex) override;
void SetParenthesisNumber(_In_ unsigned int parenthesisCount) override;
@ -101,7 +102,6 @@ namespace CalculationManager
void BinaryOperatorReceived() override;
void MemoryItemChanged(unsigned int indexOfMemory) override;
CalculatorManager(ICalcDisplay* displayCallback, IResourceProvider* resourceProvider);
~CalculatorManager();
@ -114,10 +114,10 @@ namespace CalculationManager
void DeSerializeCommands(_In_ const std::vector<unsigned char>& serializedData);
void SerializeMemory();
std::vector<long> GetSerializedMemory();
void DeSerializeMemory(const std::vector<long> &serializedMemory);
void DeSerializeMemory(const std::vector<long>& serializedMemory);
void SerializePrimaryDisplay();
std::vector<long> GetSerializedPrimaryDisplay();
void DeSerializePrimaryDisplay(const std::vector<long> &serializedPrimaryDisplay);
void DeSerializePrimaryDisplay(const std::vector<long>& serializedPrimaryDisplay);
Command SerializeSavedDegreeMode();
void MemorizeNumber();
@ -128,7 +128,10 @@ namespace CalculationManager
void MemorizedNumberClearAll();
bool IsEngineRecording();
std::vector<unsigned char> GetSavedCommands(){ return m_savedCommands; }
std::vector<unsigned char> GetSavedCommands()
{
return m_savedCommands;
}
void SetRadix(RADIX_TYPE iRadixType);
void SetMemorizedNumbersString();
std::wstring GetResultForRadix(uint32_t radix, int32_t precision);
@ -141,7 +144,10 @@ namespace CalculationManager
std::shared_ptr<HISTORYITEM> const& GetHistoryItem(_In_ unsigned int uIdx);
bool RemoveHistoryItem(_In_ unsigned int uIdx);
void ClearHistory();
size_t MaxHistorySize() const { return m_pHistory->MaxHistorySize(); }
size_t MaxHistorySize() const
{
return m_pHistory->MaxHistorySize();
}
CalculationManager::Command GetCurrentDegreeMode();
void SetHistory(_In_ CALCULATOR_MODE eMode, _In_ std::vector<std::shared_ptr<HISTORYITEM>> const& history);
void SetInHistoryItemLoadMode(_In_ bool isHistoryItemLoadMode);

View file

@ -8,7 +8,9 @@ namespace CalculationManager
class IResourceProvider
{
public:
virtual ~IResourceProvider() { }
virtual ~IResourceProvider()
{
}
// Should return a string from the resource table for strings used
// by the calculation engine. The strings that must be defined

View file

@ -8,13 +8,13 @@
#include <winerror.h>
#include "Ratpack/CalcErr.h"
#include <stdexcept> // for std::out_of_range
#include <sal.h> // for SAL
#include <sal.h> // for SAL
template <typename TType>
class CalculatorVector
{
public:
ResultCode GetAt(_In_opt_ unsigned int index, _Out_ TType *item)
ResultCode GetAt(_In_opt_ unsigned int index, _Out_ TType* item)
{
ResultCode hr = S_OK;
try
@ -28,7 +28,7 @@ public:
return hr;
}
ResultCode GetSize(_Out_ unsigned int *size)
ResultCode GetSize(_Out_ unsigned int* size)
{
*size = static_cast<unsigned>(m_vector.size());
return S_OK;
@ -122,7 +122,7 @@ public:
{
ResultCode hr = S_OK;
unsigned int nTokens = 0;
std::pair <std::wstring, int> currentPair;
std::pair<std::wstring, int> currentPair;
hr = this->GetSize(&nTokens);
if (SUCCEEDED(hr))
{

View file

@ -7,9 +7,19 @@ namespace UnitConversionManager
{
enum class Command
{
Zero, One, Two, Three, Four, Five, Six, Seven, Eight, Nine,
Zero,
One,
Two,
Three,
Four,
Five,
Six,
Seven,
Eight,
Nine,
Decimal,
Negate, Backspace,
Negate,
Backspace,
Clear,
Reset,
None
@ -20,9 +30,19 @@ namespace CurrencyConversionManager
{
enum class Command
{
Zero, One, Two, Three, Four, Five, Six, Seven, Eight, Nine,
Zero,
One,
Two,
Three,
Four,
Five,
Six,
Seven,
Eight,
Nine,
Decimal,
Negate, Backspace,
Negate,
Backspace,
Clear,
None
};
@ -73,7 +93,7 @@ namespace CalculationManager
CommandROOT = 96,
CommandPWR = 97,
CommandCHOP = 98, // Unary operators must be between CommandCHOP and CommandEQU
CommandCHOP = 98, // Unary operators must be between CommandCHOP and CommandEQU
CommandROL = 99,
CommandROR = 100,
CommandCOM = 101,
@ -85,7 +105,6 @@ namespace CalculationManager
CommandCOSH = 106,
CommandTANH = 107,
CommandLN = 108,
CommandLOG = 109,
CommandSQRT = 110,
@ -94,8 +113,8 @@ namespace CalculationManager
CommandFAC = 113,
CommandREC = 114,
CommandDMS = 115,
CommandCUBEROOT = 116, // x ^ 1/3
CommandPOW10 = 117, // 10 ^ x
CommandCUBEROOT = 116, // x ^ 1/3
CommandPOW10 = 117, // 10 ^ x
CommandPERCENT = 118,
CommandFE = 119,
@ -113,7 +132,7 @@ namespace CalculationManager
CommandOPENP = 128,
CommandCLOSEP = 129,
Command0 = 130, // The controls for 0 through F must be consecutive and in order
Command0 = 130, // The controls for 0 through F must be consecutive and in order
Command1 = 131,
Command2 = 132,
Command3 = 133,
@ -128,7 +147,7 @@ namespace CalculationManager
CommandC = 142,
CommandD = 143,
CommandE = 144,
CommandF = 145, // this is last control ID which must match the string table
CommandF = 145, // this is last control ID which must match the string table
CommandINV = 146,
CommandSET_RESULT = 147,

View file

@ -13,8 +13,9 @@ constexpr wchar_t chNegate = L'-';
constexpr wchar_t chExp = L'e';
constexpr wchar_t chPlus = L'+';
CParentheses::CParentheses(_In_ int command) :m_command(command)
{}
CParentheses::CParentheses(_In_ int command) : m_command(command)
{
}
int CParentheses::GetCommand() const
{
@ -26,7 +27,7 @@ CalculationManager::CommandType CParentheses::GetCommandType() const
return CalculationManager::CommandType::Parentheses;
}
void CParentheses::Accept(_In_ ISerializeCommandVisitor &commandVisitor)
void CParentheses::Accept(_In_ ISerializeCommandVisitor& commandVisitor)
{
commandVisitor.Visit(*this);
}
@ -44,7 +45,7 @@ CUnaryCommand::CUnaryCommand(int command1, int command2)
m_command->Append(command2);
}
const shared_ptr<CalculatorVector<int>> & CUnaryCommand::GetCommands() const
const shared_ptr<CalculatorVector<int>>& CUnaryCommand::GetCommands() const
{
return m_command;
}
@ -67,13 +68,14 @@ void CUnaryCommand::SetCommands(int command1, int command2)
m_command->Append(command2);
}
void CUnaryCommand::Accept(_In_ ISerializeCommandVisitor &commandVisitor)
void CUnaryCommand::Accept(_In_ ISerializeCommandVisitor& commandVisitor)
{
commandVisitor.Visit(*this);
}
CBinaryCommand::CBinaryCommand(int command) :m_command(command)
{}
CBinaryCommand::CBinaryCommand(int command) : m_command(command)
{
}
void CBinaryCommand::SetCommand(int command)
{
@ -90,19 +92,15 @@ CalculationManager::CommandType CBinaryCommand::GetCommandType() const
return CalculationManager::CommandType::BinaryCommand;
}
void CBinaryCommand::Accept(_In_ ISerializeCommandVisitor &commandVisitor)
void CBinaryCommand::Accept(_In_ ISerializeCommandVisitor& commandVisitor)
{
commandVisitor.Visit(*this);
}
COpndCommand::COpndCommand(shared_ptr<CalculatorVector<int>> const &commands, bool fNegative, bool fDecimal, bool fSciFmt) :
m_commands(commands),
m_fNegative(fNegative),
m_fSciFmt(fSciFmt),
m_fDecimal(fDecimal),
m_fInitialized(false),
m_value{}
{}
COpndCommand::COpndCommand(shared_ptr<CalculatorVector<int>> const& commands, bool fNegative, bool fDecimal, bool fSciFmt)
: m_commands(commands), m_fNegative(fNegative), m_fSciFmt(fSciFmt), m_fDecimal(fDecimal), m_fInitialized(false), m_value{}
{
}
void COpndCommand::Initialize(Rational const& rat)
{
@ -110,7 +108,7 @@ void COpndCommand::Initialize(Rational const& rat)
m_fInitialized = true;
}
const shared_ptr<CalculatorVector<int>> & COpndCommand::GetCommands() const
const shared_ptr<CalculatorVector<int>>& COpndCommand::GetCommands() const
{
return m_commands;
}
@ -213,7 +211,7 @@ void COpndCommand::ClearAllAndAppendCommand(CalculationManager::Command command)
m_fDecimal = false;
}
const wstring & COpndCommand::GetToken(wchar_t decimalSymbol)
const wstring& COpndCommand::GetToken(wchar_t decimalSymbol)
{
static const wchar_t chZero = L'0';
@ -299,7 +297,7 @@ wstring COpndCommand::GetString(uint32_t radix, int32_t precision)
return result;
}
void COpndCommand::Accept(_In_ ISerializeCommandVisitor &commandVisitor)
void COpndCommand::Accept(_In_ ISerializeCommandVisitor& commandVisitor)
{
commandVisitor.Visit(*this);
}

View file

@ -12,7 +12,7 @@ public:
CParentheses(_In_ int command);
int GetCommand() const override;
CalculationManager::CommandType GetCommandType() const override;
void Accept(_In_ ISerializeCommandVisitor &commandVisitor) override;
void Accept(_In_ ISerializeCommandVisitor& commandVisitor) override;
private:
int m_command;
@ -23,11 +23,11 @@ class CUnaryCommand final : public IUnaryCommand
public:
CUnaryCommand(int command);
CUnaryCommand(int command1, int command2);
const std::shared_ptr<CalculatorVector<int>> & GetCommands() const override;
const std::shared_ptr<CalculatorVector<int>>& GetCommands() const override;
CalculationManager::CommandType GetCommandType() const override;
void SetCommand(int command) override;
void SetCommands(int command1, int command2) override;
void Accept(_In_ ISerializeCommandVisitor &commandVisitor) override;
void Accept(_In_ ISerializeCommandVisitor& commandVisitor) override;
private:
std::shared_ptr<CalculatorVector<int>> m_command;
@ -40,7 +40,7 @@ public:
void SetCommand(int command) override;
int GetCommand() const override;
CalculationManager::CommandType GetCommandType() const override;
void Accept(_In_ ISerializeCommandVisitor &commandVisitor) override;
void Accept(_In_ ISerializeCommandVisitor& commandVisitor) override;
private:
int m_command;
@ -49,14 +49,10 @@ private:
class COpndCommand final : public IOpndCommand
{
public:
COpndCommand(
std::shared_ptr<CalculatorVector<int>> const &commands,
bool fNegative,
bool fDecimal,
bool fSciFmt);
COpndCommand(std::shared_ptr<CalculatorVector<int>> const& commands, bool fNegative, bool fDecimal, bool fSciFmt);
void Initialize(CalcEngine::Rational const& rat);
const std::shared_ptr<CalculatorVector<int>> & GetCommands() const override;
const std::shared_ptr<CalculatorVector<int>>& GetCommands() const override;
void SetCommands(std::shared_ptr<CalculatorVector<int>> const& commands) override;
void AppendCommand(int command) override;
void ToggleSign() override;
@ -64,9 +60,9 @@ public:
bool IsNegative() const override;
bool IsSciFmt() const override;
bool IsDecimalPresent() const override;
const std::wstring & GetToken(wchar_t decimalSymbol) override;
const std::wstring& GetToken(wchar_t decimalSymbol) override;
CalculationManager::CommandType GetCommandType() const override;
void Accept(_In_ ISerializeCommandVisitor &commandVisitor) override;
void Accept(_In_ ISerializeCommandVisitor& commandVisitor) override;
std::wstring GetString(uint32_t radix, int32_t precision);
private:
@ -83,8 +79,8 @@ private:
class ISerializeCommandVisitor
{
public:
virtual void Visit(_In_ COpndCommand &opndCmd) = 0;
virtual void Visit(_In_ CUnaryCommand &unaryCmd) = 0;
virtual void Visit(_In_ CBinaryCommand &binaryCmd) = 0;
virtual void Visit(_In_ CParentheses &paraCmd) = 0;
virtual void Visit(_In_ COpndCommand& opndCmd) = 0;
virtual void Visit(_In_ CUnaryCommand& unaryCmd) = 0;
virtual void Visit(_In_ CBinaryCommand& binaryCmd) = 0;
virtual void Visit(_In_ CParentheses& paraCmd) = 0;
};

View file

@ -13,7 +13,7 @@ class IExpressionCommand
{
public:
virtual CalculationManager::CommandType GetCommandType() const = 0;
virtual void Accept(_In_ ISerializeCommandVisitor &commandVisitor) = 0;
virtual void Accept(_In_ ISerializeCommandVisitor& commandVisitor) = 0;
};
class IOperatorCommand : public IExpressionCommand
@ -25,7 +25,7 @@ public:
class IUnaryCommand : public IOperatorCommand
{
public:
virtual const std::shared_ptr<CalculatorVector<int>> & GetCommands() const = 0;
virtual const std::shared_ptr<CalculatorVector<int>>& GetCommands() const = 0;
virtual void SetCommands(int command1, int command2) = 0;
};
@ -39,14 +39,14 @@ public:
class IOpndCommand : public IExpressionCommand
{
public:
virtual const std::shared_ptr<CalculatorVector<int>> & GetCommands() const= 0;
virtual const std::shared_ptr<CalculatorVector<int>>& GetCommands() const = 0;
virtual void AppendCommand(int command) = 0;
virtual void ToggleSign() = 0;
virtual void RemoveFromEnd() = 0;
virtual bool IsNegative() const = 0;
virtual bool IsSciFmt() const = 0;
virtual bool IsDecimalPresent() const = 0;
virtual const std::wstring & GetToken(wchar_t decimalSymbol) = 0;
virtual const std::wstring& GetToken(wchar_t decimalSymbol) = 0;
virtual void SetCommands(std::shared_ptr<CalculatorVector<int>> const& commands) = 0;
};

View file

@ -17,34 +17,33 @@
// The following are the valid id's which can be passed to CCalcEngine::ProcessCommand
#define IDM_HEX 313
#define IDM_DEC 314
#define IDM_OCT 315
#define IDM_BIN 316
#define IDM_QWORD 317
#define IDM_DWORD 318
#define IDM_WORD 319
#define IDM_BYTE 320
#define IDM_DEG 321
#define IDM_RAD 322
#define IDM_GRAD 323
#define IDM_DEGREES 324
#define IDM_HEX 313
#define IDM_DEC 314
#define IDM_OCT 315
#define IDM_BIN 316
#define IDM_QWORD 317
#define IDM_DWORD 318
#define IDM_WORD 319
#define IDM_BYTE 320
#define IDM_DEG 321
#define IDM_RAD 322
#define IDM_GRAD 323
#define IDM_DEGREES 324
#define IDC_HEX IDM_HEX
#define IDC_DEC IDM_DEC
#define IDC_OCT IDM_OCT
#define IDC_BIN IDM_BIN
#define IDC_HEX IDM_HEX
#define IDC_DEC IDM_DEC
#define IDC_OCT IDM_OCT
#define IDC_BIN IDM_BIN
#define IDC_DEG IDM_DEG
#define IDC_RAD IDM_RAD
#define IDC_GRAD IDM_GRAD
#define IDC_DEGREES IDM_DEGREES
#define IDC_QWORD IDM_QWORD
#define IDC_DWORD IDM_DWORD
#define IDC_WORD IDM_WORD
#define IDC_BYTE IDM_BYTE
#define IDC_DEG IDM_DEG
#define IDC_RAD IDM_RAD
#define IDC_GRAD IDM_GRAD
#define IDC_DEGREES IDM_DEGREES
#define IDC_QWORD IDM_QWORD
#define IDC_DWORD IDM_DWORD
#define IDC_WORD IDM_WORD
#define IDC_BYTE IDM_BYTE
// Key IDs:
// These id's must be consecutive from IDC_FIRSTCONTROL to IDC_LASTCONTROL.
@ -55,162 +54,158 @@
// Find the string id for that control from the rc file
// Now define the control's id as IDC_FRISTCONTROL+stringID(IDC_ST_AVE)
#define IDC_FIRSTCONTROL IDC_SIGN
#define IDC_SIGN 80
#define IDC_CLEAR 81
#define IDC_CENTR 82
#define IDC_BACK 83
#define IDC_SIGN 80
#define IDC_CLEAR 81
#define IDC_CENTR 82
#define IDC_BACK 83
#define IDC_PNT 84
#define IDC_PNT 84
// Hole 85
#define IDC_AND 86 // Binary operators must be between IDC_AND and IDC_PWR
#define IDC_OR 87
#define IDC_XOR 88
#define IDC_LSHF 89
#define IDC_RSHF 90
#define IDC_DIV 91
#define IDC_MUL 92
#define IDC_ADD 93
#define IDC_SUB 94
#define IDC_MOD 95
#define IDC_ROOT 96
#define IDC_PWR 97
#define IDC_AND 86 // Binary operators must be between IDC_AND and IDC_PWR
#define IDC_OR 87
#define IDC_XOR 88
#define IDC_LSHF 89
#define IDC_RSHF 90
#define IDC_DIV 91
#define IDC_MUL 92
#define IDC_ADD 93
#define IDC_SUB 94
#define IDC_MOD 95
#define IDC_ROOT 96
#define IDC_PWR 97
#define IDC_UNARYFIRST IDC_CHOP
#define IDC_CHOP 98 // Unary operators must be between IDC_CHOP and IDC_EQU
#define IDC_ROL 99
#define IDC_ROR 100
#define IDC_COM 101
#define IDC_SIN 102
#define IDC_COS 103
#define IDC_TAN 104
#define IDC_UNARYFIRST IDC_CHOP
#define IDC_CHOP 98 // Unary operators must be between IDC_CHOP and IDC_EQU
#define IDC_ROL 99
#define IDC_ROR 100
#define IDC_COM 101
#define IDC_SIN 102
#define IDC_COS 103
#define IDC_TAN 104
#define IDC_SINH 105
#define IDC_COSH 106
#define IDC_TANH 107
#define IDC_SINH 105
#define IDC_COSH 106
#define IDC_TANH 107
#define IDC_LN 108
#define IDC_LOG 109
#define IDC_SQRT 110
#define IDC_SQR 111
#define IDC_CUB 112
#define IDC_FAC 113
#define IDC_REC 114
#define IDC_DMS 115
#define IDC_CUBEROOT 116 // x ^ 1/3
#define IDC_POW10 117 // 10 ^ x
#define IDC_PERCENT 118
#define IDC_LN 108
#define IDC_LOG 109
#define IDC_SQRT 110
#define IDC_SQR 111
#define IDC_CUB 112
#define IDC_FAC 113
#define IDC_REC 114
#define IDC_DMS 115
#define IDC_CUBEROOT 116 // x ^ 1/3
#define IDC_POW10 117 // 10 ^ x
#define IDC_PERCENT 118
#define IDC_UNARYLAST IDC_PERCENT
#define IDC_FE 119
#define IDC_PI 120
#define IDC_EQU 121
#define IDC_FE 119
#define IDC_PI 120
#define IDC_EQU 121
#define IDC_MCLEAR 122
#define IDC_RECALL 123
#define IDC_STORE 124
#define IDC_MPLUS 125
#define IDC_MMINUS 126
#define IDC_MCLEAR 122
#define IDC_RECALL 123
#define IDC_STORE 124
#define IDC_MPLUS 125
#define IDC_MMINUS 126
#define IDC_EXP 127
#define IDC_EXP 127
#define IDC_OPENP 128
#define IDC_CLOSEP 129
#define IDC_OPENP 128
#define IDC_CLOSEP 129
#define IDC_0 130 // The controls for 0 through F must be consecutive and in order
#define IDC_1 131
#define IDC_2 132
#define IDC_3 133
#define IDC_4 134
#define IDC_5 135
#define IDC_6 136
#define IDC_7 137
#define IDC_8 138
#define IDC_9 139
#define IDC_A 140
#define IDC_B 141
#define IDC_C 142
#define IDC_D 143
#define IDC_E 144
#define IDC_F 145 // this is last control ID which must match the string table
#define IDC_INV 146
#define IDC_SET_RESULT 147
#define IDC_0 130 // The controls for 0 through F must be consecutive and in order
#define IDC_1 131
#define IDC_2 132
#define IDC_3 133
#define IDC_4 134
#define IDC_5 135
#define IDC_6 136
#define IDC_7 137
#define IDC_8 138
#define IDC_9 139
#define IDC_A 140
#define IDC_B 141
#define IDC_C 142
#define IDC_D 143
#define IDC_E 144
#define IDC_F 145 // this is last control ID which must match the string table
#define IDC_INV 146
#define IDC_SET_RESULT 147
#define IDC_LASTCONTROL IDC_SET_RESULT
#define IDC_BINEDITSTART 700
#define IDC_BINPOS0 700
#define IDC_BINPOS1 701
#define IDC_BINPOS2 702
#define IDC_BINPOS3 703
#define IDC_BINPOS4 704
#define IDC_BINPOS5 705
#define IDC_BINPOS6 706
#define IDC_BINPOS7 707
#define IDC_BINPOS8 708
#define IDC_BINPOS9 709
#define IDC_BINPOS10 710
#define IDC_BINPOS11 711
#define IDC_BINPOS12 712
#define IDC_BINPOS13 713
#define IDC_BINPOS14 714
#define IDC_BINPOS15 715
#define IDC_BINPOS16 716
#define IDC_BINPOS17 717
#define IDC_BINPOS18 718
#define IDC_BINPOS19 719
#define IDC_BINPOS20 720
#define IDC_BINPOS21 721
#define IDC_BINPOS22 722
#define IDC_BINPOS23 723
#define IDC_BINPOS24 724
#define IDC_BINPOS25 725
#define IDC_BINPOS26 726
#define IDC_BINPOS27 727
#define IDC_BINPOS28 728
#define IDC_BINPOS29 729
#define IDC_BINPOS30 730
#define IDC_BINPOS31 731
#define IDC_BINPOS32 732
#define IDC_BINPOS33 733
#define IDC_BINPOS34 734
#define IDC_BINPOS35 735
#define IDC_BINPOS36 736
#define IDC_BINPOS37 737
#define IDC_BINPOS38 738
#define IDC_BINPOS39 739
#define IDC_BINPOS40 740
#define IDC_BINPOS41 741
#define IDC_BINPOS42 742
#define IDC_BINPOS43 743
#define IDC_BINPOS44 744
#define IDC_BINPOS45 745
#define IDC_BINPOS46 746
#define IDC_BINPOS47 747
#define IDC_BINPOS48 748
#define IDC_BINPOS49 749
#define IDC_BINPOS50 750
#define IDC_BINPOS51 751
#define IDC_BINPOS52 752
#define IDC_BINPOS53 753
#define IDC_BINPOS54 754
#define IDC_BINPOS55 755
#define IDC_BINPOS56 756
#define IDC_BINPOS57 757
#define IDC_BINPOS58 758
#define IDC_BINPOS59 759
#define IDC_BINPOS60 760
#define IDC_BINPOS61 761
#define IDC_BINPOS62 762
#define IDC_BINPOS63 763
#define IDC_BINEDITEND 763
#define IDC_BINEDITSTART 700
#define IDC_BINPOS0 700
#define IDC_BINPOS1 701
#define IDC_BINPOS2 702
#define IDC_BINPOS3 703
#define IDC_BINPOS4 704
#define IDC_BINPOS5 705
#define IDC_BINPOS6 706
#define IDC_BINPOS7 707
#define IDC_BINPOS8 708
#define IDC_BINPOS9 709
#define IDC_BINPOS10 710
#define IDC_BINPOS11 711
#define IDC_BINPOS12 712
#define IDC_BINPOS13 713
#define IDC_BINPOS14 714
#define IDC_BINPOS15 715
#define IDC_BINPOS16 716
#define IDC_BINPOS17 717
#define IDC_BINPOS18 718
#define IDC_BINPOS19 719
#define IDC_BINPOS20 720
#define IDC_BINPOS21 721
#define IDC_BINPOS22 722
#define IDC_BINPOS23 723
#define IDC_BINPOS24 724
#define IDC_BINPOS25 725
#define IDC_BINPOS26 726
#define IDC_BINPOS27 727
#define IDC_BINPOS28 728
#define IDC_BINPOS29 729
#define IDC_BINPOS30 730
#define IDC_BINPOS31 731
#define IDC_BINPOS32 732
#define IDC_BINPOS33 733
#define IDC_BINPOS34 734
#define IDC_BINPOS35 735
#define IDC_BINPOS36 736
#define IDC_BINPOS37 737
#define IDC_BINPOS38 738
#define IDC_BINPOS39 739
#define IDC_BINPOS40 740
#define IDC_BINPOS41 741
#define IDC_BINPOS42 742
#define IDC_BINPOS43 743
#define IDC_BINPOS44 744
#define IDC_BINPOS45 745
#define IDC_BINPOS46 746
#define IDC_BINPOS47 747
#define IDC_BINPOS48 748
#define IDC_BINPOS49 749
#define IDC_BINPOS50 750
#define IDC_BINPOS51 751
#define IDC_BINPOS52 752
#define IDC_BINPOS53 753
#define IDC_BINPOS54 754
#define IDC_BINPOS55 755
#define IDC_BINPOS56 756
#define IDC_BINPOS57 757
#define IDC_BINPOS58 758
#define IDC_BINPOS59 759
#define IDC_BINPOS60 760
#define IDC_BINPOS61 761
#define IDC_BINPOS62 762
#define IDC_BINPOS63 763
#define IDC_BINEDITEND 763
// The strings in the following range IDS_ENGINESTR_FIRST ... IDS_ENGINESTR_MAX are strings allocated in the
// resource for the purpose internal to Engine and cant be used by the clients
#define IDS_ENGINESTR_FIRST 0
#define IDS_ENGINESTR_MAX 200
#define IDS_ENGINESTR_FIRST 0
#define IDS_ENGINESTR_MAX 200

View file

@ -20,7 +20,7 @@
#include "../CalculatorVector.h"
#include "../ExpressionCommand.h"
#include "RadixType.h"
#include "History.h" // for History Collector
#include "History.h" // for History Collector
#include "CalcInput.h"
#include "CalcUtils.h"
#include "ICalcDisplay.h"
@ -31,11 +31,12 @@
// The real exports follows later
// This is expected to be in same order as IDM_QWORD, IDM_DWORD etc.
enum eNUM_WIDTH {
QWORD_WIDTH, // Number width of 64 bits mode (default)
DWORD_WIDTH, // Number width of 32 bits mode
WORD_WIDTH, // Number width of 16 bits mode
BYTE_WIDTH // Number width of 16 bits mode
enum eNUM_WIDTH
{
QWORD_WIDTH, // Number width of 64 bits mode (default)
DWORD_WIDTH, // Number width of 32 bits mode
WORD_WIDTH, // Number width of 16 bits mode
BYTE_WIDTH // Number width of 16 bits mode
};
typedef enum eNUM_WIDTH NUM_WIDTH;
static constexpr size_t NUM_WIDTH_LENGTH = 4;
@ -50,58 +51,80 @@ namespace CalculatorEngineTests
class CalcEngineTests;
}
class CCalcEngine {
class CCalcEngine
{
public:
CCalcEngine(bool fPrecedence, bool fIntegerMode, CalculationManager::IResourceProvider* const pResourceProvider, __in_opt ICalcDisplay *pCalcDisplay, __in_opt std::shared_ptr<IHistoryDisplay> pHistoryDisplay);
CCalcEngine(bool fPrecedence, bool fIntegerMode, CalculationManager::IResourceProvider* const pResourceProvider, __in_opt ICalcDisplay* pCalcDisplay,
__in_opt std::shared_ptr<IHistoryDisplay> pHistoryDisplay);
void ProcessCommand(OpCode wID);
void DisplayError (uint32_t nError);
void DisplayError(uint32_t nError);
std::unique_ptr<CalcEngine::Rational> PersistedMemObject();
void PersistedMemObject(CalcEngine::Rational const& memObject);
bool FInErrorState() { return m_bError; }
bool FInRecordingState() { return m_bRecord; }
bool FInErrorState()
{
return m_bError;
}
bool FInRecordingState()
{
return m_bRecord;
}
void SettingsChanged();
bool IsCurrentTooBigForTrig();
int GetCurrentRadix();
std::wstring GetCurrentResultForRadix(uint32_t radix, int32_t precision);
void ChangePrecision(int32_t precision) { m_precision = precision; ChangeConstants(m_radix, precision); }
void ChangePrecision(int32_t precision)
{
m_precision = precision;
ChangeConstants(m_radix, precision);
}
std::wstring GroupDigitsPerRadix(std::wstring_view numberString, uint32_t radix);
std::wstring GetStringForDisplay(CalcEngine::Rational const& rat, uint32_t radix);
void UpdateMaxIntDigits();
wchar_t DecimalSeparator() const;
// Static methods for the instance
static void InitialOneTimeOnlySetup(CalculationManager::IResourceProvider& resourceProvider); // Once per load time to call to initialize all shared global variables
static void
InitialOneTimeOnlySetup(CalculationManager::IResourceProvider& resourceProvider); // Once per load time to call to initialize all shared global variables
// returns the ptr to string representing the operator. Mostly same as the button, but few special cases for x^y etc.
static std::wstring_view GetString(int ids) { return s_engineStrings[std::to_wstring(ids)]; }
static std::wstring_view GetString(std::wstring ids) { return s_engineStrings[ids]; }
static std::wstring_view OpCodeToString(int nOpCode) { return GetString(IdStrFromCmdId(nOpCode)); }
static std::wstring_view GetString(int ids)
{
return s_engineStrings[std::to_wstring(ids)];
}
static std::wstring_view GetString(std::wstring ids)
{
return s_engineStrings[ids];
}
static std::wstring_view OpCodeToString(int nOpCode)
{
return GetString(IdStrFromCmdId(nOpCode));
}
static std::wstring_view OpCodeToUnaryString(int nOpCode, bool fInv, ANGLE_TYPE angletype);
private:
bool m_fPrecedence;
bool m_fIntegerMode; /* This is true if engine is explicitly called to be in integer mode. All bases are restricted to be in integers only */
ICalcDisplay *m_pCalcDisplay;
ICalcDisplay* m_pCalcDisplay;
CalculationManager::IResourceProvider* const m_resourceProvider;
int m_nOpCode; /* ID value of operation. */
int m_nOpCode; /* ID value of operation. */
int m_nPrevOpCode; // opcode which computed the number in m_currentVal. 0 if it is already bracketed or plain number or
// if it hasn't yet been computed
bool m_bChangeOp; /* Flag for changing operation. */
bool m_bRecord; // Global mode: recording or displaying
bool m_bSetCalcState; // Flag for setting the engine result state
bool m_bChangeOp; /* Flag for changing operation. */
bool m_bRecord; // Global mode: recording or displaying
bool m_bSetCalcState; // Flag for setting the engine result state
CalcEngine::CalcInput m_input; // Global calc input object for decimal strings
eNUMOBJ_FMT m_nFE; /* Scientific notation conversion flag. */
eNUMOBJ_FMT m_nFE; /* Scientific notation conversion flag. */
CalcEngine::Rational m_maxTrigonometricNum;
std::unique_ptr<CalcEngine::Rational> m_memoryValue; // Current memory value.
CalcEngine::Rational m_holdVal; // For holding the second operand in repetitive calculations ( pressing "=" continuously)
CalcEngine::Rational m_currentVal; // Currently displayed number used everywhere.
CalcEngine::Rational m_lastVal; // Number before operation (left operand).
std::array<CalcEngine::Rational, MAXPRECDEPTH> m_parenVals; // Holding array for parenthesis values.
CalcEngine::Rational m_currentVal; // Currently displayed number used everywhere.
CalcEngine::Rational m_lastVal; // Number before operation (left operand).
std::array<CalcEngine::Rational, MAXPRECDEPTH> m_parenVals; // Holding array for parenthesis values.
std::array<CalcEngine::Rational, MAXPRECDEPTH> m_precedenceVals; // Holding array for precedence values.
bool m_bError; // Error flag.
bool m_bInv; // Inverse on/off flag.
bool m_bNoPrevEqu; /* Flag for previous equals. */
bool m_bError; // Error flag.
bool m_bInv; // Inverse on/off flag.
bool m_bNoPrevEqu; /* Flag for previous equals. */
uint32_t m_radix;
int32_t m_precision;
@ -110,20 +133,20 @@ private:
std::wstring m_numberString;
int m_nTempCom; /* Holding place for the last command. */
int m_openParenCount; // Number of open parentheses.
std::array<int, MAXPRECDEPTH> m_nOp; /* Holding array for parenthesis operations. */
std::array<int, MAXPRECDEPTH> m_nPrecOp; /* Holding array for precedence operations. */
size_t m_precedenceOpCount; /* Current number of precedence ops in holding. */
int m_nLastCom; // Last command entered.
ANGLE_TYPE m_angletype; // Current Angle type when in dec mode. one of deg, rad or grad
NUM_WIDTH m_numwidth; // one of qword, dword, word or byte mode.
int32_t m_dwWordBitWidth; // # of bits in currently selected word size
int m_nTempCom; /* Holding place for the last command. */
int m_openParenCount; // Number of open parentheses.
std::array<int, MAXPRECDEPTH> m_nOp; /* Holding array for parenthesis operations. */
std::array<int, MAXPRECDEPTH> m_nPrecOp; /* Holding array for precedence operations. */
size_t m_precedenceOpCount; /* Current number of precedence ops in holding. */
int m_nLastCom; // Last command entered.
ANGLE_TYPE m_angletype; // Current Angle type when in dec mode. one of deg, rad or grad
NUM_WIDTH m_numwidth; // one of qword, dword, word or byte mode.
int32_t m_dwWordBitWidth; // # of bits in currently selected word size
CHistoryCollector m_HistoryCollector; // Accumulator of each line of history as various commands are processed
std::array<CalcEngine::Rational, NUM_WIDTH_LENGTH> m_chopNumbers; // word size enforcement
std::array<std::wstring, NUM_WIDTH_LENGTH> m_maxDecimalValueStrings; // maximum values represented by a given word width based off m_chopNumbers
std::array<CalcEngine::Rational, NUM_WIDTH_LENGTH> m_chopNumbers; // word size enforcement
std::array<std::wstring, NUM_WIDTH_LENGTH> m_maxDecimalValueStrings; // maximum values represented by a given word width based off m_chopNumbers
static std::unordered_map<std::wstring, std::wstring> s_engineStrings; // the string table shared across all instances
wchar_t m_decimalSeparator;
wchar_t m_groupSeparator;
@ -143,7 +166,7 @@ private:
CalcEngine::Rational DoOperation(int operation, CalcEngine::Rational const& lhs, CalcEngine::Rational const& rhs);
void SetRadixTypeAndNumWidth(RADIX_TYPE radixtype, NUM_WIDTH numwidth);
int32_t DwWordBitWidthFromeNumWidth(NUM_WIDTH numwidth);
uint32_t NRadixFromRadixType( RADIX_TYPE radixtype);
uint32_t NRadixFromRadixType(RADIX_TYPE radixtype);
bool TryToggleBit(CalcEngine::Rational& rat, uint32_t wbitno);
void CheckAndAddLastBinOpToHistory(bool addToHistory = true);
@ -151,7 +174,10 @@ private:
void InitChopNumbers();
static void LoadEngineStrings(CalculationManager::IResourceProvider& resourceProvider);
static int IdStrFromCmdId(int id) { return id - IDC_FIRSTCONTROL + IDS_ENGINESTR_FIRST; }
static int IdStrFromCmdId(int id)
{
return id - IDC_FIRSTCONTROL + IDS_ENGINESTR_FIRST;
}
static std::vector<uint32_t> DigitGroupingStringToGroupingVector(std::wstring_view groupingString);
std::wstring GroupDigits(std::wstring_view delimiter, std::vector<uint32_t> const& grouping, std::wstring_view displayString, bool isNumNegative = false);

View file

@ -13,16 +13,24 @@ namespace CalcEngine
class CalcNumSec
{
public:
CalcNumSec() :
value(),
m_isNegative(false)
{}
CalcNumSec() : value(), m_isNegative(false)
{
}
void Clear();
bool IsEmpty() { return value.empty(); }
bool IsEmpty()
{
return value.empty();
}
bool IsNegative() { return m_isNegative; }
void IsNegative(bool isNegative) { m_isNegative = isNegative; }
bool IsNegative()
{
return m_isNegative;
}
void IsNegative(bool isNegative)
{
m_isNegative = isNegative;
}
std::wstring value;
@ -34,16 +42,12 @@ namespace CalcEngine
{
public:
CalcInput() : CalcInput(L'.')
{}
{
}
CalcInput(wchar_t decSymbol) :
m_hasExponent(false),
m_hasDecimal(false),
m_decPtIndex(0),
m_decSymbol(decSymbol),
m_base(),
m_exponent()
{}
CalcInput(wchar_t decSymbol) : m_hasExponent(false), m_hasDecimal(false), m_decPtIndex(0), m_decSymbol(decSymbol), m_base(), m_exponent()
{
}
void Clear();
bool TryToggleSign(bool isIntegerMode, std::wstring_view maxNumStr);

View file

@ -171,126 +171,123 @@ inline constexpr auto SIDS_ERR_INPUT_OVERFLOW = L"119";
inline constexpr auto SIDS_ERR_OUTPUT_OVERFLOW = L"120";
// Include the resource key ID from above into this vector to load it into memory for the engine to use
inline constexpr std::array<std::wstring_view, 120> g_sids =
{
SIDS_PLUS_MINUS,
SIDS_C,
SIDS_CE,
SIDS_BACKSPACE,
SIDS_DECIMAL_SEPARATOR,
SIDS_EMPTY_STRING,
SIDS_AND,
SIDS_OR,
SIDS_XOR,
SIDS_LSH,
SIDS_RSH,
SIDS_DIVIDE,
SIDS_MULTIPLY,
SIDS_PLUS,
SIDS_MINUS,
SIDS_MOD,
SIDS_YROOT,
SIDS_POW_HAT,
SIDS_INT,
SIDS_ROL,
SIDS_ROR,
SIDS_NOT,
SIDS_SIN,
SIDS_COS,
SIDS_TAN,
SIDS_SINH,
SIDS_COSH,
SIDS_TANH,
SIDS_LN,
SIDS_LOG,
SIDS_SQRT,
SIDS_XPOW2,
SIDS_XPOW3,
SIDS_NFACTORIAL,
SIDS_RECIPROCAL,
SIDS_DMS,
SIDS_CUBEROOT,
SIDS_POWTEN,
SIDS_PERCENT,
SIDS_SCIENTIFIC_NOTATION,
SIDS_PI,
SIDS_EQUAL,
SIDS_MC,
SIDS_MR,
SIDS_MS,
SIDS_MPLUS,
SIDS_MMINUS,
SIDS_EXP,
SIDS_OPEN_PAREN,
SIDS_CLOSE_PAREN,
SIDS_0,
SIDS_1,
SIDS_2,
SIDS_3,
SIDS_4,
SIDS_5,
SIDS_6,
SIDS_7,
SIDS_8,
SIDS_9,
SIDS_A,
SIDS_B,
SIDS_C,
SIDS_D,
SIDS_E,
SIDS_F,
SIDS_FRAC,
SIDS_SIND,
SIDS_COSD,
SIDS_TAND,
SIDS_ASIND,
SIDS_ACOSD,
SIDS_ATAND,
SIDS_SINR,
SIDS_COSR,
SIDS_TANR,
SIDS_ASINR,
SIDS_ACOSR,
SIDS_ATANR,
SIDS_SING,
SIDS_COSG,
SIDS_TANG,
SIDS_ASING,
SIDS_ACOSG,
SIDS_ATANG,
SIDS_ASINH,
SIDS_ACOSH,
SIDS_ATANH,
SIDS_POWE,
SIDS_POWTEN2,
SIDS_SQRT2,
SIDS_SQR,
SIDS_CUBE,
SIDS_CUBERT,
SIDS_FACT,
SIDS_RECIPROC,
SIDS_DEGREES,
SIDS_NEGATE,
SIDS_RSH,
SIDS_DIVIDEBYZERO,
SIDS_DOMAIN,
SIDS_UNDEFINED,
SIDS_POS_INFINITY,
SIDS_NEG_INFINITY,
SIDS_ABORTED,
SIDS_NOMEM,
SIDS_TOOMANY,
SIDS_OVERFLOW,
SIDS_NORESULT,
SIDS_INSUFFICIENT_DATA,
SIDS_ERR_UNK_CH,
SIDS_ERR_UNK_FN,
SIDS_ERR_UNEX_NUM,
SIDS_ERR_UNEX_CH,
SIDS_ERR_UNEX_SZ,
SIDS_ERR_MISMATCH_CLOSE,
SIDS_ERR_UNEX_END,
SIDS_ERR_SG_INV_ERROR,
SIDS_ERR_INPUT_OVERFLOW,
SIDS_ERR_OUTPUT_OVERFLOW
};
inline constexpr std::array<std::wstring_view, 120> g_sids = { SIDS_PLUS_MINUS,
SIDS_C,
SIDS_CE,
SIDS_BACKSPACE,
SIDS_DECIMAL_SEPARATOR,
SIDS_EMPTY_STRING,
SIDS_AND,
SIDS_OR,
SIDS_XOR,
SIDS_LSH,
SIDS_RSH,
SIDS_DIVIDE,
SIDS_MULTIPLY,
SIDS_PLUS,
SIDS_MINUS,
SIDS_MOD,
SIDS_YROOT,
SIDS_POW_HAT,
SIDS_INT,
SIDS_ROL,
SIDS_ROR,
SIDS_NOT,
SIDS_SIN,
SIDS_COS,
SIDS_TAN,
SIDS_SINH,
SIDS_COSH,
SIDS_TANH,
SIDS_LN,
SIDS_LOG,
SIDS_SQRT,
SIDS_XPOW2,
SIDS_XPOW3,
SIDS_NFACTORIAL,
SIDS_RECIPROCAL,
SIDS_DMS,
SIDS_CUBEROOT,
SIDS_POWTEN,
SIDS_PERCENT,
SIDS_SCIENTIFIC_NOTATION,
SIDS_PI,
SIDS_EQUAL,
SIDS_MC,
SIDS_MR,
SIDS_MS,
SIDS_MPLUS,
SIDS_MMINUS,
SIDS_EXP,
SIDS_OPEN_PAREN,
SIDS_CLOSE_PAREN,
SIDS_0,
SIDS_1,
SIDS_2,
SIDS_3,
SIDS_4,
SIDS_5,
SIDS_6,
SIDS_7,
SIDS_8,
SIDS_9,
SIDS_A,
SIDS_B,
SIDS_C,
SIDS_D,
SIDS_E,
SIDS_F,
SIDS_FRAC,
SIDS_SIND,
SIDS_COSD,
SIDS_TAND,
SIDS_ASIND,
SIDS_ACOSD,
SIDS_ATAND,
SIDS_SINR,
SIDS_COSR,
SIDS_TANR,
SIDS_ASINR,
SIDS_ACOSR,
SIDS_ATANR,
SIDS_SING,
SIDS_COSG,
SIDS_TANG,
SIDS_ASING,
SIDS_ACOSG,
SIDS_ATANG,
SIDS_ASINH,
SIDS_ACOSH,
SIDS_ATANH,
SIDS_POWE,
SIDS_POWTEN2,
SIDS_SQRT2,
SIDS_SQR,
SIDS_CUBE,
SIDS_CUBERT,
SIDS_FACT,
SIDS_RECIPROC,
SIDS_DEGREES,
SIDS_NEGATE,
SIDS_RSH,
SIDS_DIVIDEBYZERO,
SIDS_DOMAIN,
SIDS_UNDEFINED,
SIDS_POS_INFINITY,
SIDS_NEG_INFINITY,
SIDS_ABORTED,
SIDS_NOMEM,
SIDS_TOOMANY,
SIDS_OVERFLOW,
SIDS_NORESULT,
SIDS_INSUFFICIENT_DATA,
SIDS_ERR_UNK_CH,
SIDS_ERR_UNK_FN,
SIDS_ERR_UNEX_NUM,
SIDS_ERR_UNEX_CH,
SIDS_ERR_UNEX_SZ,
SIDS_ERR_MISMATCH_CLOSE,
SIDS_ERR_UNEX_END,
SIDS_ERR_SG_INV_ERROR,
SIDS_ERR_INPUT_OVERFLOW,
SIDS_ERR_OUTPUT_OVERFLOW };

View file

@ -14,9 +14,10 @@ static constexpr size_t MAXPRECDEPTH = 25;
// Helper class really a internal class to CCalcEngine, to accumulate each history line of text by collecting the
// operands, operator, unary operator etc. Since it is a separate entity, it can be unit tested on its own but does
// rely on CCalcEngine calling it in appropriate order.
class CHistoryCollector {
class CHistoryCollector
{
public:
CHistoryCollector(ICalcDisplay *pCalcDisplay, std::shared_ptr<IHistoryDisplay> pHistoryDisplay, wchar_t decimalSymbol); // Can throw errors
CHistoryCollector(ICalcDisplay* pCalcDisplay, std::shared_ptr<IHistoryDisplay> pHistoryDisplay, wchar_t decimalSymbol); // Can throw errors
~CHistoryCollector();
void AddOpndToHistory(std::wstring_view numStr, CalcEngine::Rational const& rat, bool fRepetition = false);
void RemoveLastOpndFromHistory();
@ -31,24 +32,25 @@ public:
bool FOpndAddedToHistory();
void CompleteHistoryLine(std::wstring_view numStr);
void ClearHistoryLine(std::wstring_view errStr);
int AddCommand(_In_ const std::shared_ptr<IExpressionCommand> & spCommand);
int AddCommand(_In_ const std::shared_ptr<IExpressionCommand>& spCommand);
void UpdateHistoryExpression(uint32_t radix, int32_t precision);
void SetDecimalSymbol(wchar_t decimalSymbol);
private:
std::shared_ptr<IHistoryDisplay> m_pHistoryDisplay;
ICalcDisplay *m_pCalcDisplay;
ICalcDisplay* m_pCalcDisplay;
int m_iCurLineHistStart; // index of the beginning of the current equation
// a sort of state, set to the index before 2 after 2 in the expression 2 + 3 say. Useful for auto correct portion of history and for
// attaching the unary op around the last operand
int m_lastOpStartIndex; // index of the beginning of the last operand added to the history
int m_lastOpStartIndex; // index of the beginning of the last operand added to the history
int m_lastBinOpStartIndex; // index of the beginning of the last binary operator added to the history
std::array<int, MAXPRECDEPTH> m_operandIndices; // Stack of index of opnd's beginning for each '('. A parallel array to m_hnoParNum, but abstracted independently of that
std::array<int, MAXPRECDEPTH>
m_operandIndices; // Stack of index of opnd's beginning for each '('. A parallel array to m_hnoParNum, but abstracted independently of that
int m_curOperandIndex; // Stack index for the above stack
bool m_bLastOpndBrace; // iff the last opnd in history is already braced so we can avoid putting another one for unary operator
bool m_bLastOpndBrace; // iff the last opnd in history is already braced so we can avoid putting another one for unary operator
wchar_t m_decimalSymbol;
std::shared_ptr<CalculatorVector <std::pair<std::wstring, int>>> m_spTokens;
std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> m_spTokens;
std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> m_spCommands;
private:

View file

@ -7,11 +7,13 @@
#include "../ExpressionCommandInterface.h"
// Callback interface to be implemented by the clients of CCalcEngine
class ICalcDisplay {
class ICalcDisplay
{
public:
virtual void SetPrimaryDisplay(const std::wstring& pszText, bool isError) = 0;
virtual void SetIsInError(bool isInError) = 0;
virtual void SetExpressionDisplay(_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const &tokens, _Inout_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const &commands) = 0;
virtual void SetExpressionDisplay(_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const& tokens,
_Inout_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const& commands) = 0;
virtual void SetParenthesisNumber(_In_ unsigned int count) = 0;
virtual void OnNoRightParenAdded() = 0;
virtual void MaxDigitsReached() = 0; // not an error but still need to inform UI layer.

View file

@ -4,8 +4,11 @@
#pragma once
// Callback interface to be implemented by the clients of CCalcEngine if they require equation history
class IHistoryDisplay {
class IHistoryDisplay
{
public:
virtual ~IHistoryDisplay() {};
virtual unsigned int AddToHistory(_In_ std::shared_ptr<CalculatorVector <std::pair<std::wstring, int>>> const &tokens, _In_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const &commands, _In_ std::wstring_view result) = 0;
virtual ~IHistoryDisplay(){};
virtual unsigned int AddToHistory(_In_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const& tokens,
_In_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const& commands,
_In_ std::wstring_view result) = 0;
};

View file

@ -4,7 +4,8 @@
#pragma once
// This is expected to be in same order as IDM_HEX, IDM_DEC, IDM_OCT, IDM_BIN
enum eRADIX_TYPE {
enum eRADIX_TYPE
{
HEX_RADIX,
DEC_RADIX,
OCT_RADIX,

View file

@ -41,46 +41,45 @@ typedef int32_t ResultCode;
// CALC_E_DIVIDEBYZERO
//
// The current operation would require a divide by zero to complete
#define CALC_E_DIVIDEBYZERO ((uint32_t)0x80000000)
#define CALC_E_DIVIDEBYZERO ((uint32_t)0x80000000)
// CALC_E_DOMAIN
//
// The given input is not within the domain of this function
#define CALC_E_DOMAIN ((uint32_t)0x80000001)
#define CALC_E_DOMAIN ((uint32_t)0x80000001)
// CALC_E_INDEFINITE
//
// The result of this function is undefined
#define CALC_E_INDEFINITE ((uint32_t)0x80000002)
#define CALC_E_INDEFINITE ((uint32_t)0x80000002)
// CALC_E_POSINFINITY
//
// The result of this function is Positive Infinity.
#define CALC_E_POSINFINITY ((uint32_t)0x80000003)
#define CALC_E_POSINFINITY ((uint32_t)0x80000003)
// CALC_E_NEGINFINITY
//
// The result of this function is Negative Infinity
#define CALC_E_NEGINFINITY ((uint32_t)0x80000004)
#define CALC_E_NEGINFINITY ((uint32_t)0x80000004)
// CALC_E_INVALIDRANGE
//
// The given input is within the domain of the function but is beyond
// the range for which calc can successfully compute the answer
#define CALC_E_INVALIDRANGE ((uint32_t)0x80000006)
#define CALC_E_INVALIDRANGE ((uint32_t)0x80000006)
// CALC_E_OUTOFMEMORY
//
// There is not enough free memory to complete the requested function
#define CALC_E_OUTOFMEMORY ((uint32_t)0x80000007)
#define CALC_E_OUTOFMEMORY ((uint32_t)0x80000007)
// CALC_E_OVERFLOW
//
// The result of this operation is an overflow
#define CALC_E_OVERFLOW ((uint32_t)0x80000008)
#define CALC_E_OVERFLOW ((uint32_t)0x80000008)
// CALC_E_NORESULT
//
// The result of this operation is undefined
#define CALC_E_NORESULT ((uint32_t)0x80000009)
#define CALC_E_NORESULT ((uint32_t)0x80000009)

View file

@ -17,7 +17,7 @@
#include "ratpak.h"
#include <cstring> // for memmove
void _mulnumx( PNUMBER *pa, PNUMBER b );
void _mulnumx(PNUMBER* pa, PNUMBER b);
//----------------------------------------------------------------------------
//
@ -34,30 +34,30 @@ void _mulnumx( PNUMBER *pa, PNUMBER b );
//
//----------------------------------------------------------------------------
void __inline mulnumx( PNUMBER *pa, PNUMBER b )
void __inline mulnumx(PNUMBER* pa, PNUMBER b)
{
if ( b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0 )
{
if (b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0)
{
// If b is not one we multiply
if ( (*pa)->cdigit > 1 || (*pa)->mant[0] != 1 || (*pa)->exp != 0 )
{
if ((*pa)->cdigit > 1 || (*pa)->mant[0] != 1 || (*pa)->exp != 0)
{
// pa and b are both non-one.
_mulnumx( pa, b );
}
_mulnumx(pa, b);
}
else
{
{
// if pa is one and b isn't just copy b. and adjust the sign.
int32_t sign = (*pa)->sign;
DUPNUM(*pa,b);
DUPNUM(*pa, b);
(*pa)->sign *= sign;
}
}
}
else
{
{
// B is +/- 1, But we do have to set the sign.
(*pa)->sign *= b->sign;
}
}
}
//----------------------------------------------------------------------------
@ -76,29 +76,29 @@ void __inline mulnumx( PNUMBER *pa, PNUMBER b )
//
//----------------------------------------------------------------------------
void _mulnumx( PNUMBER *pa, PNUMBER b )
void _mulnumx(PNUMBER* pa, PNUMBER b)
{
PNUMBER c= nullptr; // c will contain the result.
PNUMBER a= nullptr; // a is the dereferenced number pointer from *pa
MANTTYPE *ptra; // ptra is a pointer to the mantissa of a.
MANTTYPE *ptrb; // ptrb is a pointer to the mantissa of b.
MANTTYPE *ptrc; // ptrc is a pointer to the mantissa of c.
MANTTYPE *ptrcoffset; // ptrcoffset, is the anchor location of the next
// single digit multiply partial result.
int32_t iadigit=0; // Index of digit being used in the first number.
int32_t ibdigit=0; // Index of digit being used in the second number.
MANTTYPE da=0; // da is the digit from the fist number.
TWO_MANTTYPE cy=0; // cy is the carry resulting from the addition of
// a multiplied row into the result.
TWO_MANTTYPE mcy=0; // mcy is the resultant from a single
// multiply, AND the carry of that multiply.
int32_t icdigit=0; // Index of digit being calculated in final result.
PNUMBER c = nullptr; // c will contain the result.
PNUMBER a = nullptr; // a is the dereferenced number pointer from *pa
MANTTYPE* ptra; // ptra is a pointer to the mantissa of a.
MANTTYPE* ptrb; // ptrb is a pointer to the mantissa of b.
MANTTYPE* ptrc; // ptrc is a pointer to the mantissa of c.
MANTTYPE* ptrcoffset; // ptrcoffset, is the anchor location of the next
// single digit multiply partial result.
int32_t iadigit = 0; // Index of digit being used in the first number.
int32_t ibdigit = 0; // Index of digit being used in the second number.
MANTTYPE da = 0; // da is the digit from the fist number.
TWO_MANTTYPE cy = 0; // cy is the carry resulting from the addition of
// a multiplied row into the result.
TWO_MANTTYPE mcy = 0; // mcy is the resultant from a single
// multiply, AND the carry of that multiply.
int32_t icdigit = 0; // Index of digit being calculated in final result.
a=*pa;
a = *pa;
ibdigit = a->cdigit + b->cdigit - 1;
createnum( c, ibdigit + 1 );
createnum(c, ibdigit + 1);
c->cdigit = ibdigit;
c->sign = a->sign * b->sign;
@ -106,36 +106,35 @@ void _mulnumx( PNUMBER *pa, PNUMBER b )
ptra = a->mant;
ptrcoffset = c->mant;
for ( iadigit = a->cdigit; iadigit > 0; iadigit-- )
for (iadigit = a->cdigit; iadigit > 0; iadigit--)
{
da = *ptra++;
da = *ptra++;
ptrb = b->mant;
// Shift ptrc, and ptrcoffset, one for each digit
ptrc = ptrcoffset++;
for ( ibdigit = b->cdigit; ibdigit > 0; ibdigit-- )
for (ibdigit = b->cdigit; ibdigit > 0; ibdigit--)
{
cy = 0;
mcy = (uint64_t)da * (*ptrb);
if ( mcy )
if (mcy)
{
icdigit = 0;
if ( ibdigit == 1 && iadigit == 1 )
if (ibdigit == 1 && iadigit == 1)
{
c->cdigit++;
}
}
// If result is nonzero, or while result of carry is nonzero...
while ( mcy || cy )
while (mcy || cy)
{
// update carry from addition(s) and multiply.
cy += (TWO_MANTTYPE)ptrc[icdigit]+((uint32_t)mcy&((uint32_t)~BASEX));
cy += (TWO_MANTTYPE)ptrc[icdigit] + ((uint32_t)mcy & ((uint32_t)~BASEX));
// update result digit from
ptrc[icdigit++]=(MANTTYPE)((uint32_t)cy&((uint32_t)~BASEX));
ptrc[icdigit++] = (MANTTYPE)((uint32_t)cy & ((uint32_t)~BASEX));
// update carries from
mcy >>= BASEXPWR;
@ -144,19 +143,18 @@ void _mulnumx( PNUMBER *pa, PNUMBER b )
ptrb++;
ptrc++;
}
}
// prevent different kinds of zeros, by stripping leading duplicate zeros.
// digits are in order of increasing significance.
while ( c->cdigit > 1 && c->mant[c->cdigit-1] == 0 )
{
while (c->cdigit > 1 && c->mant[c->cdigit - 1] == 0)
{
c->cdigit--;
}
}
destroynum( *pa );
*pa=c;
destroynum(*pa);
*pa = c;
}
//-----------------------------------------------------------------------------
//
@ -174,34 +172,33 @@ void _mulnumx( PNUMBER *pa, PNUMBER b )
//
//-----------------------------------------------------------------------------
void numpowi32x( _Inout_ PNUMBER *proot, _In_ int32_t power )
void numpowi32x(_Inout_ PNUMBER* proot, _In_ int32_t power)
{
PNUMBER lret = i32tonum( 1, BASEX );
PNUMBER lret = i32tonum(1, BASEX);
// Once the power remaining is zero we are done.
while ( power > 0 )
{
while (power > 0)
{
// If this bit in the power decomposition is on, multiply the result
// by the root number.
if ( power & 1 )
{
mulnumx( &lret, *proot );
}
if (power & 1)
{
mulnumx(&lret, *proot);
}
// multiply the root number by itself to scale for the next bit (i.e.
// square it.
mulnumx( proot, *proot );
mulnumx(proot, *proot);
// move the next bit of the power into place.
power >>= 1;
}
destroynum( *proot );
*proot=lret;
}
destroynum(*proot);
*proot = lret;
}
void _divnumx( PNUMBER *pa, PNUMBER b, int32_t precision);
void _divnumx(PNUMBER* pa, PNUMBER b, int32_t precision);
//----------------------------------------------------------------------------
//
@ -218,30 +215,30 @@ void _divnumx( PNUMBER *pa, PNUMBER b, int32_t precision);
//
//----------------------------------------------------------------------------
void __inline divnumx( PNUMBER *pa, PNUMBER b, int32_t precision)
void __inline divnumx(PNUMBER* pa, PNUMBER b, int32_t precision)
{
if ( b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0 )
{
if (b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0)
{
// b is not one.
if ( (*pa)->cdigit > 1 || (*pa)->mant[0] != 1 || (*pa)->exp != 0 )
{
if ((*pa)->cdigit > 1 || (*pa)->mant[0] != 1 || (*pa)->exp != 0)
{
// pa and b are both not one.
_divnumx( pa, b, precision);
}
_divnumx(pa, b, precision);
}
else
{
{
// if pa is one and b is not one, just copy b, and adjust the sign.
int32_t sign = (*pa)->sign;
DUPNUM(*pa,b);
DUPNUM(*pa, b);
(*pa)->sign *= sign;
}
}
}
else
{
{
// b is one so don't divide, but set the sign.
(*pa)->sign *= b->sign;
}
}
}
//----------------------------------------------------------------------------
@ -257,111 +254,109 @@ void __inline divnumx( PNUMBER *pa, PNUMBER b, int32_t precision)
//
//----------------------------------------------------------------------------
void _divnumx( PNUMBER *pa, PNUMBER b, int32_t precision)
void _divnumx(PNUMBER* pa, PNUMBER b, int32_t precision)
{
PNUMBER a= nullptr; // a is the dereferenced number pointer from *pa
PNUMBER c= nullptr; // c will contain the result.
PNUMBER a = nullptr; // a is the dereferenced number pointer from *pa
PNUMBER c = nullptr; // c will contain the result.
PNUMBER lasttmp = nullptr; // lasttmp allows a backup when the algorithm
// guesses one bit too far.
// guesses one bit too far.
PNUMBER tmp = nullptr; // current guess being worked on for divide.
PNUMBER rem = nullptr; // remainder after applying guess.
int32_t cdigits; // count of digits for answer.
MANTTYPE *ptrc; // ptrc is a pointer to the mantissa of c.
MANTTYPE* ptrc; // ptrc is a pointer to the mantissa of c.
int32_t thismax = precision + g_ratio; // set a maximum number of internal digits
// to shoot for in the divide.
// to shoot for in the divide.
a=*pa;
if ( thismax < a->cdigit )
{
a = *pa;
if (thismax < a->cdigit)
{
// a has more digits than precision specified, bump up digits to shoot
// for.
thismax = a->cdigit;
}
}
if ( thismax < b->cdigit )
{
if (thismax < b->cdigit)
{
// b has more digits than precision specified, bump up digits to shoot
// for.
thismax = b->cdigit;
}
}
// Create c (the divide answer) and set up exponent and sign.
createnum( c, thismax + 1 );
c->exp = (a->cdigit+a->exp) - (b->cdigit+b->exp) + 1;
createnum(c, thismax + 1);
c->exp = (a->cdigit + a->exp) - (b->cdigit + b->exp) + 1;
c->sign = a->sign * b->sign;
ptrc = c->mant + thismax;
cdigits = 0;
DUPNUM( rem, a );
DUPNUM(rem, a);
rem->sign = b->sign;
rem->exp = b->cdigit + b->exp - rem->cdigit;
while ( cdigits++ < thismax && !zernum(rem) )
{
while (cdigits++ < thismax && !zernum(rem))
{
int32_t digit = 0;
*ptrc = 0;
while ( !lessnum( rem, b ) )
{
while (!lessnum(rem, b))
{
digit = 1;
DUPNUM( tmp, b );
destroynum( lasttmp );
lasttmp=i32tonum( 0, BASEX );
while ( lessnum( tmp, rem ) )
{
destroynum( lasttmp );
DUPNUM(lasttmp,tmp);
addnum( &tmp, tmp, BASEX );
DUPNUM(tmp, b);
destroynum(lasttmp);
lasttmp = i32tonum(0, BASEX);
while (lessnum(tmp, rem))
{
destroynum(lasttmp);
DUPNUM(lasttmp, tmp);
addnum(&tmp, tmp, BASEX);
digit *= 2;
}
if ( lessnum( rem, tmp ) )
{
}
if (lessnum(rem, tmp))
{
// too far, back up...
destroynum( tmp );
destroynum(tmp);
digit /= 2;
tmp=lasttmp;
lasttmp= nullptr;
}
tmp = lasttmp;
lasttmp = nullptr;
}
tmp->sign *= -1;
addnum( &rem, tmp, BASEX );
destroynum( tmp );
destroynum( lasttmp );
addnum(&rem, tmp, BASEX);
destroynum(tmp);
destroynum(lasttmp);
*ptrc |= digit;
}
}
rem->exp++;
ptrc--;
}
}
cdigits--;
if ( c->mant != ++ptrc )
{
memmove( c->mant, ptrc, (int)(cdigits*sizeof(MANTTYPE)) );
}
if (c->mant != ++ptrc)
{
memmove(c->mant, ptrc, (int)(cdigits * sizeof(MANTTYPE)));
}
if ( !cdigits )
{
if (!cdigits)
{
// A zero, make sure no weird exponents creep in
c->exp = 0;
c->cdigit = 1;
}
}
else
{
{
c->cdigit = cdigits;
c->exp -= cdigits;
// prevent different kinds of zeros, by stripping leading duplicate
// zeros. digits are in order of increasing significance.
while ( c->cdigit > 1 && c->mant[c->cdigit-1] == 0 )
{
while (c->cdigit > 1 && c->mant[c->cdigit - 1] == 0)
{
c->cdigit--;
}
}
}
destroynum( rem );
destroynum(rem);
destroynum( *pa );
*pa=c;
destroynum(*pa);
*pa = c;
}

File diff suppressed because it is too large Load diff

View file

@ -16,7 +16,6 @@
//-----------------------------------------------------------------------------
#include "ratpak.h"
//-----------------------------------------------------------------------------
//
// FUNCTION: exprat
@ -40,63 +39,63 @@
//
//-----------------------------------------------------------------------------
void _exprat( PRAT *px, int32_t precision)
void _exprat(PRAT* px, int32_t precision)
{
CREATETAYLOR();
addnum(&(pret->pp),num_one, BASEX);
addnum(&(pret->pq),num_one, BASEX);
DUPRAT(thisterm,pret);
addnum(&(pret->pp), num_one, BASEX);
addnum(&(pret->pq), num_one, BASEX);
DUPRAT(thisterm, pret);
n2=i32tonum(0L, BASEX);
n2 = i32tonum(0L, BASEX);
do {
do
{
NEXTTERM(*px, INC(n2) DIVNUM(n2), precision);
} while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
DESTROYTAYLOR();
}
void exprat( PRAT *px, uint32_t radix, int32_t precision)
void exprat(PRAT* px, uint32_t radix, int32_t precision)
{
PRAT pwr= nullptr;
PRAT pint= nullptr;
PRAT pwr = nullptr;
PRAT pint = nullptr;
int32_t intpwr;
if ( rat_gt( *px, rat_max_exp, precision) || rat_lt( *px, rat_min_exp, precision) )
{
if (rat_gt(*px, rat_max_exp, precision) || rat_lt(*px, rat_min_exp, precision))
{
// Don't attempt exp of anything large.
throw( CALC_E_DOMAIN );
}
throw(CALC_E_DOMAIN);
}
DUPRAT(pwr,rat_exp);
DUPRAT(pint,*px);
DUPRAT(pwr, rat_exp);
DUPRAT(pint, *px);
intrat(&pint, radix, precision);
intpwr = rattoi32(pint, radix, precision);
ratpowi32( &pwr, intpwr, precision);
ratpowi32(&pwr, intpwr, precision);
subrat(px, pint, precision);
// It just so happens to be an integral power of e.
if ( rat_gt( *px, rat_negsmallest, precision) && rat_lt( *px, rat_smallest, precision) )
{
DUPRAT(*px,pwr);
}
if (rat_gt(*px, rat_negsmallest, precision) && rat_lt(*px, rat_smallest, precision))
{
DUPRAT(*px, pwr);
}
else
{
{
_exprat(px, precision);
mulrat(px, pwr, precision);
}
}
destroyrat( pwr );
destroyrat( pint );
destroyrat(pwr);
destroyrat(pint);
}
//-----------------------------------------------------------------------------
//
// FUNCTION: lograt, _lograt
@ -124,7 +123,7 @@ void exprat( PRAT *px, uint32_t radix, int32_t precision)
//
//-----------------------------------------------------------------------------
void _lograt( PRAT *px, int32_t precision)
void _lograt(PRAT* px, int32_t precision)
{
CREATETAYLOR();
@ -133,76 +132,75 @@ void _lograt( PRAT *px, int32_t precision)
// sub one from x
(*px)->pq->sign *= -1;
addnum(&((*px)->pp),(*px)->pq, BASEX);
addnum(&((*px)->pp), (*px)->pq, BASEX);
(*px)->pq->sign *= -1;
DUPRAT(pret,*px);
DUPRAT(thisterm,*px);
DUPRAT(pret, *px);
DUPRAT(thisterm, *px);
n2=i32tonum(1L, BASEX);
n2 = i32tonum(1L, BASEX);
(*px)->pp->sign *= -1;
do {
do
{
NEXTTERM(*px, MULNUM(n2) INC(n2) DIVNUM(n2), precision);
TRIMTOP(*px, precision);
} while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
DESTROYTAYLOR();
}
void lograt( PRAT *px, int32_t precision)
void lograt(PRAT* px, int32_t precision)
{
bool fneglog;
PRAT pwr = nullptr; // pwr is the large scaling factor.
PRAT offset = nullptr; // offset is the incremental scaling factor.
PRAT pwr = nullptr; // pwr is the large scaling factor.
PRAT offset = nullptr; // offset is the incremental scaling factor.
// Check for someone taking the log of zero or a negative number.
if ( rat_le( *px, rat_zero, precision) )
{
throw( CALC_E_DOMAIN );
}
if (rat_le(*px, rat_zero, precision))
{
throw(CALC_E_DOMAIN);
}
// Get number > 1, for scaling
fneglog = rat_lt( *px, rat_one, precision);
if ( fneglog )
{
fneglog = rat_lt(*px, rat_one, precision);
if (fneglog)
{
// WARNING: This is equivalent to doing *px = 1 / *px
PNUMBER pnumtemp= nullptr;
PNUMBER pnumtemp = nullptr;
pnumtemp = (*px)->pp;
(*px)->pp = (*px)->pq;
(*px)->pq = pnumtemp;
}
}
// Scale the number within BASEX factor of 1, for the large scale.
// log(x*2^(BASEXPWR*k)) = BASEXPWR*k*log(2)+log(x)
if ( LOGRAT2(*px) > 1 )
{
if (LOGRAT2(*px) > 1)
{
// Take advantage of px's base BASEX to scale quickly down to
// a reasonable range.
int32_t intpwr;
intpwr=LOGRAT2(*px)-1;
intpwr = LOGRAT2(*px) - 1;
(*px)->pq->exp += intpwr;
pwr=i32torat(intpwr*BASEXPWR);
pwr = i32torat(intpwr * BASEXPWR);
mulrat(&pwr, ln_two, precision);
// ln(x+e)-ln(x) looks close to e when x is close to one using some
// expansions. This means we can trim past precision digits+1.
TRIMTOP(*px, precision);
}
}
else
{
DUPRAT(pwr,rat_zero);
}
{
DUPRAT(pwr, rat_zero);
}
DUPRAT(offset,rat_zero);
DUPRAT(offset, rat_zero);
// Scale the number between 1 and e_to_one_half, for the small scale.
while ( rat_gt( *px, e_to_one_half, precision) )
{
divrat( px, e_to_one_half, precision);
addrat( &offset, rat_one, precision);
}
while (rat_gt(*px, e_to_one_half, precision))
{
divrat(px, e_to_one_half, precision);
addrat(&offset, rat_one, precision);
}
_lograt(px, precision);
@ -217,16 +215,16 @@ void lograt( PRAT *px, int32_t precision)
trimit(px, precision);
// If number started out < 1 rescale answer to negative.
if ( fneglog )
{
if (fneglog)
{
(*px)->pp->sign *= -1;
}
}
destroyrat(offset);
destroyrat(pwr);
}
void log10rat( PRAT *px, int32_t precision)
void log10rat(PRAT* px, int32_t precision)
{
lograt(px, precision);
@ -246,7 +244,7 @@ bool IsEven(PRAT x, uint32_t radix, int32_t precision)
fracrat(&tmp, radix, precision);
addrat(&tmp, tmp, precision);
subrat(&tmp, rat_one, precision);
if ( rat_lt( tmp, rat_zero, precision))
if (rat_lt(tmp, rat_zero, precision))
{
bRet = true;
}
@ -269,7 +267,7 @@ bool IsEven(PRAT x, uint32_t radix, int32_t precision)
//
//
//---------------------------------------------------------------------------
void powrat(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
void powrat(PRAT* px, PRAT y, uint32_t radix, int32_t precision)
{
// Handle cases where px or y is 0 by calling powratcomp directly
if (zerrat(*px) || zerrat(y))
@ -296,12 +294,12 @@ void powrat(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
}
}
void powratNumeratorDenominator(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
void powratNumeratorDenominator(PRAT* px, PRAT y, uint32_t radix, int32_t precision)
{
// Prepare rationals
PRAT yNumerator = nullptr;
PRAT yDenominator = nullptr;
DUPRAT(yNumerator, rat_zero); // yNumerator->pq is 1 one
DUPRAT(yNumerator, rat_zero); // yNumerator->pq is 1 one
DUPRAT(yDenominator, rat_zero); // yDenominator->pq is 1 one
DUPNUM(yNumerator->pp, y->pp);
DUPNUM(yDenominator->pp, y->pq);
@ -405,7 +403,7 @@ void powratNumeratorDenominator(PRAT *px, PRAT y, uint32_t radix, int32_t precis
//
//
//---------------------------------------------------------------------------
void powratcomp(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
void powratcomp(PRAT* px, PRAT y, uint32_t radix, int32_t precision)
{
int32_t sign = SIGN(*px);
@ -413,76 +411,74 @@ void powratcomp(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
(*px)->pp->sign = 1;
(*px)->pq->sign = 1;
if ( zerrat( *px ) )
{
if (zerrat(*px))
{
// *px is zero.
if ( rat_lt( y, rat_zero, precision) )
{
throw( CALC_E_DOMAIN );
}
else if ( zerrat( y ) )
{
// *px and y are both zero, special case a 1 return.
DUPRAT(*px,rat_one);
// Ensure sign is positive.
sign = 1;
}
}
else
if (rat_lt(y, rat_zero, precision))
{
PRAT pxint= nullptr;
DUPRAT(pxint,*px);
subrat(&pxint, rat_one, precision);
if ( rat_gt( pxint, rat_negsmallest, precision) &&
rat_lt( pxint, rat_smallest, precision) && ( sign == 1 ) )
{
// *px is one, special case a 1 return.
DUPRAT(*px,rat_one);
throw(CALC_E_DOMAIN);
}
else if (zerrat(y))
{
// *px and y are both zero, special case a 1 return.
DUPRAT(*px, rat_one);
// Ensure sign is positive.
sign = 1;
}
}
}
else
{
PRAT pxint = nullptr;
DUPRAT(pxint, *px);
subrat(&pxint, rat_one, precision);
if (rat_gt(pxint, rat_negsmallest, precision) && rat_lt(pxint, rat_smallest, precision) && (sign == 1))
{
// *px is one, special case a 1 return.
DUPRAT(*px, rat_one);
// Ensure sign is positive.
sign = 1;
}
else
{
{
// Only do the exp if the number isn't zero or one
PRAT podd = nullptr;
DUPRAT(podd,y);
DUPRAT(podd, y);
fracrat(&podd, radix, precision);
if ( rat_gt( podd, rat_negsmallest, precision) && rat_lt( podd, rat_smallest, precision) )
{
if (rat_gt(podd, rat_negsmallest, precision) && rat_lt(podd, rat_smallest, precision))
{
// If power is an integer let ratpowi32 deal with it.
PRAT iy = nullptr;
int32_t inty;
DUPRAT(iy,y);
DUPRAT(iy, y);
subrat(&iy, podd, precision);
inty = rattoi32(iy, radix, precision);
PRAT plnx = nullptr;
DUPRAT(plnx,*px);
DUPRAT(plnx, *px);
lograt(&plnx, precision);
mulrat(&plnx, iy, precision);
if ( rat_gt( plnx, rat_max_exp, precision) || rat_lt( plnx, rat_min_exp, precision) )
{
if (rat_gt(plnx, rat_max_exp, precision) || rat_lt(plnx, rat_min_exp, precision))
{
// Don't attempt exp of anything large or small.A
destroyrat(plnx);
destroyrat(iy);
destroyrat(pxint);
destroyrat(podd);
throw( CALC_E_DOMAIN );
}
throw(CALC_E_DOMAIN);
}
destroyrat(plnx);
ratpowi32(px, inty, precision);
if ( ( inty & 1 ) == 0 )
{
sign=1;
}
destroyrat(iy);
}
else
if ((inty & 1) == 0)
{
sign = 1;
}
destroyrat(iy);
}
else
{
// power is a fraction
if ( sign == -1 )
{
if (sign == -1)
{
// Need to throw an error if the exponent has an even denominator.
// As a first step, the numerator and denominator must be divided by 2 as many times as
// possible, so that 2/6 is allowed.
@ -492,7 +488,7 @@ void powratcomp(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
bool fBadExponent = false;
// Get the numbers in arbitrary precision rational number format
DUPRAT(pNumerator, rat_zero); // pNumerator->pq is 1 one
DUPRAT(pNumerator, rat_zero); // pNumerator->pq is 1 one
DUPRAT(pDenominator, rat_zero); // pDenominator->pq is 1 one
DUPNUM(pNumerator->pp, y->pp);
@ -501,39 +497,39 @@ void powratcomp(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
pDenominator->pp->sign = 1;
while (IsEven(pNumerator, radix, precision) && IsEven(pDenominator, radix, precision)) // both Numerator & denominator is even
{
{
divrat(&pNumerator, rat_two, precision);
divrat(&pDenominator, rat_two, precision);
}
}
if (IsEven(pDenominator, radix, precision)) // denominator is still even
{
fBadExponent = true;
}
{
fBadExponent = true;
}
if (IsEven(pNumerator, radix, precision)) // numerator is still even
{
{
sign = 1;
}
}
destroyrat(pNumerator);
destroyrat(pDenominator);
if (fBadExponent)
{
throw( CALC_E_DOMAIN );
}
}
else
{
throw(CALC_E_DOMAIN);
}
}
else
{
// If the exponent is not odd disregard the sign.
sign = 1;
}
}
lograt(px, precision);
mulrat(px, y, precision);
exprat(px, radix, precision);
}
destroyrat(podd);
}
destroyrat(pxint);
}
destroyrat(podd);
}
destroyrat(pxint);
}
(*px)->pp->sign *= sign;
}

View file

@ -15,8 +15,7 @@
//-----------------------------------------------------------------------------
#include "ratpak.h"
#define ABSRAT(x) (((x)->pp->sign=1),((x)->pq->sign=1))
#define ABSRAT(x) (((x)->pp->sign = 1), ((x)->pq->sign = 1))
#define NEGATE(x) ((x)->pp->sign *= -1)
//-----------------------------------------------------------------------------
@ -55,37 +54,36 @@
//
//-----------------------------------------------------------------------------
void _gamma( PRAT *pn, uint32_t radix, int32_t precision)
void _gamma(PRAT* pn, uint32_t radix, int32_t precision)
{
PRAT factorial= nullptr;
PNUMBER count= nullptr;
PRAT tmp= nullptr;
PRAT one_pt_five= nullptr;
PRAT a= nullptr;
PRAT a2= nullptr;
PRAT term= nullptr;
PRAT sum= nullptr;
PRAT err= nullptr;
PRAT mpy= nullptr;
PRAT factorial = nullptr;
PNUMBER count = nullptr;
PRAT tmp = nullptr;
PRAT one_pt_five = nullptr;
PRAT a = nullptr;
PRAT a2 = nullptr;
PRAT term = nullptr;
PRAT sum = nullptr;
PRAT err = nullptr;
PRAT mpy = nullptr;
PRAT ratprec = nullptr;
PRAT ratRadix = nullptr;
int32_t oldprec;
// Set up constants and initial conditions
oldprec = precision;
ratprec = i32torat( oldprec );
ratprec = i32torat(oldprec);
// Find the best 'A' for convergence to the required precision.
a=i32torat( radix );
a = i32torat(radix);
lograt(&a, precision);
mulrat(&a, ratprec, precision);
// Really is -ln(n)+1, but -ln(n) will be < 1
// if we scale n between 0.5 and 1.5
addrat(&a, rat_two, precision);
DUPRAT(tmp,a);
DUPRAT(tmp, a);
lograt(&tmp, precision);
mulrat(&tmp, *pn, precision);
addrat(&a, tmp, precision);
@ -94,85 +92,85 @@ void _gamma( PRAT *pn, uint32_t radix, int32_t precision)
// Calculate the necessary bump in precision and up the precision.
// The following code is equivalent to
// precision += ln(exp(a)*pow(a,n+1.5))-ln(radix));
DUPRAT(tmp,*pn);
one_pt_five=i32torat( 3L );
divrat( &one_pt_five, rat_two, precision);
addrat( &tmp, one_pt_five, precision);
DUPRAT(term,a);
powratcomp( &term, tmp, radix, precision);
DUPRAT( tmp, a );
exprat( &tmp, radix, precision);
mulrat( &term, tmp, precision);
lograt( &term, precision);
DUPRAT(tmp, *pn);
one_pt_five = i32torat(3L);
divrat(&one_pt_five, rat_two, precision);
addrat(&tmp, one_pt_five, precision);
DUPRAT(term, a);
powratcomp(&term, tmp, radix, precision);
DUPRAT(tmp, a);
exprat(&tmp, radix, precision);
mulrat(&term, tmp, precision);
lograt(&term, precision);
ratRadix = i32torat(radix);
DUPRAT(tmp,ratRadix);
lograt( &tmp, precision);
subrat( &term, tmp, precision);
precision += rattoi32( term, radix, precision);
DUPRAT(tmp, ratRadix);
lograt(&tmp, precision);
subrat(&term, tmp, precision);
precision += rattoi32(term, radix, precision);
// Set up initial terms for series, refer to series in above comment block.
DUPRAT(factorial,rat_one); // Start factorial out with one
count = i32tonum( 0L, BASEX );
DUPRAT(factorial, rat_one); // Start factorial out with one
count = i32tonum(0L, BASEX);
DUPRAT(mpy,a);
powratcomp(&mpy,*pn, radix, precision);
DUPRAT(mpy, a);
powratcomp(&mpy, *pn, radix, precision);
// a2=a^2
DUPRAT(a2,a);
DUPRAT(a2, a);
mulrat(&a2, a, precision);
// sum=(1/n)-(a/(n+1))
DUPRAT(sum,rat_one);
DUPRAT(sum, rat_one);
divrat(&sum, *pn, precision);
DUPRAT(tmp,*pn);
DUPRAT(tmp, *pn);
addrat(&tmp, rat_one, precision);
DUPRAT(term,a);
DUPRAT(term, a);
divrat(&term, tmp, precision);
subrat(&sum, term, precision);
DUPRAT(err,ratRadix);
DUPRAT(err, ratRadix);
NEGATE(ratprec);
powratcomp(&err,ratprec, radix, precision);
powratcomp(&err, ratprec, radix, precision);
divrat(&err, ratRadix, precision);
// Just get something not tiny in term
DUPRAT(term, rat_two );
DUPRAT(term, rat_two);
// Loop until precision is reached, or asked to halt.
while ( !zerrat( term ) && rat_gt( term, err, precision) )
{
while (!zerrat(term) && rat_gt(term, err, precision))
{
addrat(pn, rat_two, precision);
// WARNING: mixing numbers and rationals here.
// for speed and efficiency.
INC(count);
mulnumx(&(factorial->pp),count);
mulnumx(&(factorial->pp), count);
INC(count)
mulnumx(&(factorial->pp),count);
mulnumx(&(factorial->pp), count);
divrat(&factorial, a2, precision);
DUPRAT(tmp,*pn);
addrat( &tmp, rat_one, precision);
DUPRAT(tmp, *pn);
addrat(&tmp, rat_one, precision);
destroyrat(term);
createrat(term);
DUPNUM(term->pp,count);
DUPNUM(term->pq,num_one);
addrat( &term, rat_one, precision);
mulrat( &term, tmp, precision);
DUPRAT(tmp,a);
divrat( &tmp, term, precision);
DUPNUM(term->pp, count);
DUPNUM(term->pq, num_one);
addrat(&term, rat_one, precision);
mulrat(&term, tmp, precision);
DUPRAT(tmp, a);
divrat(&tmp, term, precision);
DUPRAT(term,rat_one);
divrat( &term, *pn, precision);
subrat( &term, tmp, precision);
DUPRAT(term, rat_one);
divrat(&term, *pn, precision);
subrat(&term, tmp, precision);
divrat (&term, factorial, precision);
addrat( &sum, term, precision);
divrat(&term, factorial, precision);
addrat(&sum, term, precision);
ABSRAT(term);
}
}
// Multiply by factor.
mulrat( &sum, mpy, precision);
mulrat(&sum, mpy, precision);
// And cleanup
precision = oldprec;
@ -188,70 +186,67 @@ void _gamma( PRAT *pn, uint32_t radix, int32_t precision)
destroyrat(factorial);
destroyrat(*pn);
DUPRAT(*pn,sum);
DUPRAT(*pn, sum);
destroyrat(sum);
}
void factrat( PRAT *px, uint32_t radix, int32_t precision)
void factrat(PRAT* px, uint32_t radix, int32_t precision)
{
PRAT fact = nullptr;
PRAT frac = nullptr;
PRAT neg_rat_one = nullptr;
if ( rat_gt( *px, rat_max_fact, precision) || rat_lt( *px, rat_min_fact, precision) )
{
if (rat_gt(*px, rat_max_fact, precision) || rat_lt(*px, rat_min_fact, precision))
{
// Don't attempt factorial of anything too large or small.
throw CALC_E_OVERFLOW;
}
}
DUPRAT(fact,rat_one);
DUPRAT(fact, rat_one);
DUPRAT(neg_rat_one,rat_one);
DUPRAT(neg_rat_one, rat_one);
neg_rat_one->pp->sign *= -1;
DUPRAT( frac, *px );
fracrat( &frac, radix, precision);
DUPRAT(frac, *px);
fracrat(&frac, radix, precision);
// Check for negative integers and throw an error.
if ( ( zerrat(frac) || ( LOGRATRADIX(frac) <= -precision) ) &&
( SIGN(*px) == -1 ) )
{
if ((zerrat(frac) || (LOGRATRADIX(frac) <= -precision)) && (SIGN(*px) == -1))
{
throw CALC_E_DOMAIN;
}
while ( rat_gt( *px, rat_zero, precision) &&
( LOGRATRADIX(*px) > -precision) )
{
mulrat( &fact, *px, precision);
subrat( px, rat_one, precision);
}
}
while (rat_gt(*px, rat_zero, precision) && (LOGRATRADIX(*px) > -precision))
{
mulrat(&fact, *px, precision);
subrat(px, rat_one, precision);
}
// Added to make numbers 'close enough' to integers use integer factorial.
if ( LOGRATRADIX(*px) <= -precision)
{
DUPRAT((*px),rat_zero);
if (LOGRATRADIX(*px) <= -precision)
{
DUPRAT((*px), rat_zero);
intrat(&fact, radix, precision);
}
}
while ( rat_lt( *px, neg_rat_one, precision) )
{
addrat( px, rat_one, precision);
divrat( &fact, *px, precision);
}
while (rat_lt(*px, neg_rat_one, precision))
{
addrat(px, rat_one, precision);
divrat(&fact, *px, precision);
}
if ( rat_neq( *px, rat_zero, precision) )
{
addrat( px, rat_one, precision);
_gamma( px, radix, precision);
mulrat( px, fact, precision);
}
if (rat_neq(*px, rat_zero, precision))
{
addrat(px, rat_one, precision);
_gamma(px, radix, precision);
mulrat(px, fact, precision);
}
else
{
DUPRAT(*px,fact);
}
{
DUPRAT(*px, fact);
}
destroyrat(fact);
destroyrat(frac);
destroyrat(neg_rat_one);
}

View file

@ -17,26 +17,23 @@
//-----------------------------------------------------------------------------
#include "ratpak.h"
void ascalerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, int32_t precision)
void ascalerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, int32_t precision)
{
switch ( angletype )
{
switch (angletype)
{
case ANGLE_RAD:
break;
case ANGLE_DEG:
divrat( pa, two_pi, precision);
mulrat( pa, rat_360, precision);
divrat(pa, two_pi, precision);
mulrat(pa, rat_360, precision);
break;
case ANGLE_GRAD:
divrat( pa, two_pi, precision);
mulrat( pa, rat_400, precision);
divrat(pa, two_pi, precision);
mulrat(pa, rat_400, precision);
break;
}
}
}
//-----------------------------------------------------------------------------
//
// FUNCTION: asinrat, _asinrat
@ -64,86 +61,83 @@ void ascalerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, int32_t precision)
//
//-----------------------------------------------------------------------------
void _asinrat( PRAT *px, int32_t precision)
void _asinrat(PRAT* px, int32_t precision)
{
CREATETAYLOR();
DUPRAT(pret,*px);
DUPRAT(thisterm,*px);
DUPNUM(n2,num_one);
DUPRAT(pret, *px);
DUPRAT(thisterm, *px);
DUPNUM(n2, num_one);
do
{
NEXTTERM(xx,MULNUM(n2) MULNUM(n2)
INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
}
while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
{
NEXTTERM(xx, MULNUM(n2) MULNUM(n2) INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
DESTROYTAYLOR();
}
void asinanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
void asinanglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
{
asinrat( pa, radix, precision);
ascalerat( pa, angletype, precision);
asinrat(pa, radix, precision);
ascalerat(pa, angletype, precision);
}
void asinrat( PRAT *px, uint32_t radix, int32_t precision)
void asinrat(PRAT* px, uint32_t radix, int32_t precision)
{
PRAT pret= nullptr;
PRAT phack= nullptr;
PRAT pret = nullptr;
PRAT phack = nullptr;
int32_t sgn = SIGN(*px);
(*px)->pp->sign = 1;
(*px)->pq->sign = 1;
// Avoid the really bad part of the asin curve near +/-1.
DUPRAT(phack,*px);
DUPRAT(phack, *px);
subrat(&phack, rat_one, precision);
// Since *px might be epsilon near zero we must set it to zero.
if ( rat_le(phack, rat_smallest, precision) && rat_ge(phack, rat_negsmallest, precision) )
{
if (rat_le(phack, rat_smallest, precision) && rat_ge(phack, rat_negsmallest, precision))
{
destroyrat(phack);
DUPRAT( *px, pi_over_two );
}
DUPRAT(*px, pi_over_two);
}
else
{
{
destroyrat(phack);
if ( rat_gt( *px, pt_eight_five, precision) )
if (rat_gt(*px, pt_eight_five, precision))
{
if (rat_gt(*px, rat_one, precision))
{
if ( rat_gt( *px, rat_one, precision) )
subrat(px, rat_one, precision);
if (rat_gt(*px, rat_smallest, precision))
{
subrat( px, rat_one, precision);
if ( rat_gt( *px, rat_smallest, precision) )
{
throw( CALC_E_DOMAIN );
}
else
{
DUPRAT(*px,rat_one);
}
throw(CALC_E_DOMAIN);
}
DUPRAT(pret,*px);
mulrat( px, pret, precision);
else
{
DUPRAT(*px, rat_one);
}
}
DUPRAT(pret, *px);
mulrat(px, pret, precision);
(*px)->pp->sign *= -1;
addrat( px, rat_one, precision);
rootrat( px, rat_two, radix, precision);
_asinrat( px, precision);
addrat(px, rat_one, precision);
rootrat(px, rat_two, radix, precision);
_asinrat(px, precision);
(*px)->pp->sign *= -1;
addrat( px, pi_over_two, precision);
addrat(px, pi_over_two, precision);
destroyrat(pret);
}
else
{
_asinrat( px, precision);
}
}
else
{
_asinrat(px, precision);
}
}
(*px)->pp->sign = sgn;
(*px)->pq->sign = 1;
}
//-----------------------------------------------------------------------------
//
// FUNCTION: acosrat, _acosrat
@ -170,35 +164,33 @@ void asinrat( PRAT *px, uint32_t radix, int32_t precision)
//
//-----------------------------------------------------------------------------
void acosanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
void acosanglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
{
acosrat( pa, radix, precision);
ascalerat( pa, angletype, precision);
acosrat(pa, radix, precision);
ascalerat(pa, angletype, precision);
}
void _acosrat( PRAT *px, int32_t precision)
void _acosrat(PRAT* px, int32_t precision)
{
CREATETAYLOR();
createrat(thisterm);
thisterm->pp=i32tonum( 1L, BASEX );
thisterm->pq=i32tonum( 1L, BASEX );
thisterm->pp = i32tonum(1L, BASEX);
thisterm->pq = i32tonum(1L, BASEX);
DUPNUM(n2,num_one);
DUPNUM(n2, num_one);
do
{
NEXTTERM(xx,MULNUM(n2) MULNUM(n2)
INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
}
while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
{
NEXTTERM(xx, MULNUM(n2) MULNUM(n2) INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
DESTROYTAYLOR();
}
void acosrat( PRAT *px, uint32_t radix, int32_t precision)
void acosrat(PRAT* px, uint32_t radix, int32_t precision)
{
int32_t sgn = SIGN(*px);
@ -206,24 +198,24 @@ void acosrat( PRAT *px, uint32_t radix, int32_t precision)
(*px)->pp->sign = 1;
(*px)->pq->sign = 1;
if ( rat_equ( *px, rat_one, precision) )
if (rat_equ(*px, rat_one, precision))
{
if (sgn == -1)
{
if ( sgn == -1 )
{
DUPRAT(*px,pi);
}
else
{
DUPRAT( *px, rat_zero );
}
DUPRAT(*px, pi);
}
else
else
{
DUPRAT(*px, rat_zero);
}
}
else
{
(*px)->pp->sign = sgn;
asinrat( px, radix, precision);
asinrat(px, radix, precision);
(*px)->pp->sign *= -1;
addrat(px, pi_over_two, precision);
}
}
}
//-----------------------------------------------------------------------------
@ -257,79 +249,79 @@ void acosrat( PRAT *px, uint32_t radix, int32_t precision)
//
//-----------------------------------------------------------------------------
void atananglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
void atananglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
{
atanrat( pa, radix, precision);
ascalerat( pa, angletype, precision);
atanrat(pa, radix, precision);
ascalerat(pa, angletype, precision);
}
void _atanrat( PRAT *px, int32_t precision)
void _atanrat(PRAT* px, int32_t precision)
{
CREATETAYLOR();
DUPRAT(pret,*px);
DUPRAT(thisterm,*px);
DUPRAT(pret, *px);
DUPRAT(thisterm, *px);
DUPNUM(n2,num_one);
DUPNUM(n2, num_one);
xx->pp->sign *= -1;
do {
NEXTTERM(xx,MULNUM(n2) INC(n2) INC(n2) DIVNUM(n2), precision);
} while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
do
{
NEXTTERM(xx, MULNUM(n2) INC(n2) INC(n2) DIVNUM(n2), precision);
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
DESTROYTAYLOR();
}
void atanrat( PRAT *px, uint32_t radix, int32_t precision)
void atanrat(PRAT* px, uint32_t radix, int32_t precision)
{
PRAT tmpx= nullptr;
PRAT tmpx = nullptr;
int32_t sgn = SIGN(*px);
(*px)->pp->sign = 1;
(*px)->pq->sign = 1;
if ( rat_gt( (*px), pt_eight_five, precision) )
if (rat_gt((*px), pt_eight_five, precision))
{
if (rat_gt((*px), rat_two, precision))
{
if ( rat_gt( (*px), rat_two, precision) )
{
(*px)->pp->sign = sgn;
(*px)->pq->sign = 1;
DUPRAT(tmpx,rat_one);
DUPRAT(tmpx, rat_one);
divrat(&tmpx, (*px), precision);
_atanrat(&tmpx, precision);
tmpx->pp->sign = sgn;
tmpx->pq->sign = 1;
DUPRAT(*px,pi_over_two);
DUPRAT(*px, pi_over_two);
subrat(px, tmpx, precision);
destroyrat( tmpx );
}
destroyrat(tmpx);
}
else
{
{
(*px)->pp->sign = sgn;
DUPRAT(tmpx,*px);
mulrat( &tmpx, *px, precision);
addrat( &tmpx, rat_one, precision);
rootrat( &tmpx, rat_two, radix, precision);
divrat( px, tmpx, precision);
destroyrat( tmpx );
asinrat( px, radix, precision);
DUPRAT(tmpx, *px);
mulrat(&tmpx, *px, precision);
addrat(&tmpx, rat_one, precision);
rootrat(&tmpx, rat_two, radix, precision);
divrat(px, tmpx, precision);
destroyrat(tmpx);
asinrat(px, radix, precision);
(*px)->pp->sign = sgn;
(*px)->pq->sign = 1;
}
}
}
else
{
{
(*px)->pp->sign = sgn;
(*px)->pq->sign = 1;
_atanrat( px, precision);
}
if ( rat_gt( *px, pi_over_two, precision) )
{
subrat( px, pi, precision);
}
_atanrat(px, precision);
}
if (rat_gt(*px, pi_over_two, precision))
{
subrat(px, pi, precision);
}
}

View file

@ -18,8 +18,6 @@
//-----------------------------------------------------------------------------
#include "ratpak.h"
//-----------------------------------------------------------------------------
//
// FUNCTION: asinhrat
@ -49,47 +47,44 @@
//
//-----------------------------------------------------------------------------
void asinhrat( PRAT *px, uint32_t radix, int32_t precision)
void asinhrat(PRAT* px, uint32_t radix, int32_t precision)
{
PRAT neg_pt_eight_five = nullptr;
DUPRAT(neg_pt_eight_five,pt_eight_five);
DUPRAT(neg_pt_eight_five, pt_eight_five);
neg_pt_eight_five->pp->sign *= -1;
if ( rat_gt( *px, pt_eight_five, precision) || rat_lt( *px, neg_pt_eight_five, precision) )
{
if (rat_gt(*px, pt_eight_five, precision) || rat_lt(*px, neg_pt_eight_five, precision))
{
PRAT ptmp = nullptr;
DUPRAT(ptmp,(*px));
DUPRAT(ptmp, (*px));
mulrat(&ptmp, *px, precision);
addrat(&ptmp, rat_one, precision);
rootrat(&ptmp, rat_two, radix, precision);
addrat(px, ptmp, precision);
lograt(px, precision);
destroyrat(ptmp);
}
}
else
{
{
CREATETAYLOR();
xx->pp->sign *= -1;
DUPRAT(pret,(*px));
DUPRAT(thisterm,(*px));
DUPRAT(pret, (*px));
DUPRAT(thisterm, (*px));
DUPNUM(n2,num_one);
DUPNUM(n2, num_one);
do
{
NEXTTERM(xx,MULNUM(n2) MULNUM(n2)
INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
}
while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
{
NEXTTERM(xx, MULNUM(n2) MULNUM(n2) INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
DESTROYTAYLOR();
}
}
destroyrat(neg_pt_eight_five);
}
//-----------------------------------------------------------------------------
//
// FUNCTION: acoshrat
@ -106,24 +101,24 @@ void asinhrat( PRAT *px, uint32_t radix, int32_t precision)
//
//-----------------------------------------------------------------------------
void acoshrat( PRAT *px, uint32_t radix, int32_t precision)
void acoshrat(PRAT* px, uint32_t radix, int32_t precision)
{
if ( rat_lt( *px, rat_one, precision) )
{
if (rat_lt(*px, rat_one, precision))
{
throw CALC_E_DOMAIN;
}
}
else
{
{
PRAT ptmp = nullptr;
DUPRAT(ptmp,(*px));
DUPRAT(ptmp, (*px));
mulrat(&ptmp, *px, precision);
subrat(&ptmp, rat_one, precision);
rootrat(&ptmp,rat_two, radix, precision);
rootrat(&ptmp, rat_two, radix, precision);
addrat(px, ptmp, precision);
lograt(px, precision);
destroyrat(ptmp);
}
}
}
//-----------------------------------------------------------------------------
@ -143,11 +138,11 @@ void acoshrat( PRAT *px, uint32_t radix, int32_t precision)
//
//-----------------------------------------------------------------------------
void atanhrat( PRAT *px, int32_t precision)
void atanhrat(PRAT* px, int32_t precision)
{
PRAT ptmp = nullptr;
DUPRAT(ptmp,(*px));
DUPRAT(ptmp, (*px));
subrat(&ptmp, rat_one, precision);
addrat(px, rat_one, precision);
divrat(px, ptmp, precision);
@ -156,4 +151,3 @@ void atanhrat( PRAT *px, int32_t precision)
divrat(px, rat_two, precision);
destroyrat(ptmp);
}

View file

@ -17,7 +17,7 @@
using namespace std;
void lshrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
void lshrat(PRAT* pa, PRAT b, uint32_t radix, int32_t precision)
{
PRAT pwr = nullptr;
@ -40,7 +40,7 @@ void lshrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
}
}
void rshrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
void rshrat(PRAT* pa, PRAT b, uint32_t radix, int32_t precision)
{
PRAT pwr = nullptr;
@ -63,29 +63,29 @@ void rshrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
}
}
void boolrat(PRAT *pa, PRAT b, int func, uint32_t radix, int32_t precision);
void boolnum(PNUMBER *pa, PNUMBER b, int func);
void boolrat(PRAT* pa, PRAT b, int func, uint32_t radix, int32_t precision);
void boolnum(PNUMBER* pa, PNUMBER b, int func);
enum {
enum
{
FUNC_AND,
FUNC_OR,
FUNC_XOR
} BOOL_FUNCS;
void andrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
void andrat(PRAT* pa, PRAT b, uint32_t radix, int32_t precision)
{
boolrat(pa, b, FUNC_AND, radix, precision);
}
void orrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
void orrat(PRAT* pa, PRAT b, uint32_t radix, int32_t precision)
{
boolrat(pa, b, FUNC_OR, radix, precision);
}
void xorrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
void xorrat(PRAT* pa, PRAT b, uint32_t radix, int32_t precision)
{
boolrat(pa, b, FUNC_XOR, radix, precision);
@ -103,7 +103,7 @@ void xorrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
//
//---------------------------------------------------------------------------
void boolrat(PRAT *pa, PRAT b, int func, uint32_t radix, int32_t precision)
void boolrat(PRAT* pa, PRAT b, int func, uint32_t radix, int32_t precision)
{
PRAT tmp = nullptr;
@ -129,22 +129,21 @@ void boolrat(PRAT *pa, PRAT b, int func, uint32_t radix, int32_t precision)
//
//---------------------------------------------------------------------------
void boolnum(PNUMBER *pa, PNUMBER b, int func)
void boolnum(PNUMBER* pa, PNUMBER b, int func)
{
PNUMBER c = nullptr;
PNUMBER a = nullptr;
MANTTYPE *pcha;
MANTTYPE *pchb;
MANTTYPE *pchc;
MANTTYPE* pcha;
MANTTYPE* pchb;
MANTTYPE* pchc;
int32_t cdigits;
int32_t mexp;
MANTTYPE da;
MANTTYPE db;
a = *pa;
cdigits = max(a->cdigit + a->exp, b->cdigit + b->exp) -
min(a->exp, b->exp);
cdigits = max(a->cdigit + a->exp, b->cdigit + b->exp) - min(a->exp, b->exp);
createnum(c, cdigits);
c->exp = min(a->exp, b->exp);
mexp = c->exp;
@ -154,12 +153,8 @@ void boolnum(PNUMBER *pa, PNUMBER b, int func)
pchc = c->mant;
for (; cdigits > 0; cdigits--, mexp++)
{
da = (((mexp >= a->exp) && (cdigits + a->exp - c->exp >
(c->cdigit - a->cdigit))) ?
*pcha++ : 0);
db = (((mexp >= b->exp) && (cdigits + b->exp - c->exp >
(c->cdigit - b->cdigit))) ?
*pchb++ : 0);
da = (((mexp >= a->exp) && (cdigits + a->exp - c->exp > (c->cdigit - a->cdigit))) ? *pcha++ : 0);
db = (((mexp >= b->exp) && (cdigits + b->exp - c->exp > (c->cdigit - b->cdigit))) ? *pchb++ : 0);
switch (func)
{
case FUNC_AND:
@ -196,7 +191,7 @@ void boolnum(PNUMBER *pa, PNUMBER b, int func)
//
//-----------------------------------------------------------------------------
void remrat(PRAT *pa, PRAT b)
void remrat(PRAT* pa, PRAT b)
{
if (zerrat(b))
@ -227,15 +222,15 @@ void remrat(PRAT *pa, PRAT b)
// RETURN: None, changes pointer.
//
// DESCRIPTION: Calculate the remainder of *pa / b, with the sign of the result
// either zero or has the same sign as the divisor.
// either zero or has the same sign as the divisor.
// NOTE: When *pa or b are negative, the result won't be the same as
// the C/C++ operator %, use remrat if it's the behavior you expect.
// the C/C++ operator %, use remrat if it's the behavior you expect.
//
//-----------------------------------------------------------------------------
void modrat(PRAT *pa, PRAT b)
void modrat(PRAT* pa, PRAT b)
{
//contrary to remrat(X, 0) returning 0, modrat(X, 0) must return X
// contrary to remrat(X, 0) returning 0, modrat(X, 0) must return X
if (zerrat(b))
{
return;

View file

@ -41,51 +41,49 @@ using namespace std;
//
//----------------------------------------------------------------------------
void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix);
void _addnum(PNUMBER* pa, PNUMBER b, uint32_t radix);
void __inline addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
void __inline addnum(PNUMBER* pa, PNUMBER b, uint32_t radix)
{
if ( b->cdigit > 1 || b->mant[0] != 0 )
{ // If b is zero we are done.
if ( (*pa)->cdigit > 1 || (*pa)->mant[0] != 0 )
{ // pa and b are both nonzero.
_addnum( pa, b, radix);
}
else
{ // if pa is zero and b isn't just copy b.
DUPNUM(*pa,b);
}
if (b->cdigit > 1 || b->mant[0] != 0)
{ // If b is zero we are done.
if ((*pa)->cdigit > 1 || (*pa)->mant[0] != 0)
{ // pa and b are both nonzero.
_addnum(pa, b, radix);
}
else
{ // if pa is zero and b isn't just copy b.
DUPNUM(*pa, b);
}
}
}
void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
void _addnum(PNUMBER* pa, PNUMBER b, uint32_t radix)
{
PNUMBER c= nullptr; // c will contain the result.
PNUMBER a= nullptr; // a is the dereferenced number pointer from *pa
MANTTYPE *pcha; // pcha is a pointer to the mantissa of a.
MANTTYPE *pchb; // pchb is a pointer to the mantissa of b.
MANTTYPE *pchc; // pchc is a pointer to the mantissa of c.
int32_t cdigits; // cdigits is the max count of the digits results
// used as a counter.
int32_t mexp; // mexp is the exponent of the result.
MANTTYPE da; // da is a single 'digit' after possible padding.
MANTTYPE db; // db is a single 'digit' after possible padding.
MANTTYPE cy=0; // cy is the value of a carry after adding two 'digits'
int32_t fcompla = 0; // fcompla is a flag to signal a is negative.
int32_t fcomplb = 0; // fcomplb is a flag to signal b is negative.
a=*pa;
PNUMBER c = nullptr; // c will contain the result.
PNUMBER a = nullptr; // a is the dereferenced number pointer from *pa
MANTTYPE* pcha; // pcha is a pointer to the mantissa of a.
MANTTYPE* pchb; // pchb is a pointer to the mantissa of b.
MANTTYPE* pchc; // pchc is a pointer to the mantissa of c.
int32_t cdigits; // cdigits is the max count of the digits results
// used as a counter.
int32_t mexp; // mexp is the exponent of the result.
MANTTYPE da; // da is a single 'digit' after possible padding.
MANTTYPE db; // db is a single 'digit' after possible padding.
MANTTYPE cy = 0; // cy is the value of a carry after adding two 'digits'
int32_t fcompla = 0; // fcompla is a flag to signal a is negative.
int32_t fcomplb = 0; // fcomplb is a flag to signal b is negative.
a = *pa;
// Calculate the overlap of the numbers after alignment, this includes
// necessary padding 0's
cdigits = max( a->cdigit+a->exp, b->cdigit+b->exp ) -
min( a->exp, b->exp );
cdigits = max(a->cdigit + a->exp, b->cdigit + b->exp) - min(a->exp, b->exp);
createnum( c, cdigits + 1 );
c->exp = min( a->exp, b->exp );
createnum(c, cdigits + 1);
c->exp = min(a->exp, b->exp);
mexp = c->exp;
c->cdigit = cdigits;
pcha = a->mant;
@ -93,89 +91,82 @@ void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
pchc = c->mant;
// Figure out the sign of the numbers
if ( a->sign != b->sign )
{
if (a->sign != b->sign)
{
cy = 1;
fcompla = ( a->sign == -1 );
fcomplb = ( b->sign == -1 );
}
fcompla = (a->sign == -1);
fcomplb = (b->sign == -1);
}
// Loop over all the digits, real and 0 padded. Here we know a and b are
// aligned
for ( ;cdigits > 0; cdigits--, mexp++ )
{
for (; cdigits > 0; cdigits--, mexp++)
{
// Get digit from a, taking padding into account.
da = ( ( ( mexp >= a->exp ) && ( cdigits + a->exp - c->exp >
(c->cdigit - a->cdigit) ) ) ?
*pcha++ : 0 );
da = (((mexp >= a->exp) && (cdigits + a->exp - c->exp > (c->cdigit - a->cdigit))) ? *pcha++ : 0);
// Get digit from b, taking padding into account.
db = ( ( ( mexp >= b->exp ) && ( cdigits + b->exp - c->exp >
(c->cdigit - b->cdigit) ) ) ?
*pchb++ : 0 );
db = (((mexp >= b->exp) && (cdigits + b->exp - c->exp > (c->cdigit - b->cdigit))) ? *pchb++ : 0);
// Handle complementing for a and b digit. Might be a better way, but
// haven't found it yet.
if ( fcompla )
{
da = (MANTTYPE)(radix) - 1 - da;
}
if ( fcomplb )
{
db = (MANTTYPE)(radix) - 1 - db;
}
if (fcompla)
{
da = (MANTTYPE)(radix)-1 - da;
}
if (fcomplb)
{
db = (MANTTYPE)(radix)-1 - db;
}
// Update carry as necessary
cy = da + db + cy;
*pchc++ = (MANTTYPE)(cy % (MANTTYPE)radix);
cy /= (MANTTYPE)radix;
}
}
// Handle carry from last sum as extra digit
if ( cy && !(fcompla || fcomplb) )
{
if (cy && !(fcompla || fcomplb))
{
*pchc++ = cy;
c->cdigit++;
}
}
// Compute sign of result
if ( !(fcompla || fcomplb) )
{
if (!(fcompla || fcomplb))
{
c->sign = a->sign;
}
}
else
{
if (cy)
{
if ( cy )
{
c->sign = 1;
}
}
else
{
{
// In this particular case an overflow or underflow has occurred
// and all the digits need to be complemented, at one time an
// attempt to handle this above was made, it turned out to be much
// slower on average.
c->sign = -1;
cy = 1;
for ( ( cdigits = c->cdigit ), (pchc = c->mant);
cdigits > 0;
cdigits-- )
{
for ((cdigits = c->cdigit), (pchc = c->mant); cdigits > 0; cdigits--)
{
cy = (MANTTYPE)radix - (MANTTYPE)1 - *pchc + cy;
*pchc++ = (MANTTYPE)( cy % (MANTTYPE)radix);
*pchc++ = (MANTTYPE)(cy % (MANTTYPE)radix);
cy /= (MANTTYPE)radix;
}
}
}
}
// Remove leading zeros, remember digits are in order of
// increasing significance. i.e. 100 would be 0,0,1
while ( c->cdigit > 1 && *(--pchc) == 0 )
{
while (c->cdigit > 1 && *(--pchc) == 0)
{
c->cdigit--;
}
destroynum( *pa );
*pa=c;
}
destroynum(*pa);
*pa = c;
}
//----------------------------------------------------------------------------
@ -193,52 +184,52 @@ void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
//
//----------------------------------------------------------------------------
void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix);
void _mulnum(PNUMBER* pa, PNUMBER b, uint32_t radix);
void __inline mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
void __inline mulnum(PNUMBER* pa, PNUMBER b, uint32_t radix)
{
if ( b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0 )
{ // If b is one we don't multiply exactly.
if ( (*pa)->cdigit > 1 || (*pa)->mant[0] != 1 || (*pa)->exp != 0 )
{ // pa and b are both non-one.
_mulnum( pa, b, radix);
}
if (b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0)
{ // If b is one we don't multiply exactly.
if ((*pa)->cdigit > 1 || (*pa)->mant[0] != 1 || (*pa)->exp != 0)
{ // pa and b are both non-one.
_mulnum(pa, b, radix);
}
else
{ // if pa is one and b isn't just copy b, and adjust the sign.
{ // if pa is one and b isn't just copy b, and adjust the sign.
int32_t sign = (*pa)->sign;
DUPNUM(*pa,b);
DUPNUM(*pa, b);
(*pa)->sign *= sign;
}
}
}
else
{ // But we do have to set the sign.
{ // But we do have to set the sign.
(*pa)->sign *= b->sign;
}
}
}
void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
void _mulnum(PNUMBER* pa, PNUMBER b, uint32_t radix)
{
PNUMBER c= nullptr; // c will contain the result.
PNUMBER a= nullptr; // a is the dereferenced number pointer from *pa
MANTTYPE *pcha; // pcha is a pointer to the mantissa of a.
MANTTYPE *pchb; // pchb is a pointer to the mantissa of b.
MANTTYPE *pchc; // pchc is a pointer to the mantissa of c.
MANTTYPE *pchcoffset; // pchcoffset, is the anchor location of the next
// single digit multiply partial result.
int32_t iadigit = 0; // Index of digit being used in the first number.
int32_t ibdigit = 0; // Index of digit being used in the second number.
MANTTYPE da = 0; // da is the digit from the fist number.
TWO_MANTTYPE cy = 0; // cy is the carry resulting from the addition of
// a multiplied row into the result.
TWO_MANTTYPE mcy = 0; // mcy is the resultant from a single
// multiply, AND the carry of that multiply.
int32_t icdigit = 0; // Index of digit being calculated in final result.
PNUMBER c = nullptr; // c will contain the result.
PNUMBER a = nullptr; // a is the dereferenced number pointer from *pa
MANTTYPE* pcha; // pcha is a pointer to the mantissa of a.
MANTTYPE* pchb; // pchb is a pointer to the mantissa of b.
MANTTYPE* pchc; // pchc is a pointer to the mantissa of c.
MANTTYPE* pchcoffset; // pchcoffset, is the anchor location of the next
// single digit multiply partial result.
int32_t iadigit = 0; // Index of digit being used in the first number.
int32_t ibdigit = 0; // Index of digit being used in the second number.
MANTTYPE da = 0; // da is the digit from the fist number.
TWO_MANTTYPE cy = 0; // cy is the carry resulting from the addition of
// a multiplied row into the result.
TWO_MANTTYPE mcy = 0; // mcy is the resultant from a single
// multiply, AND the carry of that multiply.
int32_t icdigit = 0; // Index of digit being calculated in final result.
a=*pa;
a = *pa;
ibdigit = a->cdigit + b->cdigit - 1;
createnum( c, ibdigit + 1 );
createnum(c, ibdigit + 1);
c->cdigit = ibdigit;
c->sign = a->sign * b->sign;
@ -246,58 +237,56 @@ void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
pcha = a->mant;
pchcoffset = c->mant;
for ( iadigit = a->cdigit; iadigit > 0; iadigit-- )
{
da = *pcha++;
for (iadigit = a->cdigit; iadigit > 0; iadigit--)
{
da = *pcha++;
pchb = b->mant;
// Shift pchc, and pchcoffset, one for each digit
pchc = pchcoffset++;
for ( ibdigit = b->cdigit; ibdigit > 0; ibdigit-- )
{
for (ibdigit = b->cdigit; ibdigit > 0; ibdigit--)
{
cy = 0;
mcy = (TWO_MANTTYPE)da * *pchb;
if ( mcy )
{
if (mcy)
{
icdigit = 0;
if ( ibdigit == 1 && iadigit == 1 )
{
c->cdigit++;
}
}
// If result is nonzero, or while result of carry is nonzero...
while ( mcy || cy )
if (ibdigit == 1 && iadigit == 1)
{
c->cdigit++;
}
}
// If result is nonzero, or while result of carry is nonzero...
while (mcy || cy)
{
// update carry from addition(s) and multiply.
cy += (TWO_MANTTYPE)pchc[icdigit]+(mcy%(TWO_MANTTYPE)radix);
cy += (TWO_MANTTYPE)pchc[icdigit] + (mcy % (TWO_MANTTYPE)radix);
// update result digit from
pchc[icdigit++]=(MANTTYPE)(cy%(TWO_MANTTYPE)radix);
pchc[icdigit++] = (MANTTYPE)(cy % (TWO_MANTTYPE)radix);
// update carries from
mcy /= (TWO_MANTTYPE)radix;
cy /= (TWO_MANTTYPE)radix;
}
}
pchb++;
pchc++;
}
}
}
// prevent different kinds of zeros, by stripping leading duplicate zeros.
// digits are in order of increasing significance.
while ( c->cdigit > 1 && c->mant[c->cdigit-1] == 0 )
{
while (c->cdigit > 1 && c->mant[c->cdigit - 1] == 0)
{
c->cdigit--;
}
}
destroynum( *pa );
*pa=c;
destroynum(*pa);
*pa = c;
}
//----------------------------------------------------------------------------
//
// FUNCTION: remnum
@ -313,55 +302,53 @@ void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
//
//----------------------------------------------------------------------------
void remnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
void remnum(PNUMBER* pa, PNUMBER b, uint32_t radix)
{
PNUMBER tmp = nullptr; // tmp is the working remainder.
PNUMBER lasttmp = nullptr; // lasttmp is the last remainder which worked.
// Once *pa is less than b, *pa is the remainder.
while ( !lessnum( *pa, b ) )
while (!lessnum(*pa, b))
{
DUPNUM(tmp, b);
if (lessnum(tmp, *pa))
{
DUPNUM( tmp, b );
if ( lessnum( tmp, *pa ) )
{
// Start off close to the right answer for subtraction.
tmp->exp = (*pa)->cdigit+(*pa)->exp - tmp->cdigit;
if ( MSD(*pa) <= MSD(tmp) )
{
tmp->exp = (*pa)->cdigit + (*pa)->exp - tmp->cdigit;
if (MSD(*pa) <= MSD(tmp))
{
// Don't take the chance that the numbers are equal.
tmp->exp--;
}
}
}
destroynum( lasttmp );
lasttmp=i32tonum( 0, radix);
destroynum(lasttmp);
lasttmp = i32tonum(0, radix);
while ( lessnum( tmp, *pa ) )
{
DUPNUM( lasttmp, tmp );
addnum( &tmp, tmp, radix);
}
while (lessnum(tmp, *pa))
{
DUPNUM(lasttmp, tmp);
addnum(&tmp, tmp, radix);
}
if ( lessnum( *pa, tmp ) )
{
if (lessnum(*pa, tmp))
{
// too far, back up...
destroynum( tmp );
tmp=lasttmp;
lasttmp= nullptr;
}
destroynum(tmp);
tmp = lasttmp;
lasttmp = nullptr;
}
// Subtract the working remainder from the remainder holder.
tmp->sign = -1*(*pa)->sign;
addnum( pa, tmp, radix);
tmp->sign = -1 * (*pa)->sign;
addnum(pa, tmp, radix);
destroynum( tmp );
destroynum( lasttmp );
}
destroynum(tmp);
destroynum(lasttmp);
}
}
//---------------------------------------------------------------------------
//
// FUNCTION: divnum
@ -376,23 +363,23 @@ void remnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
//
//---------------------------------------------------------------------------
void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision);
void _divnum(PNUMBER* pa, PNUMBER b, uint32_t radix, int32_t precision);
void __inline divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
void __inline divnum(PNUMBER* pa, PNUMBER b, uint32_t radix, int32_t precision)
{
if ( b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0 )
{
if (b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0)
{
// b is not one
_divnum( pa, b, radix, precision);
}
_divnum(pa, b, radix, precision);
}
else
{ // But we do have to set the sign.
{ // But we do have to set the sign.
(*pa)->sign *= b->sign;
}
}
}
void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
void _divnum(PNUMBER* pa, PNUMBER b, uint32_t radix, int32_t precision)
{
PNUMBER a = *pa;
int32_t thismax = precision + 2;
@ -411,7 +398,7 @@ void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
c->exp = (a->cdigit + a->exp) - (b->cdigit + b->exp) + 1;
c->sign = a->sign * b->sign;
MANTTYPE *ptrc = c->mant + thismax;
MANTTYPE* ptrc = c->mant + thismax;
PNUMBER rem = nullptr;
PNUMBER tmp = nullptr;
DUPNUM(rem, a);
@ -489,7 +476,6 @@ void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
*pa = c;
}
//---------------------------------------------------------------------------
//
// FUNCTION: equnum
@ -503,58 +489,56 @@ void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
//
//---------------------------------------------------------------------------
bool equnum( PNUMBER a, PNUMBER b )
bool equnum(PNUMBER a, PNUMBER b)
{
int32_t diff;
MANTTYPE *pa;
MANTTYPE *pb;
MANTTYPE* pa;
MANTTYPE* pb;
int32_t cdigits;
int32_t ccdigits;
MANTTYPE da;
MANTTYPE db;
MANTTYPE da;
MANTTYPE db;
diff = ( a->cdigit + a->exp ) - ( b->cdigit + b->exp );
if ( diff < 0 )
{
diff = (a->cdigit + a->exp) - (b->cdigit + b->exp);
if (diff < 0)
{
// If the exponents are different, these are different numbers.
return false;
}
}
else
{
if (diff > 0)
{
if ( diff > 0 )
{
// If the exponents are different, these are different numbers.
return false;
}
}
else
{
{
// OK the exponents match.
pa = a->mant;
pb = b->mant;
pa += a->cdigit - 1;
pb += b->cdigit - 1;
cdigits = max( a->cdigit, b->cdigit );
cdigits = max(a->cdigit, b->cdigit);
ccdigits = cdigits;
// Loop over all digits until we run out of digits or there is a
// difference in the digits.
for ( ;cdigits > 0; cdigits-- )
for (; cdigits > 0; cdigits--)
{
da = ((cdigits > (ccdigits - a->cdigit)) ? *pa-- : 0);
db = ((cdigits > (ccdigits - b->cdigit)) ? *pb-- : 0);
if (da != db)
{
da = ( (cdigits > (ccdigits - a->cdigit) ) ?
*pa-- : 0 );
db = ( (cdigits > (ccdigits - b->cdigit) ) ?
*pb-- : 0 );
if ( da != db )
{
return false;
}
}
}
// In this case, they are equal.
return true;
}
}
}
}
//---------------------------------------------------------------------------
@ -571,54 +555,51 @@ bool equnum( PNUMBER a, PNUMBER b )
//
//---------------------------------------------------------------------------
bool lessnum( PNUMBER a, PNUMBER b )
bool lessnum(PNUMBER a, PNUMBER b)
{
int32_t diff;
MANTTYPE *pa;
MANTTYPE *pb;
MANTTYPE* pa;
MANTTYPE* pb;
int32_t cdigits;
int32_t ccdigits;
MANTTYPE da;
MANTTYPE db;
MANTTYPE da;
MANTTYPE db;
diff = ( a->cdigit + a->exp ) - ( b->cdigit + b->exp );
if ( diff < 0 )
{
diff = (a->cdigit + a->exp) - (b->cdigit + b->exp);
if (diff < 0)
{
// The exponent of a is less than b
return true;
}
}
else
{
if (diff > 0)
{
if ( diff > 0 )
{
return false;
}
}
else
{
{
pa = a->mant;
pb = b->mant;
pa += a->cdigit - 1;
pb += b->cdigit - 1;
cdigits = max( a->cdigit, b->cdigit );
cdigits = max(a->cdigit, b->cdigit);
ccdigits = cdigits;
for ( ;cdigits > 0; cdigits-- )
for (; cdigits > 0; cdigits--)
{
da = ((cdigits > (ccdigits - a->cdigit)) ? *pa-- : 0);
db = ((cdigits > (ccdigits - b->cdigit)) ? *pb-- : 0);
diff = da - db;
if (diff)
{
da = ( (cdigits > (ccdigits - a->cdigit) ) ?
*pa-- : 0 );
db = ( (cdigits > (ccdigits - b->cdigit) ) ?
*pb-- : 0 );
diff = da-db;
if ( diff )
{
return( diff < 0 );
}
return (diff < 0);
}
}
// In this case, they are equal.
return false;
}
}
}
}
//----------------------------------------------------------------------------
@ -633,24 +614,24 @@ bool lessnum( PNUMBER a, PNUMBER b )
//
//----------------------------------------------------------------------------
bool zernum( PNUMBER a )
bool zernum(PNUMBER a)
{
int32_t length;
MANTTYPE *pcha;
MANTTYPE* pcha;
length = a->cdigit;
pcha = a->mant;
// loop over all the digits until you find a nonzero or until you run
// out of digits
while ( length-- > 0 )
while (length-- > 0)
{
if (*pcha++)
{
if ( *pcha++ )
{
// One of the digits isn't zero, therefore the number isn't zero
return false;
}
}
}
// All of the digits are zero, therefore the number is zero
return true;
}

View file

@ -37,23 +37,23 @@ using namespace std;
//
//-----------------------------------------------------------------------------
void gcdrat( PRAT *pa, int32_t precision)
void gcdrat(PRAT* pa, int32_t precision)
{
PNUMBER pgcd= nullptr;
PRAT a= nullptr;
PNUMBER pgcd = nullptr;
PRAT a = nullptr;
a=*pa;
pgcd = gcd( a->pp, a->pq );
a = *pa;
pgcd = gcd(a->pp, a->pq);
if ( !zernum( pgcd ) )
{
divnumx( &(a->pp), pgcd, precision);
divnumx( &(a->pq), pgcd, precision);
}
if (!zernum(pgcd))
{
divnumx(&(a->pp), pgcd, precision);
divnumx(&(a->pq), pgcd, precision);
}
destroynum( pgcd );
*pa=a;
destroynum(pgcd);
*pa = a;
RENORMALIZE(*pa);
}
@ -70,16 +70,16 @@ void gcdrat( PRAT *pa, int32_t precision)
//
//-----------------------------------------------------------------------------
void fracrat( PRAT *pa , uint32_t radix, int32_t precision)
void fracrat(PRAT* pa, uint32_t radix, int32_t precision)
{
// Only do the flatrat operation if number is nonzero.
// and only if the bottom part is not one.
if ( !zernum( (*pa)->pp ) && !equnum( (*pa)->pq, num_one ) )
if (!zernum((*pa)->pp) && !equnum((*pa)->pq, num_one))
{
flatrat(*pa, radix, precision);
}
remnum( &((*pa)->pp), (*pa)->pq, BASEX );
remnum(&((*pa)->pp), (*pa)->pq, BASEX);
// Get *pa back in the integer over integer form.
RENORMALIZE(*pa);
@ -98,26 +98,25 @@ void fracrat( PRAT *pa , uint32_t radix, int32_t precision)
//
//-----------------------------------------------------------------------------
void mulrat( PRAT *pa, PRAT b, int32_t precision)
void mulrat(PRAT* pa, PRAT b, int32_t precision)
{
{
// Only do the multiply if it isn't zero.
if ( !zernum( (*pa)->pp ) )
{
mulnumx( &((*pa)->pp), b->pp );
mulnumx( &((*pa)->pq), b->pq );
if (!zernum((*pa)->pp))
{
mulnumx(&((*pa)->pp), b->pp);
mulnumx(&((*pa)->pq), b->pq);
trimit(pa, precision);
}
}
else
{
{
// If it is zero, blast a one in the denominator.
DUPNUM( ((*pa)->pq), num_one );
}
DUPNUM(((*pa)->pq), num_one);
}
#ifdef MULGCD
gcdrat( pa );
gcdrat(pa);
#endif
}
//-----------------------------------------------------------------------------
@ -133,44 +132,41 @@ void mulrat( PRAT *pa, PRAT b, int32_t precision)
//
//-----------------------------------------------------------------------------
void divrat( PRAT *pa, PRAT b, int32_t precision)
void divrat(PRAT* pa, PRAT b, int32_t precision)
{
if ( !zernum( (*pa)->pp ) )
{
if (!zernum((*pa)->pp))
{
// Only do the divide if the top isn't zero.
mulnumx( &((*pa)->pp), b->pq );
mulnumx( &((*pa)->pq), b->pp );
mulnumx(&((*pa)->pp), b->pq);
mulnumx(&((*pa)->pq), b->pp);
if ( zernum( (*pa)->pq ) )
{
// raise an exception if the bottom is 0.
throw( CALC_E_DIVIDEBYZERO );
}
trimit(pa, precision);
}
else
if (zernum((*pa)->pq))
{
// raise an exception if the bottom is 0.
throw(CALC_E_DIVIDEBYZERO);
}
trimit(pa, precision);
}
else
{
// Top is zero.
if ( zerrat( b ) )
{
if (zerrat(b))
{
// If bottom is zero
// 0 / 0 is indefinite, raise an exception.
throw( CALC_E_INDEFINITE );
}
else
{
// 0/x make a unique 0.
DUPNUM( ((*pa)->pq), num_one );
}
throw(CALC_E_INDEFINITE);
}
else
{
// 0/x make a unique 0.
DUPNUM(((*pa)->pq), num_one);
}
}
#ifdef DIVGCD
gcdrat( pa );
gcdrat(pa);
#endif
}
//-----------------------------------------------------------------------------
@ -186,11 +182,11 @@ void divrat( PRAT *pa, PRAT b, int32_t precision)
//
//-----------------------------------------------------------------------------
void subrat( PRAT *pa, PRAT b, int32_t precision)
void subrat(PRAT* pa, PRAT b, int32_t precision)
{
b->pp->sign *= -1;
addrat( pa, b, precision);
addrat(pa, b, precision);
b->pp->sign *= -1;
}
@ -207,13 +203,13 @@ void subrat( PRAT *pa, PRAT b, int32_t precision)
//
//-----------------------------------------------------------------------------
void addrat( PRAT *pa, PRAT b, int32_t precision)
void addrat(PRAT* pa, PRAT b, int32_t precision)
{
PNUMBER bot= nullptr;
PNUMBER bot = nullptr;
if ( equnum( (*pa)->pq, b->pq ) )
{
if (equnum((*pa)->pq, b->pq))
{
// Very special case, q's match.,
// make sure signs are involved in the calculation
// we have to do this since the optimization here is only
@ -222,33 +218,30 @@ void addrat( PRAT *pa, PRAT b, int32_t precision)
(*pa)->pq->sign = 1;
b->pp->sign *= b->pq->sign;
b->pq->sign = 1;
addnum( &((*pa)->pp), b->pp, BASEX );
}
addnum(&((*pa)->pp), b->pp, BASEX);
}
else
{
{
// Usual case q's aren't the same.
DUPNUM( bot, (*pa)->pq );
mulnumx( &bot, b->pq );
mulnumx( &((*pa)->pp), b->pq );
mulnumx( &((*pa)->pq), b->pp );
addnum( &((*pa)->pp), (*pa)->pq, BASEX );
destroynum( (*pa)->pq );
DUPNUM(bot, (*pa)->pq);
mulnumx(&bot, b->pq);
mulnumx(&((*pa)->pp), b->pq);
mulnumx(&((*pa)->pq), b->pp);
addnum(&((*pa)->pp), (*pa)->pq, BASEX);
destroynum((*pa)->pq);
(*pa)->pq = bot;
trimit(pa, precision);
// Get rid of negative zeros here.
(*pa)->pp->sign *= (*pa)->pq->sign;
(*pa)->pq->sign = 1;
}
}
#ifdef ADDGCD
gcdrat( pa );
gcdrat(pa);
#endif
}
//-----------------------------------------------------------------------------
//
// FUNCTION: rootrat
@ -262,11 +255,11 @@ void addrat( PRAT *pa, PRAT b, int32_t precision)
//
//-----------------------------------------------------------------------------
void rootrat( PRAT *py, PRAT n, uint32_t radix, int32_t precision)
void rootrat(PRAT* py, PRAT n, uint32_t radix, int32_t precision)
{
// Initialize 1/n
PRAT oneovern= nullptr;
DUPRAT(oneovern,rat_one);
PRAT oneovern = nullptr;
DUPRAT(oneovern, rat_one);
divrat(&oneovern, n, precision);
powrat(py, oneovern, radix, precision);
@ -274,7 +267,6 @@ void rootrat( PRAT *py, PRAT n, uint32_t radix, int32_t precision)
destroyrat(oneovern);
}
//-----------------------------------------------------------------------------
//
// FUNCTION: zerrat
@ -288,10 +280,8 @@ void rootrat( PRAT *py, PRAT n, uint32_t radix, int32_t precision)
//
//-----------------------------------------------------------------------------
bool zerrat( PRAT a )
bool zerrat(PRAT a)
{
return( zernum(a->pp) );
return (zernum(a->pp));
}

File diff suppressed because it is too large Load diff

View file

@ -21,27 +21,29 @@
#include <string>
#include "CalcErr.h"
#include <cstring> // for memmove
#include <sal.h> // for SAL
#include <sal.h> // for SAL
static constexpr uint32_t BASEXPWR = 31L;// Internal log2(BASEX)
static constexpr uint32_t BASEXPWR = 31L; // Internal log2(BASEX)
static constexpr uint32_t BASEX = 0x80000000; // Internal radix used in calculations, hope to raise
// this to 2^32 after solving scaling problems with
// overflow detection esp. in mul
// this to 2^32 after solving scaling problems with
// overflow detection esp. in mul
typedef uint32_t MANTTYPE;
typedef uint64_t TWO_MANTTYPE;
enum eNUMOBJ_FMT {
FMT_FLOAT, // returns floating point, or exponential if number is too big
FMT_SCIENTIFIC, // always returns scientific notation
FMT_ENGINEERING // always returns engineering notation such that exponent is a multiple of 3
enum eNUMOBJ_FMT
{
FMT_FLOAT, // returns floating point, or exponential if number is too big
FMT_SCIENTIFIC, // always returns scientific notation
FMT_ENGINEERING // always returns engineering notation such that exponent is a multiple of 3
};
enum eANGLE_TYPE {
ANGLE_DEG, // Calculate trig using 360 degrees per revolution
ANGLE_RAD, // Calculate trig using 2 pi radians per revolution
ANGLE_GRAD // Calculate trig using 400 gradients per revolution
enum eANGLE_TYPE
{
ANGLE_DEG, // Calculate trig using 360 degrees per revolution
ANGLE_RAD, // Calculate trig using 2 pi radians per revolution
ANGLE_GRAD // Calculate trig using 400 gradients per revolution
};
@ -55,21 +57,20 @@ typedef enum eANGLE_TYPE ANGLE_TYPE;
//-----------------------------------------------------------------------------
#pragma warning(push)
#pragma warning(disable:4200) // nonstandard extension used : zero-sized array in struct/union
#pragma warning(disable : 4200) // nonstandard extension used : zero-sized array in struct/union
typedef struct _number
{
int32_t sign; // The sign of the mantissa, +1, or -1
int32_t cdigit; // The number of digits, or what passes for digits in the
int32_t sign; // The sign of the mantissa, +1, or -1
int32_t cdigit; // The number of digits, or what passes for digits in the
// radix being used.
int32_t exp; // The offset of digits from the radix point
int32_t exp; // The offset of digits from the radix point
// (decimal point in radix 10)
MANTTYPE mant[];
// This is actually allocated as a continuation of the
// NUMBER structure.
// This is actually allocated as a continuation of the
// NUMBER structure.
} NUMBER, *PNUMBER, **PPNUMBER;
#pragma warning(pop)
//-----------------------------------------------------------------------------
//
// RAT type is a representation radix on 2 NUMBER types.
@ -78,10 +79,10 @@ typedef struct _number
//-----------------------------------------------------------------------------
typedef struct _rat
{
{
PNUMBER pp;
PNUMBER pq;
} RAT, *PRAT;
} RAT, *PRAT;
static constexpr uint32_t MAX_LONG_SIZE = 33; // Base 2 requires 32 'digits'
@ -135,27 +136,34 @@ extern PRAT rat_max_i32;
extern PRAT rat_min_i32;
// DUPNUM Duplicates a number taking care of allocation and internals
#define DUPNUM(a,b) destroynum(a);createnum( a, (b)->cdigit );_dupnum(a, b);
#define DUPNUM(a, b) \
destroynum(a); \
createnum(a, (b)->cdigit); \
_dupnum(a, b);
// DUPRAT Duplicates a rational taking care of allocation and internals
#define DUPRAT(a,b) destroyrat(a);createrat(a);DUPNUM((a)->pp,(b)->pp);DUPNUM((a)->pq,(b)->pq);
#define DUPRAT(a, b) \
destroyrat(a); \
createrat(a); \
DUPNUM((a)->pp, (b)->pp); \
DUPNUM((a)->pq, (b)->pq);
// LOG*RADIX calculates the integral portion of the log of a number in
// the base currently being used, only accurate to within g_ratio
#define LOGNUMRADIX(pnum) (((pnum)->cdigit+(pnum)->exp)*g_ratio)
#define LOGRATRADIX(prat) (LOGNUMRADIX((prat)->pp)-LOGNUMRADIX((prat)->pq))
#define LOGNUMRADIX(pnum) (((pnum)->cdigit + (pnum)->exp) * g_ratio)
#define LOGRATRADIX(prat) (LOGNUMRADIX((prat)->pp) - LOGNUMRADIX((prat)->pq))
// LOG*2 calculates the integral portion of the log of a number in
// the internal base being used, only accurate to within g_ratio
#define LOGNUM2(pnum) ((pnum)->cdigit+(pnum)->exp)
#define LOGRAT2(prat) (LOGNUM2((prat)->pp)-LOGNUM2((prat)->pq))
#define LOGNUM2(pnum) ((pnum)->cdigit + (pnum)->exp)
#define LOGRAT2(prat) (LOGNUM2((prat)->pp) - LOGNUM2((prat)->pq))
// SIGN returns the sign of the rational
#define SIGN(prat) ((prat)->pp->sign*(prat)->pq->sign)
#define SIGN(prat) ((prat)->pp->sign * (prat)->pq->sign)
#if defined( DEBUG_RATPAK )
#if defined(DEBUG_RATPAK)
//-----------------------------------------------------------------------------
//
// Debug versions of rational number creation and destruction routines.
@ -163,37 +171,39 @@ extern PRAT rat_min_i32;
//
//-----------------------------------------------------------------------------
#define createrat(y) (y)=_createrat(); \
{ \
std::wstringstream outputString; \
outputString << "createrat " << y << " " << # y << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
OutputDebugString(outputString.str().c_str()); \
}
#define destroyrat(x) \
{ \
std::wstringstream outputString; \
outputString << "destroyrat " << x << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
OutputDebugString(outputString.str().c_str()); \
} \
_destroyrat(x),(x)=nullptr
#define createnum(y,x) (y)=_createnum(x); \
{ \
std::wstringstream outputString; \
outputString << "createnum " << y << " " << # y << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
OutputDebugString(outputString.str().c_str()); \
}
#define destroynum(x) \
{ \
std::wstringstream outputString; \
outputString << "destroynum " << x << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
OutputDebugString(outputString.str().c_str()); \
} \
_destroynum(x),(x)=nullptr
#define createrat(y) \
(y) = _createrat(); \
{ \
std::wstringstream outputString; \
outputString << "createrat " << y << " " << #y << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
OutputDebugString(outputString.str().c_str()); \
}
#define destroyrat(x) \
{ \
std::wstringstream outputString; \
outputString << "destroyrat " << x << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
OutputDebugString(outputString.str().c_str()); \
} \
_destroyrat(x), (x) = nullptr
#define createnum(y, x) \
(y) = _createnum(x); \
{ \
std::wstringstream outputString; \
outputString << "createnum " << y << " " << #y << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
OutputDebugString(outputString.str().c_str()); \
}
#define destroynum(x) \
{ \
std::wstringstream outputString; \
outputString << "destroynum " << x << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
OutputDebugString(outputString.str().c_str()); \
} \
_destroynum(x), (x) = nullptr
#else
#define createrat(y) (y)=_createrat()
#define destroyrat(x) _destroyrat(x),(x)=nullptr
#define createnum(y,x) (y)=_createnum(x)
#define destroynum(x) _destroynum(x),(x)=nullptr
#define createrat(y) (y) = _createrat()
#define destroyrat(x) _destroyrat(x), (x) = nullptr
#define createnum(y, x) (y) = _createnum(x)
#define destroynum(x) _destroynum(x), (x) = nullptr
#endif
//-----------------------------------------------------------------------------
@ -204,40 +214,47 @@ _destroynum(x),(x)=nullptr
//-----------------------------------------------------------------------------
// RENORMALIZE, gets the exponents non-negative.
#define RENORMALIZE(x) if ( (x)->pp->exp < 0 ) { \
(x)->pq->exp -= (x)->pp->exp; \
(x)->pp->exp = 0; \
} \
if ( (x)->pq->exp < 0 ) { \
(x)->pp->exp -= (x)->pq->exp; \
(x)->pq->exp = 0; \
#define RENORMALIZE(x) \
if ((x)->pp->exp < 0) \
{ \
(x)->pq->exp -= (x)->pp->exp; \
(x)->pp->exp = 0; \
} \
if ((x)->pq->exp < 0) \
{ \
(x)->pp->exp -= (x)->pq->exp; \
(x)->pq->exp = 0; \
}
// TRIMNUM ASSUMES the number is in radix form NOT INTERNAL BASEX!!!
#define TRIMNUM(x, precision) if ( !g_ftrueinfinite ) { \
int32_t trim = (x)->cdigit - precision-g_ratio;\
if ( trim > 1 ) \
{ \
memmove( (x)->mant, &((x)->mant[trim]), sizeof(MANTTYPE)*((x)->cdigit-trim) ); \
(x)->cdigit -= trim; \
(x)->exp += trim; \
} \
}
#define TRIMNUM(x, precision) \
if (!g_ftrueinfinite) \
{ \
int32_t trim = (x)->cdigit - precision - g_ratio; \
if (trim > 1) \
{ \
memmove((x)->mant, &((x)->mant[trim]), sizeof(MANTTYPE) * ((x)->cdigit - trim)); \
(x)->cdigit -= trim; \
(x)->exp += trim; \
} \
}
// TRIMTOP ASSUMES the number is in INTERNAL BASEX!!!
#define TRIMTOP(x, precision) if ( !g_ftrueinfinite ) { \
int32_t trim = (x)->pp->cdigit - (precision/g_ratio) - 2;\
if ( trim > 1 ) \
{ \
memmove( (x)->pp->mant, &((x)->pp->mant[trim]), sizeof(MANTTYPE)*((x)->pp->cdigit-trim) ); \
(x)->pp->cdigit -= trim; \
(x)->pp->exp += trim; \
} \
trim = std::min((x)->pp->exp,(x)->pq->exp);\
(x)->pp->exp -= trim;\
(x)->pq->exp -= trim;\
}
#define TRIMTOP(x, precision) \
if (!g_ftrueinfinite) \
{ \
int32_t trim = (x)->pp->cdigit - (precision / g_ratio) - 2; \
if (trim > 1) \
{ \
memmove((x)->pp->mant, &((x)->pp->mant[trim]), sizeof(MANTTYPE) * ((x)->pp->cdigit - trim)); \
(x)->pp->cdigit -= trim; \
(x)->pp->exp += trim; \
} \
trim = std::min((x)->pp->exp, (x)->pq->exp); \
(x)->pp->exp -= trim; \
(x)->pq->exp -= trim; \
}
#define SMALL_ENOUGH_RAT(a, precision) (zernum((a)->pp) || ( ( ( (a)->pq->cdigit + (a)->pq->exp ) - ( (a)->pp->cdigit + (a)->pp->exp ) - 1 ) * g_ratio > precision ) )
#define SMALL_ENOUGH_RAT(a, precision) (zernum((a)->pp) || ((((a)->pq->cdigit + (a)->pq->exp) - ((a)->pp->cdigit + (a)->pp->exp) - 1) * g_ratio > precision))
//-----------------------------------------------------------------------------
//
@ -246,50 +263,55 @@ memmove( (x)->pp->mant, &((x)->pp->mant[trim]), sizeof(MANTTYPE)*((x)->pp->cdigi
//
//-----------------------------------------------------------------------------
#define CREATETAYLOR() PRAT xx=nullptr;\
PNUMBER n2=nullptr; \
PRAT pret=nullptr; \
PRAT thisterm=nullptr; \
DUPRAT(xx,*px); \
mulrat(&xx,*px, precision); \
createrat(pret); \
pret->pp=i32tonum( 0L, BASEX ); \
pret->pq=i32tonum( 0L, BASEX );
#define CREATETAYLOR() \
PRAT xx = nullptr; \
PNUMBER n2 = nullptr; \
PRAT pret = nullptr; \
PRAT thisterm = nullptr; \
DUPRAT(xx, *px); \
mulrat(&xx, *px, precision); \
createrat(pret); \
pret->pp = i32tonum(0L, BASEX); \
pret->pq = i32tonum(0L, BASEX);
#define DESTROYTAYLOR() destroynum( n2 ); \
destroyrat( xx );\
destroyrat( thisterm );\
destroyrat( *px );\
trimit(&pret, precision);\
*px=pret;
#define DESTROYTAYLOR() \
destroynum(n2); \
destroyrat(xx); \
destroyrat(thisterm); \
destroyrat(*px); \
trimit(&pret, precision); \
*px = pret;
// INC(a) is the rational equivalent of a++
// Check to see if we can avoid doing this the hard way.
#define INC(a) if ( (a)->mant[0] < BASEX - 1 ) \
{ \
(a)->mant[0]++; \
} \
else \
{ \
addnum( &(a), num_one, BASEX); \
#define INC(a) \
if ((a)->mant[0] < BASEX - 1) \
{ \
(a)->mant[0]++; \
} \
else \
{ \
addnum(&(a), num_one, BASEX); \
}
#define MSD(x) ((x)->mant[(x)->cdigit-1])
#define MSD(x) ((x)->mant[(x)->cdigit - 1])
// MULNUM(b) is the rational equivalent of thisterm *= b where thisterm is
// a rational and b is a number, NOTE this is a mixed type operation for
// efficiency reasons.
#define MULNUM(b) mulnumx( &(thisterm->pp), b);
#define MULNUM(b) mulnumx(&(thisterm->pp), b);
// DIVNUM(b) is the rational equivalent of thisterm /= b where thisterm is
// a rational and b is a number, NOTE this is a mixed type operation for
// efficiency reasons.
#define DIVNUM(b) mulnumx( &(thisterm->pq), b);
#define DIVNUM(b) mulnumx(&(thisterm->pq), b);
// NEXTTERM(p,d) is the rational equivalent of
// thisterm *= p
// d <d is usually an expansion of operations to get thisterm updated.>
// pret += thisterm
#define NEXTTERM(p,d,precision) mulrat(&thisterm,p,precision);d addrat( &pret, thisterm, precision )
#define NEXTTERM(p, d, precision) \
mulrat(&thisterm, p, precision); \
d addrat(&pret, thisterm, precision)
//-----------------------------------------------------------------------------
//
@ -299,9 +321,9 @@ memmove( (x)->pp->mant, &((x)->pp->mant[trim]), sizeof(MANTTYPE)*((x)->pp->cdigi
extern bool g_ftrueinfinite; // set to true to allow infinite precision
// don't use unless you know what you are doing
// used to help decide when to stop calculating.
// used to help decide when to stop calculating.
extern int32_t g_ratio; // Internally calculated ratio of internal radix
extern int32_t g_ratio; // Internally calculated ratio of internal radix
//-----------------------------------------------------------------------------
//
@ -315,10 +337,10 @@ extern void SetDecimalSeparator(wchar_t decimalSeparator);
// Call whenever either radix or precision changes, is smarter about recalculating constants.
extern void ChangeConstants(uint32_t radix, int32_t precision);
extern bool equnum(_In_ PNUMBER a, _In_ PNUMBER b ); // returns true of a == b
extern bool lessnum(_In_ PNUMBER a, _In_ PNUMBER b ); // returns true of a < b
extern bool zernum(_In_ PNUMBER a ); // returns true of a == 0
extern bool zerrat(_In_ PRAT a ); // returns true if a == 0/q
extern bool equnum(_In_ PNUMBER a, _In_ PNUMBER b); // returns true of a == b
extern bool lessnum(_In_ PNUMBER a, _In_ PNUMBER b); // returns true of a < b
extern bool zernum(_In_ PNUMBER a); // returns true of a == 0
extern bool zerrat(_In_ PRAT a); // returns true if a == 0/q
extern std::wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_t precision);
// returns a text representation of a PRAT
@ -328,16 +350,18 @@ extern PNUMBER RatToNumber(_In_ PRAT prat, uint32_t radix, int32_t precision);
// flattens a PRAT by converting it to a PNUMBER and back to a PRAT
extern void flatrat(_Inout_ PRAT& prat, uint32_t radix, int32_t precision);
extern int32_t numtoi32(_In_ PNUMBER pnum, uint32_t radix );
extern int32_t numtoi32(_In_ PNUMBER pnum, uint32_t radix);
extern int32_t rattoi32(_In_ PRAT prat, uint32_t radix, int32_t precision);
uint64_t rattoUi64(_In_ PRAT prat, uint32_t radix, int32_t precision);
extern PNUMBER _createnum(_In_ uint32_t size ); // returns an empty number structure with size digits
extern PNUMBER _createnum(_In_ uint32_t size); // returns an empty number structure with size digits
extern PNUMBER nRadixxtonum(_In_ PNUMBER a, uint32_t radix, int32_t precision);
extern PNUMBER gcd(_In_ PNUMBER a, _In_ PNUMBER b );
extern PNUMBER StringToNumber(std::wstring_view numberString, uint32_t radix, int32_t precision); // takes a text representation of a number and returns a number.
extern PNUMBER gcd(_In_ PNUMBER a, _In_ PNUMBER b);
extern PNUMBER StringToNumber(std::wstring_view numberString, uint32_t radix,
int32_t precision); // takes a text representation of a number and returns a number.
// takes a text representation of a number as a mantissa with sign and an exponent with sign.
extern PRAT StringToRat(bool mantissaIsNegative, std::wstring_view mantissa, bool exponentIsNegative, std::wstring_view exponent, uint32_t radix, int32_t precision);
extern PRAT StringToRat(bool mantissaIsNegative, std::wstring_view mantissa, bool exponentIsNegative, std::wstring_view exponent, uint32_t radix,
int32_t precision);
extern PNUMBER i32factnum(int32_t ini32, uint32_t radix);
extern PNUMBER i32prodnum(int32_t start, int32_t stop, uint32_t radix);
@ -346,119 +370,119 @@ extern PNUMBER Ui32tonum(uint32_t ini32, uint32_t radix);
extern PNUMBER numtonRadixx(PNUMBER a, uint32_t radix);
// creates a empty/undefined rational representation (p/q)
extern PRAT _createrat( void );
extern PRAT _createrat(void);
// returns a new rat structure with the acos of x->p/x->q taking into account
// angle type
extern void acosanglerat( _Inout_ PRAT *px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
extern void acosanglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
// returns a new rat structure with the acosh of x->p/x->q
extern void acoshrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
extern void acoshrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the acos of x->p/x->q
extern void acosrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
extern void acosrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the asin of x->p/x->q taking into account
// angle type
extern void asinanglerat( _Inout_ PRAT *px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
extern void asinanglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
extern void asinhrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
extern void asinhrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the asinh of x->p/x->q
// returns a new rat structure with the asin of x->p/x->q
extern void asinrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
extern void asinrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the atan of x->p/x->q taking into account
// angle type
extern void atananglerat( _Inout_ PRAT *px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
extern void atananglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
// returns a new rat structure with the atanh of x->p/x->q
extern void atanhrat( _Inout_ PRAT *px, int32_t precision);
extern void atanhrat(_Inout_ PRAT* px, int32_t precision);
// returns a new rat structure with the atan of x->p/x->q
extern void atanrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
extern void atanrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the cosh of x->p/x->q
extern void coshrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
extern void coshrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the cos of x->p/x->q
extern void cosrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
extern void cosrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the cos of x->p/x->q taking into account
// angle type
extern void cosanglerat( _Inout_ PRAT *px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
extern void cosanglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
// returns a new rat structure with the exp of x->p/x->q this should not be called explicitly.
extern void _exprat( _Inout_ PRAT *px, int32_t precision);
extern void _exprat(_Inout_ PRAT* px, int32_t precision);
// returns a new rat structure with the exp of x->p/x->q
extern void exprat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
extern void exprat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the log base 10 of x->p/x->q
extern void log10rat( _Inout_ PRAT *px, int32_t precision);
extern void log10rat(_Inout_ PRAT* px, int32_t precision);
// returns a new rat structure with the natural log of x->p/x->q
extern void lograt( _Inout_ PRAT *px, int32_t precision);
extern void lograt(_Inout_ PRAT* px, int32_t precision);
extern PRAT i32torat( int32_t ini32 );
extern PRAT Ui32torat( uint32_t inui32 );
extern PRAT numtorat( _In_ PNUMBER pin, uint32_t radix);
extern PRAT i32torat(int32_t ini32);
extern PRAT Ui32torat(uint32_t inui32);
extern PRAT numtorat(_In_ PNUMBER pin, uint32_t radix);
extern void sinhrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
extern void sinrat( _Inout_ PRAT *px );
extern void sinhrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
extern void sinrat(_Inout_ PRAT* px);
// returns a new rat structure with the sin of x->p/x->q taking into account
// angle type
extern void sinanglerat( _Inout_ PRAT *px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
extern void sinanglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
extern void tanhrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
extern void tanrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
extern void tanhrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
extern void tanrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the tan of x->p/x->q taking into account
// angle type
extern void tananglerat( _Inout_ PRAT *px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
extern void tananglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
extern void _dupnum(_In_ PNUMBER dest, _In_ const NUMBER * const src);
extern void _dupnum(_In_ PNUMBER dest, _In_ const NUMBER* const src);
extern void _destroynum( _In_ PNUMBER pnum );
extern void _destroyrat( _In_ PRAT prat );
extern void addnum( _Inout_ PNUMBER *pa, _In_ PNUMBER b, uint32_t radix);
extern void addrat( _Inout_ PRAT *pa, _In_ PRAT b, int32_t precision);
extern void andrat( _Inout_ PRAT *pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void divnum( _Inout_ PNUMBER *pa, _In_ PNUMBER b, uint32_t radix, int32_t precision);
extern void divnumx( _Inout_ PNUMBER *pa, _In_ PNUMBER b, int32_t precision);
extern void divrat( _Inout_ PRAT *pa, _In_ PRAT b, int32_t precision);
extern void fracrat( _Inout_ PRAT *pa , uint32_t radix, int32_t precision);
extern void factrat( _Inout_ PRAT *pa, uint32_t radix, int32_t precision);
extern void remrat(_Inout_ PRAT *pa, _In_ PRAT b);
extern void modrat(_Inout_ PRAT *pa, _In_ PRAT b);
extern void gcdrat( _Inout_ PRAT *pa, int32_t precision);
extern void intrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
extern void mulnum( _Inout_ PNUMBER *pa, _In_ PNUMBER b, uint32_t radix);
extern void mulnumx( _Inout_ PNUMBER *pa, _In_ PNUMBER b );
extern void mulrat( _Inout_ PRAT *pa, _In_ PRAT b, int32_t precision);
extern void numpowi32( _Inout_ PNUMBER *proot, int32_t power, uint32_t radix, int32_t precision);
extern void numpowi32x( _Inout_ PNUMBER *proot, int32_t power );
extern void orrat( _Inout_ PRAT *pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void powrat( _Inout_ PRAT *pa, _In_ PRAT b , uint32_t radix, int32_t precision);
extern void powratNumeratorDenominator(_Inout_ PRAT *pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void powratcomp(_Inout_ PRAT *pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void ratpowi32( _Inout_ PRAT *proot, int32_t power, int32_t precision);
extern void remnum( _Inout_ PNUMBER *pa, _In_ PNUMBER b, uint32_t radix);
extern void rootrat( _Inout_ PRAT *pa, _In_ PRAT b , uint32_t radix, int32_t precision);
extern void scale2pi( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
extern void scale( _Inout_ PRAT *px, _In_ PRAT scalefact, uint32_t radix, int32_t precision);
extern void subrat( _Inout_ PRAT *pa, _In_ PRAT b, int32_t precision);
extern void xorrat( _Inout_ PRAT *pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void lshrat( _Inout_ PRAT *pa, _In_ PRAT b , uint32_t radix, int32_t precision);
extern void rshrat( _Inout_ PRAT *pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern bool rat_equ( _In_ PRAT a, _In_ PRAT b, int32_t precision);
extern bool rat_neq( _In_ PRAT a, _In_ PRAT b, int32_t precision);
extern bool rat_gt( _In_ PRAT a, _In_ PRAT b, int32_t precision);
extern bool rat_ge( _In_ PRAT a, _In_ PRAT b, int32_t precision);
extern bool rat_lt( _In_ PRAT a, _In_ PRAT b, int32_t precision);
extern bool rat_le( _In_ PRAT a, _In_ PRAT b, int32_t precision);
extern void inbetween( _In_ PRAT *px, _In_ PRAT range, int32_t precision);
extern void trimit( _Inout_ PRAT *px, int32_t precision);
extern void _dumprawrat(_In_ const wchar_t *varname, _In_ PRAT rat, std::wostream& out);
extern void _dumprawnum(_In_ const wchar_t *varname, _In_ PNUMBER num, std::wostream& out);
extern void _destroynum(_In_ PNUMBER pnum);
extern void _destroyrat(_In_ PRAT prat);
extern void addnum(_Inout_ PNUMBER* pa, _In_ PNUMBER b, uint32_t radix);
extern void addrat(_Inout_ PRAT* pa, _In_ PRAT b, int32_t precision);
extern void andrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void divnum(_Inout_ PNUMBER* pa, _In_ PNUMBER b, uint32_t radix, int32_t precision);
extern void divnumx(_Inout_ PNUMBER* pa, _In_ PNUMBER b, int32_t precision);
extern void divrat(_Inout_ PRAT* pa, _In_ PRAT b, int32_t precision);
extern void fracrat(_Inout_ PRAT* pa, uint32_t radix, int32_t precision);
extern void factrat(_Inout_ PRAT* pa, uint32_t radix, int32_t precision);
extern void remrat(_Inout_ PRAT* pa, _In_ PRAT b);
extern void modrat(_Inout_ PRAT* pa, _In_ PRAT b);
extern void gcdrat(_Inout_ PRAT* pa, int32_t precision);
extern void intrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
extern void mulnum(_Inout_ PNUMBER* pa, _In_ PNUMBER b, uint32_t radix);
extern void mulnumx(_Inout_ PNUMBER* pa, _In_ PNUMBER b);
extern void mulrat(_Inout_ PRAT* pa, _In_ PRAT b, int32_t precision);
extern void numpowi32(_Inout_ PNUMBER* proot, int32_t power, uint32_t radix, int32_t precision);
extern void numpowi32x(_Inout_ PNUMBER* proot, int32_t power);
extern void orrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void powrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void powratNumeratorDenominator(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void powratcomp(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void ratpowi32(_Inout_ PRAT* proot, int32_t power, int32_t precision);
extern void remnum(_Inout_ PNUMBER* pa, _In_ PNUMBER b, uint32_t radix);
extern void rootrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void scale2pi(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
extern void scale(_Inout_ PRAT* px, _In_ PRAT scalefact, uint32_t radix, int32_t precision);
extern void subrat(_Inout_ PRAT* pa, _In_ PRAT b, int32_t precision);
extern void xorrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void lshrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void rshrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern bool rat_equ(_In_ PRAT a, _In_ PRAT b, int32_t precision);
extern bool rat_neq(_In_ PRAT a, _In_ PRAT b, int32_t precision);
extern bool rat_gt(_In_ PRAT a, _In_ PRAT b, int32_t precision);
extern bool rat_ge(_In_ PRAT a, _In_ PRAT b, int32_t precision);
extern bool rat_lt(_In_ PRAT a, _In_ PRAT b, int32_t precision);
extern bool rat_le(_In_ PRAT a, _In_ PRAT b, int32_t precision);
extern void inbetween(_In_ PRAT* px, _In_ PRAT range, int32_t precision);
extern void trimit(_Inout_ PRAT* px, int32_t precision);
extern void _dumprawrat(_In_ const wchar_t* varname, _In_ PRAT rat, std::wostream& out);
extern void _dumprawnum(_In_ const wchar_t* varname, _In_ PNUMBER num, std::wostream& out);

View file

@ -19,36 +19,47 @@
//----------------------------------------------------------------------------
#include <string>
#include <cstring> // for memmove
#include <cstring> // for memmove
#include <iostream> // for wostream
#include "ratpak.h"
using namespace std;
void _readconstants( void );
void _readconstants(void);
#if defined( GEN_CONST )
#if defined(GEN_CONST)
static int cbitsofprecision = 0;
#define READRAWRAT(v)
#define READRAWNUM(v)
#define DUMPRAWRAT(v) _dumprawrat(#v,v, wcout)
#define DUMPRAWNUM(v) fprintf( stderr, \
"// Autogenerated by _dumprawrat in support.cpp\n" ); \
fprintf( stderr, "inline const NUMBER init_" #v "= {\n" ); \
_dumprawnum(v, wcout); \
fprintf( stderr, "};\n" )
#define DUMPRAWRAT(v) _dumprawrat(#v, v, wcout)
#define DUMPRAWNUM(v) \
fprintf(stderr, "// Autogenerated by _dumprawrat in support.cpp\n"); \
fprintf(stderr, "inline const NUMBER init_" #v "= {\n"); \
_dumprawnum(v, wcout); \
fprintf(stderr, "};\n")
#else
#define DUMPRAWRAT(v)
#define DUMPRAWNUM(v)
#define READRAWRAT(v) createrat(v); DUPNUM((v)->pp,(&(init_p_##v))); \
DUPNUM((v)->pq,(&(init_q_##v)));
#define READRAWNUM(v) DUPNUM(v,(&(init_##v)))
#define READRAWRAT(v) \
createrat(v); \
DUPNUM((v)->pp, (&(init_p_##v))); \
DUPNUM((v)->pq, (&(init_q_##v)));
#define READRAWNUM(v) DUPNUM(v, (&(init_##v)))
#define INIT_AND_DUMP_RAW_NUM_IF_NULL(r, v) if (r == nullptr) { r = i32tonum(v, BASEX); DUMPRAWNUM(v); }
#define INIT_AND_DUMP_RAW_RAT_IF_NULL(r, v) if (r == nullptr) { r = i32torat(v); DUMPRAWRAT(v); }
#define INIT_AND_DUMP_RAW_NUM_IF_NULL(r, v) \
if (r == nullptr) \
{ \
r = i32tonum(v, BASEX); \
DUMPRAWNUM(v); \
}
#define INIT_AND_DUMP_RAW_RAT_IF_NULL(r, v) \
if (r == nullptr) \
{ \
r = i32torat(v); \
DUMPRAWRAT(v); \
}
static constexpr int RATIO_FOR_DECIMAL = 9;
static constexpr int DECIMAL = 10;
@ -60,51 +71,51 @@ static int cbitsofprecision = RATIO_FOR_DECIMAL * DECIMAL * CALC_DECIMAL_DIGITS_
#endif
bool g_ftrueinfinite = false; // Set to true if you don't want
// chopping internally
// precision used internally
bool g_ftrueinfinite = false; // Set to true if you don't want
// chopping internally
// precision used internally
PNUMBER num_one= nullptr;
PNUMBER num_two= nullptr;
PNUMBER num_five= nullptr;
PNUMBER num_six= nullptr;
PNUMBER num_ten= nullptr;
PNUMBER num_one = nullptr;
PNUMBER num_two = nullptr;
PNUMBER num_five = nullptr;
PNUMBER num_six = nullptr;
PNUMBER num_ten = nullptr;
PRAT ln_ten= nullptr;
PRAT ln_two= nullptr;
PRAT rat_zero= nullptr;
PRAT rat_one= nullptr;
PRAT rat_neg_one= nullptr;
PRAT rat_two= nullptr;
PRAT rat_six= nullptr;
PRAT rat_half= nullptr;
PRAT rat_ten= nullptr;
PRAT pt_eight_five= nullptr;
PRAT pi= nullptr;
PRAT pi_over_two= nullptr;
PRAT two_pi= nullptr;
PRAT one_pt_five_pi= nullptr;
PRAT e_to_one_half= nullptr;
PRAT rat_exp= nullptr;
PRAT rad_to_deg= nullptr;
PRAT rad_to_grad= nullptr;
PRAT rat_qword= nullptr;
PRAT rat_dword= nullptr; // unsigned max ui32
PRAT rat_word= nullptr;
PRAT rat_byte= nullptr;
PRAT rat_360= nullptr;
PRAT rat_400= nullptr;
PRAT rat_180= nullptr;
PRAT rat_200= nullptr;
PRAT rat_nRadix= nullptr;
PRAT rat_smallest= nullptr;
PRAT rat_negsmallest= nullptr;
PRAT rat_max_exp= nullptr;
PRAT rat_min_exp= nullptr;
PRAT ln_ten = nullptr;
PRAT ln_two = nullptr;
PRAT rat_zero = nullptr;
PRAT rat_one = nullptr;
PRAT rat_neg_one = nullptr;
PRAT rat_two = nullptr;
PRAT rat_six = nullptr;
PRAT rat_half = nullptr;
PRAT rat_ten = nullptr;
PRAT pt_eight_five = nullptr;
PRAT pi = nullptr;
PRAT pi_over_two = nullptr;
PRAT two_pi = nullptr;
PRAT one_pt_five_pi = nullptr;
PRAT e_to_one_half = nullptr;
PRAT rat_exp = nullptr;
PRAT rad_to_deg = nullptr;
PRAT rad_to_grad = nullptr;
PRAT rat_qword = nullptr;
PRAT rat_dword = nullptr; // unsigned max ui32
PRAT rat_word = nullptr;
PRAT rat_byte = nullptr;
PRAT rat_360 = nullptr;
PRAT rat_400 = nullptr;
PRAT rat_180 = nullptr;
PRAT rat_200 = nullptr;
PRAT rat_nRadix = nullptr;
PRAT rat_smallest = nullptr;
PRAT rat_negsmallest = nullptr;
PRAT rat_max_exp = nullptr;
PRAT rat_min_exp = nullptr;
PRAT rat_max_fact = nullptr;
PRAT rat_min_fact = nullptr;
PRAT rat_min_i32= nullptr; // min signed i32
PRAT rat_max_i32= nullptr; // max signed i32
PRAT rat_min_i32 = nullptr; // min signed i32
PRAT rat_max_i32 = nullptr; // max signed i32
//----------------------------------------------------------------------------
//
@ -127,14 +138,14 @@ void ChangeConstants(uint32_t radix, int32_t precision)
uint64_t limit = static_cast<uint64_t>(BASEX) / static_cast<uint64_t>(radix);
g_ratio = 0;
for (uint32_t digit = 1; digit < limit; digit *= radix )
for (uint32_t digit = 1; digit < limit; digit *= radix)
{
g_ratio++;
}
g_ratio += !g_ratio;
destroyrat(rat_nRadix);
rat_nRadix=i32torat( radix );
rat_nRadix = i32torat(radix);
// Check to see what we have to recalculate and what we don't
if (cbitsofprecision < (g_ratio * static_cast<int32_t>(radix) * precision))
@ -253,7 +264,6 @@ void ChangeConstants(uint32_t radix, int32_t precision)
lograt(&ln_two, extraPrecision);
DUMPRAWRAT(ln_two);
destroyrat(rad_to_deg);
rad_to_deg = i32torat(180L);
divrat(&rad_to_deg, pi, extraPrecision);
@ -273,7 +283,6 @@ void ChangeConstants(uint32_t radix, int32_t precision)
DUPRAT(rat_negsmallest, rat_smallest);
rat_negsmallest->pp->sign = -1;
}
}
//----------------------------------------------------------------------------
@ -287,21 +296,21 @@ void ChangeConstants(uint32_t radix, int32_t precision)
//
//----------------------------------------------------------------------------
void intrat( PRAT *px, uint32_t radix, int32_t precision)
void intrat(PRAT* px, uint32_t radix, int32_t precision)
{
// Only do the intrat operation if number is nonzero.
// and only if the bottom part is not one.
if ( !zernum( (*px)->pp ) && !equnum( (*px)->pq, num_one ) )
if (!zernum((*px)->pp) && !equnum((*px)->pq, num_one))
{
flatrat(*px, radix, precision);
// Subtract the fractional part of the rational
PRAT pret = nullptr;
DUPRAT(pret,*px);
remrat( &pret, rat_one );
DUPRAT(pret, *px);
remrat(&pret, rat_one);
subrat( px, pret, precision);
destroyrat( pret );
subrat(px, pret, precision);
destroyrat(pret);
// Simplify the value if possible to resolve rounding errors
flatrat(*px, radix, precision);
@ -319,16 +328,16 @@ void intrat( PRAT *px, uint32_t radix, int32_t precision)
//
//---------------------------------------------------------------------------
bool rat_equ( PRAT a, PRAT b, int32_t precision)
bool rat_equ(PRAT a, PRAT b, int32_t precision)
{
PRAT rattmp= nullptr;
DUPRAT(rattmp,a);
PRAT rattmp = nullptr;
DUPRAT(rattmp, a);
rattmp->pp->sign *= -1;
addrat( &rattmp, b, precision);
bool bret = zernum( rattmp->pp );
destroyrat( rattmp );
return( bret );
addrat(&rattmp, b, precision);
bool bret = zernum(rattmp->pp);
destroyrat(rattmp);
return (bret);
}
//---------------------------------------------------------------------------
@ -342,20 +351,19 @@ bool rat_equ( PRAT a, PRAT b, int32_t precision)
//
//---------------------------------------------------------------------------
bool rat_ge( PRAT a, PRAT b, int32_t precision)
bool rat_ge(PRAT a, PRAT b, int32_t precision)
{
PRAT rattmp= nullptr;
DUPRAT(rattmp,a);
PRAT rattmp = nullptr;
DUPRAT(rattmp, a);
b->pp->sign *= -1;
addrat( &rattmp, b, precision);
addrat(&rattmp, b, precision);
b->pp->sign *= -1;
bool bret = ( zernum( rattmp->pp ) || SIGN(rattmp) == 1 );
destroyrat( rattmp );
return( bret );
bool bret = (zernum(rattmp->pp) || SIGN(rattmp) == 1);
destroyrat(rattmp);
return (bret);
}
//---------------------------------------------------------------------------
//
// FUNCTION: rat_gt
@ -367,17 +375,17 @@ bool rat_ge( PRAT a, PRAT b, int32_t precision)
//
//---------------------------------------------------------------------------
bool rat_gt( PRAT a, PRAT b, int32_t precision)
bool rat_gt(PRAT a, PRAT b, int32_t precision)
{
PRAT rattmp= nullptr;
DUPRAT(rattmp,a);
PRAT rattmp = nullptr;
DUPRAT(rattmp, a);
b->pp->sign *= -1;
addrat( &rattmp, b, precision);
addrat(&rattmp, b, precision);
b->pp->sign *= -1;
bool bret = ( !zernum( rattmp->pp ) && SIGN(rattmp) == 1 );
destroyrat( rattmp );
return( bret );
bool bret = (!zernum(rattmp->pp) && SIGN(rattmp) == 1);
destroyrat(rattmp);
return (bret);
}
//---------------------------------------------------------------------------
@ -391,21 +399,19 @@ bool rat_gt( PRAT a, PRAT b, int32_t precision)
//
//---------------------------------------------------------------------------
bool rat_le( PRAT a, PRAT b, int32_t precision)
bool rat_le(PRAT a, PRAT b, int32_t precision)
{
PRAT rattmp= nullptr;
DUPRAT(rattmp,a);
PRAT rattmp = nullptr;
DUPRAT(rattmp, a);
b->pp->sign *= -1;
addrat( &rattmp, b, precision);
addrat(&rattmp, b, precision);
b->pp->sign *= -1;
bool bret = ( zernum( rattmp->pp ) || SIGN(rattmp) == -1 );
destroyrat( rattmp );
return( bret );
bool bret = (zernum(rattmp->pp) || SIGN(rattmp) == -1);
destroyrat(rattmp);
return (bret);
}
//---------------------------------------------------------------------------
//
// FUNCTION: rat_lt
@ -417,20 +423,19 @@ bool rat_le( PRAT a, PRAT b, int32_t precision)
//
//---------------------------------------------------------------------------
bool rat_lt( PRAT a, PRAT b, int32_t precision)
bool rat_lt(PRAT a, PRAT b, int32_t precision)
{
PRAT rattmp= nullptr;
DUPRAT(rattmp,a);
PRAT rattmp = nullptr;
DUPRAT(rattmp, a);
b->pp->sign *= -1;
addrat( &rattmp, b, precision);
addrat(&rattmp, b, precision);
b->pp->sign *= -1;
bool bret = ( !zernum( rattmp->pp ) && SIGN(rattmp) == -1 );
destroyrat( rattmp );
return( bret );
bool bret = (!zernum(rattmp->pp) && SIGN(rattmp) == -1);
destroyrat(rattmp);
return (bret);
}
//---------------------------------------------------------------------------
//
// FUNCTION: rat_neq
@ -442,17 +447,16 @@ bool rat_lt( PRAT a, PRAT b, int32_t precision)
//
//---------------------------------------------------------------------------
bool rat_neq( PRAT a, PRAT b, int32_t precision)
bool rat_neq(PRAT a, PRAT b, int32_t precision)
{
PRAT rattmp= nullptr;
DUPRAT(rattmp,a);
PRAT rattmp = nullptr;
DUPRAT(rattmp, a);
rattmp->pp->sign *= -1;
addrat( &rattmp, b, precision);
bool bret = !( zernum( rattmp->pp ) );
destroyrat( rattmp );
return( bret );
addrat(&rattmp, b, precision);
bool bret = !(zernum(rattmp->pp));
destroyrat(rattmp);
return (bret);
}
//---------------------------------------------------------------------------
@ -466,27 +470,26 @@ bool rat_neq( PRAT a, PRAT b, int32_t precision)
//
//---------------------------------------------------------------------------
void scale( PRAT *px, PRAT scalefact, uint32_t radix, int32_t precision )
void scale(PRAT* px, PRAT scalefact, uint32_t radix, int32_t precision)
{
PRAT pret = nullptr;
DUPRAT(pret,*px);
DUPRAT(pret, *px);
// Logscale is a quick way to tell how much extra precision is needed for
// scaling by scalefact.
int32_t logscale = g_ratio * ( (pret->pp->cdigit+pret->pp->exp) -
(pret->pq->cdigit+pret->pq->exp) );
if ( logscale > 0 )
int32_t logscale = g_ratio * ((pret->pp->cdigit + pret->pp->exp) - (pret->pq->cdigit + pret->pq->exp));
if (logscale > 0)
{
precision += logscale;
}
divrat( &pret, scalefact, precision);
divrat(&pret, scalefact, precision);
intrat(&pret, radix, precision);
mulrat( &pret, scalefact, precision);
mulrat(&pret, scalefact, precision);
pret->pp->sign *= -1;
addrat( px, pret, precision);
addrat(px, pret, precision);
destroyrat( pret );
destroyrat(pret);
}
//---------------------------------------------------------------------------
@ -500,38 +503,37 @@ void scale( PRAT *px, PRAT scalefact, uint32_t radix, int32_t precision )
//
//---------------------------------------------------------------------------
void scale2pi( PRAT *px, uint32_t radix, int32_t precision )
void scale2pi(PRAT* px, uint32_t radix, int32_t precision)
{
PRAT pret = nullptr;
PRAT my_two_pi = nullptr;
DUPRAT(pret,*px);
DUPRAT(pret, *px);
// Logscale is a quick way to tell how much extra precision is needed for
// scaling by 2 pi.
int32_t logscale = g_ratio * ( (pret->pp->cdigit+pret->pp->exp) -
(pret->pq->cdigit+pret->pq->exp) );
if ( logscale > 0 )
int32_t logscale = g_ratio * ((pret->pp->cdigit + pret->pp->exp) - (pret->pq->cdigit + pret->pq->exp));
if (logscale > 0)
{
precision += logscale;
DUPRAT(my_two_pi,rat_half);
asinrat( &my_two_pi, radix, precision);
mulrat( &my_two_pi, rat_six, precision);
mulrat( &my_two_pi, rat_two, precision);
DUPRAT(my_two_pi, rat_half);
asinrat(&my_two_pi, radix, precision);
mulrat(&my_two_pi, rat_six, precision);
mulrat(&my_two_pi, rat_two, precision);
}
else
{
DUPRAT(my_two_pi,two_pi);
DUPRAT(my_two_pi, two_pi);
logscale = 0;
}
divrat( &pret, my_two_pi, precision);
divrat(&pret, my_two_pi, precision);
intrat(&pret, radix, precision);
mulrat( &pret, my_two_pi, precision);
mulrat(&pret, my_two_pi, precision);
pret->pp->sign *= -1;
addrat( px, pret, precision);
addrat(px, pret, precision);
destroyrat( my_two_pi );
destroyrat( pret );
destroyrat(my_two_pi);
destroyrat(pret);
}
//---------------------------------------------------------------------------
@ -544,22 +546,22 @@ void scale2pi( PRAT *px, uint32_t radix, int32_t precision )
//
//---------------------------------------------------------------------------
void inbetween( PRAT *px, PRAT range, int32_t precision)
void inbetween(PRAT* px, PRAT range, int32_t precision)
{
if ( rat_gt(*px,range, precision) )
{
DUPRAT(*px,range);
}
if (rat_gt(*px, range, precision))
{
DUPRAT(*px, range);
}
else
{
range->pp->sign *= -1;
if (rat_lt(*px, range, precision))
{
range->pp->sign *= -1;
if ( rat_lt(*px, range, precision) )
{
DUPRAT(*px,range);
}
range->pp->sign *= -1;
DUPRAT(*px, range);
}
range->pp->sign *= -1;
}
}
//---------------------------------------------------------------------------
@ -573,11 +575,11 @@ void inbetween( PRAT *px, PRAT range, int32_t precision)
//
//---------------------------------------------------------------------------
void _dumprawrat( const wchar_t *varname, PRAT rat, wostream& out)
void _dumprawrat(const wchar_t* varname, PRAT rat, wostream& out)
{
_dumprawnum(varname, rat->pp, out );
_dumprawnum(varname, rat->pq, out );
_dumprawnum(varname, rat->pp, out);
_dumprawnum(varname, rat->pq, out);
}
//---------------------------------------------------------------------------
@ -591,26 +593,26 @@ void _dumprawrat( const wchar_t *varname, PRAT rat, wostream& out)
//
//---------------------------------------------------------------------------
void _dumprawnum(const wchar_t *varname, PNUMBER num, wostream& out)
void _dumprawnum(const wchar_t* varname, PNUMBER num, wostream& out)
{
int i;
out << L"NUMBER " << varname << L" = {\n";
out << L"\t"<< num->sign << L",\n";
out << L"\t" << num->sign << L",\n";
out << L"\t" << num->cdigit << L",\n";
out << L"\t" << num->exp << L",\n";
out << L"\t{ ";
for ( i = 0; i < num->cdigit; i++ )
{
out << L" "<< num->mant[i] << L",";
}
for (i = 0; i < num->cdigit; i++)
{
out << L" " << num->mant[i] << L",";
}
out << L"}\n";
out << L"};\n";
}
void _readconstants( void )
void _readconstants(void)
{
READRAWNUM(num_one);
@ -674,43 +676,43 @@ void _readconstants( void )
//
//---------------------------------------------------------------------------
void trimit( PRAT *px, int32_t precision)
void trimit(PRAT* px, int32_t precision)
{
if ( !g_ftrueinfinite )
{
if (!g_ftrueinfinite)
{
int32_t trim;
PNUMBER pp=(*px)->pp;
PNUMBER pq=(*px)->pq;
trim = g_ratio * (min((pp->cdigit+pp->exp),(pq->cdigit+pq->exp))-1) - precision;
if ( trim > g_ratio )
{
PNUMBER pp = (*px)->pp;
PNUMBER pq = (*px)->pq;
trim = g_ratio * (min((pp->cdigit + pp->exp), (pq->cdigit + pq->exp)) - 1) - precision;
if (trim > g_ratio)
{
trim /= g_ratio;
if ( trim <= pp->exp )
{
if (trim <= pp->exp)
{
pp->exp -= trim;
}
else
{
memmove( pp->mant, &(pp->mant[trim-pp->exp]), sizeof(MANTTYPE)*(pp->cdigit-trim+pp->exp) );
pp->cdigit -= trim-pp->exp;
pp->exp = 0;
}
if ( trim <= pq->exp )
{
pq->exp -= trim;
}
else
{
memmove( pq->mant, &(pq->mant[trim-pq->exp]), sizeof(MANTTYPE)*(pq->cdigit-trim+pq->exp) );
pq->cdigit -= trim-pq->exp;
pq->exp = 0;
}
}
trim = min(pp->exp,pq->exp);
else
{
memmove(pp->mant, &(pp->mant[trim - pp->exp]), sizeof(MANTTYPE) * (pp->cdigit - trim + pp->exp));
pp->cdigit -= trim - pp->exp;
pp->exp = 0;
}
if (trim <= pq->exp)
{
pq->exp -= trim;
}
else
{
memmove(pq->mant, &(pq->mant[trim - pq->exp]), sizeof(MANTTYPE) * (pq->cdigit - trim + pq->exp));
pq->cdigit -= trim - pq->exp;
pq->exp = 0;
}
}
trim = min(pp->exp, pq->exp);
pp->exp -= trim;
pq->exp -= trim;
}
}
}

View file

@ -16,25 +16,22 @@
#include "ratpak.h"
void scalerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision )
void scalerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
{
switch ( angletype )
switch (angletype)
{
case ANGLE_RAD:
scale2pi( pa, radix, precision);
scale2pi(pa, radix, precision);
break;
case ANGLE_DEG:
scale( pa, rat_360, radix, precision);
scale(pa, rat_360, radix, precision);
break;
case ANGLE_GRAD:
scale( pa, rat_400, radix, precision);
scale(pa, rat_400, radix, precision);
break;
}
}
//-----------------------------------------------------------------------------
//
// FUNCTION: sinrat, _sinrat
@ -66,21 +63,21 @@ void scalerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t p
//
//-----------------------------------------------------------------------------
void _sinrat( PRAT *px, int32_t precision)
void _sinrat(PRAT* px, int32_t precision)
{
CREATETAYLOR();
DUPRAT(pret,*px);
DUPRAT(thisterm,*px);
DUPRAT(pret, *px);
DUPRAT(thisterm, *px);
DUPNUM(n2,num_one);
DUPNUM(n2, num_one);
xx->pp->sign *= -1;
do {
NEXTTERM(xx,INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
} while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
do
{
NEXTTERM(xx, INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
DESTROYTAYLOR();
@ -89,42 +86,42 @@ void _sinrat( PRAT *px, int32_t precision)
inbetween(px, rat_one, precision);
// Since *px might be epsilon near zero we must set it to zero.
if ( rat_le(*px, rat_smallest, precision) && rat_ge(*px, rat_negsmallest, precision) )
{
DUPRAT(*px,rat_zero);
}
if (rat_le(*px, rat_smallest, precision) && rat_ge(*px, rat_negsmallest, precision))
{
DUPRAT(*px, rat_zero);
}
}
void sinrat( PRAT *px, uint32_t radix, int32_t precision)
void sinrat(PRAT* px, uint32_t radix, int32_t precision)
{
scale2pi(px, radix, precision);
_sinrat(px, precision);
}
void sinanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
void sinanglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
{
scalerat( pa, angletype, radix, precision);
switch ( angletype )
{
scalerat(pa, angletype, radix, precision);
switch (angletype)
{
case ANGLE_DEG:
if ( rat_gt( *pa, rat_180, precision) )
{
if (rat_gt(*pa, rat_180, precision))
{
subrat(pa, rat_360, precision);
}
divrat( pa, rat_180, precision);
mulrat( pa, pi, precision);
}
divrat(pa, rat_180, precision);
mulrat(pa, pi, precision);
break;
case ANGLE_GRAD:
if ( rat_gt( *pa, rat_200, precision) )
{
subrat(pa,rat_400, precision);
}
divrat( pa, rat_200, precision);
mulrat( pa, pi, precision);
break;
if (rat_gt(*pa, rat_200, precision))
{
subrat(pa, rat_400, precision);
}
_sinrat( pa, precision);
divrat(pa, rat_200, precision);
mulrat(pa, pi, precision);
break;
}
_sinrat(pa, precision);
}
//-----------------------------------------------------------------------------
@ -158,8 +155,7 @@ void sinanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_
//
//-----------------------------------------------------------------------------
void _cosrat( PRAT *px, uint32_t radix, int32_t precision)
void _cosrat(PRAT* px, uint32_t radix, int32_t precision)
{
CREATETAYLOR();
@ -167,67 +163,68 @@ void _cosrat( PRAT *px, uint32_t radix, int32_t precision)
destroynum(pret->pp);
destroynum(pret->pq);
pret->pp=i32tonum( 1L, radix);
pret->pq=i32tonum( 1L, radix);
pret->pp = i32tonum(1L, radix);
pret->pq = i32tonum(1L, radix);
DUPRAT(thisterm,pret)
DUPRAT(thisterm, pret)
n2=i32tonum(0L, radix);
n2 = i32tonum(0L, radix);
xx->pp->sign *= -1;
do {
NEXTTERM(xx,INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
} while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
do
{
NEXTTERM(xx, INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
DESTROYTAYLOR();
// Since *px might be epsilon above 1 or below -1, due to TRIMIT we need
// this trick here.
inbetween(px, rat_one, precision);
// Since *px might be epsilon near zero we must set it to zero.
if ( rat_le(*px, rat_smallest, precision) && rat_ge(*px, rat_negsmallest, precision) )
{
DUPRAT(*px,rat_zero);
}
if (rat_le(*px, rat_smallest, precision) && rat_ge(*px, rat_negsmallest, precision))
{
DUPRAT(*px, rat_zero);
}
}
void cosrat( PRAT *px, uint32_t radix, int32_t precision)
void cosrat(PRAT* px, uint32_t radix, int32_t precision)
{
scale2pi(px, radix, precision);
_cosrat(px, radix, precision);
}
void cosanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
void cosanglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
{
scalerat( pa, angletype, radix, precision);
switch ( angletype )
{
scalerat(pa, angletype, radix, precision);
switch (angletype)
{
case ANGLE_DEG:
if ( rat_gt( *pa, rat_180, precision) )
{
PRAT ptmp= nullptr;
DUPRAT(ptmp,rat_360);
if (rat_gt(*pa, rat_180, precision))
{
PRAT ptmp = nullptr;
DUPRAT(ptmp, rat_360);
subrat(&ptmp, *pa, precision);
destroyrat(*pa);
*pa=ptmp;
}
divrat( pa, rat_180, precision);
mulrat( pa, pi, precision);
*pa = ptmp;
}
divrat(pa, rat_180, precision);
mulrat(pa, pi, precision);
break;
case ANGLE_GRAD:
if ( rat_gt( *pa, rat_200, precision) )
{
PRAT ptmp= nullptr;
DUPRAT(ptmp,rat_400);
if (rat_gt(*pa, rat_200, precision))
{
PRAT ptmp = nullptr;
DUPRAT(ptmp, rat_400);
subrat(&ptmp, *pa, precision);
destroyrat(*pa);
*pa=ptmp;
}
divrat( pa, rat_200, precision);
mulrat( pa, pi, precision);
break;
*pa = ptmp;
}
_cosrat( pa, radix, precision);
divrat(pa, rat_200, precision);
mulrat(pa, pi, precision);
break;
}
_cosrat(pa, radix, precision);
}
//-----------------------------------------------------------------------------
@ -242,55 +239,52 @@ void cosanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_
//
//-----------------------------------------------------------------------------
void _tanrat( PRAT *px, uint32_t radix, int32_t precision)
void _tanrat(PRAT* px, uint32_t radix, int32_t precision)
{
PRAT ptmp= nullptr;
PRAT ptmp = nullptr;
DUPRAT(ptmp,*px);
DUPRAT(ptmp, *px);
_sinrat(px, precision);
_cosrat(&ptmp, radix, precision);
if ( zerrat( ptmp ) )
{
if (zerrat(ptmp))
{
destroyrat(ptmp);
throw( CALC_E_DOMAIN );
}
throw(CALC_E_DOMAIN);
}
divrat(px, ptmp, precision);
destroyrat(ptmp);
}
void tanrat( PRAT *px, uint32_t radix, int32_t precision)
void tanrat(PRAT* px, uint32_t radix, int32_t precision)
{
scale2pi(px, radix, precision);
_tanrat(px, radix, precision);
}
void tananglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
void tananglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
{
scalerat( pa, angletype, radix, precision);
switch ( angletype )
{
scalerat(pa, angletype, radix, precision);
switch (angletype)
{
case ANGLE_DEG:
if ( rat_gt( *pa, rat_180, precision) )
{
if (rat_gt(*pa, rat_180, precision))
{
subrat(pa, rat_180, precision);
}
divrat( pa, rat_180, precision);
mulrat( pa, pi, precision);
}
divrat(pa, rat_180, precision);
mulrat(pa, pi, precision);
break;
case ANGLE_GRAD:
if ( rat_gt( *pa, rat_200, precision) )
{
if (rat_gt(*pa, rat_200, precision))
{
subrat(pa, rat_200, precision);
}
divrat( pa, rat_200, precision);
mulrat( pa, pi, precision);
break;
}
_tanrat( pa, radix, precision);
divrat(pa, rat_200, precision);
mulrat(pa, pi, precision);
break;
}
_tanrat(pa, radix, precision);
}

View file

@ -16,22 +16,19 @@
//-----------------------------------------------------------------------------
#include "ratpak.h"
bool IsValidForHypFunc(PRAT px, int32_t precision)
{
PRAT ptmp = nullptr;
bool bRet = true;
DUPRAT(ptmp,rat_min_exp);
DUPRAT(ptmp, rat_min_exp);
divrat(&ptmp, rat_ten, precision);
if ( rat_lt( px, ptmp, precision) )
if (rat_lt(px, ptmp, precision))
{
bRet = false;
}
destroyrat( ptmp );
destroyrat(ptmp);
return bRet;
}
//-----------------------------------------------------------------------------
@ -67,49 +64,49 @@ bool IsValidForHypFunc(PRAT px, int32_t precision)
//
//-----------------------------------------------------------------------------
void _sinhrat( PRAT *px, int32_t precision)
void _sinhrat(PRAT* px, int32_t precision)
{
if ( !IsValidForHypFunc(*px, precision))
{
if (!IsValidForHypFunc(*px, precision))
{
// Don't attempt exp of anything large or small
throw( CALC_E_DOMAIN );
}
throw(CALC_E_DOMAIN);
}
CREATETAYLOR();
DUPRAT(pret,*px);
DUPRAT(thisterm,pret);
DUPRAT(pret, *px);
DUPRAT(thisterm, pret);
DUPNUM(n2,num_one);
DUPNUM(n2, num_one);
do {
NEXTTERM(xx,INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
} while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
do
{
NEXTTERM(xx, INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
DESTROYTAYLOR();
}
void sinhrat( PRAT *px, uint32_t radix, int32_t precision)
void sinhrat(PRAT* px, uint32_t radix, int32_t precision)
{
PRAT tmpx= nullptr;
PRAT tmpx = nullptr;
if ( rat_ge( *px, rat_one, precision) )
{
DUPRAT(tmpx,*px);
if (rat_ge(*px, rat_one, precision))
{
DUPRAT(tmpx, *px);
exprat(px, radix, precision);
tmpx->pp->sign *= -1;
exprat(&tmpx, radix, precision);
subrat( px, tmpx, precision);
divrat( px, rat_two, precision);
destroyrat( tmpx );
}
subrat(px, tmpx, precision);
divrat(px, rat_two, precision);
destroyrat(tmpx);
}
else
{
_sinhrat( px, precision);
}
{
_sinhrat(px, precision);
}
}
//-----------------------------------------------------------------------------
@ -146,59 +143,59 @@ void sinhrat( PRAT *px, uint32_t radix, int32_t precision)
//
//-----------------------------------------------------------------------------
void _coshrat( PRAT *px, uint32_t radix, int32_t precision)
void _coshrat(PRAT* px, uint32_t radix, int32_t precision)
{
if ( !IsValidForHypFunc(*px, precision))
{
if (!IsValidForHypFunc(*px, precision))
{
// Don't attempt exp of anything large or small
throw( CALC_E_DOMAIN );
}
throw(CALC_E_DOMAIN);
}
CREATETAYLOR();
pret->pp=i32tonum( 1L, radix);
pret->pq=i32tonum( 1L, radix);
pret->pp = i32tonum(1L, radix);
pret->pq = i32tonum(1L, radix);
DUPRAT(thisterm,pret)
DUPRAT(thisterm, pret)
n2=i32tonum(0L, radix);
n2 = i32tonum(0L, radix);
do {
NEXTTERM(xx,INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
} while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
do
{
NEXTTERM(xx, INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
DESTROYTAYLOR();
}
void coshrat( PRAT *px, uint32_t radix, int32_t precision)
void coshrat(PRAT* px, uint32_t radix, int32_t precision)
{
PRAT tmpx= nullptr;
PRAT tmpx = nullptr;
(*px)->pp->sign = 1;
(*px)->pq->sign = 1;
if ( rat_ge( *px, rat_one, precision) )
{
DUPRAT(tmpx,*px);
if (rat_ge(*px, rat_one, precision))
{
DUPRAT(tmpx, *px);
exprat(px, radix, precision);
tmpx->pp->sign *= -1;
exprat(&tmpx, radix, precision);
addrat( px, tmpx, precision);
divrat( px, rat_two, precision);
destroyrat( tmpx );
}
addrat(px, tmpx, precision);
divrat(px, rat_two, precision);
destroyrat(tmpx);
}
else
{
_coshrat( px, radix, precision);
}
{
_coshrat(px, radix, precision);
}
// Since *px might be epsilon below 1 due to TRIMIT
// we need this trick here.
if ( rat_lt(*px, rat_one, precision) )
{
DUPRAT(*px,rat_one);
}
if (rat_lt(*px, rat_one, precision))
{
DUPRAT(*px, rat_one);
}
}
//-----------------------------------------------------------------------------
@ -214,17 +211,16 @@ void coshrat( PRAT *px, uint32_t radix, int32_t precision)
//
//-----------------------------------------------------------------------------
void tanhrat( PRAT *px, uint32_t radix, int32_t precision)
void tanhrat(PRAT* px, uint32_t radix, int32_t precision)
{
PRAT ptmp= nullptr;
PRAT ptmp = nullptr;
DUPRAT(ptmp,*px);
DUPRAT(ptmp, *px);
sinhrat(px, radix, precision);
coshrat(&ptmp, radix, precision);
mulnumx(&((*px)->pp),ptmp->pq);
mulnumx(&((*px)->pq),ptmp->pp);
mulnumx(&((*px)->pp), ptmp->pq);
mulnumx(&((*px)->pq), ptmp->pp);
destroyrat(ptmp);
}

View file

@ -34,8 +34,7 @@ unordered_map<wstring, wchar_t> unquoteConversions;
/// Constructor, sets up all the variables and requires a configLoader
/// </summary>
/// <param name="dataLoader">An instance of the IConverterDataLoader interface which we use to read in category/unit names and conversion data</param>
UnitConverter::UnitConverter(_In_ const shared_ptr<IConverterDataLoader>& dataLoader) :
UnitConverter::UnitConverter(dataLoader, nullptr)
UnitConverter::UnitConverter(_In_ const shared_ptr<IConverterDataLoader>& dataLoader) : UnitConverter::UnitConverter(dataLoader, nullptr)
{
}
@ -192,14 +191,14 @@ void UnitConverter::SwitchActive(const wstring& newValue)
}
}
wstring UnitConverter::CategoryToString(const Category& c, const wchar_t * delimiter)
wstring UnitConverter::CategoryToString(const Category& c, const wchar_t* delimiter)
{
wstringstream out(wstringstream::out);
out << Quote(std::to_wstring(c.id)) << delimiter << Quote(std::to_wstring(c.supportsNegative)) << delimiter << Quote(c.name) << delimiter;
return out.str();
}
vector<wstring> UnitConverter::StringToVector(const wstring& w, const wchar_t * delimiter, bool addRemainder)
vector<wstring> UnitConverter::StringToVector(const wstring& w, const wchar_t* delimiter, bool addRemainder)
{
size_t delimiterIndex = w.find(delimiter);
size_t startIndex = 0;
@ -229,10 +228,12 @@ Category UnitConverter::StringToCategory(const wstring& w)
return serializedCategory;
}
wstring UnitConverter::UnitToString(const Unit& u, const wchar_t * delimiter)
wstring UnitConverter::UnitToString(const Unit& u, const wchar_t* delimiter)
{
wstringstream out(wstringstream::out);
out << Quote(std::to_wstring(u.id)) << delimiter << Quote(u.name) << delimiter << Quote(u.abbreviation) << delimiter << std::to_wstring(u.isConversionSource) << delimiter << std::to_wstring(u.isConversionTarget) << delimiter << std::to_wstring(u.isWhimsical) << delimiter;
out << Quote(std::to_wstring(u.id)) << delimiter << Quote(u.name) << delimiter << Quote(u.abbreviation) << delimiter
<< std::to_wstring(u.isConversionSource) << delimiter << std::to_wstring(u.isConversionTarget) << delimiter << std::to_wstring(u.isWhimsical)
<< delimiter;
return out.str();
}
@ -262,7 +263,7 @@ ConversionData UnitConverter::StringToConversionData(const wstring& w)
return serializedConversionData;
}
wstring UnitConverter::ConversionDataToString(ConversionData d, const wchar_t * delimiter)
wstring UnitConverter::ConversionDataToString(ConversionData d, const wchar_t* delimiter)
{
wstringstream out(wstringstream::out);
out.precision(32);
@ -289,12 +290,13 @@ wstring UnitConverter::Serialize()
}
wstringstream out(wstringstream::out);
const wchar_t * delimiter = L";";
const wchar_t* delimiter = L";";
out << UnitToString(m_fromType, delimiter) << "|";
out << UnitToString(m_toType, delimiter) << "|";
out << CategoryToString(m_currentCategory, delimiter) << "|";
out << std::to_wstring(m_currentHasDecimal) << delimiter << std::to_wstring(m_returnHasDecimal) << delimiter << std::to_wstring(m_switchedActive) << delimiter;
out << std::to_wstring(m_currentHasDecimal) << delimiter << std::to_wstring(m_returnHasDecimal) << delimiter << std::to_wstring(m_switchedActive)
<< delimiter;
out << m_currentDisplay << delimiter << m_returnDisplay << delimiter << "|";
wstringstream categoryString(wstringstream::out);
wstringstream categoryToUnitString(wstringstream::out);
@ -311,7 +313,8 @@ wstring UnitConverter::Serialize()
{
categoryToUnitString << UnitToString(u, delimiter) << ",";
}
categoryToUnitString << "[" << "]";
categoryToUnitString << "["
<< "]";
}
for (const auto& cur : m_ratioMap)
@ -322,7 +325,8 @@ wstring UnitConverter::Serialize()
unitToUnitToDoubleString << UnitToString(curConversion.first, delimiter) << ":";
unitToUnitToDoubleString << ConversionDataToString(curConversion.second, delimiter) << ":,";
}
unitToUnitToDoubleString << "[" << "]";
unitToUnitToDoubleString << "["
<< "]";
}
out << categoryString.str() << "|";
@ -429,7 +433,6 @@ void UnitConverter::RestoreUserPreferences(const wstring& userPreferences)
m_toType = toType;
}
}
}
/// <summary>
@ -438,7 +441,7 @@ void UnitConverter::RestoreUserPreferences(const wstring& userPreferences)
wstring UnitConverter::SaveUserPreferences()
{
wstringstream out(wstringstream::out);
const wchar_t * delimiter = L";";
const wchar_t* delimiter = L";";
out << UnitToString(m_fromType, delimiter) << "|";
out << UnitToString(m_toType, delimiter) << "|";
@ -457,7 +460,7 @@ wstring UnitConverter::Quote(const wstring& s)
// Iterate over the delimiter characters we need to quote
wstring::const_iterator cursor = s.begin();
while(cursor != s.end())
while (cursor != s.end())
{
if (quoteConversions.find(*cursor) != quoteConversions.end())
{
@ -481,9 +484,9 @@ wstring UnitConverter::Unquote(const wstring& s)
wstringstream quotedSubString(wstringstream::out);
wstringstream unquotedString(wstringstream::out);
wstring::const_iterator cursor = s.begin();
while(cursor != s.end())
while (cursor != s.end())
{
if(*cursor == LEFTESCAPECHAR)
if (*cursor == LEFTESCAPECHAR)
{
quotedSubString.str(L"");
while (cursor != s.end() && *cursor != RIGHTESCAPECHAR)
@ -529,7 +532,8 @@ void UnitConverter::SendCommand(Command command)
clearFront = true;
}
bool clearBack = false;
if ((m_currentHasDecimal && m_currentDisplay.size() - 1 >= MAXIMUMDIGITSALLOWED) || (!m_currentHasDecimal && m_currentDisplay.size() >= MAXIMUMDIGITSALLOWED))
if ((m_currentHasDecimal && m_currentDisplay.size() - 1 >= MAXIMUMDIGITSALLOWED)
|| (!m_currentHasDecimal && m_currentDisplay.size() >= MAXIMUMDIGITSALLOWED))
{
clearBack = true;
}
@ -643,7 +647,6 @@ void UnitConverter::SendCommand(Command command)
break;
}
if (clearFront)
{
m_currentDisplay.erase(0, 1);
@ -684,26 +687,27 @@ void UnitConverter::SetViewModelCurrencyCallback(_In_ const shared_ptr<IViewMode
task<pair<bool, wstring>> UnitConverter::RefreshCurrencyRatios()
{
shared_ptr<ICurrencyConverterDataLoader> currencyDataLoader = GetCurrencyConverterDataLoader();
return create_task([this, currencyDataLoader]()
{
if (currencyDataLoader != nullptr)
{
return currencyDataLoader->TryLoadDataFromWebOverrideAsync();
}
else
{
return task_from_result(false);
}
}).then([this, currencyDataLoader](bool didLoad)
{
wstring timestamp = L"";
if (currencyDataLoader != nullptr)
{
timestamp = currencyDataLoader->GetCurrencyTimestamp();
}
return create_task([this, currencyDataLoader]() {
if (currencyDataLoader != nullptr)
{
return currencyDataLoader->TryLoadDataFromWebOverrideAsync();
}
else
{
return task_from_result(false);
}
})
.then(
[this, currencyDataLoader](bool didLoad) {
wstring timestamp = L"";
if (currencyDataLoader != nullptr)
{
timestamp = currencyDataLoader->GetCurrencyTimestamp();
}
return make_pair(didLoad, timestamp);
}, task_continuation_context::use_default());
return make_pair(didLoad, timestamp);
},
task_continuation_context::use_default());
}
shared_ptr<ICurrencyConverterDataLoader> UnitConverter::GetCurrencyConverterDataLoader()
@ -752,7 +756,7 @@ vector<tuple<wstring, Unit>> UnitConverter::CalculateSuggested()
newEntry.magnitude = log10(convertedValue);
newEntry.value = convertedValue;
newEntry.type = cur.first;
if(newEntry.type.isWhimsical == false)
if (newEntry.type.isWhimsical == false)
intermediateVector.push_back(newEntry);
else
intermediateWhimsicalVector.push_back(newEntry);
@ -760,9 +764,7 @@ vector<tuple<wstring, Unit>> UnitConverter::CalculateSuggested()
}
// Sort the resulting list by absolute magnitude, breaking ties by choosing the positive value
sort(intermediateVector.begin(), intermediateVector.end(), []
(SuggestedValueIntermediate first, SuggestedValueIntermediate second)
{
sort(intermediateVector.begin(), intermediateVector.end(), [](SuggestedValueIntermediate first, SuggestedValueIntermediate second) {
if (abs(first.magnitude) == abs(second.magnitude))
{
return first.magnitude > second.magnitude;
@ -783,7 +785,7 @@ vector<tuple<wstring, Unit>> UnitConverter::CalculateSuggested()
}
else if (abs(entry.value) < 1000)
{
roundedString = RoundSignificant(entry.value, 1);
roundedString = RoundSignificant(entry.value, 1);
}
else
{
@ -798,9 +800,7 @@ vector<tuple<wstring, Unit>> UnitConverter::CalculateSuggested()
// The Whimsicals are determined differently
// Sort the resulting list by absolute magnitude, breaking ties by choosing the positive value
sort(intermediateWhimsicalVector.begin(), intermediateWhimsicalVector.end(), []
(SuggestedValueIntermediate first, SuggestedValueIntermediate second)
{
sort(intermediateWhimsicalVector.begin(), intermediateWhimsicalVector.end(), [](SuggestedValueIntermediate first, SuggestedValueIntermediate second) {
if (abs(first.magnitude) == abs(second.magnitude))
{
return first.magnitude > second.magnitude;
@ -922,7 +922,6 @@ shared_ptr<IConverterDataLoader> UnitConverter::GetDataLoaderForCategory(const C
/// </summary>
void UnitConverter::InitializeSelectedUnits()
{
if (m_categoryToUnits.empty())
{
return;
@ -1057,7 +1056,7 @@ void UnitConverter::TrimString(wstring& returnString)
}
wstring::iterator iter;
for (iter = returnString.end() - 1; ;iter--)
for (iter = returnString.end() - 1;; iter--)
{
if (*iter != L'0')
{
@ -1065,9 +1064,9 @@ void UnitConverter::TrimString(wstring& returnString)
break;
}
}
if (*(returnString.end()-1) == L'.')
if (*(returnString.end() - 1) == L'.')
{
returnString.erase(returnString.end()-1, returnString.end());
returnString.erase(returnString.end() - 1, returnString.end());
}
}

View file

@ -6,7 +6,7 @@
#include <vector>
#include <unordered_map>
#include <ppltasks.h>
#include <sal.h> // for SAL
#include <sal.h> // for SAL
#include <memory> // for std::shared_ptr
namespace UnitConversionManager
@ -15,13 +15,22 @@ namespace UnitConversionManager
struct Unit
{
Unit(){}
Unit()
{
}
Unit(int id, std::wstring name, std::wstring abbreviation, bool isConversionSource, bool isConversionTarget, bool isWhimsical)
: id(id), name(name), accessibleName(name), abbreviation(abbreviation), isConversionSource(isConversionSource), isConversionTarget(isConversionTarget), isWhimsical(isWhimsical)
: id(id)
, name(name)
, accessibleName(name)
, abbreviation(abbreviation)
, isConversionSource(isConversionSource)
, isConversionTarget(isConversionTarget)
, isWhimsical(isWhimsical)
{
}
Unit(int id, std::wstring currencyName, std::wstring countryName, std::wstring abbreviation, bool isRtlLanguage, bool isConversionSource, bool isConversionTarget)
Unit(int id, std::wstring currencyName, std::wstring countryName, std::wstring abbreviation, bool isRtlLanguage, bool isConversionSource,
bool isConversionTarget)
: id(id), abbreviation(abbreviation), isConversionSource(isConversionSource), isConversionTarget(isConversionTarget), isWhimsical(false)
{
std::wstring nameValue1 = isRtlLanguage ? currencyName : countryName;
@ -31,7 +40,9 @@ namespace UnitConversionManager
accessibleName = nameValue1 + L" " + nameValue2;
}
virtual ~Unit() {}
virtual ~Unit()
{
}
int id;
std::wstring name;
@ -41,12 +52,12 @@ namespace UnitConversionManager
bool isConversionTarget;
bool isWhimsical;
bool operator!= (const Unit& that) const
bool operator!=(const Unit& that) const
{
return that.id != id;
}
bool operator== (const Unit& that) const
bool operator==(const Unit& that) const
{
return that.id == id;
}
@ -61,7 +72,9 @@ namespace UnitConversionManager
struct Category
{
Category(){}
Category()
{
}
Category(int id, std::wstring name, bool supportsNegative) : id(id), name(name), supportsNegative(supportsNegative)
{
@ -71,12 +84,12 @@ namespace UnitConversionManager
std::wstring name;
bool supportsNegative;
bool operator!= (const Category& that) const
bool operator!=(const Category& that) const
{
return that.id != id;
}
bool operator== (const Category& that) const
bool operator==(const Category& that) const
{
return that.id == id;
}
@ -85,7 +98,8 @@ namespace UnitConversionManager
class UnitHash
{
public:
size_t operator() (const Unit & x) const {
size_t operator()(const Unit& x) const
{
return x.id;
}
};
@ -93,7 +107,8 @@ namespace UnitConversionManager
class CategoryHash
{
public:
size_t operator() (const Category & x) const {
size_t operator()(const Category& x) const
{
return x.id;
}
};
@ -107,12 +122,16 @@ namespace UnitConversionManager
struct ConversionData
{
ConversionData(){}
ConversionData()
{
}
ConversionData(double ratio, double offset, bool offsetFirst) : ratio(ratio), offset(offset), offsetFirst(offsetFirst)
{
}
virtual ~ConversionData() {}
virtual ~ConversionData()
{
}
double ratio;
double offset;
@ -136,13 +155,17 @@ namespace UnitConversionManager
};
typedef std::tuple<std::vector<UnitConversionManager::Unit>, UnitConversionManager::Unit, UnitConversionManager::Unit> CategorySelectionInitializer;
typedef std::unordered_map<UnitConversionManager::Unit, std::unordered_map<UnitConversionManager::Unit, UnitConversionManager::ConversionData, UnitConversionManager::UnitHash>, UnitConversionManager::UnitHash> UnitToUnitToConversionDataMap;
typedef std::unordered_map<UnitConversionManager::Category, std::vector<UnitConversionManager::Unit>, UnitConversionManager::CategoryHash> CategoryToUnitVectorMap;
typedef std::unordered_map<UnitConversionManager::Unit,
std::unordered_map<UnitConversionManager::Unit, UnitConversionManager::ConversionData, UnitConversionManager::UnitHash>,
UnitConversionManager::UnitHash>
UnitToUnitToConversionDataMap;
typedef std::unordered_map<UnitConversionManager::Category, std::vector<UnitConversionManager::Unit>, UnitConversionManager::CategoryHash>
CategoryToUnitVectorMap;
class IViewModelCurrencyCallback
{
public:
virtual ~IViewModelCurrencyCallback() { };
virtual ~IViewModelCurrencyCallback(){};
virtual void CurrencyDataLoadFinished(bool didLoad) = 0;
virtual void CurrencySymbolsCallback(_In_ const std::wstring& fromSymbol, _In_ const std::wstring& toSymbol) = 0;
virtual void CurrencyRatiosCallback(_In_ const std::wstring& ratioEquality, _In_ const std::wstring& accRatioEquality) = 0;
@ -153,8 +176,8 @@ namespace UnitConversionManager
class IConverterDataLoader
{
public:
virtual ~IConverterDataLoader() { };
virtual void LoadData() = 0; // prepare data if necessary before calling other functions
virtual ~IConverterDataLoader(){};
virtual void LoadData() = 0; // prepare data if necessary before calling other functions
virtual std::vector<Category> LoadOrderedCategories() = 0;
virtual std::vector<Unit> LoadOrderedUnits(const Category& c) = 0;
virtual std::unordered_map<Unit, ConversionData, UnitHash> LoadOrderedRatios(const Unit& u) = 0;
@ -165,8 +188,10 @@ namespace UnitConversionManager
{
public:
virtual void SetViewModelCallback(const std::shared_ptr<UnitConversionManager::IViewModelCurrencyCallback>& callback) = 0;
virtual std::pair<std::wstring, std::wstring> GetCurrencySymbols(_In_ const UnitConversionManager::Unit& unit1, _In_ const UnitConversionManager::Unit& unit2) = 0;
virtual std::pair<std::wstring, std::wstring> GetCurrencyRatioEquality(_In_ const UnitConversionManager::Unit& unit1, _In_ const UnitConversionManager::Unit& unit2) = 0;
virtual std::pair<std::wstring, std::wstring> GetCurrencySymbols(_In_ const UnitConversionManager::Unit& unit1,
_In_ const UnitConversionManager::Unit& unit2) = 0;
virtual std::pair<std::wstring, std::wstring> GetCurrencyRatioEquality(_In_ const UnitConversionManager::Unit& unit1,
_In_ const UnitConversionManager::Unit& unit2) = 0;
virtual std::wstring GetCurrencyTimestamp() = 0;
virtual concurrency::task<bool> TryLoadDataFromCacheAsync() = 0;
@ -177,7 +202,7 @@ namespace UnitConversionManager
class IUnitConverterVMCallback
{
public:
virtual ~IUnitConverterVMCallback() { };
virtual ~IUnitConverterVMCallback(){};
virtual void DisplayCallback(const std::wstring& from, const std::wstring& to) = 0;
virtual void SuggestedValueCallback(const std::vector<std::tuple<std::wstring, Unit>>& suggestedValues) = 0;
virtual void MaxDigitsReached() = 0;
@ -186,8 +211,10 @@ namespace UnitConversionManager
class IUnitConverter
{
public:
virtual ~IUnitConverter() { }
virtual void Initialize() = 0; // Use to initialize first time, use deserialize instead to rehydrate
virtual ~IUnitConverter()
{
}
virtual void Initialize() = 0; // Use to initialize first time, use deserialize instead to rehydrate
virtual std::vector<Category> GetCategories() = 0;
virtual CategorySelectionInitializer SetCurrentCategory(const Category& input) = 0;
virtual Category GetCurrentCategory() = 0;
@ -230,7 +257,7 @@ namespace UnitConversionManager
void ResetCategoriesAndRatios() override;
// IUnitConverter
static std::vector<std::wstring> StringToVector(const std::wstring& w, const wchar_t * delimiter, bool addRemainder = false);
static std::vector<std::wstring> StringToVector(const std::wstring& w, const wchar_t* delimiter, bool addRemainder = false);
static std::wstring Quote(const std::wstring& s);
static std::wstring Unquote(const std::wstring& s);
@ -243,11 +270,11 @@ namespace UnitConversionManager
void InitializeSelectedUnits();
std::wstring RoundSignificant(double num, int numSignificant);
Category StringToCategory(const std::wstring& w);
std::wstring CategoryToString(const Category& c, const wchar_t * delimiter);
std::wstring UnitToString(const Unit& u, const wchar_t * delimiter);
std::wstring CategoryToString(const Category& c, const wchar_t* delimiter);
std::wstring UnitToString(const Unit& u, const wchar_t* delimiter);
Unit StringToUnit(const std::wstring& w);
ConversionData StringToConversionData(const std::wstring& w);
std::wstring ConversionDataToString(ConversionData d, const wchar_t * delimiter);
std::wstring ConversionDataToString(ConversionData d, const wchar_t* delimiter);
void UpdateCurrencySymbols();
void UpdateViewModel();
bool AnyUnitIsEmpty();

View file

@ -38,13 +38,13 @@ namespace
StringReference ClearMemoryVisibilityPropertyName(L"ClearMemoryVisibility");
}
ApplicationViewModel::ApplicationViewModel() :
m_CalculatorViewModel(nullptr),
m_DateCalcViewModel(nullptr),
m_ConverterViewModel(nullptr),
m_PreviousMode(ViewMode::None),
m_mode(ViewMode::None),
m_categories(nullptr)
ApplicationViewModel::ApplicationViewModel()
: m_CalculatorViewModel(nullptr)
, m_DateCalcViewModel(nullptr)
, m_ConverterViewModel(nullptr)
, m_PreviousMode(ViewMode::None)
, m_mode(ViewMode::None)
, m_categories(nullptr)
{
SetMenuCategories();
}
@ -60,7 +60,7 @@ void ApplicationViewModel::Mode::set(ViewMode value)
}
}
void ApplicationViewModel::Categories::set(IObservableVector<NavCategoryGroup^>^ value)
void ApplicationViewModel::Categories::set(IObservableVector<NavCategoryGroup ^> ^ value)
{
if (m_categories != value)
{
@ -90,7 +90,7 @@ void ApplicationViewModel::Initialize(ViewMode mode)
throw;
}
}
catch (Exception^ e)
catch (Exception ^ e)
{
TraceLogger::GetInstance().LogPlatformException(__FUNCTIONW__, e);
if (!TryRecoverFromNavigationModeFailure())
@ -165,7 +165,7 @@ void ApplicationViewModel::OnModeChanged()
RaisePropertyChanged(ClearMemoryVisibilityPropertyName);
}
void ApplicationViewModel::OnCopyCommand(Object^ parameter)
void ApplicationViewModel::OnCopyCommand(Object ^ parameter)
{
if (NavCategory::IsConverterViewMode(m_mode))
{
@ -181,7 +181,7 @@ void ApplicationViewModel::OnCopyCommand(Object^ parameter)
}
}
void ApplicationViewModel::OnPasteCommand(Object^ parameter)
void ApplicationViewModel::OnPasteCommand(Object ^ parameter)
{
if (NavCategory::IsConverterViewMode(m_mode))
{

View file

@ -11,20 +11,19 @@ namespace CalculatorApp
{
namespace ViewModel
{
[Windows::UI::Xaml::Data::Bindable]
public ref class ApplicationViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
[Windows::UI::Xaml::Data::Bindable] public ref class ApplicationViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
{
public:
ApplicationViewModel();
void Initialize(CalculatorApp::Common::ViewMode mode); // Use for first init, use deserialize for rehydration
void Initialize(CalculatorApp::Common::ViewMode mode); // Use for first init, use deserialize for rehydration
OBSERVABLE_OBJECT();
OBSERVABLE_PROPERTY_RW(StandardCalculatorViewModel^, CalculatorViewModel);
OBSERVABLE_PROPERTY_RW(DateCalculatorViewModel^, DateCalcViewModel);
OBSERVABLE_PROPERTY_RW(UnitConverterViewModel^, ConverterViewModel);
OBSERVABLE_PROPERTY_RW(StandardCalculatorViewModel ^, CalculatorViewModel);
OBSERVABLE_PROPERTY_RW(DateCalculatorViewModel ^, DateCalcViewModel);
OBSERVABLE_PROPERTY_RW(UnitConverterViewModel ^, ConverterViewModel);
OBSERVABLE_PROPERTY_RW(CalculatorApp::Common::ViewMode, PreviousMode);
OBSERVABLE_NAMED_PROPERTY_RW(Platform::String^, CategoryName);
OBSERVABLE_NAMED_PROPERTY_RW(Platform::String ^, CategoryName);
COMMAND_FOR_METHOD(CopyCommand, ApplicationViewModel::OnCopyCommand);
COMMAND_FOR_METHOD(PasteCommand, ApplicationViewModel::OnPasteCommand);
@ -60,9 +59,8 @@ namespace CalculatorApp
{
Windows::UI::Xaml::Visibility get()
{
return CalculatorApp::Common::NavCategory::IsCalculatorViewMode(Mode)
? Windows::UI::Xaml::Visibility::Visible
: Windows::UI::Xaml::Visibility::Collapsed;
return CalculatorApp::Common::NavCategory::IsCalculatorViewMode(Mode) ? Windows::UI::Xaml::Visibility::Visible
: Windows::UI::Xaml::Visibility::Collapsed;
}
}
@ -71,13 +69,13 @@ namespace CalculatorApp
void OnModeChanged();
void OnCopyCommand(Platform::Object^ parameter);
void OnPasteCommand(Platform::Object^ parameter);
void OnCopyCommand(Platform::Object ^ parameter);
void OnPasteCommand(Platform::Object ^ parameter);
void SetMenuCategories();
CalculatorApp::Common::ViewMode m_mode;
Windows::Foundation::Collections::IObservableVector<CalculatorApp::Common::NavCategoryGroup^>^ m_categories;
Windows::Foundation::Collections::IObservableVector<CalculatorApp::Common::NavCategoryGroup ^> ^ m_categories;
};
}
}

View file

@ -3,107 +3,102 @@
#pragma once
namespace CalculatorApp { namespace Common
namespace CalculatorApp
{
ref class AlwaysSelectedCollectionView sealed:
public Windows::UI::Xaml::DependencyObject,
public Windows::UI::Xaml::Data::ICollectionView
namespace Common
{
internal:
AlwaysSelectedCollectionView(Windows::UI::Xaml::Interop::IBindableVector^ source):
m_currentPosition(-1)
ref class AlwaysSelectedCollectionView sealed : public Windows::UI::Xaml::DependencyObject, public Windows::UI::Xaml::Data::ICollectionView
{
m_source = source;
internal : AlwaysSelectedCollectionView(Windows::UI::Xaml::Interop::IBindableVector ^ source) : m_currentPosition(-1)
{
m_source = source;
Windows::UI::Xaml::Interop::IBindableObservableVector^ observable = dynamic_cast<Windows::UI::Xaml::Interop::IBindableObservableVector^>(source);
if (observable)
{
observable->VectorChanged +=
ref new Windows::UI::Xaml::Interop::BindableVectorChangedEventHandler(this, &AlwaysSelectedCollectionView::OnSourceBindableVectorChanged);
}
}
private:
// ICollectionView
// Not implemented methods
virtual WF::IAsyncOperation<Windows::UI::Xaml::Data::LoadMoreItemsResult>^ LoadMoreItemsAsync(unsigned int) = Windows::UI::Xaml::Data::ICollectionView::LoadMoreItemsAsync
{
throw ref new Platform::NotImplementedException();
}
virtual bool MoveCurrentToFirst() = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentToFirst
{
throw ref new Platform::NotImplementedException();
}
virtual bool MoveCurrentToLast() = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentToLast
{
throw ref new Platform::NotImplementedException();
}
virtual bool MoveCurrentToNext() = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentToNext
{
throw ref new Platform::NotImplementedException();
}
virtual bool MoveCurrentToPrevious() = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentToPrevious
{
throw ref new Platform::NotImplementedException();
}
property Windows::Foundation::Collections::IObservableVector<Platform::Object^>^ CollectionGroups
{
virtual Windows::Foundation::Collections::IObservableVector<Platform::Object^>^ get() = Windows::UI::Xaml::Data::ICollectionView::CollectionGroups::get
{
return ref new Platform::Collections::Vector<Platform::Object^>();
}
}
property bool HasMoreItems
{
virtual bool get() = Windows::UI::Xaml::Data::ICollectionView::HasMoreItems::get
{
return false;
}
}
// Implemented methods
virtual bool MoveCurrentTo(Platform::Object^ item) = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentTo
{
if (item)
{
unsigned int newCurrentPosition = 0;
bool result = m_source->IndexOf(item, &newCurrentPosition);
if (result)
Windows::UI::Xaml::Interop::IBindableObservableVector ^ observable =
dynamic_cast<Windows::UI::Xaml::Interop::IBindableObservableVector ^>(source);
if (observable)
{
m_currentPosition = newCurrentPosition;
m_currentChanged(this, nullptr);
return true;
observable->VectorChanged += ref new Windows::UI::Xaml::Interop::BindableVectorChangedEventHandler(
this, &AlwaysSelectedCollectionView::OnSourceBindableVectorChanged);
}
}
// The item is not in the collection
// We're going to schedule a call back later so we
// restore the selection to the way we wanted it to begin with
if (m_currentPosition >= 0 && m_currentPosition < static_cast<int>(m_source->Size))
private:
// ICollectionView
// Not implemented methods
virtual WF::IAsyncOperation<
Windows::UI::Xaml::Data::LoadMoreItemsResult> ^ LoadMoreItemsAsync(unsigned int) = Windows::UI::Xaml::Data::ICollectionView::LoadMoreItemsAsync
{
this->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal,
ref new Windows::UI::Core::DispatchedHandler(
[this]()
{
m_currentChanged(this, nullptr);
}));
throw ref new Platform::NotImplementedException();
}
return false;
}
virtual bool MoveCurrentToPosition(int index) = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentToPosition
{
if (index < 0 || index >= static_cast<int>(m_source->Size))
virtual bool MoveCurrentToFirst() = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentToFirst
{
throw ref new Platform::NotImplementedException();
}
virtual bool MoveCurrentToLast() = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentToLast
{
throw ref new Platform::NotImplementedException();
}
virtual bool MoveCurrentToNext() = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentToNext
{
throw ref new Platform::NotImplementedException();
}
virtual bool MoveCurrentToPrevious() = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentToPrevious
{
throw ref new Platform::NotImplementedException();
}
property Windows::Foundation::Collections::IObservableVector<Platform::Object ^> ^ CollectionGroups {
virtual Windows::Foundation::Collections::IObservableVector<Platform::Object
^> ^ get() = Windows::UI::Xaml::Data::ICollectionView::CollectionGroups::get
{
return ref new Platform::Collections::Vector<Platform::Object ^>();
}
} property bool HasMoreItems
{
virtual bool get() = Windows::UI::Xaml::Data::ICollectionView::HasMoreItems::get
{
return false;
}
}
// Implemented methods
virtual bool MoveCurrentTo(Platform::Object ^ item) = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentTo
{
if (item)
{
unsigned int newCurrentPosition = 0;
bool result = m_source->IndexOf(item, &newCurrentPosition);
if (result)
{
m_currentPosition = newCurrentPosition;
m_currentChanged(this, nullptr);
return true;
}
}
// The item is not in the collection
// We're going to schedule a call back later so we
// restore the selection to the way we wanted it to begin with
if (m_currentPosition >= 0 && m_currentPosition < static_cast<int>(m_source->Size))
{
this->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal,
ref new Windows::UI::Core::DispatchedHandler([this]() { m_currentChanged(this, nullptr); }));
}
return false;
}
m_currentPosition = index;
m_currentChanged(this, nullptr);
return true;
}
virtual bool MoveCurrentToPosition(int index) = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentToPosition
{
if (index < 0 || index >= static_cast<int>(m_source->Size))
{
return false;
}
property Platform::Object^ CurrentItem
m_currentPosition = index;
m_currentChanged(this, nullptr);
return true;
}
property Platform::Object^ CurrentItem
{
virtual Platform::Object^ get() = Windows::UI::Xaml::Data::ICollectionView::CurrentItem::get
{
@ -116,30 +111,30 @@ namespace CalculatorApp { namespace Common
}
property int CurrentPosition
{
virtual int get() = Windows::UI::Xaml::Data::ICollectionView::CurrentPosition::get
{
return m_currentPosition;
virtual int get() = Windows::UI::Xaml::Data::ICollectionView::CurrentPosition::get
{
return m_currentPosition;
}
}
}
property bool IsCurrentAfterLast
{
virtual bool get() = Windows::UI::Xaml::Data::ICollectionView::IsCurrentAfterLast::get
property bool IsCurrentAfterLast
{
return m_currentPosition >= static_cast<int>(m_source->Size);
virtual bool get() = Windows::UI::Xaml::Data::ICollectionView::IsCurrentAfterLast::get
{
return m_currentPosition >= static_cast<int>(m_source->Size);
}
}
}
property bool IsCurrentBeforeFirst
{
virtual bool get() = Windows::UI::Xaml::Data::ICollectionView::IsCurrentBeforeFirst::get
property bool IsCurrentBeforeFirst
{
return m_currentPosition < 0;
virtual bool get() = Windows::UI::Xaml::Data::ICollectionView::IsCurrentBeforeFirst::get
{
return m_currentPosition < 0;
}
}
}
event WF::EventHandler<Platform::Object^>^ CurrentChanged
event WF::EventHandler<Platform::Object^>^ CurrentChanged
{
virtual WF::EventRegistrationToken add(WF::EventHandler<Platform::Object^>^ handler) = Windows::UI::Xaml::Data::ICollectionView::CurrentChanged::add
{
@ -165,63 +160,67 @@ namespace CalculatorApp { namespace Common
// IVector<Object^>
// Not implemented methods
virtual void Append(Platform::Object^ /*item*/) = Windows::Foundation::Collections::IVector<Platform::Object^>::Append
{
throw ref new Platform::NotImplementedException();
}
virtual void Clear() = Windows::Foundation::Collections::IVector<Platform::Object^>::Clear
{
throw ref new Platform::NotImplementedException();
}
virtual unsigned int GetMany(unsigned int /*startIndex*/, Platform::WriteOnlyArray<Platform::Object^>^ /*items*/) = Windows::Foundation::Collections::IVector<Platform::Object^>::GetMany
{
throw ref new Platform::NotImplementedException();
}
virtual Windows::Foundation::Collections::IVectorView<Platform::Object^>^ GetView() = Windows::Foundation::Collections::IVector<Platform::Object^>::GetView
{
throw ref new Platform::NotImplementedException();
}
virtual void InsertAt(unsigned int /*index*/, Platform::Object^ /*item*/) = Windows::Foundation::Collections::IVector<Platform::Object^>::InsertAt
{
throw ref new Platform::NotImplementedException();
}
virtual void RemoveAt(unsigned int /*index*/) = Windows::Foundation::Collections::IVector<Platform::Object^>::RemoveAt
{
throw ref new Platform::NotImplementedException();
}
virtual void RemoveAtEnd() = Windows::Foundation::Collections::IVector<Platform::Object^>::RemoveAtEnd
{
throw ref new Platform::NotImplementedException();
}
virtual void ReplaceAll(const Platform::Array<Platform::Object^>^ /*items*/) = Windows::Foundation::Collections::IVector<Platform::Object^>::ReplaceAll
{
throw ref new Platform::NotImplementedException();
}
virtual void SetAt(unsigned int /*index*/, Platform::Object^ /*item*/) = Windows::Foundation::Collections::IVector<Platform::Object^>::SetAt
{
throw ref new Platform::NotImplementedException();
}
// Implemented methods
virtual Platform::Object^ GetAt(unsigned int index) = Windows::Foundation::Collections::IVector<Platform::Object^>::GetAt
{
return m_source->GetAt(index);
}
virtual bool IndexOf(Platform::Object^ item, unsigned int* index) = Windows::Foundation::Collections::IVector<Platform::Object^>::IndexOf
{
return m_source->IndexOf(item, index);
}
property unsigned int Size
{
virtual unsigned int get() = Windows::Foundation::Collections::IVector<Platform::Object^>::Size::get
{
return m_source->Size;
throw ref new Platform::NotImplementedException();
}
virtual void Clear() = Windows::Foundation::Collections::IVector<Platform::Object ^>::Clear
{
throw ref new Platform::NotImplementedException();
}
virtual unsigned int
GetMany(unsigned int /*startIndex*/,
Platform::WriteOnlyArray<Platform::Object ^> ^ /*items*/) = Windows::Foundation::Collections::IVector<Platform::Object ^>::GetMany
{
throw ref new Platform::NotImplementedException();
}
virtual Windows::Foundation::Collections::IVectorView<Platform::Object ^> ^ GetView() = Windows::Foundation::Collections::IVector<Platform::Object
^>::GetView
{
throw ref new Platform::NotImplementedException();
}
virtual void InsertAt(unsigned int /*index*/, Platform::Object ^ /*item*/) = Windows::Foundation::Collections::IVector<Platform::Object ^>::InsertAt
{
throw ref new Platform::NotImplementedException();
}
virtual void RemoveAt(unsigned int /*index*/) = Windows::Foundation::Collections::IVector<Platform::Object ^>::RemoveAt
{
throw ref new Platform::NotImplementedException();
}
virtual void RemoveAtEnd() = Windows::Foundation::Collections::IVector<Platform::Object ^>::RemoveAtEnd
{
throw ref new Platform::NotImplementedException();
}
virtual void
ReplaceAll(const Platform::Array<Platform::Object ^> ^ /*items*/) = Windows::Foundation::Collections::IVector<Platform::Object ^>::ReplaceAll
{
throw ref new Platform::NotImplementedException();
}
virtual void SetAt(unsigned int /*index*/, Platform::Object ^ /*item*/) = Windows::Foundation::Collections::IVector<Platform::Object ^>::SetAt
{
throw ref new Platform::NotImplementedException();
}
}
// IObservableVector<Object^>
event Windows::Foundation::Collections::VectorChangedEventHandler<Platform::Object^>^ VectorChanged
// Implemented methods
virtual Platform::Object ^ GetAt(unsigned int index) = Windows::Foundation::Collections::IVector<Platform::Object ^>::GetAt
{
return m_source->GetAt(index);
}
virtual bool IndexOf(Platform::Object ^ item, unsigned int* index) = Windows::Foundation::Collections::IVector<Platform::Object ^>::IndexOf
{
return m_source->IndexOf(item, index);
}
property unsigned int Size
{
virtual unsigned int get() = Windows::Foundation::Collections::IVector<Platform::Object ^>::Size::get
{
return m_source->Size;
}
}
// IObservableVector<Object^>
event Windows::Foundation::Collections::VectorChangedEventHandler<Platform::Object^>^ VectorChanged
{
virtual WF::EventRegistrationToken add(Windows::Foundation::Collections::VectorChangedEventHandler<Platform::Object^>^ handler) = Windows::Foundation::Collections::IObservableVector<Platform::Object^>::VectorChanged::add
{
@ -236,52 +235,51 @@ namespace CalculatorApp { namespace Common
// IIterable<Object^>
// Not implemented
virtual Windows::Foundation::Collections::IIterator<Platform::Object^>^ First() = Windows::Foundation::Collections::IIterable<Platform::Object^>::First
{
throw ref new Platform::NotImplementedException();
}
// Event handlers
void OnSourceBindableVectorChanged(Windows::UI::Xaml::Interop::IBindableObservableVector^ source, Platform::Object^ e)
{
Windows::Foundation::Collections::IVectorChangedEventArgs^ args = safe_cast<Windows::Foundation::Collections::IVectorChangedEventArgs^>(e);
m_vectorChanged(this, args);
}
Windows::UI::Xaml::Interop::IBindableVector^ m_source;
int m_currentPosition;
event WF::EventHandler<Platform::Object^>^ m_currentChanged;
event Windows::UI::Xaml::Data::CurrentChangingEventHandler^ m_currentChanging;
event Windows::Foundation::Collections::VectorChangedEventHandler<Platform::Object^>^ m_vectorChanged;
};
public ref class AlwaysSelectedCollectionViewConverter sealed: public Windows::UI::Xaml::Data::IValueConverter
{
public:
AlwaysSelectedCollectionViewConverter()
{ }
private:
virtual Platform::Object^ Convert(
Platform::Object^ value,
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
Platform::Object^ /*parameter*/,
Platform::String^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::Convert
{
auto result = dynamic_cast<Windows::UI::Xaml::Interop::IBindableVector^>(value);
if (result)
{
return ref new AlwaysSelectedCollectionView(result);
throw ref new Platform::NotImplementedException();
}
return Windows::UI::Xaml::DependencyProperty::UnsetValue; // Can't convert
}
virtual Platform::Object^ ConvertBack(
Platform::Object^ /*value*/,
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
Platform::Object^ /*parameter*/,
Platform::String^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::ConvertBack
// Event handlers
void OnSourceBindableVectorChanged(Windows::UI::Xaml::Interop::IBindableObservableVector ^ source, Platform::Object ^ e)
{
Windows::Foundation::Collections::IVectorChangedEventArgs ^ args = safe_cast<Windows::Foundation::Collections::IVectorChangedEventArgs ^>(e);
m_vectorChanged(this, args);
}
Windows::UI::Xaml::Interop::IBindableVector ^ m_source;
int m_currentPosition;
event WF::EventHandler<Platform::Object ^> ^ m_currentChanged;
event Windows::UI::Xaml::Data::CurrentChangingEventHandler ^ m_currentChanging;
event Windows::Foundation::Collections::VectorChangedEventHandler<Platform::Object ^> ^ m_vectorChanged;
};
public
ref class AlwaysSelectedCollectionViewConverter sealed : public Windows::UI::Xaml::Data::IValueConverter
{
return Windows::UI::Xaml::DependencyProperty::UnsetValue;
}
};
}}
public:
AlwaysSelectedCollectionViewConverter()
{
}
private:
virtual Platform::Object
^ Convert(Platform::Object ^ value, Windows::UI::Xaml::Interop::TypeName /*targetType*/, Platform::Object ^ /*parameter*/,
Platform::String ^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::Convert
{
auto result = dynamic_cast<Windows::UI::Xaml::Interop::IBindableVector ^>(value);
if (result)
{
return ref new AlwaysSelectedCollectionView(result);
}
return Windows::UI::Xaml::DependencyProperty::UnsetValue; // Can't convert
}
virtual Platform::Object
^ ConvertBack(Platform::Object ^ /*value*/, Windows::UI::Xaml::Interop::TypeName /*targetType*/, Platform::Object ^ /*parameter*/,
Platform::String ^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::ConvertBack
{
return Windows::UI::Xaml::DependencyProperty::UnsetValue;
}
};
}
}

View file

@ -14,18 +14,18 @@ AppResourceProvider::AppResourceProvider()
m_cEngineStringResLoader = ResourceLoader::GetForViewIndependentUse(L"CEngineStrings");
}
AppResourceProvider & AppResourceProvider::GetInstance()
AppResourceProvider& AppResourceProvider::GetInstance()
{
static AppResourceProvider s_instance;
return s_instance;
}
String^ AppResourceProvider::GetResourceString(_In_ String^ key)
String ^ AppResourceProvider::GetResourceString(_In_ String ^ key)
{
return m_stringResLoader->GetString(key);
}
String^ AppResourceProvider::GetCEngineString(_In_ String^ key)
String ^ AppResourceProvider::GetCEngineString(_In_ String ^ key)
{
return m_cEngineStringResLoader->GetString(key);
}

View file

@ -8,13 +8,13 @@ namespace CalculatorApp
class AppResourceProvider
{
public:
static AppResourceProvider & GetInstance();
Platform::String^ GetResourceString(_In_ Platform::String^ key);
Platform::String^ GetCEngineString(_In_ Platform::String^ key);
static AppResourceProvider& GetInstance();
Platform::String ^ GetResourceString(_In_ Platform::String ^ key);
Platform::String ^ GetCEngineString(_In_ Platform::String ^ key);
private:
AppResourceProvider();
Windows::ApplicationModel::Resources::ResourceLoader^ m_stringResLoader;
Windows::ApplicationModel::Resources::ResourceLoader^ m_cEngineStringResLoader;
Windows::ApplicationModel::Resources::ResourceLoader ^ m_stringResLoader;
Windows::ApplicationModel::Resources::ResourceLoader ^ m_cEngineStringResLoader;
};
}

View file

@ -11,16 +11,17 @@
namespace CalculatorApp::Common::Automation
{
public interface class INarratorAnnouncementHost
public
interface class INarratorAnnouncementHost
{
public:
// Is the host available on this OS.
bool IsHostAvailable();
// Make a new instance of a concrete host.
INarratorAnnouncementHost^ MakeHost();
INarratorAnnouncementHost ^ MakeHost();
// Make an announcement using the concrete host's preferred method.
void Announce(NarratorAnnouncement^ announcement);
void Announce(NarratorAnnouncement ^ announcement);
};
}

View file

@ -9,9 +9,9 @@ using namespace Windows::UI::Xaml::Automation;
using namespace Windows::UI::Xaml::Automation::Peers;
using namespace Windows::UI::Xaml::Controls;
LiveRegionHost::LiveRegionHost() :
m_host(nullptr)
{}
LiveRegionHost::LiveRegionHost() : m_host(nullptr)
{
}
bool LiveRegionHost::IsHostAvailable()
{
@ -19,12 +19,12 @@ bool LiveRegionHost::IsHostAvailable()
return true;
}
INarratorAnnouncementHost^ LiveRegionHost::MakeHost()
INarratorAnnouncementHost ^ LiveRegionHost::MakeHost()
{
return ref new LiveRegionHost();
}
void LiveRegionHost::Announce(NarratorAnnouncement^ announcement)
void LiveRegionHost::Announce(NarratorAnnouncement ^ announcement)
{
if (m_host == nullptr)
{
@ -33,7 +33,7 @@ void LiveRegionHost::Announce(NarratorAnnouncement^ announcement)
}
AutomationProperties::SetName(m_host, announcement->Announcement);
AutomationPeer^ peer = FrameworkElementAutomationPeer::FromElement(m_host);
AutomationPeer ^ peer = FrameworkElementAutomationPeer::FromElement(m_host);
if (peer != nullptr)
{
peer->RaiseAutomationEvent(AutomationEvents::LiveRegionChanged);

View file

@ -16,17 +16,18 @@ namespace CalculatorApp::Common::Automation
// When the app switches to min version RS3, this class can be removed
// and the app will switch to using the Notification API.
// TODO - MSFT 12735088
public ref class LiveRegionHost sealed : public INarratorAnnouncementHost
public
ref class LiveRegionHost sealed : public INarratorAnnouncementHost
{
public:
LiveRegionHost();
virtual bool IsHostAvailable();
virtual INarratorAnnouncementHost^ MakeHost();
virtual INarratorAnnouncementHost ^ MakeHost();
virtual void Announce(NarratorAnnouncement^ announcement);
virtual void Announce(NarratorAnnouncement ^ announcement);
private:
Windows::UI::Xaml::UIElement^ m_host;
Windows::UI::Xaml::UIElement ^ m_host;
};
}

View file

@ -25,24 +25,18 @@ namespace CalculatorApp::Common::Automation
}
}
NarratorAnnouncement::NarratorAnnouncement(
String^ announcement,
String^ activityId,
AutomationNotificationKind kind,
AutomationNotificationProcessing processing)
:
m_announcement(announcement),
m_activityId(activityId),
m_kind(kind),
m_processing(processing)
{}
NarratorAnnouncement::NarratorAnnouncement(String ^ announcement, String ^ activityId, AutomationNotificationKind kind,
AutomationNotificationProcessing processing)
: m_announcement(announcement), m_activityId(activityId), m_kind(kind), m_processing(processing)
{
}
String^ NarratorAnnouncement::Announcement::get()
String ^ NarratorAnnouncement::Announcement::get()
{
return m_announcement;
}
String^ NarratorAnnouncement::ActivityId::get()
String ^ NarratorAnnouncement::ActivityId::get()
{
return m_activityId;
}
@ -57,108 +51,73 @@ AutomationNotificationProcessing NarratorAnnouncement::Processing::get()
return m_processing;
}
bool NarratorAnnouncement::IsValid(NarratorAnnouncement^ announcement)
bool NarratorAnnouncement::IsValid(NarratorAnnouncement ^ announcement)
{
return announcement != nullptr
&& announcement->Announcement != nullptr
&& !announcement->Announcement->IsEmpty();
return announcement != nullptr && announcement->Announcement != nullptr && !announcement->Announcement->IsEmpty();
}
NarratorAnnouncement^ CalculatorAnnouncement::GetDisplayUpdatedAnnouncement(String^ announcement)
NarratorAnnouncement ^ CalculatorAnnouncement::GetDisplayUpdatedAnnouncement(String ^ announcement)
{
return ref new NarratorAnnouncement(
announcement,
CalculatorActivityIds::DisplayUpdated,
AutomationNotificationKind::Other,
AutomationNotificationProcessing::ImportantMostRecent);
return ref new NarratorAnnouncement(announcement, CalculatorActivityIds::DisplayUpdated, AutomationNotificationKind::Other,
AutomationNotificationProcessing::ImportantMostRecent);
}
NarratorAnnouncement^ CalculatorAnnouncement::GetMaxDigitsReachedAnnouncement(String^ announcement)
NarratorAnnouncement ^ CalculatorAnnouncement::GetMaxDigitsReachedAnnouncement(String ^ announcement)
{
return ref new NarratorAnnouncement(
announcement,
CalculatorActivityIds::MaxDigitsReached,
AutomationNotificationKind::Other,
AutomationNotificationProcessing::ImportantMostRecent);
return ref new NarratorAnnouncement(announcement, CalculatorActivityIds::MaxDigitsReached, AutomationNotificationKind::Other,
AutomationNotificationProcessing::ImportantMostRecent);
}
NarratorAnnouncement^ CalculatorAnnouncement::GetMemoryClearedAnnouncement(String^ announcement)
NarratorAnnouncement ^ CalculatorAnnouncement::GetMemoryClearedAnnouncement(String ^ announcement)
{
return ref new NarratorAnnouncement(
announcement,
CalculatorActivityIds::MemoryCleared,
AutomationNotificationKind::ItemRemoved,
AutomationNotificationProcessing::ImportantMostRecent);
return ref new NarratorAnnouncement(announcement, CalculatorActivityIds::MemoryCleared, AutomationNotificationKind::ItemRemoved,
AutomationNotificationProcessing::ImportantMostRecent);
}
NarratorAnnouncement^ CalculatorAnnouncement::GetMemoryItemChangedAnnouncement(String^ announcement)
NarratorAnnouncement ^ CalculatorAnnouncement::GetMemoryItemChangedAnnouncement(String ^ announcement)
{
return ref new NarratorAnnouncement(
announcement,
CalculatorActivityIds::MemoryItemChanged,
AutomationNotificationKind::ActionCompleted,
AutomationNotificationProcessing::MostRecent);
return ref new NarratorAnnouncement(announcement, CalculatorActivityIds::MemoryItemChanged, AutomationNotificationKind::ActionCompleted,
AutomationNotificationProcessing::MostRecent);
}
NarratorAnnouncement^ CalculatorAnnouncement::GetMemoryItemAddedAnnouncement(String^ announcement)
NarratorAnnouncement ^ CalculatorAnnouncement::GetMemoryItemAddedAnnouncement(String ^ announcement)
{
return ref new NarratorAnnouncement(
announcement,
CalculatorActivityIds::MemoryItemAdded,
AutomationNotificationKind::ItemAdded,
AutomationNotificationProcessing::MostRecent);
return ref new NarratorAnnouncement(announcement, CalculatorActivityIds::MemoryItemAdded, AutomationNotificationKind::ItemAdded,
AutomationNotificationProcessing::MostRecent);
}
NarratorAnnouncement^ CalculatorAnnouncement::GetHistoryClearedAnnouncement(String^ announcement)
NarratorAnnouncement ^ CalculatorAnnouncement::GetHistoryClearedAnnouncement(String ^ announcement)
{
return ref new NarratorAnnouncement(
announcement,
CalculatorActivityIds::HistoryCleared,
AutomationNotificationKind::ItemRemoved,
AutomationNotificationProcessing::MostRecent);
return ref new NarratorAnnouncement(announcement, CalculatorActivityIds::HistoryCleared, AutomationNotificationKind::ItemRemoved,
AutomationNotificationProcessing::MostRecent);
}
NarratorAnnouncement^ CalculatorAnnouncement::GetCategoryNameChangedAnnouncement(String^ announcement)
NarratorAnnouncement ^ CalculatorAnnouncement::GetCategoryNameChangedAnnouncement(String ^ announcement)
{
return ref new NarratorAnnouncement(
announcement,
CalculatorActivityIds::CategoryNameChanged,
AutomationNotificationKind::ActionCompleted,
AutomationNotificationProcessing::ImportantMostRecent);
return ref new NarratorAnnouncement(announcement, CalculatorActivityIds::CategoryNameChanged, AutomationNotificationKind::ActionCompleted,
AutomationNotificationProcessing::ImportantMostRecent);
}
NarratorAnnouncement^ CalculatorAnnouncement::GetUpdateCurrencyRatesAnnouncement(String^ announcement)
NarratorAnnouncement ^ CalculatorAnnouncement::GetUpdateCurrencyRatesAnnouncement(String ^ announcement)
{
return ref new NarratorAnnouncement(
announcement,
CalculatorActivityIds::UpdateCurrencyRates,
AutomationNotificationKind::ActionCompleted,
AutomationNotificationProcessing::ImportantMostRecent);
return ref new NarratorAnnouncement(announcement, CalculatorActivityIds::UpdateCurrencyRates, AutomationNotificationKind::ActionCompleted,
AutomationNotificationProcessing::ImportantMostRecent);
}
NarratorAnnouncement^ CalculatorAnnouncement::GetDisplayCopiedAnnouncement(String^ announcement)
NarratorAnnouncement ^ CalculatorAnnouncement::GetDisplayCopiedAnnouncement(String ^ announcement)
{
return ref new NarratorAnnouncement(
announcement,
CalculatorActivityIds::DisplayCopied,
AutomationNotificationKind::ActionCompleted,
AutomationNotificationProcessing::ImportantMostRecent);
return ref new NarratorAnnouncement(announcement, CalculatorActivityIds::DisplayCopied, AutomationNotificationKind::ActionCompleted,
AutomationNotificationProcessing::ImportantMostRecent);
}
NarratorAnnouncement^ CalculatorAnnouncement::GetOpenParenthesisCountChangedAnnouncement(String^ announcement)
NarratorAnnouncement ^ CalculatorAnnouncement::GetOpenParenthesisCountChangedAnnouncement(String ^ announcement)
{
return ref new NarratorAnnouncement(
announcement,
CalculatorActivityIds::OpenParenthesisCountChanged,
AutomationNotificationKind::ActionCompleted,
AutomationNotificationProcessing::ImportantMostRecent);
return ref new NarratorAnnouncement(announcement, CalculatorActivityIds::OpenParenthesisCountChanged, AutomationNotificationKind::ActionCompleted,
AutomationNotificationProcessing::ImportantMostRecent);
}
NarratorAnnouncement^ CalculatorAnnouncement::GetNoRightParenthesisAddedAnnouncement(String^ announcement)
NarratorAnnouncement ^ CalculatorAnnouncement::GetNoRightParenthesisAddedAnnouncement(String ^ announcement)
{
return ref new NarratorAnnouncement(
announcement,
CalculatorActivityIds::NoParenthesisAdded,
AutomationNotificationKind::ActionCompleted,
AutomationNotificationProcessing::ImportantMostRecent);
return ref new NarratorAnnouncement(announcement, CalculatorActivityIds::NoParenthesisAdded, AutomationNotificationKind::ActionCompleted,
AutomationNotificationProcessing::ImportantMostRecent);
}

View file

@ -11,7 +11,8 @@ namespace CalculatorApp::Common::Automation
// enums should be removed and the Windows types should be used
// instead.
// TODO - MSFT 12735088
public enum class AutomationNotificationKind
public
enum class AutomationNotificationKind
{
ItemAdded = 0,
ItemRemoved = 1,
@ -20,7 +21,8 @@ namespace CalculatorApp::Common::Automation
Other = 4
};
public enum class AutomationNotificationProcessing
public
enum class AutomationNotificationProcessing
{
ImportantAll = 0,
ImportantMostRecent = 1,
@ -29,20 +31,17 @@ namespace CalculatorApp::Common::Automation
CurrentThenMostRecent = 4
};
public ref class NarratorAnnouncement sealed
public
ref class NarratorAnnouncement sealed
{
public:
property Platform::String^ Announcement
{
Platform::String^ get();
}
property Platform::String
^ Announcement { Platform::String ^ get(); }
property Platform::String^ ActivityId
{
Platform::String^ get();
}
property Platform::String
^ ActivityId { Platform::String ^ get(); }
property AutomationNotificationKind Kind
property AutomationNotificationKind Kind
{
AutomationNotificationKind get();
}
@ -52,21 +51,18 @@ namespace CalculatorApp::Common::Automation
AutomationNotificationProcessing get();
}
static bool IsValid(NarratorAnnouncement^ announcement);
static bool IsValid(NarratorAnnouncement ^ announcement);
private:
// Make CalculatorAnnouncement a friend class so it is the only
// class that can access the private constructor.
friend class CalculatorAnnouncement;
NarratorAnnouncement(
Platform::String^ announcement,
Platform::String^ activityId,
AutomationNotificationKind kind,
AutomationNotificationProcessing processing);
NarratorAnnouncement(Platform::String ^ announcement, Platform::String ^ activityId, AutomationNotificationKind kind,
AutomationNotificationProcessing processing);
Platform::String^ m_announcement;
Platform::String^ m_activityId;
Platform::String ^ m_announcement;
Platform::String ^ m_activityId;
AutomationNotificationKind m_kind;
AutomationNotificationProcessing m_processing;
};
@ -76,22 +72,22 @@ namespace CalculatorApp::Common::Automation
class CalculatorAnnouncement
{
public:
static NarratorAnnouncement^ GetDisplayUpdatedAnnouncement(Platform::String^ announcement);
static NarratorAnnouncement^ GetMaxDigitsReachedAnnouncement(Platform::String^ announcement);
static NarratorAnnouncement ^ GetDisplayUpdatedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement ^ GetMaxDigitsReachedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement^ GetMemoryClearedAnnouncement(Platform::String^ announcement);
static NarratorAnnouncement^ GetMemoryItemChangedAnnouncement(Platform::String^ announcement);
static NarratorAnnouncement^ GetMemoryItemAddedAnnouncement(Platform::String^ announcement);
static NarratorAnnouncement ^ GetMemoryClearedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement ^ GetMemoryItemChangedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement ^ GetMemoryItemAddedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement^ GetHistoryClearedAnnouncement(Platform::String^ announcement);
static NarratorAnnouncement ^ GetHistoryClearedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement^ GetCategoryNameChangedAnnouncement(Platform::String^ announcement);
static NarratorAnnouncement ^ GetCategoryNameChangedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement^ GetUpdateCurrencyRatesAnnouncement(Platform::String^ announcement);
static NarratorAnnouncement ^ GetUpdateCurrencyRatesAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement^ GetDisplayCopiedAnnouncement(Platform::String^ announcement);
static NarratorAnnouncement ^ GetDisplayCopiedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement^ GetOpenParenthesisCountChangedAnnouncement(Platform::String^ announcement);
static NarratorAnnouncement^ GetNoRightParenthesisAddedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement ^ GetOpenParenthesisCountChangedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement ^ GetNoRightParenthesisAddedAnnouncement(Platform::String ^ announcement);
};
}

View file

@ -9,8 +9,8 @@
using namespace CalculatorApp::Common::Automation;
using namespace std;
INarratorAnnouncementHost^ NarratorAnnouncementHostFactory::s_hostProducer;
vector<INarratorAnnouncementHost^> NarratorAnnouncementHostFactory::s_hosts;
INarratorAnnouncementHost ^ NarratorAnnouncementHostFactory::s_hostProducer;
vector<INarratorAnnouncementHost ^> NarratorAnnouncementHostFactory::s_hosts;
// This static variable is used only to call the initialization function, to initialize the other static variables.
int NarratorAnnouncementHostFactory::s_init = NarratorAnnouncementHostFactory::Initialize();
@ -32,15 +32,12 @@ void NarratorAnnouncementHostFactory::RegisterHosts()
{
// The host that will be used is the first available host,
// therefore, order of hosts is important here.
NarratorAnnouncementHostFactory::s_hosts = {
ref new NotificationHost(),
ref new LiveRegionHost()
};
NarratorAnnouncementHostFactory::s_hosts = { ref new NotificationHost(), ref new LiveRegionHost() };
}
INarratorAnnouncementHost^ NarratorAnnouncementHostFactory::GetHostProducer()
INarratorAnnouncementHost ^ NarratorAnnouncementHostFactory::GetHostProducer()
{
for (INarratorAnnouncementHost^ host : NarratorAnnouncementHostFactory::s_hosts)
for (INarratorAnnouncementHost ^ host : NarratorAnnouncementHostFactory::s_hosts)
{
if (host->IsHostAvailable())
{
@ -52,7 +49,7 @@ INarratorAnnouncementHost^ NarratorAnnouncementHostFactory::GetHostProducer()
return nullptr;
}
INarratorAnnouncementHost^ NarratorAnnouncementHostFactory::MakeHost()
INarratorAnnouncementHost ^ NarratorAnnouncementHostFactory::MakeHost()
{
if (NarratorAnnouncementHostFactory::s_hostProducer == nullptr)
{

View file

@ -14,18 +14,20 @@ namespace CalculatorApp::Common::Automation
class NarratorAnnouncementHostFactory
{
public:
static INarratorAnnouncementHost^ MakeHost();
static INarratorAnnouncementHost ^ MakeHost();
private:
NarratorAnnouncementHostFactory() {}
NarratorAnnouncementHostFactory()
{
}
static int Initialize();
static void RegisterHosts();
static INarratorAnnouncementHost^ GetHostProducer();
static INarratorAnnouncementHost ^ GetHostProducer();
private:
static int s_init;
static INarratorAnnouncementHost^ s_hostProducer;
static std::vector<INarratorAnnouncementHost^> s_hosts;
static INarratorAnnouncementHost ^ s_hostProducer;
static std::vector<INarratorAnnouncementHost ^> s_hosts;
};
}

View file

@ -13,17 +13,16 @@ using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Automation;
using namespace Windows::UI::Xaml::Automation::Peers;
DependencyProperty^ NarratorNotifier::s_announcementProperty;
DependencyProperty ^ NarratorNotifier::s_announcementProperty;
NarratorNotifier::NarratorNotifier()
{
m_announcementHost = NarratorAnnouncementHostFactory::MakeHost();
}
void NarratorNotifier::Announce(NarratorAnnouncement^ announcement)
void NarratorNotifier::Announce(NarratorAnnouncement ^ announcement)
{
if (NarratorAnnouncement::IsValid(announcement)
&& m_announcementHost != nullptr)
if (NarratorAnnouncement::IsValid(announcement) && m_announcementHost != nullptr)
{
m_announcementHost->Announce(announcement);
}
@ -31,20 +30,18 @@ void NarratorNotifier::Announce(NarratorAnnouncement^ announcement)
void NarratorNotifier::RegisterDependencyProperties()
{
s_announcementProperty = DependencyProperty::Register(
L"Announcement", // The name of the dependency property.
NarratorAnnouncement::typeid, // The type of the dependency property.
NarratorNotifier::typeid, // The owner of the dependency property.
ref new PropertyMetadata(
nullptr, // Default value of the dependency property.
ref new PropertyChangedCallback(OnAnnouncementChanged)));
s_announcementProperty = DependencyProperty::Register(L"Announcement", // The name of the dependency property.
NarratorAnnouncement::typeid, // The type of the dependency property.
NarratorNotifier::typeid, // The owner of the dependency property.
ref new PropertyMetadata(nullptr, // Default value of the dependency property.
ref new PropertyChangedCallback(OnAnnouncementChanged)));
}
void NarratorNotifier::OnAnnouncementChanged(_In_ DependencyObject^ dependencyObject, _In_ DependencyPropertyChangedEventArgs^ e)
void NarratorNotifier::OnAnnouncementChanged(_In_ DependencyObject ^ dependencyObject, _In_ DependencyPropertyChangedEventArgs ^ e)
{
auto instance = safe_cast<NarratorNotifier^>(dependencyObject);
auto instance = safe_cast<NarratorNotifier ^>(dependencyObject);
if (instance != nullptr)
{
instance->Announce(safe_cast<NarratorAnnouncement^>(e->NewValue));
instance->Announce(safe_cast<NarratorAnnouncement ^>(e->NewValue));
}
}

View file

@ -8,12 +8,13 @@
namespace CalculatorApp::Common::Automation
{
public ref class NarratorNotifier sealed : public Windows::UI::Xaml::DependencyObject
public
ref class NarratorNotifier sealed : public Windows::UI::Xaml::DependencyObject
{
public:
NarratorNotifier();
void Announce(NarratorAnnouncement^ announcement);
void Announce(NarratorAnnouncement ^ announcement);
property NarratorAnnouncement^ Announcement
{
@ -26,32 +27,25 @@ namespace CalculatorApp::Common::Automation
static void RegisterDependencyProperties();
static property Windows::UI::Xaml::DependencyProperty^ AnnouncementProperty
{
Windows::UI::Xaml::DependencyProperty^ get()
{
return s_announcementProperty;
}
}
static property Windows::UI::Xaml::DependencyProperty
^ AnnouncementProperty { Windows::UI::Xaml::DependencyProperty ^ get() { return s_announcementProperty; } }
static NarratorAnnouncement^ GetAnnouncement(Windows::UI::Xaml::DependencyObject^ element)
{
return safe_cast<NarratorAnnouncement^>(element->GetValue(s_announcementProperty));
}
static NarratorAnnouncement
^ GetAnnouncement(Windows::UI::Xaml::DependencyObject
^ element) { return safe_cast<NarratorAnnouncement ^>(element->GetValue(s_announcementProperty)); }
static void SetAnnouncement(Windows::UI::Xaml::DependencyObject^ element, NarratorAnnouncement^ value)
static void SetAnnouncement(Windows::UI::Xaml::DependencyObject ^ element, NarratorAnnouncement ^ value)
{
element->SetValue(s_announcementProperty, value);
}
private:
static void OnAnnouncementChanged(
_In_ Windows::UI::Xaml::DependencyObject^ dependencyObject,
_In_ Windows::UI::Xaml::DependencyPropertyChangedEventArgs^ eventArgs);
static void OnAnnouncementChanged(_In_ Windows::UI::Xaml::DependencyObject ^ dependencyObject,
_In_ Windows::UI::Xaml::DependencyPropertyChangedEventArgs ^ eventArgs);
static Windows::UI::Xaml::DependencyProperty^ s_announcementProperty;
static Windows::UI::Xaml::DependencyProperty ^ s_announcementProperty;
private:
INarratorAnnouncementHost^ m_announcementHost;
INarratorAnnouncementHost ^ m_announcementHost;
};
}

View file

@ -10,23 +10,21 @@ using namespace Windows::UI::Xaml::Automation;
using namespace Windows::UI::Xaml::Automation::Peers;
using namespace Windows::UI::Xaml::Controls;
NotificationHost::NotificationHost() :
m_host(nullptr)
{}
NotificationHost::NotificationHost() : m_host(nullptr)
{
}
bool NotificationHost::IsHostAvailable()
{
return ApiInformation::IsMethodPresent(
L"Windows.UI.Xaml.Automation.Peers.AutomationPeer",
L"RaiseNotificationEvent");
return ApiInformation::IsMethodPresent(L"Windows.UI.Xaml.Automation.Peers.AutomationPeer", L"RaiseNotificationEvent");
}
INarratorAnnouncementHost^ NotificationHost::MakeHost()
INarratorAnnouncementHost ^ NotificationHost::MakeHost()
{
return ref new NotificationHost();
}
void NotificationHost::Announce(NarratorAnnouncement^ announcement)
void NotificationHost::Announce(NarratorAnnouncement ^ announcement)
{
if (m_host == nullptr)
{
@ -36,16 +34,12 @@ void NotificationHost::Announce(NarratorAnnouncement^ announcement)
auto peer = FrameworkElementAutomationPeer::FromElement(m_host);
if (peer != nullptr)
{
peer->RaiseNotificationEvent(
GetWindowsNotificationKind(announcement->Kind),
GetWindowsNotificationProcessing(announcement->Processing),
announcement->Announcement,
announcement->ActivityId);
peer->RaiseNotificationEvent(GetWindowsNotificationKind(announcement->Kind), GetWindowsNotificationProcessing(announcement->Processing),
announcement->Announcement, announcement->ActivityId);
}
}
StandardPeers::AutomationNotificationKind NotificationHost::GetWindowsNotificationKind(
CustomPeers::AutomationNotificationKind customKindType)
StandardPeers::AutomationNotificationKind NotificationHost::GetWindowsNotificationKind(CustomPeers::AutomationNotificationKind customKindType)
{
switch (customKindType)
{
@ -71,8 +65,8 @@ StandardPeers::AutomationNotificationKind NotificationHost::GetWindowsNotificati
return StandardPeers::AutomationNotificationKind::Other;
}
StandardPeers::AutomationNotificationProcessing NotificationHost::GetWindowsNotificationProcessing(
CustomPeers::AutomationNotificationProcessing customProcessingType)
StandardPeers::AutomationNotificationProcessing
NotificationHost::GetWindowsNotificationProcessing(CustomPeers::AutomationNotificationProcessing customProcessingType)
{
switch (customProcessingType)
{

View file

@ -10,25 +10,25 @@
namespace CalculatorApp::Common::Automation
{
public ref class NotificationHost sealed : public INarratorAnnouncementHost
public
ref class NotificationHost sealed : public INarratorAnnouncementHost
{
public:
NotificationHost();
virtual bool IsHostAvailable();
virtual INarratorAnnouncementHost^ MakeHost();
virtual INarratorAnnouncementHost ^ MakeHost();
virtual void Announce(NarratorAnnouncement^ announcement);
virtual void Announce(NarratorAnnouncement ^ announcement);
private:
static Windows::UI::Xaml::Automation::Peers::AutomationNotificationKind GetWindowsNotificationKind(
CalculatorApp::Common::Automation::AutomationNotificationKind customKindType);
static Windows::UI::Xaml::Automation::Peers::AutomationNotificationKind
GetWindowsNotificationKind(CalculatorApp::Common::Automation::AutomationNotificationKind customKindType);
static Windows::UI::Xaml::Automation::Peers::AutomationNotificationProcessing GetWindowsNotificationProcessing(
CalculatorApp::Common::Automation::AutomationNotificationProcessing customProcessingType);
static Windows::UI::Xaml::Automation::Peers::AutomationNotificationProcessing
GetWindowsNotificationProcessing(CalculatorApp::Common::Automation::AutomationNotificationProcessing customProcessingType);
private:
Windows::UI::Xaml::UIElement^ m_host;
Windows::UI::Xaml::UIElement ^ m_host;
};
}

View file

@ -13,22 +13,22 @@ using namespace Windows::UI::Xaml::Data;
/// Notifies listeners that a property value has changed.
/// </summary>
/// <param name="propertyName">Name of the property used to notify listeners.</param>
void BindableBase::OnPropertyChanged(String^ propertyName)
void BindableBase::OnPropertyChanged(String ^ propertyName)
{
PropertyChanged(this, ref new PropertyChangedEventArgs(propertyName));
}
Windows::UI::Xaml::Data::ICustomProperty^ BindableBase::GetCustomProperty(Platform::String^ name)
Windows::UI::Xaml::Data::ICustomProperty ^ BindableBase::GetCustomProperty(Platform::String ^ name)
{
return nullptr;
}
Windows::UI::Xaml::Data::ICustomProperty^ BindableBase::GetIndexedProperty(Platform::String^ name, Windows::UI::Xaml::Interop::TypeName type)
Windows::UI::Xaml::Data::ICustomProperty ^ BindableBase::GetIndexedProperty(Platform::String ^ name, Windows::UI::Xaml::Interop::TypeName type)
{
return nullptr;
}
Platform::String^ BindableBase::GetStringRepresentation()
Platform::String ^ BindableBase::GetStringRepresentation()
{
return this->ToString();
}

View file

@ -10,26 +10,29 @@ namespace CalculatorApp
/// <summary>
/// Implementation of <see cref="INotifyPropertyChanged"/> to simplify models.
/// </summary>
[Windows::Foundation::Metadata::WebHostHidden]
public ref class BindableBase : Windows::UI::Xaml::DependencyObject, Windows::UI::Xaml::Data::INotifyPropertyChanged, Windows::UI::Xaml::Data::ICustomPropertyProvider
[Windows::Foundation::Metadata::WebHostHidden] public ref class BindableBase : Windows::UI::Xaml::DependencyObject,
Windows::UI::Xaml::Data::INotifyPropertyChanged,
Windows::UI::Xaml::Data::ICustomPropertyProvider
{
public:
virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler^ PropertyChanged;
virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler ^ PropertyChanged;
public:
// ICustomPropertyProvider
virtual Windows::UI::Xaml::Data::ICustomProperty^ GetCustomProperty(Platform::String^ name);
virtual Windows::UI::Xaml::Data::ICustomProperty^ GetIndexedProperty(Platform::String^ name, Windows::UI::Xaml::Interop::TypeName type);
virtual Platform::String^ GetStringRepresentation();
virtual Windows::UI::Xaml::Data::ICustomProperty ^ GetCustomProperty(Platform::String ^ name);
virtual Windows::UI::Xaml::Data::ICustomProperty ^ GetIndexedProperty(Platform::String ^ name, Windows::UI::Xaml::Interop::TypeName type);
virtual Platform::String ^ GetStringRepresentation();
property Windows::UI::Xaml::Interop::TypeName Type
{
virtual Windows::UI::Xaml::Interop::TypeName get() { return this->GetType(); }
virtual Windows::UI::Xaml::Interop::TypeName get()
{
return this->GetType();
}
}
protected:
virtual void OnPropertyChanged(Platform::String^ propertyName);
virtual void OnPropertyChanged(Platform::String ^ propertyName);
};
}
}

View file

@ -8,9 +8,9 @@ using namespace CalculatorApp;
using namespace CalculatorApp::Common;
using namespace Platform;
NumbersAndOperatorsEnum CalculatorButtonPressedEventArgs::GetOperationFromCommandParameter(_In_ Object^ commandParameter)
NumbersAndOperatorsEnum CalculatorButtonPressedEventArgs::GetOperationFromCommandParameter(_In_ Object ^ commandParameter)
{
auto eventArgs = dynamic_cast<CalculatorButtonPressedEventArgs^>(commandParameter);
auto eventArgs = dynamic_cast<CalculatorButtonPressedEventArgs ^>(commandParameter);
if (eventArgs != nullptr)
{
return eventArgs->Operation;
@ -21,9 +21,9 @@ NumbersAndOperatorsEnum CalculatorButtonPressedEventArgs::GetOperationFromComman
}
}
String^ CalculatorButtonPressedEventArgs::GetAuditoryFeedbackFromCommandParameter(_In_ Object^ commandParameter)
String ^ CalculatorButtonPressedEventArgs::GetAuditoryFeedbackFromCommandParameter(_In_ Object ^ commandParameter)
{
auto eventArgs = dynamic_cast<CalculatorButtonPressedEventArgs^>(commandParameter);
auto eventArgs = dynamic_cast<CalculatorButtonPressedEventArgs ^>(commandParameter);
if (eventArgs != nullptr)
{
return eventArgs->AuditoryFeedback;
@ -33,4 +33,3 @@ String^ CalculatorButtonPressedEventArgs::GetAuditoryFeedbackFromCommandParamete
return nullptr;
}
}

View file

@ -10,18 +10,20 @@ namespace CalculatorApp
{
namespace Common
{
public ref class CalculatorButtonPressedEventArgs sealed
public
ref class CalculatorButtonPressedEventArgs sealed
{
public:
PROPERTY_R(Platform::String^, AuditoryFeedback);
PROPERTY_R(Platform::String ^, AuditoryFeedback);
PROPERTY_R(CalculatorApp::NumbersAndOperatorsEnum, Operation);
CalculatorButtonPressedEventArgs(
Platform::String^ feedback, CalculatorApp::NumbersAndOperatorsEnum operation) :
m_AuditoryFeedback(feedback), m_Operation(operation) {}
CalculatorButtonPressedEventArgs(Platform::String ^ feedback, CalculatorApp::NumbersAndOperatorsEnum operation)
: m_AuditoryFeedback(feedback), m_Operation(operation)
{
}
static CalculatorApp::NumbersAndOperatorsEnum GetOperationFromCommandParameter(_In_ Platform::Object^ commandParameter);
static Platform::String^ GetAuditoryFeedbackFromCommandParameter(_In_ Platform::Object^ commandParameter);
static CalculatorApp::NumbersAndOperatorsEnum GetOperationFromCommandParameter(_In_ Platform::Object ^ commandParameter);
static Platform::String ^ GetAuditoryFeedbackFromCommandParameter(_In_ Platform::Object ^ commandParameter);
};
}
}

View file

@ -9,205 +9,207 @@ namespace CalculatorApp
{
namespace CM = CalculationManager;
public enum class NumbersAndOperatorsEnum
public
enum class NumbersAndOperatorsEnum
{
Zero = (int) CM::Command::Command0,
One = (int) CM::Command::Command1,
Two = (int) CM::Command::Command2,
Three = (int) CM::Command::Command3,
Four = (int) CM::Command::Command4,
Five = (int) CM::Command::Command5,
Six = (int) CM::Command::Command6,
Seven = (int) CM::Command::Command7,
Eight = (int) CM::Command::Command8,
Nine = (int) CM::Command::Command9,
Add = (int) CM::Command::CommandADD,
Subtract = (int) CM::Command::CommandSUB,
Multiply = (int) CM::Command::CommandMUL,
Divide = (int) CM::Command::CommandDIV,
Invert = (int) CM::Command::CommandREC,
Equals = (int) CM::Command::CommandEQU,
Decimal = (int) CM::Command::CommandPNT,
Sqrt = (int) CM::Command::CommandSQRT,
Percent = (int) CM::Command::CommandPERCENT,
Negate = (int) CM::Command::CommandSIGN,
Backspace = (int) CM::Command::CommandBACK,
ClearEntry = (int) CM::Command::CommandCENTR,
Clear = (int) CM::Command::CommandCLEAR,
Degree = (int) CM::Command::CommandDEG,
Radians = (int) CM::Command::CommandRAD,
Grads = (int) CM::Command::CommandGRAD,
Degrees = (int) CM::Command::CommandDegrees,
OpenParenthesis = (int) CM::Command::CommandOPENP,
CloseParenthesis = (int) CM::Command::CommandCLOSEP,
Pi = (int) CM::Command::CommandPI,
Sin = (int) CM::Command::CommandSIN,
Cos = (int) CM::Command::CommandCOS,
Tan = (int) CM::Command::CommandTAN,
Factorial = (int) CM::Command::CommandFAC,
XPower2 = (int) CM::Command::CommandSQR,
Mod = (int) CM::Command::CommandMOD,
FToE = (int) CM::Command::CommandFE,
LogBaseE = (int) CM::Command::CommandLN,
InvSin = (int) CM::Command::CommandASIN,
InvCos = (int) CM::Command::CommandACOS,
InvTan = (int) CM::Command::CommandATAN,
LogBase10 = (int) CM::Command::CommandLOG,
XPowerY = (int) CM::Command::CommandPWR,
YRootX = (int) CM::Command::CommandROOT,
TenPowerX = (int) CM::Command::CommandPOW10,
EPowerX = (int) CM::Command::CommandPOWE,
Exp = (int) CM::Command::CommandEXP,
IsScientificMode = (int) CM::Command::ModeScientific,
IsStandardMode = (int) CM::Command::ModeBasic,
None = (int) CM::Command::CommandNULL,
IsProgrammerMode = (int) CM::Command::ModeProgrammer,
DecButton = (int) CM::Command::CommandDec,
OctButton = (int) CM::Command::CommandOct,
HexButton = (int) CM::Command::CommandHex,
BinButton = (int) CM::Command::CommandBin,
And = (int) CM::Command::CommandAnd,
Ror = (int) CM::Command::CommandROR,
Rol = (int) CM::Command::CommandROL,
Or = (int) CM::Command::CommandOR,
Lsh = (int) CM::Command::CommandLSHF,
Rsh = (int) CM::Command::CommandRSHF,
Xor = (int) CM::Command::CommandXor,
Not = (int) CM::Command::CommandNot,
A = (int) CM::Command::CommandA,
B = (int) CM::Command::CommandB,
C = (int) CM::Command::CommandC,
D = (int) CM::Command::CommandD,
E = (int) CM::Command::CommandE,
F = (int) CM::Command::CommandF,
Zero = (int)CM::Command::Command0,
One = (int)CM::Command::Command1,
Two = (int)CM::Command::Command2,
Three = (int)CM::Command::Command3,
Four = (int)CM::Command::Command4,
Five = (int)CM::Command::Command5,
Six = (int)CM::Command::Command6,
Seven = (int)CM::Command::Command7,
Eight = (int)CM::Command::Command8,
Nine = (int)CM::Command::Command9,
Add = (int)CM::Command::CommandADD,
Subtract = (int)CM::Command::CommandSUB,
Multiply = (int)CM::Command::CommandMUL,
Divide = (int)CM::Command::CommandDIV,
Invert = (int)CM::Command::CommandREC,
Equals = (int)CM::Command::CommandEQU,
Decimal = (int)CM::Command::CommandPNT,
Sqrt = (int)CM::Command::CommandSQRT,
Percent = (int)CM::Command::CommandPERCENT,
Negate = (int)CM::Command::CommandSIGN,
Backspace = (int)CM::Command::CommandBACK,
ClearEntry = (int)CM::Command::CommandCENTR,
Clear = (int)CM::Command::CommandCLEAR,
Degree = (int)CM::Command::CommandDEG,
Radians = (int)CM::Command::CommandRAD,
Grads = (int)CM::Command::CommandGRAD,
Degrees = (int)CM::Command::CommandDegrees,
OpenParenthesis = (int)CM::Command::CommandOPENP,
CloseParenthesis = (int)CM::Command::CommandCLOSEP,
Pi = (int)CM::Command::CommandPI,
Sin = (int)CM::Command::CommandSIN,
Cos = (int)CM::Command::CommandCOS,
Tan = (int)CM::Command::CommandTAN,
Factorial = (int)CM::Command::CommandFAC,
XPower2 = (int)CM::Command::CommandSQR,
Mod = (int)CM::Command::CommandMOD,
FToE = (int)CM::Command::CommandFE,
LogBaseE = (int)CM::Command::CommandLN,
InvSin = (int)CM::Command::CommandASIN,
InvCos = (int)CM::Command::CommandACOS,
InvTan = (int)CM::Command::CommandATAN,
LogBase10 = (int)CM::Command::CommandLOG,
XPowerY = (int)CM::Command::CommandPWR,
YRootX = (int)CM::Command::CommandROOT,
TenPowerX = (int)CM::Command::CommandPOW10,
EPowerX = (int)CM::Command::CommandPOWE,
Exp = (int)CM::Command::CommandEXP,
IsScientificMode = (int)CM::Command::ModeScientific,
IsStandardMode = (int)CM::Command::ModeBasic,
None = (int)CM::Command::CommandNULL,
IsProgrammerMode = (int)CM::Command::ModeProgrammer,
DecButton = (int)CM::Command::CommandDec,
OctButton = (int)CM::Command::CommandOct,
HexButton = (int)CM::Command::CommandHex,
BinButton = (int)CM::Command::CommandBin,
And = (int)CM::Command::CommandAnd,
Ror = (int)CM::Command::CommandROR,
Rol = (int)CM::Command::CommandROL,
Or = (int)CM::Command::CommandOR,
Lsh = (int)CM::Command::CommandLSHF,
Rsh = (int)CM::Command::CommandRSHF,
Xor = (int)CM::Command::CommandXor,
Not = (int)CM::Command::CommandNot,
A = (int)CM::Command::CommandA,
B = (int)CM::Command::CommandB,
C = (int)CM::Command::CommandC,
D = (int)CM::Command::CommandD,
E = (int)CM::Command::CommandE,
F = (int)CM::Command::CommandF,
Memory, // This is the memory button. Doesn't have a direct mapping to the CalcEngine.
Sinh = (int) CM::Command::CommandSINH,
Cosh = (int) CM::Command::CommandCOSH,
Tanh = (int) CM::Command::CommandTANH,
InvSinh = (int) CM::Command::CommandASINH,
InvCosh = (int) CM::Command::CommandACOSH,
InvTanh = (int) CM::Command::CommandATANH,
Qword = (int) CM::Command::CommandQword,
Dword = (int) CM::Command::CommandDword,
Word = (int) CM::Command::CommandWord,
Byte = (int) CM::Command::CommandByte,
Cube = (int) CM::Command::CommandCUB,
DMS = (int) CM::Command::CommandDMS,
Sinh = (int)CM::Command::CommandSINH,
Cosh = (int)CM::Command::CommandCOSH,
Tanh = (int)CM::Command::CommandTANH,
InvSinh = (int)CM::Command::CommandASINH,
InvCosh = (int)CM::Command::CommandACOSH,
InvTanh = (int)CM::Command::CommandATANH,
Qword = (int)CM::Command::CommandQword,
Dword = (int)CM::Command::CommandDword,
Word = (int)CM::Command::CommandWord,
Byte = (int)CM::Command::CommandByte,
Cube = (int)CM::Command::CommandCUB,
DMS = (int)CM::Command::CommandDMS,
BINSTART = (int) CM::Command::CommandBINEDITSTART,
BINPOS0 = (int) CM::Command::CommandBINPOS0,
BINPOS1 = (int) CM::Command::CommandBINPOS1,
BINPOS2 = (int) CM::Command::CommandBINPOS2,
BINPOS3 = (int) CM::Command::CommandBINPOS3,
BINPOS4 = (int) CM::Command::CommandBINPOS4,
BINPOS5 = (int) CM::Command::CommandBINPOS5,
BINPOS6 = (int) CM::Command::CommandBINPOS6,
BINPOS7 = (int) CM::Command::CommandBINPOS7,
BINPOS8 = (int) CM::Command::CommandBINPOS8,
BINPOS9 = (int) CM::Command::CommandBINPOS9,
BINPOS10 = (int) CM::Command::CommandBINPOS10,
BINPOS11 = (int) CM::Command::CommandBINPOS11,
BINPOS12 = (int) CM::Command::CommandBINPOS12,
BINPOS13 = (int) CM::Command::CommandBINPOS13,
BINPOS14 = (int) CM::Command::CommandBINPOS14,
BINPOS15 = (int) CM::Command::CommandBINPOS15,
BINPOS16 = (int) CM::Command::CommandBINPOS16,
BINPOS17 = (int) CM::Command::CommandBINPOS17,
BINPOS18 = (int) CM::Command::CommandBINPOS18,
BINPOS19 = (int) CM::Command::CommandBINPOS19,
BINPOS20 = (int) CM::Command::CommandBINPOS20,
BINPOS21 = (int) CM::Command::CommandBINPOS21,
BINPOS22 = (int) CM::Command::CommandBINPOS22,
BINPOS23 = (int) CM::Command::CommandBINPOS23,
BINPOS24 = (int) CM::Command::CommandBINPOS24,
BINPOS25 = (int) CM::Command::CommandBINPOS25,
BINPOS26 = (int) CM::Command::CommandBINPOS26,
BINPOS27 = (int) CM::Command::CommandBINPOS27,
BINPOS28 = (int) CM::Command::CommandBINPOS28,
BINPOS29 = (int) CM::Command::CommandBINPOS29,
BINPOS30 = (int) CM::Command::CommandBINPOS30,
BINPOS31 = (int) CM::Command::CommandBINPOS31,
BINPOS32 = (int) CM::Command::CommandBINPOS32,
BINPOS33 = (int) CM::Command::CommandBINPOS33,
BINPOS34 = (int) CM::Command::CommandBINPOS34,
BINPOS35 = (int) CM::Command::CommandBINPOS35,
BINPOS36 = (int) CM::Command::CommandBINPOS36,
BINPOS37 = (int) CM::Command::CommandBINPOS37,
BINPOS38 = (int) CM::Command::CommandBINPOS38,
BINPOS39 = (int) CM::Command::CommandBINPOS39,
BINPOS40 = (int) CM::Command::CommandBINPOS40,
BINPOS41 = (int) CM::Command::CommandBINPOS41,
BINPOS42 = (int) CM::Command::CommandBINPOS42,
BINPOS43 = (int) CM::Command::CommandBINPOS43,
BINPOS44 = (int) CM::Command::CommandBINPOS44,
BINPOS45 = (int) CM::Command::CommandBINPOS45,
BINPOS46 = (int) CM::Command::CommandBINPOS46,
BINPOS47 = (int) CM::Command::CommandBINPOS47,
BINPOS48 = (int) CM::Command::CommandBINPOS48,
BINPOS49 = (int) CM::Command::CommandBINPOS49,
BINPOS50 = (int) CM::Command::CommandBINPOS50,
BINPOS51 = (int) CM::Command::CommandBINPOS51,
BINPOS52 = (int) CM::Command::CommandBINPOS52,
BINPOS53 = (int) CM::Command::CommandBINPOS53,
BINPOS54 = (int) CM::Command::CommandBINPOS54,
BINPOS55 = (int) CM::Command::CommandBINPOS55,
BINPOS56 = (int) CM::Command::CommandBINPOS56,
BINPOS57 = (int) CM::Command::CommandBINPOS57,
BINPOS58 = (int) CM::Command::CommandBINPOS58,
BINPOS59 = (int) CM::Command::CommandBINPOS59,
BINPOS60 = (int) CM::Command::CommandBINPOS60,
BINPOS61 = (int) CM::Command::CommandBINPOS61,
BINPOS62 = (int) CM::Command::CommandBINPOS62,
BINPOS63 = (int) CM::Command::CommandBINPOS63,
BINEND = (int) CM::Command::CommandBINEDITEND,
Hyp = (int) CM::Command::CommandHYP
BINSTART = (int)CM::Command::CommandBINEDITSTART,
BINPOS0 = (int)CM::Command::CommandBINPOS0,
BINPOS1 = (int)CM::Command::CommandBINPOS1,
BINPOS2 = (int)CM::Command::CommandBINPOS2,
BINPOS3 = (int)CM::Command::CommandBINPOS3,
BINPOS4 = (int)CM::Command::CommandBINPOS4,
BINPOS5 = (int)CM::Command::CommandBINPOS5,
BINPOS6 = (int)CM::Command::CommandBINPOS6,
BINPOS7 = (int)CM::Command::CommandBINPOS7,
BINPOS8 = (int)CM::Command::CommandBINPOS8,
BINPOS9 = (int)CM::Command::CommandBINPOS9,
BINPOS10 = (int)CM::Command::CommandBINPOS10,
BINPOS11 = (int)CM::Command::CommandBINPOS11,
BINPOS12 = (int)CM::Command::CommandBINPOS12,
BINPOS13 = (int)CM::Command::CommandBINPOS13,
BINPOS14 = (int)CM::Command::CommandBINPOS14,
BINPOS15 = (int)CM::Command::CommandBINPOS15,
BINPOS16 = (int)CM::Command::CommandBINPOS16,
BINPOS17 = (int)CM::Command::CommandBINPOS17,
BINPOS18 = (int)CM::Command::CommandBINPOS18,
BINPOS19 = (int)CM::Command::CommandBINPOS19,
BINPOS20 = (int)CM::Command::CommandBINPOS20,
BINPOS21 = (int)CM::Command::CommandBINPOS21,
BINPOS22 = (int)CM::Command::CommandBINPOS22,
BINPOS23 = (int)CM::Command::CommandBINPOS23,
BINPOS24 = (int)CM::Command::CommandBINPOS24,
BINPOS25 = (int)CM::Command::CommandBINPOS25,
BINPOS26 = (int)CM::Command::CommandBINPOS26,
BINPOS27 = (int)CM::Command::CommandBINPOS27,
BINPOS28 = (int)CM::Command::CommandBINPOS28,
BINPOS29 = (int)CM::Command::CommandBINPOS29,
BINPOS30 = (int)CM::Command::CommandBINPOS30,
BINPOS31 = (int)CM::Command::CommandBINPOS31,
BINPOS32 = (int)CM::Command::CommandBINPOS32,
BINPOS33 = (int)CM::Command::CommandBINPOS33,
BINPOS34 = (int)CM::Command::CommandBINPOS34,
BINPOS35 = (int)CM::Command::CommandBINPOS35,
BINPOS36 = (int)CM::Command::CommandBINPOS36,
BINPOS37 = (int)CM::Command::CommandBINPOS37,
BINPOS38 = (int)CM::Command::CommandBINPOS38,
BINPOS39 = (int)CM::Command::CommandBINPOS39,
BINPOS40 = (int)CM::Command::CommandBINPOS40,
BINPOS41 = (int)CM::Command::CommandBINPOS41,
BINPOS42 = (int)CM::Command::CommandBINPOS42,
BINPOS43 = (int)CM::Command::CommandBINPOS43,
BINPOS44 = (int)CM::Command::CommandBINPOS44,
BINPOS45 = (int)CM::Command::CommandBINPOS45,
BINPOS46 = (int)CM::Command::CommandBINPOS46,
BINPOS47 = (int)CM::Command::CommandBINPOS47,
BINPOS48 = (int)CM::Command::CommandBINPOS48,
BINPOS49 = (int)CM::Command::CommandBINPOS49,
BINPOS50 = (int)CM::Command::CommandBINPOS50,
BINPOS51 = (int)CM::Command::CommandBINPOS51,
BINPOS52 = (int)CM::Command::CommandBINPOS52,
BINPOS53 = (int)CM::Command::CommandBINPOS53,
BINPOS54 = (int)CM::Command::CommandBINPOS54,
BINPOS55 = (int)CM::Command::CommandBINPOS55,
BINPOS56 = (int)CM::Command::CommandBINPOS56,
BINPOS57 = (int)CM::Command::CommandBINPOS57,
BINPOS58 = (int)CM::Command::CommandBINPOS58,
BINPOS59 = (int)CM::Command::CommandBINPOS59,
BINPOS60 = (int)CM::Command::CommandBINPOS60,
BINPOS61 = (int)CM::Command::CommandBINPOS61,
BINPOS62 = (int)CM::Command::CommandBINPOS62,
BINPOS63 = (int)CM::Command::CommandBINPOS63,
BINEND = (int)CM::Command::CommandBINEDITEND,
Hyp = (int)CM::Command::CommandHYP
};
// This contains list of functions whose usage we are tracelogging
public enum class FunctionLogEnum
public
enum class FunctionLogEnum
{
Invert = (int) CM::Command::CommandREC,
Sqrt = (int) CM::Command::CommandSQRT,
Percent = (int) CM::Command::CommandPERCENT,
Negate = (int) CM::Command::CommandSIGN,
Degrees = (int) CM::Command::CommandDegrees,
Pi = (int) CM::Command::CommandPI,
Sin = (int) CM::Command::CommandSIN,
Cos = (int) CM::Command::CommandCOS,
Tan = (int) CM::Command::CommandTAN,
Factorial = (int) CM::Command::CommandFAC,
XPower2 = (int) CM::Command::CommandSQR,
Mod = (int) CM::Command::CommandMOD,
FToE = (int) CM::Command::CommandFE,
LogBaseE = (int) CM::Command::CommandLN,
InvSin = (int) CM::Command::CommandASIN,
InvCos = (int) CM::Command::CommandACOS,
InvTan = (int) CM::Command::CommandATAN,
LogBase10 = (int) CM::Command::CommandLOG,
XPowerY = (int) CM::Command::CommandPWR,
YRootX = (int) CM::Command::CommandROOT,
TenPowerX = (int) CM::Command::CommandPOW10,
EPowerX = (int) CM::Command::CommandPOWE,
Exp = (int) CM::Command::CommandEXP,
DecButton = (int) CM::Command::CommandDec,
OctButton = (int) CM::Command::CommandOct,
HexButton = (int) CM::Command::CommandHex,
BinButton = (int) CM::Command::CommandBin,
And = (int) CM::Command::CommandAnd,
Ror = (int) CM::Command::CommandROR,
Rol = (int) CM::Command::CommandROL,
Or = (int) CM::Command::CommandOR,
Lsh = (int) CM::Command::CommandLSHF,
Rsh = (int) CM::Command::CommandRSHF,
Xor = (int) CM::Command::CommandXor,
Not = (int) CM::Command::CommandNot,
Sinh = (int) CM::Command::CommandSINH,
Cosh = (int) CM::Command::CommandCOSH,
Tanh = (int) CM::Command::CommandTANH,
InvSinh = (int) CM::Command::CommandASINH,
InvCosh = (int) CM::Command::CommandACOSH,
InvTanh = (int) CM::Command::CommandATANH,
Cube = (int) CM::Command::CommandCUB,
DMS = (int) CM::Command::CommandDMS,
Invert = (int)CM::Command::CommandREC,
Sqrt = (int)CM::Command::CommandSQRT,
Percent = (int)CM::Command::CommandPERCENT,
Negate = (int)CM::Command::CommandSIGN,
Degrees = (int)CM::Command::CommandDegrees,
Pi = (int)CM::Command::CommandPI,
Sin = (int)CM::Command::CommandSIN,
Cos = (int)CM::Command::CommandCOS,
Tan = (int)CM::Command::CommandTAN,
Factorial = (int)CM::Command::CommandFAC,
XPower2 = (int)CM::Command::CommandSQR,
Mod = (int)CM::Command::CommandMOD,
FToE = (int)CM::Command::CommandFE,
LogBaseE = (int)CM::Command::CommandLN,
InvSin = (int)CM::Command::CommandASIN,
InvCos = (int)CM::Command::CommandACOS,
InvTan = (int)CM::Command::CommandATAN,
LogBase10 = (int)CM::Command::CommandLOG,
XPowerY = (int)CM::Command::CommandPWR,
YRootX = (int)CM::Command::CommandROOT,
TenPowerX = (int)CM::Command::CommandPOW10,
EPowerX = (int)CM::Command::CommandPOWE,
Exp = (int)CM::Command::CommandEXP,
DecButton = (int)CM::Command::CommandDec,
OctButton = (int)CM::Command::CommandOct,
HexButton = (int)CM::Command::CommandHex,
BinButton = (int)CM::Command::CommandBin,
And = (int)CM::Command::CommandAnd,
Ror = (int)CM::Command::CommandROR,
Rol = (int)CM::Command::CommandROL,
Or = (int)CM::Command::CommandOR,
Lsh = (int)CM::Command::CommandLSHF,
Rsh = (int)CM::Command::CommandRSHF,
Xor = (int)CM::Command::CommandXor,
Not = (int)CM::Command::CommandNot,
Sinh = (int)CM::Command::CommandSINH,
Cosh = (int)CM::Command::CommandCOSH,
Tanh = (int)CM::Command::CommandTANH,
InvSinh = (int)CM::Command::CommandASINH,
InvCosh = (int)CM::Command::CommandACOSH,
InvTanh = (int)CM::Command::CommandATANH,
Cube = (int)CM::Command::CommandCUB,
DMS = (int)CM::Command::CommandDMS,
};
}

View file

@ -69,11 +69,12 @@ void CalculatorDisplay::SetIsInError(bool isError)
}
}
void CalculatorDisplay::SetExpressionDisplay(_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const &tokens, _Inout_ std::shared_ptr<CalculatorVector <std::shared_ptr<IExpressionCommand>>> const &commands)
void CalculatorDisplay::SetExpressionDisplay(_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const& tokens,
_Inout_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const& commands)
{
if (m_callbackReference != nullptr)
{
if(auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>())
if (auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>())
{
calcVM->SetExpressionDisplay(tokens, commands);
}

View file

@ -8,7 +8,7 @@
namespace CalculatorApp
{
// Callback interface to be implemented by the CalculatorManager
class CalculatorDisplay: public ICalcDisplay
class CalculatorDisplay : public ICalcDisplay
{
public:
CalculatorDisplay();
@ -18,7 +18,8 @@ namespace CalculatorApp
private:
void SetPrimaryDisplay(_In_ const std::wstring& displayString, _In_ bool isError) override;
void SetIsInError(bool isError) override;
void SetExpressionDisplay(_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const &tokens, _Inout_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const &commands) override;
void SetExpressionDisplay(_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const& tokens,
_Inout_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const& commands) override;
void SetMemorizedNumbers(_In_ const std::vector<std::wstring>& memorizedNumbers) override;
void OnHistoryItemAdded(_In_ unsigned int addedItemIndex) override;
void SetParenthesisNumber(_In_ unsigned int parenthesisCount) override;

View file

@ -8,19 +8,19 @@ using namespace CalculatorApp::Common;
using namespace concurrency;
using namespace std;
ConversionResultTaskHelper::ConversionResultTaskHelper(unsigned int delay, const function<void()> functionToRun) :
m_delay{ delay },
m_storedFunction{ functionToRun }
ConversionResultTaskHelper::ConversionResultTaskHelper(unsigned int delay, const function<void()> functionToRun)
: m_delay{ delay }, m_storedFunction{ functionToRun }
{
auto token = m_cts.get_token();
auto delayTask = CompleteAfter(delay);
delayTask.then([this, token]()
{
if (!token.is_canceled())
{
m_storedFunction();
}
}, task_continuation_context::use_current());
delayTask.then(
[this, token]() {
if (!token.is_canceled())
{
m_storedFunction();
}
},
task_continuation_context::use_current());
}
ConversionResultTaskHelper::~ConversionResultTaskHelper()

View file

@ -15,10 +15,7 @@ using namespace Windows::Foundation;
using namespace Windows::System;
using namespace Windows::ApplicationModel::DataTransfer;
String^ CopyPasteManager::supportedFormats[] =
{
StandardDataFormats::Text
};
String ^ CopyPasteManager::supportedFormats[] = { StandardDataFormats::Text };
static constexpr wstring_view c_validCharacterSet{ L"0123456789()+-*/.abcdefABCDEF" };
@ -40,43 +37,26 @@ static const wstring c_binProgrammerChars = L"[0-1]+((_|'|`)[0-1]+)*";
static const wstring c_uIntSuffixes = L"[uU]?[lL]{0,2}";
// RegEx Patterns used by various modes
static const array<wregex, 1> standardModePatterns =
{
wregex(c_wspc + c_signedDecFloat + c_wspc)
};
static const array<wregex, 2> scientificModePatterns =
{
wregex(L"(" + c_wspc + L"[-+]?)|(" + c_wspcLParenSigned + L")" + c_signedDecFloat + c_wspcRParens),
wregex(L"(" + c_wspc + L"[-+]?)|(" + c_wspcLParenSigned + L")" + c_signedDecFloat + L"[e]([+]|[-])+\\d+" + c_wspcRParens)
};
static const array<array<wregex, 5>, 4> programmerModePatterns =
{ {
// Hex numbers like 5F, 4A0C, 0xa9, 0xFFull, 47CDh
{
wregex(c_wspcLParens + L"(0[xX])?" + c_hexProgrammerChars + c_uIntSuffixes + c_wspcRParens),
wregex(c_wspcLParens + c_hexProgrammerChars + L"[hH]?" + c_wspcRParens)
},
// Decimal numbers like -145, 145, 0n145, 123ull etc
{
wregex(c_wspcLParens + L"[-+]?" + c_decProgrammerChars + L"[lL]{0,2}" +c_wspcRParens),
wregex(c_wspcLParens + L"(0[nN])?" + c_decProgrammerChars + c_uIntSuffixes + c_wspcRParens)
},
// Octal numbers like 06, 010, 0t77, 0o77, 077ull etc
{
wregex(c_wspcLParens + L"(0[otOT])?" + c_octProgrammerChars + c_uIntSuffixes + c_wspcRParens)
},
// Binary numbers like 011010110, 0010110, 10101001, 1001b, 0b1001, 0y1001, 0b1001ull
{
wregex(c_wspcLParens + L"(0[byBY])?" + c_binProgrammerChars + c_uIntSuffixes + c_wspcRParens),
wregex(c_wspcLParens + c_binProgrammerChars + L"[bB]?" + c_wspcRParens)
}
} };
static const array<wregex, 1> unitConverterPatterns =
{
wregex(c_wspc + L"[-+]?\\d*[.]?\\d*" + c_wspc)
static const array<wregex, 1> standardModePatterns = { wregex(c_wspc + c_signedDecFloat + c_wspc) };
static const array<wregex, 2> scientificModePatterns = { wregex(L"(" + c_wspc + L"[-+]?)|(" + c_wspcLParenSigned + L")" + c_signedDecFloat + c_wspcRParens),
wregex(L"(" + c_wspc + L"[-+]?)|(" + c_wspcLParenSigned + L")" + c_signedDecFloat
+ L"[e]([+]|[-])+\\d+" + c_wspcRParens) };
static const array<array<wregex, 5>, 4> programmerModePatterns = {
{ // Hex numbers like 5F, 4A0C, 0xa9, 0xFFull, 47CDh
{ wregex(c_wspcLParens + L"(0[xX])?" + c_hexProgrammerChars + c_uIntSuffixes + c_wspcRParens),
wregex(c_wspcLParens + c_hexProgrammerChars + L"[hH]?" + c_wspcRParens) },
// Decimal numbers like -145, 145, 0n145, 123ull etc
{ wregex(c_wspcLParens + L"[-+]?" + c_decProgrammerChars + L"[lL]{0,2}" + c_wspcRParens),
wregex(c_wspcLParens + L"(0[nN])?" + c_decProgrammerChars + c_uIntSuffixes + c_wspcRParens) },
// Octal numbers like 06, 010, 0t77, 0o77, 077ull etc
{ wregex(c_wspcLParens + L"(0[otOT])?" + c_octProgrammerChars + c_uIntSuffixes + c_wspcRParens) },
// Binary numbers like 011010110, 0010110, 10101001, 1001b, 0b1001, 0y1001, 0b1001ull
{ wregex(c_wspcLParens + L"(0[byBY])?" + c_binProgrammerChars + c_uIntSuffixes + c_wspcRParens),
wregex(c_wspcLParens + c_binProgrammerChars + L"[bB]?" + c_wspcRParens) } }
};
static const array<wregex, 1> unitConverterPatterns = { wregex(c_wspc + L"[-+]?\\d*[.]?\\d*" + c_wspc) };
void CopyPasteManager::CopyToClipboard(String^ stringToCopy)
void CopyPasteManager::CopyToClipboard(String ^ stringToCopy)
{
// Copy the string to the clipboard
auto dataPackage = ref new DataPackage();
@ -84,7 +64,7 @@ void CopyPasteManager::CopyToClipboard(String^ stringToCopy)
Clipboard::SetContent(dataPackage);
}
task<String^> CopyPasteManager::GetStringToPaste(ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, int bitLengthType)
task<String ^> CopyPasteManager::GetStringToPaste(ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, int bitLengthType)
{
// Retrieve the text in the clipboard
auto dataPackageView = Clipboard::GetContent();
@ -95,11 +75,9 @@ task<String^> CopyPasteManager::GetStringToPaste(ViewMode mode, CategoryGroupTyp
//-- add support to allow pasting for expressions like 1.3e12(as of now we allow 1.3e+12)
return create_task((dataPackageView->GetTextAsync(::StandardDataFormats::Text)))
.then([mode, modeType, programmerNumberBase, bitLengthType](String^ pastedText)
{
return ValidatePasteExpression(pastedText, mode, modeType, programmerNumberBase, bitLengthType);
}
, task_continuation_context::use_arbitrary());
.then([mode, modeType, programmerNumberBase,
bitLengthType](String ^ pastedText) { return ValidatePasteExpression(pastedText, mode, modeType, programmerNumberBase, bitLengthType); },
task_continuation_context::use_arbitrary());
}
int CopyPasteManager::ClipboardTextFormat()
@ -116,14 +94,14 @@ int CopyPasteManager::ClipboardTextFormat()
return -1;
}
String^ CopyPasteManager::ValidatePasteExpression(String^ pastedText, ViewMode mode, int programmerNumberBase, int bitLengthType)
String ^ CopyPasteManager::ValidatePasteExpression(String ^ pastedText, ViewMode mode, int programmerNumberBase, int bitLengthType)
{
return CopyPasteManager::ValidatePasteExpression(pastedText, mode, NavCategory::GetGroupType(mode), programmerNumberBase, bitLengthType);
}
// return "NoOp" if pastedText is invalid else return pastedText
String^ CopyPasteManager::ValidatePasteExpression(String^ pastedText, ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, int bitLengthType)
String ^ CopyPasteManager::ValidatePasteExpression(String ^ pastedText, ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, int bitLengthType)
{
if (pastedText->Length() > MaxPasteableLength)
{
@ -135,7 +113,7 @@ String^ CopyPasteManager::ValidatePasteExpression(String^ pastedText, ViewMode m
wstring pasteExpression = pastedText->Data();
// Get english translated expression
String^ englishString = LocalizationSettings::GetInstance().GetEnglishValueFromLocalizedDigits(pasteExpression);
String ^ englishString = LocalizationSettings::GetInstance().GetEnglishValueFromLocalizedDigits(pasteExpression);
// Removing the spaces, comma separator from the pasteExpression to allow pasting of expressions like 1 + 2+1,333
pasteExpression = RemoveUnwantedCharsFromWstring(englishString->Data());
@ -223,7 +201,8 @@ vector<wstring> CopyPasteManager::ExtractOperands(const wstring& pasteExpression
if ((pasteExpression.at(i) == L'+') || (pasteExpression.at(i) == L'-'))
{
// don't break the expression into operands if the encountered character corresponds to sign command(+-)
if (isPreviousOpenParen || startOfExpression || isPreviousOperator || ((mode != ViewMode::Programmer) && !((i != 0) && (pasteExpression.at(i - 1) != L'e'))))
if (isPreviousOpenParen || startOfExpression || isPreviousOperator
|| ((mode != ViewMode::Programmer) && !((i != 0) && (pasteExpression.at(i - 1) != L'e'))))
{
isPreviousOperator = false;
continue;
@ -267,7 +246,7 @@ bool CopyPasteManager::ExpressionRegExMatch(vector<wstring> operands, ViewMode m
}
vector<wregex> patterns{};
if (mode == ViewMode::Standard)
{
patterns.assign(standardModePatterns.begin(), standardModePatterns.end());
@ -339,7 +318,7 @@ pair<size_t, uint64_t> CopyPasteManager::GetMaxOperandLengthAndValue(ViewMode mo
{
constexpr size_t defaultMaxOperandLength = 0;
constexpr uint64_t defaultMaxValue = 0;
if (mode == ViewMode::Standard)
{
return make_pair(MaxStandardOperandLength, defaultMaxValue);
@ -452,26 +431,28 @@ bool CopyPasteManager::TryOperandToULL(const wstring& operand, int numberBase, u
}
size_t CopyPasteManager::OperandLength(const wstring& operand, ViewMode mode, CategoryGroupType modeType, int programmerNumberBase)
{
if (modeType == CategoryGroupType::Converter) {
{
if (modeType == CategoryGroupType::Converter)
{
return operand.length();
}
switch(mode) {
case ViewMode::Standard:
case ViewMode::Scientific:
return StandardScientificOperandLength(operand);
switch (mode)
{
case ViewMode::Standard:
case ViewMode::Scientific:
return StandardScientificOperandLength(operand);
case ViewMode::Programmer:
return ProgrammerOperandLength(operand, programmerNumberBase);
case ViewMode::Programmer:
return ProgrammerOperandLength(operand, programmerNumberBase);
default:
return 0;
default:
return 0;
}
}
size_t CopyPasteManager::StandardScientificOperandLength(const wstring& operand)
{
{
const bool hasDecimal = operand.find('.') != wstring::npos;
if (hasDecimal)
@ -494,7 +475,6 @@ size_t CopyPasteManager::StandardScientificOperandLength(const wstring& operand)
size_t CopyPasteManager::ProgrammerOperandLength(const wstring& operand, int numberBase)
{
vector<wstring> prefixes{};
vector<wstring> suffixes{};
switch (numberBase)
@ -515,7 +495,7 @@ size_t CopyPasteManager::ProgrammerOperandLength(const wstring& operand, int num
break;
default:
// No defined prefixes/suffixes
return 0;
return 0;
}
// UInt suffixes are common across all modes

View file

@ -25,8 +25,9 @@ namespace CalculatorApp
class CopyPasteManager
{
public:
static void CopyToClipboard(Platform::String^ stringToCopy);
static concurrency::task<Platform::String^> GetStringToPaste(CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, int programmerNumberBase = -1, int bitLengthType = -1);
static void CopyToClipboard(Platform::String ^ stringToCopy);
static concurrency::task<Platform::String ^> GetStringToPaste(CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType,
int programmerNumberBase = -1, int bitLengthType = -1);
static bool HasStringToPaste()
{
return ClipboardTextFormat() >= 0;
@ -36,25 +37,23 @@ namespace CalculatorApp
private:
static int ClipboardTextFormat();
static Platform::String^ ValidatePasteExpression(
Platform::String^ pastedText,
CalculatorApp::Common::ViewMode mode,
int programmerNumberBase,
int bitLengthType);
static Platform::String^ ValidatePasteExpression(
Platform::String^ pastedText,
CalculatorApp::Common::ViewMode mode,
CalculatorApp::Common::CategoryGroupType modeType,
int programmerNumberBase,
int bitLengthType);
static Platform::String
^ ValidatePasteExpression(Platform::String ^ pastedText, CalculatorApp::Common::ViewMode mode, int programmerNumberBase, int bitLengthType);
static Platform::String
^ ValidatePasteExpression(Platform::String ^ pastedText, CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType,
int programmerNumberBase, int bitLengthType);
static std::vector<std::wstring> ExtractOperands(const std::wstring& pasteExpression, CalculatorApp::Common::ViewMode mode, int programmerNumberBase = -1, int bitLengthType = -1);
static bool ExpressionRegExMatch(std::vector<std::wstring> operands, CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, int programmerNumberBase = -1, int bitLengthType = -1);
static std::vector<std::wstring> ExtractOperands(const std::wstring& pasteExpression, CalculatorApp::Common::ViewMode mode,
int programmerNumberBase = -1, int bitLengthType = -1);
static bool ExpressionRegExMatch(std::vector<std::wstring> operands, CalculatorApp::Common::ViewMode mode,
CalculatorApp::Common::CategoryGroupType modeType, int programmerNumberBase = -1, int bitLengthType = -1);
static std::pair<size_t, uint64_t> GetMaxOperandLengthAndValue(CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, int programmerNumberBase = -1, int bitLengthType = -1);
static std::pair<size_t, uint64_t> GetMaxOperandLengthAndValue(CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType,
int programmerNumberBase = -1, int bitLengthType = -1);
static std::wstring SanitizeOperand(const std::wstring& operand);
static bool TryOperandToULL(const std::wstring& operand, int numberBase, unsigned long long int& result);
static size_t OperandLength(const std::wstring& operand, CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, int programmerNumberBase = -1);
static size_t OperandLength(const std::wstring& operand, CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType,
int programmerNumberBase = -1);
static size_t StandardScientificOperandLength(const std::wstring& operand);
static size_t ProgrammerOperandLength(const std::wstring& operand, int numberBase);
static std::wstring RemoveUnwantedCharsFromWstring(const std::wstring& input);
@ -67,7 +66,7 @@ namespace CalculatorApp
static constexpr size_t MaxExponentLength = 4;
static constexpr size_t MaxProgrammerBitLength = 64;
static Platform::String^ supportedFormats[];
static Platform::String ^ supportedFormats[];
friend class CalculatorUnitTests::CopyPasteManagerTest;
};

View file

@ -9,7 +9,7 @@ using namespace Windows::Foundation;
using namespace Windows::Globalization;
using namespace CalculatorApp::Common::DateCalculation;
DateCalculationEngine::DateCalculationEngine(_In_ String^ calendarIdentifier)
DateCalculationEngine::DateCalculationEngine(_In_ String ^ calendarIdentifier)
{
m_calendar = ref new Calendar();
m_calendar->ChangeTimeZone("UTC");
@ -18,7 +18,7 @@ DateCalculationEngine::DateCalculationEngine(_In_ String^ calendarIdentifier)
// Adding Duration to a Date
// Returns: True if function succeeds to calculate the date else returns False
bool DateCalculationEngine::AddDuration(_In_ DateTime startDate, _In_ const DateDifference& duration, _Out_ DateTime *endDate)
bool DateCalculationEngine::AddDuration(_In_ DateTime startDate, _In_ const DateDifference& duration, _Out_ DateTime* endDate)
{
auto currentCalendarSystem = m_calendar->GetCalendarSystem();
@ -28,9 +28,10 @@ bool DateCalculationEngine::AddDuration(_In_ DateTime startDate, _In_ const Date
// The Japanese Era system can have multiple year partitions within the same year.
// For example, April 30, 2019 is denoted April 30, Heisei 31; May 1, 2019 is denoted as May 1, Reiwa 1.
// The Calendar treats Heisei 31 and Reiwa 1 as separate years, which results in some unexpected behaviors where subtracting a year from Reiwa 1 results in a date in Heisei 31.
// To provide the expected result across era boundaries, we first convert the Japanese era system to a Gregorian system, do date math, and then convert back to the Japanese era system.
// This works because the Japanese era system maintains the same year/month boundaries and durations as the Gregorian system and is only different in display value.
// The Calendar treats Heisei 31 and Reiwa 1 as separate years, which results in some unexpected behaviors where subtracting a year from Reiwa 1 results
// in a date in Heisei 31. To provide the expected result across era boundaries, we first convert the Japanese era system to a Gregorian system, do date
// math, and then convert back to the Japanese era system. This works because the Japanese era system maintains the same year/month boundaries and
// durations as the Gregorian system and is only different in display value.
if (currentCalendarSystem == CalendarIdentifiers::Japanese)
{
m_calendar->ChangeCalendarSystem(CalendarIdentifiers::Gregorian);
@ -51,7 +52,7 @@ bool DateCalculationEngine::AddDuration(_In_ DateTime startDate, _In_ const Date
*endDate = m_calendar->GetDateTime();
}
catch (Platform::InvalidArgumentException^ ex)
catch (Platform::InvalidArgumentException ^ ex)
{
// ensure that we revert to the correct calendar system
m_calendar->ChangeCalendarSystem(currentCalendarSystem);
@ -67,7 +68,7 @@ bool DateCalculationEngine::AddDuration(_In_ DateTime startDate, _In_ const Date
// Subtracting Duration from a Date
// Returns: True if function succeeds to calculate the date else returns False
bool DateCalculationEngine::SubtractDuration(_In_ DateTime startDate, _In_ const DateDifference& duration, _Out_ DateTime *endDate)
bool DateCalculationEngine::SubtractDuration(_In_ DateTime startDate, _In_ const DateDifference& duration, _Out_ DateTime* endDate)
{
auto currentCalendarSystem = m_calendar->GetCalendarSystem();
@ -79,9 +80,10 @@ bool DateCalculationEngine::SubtractDuration(_In_ DateTime startDate, _In_ const
// The Japanese Era system can have multiple year partitions within the same year.
// For example, April 30, 2019 is denoted April 30, Heisei 31; May 1, 2019 is denoted as May 1, Reiwa 1.
// The Calendar treats Heisei 31 and Reiwa 1 as separate years, which results in some unexpected behaviors where subtracting a year from Reiwa 1 results in a date in Heisei 31.
// To provide the expected result across era boundaries, we first convert the Japanese era system to a Gregorian system, do date math, and then convert back to the Japanese era system.
// This works because the Japanese era system maintains the same year/month boundaries and durations as the Gregorian system and is only different in display value.
// The Calendar treats Heisei 31 and Reiwa 1 as separate years, which results in some unexpected behaviors where subtracting a year from Reiwa 1 results
// in a date in Heisei 31. To provide the expected result across era boundaries, we first convert the Japanese era system to a Gregorian system, do date
// math, and then convert back to the Japanese era system. This works because the Japanese era system maintains the same year/month boundaries and
// durations as the Gregorian system and is only different in display value.
if (currentCalendarSystem == CalendarIdentifiers::Japanese)
{
m_calendar->ChangeCalendarSystem(CalendarIdentifiers::Gregorian);
@ -101,7 +103,7 @@ bool DateCalculationEngine::SubtractDuration(_In_ DateTime startDate, _In_ const
}
*endDate = m_calendar->GetDateTime();
}
catch (Platform::InvalidArgumentException^ ex)
catch (Platform::InvalidArgumentException ^ ex)
{
// ensure that we revert to the correct calendar system
m_calendar->ChangeCalendarSystem(currentCalendarSystem);
@ -117,7 +119,7 @@ bool DateCalculationEngine::SubtractDuration(_In_ DateTime startDate, _In_ const
}
// Calculate the difference between two dates
void DateCalculationEngine::GetDateDifference(_In_ DateTime date1, _In_ DateTime date2, _In_ DateUnit outputFormat, _Out_ DateDifference *difference)
void DateCalculationEngine::GetDateDifference(_In_ DateTime date1, _In_ DateTime date2, _In_ DateUnit outputFormat, _Out_ DateDifference* difference)
{
DateTime startDate;
DateTime endDate;
@ -149,8 +151,7 @@ void DateCalculationEngine::GetDateDifference(_In_ DateTime date1, _In_ DateTime
UINT approximateDaysInYear;
// If we're unable to calculate the days-in-month or days-in-year, we'll leave the values at 0.
if (TryGetCalendarDaysInMonth(startDate, daysInMonth)
&& TryGetCalendarDaysInYear(endDate, approximateDaysInYear))
if (TryGetCalendarDaysInMonth(startDate, daysInMonth) && TryGetCalendarDaysInYear(endDate, approximateDaysInYear))
{
UINT daysIn[c_unitsOfDate] = { approximateDaysInYear, daysInMonth, c_daysInWeek, 1 };
@ -172,7 +173,7 @@ void DateCalculationEngine::GetDateDifference(_In_ DateTime date1, _In_ DateTime
{
pivotDate = AdjustCalendarDate(pivotDate, dateUnit, static_cast<int>(differenceInDates[unitIndex]));
}
catch (Platform::InvalidArgumentException^)
catch (Platform::InvalidArgumentException ^)
{
// Operation failed due to out of bound result
// Do nothing
@ -208,7 +209,7 @@ void DateCalculationEngine::GetDateDifference(_In_ DateTime date1, _In_ DateTime
pivotDate = AdjustCalendarDate(pivotDate, dateUnit, 1);
differenceInDates[unitIndex] += 1;
}
catch (Platform::InvalidArgumentException^)
catch (Platform::InvalidArgumentException ^)
{
// handling for 31st Dec, 9999 last valid date
// Do nothing - break out
@ -233,7 +234,6 @@ void DateCalculationEngine::GetDateDifference(_In_ DateTime date1, _In_ DateTime
difference->day = differenceInDates[3];
}
// Private Methods
// Gets number of days between the two date time values
@ -311,9 +311,10 @@ DateTime DateCalculationEngine::AdjustCalendarDate(Windows::Foundation::DateTime
// The Japanese Era system can have multiple year partitions within the same year.
// For example, April 30, 2019 is denoted April 30, Heisei 31; May 1, 2019 is denoted as May 1, Reiwa 1.
// The Calendar treats Heisei 31 and Reiwa 1 as separate years, which results in some unexpected behaviors where subtracting a year from Reiwa 1 results in a date in Heisei 31.
// To provide the expected result across era boundaries, we first convert the Japanese era system to a Gregorian system, do date math, and then convert back to the Japanese era system.
// This works because the Japanese era system maintains the same year/month boundaries and durations as the Gregorian system and is only different in display value.
// The Calendar treats Heisei 31 and Reiwa 1 as separate years, which results in some unexpected behaviors where subtracting a year from Reiwa 1 results in
// a date in Heisei 31. To provide the expected result across era boundaries, we first convert the Japanese era system to a Gregorian system, do date math,
// and then convert back to the Japanese era system. This works because the Japanese era system maintains the same year/month boundaries and durations as
// the Gregorian system and is only different in display value.
auto currentCalendarSystem = m_calendar->GetCalendarSystem();
if (currentCalendarSystem == CalendarIdentifiers::Japanese)
{
@ -322,15 +323,15 @@ DateTime DateCalculationEngine::AdjustCalendarDate(Windows::Foundation::DateTime
switch (dateUnit)
{
case DateUnit::Year:
m_calendar->AddYears(difference);
break;
case DateUnit::Month:
m_calendar->AddMonths(difference);
break;
case DateUnit::Week:
m_calendar->AddWeeks(difference);
break;
case DateUnit::Year:
m_calendar->AddYears(difference);
break;
case DateUnit::Month:
m_calendar->AddMonths(difference);
break;
case DateUnit::Week:
m_calendar->AddWeeks(difference);
break;
}
m_calendar->ChangeCalendarSystem(currentCalendarSystem);

View file

@ -9,8 +9,8 @@ const uint64_t c_minute = 60 * c_second;
const uint64_t c_hour = 60 * c_minute;
const uint64_t c_day = 24 * c_hour;
const int c_unitsOfDate = 4; // Units Year,Month,Week,Day
const int c_unitsGreaterThanDays = 3; // Units Greater than Days (Year/Month/Week) 3
const int c_unitsOfDate = 4; // Units Year,Month,Week,Day
const int c_unitsGreaterThanDays = 3; // Units Greater than Days (Year/Month/Week) 3
const int c_daysInWeek = 7;
namespace CalculatorApp
@ -19,7 +19,8 @@ namespace CalculatorApp
{
namespace DateCalculation
{
public enum class _Enum_is_bitflag_ DateUnit
public
enum class _Enum_is_bitflag_ DateUnit
{
Year = 0x01,
Month = 0x02,
@ -40,16 +41,19 @@ namespace CalculatorApp
{
public:
// Constructor
DateCalculationEngine(_In_ Platform::String^ calendarIdentifier);
DateCalculationEngine(_In_ Platform::String ^ calendarIdentifier);
// Public Methods
bool __nothrow AddDuration(_In_ Windows::Foundation::DateTime startDate, _In_ const DateDifference& duration, _Out_ Windows::Foundation::DateTime *endDate);
bool __nothrow SubtractDuration(_In_ Windows::Foundation::DateTime startDate, _In_ const DateDifference& duration, _Out_ Windows::Foundation::DateTime *endDate);
void __nothrow GetDateDifference(_In_ Windows::Foundation::DateTime date1, _In_ Windows::Foundation::DateTime date2, _In_ DateUnit outputFormat, _Out_ DateDifference *difference);
bool __nothrow AddDuration(_In_ Windows::Foundation::DateTime startDate, _In_ const DateDifference& duration,
_Out_ Windows::Foundation::DateTime* endDate);
bool __nothrow SubtractDuration(_In_ Windows::Foundation::DateTime startDate, _In_ const DateDifference& duration,
_Out_ Windows::Foundation::DateTime* endDate);
void __nothrow GetDateDifference(_In_ Windows::Foundation::DateTime date1, _In_ Windows::Foundation::DateTime date2, _In_ DateUnit outputFormat,
_Out_ DateDifference* difference);
private:
// Private Variables
Windows::Globalization::Calendar^ m_calendar;
Windows::Globalization::Calendar ^ m_calendar;
// Private Methods
int GetDifferenceInDays(Windows::Foundation::DateTime date1, Windows::Foundation::DateTime date2);

View file

@ -8,33 +8,31 @@ namespace CalculatorApp
namespace Common
{
template <typename TTarget>
ref class DelegateCommand: public Windows::UI::Xaml::Input::ICommand
ref class DelegateCommand : public Windows::UI::Xaml::Input::ICommand
{
internal:
internal :
typedef void (TTarget::*CommandHandlerFunc)(Platform::Object^);
typedef void (TTarget::*CommandHandlerFunc)(Platform::Object ^);
DelegateCommand(TTarget^ target, CommandHandlerFunc func):
m_weakTarget(target),
m_function(func)
{ }
DelegateCommand(TTarget ^ target, CommandHandlerFunc func) : m_weakTarget(target), m_function(func)
{
}
private:
// Explicit, and private, implementation of ICommand, this way of programming makes it so
// the ICommand methods will only be available if the ICommand interface is requested via a dynamic_cast
// The ICommand interface is meant to be consumed by Xaml and not by the app, this is a defensive measure against
// code in the app calling Execute.
virtual void ExecuteImpl(Platform::Object^ parameter) sealed = Windows::UI::Xaml::Input::ICommand::Execute
virtual void ExecuteImpl(Platform::Object ^ parameter) sealed = Windows::UI::Xaml::Input::ICommand::Execute
{
TTarget^ target = m_weakTarget.Resolve<TTarget>();
TTarget ^ target = m_weakTarget.Resolve<TTarget>();
if (target)
{
(target->*m_function)(parameter);
}
}
virtual bool CanExecuteImpl(Platform::Object^ parameter) sealed = Windows::UI::Xaml::Input::ICommand::CanExecute
virtual bool CanExecuteImpl(Platform::Object ^ parameter) sealed = Windows::UI::Xaml::Input::ICommand::CanExecute
{
return true;
}
@ -57,14 +55,12 @@ namespace CalculatorApp
CommandHandlerFunc m_function;
Platform::WeakReference m_weakTarget;
};
template <typename TTarget, typename TFuncPtr>
DelegateCommand<TTarget>^ MakeDelegate(TTarget^ target, TFuncPtr&& function)
{
return ref new DelegateCommand<TTarget>(target, std::forward<TFuncPtr>(function));
}
DelegateCommand<TTarget> ^ MakeDelegate(TTarget ^ target, TFuncPtr&& function) {
return ref new DelegateCommand<TTarget>(target, std::forward<TFuncPtr>(function));
}
}
}

View file

@ -7,30 +7,35 @@
namespace CalculatorApp::Common
{
public enum class TokenType
public
enum class TokenType
{
Operator,
Operand,
Separator
};
[Windows::UI::Xaml::Data::Bindable]
public ref class DisplayExpressionToken sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
[Windows::UI::Xaml::Data::Bindable] public ref class DisplayExpressionToken sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
{
internal:
DisplayExpressionToken(Platform::String^ token, int tokenPosition, bool fEditable, TokenType type) :
m_Token(token), m_TokenPosition(tokenPosition), m_IsTokenEditable(fEditable), m_Type(type), m_OriginalToken(token), m_InEditMode(false)
{}
internal : DisplayExpressionToken(Platform::String ^ token, int tokenPosition, bool fEditable, TokenType type)
: m_Token(token), m_TokenPosition(tokenPosition), m_IsTokenEditable(fEditable), m_Type(type), m_OriginalToken(token), m_InEditMode(false)
{
}
public:
OBSERVABLE_OBJECT();
OBSERVABLE_PROPERTY_RW(Platform::String^, Token);
OBSERVABLE_PROPERTY_RW(Platform::String ^, Token);
OBSERVABLE_PROPERTY_RW(int, TokenPosition);
OBSERVABLE_PROPERTY_RW(bool, IsTokenEditable);
OBSERVABLE_PROPERTY_RW(int, CommandIndex);
OBSERVABLE_PROPERTY_R(Platform::String^, OriginalToken);
OBSERVABLE_PROPERTY_R(Platform::String ^, OriginalToken);
property bool IsTokenInEditMode {
bool get() { return m_InEditMode; }
property bool IsTokenInEditMode
{
bool get()
{
return m_InEditMode;
}
void set(bool val)
{
if (!val)
@ -40,8 +45,8 @@ namespace CalculatorApp::Common
m_InEditMode = val;
}
}
internal:
OBSERVABLE_PROPERTY_RW(TokenType, Type);
internal : OBSERVABLE_PROPERTY_RW(TokenType, Type);
private:
bool m_InEditMode;
};

View file

@ -44,7 +44,7 @@ namespace CalculatorApp
}
StringReference idRef(id.c_str());
String^ str = m_resLoader->GetString(idRef);
String ^ str = m_resLoader->GetString(idRef);
return str->Begin();
}
}

View file

@ -14,6 +14,6 @@ namespace CalculatorApp
virtual std::wstring GetCEngineString(const std::wstring& id) override;
private:
Windows::ApplicationModel::Resources::ResourceLoader^ m_resLoader;
Windows::ApplicationModel::Resources::ResourceLoader ^ m_resLoader;
};
}

View file

@ -7,7 +7,9 @@
using namespace CalculatorApp::Common;
using namespace Windows::Storage::Streams;
CommandDeserializer::CommandDeserializer(_In_ DataReader^ dataReader) :m_dataReader(dataReader){}
CommandDeserializer::CommandDeserializer(_In_ DataReader ^ dataReader) : m_dataReader(dataReader)
{
}
std::shared_ptr<IExpressionCommand> CommandDeserializer::Deserialize(_In_ CalculationManager::CommandType cmdType)
{
@ -20,7 +22,7 @@ std::shared_ptr<IExpressionCommand> CommandDeserializer::Deserialize(_In_ Calcul
case CalculationManager::CommandType::Parentheses:
return std::make_shared<CParentheses>(DeserializeParentheses());
return std::make_shared<CParentheses>(DeserializeParentheses());
break;
case CalculationManager::CommandType::UnaryCommand:

View file

@ -12,11 +12,11 @@ namespace CalculatorApp
class CommandDeserializer
{
public:
CommandDeserializer(_In_ Windows::Storage::Streams::DataReader^ dataReader);
CommandDeserializer(_In_ Windows::Storage::Streams::DataReader ^ dataReader);
std::shared_ptr<IExpressionCommand> Deserialize(_In_ CalculationManager::CommandType cmdType);
private:
Windows::Storage::Streams::DataReader^ m_dataReader;
Windows::Storage::Streams::DataReader ^ m_dataReader;
COpndCommand DeserializeOperand();
CParentheses DeserializeParentheses();
CUnaryCommand DeserializeUnary();

View file

@ -7,11 +7,11 @@
using namespace CalculatorApp::Common;
using namespace Windows::Storage::Streams;
SerializeCommandVisitor::SerializeCommandVisitor(_In_ DataWriter^ dataWriter) :m_dataWriter(dataWriter)
SerializeCommandVisitor::SerializeCommandVisitor(_In_ DataWriter ^ dataWriter) : m_dataWriter(dataWriter)
{
}
void SerializeCommandVisitor::Visit(_In_ COpndCommand &opndCmd)
void SerializeCommandVisitor::Visit(_In_ COpndCommand& opndCmd)
{
m_dataWriter->WriteBoolean(opndCmd.IsNegative());
m_dataWriter->WriteBoolean(opndCmd.IsDecimalPresent());
@ -29,7 +29,7 @@ void SerializeCommandVisitor::Visit(_In_ COpndCommand &opndCmd)
}
}
void SerializeCommandVisitor::Visit(_In_ CUnaryCommand &unaryCmd)
void SerializeCommandVisitor::Visit(_In_ CUnaryCommand& unaryCmd)
{
auto cmds = unaryCmd.GetCommands();
unsigned int cmdSize;
@ -43,13 +43,13 @@ void SerializeCommandVisitor::Visit(_In_ CUnaryCommand &unaryCmd)
}
}
void SerializeCommandVisitor::Visit(_In_ CBinaryCommand &binaryCmd)
void SerializeCommandVisitor::Visit(_In_ CBinaryCommand& binaryCmd)
{
int cmd = binaryCmd.GetCommand();
m_dataWriter->WriteInt32(cmd);
}
void SerializeCommandVisitor::Visit(_In_ CParentheses &paraCmd)
void SerializeCommandVisitor::Visit(_In_ CParentheses& paraCmd)
{
int parenthesisCmd = paraCmd.GetCommand();
m_dataWriter->WriteInt32(parenthesisCmd);

View file

@ -12,15 +12,15 @@ namespace CalculatorApp
class SerializeCommandVisitor : public ISerializeCommandVisitor
{
public:
SerializeCommandVisitor(_In_ Windows::Storage::Streams::DataWriter^ dataWriter);
SerializeCommandVisitor(_In_ Windows::Storage::Streams::DataWriter ^ dataWriter);
void Visit(_In_ COpndCommand &opndCmd);
void Visit(_In_ CUnaryCommand &unaryCmd);
void Visit(_In_ CBinaryCommand &binaryCmd);
void Visit(_In_ CParentheses &paraCmd);
void Visit(_In_ COpndCommand& opndCmd);
void Visit(_In_ CUnaryCommand& unaryCmd);
void Visit(_In_ CBinaryCommand& binaryCmd);
void Visit(_In_ CParentheses& paraCmd);
private:
Windows::Storage::Streams::DataWriter^ m_dataWriter;
Windows::Storage::Streams::DataWriter ^ m_dataWriter;
};
}
}

View file

@ -70,11 +70,11 @@ namespace CalculatorApp
}
}
void LightUpButton(ButtonBase^ button)
void LightUpButton(ButtonBase ^ button)
{
// If the button is a toggle button then we don't need
// to change the UI of the button
if (dynamic_cast<ToggleButton^>(button))
if (dynamic_cast<ToggleButton ^>(button))
{
return;
}
@ -83,7 +83,7 @@ namespace CalculatorApp
VisualStateManager::GoToState(button, "Pressed", true);
// This timer will fire after lightUpTime and make the button
// go back to the normal state.
// go back to the normal state.
// This timer will only fire once after which it will be destroyed
auto timer = ref new DispatcherTimer();
TimeSpan lightUpTime{};
@ -92,22 +92,20 @@ namespace CalculatorApp
WeakReference timerWeakReference(timer);
WeakReference buttonWeakReference(button);
timer->Tick += ref new EventHandler<Object^>(
[buttonWeakReference, timerWeakReference](Object^, Object^)
timer->Tick += ref new EventHandler<Object ^>([buttonWeakReference, timerWeakReference](Object ^, Object ^) {
auto button = buttonWeakReference.Resolve<ButtonBase>();
if (button)
{
auto button = buttonWeakReference.Resolve<ButtonBase>();
if (button)
{
VisualStateManager::GoToState(button, "Normal", true);
}
VisualStateManager::GoToState(button, "Normal", true);
}
// Cancel the timer after we're done so it only fires once
auto timer = timerWeakReference.Resolve<DispatcherTimer>();
if (timer)
{
timer->Stop();
}
});
// Cancel the timer after we're done so it only fires once
auto timer = timerWeakReference.Resolve<DispatcherTimer>();
if (timer)
{
timer->Stop();
}
});
timer->Start();
}
@ -130,7 +128,7 @@ namespace CalculatorApp
}
}
void RunButtonCommand(ButtonBase^ button)
void RunButtonCommand(ButtonBase ^ button)
{
if (button->IsEnabled)
{
@ -141,14 +139,14 @@ namespace CalculatorApp
command->Execute(parameter);
}
auto radio = dynamic_cast<RadioButton^>(button);
auto radio = dynamic_cast<RadioButton ^>(button);
if (radio)
{
radio->IsChecked = true;
return;
}
auto toggle = dynamic_cast<ToggleButton^>(button);
auto toggle = dynamic_cast<ToggleButton ^>(button);
if (toggle)
{
toggle->IsChecked = !toggle->IsChecked->Value;
@ -163,7 +161,7 @@ static multimap<int, bool> s_ignoreNextEscape;
static multimap<int, bool> s_keepIgnoringEscape;
static multimap<int, bool> s_fHonorShortcuts;
static multimap<int, bool> s_fHandledEnter;
static multimap<int, Flyout^> s_AboutFlyout;
static multimap<int, Flyout ^> s_AboutFlyout;
void KeyboardShortcutManager::IgnoreEscape(bool onlyOnce)
{
@ -205,15 +203,12 @@ void KeyboardShortcutManager::HonorEscape()
}
}
void KeyboardShortcutManager::OnCharacterPropertyChanged(
DependencyObject^ target,
String^ oldValue,
String^ newValue)
void KeyboardShortcutManager::OnCharacterPropertyChanged(DependencyObject ^ target, String ^ oldValue, String ^ newValue)
{
// Writer lock for the static maps
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
auto button = safe_cast<ButtonBase^>(target);
auto button = safe_cast<ButtonBase ^>(target);
int viewId = Utils::GetWindowId();
auto iterViewMap = s_CharacterForButtons.find(viewId);
@ -254,15 +249,12 @@ void KeyboardShortcutManager::OnCharacterPropertyChanged(
}
}
void KeyboardShortcutManager::OnVirtualKeyPropertyChanged(
DependencyObject^ target,
MyVirtualKey /*oldValue*/,
MyVirtualKey newValue)
void KeyboardShortcutManager::OnVirtualKeyPropertyChanged(DependencyObject ^ target, MyVirtualKey /*oldValue*/, MyVirtualKey newValue)
{
// Writer lock for the static maps
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
auto button = static_cast<ButtonBase^>(target);
auto button = static_cast<ButtonBase ^>(target);
int viewId = Utils::GetWindowId();
auto iterViewMap = s_VirtualKeysForButtons.find(viewId);
@ -280,20 +272,17 @@ void KeyboardShortcutManager::OnVirtualKeyPropertyChanged(
}
}
void KeyboardShortcutManager::OnVirtualKeyControlChordPropertyChanged(
DependencyObject^ target,
MyVirtualKey /*oldValue*/,
MyVirtualKey newValue)
void KeyboardShortcutManager::OnVirtualKeyControlChordPropertyChanged(DependencyObject ^ target, MyVirtualKey /*oldValue*/, MyVirtualKey newValue)
{
// Writer lock for the static maps
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
Control^ control = dynamic_cast<ButtonBase^>(target);
Control ^ control = dynamic_cast<ButtonBase ^>(target);
if (control == nullptr)
{
// Handling Ctrl+E shortcut for Date Calc, target would be NavigationView^ in that case
control = safe_cast<MUXC::NavigationView^>(target);
control = safe_cast<MUXC::NavigationView ^>(target);
}
int viewId = Utils::GetWindowId();
@ -312,15 +301,12 @@ void KeyboardShortcutManager::OnVirtualKeyControlChordPropertyChanged(
}
}
void KeyboardShortcutManager::OnVirtualKeyShiftChordPropertyChanged(
DependencyObject^ target,
MyVirtualKey /*oldValue*/,
MyVirtualKey newValue)
void KeyboardShortcutManager::OnVirtualKeyShiftChordPropertyChanged(DependencyObject ^ target, MyVirtualKey /*oldValue*/, MyVirtualKey newValue)
{
// Writer lock for the static maps
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
auto button = safe_cast<ButtonBase^>(target);
auto button = safe_cast<ButtonBase ^>(target);
int viewId = Utils::GetWindowId();
auto iterViewMap = s_VirtualKeyShiftChordsForButtons.find(viewId);
@ -338,15 +324,12 @@ void KeyboardShortcutManager::OnVirtualKeyShiftChordPropertyChanged(
}
}
void KeyboardShortcutManager::OnVirtualKeyAltChordPropertyChanged(
DependencyObject^ target,
MyVirtualKey /*oldValue*/,
MyVirtualKey newValue)
void KeyboardShortcutManager::OnVirtualKeyAltChordPropertyChanged(DependencyObject ^ target, MyVirtualKey /*oldValue*/, MyVirtualKey newValue)
{
// Writer lock for the static maps
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
MUXC::NavigationView^ navView = safe_cast<MUXC::NavigationView^>(target);
MUXC::NavigationView ^ navView = safe_cast<MUXC::NavigationView ^>(target);
int viewId = Utils::GetWindowId();
auto iterViewMap = s_VirtualKeyAltChordsForButtons.find(viewId);
@ -364,15 +347,12 @@ void KeyboardShortcutManager::OnVirtualKeyAltChordPropertyChanged(
}
}
void KeyboardShortcutManager::OnVirtualKeyControlShiftChordPropertyChanged(
DependencyObject^ target,
MyVirtualKey /*oldValue*/,
MyVirtualKey newValue)
void KeyboardShortcutManager::OnVirtualKeyControlShiftChordPropertyChanged(DependencyObject ^ target, MyVirtualKey /*oldValue*/, MyVirtualKey newValue)
{
// Writer lock for the static maps
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
auto button = safe_cast<ButtonBase^>(target);
auto button = safe_cast<ButtonBase ^>(target);
int viewId = Utils::GetWindowId();
auto iterViewMap = s_VirtualKeyControlShiftChordsForButtons.find(viewId);
@ -390,15 +370,12 @@ void KeyboardShortcutManager::OnVirtualKeyControlShiftChordPropertyChanged(
}
}
void KeyboardShortcutManager::OnVirtualKeyInverseChordPropertyChanged(
DependencyObject^ target,
MyVirtualKey /*oldValue*/,
MyVirtualKey newValue)
void KeyboardShortcutManager::OnVirtualKeyInverseChordPropertyChanged(DependencyObject ^ target, MyVirtualKey /*oldValue*/, MyVirtualKey newValue)
{
// Writer lock for the static maps
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
auto button = safe_cast<ButtonBase^>(target);
auto button = safe_cast<ButtonBase ^>(target);
int viewId = Utils::GetWindowId();
auto iterViewMap = s_VirtualKeyInverseChordsForButtons.find(viewId);
@ -416,15 +393,12 @@ void KeyboardShortcutManager::OnVirtualKeyInverseChordPropertyChanged(
}
}
void KeyboardShortcutManager::OnVirtualKeyControlInverseChordPropertyChanged(
DependencyObject^ target,
MyVirtualKey /*oldValue*/,
MyVirtualKey newValue)
void KeyboardShortcutManager::OnVirtualKeyControlInverseChordPropertyChanged(DependencyObject ^ target, MyVirtualKey /*oldValue*/, MyVirtualKey newValue)
{
// Writer lock for the static maps
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
auto button = safe_cast<ButtonBase^>(target);
auto button = safe_cast<ButtonBase ^>(target);
int viewId = Utils::GetWindowId();
auto iterViewMap = s_VirtualKeyControlInverseChordsForButtons.find(viewId);
@ -445,7 +419,7 @@ void KeyboardShortcutManager::OnVirtualKeyControlInverseChordPropertyChanged(
// In the three event handlers below we will not mark the event as handled
// because this is a supplemental operation and we don't want to interfere with
// the normal keyboard handling.
void KeyboardShortcutManager::OnCharacterReceivedHandler(CoreWindow^ sender, CharacterReceivedEventArgs^ args)
void KeyboardShortcutManager::OnCharacterReceivedHandler(CoreWindow ^ sender, CharacterReceivedEventArgs ^ args)
{
int viewId = Utils::GetWindowId();
auto currentHonorShortcuts = s_fHonorShortcuts.find(viewId);
@ -472,7 +446,8 @@ const std::multimap<MyVirtualKey, WeakReference>& GetCurrentKeyDictionary(MyVirt
{
return s_VirtualKeyAltChordsForButtons.find(viewId)->second;
}
else if ((s_ShiftKeyPressed.find(viewId)->second) && ((Window::Current->CoreWindow->GetKeyState(VirtualKey::Control) & CoreVirtualKeyStates::Down) == CoreVirtualKeyStates::Down))
else if ((s_ShiftKeyPressed.find(viewId)->second)
&& ((Window::Current->CoreWindow->GetKeyState(VirtualKey::Control) & CoreVirtualKeyStates::Down) == CoreVirtualKeyStates::Down))
{
return s_VirtualKeyControlShiftChordsForButtons.find(viewId)->second;
}
@ -521,7 +496,7 @@ const std::multimap<MyVirtualKey, WeakReference>& GetCurrentKeyDictionary(MyVirt
}
}
void KeyboardShortcutManager::OnKeyDownHandler(CoreWindow^ sender, KeyEventArgs^ args)
void KeyboardShortcutManager::OnKeyDownHandler(CoreWindow ^ sender, KeyEventArgs ^ args)
{
// If keyboard shortcuts like Ctrl+C or Ctrl+V are not handled
if (!args->Handled)
@ -536,25 +511,23 @@ void KeyboardShortcutManager::OnKeyDownHandler(CoreWindow^ sender, KeyEventArgs^
bool isShiftKeyPressed = (currentShiftKeyPressed != s_ShiftKeyPressed.end()) && (currentShiftKeyPressed->second);
// Handle Ctrl + E for DateCalculator
if ((key == VirtualKey::E) &&
isControlKeyPressed &&
!isShiftKeyPressed)
if ((key == VirtualKey::E) && isControlKeyPressed && !isShiftKeyPressed)
{
const auto& lookupMap = GetCurrentKeyDictionary(static_cast<MyVirtualKey>(key));
auto buttons = lookupMap.equal_range(static_cast<MyVirtualKey>(key));
auto navView = buttons.first->second.Resolve<MUXC::NavigationView>();
auto appViewModel = safe_cast<ApplicationViewModel^>(navView->DataContext);
auto appViewModel = safe_cast<ApplicationViewModel ^>(navView->DataContext);
appViewModel->Mode = ViewMode::Date;
auto categoryName = AppResourceProvider::GetInstance().GetResourceString(L"DateCalculationModeText");
appViewModel->CategoryName = categoryName;
auto menuItems = static_cast<IObservableVector<Object^>^>(navView->MenuItemsSource);
auto menuItems = static_cast<IObservableVector<Object ^> ^>(navView->MenuItemsSource);
auto flatIndex = NavCategory::GetFlatIndex(ViewMode::Date);
navView->SelectedItem = menuItems->GetAt(flatIndex);
return;
}
auto currentHonorShortcuts = s_fHonorShortcuts.find(viewId);
auto currentHonorShortcuts = s_fHonorShortcuts.find(viewId);
auto currentIgnoreNextEscape = s_ignoreNextEscape.find(viewId);
@ -615,9 +588,9 @@ void KeyboardShortcutManager::OnKeyDownHandler(CoreWindow^ sender, KeyEventArgs^
{
RunFirstEnabledButtonCommand(buttons);
// Ctrl+C and Ctrl+V shifts focus to some button because of which enter doesn't work after copy/paste. So don't shift focus if Ctrl+C or Ctrl+V is pressed.
// When drop down is open, pressing escape shifts focus to clear button. So dont's shift focus if drop down is open.
// Ctrl+Insert is equivalent to Ctrl+C and Shift+Insert is equivalent to Ctrl+V
// Ctrl+C and Ctrl+V shifts focus to some button because of which enter doesn't work after copy/paste. So don't shift focus if Ctrl+C or Ctrl+V
// is pressed. When drop down is open, pressing escape shifts focus to clear button. So dont's shift focus if drop down is open. Ctrl+Insert is
// equivalent to Ctrl+C and Shift+Insert is equivalent to Ctrl+V
if (currentIsDropDownOpen != s_IsDropDownOpen.end() && !currentIsDropDownOpen->second)
{
// Do not Light Up Buttons when Ctrl+C, Ctrl+V, Ctrl+Insert or Shift+Insert is pressed
@ -632,7 +605,7 @@ void KeyboardShortcutManager::OnKeyDownHandler(CoreWindow^ sender, KeyEventArgs^
}
}
void KeyboardShortcutManager::OnKeyUpHandler(CoreWindow^ sender, KeyEventArgs^ args)
void KeyboardShortcutManager::OnKeyUpHandler(CoreWindow ^ sender, KeyEventArgs ^ args)
{
int viewId = Utils::GetWindowId();
auto key = args->VirtualKey;
@ -665,7 +638,7 @@ void KeyboardShortcutManager::OnKeyUpHandler(CoreWindow^ sender, KeyEventArgs^ a
}
}
void KeyboardShortcutManager::OnAcceleratorKeyActivated(CoreDispatcher^, AcceleratorKeyEventArgs^ args)
void KeyboardShortcutManager::OnAcceleratorKeyActivated(CoreDispatcher ^, AcceleratorKeyEventArgs ^ args)
{
if (args->KeyStatus.IsKeyReleased)
{
@ -685,12 +658,12 @@ void KeyboardShortcutManager::OnAcceleratorKeyActivated(CoreDispatcher^, Acceler
auto item = listIterator->second.Resolve<MUXC::NavigationView>();
if (item != nullptr)
{
auto navView = safe_cast<MUXC::NavigationView^> (item);
auto navView = safe_cast<MUXC::NavigationView ^>(item);
auto menuItems = static_cast<IObservableVector<Object^>^>(navView->MenuItemsSource);
auto menuItems = static_cast<IObservableVector<Object ^> ^>(navView->MenuItemsSource);
if (menuItems != nullptr)
{
auto vm = safe_cast<ApplicationViewModel^>(navView->DataContext);
auto vm = safe_cast<ApplicationViewModel ^>(navView->DataContext);
if (nullptr != vm)
{
ViewMode toMode = NavCategory::GetViewModeForVirtualKey(static_cast<MyVirtualKey>(key));
@ -722,13 +695,11 @@ void KeyboardShortcutManager::Initialize()
{
auto coreWindow = Window::Current->CoreWindow;
coreWindow->CharacterReceived +=
ref new TypedEventHandler<CoreWindow^, CharacterReceivedEventArgs^>(&KeyboardShortcutManager::OnCharacterReceivedHandler);
coreWindow->KeyDown +=
ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(&KeyboardShortcutManager::OnKeyDownHandler);
coreWindow->KeyUp +=
ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(&KeyboardShortcutManager::OnKeyUpHandler);
ref new TypedEventHandler<CoreWindow ^, CharacterReceivedEventArgs ^>(&KeyboardShortcutManager::OnCharacterReceivedHandler);
coreWindow->KeyDown += ref new TypedEventHandler<CoreWindow ^, KeyEventArgs ^>(&KeyboardShortcutManager::OnKeyDownHandler);
coreWindow->KeyUp += ref new TypedEventHandler<CoreWindow ^, KeyEventArgs ^>(&KeyboardShortcutManager::OnKeyUpHandler);
coreWindow->Dispatcher->AcceleratorKeyActivated +=
ref new TypedEventHandler<CoreDispatcher^, AcceleratorKeyEventArgs^>(&KeyboardShortcutManager::OnAcceleratorKeyActivated);
ref new TypedEventHandler<CoreDispatcher ^, AcceleratorKeyEventArgs ^>(&KeyboardShortcutManager::OnAcceleratorKeyActivated);
KeyboardShortcutManager::RegisterNewAppViewId();
}
@ -755,7 +726,7 @@ void KeyboardShortcutManager::UpdateDropDownState(bool isOpen)
}
}
void KeyboardShortcutManager::UpdateDropDownState(Flyout^ aboutPageFlyout)
void KeyboardShortcutManager::UpdateDropDownState(Flyout ^ aboutPageFlyout)
{
int viewId = Utils::GetWindowId();

View file

@ -10,14 +10,17 @@ namespace CalculatorApp
{
namespace Common
{
public ref class KeyboardShortcutManager sealed
public
ref class KeyboardShortcutManager sealed
{
public:
KeyboardShortcutManager() {}
KeyboardShortcutManager()
{
}
DEPENDENCY_PROPERTY_OWNER(KeyboardShortcutManager);
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(Platform::String^, Character);
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(Platform::String ^, Character);
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(MyVirtualKey, VirtualKey);
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(MyVirtualKey, VirtualKeyControlChord);
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(MyVirtualKey, VirtualKeyShiftChord);
@ -26,9 +29,10 @@ namespace CalculatorApp
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(MyVirtualKey, VirtualKeyInverseChord);
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(MyVirtualKey, VirtualKeyControlInverseChord);
internal:
internal :
static void Initialize();
static void
Initialize();
// Sometimes, like with popups, escape is treated as special and even
// though it is handled we get it passed through to us. In those cases
@ -42,57 +46,34 @@ namespace CalculatorApp
static void HandledEnter(bool ishandled);
static void UpdateDropDownState(bool);
static void ShiftButtonChecked(bool checked);
static void UpdateDropDownState(Windows::UI::Xaml::Controls::Flyout^ aboutPageFlyout);
static void UpdateDropDownState(Windows::UI::Xaml::Controls::Flyout ^ aboutPageFlyout);
static void RegisterNewAppViewId();
static void OnWindowClosed(int viewId);
private:
static void OnCharacterPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, Platform::String ^ oldValue, Platform::String ^ newValue);
static void OnCharacterPropertyChanged(
Windows::UI::Xaml::DependencyObject^ target,
Platform::String^ oldValue,
Platform::String^ newValue);
static void OnVirtualKeyPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, MyVirtualKey oldValue, MyVirtualKey newValue);
static void OnVirtualKeyPropertyChanged(
Windows::UI::Xaml::DependencyObject^ target,
MyVirtualKey oldValue,
MyVirtualKey newValue);
static void OnVirtualKeyControlChordPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, MyVirtualKey oldValue, MyVirtualKey newValue);
static void OnVirtualKeyControlChordPropertyChanged(
Windows::UI::Xaml::DependencyObject^ target,
MyVirtualKey oldValue,
MyVirtualKey newValue);
static void OnVirtualKeyShiftChordPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, MyVirtualKey oldValue, MyVirtualKey newValue);
static void OnVirtualKeyShiftChordPropertyChanged(
Windows::UI::Xaml::DependencyObject^ target,
MyVirtualKey oldValue,
MyVirtualKey newValue);
static void OnVirtualKeyInverseChordPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, MyVirtualKey oldValue, MyVirtualKey newValue);
static void OnVirtualKeyInverseChordPropertyChanged(
Windows::UI::Xaml::DependencyObject^ target,
MyVirtualKey oldValue,
MyVirtualKey newValue);
static void OnVirtualKeyControlInverseChordPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, MyVirtualKey oldValue,
MyVirtualKey newValue);
static void OnVirtualKeyControlInverseChordPropertyChanged(
Windows::UI::Xaml::DependencyObject^ target,
MyVirtualKey oldValue,
MyVirtualKey newValue);
static void OnVirtualKeyAltChordPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, MyVirtualKey oldValue, MyVirtualKey newValue);
static void OnVirtualKeyAltChordPropertyChanged(
Windows::UI::Xaml::DependencyObject^ target,
MyVirtualKey oldValue,
MyVirtualKey newValue);
static void OnVirtualKeyControlShiftChordPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, MyVirtualKey oldValue,
MyVirtualKey newValue);
static void OnVirtualKeyControlShiftChordPropertyChanged(
Windows::UI::Xaml::DependencyObject^ target,
MyVirtualKey oldValue,
MyVirtualKey newValue);
static void OnCharacterReceivedHandler(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CharacterReceivedEventArgs^ args);
static void OnKeyDownHandler(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args);
static void OnKeyUpHandler(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args);
static void OnAcceleratorKeyActivated(Windows::UI::Core::CoreDispatcher^, Windows::UI::Core::AcceleratorKeyEventArgs^ args);
static void OnCharacterReceivedHandler(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::CharacterReceivedEventArgs ^ args);
static void OnKeyDownHandler(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::KeyEventArgs ^ args);
static void OnKeyUpHandler(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::KeyEventArgs ^ args);
static void OnAcceleratorKeyActivated(Windows::UI::Core::CoreDispatcher ^, Windows::UI::Core::AcceleratorKeyEventArgs ^ args);
};
}
}

View file

@ -33,16 +33,15 @@ DEPENDENCY_PROPERTY_INITIALIZATION(LocalizationService, FontSize);
static reader_writer_lock s_locServiceInstanceLock;
LocalizationService^ LocalizationService::s_singletonInstance = nullptr;
LocalizationService ^ LocalizationService::s_singletonInstance = nullptr;
// Resources for the engine use numbers as keys. It's inconvenient, but also difficult to
// change given that the engine heavily relies on perfect ordering of certain elements.
// The key for open parenthesis, '(', is "48".
static constexpr auto s_openParenResourceKey = L"48";
LocalizationService^ LocalizationService::GetInstance()
LocalizationService ^ LocalizationService::GetInstance()
{
if (s_singletonInstance == nullptr)
{
// Writer lock for the static maps
@ -59,20 +58,20 @@ LocalizationService^ LocalizationService::GetInstance()
LocalizationService::LocalizationService()
{
m_language = ApplicationLanguages::Languages->GetAt(0);
m_flowDirection = ResourceContext::GetForCurrentView()->QualifierValues->Lookup(L"LayoutDirection")
!= L"LTR" ? FlowDirection::RightToLeft : FlowDirection::LeftToRight;
m_flowDirection =
ResourceContext::GetForCurrentView()->QualifierValues->Lookup(L"LayoutDirection") != L"LTR" ? FlowDirection::RightToLeft : FlowDirection::LeftToRight;
auto resourceLoader = AppResourceProvider::GetInstance();
m_fontFamilyOverride = resourceLoader.GetResourceString(L"LocalizedFontFamilyOverride");
String^ reserved = L"RESERVED_FOR_FONTLOC";
String ^ reserved = L"RESERVED_FOR_FONTLOC";
m_overrideFontApiValues = ((m_fontFamilyOverride != nullptr) && (m_fontFamilyOverride != reserved));
if (m_overrideFontApiValues)
{
String^ localizedUICaptionFontSizeFactorOverride = resourceLoader.GetResourceString(L"LocalizedUICaptionFontSizeFactorOverride");
String^ localizedUITextFontSizeFactorOverride = resourceLoader.GetResourceString(L"LocalizedUITextFontSizeFactorOverride");
String^ localizedFontWeightOverride = resourceLoader.GetResourceString(L"LocalizedFontWeightOverride");
String ^ localizedUICaptionFontSizeFactorOverride = resourceLoader.GetResourceString(L"LocalizedUICaptionFontSizeFactorOverride");
String ^ localizedUITextFontSizeFactorOverride = resourceLoader.GetResourceString(L"LocalizedUITextFontSizeFactorOverride");
String ^ localizedFontWeightOverride = resourceLoader.GetResourceString(L"LocalizedFontWeightOverride");
// If any of the font overrides are modified then all of them need to be modified
assert(localizedFontWeightOverride != reserved);
@ -87,7 +86,7 @@ LocalizationService::LocalizationService()
m_fontGroup = ref new LanguageFontGroup(m_language);
}
FontWeight LocalizationService::ParseFontWeight(String^ fontWeight)
FontWeight LocalizationService::ParseFontWeight(String ^ fontWeight)
{
wstring weight = fontWeight->Data();
transform(weight.begin(), weight.end(), weight.begin(), towlower);
@ -153,7 +152,7 @@ bool LocalizationService::IsRtlLayout()
return m_flowDirection == FlowDirection::RightToLeft;
}
String^ LocalizationService::GetLanguage()
String ^ LocalizationService::GetLanguage()
{
return m_language;
}
@ -163,7 +162,7 @@ bool LocalizationService::GetOverrideFontApiValues()
return m_overrideFontApiValues;
}
FontFamily^ LocalizationService::GetLanguageFontFamilyForType(LanguageFontType fontType)
FontFamily ^ LocalizationService::GetLanguageFontFamilyForType(LanguageFontType fontType)
{
if (m_overrideFontApiValues)
{
@ -175,7 +174,7 @@ FontFamily^ LocalizationService::GetLanguageFontFamilyForType(LanguageFontType f
}
}
LanguageFont^ LocalizationService::GetLanguageFont(LanguageFontType fontType)
LanguageFont ^ LocalizationService::GetLanguageFont(LanguageFontType fontType)
{
assert(!m_overrideFontApiValues);
assert(m_fontGroup);
@ -191,7 +190,7 @@ LanguageFont^ LocalizationService::GetLanguageFont(LanguageFontType fontType)
}
}
String^ LocalizationService::GetFontFamilyOverride()
String ^ LocalizationService::GetFontFamilyOverride()
{
assert(m_overrideFontApiValues);
return m_fontFamilyOverride;
@ -218,24 +217,24 @@ double LocalizationService::GetFontScaleFactorOverride(LanguageFontType fontType
}
}
void LocalizationService::OnFontTypePropertyChanged(DependencyObject^ target, LanguageFontType /*oldValue*/, LanguageFontType /*newValue*/)
void LocalizationService::OnFontTypePropertyChanged(DependencyObject ^ target, LanguageFontType /*oldValue*/, LanguageFontType /*newValue*/)
{
UpdateFontFamilyAndSize(target);
}
void LocalizationService::OnFontWeightPropertyChanged(DependencyObject^ target, FontWeight /*oldValue*/, FontWeight /*newValue*/)
void LocalizationService::OnFontWeightPropertyChanged(DependencyObject ^ target, FontWeight /*oldValue*/, FontWeight /*newValue*/)
{
UpdateFontFamilyAndSize(target);
}
void LocalizationService::OnFontSizePropertyChanged(DependencyObject^ target, double /*oldValue*/, double /*newValue*/)
void LocalizationService::OnFontSizePropertyChanged(DependencyObject ^ target, double /*oldValue*/, double /*newValue*/)
{
UpdateFontFamilyAndSize(target);
}
void LocalizationService::UpdateFontFamilyAndSize(DependencyObject^ target)
void LocalizationService::UpdateFontFamilyAndSize(DependencyObject ^ target)
{
FontFamily^ fontFamily;
FontFamily ^ fontFamily;
FontWeight fontWeight;
bool fOverrideFontWeight = false;
double scaleFactor;
@ -259,7 +258,7 @@ void LocalizationService::UpdateFontFamilyAndSize(DependencyObject^ target)
double sizeToUse = LocalizationService::GetFontSize(target) * scaleFactor;
auto control = dynamic_cast<Control^>(target);
auto control = dynamic_cast<Control ^>(target);
if (control)
{
control->FontFamily = fontFamily;
@ -278,7 +277,7 @@ void LocalizationService::UpdateFontFamilyAndSize(DependencyObject^ target)
}
else
{
auto textBlock = dynamic_cast<TextBlock^>(target);
auto textBlock = dynamic_cast<TextBlock ^>(target);
if (textBlock)
{
textBlock->FontFamily = fontFamily;
@ -297,7 +296,7 @@ void LocalizationService::UpdateFontFamilyAndSize(DependencyObject^ target)
}
else
{
RichTextBlock^ richTextBlock = dynamic_cast<RichTextBlock^>(target);
RichTextBlock ^ richTextBlock = dynamic_cast<RichTextBlock ^>(target);
if (richTextBlock)
{
richTextBlock->FontFamily = fontFamily;
@ -316,7 +315,7 @@ void LocalizationService::UpdateFontFamilyAndSize(DependencyObject^ target)
}
else
{
TextElement^ textElement = dynamic_cast<TextElement^>(target);
TextElement ^ textElement = dynamic_cast<TextElement ^>(target);
if (textElement)
{
textElement->FontFamily = fontFamily;
@ -340,9 +339,9 @@ void LocalizationService::UpdateFontFamilyAndSize(DependencyObject^ target)
// If successful, returns a formatter that respects the user's regional format settings,
// as configured by running intl.cpl.
DecimalFormatter^ LocalizationService::GetRegionalSettingsAwareDecimalFormatter()
DecimalFormatter ^ LocalizationService::GetRegionalSettingsAwareDecimalFormatter()
{
IIterable<String^>^ languageIdentifiers = LocalizationService::GetLanguageIdentifiers();
IIterable<String ^> ^ languageIdentifiers = LocalizationService::GetLanguageIdentifiers();
if (languageIdentifiers != nullptr)
{
return ref new DecimalFormatter(languageIdentifiers, GlobalizationPreferences::HomeGeographicRegion);
@ -355,9 +354,9 @@ DecimalFormatter^ LocalizationService::GetRegionalSettingsAwareDecimalFormatter(
// as configured by running intl.cpl.
//
// This helper function creates a DateTimeFormatter with a TwentyFour hour clock
DateTimeFormatter^ LocalizationService::GetRegionalSettingsAwareDateTimeFormatter(_In_ String^ format)
DateTimeFormatter ^ LocalizationService::GetRegionalSettingsAwareDateTimeFormatter(_In_ String ^ format)
{
IIterable<String^>^ languageIdentifiers = LocalizationService::GetLanguageIdentifiers();
IIterable<String ^> ^ languageIdentifiers = LocalizationService::GetLanguageIdentifiers();
if (languageIdentifiers == nullptr)
{
languageIdentifiers = ApplicationLanguages::Languages;
@ -368,41 +367,30 @@ DateTimeFormatter^ LocalizationService::GetRegionalSettingsAwareDateTimeFormatte
// If successful, returns a formatter that respects the user's regional format settings,
// as configured by running intl.cpl.
DateTimeFormatter^ LocalizationService::GetRegionalSettingsAwareDateTimeFormatter(
_In_ String^ format,
_In_ String^ calendarIdentifier,
_In_ String^ clockIdentifier)
DateTimeFormatter
^ LocalizationService::GetRegionalSettingsAwareDateTimeFormatter(_In_ String ^ format, _In_ String ^ calendarIdentifier, _In_ String ^ clockIdentifier)
{
IIterable<String^>^ languageIdentifiers = LocalizationService::GetLanguageIdentifiers();
IIterable<String ^> ^ languageIdentifiers = LocalizationService::GetLanguageIdentifiers();
if (languageIdentifiers == nullptr)
{
languageIdentifiers = ApplicationLanguages::Languages;
}
return ref new DateTimeFormatter(
format,
languageIdentifiers,
GlobalizationPreferences::HomeGeographicRegion,
calendarIdentifier,
clockIdentifier);
return ref new DateTimeFormatter(format, languageIdentifiers, GlobalizationPreferences::HomeGeographicRegion, calendarIdentifier, clockIdentifier);
}
CurrencyFormatter^ LocalizationService::GetRegionalSettingsAwareCurrencyFormatter()
CurrencyFormatter ^ LocalizationService::GetRegionalSettingsAwareCurrencyFormatter()
{
String^ userCurrency = (GlobalizationPreferences::Currencies->Size > 0)
? GlobalizationPreferences::Currencies->GetAt(0)
: StringReference(DefaultCurrencyCode.data());
String ^ userCurrency =
(GlobalizationPreferences::Currencies->Size > 0) ? GlobalizationPreferences::Currencies->GetAt(0) : StringReference(DefaultCurrencyCode.data());
IIterable<String^>^ languageIdentifiers = LocalizationService::GetLanguageIdentifiers();
IIterable<String ^> ^ languageIdentifiers = LocalizationService::GetLanguageIdentifiers();
if (languageIdentifiers == nullptr)
{
languageIdentifiers = ApplicationLanguages::Languages;
}
auto currencyFormatter = ref new CurrencyFormatter(
userCurrency,
languageIdentifiers,
GlobalizationPreferences::HomeGeographicRegion);
auto currencyFormatter = ref new CurrencyFormatter(userCurrency, languageIdentifiers, GlobalizationPreferences::HomeGeographicRegion);
int fractionDigits = LocalizationSettings::GetInstance().GetCurrencyTrailingDigits();
currencyFormatter->FractionDigits = fractionDigits;
@ -410,7 +398,7 @@ CurrencyFormatter^ LocalizationService::GetRegionalSettingsAwareCurrencyFormatte
return currencyFormatter;
}
IIterable<String^>^ LocalizationService::GetLanguageIdentifiers()
IIterable<String ^> ^ LocalizationService::GetLanguageIdentifiers()
{
WCHAR currentLocale[LOCALE_NAME_MAX_LENGTH] = {};
int result = GetUserDefaultLocaleName(currentLocale, LOCALE_NAME_MAX_LENGTH);
@ -426,12 +414,12 @@ IIterable<String^>^ LocalizationService::GetLanguageIdentifiers()
*underscore = L'\0';
}
String^ localeString = ref new String(currentLocale);
String ^ localeString = ref new String(currentLocale);
// validate if the locale we have is valid
// otherwise we fallback to the default.
if (Language::IsWellFormed(localeString))
{
auto languageList = ref new Vector<String^>();
auto languageList = ref new Vector<String ^>();
languageList->Append(localeString);
return languageList;
}
@ -448,49 +436,34 @@ unordered_map<wstring, wstring> LocalizationService::GetTokenToReadableNameMap()
// standard project resources.
static vector<pair<wstring, wstring>> s_parenEngineKeyResourceMap = {
// Sine permutations
make_pair<wstring, wstring>(L"67", L"SineDegrees"),
make_pair<wstring, wstring>(L"73", L"SineRadians"),
make_pair<wstring, wstring>(L"79", L"SineGradians"),
make_pair<wstring, wstring>(L"70", L"InverseSineDegrees"),
make_pair<wstring, wstring>(L"76", L"InverseSineRadians"),
make_pair<wstring, wstring>(L"82", L"InverseSineGradians"),
make_pair<wstring, wstring>(L"25", L"HyperbolicSine"),
make_pair<wstring, wstring>(L"85", L"InverseHyperbolicSine"),
make_pair<wstring, wstring>(L"67", L"SineDegrees"), make_pair<wstring, wstring>(L"73", L"SineRadians"),
make_pair<wstring, wstring>(L"79", L"SineGradians"), make_pair<wstring, wstring>(L"70", L"InverseSineDegrees"),
make_pair<wstring, wstring>(L"76", L"InverseSineRadians"), make_pair<wstring, wstring>(L"82", L"InverseSineGradians"),
make_pair<wstring, wstring>(L"25", L"HyperbolicSine"), make_pair<wstring, wstring>(L"85", L"InverseHyperbolicSine"),
// Cosine permutations
make_pair<wstring, wstring>(L"68", L"CosineDegrees"),
make_pair<wstring, wstring>(L"74", L"CosineRadians"),
make_pair<wstring, wstring>(L"80", L"CosineGradians"),
make_pair<wstring, wstring>(L"71", L"InverseCosineDegrees"),
make_pair<wstring, wstring>(L"77", L"InverseCosineRadians"),
make_pair<wstring, wstring>(L"83", L"InverseCosineGradians"),
make_pair<wstring, wstring>(L"26", L"HyperbolicCosine"),
make_pair<wstring, wstring>(L"86", L"InverseHyperbolicCosine"),
make_pair<wstring, wstring>(L"68", L"CosineDegrees"), make_pair<wstring, wstring>(L"74", L"CosineRadians"),
make_pair<wstring, wstring>(L"80", L"CosineGradians"), make_pair<wstring, wstring>(L"71", L"InverseCosineDegrees"),
make_pair<wstring, wstring>(L"77", L"InverseCosineRadians"), make_pair<wstring, wstring>(L"83", L"InverseCosineGradians"),
make_pair<wstring, wstring>(L"26", L"HyperbolicCosine"), make_pair<wstring, wstring>(L"86", L"InverseHyperbolicCosine"),
// Tangent permutations
make_pair<wstring, wstring>(L"69", L"TangentDegrees"),
make_pair<wstring, wstring>(L"75", L"TangentRadians"),
make_pair<wstring, wstring>(L"81", L"TangentGradians"),
make_pair<wstring, wstring>(L"72", L"InverseTangentDegrees"),
make_pair<wstring, wstring>(L"78", L"InverseTangentRadians"),
make_pair<wstring, wstring>(L"84", L"InverseTangentGradians"),
make_pair<wstring, wstring>(L"27", L"HyperbolicTangent"),
make_pair<wstring, wstring>(L"87", L"InverseHyperbolicTangent"),
make_pair<wstring, wstring>(L"69", L"TangentDegrees"), make_pair<wstring, wstring>(L"75", L"TangentRadians"),
make_pair<wstring, wstring>(L"81", L"TangentGradians"), make_pair<wstring, wstring>(L"72", L"InverseTangentDegrees"),
make_pair<wstring, wstring>(L"78", L"InverseTangentRadians"), make_pair<wstring, wstring>(L"84", L"InverseTangentGradians"),
make_pair<wstring, wstring>(L"27", L"HyperbolicTangent"), make_pair<wstring, wstring>(L"87", L"InverseHyperbolicTangent"),
// Miscellaneous Scientific functions
make_pair<wstring, wstring>(L"94", L"Factorial"),
make_pair<wstring, wstring>(L"35", L"DegreeMinuteSecond"),
make_pair<wstring, wstring>(L"28", L"NaturalLog"),
make_pair<wstring, wstring>(L"91", L"Square")
make_pair<wstring, wstring>(L"94", L"Factorial"), make_pair<wstring, wstring>(L"35", L"DegreeMinuteSecond"),
make_pair<wstring, wstring>(L"28", L"NaturalLog"), make_pair<wstring, wstring>(L"91", L"Square")
};
static vector<pair<wstring, wstring>> s_noParenEngineKeyResourceMap = {
// Programmer mode functions
make_pair<wstring, wstring>(L"9", L"LeftShift"),
make_pair<wstring, wstring>(L"10", L"RightShift"),
static vector<pair<wstring, wstring>> s_noParenEngineKeyResourceMap = { // Programmer mode functions
make_pair<wstring, wstring>(L"9", L"LeftShift"),
make_pair<wstring, wstring>(L"10", L"RightShift"),
// Y Root scientific function
make_pair<wstring, wstring>(L"16", L"YRoot")
// Y Root scientific function
make_pair<wstring, wstring>(L"16", L"YRoot")
};
unordered_map<wstring, wstring> tokenToReadableNameMap{};
@ -523,7 +496,7 @@ unordered_map<wstring, wstring> LocalizationService::GetTokenToReadableNameMap()
return tokenToReadableNameMap;
}
String^ LocalizationService::GetNarratorReadableToken(String^ rawToken)
String ^ LocalizationService::GetNarratorReadableToken(String ^ rawToken)
{
static unordered_map<wstring, wstring> s_tokenToReadableNameMap = GetTokenToReadableNameMap();
@ -534,12 +507,12 @@ String^ LocalizationService::GetNarratorReadableToken(String^ rawToken)
}
else
{
static const String^ openParen = AppResourceProvider::GetInstance().GetCEngineString(StringReference(s_openParenResourceKey));
static const String ^ openParen = AppResourceProvider::GetInstance().GetCEngineString(StringReference(s_openParenResourceKey));
return ref new String(itr->second.c_str()) + L" " + openParen;
}
}
String^ LocalizationService::GetNarratorReadableString(String^ rawString)
String ^ LocalizationService::GetNarratorReadableString(String ^ rawString)
{
wstringstream readableString{};
readableString << L"";

View file

@ -5,81 +5,83 @@
#include "Utils.h"
namespace CalculatorApp { namespace Common
namespace CalculatorApp
{
namespace LocalizationServiceProperties
namespace Common
{
static constexpr std::wstring_view DefaultCurrencyCode{ L"USD" };
namespace LocalizationServiceProperties
{
static constexpr std::wstring_view DefaultCurrencyCode{ L"USD" };
}
public
enum class LanguageFontType
{
UIText,
UICaption,
};
public
ref class LocalizationService sealed
{
public:
DEPENDENCY_PROPERTY_OWNER(LocalizationService);
DEPENDENCY_PROPERTY_ATTACHED_WITH_DEFAULT_AND_CALLBACK(LanguageFontType, FontType, LanguageFontType::UIText);
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(double, FontSize);
internal : static LocalizationService ^ GetInstance();
Windows::UI::Xaml::FlowDirection GetFlowDirection();
bool IsRtlLayout();
bool GetOverrideFontApiValues();
Platform::String ^ GetLanguage();
Windows::UI::Xaml::Media::FontFamily ^ GetLanguageFontFamilyForType(LanguageFontType fontType);
Platform::String ^ GetFontFamilyOverride();
Windows::UI::Text::FontWeight GetFontWeightOverride();
double GetFontScaleFactorOverride(LanguageFontType fontType);
static Windows::Globalization::NumberFormatting::DecimalFormatter ^ GetRegionalSettingsAwareDecimalFormatter();
static Windows::Globalization::DateTimeFormatting::DateTimeFormatter ^ GetRegionalSettingsAwareDateTimeFormatter(_In_ Platform::String ^ format);
static Windows::Globalization::DateTimeFormatting::DateTimeFormatter
^ GetRegionalSettingsAwareDateTimeFormatter(_In_ Platform::String ^ format, _In_ Platform::String ^ calendarIdentifier,
_In_ Platform::String ^ clockIdentifier);
static Windows::Globalization::NumberFormatting::CurrencyFormatter ^ GetRegionalSettingsAwareCurrencyFormatter();
static Platform::String ^ GetNarratorReadableToken(Platform::String ^ rawToken);
static Platform::String ^ GetNarratorReadableString(Platform::String ^ rawString);
private:
Windows::Globalization::Fonts::LanguageFont ^ GetLanguageFont(LanguageFontType fontType);
Windows::UI::Text::FontWeight ParseFontWeight(Platform::String ^ fontWeight);
static Windows::Foundation::Collections::IIterable<Platform::String ^> ^ GetLanguageIdentifiers();
// Attached property callbacks
static void OnFontTypePropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, LanguageFontType oldValue, LanguageFontType newValue);
static void OnFontWeightPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, Windows::UI::Text::FontWeight oldValue,
Windows::UI::Text::FontWeight newValue);
static void OnFontSizePropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, double oldValue, double newValue);
static void UpdateFontFamilyAndSize(Windows::UI::Xaml::DependencyObject ^ target);
static std::unordered_map<std::wstring, std::wstring> GetTokenToReadableNameMap();
private:
LocalizationService();
static LocalizationService ^ s_singletonInstance;
Windows::Globalization::Fonts::LanguageFontGroup ^ m_fontGroup;
Platform::String ^ m_language;
Windows::UI::Xaml::FlowDirection m_flowDirection;
bool m_overrideFontApiValues;
Platform::String ^ m_fontFamilyOverride;
Windows::UI::Text::FontWeight m_fontWeightOverride;
double m_uiTextFontScaleFactorOverride;
double m_uiCaptionFontScaleFactorOverride;
};
}
public enum class LanguageFontType
{
UIText,
UICaption,
};
public ref class LocalizationService sealed
{
public:
DEPENDENCY_PROPERTY_OWNER(LocalizationService);
DEPENDENCY_PROPERTY_ATTACHED_WITH_DEFAULT_AND_CALLBACK(LanguageFontType, FontType, LanguageFontType::UIText);
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(double, FontSize);
internal:
static LocalizationService^ GetInstance();
Windows::UI::Xaml::FlowDirection GetFlowDirection();
bool IsRtlLayout();
bool GetOverrideFontApiValues();
Platform::String^ GetLanguage();
Windows::UI::Xaml::Media::FontFamily^ GetLanguageFontFamilyForType(LanguageFontType fontType);
Platform::String^ GetFontFamilyOverride();
Windows::UI::Text::FontWeight GetFontWeightOverride();
double GetFontScaleFactorOverride(LanguageFontType fontType);
static Windows::Globalization::NumberFormatting::DecimalFormatter^ GetRegionalSettingsAwareDecimalFormatter();
static Windows::Globalization::DateTimeFormatting::DateTimeFormatter^ GetRegionalSettingsAwareDateTimeFormatter(_In_ Platform::String^ format);
static Windows::Globalization::DateTimeFormatting::DateTimeFormatter^ GetRegionalSettingsAwareDateTimeFormatter(
_In_ Platform::String^ format,
_In_ Platform::String^ calendarIdentifier,
_In_ Platform::String^ clockIdentifier);
static Windows::Globalization::NumberFormatting::CurrencyFormatter^ GetRegionalSettingsAwareCurrencyFormatter();
static Platform::String^ GetNarratorReadableToken(Platform::String^ rawToken);
static Platform::String^ GetNarratorReadableString(Platform::String^ rawString);
private:
Windows::Globalization::Fonts::LanguageFont^ GetLanguageFont(LanguageFontType fontType);
Windows::UI::Text::FontWeight ParseFontWeight(Platform::String^ fontWeight);
static Windows::Foundation::Collections::IIterable<Platform::String^>^ GetLanguageIdentifiers();
// Attached property callbacks
static void OnFontTypePropertyChanged(Windows::UI::Xaml::DependencyObject^ target, LanguageFontType oldValue, LanguageFontType newValue);
static void OnFontWeightPropertyChanged(Windows::UI::Xaml::DependencyObject^ target, Windows::UI::Text::FontWeight oldValue, Windows::UI::Text::FontWeight newValue);
static void OnFontSizePropertyChanged(Windows::UI::Xaml::DependencyObject^ target, double oldValue, double newValue);
static void UpdateFontFamilyAndSize(Windows::UI::Xaml::DependencyObject^ target);
static std::unordered_map<std::wstring, std::wstring> GetTokenToReadableNameMap();
private:
LocalizationService();
static LocalizationService^ s_singletonInstance;
Windows::Globalization::Fonts::LanguageFontGroup^ m_fontGroup;
Platform::String^ m_language;
Windows::UI::Xaml::FlowDirection m_flowDirection;
bool m_overrideFontApiValues;
Platform::String^ m_fontFamilyOverride;
Windows::UI::Text::FontWeight m_fontWeightOverride;
double m_uiTextFontScaleFactorOverride;
double m_uiCaptionFontScaleFactorOverride;
};
}}
}

View file

@ -18,7 +18,7 @@ namespace CalculatorApp
int result = 0;
// Use DecimalFormatter as it respects the locale and the user setting
Windows::Globalization::NumberFormatting::DecimalFormatter^ formatter;
Windows::Globalization::NumberFormatting::DecimalFormatter ^ formatter;
formatter = CalculatorApp::Common::LocalizationService::GetRegionalSettingsAwareDecimalFormatter();
formatter->FractionDigits = 0;
formatter->IsDecimalPointAlwaysDisplayed = false;
@ -29,9 +29,7 @@ namespace CalculatorApp
}
wchar_t resolvedName[LOCALE_NAME_MAX_LENGTH];
result = ResolveLocaleName(formatter->ResolvedLanguage->Data(),
resolvedName,
LOCALE_NAME_MAX_LENGTH);
result = ResolveLocaleName(formatter->ResolvedLanguage->Data(), resolvedName, LOCALE_NAME_MAX_LENGTH);
if (result == 0)
{
throw std::runtime_error("Unexpected error resolving locale name");
@ -40,30 +38,21 @@ namespace CalculatorApp
{
m_resolvedName = resolvedName;
wchar_t decimalString[LocaleSettingBufferSize] = L"";
result = GetLocaleInfoEx(m_resolvedName.c_str(),
LOCALE_SDECIMAL,
decimalString,
static_cast<int>(std::size(decimalString)));
result = GetLocaleInfoEx(m_resolvedName.c_str(), LOCALE_SDECIMAL, decimalString, static_cast<int>(std::size(decimalString)));
if (result == 0)
{
throw std::runtime_error("Unexpected error while getting locale info");
}
wchar_t groupingSymbolString[LocaleSettingBufferSize] = L"";
result = GetLocaleInfoEx(m_resolvedName.c_str(),
LOCALE_STHOUSAND,
groupingSymbolString,
static_cast<int>(std::size(groupingSymbolString)));
result = GetLocaleInfoEx(m_resolvedName.c_str(), LOCALE_STHOUSAND, groupingSymbolString, static_cast<int>(std::size(groupingSymbolString)));
if (result == 0)
{
throw std::runtime_error("Unexpected error while getting locale info");
}
wchar_t numberGroupingString[LocaleSettingBufferSize] = L"";
result = GetLocaleInfoEx(m_resolvedName.c_str(),
LOCALE_SGROUPING,
numberGroupingString,
static_cast<int>(std::size(numberGroupingString)));
result = GetLocaleInfoEx(m_resolvedName.c_str(), LOCALE_SGROUPING, numberGroupingString, static_cast<int>(std::size(numberGroupingString)));
if (result == 0)
{
throw std::runtime_error("Unexpected error while getting locale info");
@ -71,20 +60,16 @@ namespace CalculatorApp
// Get locale info for List Separator, eg. comma is used in many locales
wchar_t listSeparatorString[4] = L"";
result = ::GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT,
LOCALE_SLIST,
listSeparatorString,
static_cast<int>(std::size(listSeparatorString))); // Max length of the expected return value is 4
result = ::GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SLIST, listSeparatorString,
static_cast<int>(std::size(listSeparatorString))); // Max length of the expected return value is 4
if (result == 0)
{
throw std::runtime_error("Unexpected error while getting locale info");
}
int currencyTrailingDigits = 0;
result = GetLocaleInfoEx(m_resolvedName.c_str(),
LOCALE_ICURRDIGITS | LOCALE_RETURN_NUMBER,
(LPWSTR)&currencyTrailingDigits,
sizeof(currencyTrailingDigits) / sizeof(WCHAR));
result = GetLocaleInfoEx(m_resolvedName.c_str(), LOCALE_ICURRDIGITS | LOCALE_RETURN_NUMBER, (LPWSTR)&currencyTrailingDigits,
sizeof(currencyTrailingDigits) / sizeof(WCHAR));
if (result == 0)
{
throw std::runtime_error("Unexpected error while getting locale info");
@ -93,10 +78,8 @@ namespace CalculatorApp
// Currency symbol precedence is either 0 or 1.
// A value of 0 indicates the symbol follows the currency value.
int currencySymbolPrecedence = 1;
result = GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT,
LOCALE_IPOSSYMPRECEDES | LOCALE_RETURN_NUMBER,
(LPWSTR)&currencySymbolPrecedence,
sizeof(currencySymbolPrecedence) / sizeof(WCHAR));
result = GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_IPOSSYMPRECEDES | LOCALE_RETURN_NUMBER, (LPWSTR)&currencySymbolPrecedence,
sizeof(currencySymbolPrecedence) / sizeof(WCHAR));
// As CalcEngine only supports the first character of the decimal separator,
// Only first character of the decimal separator string is supported.
@ -112,24 +95,21 @@ namespace CalculatorApp
// Note: This function returns 0 on failure.
// We'll ignore the failure in that case and the CalendarIdentifier would get set to GregorianCalendar.
CALID calId;
::GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT,
LOCALE_ICALENDARTYPE | LOCALE_RETURN_NUMBER,
reinterpret_cast<PWSTR>(&calId),
sizeof(calId));
::GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_ICALENDARTYPE | LOCALE_RETURN_NUMBER, reinterpret_cast<PWSTR>(&calId), sizeof(calId));
m_calendarIdentifier = GetCalendarIdentifierFromCalid(calId);
// Get FirstDayOfWeek Date and Time setting
wchar_t day[80] = L"";
::GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT,
LOCALE_IFIRSTDAYOFWEEK, // The first day in a week
reinterpret_cast<PWSTR>(day), // Argument is of type PWSTR
static_cast<int>(std::size(day))); // Max return size are 80 characters
LOCALE_IFIRSTDAYOFWEEK, // The first day in a week
reinterpret_cast<PWSTR>(day), // Argument is of type PWSTR
static_cast<int>(std::size(day))); // Max return size are 80 characters
// The LOCALE_IFIRSTDAYOFWEEK integer value varies from 0, 1, .. 6 for Monday, Tuesday, ... Sunday
// DayOfWeek enum value varies from 0, 1, .. 6 for Sunday, Monday, ... Saturday
// Hence, DayOfWeek = (valueof(LOCALE_IFIRSTDAYOFWEEK) + 1) % 7
m_firstDayOfWeek = static_cast<Windows::Globalization::DayOfWeek>((_wtoi(day) + 1) % 7); // static cast int to DayOfWeek enum
m_firstDayOfWeek = static_cast<Windows::Globalization::DayOfWeek>((_wtoi(day) + 1) % 7); // static cast int to DayOfWeek enum
}
public:
@ -149,7 +129,7 @@ namespace CalculatorApp
return localizationSettings;
}
Platform::String^ GetLocaleName() const
Platform::String ^ GetLocaleName() const
{
return ref new Platform::String(m_resolvedName.c_str());
}
@ -179,7 +159,7 @@ namespace CalculatorApp
}
}
Platform::String^ GetEnglishValueFromLocalizedDigits(const std::wstring& localizedString) const
Platform::String ^ GetEnglishValueFromLocalizedDigits(const std::wstring& localizedString) const
{
if (m_resolvedName == L"en-US")
{
@ -201,7 +181,7 @@ namespace CalculatorApp
{
ch = j.ToString()->Data()[0];
break;
//ch = val - L'0';
// ch = val - L'0';
}
}
}
@ -305,7 +285,7 @@ namespace CalculatorApp
}
}
Platform::String^ GetCalendarIdentifier() const
Platform::String ^ GetCalendarIdentifier() const
{
return m_calendarIdentifier;
}
@ -378,7 +358,7 @@ namespace CalculatorApp
// Hexadecimal characters are not currently localized
static constexpr std::array<wchar_t, 6> s_hexSymbols{ L'A', L'B', L'C', L'D', L'E', L'F' };
std::wstring m_listSeparator;
Platform::String^ m_calendarIdentifier;
Platform::String ^ m_calendarIdentifier;
Windows::Globalization::DayOfWeek m_firstDayOfWeek;
int m_currencySymbolPrecedence;
std::wstring m_resolvedName;

View file

@ -19,13 +19,7 @@ namespace CalculatorApp
std::unique_ptr<wchar_t[]> spBuffer = std::unique_ptr<wchar_t[]>(new wchar_t[length]);
va_list args = NULL;
va_start(args, pMessage);
DWORD fmtReturnVal = FormatMessage(FORMAT_MESSAGE_FROM_STRING,
pMessage,
0,
0,
spBuffer.get(),
length,
&args);
DWORD fmtReturnVal = FormatMessage(FORMAT_MESSAGE_FROM_STRING, pMessage, 0, 0, spBuffer.get(), length, &args);
va_end(args);
if (fmtReturnVal != 0)

View file

@ -7,7 +7,8 @@ namespace CalculatorApp
{
namespace Common
{
public enum class MyVirtualKey
public
enum class MyVirtualKey
{
None = 0,
LeftButton = 1,

View file

@ -24,80 +24,89 @@ static constexpr bool POSITIVE_ONLY = false;
// The order of items in this list determines the order of groups in the menu.
static constexpr array<const NavCategoryGroupInitializer, 2> s_categoryGroupManifest = {
NavCategoryGroupInitializer { CategoryGroupType::Calculator, L"CalculatorModeTextCaps", L"CalculatorModeText", L"CalculatorModePluralText"},
NavCategoryGroupInitializer { CategoryGroupType::Converter, L"ConverterModeTextCaps", L"ConverterModeText", L"ConverterModePluralText" }
NavCategoryGroupInitializer{ CategoryGroupType::Calculator, L"CalculatorModeTextCaps", L"CalculatorModeText", L"CalculatorModePluralText" },
NavCategoryGroupInitializer{ CategoryGroupType::Converter, L"ConverterModeTextCaps", L"ConverterModeText", L"ConverterModePluralText" }
};
// vvv THESE CONSTANTS SHOULD NEVER CHANGE vvv
static constexpr int STANDARD_ID = 0;
static constexpr int SCIENTIFIC_ID = 1;
static constexpr int PROGRAMMER_ID = 2;
static constexpr int DATE_ID = 3;
static constexpr int VOLUME_ID = 4;
static constexpr int LENGTH_ID = 5;
static constexpr int WEIGHT_ID = 6;
static constexpr int STANDARD_ID = 0;
static constexpr int SCIENTIFIC_ID = 1;
static constexpr int PROGRAMMER_ID = 2;
static constexpr int DATE_ID = 3;
static constexpr int VOLUME_ID = 4;
static constexpr int LENGTH_ID = 5;
static constexpr int WEIGHT_ID = 6;
static constexpr int TEMPERATURE_ID = 7;
static constexpr int ENERGY_ID = 8;
static constexpr int AREA_ID = 9;
static constexpr int SPEED_ID = 10;
static constexpr int TIME_ID = 11;
static constexpr int POWER_ID = 12;
static constexpr int DATA_ID = 13;
static constexpr int PRESSURE_ID = 14;
static constexpr int ANGLE_ID = 15;
static constexpr int CURRENCY_ID = 16;
static constexpr int ENERGY_ID = 8;
static constexpr int AREA_ID = 9;
static constexpr int SPEED_ID = 10;
static constexpr int TIME_ID = 11;
static constexpr int POWER_ID = 12;
static constexpr int DATA_ID = 13;
static constexpr int PRESSURE_ID = 14;
static constexpr int ANGLE_ID = 15;
static constexpr int CURRENCY_ID = 16;
// ^^^ THESE CONSTANTS SHOULD NEVER CHANGE ^^^
// The order of items in this list determines the order of items in the menu.
static constexpr array<const NavCategoryInitializer, 17> s_categoryManifest = {
NavCategoryInitializer { ViewMode::Standard, STANDARD_ID, L"Standard", L"StandardMode", L"\uE8EF", CategoryGroupType::Calculator, MyVirtualKey::Number1, SUPPORTS_ALL },
NavCategoryInitializer { ViewMode::Scientific, SCIENTIFIC_ID, L"Scientific", L"ScientificMode", L"\uF196", CategoryGroupType::Calculator, MyVirtualKey::Number2, SUPPORTS_ALL },
NavCategoryInitializer { ViewMode::Programmer, PROGRAMMER_ID, L"Programmer", L"ProgrammerMode", L"\uECCE", CategoryGroupType::Calculator, MyVirtualKey::Number3, SUPPORTS_ALL },
NavCategoryInitializer { ViewMode::Date, DATE_ID, L"Date", L"DateCalculationMode", L"\uE787", CategoryGroupType::Calculator, MyVirtualKey::Number4, SUPPORTS_ALL },
NavCategoryInitializer { ViewMode::Currency, CURRENCY_ID, L"Currency", L"CategoryName_Currency", L"\uEB0D", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY },
NavCategoryInitializer { ViewMode::Volume, VOLUME_ID, L"Volume", L"CategoryName_Volume", L"\uF1AA", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY },
NavCategoryInitializer { ViewMode::Length, LENGTH_ID, L"Length", L"CategoryName_Length", L"\uECC6", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY },
NavCategoryInitializer { ViewMode::Weight, WEIGHT_ID, L"Weight and Mass", L"CategoryName_Weight", L"\uF4C1", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY },
NavCategoryInitializer { ViewMode::Temperature, TEMPERATURE_ID, L"Temperature", L"CategoryName_Temperature", L"\uE7A3", CategoryGroupType::Converter, MyVirtualKey::None, SUPPORTS_NEGATIVE },
NavCategoryInitializer { ViewMode::Energy, ENERGY_ID, L"Energy", L"CategoryName_Energy", L"\uECAD", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY },
NavCategoryInitializer { ViewMode::Area, AREA_ID, L"Area", L"CategoryName_Area", L"\uE809", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY },
NavCategoryInitializer { ViewMode::Speed, SPEED_ID, L"Speed", L"CategoryName_Speed", L"\uEADA", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY },
NavCategoryInitializer { ViewMode::Time, TIME_ID, L"Time", L"CategoryName_Time", L"\uE917", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY },
NavCategoryInitializer { ViewMode::Power, POWER_ID, L"Power", L"CategoryName_Power", L"\uE945", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY },
NavCategoryInitializer { ViewMode::Data, DATA_ID, L"Data", L"CategoryName_Data", L"\uF20F", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY },
NavCategoryInitializer { ViewMode::Pressure, PRESSURE_ID, L"Pressure", L"CategoryName_Pressure", L"\uEC4A", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY },
NavCategoryInitializer { ViewMode::Angle, ANGLE_ID, L"Angle", L"CategoryName_Angle", L"\uF515", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY }
NavCategoryInitializer{ ViewMode::Standard, STANDARD_ID, L"Standard", L"StandardMode", L"\uE8EF", CategoryGroupType::Calculator, MyVirtualKey::Number1,
SUPPORTS_ALL },
NavCategoryInitializer{ ViewMode::Scientific, SCIENTIFIC_ID, L"Scientific", L"ScientificMode", L"\uF196", CategoryGroupType::Calculator,
MyVirtualKey::Number2, SUPPORTS_ALL },
NavCategoryInitializer{ ViewMode::Programmer, PROGRAMMER_ID, L"Programmer", L"ProgrammerMode", L"\uECCE", CategoryGroupType::Calculator,
MyVirtualKey::Number3, SUPPORTS_ALL },
NavCategoryInitializer{ ViewMode::Date, DATE_ID, L"Date", L"DateCalculationMode", L"\uE787", CategoryGroupType::Calculator, MyVirtualKey::Number4,
SUPPORTS_ALL },
NavCategoryInitializer{ ViewMode::Currency, CURRENCY_ID, L"Currency", L"CategoryName_Currency", L"\uEB0D", CategoryGroupType::Converter, MyVirtualKey::None,
POSITIVE_ONLY },
NavCategoryInitializer{ ViewMode::Volume, VOLUME_ID, L"Volume", L"CategoryName_Volume", L"\uF1AA", CategoryGroupType::Converter, MyVirtualKey::None,
POSITIVE_ONLY },
NavCategoryInitializer{ ViewMode::Length, LENGTH_ID, L"Length", L"CategoryName_Length", L"\uECC6", CategoryGroupType::Converter, MyVirtualKey::None,
POSITIVE_ONLY },
NavCategoryInitializer{ ViewMode::Weight, WEIGHT_ID, L"Weight and Mass", L"CategoryName_Weight", L"\uF4C1", CategoryGroupType::Converter,
MyVirtualKey::None, POSITIVE_ONLY },
NavCategoryInitializer{ ViewMode::Temperature, TEMPERATURE_ID, L"Temperature", L"CategoryName_Temperature", L"\uE7A3", CategoryGroupType::Converter,
MyVirtualKey::None, SUPPORTS_NEGATIVE },
NavCategoryInitializer{ ViewMode::Energy, ENERGY_ID, L"Energy", L"CategoryName_Energy", L"\uECAD", CategoryGroupType::Converter, MyVirtualKey::None,
POSITIVE_ONLY },
NavCategoryInitializer{ ViewMode::Area, AREA_ID, L"Area", L"CategoryName_Area", L"\uE809", CategoryGroupType::Converter, MyVirtualKey::None,
POSITIVE_ONLY },
NavCategoryInitializer{ ViewMode::Speed, SPEED_ID, L"Speed", L"CategoryName_Speed", L"\uEADA", CategoryGroupType::Converter, MyVirtualKey::None,
POSITIVE_ONLY },
NavCategoryInitializer{ ViewMode::Time, TIME_ID, L"Time", L"CategoryName_Time", L"\uE917", CategoryGroupType::Converter, MyVirtualKey::None,
POSITIVE_ONLY },
NavCategoryInitializer{ ViewMode::Power, POWER_ID, L"Power", L"CategoryName_Power", L"\uE945", CategoryGroupType::Converter, MyVirtualKey::None,
POSITIVE_ONLY },
NavCategoryInitializer{ ViewMode::Data, DATA_ID, L"Data", L"CategoryName_Data", L"\uF20F", CategoryGroupType::Converter, MyVirtualKey::None,
POSITIVE_ONLY },
NavCategoryInitializer{ ViewMode::Pressure, PRESSURE_ID, L"Pressure", L"CategoryName_Pressure", L"\uEC4A", CategoryGroupType::Converter, MyVirtualKey::None,
POSITIVE_ONLY },
NavCategoryInitializer{ ViewMode::Angle, ANGLE_ID, L"Angle", L"CategoryName_Angle", L"\uF515", CategoryGroupType::Converter, MyVirtualKey::None,
POSITIVE_ONLY }
};
// This function should only be used when storing the mode to app data.
int NavCategory::Serialize(ViewMode mode)
{
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest),
[mode](const NavCategoryInitializer& initializer)
{
return initializer.viewMode == mode;
});
auto iter =
find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode](const NavCategoryInitializer& initializer) { return initializer.viewMode == mode; });
return (iter != s_categoryManifest.end())
? iter->serializationId
: -1;
return (iter != s_categoryManifest.end()) ? iter->serializationId : -1;
}
// This function should only be used when restoring the mode from app data.
ViewMode NavCategory::Deserialize(Platform::Object^ obj)
ViewMode NavCategory::Deserialize(Platform::Object ^ obj)
{
// If we cast directly to ViewMode we will fail
// because we technically store an int.
// Need to cast to int, then ViewMode.
auto boxed = dynamic_cast<Box<int>^>(obj);
auto boxed = dynamic_cast<Box<int> ^>(obj);
if (boxed != nullptr)
{
int serializationId = boxed->Value;
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest),
[serializationId](const NavCategoryInitializer& initializer)
{
return initializer.serializationId == serializationId;
});
[serializationId](const NavCategoryInitializer& initializer) { return initializer.serializationId == serializationId; });
if (iter != s_categoryManifest.end())
{
@ -110,11 +119,8 @@ ViewMode NavCategory::Deserialize(Platform::Object^ obj)
bool NavCategory::IsValidViewMode(ViewMode mode)
{
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest),
[mode](const NavCategoryInitializer& initializer)
{
return initializer.viewMode == mode;
});
auto iter =
find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode](const NavCategoryInitializer& initializer) { return initializer.viewMode == mode; });
return iter != s_categoryManifest.end();
}
@ -139,64 +145,41 @@ bool NavCategory::IsConverterViewMode(ViewMode mode)
bool NavCategory::IsModeInCategoryGroup(ViewMode mode, CategoryGroupType type)
{
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest),
[mode, type](const NavCategoryInitializer& initializer)
{
return initializer.viewMode == mode && initializer.groupType == type;
});
[mode, type](const NavCategoryInitializer& initializer) { return initializer.viewMode == mode && initializer.groupType == type; });
return iter != s_categoryManifest.end();
}
String^ NavCategory::GetFriendlyName(ViewMode mode)
String ^ NavCategory::GetFriendlyName(ViewMode mode)
{
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest),
[mode](const NavCategoryInitializer& initializer)
{
return initializer.viewMode == mode;
});
auto iter =
find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode](const NavCategoryInitializer& initializer) { return initializer.viewMode == mode; });
return (iter != s_categoryManifest.end())
? StringReference(iter->friendlyName)
: L"None";
return (iter != s_categoryManifest.end()) ? StringReference(iter->friendlyName) : L"None";
}
ViewMode NavCategory::GetViewModeForFriendlyName(String^ name)
ViewMode NavCategory::GetViewModeForFriendlyName(String ^ name)
{
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest),
[name](const NavCategoryInitializer& initializer)
{
return wcscmp(initializer.friendlyName, name->Data()) == 0;
});
[name](const NavCategoryInitializer& initializer) { return wcscmp(initializer.friendlyName, name->Data()) == 0; });
return (iter != s_categoryManifest.end())
? iter->viewMode
: ViewMode::None;
return (iter != s_categoryManifest.end()) ? iter->viewMode : ViewMode::None;
}
String^ NavCategory::GetNameResourceKey(ViewMode mode)
String ^ NavCategory::GetNameResourceKey(ViewMode mode)
{
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest),
[mode](const NavCategoryInitializer& initializer)
{
return initializer.viewMode == mode;
});
auto iter =
find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode](const NavCategoryInitializer& initializer) { return initializer.viewMode == mode; });
return (iter != s_categoryManifest.end())
? StringReference(iter->nameResourceKey) + "Text"
: nullptr;
return (iter != s_categoryManifest.end()) ? StringReference(iter->nameResourceKey) + "Text" : nullptr;
}
CategoryGroupType NavCategory::GetGroupType(ViewMode mode)
{
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest),
[mode](const NavCategoryInitializer& initializer)
{
return initializer.viewMode == mode;
});
auto iter =
find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode](const NavCategoryInitializer& initializer) { return initializer.viewMode == mode; });
return (iter != s_categoryManifest.end())
? iter->groupType
: CategoryGroupType::None;
return (iter != s_categoryManifest.end()) ? iter->groupType : CategoryGroupType::None;
}
// GetIndex is 0-based, GetPosition is 1-based
@ -210,9 +193,7 @@ int NavCategory::GetFlatIndex(ViewMode mode)
{
int index = -1;
CategoryGroupType type = CategoryGroupType::None;
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest),
[mode, &type, &index](const NavCategoryInitializer& initializer)
{
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode, &type, &index](const NavCategoryInitializer& initializer) {
index++;
if (initializer.groupType != type)
{
@ -223,18 +204,14 @@ int NavCategory::GetFlatIndex(ViewMode mode)
return initializer.viewMode == mode;
});
return (iter != s_categoryManifest.end())
? index
: -1;
return (iter != s_categoryManifest.end()) ? index : -1;
}
// GetIndex is 0-based, GetPosition is 1-based
int NavCategory::GetIndexInGroup(ViewMode mode, CategoryGroupType type)
{
int index = -1;
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest),
[mode, type, &index](const NavCategoryInitializer& initializer)
{
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode, type, &index](const NavCategoryInitializer& initializer) {
if (initializer.groupType == type)
{
index++;
@ -244,38 +221,27 @@ int NavCategory::GetIndexInGroup(ViewMode mode, CategoryGroupType type)
return false;
});
return (iter != s_categoryManifest.end())
? index
: -1;
return (iter != s_categoryManifest.end()) ? index : -1;
}
// GetIndex is 0-based, GetPosition is 1-based
int NavCategory::GetPosition(ViewMode mode)
{
int position = 0;
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest),
[mode, &position](const NavCategoryInitializer& initializer)
{
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode, &position](const NavCategoryInitializer& initializer) {
position++;
return initializer.viewMode == mode;
});
return (iter != s_categoryManifest.end())
? position
: -1;
return (iter != s_categoryManifest.end()) ? position : -1;
}
ViewMode NavCategory::GetViewModeForVirtualKey(MyVirtualKey virtualKey)
{
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest),
[virtualKey](const NavCategoryInitializer& initializer)
{
return initializer.virtualKey == virtualKey;
});
[virtualKey](const NavCategoryInitializer& initializer) { return initializer.virtualKey == virtualKey; });
return (iter != s_categoryManifest.end())
? iter->viewMode
: ViewMode::None;
return (iter != s_categoryManifest.end()) ? iter->viewMode : ViewMode::None;
}
vector<MyVirtualKey> NavCategory::GetCategoryAcceleratorKeys()
@ -292,63 +258,54 @@ vector<MyVirtualKey> NavCategory::GetCategoryAcceleratorKeys()
return accelerators;
}
NavCategoryGroup::NavCategoryGroup(const NavCategoryGroupInitializer& groupInitializer) :
m_Categories(ref new Vector<NavCategory^>())
NavCategoryGroup::NavCategoryGroup(const NavCategoryGroupInitializer& groupInitializer) : m_Categories(ref new Vector<NavCategory ^>())
{
m_GroupType = groupInitializer.type;
auto resProvider = AppResourceProvider::GetInstance();
String^ headerResourceKey = StringReference(groupInitializer.headerResourceKey);
String^ modeResourceKey = StringReference(groupInitializer.modeResourceKey);
String^ automationResourceKey = StringReference(groupInitializer.automationResourceKey);
String ^ headerResourceKey = StringReference(groupInitializer.headerResourceKey);
String ^ modeResourceKey = StringReference(groupInitializer.modeResourceKey);
String ^ automationResourceKey = StringReference(groupInitializer.automationResourceKey);
m_Name = resProvider.GetResourceString(headerResourceKey);
String^ groupMode = resProvider.GetResourceString(modeResourceKey);
String^ automationName = resProvider.GetResourceString(automationResourceKey);
String ^ groupMode = resProvider.GetResourceString(modeResourceKey);
String ^ automationName = resProvider.GetResourceString(automationResourceKey);
String^ navCategoryHeaderAutomationNameFormat = resProvider.GetResourceString(L"NavCategoryHeader_AutomationNameFormat");
m_AutomationName = ref new String(LocalizationStringUtil::GetLocalizedString(
navCategoryHeaderAutomationNameFormat->Data(),
automationName->Data()).c_str());
String ^ navCategoryHeaderAutomationNameFormat = resProvider.GetResourceString(L"NavCategoryHeader_AutomationNameFormat");
m_AutomationName =
ref new String(LocalizationStringUtil::GetLocalizedString(navCategoryHeaderAutomationNameFormat->Data(), automationName->Data()).c_str());
String^ navCategoryItemAutomationNameFormat = resProvider.GetResourceString(L"NavCategoryItem_AutomationNameFormat");
String ^ navCategoryItemAutomationNameFormat = resProvider.GetResourceString(L"NavCategoryItem_AutomationNameFormat");
for (const NavCategoryInitializer& categoryInitializer : s_categoryManifest)
{
if (categoryInitializer.groupType == groupInitializer.type)
{
String^ nameResourceKey = StringReference(categoryInitializer.nameResourceKey);
String^ categoryName = resProvider.GetResourceString(nameResourceKey + "Text");
String^ categoryAutomationName = ref new String(LocalizationStringUtil::GetLocalizedString(
navCategoryItemAutomationNameFormat->Data(),
categoryName->Data(),
m_Name->Data()).c_str());
String ^ nameResourceKey = StringReference(categoryInitializer.nameResourceKey);
String ^ categoryName = resProvider.GetResourceString(nameResourceKey + "Text");
String ^ categoryAutomationName = ref new String(
LocalizationStringUtil::GetLocalizedString(navCategoryItemAutomationNameFormat->Data(), categoryName->Data(), m_Name->Data()).c_str());
m_Categories->Append(ref new NavCategory(
categoryName,
categoryAutomationName,
StringReference(categoryInitializer.glyph),
resProvider.GetResourceString(nameResourceKey + "AccessKey"),
groupMode,
categoryInitializer.viewMode,
categoryInitializer.supportsNegative));
m_Categories->Append(ref new NavCategory(categoryName, categoryAutomationName, StringReference(categoryInitializer.glyph),
resProvider.GetResourceString(nameResourceKey + "AccessKey"), groupMode, categoryInitializer.viewMode,
categoryInitializer.supportsNegative));
}
}
}
IObservableVector<NavCategoryGroup^>^ NavCategoryGroup::CreateMenuOptions()
IObservableVector<NavCategoryGroup ^> ^ NavCategoryGroup::CreateMenuOptions()
{
auto menuOptions = ref new Vector<NavCategoryGroup^>();
auto menuOptions = ref new Vector<NavCategoryGroup ^>();
menuOptions->Append(CreateCalculatorCategory());
menuOptions->Append(CreateConverterCategory());
return menuOptions;
}
NavCategoryGroup^ NavCategoryGroup::CreateCalculatorCategory()
NavCategoryGroup ^ NavCategoryGroup::CreateCalculatorCategory()
{
return ref new NavCategoryGroup(s_categoryGroupManifest.at(0));
}
NavCategoryGroup^ NavCategoryGroup::CreateConverterCategory()
NavCategoryGroup ^ NavCategoryGroup::CreateConverterCategory()
{
return ref new NavCategoryGroup(s_categoryGroupManifest.at(1));
}
@ -357,23 +314,15 @@ vector<NavCategoryInitializer> NavCategoryGroup::GetInitializerCategoryGroup(Cat
{
vector<NavCategoryInitializer> initializers{};
copy_if(begin(s_categoryManifest), end(s_categoryManifest), back_inserter(initializers),
[groupType](const NavCategoryInitializer& initializer)
{
return initializer.groupType == groupType;
});
[groupType](const NavCategoryInitializer& initializer) { return initializer.groupType == groupType; });
return initializers;
}
String^ NavCategoryGroup::GetHeaderResourceKey(CategoryGroupType type)
String ^ NavCategoryGroup::GetHeaderResourceKey(CategoryGroupType type)
{
auto iter = find_if(begin(s_categoryGroupManifest), end(s_categoryGroupManifest),
[type](const NavCategoryGroupInitializer& initializer)
{
return initializer.type == type;
});
[type](const NavCategoryGroupInitializer& initializer) { return initializer.type == type; });
return (iter != s_categoryGroupManifest.end())
? StringReference(iter->headerResourceKey)
: nullptr;
return (iter != s_categoryGroupManifest.end()) ? StringReference(iter->headerResourceKey) : nullptr;
}

View file

@ -24,7 +24,8 @@ namespace CalculatorApp
// Don't change the order of these enums
// and definitely don't use int arithmetic
// to change modes.
public enum class ViewMode
public
enum class ViewMode
{
None = -1,
Standard = 0,
@ -46,81 +47,74 @@ namespace CalculatorApp
Currency = 16
};
public enum class CategoryGroupType
public
enum class CategoryGroupType
{
None = -1,
Calculator = 0,
Converter = 1
};
private struct NavCategoryInitializer
private
struct NavCategoryInitializer
{
constexpr NavCategoryInitializer(
ViewMode mode,
int id,
wchar_t const * name,
wchar_t const * nameKey,
wchar_t const * glyph,
CategoryGroupType group,
MyVirtualKey vKey,
bool categorySupportsNegative)
:
viewMode(mode),
serializationId(id),
friendlyName(name),
nameResourceKey(nameKey),
glyph(glyph),
groupType(group),
virtualKey(vKey),
supportsNegative(categorySupportsNegative)
{}
constexpr NavCategoryInitializer(ViewMode mode, int id, wchar_t const* name, wchar_t const* nameKey, wchar_t const* glyph, CategoryGroupType group,
MyVirtualKey vKey, bool categorySupportsNegative)
: viewMode(mode)
, serializationId(id)
, friendlyName(name)
, nameResourceKey(nameKey)
, glyph(glyph)
, groupType(group)
, virtualKey(vKey)
, supportsNegative(categorySupportsNegative)
{
}
const ViewMode viewMode;
const int serializationId;
const wchar_t * const friendlyName;
const wchar_t * const nameResourceKey;
const wchar_t * const glyph;
const wchar_t* const friendlyName;
const wchar_t* const nameResourceKey;
const wchar_t* const glyph;
const CategoryGroupType groupType;
const MyVirtualKey virtualKey;
const bool supportsNegative;
};
private struct NavCategoryGroupInitializer
private
struct NavCategoryGroupInitializer
{
constexpr NavCategoryGroupInitializer(CategoryGroupType t, wchar_t const * h, wchar_t const * n, wchar_t const * a) :
type(t), headerResourceKey(h), modeResourceKey(n), automationResourceKey(a)
{}
constexpr NavCategoryGroupInitializer(CategoryGroupType t, wchar_t const* h, wchar_t const* n, wchar_t const* a)
: type(t), headerResourceKey(h), modeResourceKey(n), automationResourceKey(a)
{
}
const CategoryGroupType type;
const wchar_t *headerResourceKey;
const wchar_t *modeResourceKey;
const wchar_t *automationResourceKey;
const wchar_t* headerResourceKey;
const wchar_t* modeResourceKey;
const wchar_t* automationResourceKey;
};
[Windows::UI::Xaml::Data::Bindable]
public ref class NavCategory sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
[Windows::UI::Xaml::Data::Bindable] public ref class NavCategory sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
{
public:
OBSERVABLE_OBJECT();
property Platform::String^ Name
{
Platform::String^ get() { return m_name; }
}
property Platform::String
^ Name { Platform::String ^ get() { return m_name; } }
property Platform::String^ AutomationName
{
Platform::String^ get() { return m_automationName; }
}
property Platform::String
^ AutomationName { Platform::String ^ get() { return m_automationName; } }
property Platform::String^ Glyph
{
Platform::String^ get() { return m_glyph; }
}
property Platform::String
^ Glyph { Platform::String ^ get() { return m_glyph; } }
property int Position
property int Position
{
int get() { return m_position; }
int get()
{
return m_position;
}
}
property ViewMode Mode
@ -131,24 +125,13 @@ namespace CalculatorApp
}
}
property Platform::String^ AutomationId
{
Platform::String^ get()
{
return m_viewMode.ToString();
}
}
property Platform::String
^ AutomationId { Platform::String ^ get() { return m_viewMode.ToString(); } }
property Platform::String^ AccessKey
{
Platform::String^ get()
{
return m_accessKey;
}
}
property Platform::String
^ AccessKey { Platform::String ^ get() { return m_accessKey; } }
property bool SupportsNegative
property bool SupportsNegative
{
bool get()
{
@ -158,16 +141,16 @@ namespace CalculatorApp
// For saving/restoring last mode used.
static int Serialize(ViewMode mode);
static ViewMode Deserialize(Platform::Object^ obj);
static ViewMode GetViewModeForFriendlyName(Platform::String^ name);
static ViewMode Deserialize(Platform::Object ^ obj);
static ViewMode GetViewModeForFriendlyName(Platform::String ^ name);
static bool IsValidViewMode(ViewMode mode);
static bool IsCalculatorViewMode(ViewMode mode);
static bool IsDateCalculatorViewMode(ViewMode mode);
static bool IsConverterViewMode(ViewMode mode);
static Platform::String^ GetFriendlyName(ViewMode mode);
static Platform::String^ GetNameResourceKey(ViewMode mode);
static Platform::String ^ GetFriendlyName(ViewMode mode);
static Platform::String ^ GetNameResourceKey(ViewMode mode);
static CategoryGroupType GetGroupType(ViewMode mode);
// GetIndex is 0-based, GetPosition is 1-based
@ -178,15 +161,15 @@ namespace CalculatorApp
static ViewMode GetViewModeForVirtualKey(MyVirtualKey virtualKey);
internal:
NavCategory(Platform::String^ name, Platform::String^ automationName, Platform::String^ glyph, Platform::String^ accessKey, Platform::String^ mode, ViewMode viewMode, bool supportsNegative) :
m_name(name),
m_automationName(automationName),
m_glyph(glyph),
m_accessKey(accessKey),
m_mode(mode),
m_viewMode(viewMode),
m_supportsNegative(supportsNegative)
internal : NavCategory(Platform::String ^ name, Platform::String ^ automationName, Platform::String ^ glyph, Platform::String ^ accessKey,
Platform::String ^ mode, ViewMode viewMode, bool supportsNegative)
: m_name(name)
, m_automationName(automationName)
, m_glyph(glyph)
, m_accessKey(accessKey)
, m_mode(mode)
, m_viewMode(viewMode)
, m_supportsNegative(supportsNegative)
{
m_position = NavCategory::GetPosition(m_viewMode);
}
@ -197,33 +180,30 @@ namespace CalculatorApp
static bool IsModeInCategoryGroup(ViewMode mode, CategoryGroupType groupType);
ViewMode m_viewMode;
Platform::String^ m_name;
Platform::String^ m_automationName;
Platform::String^ m_glyph;
Platform::String^ m_accessKey;
Platform::String^ m_mode;
Platform::String ^ m_name;
Platform::String ^ m_automationName;
Platform::String ^ m_glyph;
Platform::String ^ m_accessKey;
Platform::String ^ m_mode;
int m_position;
bool m_supportsNegative;
};
[Windows::UI::Xaml::Data::Bindable]
public ref class NavCategoryGroup sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
[Windows::UI::Xaml::Data::Bindable] public ref class NavCategoryGroup sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
{
public:
OBSERVABLE_OBJECT();
OBSERVABLE_PROPERTY_R(Platform::String^, Name);
OBSERVABLE_PROPERTY_R(Platform::String^, AutomationName);
OBSERVABLE_PROPERTY_R(Platform::String ^, Name);
OBSERVABLE_PROPERTY_R(Platform::String ^, AutomationName);
OBSERVABLE_PROPERTY_R(CategoryGroupType, GroupType);
OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector<NavCategory^>^, Categories);
OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector<NavCategory ^> ^, Categories);
static Windows::Foundation::Collections::IObservableVector<NavCategoryGroup^>^ CreateMenuOptions();
static Windows::Foundation::Collections::IObservableVector<NavCategoryGroup ^> ^ CreateMenuOptions();
static Platform::String^ GetHeaderResourceKey(CategoryGroupType type);
static Platform::String ^ GetHeaderResourceKey(CategoryGroupType type);
internal:
static NavCategoryGroup^ CreateCalculatorCategory();
static NavCategoryGroup^ CreateConverterCategory();
internal : static NavCategoryGroup ^ CreateCalculatorCategory();
static NavCategoryGroup ^ CreateConverterCategory();
private:
NavCategoryGroup(const NavCategoryGroupInitializer& groupInitializer);

View file

@ -10,9 +10,8 @@ using namespace Windows::Networking::Connectivity;
NetworkManager::NetworkManager()
{
m_NetworkStatusChangedToken =
NetworkInformation::NetworkStatusChanged += ref new NetworkStatusChangedEventHandler(
this, &NetworkManager::OnNetworkStatusChange, CallbackContext::Same);
m_NetworkStatusChangedToken = NetworkInformation::NetworkStatusChanged +=
ref new NetworkStatusChangedEventHandler(this, &NetworkManager::OnNetworkStatusChange, CallbackContext::Same);
}
NetworkManager::~NetworkManager()
@ -23,14 +22,13 @@ NetworkManager::~NetworkManager()
NetworkAccessBehavior NetworkManager::GetNetworkAccessBehavior()
{
NetworkAccessBehavior behavior = NetworkAccessBehavior::Offline;
ConnectionProfile^ connectionProfile = NetworkInformation::GetInternetConnectionProfile();
ConnectionProfile ^ connectionProfile = NetworkInformation::GetInternetConnectionProfile();
if (connectionProfile != nullptr)
{
NetworkConnectivityLevel connectivityLevel = connectionProfile->GetNetworkConnectivityLevel();
if (connectivityLevel == NetworkConnectivityLevel::InternetAccess
|| connectivityLevel == NetworkConnectivityLevel::ConstrainedInternetAccess)
if (connectivityLevel == NetworkConnectivityLevel::InternetAccess || connectivityLevel == NetworkConnectivityLevel::ConstrainedInternetAccess)
{
ConnectionCost^ connectionCost = connectionProfile->GetConnectionCost();
ConnectionCost ^ connectionCost = connectionProfile->GetConnectionCost();
behavior = ConvertCostInfoToBehavior(connectionCost);
}
}
@ -38,16 +36,15 @@ NetworkAccessBehavior NetworkManager::GetNetworkAccessBehavior()
return behavior;
}
void NetworkManager::OnNetworkStatusChange(_In_ Object^ /*sender*/)
void NetworkManager::OnNetworkStatusChange(_In_ Object ^ /*sender*/)
{
NetworkBehaviorChanged(GetNetworkAccessBehavior());
}
// See app behavior guidelines at https://msdn.microsoft.com/en-us/library/windows/apps/xaml/jj835821(v=win.10).aspx
NetworkAccessBehavior NetworkManager::ConvertCostInfoToBehavior(_In_ ConnectionCost^ connectionCost)
NetworkAccessBehavior NetworkManager::ConvertCostInfoToBehavior(_In_ ConnectionCost ^ connectionCost)
{
if (connectionCost->Roaming || connectionCost->OverDataLimit
|| connectionCost->NetworkCostType == NetworkCostType::Variable
if (connectionCost->Roaming || connectionCost->OverDataLimit || connectionCost->NetworkCostType == NetworkCostType::Variable
|| connectionCost->NetworkCostType == NetworkCostType::Fixed)
{
return NetworkAccessBehavior::OptIn;

View file

@ -5,29 +5,32 @@
namespace CalculatorApp
{
public enum class NetworkAccessBehavior
public
enum class NetworkAccessBehavior
{
Normal = 0,
OptIn = 1,
Offline = 2
};
public delegate void NetworkBehaviorChangedHandler(NetworkAccessBehavior behavior);
public
delegate void NetworkBehaviorChangedHandler(NetworkAccessBehavior behavior);
public ref class NetworkManager sealed
public
ref class NetworkManager sealed
{
public:
NetworkManager();
static NetworkAccessBehavior GetNetworkAccessBehavior();
event NetworkBehaviorChangedHandler^ NetworkBehaviorChanged;
event NetworkBehaviorChangedHandler ^ NetworkBehaviorChanged;
private:
~NetworkManager();
void OnNetworkStatusChange(_In_ Platform::Object^ sender);
static NetworkAccessBehavior ConvertCostInfoToBehavior(_In_ Windows::Networking::Connectivity::ConnectionCost^ connectionCost);
void OnNetworkStatusChange(_In_ Platform::Object ^ sender);
static NetworkAccessBehavior ConvertCostInfoToBehavior(_In_ Windows::Networking::Connectivity::ConnectionCost ^ connectionCost);
private:
Windows::Foundation::EventRegistrationToken m_NetworkStatusChangedToken;

View file

@ -11,30 +11,19 @@ namespace CalculatorApp
class TraceActivity
{
public:
TraceActivity() :
m_channel(nullptr),
m_activity(nullptr),
m_fields(nullptr)
{ }
TraceActivity() : m_channel(nullptr), m_activity(nullptr), m_fields(nullptr)
{
}
TraceActivity(
winrt::Windows::Foundation::Diagnostics::LoggingChannel channel,
std::wstring_view activityName,
winrt::Windows::Foundation::Diagnostics::LoggingFields fields) :
m_channel(channel),
m_activityName(activityName),
m_fields(fields),
m_activity(nullptr)
TraceActivity(winrt::Windows::Foundation::Diagnostics::LoggingChannel channel, std::wstring_view activityName,
winrt::Windows::Foundation::Diagnostics::LoggingFields fields)
: m_channel(channel), m_activityName(activityName), m_fields(fields), m_activity(nullptr)
{
// Write the activity's START event. Note that you must not specify keyword
// or level for START and STOP events because they always use the activity's
// keyword and level.
m_activity = m_channel.StartActivity(
m_activityName,
m_fields,
winrt::Windows::Foundation::Diagnostics::LoggingLevel::Verbose,
winrt::Windows::Foundation::Diagnostics::LoggingOptions(WINEVENT_KEYWORD_RESPONSE_TIME)
);
m_activity = m_channel.StartActivity(m_activityName, m_fields, winrt::Windows::Foundation::Diagnostics::LoggingLevel::Verbose,
winrt::Windows::Foundation::Diagnostics::LoggingOptions(WINEVENT_KEYWORD_RESPONSE_TIME));
}
~TraceActivity()

View file

@ -21,74 +21,72 @@ namespace CalculatorApp
{
static multimap<int, vector<wstring>> s_memoryMap;
static constexpr array<const wchar_t * const, 9> s_programmerType{
L"N/A", L"QwordType", L"DwordType",
L"WordType", L"ByteType", L"HexBase",
L"DecBase", L"OctBase", L"BinBase" };
static constexpr array<const wchar_t* const, 9> s_programmerType{ L"N/A", L"QwordType", L"DwordType", L"WordType", L"ByteType",
L"HexBase", L"DecBase", L"OctBase", L"BinBase" };
static reader_writer_lock s_traceLoggerLock;
// Telemetry events. Uploaded to asimov.
constexpr auto EVENT_NAME_DEBUG = L"Debug";
constexpr auto EVENT_NAME_ERROR = L"ErrorMessage";
constexpr auto EVENT_NAME_APP_PRELAUNCHED_BY_SYSTEM = L"AppPrelaunchedBySystem";
constexpr auto EVENT_NAME_PRELAUNCHED_APP_ACTIVATED_BY_USER = L"PrelaunchedAppActivatedByUser";
constexpr auto EVENT_NAME_APP_LAUNCH_BEGIN = L"AppLaunchBegin";
constexpr auto EVENT_NAME_APP_LAUNCH_END = L"AppLaunchEnd";
constexpr auto EVENT_NAME_APP_RESUME_END = L"AppResumeEnd";
constexpr auto EVENT_NAME_PREVIOUS_STATE_WINDOW_ON_CREATION = L"PreviousStateOnWindowCreation";
constexpr auto EVENT_NAME_SIZE_ON_SUSPENSION = L"CalculatorSizeOnSuspension";
constexpr auto EVENT_NAME_CALCULATOR_VIEWED_IN_SESSION = L"CalculatorViewedInSession";
constexpr auto EVENT_NAME_DATE_CALCULATOR_VIEWED_IN_SESSION = L"DateCalculatorViewedInSession";
constexpr auto EVENT_NAME_CONVERTER_VIEWED_IN_SESSION = L"ConverterViewedInSession";
constexpr auto EVENT_NAME_MODE_CHANGE_BEGIN = L"ModeChangeBegin";
constexpr auto EVENT_NAME_MODE_CHANGE_END = L"ModeChangeEnd";
constexpr auto EVENT_NAME_HISTORY_BODY_OPENED = L"HistoryBodyOpened";
constexpr auto EVENT_NAME_HISTORY_ITEM_LOAD_BEGIN = L"HistoryItemLoadBegin";
constexpr auto EVENT_NAME_HISTORY_ITEM_LOAD_END = L"HistoryItemLoadEnd";
constexpr auto EVENT_NAME_HISTORY_FLYOUT_OPEN_BEGIN = L"HistoryFlyoutOpenBegin";
constexpr auto EVENT_NAME_HISTORY_FLYOUT_OPEN_END = L"HistoryFlyoutOpenEnd";
constexpr auto EVENT_NAME_NEW_WINDOW_CREATION_BEGIN = L"NewWindowCreationBegin";
constexpr auto EVENT_NAME_NEW_WINDOW_CREATION_END = L"NewWindowCreationEnd";
constexpr auto EVENT_NAME_HISTORY_CLEAR = L"HistoryClearBegin";
constexpr auto EVENT_NAME_MULTIPLE_MEMORY_USED = L"MultipleMemoryUsed";
constexpr auto EVENT_NAME_SINGLE_MEMORY_USED = L"SingleMemoryUsed";
constexpr auto EVENT_NAME_SHARED_MEMORY_USED = L"SharedMemoryUsed";
constexpr auto EVENT_NAME_MEMORY_BODY_OPENED = L"MemoryBodyOpened";
constexpr auto EVENT_NAME_MEMORY_FLYOUT_OPEN_BEGIN = L"MemoryFlyoutOpenBegin";
constexpr auto EVENT_NAME_MEMORY_FLYOUT_OPEN_END = L"MemoryFlyoutOpenEnd";
constexpr auto EVENT_NAME_MEMORY_CLEAR_ALL = L"MemoryClearAll";
constexpr auto EVENT_NAME_INVALID_PASTED_INPUT_OCCURRED = L"InvalidPastedInputOccurred";
constexpr auto EVENT_NAME_VALID_INPUT_PASTED = L"ValidInputPasted";
constexpr auto EVENT_NAME_BITFLIP_PANE_CLICKED = L"BitFlipPaneClicked";
constexpr auto EVENT_NAME_BITFLIP_BUTTONS_USED = L"BitFlipToggleButtonUsed";
constexpr auto EVENT_NAME_ANGLE_BUTTONS_USED = L"AngleButtonUsedInSession";
constexpr auto EVENT_NAME_HYP_BUTTON_USED = L"HypButtonUsedInSession";
constexpr auto EVENT_NAME_FUNCTION_USAGE = L"FunctionUsageInSession";
constexpr auto EVENT_NAME_BITLENGTH_BUTTON_USED = L"BitLengthButtonUsed";
constexpr auto EVENT_NAME_RADIX_BUTTON_USED = L"RadixButtonUsed";
constexpr auto EVENT_NAME_MAX_WINDOW_COUNT = L"MaxWindowCountInSession";
constexpr auto EVENT_NAME_WINDOW_LAUNCHED_PROTOCOL = L"WindowActivatedThroughProtocol";
constexpr auto EVENT_NAME_WINDOW_LAUNCHED_TILESEARCH = L"WindowLaunchedThroughTile";
constexpr auto EVENT_NAME_DATE_DIFFERENCE_USED = L"DateDifferenceModeUsed";
constexpr auto EVENT_NAME_DATE_ADD_SUBTRACT_USED = L"DateAddSubtractModeUsed";
constexpr auto EVENT_NAME_DATE_DIFFERENCE_FOUND = L"DateDifferenceFound";
constexpr auto EVENT_NAME_HIDE_IF_SHOWN = L"HideIfShown";
constexpr auto EVENT_NAME_ABOUT_FLYOUT_OPENED = L"AboutFlyoutOpened";
constexpr auto EVENT_NAME_NAV_BAR_OPENED = L"NavBarOpened";
constexpr auto EVENT_NAME_CORE_WINDOW_WAS_NULL = L"CoreWindowWasNull";
constexpr auto EVENT_NAME_DEBUG = L"Debug";
constexpr auto EVENT_NAME_ERROR = L"ErrorMessage";
constexpr auto EVENT_NAME_APP_PRELAUNCHED_BY_SYSTEM = L"AppPrelaunchedBySystem";
constexpr auto EVENT_NAME_PRELAUNCHED_APP_ACTIVATED_BY_USER = L"PrelaunchedAppActivatedByUser";
constexpr auto EVENT_NAME_APP_LAUNCH_BEGIN = L"AppLaunchBegin";
constexpr auto EVENT_NAME_APP_LAUNCH_END = L"AppLaunchEnd";
constexpr auto EVENT_NAME_APP_RESUME_END = L"AppResumeEnd";
constexpr auto EVENT_NAME_PREVIOUS_STATE_WINDOW_ON_CREATION = L"PreviousStateOnWindowCreation";
constexpr auto EVENT_NAME_SIZE_ON_SUSPENSION = L"CalculatorSizeOnSuspension";
constexpr auto EVENT_NAME_CALCULATOR_VIEWED_IN_SESSION = L"CalculatorViewedInSession";
constexpr auto EVENT_NAME_DATE_CALCULATOR_VIEWED_IN_SESSION = L"DateCalculatorViewedInSession";
constexpr auto EVENT_NAME_CONVERTER_VIEWED_IN_SESSION = L"ConverterViewedInSession";
constexpr auto EVENT_NAME_MODE_CHANGE_BEGIN = L"ModeChangeBegin";
constexpr auto EVENT_NAME_MODE_CHANGE_END = L"ModeChangeEnd";
constexpr auto EVENT_NAME_HISTORY_BODY_OPENED = L"HistoryBodyOpened";
constexpr auto EVENT_NAME_HISTORY_ITEM_LOAD_BEGIN = L"HistoryItemLoadBegin";
constexpr auto EVENT_NAME_HISTORY_ITEM_LOAD_END = L"HistoryItemLoadEnd";
constexpr auto EVENT_NAME_HISTORY_FLYOUT_OPEN_BEGIN = L"HistoryFlyoutOpenBegin";
constexpr auto EVENT_NAME_HISTORY_FLYOUT_OPEN_END = L"HistoryFlyoutOpenEnd";
constexpr auto EVENT_NAME_NEW_WINDOW_CREATION_BEGIN = L"NewWindowCreationBegin";
constexpr auto EVENT_NAME_NEW_WINDOW_CREATION_END = L"NewWindowCreationEnd";
constexpr auto EVENT_NAME_HISTORY_CLEAR = L"HistoryClearBegin";
constexpr auto EVENT_NAME_MULTIPLE_MEMORY_USED = L"MultipleMemoryUsed";
constexpr auto EVENT_NAME_SINGLE_MEMORY_USED = L"SingleMemoryUsed";
constexpr auto EVENT_NAME_SHARED_MEMORY_USED = L"SharedMemoryUsed";
constexpr auto EVENT_NAME_MEMORY_BODY_OPENED = L"MemoryBodyOpened";
constexpr auto EVENT_NAME_MEMORY_FLYOUT_OPEN_BEGIN = L"MemoryFlyoutOpenBegin";
constexpr auto EVENT_NAME_MEMORY_FLYOUT_OPEN_END = L"MemoryFlyoutOpenEnd";
constexpr auto EVENT_NAME_MEMORY_CLEAR_ALL = L"MemoryClearAll";
constexpr auto EVENT_NAME_INVALID_PASTED_INPUT_OCCURRED = L"InvalidPastedInputOccurred";
constexpr auto EVENT_NAME_VALID_INPUT_PASTED = L"ValidInputPasted";
constexpr auto EVENT_NAME_BITFLIP_PANE_CLICKED = L"BitFlipPaneClicked";
constexpr auto EVENT_NAME_BITFLIP_BUTTONS_USED = L"BitFlipToggleButtonUsed";
constexpr auto EVENT_NAME_ANGLE_BUTTONS_USED = L"AngleButtonUsedInSession";
constexpr auto EVENT_NAME_HYP_BUTTON_USED = L"HypButtonUsedInSession";
constexpr auto EVENT_NAME_FUNCTION_USAGE = L"FunctionUsageInSession";
constexpr auto EVENT_NAME_BITLENGTH_BUTTON_USED = L"BitLengthButtonUsed";
constexpr auto EVENT_NAME_RADIX_BUTTON_USED = L"RadixButtonUsed";
constexpr auto EVENT_NAME_MAX_WINDOW_COUNT = L"MaxWindowCountInSession";
constexpr auto EVENT_NAME_WINDOW_LAUNCHED_PROTOCOL = L"WindowActivatedThroughProtocol";
constexpr auto EVENT_NAME_WINDOW_LAUNCHED_TILESEARCH = L"WindowLaunchedThroughTile";
constexpr auto EVENT_NAME_DATE_DIFFERENCE_USED = L"DateDifferenceModeUsed";
constexpr auto EVENT_NAME_DATE_ADD_SUBTRACT_USED = L"DateAddSubtractModeUsed";
constexpr auto EVENT_NAME_DATE_DIFFERENCE_FOUND = L"DateDifferenceFound";
constexpr auto EVENT_NAME_HIDE_IF_SHOWN = L"HideIfShown";
constexpr auto EVENT_NAME_ABOUT_FLYOUT_OPENED = L"AboutFlyoutOpened";
constexpr auto EVENT_NAME_NAV_BAR_OPENED = L"NavBarOpened";
constexpr auto EVENT_NAME_CORE_WINDOW_WAS_NULL = L"CoreWindowWasNull";
constexpr auto EVENT_NAME_EXCEPTION = L"Exception";
constexpr auto EVENT_NAME_EXCEPTION = L"Exception";
constexpr auto PDT_PRIVACY_DATA_TAG = L"PartA_PrivTags";
constexpr auto PDT_PRODUCT_AND_SERVICE_USAGE = 0x0000'0000'0200'0000u;
constexpr auto PDT_PRIVACY_DATA_TAG = L"PartA_PrivTags";
constexpr auto PDT_PRODUCT_AND_SERVICE_USAGE = 0x0000'0000'0200'0000u;
#ifdef SEND_TELEMETRY
// c.f. WINEVENT_KEYWORD_RESERVED_63-56 0xFF00000000000000 // Bits 63-56 - channel keywords
// c.f. WINEVENT_KEYWORD_* 0x00FF000000000000 // Bits 55-48 - system-reserved keywords
constexpr int64_t MICROSOFT_KEYWORD_CRITICAL_DATA = 0x0000800000000000; // Bit 47
constexpr int64_t MICROSOFT_KEYWORD_MEASURES = 0x0000400000000000; // Bit 46
constexpr int64_t MICROSOFT_KEYWORD_TELEMETRY = 0x0000200000000000; // Bit 45
constexpr int64_t MICROSOFT_KEYWORD_RESERVED_44 = 0x0000100000000000; // Bit 44 (reserved for future assignment)
constexpr int64_t MICROSOFT_KEYWORD_MEASURES = 0x0000400000000000; // Bit 46
constexpr int64_t MICROSOFT_KEYWORD_TELEMETRY = 0x0000200000000000; // Bit 45
constexpr int64_t MICROSOFT_KEYWORD_RESERVED_44 = 0x0000100000000000; // Bit 44 (reserved for future assignment)
#else
// define all Keyword options as 0 when we do not want to upload app telemetry
constexpr int64_t MICROSOFT_KEYWORD_CRITICAL_DATA = 0;
@ -99,11 +97,12 @@ namespace CalculatorApp
#pragma region TraceLogger setup and cleanup
TraceLogger::TraceLogger() :
g_calculatorProvider(
TraceLogger::TraceLogger()
: g_calculatorProvider(
L"MicrosoftCalculator",
LoggingChannelOptions(GUID{ 0x4f50731a, 0x89cf, 0x4782, 0xb3, 0xe0, 0xdc, 0xe8, 0xc9, 0x4, 0x76, 0xba }), // Microsoft Telemetry group
GUID{ 0x905ca09, 0x610e, 0x401e, 0xb6, 0x50, 0x2f, 0x21, 0x29, 0x80, 0xb9, 0xe0 }), // Unique providerID {0905CA09-610E-401E-B650-2F212980B9E0}
GUID{ 0x905ca09, 0x610e, 0x401e, 0xb6, 0x50, 0x2f, 0x21, 0x29, 0x80, 0xb9, 0xe0 })
, // Unique providerID {0905CA09-610E-401E-B650-2F212980B9E0}
m_appLaunchActivity{ nullptr }
{
// initialize the function array
@ -307,7 +306,8 @@ namespace CalculatorApp
void TraceLogger::LogSharedMemoryUsed(wstring_view fromMode, wstring_view toMode, unsigned int memorySize) const
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{};
fields.AddString(L"FromMode", fromMode);
@ -318,7 +318,8 @@ namespace CalculatorApp
void TraceLogger::LogBitFlipPaneClicked() const
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{};
LogTelemetryEvent(EVENT_NAME_BITFLIP_PANE_CLICKED, fields);
@ -326,7 +327,8 @@ namespace CalculatorApp
void TraceLogger::LogBitFlipUsed() const
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{};
LogTelemetryEvent(EVENT_NAME_BITFLIP_BUTTONS_USED, fields);
@ -339,11 +341,8 @@ namespace CalculatorApp
if (!isAppLaunchBeginLogged)
{
m_appLaunchActivity = g_calculatorProvider.StartActivity(
EVENT_NAME_APP_LAUNCH_BEGIN,
nullptr,
LoggingLevel::Verbose,
LoggingOptions(MICROSOFT_KEYWORD_TELEMETRY));
m_appLaunchActivity =
g_calculatorProvider.StartActivity(EVENT_NAME_APP_LAUNCH_BEGIN, nullptr, LoggingLevel::Verbose, LoggingOptions(MICROSOFT_KEYWORD_TELEMETRY));
isAppLaunchBeginLogged = true;
}
@ -376,7 +375,8 @@ namespace CalculatorApp
void TraceLogger::LogDebug(wstring_view debugData)
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{};
fields.AddString(L"DebugData", debugData);
@ -385,7 +385,8 @@ namespace CalculatorApp
void TraceLogger::LogOnAppLaunch(wstring_view previousExecutionState) const
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{};
fields.AddString(L"PreviousExecutionState", previousExecutionState);
@ -394,7 +395,8 @@ namespace CalculatorApp
void TraceLogger::LogAboutFlyoutOpened() const
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{};
LogTelemetryEvent(EVENT_NAME_ABOUT_FLYOUT_OPENED, fields);
@ -402,7 +404,8 @@ namespace CalculatorApp
void TraceLogger::LogNavBarOpened() const
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{};
LogTelemetryEvent(EVENT_NAME_NAV_BAR_OPENED, fields);
@ -410,7 +413,8 @@ namespace CalculatorApp
void TraceLogger::LogClearHistory() const
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{};
LogTelemetryEvent(EVENT_NAME_HISTORY_CLEAR, fields);
@ -418,7 +422,8 @@ namespace CalculatorApp
void TraceLogger::LogHistoryFlyoutOpenBegin(unsigned int historyItemCount) const
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
// we want to record the event only when history item count is atleast 20
if (historyItemCount >= 20)
@ -431,7 +436,8 @@ namespace CalculatorApp
void TraceLogger::LogHistoryFlyoutOpenEnd(int historyItemCount) const
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
if (historyItemCount >= 20)
{
@ -443,7 +449,8 @@ namespace CalculatorApp
void TraceLogger::LogHistoryBodyOpened() const
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{};
LogTelemetryEvent(EVENT_NAME_HISTORY_BODY_OPENED, fields);
@ -451,7 +458,8 @@ namespace CalculatorApp
void TraceLogger::LogMemoryFlyoutOpenBegin(unsigned int memoryItemCount) const
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
// we want to record the event only when memory item count is atleast 4
if (memoryItemCount >= 4)
@ -464,7 +472,8 @@ namespace CalculatorApp
void TraceLogger::LogMemoryFlyoutOpenEnd(unsigned int memoryItemCount) const
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
if (memoryItemCount >= 4)
{
@ -476,7 +485,8 @@ namespace CalculatorApp
void TraceLogger::LogMemoryBodyOpened() const
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{};
LogTelemetryEvent(EVENT_NAME_MEMORY_BODY_OPENED, fields);
@ -487,7 +497,8 @@ namespace CalculatorApp
// Use of this function is to analyze perf of mode change.
void TraceLogger::LogModeChangeBegin(ViewMode fromMode, ViewMode toMode, int windowId)
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
if (NavCategory::IsValidViewMode(fromMode) && NavCategory::IsValidViewMode(toMode))
{
@ -502,7 +513,8 @@ namespace CalculatorApp
// comment: same as LogModeChangeBegin
void TraceLogger::LogModeChangeEnd(ViewMode toMode, int windowId) const
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
if (NavCategory::IsValidViewMode(toMode))
{
@ -515,7 +527,8 @@ namespace CalculatorApp
void TraceLogger::LogHistoryItemLoadBegin() const
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{};
LogTelemetryEvent(EVENT_NAME_HISTORY_ITEM_LOAD_BEGIN, fields);
@ -523,7 +536,8 @@ namespace CalculatorApp
void TraceLogger::LogHistoryItemLoadEnd(unsigned int historyTokenCount) const
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{};
fields.AddUInt32(L"HistoryTokenCount", historyTokenCount);
@ -532,7 +546,8 @@ namespace CalculatorApp
void TraceLogger::LogNewWindowCreationBegin(int windowId)
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{};
fields.AddUInt32(L"WindowId", windowId);
@ -541,7 +556,8 @@ namespace CalculatorApp
void TraceLogger::LogNewWindowCreationEnd(int windowId)
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{};
fields.AddUInt32(L"WindowId", windowId);
@ -550,7 +566,8 @@ namespace CalculatorApp
void TraceLogger::LogError(wstring_view errorString)
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{};
fields.AddString(L"ErrorString", errorString);
@ -559,7 +576,8 @@ namespace CalculatorApp
void TraceLogger::LogPrelaunchedAppActivatedByUser()
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{};
LogTelemetryEvent(EVENT_NAME_PRELAUNCHED_APP_ACTIVATED_BY_USER, fields);
@ -567,7 +585,8 @@ namespace CalculatorApp
void TraceLogger::LogAppPrelaunchedBySystem()
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{};
LogTelemetryEvent(EVENT_NAME_APP_PRELAUNCHED_BY_SYSTEM, fields);
@ -588,9 +607,11 @@ namespace CalculatorApp
}
}
void TraceLogger::LogMemoryUsed(int windowId, unsigned int slotPosition, bool isStandard, bool isScientific, bool isProgrammer, unsigned int memorySize) const
void TraceLogger::LogMemoryUsed(int windowId, unsigned int slotPosition, bool isStandard, bool isScientific, bool isProgrammer,
unsigned int memorySize) const
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
// Reader lock for the static resources
reader_writer_lock::scoped_lock_read lock(s_traceLoggerLock);
@ -625,7 +646,8 @@ namespace CalculatorApp
void TraceLogger::LogMultipleMemoryUsed(unsigned int slotPosition, unsigned int memorySize) const
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{};
fields.AddUInt32(L"MemoryIndex", slotPosition);
@ -635,7 +657,8 @@ namespace CalculatorApp
void TraceLogger::LogSingleMemoryUsed(unsigned int memorySize) const
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{};
fields.AddUInt32(L"MemoryListSize", memorySize);
@ -644,7 +667,8 @@ namespace CalculatorApp
void TraceLogger::LogInvalidPastedInputOccurred(wstring_view reason, ViewMode mode, int programmerNumberBase, int bitLengthType)
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{};
fields.AddString(L"Mode", NavCategory::GetFriendlyName(mode)->Data());
@ -657,7 +681,8 @@ namespace CalculatorApp
void TraceLogger::LogValidInputPasted(ViewMode mode) const
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{};
fields.AddString(L"Mode", NavCategory::GetFriendlyName(mode)->Data());
@ -666,7 +691,8 @@ namespace CalculatorApp
void TraceLogger::LogStandardException(wstring_view functionName, const exception& e) const
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{};
fields.AddString(L"FunctionName", functionName);
@ -678,7 +704,8 @@ namespace CalculatorApp
void TraceLogger::LogWinRTException(wstring_view functionName, hresult_error const& e) const
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{};
fields.AddString(L"FunctionName", functionName);
@ -687,9 +714,10 @@ namespace CalculatorApp
LogMeasureEvent(EVENT_NAME_EXCEPTION, fields);
}
void TraceLogger::LogPlatformException(wstring_view functionName, Platform::Exception^ e) const
void TraceLogger::LogPlatformException(wstring_view functionName, Platform::Exception ^ e) const
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{};
fields.AddString(L"FunctionName", functionName);
@ -733,11 +761,11 @@ namespace CalculatorApp
{
return s_programmerType[index];
}
//return "N/A"
// return "N/A"
return s_programmerType[0];
}
bool TraceLogger::GetIndex(int &index)
bool TraceLogger::GetIndex(int& index)
{
if (findIndex[index] > 0)
{
@ -755,7 +783,8 @@ namespace CalculatorApp
void TraceLogger::LogMaxWindowCount()
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{};
fields.AddUInt32(L"WindowCount", (unsigned int)maxWindowCount);
@ -764,7 +793,8 @@ namespace CalculatorApp
void TraceLogger::LogWindowActivated() const
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{};
LogTelemetryEvent(EVENT_NAME_WINDOW_LAUNCHED_PROTOCOL, fields);
@ -772,7 +802,8 @@ namespace CalculatorApp
void TraceLogger::LogWindowLaunched() const
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{};
LogTelemetryEvent(EVENT_NAME_WINDOW_LAUNCHED_TILESEARCH, fields);
@ -840,7 +871,8 @@ namespace CalculatorApp
void TraceLogger::LogFunctionUsage(int windowId)
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
for (int i = 0; i < functionCount; i++)
{
@ -897,8 +929,7 @@ namespace CalculatorApp
// Ignore first 3 calls during the initialization of the combo box selected items for Add mode
int firstChangeEventCount = isAddMode ? 4 : 1;
if (((*usageMap)[windowId] == firstChangeEventCount)
&& (!(*isLoggedInSession)))
if (((*usageMap)[windowId] == firstChangeEventCount) && (!(*isLoggedInSession)))
{
LoggingFields fields{};
fields.AddString(L"AddSubtractMode", isAddMode ? L"Add" : L"Subtract");
@ -910,16 +941,12 @@ namespace CalculatorApp
void TraceLogger::LogDateClippedTimeDifferenceFound(Calendar const& today, DateTime const& clippedTime) const
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
auto calendarSystem = today.GetCalendarSystem();
auto clock = today.GetClock();
DateTimeFormatter dtFormatter{
L"longdate shorttime",
{ L"en-US" },
GlobalizationPreferences::HomeGeographicRegion(),
calendarSystem,
clock };
DateTimeFormatter dtFormatter{ L"longdate shorttime", { L"en-US" }, GlobalizationPreferences::HomeGeographicRegion(), calendarSystem, clock };
LoggingFields fields{};
fields.AddString(L"ResolvedCalendarLanguage", today.ResolvedLanguage());
@ -934,7 +961,8 @@ namespace CalculatorApp
void TraceLogger::LogUserRequestedRefreshFailed() const
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{};
LogTelemetryEvent(L"UserRequestedRefreshFailed", fields);
@ -942,7 +970,8 @@ namespace CalculatorApp
void TraceLogger::LogConversionResult(wstring_view fromValue, wstring_view fromUnit, wstring_view toValue, wstring_view toUnit) const
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
wstring behaviorString{};
NetworkAccessBehavior behavior = NetworkManager::GetNetworkAccessBehavior();
@ -979,10 +1008,10 @@ namespace CalculatorApp
void TraceLogger::LogCoreWindowWasNull() const
{
if (!GetTraceLoggingProviderEnabled()) return;
if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{};
LogTelemetryEvent(EVENT_NAME_CORE_WINDOW_WAS_NULL, fields);
}
}

View file

@ -18,7 +18,10 @@ namespace CalculatorApp
public:
int count;
std::wstring funcName;
FuncLog() { count = 0; }
FuncLog()
{
count = 0;
}
FuncLog(std::wstring fName)
{
funcName = fName;
@ -30,7 +33,7 @@ namespace CalculatorApp
{
public:
TraceLogger(_In_ TraceLogger const&) = delete;
TraceLogger const & operator= (_In_ TraceLogger const&) = delete;
TraceLogger const& operator=(_In_ TraceLogger const&) = delete;
~TraceLogger();
static TraceLogger& GetInstance();
bool GetTraceLoggingProviderEnabled() const;
@ -93,21 +96,22 @@ namespace CalculatorApp
// Trace methods for Date Calculator usage
void LogDateDifferenceModeUsed(int windowId);
void LogDateAddSubtractModeUsed(int windowId, bool isAddMode);
void LogDateClippedTimeDifferenceFound(winrt::Windows::Globalization::Calendar const& today, winrt::Windows::Foundation::DateTime const& clippedTime) const;
void LogDateClippedTimeDifferenceFound(winrt::Windows::Globalization::Calendar const& today,
winrt::Windows::Foundation::DateTime const& clippedTime) const;
void LogStandardException(std::wstring_view functionName, _In_ const std::exception& e) const;
void LogWinRTException(std::wstring_view functionName, _In_ winrt::hresult_error const& e) const;
void LogPlatformException(std::wstring_view functionName, _In_ Platform::Exception^ e) const;
void LogPlatformException(std::wstring_view functionName, _In_ Platform::Exception ^ e) const;
private:
// Create an instance of TraceLogger
TraceLogger();
// Any new Log method should
// a) decide the level of logging. This will help us in limiting recording of events only up to a certain level. See this link for guidance https://msdn.microsoft.com/en-us/library/windows/desktop/aa363742(v=vs.85).aspx
// We're using Verbose level for events that are called frequently and needed only for debugging or capturing perf for specific scenarios
// b) should decide whether or not to log to telemetry and pass TraceLoggingKeyword(MICROSOFT_KEYWORD_TELEMETRY) accordingly
// c) Should accept a variable number of additional data arguments if needed
// a) decide the level of logging. This will help us in limiting recording of events only up to a certain level. See this link for guidance
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa363742(v=vs.85).aspx We're using Verbose level for events that are called frequently and
// needed only for debugging or capturing perf for specific scenarios b) should decide whether or not to log to telemetry and pass
// TraceLoggingKeyword(MICROSOFT_KEYWORD_TELEMETRY) accordingly c) Should accept a variable number of additional data arguments if needed
void LogTelemetryEvent(std::wstring_view eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields) const;
void LogMeasureEvent(std::wstring_view eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields) const;
void LogCriticalDataEvent(std::wstring_view eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields) const;
@ -133,7 +137,7 @@ namespace CalculatorApp
bool isHypButtonLogged = false;
bool isAngleButtonInitialized = false;
unsigned int findIndex[maxFunctionSize] = { 0 };
bool GetIndex(int &index);
bool GetIndex(int& index);
std::wstring GetProgrammerType(int index);
size_t maxWindowCount = 0;
bool isAppLaunchBeginLogged = false;

View file

@ -30,12 +30,12 @@ void Utils::IFTPlatformException(HRESULT hr)
{
if (FAILED(hr))
{
Platform::Exception^ exception = ref new Platform::Exception(hr);
Platform::Exception ^ exception = ref new Platform::Exception(hr);
throw(exception);
}
}
String^ Utils::GetStringValue(String^ input)
String ^ Utils::GetStringValue(String ^ input)
{
// Remove first and last " characters
if (input->Length() >= 3)
@ -68,20 +68,16 @@ int Utils::GetWindowId()
return windowId;
}
void Utils::RunOnUIThreadNonblocking(std::function<void()>&& function, _In_ CoreDispatcher^ currentDispatcher)
void Utils::RunOnUIThreadNonblocking(std::function<void()>&& function, _In_ CoreDispatcher ^ currentDispatcher)
{
if (currentDispatcher != nullptr)
{
auto task = create_task(currentDispatcher->RunAsync(CoreDispatcherPriority::Normal,
ref new DispatchedHandler([function]()
{
function();
})));
auto task = create_task(currentDispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([function]() { function(); })));
}
}
// Returns if the last character of a wstring is the target wchar_t
bool Utils::IsLastCharacterTarget(_In_ wstring const &input, _In_ wchar_t target)
bool Utils::IsLastCharacterTarget(_In_ wstring const& input, _In_ wchar_t target)
{
return !input.empty() && input.back() == target;
}
@ -96,9 +92,8 @@ wstring Utils::RemoveUnwantedCharsFromWstring(wstring input, wchar_t* unwantedCh
return input;
}
void Utils::SerializeCommandsAndTokens(_In_ shared_ptr<CalculatorVector <pair<wstring, int>>> const &tokens,
_In_ shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> const &commands,
DataWriter^ writer)
void Utils::SerializeCommandsAndTokens(_In_ shared_ptr<CalculatorVector<pair<wstring, int>>> const& tokens,
_In_ shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> const& commands, DataWriter ^ writer)
{
unsigned int commandsSize;
IFTPlatformException(commands->GetSize(&commandsSize));
@ -134,7 +129,7 @@ void Utils::SerializeCommandsAndTokens(_In_ shared_ptr<CalculatorVector <pair<ws
}
}
const shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> Utils::DeserializeCommands(DataReader^ reader)
const shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> Utils::DeserializeCommands(DataReader ^ reader)
{
shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> commandVector = make_shared<CalculatorVector<shared_ptr<IExpressionCommand>>>();
auto commandVectorSize = reader->ReadUInt32();
@ -151,9 +146,9 @@ const shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> Utils::Deseri
return commandVector;
}
const shared_ptr<CalculatorVector <pair<wstring, int>>> Utils::DeserializeTokens(DataReader^ reader)
const shared_ptr<CalculatorVector<pair<wstring, int>>> Utils::DeserializeTokens(DataReader ^ reader)
{
shared_ptr<CalculatorVector <pair<wstring, int>>> tokenVector = make_shared<CalculatorVector<pair<wstring, int>>>();
shared_ptr<CalculatorVector<pair<wstring, int>>> tokenVector = make_shared<CalculatorVector<pair<wstring, int>>>();
auto tokensSize = reader->ReadUInt32();
for (unsigned int i = 0; i < tokensSize; ++i)
@ -193,14 +188,14 @@ bool Utils::IsDateTimeOlderThan(DateTime dateTime, const long long duration)
return dateTime.UniversalTime + duration < now.UniversalTime;
}
task<void> Utils::WriteFileToFolder(IStorageFolder^ folder, String^ fileName, String^ contents, CreationCollisionOption collisionOption)
task<void> Utils::WriteFileToFolder(IStorageFolder ^ folder, String ^ fileName, String ^ contents, CreationCollisionOption collisionOption)
{
if (folder == nullptr)
{
co_return;
}
StorageFile^ file = co_await folder->CreateFileAsync(fileName, collisionOption);
StorageFile ^ file = co_await folder->CreateFileAsync(fileName, collisionOption);
if (file == nullptr)
{
co_return;
@ -209,19 +204,19 @@ task<void> Utils::WriteFileToFolder(IStorageFolder^ folder, String^ fileName, St
co_await FileIO::WriteTextAsync(file, contents);
}
task<String^> Utils::ReadFileFromFolder(IStorageFolder^ folder, String^ fileName)
task<String ^> Utils::ReadFileFromFolder(IStorageFolder ^ folder, String ^ fileName)
{
if (folder == nullptr)
{
co_return nullptr;
}
StorageFile^ file = co_await folder->GetFileAsync(fileName);
StorageFile ^ file = co_await folder->GetFileAsync(fileName);
if (file == nullptr)
{
co_return nullptr;
}
String^ contents = co_await FileIO::ReadTextAsync(file);
String ^ contents = co_await FileIO::ReadTextAsync(file);
co_return contents;
}

View file

@ -9,92 +9,171 @@
// Utility macros to make Models easier to write
// generates a member variable called m_<n>
#define PROPERTY_R(t, n)\
property t n {\
t get() { return m_##n; }\
private: void set(t value) { m_##n = value; }\
} private: t m_##n; public:
#define PROPERTY_R(t, n) \
property t n \
{ \
t get() \
{ \
return m_##n; \
} \
\
private: \
void set(t value) \
{ \
m_##n = value; \
} \
} \
private: \
t m_##n; \
public:
#define PROPERTY_RW(t, n)\
property t n {\
t get() { return m_##n; }\
void set(t value) { m_##n = value; }\
} private: t m_##n; public:
#define PROPERTY_RW(t, n) \
property t n \
{ \
t get() \
{ \
return m_##n; \
} \
void set(t value) \
{ \
m_##n = value; \
} \
} \
private: \
t m_##n; \
public:
#define OBSERVABLE_PROPERTY_R(t, n)\
property t n {\
t get() { return m_##n; }\
private: void set(t value) {\
if (m_##n != value) {\
m_##n = value;\
RaisePropertyChanged(L#n);\
}}\
} private: t m_##n; public:
#define OBSERVABLE_PROPERTY_R(t, n) \
property t n \
{ \
t get() \
{ \
return m_##n; \
} \
\
private: \
void set(t value) \
{ \
if (m_##n != value) \
{ \
m_##n = value; \
RaisePropertyChanged(L#n); \
} \
} \
} \
private: \
t m_##n; \
public:
#define OBSERVABLE_PROPERTY_RW(t, n)\
property t n {\
t get() { return m_##n; }\
void set(t value) {\
if (m_##n != value) {\
m_##n = value;\
RaisePropertyChanged(L#n);\
}\
}\
} private: t m_##n; public:
#define OBSERVABLE_PROPERTY_RW(t, n) \
property t n \
{ \
t get() \
{ \
return m_##n; \
} \
void set(t value) \
{ \
if (m_##n != value) \
{ \
m_##n = value; \
RaisePropertyChanged(L#n); \
} \
} \
} \
private: \
t m_##n; \
public:
#define OBSERVABLE_NAMED_PROPERTY_R(t, n)\
OBSERVABLE_PROPERTY_R(t, n)\
internal: static property Platform::String^ n##PropertyName {\
Platform::String^ get() { return Platform::StringReference(L#n); }\
} public:
#define OBSERVABLE_NAMED_PROPERTY_R(t, n) \
OBSERVABLE_PROPERTY_R(t, n) \
internal: \
static property Platform::String ^ n##PropertyName \
{ \
Platform::String ^ get() { return Platform::StringReference(L#n); } \
} \
public:
#define OBSERVABLE_NAMED_PROPERTY_RW(t, n)\
OBSERVABLE_PROPERTY_RW(t, n)\
internal: static property Platform::String^ n##PropertyName {\
Platform::String^ get() { return Platform::StringReference(L#n); }\
} public:
#define OBSERVABLE_NAMED_PROPERTY_RW(t, n) \
OBSERVABLE_PROPERTY_RW(t, n) \
internal: \
static property Platform::String ^ n##PropertyName \
{ \
Platform::String ^ get() { return Platform::StringReference(L#n); } \
} \
public:
#define OBSERVABLE_PROPERTY_FIELD(n) m_##n
// This variant of the observable object is for objects that don't want to react to property changes
#ifndef UNIT_TESTS
#define OBSERVABLE_OBJECT() virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler^ PropertyChanged;\
internal: void RaisePropertyChanged(Platform::String^ p) {\
PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs(p)); } public:
#define OBSERVABLE_OBJECT() \
virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler ^ PropertyChanged; \
internal: \
void RaisePropertyChanged(Platform::String ^ p) \
{ \
PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs(p)); \
} \
public:
#else
#define OBSERVABLE_OBJECT() virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler^ PropertyChanged;\
internal: void RaisePropertyChanged(Platform::String^ p) {\
} public:
#define OBSERVABLE_OBJECT() \
virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler ^ PropertyChanged; \
internal: \
void RaisePropertyChanged(Platform::String ^ p) \
{ \
} \
public:
#endif
// The callback specified in the macro is a method in the class that will be called every time the object changes
// the callback is supposed to be have a single parameter of type Platform::String^
#ifndef UNIT_TESTS
#define OBSERVABLE_OBJECT_CALLBACK(c) virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler^ PropertyChanged;\
internal: void RaisePropertyChanged(Platform::String^ p) {\
PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs(p));\
c(p);\
} public:
#define OBSERVABLE_OBJECT_CALLBACK(c) \
virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler ^ PropertyChanged; \
internal: \
void RaisePropertyChanged(Platform::String ^ p) \
{ \
PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs(p)); \
c(p); \
} \
public:
#else
#define OBSERVABLE_OBJECT_CALLBACK(c) virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler^ PropertyChanged;\
internal: void RaisePropertyChanged(Platform::String^ p) {\
c(p);\
} public:
#define OBSERVABLE_OBJECT_CALLBACK(c) \
virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler ^ PropertyChanged; \
internal: \
void RaisePropertyChanged(Platform::String ^ p) \
{ \
c(p); \
} \
public:
#endif
// The variable member generated by this macro should not be used in the class code, use the
// property getter instead.
#define COMMAND_FOR_METHOD(p, m) property Windows::UI::Xaml::Input::ICommand^ p {\
#define COMMAND_FOR_METHOD(p, m) \
property Windows::UI::Xaml::Input::ICommand^ p {\
Windows::UI::Xaml::Input::ICommand^ get() {\
if (!donotuse_##p) {\
donotuse_##p = CalculatorApp::Common::MakeDelegate(this, &m);\
} return donotuse_##p; }} private: Windows::UI::Xaml::Input::ICommand^ donotuse_##p; public:
} return donotuse_##p; }} private: Windows::UI::Xaml::Input::ICommand^ donotuse_##p; \
public:
#define DEPENDENCY_PROPERTY_DECLARATION(t, n)\
property t n {\
t get() { return safe_cast<t>(GetValue(s_##n##Property)); }\
void set(t value) { SetValue(s_##n##Property, value); } }\
private: static Windows::UI::Xaml::DependencyProperty^ s_##n##Property; public:
#define DEPENDENCY_PROPERTY_DECLARATION(t, n) \
property t n \
{ \
t get() \
{ \
return safe_cast<t>(GetValue(s_##n##Property)); \
} \
void set(t value) \
{ \
SetValue(s_##n##Property, value); \
} \
} \
\
private: \
static Windows::UI::Xaml::DependencyProperty ^ s_##n##Property; \
public:
// Utilities for DependencyProperties
namespace Utils
@ -114,13 +193,13 @@ namespace Utils
};
template <typename T>
struct RemoveHat<T^>
struct RemoveHat<T ^>
{
typedef T type;
};
template <typename T>
typename std::enable_if<IsRefClass<T>::value, T^>::type MakeDefault()
typename std::enable_if<IsRefClass<T>::value, T ^>::type MakeDefault()
{
return nullptr;
}
@ -283,140 +362,304 @@ namespace Utils
}
void IFTPlatformException(HRESULT hr);
Platform::String^ GetStringValue(Platform::String^ input);
bool IsLastCharacterTarget(std::wstring const &input, wchar_t target);
Platform::String ^ GetStringValue(Platform::String ^ input);
bool IsLastCharacterTarget(std::wstring const& input, wchar_t target);
std::wstring RemoveUnwantedCharsFromWstring(std::wstring inputString, wchar_t* unwantedChars, unsigned int size);
double GetDoubleFromWstring(std::wstring input);
int GetWindowId();
void RunOnUIThreadNonblocking(std::function<void()>&& function, _In_ Windows::UI::Core::CoreDispatcher^ currentDispatcher);
void SerializeCommandsAndTokens(_In_ std::shared_ptr<CalculatorVector <std::pair<std::wstring, int>>> const &tokens,
_In_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const &commands,
Windows::Storage::Streams::DataWriter^ writer);
void RunOnUIThreadNonblocking(std::function<void()>&& function, _In_ Windows::UI::Core::CoreDispatcher ^ currentDispatcher);
void SerializeCommandsAndTokens(_In_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const& tokens,
_In_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const& commands,
Windows::Storage::Streams::DataWriter ^ writer);
const std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> DeserializeCommands(Windows::Storage::Streams::DataReader^ reader);
const std::shared_ptr<CalculatorVector <std::pair<std::wstring, int>>> DeserializeTokens(Windows::Storage::Streams::DataReader^ reader);
const std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> DeserializeCommands(Windows::Storage::Streams::DataReader ^ reader);
const std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> DeserializeTokens(Windows::Storage::Streams::DataReader ^ reader);
Windows::Foundation::DateTime GetUniversalSystemTime();
bool IsDateTimeOlderThan(Windows::Foundation::DateTime dateTime, const long long duration);
concurrency::task<void> WriteFileToFolder(Windows::Storage::IStorageFolder^ folder, Platform::String^ fileName, Platform::String^ contents, Windows::Storage::CreationCollisionOption collisionOption);
concurrency::task<Platform::String^> ReadFileFromFolder(Windows::Storage::IStorageFolder^ folder, Platform::String^ fileName);
concurrency::task<void> WriteFileToFolder(Windows::Storage::IStorageFolder ^ folder, Platform::String ^ fileName, Platform::String ^ contents,
Windows::Storage::CreationCollisionOption collisionOption);
concurrency::task<Platform::String ^> ReadFileFromFolder(Windows::Storage::IStorageFolder ^ folder, Platform::String ^ fileName);
}
// This goes into the header to define the property, in the public: section of the class
#define DEPENDENCY_PROPERTY_OWNER(owner)\
private: typedef owner DependencyPropertiesOwner; public:
#define DEPENDENCY_PROPERTY_OWNER(owner) \
private: \
typedef owner DependencyPropertiesOwner; \
public:
// Normal DependencyProperty
#define DEPENDENCY_PROPERTY(type, name)\
property type name {\
type get() { return safe_cast<type>(GetValue(s_##name##Property)); }\
void set(type value) { SetValue(s_##name##Property, value); }\
} private: static Windows::UI::Xaml::DependencyProperty^ s_##name##Property;\
public: static property Windows::UI::Xaml::DependencyProperty^ name##Property {\
Windows::UI::Xaml::DependencyProperty^ get() { assert(s_##name##Property); return s_##name##Property; }\
}\
private: static Windows::UI::Xaml::DependencyProperty^ Initialize##name##Property() {\
return Utils::RegisterDependencyProperty<DependencyPropertiesOwner, type>(L#name); } public:
#define DEPENDENCY_PROPERTY(type, name) \
property type name \
{ \
type get() \
{ \
return safe_cast<type>(GetValue(s_##name##Property)); \
} \
void set(type value) \
{ \
SetValue(s_##name##Property, value); \
} \
} \
private: \
static Windows::UI::Xaml::DependencyProperty ^ s_##name##Property; \
\
public: \
static property Windows::UI::Xaml::DependencyProperty ^ name##Property \
{ \
Windows::UI::Xaml::DependencyProperty ^ get() { \
assert(s_##name##Property); \
return s_##name##Property; \
} \
} \
\
private: \
static Windows::UI::Xaml::DependencyProperty ^ Initialize##name##Property() \
{ \
return Utils::RegisterDependencyProperty<DependencyPropertiesOwner, type>(L#name); \
} \
public:
#define DEPENDENCY_PROPERTY_WITH_DEFAULT(type, name, defaultValue)\
property type name {\
type get() { return safe_cast<type>(GetValue(s_##name##Property)); }\
void set(type value) { SetValue(s_##name##Property, value); }\
} private: static Windows::UI::Xaml::DependencyProperty^ s_##name##Property;\
public: static property Windows::UI::Xaml::DependencyProperty^ name##Property {\
Windows::UI::Xaml::DependencyProperty^ get() { assert(s_##name##Property); return s_##name##Property; }\
}\
private: static Windows::UI::Xaml::DependencyProperty^ Initialize##name##Property() {\
return Utils::RegisterDependencyProperty<DependencyPropertiesOwner, type>(L#name, defaultValue); } public:
#define DEPENDENCY_PROPERTY_WITH_DEFAULT(type, name, defaultValue) \
property type name \
{ \
type get() \
{ \
return safe_cast<type>(GetValue(s_##name##Property)); \
} \
void set(type value) \
{ \
SetValue(s_##name##Property, value); \
} \
} \
private: \
static Windows::UI::Xaml::DependencyProperty ^ s_##name##Property; \
\
public: \
static property Windows::UI::Xaml::DependencyProperty ^ name##Property \
{ \
Windows::UI::Xaml::DependencyProperty ^ get() { \
assert(s_##name##Property); \
return s_##name##Property; \
} \
} \
\
private: \
static Windows::UI::Xaml::DependencyProperty ^ Initialize##name##Property() \
{ \
return Utils::RegisterDependencyProperty<DependencyPropertiesOwner, type>(L#name, defaultValue); \
} \
public:
#define DEPENDENCY_PROPERTY_WITH_CALLBACK(type, name)\
property type name {\
type get() { return safe_cast<type>(GetValue(s_##name##Property)); }\
void set(type value) { SetValue(s_##name##Property, value); }\
} private: static Windows::UI::Xaml::DependencyProperty^ s_##name##Property;\
public: static property Windows::UI::Xaml::DependencyProperty^ name##Property {\
Windows::UI::Xaml::DependencyProperty^ get() { assert(s_##name##Property); return s_##name##Property; }\
}\
private: static Windows::UI::Xaml::DependencyProperty^ Initialize##name##Property() {\
return Utils::RegisterDependencyPropertyWithCallback<DependencyPropertiesOwner, type>(L#name, &On##name##PropertyChangedImpl); }\
static void On##name##PropertyChangedImpl(Windows::UI::Xaml::DependencyObject^ sender, Windows::UI::Xaml::DependencyPropertyChangedEventArgs^ args) {\
auto self = safe_cast<DependencyPropertiesOwner^>(sender);\
self->On##name##PropertyChanged(safe_cast<type>(args->OldValue), safe_cast<type>(args->NewValue)); } public:
#define DEPENDENCY_PROPERTY_WITH_CALLBACK(type, name) \
property type name \
{ \
type get() \
{ \
return safe_cast<type>(GetValue(s_##name##Property)); \
} \
void set(type value) \
{ \
SetValue(s_##name##Property, value); \
} \
} \
private: \
static Windows::UI::Xaml::DependencyProperty ^ s_##name##Property; \
\
public: \
static property Windows::UI::Xaml::DependencyProperty ^ name##Property \
{ \
Windows::UI::Xaml::DependencyProperty ^ get() { \
assert(s_##name##Property); \
return s_##name##Property; \
} \
} \
\
private: \
static Windows::UI::Xaml::DependencyProperty ^ Initialize##name##Property() \
{ \
return Utils::RegisterDependencyPropertyWithCallback<DependencyPropertiesOwner, type>(L#name, &On##name##PropertyChangedImpl); \
} \
static void On##name##PropertyChangedImpl(Windows::UI::Xaml::DependencyObject ^ sender, Windows::UI::Xaml::DependencyPropertyChangedEventArgs ^ args) \
{ \
auto self = safe_cast<DependencyPropertiesOwner ^>(sender); \
self->On##name##PropertyChanged(safe_cast<type>(args->OldValue), safe_cast<type>(args->NewValue)); \
} \
public:
#define DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(type, name, defaultValue)\
property type name {\
type get() { return safe_cast<type>(GetValue(s_##name##Property)); }\
void set(type value) { SetValue(s_##name##Property, value); }\
} private: static Windows::UI::Xaml::DependencyProperty^ s_##name##Property;\
public: static property Windows::UI::Xaml::DependencyProperty^ name##Property {\
Windows::UI::Xaml::DependencyProperty^ get() { assert(s_##name##Property); return s_##name##Property; }\
}\
private: static Windows::UI::Xaml::DependencyProperty^ Initialize##name##Property() {\
return Utils::RegisterDependencyPropertyWithCallback<DependencyPropertiesOwner, type>(L#name, defaultValue, &On##name##PropertyChangedImpl); }\
static void On##name##PropertyChangedImpl(Windows::UI::Xaml::DependencyObject^ sender, Windows::UI::Xaml::DependencyPropertyChangedEventArgs^ args) {\
auto self = safe_cast<DependencyPropertiesOwner^>(sender);\
self->On##name##PropertyChanged(safe_cast<type>(args->OldValue), safe_cast<type>(args->NewValue)); } public:
#define DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(type, name, defaultValue) \
property type name \
{ \
type get() \
{ \
return safe_cast<type>(GetValue(s_##name##Property)); \
} \
void set(type value) \
{ \
SetValue(s_##name##Property, value); \
} \
} \
private: \
static Windows::UI::Xaml::DependencyProperty ^ s_##name##Property; \
\
public: \
static property Windows::UI::Xaml::DependencyProperty ^ name##Property \
{ \
Windows::UI::Xaml::DependencyProperty ^ get() { \
assert(s_##name##Property); \
return s_##name##Property; \
} \
} \
\
private: \
static Windows::UI::Xaml::DependencyProperty ^ Initialize##name##Property() \
{ \
return Utils::RegisterDependencyPropertyWithCallback<DependencyPropertiesOwner, type>(L#name, defaultValue, &On##name##PropertyChangedImpl); \
} \
static void On##name##PropertyChangedImpl(Windows::UI::Xaml::DependencyObject ^ sender, Windows::UI::Xaml::DependencyPropertyChangedEventArgs ^ args) \
{ \
auto self = safe_cast<DependencyPropertiesOwner ^>(sender); \
self->On##name##PropertyChanged(safe_cast<type>(args->OldValue), safe_cast<type>(args->NewValue)); \
} \
public:
// Attached DependencyProperty
#define DEPENDENCY_PROPERTY_ATTACHED(type, name)\
static type Get##name(Windows::UI::Xaml::DependencyObject^ target) { return safe_cast<type>(target->GetValue(s_##name##Property)); }\
static void Set##name(Windows::UI::Xaml::DependencyObject^ target, type value) { target->SetValue(s_##name##Property, value); }\
private: static Windows::UI::Xaml::DependencyProperty^ s_##name##Property;\
public: static property Windows::UI::Xaml::DependencyProperty^ name##Property {\
Windows::UI::Xaml::DependencyProperty^ get() { assert(s_##name##Property); return s_##name##Property; }\
}\
private: static Windows::UI::Xaml::DependencyProperty^ Initialize##name##Property() {\
return Utils::RegisterDependencyPropertyAttached<DependencyPropertiesOwner, type>(L#name); } public:
#define DEPENDENCY_PROPERTY_ATTACHED(type, name) \
static type Get##name(Windows::UI::Xaml::DependencyObject ^ target) \
{ \
return safe_cast<type>(target->GetValue(s_##name##Property)); \
} \
static void Set##name(Windows::UI::Xaml::DependencyObject ^ target, type value) \
{ \
target->SetValue(s_##name##Property, value); \
} \
\
private: \
static Windows::UI::Xaml::DependencyProperty ^ s_##name##Property; \
\
public: \
static property Windows::UI::Xaml::DependencyProperty ^ name##Property \
{ \
Windows::UI::Xaml::DependencyProperty ^ get() { \
assert(s_##name##Property); \
return s_##name##Property; \
} \
} \
\
private: \
static Windows::UI::Xaml::DependencyProperty ^ Initialize##name##Property() \
{ \
return Utils::RegisterDependencyPropertyAttached<DependencyPropertiesOwner, type>(L#name); \
} \
public:
#define DEPENDENCY_PROPERTY_ATTACHED_WITH_DEFAULT(type, name, defaultValue)\
static type Get##name(Windows::UI::Xaml::DependencyObject^ target) { return safe_cast<type>(target->GetValue(s_##name##Property)); }\
static void Set##name(Windows::UI::Xaml::DependencyObject^ target, type value) { target->SetValue(s_##name##Property, value); }\
private: static Windows::UI::Xaml::DependencyProperty^ s_##name##Property;\
public: static property Windows::UI::Xaml::DependencyProperty^ name##Property {\
Windows::UI::Xaml::DependencyProperty^ get() { assert(s_##name##Property); return s_##name##Property; }\
}\
private: static Windows::UI::Xaml::DependencyProperty^ Initialize##name##Property() {\
return Utils::RegisterDependencyPropertyAttached<DependencyPropertiesOwner, type>(L#name, defaultValue); } public:
#define DEPENDENCY_PROPERTY_ATTACHED_WITH_DEFAULT(type, name, defaultValue) \
static type Get##name(Windows::UI::Xaml::DependencyObject ^ target) \
{ \
return safe_cast<type>(target->GetValue(s_##name##Property)); \
} \
static void Set##name(Windows::UI::Xaml::DependencyObject ^ target, type value) \
{ \
target->SetValue(s_##name##Property, value); \
} \
\
private: \
static Windows::UI::Xaml::DependencyProperty ^ s_##name##Property; \
\
public: \
static property Windows::UI::Xaml::DependencyProperty ^ name##Property \
{ \
Windows::UI::Xaml::DependencyProperty ^ get() { \
assert(s_##name##Property); \
return s_##name##Property; \
} \
} \
\
private: \
static Windows::UI::Xaml::DependencyProperty ^ Initialize##name##Property() \
{ \
return Utils::RegisterDependencyPropertyAttached<DependencyPropertiesOwner, type>(L#name, defaultValue); \
} \
public:
#define DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(type, name)\
static type Get##name(Windows::UI::Xaml::DependencyObject^ target) { return safe_cast<type>(target->GetValue(s_##name##Property)); }\
static void Set##name(Windows::UI::Xaml::DependencyObject^ target, type value) { target->SetValue(s_##name##Property, value); }\
private: static Windows::UI::Xaml::DependencyProperty^ s_##name##Property;\
public: static property Windows::UI::Xaml::DependencyProperty^ name##Property {\
Windows::UI::Xaml::DependencyProperty^ get() { assert(s_##name##Property); return s_##name##Property; }\
}\
private: static Windows::UI::Xaml::DependencyProperty^ Initialize##name##Property() {\
return Utils::RegisterDependencyPropertyAttachedWithCallback<DependencyPropertiesOwner, type>(L#name, &On##name##PropertyChangedImpl); }\
static void On##name##PropertyChangedImpl(Windows::UI::Xaml::DependencyObject^ sender, Windows::UI::Xaml::DependencyPropertyChangedEventArgs^ args) {\
On##name##PropertyChanged(sender, safe_cast<type>(args->OldValue), safe_cast<type>(args->NewValue)); } public:
#define DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(type, name) \
static type Get##name(Windows::UI::Xaml::DependencyObject ^ target) \
{ \
return safe_cast<type>(target->GetValue(s_##name##Property)); \
} \
static void Set##name(Windows::UI::Xaml::DependencyObject ^ target, type value) \
{ \
target->SetValue(s_##name##Property, value); \
} \
\
private: \
static Windows::UI::Xaml::DependencyProperty ^ s_##name##Property; \
\
public: \
static property Windows::UI::Xaml::DependencyProperty ^ name##Property \
{ \
Windows::UI::Xaml::DependencyProperty ^ get() { \
assert(s_##name##Property); \
return s_##name##Property; \
} \
} \
\
private: \
static Windows::UI::Xaml::DependencyProperty ^ Initialize##name##Property() \
{ \
return Utils::RegisterDependencyPropertyAttachedWithCallback<DependencyPropertiesOwner, type>(L#name, &On##name##PropertyChangedImpl); \
} \
static void On##name##PropertyChangedImpl(Windows::UI::Xaml::DependencyObject ^ sender, Windows::UI::Xaml::DependencyPropertyChangedEventArgs ^ args) \
{ \
On##name##PropertyChanged(sender, safe_cast<type>(args->OldValue), safe_cast<type>(args->NewValue)); \
} \
public:
#define DEPENDENCY_PROPERTY_ATTACHED_WITH_DEFAULT_AND_CALLBACK(type, name, defaultValue)\
static type Get##name(Windows::UI::Xaml::DependencyObject^ target) { return safe_cast<type>(target->GetValue(s_##name##Property)); }\
static void Set##name(Windows::UI::Xaml::DependencyObject^ target, type value) { target->SetValue(s_##name##Property, value); }\
private: static Windows::UI::Xaml::DependencyProperty^ s_##name##Property;\
public: static property Windows::UI::Xaml::DependencyProperty^ name##Property {\
Windows::UI::Xaml::DependencyProperty^ get() { assert(s_##name##Property); return s_##name##Property; }\
}\
private: static Windows::UI::Xaml::DependencyProperty^ Initialize##name##Property() {\
return Utils::RegisterDependencyPropertyAttachedWithCallback<DependencyPropertiesOwner, type>(L#name, defaultValue, &On##name##PropertyChangedImpl); }\
static void On##name##PropertyChangedImpl(Windows::UI::Xaml::DependencyObject^ sender, Windows::UI::Xaml::DependencyPropertyChangedEventArgs^ args) {\
On##name##PropertyChanged(sender, safe_cast<type>(args->OldValue), safe_cast<type>(args->NewValue)); } public:
#define DEPENDENCY_PROPERTY_ATTACHED_WITH_DEFAULT_AND_CALLBACK(type, name, defaultValue) \
static type Get##name(Windows::UI::Xaml::DependencyObject ^ target) \
{ \
return safe_cast<type>(target->GetValue(s_##name##Property)); \
} \
static void Set##name(Windows::UI::Xaml::DependencyObject ^ target, type value) \
{ \
target->SetValue(s_##name##Property, value); \
} \
\
private: \
static Windows::UI::Xaml::DependencyProperty ^ s_##name##Property; \
\
public: \
static property Windows::UI::Xaml::DependencyProperty ^ name##Property \
{ \
Windows::UI::Xaml::DependencyProperty ^ get() { \
assert(s_##name##Property); \
return s_##name##Property; \
} \
} \
\
private: \
static Windows::UI::Xaml::DependencyProperty ^ Initialize##name##Property() \
{ \
return Utils::RegisterDependencyPropertyAttachedWithCallback<DependencyPropertiesOwner, type>(L#name, defaultValue, &On##name##PropertyChangedImpl); \
} \
static void On##name##PropertyChangedImpl(Windows::UI::Xaml::DependencyObject ^ sender, Windows::UI::Xaml::DependencyPropertyChangedEventArgs ^ args) \
{ \
On##name##PropertyChanged(sender, safe_cast<type>(args->OldValue), safe_cast<type>(args->NewValue)); \
} \
public:
// This goes into the cpp to initialize the static variable
#define DEPENDENCY_PROPERTY_INITIALIZATION(owner, name)\
Windows::UI::Xaml::DependencyProperty^ owner::s_##name##Property =\
owner::Initialize##name##Property();
#define DEPENDENCY_PROPERTY_INITIALIZATION(owner, name) Windows::UI::Xaml::DependencyProperty ^ owner::s_##name##Property = owner::Initialize##name##Property();
namespace CalculatorApp
{
template <typename T>
T from_cx(Platform::Object^ from)
T from_cx(Platform::Object ^ from)
{
T to{ nullptr };
winrt::check_hresult(reinterpret_cast<::IUnknown*>(from)->QueryInterface(winrt::guid_of<T>(),
reinterpret_cast<void**>(winrt::put_abi(to))));
winrt::check_hresult(reinterpret_cast<::IUnknown*>(from)->QueryInterface(winrt::guid_of<T>(), reinterpret_cast<void**>(winrt::put_abi(to))));
return to;
}

View file

@ -3,81 +3,78 @@
#pragma once
namespace CalculatorApp { namespace Common
namespace CalculatorApp
{
public ref class ValidSelectedItemConverter sealed: public Windows::UI::Xaml::Data::IValueConverter
namespace Common
{
public:
ValidSelectedItemConverter()
{ }
private:
virtual Platform::Object^ Convert(
Platform::Object^ value,
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
Platform::Object^ /*parameter*/,
Platform::String^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::Convert
public
ref class ValidSelectedItemConverter sealed : public Windows::UI::Xaml::Data::IValueConverter
{
// Pass through as we don't want to change the value from the source
return value;
}
virtual Platform::Object^ ConvertBack(
Platform::Object^ value,
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
Platform::Object^ /*parameter*/,
Platform::String^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::ConvertBack
{
if (value)
public:
ValidSelectedItemConverter()
{
}
private:
virtual Platform::Object
^ Convert(Platform::Object ^ value, Windows::UI::Xaml::Interop::TypeName /*targetType*/, Platform::Object ^ /*parameter*/,
Platform::String ^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::Convert
{
// Pass through as we don't want to change the value from the source
return value;
}
// Stop the binding if the object is nullptr
return Windows::UI::Xaml::DependencyProperty::UnsetValue;
}
};
public ref class ValidSelectedIndexConverter sealed: public Windows::UI::Xaml::Data::IValueConverter
{
public:
ValidSelectedIndexConverter()
{ }
private:
virtual Platform::Object^ Convert(
Platform::Object^ value,
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
Platform::Object^ /*parameter*/,
Platform::String^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::Convert
{
// Pass through as we don't want to change the value from the source
return value;
}
virtual Platform::Object^ ConvertBack(
Platform::Object^ value,
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
Platform::Object^ /*parameter*/,
Platform::String^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::ConvertBack
{
// The value to be valid has to be a boxed int32 value
// extract that value and ensure it is valid, ie >= 0
if (value)
virtual Platform::Object
^ ConvertBack(Platform::Object ^ value, Windows::UI::Xaml::Interop::TypeName /*targetType*/, Platform::Object ^ /*parameter*/,
Platform::String ^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::ConvertBack
{
auto box = dynamic_cast<Windows::Foundation::IPropertyValue^>(value);
if (box && box->Type == Windows::Foundation::PropertyType::Int32)
if (value)
{
int index = box->GetInt32();
if (index >= 0)
return value;
}
// Stop the binding if the object is nullptr
return Windows::UI::Xaml::DependencyProperty::UnsetValue;
}
};
public
ref class ValidSelectedIndexConverter sealed : public Windows::UI::Xaml::Data::IValueConverter
{
public:
ValidSelectedIndexConverter()
{
}
private:
virtual Platform::Object
^ Convert(Platform::Object ^ value, Windows::UI::Xaml::Interop::TypeName /*targetType*/, Platform::Object ^ /*parameter*/,
Platform::String ^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::Convert
{
// Pass through as we don't want to change the value from the source
return value;
}
virtual Platform::Object
^ ConvertBack(Platform::Object ^ value, Windows::UI::Xaml::Interop::TypeName /*targetType*/, Platform::Object ^ /*parameter*/,
Platform::String ^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::ConvertBack
{
// The value to be valid has to be a boxed int32 value
// extract that value and ensure it is valid, ie >= 0
if (value)
{
auto box = dynamic_cast<Windows::Foundation::IPropertyValue ^>(value);
if (box && box->Type == Windows::Foundation::PropertyType::Int32)
{
return value;
int index = box->GetInt32();
if (index >= 0)
{
return value;
}
}
}
// The value is not valid therefore stop the binding right here
return Windows::UI::Xaml::DependencyProperty::UnsetValue;
}
// The value is not valid therefore stop the binding right here
return Windows::UI::Xaml::DependencyProperty::UnsetValue;
}
};
}}
};
}
}

View file

@ -46,21 +46,14 @@ static constexpr auto CACHE_LANGCODE_KEY = L"CURRENCY_CONVERTER_LANGCODE";
static constexpr auto CACHE_DELIMITER = L"%";
static constexpr auto STATIC_DATA_FILENAME = L"CURRENCY_CONVERTER_STATIC_DATA.txt";
static constexpr array<wstring_view, 5> STATIC_DATA_PROPERTIES = {
wstring_view{ L"CountryCode", 11 },
wstring_view{ L"CountryName", 11 },
wstring_view{ L"CurrencyCode", 12 },
wstring_view{ L"CurrencyName", 12 },
wstring_view{ L"CurrencySymbol", 14 }
};
static constexpr array<wstring_view, 5> STATIC_DATA_PROPERTIES = { wstring_view{ L"CountryCode", 11 }, wstring_view{ L"CountryName", 11 },
wstring_view{ L"CurrencyCode", 12 }, wstring_view{ L"CurrencyName", 12 },
wstring_view{ L"CurrencySymbol", 14 } };
static constexpr auto ALL_RATIOS_DATA_FILENAME = L"CURRENCY_CONVERTER_ALL_RATIOS_DATA.txt";
static constexpr auto RATIO_KEY = L"Rt";
static constexpr auto CURRENCY_CODE_KEY = L"An";
static constexpr array<wstring_view, 2> ALL_RATIOS_DATA_PROPERTIES = {
wstring_view{ RATIO_KEY, 2 },
wstring_view{ CURRENCY_CODE_KEY, 2 }
};
static constexpr array<wstring_view, 2> ALL_RATIOS_DATA_PROPERTIES = { wstring_view{ RATIO_KEY, 2 }, wstring_view{ CURRENCY_CODE_KEY, 2 } };
static constexpr auto DEFAULT_FROM_TO_CURRENCY_FILE_URI = L"ms-appx:///DataLoaders/DefaultFromToCurrency.json";
static constexpr auto FROM_KEY = L"from";
@ -92,14 +85,14 @@ namespace CalculatorApp
}
}
CurrencyDataLoader::CurrencyDataLoader(_In_ unique_ptr<ICurrencyHttpClient> client) :
m_client(move(client)),
m_loadStatus(CurrencyLoadStatus::NotLoaded),
m_responseLanguage(L"en-US"),
m_ratioFormat(L""),
m_timestampFormat(L""),
m_networkManager(ref new NetworkManager()),
m_meteredOverrideSet(false)
CurrencyDataLoader::CurrencyDataLoader(_In_ unique_ptr<ICurrencyHttpClient> client)
: m_client(move(client))
, m_loadStatus(CurrencyLoadStatus::NotLoaded)
, m_responseLanguage(L"en-US")
, m_ratioFormat(L"")
, m_timestampFormat(L"")
, m_networkManager(ref new NetworkManager())
, m_meteredOverrideSet(false)
{
if (GlobalizationPreferences::Languages->Size > 0)
{
@ -141,11 +134,8 @@ void CurrencyDataLoader::RegisterForNetworkBehaviorChanges()
{
UnregisterForNetworkBehaviorChanges();
m_networkBehaviorToken =
m_networkManager->NetworkBehaviorChanged += ref new NetworkBehaviorChangedHandler([this](NetworkAccessBehavior newBehavior)
{
this->OnNetworkBehaviorChanged(newBehavior);
});
m_networkBehaviorToken = m_networkManager->NetworkBehaviorChanged +=
ref new NetworkBehaviorChangedHandler([this](NetworkAccessBehavior newBehavior) { this->OnNetworkBehaviorChanged(newBehavior); });
OnNetworkBehaviorChanged(NetworkManager::GetNetworkAccessBehavior());
}
@ -186,8 +176,7 @@ void CurrencyDataLoader::LoadData()
if (!LoadFinished())
{
create_task([this]() -> task<bool>
{
create_task([this]() -> task<bool> {
vector<function<task<bool>()>> loadFunctions = {
[this]() { return TryLoadDataFromCacheAsync(); },
[this]() { return TryLoadDataFromWebAsync(); },
@ -204,11 +193,13 @@ void CurrencyDataLoader::LoadData()
}
co_return didLoad;
}).then([this](bool didLoad)
{
UpdateDisplayedTimestamp();
NotifyDataLoadFinished(didLoad);
}, task_continuation_context::use_current());
})
.then(
[this](bool didLoad) {
UpdateDisplayedTimestamp();
NotifyDataLoadFinished(didLoad);
},
task_continuation_context::use_current());
}
};
#pragma optimize("", on)
@ -284,27 +275,19 @@ pair<wstring, wstring> CurrencyDataLoader::GetCurrencyRatioEquality(_In_ const U
wstring digitSymbol = wstring{ LocalizationSettings::GetInstance().GetDigitSymbolFromEnUsDigit(L'1') };
wstring roundedFormat = m_ratioFormatter->Format(rounded)->Data();
wstring ratioString = LocalizationStringUtil::GetLocalizedString(
m_ratioFormat.c_str(),
digitSymbol.c_str(),
unit1.abbreviation.c_str(),
roundedFormat.c_str(),
unit2.abbreviation.c_str()
);
wstring ratioString = LocalizationStringUtil::GetLocalizedString(m_ratioFormat.c_str(), digitSymbol.c_str(), unit1.abbreviation.c_str(),
roundedFormat.c_str(), unit2.abbreviation.c_str());
wstring accessibleRatioString = LocalizationStringUtil::GetLocalizedString(
m_ratioFormat.c_str(),
digitSymbol.c_str(),
unit1.accessibleName.c_str(),
roundedFormat.c_str(),
unit2.accessibleName.c_str()
);
m_ratioFormat.c_str(), digitSymbol.c_str(), unit1.accessibleName.c_str(), roundedFormat.c_str(), unit2.accessibleName.c_str());
return make_pair(ratioString, accessibleRatioString);
}
}
}
catch (...) {}
catch (...)
{
}
return make_pair(L"", L"");
}
@ -324,8 +307,7 @@ task<bool> CurrencyDataLoader::TryLoadDataFromCacheAsync()
bool loadComplete = false;
m_cacheTimestamp = static_cast<DateTime>(localSettings->Values->Lookup(CacheTimestampKey));
if (Utils::IsDateTimeOlderThan(m_cacheTimestamp, DAY_DURATION)
&& m_networkAccessBehavior == NetworkAccessBehavior::Normal)
if (Utils::IsDateTimeOlderThan(m_cacheTimestamp, DAY_DURATION) && m_networkAccessBehavior == NetworkAccessBehavior::Normal)
{
loadComplete = co_await TryLoadDataFromWebAsync();
}
@ -337,7 +319,7 @@ task<bool> CurrencyDataLoader::TryLoadDataFromCacheAsync()
co_return loadComplete;
}
catch (Exception^ ex)
catch (Exception ^ ex)
{
TraceLogger::GetInstance().LogPlatformException(__FUNCTIONW__, ex);
co_return false;
@ -361,29 +343,24 @@ task<bool> CurrencyDataLoader::TryFinishLoadFromCacheAsync()
co_return false;
}
if (!localSettings->Values->HasKey(CacheLangcodeKey)
|| !static_cast<String^>(localSettings->Values->Lookup(CacheLangcodeKey))->Equals(m_responseLanguage))
if (!localSettings->Values->HasKey(CacheLangcodeKey) || !static_cast<String ^>(localSettings->Values->Lookup(CacheLangcodeKey))->Equals(m_responseLanguage))
{
co_return false;
}
StorageFolder^ localCacheFolder = ApplicationData::Current->LocalCacheFolder;
StorageFolder ^ localCacheFolder = ApplicationData::Current->LocalCacheFolder;
if (localCacheFolder == nullptr)
{
co_return false;
}
String^ staticDataResponse = co_await Utils::ReadFileFromFolder(localCacheFolder, StaticDataFilename);
String^ allRatiosResponse = co_await Utils::ReadFileFromFolder(localCacheFolder, AllRatiosDataFilename);
String ^ staticDataResponse = co_await Utils::ReadFileFromFolder(localCacheFolder, StaticDataFilename);
String ^ allRatiosResponse = co_await Utils::ReadFileFromFolder(localCacheFolder, AllRatiosDataFilename);
vector<UCM::CurrencyStaticData> staticData{};
CurrencyRatioMap ratioMap{};
bool didParse = TryParseWebResponses(
staticDataResponse,
allRatiosResponse,
staticData,
ratioMap);
bool didParse = TryParseWebResponses(staticDataResponse, allRatiosResponse, staticData, ratioMap);
if (!didParse)
{
co_return false;
@ -406,14 +383,13 @@ task<bool> CurrencyDataLoader::TryLoadDataFromWebAsync()
co_return false;
}
if (m_networkAccessBehavior == NetworkAccessBehavior::Offline ||
(m_networkAccessBehavior == NetworkAccessBehavior::OptIn && !m_meteredOverrideSet))
if (m_networkAccessBehavior == NetworkAccessBehavior::Offline || (m_networkAccessBehavior == NetworkAccessBehavior::OptIn && !m_meteredOverrideSet))
{
co_return false;
}
String^ staticDataResponse = co_await m_client->GetCurrencyMetadata();
String^ allRatiosResponse = co_await m_client->GetCurrencyRatios();
String ^ staticDataResponse = co_await m_client->GetCurrencyMetadata();
String ^ allRatiosResponse = co_await m_client->GetCurrencyRatios();
if (staticDataResponse == nullptr || allRatiosResponse == nullptr)
{
co_return false;
@ -422,11 +398,7 @@ task<bool> CurrencyDataLoader::TryLoadDataFromWebAsync()
vector<UCM::CurrencyStaticData> staticData{};
CurrencyRatioMap ratioMap{};
bool didParse = TryParseWebResponses(
staticDataResponse,
allRatiosResponse,
staticData,
ratioMap);
bool didParse = TryParseWebResponses(staticDataResponse, allRatiosResponse, staticData, ratioMap);
if (!didParse)
{
co_return false;
@ -437,19 +409,12 @@ task<bool> CurrencyDataLoader::TryLoadDataFromWebAsync()
try
{
const vector<pair<String^, String^>> cachedFiles = {
{ StaticDataFilename, staticDataResponse },
{ AllRatiosDataFilename, allRatiosResponse }
};
const vector<pair<String ^, String ^>> cachedFiles = { { StaticDataFilename, staticDataResponse }, { AllRatiosDataFilename, allRatiosResponse } };
StorageFolder^ localCacheFolder = ApplicationData::Current->LocalCacheFolder;
StorageFolder ^ localCacheFolder = ApplicationData::Current->LocalCacheFolder;
for (const auto& fileInfo : cachedFiles)
{
co_await Utils::WriteFileToFolder(
localCacheFolder,
fileInfo.first,
fileInfo.second,
CreationCollisionOption::ReplaceExisting);
co_await Utils::WriteFileToFolder(localCacheFolder, fileInfo.first, fileInfo.second, CreationCollisionOption::ReplaceExisting);
}
SaveLangCodeAndTimestamp();
@ -464,7 +429,7 @@ task<bool> CurrencyDataLoader::TryLoadDataFromWebAsync()
co_return true;
}
catch (Exception^ ex)
catch (Exception ^ ex)
{
TraceLogger::GetInstance().LogPlatformException(__FUNCTIONW__, ex);
co_return false;
@ -494,19 +459,15 @@ task<bool> CurrencyDataLoader::TryLoadDataFromWebOverrideAsync()
};
#pragma optimize("", on)
bool CurrencyDataLoader::TryParseWebResponses(
_In_ String^ staticDataJson,
_In_ String^ allRatiosJson,
_Inout_ vector<UCM::CurrencyStaticData>& staticData,
_Inout_ CurrencyRatioMap& allRatiosData)
bool CurrencyDataLoader::TryParseWebResponses(_In_ String ^ staticDataJson, _In_ String ^ allRatiosJson, _Inout_ vector<UCM::CurrencyStaticData>& staticData,
_Inout_ CurrencyRatioMap& allRatiosData)
{
return TryParseStaticData(staticDataJson, staticData)
&& TryParseAllRatiosData(allRatiosJson, allRatiosData);
return TryParseStaticData(staticDataJson, staticData) && TryParseAllRatiosData(allRatiosJson, allRatiosData);
}
bool CurrencyDataLoader::TryParseStaticData(_In_ String^ rawJson, _Inout_ vector<UCM::CurrencyStaticData>& staticData)
bool CurrencyDataLoader::TryParseStaticData(_In_ String ^ rawJson, _Inout_ vector<UCM::CurrencyStaticData>& staticData)
{
JsonArray^ data = nullptr;
JsonArray ^ data = nullptr;
if (!JsonArray::TryParse(rawJson, &data))
{
return false;
@ -518,46 +479,31 @@ bool CurrencyDataLoader::TryParseStaticData(_In_ String^ rawJson, _Inout_ vector
wstring currencyName{ L"" };
wstring currencySymbol{ L"" };
vector<wstring*> values = {
&countryCode,
&countryName,
&currencyCode,
&currencyName,
&currencySymbol
};
vector<wstring*> values = { &countryCode, &countryName, &currencyCode, &currencyName, &currencySymbol };
assert(values.size() == STATIC_DATA_PROPERTIES.size());
staticData.resize(size_t{ data->Size });
for (unsigned int i = 0; i < data->Size; i++)
{
JsonObject^ obj = data->GetAt(i)->GetObject();
JsonObject ^ obj = data->GetAt(i)->GetObject();
for (size_t j = 0; j < values.size(); j++)
{
(*values[j]) = obj->GetNamedString(StringReference(STATIC_DATA_PROPERTIES[j].data()))->Data();
}
staticData[i] = CurrencyStaticData{
countryCode,
countryName,
currencyCode,
currencyName,
currencySymbol
};
staticData[i] = CurrencyStaticData{ countryCode, countryName, currencyCode, currencyName, currencySymbol };
}
// TODO - MSFT 8533667: this sort will be replaced by a WinRT call to sort localized strings
sort(begin(staticData), end(staticData), [](CurrencyStaticData unit1, CurrencyStaticData unit2)
{
return unit1.countryName < unit2.countryName;
});
sort(begin(staticData), end(staticData), [](CurrencyStaticData unit1, CurrencyStaticData unit2) { return unit1.countryName < unit2.countryName; });
return true;
}
bool CurrencyDataLoader::TryParseAllRatiosData(_In_ String^ rawJson, _Inout_ CurrencyRatioMap& allRatios)
bool CurrencyDataLoader::TryParseAllRatiosData(_In_ String ^ rawJson, _Inout_ CurrencyRatioMap& allRatios)
{
JsonArray^ data = nullptr;
JsonArray ^ data = nullptr;
if (!JsonArray::TryParse(rawJson, &data))
{
return false;
@ -568,17 +514,13 @@ bool CurrencyDataLoader::TryParseAllRatiosData(_In_ String^ rawJson, _Inout_ Cur
allRatios.clear();
for (unsigned int i = 0; i < data->Size; i++)
{
JsonObject^ obj = data->GetAt(i)->GetObject();
JsonObject ^ obj = data->GetAt(i)->GetObject();
// Rt is ratio, An is target currency ISO code.
double relativeRatio = obj->GetNamedNumber(StringReference(RATIO_KEY));
wstring targetCurrencyCode = obj->GetNamedString(StringReference(CURRENCY_CODE_KEY))->Data();
allRatios.emplace(targetCurrencyCode, CurrencyRatio{
relativeRatio,
sourceCurrencyCode,
targetCurrencyCode
});
allRatios.emplace(targetCurrencyCode, CurrencyRatio{ relativeRatio, sourceCurrencyCode, targetCurrencyCode });
}
return true;
@ -702,7 +644,7 @@ void CurrencyDataLoader::NotifyDataLoadFinished(bool didLoad)
void CurrencyDataLoader::SaveLangCodeAndTimestamp()
{
ApplicationDataContainer^ localSettings = ApplicationData::Current->LocalSettings;
ApplicationDataContainer ^ localSettings = ApplicationData::Current->LocalSettings;
if (localSettings == nullptr)
{
return;
@ -729,17 +671,13 @@ wstring CurrencyDataLoader::GetCurrencyTimestamp()
DateTime epoch{};
if (m_cacheTimestamp.UniversalTime != epoch.UniversalTime)
{
DateTimeFormatter^ dateFormatter = ref new DateTimeFormatter(L"{month.abbreviated} {day.integer}, {year.full}");
DateTimeFormatter ^ dateFormatter = ref new DateTimeFormatter(L"{month.abbreviated} {day.integer}, {year.full}");
wstring date = dateFormatter->Format(m_cacheTimestamp)->Data();
DateTimeFormatter^ timeFormatter = ref new DateTimeFormatter(L"shorttime");
DateTimeFormatter ^ timeFormatter = ref new DateTimeFormatter(L"shorttime");
wstring time = timeFormatter->Format(m_cacheTimestamp)->Data();
timestamp = LocalizationStringUtil::GetLocalizedString(
m_timestampFormat.c_str(),
date.c_str(),
time.c_str()
);
timestamp = LocalizationStringUtil::GetLocalizedString(m_timestampFormat.c_str(), date.c_str(), time.c_str());
}
return timestamp;
@ -758,23 +696,25 @@ task<SelectedUnits> CurrencyDataLoader::GetDefaultFromToCurrency()
try
{
// Second, see if the current locale has preset defaults in DefaultFromToCurrency.json.
Uri^ fileUri = ref new Uri(StringReference(DEFAULT_FROM_TO_CURRENCY_FILE_URI));
StorageFile^ defaultFromToCurrencyFile = co_await StorageFile::GetFileFromApplicationUriAsync(fileUri);
Uri ^ fileUri = ref new Uri(StringReference(DEFAULT_FROM_TO_CURRENCY_FILE_URI));
StorageFile ^ defaultFromToCurrencyFile = co_await StorageFile::GetFileFromApplicationUriAsync(fileUri);
if (defaultFromToCurrencyFile != nullptr)
{
String^ fileContents = co_await FileIO::ReadTextAsync(defaultFromToCurrencyFile);
JsonObject^ fromToObject = JsonObject::Parse(fileContents);
JsonObject^ regionalDefaults = fromToObject->GetNamedObject(m_responseLanguage);
String ^ fileContents = co_await FileIO::ReadTextAsync(defaultFromToCurrencyFile);
JsonObject ^ fromToObject = JsonObject::Parse(fileContents);
JsonObject ^ regionalDefaults = fromToObject->GetNamedObject(m_responseLanguage);
// Get both values before assignment in-case either fails.
String^ selectedFrom = regionalDefaults->GetNamedString(StringReference(FROM_KEY));
String^ selectedTo = regionalDefaults->GetNamedString(StringReference(TO_KEY));
String ^ selectedFrom = regionalDefaults->GetNamedString(StringReference(FROM_KEY));
String ^ selectedTo = regionalDefaults->GetNamedString(StringReference(TO_KEY));
fromCurrency = selectedFrom->Data();
toCurrency = selectedTo->Data();
}
}
catch (...) {}
catch (...)
{
}
}
co_return make_pair(fromCurrency, toCurrency);
@ -783,16 +723,16 @@ task<SelectedUnits> CurrencyDataLoader::GetDefaultFromToCurrency()
bool CurrencyDataLoader::TryGetLastUsedCurrenciesFromLocalSettings(_Out_ wstring* const fromCurrency, _Out_ wstring* const toCurrency)
{
String^ fromKey = UnitConverterResourceKeys::CurrencyUnitFromKey;
String^ toKey = UnitConverterResourceKeys::CurrencyUnitToKey;
ApplicationDataContainer^ localSettings = ApplicationData::Current->LocalSettings;
String ^ fromKey = UnitConverterResourceKeys::CurrencyUnitFromKey;
String ^ toKey = UnitConverterResourceKeys::CurrencyUnitToKey;
ApplicationDataContainer ^ localSettings = ApplicationData::Current->LocalSettings;
if (localSettings != nullptr && localSettings->Values != nullptr)
{
IPropertySet^ values = localSettings->Values;
IPropertySet ^ values = localSettings->Values;
if (values->HasKey(fromKey) && values->HasKey(toKey))
{
*fromCurrency = static_cast<String^>(values->Lookup(fromKey))->Data();
*toCurrency = static_cast<String^>(values->Lookup(toKey))->Data();
*fromCurrency = static_cast<String ^>(values->Lookup(fromKey))->Data();
*toCurrency = static_cast<String ^>(values->Lookup(toKey))->Data();
return true;
}
@ -803,12 +743,12 @@ bool CurrencyDataLoader::TryGetLastUsedCurrenciesFromLocalSettings(_Out_ wstring
void CurrencyDataLoader::SaveSelectedUnitsToLocalSettings(_In_ const SelectedUnits& selectedUnits)
{
String^ fromKey = UnitConverterResourceKeys::CurrencyUnitFromKey;
String^ toKey = UnitConverterResourceKeys::CurrencyUnitToKey;
ApplicationDataContainer^ localSettings = ApplicationData::Current->LocalSettings;
String ^ fromKey = UnitConverterResourceKeys::CurrencyUnitFromKey;
String ^ toKey = UnitConverterResourceKeys::CurrencyUnitToKey;
ApplicationDataContainer ^ localSettings = ApplicationData::Current->LocalSettings;
if (localSettings != nullptr && localSettings->Values != nullptr)
{
IPropertySet^ values = localSettings->Values;
IPropertySet ^ values = localSettings->Values;
values->Insert(fromKey, StringReference(selectedUnits.first.c_str()));
values->Insert(toKey, StringReference(selectedUnits.second.c_str()));
}

Some files were not shown because too many files have changed in this diff Show more