Merge with upstream/master

This commit is contained in:
Rudy Huyn 2019-03-25 22:52:15 -07:00
commit b871f52c03
372 changed files with 3112 additions and 2149 deletions

View file

@ -5,7 +5,6 @@ root = true
[*]
indent_style = space
indent_size = 4
end_of_line = crlf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

1
.gitignore vendored
View file

@ -290,4 +290,5 @@ __pycache__/
# Calculator specific
Generated Files/
!/build/config/TRexDefs/**
!src/Calculator/TemporaryKey.pfx
!src/CalculatorUnitTests/CalculatorUnitTests_TemporaryKey.pfx

View file

@ -15,30 +15,33 @@ name: $(BuildDefinitionName)_$(date:yyMM).$(date:dd)$(rev:rrr)
jobs:
- job: Localize
pool:
name: Package ES Custom Demands Lab A
demands:
- ClientAlias -equals PKGESUTILAPPS
workspace:
clean: outputs
vmImage: vs2017-win2016
variables:
skipComponentGovernanceDetection: true
steps:
- checkout: self
clean: true
- task: PkgESSetupBuild@10
displayName: Initialize Package ES
- task: MicrosoftTDBuild.tdbuild-task.tdbuild-task.TouchdownBuildTask@1
displayName: Send resources to Touchdown Build
inputs:
productName: Calculator
branchVersion: true
teamId: 86
authId: d3dd8113-65b3-4526-bdca-a00a7d1c37ba
authKey: $(LocServiceKey)
isPreview: false
relativePathRoot: src/Calculator/Resources/en-US/
resourceFilePath: '*.resw'
outputDirectoryRoot: src/Calculator/Resources/
- task: PkgESTouchdownLocService@10
displayName: Package ES Touchdown Loc Service
- script: |
cd $(Build.SourcesDirectory)
git add -A
git diff --cached --exit-code
echo '##vso[task.setvariable variable=hasChanges]%errorlevel%'
git diff --cached > $(Build.ArtifactStagingDirectory)\LocalizedStrings.patch
displayName: Check for changes and create patch file
- task: PublishPipelineArtifact@0
displayName: Publish patch file as artifact
condition: eq(variables['hasChanges'], '1')
inputs:
IsCallToServiceStepSelected: true
IsCheckedInFileSelected: true
CheckinFilesAtOriginFilePath: true
GitLocPath: Loc/Resources
LocConfigFile: build/config/LocConfigPackageEs.xml
AuthenticationMode: OAuth
ClientApplicationID: d3dd8113-65b3-4526-bdca-a00a7d1c37ba
ApplicationKeyID: $(LocServiceKey)
SendToLoc: true
artifactName: Patch
targetPath: $(Build.ArtifactStagingDirectory)

View file

@ -9,8 +9,8 @@ pr: none
variables:
versionMajor: 10
versionMinor: 1902
versionBuild: $[counter('10.1902.*', 0)]
versionMinor: 1903
versionBuild: $[counter('10.1903.*', 0)]
versionPatch: 0
name: '$(versionMajor).$(versionMinor).$(versionBuild).$(versionPatch)'

View file

@ -29,7 +29,7 @@ jobs:
downloadDirectory: $(Build.SourcesDirectory)
vstsFeed: WindowsApps
vstsFeedPackage: calculator-internals
vstsPackageVersion: 0.0.7
vstsPackageVersion: 0.0.10
- template: ./build-single-architecture.yaml
parameters:

View file

@ -87,7 +87,7 @@ jobs:
downloadDirectory: $(Build.SourcesDirectory)
vstsFeed: WindowsApps
vstsFeedPackage: calculator-internals
vstsPackageVersion: 0.0.7
vstsPackageVersion: 0.0.10
- task: PkgESStoreBrokerPackage@10
displayName: Create StoreBroker Packages

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 61 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 64 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 MiB

After

Width:  |  Height:  |  Size: 3 MiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 MiB

After

Width:  |  Height:  |  Size: 2.1 MiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 MiB

After

Width:  |  Height:  |  Size: 3.1 MiB

Before After
Before After

View file

@ -9,6 +9,7 @@ In 2019, the Windows Calculator team is focused on:
* Iterating upon the existing app design based on the latest [Fluent Design guidelines](https://developer.microsoft.com/en-us/windows/apps/design)
* Improving testing and diagnostics within the project
* Investigating new features with a focus on addressing top user feedback, including:
* Adding graphing mode
* Adding the ability for users to pin Calculator on top of other windows
* Providing additional customization options
* [Your feature idea here] - please review our [new feature development process](https://github.com/Microsoft/calculator/blob/master/docs/NewFeatureProcess.md) to get started!

View file

@ -1,10 +0,0 @@
root = true
[*.{xaml,cpp,h}]
charset = utf-8-bom
indent_style = space
indent_size = 4
[*.{cpp,h}]
insert_final_newline = true
trim_trailing_whitespace = true

View file

@ -3,6 +3,7 @@
#include "pch.h"
#include "Header Files/CalcEngine.h"
#include "Header Files/CalcUtils.h"
bool IsOpInRange(WPARAM op, uint32_t x, uint32_t y)
{

View file

@ -2,18 +2,25 @@
// Licensed under the MIT License.
#include "pch.h"
#pragma once
#include "Header Files/CalcEngine.h"
#include "Command.h"
#include "CalculatorVector.h"
#include "ExpressionCommand.h"
#include "CalcException.h"
constexpr int ASCII_0 = 48;
using namespace std;
using namespace CalcEngine;
namespace {
void IFT(HRESULT hr)
{
if (FAILED(hr))
{
throw hr;
}
}
}
void CHistoryCollector::ReinitHistory()
{
m_lastOpStartIndex = -1;
@ -406,37 +413,39 @@ int CHistoryCollector::AddCommand(_In_ const std::shared_ptr<IExpressionCommand>
return nCommands - 1;
}
//To Update the operands in the Expression according to the current Radix
// To Update the operands in the Expression according to the current Radix
void CHistoryCollector::UpdateHistoryExpression(uint32_t radix, int32_t precision)
{
if (m_spTokens != nullptr)
if (m_spTokens == nullptr)
{
unsigned int size;
IFT(m_spTokens->GetSize(&size));
return;
}
for (unsigned int i = 0; i < size; ++i)
unsigned int size;
IFT(m_spTokens->GetSize(&size));
for (unsigned int i = 0; i < size; ++i)
{
std::pair<std::wstring, int> token;
IFT(m_spTokens->GetAt(i, &token));
int commandPosition = token.second;
if (commandPosition != -1)
{
std::pair<std::wstring, int> token;
IFT(m_spTokens->GetAt(i, &token));
int commandPosition = token.second;
if (commandPosition != -1)
std::shared_ptr<IExpressionCommand> expCommand;
IFT(m_spCommands->GetAt(commandPosition, &expCommand));
if (expCommand != nullptr && CalculationManager::CommandType::OperandCommand == expCommand->GetCommandType())
{
std::shared_ptr<IExpressionCommand> expCommand;
IFT(m_spCommands->GetAt(commandPosition, &expCommand));
if (expCommand != nullptr && CalculationManager::CommandType::OperandCommand == expCommand->GetCommandType())
std::shared_ptr<COpndCommand> opndCommand = std::static_pointer_cast<COpndCommand>(expCommand);
if (opndCommand != nullptr)
{
std::shared_ptr<COpndCommand> opndCommand = std::static_pointer_cast<COpndCommand>(expCommand);
if (opndCommand != nullptr)
{
token.first = opndCommand->GetString(radix, precision);
IFT(m_spTokens->SetAt(i, token));
opndCommand->SetCommands(GetOperandCommandsFromString(token.first));
}
token.first = opndCommand->GetString(radix, precision);
IFT(m_spTokens->SetAt(i, token));
opndCommand->SetCommands(GetOperandCommandsFromString(token.first));
}
}
}
SetExpressionDisplay();
}
SetExpressionDisplay();
}
void CHistoryCollector::SetDecimalSymbol(wchar_t decimalSymbol)
@ -444,7 +453,7 @@ void CHistoryCollector::SetDecimalSymbol(wchar_t decimalSymbol)
m_decimalSymbol = decimalSymbol;
}
//Update the commands corresponding to the passed string Number
// Update the commands corresponding to the passed string Number
std::shared_ptr<CalculatorVector<int>> CHistoryCollector::GetOperandCommandsFromString(wstring_view numStr)
{
std::shared_ptr<CalculatorVector<int>> commands = std::make_shared<CalculatorVector<int>>();

View file

@ -26,39 +26,41 @@
using namespace std;
using namespace CalcEngine;
// 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 BYTE 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 };
int iPrec;
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 BYTE 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;
while ((iPrec < ARRAYSIZE(rgbPrec)) && (nopCode != rgbPrec[iPrec]))
{
iPrec += 2;
}
if (iPrec >= ARRAYSIZE(rgbPrec))
{
iPrec = 0;
}
return rgbPrec[iPrec + 1];
while ((iPrec < size(rgbPrec)) && (nopCode != rgbPrec[iPrec]))
{
iPrec += 2;
}
if (iPrec >= size(rgbPrec))
{
iPrec = 0;
}
return rgbPrec[iPrec + 1];
}
}
// HandleErrorCommand
//
// When it is discovered by the state machine that at this point the input is not valid (eg. "1+)"), we want to proceed as though this input never
// When it is discovered by the state machine that at this point the input is not valid (eg. "1+)"), we want to proceed as though this input never
// occurred and may be some feedback to user like Beep. The rest of input can then continue by just ignoring this command.
void CCalcEngine::HandleErrorCommand(WPARAM idc)
{
if (!IsGuiSettingOpCode(idc))
{
// we would have saved the prev command. Need to forget this state
// We would have saved the prev command. Need to forget this state
m_nTempCom = m_nLastCom;
}
}
@ -180,7 +182,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
// BINARY OPERATORS:
if (IsBinOpCode(wParam))
{
/* Change the operation if last input was operation. */
// Change the operation if last input was operation.
if (IsBinOpCode(m_nLastCom))
{
INT nPrev;
@ -544,6 +546,11 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
if ((m_openParenCount >= MAXPRECDEPTH && nx) || (!m_openParenCount && !nx)
|| ((m_precedenceOpCount >= MAXPRECDEPTH && m_nPrecOp[m_precedenceOpCount - 1] != 0)))
{
if (!m_openParenCount && !nx)
{
m_pCalcDisplay->OnNoRightParenAdded();
}
HandleErrorCommand(wParam);
break;
}
@ -940,7 +947,7 @@ wstring_view CCalcEngine::OpCodeToUnaryString(int nOpCode, bool fInv, ANGLE_TYPE
// Try to lookup the ID in the UFNE table
int ids = 0;
int iufne = nOpCode - IDC_UNARYFIRST;
if (iufne >= 0 && iufne < ARRAYSIZE(rgUfne))
if (iufne >= 0 && (size_t)iufne < size(rgUfne))
{
if (fInv)
{
@ -1020,7 +1027,7 @@ wstring CCalcEngine::GetCurrentResultForRadix(uint32_t radix, int32_t precision)
wstring numberString = GetStringForDisplay(rat, radix);
if (!numberString.empty())
{
//revert the precision to previously stored precision
// Revert the precision to previously stored precision
ChangeConstants(m_radix, m_precision);
}

View file

@ -70,7 +70,7 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
uint64_t w64Bits = result.ToUInt64_t();
uint64_t lsb = ((w64Bits & 0x01) == 1) ? 1 : 0;
w64Bits >>= 1; //RShift by 1
w64Bits >>= 1; // RShift by 1
w64Bits |= (lsb << (m_dwWordBitWidth - 1));
result = w64Bits;

View file

@ -6,6 +6,7 @@
using namespace CalcEngine;
using namespace CalcEngine::RationalMath;
using namespace std;
// To be called when either the radix or num width changes. You can use -1 in either of these values to mean
// dont change that.
@ -55,7 +56,7 @@ LONG CCalcEngine::DwWordBitWidthFromeNumWidth(NUM_WIDTH /*numwidth*/)
static constexpr int nBitMax[] = { 64, 32, 16, 8 };
LONG wmax = nBitMax[0];
if (m_numwidth >= 0 && m_numwidth < ARRAYSIZE(nBitMax))
if (m_numwidth >= 0 && (size_t)m_numwidth < size(nBitMax))
{
wmax = nBitMax[m_numwidth];
}
@ -68,7 +69,7 @@ uint32_t CCalcEngine::NRadixFromRadixType(RADIX_TYPE radixtype)
uint32_t radix = 10;
// convert special bases into symbolic values
if (radixtype >= 0 && radixtype < ARRAYSIZE(rgnRadish))
if (radixtype >= 0 && (size_t)radixtype < size(rgnRadish))
{
radix = rgnRadish[radixtype];
}

View file

@ -1,26 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
class CalcException : public std::exception
{
public:
CalcException(HRESULT hr)
{
m_hr = hr;
}
HRESULT GetException()
{
return m_hr;
}
private:
HRESULT m_hr;
};
void IFT(HRESULT hr)
{
if (FAILED(hr))
{
CalcException exception(hr);
throw(exception);
}
}

View file

@ -119,7 +119,6 @@
<ClInclude Include="Ratpack\ratpak.h">
<Filter>RatPack</Filter>
</ClInclude>
<ClInclude Include="CalcException.h" />
<ClInclude Include="CalculatorVector.h" />
<ClInclude Include="Header Files\CalcEngine.h">
<Filter>Header Files</Filter>

View file

@ -7,8 +7,7 @@
using namespace std;
using namespace CalculationManager;
CalculatorHistory::CalculatorHistory(CALCULATOR_MODE eMode, size_t maxSize) :
m_mode(eMode),
CalculatorHistory::CalculatorHistory(size_t maxSize) :
m_maxHistorySize(maxSize)
{}
@ -35,15 +34,13 @@ unsigned int CalculatorHistory::AddToHistory(_In_ shared_ptr<CalculatorVector <p
unsigned int CalculatorHistory::AddItem(_In_ shared_ptr<HISTORYITEM> const &spHistoryItem)
{
int lastIndex;
if (m_historyItems.size() >= m_maxHistorySize)
{
m_historyItems.erase(m_historyItems.begin());
}
m_historyItems.push_back(spHistoryItem);
lastIndex = static_cast<unsigned>(m_historyItems.size() - 1);
unsigned int lastIndex = static_cast<unsigned>(m_historyItems.size() - 1);
return lastIndex;
}

View file

@ -31,7 +31,7 @@ namespace CalculationManager
{
public:
CalculatorHistory(CALCULATOR_MODE eMode, const size_t maxSize);
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);
std::vector<std::shared_ptr<HISTORYITEM>> const& GetHistory();
std::shared_ptr<HISTORYITEM> const& GetHistoryItem(unsigned int uIdx);
@ -43,7 +43,6 @@ namespace CalculationManager
private:
std::vector<std::shared_ptr<HISTORYITEM>> m_historyItems;
CALCULATOR_MODE m_mode;
const size_t m_maxHistorySize;
};
}

View file

@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#include "pch.h"
@ -24,15 +24,15 @@ 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_isExponentialFormat(false),
m_persistedPrimaryValue(),
m_currentCalculatorEngine(nullptr),
m_pStdHistory(new CalculatorHistory(CM_STD, MAX_HISTORY_ITEMS)),
m_pSciHistory(new CalculatorHistory(CM_SCI, MAX_HISTORY_ITEMS)),
m_inHistoryItemLoadMode(false)
m_pStdHistory(new CalculatorHistory(MAX_HISTORY_ITEMS)),
m_pSciHistory(new CalculatorHistory(MAX_HISTORY_ITEMS))
{
CCalcEngine::InitialOneTimeOnlySetup(*m_resourceProvider);
}
@ -109,7 +109,6 @@ namespace CalculationManager
/// <summary>
/// Callback from the engine
/// Used to set the current unmatched open parenthesis count
/// </summary>
/// <param name="parenthesisCount">string containing the parenthesis count</param>
void CalculatorManager::SetParenDisplayText(const wstring& parenthesisCount)
@ -117,6 +116,14 @@ namespace CalculationManager
m_displayCallback->SetParenDisplayText(parenthesisCount);
}
/// <summary>
/// Callback from the engine
/// </summary>
void CalculatorManager::OnNoRightParenAdded()
{
m_displayCallback->OnNoRightParenAdded();
}
/// <summary>
/// Reset CalculatorManager.
/// Set the mode to the standard calculator
@ -285,7 +292,7 @@ namespace CalculationManager
break;
case Command::CommandFE:
m_isExponentialFormat = !m_isExponentialFormat;
// fall through
[[fallthrough]];
default:
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(command));
break;
@ -301,7 +308,10 @@ namespace CalculationManager
unsigned char CalculatorManager::MapCommandForSerialize(Command command)
{
unsigned int commandToSave = static_cast<unsigned int>(command);
commandToSave > UCHAR_MAX ? commandToSave -= UCHAR_MAX : commandToSave;
if (commandToSave > UCHAR_MAX)
{
commandToSave -= UCHAR_MAX;
}
return static_cast<unsigned char>(commandToSave);
}
@ -353,7 +363,7 @@ namespace CalculationManager
/// <param name = "serializedPrimaryDisplay">Serialized Rational of primary display</param>
void CalculatorManager::DeSerializePrimaryDisplay(const vector<long> &serializedPrimaryDisplay)
{
if (serializedPrimaryDisplay.size() == 0)
if (serializedPrimaryDisplay.empty())
{
return;
}
@ -428,9 +438,9 @@ namespace CalculationManager
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.
//Hence, a simple cast to MemoryCommand is not sufficient.
// 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.
// Hence, a simple cast to MemoryCommand is not sufficient.
MemoryCommand memoryCommand = static_cast<MemoryCommand>(*commandItr + UCHAR_MAX + 1);
unsigned int indexOfMemory = 0;
switch (memoryCommand)
@ -483,22 +493,25 @@ namespace CalculationManager
void CalculatorManager::MemorizeNumber()
{
m_savedCommands.push_back(MEMORY_COMMAND_TO_UNSIGNED_CHAR(MemoryCommand::MemorizeNumber));
if (!(m_currentCalculatorEngine->FInErrorState()))
if (m_currentCalculatorEngine->FInErrorState())
{
m_currentCalculatorEngine->ProcessCommand(IDC_STORE);
auto memoryObjectPtr = m_currentCalculatorEngine->PersistedMemObject();
if (memoryObjectPtr != nullptr)
{
m_memorizedNumbers.insert(m_memorizedNumbers.begin(), *memoryObjectPtr);
}
if (m_memorizedNumbers.size() > m_maximumMemorySize)
{
m_memorizedNumbers.resize(m_maximumMemorySize);
}
this->SetMemorizedNumbersString();
return;
}
m_currentCalculatorEngine->ProcessCommand(IDC_STORE);
auto memoryObjectPtr = m_currentCalculatorEngine->PersistedMemObject();
if (memoryObjectPtr != nullptr)
{
m_memorizedNumbers.insert(m_memorizedNumbers.begin(), *memoryObjectPtr);
}
if (m_memorizedNumbers.size() > m_maximumMemorySize)
{
m_memorizedNumbers.resize(m_maximumMemorySize);
}
this->SetMemorizedNumbersString();
}
/// <summary>
@ -509,11 +522,14 @@ namespace CalculationManager
void CalculatorManager::MemorizedNumberLoad(_In_ unsigned int indexOfMemory)
{
SaveMemoryCommand(MemoryCommand::MemorizedNumberLoad, indexOfMemory);
if (!(m_currentCalculatorEngine->FInErrorState()))
if (m_currentCalculatorEngine->FInErrorState())
{
this->MemorizedNumberSelect(indexOfMemory);
m_currentCalculatorEngine->ProcessCommand(IDC_RECALL);
return;
}
this->MemorizedNumberSelect(indexOfMemory);
m_currentCalculatorEngine->ProcessCommand(IDC_RECALL);
}
/// <summary>
@ -525,24 +541,27 @@ namespace CalculationManager
void CalculatorManager::MemorizedNumberAdd(_In_ unsigned int indexOfMemory)
{
SaveMemoryCommand(MemoryCommand::MemorizedNumberAdd, indexOfMemory);
if (!(m_currentCalculatorEngine->FInErrorState()))
if (m_currentCalculatorEngine->FInErrorState())
{
if (m_memorizedNumbers.empty())
{
this->MemorizeNumber();
}
else
{
this->MemorizedNumberSelect(indexOfMemory);
m_currentCalculatorEngine->ProcessCommand(IDC_MPLUS);
this->MemorizedNumberChanged(indexOfMemory);
this->SetMemorizedNumbersString();
}
m_displayCallback->MemoryItemChanged(indexOfMemory);
return;
}
if (m_memorizedNumbers.empty())
{
this->MemorizeNumber();
}
else
{
this->MemorizedNumberSelect(indexOfMemory);
m_currentCalculatorEngine->ProcessCommand(IDC_MPLUS);
this->MemorizedNumberChanged(indexOfMemory);
this->SetMemorizedNumbersString();
}
m_displayCallback->MemoryItemChanged(indexOfMemory);
}
void CalculatorManager::MemorizedNumberClear(_In_ unsigned int indexOfMemory)
@ -563,27 +582,30 @@ namespace CalculationManager
void CalculatorManager::MemorizedNumberSubtract(_In_ unsigned int indexOfMemory)
{
SaveMemoryCommand(MemoryCommand::MemorizedNumberSubtract, indexOfMemory);
if (!(m_currentCalculatorEngine->FInErrorState()))
if (m_currentCalculatorEngine->FInErrorState())
{
// To add negative of the number on display to the memory -x = x - 2x
if (m_memorizedNumbers.empty())
{
this->MemorizeNumber();
this->MemorizedNumberSubtract(0);
this->MemorizedNumberSubtract(0);
}
else
{
this->MemorizedNumberSelect(indexOfMemory);
m_currentCalculatorEngine->ProcessCommand(IDC_MMINUS);
this->MemorizedNumberChanged(indexOfMemory);
this->SetMemorizedNumbersString();
}
m_displayCallback->MemoryItemChanged(indexOfMemory);
return;
}
// To add negative of the number on display to the memory -x = x - 2x
if (m_memorizedNumbers.empty())
{
this->MemorizeNumber();
this->MemorizedNumberSubtract(0);
this->MemorizedNumberSubtract(0);
}
else
{
this->MemorizedNumberSelect(indexOfMemory);
m_currentCalculatorEngine->ProcessCommand(IDC_MMINUS);
this->MemorizedNumberChanged(indexOfMemory);
this->SetMemorizedNumbersString();
}
m_displayCallback->MemoryItemChanged(indexOfMemory);
}
/// <summary>
@ -606,11 +628,13 @@ namespace CalculationManager
/// <param name="indexOfMemory">Index of the target memory</param>
void CalculatorManager::MemorizedNumberSelect(_In_ unsigned int indexOfMemory)
{
if (!(m_currentCalculatorEngine->FInErrorState()))
if (m_currentCalculatorEngine->FInErrorState())
{
auto memoryObject = m_memorizedNumbers.at(indexOfMemory);
m_currentCalculatorEngine->PersistedMemObject(memoryObject);
return;
}
auto memoryObject = m_memorizedNumbers.at(indexOfMemory);
m_currentCalculatorEngine->PersistedMemObject(memoryObject);
}
/// <summary>
@ -620,13 +644,15 @@ namespace CalculationManager
/// <param name="indexOfMemory">Index of the target memory</param>
void CalculatorManager::MemorizedNumberChanged(_In_ unsigned int indexOfMemory)
{
if (!(m_currentCalculatorEngine->FInErrorState()))
if (m_currentCalculatorEngine->FInErrorState())
{
auto memoryObject = m_currentCalculatorEngine->PersistedMemObject();
if (memoryObject != nullptr)
{
m_memorizedNumbers.at(indexOfMemory) = *memoryObject;
}
return;
}
auto memoryObject = m_currentCalculatorEngine->PersistedMemObject();
if (memoryObject != nullptr)
{
m_memorizedNumbers.at(indexOfMemory) = *memoryObject;
}
}

View file

@ -42,7 +42,7 @@ namespace CalculationManager
MemorizedNumberClear = 335
};
class CalculatorManager sealed : public virtual ICalcDisplay
class CalculatorManager final : public ICalcDisplay
{
private:
ICalcDisplay* const m_displayCallback;
@ -94,7 +94,8 @@ namespace CalculationManager
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 SetParenDisplayText(const std::wstring& parenthesisCount);
void SetParenDisplayText(const std::wstring& parenthesisCount) override;
void OnNoRightParenAdded() override;
void DisplayPasteError();
void MaxDigitsReached() override;
void BinaryOperatorReceived() override;
@ -140,7 +141,7 @@ namespace CalculationManager
std::shared_ptr<HISTORYITEM> const& GetHistoryItem(_In_ unsigned int uIdx);
bool RemoveHistoryItem(_In_ unsigned int uIdx);
void ClearHistory();
const 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

@ -94,7 +94,7 @@ namespace CalculationManager
CommandFAC = 113,
CommandREC = 114,
CommandDMS = 115,
CommandCUBEROOT = 116, //x ^ 1/3
CommandCUBEROOT = 116, // x ^ 1/3
CommandPOW10 = 117, // 10 ^ x
CommandPERCENT = 118,

View file

@ -98,8 +98,8 @@ void CBinaryCommand::Accept(_In_ ISerializeCommandVisitor &commandVisitor)
COpndCommand::COpndCommand(shared_ptr<CalculatorVector<int>> const &commands, bool fNegative, bool fDecimal, bool fSciFmt) :
m_commands(commands),
m_fNegative(fNegative),
m_fDecimal(fDecimal),
m_fSciFmt(fSciFmt),
m_fDecimal(fDecimal),
m_fInitialized(false),
m_value{}
{}

View file

@ -97,7 +97,7 @@
#define IDC_FAC 113
#define IDC_REC 114
#define IDC_DMS 115
#define IDC_CUBEROOT 116 //x ^ 1/3
#define IDC_CUBEROOT 116 // x ^ 1/3
#define IDC_POW10 117 // 10 ^ x
#define IDC_PERCENT 118
#define IDC_UNARYLAST IDC_PERCENT

View file

@ -85,7 +85,7 @@ private:
// 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_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. */
CalcEngine::Rational m_maxTrigonometricNum;

View file

@ -13,6 +13,7 @@ public:
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 SetParenDisplayText(const std::wstring& pszText) = 0;
virtual void OnNoRightParenAdded() = 0;
virtual void MaxDigitsReached() = 0; // not an error but still need to inform UI layer.
virtual void BinaryOperatorReceived() = 0;
virtual void OnHistoryItemAdded(_In_ unsigned int addedItemIndex) = 0;

View file

@ -61,7 +61,7 @@ void* zmalloc(size_t a)
//
//-----------------------------------------------------------------------------
void _dupnum(_In_ PNUMBER dest, _In_ PNUMBER src)
void _dupnum(_In_ PNUMBER dest, _In_ const NUMBER * const src)
{
memcpy(dest, src, (int)(sizeof(NUMBER) + ((src)->cdigit)*(sizeof(MANTTYPE))));
}
@ -612,6 +612,7 @@ PNUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precis
break;
}
// Drop through in the 'e'-as-a-digit case
[[fallthrough]];
default:
state = machine[state][NZ];
break;
@ -646,7 +647,7 @@ PNUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precis
break;
case LD:
pnumret->exp++;
// Fall through
[[fallthrough]];
case DD:
{
curChar = NormalizeCharDigit(curChar, radix);
@ -1270,7 +1271,7 @@ PNUMBER RatToNumber(_In_ PRAT prat, uint32_t radix, int32_t precision)
// Convert p and q of rational form from internal base to requested base.
// Scale by largest power of BASEX possible.
long scaleby = min(temprat->pp->exp, temprat->pq->exp);
scaleby = max(scaleby, 0);
scaleby = max(scaleby, 0l);
temprat->pp->exp -= scaleby;
temprat->pq->exp -= scaleby;

View file

@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//---------------------------------------------------------------------------
@ -16,7 +16,7 @@
#include "pch.h"
#include "ratpak.h"
using namespace std;
void lshrat( PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
@ -211,9 +211,8 @@ void modrat( PRAT *pa, PRAT b )
remnum( &((*pa)->pp), tmp->pp, BASEX );
mulnumx( &((*pa)->pq), tmp->pq );
//Get *pa back in the integer over integer form.
// Get *pa back in the integer over integer form.
RENORMALIZE(*pa);
destroyrat( tmp );
}

View file

@ -82,7 +82,7 @@ void fracrat( PRAT *pa , uint32_t radix, int32_t precision)
remnum( &((*pa)->pp), (*pa)->pq, BASEX );
//Get *pa back in the integer over integer form.
// Get *pa back in the integer over integer form.
RENORMALIZE(*pa);
}

View file

@ -1,480 +1,482 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
// Autogenerated by _dumprawrat in support.c
NUMBER init_num_one= {
#pragma once
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_num_one= {
1,
1,
0,
{ 1,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_num_two= {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_num_two= {
1,
1,
0,
{ 2,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_num_five= {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_num_five= {
1,
1,
0,
{ 5,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_num_six= {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_num_six= {
1,
1,
0,
{ 6,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_num_ten= {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_num_ten= {
1,
1,
0,
{ 10,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_rat_smallest = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_smallest = {
1,
1,
0,
{ 1,}
};
NUMBER init_q_rat_smallest = {
inline const NUMBER init_q_rat_smallest = {
1,
4,
0,
{ 0, 190439170, 901055854, 10097,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_rat_negsmallest = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_negsmallest = {
-1,
1,
0,
{ 1,}
};
NUMBER init_q_rat_negsmallest = {
inline const NUMBER init_q_rat_negsmallest = {
1,
4,
0,
{ 0, 190439170, 901055854, 10097,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_pt_eight_five = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_pt_eight_five = {
1,
1,
0,
{ 85,}
};
NUMBER init_q_pt_eight_five = {
inline const NUMBER init_q_pt_eight_five = {
1,
1,
0,
{ 100,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_rat_six = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_six = {
1,
1,
0,
{ 6,}
};
NUMBER init_q_rat_six = {
inline const NUMBER init_q_rat_six = {
1,
1,
0,
{ 1,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_rat_two = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_two = {
1,
1,
0,
{ 2,}
};
NUMBER init_q_rat_two = {
inline const NUMBER init_q_rat_two = {
1,
1,
0,
{ 1,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_rat_zero = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_zero = {
1,
1,
0,
{ 0,}
};
NUMBER init_q_rat_zero = {
inline const NUMBER init_q_rat_zero = {
1,
1,
0,
{ 1,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_rat_one = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_one = {
1,
1,
0,
{ 1,}
};
NUMBER init_q_rat_one = {
inline const NUMBER init_q_rat_one = {
1,
1,
0,
{ 1,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_rat_neg_one = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_neg_one = {
-1,
1,
0,
{ 1,}
};
NUMBER init_q_rat_neg_one = {
inline const NUMBER init_q_rat_neg_one = {
1,
1,
0,
{ 1,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_rat_half = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_half = {
1,
1,
0,
{ 1,}
};
NUMBER init_q_rat_half = {
inline const NUMBER init_q_rat_half = {
1,
1,
0,
{ 2,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_rat_ten = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_ten = {
1,
1,
0,
{ 10,}
};
NUMBER init_q_rat_ten = {
inline const NUMBER init_q_rat_ten = {
1,
1,
0,
{ 1,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_pi = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_pi = {
1,
6,
0,
{ 125527896, 283898350, 1960493936, 1672850762, 1288168272, 8,}
};
NUMBER init_q_pi = {
inline const NUMBER init_q_pi = {
1,
6,
0,
{ 1288380402, 1120116153, 1860424692, 1944118326, 1583591604, 2,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_two_pi = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_two_pi = {
1,
6,
0,
{ 251055792, 567796700, 1773504224, 1198217877, 428852897, 17,}
};
NUMBER init_q_two_pi = {
inline const NUMBER init_q_two_pi = {
1,
6,
0,
{ 1288380402, 1120116153, 1860424692, 1944118326, 1583591604, 2,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_pi_over_two = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_pi_over_two = {
1,
6,
0,
{ 125527896, 283898350, 1960493936, 1672850762, 1288168272, 8,}
};
NUMBER init_q_pi_over_two = {
inline const NUMBER init_q_pi_over_two = {
1,
6,
0,
{ 429277156, 92748659, 1573365737, 1740753005, 1019699561, 5,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_one_pt_five_pi = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_one_pt_five_pi = {
1,
6,
0,
{ 1241201312, 270061909, 1051574664, 1924965045, 1340320627, 70,}
};
NUMBER init_q_one_pt_five_pi = {
inline const NUMBER init_q_one_pt_five_pi = {
1,
6,
0,
{ 1579671539, 1837970263, 1067644340, 523549916, 2119366659, 14,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_e_to_one_half = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_e_to_one_half = {
1,
6,
0,
{ 256945612, 216219427, 223516738, 477442596, 581063757, 23,}
};
NUMBER init_q_e_to_one_half = {
inline const NUMBER init_q_e_to_one_half = {
1,
6,
0,
{ 1536828363, 698484484, 1127331835, 224219346, 245499408, 14,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_rat_exp = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_exp = {
1,
6,
0,
{ 943665199, 1606559160, 1094967530, 1759391384, 1671799163, 1123581,}
};
NUMBER init_q_rat_exp = {
inline const NUMBER init_q_rat_exp = {
1,
6,
0,
{ 879242208, 2022880100, 617392930, 1374929092, 1367479163, 413342,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_ln_ten = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_ln_ten = {
1,
6,
0,
{ 2086268922, 165794492, 1416063951, 1851428830, 1893239400, 65366841,}
};
NUMBER init_q_ln_ten = {
inline const NUMBER init_q_ln_ten = {
1,
6,
0,
{ 26790652, 564532679, 783998273, 216030448, 1564709968, 28388458,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_ln_two = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_ln_two = {
1,
6,
0,
{ 1789230241, 1057927868, 715399197, 908801241, 1411265331, 3,}
};
NUMBER init_q_ln_two = {
inline const NUMBER init_q_ln_two = {
1,
6,
0,
{ 1559869847, 1930657510, 1228561531, 219003871, 593099283, 5,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_rad_to_deg = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rad_to_deg = {
1,
6,
0,
{ 2127722024, 1904928383, 2016479213, 2048947859, 1578647346, 492,}
};
NUMBER init_q_rad_to_deg = {
inline const NUMBER init_q_rad_to_deg = {
1,
6,
0,
{ 125527896, 283898350, 1960493936, 1672850762, 1288168272, 8,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_rad_to_grad = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rad_to_grad = {
1,
6,
0,
{ 2125526288, 684931327, 570267400, 129125085, 1038224725, 547,}
};
NUMBER init_q_rad_to_grad = {
inline const NUMBER init_q_rad_to_grad = {
1,
6,
0,
{ 125527896, 283898350, 1960493936, 1672850762, 1288168272, 8,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_rat_qword = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_qword = {
1,
3,
0,
{ 2147483647, 2147483647, 3,}
};
NUMBER init_q_rat_qword = {
inline const NUMBER init_q_rat_qword = {
1,
1,
0,
{ 1,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_rat_dword = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_dword = {
1,
2,
0,
{ 2147483647, 1,}
};
NUMBER init_q_rat_dword = {
inline const NUMBER init_q_rat_dword = {
1,
1,
0,
{ 1,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_rat_max_long = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_max_long = {
1,
1,
0,
{ 2147483647,}
};
NUMBER init_q_rat_max_long = {
inline const NUMBER init_q_rat_max_long = {
1,
1,
0,
{ 1,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_rat_min_long = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_min_long = {
-1,
2,
0,
{ 0, 1,}
};
NUMBER init_q_rat_min_long = {
inline const NUMBER init_q_rat_min_long = {
1,
1,
0,
{ 1,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_rat_word = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_word = {
1,
1,
0,
{ 65535,}
};
NUMBER init_q_rat_word = {
inline const NUMBER init_q_rat_word = {
1,
1,
0,
{ 1,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_rat_byte = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_byte = {
1,
1,
0,
{ 255,}
};
NUMBER init_q_rat_byte = {
inline const NUMBER init_q_rat_byte = {
1,
1,
0,
{ 1,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_rat_400 = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_400 = {
1,
1,
0,
{ 400,}
};
NUMBER init_q_rat_400 = {
inline const NUMBER init_q_rat_400 = {
1,
1,
0,
{ 1,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_rat_360 = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_360 = {
1,
1,
0,
{ 360,}
};
NUMBER init_q_rat_360 = {
inline const NUMBER init_q_rat_360 = {
1,
1,
0,
{ 1,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_rat_200 = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_200 = {
1,
1,
0,
{ 200,}
};
NUMBER init_q_rat_200 = {
inline const NUMBER init_q_rat_200 = {
1,
1,
0,
{ 1,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_rat_180 = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_180 = {
1,
1,
0,
{ 180,}
};
NUMBER init_q_rat_180 = {
inline const NUMBER init_q_rat_180 = {
1,
1,
0,
{ 1,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_rat_max_exp = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_max_exp = {
1,
1,
0,
{ 100000,}
};
NUMBER init_q_rat_max_exp = {
inline const NUMBER init_q_rat_max_exp = {
1,
1,
0,
{ 1,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_rat_min_exp = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_min_exp = {
-1,
1,
0,
{ 100000,}
};
NUMBER init_q_rat_min_exp = {
inline const NUMBER init_q_rat_min_exp = {
1,
1,
0,
{ 1,}
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_rat_max_fact = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_max_fact = {
1,
1,
0,
{ 3249, }
};
NUMBER init_q_rat_max_fact = {
inline const NUMBER init_q_rat_max_fact = {
1,
1,
0,
{ 1, }
};
// Autogenerated by _dumprawrat in support.c
NUMBER init_p_rat_min_fact = {
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_min_fact = {
-1,
1,
0,
{ 1000, }
};
NUMBER init_q_rat_min_fact = {
inline const NUMBER init_q_rat_min_fact = {
1,
1,
0,

View file

@ -225,7 +225,7 @@ memmove( (x)->pp->mant, &((x)->pp->mant[trim]), sizeof(MANTTYPE)*((x)->pp->cdigi
(x)->pp->cdigit -= trim; \
(x)->pp->exp += trim; \
} \
trim = min((x)->pp->exp,(x)->pq->exp);\
trim = std::min((x)->pp->exp,(x)->pq->exp);\
(x)->pp->exp -= trim;\
(x)->pq->exp -= trim;\
}
@ -411,7 +411,7 @@ extern void tanrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
// angle type
extern void tananglerat( _Inout_ PRAT *px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
extern void _dupnum(_In_ PNUMBER dest, _In_ PNUMBER src);
extern void _dupnum(_In_ PNUMBER dest, _In_ const NUMBER * const src);
extern void _destroynum( _In_ PNUMBER pnum );
extern void _destroyrat( _In_ PRAT prat );

View file

@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//----------------------------------------------------------------------------
@ -31,8 +31,8 @@ static int cbitsofprecision = 0;
#define READRAWNUM(v)
#define DUMPRAWRAT(v) _dumprawrat(#v,v, wcout)
#define DUMPRAWNUM(v) fprintf( stderr, \
"// Autogenerated by _dumprawrat in support.c\n" ); \
fprintf( stderr, "NUMBER init_" #v "= {\n" ); \
"// Autogenerated by _dumprawrat in support.cpp\n" ); \
fprintf( stderr, "inline const NUMBER init_" #v "= {\n" ); \
_dumprawnum(v, wcout); \
fprintf( stderr, "};\n" )

View file

@ -46,7 +46,7 @@ UnitConverter::UnitConverter(_In_ const shared_ptr<IConverterDataLoader>& dataLo
{
m_dataLoader = dataLoader;
m_currencyDataLoader = currencyDataLoader;
//declaring the delimiter character conversion map
// declaring the delimiter character conversion map
quoteConversions[L'|'] = L"{p}";
quoteConversions[L'['] = L"{lc}";
quoteConversions[L']'] = L"{rc}";
@ -109,22 +109,8 @@ CategorySelectionInitializer UnitConverter::SetCurrentCategory(const Category& i
vector<Unit>& unitVector = m_categoryToUnits[m_currentCategory];
for (unsigned int i = 0; i < unitVector.size(); i++)
{
if (unitVector[i].id == m_fromType.id)
{
unitVector[i].isConversionSource = true;
}
else
{
unitVector[i].isConversionSource = false;
}
if (unitVector[i].id == m_toType.id)
{
unitVector[i].isConversionTarget = true;
}
else
{
unitVector[i].isConversionTarget = false;
}
unitVector[i].isConversionSource = (unitVector[i].id == m_fromType.id);
unitVector[i].isConversionTarget = (unitVector[i].id == m_toType.id);
}
m_currentCategory = input;
if (!m_currentCategory.supportsNegative && m_currentDisplay.front() == L'-')
@ -156,15 +142,17 @@ Category UnitConverter::GetCurrentCategory()
/// <param name="toType">Unit struct we are converting to</param>
void UnitConverter::SetCurrentUnitTypes(const Unit& fromType, const Unit& toType)
{
if (CheckLoad())
if (!CheckLoad())
{
m_fromType = fromType;
m_toType = toType;
Calculate();
UpdateCurrencySymbols();
UpdateViewModel();
return;
}
m_fromType = fromType;
m_toType = toType;
Calculate();
UpdateCurrencySymbols();
UpdateViewModel();
}
/// <summary>
@ -181,22 +169,24 @@ void UnitConverter::SetCurrentUnitTypes(const Unit& fromType, const Unit& toType
/// </param>
void UnitConverter::SwitchActive(const wstring& newValue)
{
if (CheckLoad())
if (!CheckLoad())
{
swap(m_fromType, m_toType);
swap(m_currentHasDecimal, m_returnHasDecimal);
m_returnDisplay = m_currentDisplay;
m_currentDisplay = newValue;
m_currentHasDecimal = (m_currentDisplay.find(L'.') != m_currentDisplay.npos);
m_switchedActive = true;
return;
}
if (m_currencyDataLoader != nullptr && m_vmCurrencyCallback != nullptr)
{
shared_ptr<ICurrencyConverterDataLoader> currencyDataLoader = GetCurrencyConverterDataLoader();
const pair<wstring, wstring> currencyRatios = currencyDataLoader->GetCurrencyRatioEquality(m_fromType, m_toType);
swap(m_fromType, m_toType);
swap(m_currentHasDecimal, m_returnHasDecimal);
m_returnDisplay = m_currentDisplay;
m_currentDisplay = newValue;
m_currentHasDecimal = (m_currentDisplay.find(L'.') != m_currentDisplay.npos);
m_switchedActive = true;
m_vmCurrencyCallback->CurrencyRatiosCallback(currencyRatios.first, currencyRatios.second);
}
if (m_currencyDataLoader != nullptr && m_vmCurrencyCallback != nullptr)
{
shared_ptr<ICurrencyConverterDataLoader> currencyDataLoader = GetCurrencyConverterDataLoader();
const pair<wstring, wstring> currencyRatios = currencyDataLoader->GetCurrencyRatioEquality(m_fromType, m_toType);
m_vmCurrencyCallback->CurrencyRatiosCallback(currencyRatios.first, currencyRatios.second);
}
}
@ -291,55 +281,53 @@ wstring UnitConverter::ConversionDataToString(ConversionData d, const wchar_t *
/// </summary>
wstring UnitConverter::Serialize()
{
if (CheckLoad())
{
wstringstream out(wstringstream::out);
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 << m_currentDisplay << delimiter << m_returnDisplay << delimiter << "|";
wstringstream categoryString(wstringstream::out);
wstringstream categoryToUnitString(wstringstream::out);
wstringstream unitToUnitToDoubleString(wstringstream::out);
for (const Category& c : m_categories)
{
categoryString << CategoryToString(c, delimiter) << ",";
}
for (const auto& cur : m_categoryToUnits)
{
categoryToUnitString << CategoryToString(cur.first, delimiter) << "[";
for (const Unit& u : cur.second)
{
categoryToUnitString << UnitToString(u, delimiter) << ",";
}
categoryToUnitString << "[" << "]";
}
for (const auto& cur : m_ratioMap)
{
unitToUnitToDoubleString << UnitToString(cur.first, delimiter) << "[";
for (const auto& curConversion : cur.second)
{
unitToUnitToDoubleString << UnitToString(curConversion.first, delimiter) << ":";
unitToUnitToDoubleString << ConversionDataToString(curConversion.second, delimiter) << ":,";
}
unitToUnitToDoubleString << "[" << "]";
}
out << categoryString.str() << "|";
out << categoryToUnitString.str() << "|";
out << unitToUnitToDoubleString.str() << "|";
wstring test = out.str();
return test;
}
else
if (!CheckLoad())
{
return wstring();
}
wstringstream out(wstringstream::out);
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 << m_currentDisplay << delimiter << m_returnDisplay << delimiter << "|";
wstringstream categoryString(wstringstream::out);
wstringstream categoryToUnitString(wstringstream::out);
wstringstream unitToUnitToDoubleString(wstringstream::out);
for (const Category& c : m_categories)
{
categoryString << CategoryToString(c, delimiter) << ",";
}
for (const auto& cur : m_categoryToUnits)
{
categoryToUnitString << CategoryToString(cur.first, delimiter) << "[";
for (const Unit& u : cur.second)
{
categoryToUnitString << UnitToString(u, delimiter) << ",";
}
categoryToUnitString << "[" << "]";
}
for (const auto& cur : m_ratioMap)
{
unitToUnitToDoubleString << UnitToString(cur.first, delimiter) << "[";
for (const auto& curConversion : cur.second)
{
unitToUnitToDoubleString << UnitToString(curConversion.first, delimiter) << ":";
unitToUnitToDoubleString << ConversionDataToString(curConversion.second, delimiter) << ":,";
}
unitToUnitToDoubleString << "[" << "]";
}
out << categoryString.str() << "|";
out << categoryToUnitString.str() << "|";
out << unitToUnitToDoubleString.str() << "|";
wstring test = out.str();
return test;
}
/// <summary>
@ -349,55 +337,58 @@ wstring UnitConverter::Serialize()
void UnitConverter::DeSerialize(const wstring& serializedData)
{
Reset();
if (!serializedData.empty())
if (serializedData.empty())
{
vector<wstring> outerTokens = StringToVector(serializedData, L"|");
assert(outerTokens.size() == EXPECTEDSERIALIZEDTOKENCOUNT);
m_fromType = StringToUnit(outerTokens[0]);
m_toType = StringToUnit(outerTokens[1]);
m_currentCategory = StringToCategory(outerTokens[2]);
vector<wstring> stateDataTokens = StringToVector(outerTokens[3], L";");
assert(stateDataTokens.size() == EXPECTEDSTATEDATATOKENCOUNT);
m_currentHasDecimal = (stateDataTokens[0].compare(L"1") == 0);
m_returnHasDecimal = (stateDataTokens[1].compare(L"1") == 0);
m_switchedActive = (stateDataTokens[2].compare(L"1") == 0);
m_currentDisplay = stateDataTokens[3];
m_returnDisplay = stateDataTokens[4];
vector<wstring> categoryListTokens = StringToVector(outerTokens[4], L",");
for (wstring token : categoryListTokens)
{
m_categories.push_back(StringToCategory(token));
}
vector<wstring> unitVectorTokens = StringToVector(outerTokens[5], L"]");
for (wstring unitVector : unitVectorTokens)
{
vector<wstring> mapcomponents = StringToVector(unitVector, L"[");
assert(mapcomponents.size() == EXPECTEDMAPCOMPONENTTOKENCOUNT);
Category key = StringToCategory(mapcomponents[0]);
vector<wstring> units = StringToVector(mapcomponents[1], L",");
for (wstring unit : units)
{
m_categoryToUnits[key].push_back(StringToUnit(unit));
}
}
vector<wstring> ratioMapTokens = StringToVector(outerTokens[6], L"]");
for (wstring token : ratioMapTokens)
{
vector<wstring> ratioMapComponentTokens = StringToVector(token, L"[");
assert(ratioMapComponentTokens.size() == EXPECTEDMAPCOMPONENTTOKENCOUNT);
Unit key = StringToUnit(ratioMapComponentTokens[0]);
vector<wstring> ratioMapList = StringToVector(ratioMapComponentTokens[1], L",");
for (wstring subtoken : ratioMapList)
{
vector<wstring> ratioMapSubComponentTokens = StringToVector(subtoken, L":");
assert(ratioMapSubComponentTokens.size() == EXPECTEDMAPCOMPONENTTOKENCOUNT);
Unit subkey = StringToUnit(ratioMapSubComponentTokens[0]);
ConversionData conversion = StringToConversionData(ratioMapSubComponentTokens[1]);
m_ratioMap[key][subkey] = conversion;
}
}
UpdateViewModel();
return;
}
vector<wstring> outerTokens = StringToVector(serializedData, L"|");
assert(outerTokens.size() == EXPECTEDSERIALIZEDTOKENCOUNT);
m_fromType = StringToUnit(outerTokens[0]);
m_toType = StringToUnit(outerTokens[1]);
m_currentCategory = StringToCategory(outerTokens[2]);
vector<wstring> stateDataTokens = StringToVector(outerTokens[3], L";");
assert(stateDataTokens.size() == EXPECTEDSTATEDATATOKENCOUNT);
m_currentHasDecimal = (stateDataTokens[0].compare(L"1") == 0);
m_returnHasDecimal = (stateDataTokens[1].compare(L"1") == 0);
m_switchedActive = (stateDataTokens[2].compare(L"1") == 0);
m_currentDisplay = stateDataTokens[3];
m_returnDisplay = stateDataTokens[4];
vector<wstring> categoryListTokens = StringToVector(outerTokens[4], L",");
for (wstring token : categoryListTokens)
{
m_categories.push_back(StringToCategory(token));
}
vector<wstring> unitVectorTokens = StringToVector(outerTokens[5], L"]");
for (wstring unitVector : unitVectorTokens)
{
vector<wstring> mapcomponents = StringToVector(unitVector, L"[");
assert(mapcomponents.size() == EXPECTEDMAPCOMPONENTTOKENCOUNT);
Category key = StringToCategory(mapcomponents[0]);
vector<wstring> units = StringToVector(mapcomponents[1], L",");
for (wstring unit : units)
{
m_categoryToUnits[key].push_back(StringToUnit(unit));
}
}
vector<wstring> ratioMapTokens = StringToVector(outerTokens[6], L"]");
for (wstring token : ratioMapTokens)
{
vector<wstring> ratioMapComponentTokens = StringToVector(token, L"[");
assert(ratioMapComponentTokens.size() == EXPECTEDMAPCOMPONENTTOKENCOUNT);
Unit key = StringToUnit(ratioMapComponentTokens[0]);
vector<wstring> ratioMapList = StringToVector(ratioMapComponentTokens[1], L",");
for (wstring subtoken : ratioMapList)
{
vector<wstring> ratioMapSubComponentTokens = StringToVector(subtoken, L":");
assert(ratioMapSubComponentTokens.size() == EXPECTEDMAPCOMPONENTTOKENCOUNT);
Unit subkey = StringToUnit(ratioMapSubComponentTokens[0]);
ConversionData conversion = StringToConversionData(ratioMapSubComponentTokens[1]);
m_ratioMap[key][subkey] = conversion;
}
}
UpdateViewModel();
}
/// <summary>
@ -406,15 +397,17 @@ void UnitConverter::DeSerialize(const wstring& serializedData)
/// <param name="userPreferences">wstring holding the serialized data. If it does not have expected number of parameters, we will ignore it</param>
void UnitConverter::RestoreUserPreferences(const wstring& userPreferences)
{
if (!userPreferences.empty())
if (userPreferences.empty())
{
vector<wstring> outerTokens = StringToVector(userPreferences, L"|");
if (outerTokens.size() == 3)
{
m_fromType = StringToUnit(outerTokens[0]);
m_toType = StringToUnit(outerTokens[1]);
m_currentCategory = StringToCategory(outerTokens[2]);
}
return;
}
vector<wstring> outerTokens = StringToVector(userPreferences, L"|");
if (outerTokens.size() == 3)
{
m_fromType = StringToUnit(outerTokens[0]);
m_toType = StringToUnit(outerTokens[1]);
m_currentCategory = StringToCategory(outerTokens[2]);
}
}
@ -441,7 +434,7 @@ wstring UnitConverter::Quote(const wstring& s)
{
wstringstream quotedString(wstringstream::out);
//Iterate over the delimiter characters we need to quote
// Iterate over the delimiter characters we need to quote
wstring::const_iterator cursor = s.begin();
while(cursor != s.end())
{
@ -479,7 +472,7 @@ wstring UnitConverter::Unquote(const wstring& s)
}
if (cursor == s.end())
{
//badly formatted
// Badly formatted
break;
}
else
@ -503,144 +496,146 @@ wstring UnitConverter::Unquote(const wstring& s)
/// <param name="command">Command enum representing the command that was entered</param>
void UnitConverter::SendCommand(Command command)
{
if (CheckLoad())
if (!CheckLoad())
{
//TODO: Localization of characters
bool clearFront = false;
if (m_currentDisplay == L"0")
return;
}
// TODO: Localization of characters
bool clearFront = false;
if (m_currentDisplay == L"0")
{
clearFront = true;
}
bool clearBack = false;
if ((m_currentHasDecimal && m_currentDisplay.size() - 1 >= MAXIMUMDIGITSALLOWED) || (!m_currentHasDecimal && m_currentDisplay.size() >= MAXIMUMDIGITSALLOWED))
{
clearBack = true;
}
if (command != Command::Negate && m_switchedActive)
{
ClearValues();
m_switchedActive = false;
clearFront = true;
clearBack = false;
}
switch (command)
{
case Command::Zero:
m_currentDisplay += L"0";
break;
case Command::One:
m_currentDisplay += L"1";
break;
case Command::Two:
m_currentDisplay += L"2";
break;
case Command::Three:
m_currentDisplay += L"3";
break;
case Command::Four:
m_currentDisplay += L"4";
break;
case Command::Five:
m_currentDisplay += L"5";
break;
case Command::Six:
m_currentDisplay += L"6";
break;
case Command::Seven:
m_currentDisplay += L"7";
break;
case Command::Eight:
m_currentDisplay += L"8";
break;
case Command::Nine:
m_currentDisplay += L"9";
break;
case Command::Decimal:
clearFront = false;
clearBack = false;
if (!m_currentHasDecimal)
{
clearFront = true;
m_currentDisplay += L".";
m_currentHasDecimal = true;
}
bool clearBack = false;
if ((m_currentHasDecimal && m_currentDisplay.size() - 1 >= MAXIMUMDIGITSALLOWED) || (!m_currentHasDecimal && m_currentDisplay.size() >= MAXIMUMDIGITSALLOWED))
break;
case Command::Backspace:
clearFront = false;
clearBack = false;
if ((m_currentDisplay.front() != '-' && m_currentDisplay.size() > 1) || m_currentDisplay.size() > 2)
{
clearBack = true;
}
if (command != Command::Negate && m_switchedActive)
{
ClearValues();
m_switchedActive = false;
clearFront = true;
clearBack = false;
}
switch (command)
{
case Command::Zero:
m_currentDisplay += L"0";
break;
case Command::One:
m_currentDisplay += L"1";
break;
case Command::Two:
m_currentDisplay += L"2";
break;
case Command::Three:
m_currentDisplay += L"3";
break;
case Command::Four:
m_currentDisplay += L"4";
break;
case Command::Five:
m_currentDisplay += L"5";
break;
case Command::Six:
m_currentDisplay += L"6";
break;
case Command::Seven:
m_currentDisplay += L"7";
break;
case Command::Eight:
m_currentDisplay += L"8";
break;
case Command::Nine:
m_currentDisplay += L"9";
break;
case Command::Decimal:
clearFront = false;
clearBack = false;
if (!m_currentHasDecimal)
if (m_currentDisplay.back() == '.')
{
m_currentDisplay += L".";
m_currentHasDecimal = true;
m_currentHasDecimal = false;
}
break;
m_currentDisplay.pop_back();
}
else
{
m_currentDisplay = L"0";
m_currentHasDecimal = false;
}
break;
case Command::Backspace:
clearFront = false;
clearBack = false;
if ((m_currentDisplay.front() != '-' && m_currentDisplay.size() > 1) || m_currentDisplay.size() > 2)
case Command::Negate:
clearFront = false;
clearBack = false;
if (m_currentCategory.supportsNegative)
{
if (m_currentDisplay.front() == '-')
{
if (m_currentDisplay.back() == '.')
{
m_currentHasDecimal = false;
}
m_currentDisplay.pop_back();
m_currentDisplay.erase(0, 1);
}
else
{
m_currentDisplay = L"0";
m_currentHasDecimal = false;
m_currentDisplay.insert(0, 1, '-');
}
break;
case Command::Negate:
clearFront = false;
clearBack = false;
if (m_currentCategory.supportsNegative)
{
if (m_currentDisplay.front() == '-')
{
m_currentDisplay.erase(0, 1);
}
else
{
m_currentDisplay.insert(0, 1, '-');
}
}
break;
case Command::Clear:
clearFront = false;
clearBack = false;
ClearValues();
break;
case Command::Reset:
clearFront = false;
clearBack = false;
ClearValues();
Reset();
break;
default:
break;
}
break;
case Command::Clear:
clearFront = false;
clearBack = false;
ClearValues();
break;
if (clearFront)
{
m_currentDisplay.erase(0, 1);
}
if (clearBack)
{
m_currentDisplay.erase(m_currentDisplay.size() - 1, 1);
m_vmCallback->MaxDigitsReached();
}
case Command::Reset:
clearFront = false;
clearBack = false;
ClearValues();
Reset();
break;
Calculate();
UpdateViewModel();
default:
break;
}
if (clearFront)
{
m_currentDisplay.erase(0, 1);
}
if (clearBack)
{
m_currentDisplay.erase(m_currentDisplay.size() - 1, 1);
m_vmCallback->MaxDigitsReached();
}
Calculate();
UpdateViewModel();
}
/// <summary>
@ -728,7 +723,7 @@ vector<tuple<wstring, Unit>> UnitConverter::CalculateSuggested()
vector<SuggestedValueIntermediate> intermediateVector;
vector<SuggestedValueIntermediate> intermediateWhimsicalVector;
unordered_map<Unit, ConversionData, UnitHash> ratios = m_ratioMap[m_fromType];
//Calculate converted values for every other unit type in this category, along with their magnitude
// Calculate converted values for every other unit type in this category, along with their magnitude
for (const auto& cur : ratios)
{
if (cur.first != m_fromType && cur.first != m_toType)
@ -745,7 +740,7 @@ vector<tuple<wstring, Unit>> UnitConverter::CalculateSuggested()
}
}
//Sort the resulting list by absolute magnitude, breaking ties by choosing the positive value
// Sort the resulting list by absolute magnitude, breaking ties by choosing the positive value
sort(intermediateVector.begin(), intermediateVector.end(), []
(SuggestedValueIntermediate first, SuggestedValueIntermediate second)
{
@ -759,7 +754,7 @@ vector<tuple<wstring, Unit>> UnitConverter::CalculateSuggested()
}
});
//Now that the list is sorted, iterate over it and populate the return vector with properly rounded and formatted return strings
// Now that the list is sorted, iterate over it and populate the return vector with properly rounded and formatted return strings
for (const auto& entry : intermediateVector)
{
wstring roundedString;
@ -783,7 +778,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 the resulting list by absolute magnitude, breaking ties by choosing the positive value
sort(intermediateWhimsicalVector.begin(), intermediateWhimsicalVector.end(), []
(SuggestedValueIntermediate first, SuggestedValueIntermediate second)
{
@ -797,7 +792,7 @@ vector<tuple<wstring, Unit>> UnitConverter::CalculateSuggested()
}
});
//Now that the list is sorted, iterate over it and populate the return vector with properly rounded and formatted return strings
// Now that the list is sorted, iterate over it and populate the return vector with properly rounded and formatted return strings
vector<tuple<wstring, Unit>> whimsicalReturnVector;
for (const auto& entry : intermediateWhimsicalVector)
@ -844,47 +839,49 @@ void UnitConverter::Reset()
ClearValues();
m_switchedActive = false;
if (!m_categories.empty())
if (m_categories.empty())
{
m_currentCategory = m_categories[0];
return;
}
m_categoryToUnits.clear();
m_ratioMap.clear();
bool readyCategoryFound = false;
for (const Category& category : m_categories)
m_currentCategory = m_categories[0];
m_categoryToUnits.clear();
m_ratioMap.clear();
bool readyCategoryFound = false;
for (const Category& category : m_categories)
{
shared_ptr<IConverterDataLoader> activeDataLoader = GetDataLoaderForCategory(category);
if (activeDataLoader == nullptr)
{
shared_ptr<IConverterDataLoader> activeDataLoader = GetDataLoaderForCategory(category);
if (activeDataLoader == nullptr)
{
// The data loader is different depending on the category, e.g. currency data loader
// is different from the static data loader.
// If there is no data loader for this category, continue.
continue;
}
vector<Unit> units = activeDataLoader->LoadOrderedUnits(category);
m_categoryToUnits[category] = units;
// Just because the units are empty, doesn't mean the user can't select this category,
// we just want to make sure we don't let an unready category be the default.
if (!units.empty())
{
for (Unit u : units)
{
m_ratioMap[u] = activeDataLoader->LoadOrderedRatios(u);
}
if (!readyCategoryFound)
{
m_currentCategory = category;
readyCategoryFound = true;
}
}
// The data loader is different depending on the category, e.g. currency data loader
// is different from the static data loader.
// If there is no data loader for this category, continue.
continue;
}
InitializeSelectedUnits();
Calculate();
vector<Unit> units = activeDataLoader->LoadOrderedUnits(category);
m_categoryToUnits[category] = units;
// Just because the units are empty, doesn't mean the user can't select this category,
// we just want to make sure we don't let an unready category be the default.
if (!units.empty())
{
for (Unit u : units)
{
m_ratioMap[u] = activeDataLoader->LoadOrderedRatios(u);
}
if (!readyCategoryFound)
{
m_currentCategory = category;
readyCategoryFound = true;
}
}
}
InitializeSelectedUnits();
Calculate();
}
/// <summary>
@ -1029,22 +1026,24 @@ void UnitConverter::Calculate()
/// <param name="input">wstring to trim</param>
void UnitConverter::TrimString(wstring& returnString)
{
if (returnString.find(L'.') != m_returnDisplay.npos)
if (returnString.find(L'.') == m_returnDisplay.npos)
{
wstring::iterator iter;
for (iter = returnString.end() - 1; ;iter--)
return;
}
wstring::iterator iter;
for (iter = returnString.end() - 1; ;iter--)
{
if (*iter != L'0')
{
if (*iter != L'0')
{
returnString.erase(iter + 1, returnString.end());
break;
}
}
if (*(returnString.end()-1) == L'.')
{
returnString.erase(returnString.end()-1, returnString.end());
returnString.erase(iter + 1, returnString.end());
break;
}
}
if (*(returnString.end()-1) == L'.')
{
returnString.erase(returnString.end()-1, returnString.end());
}
}
/// <summary>

View file

@ -51,7 +51,7 @@ namespace UnitConversionManager
// null checks.
//
// unitId, name, abbreviation, isConversionSource, isConversionTarget, isWhimsical
const Unit EMPTY_UNIT = Unit{ -1, L"", L"", true, true, false };
inline const Unit EMPTY_UNIT = Unit{ -1, L"", L"", true, true, false };
struct Category
{

View file

@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#pragma once
@ -7,11 +7,16 @@
#define WIN32_LEAN_AND_MEAN
#endif
// Windows headers define min/max macros.
// Disable it for project code.
#define NOMINMAX
#include <assert.h>
#include <windows.h>
#include <winerror.h>
#include <sstream>
#include <iostream>
#include <iterator>
#include <string>
#include <memory>
#include <vector>

View file

@ -32,14 +32,11 @@ using namespace Windows::UI::Xaml::Data;
using namespace Windows::UI::Xaml::Input;
using namespace Windows::UI::Xaml::Media;
namespace CalculatorApp::ViewModel::ApplicationViewModelProperties
namespace
{
StringReference Mode(L"Mode");
StringReference PreviousMode(L"PreviousMode");
StringReference ClearMemoryVisibility(L"ClearMemoryVisibility");
StringReference AppBarVisibility(L"AppBarVisibility");
StringReference CategoryName(L"CategoryName");
StringReference Categories(L"Categories");
StringReference CategoriesPropertyName(L"Categories");
StringReference ClearMemoryVisibilityPropertyName(L"ClearMemoryVisibility");
StringReference AppBarVisibilityPropertyName(L"AppBarVisibility");
}
ApplicationViewModel::ApplicationViewModel() :
@ -60,7 +57,7 @@ void ApplicationViewModel::Mode::set(ViewMode value)
PreviousMode = m_mode;
m_mode = value;
OnModeChanged();
RaisePropertyChanged(ApplicationViewModelProperties::Mode);
RaisePropertyChanged(ModePropertyName);
}
}
@ -69,7 +66,7 @@ void ApplicationViewModel::Categories::set(IObservableVector<NavCategoryGroup^>^
if (m_categories != value)
{
m_categories = value;
RaisePropertyChanged(ApplicationViewModelProperties::Categories);
RaisePropertyChanged(CategoriesPropertyName);
}
}
@ -163,11 +160,11 @@ void ApplicationViewModel::OnModeChanged()
//
// Save the changed mode, so that the new window launches in this mode.
// Don't save until after we have adjusted to the new mode, so we don't save a mode that fails to load.
ApplicationData::Current->LocalSettings->Values->Insert(ApplicationViewModelProperties::Mode, NavCategory::Serialize(m_mode));
ApplicationData::Current->LocalSettings->Values->Insert(ModePropertyName, NavCategory::Serialize(m_mode));
TraceLogger::GetInstance().LogModeChangeEnd(m_mode, ApplicationView::GetApplicationViewIdForWindow(CoreWindow::GetForCurrentThread()));
RaisePropertyChanged(ApplicationViewModelProperties::ClearMemoryVisibility);
RaisePropertyChanged(ApplicationViewModelProperties::AppBarVisibility);
RaisePropertyChanged(ClearMemoryVisibilityPropertyName);
RaisePropertyChanged(AppBarVisibilityPropertyName);
}
void ApplicationViewModel::OnCopyCommand(Object^ parameter)

View file

@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#pragma once
@ -11,16 +11,6 @@ namespace CalculatorApp
{
namespace ViewModel
{
namespace ApplicationViewModelProperties
{
extern Platform::StringReference Mode;
extern Platform::StringReference PreviousMode;
extern Platform::StringReference ClearMemoryVisibility;
extern Platform::StringReference AppBarVisibility;
extern Platform::StringReference CategoryName;
extern Platform::StringReference Categories;
}
[Windows::UI::Xaml::Data::Bindable]
public ref class ApplicationViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
{
@ -32,9 +22,9 @@ namespace CalculatorApp
OBSERVABLE_OBJECT();
OBSERVABLE_PROPERTY_RW(StandardCalculatorViewModel^, CalculatorViewModel);
OBSERVABLE_PROPERTY_RW(DateCalculatorViewModel^, DateCalcViewModel);
OBSERVABLE_PROPERTY_RW(CalculatorApp::ViewModel::UnitConverterViewModel^, ConverterViewModel);
OBSERVABLE_PROPERTY_RW(UnitConverterViewModel^, ConverterViewModel);
OBSERVABLE_PROPERTY_RW(CalculatorApp::Common::ViewMode, PreviousMode);
OBSERVABLE_PROPERTY_RW(Platform::String^, CategoryName);
OBSERVABLE_NAMED_PROPERTY_RW(Platform::String^, CategoryName);
COMMAND_FOR_METHOD(CopyCommand, ApplicationViewModel::OnCopyCommand);
COMMAND_FOR_METHOD(PasteCommand, ApplicationViewModel::OnPasteCommand);
@ -48,6 +38,13 @@ namespace CalculatorApp
void set(CalculatorApp::Common::ViewMode value);
}
static property Platform::String^ ModePropertyName
{
Platform::String^ get()
{
return Platform::StringReference(L"Mode");
}
}
property Windows::Foundation::Collections::IObservableVector<CalculatorApp::Common::NavCategoryGroup^>^ Categories
{

View file

@ -1,8 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#pragma once
#include "pch.h"
#include "AppResourceProvider.h"

View file

@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#include "pch.h"
@ -20,6 +20,8 @@ namespace CalculatorApp::Common::Automation
StringReference CategoryNameChanged(L"CategoryNameChanged");
StringReference UpdateCurrencyRates(L"UpdateCurrencyRates");
StringReference DisplayCopied(L"DisplayCopied");
StringReference OpenParenthesisCountChanged(L"OpenParenthesisCountChanged");
StringReference NoParenthesisAdded(L"NoParenthesisAdded");
}
}
@ -142,3 +144,21 @@ NarratorAnnouncement^ CalculatorAnnouncement::GetDisplayCopiedAnnouncement(Strin
AutomationNotificationKind::ActionCompleted,
AutomationNotificationProcessing::ImportantMostRecent);
}
NarratorAnnouncement^ CalculatorAnnouncement::GetOpenParenthesisCountChangedAnnouncement(String^ announcement)
{
return ref new NarratorAnnouncement(
announcement,
CalculatorActivityIds::OpenParenthesisCountChanged,
AutomationNotificationKind::ActionCompleted,
AutomationNotificationProcessing::ImportantMostRecent);
}
NarratorAnnouncement^ CalculatorAnnouncement::GetNoRightParenthesisAddedAnnouncement(String^ announcement)
{
return ref new NarratorAnnouncement(
announcement,
CalculatorActivityIds::NoParenthesisAdded,
AutomationNotificationKind::ActionCompleted,
AutomationNotificationProcessing::ImportantMostRecent);
}

View file

@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#pragma once
@ -90,5 +90,8 @@ namespace CalculatorApp::Common::Automation
static NarratorAnnouncement^ GetUpdateCurrencyRatesAnnouncement(Platform::String^ announcement);
static NarratorAnnouncement^ GetDisplayCopiedAnnouncement(Platform::String^ announcement);
static NarratorAnnouncement^ GetOpenParenthesisCountChangedAnnouncement(Platform::String^ announcement);
static NarratorAnnouncement^ GetNoRightParenthesisAddedAnnouncement(Platform::String ^ announcement);
};
}

View file

@ -29,8 +29,7 @@ void CalculatorDisplay::SetPrimaryDisplay(_In_ const wstring& displayStringValue
{
if (m_callbackReference)
{
auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>();
if (calcVM)
if (auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>())
{
calcVM->SetPrimaryDisplay(displayStringValue, isError);
}
@ -41,20 +40,29 @@ void CalculatorDisplay::SetParenDisplayText(_In_ const std::wstring& parenthesis
{
if (m_callbackReference != nullptr)
{
auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>();
if (calcVM)
if (auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>())
{
calcVM->SetParenthesisCount(parenthesisCount);
}
}
}
void CalculatorDisplay::OnNoRightParenAdded()
{
if (m_callbackReference != nullptr)
{
if (auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>())
{
calcVM->OnNoRightParenAdded();
}
}
}
void CalculatorDisplay::SetIsInError(bool isError)
{
if (m_callbackReference != nullptr)
{
auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>();
if (calcVM)
if (auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>())
{
calcVM->IsInError = isError;
}
@ -65,8 +73,7 @@ void CalculatorDisplay::SetExpressionDisplay(_Inout_ std::shared_ptr<CalculatorV
{
if (m_callbackReference != nullptr)
{
auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>();
if (calcVM)
if(auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>())
{
calcVM->SetExpressionDisplay(tokens, commands);
}
@ -77,8 +84,7 @@ void CalculatorDisplay::SetMemorizedNumbers(_In_ const vector<std::wstring>& new
{
if (m_callbackReference != nullptr)
{
auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>();
if (calcVM)
if (auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>())
{
calcVM->SetMemorizedNumbers(newMemorizedNumbers);
}
@ -89,8 +95,7 @@ void CalculatorDisplay::OnHistoryItemAdded(_In_ unsigned int addedItemIndex)
{
if (m_historyCallbackReference != nullptr)
{
auto historyVM = m_historyCallbackReference.Resolve<ViewModel::HistoryViewModel>();
if (historyVM)
if (auto historyVM = m_historyCallbackReference.Resolve<ViewModel::HistoryViewModel>())
{
historyVM->OnHistoryItemAdded(addedItemIndex);
}
@ -101,8 +106,7 @@ void CalculatorDisplay::MaxDigitsReached()
{
if (m_callbackReference != nullptr)
{
auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>();
if (calcVM)
if (auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>())
{
calcVM->OnMaxDigitsReached();
}
@ -113,8 +117,7 @@ void CalculatorDisplay::BinaryOperatorReceived()
{
if (m_callbackReference != nullptr)
{
auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>();
if (calcVM)
if (auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>())
{
calcVM->OnBinaryOperatorReceived();
}
@ -125,8 +128,7 @@ void CalculatorDisplay::MemoryItemChanged(unsigned int indexOfMemory)
{
if (m_callbackReference != nullptr)
{
auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>();
if (calcVM)
if (auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>())
{
calcVM->OnMemoryItemChanged(indexOfMemory);
}

View file

@ -22,6 +22,7 @@ namespace CalculatorApp
void SetMemorizedNumbers(_In_ const std::vector<std::wstring>& memorizedNumbers) override;
void OnHistoryItemAdded(_In_ unsigned int addedItemIndex) override;
void SetParenDisplayText(_In_ const std::wstring& parenthesisCount) override;
void OnNoRightParenAdded() override;
void MaxDigitsReached() override;
void BinaryOperatorReceived() override;
void MemoryItemChanged(unsigned int indexOfMemory) override;

View file

@ -26,6 +26,7 @@ constexpr wstring_view c_validCharacterSet{ L"0123456789()+-*/.abcdefABCDEF" };
// [\s\x85] means white-space characters
static const wstring c_wspc = L"[\\s\\x85]*";
static const wstring c_wspcLParens = c_wspc + L"[(]*" + c_wspc;
static const wstring c_wspcLParenSigned = c_wspc + L"([-+]?[(])*" + c_wspc;
static const wstring c_wspcRParens = c_wspc + L"[)]*" + c_wspc;
static const wstring c_signedDecFloat = L"[-+]?\\d*(\\d|[.])\\d*";
@ -44,8 +45,8 @@ static const array<wregex, 1> standardModePatterns =
};
static const array<wregex, 2> scientificModePatterns =
{
wregex(c_wspcLParens + c_signedDecFloat + c_wspcRParens),
wregex(c_wspcLParens + c_signedDecFloat + L"[e]([+]|[-])+\\d+" + c_wspcRParens)
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 =
{ {
@ -129,7 +130,7 @@ String^ CopyPasteManager::ValidatePasteExpression(String^ pastedText, ViewMode m
if (pastedText->Length() > MaxPasteableLength)
{
// return NoOp to indicate don't paste anything.
TraceLogger::GetInstance().LogInvalidInputPasted(L"PastedExpressionSizeGreaterThanMaxAllowed", L"MoreThanMaxInput", mode, programmerNumberBase, bitLengthType);
TraceLogger::GetInstance().LogInvalidPastedInputOccurred(L"PastedExpressionSizeGreaterThanMaxAllowed", mode, programmerNumberBase, bitLengthType);
return StringReference(PasteErrorString);
}
@ -139,7 +140,7 @@ String^ CopyPasteManager::ValidatePasteExpression(String^ pastedText, ViewMode m
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 = Utils::RemoveUnwantedCharsFromWstring(englishString->Data());
pasteExpression = RemoveUnwantedCharsFromWstring(englishString->Data());
// If the last character is an = sign, remove it from the pasteExpression to allow evaluating the result on paste.
if (!pasteExpression.empty() && pasteExpression.back() == L'=')
@ -164,7 +165,7 @@ String^ CopyPasteManager::ValidatePasteExpression(String^ pastedText, ViewMode m
// validate each operand with patterns for different modes
if (!ExpressionRegExMatch(operands, mode, modeType, programmerNumberBase, bitLengthType))
{
TraceLogger::GetInstance().LogInvalidInputPasted(L"InvalidExpressionForPresentMode", pastedText->Data(), mode, programmerNumberBase, bitLengthType);
TraceLogger::GetInstance().LogInvalidPastedInputOccurred(L"InvalidExpressionForPresentMode", mode, programmerNumberBase, bitLengthType);
return StringReference(PasteErrorString);
}
@ -193,7 +194,7 @@ vector<wstring> CopyPasteManager::ExtractOperands(const wstring& pasteExpression
if (operands.size() >= MaxOperandCount)
{
TraceLogger::GetInstance().LogInvalidInputPasted(L"OperandCountGreaterThanMaxCount", pasteExpression.c_str(), mode, programmerNumberBase, bitLengthType);
TraceLogger::GetInstance().LogInvalidPastedInputOccurred(L"OperandCountGreaterThanMaxCount", mode, programmerNumberBase, bitLengthType);
operands.clear();
return operands;
}
@ -207,7 +208,7 @@ vector<wstring> CopyPasteManager::ExtractOperands(const wstring& pasteExpression
// to disallow pasting of 1e+12345 as 1e+1234, max exponent that can be pasted is 9999.
if (expLength > MaxExponentLength)
{
TraceLogger::GetInstance().LogInvalidInputPasted(L"ExponentLengthGreaterThanMaxLength", pasteExpression.c_str(), mode, programmerNumberBase, bitLengthType);
TraceLogger::GetInstance().LogInvalidPastedInputOccurred(L"ExponentLengthGreaterThanMaxLength", mode, programmerNumberBase, bitLengthType);
operands.clear();
return operands;
}
@ -402,9 +403,9 @@ pair<size_t, uint64_t> CopyPasteManager::GetMaxOperandLengthAndValue(ViewMode mo
wstring CopyPasteManager::SanitizeOperand(const wstring& operand)
{
wchar_t unWantedChars[] = { L'\'', L'_', L'`', L'(', L')', L'-' };
wchar_t unWantedChars[] = { L'\'', L'_', L'`', L'(', L')', L'-', L'+' };
return Utils::RemoveUnwantedCharsFromWstring(operand, unWantedChars, ARRAYSIZE(unWantedChars));
return Utils::RemoveUnwantedCharsFromWstring(operand, unWantedChars, static_cast<int>(size(unWantedChars)));
}
bool CopyPasteManager::TryOperandToULL(const wstring& operand, int numberBase, unsigned long long int& result)
@ -567,3 +568,21 @@ size_t CopyPasteManager::ProgrammerOperandLength(const wstring& operand, int num
return len;
}
// return wstring after removing characters like space, comma, double quotes, and monetary prefix currency symbols supported by the Windows keyboard:
// yen or yuan(¥) - 165
// unspecified currency sign(¤) - 164
// Ghanaian cedi(₵) - 8373
// dollar or peso($) - 36
// colón(₡) - 8353
// won(₩) - 8361
// shekel(₪) - 8362
// naira(₦) - 8358
// Indian rupee(₹) - 8377
// pound(£) - 163
// euro(€) - 8364
wstring CopyPasteManager::RemoveUnwantedCharsFromWstring(const wstring& input)
{
wchar_t unWantedChars[] = { L' ', L',', L'"', 165, 164, 8373, 36, 8353, 8361, 8362, 8358, 8377, 163, 8364, 8234, 8235, 8236, 8237 };
return Utils::RemoveUnwantedCharsFromWstring(input, unWantedChars, 18);
}

View file

@ -58,6 +58,7 @@ namespace CalculatorApp
static size_t OperandLength(std::wstring operand, CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, int programmerNumberBase = -1);
static size_t StandardScientificOperandLength(std::wstring operand);
static size_t ProgrammerOperandLength(const std::wstring& operand, int numberBase);
static std::wstring RemoveUnwantedCharsFromWstring(const std::wstring& input);
static constexpr size_t MaxStandardOperandLength = 16;
static constexpr size_t MaxScientificOperandLength = 32;

View file

@ -12,6 +12,7 @@ using namespace CalculatorApp::Common::DateCalculation;
DateCalculationEngine::DateCalculationEngine(_In_ String^ calendarIdentifier)
{
m_calendar = ref new Calendar();
m_calendar->ChangeTimeZone("UTC");
m_calendar->ChangeCalendarSystem(calendarIdentifier);
}

View file

@ -4,6 +4,8 @@
#pragma once
#include "LocalizationService.h"
#include <iterator>
namespace CalculatorApp
{
namespace Common
@ -41,7 +43,7 @@ namespace CalculatorApp
result = GetLocaleInfoEx(m_resolvedName.c_str(),
LOCALE_SDECIMAL,
decimalString,
ARRAYSIZE(decimalString));
static_cast<int>(std::size(decimalString)));
if (result == 0)
{
throw std::runtime_error("Unexpected error while getting locale info");
@ -51,7 +53,7 @@ namespace CalculatorApp
result = GetLocaleInfoEx(m_resolvedName.c_str(),
LOCALE_STHOUSAND,
groupingSymbolString,
ARRAYSIZE(groupingSymbolString));
static_cast<int>(std::size(groupingSymbolString)));
if (result == 0)
{
throw std::runtime_error("Unexpected error while getting locale info");
@ -61,7 +63,7 @@ namespace CalculatorApp
result = GetLocaleInfoEx(m_resolvedName.c_str(),
LOCALE_SGROUPING,
numberGroupingString,
ARRAYSIZE(numberGroupingString));
static_cast<int>(std::size(numberGroupingString)));
if (result == 0)
{
throw std::runtime_error("Unexpected error while getting locale info");
@ -72,7 +74,7 @@ namespace CalculatorApp
result = ::GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT,
LOCALE_SLIST,
listSeparatorString,
ARRAYSIZE(listSeparatorString)); // Max length of the expected return value is 4
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");
@ -122,7 +124,7 @@ namespace CalculatorApp
::GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT,
LOCALE_IFIRSTDAYOFWEEK, // The first day in a week
reinterpret_cast<PWSTR>(day), // Argument is of type PWSTR
ARRAYSIZE(day)); // Max return size are 80 characters
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

View file

@ -1,8 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#pragma once
#include "pch.h"
#include "TraceLogger.h"
#include "NetworkManager.h"
@ -59,7 +57,7 @@ namespace CalculatorApp
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_INPUT_PASTED = L"InvalidInputPasted";
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";
@ -81,6 +79,9 @@ namespace CalculatorApp
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;
#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
@ -102,7 +103,7 @@ namespace CalculatorApp
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
@ -481,9 +482,9 @@ namespace CalculatorApp
LogTelemetryEvent(EVENT_NAME_MEMORY_BODY_OPENED, fields);
}
//If calculator is launched in any mode other than standard then this call will come which is not intended. But there is no way to avoid it.
//So don't use this function to analyze the count of mode change in session instead use CalculatorViewedInSession and ConverterViewedInSession to do that.
//Use of this function is to analyze perf of mode change.
// If calculator is launched in any mode other than standard then this call will come which is not intended. But there is no way to avoid it.
// So don't use this function to analyze the count of mode change in session instead use CalculatorViewedInSession and ConverterViewedInSession to do that.
// Use of this function is to analyze perf of mode change.
void TraceLogger::LogModeChangeBegin(ViewMode fromMode, ViewMode toMode, int windowId)
{
if (!GetTraceLoggingProviderEnabled()) return;
@ -498,7 +499,7 @@ namespace CalculatorApp
}
}
//comment: same as LogModeChangeBegin
// comment: same as LogModeChangeBegin
void TraceLogger::LogModeChangeEnd(ViewMode toMode, int windowId) const
{
if (!GetTraceLoggingProviderEnabled()) return;
@ -641,17 +642,17 @@ namespace CalculatorApp
LogTelemetryEvent(EVENT_NAME_SINGLE_MEMORY_USED, fields);
}
void TraceLogger::LogInvalidInputPasted(wstring_view reason, wstring_view pastedExpression, ViewMode mode, int programmerNumberBase, int bitLengthType)
void TraceLogger::LogInvalidPastedInputOccurred(wstring_view reason, ViewMode mode, int programmerNumberBase, int bitLengthType)
{
if (!GetTraceLoggingProviderEnabled()) return;
LoggingFields fields{};
fields.AddString(L"Mode", NavCategory::GetFriendlyName(mode)->Data());
fields.AddString(L"Reason", reason);
fields.AddString(L"PastedExpression", pastedExpression);
fields.AddString(L"ProgrammerNumberBase", GetProgrammerType(programmerNumberBase).c_str());
fields.AddString(L"BitLengthType", GetProgrammerType(bitLengthType).c_str());
LogTelemetryEvent(EVENT_NAME_INVALID_INPUT_PASTED, fields);
fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE);
LogTelemetryEvent(EVENT_NAME_INVALID_PASTED_INPUT_OCCURRED, fields);
}
void TraceLogger::LogValidInputPasted(ViewMode mode) const

View file

@ -64,7 +64,7 @@ namespace CalculatorApp
void LogMemoryFlyoutOpenBegin(unsigned int) const;
void LogDebug(std::wstring_view debugData);
void LogMemoryFlyoutOpenEnd(unsigned int) const;
void LogInvalidInputPasted(std::wstring_view reason, std::wstring_view pastedExpression, CalculatorApp::Common::ViewMode mode, int ProgrammerNumberBase, int bitLengthType);
void LogInvalidPastedInputOccurred(std::wstring_view reason, CalculatorApp::Common::ViewMode mode, int ProgrammerNumberBase, int bitLengthType);
void LogValidInputPasted(CalculatorApp::Common::ViewMode mode) const;
void UpdateFunctionUsage(int func);
void LogFunctionUsage(int);

View file

@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//
@ -54,7 +54,7 @@ double Utils::GetDoubleFromWstring(wstring input)
return ::atof(inputString.c_str());
}
//returns windowId for the current view
// Returns windowId for the current view
int Utils::GetWindowId()
{
int windowId = -1;
@ -80,20 +80,13 @@ void Utils::RunOnUIThreadNonblocking(std::function<void()>&& function, _In_ Core
}
}
// returns if the last character of a wstring is the target wchar_t
// Returns if the last character of a wstring is the target wchar_t
bool Utils::IsLastCharacterTarget(_In_ wstring const &input, _In_ wchar_t target)
{
return !input.empty() && input.back() == target;
}
//return wstring after removing characters like space, comma, and double quotes
wstring Utils::RemoveUnwantedCharsFromWstring(wstring input)
{
wchar_t unWantedChars[] = { L' ', L',', L'"', 8234, 8235, 8236, 8237 };
return RemoveUnwantedCharsFromWstring(input, unWantedChars, 6);
}
//return wstring after removing characters specified by unwantedChars array
// Return wstring after removing characters specified by unwantedChars array
wstring Utils::RemoveUnwantedCharsFromWstring(wstring input, wchar_t* unwantedChars, unsigned int size)
{
for (unsigned int i = 0; i < size; ++i)
@ -110,7 +103,7 @@ void Utils::SerializeCommandsAndTokens(_In_ shared_ptr<CalculatorVector <pair<ws
unsigned int commandsSize;
IFTPlatformException(commands->GetSize(&commandsSize));
// save the size of the commands vector
// Save the size of the commands vector
writer->WriteUInt32(commandsSize);
SerializeCommandVisitor cmdVisitor(writer);

View file

@ -42,10 +42,16 @@
}\
} private: t m_##n; public:
#define NAMED_OBSERVABLE_PROPERTY_RW(t, n)\
#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)\
private: property Platform::StringReference n##_PropertyName {\
Platform::StringReference get() { return Platform::StringReference(L#n); }\
internal: static property Platform::String^ n##PropertyName {\
Platform::String^ get() { return Platform::StringReference(L#n); }\
} public:
#define OBSERVABLE_PROPERTY_FIELD(n) m_##n
@ -280,7 +286,6 @@ namespace Utils
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);
std::wstring RemoveUnwantedCharsFromWstring(std::wstring input);
double GetDoubleFromWstring(std::wstring input);
int GetWindowId();
void RunOnUIThreadNonblocking(std::function<void()>&& function, _In_ Windows::UI::Core::CoreDispatcher^ currentDispatcher);

View file

@ -22,14 +22,14 @@ using namespace Windows::Globalization;
using namespace Windows::Globalization::DateTimeFormatting;
using namespace Windows::System::UserProfile;
namespace CalculatorApp::ViewModel::DateCalculatorViewModelProperties
namespace
{
StringReference StrDateDiffResult(L"StrDateDiffResult");
StringReference StrDateDiffResultAutomationName(L"StrDateDiffResultAutomationName");
StringReference StrDateDiffResultInDays(L"StrDateDiffResultInDays");
StringReference StrDateResult(L"StrDateResult");
StringReference StrDateResultAutomationName(L"StrDateResultAutomationName");
StringReference IsDiffInDays(L"IsDiffInDays");
StringReference StrDateDiffResultPropertyName(L"StrDateDiffResult");
StringReference StrDateDiffResultAutomationNamePropertyName(L"StrDateDiffResultAutomationName");
StringReference StrDateDiffResultInDaysPropertyName(L"StrDateDiffResultInDays");
StringReference StrDateResultPropertyName(L"StrDateResult");
StringReference StrDateResultAutomationNamePropertyName(L"StrDateResultAutomationName");
StringReference IsDiffInDaysPropertyName(L"IsDiffInDays");
}
DateCalculatorViewModel::DateCalculatorViewModel() :
@ -43,11 +43,7 @@ DateCalculatorViewModel::DateCalculatorViewModel() :
m_StrDateDiffResultAutomationName(L""),
m_StrDateDiffResultInDays(L""),
m_StrDateResult(L""),
m_StrDateResultAutomationName(L""),
m_fromDate({ 0 }),
m_toDate({ 0 }),
m_startDate({ 0 }),
m_dateResult({ 0 })
m_StrDateResultAutomationName(L"")
{
const auto& localizationSettings = LocalizationSettings::GetInstance();
@ -56,24 +52,24 @@ DateCalculatorViewModel::DateCalculatorViewModel() :
// Initialize Date Calc engine
m_dateCalcEngine = make_shared<DateCalculationEngine>(localizationSettings.GetCalendarIdentifier());
// Initialize dates of DatePicker controls to today's date
auto calendar = ref new Calendar();
// We force the timezone to UTC, in order to avoid being affected by Daylight Saving Time
// when we calculate the difference between 2 dates.
calendar->ChangeTimeZone("UTC");
auto today = calendar->GetDateTime();
// FromDate and ToDate should be clipped (adjusted to a consistent hour in UTC)
m_fromDate = today;
m_toDate = today;
FromDate = ClipTime(today);
ToDate = ClipTime(today);
m_fromDate = ClipTime(today);
m_toDate = ClipTime(today);
// StartDate should not be clipped
StartDate = today;
m_startDate = today;
m_dateResult = today;
// Initialize the list separator delimiter appended with a space at the end, e.g. ", "
// This will be used for date difference formatting: Y years, M months, W weeks, D days
m_listSeparator = ref new String((localizationSettings.GetListSeparator() + L" ").c_str());
m_listSeparator = localizationSettings.GetListSeparator() + L" ";
// Initialize the output results
UpdateDisplayResult();
@ -86,15 +82,6 @@ DateCalculatorViewModel::DateCalculatorViewModel() :
m_offsetValues->Append(ref new String(numberStr.c_str()));
}
/* In the ClipTime function, we used to change timezone to UTC before clipping the time.
The comment from the previous developers said this was done to eliminate the effects of
Daylight Savings Time. We can't think of a good reason why this change in timezone is
necessary and did find bugs related to the change, therefore, we have removed the
change. Just in case, we will see if the clipped time is ever a different day from the
original day, which would hopefully indicate the change in timezone was actually
necessary. We will collect telemetry if we find this case. If we don't see any
telemetry events after the application has been used for some time, we will feel safe
and can remove this function. */
DayOfWeek trueDayOfWeek = calendar->DayOfWeek;
DateTime clippedTime = ClipTime(today);
@ -110,18 +97,18 @@ DateCalculatorViewModel::DateCalculatorViewModel() :
void DateCalculatorViewModel::OnPropertyChanged(_In_ String^ prop)
{
if (prop == DateCalculatorViewModelProperties::StrDateDiffResult)
if (prop == StrDateDiffResultPropertyName)
{
UpdateStrDateDiffResultAutomationName();
}
else if (prop == DateCalculatorViewModelProperties::StrDateResult)
else if (prop == StrDateResultPropertyName)
{
UpdateStrDateResultAutomationName();
}
else if (prop != DateCalculatorViewModelProperties::StrDateDiffResultAutomationName
&& prop != DateCalculatorViewModelProperties::StrDateDiffResultInDays
&& prop != DateCalculatorViewModelProperties::StrDateResultAutomationName
&& prop != DateCalculatorViewModelProperties::IsDiffInDays)
else if (prop != StrDateDiffResultAutomationNamePropertyName
&& prop != StrDateDiffResultInDaysPropertyName
&& prop != StrDateResultAutomationNamePropertyName
&& prop != IsDiffInDaysPropertyName)
{
OnInputsChanged();
}
@ -181,8 +168,8 @@ void DateCalculatorViewModel::UpdateDisplayResult()
StrDateDiffResult = AppResourceProvider::GetInstance().GetResourceString(L"Date_SameDates");
}
else if ((m_dateDiffResult.year == 0) &&
(m_dateDiffResult.month == 0) &&
(m_dateDiffResult.week == 0))
(m_dateDiffResult.month == 0) &&
(m_dateDiffResult.week == 0))
{
IsDiffInDays = true;
StrDateDiffResultInDays = L"";
@ -245,22 +232,23 @@ void DateCalculatorViewModel::InitializeDateOutputFormats(_In_ String^ calendarI
String^ DateCalculatorViewModel::GetDateDiffString() const
{
String^ result = L"";
wstring result;
bool addDelimiter = false;
AppResourceProvider resourceLoader = AppResourceProvider::GetInstance();
auto yearCount = m_dateDiffResult.year;
if (yearCount > 0)
{
result = String::Concat(GetLocalizedNumberString(yearCount), L" ");
result += GetLocalizedNumberString(yearCount)->Data();
result += L" ";
if (yearCount > 1)
{
result = String::Concat(result, resourceLoader.GetResourceString(L"Date_Years"));
result += resourceLoader.GetResourceString(L"Date_Years")->Data();
}
else
{
result = String::Concat(result, resourceLoader.GetResourceString(L"Date_Year"));
result += resourceLoader.GetResourceString(L"Date_Year")->Data();
}
// set the flags to add a delimiter whenever the next unit is added
@ -272,22 +260,23 @@ String^ DateCalculatorViewModel::GetDateDiffString() const
{
if (addDelimiter)
{
result = String::Concat(result, m_listSeparator);
result += m_listSeparator;
}
else
{
addDelimiter = true;
}
result = String::Concat(result, String::Concat(GetLocalizedNumberString(monthCount), L" "));
result += GetLocalizedNumberString(monthCount)->Data();
result += L" ";
if (monthCount > 1)
{
result = String::Concat(result, resourceLoader.GetResourceString(L"Date_Months"));
result += resourceLoader.GetResourceString(L"Date_Months")->Data();
}
else
{
result = String::Concat(result, resourceLoader.GetResourceString(L"Date_Month"));
result += resourceLoader.GetResourceString(L"Date_Month")->Data();
}
}
@ -296,22 +285,23 @@ String^ DateCalculatorViewModel::GetDateDiffString() const
{
if (addDelimiter)
{
result = String::Concat(result, m_listSeparator);
result += m_listSeparator;
}
else
{
addDelimiter = true;
}
result = String::Concat(result, String::Concat(GetLocalizedNumberString(weekCount), L" "));
result += GetLocalizedNumberString(weekCount)->Data();
result += L" ";
if (weekCount > 1)
{
result = String::Concat(result, resourceLoader.GetResourceString(L"Date_Weeks"));
result += resourceLoader.GetResourceString(L"Date_Weeks")->Data();
}
else
{
result = String::Concat(result, resourceLoader.GetResourceString(L"Date_Week"));
result += resourceLoader.GetResourceString(L"Date_Week")->Data();
}
}
@ -320,43 +310,45 @@ String^ DateCalculatorViewModel::GetDateDiffString() const
{
if (addDelimiter)
{
result = String::Concat(result, m_listSeparator);
result += m_listSeparator;
}
else
{
addDelimiter = true;
}
result = String::Concat(result, String::Concat(GetLocalizedNumberString(dayCount), L" "));
result += GetLocalizedNumberString(dayCount)->Data();
result += L" ";
if (dayCount > 1)
{
result = String::Concat(result, resourceLoader.GetResourceString(L"Date_Days"));
result += resourceLoader.GetResourceString(L"Date_Days")->Data();
}
else
{
result = String::Concat(result, resourceLoader.GetResourceString(L"Date_Day"));
result += resourceLoader.GetResourceString(L"Date_Day")->Data();
}
}
return result;
return ref new String(result.data());
}
String^ DateCalculatorViewModel::GetDateDiffStringInDays() const
{
String^ strDateUnit;
wstring result = GetLocalizedNumberString(m_dateDiffResultInDays.day)->Data();
result += L" ";
// Display the result as '1 day' or 'N days'
if (m_dateDiffResultInDays.day > 1)
{
strDateUnit = AppResourceProvider::GetInstance().GetResourceString(L"Date_Days");
result += AppResourceProvider::GetInstance().GetResourceString(L"Date_Days")->Data();
}
else
{
strDateUnit = AppResourceProvider::GetInstance().GetResourceString(L"Date_Day");
result += AppResourceProvider::GetInstance().GetResourceString(L"Date_Day")->Data();
}
return String::Concat(GetLocalizedNumberString(m_dateDiffResultInDays.day), String::Concat(L" ", strDateUnit));
return ref new String(result.data());
}
void DateCalculatorViewModel::OnCopyCommand(Platform::Object^ parameter)
@ -378,13 +370,14 @@ String^ DateCalculatorViewModel::GetLocalizedNumberString(int value) const
return ref new String(numberStr.c_str());
}
// Adjusts the given DateTime to 12AM of the same day
// Adjusts the given DateTime to 12AM (UTC) of the same day
DateTime DateCalculatorViewModel::ClipTime(DateTime dateTime)
{
auto calendar = ref new Calendar();
calendar->ChangeTimeZone("UTC");
calendar->SetDateTime(dateTime);
calendar->Period = 1;
calendar->Hour = 12;
calendar->Period = calendar->FirstPeriodInThisDay;
calendar->Hour = calendar->FirstHourInThisPeriod;
calendar->Minute = 0;
calendar->Second = 0;
calendar->Nanosecond = 0;

View file

@ -23,8 +23,8 @@ namespace CalculatorApp
// Input Properties
OBSERVABLE_PROPERTY_RW(bool, IsDateDiffMode);
OBSERVABLE_PROPERTY_RW(bool, IsAddMode);
OBSERVABLE_PROPERTY_RW(bool, IsDiffInDays); // If diff is only in days or the dates are the same,
// then show only one result and avoid redundancy
OBSERVABLE_PROPERTY_R(bool, IsDiffInDays); // If diff is only in days or the dates are the same,
// then show only one result and avoid redundancy
OBSERVABLE_PROPERTY_RW(int, DaysOffset);
OBSERVABLE_PROPERTY_RW(int, MonthsOffset);
@ -82,11 +82,11 @@ namespace CalculatorApp
}
// Output Properties
OBSERVABLE_PROPERTY_RW(Platform::String^, StrDateDiffResult);
OBSERVABLE_PROPERTY_RW(Platform::String^, StrDateDiffResultAutomationName);
OBSERVABLE_PROPERTY_RW(Platform::String^, StrDateDiffResultInDays);
OBSERVABLE_PROPERTY_RW(Platform::String^, StrDateResult);
OBSERVABLE_PROPERTY_RW(Platform::String^, StrDateResultAutomationName);
OBSERVABLE_PROPERTY_R(Platform::String^, StrDateDiffResult);
OBSERVABLE_PROPERTY_R(Platform::String^, StrDateDiffResultAutomationName);
OBSERVABLE_PROPERTY_R(Platform::String^, StrDateDiffResultInDays);
OBSERVABLE_PROPERTY_R(Platform::String^, StrDateResult);
OBSERVABLE_PROPERTY_R(Platform::String^, StrDateResultAutomationName);
COMMAND_FOR_METHOD(CopyCommand, DateCalculatorViewModel::OnCopyCommand);
@ -104,8 +104,6 @@ namespace CalculatorApp
Platform::String^ GetLocalizedNumberString(int value) const;
static Windows::Foundation::DateTime ClipTime(Windows::Foundation::DateTime dateTime);
static void CheckClipTimeSameDay(Windows::Globalization::Calendar^ reference);
property bool IsOutOfBound
{
bool get() { return m_isOutOfBound; }
@ -146,7 +144,7 @@ namespace CalculatorApp
CalculatorApp::Common::DateCalculation::DateUnit m_daysOutputFormat;
CalculatorApp::Common::DateCalculation::DateUnit m_allDateUnitsOutputFormat;
Windows::Globalization::DateTimeFormatting::DateTimeFormatter^ m_dateTimeFormatter;
Platform::String^ m_listSeparator;
std::wstring m_listSeparator;
};
}
}

View file

@ -30,37 +30,34 @@ constexpr int StandardModePrecision = 16;
constexpr int ScientificModePrecision = 32;
constexpr int ProgrammerModePrecision = 64;
namespace CalculatorApp::ViewModel
namespace
{
namespace CalculatorViewModelProperties
{
StringReference IsMemoryEmpty(L"IsMemoryEmpty");
StringReference IsScientific(L"IsScientific");
StringReference IsStandard(L"IsStandard");
StringReference IsProgrammer(L"IsProgrammer");
StringReference DisplayValue(L"DisplayValue");
StringReference IsInError(L"IsInError");
StringReference BinaryDisplayValue(L"BinaryDisplayValue");
}
StringReference IsStandardPropertyName(L"IsStandard");
StringReference IsScientificPropertyName(L"IsScientific");
StringReference IsProgrammerPropertyName(L"IsProgrammer");
StringReference DisplayValuePropertyName(L"DisplayValue");
StringReference CalculationResultAutomationNamePropertyName(L"CalculationResultAutomationName");
}
namespace CalculatorResourceKeys
{
StringReference CalculatorExpression(L"Format_CalculatorExpression");
StringReference CalculatorResults(L"Format_CalculatorResults");
StringReference CalculatorResults_DecimalSeparator_Announced(L"Format_CalculatorResults_Decimal");
StringReference HexButton(L"Format_HexButtonValue");
StringReference DecButton(L"Format_DecButtonValue");
StringReference OctButton(L"Format_OctButtonValue");
StringReference BinButton(L"Format_BinButtonValue");
StringReference LeftParenthesisAutomationFormat(L"Format_OpenParenthesisAutomationNamePrefix");
StringReference MaxDigitsReachedFormat(L"Format_MaxDigitsReached");
StringReference ButtonPressFeedbackFormat(L"Format_ButtonPressAuditoryFeedback");
StringReference MemorySave(L"Format_MemorySave");
StringReference MemoryItemChanged(L"Format_MemorySlotChanged");
StringReference MemoryItemCleared(L"Format_MemorySlotCleared");
StringReference MemoryCleared(L"Memory_Cleared");
StringReference DisplayCopied(L"Display_Copied");
}
namespace CalculatorResourceKeys
{
StringReference CalculatorExpression(L"Format_CalculatorExpression");
StringReference CalculatorResults(L"Format_CalculatorResults");
StringReference CalculatorResults_DecimalSeparator_Announced(L"Format_CalculatorResults_Decimal");
StringReference HexButton(L"Format_HexButtonValue");
StringReference DecButton(L"Format_DecButtonValue");
StringReference OctButton(L"Format_OctButtonValue");
StringReference BinButton(L"Format_BinButtonValue");
StringReference LeftParenthesisAutomationFormat(L"Format_OpenParenthesisAutomationNamePrefix");
StringReference OpenParenthesisCountAutomationFormat(L"Format_OpenParenthesisCountAutomationNamePrefix");
StringReference NoParenthesisAdded(L"NoRightParenthesisAdded_Announcement");
StringReference MaxDigitsReachedFormat(L"Format_MaxDigitsReached");
StringReference ButtonPressFeedbackFormat(L"Format_ButtonPressAuditoryFeedback");
StringReference MemorySave(L"Format_MemorySave");
StringReference MemoryItemChanged(L"Format_MemorySlotChanged");
StringReference MemoryItemCleared(L"Format_MemorySlotCleared");
StringReference MemoryCleared(L"Memory_Cleared");
StringReference DisplayCopied(L"Display_Copied");
}
StandardCalculatorViewModel::StandardCalculatorViewModel() :
@ -92,7 +89,9 @@ StandardCalculatorViewModel::StandardCalculatorViewModel() :
m_localizedMemorySavedAutomationFormat(nullptr),
m_localizedMemoryItemChangedAutomationFormat(nullptr),
m_localizedMemoryItemClearedAutomationFormat(nullptr),
m_localizedMemoryCleared(nullptr)
m_localizedMemoryCleared(nullptr),
m_localizedOpenParenthesisCountChangedAutomationFormat(nullptr),
m_localizedNoRightParenthesisAddedFormat(nullptr)
{
WeakReference calculatorViewModel(this);
m_calculatorDisplay.SetCallback(calculatorViewModel);
@ -226,6 +225,34 @@ void StandardCalculatorViewModel::SetParenthesisCount(_In_ const wstring& parent
}
}
void StandardCalculatorViewModel::SetOpenParenthesisCountNarratorAnnouncement()
{
String^ parenthesisCount = ((m_OpenParenthesisCount == nullptr) ? "0" : m_OpenParenthesisCount);
wstring localizedParenthesisCount = parenthesisCount->Data();
LocalizationSettings::GetInstance().LocalizeDisplayValue(&localizedParenthesisCount);
String^ announcement = LocalizationStringUtil::GetLocalizedNarratorAnnouncement(
CalculatorResourceKeys::OpenParenthesisCountAutomationFormat,
m_localizedOpenParenthesisCountChangedAutomationFormat,
localizedParenthesisCount.c_str());
Announcement = CalculatorAnnouncement::GetOpenParenthesisCountChangedAnnouncement(announcement);
}
void StandardCalculatorViewModel::OnNoRightParenAdded()
{
SetNoParenAddedNarratorAnnouncement();
}
void StandardCalculatorViewModel::SetNoParenAddedNarratorAnnouncement()
{
String^ announcement = LocalizationStringUtil::GetLocalizedNarratorAnnouncement(
CalculatorResourceKeys::NoParenthesisAdded,
m_localizedNoRightParenthesisAddedFormat);
Announcement = CalculatorAnnouncement::GetNoRightParenthesisAddedAnnouncement(announcement);
}
void StandardCalculatorViewModel::DisableButtons(CommandType selectedExpressionCommandType)
{
if (selectedExpressionCommandType == CommandType::OperandCommand)
@ -483,7 +510,7 @@ void StandardCalculatorViewModel::HandleUpdatedOperandData(Command cmdenum)
if (IsOperandTextCompletelySelected)
{
//Clear older text;
// Clear older text;
m_selectedExpressionLastData = L"";
if (ch == L'x')
{
@ -525,6 +552,7 @@ void StandardCalculatorViewModel::HandleUpdatedOperandData(Command cmdenum)
length = m_selectedExpressionLastData->Length() + 1;
if (length > 50)
{
delete [] temp;
return;
}
for (; i < length; ++i)
@ -550,8 +578,7 @@ void StandardCalculatorViewModel::HandleUpdatedOperandData(Command cmdenum)
bool StandardCalculatorViewModel::IsOperator(Command cmdenum)
{
if ((cmdenum == Command::Command0) || (cmdenum == Command::Command1) || (cmdenum == Command::Command2) || (cmdenum == Command::Command3) || (cmdenum == Command::Command4) || (cmdenum == Command::Command5)
|| (cmdenum == Command::Command6) || (cmdenum == Command::Command7) || (cmdenum == Command::Command8) || (cmdenum == Command::Command9) || (cmdenum == Command::CommandPNT) || (cmdenum == Command::CommandBACK)
if ((cmdenum >= Command::Command0 && cmdenum <= Command::Command9) || (cmdenum == Command::CommandPNT) || (cmdenum == Command::CommandBACK)
|| (cmdenum == Command::CommandEXP) || (cmdenum == Command::CommandFE) || (cmdenum == Command::ModeBasic) || (cmdenum == Command::ModeProgrammer) || (cmdenum == Command::ModeScientific)
|| (cmdenum == Command::CommandINV) || (cmdenum == Command::CommandCENTR) || (cmdenum == Command::CommandDEG) || (cmdenum == Command::CommandRAD) || (cmdenum == Command::CommandGRAD)
|| ((cmdenum >= Command::CommandBINEDITSTART) && (cmdenum <= Command::CommandBINEDITEND)))
@ -624,8 +651,7 @@ void StandardCalculatorViewModel::OnButtonPressed(Object^ parameter)
{
m_CurrentAngleType = numOpEnum;
}
if ((cmdenum == Command::Command0) || (cmdenum == Command::Command1) || (cmdenum == Command::Command2) || (cmdenum == Command::Command3) || (cmdenum == Command::Command4) || (cmdenum == Command::Command5)
|| (cmdenum == Command::Command6) || (cmdenum == Command::Command7) || (cmdenum == Command::Command8) || (cmdenum == Command::Command9) || (cmdenum == Command::CommandPNT) || (cmdenum == Command::CommandBACK) || (cmdenum == Command::CommandEXP))
if ((cmdenum >= Command::Command0 && cmdenum <= Command::Command9) || (cmdenum == Command::CommandPNT) || (cmdenum == Command::CommandBACK) || (cmdenum == Command::CommandEXP))
{
IsOperatorCommand = false;
}
@ -1162,10 +1188,10 @@ Array<unsigned char>^ StandardCalculatorViewModel::Serialize()
writer->WriteInt32(data);
}
//For ProgrammerMode
// For ProgrammerMode
writer->WriteUInt32(static_cast<UINT32>(CurrentRadixType));
//Serialize commands of calculator manager
// Serialize commands of calculator manager
vector<unsigned char> serializedCommand = m_standardCalculatorManager.SerializeCommands();
writer->WriteUInt32(static_cast<UINT32>(serializedCommand.size()));
writer->WriteBytes(ref new Array<unsigned char>(serializedCommand.data(), static_cast<unsigned int>(serializedCommand.size())));
@ -1175,7 +1201,7 @@ Array<unsigned char>^ StandardCalculatorViewModel::Serialize()
Utils::SerializeCommandsAndTokens(m_tokens, m_commands, writer);
}
//Convert viewmodel data in writer to bytes
// Convert viewmodel data in writer to bytes
IBuffer^ buffer = writer->DetachBuffer();
DataReader^ reader = DataReader::FromBuffer(buffer);
Platform::Array<unsigned char>^ viewModelDataAsBytes = ref new Array<unsigned char>(buffer->Length);
@ -1223,7 +1249,7 @@ void StandardCalculatorViewModel::Deserialize(Array<unsigned char>^ state)
m_standardCalculatorManager.DeSerializePrimaryDisplay(serializedPrimaryDisplay);
CurrentRadixType = reader->ReadUInt32();
//Read command data and Deserialize
// Read command data and Deserialize
UINT32 modeldatalength = reader->ReadUInt32();
Array<unsigned char>^ modelDataAsBytes = ref new Array<unsigned char>(modeldatalength);
reader->ReadBytes(modelDataAsBytes);
@ -1242,30 +1268,30 @@ void StandardCalculatorViewModel::Deserialize(Array<unsigned char>^ state)
void StandardCalculatorViewModel::OnPropertyChanged(String^ propertyname)
{
if (propertyname == CalculatorViewModelProperties::IsScientific)
if (propertyname == IsScientificPropertyName)
{
if (IsScientific)
{
OnButtonPressed(NumbersAndOperatorsEnum::IsScientificMode);
}
}
else if (propertyname == CalculatorViewModelProperties::IsProgrammer)
else if (propertyname == IsProgrammerPropertyName)
{
if (IsProgrammer)
{
OnButtonPressed(NumbersAndOperatorsEnum::IsProgrammerMode);
}
}
else if (propertyname == CalculatorViewModelProperties::IsStandard)
else if (propertyname == IsStandardPropertyName)
{
if (IsStandard)
{
OnButtonPressed(NumbersAndOperatorsEnum::IsStandardMode);
}
}
else if (propertyname == CalculatorViewModelProperties::DisplayValue)
else if (propertyname == DisplayValuePropertyName)
{
RaisePropertyChanged(CalculationResultAutomationName_PropertyName);
RaisePropertyChanged(CalculationResultAutomationNamePropertyName);
Announcement = GetDisplayUpdatedNarratorAnnouncement();
}
}
@ -1614,7 +1640,7 @@ bool StandardCalculatorViewModel::IsOpnd(int nOpCode)
Command::CommandPNT
};
for (int i = 0; i < ARRAYSIZE(opnd); i++)
for (unsigned int i = 0; i < size(opnd); i++)
{
if (nOpCode == static_cast<int>(opnd[i]))
{
@ -1645,7 +1671,7 @@ bool StandardCalculatorViewModel::IsUnaryOp(int nOpCode)
Command::CommandCUB
};
for (int i = 0; i < ARRAYSIZE(unaryOp); i++)
for (unsigned int i = 0; i < size(unaryOp); i++)
{
if (nOpCode == static_cast<int>(unaryOp[i]))
{
@ -1672,7 +1698,7 @@ bool StandardCalculatorViewModel::IsTrigOp(int nOpCode)
Command::CommandATAN
};
for (int i = 0; i < ARRAYSIZE(trigOp); i++)
for (unsigned int i = 0; i < size(trigOp); i++)
{
if (nOpCode == static_cast<int>(trigOp[i]))
{
@ -1695,7 +1721,7 @@ bool StandardCalculatorViewModel::IsBinOp(int nOpCode)
Command::CommandPWR
};
for (int i = 0; i < ARRAYSIZE(binOp); i++)
for (unsigned int i = 0; i < size(binOp); i++)
{
if (nOpCode == static_cast<int>(binOp[i]))
{
@ -1729,7 +1755,7 @@ bool StandardCalculatorViewModel::IsRecoverableCommand(int nOpCode)
Command::CommandF
};
for (int i = 0; i < ARRAYSIZE(recoverableCommands); i++)
for (unsigned int i = 0; i < size(recoverableCommands); i++)
{
if (nOpCode == static_cast<int>(recoverableCommands[i]))
{
@ -1947,7 +1973,7 @@ void StandardCalculatorViewModel::UpdatecommandsInRecordingMode()
}
else
{
//reset all vars
// Reset all vars
isDecimal = false;
isNegative = false;
isExpMode = false;

View file

@ -31,12 +31,6 @@ namespace CalculatorApp
#define ASCII_0 48
public delegate void HideMemoryClickedHandler();
public delegate void ProgModeRadixChangeHandler();
namespace CalculatorViewModelProperties
{
extern Platform::StringReference IsMemoryEmpty;
extern Platform::StringReference IsInError;
extern Platform::StringReference BinaryDisplayValue;
}
[Windows::UI::Xaml::Data::Bindable]
public ref class StandardCalculatorViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
@ -51,14 +45,14 @@ namespace CalculatorApp
OBSERVABLE_OBJECT_CALLBACK(OnPropertyChanged);
OBSERVABLE_PROPERTY_RW(Platform::String^, DisplayValue);
OBSERVABLE_PROPERTY_RW(HistoryViewModel^, HistoryVM);
OBSERVABLE_PROPERTY_RW(bool, IsInError);
OBSERVABLE_NAMED_PROPERTY_RW(bool, IsInError);
OBSERVABLE_PROPERTY_RW(bool, IsOperatorCommand);
OBSERVABLE_PROPERTY_RW(Platform::String^, DisplayStringExpression);
OBSERVABLE_PROPERTY_RW(Windows::Foundation::Collections::IVector<Common::DisplayExpressionToken^>^, ExpressionTokens);
OBSERVABLE_PROPERTY_RW(Platform::String^, DecimalDisplayValue);
OBSERVABLE_PROPERTY_RW(Platform::String^, HexDisplayValue);
OBSERVABLE_PROPERTY_RW(Platform::String^, OctalDisplayValue);
OBSERVABLE_PROPERTY_RW(Platform::String^, BinaryDisplayValue);
OBSERVABLE_NAMED_PROPERTY_RW(Platform::String^, BinaryDisplayValue);
OBSERVABLE_PROPERTY_RW(Platform::String^, HexDisplayValue_AutomationName);
OBSERVABLE_PROPERTY_RW(Platform::String^, DecDisplayValue_AutomationName);
OBSERVABLE_PROPERTY_RW(Platform::String^, OctDisplayValue_AutomationName);
@ -69,19 +63,19 @@ namespace CalculatorApp
OBSERVABLE_PROPERTY_RW(bool, IsDecimalEnabled);
OBSERVABLE_PROPERTY_RW(bool, IsCurrentViewPinned);
OBSERVABLE_PROPERTY_RW(Windows::Foundation::Collections::IVector<MemoryItemViewModel^>^, MemorizedNumbers);
OBSERVABLE_PROPERTY_RW(bool, IsMemoryEmpty);
OBSERVABLE_NAMED_PROPERTY_RW(bool, IsMemoryEmpty);
OBSERVABLE_PROPERTY_RW(bool, IsFToEChecked);
OBSERVABLE_PROPERTY_RW(bool, IsFToEEnabled);
OBSERVABLE_PROPERTY_RW(bool, IsHyperbolicChecked);
OBSERVABLE_PROPERTY_RW(bool, AreHEXButtonsEnabled);
NAMED_OBSERVABLE_PROPERTY_RW(Platform::String^, CalculationResultAutomationName);
NAMED_OBSERVABLE_PROPERTY_RW(Platform::String^, CalculationExpressionAutomationName);
OBSERVABLE_PROPERTY_RW(Platform::String^, CalculationResultAutomationName);
OBSERVABLE_PROPERTY_RW(Platform::String^, CalculationExpressionAutomationName);
OBSERVABLE_PROPERTY_RW(bool, IsShiftProgrammerChecked);
OBSERVABLE_PROPERTY_RW(bool, IsQwordEnabled);
OBSERVABLE_PROPERTY_RW(bool, IsDwordEnabled);
OBSERVABLE_PROPERTY_RW(bool, IsWordEnabled);
OBSERVABLE_PROPERTY_RW(bool, IsByteEnabled);
OBSERVABLE_PROPERTY_RW(Platform::String^, OpenParenthesisCount);
OBSERVABLE_NAMED_PROPERTY_RW(Platform::String^, OpenParenthesisCount);
OBSERVABLE_PROPERTY_RW(int, CurrentRadixType);
OBSERVABLE_PROPERTY_RW(bool, AreTokensUpdated);
OBSERVABLE_PROPERTY_RW(bool, AreHistoryShortcutsEnabled);
@ -276,7 +270,7 @@ namespace CalculatorApp
NumbersAndOperatorsEnum MapCharacterToButtonId(const wchar_t ch, bool& canSendNegate);
//Memory feature related methods. They are internal because they need to called from the MainPage code-behind
// Memory feature related methods. They are internal because they need to called from the MainPage code-behind
void OnMemoryButtonPressed();
void OnMemoryItemPressed(Platform::Object^ memoryItemPosition);
void OnMemoryAdd(Platform::Object^ memoryItemPosition);
@ -290,6 +284,9 @@ namespace CalculatorApp
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);
void SetHistoryExpressionDisplay(_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const &tokens, _Inout_ std::shared_ptr<CalculatorVector <std::shared_ptr<IExpressionCommand>>> const &commands);
void SetParenthesisCount(_In_ const std::wstring& parenthesisCount);
void SetOpenParenthesisCountNarratorAnnouncement();
void OnNoRightParenAdded();
void SetNoParenAddedNarratorAnnouncement();
void OnMaxDigitsReached();
void OnBinaryOperatorReceived();
void OnMemoryItemChanged(unsigned int indexOfMemory);
@ -337,6 +334,8 @@ namespace CalculatorApp
Platform::String^ m_localizedMemoryItemChangedAutomationFormat;
Platform::String^ m_localizedMemoryItemClearedAutomationFormat;
Platform::String^ m_localizedMemoryCleared;
Platform::String^ m_localizedOpenParenthesisCountChangedAutomationFormat;
Platform::String^ m_localizedNoRightParenthesisAddedFormat;
bool m_pinned;
bool m_isOperandEnabled;

View file

@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#include "pch.h"
@ -53,48 +53,40 @@ constexpr size_t SELECTED_TARGET_UNIT = 2;
// x millisecond delay before we consider conversion to be final
constexpr unsigned int CONVERSION_FINALIZED_DELAY_IN_MS = 1000;
const wregex regexTrimSpacesStart = wregex(L"^\\s+");
const wregex regexTrimSpacesEnd = wregex(L"\\s+$");
namespace CalculatorApp::ViewModel
namespace
{
namespace UnitConverterViewModelProperties
{
StringReference CurrentCategory(L"CurrentCategory");
StringReference Unit1(L"Unit1");
StringReference Unit2(L"Unit2");
StringReference Value1Active(L"Value1Active");
StringReference Value2Active(L"Value2Active");
StringReference Value1(L"Value1");
StringReference Value2(L"Value2");
StringReference Value1AutomationName(L"Value1AutomationName");
StringReference Value2AutomationName(L"Value2AutomationName");
StringReference SupplementaryVisibility(L"SupplementaryVisibility");
StringReference SupplementaryResults(L"SupplementaryResults");
StringReference Unit1AutomationName(L"Unit1AutomationName");
StringReference Unit2AutomationName(L"Unit2AutomationName");
StringReference CurrencySymbol1(L"CurrencySymbol1");
StringReference CurrencySymbol2(L"CurrencySymbol2");
StringReference CurrencySymbolVisibility(L"CurrencySymbolVisibility");
StringReference CurrencyRatioEquality(L"CurrencyRatioEquality");
StringReference CurrencyRatioEqualityAutomationName(L"CurrencyRatioEqualityAutomationName");
StringReference NetworkBehavior(L"NetworkBehavior");
StringReference CurrencyDataLoadFailed(L"CurrencyDataLoadFailed");
StringReference CurrencyDataIsWeekOld(L"CurrencyDataIsWeekOld");
StringReference IsCurrencyLoadingVisible(L"IsCurrencyLoadingVisible");
}
StringReference CurrentCategoryPropertyName(L"CurrentCategory");
StringReference Unit1AutomationNamePropertyName(L"Unit1AutomationName");
StringReference Unit2AutomationNamePropertyName(L"Unit2AutomationName");
StringReference Unit1PropertyName(L"Unit1");
StringReference Unit2PropertyName(L"Unit2");
StringReference Value1PropertyName(L"Value1");
StringReference Value2PropertyName(L"Value2");
StringReference Value1ActivePropertyName(L"Value1Active");
StringReference Value2ActivePropertyName(L"Value2Active");
StringReference Value1AutomationNamePropertyName(L"Value1AutomationName");
StringReference Value2AutomationNamePropertyName(L"Value2AutomationName");
StringReference CurrencySymbol1PropertyName(L"CurrencySymbol1");
StringReference CurrencySymbol2PropertyName(L"CurrencySymbol2");
StringReference CurrencySymbolVisibilityPropertyName(L"CurrencySymbolVisibility");
StringReference SupplementaryVisibilityPropertyName(L"SupplementaryVisibility");
}
namespace UnitConverterResourceKeys
{
StringReference ValueFromFormat(L"Format_ValueFrom");
StringReference ValueFromDecimalFormat(L"Format_ValueFrom_Decimal");
StringReference ValueToFormat(L"Format_ValueTo");
StringReference ConversionResultFormat(L"Format_ConversionResult");
StringReference InputUnit_Name(L"InputUnit_Name");
StringReference OutputUnit_Name(L"OutputUnit_Name");
StringReference MaxDigitsReachedFormat(L"Format_MaxDigitsReached");
StringReference UpdatingCurrencyRates(L"UpdatingCurrencyRates");
StringReference CurrencyRatesUpdated(L"CurrencyRatesUpdated");
StringReference CurrencyRatesUpdateFailed(L"CurrencyRatesUpdateFailed");
}
namespace CalculatorApp::ViewModel::UnitConverterResourceKeys
{
StringReference ValueFromFormat(L"Format_ValueFrom");
StringReference ValueFromDecimalFormat(L"Format_ValueFrom_Decimal");
StringReference ValueToFormat(L"Format_ValueTo");
StringReference ConversionResultFormat(L"Format_ConversionResult");
StringReference InputUnit_Name(L"InputUnit_Name");
StringReference OutputUnit_Name(L"OutputUnit_Name");
StringReference MaxDigitsReachedFormat(L"Format_MaxDigitsReached");
StringReference UpdatingCurrencyRates(L"UpdatingCurrencyRates");
StringReference CurrencyRatesUpdated(L"CurrencyRatesUpdated");
StringReference CurrencyRatesUpdateFailed(L"CurrencyRatesUpdateFailed");
}
UnitConverterViewModel::UnitConverterViewModel(const shared_ptr<UCM::IUnitConverter>& model) :
@ -202,12 +194,10 @@ void UnitConverterViewModel::BuildUnitList(const vector<UCM::Unit>& modelUnitLis
m_Units->Clear();
for (const UCM::Unit& modelUnit : modelUnitList)
{
if (modelUnit.isWhimsical)
if (!modelUnit.isWhimsical)
{
continue;
m_Units->Append(ref new Unit(modelUnit));
}
m_Units->Append(ref new Unit(modelUnit));
}
if (m_Units->Size == 0)
@ -281,8 +271,8 @@ void UnitConverterViewModel::OnSwitchActive(Platform::Object^ unused)
Utils::Swap(&m_localizedValueFromFormat, &m_localizedValueToFormat);
Utils::Swap(&m_Unit1AutomationName, &m_Unit2AutomationName);
RaisePropertyChanged(UnitConverterViewModelProperties::Unit1AutomationName);
RaisePropertyChanged(UnitConverterViewModelProperties::Unit2AutomationName);
RaisePropertyChanged(Unit1AutomationNamePropertyName);
RaisePropertyChanged(Unit2AutomationNamePropertyName);
m_isInputBlocked = false;
m_model->SwitchActive(m_valueFromUnlocalized);
@ -348,10 +338,15 @@ String^ UnitConverterViewModel::ConvertToLocalizedString(const std::wstring& str
if (pos != wstring::npos)
{
currencyResult.erase(pos, currencyCode.length());
pos = currencyResult.find(L'\u00a0'); // non-breaking space
if (pos != wstring::npos)
std::wsmatch sm;
if (regex_search(currencyResult, sm, regexTrimSpacesStart))
{
currencyResult.erase(pos, 1);
currencyResult.erase(sm.prefix().length(), sm.length());
}
if (regex_search(currencyResult, sm, regexTrimSpacesEnd))
{
currencyResult.erase(sm.prefix().length(), sm.length());
}
}
@ -479,7 +474,7 @@ void UnitConverterViewModel::OnButtonPressed(Platform::Object^ parameter)
NumbersAndOperatorsEnum numOpEnum = CalculatorButtonPressedEventArgs::GetOperationFromCommandParameter(parameter);
UCM::Command command = CommandFromButtonId(numOpEnum);
//Don't clear the display if combo box is open and escape is pressed
// Don't clear the display if combo box is open and escape is pressed
if (command == UCM::Command::Clear && IsDropDownOpen)
{
return;
@ -556,13 +551,13 @@ void UnitConverterViewModel::OnPropertyChanged(Platform::String^ prop)
{
static bool isCategoryChanging = false;
if (prop->Equals(UnitConverterViewModelProperties::CurrentCategory))
if (prop == CurrentCategoryPropertyName)
{
isCategoryChanging = true;
CategoryChanged->Execute(nullptr);
isCategoryChanging = false;
}
else if (prop->Equals(UnitConverterViewModelProperties::Unit1) || prop->Equals(UnitConverterViewModelProperties::Unit2))
else if (prop == Unit1PropertyName || prop == Unit2PropertyName)
{
// Category changes will handle updating units after they've both been updated.
// This event should only be used to update units from explicit user interaction.
@ -571,7 +566,7 @@ void UnitConverterViewModel::OnPropertyChanged(Platform::String^ prop)
UnitChanged->Execute(nullptr);
}
// Get the localized automation name for each CalculationResults field
if (prop->Equals(UnitConverterViewModelProperties::Unit1))
if (prop == Unit1PropertyName)
{
UpdateValue1AutomationName();
}
@ -580,15 +575,15 @@ void UnitConverterViewModel::OnPropertyChanged(Platform::String^ prop)
UpdateValue2AutomationName();
}
}
else if (prop->Equals(UnitConverterViewModelProperties::Value1))
else if (prop == Value1PropertyName)
{
UpdateValue1AutomationName();
}
else if (prop->Equals(UnitConverterViewModelProperties::Value2))
else if (prop == Value2PropertyName)
{
UpdateValue2AutomationName();
}
else if (prop->Equals(UnitConverterViewModelProperties::Value1Active) || prop->Equals(UnitConverterViewModelProperties::Value2Active))
else if (prop == Value1ActivePropertyName || prop == Value2ActivePropertyName)
{
// if one of the values is activated, and as a result both are true, it means
// that we're trying to switch.
@ -600,11 +595,11 @@ void UnitConverterViewModel::OnPropertyChanged(Platform::String^ prop)
UpdateValue1AutomationName();
UpdateValue2AutomationName();
}
else if (prop->Equals(UnitConverterViewModelProperties::SupplementaryResults))
else if (prop == SupplementaryResultsPropertyName)
{
RaisePropertyChanged(UnitConverterViewModelProperties::SupplementaryVisibility);
RaisePropertyChanged(SupplementaryVisibilityPropertyName);
}
else if (prop->Equals(UnitConverterViewModelProperties::Value1AutomationName))
else if (prop == Value1AutomationNamePropertyName)
{
m_isValue1Updating = false;
if (!m_isValue2Updating)
@ -612,7 +607,7 @@ void UnitConverterViewModel::OnPropertyChanged(Platform::String^ prop)
AnnounceConversionResult();
}
}
else if (prop->Equals(UnitConverterViewModelProperties::Value2AutomationName))
else if (prop == Value2AutomationNamePropertyName)
{
m_isValue2Updating = false;
if (!m_isValue1Updating)
@ -620,9 +615,9 @@ void UnitConverterViewModel::OnPropertyChanged(Platform::String^ prop)
AnnounceConversionResult();
}
}
else if (prop->Equals(UnitConverterViewModelProperties::CurrencySymbol1) || prop->Equals(UnitConverterViewModelProperties::CurrencySymbol2))
else if (prop == CurrencySymbol1PropertyName || prop == CurrencySymbol2PropertyName)
{
RaisePropertyChanged(UnitConverterViewModelProperties::CurrencySymbolVisibility);
RaisePropertyChanged(CurrencySymbolVisibilityPropertyName);
}
}
@ -643,10 +638,8 @@ String^ UnitConverterViewModel::Serialize()
String^ serializedData = ref new String(wstring(out.str()).c_str());
return serializedData;
}
else
{
return nullptr;
}
return nullptr;
}
void UnitConverterViewModel::Deserialize(Platform::String^ state)
@ -674,7 +667,7 @@ void UnitConverterViewModel::Deserialize(Platform::String^ state)
RaisePropertyChanged(nullptr); // Update since all props have been updated.
}
//Saving User Preferences of Category and Associated-Units across Sessions.
// Saving User Preferences of Category and Associated-Units across Sessions.
void UnitConverterViewModel::SaveUserPreferences()
{
if (UnitsAreValid())
@ -695,7 +688,7 @@ void UnitConverterViewModel::SaveUserPreferences()
}
}
//Restoring User Preferences of Category and Associated-Units.
// Restoring User Preferences of Category and Associated-Units.
void UnitConverterViewModel::RestoreUserPreferences()
{
if (!IsCurrencyCurrentCategory)
@ -849,7 +842,7 @@ void UnitConverterViewModel::RefreshSupplementaryResults()
}
m_cacheMutex.unlock();
RaisePropertyChanged(UnitConverterViewModelProperties::SupplementaryResults);
RaisePropertyChanged(SupplementaryResultsPropertyName);
//EventWriteConverterSupplementaryResultsUpdated();
}
@ -879,14 +872,11 @@ void UnitConverterViewModel::UpdateInputBlocked(_In_ const wstring& currencyInpu
{
// currencyInput is in en-US and has the default decimal separator, so this is safe to do.
auto posOfDecimal = currencyInput.find(L'.');
m_isInputBlocked = false;
if (posOfDecimal != wstring::npos && IsCurrencyCurrentCategory)
{
m_isInputBlocked = (posOfDecimal + static_cast<size_t>(m_currencyMaxFractionDigits) + 1 == currencyInput.length());
}
else
{
m_isInputBlocked = false;
}
}
NumbersAndOperatorsEnum UnitConverterViewModel::MapCharacterToButtonId(
@ -988,7 +978,7 @@ void UnitConverterViewModel::OnPaste(String^ stringToPaste, ViewMode mode)
}
// Negate is only allowed if it's the first legal character, which is handled above.
if (NumbersAndOperatorsEnum::None != op && NumbersAndOperatorsEnum::Negate != op)
if (NumbersAndOperatorsEnum::Negate != op)
{
UCM::Command cmd = CommandFromButtonId(op);
m_model->SendCommand(cmd);

View file

@ -138,25 +138,6 @@ namespace CalculatorApp
return ref new Activatable<TActivatable>(activatable);
}
namespace UnitConverterViewModelProperties
{
extern Platform::StringReference CurrentCategory;
extern Platform::StringReference Unit1;
extern Platform::StringReference Unit2;
extern Platform::StringReference Value1Active;
extern Platform::StringReference Value2Active;
extern Platform::StringReference SupplementaryVisibility;
extern Platform::StringReference SupplementaryResults;
extern Platform::StringReference CurrencySymbol1;
extern Platform::StringReference CurrencySymbol2;
extern Platform::StringReference CurrencySymbolVisibility;
extern Platform::StringReference CurrencyRatioEquality;
extern Platform::StringReference NetworkBehavior;
extern Platform::StringReference CurrencyDataLoadFailed;
extern Platform::StringReference CurrencyDataIsWeekOld;
extern Platform::StringReference IsCurrencyLoadingVisible;
}
[Windows::UI::Xaml::Data::Bindable]
public ref class UnitConverterViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
{
@ -176,7 +157,7 @@ namespace CalculatorApp
OBSERVABLE_PROPERTY_RW(Platform::String^, CurrencySymbol2);
OBSERVABLE_PROPERTY_RW(Unit^, Unit2);
OBSERVABLE_PROPERTY_RW(Platform::String^, Value2);
OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector<SupplementaryResult^>^, SupplementaryResults);
OBSERVABLE_NAMED_PROPERTY_R(Windows::Foundation::Collections::IObservableVector<SupplementaryResult^>^, SupplementaryResults);
OBSERVABLE_PROPERTY_RW(bool, Value1Active);
OBSERVABLE_PROPERTY_RW(bool, Value2Active);
OBSERVABLE_PROPERTY_RW(Platform::String^, Value1AutomationName);
@ -187,14 +168,14 @@ namespace CalculatorApp
OBSERVABLE_PROPERTY_RW(bool, IsDecimalEnabled);
OBSERVABLE_PROPERTY_RW(bool, IsDropDownOpen);
OBSERVABLE_PROPERTY_RW(bool, IsDropDownEnabled);
OBSERVABLE_PROPERTY_RW(bool, IsCurrencyLoadingVisible);
OBSERVABLE_NAMED_PROPERTY_RW(bool, IsCurrencyLoadingVisible);
OBSERVABLE_PROPERTY_RW(bool, IsCurrencyCurrentCategory);
OBSERVABLE_PROPERTY_RW(Platform::String^, CurrencyRatioEquality);
OBSERVABLE_PROPERTY_RW(Platform::String^, CurrencyRatioEqualityAutomationName);
OBSERVABLE_PROPERTY_RW(Platform::String^, CurrencyTimestamp);
OBSERVABLE_PROPERTY_RW(CalculatorApp::NetworkAccessBehavior, NetworkBehavior);
OBSERVABLE_PROPERTY_RW(bool, CurrencyDataLoadFailed);
OBSERVABLE_PROPERTY_RW(bool, CurrencyDataIsWeekOld);
OBSERVABLE_NAMED_PROPERTY_RW(CalculatorApp::NetworkAccessBehavior, NetworkBehavior);
OBSERVABLE_NAMED_PROPERTY_RW(bool, CurrencyDataLoadFailed);
OBSERVABLE_NAMED_PROPERTY_RW(bool, CurrencyDataIsWeekOld);
property Windows::UI::Xaml::Visibility SupplementaryVisibility
{
@ -243,7 +224,7 @@ namespace CalculatorApp
Platform::String^ Serialize();
void Deserialize(Platform::String^ state);
//Saving And Restoring User Preferences of Category and Associated-Units across Sessions.
// Saving And Restoring User Preferences of Category and Associated-Units across Sessions.
void SaveUserPreferences();
void RestoreUserPreferences();

View file

@ -10,6 +10,10 @@
#define WIN32_LEAN_AND_MEAN
#endif
// Windows headers define min/max macros.
// Disable it for project code.
#define NOMINMAX
#include <windows.h>
#include <collection.h>
@ -26,7 +30,7 @@
#include <sstream>
#include <concrt.h>
#include <regex>
#include <iterator>
// C++\WinRT Headers
#include "winrt/base.h"
#include "winrt/Windows.Foundation.Diagnostics.h"

View file

@ -9,7 +9,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CalcManager", "CalcManager\
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3A5DF651-B8A1-45CA-9135-964A6FC7F5D1}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
nuget.config = nuget.config
EndProjectSection
EndProject

View file

@ -38,7 +38,7 @@
<Paragraph>
<Run x:Name="AboutFlyoutVersion"/>
<LineBreak/>
<Run x:Uid="AboutControlCopyright"/>
<Run x:Name="AboutControlCopyrightRun"/>
</Paragraph>
</RichTextBlock>
<HyperlinkButton x:Name="AboutFlyoutEULA"

View file

@ -8,6 +8,7 @@
#include "CalcViewModel/Common/LocalizationStringUtil.h"
#include "CalcViewModel/Common/TraceLogger.h"
using namespace std;
using namespace CalculatorApp;
using namespace CalculatorApp::Common;
using namespace Platform;
@ -19,6 +20,10 @@ using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Controls::Primitives;
using namespace Windows::UI::Xaml::Data;
#ifndef BUILD_YEAR
#define BUILD_YEAR 2019
#endif
AboutFlyout::AboutFlyout()
{
auto locService = LocalizationService::GetInstance();
@ -31,6 +36,10 @@ AboutFlyout::AboutFlyout()
this->SetVersionString();
Header->Text = resourceLoader.GetResourceString("AboutButton/Content");
auto copyrightText = LocalizationStringUtil::GetLocalizedString(resourceLoader.GetResourceString("AboutControlCopyright")->Data(), to_wstring(BUILD_YEAR).c_str());
AboutControlCopyrightRun->Text = ref new String(copyrightText.c_str());
}
void AboutFlyout::FeedbackButton_Click(_In_ Object^ sender, _In_ RoutedEventArgs^ e)

View file

@ -371,12 +371,13 @@
</Grid.ColumnDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ActiveStates">
<VisualState x:Name="Active"/>
<VisualState x:Name="Normal">
<VisualState x:Name="Active">
<VisualState.Setters>
<Setter Target="normalOutput.FontWeight" Value="Light"/>
<Setter Target="normalOutput.FontWeight" Value="SemiBold"/>
<Setter Target="normalOutput.IsTextSelectionEnabled" Value="True"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Normal"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ScrollViewer x:Name="textContainer"
@ -390,7 +391,7 @@
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Foreground="{TemplateBinding Foreground}"
FontSize="{TemplateBinding FontSize}"
FontWeight="SemiBold"
FontWeight="Light"
AutomationProperties.AccessibilityView="Raw"
Text="{TemplateBinding DisplayValue}"
TextAlignment="{TemplateBinding HorizontalContentAlignment}"
@ -457,12 +458,13 @@
</Grid.ColumnDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ActiveStates">
<VisualState x:Name="Active"/>
<VisualState x:Name="Normal">
<VisualState x:Name="Active">
<VisualState.Setters>
<Setter Target="normalOutput.FontWeight" Value="Light"/>
<Setter Target="normalOutput.IsTextSelectionEnabled" Value="True"/>
<Setter Target="normalOutput.FontWeight" Value="SemiBold"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Normal"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ScrollViewer x:Name="textContainer"
@ -476,7 +478,7 @@
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Foreground="{TemplateBinding Foreground}"
FontSize="{TemplateBinding FontSize}"
FontWeight="SemiBold"
FontWeight="Light"
AutomationProperties.AccessibilityView="Raw"
Text="{TemplateBinding DisplayValue}"
TextAlignment="{TemplateBinding HorizontalContentAlignment}"
@ -544,12 +546,13 @@
</Grid.ColumnDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ActiveStates">
<VisualState x:Name="Active"/>
<VisualState x:Name="Normal">
<VisualState x:Name="Active">
<VisualState.Setters>
<Setter Target="normalOutput.FontWeight" Value="Light"/>
<Setter Target="normalOutput.FontWeight" Value="SemiBold"/>
<Setter Target="normalOutput.IsTextSelectionEnabled" Value="True"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Normal"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ScrollViewer x:Name="textContainer"
@ -563,7 +566,7 @@
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Foreground="{TemplateBinding Foreground}"
FontSize="{TemplateBinding FontSize}"
FontWeight="SemiBold"
FontWeight="Light"
AutomationProperties.AccessibilityView="Raw"
Text="{TemplateBinding DisplayValue}"
TextAlignment="{TemplateBinding HorizontalContentAlignment}"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 391 B

After

Width:  |  Height:  |  Size: 384 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 513 B

After

Width:  |  Height:  |  Size: 484 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 806 B

After

Width:  |  Height:  |  Size: 728 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 235 B

After

Width:  |  Height:  |  Size: 234 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 456 B

After

Width:  |  Height:  |  Size: 441 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 487 B

After

Width:  |  Height:  |  Size: 470 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 532 B

After

Width:  |  Height:  |  Size: 511 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 557 B

After

Width:  |  Height:  |  Size: 503 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 683 B

After

Width:  |  Height:  |  Size: 634 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 485 B

After

Width:  |  Height:  |  Size: 296 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 524 B

After

Width:  |  Height:  |  Size: 331 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 577 B

After

Width:  |  Height:  |  Size: 390 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 690 B

After

Width:  |  Height:  |  Size: 484 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 996 B

After

Width:  |  Height:  |  Size: 728 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 371 B

After

Width:  |  Height:  |  Size: 180 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 384 B

After

Width:  |  Height:  |  Size: 193 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 421 B

After

Width:  |  Height:  |  Size: 231 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 453 B

After

Width:  |  Height:  |  Size: 262 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 474 B

After

Width:  |  Height:  |  Size: 284 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 491 B

After

Width:  |  Height:  |  Size: 303 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 505 B

After

Width:  |  Height:  |  Size: 311 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 558 B

After

Width:  |  Height:  |  Size: 370 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 630 B

After

Width:  |  Height:  |  Size: 445 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 665 B

After

Width:  |  Height:  |  Size: 471 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 707 B

After

Width:  |  Height:  |  Size: 506 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 737 B

After

Width:  |  Height:  |  Size: 507 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 867 B

After

Width:  |  Height:  |  Size: 639 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 371 B

After

Width:  |  Height:  |  Size: 180 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 371 B

After

Width:  |  Height:  |  Size: 180 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 371 B

After

Width:  |  Height:  |  Size: 180 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 384 B

After

Width:  |  Height:  |  Size: 193 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 384 B

After

Width:  |  Height:  |  Size: 193 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 384 B

After

Width:  |  Height:  |  Size: 193 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 235 B

After

Width:  |  Height:  |  Size: 234 B

Before After
Before After

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