diff --git a/build/pipelines/azure-pipelines.ci.yaml b/build/pipelines/azure-pipelines.ci.yaml index 70406504..dbac9583 100644 --- a/build/pipelines/azure-pipelines.ci.yaml +++ b/build/pipelines/azure-pipelines.ci.yaml @@ -7,11 +7,9 @@ trigger: - master - servicing/* -- feature/* pr: - master - servicing/* -- feature/* name: 0.$(Date:yyMM).$(DayOfMonth)$(Rev:rr).0 @@ -43,15 +41,9 @@ jobs: - template: ./templates/run-unit-tests.yaml parameters: platform: x64 - reimageServiceConnection: essential-experiences-interactive-reimage - reimageSubscriptionId: a8f5eb47-e59c-44b4-8e42-e70811a047b5 - reimageResourceGroup: EETestPublic - template: ./templates/run-unit-tests.yaml parameters: platform: x86 - reimageServiceConnection: essential-experiences-interactive-reimage - reimageSubscriptionId: a8f5eb47-e59c-44b4-8e42-e70811a047b5 - reimageResourceGroup: EETestPublic - template: ./templates/package-appxbundle.yaml diff --git a/build/pipelines/azure-pipelines.loc.yaml b/build/pipelines/azure-pipelines.loc.yaml index 7c5ef246..287188be 100644 --- a/build/pipelines/azure-pipelines.loc.yaml +++ b/build/pipelines/azure-pipelines.loc.yaml @@ -15,11 +15,10 @@ name: $(BuildDefinitionName)_$(date:yyMM).$(date:dd)$(rev:rrr) jobs: - job: Localize pool: - vmImage: vs2017-win2016 + vmImage: windows-2019 variables: skipComponentGovernanceDetection: true steps: - - task: MicrosoftTDBuild.tdbuild-task.tdbuild-task.TouchdownBuildTask@1 displayName: Send resources to Touchdown Build inputs: diff --git a/build/pipelines/azure-pipelines.release.yaml b/build/pipelines/azure-pipelines.release.yaml index c26df788..33e10c63 100644 --- a/build/pipelines/azure-pipelines.release.yaml +++ b/build/pipelines/azure-pipelines.release.yaml @@ -9,8 +9,8 @@ pr: none variables: versionMajor: 10 - versionMinor: 1907 - versionBuild: $[counter('10.1907.*', 0)] + versionMinor: 1910 + versionBuild: $[counter('10.1910.*', 0)] versionPatch: 0 name: '$(versionMajor).$(versionMinor).$(versionBuild).$(versionPatch)' @@ -48,16 +48,10 @@ jobs: - template: ./templates/run-unit-tests.yaml parameters: platform: x64 - reimageServiceConnection: macool-sandbox-interactiveDesktopRS5 - reimageSubscriptionId: 012a8008-c00f-45b3-9828-41ebba30141d - reimageResourceGroup: interactiveDesktopRS5 - template: ./templates/run-unit-tests.yaml parameters: platform: x86 - reimageServiceConnection: macool-sandbox-interactiveDesktopRS5 - reimageSubscriptionId: 012a8008-c00f-45b3-9828-41ebba30141d - reimageResourceGroup: interactiveDesktopRS5 - template: ./templates/package-appxbundle.yaml diff --git a/build/pipelines/templates/build-app-internal.yaml b/build/pipelines/templates/build-app-internal.yaml index 8aa5f675..d776c215 100644 --- a/build/pipelines/templates/build-app-internal.yaml +++ b/build/pipelines/templates/build-app-internal.yaml @@ -21,7 +21,7 @@ jobs: steps: - checkout: self clean: true - + - task: UniversalPackages@0 displayName: Download internals package inputs: @@ -29,7 +29,7 @@ jobs: downloadDirectory: $(Build.SourcesDirectory) vstsFeed: WindowsApps vstsFeedPackage: calculator-internals - vstsPackageVersion: 0.0.18 + vstsPackageVersion: 0.0.22 - template: ./build-single-architecture.yaml parameters: @@ -64,4 +64,4 @@ jobs: - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 displayName: Detect open source components inputs: - sourceScanPath: $(Agent.BuildDirectory) \ No newline at end of file + sourceScanPath: $(Agent.BuildDirectory) diff --git a/build/pipelines/templates/prepare-release-internalonly.yaml b/build/pipelines/templates/prepare-release-internalonly.yaml index 38d0f307..9c7a45ea 100644 --- a/build/pipelines/templates/prepare-release-internalonly.yaml +++ b/build/pipelines/templates/prepare-release-internalonly.yaml @@ -19,6 +19,12 @@ jobs: clean: outputs variables: skipComponentGovernanceDetection: true + SBMediaRootPath: '$(TEMP)\SBMedia' + SBPackagePath: '$(Build.ArtifactStagingDirectory)\storeBrokerPayload' + SBLogPath: '$(SBPackagePath)\StoreBroker.log' + FlightId: '161f0975-cb5f-475b-8ef6-26383c37621f' + AppId: '9WZDNCRFHVN5' + ProductId: '00009007199266248474' steps: - checkout: self clean: true @@ -91,61 +97,74 @@ jobs: downloadDirectory: $(Build.SourcesDirectory) vstsFeed: WindowsApps vstsFeedPackage: calculator-internals - vstsPackageVersion: 0.0.18 + vstsPackageVersion: 0.0.22 - - task: PkgESStoreBrokerPackage@10 - displayName: Create StoreBroker Packages - env: - XES_SERIALPOSTBUILDREADY: True + - powershell: | + # Just modify this line to indicate where your en-us PDP file is. Leave the other lines alone. + $enUSPdpFilePath = "$(Build.SourcesDirectory)\PDP\en-US\PDP.xml" + + # This is going to save the release value from the PDP file to $(SBMediaReleaseVersion) + # which you can then refer to in the UniversalPackages task. + $release = ([xml](Get-Content $enUSPdpFilePath)).ProductDescription.Release.Trim() + Write-Host "##vso[task.setvariable variable=SBMediaReleaseVersion;]$release" + displayName: Determine the PDP Media release version from the en-us PDP file + + - task: UniversalPackages@0 + displayName: Download PDP media (screenshots, trailers) universal package inputs: - addToFlight: false - configPath: tools/Build/StoreBroker/SBCalculatorConfig.json - PDPRootPath: $(Build.SourcesDirectory)\PDP - imagesRootPath: $(Build.SourcesDirectory)\PDPMediaRoot - appxPath: $(Build.ArtifactStagingDirectory)\appxBundleSigned\Microsoft.WindowsCalculator_8wekyb3d8bbwe.appxbundle - useArtifactServiceForMedia: true - outPath: $(Build.ArtifactStagingDirectory)\StoreBrokerPayload - paToken: $(System.AccessToken) - logRootPath: $(Build.ArtifactStagingDirectory)/StoreBrokerLogs + command: download + downloadDirectory: $(SBMediaRootPath)/$(SBMediaReleaseVersion) + vstsFeed: WindowsInboxApps + vstsFeedPackage: calculator-pdp-media + vstsPackageVersion: $(SBMediaReleaseVersion) + + - task: MS-RDX-MRO.windows-store-publish-dev.package-task.store-package@2 + displayName: Create StoreBroker Payload + inputs: + serviceEndpoint: StoreBrokerProxy + sbConfigPath: Tools/Build/StoreBroker/SBCalculatorConfig.json + sourceFolder: $(Build.ArtifactStagingDirectory)/appxBundleSigned + contents: Microsoft.WindowsCalculator_8wekyb3d8bbwe.appxbundle + pdpPath: '$(Build.SourcesDirectory)\PDP' + pdpInclude: PDP.xml + pdpMediaPath: '$(SBMediaRootPath)' + outSBPackagePath: '$(SBPackagePath)' + outSBName: SBCalculator - task: PublishBuildArtifacts@1 - displayName: Publish StoreBrokerPayload artifact + displayName: Publish StoreBroker Payload artifact inputs: + pathtoPublish: '$(SBPackagePath)' artifactName: storeBrokerPayload - pathToPublish: $(Build.ArtifactStagingDirectory)/StoreBrokerPayload - - task: PkgESStoreBrokerFlight@10 + - task: MS-RDX-MRO.windows-store-publish-dev.flight-task.store-flight@2 + displayName: 'Flight StoreBroker Payload to team ring' name: StoreBrokerFlight - displayName: Flight package with StoreBroker - env: - XES_SERIALPOSTBUILDREADY: True inputs: - packageToFlight: Custom - appId: 9WZDNCRFHVN5 - flightId: 161f0975-cb5f-475b-8ef6-26383c37621f - submissionDataPath: $(Build.ArtifactStagingDirectory)/StoreBrokerPayload/SBCalculator.json - packagePath: $(Build.ArtifactStagingDirectory)/StoreBrokerPayload/SBCalculator.zip - updatePackageAction: AddPackages - logRootPath: $(Build.ArtifactStagingDirectory)/StoreBrokerLogs - - - task: PublishBuildArtifacts@1 - displayName: Publish StoreBrokerLogs artifact - inputs: - artifactName: storeBrokerLogs - pathToPublish: $(Build.ArtifactStagingDirectory)/StoreBrokerLogs + serviceEndpoint: StoreBrokerProxy + appId: '$(AppId)' + flightId: '$(FlightId)' + inputMethod: JsonAndZip + jsonPath: '$(SBPackagePath)\SBCalculator.json' + zipPath: '$(SBPackagePath)\SBCalculator.zip' + force: true + skipPolling: true + targetPublishMode: Immediate + logPath: '$(SBLogPath)' - task: PkgESStoreBrokerAeroUpload@10 displayName: Upload to Aero flighting dashboard env: SYSTEM_ACCESSTOKEN: $(System.AccessToken) inputs: - productId: 00009007199266248474 - flightId: 161f0975-cb5f-475b-8ef6-26383c37621f - submissionId: $(StoreBrokerFlight.WS_SubmissionId) - submissionDataPath: $(Build.ArtifactStagingDirectory)/StoreBrokerPayload/SBCalculator.json - packagePath: $(Build.ArtifactStagingDirectory)/StoreBrokerPayload/SBCalculator.zip + ProductId: '$(ProductId)' + FlightId: '$(FlightId)' + SubmissionId: '$(StoreBrokerFlight.WS_SubmissionId)' + SubmissionDataPath: '$(SBPackagePath)\SBCalculator.json' + PackagePath: '$(SBPackagePath)\SBCalculator.zip' + AeroEnvironment: Production - task: PkgESLateTasks@10 displayName: Run PackageES LateTasks env: - XES_DISABLEPROV: true \ No newline at end of file + XES_DISABLEPROV: true diff --git a/build/pipelines/templates/run-unit-tests.yaml b/build/pipelines/templates/run-unit-tests.yaml index 2a000118..56f60969 100644 --- a/build/pipelines/templates/run-unit-tests.yaml +++ b/build/pipelines/templates/run-unit-tests.yaml @@ -1,29 +1,20 @@ -# This template contains jobs to run unit tests on the interactive test agents. +# This template contains jobs to run unit tests. parameters: platform: '' - reimageServiceConnection: '' - reimageSubscriptionId: '' - reimageResourceGroup: '' + runsettingsFileName: '' jobs: - job: UnitTests${{ parameters.platform }} displayName: UnitTests ${{ parameters.platform }} dependsOn: Build${{ parameters.platform }} + condition: succeeded() pool: - name: Essential Experiences Interactive - workspace: - clean: outputs + vmImage: windows-2019 variables: skipComponentGovernanceDetection: true steps: - checkout: none - - - powershell: Write-Host "##vso[task.setvariable variable=agentInstanceId;isOutput=true]$($env:AgentName -replace '\D+' -as [int])" - name: LogAgentStep - displayName: Log this agent's instance for later cleanup - env: - AgentName: $(Agent.Name) - task: DownloadBuildArtifacts@0 displayName: Download CalculatorUnitTests @@ -41,19 +32,4 @@ jobs: displayName: Run CalculatorUnitTests inputs: testAssemblyVer2: $(Build.ArtifactStagingDirectory)\drop\Release\${{ parameters.platform }}\CalculatorUnitTests\AppPackages\CalculatorUnitTests_Test\CalculatorUnitTests.appx - otherConsoleOptions: /Platform:${{ parameters.platform }} - -- job: CleanUpUnitTests${{ parameters.platform }} - dependsOn: UnitTests${{ parameters.platform }} - condition: and(always(), ne(dependencies.UnitTests${{ parameters.platform }}.Outputs['LogAgentStep.agentInstanceId'], '')) - pool: server - variables: - agentInstanceId: $[ dependencies.UnitTests${{ parameters.platform }}.outputs['LogAgentStep.agentInstanceId'] ] - steps: - - task: InvokeRESTAPI@1 - displayName: Reimage test machine - inputs: - connectionType: connectedServiceNameARM - azureServiceConnection: ${{ parameters.reimageServiceConnection }} - urlSuffix: subscriptions/${{ parameters.reimageSubscriptionId }}/resourceGroups/${{ parameters.reimageResourceGroup }}/providers/Microsoft.Compute/virtualMachineScaleSets/essential/reimage?api-version=2018-10-01 - body: '{ "instanceIds": ["$(agentInstanceId)"] }' \ No newline at end of file + otherConsoleOptions: /Platform:${{ parameters.platform }} \ No newline at end of file diff --git a/src/CalcManager/CEngine/CalcInput.cpp b/src/CalcManager/CEngine/CalcInput.cpp index 600f9002..fb963079 100644 --- a/src/CalcManager/CEngine/CalcInput.cpp +++ b/src/CalcManager/CEngine/CalcInput.cpp @@ -179,7 +179,7 @@ bool CalcInput::TryAddDecimalPt() if (m_base.IsEmpty()) { - m_base.value += L"0"; // Add a leading zero + m_base.value += L'0'; // Add a leading zero } m_decPtIndex = m_base.value.size(); @@ -261,6 +261,11 @@ void CalcInput::SetDecimalSymbol(wchar_t decSymbol) } } +bool CalcInput::IsEmpty() +{ + return m_base.IsEmpty() && !m_hasExponent && m_exponent.IsEmpty() && !m_hasDecimal; +} + wstring CalcInput::ToString(uint32_t radix) { // In theory both the base and exponent could be C_NUM_MAX_DIGITS long. diff --git a/src/CalcManager/CEngine/CalcUtils.cpp b/src/CalcManager/CEngine/CalcUtils.cpp index 57510dcc..8807627f 100644 --- a/src/CalcManager/CEngine/CalcUtils.cpp +++ b/src/CalcManager/CEngine/CalcUtils.cpp @@ -11,14 +11,14 @@ bool IsOpInRange(OpCode op, uint32_t x, uint32_t y) bool IsBinOpCode(OpCode opCode) { - return IsOpInRange(opCode, IDC_AND, IDC_PWR); + return IsOpInRange(opCode, IDC_AND, IDC_PWR) || IsOpInRange(opCode, IDC_BINARYEXTENDEDFIRST, IDC_BINARYEXTENDEDLAST); } // WARNING: IDC_SIGN is a special unary op but still this doesn't catch this. Caller has to be aware // of it and catch it themselves or not needing this bool IsUnaryOpCode(OpCode opCode) { - return IsOpInRange(opCode, IDC_UNARYFIRST, IDC_UNARYLAST); + return (IsOpInRange(opCode, IDC_UNARYFIRST, IDC_UNARYLAST) || IsOpInRange(opCode, IDC_UNARYEXTENDEDFIRST, IDC_UNARYEXTENDEDLAST)); } bool IsDigitOpCode(OpCode opCode) diff --git a/src/CalcManager/CEngine/History.cpp b/src/CalcManager/CEngine/History.cpp index 37add769..d3a32ebb 100644 --- a/src/CalcManager/CEngine/History.cpp +++ b/src/CalcManager/CEngine/History.cpp @@ -3,7 +3,6 @@ #include "Header Files/CalcEngine.h" #include "Command.h" -#include "CalculatorVector.h" #include "ExpressionCommand.h" constexpr int ASCII_0 = 48; @@ -13,14 +12,19 @@ using namespace CalcEngine; namespace { - void IFT(ResultCode hr) + template + static void Truncate(vector& v, unsigned int index) { - if (FAILED(hr)) + if (index >= v.size()) { - throw hr; + throw E_BOUNDS; } + + auto startIter = v.begin() + index; + v.erase(startIter, v.end()); } } + void CHistoryCollector::ReinitHistory() { m_lastOpStartIndex = -1; @@ -29,11 +33,11 @@ void CHistoryCollector::ReinitHistory() m_bLastOpndBrace = false; if (m_spTokens != nullptr) { - m_spTokens->Clear(); + m_spTokens->clear(); } if (m_spCommands != nullptr) { - m_spCommands->Clear(); + m_spCommands->clear(); } } @@ -55,13 +59,13 @@ CHistoryCollector::~CHistoryCollector() if (m_spTokens != nullptr) { - m_spTokens->Clear(); + m_spTokens->clear(); } } void CHistoryCollector::AddOpndToHistory(wstring_view numStr, Rational const& rat, bool fRepetition) { - std::shared_ptr> commands = std::make_shared>(); + std::shared_ptr> commands = std::make_shared>(); // Check for negate bool fNegative = (numStr[0] == L'-'); bool fSciFmt = false; @@ -71,7 +75,7 @@ void CHistoryCollector::AddOpndToHistory(wstring_view numStr, Rational const& ra { if (numStr[i] == m_decimalSymbol) { - IFT(commands->Append(IDC_PNT)); + commands->push_back(IDC_PNT); if (!fSciFmt) { fDecimal = true; @@ -79,12 +83,12 @@ void CHistoryCollector::AddOpndToHistory(wstring_view numStr, Rational const& ra } else if (numStr[i] == L'e') { - IFT(commands->Append(IDC_EXP)); + commands->push_back(IDC_EXP); fSciFmt = true; } else if (numStr[i] == L'-') { - IFT(commands->Append(IDC_SIGN)); + commands->push_back(IDC_SIGN); } else if (numStr[i] == L'+') { @@ -95,7 +99,7 @@ void CHistoryCollector::AddOpndToHistory(wstring_view numStr, Rational const& ra { int num = static_cast(numStr[i]) - ASCII_0; num += IDC_0; - IFT(commands->Append(num)); + commands->push_back(num); } } @@ -120,12 +124,12 @@ void CHistoryCollector::RemoveLastOpndFromHistory() // This will not restore the m_lastBinOpStartIndex, as it isn't possible to remove that also later } -void CHistoryCollector::AddBinOpToHistory(int nOpCode, bool fNoRepetition) +void CHistoryCollector::AddBinOpToHistory(int nOpCode, bool isIntegerMode, bool fNoRepetition) { int iCommandEnd = AddCommand(std::make_shared(nOpCode)); m_lastBinOpStartIndex = IchAddSzToEquationSz(L" ", -1); - IchAddSzToEquationSz(CCalcEngine::OpCodeToString(nOpCode), iCommandEnd); + IchAddSzToEquationSz(CCalcEngine::OpCodeToBinaryString(nOpCode, isIntegerMode), iCommandEnd); IchAddSzToEquationSz(L" ", -1); if (fNoRepetition) @@ -138,14 +142,14 @@ void CHistoryCollector::AddBinOpToHistory(int nOpCode, bool fNoRepetition) // This is expected to be called when a binary op in the last say 1+2+ is changing to another one say 1+2* (+ changed to *) // It needs to know by this change a Precedence inversion happened. i.e. previous op was lower or equal to its previous op, but the new // one isn't. (Eg. 1*2* to 1*2^). It can add explicit brackets to ensure the precedence is inverted. (Eg. (1*2) ^) -void CHistoryCollector::ChangeLastBinOp(int nOpCode, bool fPrecInvToHigher) +void CHistoryCollector::ChangeLastBinOp(int nOpCode, bool fPrecInvToHigher, bool isIntgerMode) { TruncateEquationSzFromIch(m_lastBinOpStartIndex); if (fPrecInvToHigher) { EnclosePrecInversionBrackets(); } - AddBinOpToHistory(nOpCode); + AddBinOpToHistory(nOpCode, isIntgerMode); } void CHistoryCollector::PushLastOpndStart(int ichOpndStart) @@ -266,6 +270,30 @@ void CHistoryCollector::AddUnaryOpToHistory(int nOpCode, bool fInv, ANGLE_TYPE a command = fInv ? static_cast(CalculationManager::Command::CommandATANH) : IDC_TANH; spExpressionCommand = std::make_shared(command); break; + case IDC_SEC: + command = fInv ? static_cast(CalculationManager::Command::CommandASEC) : IDC_SEC; + spExpressionCommand = std::make_shared(static_cast(angleOpCode), command); + break; + case IDC_CSC: + command = fInv ? static_cast(CalculationManager::Command::CommandACSC) : IDC_CSC; + spExpressionCommand = std::make_shared(static_cast(angleOpCode), command); + break; + case IDC_COT: + command = fInv ? static_cast(CalculationManager::Command::CommandACOT) : IDC_COT; + spExpressionCommand = std::make_shared(static_cast(angleOpCode), command); + break; + case IDC_SECH: + command = fInv ? static_cast(CalculationManager::Command::CommandASECH) : IDC_SECH; + spExpressionCommand = std::make_shared(command); + break; + case IDC_CSCH: + command = fInv ? static_cast(CalculationManager::Command::CommandACSCH) : IDC_CSCH; + spExpressionCommand = std::make_shared(command); + break; + case IDC_COTH: + command = fInv ? static_cast(CalculationManager::Command::CommandACOTH) : IDC_COTH; + spExpressionCommand = std::make_shared(command); + break; case IDC_LN: command = fInv ? static_cast(CalculationManager::Command::CommandPOWE) : IDC_LN; spExpressionCommand = std::make_shared(command); @@ -301,12 +329,6 @@ void CHistoryCollector::AddUnaryOpToHistory(int nOpCode, bool fInv, ANGLE_TYPE a // history of equations void CHistoryCollector::CompleteHistoryLine(wstring_view numStr) { - if (nullptr != m_pCalcDisplay) - { - m_pCalcDisplay->SetExpressionDisplay( - std::make_shared>>(), std::make_shared>>()); - } - if (nullptr != m_pHistoryDisplay) { unsigned int addedItemIndex = m_pHistoryDisplay->AddToHistory(m_spTokens, m_spCommands, numStr); @@ -319,6 +341,16 @@ void CHistoryCollector::CompleteHistoryLine(wstring_view numStr) ReinitHistory(); } +void CHistoryCollector::CompleteEquation(std::wstring_view numStr) +{ + // Add only '=' token and not add EQU command, because + // EQU command breaks loading from history (it duplicate history entries). + IchAddSzToEquationSz(CCalcEngine::OpCodeToString(IDC_EQU), -1); + + SetExpressionDisplay(); + CompleteHistoryLine(numStr); +} + void CHistoryCollector::ClearHistoryLine(wstring_view errStr) { if (errStr.empty()) // in case of error let the display stay as it is @@ -326,7 +358,7 @@ void CHistoryCollector::ClearHistoryLine(wstring_view errStr) if (nullptr != m_pCalcDisplay) { m_pCalcDisplay->SetExpressionDisplay( - std::make_shared>>(), std::make_shared>>()); + std::make_shared>>(), std::make_shared>>()); } m_iCurLineHistStart = -1; // It will get recomputed at the first Opnd ReinitHistory(); @@ -339,26 +371,17 @@ int CHistoryCollector::IchAddSzToEquationSz(wstring_view str, int icommandIndex) { if (m_spTokens == nullptr) { - m_spTokens = std::make_shared>>(); + m_spTokens = std::make_shared>>(); } - if (FAILED(m_spTokens->Append(std::make_pair(wstring(str), icommandIndex)))) - { - throw(CALC_E_OUTOFMEMORY); - } - - unsigned int nTokens; - m_spTokens->GetSize(&nTokens); - return nTokens - 1; + m_spTokens->push_back(std::pair(wstring(str), icommandIndex)); + return static_cast(m_spTokens->size() - 1); } // Inserts a given string into the global m_pszEquation at the given index ich taking care of reallocations etc. void CHistoryCollector::InsertSzInEquationSz(wstring_view str, int icommandIndex, int ich) { - if (FAILED(m_spTokens->InsertAt(ich, std::make_pair(wstring(str), icommandIndex)))) - { - throw(CALC_E_OUTOFMEMORY); - } + m_spTokens->emplace(m_spTokens->begin() + ich, wstring(str), icommandIndex); } // Chops off the current equation string from the given index @@ -366,25 +389,23 @@ void CHistoryCollector::TruncateEquationSzFromIch(int ich) { // Truncate commands int minIdx = -1; - unsigned int nTokens = 0; - std::pair currentPair; - m_spTokens->GetSize(&nTokens); + unsigned int nTokens = static_cast(m_spTokens->size()); for (unsigned int i = ich; i < nTokens; i++) { - IFT(m_spTokens->GetAt(i, ¤tPair)); + const auto& currentPair = (*m_spTokens)[i]; int curTokenId = currentPair.second; if (curTokenId != -1) { if ((minIdx != -1) || (curTokenId < minIdx)) { minIdx = curTokenId; - IFT(m_spCommands->Truncate(minIdx)); + Truncate(*m_spCommands, minIdx); } } } - IFT(m_spTokens->Truncate(ich)); + Truncate(*m_spTokens, ich); } // Adds the m_pszEquation into the running history text @@ -400,17 +421,11 @@ int CHistoryCollector::AddCommand(_In_ const std::shared_ptr { if (m_spCommands == nullptr) { - m_spCommands = std::make_shared>>(); + m_spCommands = std::make_shared>>(); } - if (FAILED(m_spCommands->Append(spCommand))) - { - throw(CALC_E_OUTOFMEMORY); - } - - unsigned int nCommands = 0; - m_spCommands->GetSize(&nCommands); - return nCommands - 1; + m_spCommands->push_back(spCommand); + return static_cast(m_spCommands->size() - 1); } // To Update the operands in the Expression according to the current Radix @@ -421,30 +436,25 @@ void CHistoryCollector::UpdateHistoryExpression(uint32_t radix, int32_t precisio return; } - unsigned int size; - IFT(m_spTokens->GetSize(&size)); - - for (unsigned int i = 0; i < size; ++i) + for (auto& token : *m_spTokens) { - std::pair token; - IFT(m_spTokens->GetAt(i, &token)); int commandPosition = token.second; if (commandPosition != -1) { - std::shared_ptr expCommand; - IFT(m_spCommands->GetAt(commandPosition, &expCommand)); + const std::shared_ptr& expCommand = m_spCommands->at(commandPosition); + if (expCommand != nullptr && CalculationManager::CommandType::OperandCommand == expCommand->GetCommandType()) { - std::shared_ptr opndCommand = std::static_pointer_cast(expCommand); + const std::shared_ptr& opndCommand = std::static_pointer_cast(expCommand); if (opndCommand != nullptr) { token.first = opndCommand->GetString(radix, precision); - IFT(m_spTokens->SetAt(i, token)); opndCommand->SetCommands(GetOperandCommandsFromString(token.first)); } } } } + SetExpressionDisplay(); } @@ -454,9 +464,9 @@ void CHistoryCollector::SetDecimalSymbol(wchar_t decimalSymbol) } // Update the commands corresponding to the passed string Number -std::shared_ptr> CHistoryCollector::GetOperandCommandsFromString(wstring_view numStr) +std::shared_ptr> CHistoryCollector::GetOperandCommandsFromString(wstring_view numStr) { - std::shared_ptr> commands = std::make_shared>(); + std::shared_ptr> commands = std::make_shared>(); // Check for negate bool fNegative = (numStr[0] == L'-'); @@ -464,15 +474,15 @@ std::shared_ptr> CHistoryCollector::GetOperandCommandsFrom { if (numStr[i] == m_decimalSymbol) { - IFT(commands->Append(IDC_PNT)); + commands->push_back(IDC_PNT); } else if (numStr[i] == L'e') { - IFT(commands->Append(IDC_EXP)); + commands->push_back(IDC_EXP); } else if (numStr[i] == L'-') { - IFT(commands->Append(IDC_SIGN)); + commands->push_back(IDC_SIGN); } else if (numStr[i] == L'+') { @@ -483,14 +493,14 @@ std::shared_ptr> CHistoryCollector::GetOperandCommandsFrom { int num = static_cast(numStr[i]) - ASCII_0; num += IDC_0; - IFT(commands->Append(num)); + commands->push_back(num); } } // If the number is negative, append a sign command at the end. if (fNegative) { - IFT(commands->Append(IDC_SIGN)); + commands->push_back(IDC_SIGN); } return commands; } diff --git a/src/CalcManager/CEngine/calc.cpp b/src/CalcManager/CEngine/calc.cpp index c71d2927..c5775379 100644 --- a/src/CalcManager/CEngine/calc.cpp +++ b/src/CalcManager/CEngine/calc.cpp @@ -24,17 +24,16 @@ static constexpr wstring_view DEFAULT_NUMBER_STR = L"0"; // Read strings for keys, errors, trig types, etc. // These will be copied from the resources to local memory. -unordered_map CCalcEngine::s_engineStrings; +unordered_map CCalcEngine::s_engineStrings; void CCalcEngine::LoadEngineStrings(CalculationManager::IResourceProvider& resourceProvider) { for (const auto& sid : g_sids) { - auto locKey = wstring{ sid }; - auto locString = resourceProvider.GetCEngineString(locKey); + auto locString = resourceProvider.GetCEngineString(sid); if (!locString.empty()) { - s_engineStrings[locKey] = locString; + s_engineStrings[sid] = locString; } } } diff --git a/src/CalcManager/CEngine/scicomm.cpp b/src/CalcManager/CEngine/scicomm.cpp index 4752ec95..f7509ab3 100644 --- a/src/CalcManager/CEngine/scicomm.cpp +++ b/src/CalcManager/CEngine/scicomm.cpp @@ -16,6 +16,7 @@ #include #include "Header Files/CalcEngine.h" #include "Header Files/CalcUtils.h" +#include "NumberFormattingUtils.h" using namespace std; using namespace CalcEngine; @@ -28,8 +29,13 @@ namespace // 0 is returned. Higher the number, higher the precedence of the operator. int NPrecedenceOfOp(int nopCode) { - static uint8_t rgbPrec[] = { 0, 0, IDC_OR, 0, IDC_XOR, 0, IDC_AND, 1, IDC_ADD, 2, IDC_SUB, 2, IDC_RSHF, - 3, IDC_LSHF, 3, IDC_MOD, 3, IDC_DIV, 3, IDC_MUL, 3, IDC_PWR, 4, IDC_ROOT, 4 }; + static uint16_t rgbPrec[] = { + 0,0, IDC_OR,0, IDC_XOR,0, + IDC_AND,1, IDC_NAND,1, IDC_NOR,1, + IDC_ADD,2, IDC_SUB,2, + IDC_RSHF,3, IDC_LSHF,3, IDC_RSHFL,3, + IDC_MOD,3, IDC_DIV,3, IDC_MUL,3, + IDC_PWR,4, IDC_ROOT,4, IDC_LOGBASEX,4 }; unsigned int iPrec; iPrec = 0; @@ -76,6 +82,15 @@ void CCalcEngine::ClearTemporaryValues() m_bError = false; } +void CCalcEngine::ClearDisplay() +{ + if (nullptr != m_pCalcDisplay) + { + m_pCalcDisplay->SetExpressionDisplay( + make_shared>>(), make_shared>>()); + } +} + void CCalcEngine::ProcessCommand(OpCode wParam) { if (wParam == IDC_SET_RESULT) @@ -103,6 +118,12 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam) m_nTempCom = (int)wParam; } + // Clear expression shown after = sign, when user do any action. + if (!m_bNoPrevEqu) + { + ClearDisplay(); + } + if (m_bError) { if (wParam == IDC_CLEAR) @@ -124,9 +145,18 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam) // Toggle Record/Display mode if appropriate. if (m_bRecord) { - if (IsOpInRange(wParam, IDC_AND, IDC_MMINUS) || IsOpInRange(wParam, IDC_OPENP, IDC_CLOSEP) || IsOpInRange(wParam, IDM_HEX, IDM_BIN) - || IsOpInRange(wParam, IDM_QWORD, IDM_BYTE) || IsOpInRange(wParam, IDM_DEG, IDM_GRAD) - || IsOpInRange(wParam, IDC_BINEDITSTART, IDC_BINEDITSTART + 63) || (IDC_INV == wParam) || (IDC_SIGN == wParam && 10 != m_radix)) + if (IsBinOpCode(wParam) || + IsUnaryOpCode(wParam) || + IsOpInRange(wParam, IDC_FE, IDC_MMINUS) || + IsOpInRange(wParam, IDC_OPENP, IDC_CLOSEP) || + IsOpInRange(wParam, IDM_HEX, IDM_BIN) || + IsOpInRange(wParam, IDM_QWORD, IDM_BYTE) || + IsOpInRange(wParam, IDM_DEG, IDM_GRAD) || + IsOpInRange(wParam, IDC_BINEDITSTART, IDC_BINEDITEND) || + (IDC_INV == wParam) || + (IDC_SIGN == wParam && 10 != m_radix) || + (IDC_RAND == wParam) || + (IDC_EULER == wParam)) { m_bRecord = false; m_currentVal = m_input.ToRational(m_radix, m_precision); @@ -193,7 +223,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam) m_nPrevOpCode = 0; // Once the precedence inversion has put additional brackets, its no longer required } } - m_HistoryCollector.ChangeLastBinOp(m_nOpCode, fPrecInvToHigher); + m_HistoryCollector.ChangeLastBinOp(m_nOpCode, fPrecInvToHigher, m_fIntegerMode); DisplayAnnounceBinaryOperator(); return; } @@ -270,10 +300,9 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam) } DisplayAnnounceBinaryOperator(); - m_lastVal = m_currentVal; m_nOpCode = (int)wParam; - m_HistoryCollector.AddBinOpToHistory(m_nOpCode); + m_HistoryCollector.AddBinOpToHistory(m_nOpCode, m_fIntegerMode); m_bNoPrevEqu = m_bChangeOp = true; return; } @@ -303,7 +332,8 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam) m_HistoryCollector.AddUnaryOpToHistory((int)wParam, m_bInv, m_angletype); } - if ((wParam == IDC_SIN) || (wParam == IDC_COS) || (wParam == IDC_TAN) || (wParam == IDC_SINH) || (wParam == IDC_COSH) || (wParam == IDC_TANH)) + if ((wParam == IDC_SIN) || (wParam == IDC_COS) || (wParam == IDC_TAN) || (wParam == IDC_SINH) || (wParam == IDC_COSH) || (wParam == IDC_TANH) + || (wParam == IDC_SEC) || (wParam == IDC_CSC) || (wParam == IDC_COT) || (wParam == IDC_SECH) || (wParam == IDC_CSCH) || (wParam == IDC_COTH)) { if (IsCurrentTooBigForTrig()) { @@ -330,9 +360,13 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam) /* reset the m_bInv flag and indicators if it is set and have been used */ - if (m_bInv - && ((wParam == IDC_CHOP) || (wParam == IDC_SIN) || (wParam == IDC_COS) || (wParam == IDC_TAN) || (wParam == IDC_LN) || (wParam == IDC_DMS) - || (wParam == IDC_DEGREES) || (wParam == IDC_SINH) || (wParam == IDC_COSH) || (wParam == IDC_TANH))) + if (m_bInv && + ((wParam == IDC_CHOP) || (wParam == IDC_SIN) || (wParam == IDC_COS) || + (wParam == IDC_TAN) || (wParam == IDC_LN) || (wParam == IDC_DMS) || + (wParam == IDC_DEGREES) || (wParam == IDC_SINH) || (wParam == IDC_COSH) || + (wParam == IDC_TANH) || (wParam == IDC_SEC) || (wParam == IDC_CSC) || + (wParam == IDC_COT) || (wParam == IDC_SECH) || (wParam == IDC_CSCH) || + (wParam == IDC_COTH))) { m_bInv = false; } @@ -341,10 +375,10 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam) } // Tiny binary edit windows clicked. Toggle that bit and update display - if (IsOpInRange(wParam, IDC_BINEDITSTART, IDC_BINEDITSTART + 63)) + if (IsOpInRange(wParam, IDC_BINEDITSTART, IDC_BINEDITEND)) { // Same reasoning as for unary operators. We need to seed it previous number - if (m_nLastCom >= IDC_AND && m_nLastCom <= IDC_PWR) + if (IsBinOpCode(m_nLastCom)) { m_currentVal = m_lastVal; } @@ -377,14 +411,14 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam) m_precedenceOpCount = m_nTempCom = m_nLastCom = m_nOpCode = 0; m_nPrevOpCode = 0; m_bNoPrevEqu = true; + m_carryBit = 0; /* clear the parenthesis status box indicator, this will not be cleared for CENTR */ if (nullptr != m_pCalcDisplay) { m_pCalcDisplay->SetParenthesisNumber(0); - m_pCalcDisplay->SetExpressionDisplay( - make_shared>>(), make_shared>>()); + ClearDisplay(); } m_HistoryCollector.ClearHistoryLine(wstring()); @@ -474,12 +508,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam) if (!m_bError) { wstring groupedString = GroupDigitsPerRadix(m_numberString, m_radix); - m_HistoryCollector.CompleteHistoryLine(groupedString); - if (nullptr != m_pCalcDisplay) - { - m_pCalcDisplay->SetExpressionDisplay( - make_shared>>(), make_shared>>()); - } + m_HistoryCollector.CompleteEquation(groupedString); } m_bChangeOp = false; @@ -700,7 +729,6 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam) case IDC_MCLEAR: m_memoryValue = make_unique(wParam == IDC_STORE ? TruncateNumForIntMath(m_currentVal) : 0); break; - case IDC_PI: if (!m_fIntegerMode) { @@ -713,7 +741,43 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam) } HandleErrorCommand(wParam); break; + case IDC_RAND: + if (!m_fIntegerMode) + { + CheckAndAddLastBinOpToHistory(); // rand is like entering the number + wstringstream str; + str << fixed << setprecision(m_precision) << GenerateRandomNumber(); + + auto rat = StringToRat(false, str.str(), false, L"", m_radix, m_precision); + if (rat != nullptr) + { + m_currentVal = Rational{ rat }; + } + else + { + m_currentVal = Rational{ 0 }; + } + destroyrat(rat); + + DisplayNum(); + m_bInv = false; + break; + } + HandleErrorCommand(wParam); + break; + case IDC_EULER: + if (!m_fIntegerMode) + { + CheckAndAddLastBinOpToHistory(); // e is like entering the number + m_currentVal = Rational{ rat_exp }; + + DisplayNum(); + m_bInv = false; + break; + } + HandleErrorCommand(wParam); + break; case IDC_FE: // Toggle exponential notation display. m_nFE = NUMOBJ_FMT(!(int)m_nFE); @@ -761,7 +825,7 @@ void CCalcEngine::ResolveHighestPrecedenceOperation() { m_currentVal = m_holdVal; DisplayNum(); // to update the m_numberString - m_HistoryCollector.AddBinOpToHistory(m_nOpCode, false); + m_HistoryCollector.AddBinOpToHistory(m_nOpCode, m_fIntegerMode, false); m_HistoryCollector.AddOpndToHistory(m_numberString, m_currentVal); // Adding the repeated last op to history } @@ -863,11 +927,14 @@ struct FunctionNameElement wstring gradString; wstring inverseGradString; // Will fall back to gradString if empty + wstring programmerModeString; + bool hasAngleStrings = ((!radString.empty()) || (!inverseRadString.empty()) || (!gradString.empty()) || (!inverseGradString.empty())); }; // Table for each unary operator -static const std::unordered_map unaryOperatorStringTable = { +static const std::unordered_map operatorStringTable = +{ { IDC_CHOP, { L"", SIDS_FRAC } }, { IDC_SIN, { SIDS_SIND, SIDS_ASIND, SIDS_SINR, SIDS_ASINR, SIDS_SING, SIDS_ASING } }, @@ -878,6 +945,14 @@ static const std::unordered_map unaryOperatorStringTab { IDC_COSH, { L"", SIDS_ACOSH } }, { IDC_TANH, { L"", SIDS_ATANH } }, + { IDC_SEC, { SIDS_SECD, SIDS_ASECD, SIDS_SECR, SIDS_ASECR, SIDS_SECG, SIDS_ASECG } }, + { IDC_CSC, { SIDS_CSCD, SIDS_ACSCD, SIDS_CSCR, SIDS_ACSCR, SIDS_CSCG, SIDS_ACSCG } }, + { IDC_COT, { SIDS_COTD, SIDS_ACOTD, SIDS_COTR, SIDS_ACOTR, SIDS_COTG, SIDS_ACOTG } }, + + { IDC_SECH, { SIDS_SECH, SIDS_ASECH } }, + { IDC_CSCH, { SIDS_CSCH, SIDS_ACSCH } }, + { IDC_COTH, { SIDS_COTH, SIDS_ACOTH } }, + { IDC_LN, { L"", SIDS_POWE } }, { IDC_SQR, { SIDS_SQR } }, { IDC_CUB, { SIDS_CUBE } }, @@ -885,7 +960,19 @@ static const std::unordered_map unaryOperatorStringTab { IDC_REC, { SIDS_RECIPROC } }, { IDC_DMS, { L"", SIDS_DEGREES } }, { IDC_SIGN, { SIDS_NEGATE } }, - { IDC_DEGREES, { SIDS_DEGREES } } + { IDC_DEGREES, { SIDS_DEGREES } }, + { IDC_POW2, { SIDS_TWOPOWX } }, + { IDC_LOGBASEX, { SIDS_LOGBASEX } }, + { IDC_ABS, { SIDS_ABS } }, + { IDC_CEIL, { SIDS_CEIL } }, + { IDC_FLOOR, { SIDS_FLOOR } }, + { IDC_NAND, { SIDS_NAND } }, + { IDC_NOR, { SIDS_NOR } }, + { IDC_RSHFL, { SIDS_RSH } }, + { IDC_RORC, { SIDS_ROR } }, + { IDC_ROLC, { SIDS_ROL } }, + { IDC_CUBEROOT, {SIDS_CUBEROOT} }, + { IDC_MOD, {SIDS_MOD, L"", L"", L"", L"", L"", SIDS_PROGRAMMER_MOD} }, }; wstring_view CCalcEngine::OpCodeToUnaryString(int nOpCode, bool fInv, ANGLE_TYPE angletype) @@ -893,7 +980,7 @@ wstring_view CCalcEngine::OpCodeToUnaryString(int nOpCode, bool fInv, ANGLE_TYPE // Try to lookup the ID in the UFNE table wstring ids = L""; - if (auto pair = unaryOperatorStringTable.find(nOpCode); pair != unaryOperatorStringTable.end()) + if (auto pair = operatorStringTable.find(nOpCode); pair != operatorStringTable.end()) { const FunctionNameElement& element = pair->second; if (!element.hasAngleStrings || ANGLE_DEG == angletype) @@ -941,6 +1028,32 @@ wstring_view CCalcEngine::OpCodeToUnaryString(int nOpCode, bool fInv, ANGLE_TYPE return OpCodeToString(nOpCode); } +wstring_view CCalcEngine::OpCodeToBinaryString(int nOpCode, bool isIntegerMode) +{ + // Try to lookup the ID in the UFNE table + wstring ids = L""; + + if (auto pair = operatorStringTable.find(nOpCode); pair != operatorStringTable.end()) + { + if (isIntegerMode && !pair->second.programmerModeString.empty()) + { + ids = pair->second.programmerModeString; + } + else + { + ids = pair->second.degreeString; + } + } + + if (!ids.empty()) + { + return GetString(ids); + } + + // If we didn't find an ID in the table, use the op code. + return OpCodeToString(nOpCode); +} + bool CCalcEngine::IsCurrentTooBigForTrig() { return m_currentVal >= m_maxTrigonometricNum; @@ -1007,3 +1120,14 @@ wstring CCalcEngine::GetStringForDisplay(Rational const& rat, uint32_t radix) return result; } + +double CCalcEngine::GenerateRandomNumber() +{ + if (m_randomGeneratorEngine == nullptr) + { + random_device rd; + m_randomGeneratorEngine = std::make_unique(rd()); + m_distr = std::make_unique>(0, 1); + } + return (*m_distr.get())(*m_randomGeneratorEngine.get()); +} diff --git a/src/CalcManager/CEngine/scifunc.cpp b/src/CalcManager/CEngine/scifunc.cpp index 5684ce43..15ef164b 100644 --- a/src/CalcManager/CEngine/scifunc.cpp +++ b/src/CalcManager/CEngine/scifunc.cpp @@ -46,8 +46,8 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r } break; - // Rotate Left with hi bit wrapped over to lo bit case IDC_ROL: + case IDC_ROLC: if (m_fIntegerMode) { result = Integer(rat); @@ -55,14 +55,23 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r uint64_t w64Bits = result.ToUInt64_t(); uint64_t msb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1; w64Bits <<= 1; // LShift by 1 - w64Bits |= msb; // Set the prev Msb as the current Lsb + + if (op == IDC_ROL) + { + w64Bits |= msb; // Set the prev Msb as the current Lsb + } + else + { + w64Bits |= m_carryBit; // Set the carry bit as the LSB + m_carryBit = msb; // Store the msb as the next carry bit + } result = w64Bits; } break; - // Rotate right with lo bit wrapped over to hi bit case IDC_ROR: + case IDC_RORC: if (m_fIntegerMode) { result = Integer(rat); @@ -70,7 +79,16 @@ 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 |= (lsb << (m_dwWordBitWidth - 1)); + + if (op == IDC_ROR) + { + w64Bits |= (lsb << (m_dwWordBitWidth - 1)); + } + else + { + w64Bits |= (m_carryBit << (m_dwWordBitWidth - 1)); + m_carryBit = lsb; + } result = w64Bits; } @@ -133,6 +151,48 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r } break; + case IDC_SEC: + if (!m_fIntegerMode) + { + result = m_bInv ? ACos(Invert(rat), m_angletype) : Invert(Cos(rat, m_angletype)); + } + break; + + case IDC_CSC: + if (!m_fIntegerMode) + { + result = m_bInv ? ASin(Invert(rat), m_angletype) : Invert(Sin(rat, m_angletype)); + } + break; + + case IDC_COT: + if (!m_fIntegerMode) + { + result = m_bInv ? ATan(Invert(rat), m_angletype) : Invert(Tan(rat, m_angletype)); + } + break; + + case IDC_SECH: + if (!m_fIntegerMode) + { + result = m_bInv ? ACosh(Invert(rat)) : Invert(Cosh(rat)); + } + break; + + case IDC_CSCH: + if (!m_fIntegerMode) + { + result = m_bInv ? ASinh(Invert(rat)) : Invert(Sinh(rat)); + } + break; + + case IDC_COTH: + if (!m_fIntegerMode) + { + result = m_bInv ? ATanh(Invert(rat)) : Invert(Tanh(rat)); + } + break; + case IDC_REC: /* Reciprocal. */ result = Invert(rat); break; @@ -158,6 +218,10 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r result = Pow(10, rat); break; + case IDC_POW2: + result = Pow(2, rat); + break; + case IDC_LN: /* Functions for natural log. */ result = m_bInv ? Exp(rat) : Log(rat); break; @@ -202,6 +266,18 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r } break; } + case IDC_CEIL: + result = (Frac(rat) > 0) ? Integer(rat + 1) : Integer(rat); + break; + + case IDC_FLOOR: + result = (Frac(rat) < 0) ? Integer(rat - 1 ) : Integer(rat); + break; + + case IDC_ABS: + result = Abs(rat); + break; + } // end switch( op ) } catch (uint32_t nErrCode) diff --git a/src/CalcManager/CEngine/scioper.cpp b/src/CalcManager/CEngine/scioper.cpp index e41aee21..6ea3956b 100644 --- a/src/CalcManager/CEngine/scioper.cpp +++ b/src/CalcManager/CEngine/scioper.cpp @@ -28,6 +28,14 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa result ^= rhs; break; + case IDC_NAND: + result = (result & rhs) ^ m_chopNumbers[m_numwidth]; + break; + + case IDC_NOR: + result = (result | rhs) ^ m_chopNumbers[m_numwidth]; + break; + case IDC_RSHF: { if (m_fIntegerMode && result >= m_dwWordBitWidth) // Lsh/Rsh >= than current word size is always 0 @@ -52,7 +60,16 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa } break; } + case IDC_RSHFL: + { + if (m_fIntegerMode && result >= m_dwWordBitWidth) // Lsh/Rsh >= than current word size is always 0 + { + throw CALC_E_NORESULT; + } + result = rhs >> result; + break; + } case IDC_LSHF: if (m_fIntegerMode && result >= m_dwWordBitWidth) // Lsh/Rsh >= than current word size is always 0 { @@ -140,6 +157,10 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa case IDC_ROOT: // Calculates rhs to the result(th) root. result = Root(rhs, result); break; + + case IDC_LOGBASEX: + result = (Log(result) / Log(rhs)); + break; } } catch (uint32_t dwErrCode) diff --git a/src/CalcManager/CalcManager.vcxproj b/src/CalcManager/CalcManager.vcxproj index a0ee84ed..487df839 100644 --- a/src/CalcManager/CalcManager.vcxproj +++ b/src/CalcManager/CalcManager.vcxproj @@ -78,24 +78,32 @@ false true v142 + NativeRecommendedRules.ruleset + true StaticLibrary false true v142 + NativeRecommendedRules.ruleset + true StaticLibrary false true v142 + NativeRecommendedRules.ruleset + true StaticLibrary false true v142 + NativeRecommendedRules.ruleset + true @@ -175,6 +183,7 @@ Level4 true pch.h + true Console @@ -209,6 +218,7 @@ Level4 true pch.h + true Console @@ -244,6 +254,7 @@ Level4 true pch.h + true Console @@ -278,6 +289,7 @@ Level4 true pch.h + true Console @@ -289,7 +301,6 @@ - diff --git a/src/CalcManager/CalcManager.vcxproj.filters b/src/CalcManager/CalcManager.vcxproj.filters index 53098917..ad7670a0 100644 --- a/src/CalcManager/CalcManager.vcxproj.filters +++ b/src/CalcManager/CalcManager.vcxproj.filters @@ -120,7 +120,6 @@ RatPack - Header Files diff --git a/src/CalcManager/CalculatorHistory.cpp b/src/CalcManager/CalculatorHistory.cpp index 14a94a8c..6c9a002b 100644 --- a/src/CalcManager/CalculatorHistory.cpp +++ b/src/CalcManager/CalculatorHistory.cpp @@ -7,25 +7,48 @@ using namespace std; using namespace CalculationManager; +namespace +{ + static wstring GetGeneratedExpression(const vector>& tokens) + { + wstring expression; + bool isFirst = true; + + for (auto const& token : tokens) + { + if (isFirst) + { + isFirst = false; + } + else + { + expression += L' '; + } + expression.append(token.first); + } + + return expression; + } +} + CalculatorHistory::CalculatorHistory(size_t maxSize) : m_maxHistorySize(maxSize) { } unsigned int CalculatorHistory::AddToHistory( - _In_ shared_ptr>> const& tokens, - _In_ shared_ptr>> const& commands, - _In_ wstring_view result) + _In_ shared_ptr>> const& tokens, + _In_ shared_ptr>> const& commands, + wstring_view result) { unsigned int addedIndex; - wstring generatedExpression; shared_ptr spHistoryItem = make_shared(); spHistoryItem->historyItemVector.spTokens = tokens; spHistoryItem->historyItemVector.spCommands = commands; // to be changed when pszexp is back - tokens->GetString(&generatedExpression); + wstring generatedExpression = GetGeneratedExpression(*tokens); // Prefixing and suffixing the special Unicode markers to ensure that the expression // in the history doesn't get broken for RTL languages spHistoryItem->historyItemVector.expression = L'\u202d' + generatedExpression + L'\u202c'; @@ -47,7 +70,7 @@ unsigned int CalculatorHistory::AddItem(_In_ shared_ptr const& spHi return lastIndex; } -bool CalculatorHistory::RemoveItem(_In_ unsigned int uIdx) +bool CalculatorHistory::RemoveItem(unsigned int uIdx) { if (uIdx > m_historyItems.size() - 1) { @@ -63,17 +86,12 @@ vector> const& CalculatorHistory::GetHistory() return m_historyItems; } -shared_ptr const& CalculatorHistory::GetHistoryItem(_In_ unsigned int uIdx) +shared_ptr const& CalculatorHistory::GetHistoryItem(unsigned int uIdx) { assert(uIdx >= 0 && uIdx < m_historyItems.size()); return m_historyItems.at(uIdx); } -CalculatorHistory::~CalculatorHistory(void) -{ - ClearHistory(); -} - void CalculatorHistory::ClearHistory() { m_historyItems.clear(); diff --git a/src/CalcManager/CalculatorHistory.h b/src/CalcManager/CalculatorHistory.h index 75b74255..e8c874a0 100644 --- a/src/CalcManager/CalculatorHistory.h +++ b/src/CalcManager/CalculatorHistory.h @@ -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 @@ -15,8 +15,8 @@ namespace CalculationManager struct HISTORYITEMVECTOR { - std::shared_ptr>> spTokens; - std::shared_ptr>> spCommands; + std::shared_ptr>> spTokens; + std::shared_ptr>> spCommands; std::wstring expression; std::wstring result; }; @@ -31,8 +31,8 @@ namespace CalculationManager public: CalculatorHistory(const size_t maxSize); unsigned int AddToHistory( - _In_ std::shared_ptr>> const& spTokens, - _In_ std::shared_ptr>> const& spCommands, + _In_ std::shared_ptr>> const& spTokens, + _In_ std::shared_ptr>> const& spCommands, std::wstring_view result); std::vector> const& GetHistory(); std::shared_ptr const& GetHistoryItem(unsigned int uIdx); @@ -43,7 +43,6 @@ namespace CalculationManager { return m_maxHistorySize; } - ~CalculatorHistory(void); private: std::vector> m_historyItems; diff --git a/src/CalcManager/CalculatorManager.cpp b/src/CalcManager/CalculatorManager.cpp index 71eebd22..e6d1f9be 100644 --- a/src/CalcManager/CalculatorManager.cpp +++ b/src/CalcManager/CalculatorManager.cpp @@ -75,14 +75,19 @@ namespace CalculationManager m_displayCallback->MemoryItemChanged(indexOfMemory); } + void CalculatorManager::InputChanged() + { + m_displayCallback->InputChanged(); + } + /// /// Call the callback function using passed in IDisplayHelper. /// Used to set the expression display value on ViewModel /// /// wstring representing expression to be displayed void CalculatorManager::SetExpressionDisplay( - _Inout_ shared_ptr>> const& tokens, - _Inout_ shared_ptr>> const& commands) + _Inout_ shared_ptr>> const& tokens, + _Inout_ shared_ptr>> const& commands) { if (!m_inHistoryItemLoadMode) { @@ -240,6 +245,7 @@ namespace CalculationManager m_savedCommands.push_back(MapCommandForSerialize(command)); } m_savedDegreeMode = m_currentDegreeMode; + InputChanged(); return; } @@ -283,6 +289,30 @@ namespace CalculationManager m_currentCalculatorEngine->ProcessCommand(static_cast(Command::CommandINV)); m_currentCalculatorEngine->ProcessCommand(static_cast(Command::CommandTANH)); break; + case Command::CommandASEC: + m_currentCalculatorEngine->ProcessCommand(static_cast(Command::CommandINV)); + m_currentCalculatorEngine->ProcessCommand(static_cast(Command::CommandSEC)); + break; + case Command::CommandACSC: + m_currentCalculatorEngine->ProcessCommand(static_cast(Command::CommandINV)); + m_currentCalculatorEngine->ProcessCommand(static_cast(Command::CommandCSC)); + break; + case Command::CommandACOT: + m_currentCalculatorEngine->ProcessCommand(static_cast(Command::CommandINV)); + m_currentCalculatorEngine->ProcessCommand(static_cast(Command::CommandCOT)); + break; + case Command::CommandASECH: + m_currentCalculatorEngine->ProcessCommand(static_cast(Command::CommandINV)); + m_currentCalculatorEngine->ProcessCommand(static_cast(Command::CommandSECH)); + break; + case Command::CommandACSCH: + m_currentCalculatorEngine->ProcessCommand(static_cast(Command::CommandINV)); + m_currentCalculatorEngine->ProcessCommand(static_cast(Command::CommandCSCH)); + break; + case Command::CommandACOTH: + m_currentCalculatorEngine->ProcessCommand(static_cast(Command::CommandINV)); + m_currentCalculatorEngine->ProcessCommand(static_cast(Command::CommandCOTH)); + break; case Command::CommandFE: m_isExponentialFormat = !m_isExponentialFormat; [[fallthrough]]; @@ -290,6 +320,8 @@ namespace CalculationManager m_currentCalculatorEngine->ProcessCommand(static_cast(command)); break; } + + InputChanged(); } /// @@ -330,6 +362,7 @@ namespace CalculationManager { m_currentCalculatorEngine->PersistedMemObject(m_persistedPrimaryValue); m_currentCalculatorEngine->ProcessCommand(IDC_RECALL); + InputChanged(); } /// @@ -376,6 +409,7 @@ namespace CalculationManager this->MemorizedNumberSelect(indexOfMemory); m_currentCalculatorEngine->ProcessCommand(IDC_RECALL); + InputChanged(); } /// @@ -606,9 +640,9 @@ namespace CalculationManager if (pHistory) { pHistory->ClearHistory(); - for (unsigned int i = 0; i < history.size(); ++i) + for (auto const& historyItem : history) { - pHistory->AddItem(history[i]); + pHistory->AddItem(historyItem); } } } @@ -638,6 +672,11 @@ namespace CalculationManager return m_currentCalculatorEngine->FInRecordingState() ? true : false; } + bool CalculatorManager::IsInputEmpty() + { + return m_currentCalculatorEngine->IsInputEmpty(); + } + void CalculatorManager::SetInHistoryItemLoadMode(_In_ bool isHistoryItemLoadMode) { m_inHistoryItemLoadMode = isHistoryItemLoadMode; diff --git a/src/CalcManager/CalculatorManager.h b/src/CalcManager/CalculatorManager.h index 358c2daf..9b38242c 100644 --- a/src/CalcManager/CalculatorManager.h +++ b/src/CalcManager/CalculatorManager.h @@ -91,8 +91,8 @@ namespace CalculationManager void SetPrimaryDisplay(_In_ const std::wstring& displayString, _In_ bool isError) override; void SetIsInError(bool isError) override; void SetExpressionDisplay( - _Inout_ std::shared_ptr>> const& tokens, - _Inout_ std::shared_ptr>> const& commands) override; + _Inout_ std::shared_ptr>> const& tokens, + _Inout_ std::shared_ptr>> const& commands) override; void SetMemorizedNumbers(_In_ const std::vector& memorizedNumbers) override; void OnHistoryItemAdded(_In_ unsigned int addedItemIndex) override; void SetParenthesisNumber(_In_ unsigned int parenthesisCount) override; @@ -101,8 +101,8 @@ namespace CalculationManager void MaxDigitsReached() override; void BinaryOperatorReceived() override; void MemoryItemChanged(unsigned int indexOfMemory) override; - - CalculatorManager(ICalcDisplay* displayCallback, IResourceProvider* resourceProvider); + void InputChanged() override; + CalculatorManager(_In_ ICalcDisplay* displayCallback, _In_ IResourceProvider* resourceProvider); void Reset(bool clearMemory = true); void SetStandardMode(); @@ -118,7 +118,8 @@ namespace CalculationManager void MemorizedNumberClearAll(); bool IsEngineRecording(); - std::vector GetSavedCommands() + bool IsInputEmpty(); + const std::vector& GetSavedCommands() const { return m_savedCommands; } diff --git a/src/CalcManager/CalculatorResource.h b/src/CalcManager/CalculatorResource.h index 5f360f35..8c4c049c 100644 --- a/src/CalcManager/CalculatorResource.h +++ b/src/CalcManager/CalculatorResource.h @@ -1,8 +1,10 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #pragma once +#include + namespace CalculationManager { class IResourceProvider @@ -19,6 +21,6 @@ namespace CalculationManager // ids "sDecimal", "sThousand" and "sGrouping". See // https://technet.microsoft.com/en-us/library/cc782655(v=ws.10).aspx // for what these values refer to. - virtual std::wstring GetCEngineString(const std::wstring& id) = 0; + virtual std::wstring GetCEngineString(std::wstring_view id) = 0; }; } diff --git a/src/CalcManager/Command.h b/src/CalcManager/Command.h index 3dd508ed..4331ddf7 100644 --- a/src/CalcManager/Command.h +++ b/src/CalcManager/Command.h @@ -97,6 +97,7 @@ namespace CalculationManager CommandROL = 99, CommandROR = 100, CommandCOM = 101, + CommandSIN = 102, CommandCOS = 103, CommandTAN = 104, @@ -151,6 +152,34 @@ namespace CalculationManager CommandINV = 146, CommandSET_RESULT = 147, + CommandSEC = 400, + CommandASEC = 401, + CommandCSC = 402, + CommandACSC = 403, + CommandCOT = 404, + CommandACOT = 405, + + CommandSECH = 406, + CommandASECH = 407, + CommandCSCH = 408, + CommandACSCH = 409, + CommandCOTH = 410, + CommandACOTH = 411, + + CommandPOW2 = 412, // 2 ^ x + CommandAbs = 413, + CommandFloor = 414, + CommandCeil = 415, + CommandROLC = 416, + CommandRORC = 417, + CommandLogBaseX = 500, + CommandNand = 501, + CommandNor = 502, + + CommandRSHFL = 505, + CommandRand = 600, + CommandEuler = 601, + CommandAnd = 86, CommandOR = 87, CommandNot = 101, diff --git a/src/CalcManager/ExpressionCommand.cpp b/src/CalcManager/ExpressionCommand.cpp index 2d0547c6..628805fb 100644 --- a/src/CalcManager/ExpressionCommand.cpp +++ b/src/CalcManager/ExpressionCommand.cpp @@ -3,7 +3,6 @@ #include #include "Header Files/CCommand.h" -#include "CalculatorVector.h" #include "ExpressionCommand.h" using namespace std; @@ -35,18 +34,18 @@ void CParentheses::Accept(_In_ ISerializeCommandVisitor& commandVisitor) CUnaryCommand::CUnaryCommand(int command) { - m_command = make_shared>(); - m_command->Append(command); + m_command = make_shared>(); + m_command->push_back(command); } CUnaryCommand::CUnaryCommand(int command1, int command2) { - m_command = make_shared>(); - m_command->Append(command1); - m_command->Append(command2); + m_command = make_shared>(); + m_command->push_back(command1); + m_command->push_back(command2); } -const shared_ptr>& CUnaryCommand::GetCommands() const +const shared_ptr>& CUnaryCommand::GetCommands() const { return m_command; } @@ -58,15 +57,15 @@ CalculationManager::CommandType CUnaryCommand::GetCommandType() const void CUnaryCommand::SetCommand(int command) { - m_command->Clear(); - m_command->Append(command); + m_command->clear(); + m_command->push_back(command); } void CUnaryCommand::SetCommands(int command1, int command2) { - m_command->Clear(); - m_command->Append(command1); - m_command->Append(command2); + m_command->clear(); + m_command->push_back(command1); + m_command->push_back(command2); } void CUnaryCommand::Accept(_In_ ISerializeCommandVisitor& commandVisitor) @@ -99,7 +98,7 @@ void CBinaryCommand::Accept(_In_ ISerializeCommandVisitor& commandVisitor) commandVisitor.Visit(*this); } -COpndCommand::COpndCommand(shared_ptr> const& commands, bool fNegative, bool fDecimal, bool fSciFmt) +COpndCommand::COpndCommand(shared_ptr> const& commands, bool fNegative, bool fDecimal, bool fSciFmt) : m_commands(commands) , m_fNegative(fNegative) , m_fSciFmt(fSciFmt) @@ -115,27 +114,25 @@ void COpndCommand::Initialize(Rational const& rat) m_fInitialized = true; } -const shared_ptr>& COpndCommand::GetCommands() const +const shared_ptr>& COpndCommand::GetCommands() const { return m_commands; } -void COpndCommand::SetCommands(shared_ptr> const& commands) +void COpndCommand::SetCommands(shared_ptr> const& commands) { m_commands = commands; } void COpndCommand::AppendCommand(int command) { - unsigned int nCommands; - m_commands->GetSize(&nCommands); if (m_fSciFmt) { ClearAllAndAppendCommand(static_cast(command)); } else { - m_commands->Append(command); + m_commands->push_back(command); } if (command == IDC_PNT) @@ -146,14 +143,8 @@ void COpndCommand::AppendCommand(int command) void COpndCommand::ToggleSign() { - unsigned int commandCount; - m_commands->GetSize(&commandCount); - - for (unsigned int i = 0; i < commandCount; i++) + for (int nOpCode : *m_commands) { - int nOpCode; - m_commands->GetAt(i, &nOpCode); - if (nOpCode != IDC_0) { m_fNegative = !m_fNegative; @@ -170,8 +161,7 @@ void COpndCommand::RemoveFromEnd() } else { - unsigned int nCommands; - m_commands->GetSize(&nCommands); + const size_t nCommands = m_commands->size(); if (nCommands == 1) { @@ -179,13 +169,14 @@ void COpndCommand::RemoveFromEnd() } else { - int nOpCode; - m_commands->GetAt(nCommands - 1, &nOpCode); + int nOpCode = m_commands->at(nCommands - 1); + if (nOpCode == IDC_PNT) { m_fDecimal = false; } - m_commands->RemoveAt(nCommands - 1); + + m_commands->pop_back(); } } } @@ -212,8 +203,8 @@ CalculationManager::CommandType COpndCommand::GetCommandType() const void COpndCommand::ClearAllAndAppendCommand(CalculationManager::Command command) { - m_commands->Clear(); - m_commands->Append(static_cast(command)); + m_commands->clear(); + m_commands->push_back(static_cast(command)); m_fSciFmt = false; m_fNegative = false; m_fDecimal = false; @@ -223,31 +214,29 @@ const wstring& COpndCommand::GetToken(wchar_t decimalSymbol) { static const wchar_t chZero = L'0'; - unsigned int nCommands; - m_commands->GetSize(&nCommands); + const size_t nCommands = m_commands->size(); m_token.clear(); - int nOpCode; - for (unsigned int i = 0; i < nCommands; i++) + for (size_t i = 0; i < nCommands; i++) { - m_commands->GetAt(i, &nOpCode); + int nOpCode = (*m_commands)[i]; + if (nOpCode == IDC_PNT) { - m_token.append(wstring{ decimalSymbol }); + m_token += decimalSymbol; } else if (nOpCode == IDC_EXP) { - m_token.append(&chExp); - int nextOpCode; - m_commands->GetAt(i + 1, &nextOpCode); + m_token += chExp; + int nextOpCode = m_commands->at(i + 1); if (nextOpCode != IDC_SIGN) { - m_token.append(&chPlus); + m_token += chPlus; } } else if (nOpCode == IDC_SIGN) { - m_token.append(&chNegate); + m_token += chNegate; } else { @@ -257,7 +246,7 @@ const wstring& COpndCommand::GetToken(wchar_t decimalSymbol) } // Remove zeros - for (unsigned int i = 0; i < m_token.size(); i++) + for (size_t i = 0; i < m_token.size(); i++) { if (m_token.at(i) != chZero) { @@ -272,29 +261,26 @@ const wstring& COpndCommand::GetToken(wchar_t decimalSymbol) if (m_fNegative) { - m_token.insert(0, &chNegate); + m_token.insert(0, 1, chNegate); } return m_token; } } - m_token.clear(); - m_token.append(&chZero); + m_token = chZero; return m_token; } wstring COpndCommand::GetString(uint32_t radix, int32_t precision) { - wstring result{}; - if (m_fInitialized) { - result = m_value.ToString(radix, eNUMOBJ_FMT::FMT_FLOAT, precision); + return m_value.ToString(radix, eNUMOBJ_FMT::FMT_FLOAT, precision); } - return result; + return wstring{}; } void COpndCommand::Accept(_In_ ISerializeCommandVisitor& commandVisitor) diff --git a/src/CalcManager/ExpressionCommand.h b/src/CalcManager/ExpressionCommand.h index 91d41e60..d8ab7ec0 100644 --- a/src/CalcManager/ExpressionCommand.h +++ b/src/CalcManager/ExpressionCommand.h @@ -23,14 +23,14 @@ class CUnaryCommand final : public IUnaryCommand public: CUnaryCommand(int command); CUnaryCommand(int command1, int command2); - const std::shared_ptr>& GetCommands() const override; + const std::shared_ptr>& GetCommands() const override; CalculationManager::CommandType GetCommandType() const override; void SetCommand(int command) override; void SetCommands(int command1, int command2) override; void Accept(_In_ ISerializeCommandVisitor& commandVisitor) override; private: - std::shared_ptr> m_command; + std::shared_ptr> m_command; }; class CBinaryCommand final : public IBinaryCommand @@ -49,11 +49,11 @@ private: class COpndCommand final : public IOpndCommand { public: - COpndCommand(std::shared_ptr> const& commands, bool fNegative, bool fDecimal, bool fSciFmt); + COpndCommand(std::shared_ptr> const& commands, bool fNegative, bool fDecimal, bool fSciFmt); void Initialize(CalcEngine::Rational const& rat); - const std::shared_ptr>& GetCommands() const override; - void SetCommands(std::shared_ptr> const& commands) override; + const std::shared_ptr>& GetCommands() const override; + void SetCommands(std::shared_ptr> const& commands) override; void AppendCommand(int command) override; void ToggleSign() override; void RemoveFromEnd() override; @@ -66,7 +66,7 @@ public: std::wstring GetString(uint32_t radix, int32_t precision); private: - std::shared_ptr> m_commands; + std::shared_ptr> m_commands; bool m_fNegative; bool m_fSciFmt; bool m_fDecimal; diff --git a/src/CalcManager/ExpressionCommandInterface.h b/src/CalcManager/ExpressionCommandInterface.h index 9115316d..4ea9b81b 100644 --- a/src/CalcManager/ExpressionCommandInterface.h +++ b/src/CalcManager/ExpressionCommandInterface.h @@ -4,7 +4,7 @@ #pragma once #include // for std::shared_ptr -#include "CalculatorVector.h" +#include #include "Command.h" class ISerializeCommandVisitor; @@ -25,7 +25,7 @@ public: class IUnaryCommand : public IOperatorCommand { public: - virtual const std::shared_ptr>& GetCommands() const = 0; + virtual const std::shared_ptr>& GetCommands() const = 0; virtual void SetCommands(int command1, int command2) = 0; }; @@ -39,7 +39,7 @@ public: class IOpndCommand : public IExpressionCommand { public: - virtual const std::shared_ptr>& GetCommands() const = 0; + virtual const std::shared_ptr>& GetCommands() const = 0; virtual void AppendCommand(int command) = 0; virtual void ToggleSign() = 0; virtual void RemoveFromEnd() = 0; @@ -47,7 +47,7 @@ public: virtual bool IsSciFmt() const = 0; virtual bool IsDecimalPresent() const = 0; virtual const std::wstring& GetToken(wchar_t decimalSymbol) = 0; - virtual void SetCommands(std::shared_ptr> const& commands) = 0; + virtual void SetCommands(std::shared_ptr> const& commands) = 0; }; class IParenthesisCommand : public IExpressionCommand diff --git a/src/CalcManager/Header Files/CCommand.h b/src/CalcManager/Header Files/CCommand.h index 6366b45a..f6d74d25 100644 --- a/src/CalcManager/Header Files/CCommand.h +++ b/src/CalcManager/Header Files/CCommand.h @@ -81,6 +81,7 @@ #define IDC_ROL 99 #define IDC_ROR 100 #define IDC_COM 101 + #define IDC_SIN 102 #define IDC_COS 103 #define IDC_TAN 104 @@ -136,7 +137,44 @@ #define IDC_INV 146 #define IDC_SET_RESULT 147 -#define IDC_LASTCONTROL IDC_SET_RESULT +#define IDC_STRING_MAPPED_VALUES 400 +#define IDC_UNARYEXTENDEDFIRST IDC_STRING_MAPPED_VALUES +#define IDC_SEC 400 // Secant +// 401 reserved for inverse +#define IDC_CSC 402 // Cosecant +// 403 reserved for inverse +#define IDC_COT 404 // Cotangent +// 405 reserved for inverse + +#define IDC_SECH 406 //Hyperbolic Secant +// 407 reserved for inverse +#define IDC_CSCH 408 //Hyperbolic Cosecant +// 409 reserved for inverse +#define IDC_COTH 410 //Hyperbolic Cotangent +// 411 reserved for inverse + +#define IDC_POW2 412 // 2 ^ x +#define IDC_ABS 413 // Absolute Value +#define IDC_FLOOR 414 // Floor +#define IDC_CEIL 415 // Ceiling + +#define IDC_ROLC 416 // Rotate Left Circular +#define IDC_RORC 417 // Rotate Right Circular + +#define IDC_UNARYEXTENDEDLAST IDC_RORC + +#define IDC_LASTCONTROL IDC_CEIL + +#define IDC_BINARYEXTENDEDFIRST 500 +#define IDC_LOGBASEX 500 // logx(y) +#define IDC_NAND 501 // Nand +#define IDC_NOR 502 // Nor + +#define IDC_RSHFL 505 //Right Shift Logical +#define IDC_BINARYEXTENDEDLAST IDC_RSHFL + +#define IDC_RAND 600 // Random +#define IDC_EULER 601 // e Constant #define IDC_BINEDITSTART 700 #define IDC_BINPOS0 700 diff --git a/src/CalcManager/Header Files/CalcEngine.h b/src/CalcManager/Header Files/CalcEngine.h index 24441857..26b80515 100644 --- a/src/CalcManager/Header Files/CalcEngine.h +++ b/src/CalcManager/Header Files/CalcEngine.h @@ -14,10 +14,10 @@ * \****************************************************************************/ +#include #include "CCommand.h" #include "EngineStrings.h" #include "../Command.h" -#include "../CalculatorVector.h" #include "../ExpressionCommand.h" #include "RadixType.h" #include "History.h" // for History Collector @@ -68,6 +68,10 @@ public: { return m_bError; } + bool IsInputEmpty() + { + return m_input.IsEmpty() && (m_numberString.empty() || m_numberString == L"0"); + } bool FInRecordingState() { return m_bRecord; @@ -94,7 +98,7 @@ public: { return s_engineStrings[std::to_wstring(ids)]; } - static std::wstring_view GetString(std::wstring ids) + static std::wstring_view GetString(std::wstring_view ids) { return s_engineStrings[ids]; } @@ -103,6 +107,7 @@ public: return GetString(IdStrFromCmdId(nOpCode)); } static std::wstring_view OpCodeToUnaryString(int nOpCode, bool fInv, ANGLE_TYPE angletype); + static std::wstring_view OpCodeToBinaryString(int nOpCode, bool isIntegerMode); private: bool m_fPrecedence; @@ -147,11 +152,16 @@ private: NUM_WIDTH m_numwidth; // one of qword, dword, word or byte mode. int32_t m_dwWordBitWidth; // # of bits in currently selected word size + std::unique_ptr m_randomGeneratorEngine; + std::unique_ptr> m_distr; + + uint64_t m_carryBit; + CHistoryCollector m_HistoryCollector; // Accumulator of each line of history as various commands are processed std::array m_chopNumbers; // word size enforcement std::array m_maxDecimalValueStrings; // maximum values represented by a given word width based off m_chopNumbers - static std::unordered_map s_engineStrings; // the string table shared across all instances + static std::unordered_map s_engineStrings; // the string table shared across all instances wchar_t m_decimalSeparator; wchar_t m_groupSeparator; @@ -165,12 +175,14 @@ private: void DisplayAnnounceBinaryOperator(); void SetPrimaryDisplay(const std::wstring& szText, bool isError = false); void ClearTemporaryValues(); + void ClearDisplay(); CalcEngine::Rational TruncateNumForIntMath(CalcEngine::Rational const& rat); CalcEngine::Rational SciCalcFunctions(CalcEngine::Rational const& rat, uint32_t op); CalcEngine::Rational DoOperation(int operation, CalcEngine::Rational const& lhs, CalcEngine::Rational const& rhs); void SetRadixTypeAndNumWidth(RADIX_TYPE radixtype, NUM_WIDTH numwidth); int32_t DwWordBitWidthFromeNumWidth(NUM_WIDTH numwidth); uint32_t NRadixFromRadixType(RADIX_TYPE radixtype); + double GenerateRandomNumber(); bool TryToggleBit(CalcEngine::Rational& rat, uint32_t wbitno); void CheckAndAddLastBinOpToHistory(bool addToHistory = true); diff --git a/src/CalcManager/Header Files/CalcInput.h b/src/CalcManager/Header Files/CalcInput.h index 045cdb89..b798d061 100644 --- a/src/CalcManager/Header Files/CalcInput.h +++ b/src/CalcManager/Header Files/CalcInput.h @@ -66,6 +66,7 @@ namespace CalcEngine bool TryBeginExponent(); void Backspace(); void SetDecimalSymbol(wchar_t decSymbol); + bool IsEmpty(); std::wstring ToString(uint32_t radix); Rational ToRational(uint32_t radix, int32_t precision); diff --git a/src/CalcManager/Header Files/EngineStrings.h b/src/CalcManager/Header Files/EngineStrings.h index fffebf0d..958c828b 100644 --- a/src/CalcManager/Header Files/EngineStrings.h +++ b/src/CalcManager/Header Files/EngineStrings.h @@ -87,7 +87,6 @@ inline constexpr auto SIDS_XPOW3 = L"32"; inline constexpr auto SIDS_NFACTORIAL = L"33"; inline constexpr auto SIDS_RECIPROCAL = L"34"; inline constexpr auto SIDS_DMS = L"35"; -inline constexpr auto SIDS_CUBEROOT = L"36"; inline constexpr auto SIDS_POWTEN = L"37"; inline constexpr auto SIDS_PERCENT = L"38"; inline constexpr auto SIDS_SCIENTIFIC_NOTATION = L"39"; @@ -172,125 +171,193 @@ inline constexpr auto SIDS_ERR_UNEX_END = L"117"; inline constexpr auto SIDS_ERR_SG_INV_ERROR = L"118"; inline constexpr auto SIDS_ERR_INPUT_OVERFLOW = L"119"; inline constexpr auto SIDS_ERR_OUTPUT_OVERFLOW = L"120"; +inline constexpr auto SIDS_SECD = L"SecDeg"; +inline constexpr auto SIDS_SECR = L"SecRad"; +inline constexpr auto SIDS_SECG = L"SecGrad"; +inline constexpr auto SIDS_ASECD = L"InverseSecDeg"; +inline constexpr auto SIDS_ASECR = L"InverseSecRad"; +inline constexpr auto SIDS_ASECG = L"InverseSecGrad"; +inline constexpr auto SIDS_CSCD = L"CscDeg"; +inline constexpr auto SIDS_CSCR = L"CscRad"; +inline constexpr auto SIDS_CSCG = L"CscGrad"; +inline constexpr auto SIDS_ACSCD = L"InverseCscDeg"; +inline constexpr auto SIDS_ACSCR = L"InverseCscRad"; +inline constexpr auto SIDS_ACSCG = L"InverseCscGrad"; +inline constexpr auto SIDS_COTD = L"CotDeg"; +inline constexpr auto SIDS_COTR = L"CotRad"; +inline constexpr auto SIDS_COTG = L"CotGrad"; +inline constexpr auto SIDS_ACOTD = L"InverseCotDeg"; +inline constexpr auto SIDS_ACOTR = L"InverseCotRad"; +inline constexpr auto SIDS_ACOTG = L"InverseCotGrad"; +inline constexpr auto SIDS_SECH = L"Sech"; +inline constexpr auto SIDS_ASECH = L"InverseSech"; +inline constexpr auto SIDS_CSCH = L"Csch"; +inline constexpr auto SIDS_ACSCH = L"InverseCsch"; +inline constexpr auto SIDS_COTH = L"Coth"; +inline constexpr auto SIDS_ACOTH = L"InverseCoth"; +inline constexpr auto SIDS_TWOPOWX = L"TwoPowX"; +inline constexpr auto SIDS_LOGBASEX = L"LogBaseX"; +inline constexpr auto SIDS_ABS = L"Abs"; +inline constexpr auto SIDS_FLOOR = L"Floor"; +inline constexpr auto SIDS_CEIL = L"Ceil"; +inline constexpr auto SIDS_NAND = L"Nand"; +inline constexpr auto SIDS_NOR = L"Nor"; +inline constexpr auto SIDS_CUBEROOT = L"CubeRoot"; +inline constexpr auto SIDS_PROGRAMMER_MOD = L"ProgrammerMod"; // Include the resource key ID from above into this vector to load it into memory for the engine to use -inline constexpr std::array g_sids = { SIDS_PLUS_MINUS, - SIDS_C, - SIDS_CE, - SIDS_BACKSPACE, - SIDS_DECIMAL_SEPARATOR, - SIDS_EMPTY_STRING, - SIDS_AND, - SIDS_OR, - SIDS_XOR, - SIDS_LSH, - SIDS_RSH, - SIDS_DIVIDE, - SIDS_MULTIPLY, - SIDS_PLUS, - SIDS_MINUS, - SIDS_MOD, - SIDS_YROOT, - SIDS_POW_HAT, - SIDS_INT, - SIDS_ROL, - SIDS_ROR, - SIDS_NOT, - SIDS_SIN, - SIDS_COS, - SIDS_TAN, - SIDS_SINH, - SIDS_COSH, - SIDS_TANH, - SIDS_LN, - SIDS_LOG, - SIDS_SQRT, - SIDS_XPOW2, - SIDS_XPOW3, - SIDS_NFACTORIAL, - SIDS_RECIPROCAL, - SIDS_DMS, - SIDS_CUBEROOT, - SIDS_POWTEN, - SIDS_PERCENT, - SIDS_SCIENTIFIC_NOTATION, - SIDS_PI, - SIDS_EQUAL, - SIDS_MC, - SIDS_MR, - SIDS_MS, - SIDS_MPLUS, - SIDS_MMINUS, - SIDS_EXP, - SIDS_OPEN_PAREN, - SIDS_CLOSE_PAREN, - SIDS_0, - SIDS_1, - SIDS_2, - SIDS_3, - SIDS_4, - SIDS_5, - SIDS_6, - SIDS_7, - SIDS_8, - SIDS_9, - SIDS_A, - SIDS_B, - SIDS_C, - SIDS_D, - SIDS_E, - SIDS_F, - SIDS_FRAC, - SIDS_SIND, - SIDS_COSD, - SIDS_TAND, - SIDS_ASIND, - SIDS_ACOSD, - SIDS_ATAND, - SIDS_SINR, - SIDS_COSR, - SIDS_TANR, - SIDS_ASINR, - SIDS_ACOSR, - SIDS_ATANR, - SIDS_SING, - SIDS_COSG, - SIDS_TANG, - SIDS_ASING, - SIDS_ACOSG, - SIDS_ATANG, - SIDS_ASINH, - SIDS_ACOSH, - SIDS_ATANH, - SIDS_POWE, - SIDS_POWTEN2, - SIDS_SQRT2, - SIDS_SQR, - SIDS_CUBE, - SIDS_CUBERT, - SIDS_FACT, - SIDS_RECIPROC, - SIDS_DEGREES, - SIDS_NEGATE, - SIDS_RSH, - SIDS_DIVIDEBYZERO, - SIDS_DOMAIN, - SIDS_UNDEFINED, - SIDS_POS_INFINITY, - SIDS_NEG_INFINITY, - SIDS_ABORTED, - SIDS_NOMEM, - SIDS_TOOMANY, - SIDS_OVERFLOW, - SIDS_NORESULT, - SIDS_INSUFFICIENT_DATA, - SIDS_ERR_UNK_CH, - SIDS_ERR_UNK_FN, - SIDS_ERR_UNEX_NUM, - SIDS_ERR_UNEX_CH, - SIDS_ERR_UNEX_SZ, - SIDS_ERR_MISMATCH_CLOSE, - SIDS_ERR_UNEX_END, - SIDS_ERR_SG_INV_ERROR, - SIDS_ERR_INPUT_OVERFLOW, - SIDS_ERR_OUTPUT_OVERFLOW }; +inline constexpr std::array g_sids = +{ + SIDS_PLUS_MINUS, + SIDS_C, + SIDS_CE, + SIDS_BACKSPACE, + SIDS_DECIMAL_SEPARATOR, + SIDS_EMPTY_STRING, + SIDS_AND, + SIDS_OR, + SIDS_XOR, + SIDS_LSH, + SIDS_RSH, + SIDS_DIVIDE, + SIDS_MULTIPLY, + SIDS_PLUS, + SIDS_MINUS, + SIDS_MOD, + SIDS_YROOT, + SIDS_POW_HAT, + SIDS_INT, + SIDS_ROL, + SIDS_ROR, + SIDS_NOT, + SIDS_SIN, + SIDS_COS, + SIDS_TAN, + SIDS_SINH, + SIDS_COSH, + SIDS_TANH, + SIDS_LN, + SIDS_LOG, + SIDS_SQRT, + SIDS_XPOW2, + SIDS_XPOW3, + SIDS_NFACTORIAL, + SIDS_RECIPROCAL, + SIDS_DMS, + SIDS_POWTEN, + SIDS_PERCENT, + SIDS_SCIENTIFIC_NOTATION, + SIDS_PI, + SIDS_EQUAL, + SIDS_MC, + SIDS_MR, + SIDS_MS, + SIDS_MPLUS, + SIDS_MMINUS, + SIDS_EXP, + SIDS_OPEN_PAREN, + SIDS_CLOSE_PAREN, + SIDS_0, + SIDS_1, + SIDS_2, + SIDS_3, + SIDS_4, + SIDS_5, + SIDS_6, + SIDS_7, + SIDS_8, + SIDS_9, + SIDS_A, + SIDS_B, + SIDS_C, + SIDS_D, + SIDS_E, + SIDS_F, + SIDS_FRAC, + SIDS_SIND, + SIDS_COSD, + SIDS_TAND, + SIDS_ASIND, + SIDS_ACOSD, + SIDS_ATAND, + SIDS_SINR, + SIDS_COSR, + SIDS_TANR, + SIDS_ASINR, + SIDS_ACOSR, + SIDS_ATANR, + SIDS_SING, + SIDS_COSG, + SIDS_TANG, + SIDS_ASING, + SIDS_ACOSG, + SIDS_ATANG, + SIDS_ASINH, + SIDS_ACOSH, + SIDS_ATANH, + SIDS_POWE, + SIDS_POWTEN2, + SIDS_SQRT2, + SIDS_SQR, + SIDS_CUBE, + SIDS_CUBERT, + SIDS_FACT, + SIDS_RECIPROC, + SIDS_DEGREES, + SIDS_NEGATE, + SIDS_RSH, + SIDS_DIVIDEBYZERO, + SIDS_DOMAIN, + SIDS_UNDEFINED, + SIDS_POS_INFINITY, + SIDS_NEG_INFINITY, + SIDS_ABORTED, + SIDS_NOMEM, + SIDS_TOOMANY, + SIDS_OVERFLOW, + SIDS_NORESULT, + SIDS_INSUFFICIENT_DATA, + SIDS_ERR_UNK_CH, + SIDS_ERR_UNK_FN, + SIDS_ERR_UNEX_NUM, + SIDS_ERR_UNEX_CH, + SIDS_ERR_UNEX_SZ, + SIDS_ERR_MISMATCH_CLOSE, + SIDS_ERR_UNEX_END, + SIDS_ERR_SG_INV_ERROR, + SIDS_ERR_INPUT_OVERFLOW, + SIDS_ERR_OUTPUT_OVERFLOW, + SIDS_SECD, + SIDS_SECG, + SIDS_SECR, + SIDS_ASECD, + SIDS_ASECR, + SIDS_ASECG, + SIDS_CSCD, + SIDS_CSCR, + SIDS_CSCG, + SIDS_ACSCD, + SIDS_ACSCR, + SIDS_ACSCG, + SIDS_COTD, + SIDS_COTR, + SIDS_COTG, + SIDS_ACOTD, + SIDS_ACOTR, + SIDS_ACOTG, + SIDS_SECH, + SIDS_ASECH, + SIDS_CSCH, + SIDS_ACSCH, + SIDS_COTH, + SIDS_ACOTH, + SIDS_TWOPOWX, + SIDS_LOGBASEX, + SIDS_ABS, + SIDS_FLOOR, + SIDS_CEIL, + SIDS_NAND, + SIDS_NOR, + SIDS_CUBEROOT, + SIDS_PROGRAMMER_MOD, +}; diff --git a/src/CalcManager/Header Files/History.h b/src/CalcManager/Header Files/History.h index b6d6d8db..66bac67f 100644 --- a/src/CalcManager/Header Files/History.h +++ b/src/CalcManager/Header Files/History.h @@ -21,8 +21,8 @@ public: ~CHistoryCollector(); void AddOpndToHistory(std::wstring_view numStr, CalcEngine::Rational const& rat, bool fRepetition = false); void RemoveLastOpndFromHistory(); - void AddBinOpToHistory(int nOpCode, bool fNoRepetition = true); - void ChangeLastBinOp(int nOpCode, bool fPrecInvToHigher); + void AddBinOpToHistory(int nOpCode, bool isIntgerMode, bool fNoRepetition = true); + void ChangeLastBinOp(int nOpCode, bool fPrecInvToHigher, bool isIntgerMode); void AddUnaryOpToHistory(int nOpCode, bool fInv, ANGLE_TYPE angletype); void AddOpenBraceToHistory(); void AddCloseBraceToHistory(); @@ -31,6 +31,7 @@ public: void EnclosePrecInversionBrackets(); bool FOpndAddedToHistory(); void CompleteHistoryLine(std::wstring_view numStr); + void CompleteEquation(std::wstring_view numStr); void ClearHistoryLine(std::wstring_view errStr); int AddCommand(_In_ const std::shared_ptr& spCommand); void UpdateHistoryExpression(uint32_t radix, int32_t precision); @@ -50,8 +51,8 @@ private: int m_curOperandIndex; // Stack index for the above stack bool m_bLastOpndBrace; // iff the last opnd in history is already braced so we can avoid putting another one for unary operator wchar_t m_decimalSymbol; - std::shared_ptr>> m_spTokens; - std::shared_ptr>> m_spCommands; + std::shared_ptr>> m_spTokens; + std::shared_ptr>> m_spCommands; private: void ReinitHistory(); @@ -59,5 +60,5 @@ private: void TruncateEquationSzFromIch(int ich); void SetExpressionDisplay(); void InsertSzInEquationSz(std::wstring_view str, int icommandIndex, int ich); - std::shared_ptr> GetOperandCommandsFromString(std::wstring_view numStr); + std::shared_ptr> GetOperandCommandsFromString(std::wstring_view numStr); }; diff --git a/src/CalcManager/Header Files/ICalcDisplay.h b/src/CalcManager/Header Files/ICalcDisplay.h index f4aebec3..ee32580c 100644 --- a/src/CalcManager/Header Files/ICalcDisplay.h +++ b/src/CalcManager/Header Files/ICalcDisplay.h @@ -3,7 +3,6 @@ #pragma once -#include "../CalculatorVector.h" #include "../ExpressionCommandInterface.h" // Callback interface to be implemented by the clients of CCalcEngine @@ -13,8 +12,8 @@ public: virtual void SetPrimaryDisplay(const std::wstring& pszText, bool isError) = 0; virtual void SetIsInError(bool isInError) = 0; virtual void SetExpressionDisplay( - _Inout_ std::shared_ptr>> const& tokens, - _Inout_ std::shared_ptr>> const& commands) = 0; + _Inout_ std::shared_ptr>> const& tokens, + _Inout_ std::shared_ptr>> const& commands) = 0; virtual void SetParenthesisNumber(_In_ unsigned int count) = 0; virtual void OnNoRightParenAdded() = 0; virtual void MaxDigitsReached() = 0; // not an error but still need to inform UI layer. @@ -22,4 +21,5 @@ public: virtual void OnHistoryItemAdded(_In_ unsigned int addedItemIndex) = 0; virtual void SetMemorizedNumbers(const std::vector& memorizedNumbers) = 0; virtual void MemoryItemChanged(unsigned int indexOfMemory) = 0; + virtual void InputChanged() = 0; }; diff --git a/src/CalcManager/Header Files/IHistoryDisplay.h b/src/CalcManager/Header Files/IHistoryDisplay.h index 7e2a9019..80794ec5 100644 --- a/src/CalcManager/Header Files/IHistoryDisplay.h +++ b/src/CalcManager/Header Files/IHistoryDisplay.h @@ -1,15 +1,17 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #pragma once +#include "../ExpressionCommandInterface.h" + // Callback interface to be implemented by the clients of CCalcEngine if they require equation history class IHistoryDisplay { public: virtual ~IHistoryDisplay(){}; virtual unsigned int AddToHistory( - _In_ std::shared_ptr>> const& tokens, - _In_ std::shared_ptr>> const& commands, + _In_ std::shared_ptr>> const& tokens, + _In_ std::shared_ptr>> const& commands, _In_ std::wstring_view result) = 0; }; diff --git a/src/CalcManager/NumberFormattingUtils.cpp b/src/CalcManager/NumberFormattingUtils.cpp index 8fde3d9a..133fdda5 100644 --- a/src/CalcManager/NumberFormattingUtils.cpp +++ b/src/CalcManager/NumberFormattingUtils.cpp @@ -16,8 +16,7 @@ namespace CalcManager::NumberFormattingUtils return; } - wstring::iterator iter; - for (iter = number.end() - 1;; iter--) + for (auto iter = number.end() - 1;; iter--) { if (*iter != L'0') { @@ -25,9 +24,9 @@ namespace CalcManager::NumberFormattingUtils break; } } - if (*(number.end() - 1) == L'.') + if (number.back() == L'.') { - number.erase(number.end() - 1, number.end()); + number.pop_back(); } } diff --git a/src/CalcManager/Ratpack/CalcErr.h b/src/CalcManager/Ratpack/CalcErr.h index 4637c2c3..ebdc6730 100644 --- a/src/CalcManager/Ratpack/CalcErr.h +++ b/src/CalcManager/Ratpack/CalcErr.h @@ -41,45 +41,45 @@ typedef int32_t ResultCode; // CALC_E_DIVIDEBYZERO // // The current operation would require a divide by zero to complete -#define CALC_E_DIVIDEBYZERO ((uint32_t)0x80000000) +static constexpr uint32_t CALC_E_DIVIDEBYZERO = (uint32_t)0x80000000; // CALC_E_DOMAIN // // The given input is not within the domain of this function -#define CALC_E_DOMAIN ((uint32_t)0x80000001) +static constexpr uint32_t CALC_E_DOMAIN = (uint32_t)0x80000001; // CALC_E_INDEFINITE // // The result of this function is undefined -#define CALC_E_INDEFINITE ((uint32_t)0x80000002) +static constexpr uint32_t CALC_E_INDEFINITE = (uint32_t)0x80000002; // CALC_E_POSINFINITY // // The result of this function is Positive Infinity. -#define CALC_E_POSINFINITY ((uint32_t)0x80000003) +static constexpr uint32_t CALC_E_POSINFINITY = (uint32_t)0x80000003; // CALC_E_NEGINFINITY // // The result of this function is Negative Infinity -#define CALC_E_NEGINFINITY ((uint32_t)0x80000004) +static constexpr uint32_t CALC_E_NEGINFINITY = (uint32_t)0x80000004; // CALC_E_INVALIDRANGE // // The given input is within the domain of the function but is beyond // the range for which calc can successfully compute the answer -#define CALC_E_INVALIDRANGE ((uint32_t)0x80000006) +static constexpr uint32_t CALC_E_INVALIDRANGE = (uint32_t)0x80000006; // CALC_E_OUTOFMEMORY // // There is not enough free memory to complete the requested function -#define CALC_E_OUTOFMEMORY ((uint32_t)0x80000007) +static constexpr uint32_t CALC_E_OUTOFMEMORY = (uint32_t)0x80000007; // CALC_E_OVERFLOW // // The result of this operation is an overflow -#define CALC_E_OVERFLOW ((uint32_t)0x80000008) +static constexpr uint32_t CALC_E_OVERFLOW = (uint32_t)0x80000008; // CALC_E_NORESULT // // The result of this operation is undefined -#define CALC_E_NORESULT ((uint32_t)0x80000009) +static constexpr uint32_t CALC_E_NORESULT = (uint32_t)0x80000009; diff --git a/src/CalcManager/Ratpack/basex.cpp b/src/CalcManager/Ratpack/basex.cpp index 6dded335..27e6a223 100644 --- a/src/CalcManager/Ratpack/basex.cpp +++ b/src/CalcManager/Ratpack/basex.cpp @@ -34,7 +34,7 @@ void _mulnumx(PNUMBER* pa, PNUMBER b); // //---------------------------------------------------------------------------- -void mulnumx(PNUMBER* pa, PNUMBER b) +void mulnumx(_Inout_ PNUMBER* pa, _In_ PNUMBER b) { if (b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0) @@ -172,7 +172,7 @@ void _mulnumx(PNUMBER* pa, PNUMBER b) // //----------------------------------------------------------------------------- -void numpowi32x(_Inout_ PNUMBER* proot, _In_ int32_t power) +void numpowi32x(_Inout_ PNUMBER* proot, int32_t power) { PNUMBER lret = i32tonum(1, BASEX); @@ -215,7 +215,7 @@ void _divnumx(PNUMBER* pa, PNUMBER b, int32_t precision); // //---------------------------------------------------------------------------- -void divnumx(PNUMBER* pa, PNUMBER b, int32_t precision) +void divnumx(_Inout_ PNUMBER* pa, _In_ PNUMBER b, int32_t precision) { if (b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0) diff --git a/src/CalcManager/Ratpack/conv.cpp b/src/CalcManager/Ratpack/conv.cpp index d96fe306..68873c91 100644 --- a/src/CalcManager/Ratpack/conv.cpp +++ b/src/CalcManager/Ratpack/conv.cpp @@ -145,7 +145,7 @@ void _dupnum(_In_ PNUMBER dest, _In_ const NUMBER* const src) // //----------------------------------------------------------------------------- -void _destroynum(_In_ PNUMBER pnum) +void _destroynum(_Frees_ptr_opt_ PNUMBER pnum) { if (pnum != nullptr) @@ -167,7 +167,7 @@ void _destroynum(_In_ PNUMBER pnum) // //----------------------------------------------------------------------------- -void _destroyrat(_In_ PRAT prat) +void _destroyrat(_Frees_ptr_opt_ PRAT prat) { if (prat != nullptr) @@ -760,7 +760,7 @@ PNUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precis // //----------------------------------------------------------------------------- -PRAT i32torat(_In_ int32_t ini32) +PRAT i32torat(int32_t ini32) { PRAT pratret = nullptr; @@ -784,7 +784,7 @@ PRAT i32torat(_In_ int32_t ini32) // //----------------------------------------------------------------------------- -PRAT Ui32torat(_In_ uint32_t inui32) +PRAT Ui32torat(uint32_t inui32) { PRAT pratret = nullptr; diff --git a/src/CalcManager/Ratpack/exp.cpp b/src/CalcManager/Ratpack/exp.cpp index 1252002d..23257f73 100644 --- a/src/CalcManager/Ratpack/exp.cpp +++ b/src/CalcManager/Ratpack/exp.cpp @@ -39,7 +39,7 @@ // //----------------------------------------------------------------------------- -void _exprat(PRAT* px, int32_t precision) +void _exprat(_Inout_ PRAT* px, int32_t precision) { CREATETAYLOR(); @@ -58,7 +58,7 @@ void _exprat(PRAT* px, int32_t precision) DESTROYTAYLOR(); } -void exprat(PRAT* px, uint32_t radix, int32_t precision) +void exprat(_Inout_ PRAT* px, uint32_t radix, int32_t precision) { PRAT pwr = nullptr; @@ -150,7 +150,7 @@ void _lograt(PRAT* px, int32_t precision) DESTROYTAYLOR(); } -void lograt(PRAT* px, int32_t precision) +void lograt(_Inout_ PRAT* px, int32_t precision) { bool fneglog; @@ -224,7 +224,7 @@ void lograt(PRAT* px, int32_t precision) destroyrat(pwr); } -void log10rat(PRAT* px, int32_t precision) +void log10rat(_Inout_ PRAT* px, int32_t precision) { lograt(px, precision); @@ -267,7 +267,7 @@ bool IsEven(PRAT x, uint32_t radix, int32_t precision) // // //--------------------------------------------------------------------------- -void powrat(PRAT* px, PRAT y, uint32_t radix, int32_t precision) +void powrat(_Inout_ PRAT* px, _In_ PRAT y, uint32_t radix, int32_t precision) { // Handle cases where px or y is 0 by calling powratcomp directly if (zerrat(*px) || zerrat(y)) @@ -294,7 +294,7 @@ void powrat(PRAT* px, PRAT y, uint32_t radix, int32_t precision) } } -void powratNumeratorDenominator(PRAT* px, PRAT y, uint32_t radix, int32_t precision) +void powratNumeratorDenominator(_Inout_ PRAT* px, _In_ PRAT y, uint32_t radix, int32_t precision) { // Prepare rationals PRAT yNumerator = nullptr; @@ -403,7 +403,7 @@ void powratNumeratorDenominator(PRAT* px, PRAT y, uint32_t radix, int32_t precis // // //--------------------------------------------------------------------------- -void powratcomp(PRAT* px, PRAT y, uint32_t radix, int32_t precision) +void powratcomp(_Inout_ PRAT* px, _In_ PRAT y, uint32_t radix, int32_t precision) { int32_t sign = SIGN(*px); diff --git a/src/CalcManager/Ratpack/fact.cpp b/src/CalcManager/Ratpack/fact.cpp index 4bb2a71a..c026e536 100644 --- a/src/CalcManager/Ratpack/fact.cpp +++ b/src/CalcManager/Ratpack/fact.cpp @@ -190,7 +190,7 @@ void _gamma(PRAT* pn, uint32_t radix, int32_t precision) destroyrat(sum); } -void factrat(PRAT* px, uint32_t radix, int32_t precision) +void factrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision) { PRAT fact = nullptr; diff --git a/src/CalcManager/Ratpack/itrans.cpp b/src/CalcManager/Ratpack/itrans.cpp index 18c1fb41..9bb94358 100644 --- a/src/CalcManager/Ratpack/itrans.cpp +++ b/src/CalcManager/Ratpack/itrans.cpp @@ -83,7 +83,7 @@ void asinanglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_ ascalerat(pa, angletype, precision); } -void asinrat(PRAT* px, uint32_t radix, int32_t precision) +void asinrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision) { PRAT pret = nullptr; @@ -190,7 +190,7 @@ void _acosrat(PRAT* px, int32_t precision) DESTROYTAYLOR(); } -void acosrat(PRAT* px, uint32_t radix, int32_t precision) +void acosrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision) { int32_t sgn = SIGN(*px); @@ -276,7 +276,7 @@ void _atanrat(PRAT* px, int32_t precision) DESTROYTAYLOR(); } -void atanrat(PRAT* px, uint32_t radix, int32_t precision) +void atanrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision) { PRAT tmpx = nullptr; diff --git a/src/CalcManager/Ratpack/itransh.cpp b/src/CalcManager/Ratpack/itransh.cpp index d1ec113f..36c3c48f 100644 --- a/src/CalcManager/Ratpack/itransh.cpp +++ b/src/CalcManager/Ratpack/itransh.cpp @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. //----------------------------------------------------------------------------- @@ -47,7 +47,7 @@ // //----------------------------------------------------------------------------- -void asinhrat(PRAT* px, uint32_t radix, int32_t precision) +void asinhrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision) { PRAT neg_pt_eight_five = nullptr; @@ -101,7 +101,7 @@ void asinhrat(PRAT* px, uint32_t radix, int32_t precision) // //----------------------------------------------------------------------------- -void acoshrat(PRAT* px, uint32_t radix, int32_t precision) +void acoshrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision) { if (rat_lt(*px, rat_one, precision)) @@ -138,7 +138,7 @@ void acoshrat(PRAT* px, uint32_t radix, int32_t precision) // //----------------------------------------------------------------------------- -void atanhrat(PRAT* px, int32_t precision) +void atanhrat(_Inout_ PRAT* px, int32_t precision) { PRAT ptmp = nullptr; diff --git a/src/CalcManager/Ratpack/logic.cpp b/src/CalcManager/Ratpack/logic.cpp index b3970ef4..c9094f33 100644 --- a/src/CalcManager/Ratpack/logic.cpp +++ b/src/CalcManager/Ratpack/logic.cpp @@ -17,7 +17,7 @@ using namespace std; -void lshrat(PRAT* pa, PRAT b, uint32_t radix, int32_t precision) +void lshrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision) { PRAT pwr = nullptr; @@ -40,7 +40,7 @@ void lshrat(PRAT* pa, PRAT b, uint32_t radix, int32_t precision) } } -void rshrat(PRAT* pa, PRAT b, uint32_t radix, int32_t precision) +void rshrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision) { PRAT pwr = nullptr; @@ -73,19 +73,19 @@ enum FUNC_XOR } BOOL_FUNCS; -void andrat(PRAT* pa, PRAT b, uint32_t radix, int32_t precision) +void andrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision) { boolrat(pa, b, FUNC_AND, radix, precision); } -void orrat(PRAT* pa, PRAT b, uint32_t radix, int32_t precision) +void orrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision) { boolrat(pa, b, FUNC_OR, radix, precision); } -void xorrat(PRAT* pa, PRAT b, uint32_t radix, int32_t precision) +void xorrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision) { boolrat(pa, b, FUNC_XOR, radix, precision); @@ -191,7 +191,7 @@ void boolnum(PNUMBER* pa, PNUMBER b, int func) // //----------------------------------------------------------------------------- -void remrat(PRAT* pa, PRAT b) +void remrat(_Inout_ PRAT* pa, _In_ PRAT b) { if (zerrat(b)) @@ -228,7 +228,7 @@ void remrat(PRAT* pa, PRAT b) // //----------------------------------------------------------------------------- -void modrat(PRAT* pa, PRAT b) +void modrat(_Inout_ PRAT* pa, _In_ PRAT b) { // contrary to remrat(X, 0) returning 0, modrat(X, 0) must return X if (zerrat(b)) diff --git a/src/CalcManager/Ratpack/num.cpp b/src/CalcManager/Ratpack/num.cpp index 773f0b7d..c4561052 100644 --- a/src/CalcManager/Ratpack/num.cpp +++ b/src/CalcManager/Ratpack/num.cpp @@ -43,7 +43,7 @@ using namespace std; void _addnum(PNUMBER* pa, PNUMBER b, uint32_t radix); -void addnum(PNUMBER* pa, PNUMBER b, uint32_t radix) +void addnum(_Inout_ PNUMBER* pa, _In_ PNUMBER b, uint32_t radix) { if (b->cdigit > 1 || b->mant[0] != 0) @@ -186,7 +186,7 @@ void _addnum(PNUMBER* pa, PNUMBER b, uint32_t radix) void _mulnum(PNUMBER* pa, PNUMBER b, uint32_t radix); -void mulnum(PNUMBER* pa, PNUMBER b, uint32_t radix) +void mulnum(_Inout_ PNUMBER* pa, _In_ PNUMBER b, uint32_t radix) { if (b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0) @@ -302,7 +302,7 @@ void _mulnum(PNUMBER* pa, PNUMBER b, uint32_t radix) // //---------------------------------------------------------------------------- -void remnum(PNUMBER* pa, PNUMBER b, uint32_t radix) +void remnum(_Inout_ PNUMBER* pa, _In_ PNUMBER b, uint32_t radix) { PNUMBER tmp = nullptr; // tmp is the working remainder. @@ -365,7 +365,7 @@ void remnum(PNUMBER* pa, PNUMBER b, uint32_t radix) void _divnum(PNUMBER* pa, PNUMBER b, uint32_t radix, int32_t precision); -void divnum(PNUMBER* pa, PNUMBER b, uint32_t radix, int32_t precision) +void divnum(_Inout_ PNUMBER* pa, _In_ PNUMBER b, uint32_t radix, int32_t precision) { if (b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0) @@ -489,7 +489,7 @@ void _divnum(PNUMBER* pa, PNUMBER b, uint32_t radix, int32_t precision) // //--------------------------------------------------------------------------- -bool equnum(PNUMBER a, PNUMBER b) +bool equnum(_In_ PNUMBER a, _In_ PNUMBER b) { int32_t diff; @@ -555,7 +555,7 @@ bool equnum(PNUMBER a, PNUMBER b) // //--------------------------------------------------------------------------- -bool lessnum(PNUMBER a, PNUMBER b) +bool lessnum(_In_ PNUMBER a, _In_ PNUMBER b) { int32_t diff; @@ -614,7 +614,7 @@ bool lessnum(PNUMBER a, PNUMBER b) // //---------------------------------------------------------------------------- -bool zernum(PNUMBER a) +bool zernum(_In_ PNUMBER a) { int32_t length; diff --git a/src/CalcManager/Ratpack/rat.cpp b/src/CalcManager/Ratpack/rat.cpp index 4315add1..c0566038 100644 --- a/src/CalcManager/Ratpack/rat.cpp +++ b/src/CalcManager/Ratpack/rat.cpp @@ -37,7 +37,7 @@ using namespace std; // //----------------------------------------------------------------------------- -void gcdrat(PRAT* pa, int32_t precision) +void gcdrat(_Inout_ PRAT* pa, int32_t precision) { PNUMBER pgcd = nullptr; @@ -70,7 +70,7 @@ void gcdrat(PRAT* pa, int32_t precision) // //----------------------------------------------------------------------------- -void fracrat(PRAT* pa, uint32_t radix, int32_t precision) +void fracrat(_Inout_ PRAT* pa, uint32_t radix, int32_t precision) { // Only do the flatrat operation if number is nonzero. // and only if the bottom part is not one. @@ -98,7 +98,7 @@ void fracrat(PRAT* pa, uint32_t radix, int32_t precision) // //----------------------------------------------------------------------------- -void mulrat(PRAT* pa, PRAT b, int32_t precision) +void mulrat(_Inout_ PRAT* pa, _In_ PRAT b, int32_t precision) { // Only do the multiply if it isn't zero. @@ -132,7 +132,7 @@ void mulrat(PRAT* pa, PRAT b, int32_t precision) // //----------------------------------------------------------------------------- -void divrat(PRAT* pa, PRAT b, int32_t precision) +void divrat(_Inout_ PRAT* pa, _In_ PRAT b, int32_t precision) { if (!zernum((*pa)->pp)) @@ -182,7 +182,7 @@ void divrat(PRAT* pa, PRAT b, int32_t precision) // //----------------------------------------------------------------------------- -void subrat(PRAT* pa, PRAT b, int32_t precision) +void subrat(_Inout_ PRAT* pa, _In_ PRAT b, int32_t precision) { b->pp->sign *= -1; @@ -203,7 +203,7 @@ void subrat(PRAT* pa, PRAT b, int32_t precision) // //----------------------------------------------------------------------------- -void addrat(PRAT* pa, PRAT b, int32_t precision) +void addrat(_Inout_ PRAT* pa, _In_ PRAT b, int32_t precision) { PNUMBER bot = nullptr; @@ -255,7 +255,7 @@ void addrat(PRAT* pa, PRAT b, int32_t precision) // //----------------------------------------------------------------------------- -void rootrat(PRAT* py, PRAT n, uint32_t radix, int32_t precision) +void rootrat(_Inout_ PRAT* py, _In_ PRAT n, uint32_t radix, int32_t precision) { // Initialize 1/n PRAT oneovern = nullptr; @@ -280,7 +280,7 @@ void rootrat(PRAT* py, PRAT n, uint32_t radix, int32_t precision) // //----------------------------------------------------------------------------- -bool zerrat(PRAT a) +bool zerrat(_In_ PRAT a) { return (zernum(a->pp)); diff --git a/src/CalcManager/Ratpack/ratpak.h b/src/CalcManager/Ratpack/ratpak.h index dc6a98d9..18b2d024 100644 --- a/src/CalcManager/Ratpack/ratpak.h +++ b/src/CalcManager/Ratpack/ratpak.h @@ -369,7 +369,7 @@ extern PNUMBER i32factnum(int32_t ini32, uint32_t radix); extern PNUMBER i32prodnum(int32_t start, int32_t stop, uint32_t radix); extern PNUMBER i32tonum(int32_t ini32, uint32_t radix); extern PNUMBER Ui32tonum(uint32_t ini32, uint32_t radix); -extern PNUMBER numtonRadixx(PNUMBER a, uint32_t radix); +extern PNUMBER numtonRadixx(_In_ PNUMBER a, uint32_t radix); // creates a empty/undefined rational representation (p/q) extern PRAT _createrat(void); @@ -446,8 +446,8 @@ extern void tananglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, extern void _dupnum(_In_ PNUMBER dest, _In_ const NUMBER* const src); -extern void _destroynum(_In_ PNUMBER pnum); -extern void _destroyrat(_In_ PRAT prat); +extern void _destroynum(_Frees_ptr_opt_ PNUMBER pnum); +extern void _destroyrat(_Frees_ptr_opt_ PRAT prat); extern void addnum(_Inout_ PNUMBER* pa, _In_ PNUMBER b, uint32_t radix); extern void addrat(_Inout_ PRAT* pa, _In_ PRAT b, int32_t precision); extern void andrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision); diff --git a/src/CalcManager/Ratpack/support.cpp b/src/CalcManager/Ratpack/support.cpp index a46b180c..81c737f5 100644 --- a/src/CalcManager/Ratpack/support.cpp +++ b/src/CalcManager/Ratpack/support.cpp @@ -296,7 +296,7 @@ void ChangeConstants(uint32_t radix, int32_t precision) // //---------------------------------------------------------------------------- -void intrat(PRAT* px, uint32_t radix, int32_t precision) +void intrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision) { // Only do the intrat operation if number is nonzero. // and only if the bottom part is not one. @@ -328,7 +328,7 @@ void intrat(PRAT* px, uint32_t radix, int32_t precision) // //--------------------------------------------------------------------------- -bool rat_equ(PRAT a, PRAT b, int32_t precision) +bool rat_equ(_In_ PRAT a, _In_ PRAT b, int32_t precision) { PRAT rattmp = nullptr; @@ -351,7 +351,7 @@ bool rat_equ(PRAT a, PRAT b, int32_t precision) // //--------------------------------------------------------------------------- -bool rat_ge(PRAT a, PRAT b, int32_t precision) +bool rat_ge(_In_ PRAT a, _In_ PRAT b, int32_t precision) { PRAT rattmp = nullptr; @@ -375,7 +375,7 @@ bool rat_ge(PRAT a, PRAT b, int32_t precision) // //--------------------------------------------------------------------------- -bool rat_gt(PRAT a, PRAT b, int32_t precision) +bool rat_gt(_In_ PRAT a, _In_ PRAT b, int32_t precision) { PRAT rattmp = nullptr; @@ -399,7 +399,7 @@ bool rat_gt(PRAT a, PRAT b, int32_t precision) // //--------------------------------------------------------------------------- -bool rat_le(PRAT a, PRAT b, int32_t precision) +bool rat_le(_In_ PRAT a, _In_ PRAT b, int32_t precision) { PRAT rattmp = nullptr; @@ -423,7 +423,7 @@ bool rat_le(PRAT a, PRAT b, int32_t precision) // //--------------------------------------------------------------------------- -bool rat_lt(PRAT a, PRAT b, int32_t precision) +bool rat_lt(_In_ PRAT a, _In_ PRAT b, int32_t precision) { PRAT rattmp = nullptr; @@ -447,7 +447,7 @@ bool rat_lt(PRAT a, PRAT b, int32_t precision) // //--------------------------------------------------------------------------- -bool rat_neq(PRAT a, PRAT b, int32_t precision) +bool rat_neq(_In_ PRAT a, _In_ PRAT b, int32_t precision) { PRAT rattmp = nullptr; @@ -470,7 +470,7 @@ bool rat_neq(PRAT a, PRAT b, int32_t precision) // //--------------------------------------------------------------------------- -void scale(PRAT* px, PRAT scalefact, uint32_t radix, int32_t precision) +void scale(_Inout_ PRAT* px, _In_ PRAT scalefact, uint32_t radix, int32_t precision) { PRAT pret = nullptr; DUPRAT(pret, *px); @@ -503,7 +503,7 @@ void scale(PRAT* px, PRAT scalefact, uint32_t radix, int32_t precision) // //--------------------------------------------------------------------------- -void scale2pi(PRAT* px, uint32_t radix, int32_t precision) +void scale2pi(_Inout_ PRAT* px, uint32_t radix, int32_t precision) { PRAT pret = nullptr; PRAT my_two_pi = nullptr; @@ -546,7 +546,7 @@ void scale2pi(PRAT* px, uint32_t radix, int32_t precision) // //--------------------------------------------------------------------------- -void inbetween(PRAT* px, PRAT range, int32_t precision) +void inbetween(_In_ PRAT* px, _In_ PRAT range, int32_t precision) { if (rat_gt(*px, range, precision)) @@ -575,7 +575,7 @@ void inbetween(PRAT* px, PRAT range, int32_t precision) // //--------------------------------------------------------------------------- -void _dumprawrat(const wchar_t* varname, PRAT rat, wostream& out) +void _dumprawrat(_In_ const wchar_t* varname, _In_ PRAT rat, wostream& out) { _dumprawnum(varname, rat->pp, out); @@ -593,7 +593,7 @@ void _dumprawrat(const wchar_t* varname, PRAT rat, wostream& out) // //--------------------------------------------------------------------------- -void _dumprawnum(const wchar_t* varname, PNUMBER num, wostream& out) +void _dumprawnum(_In_ const wchar_t* varname, _In_ PNUMBER num, wostream& out) { int i; @@ -676,7 +676,7 @@ void _readconstants(void) // //--------------------------------------------------------------------------- -void trimit(PRAT* px, int32_t precision) +void trimit(_Inout_ PRAT* px, int32_t precision) { if (!g_ftrueinfinite) diff --git a/src/CalcManager/Ratpack/trans.cpp b/src/CalcManager/Ratpack/trans.cpp index 30104abb..e848155d 100644 --- a/src/CalcManager/Ratpack/trans.cpp +++ b/src/CalcManager/Ratpack/trans.cpp @@ -187,7 +187,7 @@ void _cosrat(PRAT* px, uint32_t radix, int32_t precision) } } -void cosrat(PRAT* px, uint32_t radix, int32_t precision) +void cosrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision) { scale2pi(px, radix, precision); _cosrat(px, radix, precision); @@ -257,7 +257,7 @@ void _tanrat(PRAT* px, uint32_t radix, int32_t precision) destroyrat(ptmp); } -void tanrat(PRAT* px, uint32_t radix, int32_t precision) +void tanrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision) { scale2pi(px, radix, precision); _tanrat(px, radix, precision); diff --git a/src/CalcManager/Ratpack/transh.cpp b/src/CalcManager/Ratpack/transh.cpp index 006db769..8e033aa5 100644 --- a/src/CalcManager/Ratpack/transh.cpp +++ b/src/CalcManager/Ratpack/transh.cpp @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. //----------------------------------------------------------------------------- @@ -88,7 +88,7 @@ void _sinhrat(PRAT* px, int32_t precision) DESTROYTAYLOR(); } -void sinhrat(PRAT* px, uint32_t radix, int32_t precision) +void sinhrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision) { PRAT tmpx = nullptr; @@ -169,7 +169,7 @@ void _coshrat(PRAT* px, uint32_t radix, int32_t precision) DESTROYTAYLOR(); } -void coshrat(PRAT* px, uint32_t radix, int32_t precision) +void coshrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision) { PRAT tmpx = nullptr; @@ -211,7 +211,7 @@ void coshrat(PRAT* px, uint32_t radix, int32_t precision) // //----------------------------------------------------------------------------- -void tanhrat(PRAT* px, uint32_t radix, int32_t precision) +void tanhrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision) { PRAT ptmp = nullptr; diff --git a/src/CalcManager/UnitConverter.cpp b/src/CalcManager/UnitConverter.cpp index eb361fa5..2c9eb2b3 100644 --- a/src/CalcManager/UnitConverter.cpp +++ b/src/CalcManager/UnitConverter.cpp @@ -401,43 +401,43 @@ void UnitConverter::SendCommand(Command command) switch (command) { case Command::Zero: - m_currentDisplay += L"0"; + m_currentDisplay += L'0'; break; case Command::One: - m_currentDisplay += L"1"; + m_currentDisplay += L'1'; break; case Command::Two: - m_currentDisplay += L"2"; + m_currentDisplay += L'2'; break; case Command::Three: - m_currentDisplay += L"3"; + m_currentDisplay += L'3'; break; case Command::Four: - m_currentDisplay += L"4"; + m_currentDisplay += L'4'; break; case Command::Five: - m_currentDisplay += L"5"; + m_currentDisplay += L'5'; break; case Command::Six: - m_currentDisplay += L"6"; + m_currentDisplay += L'6'; break; case Command::Seven: - m_currentDisplay += L"7"; + m_currentDisplay += L'7'; break; case Command::Eight: - m_currentDisplay += L"8"; + m_currentDisplay += L'8'; break; case Command::Nine: - m_currentDisplay += L"9"; + m_currentDisplay += L'9'; break; case Command::Decimal: @@ -445,7 +445,7 @@ void UnitConverter::SendCommand(Command command) clearBack = false; if (!m_currentHasDecimal) { - m_currentDisplay += L"."; + m_currentDisplay += L'.'; m_currentHasDecimal = true; } break; diff --git a/src/CalcManager/pch.h b/src/CalcManager/pch.h index 9207ebff..288bbc91 100644 --- a/src/CalcManager/pch.h +++ b/src/CalcManager/pch.h @@ -22,3 +22,5 @@ #include #include #include +#include +#include diff --git a/src/CalcViewModel/ApplicationViewModel.cpp b/src/CalcViewModel/ApplicationViewModel.cpp index 90e55e69..066c9842 100644 --- a/src/CalcViewModel/ApplicationViewModel.cpp +++ b/src/CalcViewModel/ApplicationViewModel.cpp @@ -43,7 +43,7 @@ namespace ApplicationViewModel::ApplicationViewModel() : m_CalculatorViewModel(nullptr) , m_DateCalcViewModel(nullptr) - , m_GraphingCalcViewModel(nullptr) + , m_GraphingCalcViewModel(nullptr) , m_ConverterViewModel(nullptr) , m_PreviousMode(ViewMode::None) , m_mode(ViewMode::None) @@ -86,7 +86,7 @@ void ApplicationViewModel::Initialize(ViewMode mode) } catch (const std::exception& e) { - TraceLogger::GetInstance().LogStandardException(mode, __FUNCTIONW__, e); + TraceLogger::GetInstance()->LogStandardException(mode, __FUNCTIONW__, e); if (!TryRecoverFromNavigationModeFailure()) { // Could not navigate to standard mode either. @@ -96,7 +96,7 @@ void ApplicationViewModel::Initialize(ViewMode mode) } catch (Exception ^ e) { - TraceLogger::GetInstance().LogPlatformException(mode, __FUNCTIONW__, e); + TraceLogger::GetInstance()->LogPlatformException(mode, __FUNCTIONW__, e); if (!TryRecoverFromNavigationModeFailure()) { // Could not navigate to standard mode either. @@ -160,7 +160,7 @@ void ApplicationViewModel::OnModeChanged() } auto resProvider = AppResourceProvider::GetInstance(); - CategoryName = resProvider.GetResourceString(NavCategory::GetNameResourceKey(m_mode)); + CategoryName = resProvider->GetResourceString(NavCategory::GetNameResourceKey(m_mode)); // Cast mode to an int in order to save it to app data. // Save the changed mode, so that the new window launches in this mode. @@ -170,11 +170,11 @@ void ApplicationViewModel::OnModeChanged() // Log ModeChange event when not first launch, log WindowCreated on first launch if (NavCategory::IsValidViewMode(m_PreviousMode)) { - TraceLogger::GetInstance().LogModeChange(m_mode); + TraceLogger::GetInstance()->LogModeChange(m_mode); } else { - TraceLogger::GetInstance().LogWindowCreated(m_mode, ApplicationView::GetApplicationViewIdForWindow(CoreWindow::GetForCurrentThread())); + TraceLogger::GetInstance()->LogWindowCreated(m_mode, ApplicationView::GetApplicationViewIdForWindow(CoreWindow::GetForCurrentThread())); } RaisePropertyChanged(ClearMemoryVisibilityPropertyName); diff --git a/src/CalcViewModel/CalcViewModel.vcxproj b/src/CalcViewModel/CalcViewModel.vcxproj index e7b661da..829e600d 100644 --- a/src/CalcViewModel/CalcViewModel.vcxproj +++ b/src/CalcViewModel/CalcViewModel.vcxproj @@ -315,12 +315,8 @@ - - - - @@ -341,6 +337,7 @@ + @@ -361,16 +358,12 @@ - - - - @@ -407,7 +400,6 @@ - @@ -440,12 +432,12 @@ - + - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see https://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + diff --git a/src/CalcViewModel/CalcViewModel.vcxproj.filters b/src/CalcViewModel/CalcViewModel.vcxproj.filters index 3414655e..9e97ecb8 100644 --- a/src/CalcViewModel/CalcViewModel.vcxproj.filters +++ b/src/CalcViewModel/CalcViewModel.vcxproj.filters @@ -1,15 +1,28 @@  + + {1daab7c4-63f6-4266-a259-f34acad66d09} + + + {8d4edf06-c312-4312-978a-b6c2beb8295a} + + + {0184f727-b8aa-4af8-a699-63f1b56e7853} + + + {cf7dca32-9727-4f98-83c3-1c0ca7dd1e0c} + + + + - - Common @@ -58,63 +71,53 @@ Common - - Common\Automation - - - Common\Automation - Common\Automation - - Common\Automation - - - Common\Automation - - + DataLoaders DataLoaders - - GraphingCalculator + + DataLoaders GraphingCalculator - - DataLoaders + + GraphingCalculator + + + Common\Automation + + - - - + + Common + Common Common - - Common - - - Common - Common + + Common + Common @@ -145,25 +148,22 @@ Common - - Common - Common Common - + Common Common - + Common - + Common @@ -175,26 +175,14 @@ Common - - Common - - - Common\Automation - - - Common\Automation - Common\Automation - - Common\Automation + + DataLoaders - - Common\Automation - - - Common\Automation + + DataLoaders DataLoaders @@ -205,43 +193,38 @@ DataLoaders + + Common + DataLoaders - - DataLoaders + + Common\Automation - - GraphingCalculator + + Common + + + Common GraphingCalculator - - DataLoaders + + GraphingCalculator Common - DataLoaders + - - {98717b14-c8c7-4fb6-9861-abb9124b34f0} - - - {07311281-a1fd-4dd9-baef-007f159e33ed} - - - {14ddcbc1-10a4-4940-ad53-3a751b9ebea0} - - - {b017a5e6-6d25-4799-a517-99f88d65b82f} - + \ No newline at end of file diff --git a/src/CalcViewModel/Common/AppResourceProvider.cpp b/src/CalcViewModel/Common/AppResourceProvider.cpp index a75a375f..b843d55b 100644 --- a/src/CalcViewModel/Common/AppResourceProvider.cpp +++ b/src/CalcViewModel/Common/AppResourceProvider.cpp @@ -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" @@ -14,9 +14,9 @@ AppResourceProvider::AppResourceProvider() m_cEngineStringResLoader = ResourceLoader::GetForViewIndependentUse(L"CEngineStrings"); } -AppResourceProvider& AppResourceProvider::GetInstance() +AppResourceProvider ^ AppResourceProvider::GetInstance() { - static AppResourceProvider s_instance; + static AppResourceProvider ^ s_instance = ref new AppResourceProvider(); return s_instance; } diff --git a/src/CalcViewModel/Common/AppResourceProvider.h b/src/CalcViewModel/Common/AppResourceProvider.h index 8876fb91..be429a13 100644 --- a/src/CalcViewModel/Common/AppResourceProvider.h +++ b/src/CalcViewModel/Common/AppResourceProvider.h @@ -1,14 +1,14 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #pragma once namespace CalculatorApp { - class AppResourceProvider + public ref class AppResourceProvider sealed { public: - static AppResourceProvider& GetInstance(); + static AppResourceProvider ^ GetInstance(); Platform::String ^ GetResourceString(_In_ Platform::String ^ key); Platform::String ^ GetCEngineString(_In_ Platform::String ^ key); diff --git a/src/CalcViewModel/Common/Automation/NarratorAnnouncement.cpp b/src/CalcViewModel/Common/Automation/NarratorAnnouncement.cpp index 33825b08..15fca2c6 100644 --- a/src/CalcViewModel/Common/Automation/NarratorAnnouncement.cpp +++ b/src/CalcViewModel/Common/Automation/NarratorAnnouncement.cpp @@ -6,6 +6,7 @@ using namespace CalculatorApp::Common::Automation; using namespace Platform; +using namespace Windows::UI::Xaml::Automation::Peers; namespace CalculatorApp::Common::Automation { diff --git a/src/CalcViewModel/Common/Automation/NarratorAnnouncement.h b/src/CalcViewModel/Common/Automation/NarratorAnnouncement.h index e508675f..81c3856b 100644 --- a/src/CalcViewModel/Common/Automation/NarratorAnnouncement.h +++ b/src/CalcViewModel/Common/Automation/NarratorAnnouncement.h @@ -5,32 +5,6 @@ namespace CalculatorApp::Common::Automation { - // These enum types are copied from the types available in - // Windows::UI::Xaml::Automation::Peers in the RS3 SDK. - // When this app switches to min version RS3, these custom - // enums should be removed and the Windows types should be used - // instead. - // TODO - MSFT 12735088 -public - enum class AutomationNotificationKind - { - ItemAdded = 0, - ItemRemoved = 1, - ActionCompleted = 2, - ActionAborted = 3, - Other = 4 - }; - -public - enum class AutomationNotificationProcessing - { - ImportantAll = 0, - ImportantMostRecent = 1, - All = 2, - MostRecent = 3, - CurrentThenMostRecent = 4 - }; - public ref class NarratorAnnouncement sealed { @@ -41,14 +15,14 @@ public property Platform::String ^ ActivityId { Platform::String ^ get(); } - property AutomationNotificationKind Kind + property Windows::UI::Xaml::Automation::Peers::AutomationNotificationKind Kind { - AutomationNotificationKind get(); + Windows::UI::Xaml::Automation::Peers::AutomationNotificationKind get(); } - property AutomationNotificationProcessing Processing + property Windows::UI::Xaml::Automation::Peers::AutomationNotificationProcessing Processing { - AutomationNotificationProcessing get(); + Windows::UI::Xaml::Automation::Peers::AutomationNotificationProcessing get(); } static bool IsValid(NarratorAnnouncement ^ announcement); @@ -61,13 +35,13 @@ public NarratorAnnouncement( Platform::String ^ announcement, Platform::String ^ activityId, - AutomationNotificationKind kind, - AutomationNotificationProcessing processing); + Windows::UI::Xaml::Automation::Peers::AutomationNotificationKind kind, + Windows::UI::Xaml::Automation::Peers::AutomationNotificationProcessing processing); Platform::String ^ m_announcement; Platform::String ^ m_activityId; - AutomationNotificationKind m_kind; - AutomationNotificationProcessing m_processing; + Windows::UI::Xaml::Automation::Peers::AutomationNotificationKind m_kind; + Windows::UI::Xaml::Automation::Peers::AutomationNotificationProcessing m_processing; }; // CalculatorAnnouncement is intended to contain only static methods diff --git a/src/CalcViewModel/Common/Automation/NarratorNotifier.cpp b/src/CalcViewModel/Common/Automation/NarratorNotifier.cpp index bc146e68..89fa0c0b 100644 --- a/src/CalcViewModel/Common/Automation/NarratorNotifier.cpp +++ b/src/CalcViewModel/Common/Automation/NarratorNotifier.cpp @@ -5,7 +5,6 @@ #include "pch.h" #include "NarratorNotifier.h" -#include "NarratorAnnouncementHostFactory.h" using namespace CalculatorApp::Common::Automation; using namespace Platform; @@ -17,14 +16,22 @@ DependencyProperty ^ NarratorNotifier::s_announcementProperty; NarratorNotifier::NarratorNotifier() { - m_announcementHost = NarratorAnnouncementHostFactory::MakeHost(); } void NarratorNotifier::Announce(NarratorAnnouncement ^ announcement) { - if (NarratorAnnouncement::IsValid(announcement) && m_announcementHost != nullptr) + if (NarratorAnnouncement::IsValid(announcement)) { - m_announcementHost->Announce(announcement); + if (m_announcementElement == nullptr) + { + m_announcementElement = ref new Windows::UI::Xaml::Controls::TextBlock(); + } + + auto peer = FrameworkElementAutomationPeer::FromElement(m_announcementElement); + if (peer != nullptr) + { + peer->RaiseNotificationEvent(announcement->Kind, announcement->Processing, announcement->Announcement, announcement->ActivityId); + } } } diff --git a/src/CalcViewModel/Common/Automation/NarratorNotifier.h b/src/CalcViewModel/Common/Automation/NarratorNotifier.h index 55bed4e7..359bb09e 100644 --- a/src/CalcViewModel/Common/Automation/NarratorNotifier.h +++ b/src/CalcViewModel/Common/Automation/NarratorNotifier.h @@ -1,10 +1,10 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. // Declaration of the NarratorNotifier class. #pragma once -#include "INarratorAnnouncementHost.h" +#include "NarratorAnnouncement.h" namespace CalculatorApp::Common::Automation { @@ -47,6 +47,6 @@ public static Windows::UI::Xaml::DependencyProperty ^ s_announcementProperty; private: - INarratorAnnouncementHost ^ m_announcementHost; + Windows::UI::Xaml::UIElement ^ m_announcementElement; }; } diff --git a/src/CalcViewModel/Common/CalculatorButtonUser.h b/src/CalcViewModel/Common/CalculatorButtonUser.h index 5bf2cbe2..a8d176bc 100644 --- a/src/CalcViewModel/Common/CalculatorButtonUser.h +++ b/src/CalcViewModel/Common/CalculatorButtonUser.h @@ -63,6 +63,10 @@ public IsStandardMode = (int)CM::Command::ModeBasic, None = (int)CM::Command::CommandNULL, IsProgrammerMode = (int)CM::Command::ModeProgrammer, + DecButton = (int)CM::Command::CommandDec, + OctButton = (int)CM::Command::CommandOct, + HexButton = (int)CM::Command::CommandHex, + BinButton = (int)CM::Command::CommandBin, And = (int)CM::Command::CommandAnd, Ror = (int)CM::Command::CommandROR, Rol = (int)CM::Command::CommandROL, @@ -84,17 +88,38 @@ public InvSinh = (int)CM::Command::CommandASINH, InvCosh = (int)CM::Command::CommandACOSH, InvTanh = (int)CM::Command::CommandATANH, - Cube = (int) CM::Command::CommandCUB, - DMS = (int) CM::Command::CommandDMS, - Hyp = (int)CM::Command::CommandHYP, - HexButton = (int)CM::Command::CommandHex, - DecButton = (int)CM::Command::CommandDec, - OctButton = (int)CM::Command::CommandOct, - BinButton = (int)CM::Command::CommandBin, Qword = (int)CM::Command::CommandQword, Dword = (int)CM::Command::CommandDword, Word = (int)CM::Command::CommandWord, Byte = (int)CM::Command::CommandByte, + Cube = (int)CM::Command::CommandCUB, + DMS = (int)CM::Command::CommandDMS, + Hyp = (int) CM::Command::CommandHYP, + Sec = (int) CM::Command::CommandSEC, + Csc = (int) CM::Command::CommandCSC, + Cot = (int) CM::Command::CommandCOT, + InvSec = (int) CM::Command::CommandASEC, + InvCsc = (int) CM::Command::CommandACSC, + InvCot = (int) CM::Command::CommandACOT, + Sech = (int) CM::Command::CommandSECH, + Csch = (int) CM::Command::CommandCSCH, + Coth = (int) CM::Command::CommandCOTH, + InvSech = (int) CM::Command::CommandASECH, + InvCsch = (int) CM::Command::CommandACSCH, + InvCoth = (int) CM::Command::CommandACOTH, + CubeRoot = (int) CM::Command::CommandCUBEROOT, + TwoPowerX = (int) CM::Command::CommandPOW2, + LogBaseX = (int) CM::Command::CommandLogBaseX, + Nand = (int) CM::Command::CommandNand, + Nor = (int) CM::Command::CommandNor, + Abs = (int) CM::Command::CommandAbs, + Floor = (int) CM::Command::CommandFloor, + Ceil = (int) CM::Command::CommandCeil, + Rand = (int) CM::Command::CommandRand, + Euler = (int) CM::Command::CommandEuler, + RshL = (int)CM::Command::CommandRSHFL, + RolC = (int)CM::Command::CommandROLC, + RorC = (int)CM::Command::CommandRORC, Plot, X, diff --git a/src/CalcViewModel/Common/CalculatorDisplay.cpp b/src/CalcViewModel/Common/CalculatorDisplay.cpp index 91892dda..5cf8afbc 100644 --- a/src/CalcViewModel/Common/CalculatorDisplay.cpp +++ b/src/CalcViewModel/Common/CalculatorDisplay.cpp @@ -9,6 +9,7 @@ using namespace CalculatorApp; using namespace CalculationManager; +using namespace Platform; using namespace std; CalculatorDisplay::CalculatorDisplay() @@ -31,7 +32,7 @@ void CalculatorDisplay::SetPrimaryDisplay(_In_ const wstring& displayStringValue { if (auto calcVM = m_callbackReference.Resolve()) { - calcVM->SetPrimaryDisplay(displayStringValue, isError); + calcVM->SetPrimaryDisplay(StringReference(displayStringValue.c_str()), isError); } } } @@ -70,8 +71,8 @@ void CalculatorDisplay::SetIsInError(bool isError) } void CalculatorDisplay::SetExpressionDisplay( - _Inout_ std::shared_ptr>> const& tokens, - _Inout_ std::shared_ptr>> const& commands) + _Inout_ std::shared_ptr>> const& tokens, + _Inout_ std::shared_ptr>> const& commands) { if (m_callbackReference != nullptr) { @@ -136,3 +137,14 @@ void CalculatorDisplay::MemoryItemChanged(unsigned int indexOfMemory) } } } + +void CalculatorDisplay::InputChanged() +{ + if (m_callbackReference != nullptr) + { + if (auto calcVM = m_callbackReference.Resolve()) + { + calcVM->OnInputChanged(); + } + } +} diff --git a/src/CalcViewModel/Common/CalculatorDisplay.h b/src/CalcViewModel/Common/CalculatorDisplay.h index 93865c96..921260da 100644 --- a/src/CalcViewModel/Common/CalculatorDisplay.h +++ b/src/CalcViewModel/Common/CalculatorDisplay.h @@ -19,8 +19,8 @@ namespace CalculatorApp void SetPrimaryDisplay(_In_ const std::wstring& displayString, _In_ bool isError) override; void SetIsInError(bool isError) override; void SetExpressionDisplay( - _Inout_ std::shared_ptr>> const& tokens, - _Inout_ std::shared_ptr>> const& commands) override; + _Inout_ std::shared_ptr>> const& tokens, + _Inout_ std::shared_ptr>> const& commands) override; void SetMemorizedNumbers(_In_ const std::vector& memorizedNumbers) override; void OnHistoryItemAdded(_In_ unsigned int addedItemIndex) override; void SetParenthesisNumber(_In_ unsigned int parenthesisCount) override; @@ -28,6 +28,7 @@ namespace CalculatorApp void MaxDigitsReached() override; void BinaryOperatorReceived() override; void MemoryItemChanged(unsigned int indexOfMemory) override; + void InputChanged() override; private: Platform::WeakReference m_callbackReference; diff --git a/src/CalcViewModel/Common/CopyPasteManager.cpp b/src/CalcViewModel/Common/CopyPasteManager.cpp index 89c401dc..ade3a3fb 100644 --- a/src/CalcViewModel/Common/CopyPasteManager.cpp +++ b/src/CalcViewModel/Common/CopyPasteManager.cpp @@ -11,13 +11,18 @@ using namespace concurrency; using namespace CalculatorApp; using namespace CalculatorApp::Common; using namespace Platform; +using namespace Platform::Collections; using namespace Windows::Foundation; using namespace Windows::System; using namespace Windows::ApplicationModel::DataTransfer; +using namespace Windows::Foundation::Collections; -String ^ CopyPasteManager::supportedFormats[] = { StandardDataFormats::Text }; +StringReference PasteErrorString(L"NoOp"); -static constexpr wstring_view c_validCharacterSet{ L"0123456789()+-*/.abcdefABCDEF" }; +static const wstring c_validBasicCharacterSet = L"0123456789+-.e"; +static const wstring c_validStandardCharacterSet = c_validBasicCharacterSet + L"*/"; +static const wstring c_validScientificCharacterSet = c_validStandardCharacterSet + L"()^%"; +static const wstring c_validProgrammerCharacterSet = c_validStandardCharacterSet + L"()%abcdfABCDEF"; // The below values can not be "constexpr"-ed, // as both wstring_view and wchar[] can not be concatenated @@ -26,7 +31,8 @@ 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*"; +static const wstring c_signedDecFloat = L"(?:[-+]?(?:\\d+(\\.\\d*)?|\\.\\d+))"; +static const wstring c_optionalENotation = L"(?:e[+-]?\\d+)?"; // Programmer Mode Integer patterns // Support digit separators ` (WinDbg/MASM), ' (C++), and _ (C# and other languages) @@ -37,11 +43,9 @@ static const wstring c_binProgrammerChars = L"[0-1]+((_|'|`)[0-1]+)*"; static const wstring c_uIntSuffixes = L"[uU]?[lL]{0,2}"; // RegEx Patterns used by various modes -static const array standardModePatterns = { wregex(c_wspc + c_signedDecFloat + c_wspc) }; -static const array scientificModePatterns = { - wregex(L"(" + c_wspc + L"[-+]?)|(" + c_wspcLParenSigned + L")" + c_signedDecFloat + c_wspcRParens), - wregex(L"(" + c_wspc + L"[-+]?)|(" + c_wspcLParenSigned + L")" + c_signedDecFloat + L"e[+-]?\\d+" + c_wspcRParens) -}; +static const array standardModePatterns = { wregex(c_wspc + c_signedDecFloat + c_optionalENotation + c_wspc) }; +static const array scientificModePatterns = { wregex( + L"(" + c_wspc + L"[-+]?)|(" + c_wspcLParenSigned + L")" + c_signedDecFloat + c_optionalENotation + c_wspcRParens) }; static const array, 4> programmerModePatterns = { { // Hex numbers like 5F, 4A0C, 0xa9, 0xFFull, 47CDh { wregex(c_wspcLParens + L"(0[xX])?" + c_hexProgrammerChars + c_uIntSuffixes + c_wspcRParens), @@ -55,7 +59,7 @@ static const array, 4> programmerModePatterns = { { wregex(c_wspcLParens + L"(0[byBY])?" + c_binProgrammerChars + c_uIntSuffixes + c_wspcRParens), wregex(c_wspcLParens + c_binProgrammerChars + L"[bB]?" + c_wspcRParens) } } }; -static const array unitConverterPatterns = { wregex(c_wspc + L"[-+]?\\d*[.]?\\d*" + c_wspc) }; +static const array unitConverterPatterns = { wregex(c_wspc + c_signedDecFloat + c_wspc) }; void CopyPasteManager::CopyToClipboard(String ^ stringToCopy) { @@ -65,7 +69,7 @@ void CopyPasteManager::CopyToClipboard(String ^ stringToCopy) Clipboard::SetContent(dataPackage); } -task CopyPasteManager::GetStringToPaste(ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, BitLength bitLengthType) +IAsyncOperation ^ CopyPasteManager::GetStringToPaste(ViewMode mode, CategoryGroupType modeType, NumberBase programmerNumberBase, BitLength bitLengthType) { // Retrieve the text in the clipboard auto dataPackageView = Clipboard::GetContent(); @@ -75,51 +79,47 @@ task CopyPasteManager::GetStringToPaste(ViewMode mode, CategoryGroupTy //-- add support to allow pasting for expressions like .2 , -.2 //-- add support to allow pasting for expressions like 1.3e12(as of now we allow 1.3e+12) - return create_task((dataPackageView->GetTextAsync(::StandardDataFormats::Text))) - .then( - [mode, modeType, programmerNumberBase, bitLengthType](String ^ pastedText) { - return ValidatePasteExpression(pastedText, mode, modeType, programmerNumberBase, bitLengthType); - }, - task_continuation_context::use_arbitrary()); + return create_async([dataPackageView, mode, modeType, programmerNumberBase, bitLengthType] { + return create_task(dataPackageView->GetTextAsync(::StandardDataFormats::Text)) + .then( + [mode, modeType, programmerNumberBase, bitLengthType](String ^ pastedText) { + return ValidatePasteExpression(pastedText, mode, modeType, programmerNumberBase, bitLengthType); + }, + task_continuation_context::use_arbitrary()); + }); } -int CopyPasteManager::ClipboardTextFormat() +bool CopyPasteManager::HasStringToPaste() { - const auto dataPackageView = Clipboard::GetContent(); - - for (int i = 0; i < RTL_NUMBER_OF(supportedFormats); i++) - { - if (dataPackageView->Contains(supportedFormats[i])) - { - return i; - } - } - return -1; + return Clipboard::GetContent()->Contains(StandardDataFormats::Text); } -String ^ CopyPasteManager::ValidatePasteExpression(String ^ pastedText, ViewMode mode, int programmerNumberBase, BitLength bitLengthType) +String ^ CopyPasteManager::ValidatePasteExpression(String ^ pastedText, ViewMode mode, NumberBase programmerNumberBase, BitLength bitLengthType) { - return CopyPasteManager::ValidatePasteExpression(pastedText, mode, NavCategory::GetGroupType(mode), programmerNumberBase, bitLengthType); + return ValidatePasteExpression(pastedText, mode, NavCategory::GetGroupType(mode), programmerNumberBase, bitLengthType); } // return "NoOp" if pastedText is invalid else return pastedText - -String ^ CopyPasteManager::ValidatePasteExpression(String ^ pastedText, ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, BitLength bitLengthType) +String + ^ CopyPasteManager::ValidatePasteExpression( + String ^ pastedText, + ViewMode mode, + CategoryGroupType modeType, + NumberBase programmerNumberBase, + BitLength bitLengthType) { if (pastedText->Length() > MaxPasteableLength) { // return NoOp to indicate don't paste anything. - TraceLogger::GetInstance().LogError(mode, L"CopyPasteManager::ValidatePasteExpression", L"PastedExpressionSizeGreaterThanMaxAllowed"); - return StringReference(PasteErrorString); + TraceLogger::GetInstance()->LogError(mode, L"CopyPasteManager::ValidatePasteExpression", L"PastedExpressionSizeGreaterThanMaxAllowed"); + return PasteErrorString; } - wstring pasteExpression = pastedText->Data(); - // Get english translated expression - String ^ englishString = LocalizationSettings::GetInstance().GetEnglishValueFromLocalizedDigits(pasteExpression); + String ^ englishString = LocalizationSettings::GetInstance().GetEnglishValueFromLocalizedDigits(pastedText); // Removing the spaces, comma separator from the pasteExpression to allow pasting of expressions like 1 + 2+1,333 - pasteExpression = RemoveUnwantedCharsFromWstring(englishString->Data()); + auto pasteExpression = wstring(RemoveUnwantedCharsFromString(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'=') @@ -129,31 +129,32 @@ String ^ CopyPasteManager::ValidatePasteExpression(String ^ pastedText, ViewMode // Extract operands from the expression to make regex comparison easy and quick. For whole expression it was taking too much of time. // Operands vector will have the list of operands in the pasteExpression - vector operands = ExtractOperands(pasteExpression, mode); - if (operands.empty()) + auto operands = ExtractOperands(StringReference(pasteExpression.c_str()), mode); + if (operands->Size == 0) { // return NoOp to indicate don't paste anything. - return StringReference(PasteErrorString); + return PasteErrorString; } if (modeType == CategoryGroupType::Converter) { - operands = { pasteExpression }; + operands->Clear(); + operands->Append(ref new String(pasteExpression.c_str())); } // validate each operand with patterns for different modes if (!ExpressionRegExMatch(operands, mode, modeType, programmerNumberBase, bitLengthType)) { - TraceLogger::GetInstance().LogError(mode, L"CopyPasteManager::ValidatePasteExpression", L"InvalidExpressionForPresentMode"); - return StringReference(PasteErrorString); + TraceLogger::GetInstance()->LogError(mode, L"CopyPasteManager::ValidatePasteExpression", L"InvalidExpressionForPresentMode"); + return PasteErrorString; } - return ref new String(pastedText->Data()); + return pastedText; } -vector CopyPasteManager::ExtractOperands(const wstring& pasteExpression, ViewMode mode) +IVector ^ CopyPasteManager::ExtractOperands(Platform::String ^ pasteExpression, ViewMode mode) { - vector operands{}; + auto operands = ref new Vector(); size_t lastIndex = 0; bool haveOperator = false; bool startExpCounting = false; @@ -161,51 +162,72 @@ vector CopyPasteManager::ExtractOperands(const wstring& pasteExpression bool isPreviousOpenParen = false; bool isPreviousOperator = false; + wstring validCharacterSet; + switch (mode) + { + case ViewMode::Standard: + validCharacterSet = c_validStandardCharacterSet; + break; + case ViewMode::Scientific: + validCharacterSet = c_validScientificCharacterSet; + break; + case ViewMode::Programmer: + validCharacterSet = c_validProgrammerCharacterSet; + break; + default: + validCharacterSet = c_validBasicCharacterSet; + } + // This will have the exponent length size_t expLength = 0; - for (size_t i = 0; i < pasteExpression.length(); i++) + int i = -1; + for (auto currentChar : pasteExpression) { + ++i; // if the current character is not a valid one don't process it - if (c_validCharacterSet.find(pasteExpression.at(i)) == wstring_view::npos) + if (validCharacterSet.find(currentChar) == wstring_view::npos) { continue; } - if (operands.size() >= MaxOperandCount) + if (operands->Size >= MaxOperandCount) { - TraceLogger::GetInstance().LogError(mode, L"CopyPasteManager::ExtractOperands", L"OperandCountGreaterThanMaxCount"); - operands.clear(); + TraceLogger::GetInstance()->LogError(mode, L"CopyPasteManager::ExtractOperands", L"OperandCountGreaterThanMaxCount"); + operands->Clear(); return operands; } - if (startExpCounting) + if (currentChar >= L'0' && currentChar <= L'9') { - if ((pasteExpression.at(i) >= L'0') && (pasteExpression.at(i) <= L'9')) + if (startExpCounting) { expLength++; // to disallow pasting of 1e+12345 as 1e+1234, max exponent that can be pasted is 9999. if (expLength > MaxExponentLength) { - TraceLogger::GetInstance().LogError(mode, L"CopyPasteManager::ExtractOperands", L"ExponentLengthGreaterThanMaxLength"); - operands.clear(); + TraceLogger::GetInstance()->LogError(mode, L"CopyPasteManager::ExtractOperands", L"ExponentLengthGreaterThanMaxLength"); + operands->Clear(); return operands; } } + isPreviousOperator = false; } - - if ((mode != ViewMode::Programmer) && (pasteExpression.at(i) == L'e')) + else if (currentChar == L'e') { - startExpCounting = true; + if (mode != ViewMode::Programmer) + { + startExpCounting = true; + } + isPreviousOperator = false; } - - if (((pasteExpression.at(i) == L'+') || (pasteExpression.at(i) == L'-') || (pasteExpression.at(i) == L'*') || (pasteExpression.at(i) == L'/'))) + else if (currentChar == L'+' || currentChar == L'-' || currentChar == L'*' || currentChar == L'/' || currentChar == L'^' || currentChar == L'%') { - if ((pasteExpression.at(i) == L'+') || (pasteExpression.at(i) == L'-')) + if (currentChar == L'+' || currentChar == L'-') { // don't break the expression into operands if the encountered character corresponds to sign command(+-) if (isPreviousOpenParen || startOfExpression || isPreviousOperator - || ((mode != ViewMode::Programmer) && !((i != 0) && (pasteExpression.at(i - 1) != L'e')))) + || ((mode != ViewMode::Programmer) && !((i != 0) && pasteExpression->Data()[i - 1] != L'e'))) { isPreviousOperator = false; continue; @@ -216,7 +238,7 @@ vector CopyPasteManager::ExtractOperands(const wstring& pasteExpression expLength = 0; haveOperator = true; isPreviousOperator = true; - operands.push_back(pasteExpression.substr(lastIndex, i - lastIndex)); + operands->Append(ref new String(wstring(pasteExpression->Data()).substr(lastIndex, i - lastIndex).c_str())); lastIndex = i + 1; } else @@ -224,26 +246,31 @@ vector CopyPasteManager::ExtractOperands(const wstring& pasteExpression isPreviousOperator = false; } - isPreviousOpenParen = (pasteExpression.at(i) == L'('); + isPreviousOpenParen = (currentChar == L'('); startOfExpression = false; } if (!haveOperator) { - operands.clear(); - operands.push_back(pasteExpression); + operands->Clear(); + operands->Append(pasteExpression); } else { - operands.push_back(pasteExpression.substr(lastIndex, pasteExpression.length() - 1)); + operands->Append(ref new String(wstring(pasteExpression->Data()).substr(lastIndex, pasteExpression->Length() - 1).c_str())); } return operands; } -bool CopyPasteManager::ExpressionRegExMatch(vector operands, ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, BitLength bitLengthType) +bool CopyPasteManager::ExpressionRegExMatch( + IVector ^ operands, + ViewMode mode, + CategoryGroupType modeType, + NumberBase programmerNumberBase, + BitLength bitLengthType) { - if (operands.empty()) + if (operands->Size == 0) { return false; } @@ -260,14 +287,16 @@ bool CopyPasteManager::ExpressionRegExMatch(vector operands, ViewMode m } else if (mode == ViewMode::Programmer) { - patterns.assign(programmerModePatterns[programmerNumberBase - HexBase].begin(), programmerModePatterns[programmerNumberBase - HexBase].end()); + patterns.assign( + programmerModePatterns[(int)programmerNumberBase - (int)NumberBase::HexBase].begin(), + programmerModePatterns[(int)programmerNumberBase - (int)NumberBase::HexBase].end()); } else if (modeType == CategoryGroupType::Converter) { patterns.assign(unitConverterPatterns.begin(), unitConverterPatterns.end()); } - const auto [maxOperandLength, maxOperandValue] = GetMaxOperandLengthAndValue(mode, modeType, programmerNumberBase, bitLengthType); + auto maxOperandLengthAndValue = GetMaxOperandLengthAndValue(mode, modeType, programmerNumberBase, bitLengthType); bool expMatched = true; for (const auto& operand : operands) @@ -276,34 +305,34 @@ bool CopyPasteManager::ExpressionRegExMatch(vector operands, ViewMode m bool operandMatched = false; for (const auto& pattern : patterns) { - operandMatched = operandMatched || regex_match(operand, pattern); + operandMatched = operandMatched || regex_match(operand->Data(), pattern); } if (operandMatched) { // Remove characters that are valid in the expression but we do not want to include in length calculations // or which will break conversion from string-to-ULL. - const wstring operandValue = SanitizeOperand(operand); + auto operandValue = SanitizeOperand(operand); // If an operand exceeds the maximum length allowed, break and return. - if (OperandLength(operandValue, mode, modeType, programmerNumberBase) > maxOperandLength) + if (OperandLength(operandValue, mode, modeType, programmerNumberBase) > maxOperandLengthAndValue.maxLength) { expMatched = false; break; } // If maxOperandValue is set and the operandValue exceeds it, break and return. - if (maxOperandValue != 0) + if (maxOperandLengthAndValue.maxValue != 0) { - unsigned long long int operandAsULL = 0; - if (!TryOperandToULL(operandValue, programmerNumberBase, operandAsULL)) + auto operandAsULL = TryOperandToULL(operandValue, programmerNumberBase); + if (operandAsULL == nullptr) { // Operand was empty, received invalid_argument, or received out_of_range. Input is invalid. expMatched = false; break; } - if (operandAsULL > maxOperandValue) + if (operandAsULL->Value > maxOperandLengthAndValue.maxValue) { expMatched = false; break; @@ -317,18 +346,23 @@ bool CopyPasteManager::ExpressionRegExMatch(vector operands, ViewMode m return expMatched; } -pair CopyPasteManager::GetMaxOperandLengthAndValue(ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, BitLength bitLengthType) +CopyPasteMaxOperandLengthAndValue +CopyPasteManager::GetMaxOperandLengthAndValue(ViewMode mode, CategoryGroupType modeType, NumberBase programmerNumberBase, BitLength bitLengthType) { constexpr size_t defaultMaxOperandLength = 0; constexpr uint64_t defaultMaxValue = 0; - + CopyPasteMaxOperandLengthAndValue res; if (mode == ViewMode::Standard) { - return make_pair(MaxStandardOperandLength, defaultMaxValue); + res.maxLength = MaxStandardOperandLength; + res.maxValue = defaultMaxValue; + return res; } else if (mode == ViewMode::Scientific) { - return make_pair(MaxScientificOperandLength, defaultMaxValue); + res.maxLength = MaxScientificOperandLength; + res.maxValue = defaultMaxValue; + return res; } else if (mode == ViewMode::Programmer) { @@ -352,65 +386,69 @@ pair CopyPasteManager::GetMaxOperandLengthAndValue(ViewMode mo double bitsPerDigit = 0; switch (programmerNumberBase) { - case BinBase: + case NumberBase::BinBase: bitsPerDigit = log2(2); break; - case OctBase: + case NumberBase::OctBase: bitsPerDigit = log2(8); break; - case DecBase: + case NumberBase::DecBase: bitsPerDigit = log2(10); break; - case HexBase: + case NumberBase::HexBase: bitsPerDigit = log2(16); break; } - unsigned int signBit = (programmerNumberBase == DecBase) ? 1 : 0; + unsigned int signBit = (programmerNumberBase == NumberBase::DecBase) ? 1 : 0; - const auto maxLength = static_cast(ceil((bitLength - signBit) / bitsPerDigit)); + const auto maxLength = static_cast(ceil((bitLength - signBit) / bitsPerDigit)); const uint64_t maxValue = UINT64_MAX >> (MaxProgrammerBitLength - (bitLength - signBit)); - return make_pair(maxLength, maxValue); + res.maxLength = maxLength; + res.maxValue = maxValue; + return res; } else if (modeType == CategoryGroupType::Converter) { - return make_pair(MaxConverterInputLength, defaultMaxValue); + res.maxLength = MaxConverterInputLength; + res.maxValue = defaultMaxValue; + return res; } - return make_pair(defaultMaxOperandLength, defaultMaxValue); + res.maxLength = defaultMaxOperandLength; + res.maxValue = defaultMaxValue; + return res; } -wstring CopyPasteManager::SanitizeOperand(const wstring& operand) +Platform::String ^ CopyPasteManager::SanitizeOperand(Platform::String ^ operand) { - wchar_t unWantedChars[] = { L'\'', L'_', L'`', L'(', L')', L'-', L'+' }; + constexpr wchar_t unWantedChars[] = { L'\'', L'_', L'`', L'(', L')', L'-', L'+' }; - return Utils::RemoveUnwantedCharsFromWstring(operand, unWantedChars, static_cast(size(unWantedChars))); + return ref new String(Utils::RemoveUnwantedCharsFromString(operand->Data(), unWantedChars).c_str()); } -bool CopyPasteManager::TryOperandToULL(const wstring& operand, int numberBase, unsigned long long int& result) +IBox ^ CopyPasteManager::TryOperandToULL(String ^ operand, NumberBase numberBase) { - result = 0; - - if (operand.length() == 0 || operand.front() == L'-') + if (operand->Length() == 0 || operand->Data()[0] == L'-') { - return false; + return nullptr; } int intBase; switch (numberBase) { - case HexBase: + case NumberBase::HexBase: intBase = 16; break; - case OctBase: + case NumberBase::OctBase: intBase = 8; break; - case BinBase: + case NumberBase::BinBase: intBase = 2; break; default: - case DecBase: + case NumberBase::DecBase: intBase = 10; break; } @@ -418,8 +456,7 @@ bool CopyPasteManager::TryOperandToULL(const wstring& operand, int numberBase, u wstring::size_type size = 0; try { - result = stoull(operand, &size, intBase); - return true; + return stoull(operand->Data(), &size, intBase); } catch (const invalid_argument&) { @@ -430,14 +467,14 @@ bool CopyPasteManager::TryOperandToULL(const wstring& operand, int numberBase, u // Do nothing } - return false; + return nullptr; } -size_t CopyPasteManager::OperandLength(const wstring& operand, ViewMode mode, CategoryGroupType modeType, int programmerNumberBase) +ULONG32 CopyPasteManager::OperandLength(Platform::String ^ operand, ViewMode mode, CategoryGroupType modeType, NumberBase programmerNumberBase) { if (modeType == CategoryGroupType::Converter) { - return operand.length(); + return operand->Length(); } switch (mode) @@ -454,45 +491,46 @@ size_t CopyPasteManager::OperandLength(const wstring& operand, ViewMode mode, Ca } } -size_t CopyPasteManager::StandardScientificOperandLength(const wstring& operand) +ULONG32 CopyPasteManager::StandardScientificOperandLength(Platform::String ^ operand) { - const bool hasDecimal = operand.find('.') != wstring::npos; + auto operandWstring = wstring(operand->Data()); + const bool hasDecimal = operandWstring.find('.') != wstring::npos; if (hasDecimal) { - if (operand.length() >= 2) + if (operandWstring.length() >= 2) { - if ((operand[0] == L'0') && (operand[1] == L'.')) + if ((operandWstring[0] == L'0') && (operandWstring[1] == L'.')) { - return operand.length() - 2; + return static_cast(operandWstring.length() - 2); } else { - return operand.length() - 1; + return static_cast(operandWstring.length() - 1); } } } - return operand.length(); + return static_cast(operandWstring.length()); } -size_t CopyPasteManager::ProgrammerOperandLength(const wstring& operand, int numberBase) +ULONG32 CopyPasteManager::ProgrammerOperandLength(Platform::String ^ operand, NumberBase numberBase) { vector prefixes{}; vector suffixes{}; switch (numberBase) { - case BinBase: + case NumberBase::BinBase: prefixes = { L"0B", L"0Y" }; suffixes = { L"B" }; break; - case DecBase: + case NumberBase::DecBase: prefixes = { L"-", L"0N" }; break; - case OctBase: + case NumberBase::OctBase: prefixes = { L"0T", L"0O" }; break; - case HexBase: + case NumberBase::HexBase: prefixes = { L"0X" }; suffixes = { L"H" }; break; @@ -505,10 +543,10 @@ size_t CopyPasteManager::ProgrammerOperandLength(const wstring& operand, int num const array uintSuffixes = { L"ULL", L"UL", L"LL", L"U", L"L" }; suffixes.insert(suffixes.end(), uintSuffixes.begin(), uintSuffixes.end()); - wstring operandUpper = operand; + wstring operandUpper = wstring(operand->Data()); transform(operandUpper.begin(), operandUpper.end(), operandUpper.begin(), towupper); - size_t len = operand.length(); + size_t len = operand->Length(); // Detect if there is a suffix and subtract its length // Check suffixes first to allow e.g. "0b" to result in length 1 (value 0), rather than length 0 (no value). @@ -541,7 +579,7 @@ size_t CopyPasteManager::ProgrammerOperandLength(const wstring& operand, int num } } - return len; + return static_cast(len); } // return wstring after removing characters like space, comma, double quotes, and monetary prefix currency symbols supported by the Windows keyboard: @@ -556,8 +594,13 @@ size_t CopyPasteManager::ProgrammerOperandLength(const wstring& operand, int num // Indian rupee(₹) - 8377 // pound(£) - 163 // euro(€) - 8364 -wstring CopyPasteManager::RemoveUnwantedCharsFromWstring(const wstring& input) +Platform::String ^ CopyPasteManager::RemoveUnwantedCharsFromString(Platform::String ^ 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); + constexpr wchar_t unWantedChars[] = { L' ', L',', L'"', 165, 164, 8373, 36, 8353, 8361, 8362, 8358, 8377, 163, 8364, 8234, 8235, 8236, 8237 }; + return ref new String(Utils::RemoveUnwantedCharsFromString(input->Data(), unWantedChars).c_str()); +} + +bool CopyPasteManager::IsErrorMessage(Platform::String ^ message) +{ + return message == PasteErrorString; } diff --git a/src/CalcViewModel/Common/CopyPasteManager.h b/src/CalcViewModel/Common/CopyPasteManager.h index 9571cdbb..b8850d4c 100644 --- a/src/CalcViewModel/Common/CopyPasteManager.h +++ b/src/CalcViewModel/Common/CopyPasteManager.h @@ -6,6 +6,7 @@ #include "AppResourceProvider.h" #include "NavCategory.h" #include "BitLength.h" +#include "NumberBase.h" namespace CalculatorUnitTests { @@ -14,78 +15,119 @@ namespace CalculatorUnitTests namespace CalculatorApp { - inline constexpr auto HexBase = 5; - inline constexpr auto DecBase = 6; - inline constexpr auto OctBase = 7; - inline constexpr auto BinBase = 8; +public + value struct CopyPasteMaxOperandLengthAndValue + { + unsigned int maxLength; + unsigned long long maxValue; + }; - class CopyPasteManager + public ref class CopyPasteManager sealed { public: static void CopyToClipboard(Platform::String ^ stringToCopy); - static concurrency::task GetStringToPaste( - CalculatorApp::Common::ViewMode mode, - CalculatorApp::Common::CategoryGroupType modeType, - int programmerNumberBase = -1, - CalculatorApp::Common::BitLength bitLengthType = CalculatorApp::Common::BitLength::BitLengthUnknown); - static bool HasStringToPaste() + static Windows::Foundation::IAsyncOperation< + Platform::String + ^> ^ GetStringToPaste(CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, CalculatorApp::Common::NumberBase programmerNumberBase, CalculatorApp::Common::BitLength bitLengthType); + static bool HasStringToPaste(); + static bool IsErrorMessage(Platform::String ^ message); + static property unsigned int MaxPasteableLength { - return ClipboardTextFormat() >= 0; + unsigned int get() + { + return MaxPasteableLengthValue; + } + } + static property unsigned int MaxOperandCount + { + unsigned int get() + { + return MaxOperandCountValue; + } + } + static property unsigned int MaxStandardOperandLength + { + unsigned int get() + { + return MaxStandardOperandLengthValue; + } + } + static property unsigned int MaxScientificOperandLength + { + unsigned int get() + { + return MaxScientificOperandLengthValue; + } } - static constexpr auto PasteErrorString = L"NoOp"; + static property unsigned int MaxConverterInputLength + { + unsigned int get() + { + return MaxConverterInputLengthValue; + } + } + + static property unsigned int MaxExponentLength + { + unsigned int get() + { + return MaxExponentLengthValue; + } + } + + static property unsigned int MaxProgrammerBitLength + { + unsigned int get() + { + return MaxProgrammerBitLengthValue; + } + } - private: - static int ClipboardTextFormat(); static Platform::String ^ ValidatePasteExpression( Platform::String ^ pastedText, CalculatorApp::Common::ViewMode mode, - int programmerNumberBase, + CalculatorApp::Common::NumberBase programmerNumberBase, CalculatorApp::Common::BitLength bitLengthType); static Platform::String ^ ValidatePasteExpression( Platform::String ^ pastedText, CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, - int programmerNumberBase, + CalculatorApp::Common::NumberBase programmerNumberBase, CalculatorApp::Common::BitLength bitLengthType); - - static std::vector - ExtractOperands(const std::wstring& pasteExpression, CalculatorApp::Common::ViewMode mode); + static CopyPasteMaxOperandLengthAndValue GetMaxOperandLengthAndValue( + CalculatorApp::Common::ViewMode mode, + CalculatorApp::Common::CategoryGroupType modeType, + CalculatorApp::Common::NumberBase programmerNumberBase, + CalculatorApp::Common::BitLength bitLengthType); + static Windows::Foundation::Collections::IVector< + Platform::String ^> ^ ExtractOperands(Platform::String ^ pasteExpression, CalculatorApp::Common::ViewMode mode); static bool ExpressionRegExMatch( - std::vector operands, + Windows::Foundation::Collections::IVector ^ operands, CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, - int programmerNumberBase = -1, - CalculatorApp::Common::BitLength bitLengthType = CalculatorApp::Common::BitLength::BitLengthUnknown); - - static std::pair GetMaxOperandLengthAndValue( + CalculatorApp::Common::NumberBase programmerNumberBase, + CalculatorApp::Common::BitLength bitLengthType); + static Platform::String ^ SanitizeOperand(Platform::String ^ operand); + static Platform::String ^ RemoveUnwantedCharsFromString(Platform::String ^ input); + static Platform::IBox ^ TryOperandToULL(Platform::String ^ operand, CalculatorApp::Common::NumberBase numberBase); + static ULONG32 StandardScientificOperandLength(Platform::String ^ operand); + static ULONG32 OperandLength( + Platform::String ^ operand, CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, - int programmerNumberBase = -1, - CalculatorApp::Common::BitLength bitLengthType = CalculatorApp::Common::BitLength::BitLengthUnknown); - static std::wstring SanitizeOperand(const std::wstring& operand); - static bool TryOperandToULL(const std::wstring& operand, int numberBase, unsigned long long int& result); - static size_t OperandLength( - const std::wstring& operand, - CalculatorApp::Common::ViewMode mode, - CalculatorApp::Common::CategoryGroupType modeType, - int programmerNumberBase = -1); - static size_t StandardScientificOperandLength(const std::wstring& operand); - static size_t ProgrammerOperandLength(const std::wstring& operand, int numberBase); - static std::wstring RemoveUnwantedCharsFromWstring(const std::wstring& input); + CalculatorApp::Common::NumberBase programmerNumberBase); + static ULONG32 ProgrammerOperandLength(Platform::String ^ operand, CalculatorApp::Common::NumberBase numberBase); - static constexpr size_t MaxStandardOperandLength = 16; - static constexpr size_t MaxScientificOperandLength = 32; - static constexpr size_t MaxConverterInputLength = 16; - static constexpr size_t MaxOperandCount = 100; - static constexpr size_t MaxPasteableLength = 512; - static constexpr size_t MaxExponentLength = 4; - static constexpr size_t MaxProgrammerBitLength = 64; - - static Platform::String ^ supportedFormats[]; - - friend class CalculatorUnitTests::CopyPasteManagerTest; + private: + static constexpr size_t MaxStandardOperandLengthValue = 16; + static constexpr size_t MaxScientificOperandLengthValue = 32; + static constexpr size_t MaxConverterInputLengthValue = 16; + static constexpr size_t MaxOperandCountValue = 100; + static constexpr size_t MaxExponentLengthValue = 4; + static constexpr size_t MaxProgrammerBitLengthValue = 64; + static constexpr size_t MaxPasteableLengthValue = 512; }; } diff --git a/src/CalcViewModel/Common/DateCalculator.cpp b/src/CalcViewModel/Common/DateCalculator.cpp index 19d3c492..35df7231 100644 --- a/src/CalcViewModel/Common/DateCalculator.cpp +++ b/src/CalcViewModel/Common/DateCalculator.cpp @@ -9,6 +9,11 @@ using namespace Windows::Foundation; using namespace Windows::Globalization; using namespace CalculatorApp::Common::DateCalculation; +bool operator==(const DateDifference& l, const DateDifference& r) +{ + return l.year == r.year && l.month == r.month && l.week == r.week && l.day == r.day; +} + DateCalculationEngine::DateCalculationEngine(_In_ String ^ calendarIdentifier) { m_calendar = ref new Calendar(); @@ -18,10 +23,9 @@ DateCalculationEngine::DateCalculationEngine(_In_ String ^ calendarIdentifier) // Adding Duration to a Date // Returns: True if function succeeds to calculate the date else returns False -bool DateCalculationEngine::AddDuration(_In_ DateTime startDate, _In_ const DateDifference& duration, _Out_ DateTime* endDate) +IBox ^ DateCalculationEngine::AddDuration(DateTime startDate, DateDifference duration) { auto currentCalendarSystem = m_calendar->GetCalendarSystem(); - try { m_calendar->SetDateTime(startDate); @@ -50,7 +54,8 @@ bool DateCalculationEngine::AddDuration(_In_ DateTime startDate, _In_ const Date m_calendar->AddDays(duration.day); } - *endDate = m_calendar->GetDateTime(); + m_calendar->ChangeCalendarSystem(currentCalendarSystem); + return m_calendar->GetDateTime(); } catch (Platform::InvalidArgumentException ^ ex) { @@ -58,17 +63,13 @@ bool DateCalculationEngine::AddDuration(_In_ DateTime startDate, _In_ const Date m_calendar->ChangeCalendarSystem(currentCalendarSystem); // Do nothing - return false; + return nullptr; } - - m_calendar->ChangeCalendarSystem(currentCalendarSystem); - - return true; } // Subtracting Duration from a Date // Returns: True if function succeeds to calculate the date else returns False -bool DateCalculationEngine::SubtractDuration(_In_ DateTime startDate, _In_ const DateDifference& duration, _Out_ DateTime* endDate) +IBox ^ DateCalculationEngine::SubtractDuration(_In_ DateTime startDate, _In_ DateDifference duration) { auto currentCalendarSystem = m_calendar->GetCalendarSystem(); @@ -101,7 +102,18 @@ bool DateCalculationEngine::SubtractDuration(_In_ DateTime startDate, _In_ const { m_calendar->AddYears(-duration.year); } - *endDate = m_calendar->GetDateTime(); + m_calendar->ChangeCalendarSystem(currentCalendarSystem); + + auto dateTime = m_calendar->GetDateTime(); + // Check that the UniversalTime value is not negative + if (dateTime.UniversalTime >= 0) + { + return dateTime; + } + else + { + return nullptr; + } } catch (Platform::InvalidArgumentException ^ ex) { @@ -109,17 +121,12 @@ bool DateCalculationEngine::SubtractDuration(_In_ DateTime startDate, _In_ const m_calendar->ChangeCalendarSystem(currentCalendarSystem); // Do nothing - return false; + return nullptr; } - - m_calendar->ChangeCalendarSystem(currentCalendarSystem); - - // Check that the UniversalTime value is not negative - return (endDate->UniversalTime >= 0); } // Calculate the difference between two dates -bool DateCalculationEngine::TryGetDateDifference(_In_ DateTime date1, _In_ DateTime date2, _In_ DateUnit outputFormat, _Out_ DateDifference* difference) +IBox ^ DateCalculationEngine::TryGetDateDifference(_In_ DateTime date1, _In_ DateTime date2, _In_ DateUnit outputFormat) { DateTime startDate; DateTime endDate; @@ -177,8 +184,7 @@ bool DateCalculationEngine::TryGetDateDifference(_In_ DateTime date1, _In_ DateT { // Operation failed due to out of bound result // For example: 31st Dec, 9999 - last valid date - *difference = DateDifferenceUnknown; - return false; + return nullptr; } } @@ -194,8 +200,7 @@ bool DateCalculationEngine::TryGetDateDifference(_In_ DateTime date1, _In_ DateT if (differenceInDates[unitIndex] == 0) { // differenceInDates[unitIndex] is unsigned, the value can't be negative - *difference = DateDifferenceUnknown; - return false; + return nullptr; } differenceInDates[unitIndex] -= 1; pivotDate = tempPivotDate; @@ -220,8 +225,7 @@ bool DateCalculationEngine::TryGetDateDifference(_In_ DateTime date1, _In_ DateT { // Operation failed due to out of bound result // For example: 31st Dec, 9999 - last valid date - *difference = DateDifferenceUnknown; - return false; + return nullptr; } } } while (tempDaysDiff != 0); // dates are the same - exit the loop @@ -232,8 +236,7 @@ bool DateCalculationEngine::TryGetDateDifference(_In_ DateTime date1, _In_ DateT if (signedDaysDiff < 0) { // daysDiff is unsigned, the value can't be negative - *difference = DateDifferenceUnknown; - return false; + return nullptr; } daysDiff = signedDaysDiff; @@ -244,11 +247,12 @@ bool DateCalculationEngine::TryGetDateDifference(_In_ DateTime date1, _In_ DateT differenceInDates[3] = daysDiff; - difference->year = differenceInDates[0]; - difference->month = differenceInDates[1]; - difference->week = differenceInDates[2]; - difference->day = differenceInDates[3]; - return true; + DateDifference result; + result.year = differenceInDates[0]; + result.month = differenceInDates[1]; + result.week = differenceInDates[2]; + result.day = differenceInDates[3]; + return result; } // Private Methods diff --git a/src/CalcViewModel/Common/DateCalculator.h b/src/CalcViewModel/Common/DateCalculator.h index fdd885e7..7c9b6c4d 100644 --- a/src/CalcViewModel/Common/DateCalculator.h +++ b/src/CalcViewModel/Common/DateCalculator.h @@ -29,39 +29,30 @@ namespace CalculatorApp }; // Struct to store the difference between two Dates in the form of Years, Months , Weeks - struct DateDifference + public + value struct DateDifference { - int year = 0; - int month = 0; - int week = 0; - int day = 0; - - bool operator==(const DateDifference& dd) const - { - return year == dd.year && month == dd.month && week == dd.week && day == day; - } + int year; + int month; + int week; + int day; }; const DateDifference DateDifferenceUnknown{ INT_MIN, INT_MIN, INT_MIN, INT_MIN }; - class DateCalculationEngine + public + ref class DateCalculationEngine sealed { public: // Constructor DateCalculationEngine(_In_ Platform::String ^ calendarIdentifier); // Public Methods - bool __nothrow - AddDuration(_In_ Windows::Foundation::DateTime startDate, _In_ const DateDifference& duration, _Out_ Windows::Foundation::DateTime* endDate); - bool __nothrow SubtractDuration( - _In_ Windows::Foundation::DateTime startDate, - _In_ const DateDifference& duration, - _Out_ Windows::Foundation::DateTime* endDate); - bool __nothrow TryGetDateDifference( - _In_ Windows::Foundation::DateTime date1, - _In_ Windows::Foundation::DateTime date2, - _In_ DateUnit outputFormat, - _Out_ DateDifference* difference); + + Platform::IBox ^ AddDuration(_In_ Windows::Foundation::DateTime startDate, _In_ DateDifference duration); + Platform::IBox ^ SubtractDuration(_In_ Windows::Foundation::DateTime startDate, _In_ DateDifference duration); + Platform::IBox< + DateDifference> ^ TryGetDateDifference(_In_ Windows::Foundation::DateTime date1, _In_ Windows::Foundation::DateTime date2, _In_ DateUnit outputFormat); private: // Private Variables @@ -76,3 +67,5 @@ namespace CalculatorApp } } } + +bool operator==(const CalculatorApp::Common::DateCalculation::DateDifference& l, const CalculatorApp::Common::DateCalculation::DateDifference& r); diff --git a/src/CalcViewModel/Common/EngineResourceProvider.cpp b/src/CalcViewModel/Common/EngineResourceProvider.cpp index b65a2a31..05faff9f 100644 --- a/src/CalcViewModel/Common/EngineResourceProvider.cpp +++ b/src/CalcViewModel/Common/EngineResourceProvider.cpp @@ -17,7 +17,7 @@ namespace CalculatorApp m_resLoader = ResourceLoader::GetForViewIndependentUse("CEngineStrings"); } - wstring EngineResourceProvider::GetCEngineString(const wstring& id) + wstring EngineResourceProvider::GetCEngineString(wstring_view id) { const auto& localizationSettings = LocalizationSettings::GetInstance(); @@ -43,7 +43,7 @@ namespace CalculatorApp return numberGroupingString; } - StringReference idRef(id.c_str()); + StringReference idRef(id.data(), id.length()); String ^ str = m_resLoader->GetString(idRef); return str->Begin(); } diff --git a/src/CalcViewModel/Common/EngineResourceProvider.h b/src/CalcViewModel/Common/EngineResourceProvider.h index 8b5bb479..f4620c5c 100644 --- a/src/CalcViewModel/Common/EngineResourceProvider.h +++ b/src/CalcViewModel/Common/EngineResourceProvider.h @@ -11,7 +11,7 @@ namespace CalculatorApp { public: EngineResourceProvider(); - virtual std::wstring GetCEngineString(const std::wstring& id) override; + virtual std::wstring GetCEngineString(std::wstring_view id) override; private: Windows::ApplicationModel::Resources::ResourceLoader ^ m_resLoader; diff --git a/src/CalcViewModel/Common/ExpressionCommandDeserializer.cpp b/src/CalcViewModel/Common/ExpressionCommandDeserializer.cpp index e927b262..509a1659 100644 --- a/src/CalcViewModel/Common/ExpressionCommandDeserializer.cpp +++ b/src/CalcViewModel/Common/ExpressionCommandDeserializer.cpp @@ -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" @@ -47,13 +47,13 @@ COpndCommand CommandDeserializer::DeserializeOperand() bool fDecimal = m_dataReader->ReadBoolean(); bool fSciFmt = m_dataReader->ReadBoolean(); - std::shared_ptr> cmdVector = std::make_shared>(); + std::shared_ptr> cmdVector = std::make_shared>(); auto cmdVectorSize = m_dataReader->ReadUInt32(); for (unsigned int j = 0; j < cmdVectorSize; ++j) { int eachOpndcmd = m_dataReader->ReadInt32(); - cmdVector->Append(eachOpndcmd); + cmdVector->push_back(eachOpndcmd); } return COpndCommand(cmdVector, fNegative, fDecimal, fSciFmt); @@ -68,7 +68,6 @@ CParentheses CommandDeserializer::DeserializeParentheses() CUnaryCommand CommandDeserializer::DeserializeUnary() { auto cmdSize = m_dataReader->ReadUInt32(); - std::shared_ptr> cmdVector = std::make_shared>(); if (cmdSize == 1) { diff --git a/src/CalcViewModel/Common/ExpressionCommandSerializer.cpp b/src/CalcViewModel/Common/ExpressionCommandSerializer.cpp index bbf9e183..fb0cd83a 100644 --- a/src/CalcViewModel/Common/ExpressionCommandSerializer.cpp +++ b/src/CalcViewModel/Common/ExpressionCommandSerializer.cpp @@ -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" @@ -18,28 +18,22 @@ void SerializeCommandVisitor::Visit(_In_ COpndCommand& opndCmd) m_dataWriter->WriteBoolean(opndCmd.IsDecimalPresent()); m_dataWriter->WriteBoolean(opndCmd.IsSciFmt()); - auto opndCmds = opndCmd.GetCommands(); - unsigned int opndCmdSize; - opndCmds->GetSize(&opndCmdSize); + const auto& opndCmds = opndCmd.GetCommands(); + unsigned int opndCmdSize = static_cast(opndCmds->size()); m_dataWriter->WriteUInt32(opndCmdSize); - for (unsigned int j = 0; j < opndCmdSize; ++j) + for (int eachOpndcmd : *opndCmds) { - int eachOpndcmd; - opndCmds->GetAt(j, &eachOpndcmd); m_dataWriter->WriteInt32(eachOpndcmd); } } void SerializeCommandVisitor::Visit(_In_ CUnaryCommand& unaryCmd) { - auto cmds = unaryCmd.GetCommands(); - unsigned int cmdSize; - cmds->GetSize(&cmdSize); + const auto& cmds = unaryCmd.GetCommands(); + unsigned int cmdSize = static_cast(cmds->size()); m_dataWriter->WriteUInt32(cmdSize); - for (unsigned int j = 0; j < cmdSize; ++j) + for (int eachOpndcmd : *cmds) { - int eachOpndcmd; - cmds->GetAt(j, &eachOpndcmd); m_dataWriter->WriteInt32(eachOpndcmd); } } diff --git a/src/CalcViewModel/Common/KeyboardShortcutManager.cpp b/src/CalcViewModel/Common/KeyboardShortcutManager.cpp index 993b231d..957e957e 100644 --- a/src/CalcViewModel/Common/KeyboardShortcutManager.cpp +++ b/src/CalcViewModel/Common/KeyboardShortcutManager.cpp @@ -431,9 +431,9 @@ void KeyboardShortcutManager::OnCharacterReceivedHandler(CoreWindow ^ sender, Ch { wchar_t character = static_cast(args->KeyCode); auto buttons = s_CharacterForButtons.find(viewId)->second.equal_range(character); + RunFirstEnabledButtonCommand(buttons); LightUpButtons(buttons); - RunFirstEnabledButtonCommand(buttons); } } } @@ -519,7 +519,7 @@ void KeyboardShortcutManager::OnKeyDownHandler(CoreWindow ^ sender, KeyEventArgs auto navView = buttons.first->second.Resolve(); auto appViewModel = safe_cast(navView->DataContext); appViewModel->Mode = ViewMode::Date; - auto categoryName = AppResourceProvider::GetInstance().GetResourceString(L"DateCalculationModeText"); + auto categoryName = AppResourceProvider::GetInstance()->GetResourceString(L"DateCalculationModeText"); appViewModel->CategoryName = categoryName; auto menuItems = static_cast ^>(navView->MenuItemsSource); @@ -601,8 +601,6 @@ void KeyboardShortcutManager::OnKeyDownHandler(CoreWindow ^ sender, KeyEventArgs LightUpButtons(buttons); } } - - RunFirstEnabledButtonCommand(buttons); } } } diff --git a/src/CalcViewModel/Common/LocalizationService.cpp b/src/CalcViewModel/Common/LocalizationService.cpp index eacc04de..79630376 100644 --- a/src/CalcViewModel/Common/LocalizationService.cpp +++ b/src/CalcViewModel/Common/LocalizationService.cpp @@ -94,16 +94,16 @@ LocalizationService::LocalizationService(_In_ const wchar_t * const overridedLan m_locale = locale(""); } auto resourceLoader = AppResourceProvider::GetInstance(); - m_fontFamilyOverride = resourceLoader.GetResourceString(L"LocalizedFontFamilyOverride"); + m_fontFamilyOverride = resourceLoader->GetResourceString(L"LocalizedFontFamilyOverride"); String ^ reserved = L"RESERVED_FOR_FONTLOC"; m_overrideFontApiValues = ((m_fontFamilyOverride != nullptr) && (m_fontFamilyOverride != reserved)); if (m_overrideFontApiValues) { - String ^ localizedUICaptionFontSizeFactorOverride = resourceLoader.GetResourceString(L"LocalizedUICaptionFontSizeFactorOverride"); - String ^ localizedUITextFontSizeFactorOverride = resourceLoader.GetResourceString(L"LocalizedUITextFontSizeFactorOverride"); - String ^ localizedFontWeightOverride = resourceLoader.GetResourceString(L"LocalizedFontWeightOverride"); + String ^ localizedUICaptionFontSizeFactorOverride = resourceLoader->GetResourceString(L"LocalizedUICaptionFontSizeFactorOverride"); + String ^ localizedUITextFontSizeFactorOverride = resourceLoader->GetResourceString(L"LocalizedUITextFontSizeFactorOverride"); + String ^ localizedFontWeightOverride = resourceLoader->GetResourceString(L"LocalizedFontWeightOverride"); // If any of the font overrides are modified then all of them need to be modified assert(localizedFontWeightOverride != reserved); @@ -503,16 +503,49 @@ unordered_map LocalizationService::GetTokenToReadableNameMap() make_pair(L"27", L"HyperbolicTangent"), make_pair(L"87", L"InverseHyperbolicTangent"), + // Secant permutations + make_pair(L"SecDeg", L"SecantDegrees"), + make_pair(L"SecRad", L"SecantRadians"), + make_pair(L"SecGrad", L"SecantGradians"), + make_pair(L"InverseSecDeg", L"InverseSecantDegrees"), + make_pair(L"InverseSecRad", L"InverseSecantRadians"), + make_pair(L"InverseSecGrad", L"InverseSecantGradians"), + make_pair(L"Sech", L"HyperbolicSecant"), + make_pair(L"InverseSech", L"InverseHyperbolicSecant"), + + // Cosecant permutations + make_pair(L"CscDeg", L"CosecantDegrees"), + make_pair(L"CscRad", L"CosecantRadians"), + make_pair(L"CscGrad", L"CosecantGradians"), + make_pair(L"InverseCscDeg", L"InverseCosecantDegrees"), + make_pair(L"InverseCscRad", L"InverseCosecantRadians"), + make_pair(L"InverseCscGrad", L"InverseCosecantGradians"), + make_pair(L"Csch", L"HyperbolicCosecant"), + make_pair(L"InverseCsch", L"InverseHyperbolicCosecant"), + + // Cotangent permutations + make_pair(L"CotDeg", L"CotangentDegrees"), + make_pair(L"CotRad", L"CotangentRadians"), + make_pair(L"CotGrad", L"CotangentGradians"), + make_pair(L"InverseCotDeg", L"InverseCotangentDegrees"), + make_pair(L"InverseCotRad", L"InverseCotangentRadians"), + make_pair(L"InverseCotGrad", L"InverseCotangentGradians"), + make_pair(L"Coth", L"HyperbolicCotangent"), + make_pair(L"InverseCoth", L"InverseHyperbolicCotangent"), + // Miscellaneous Scientific functions make_pair(L"94", L"Factorial"), make_pair(L"35", L"DegreeMinuteSecond"), make_pair(L"28", L"NaturalLog"), - make_pair(L"91", L"Square") + make_pair(L"91", L"Square"), + make_pair(L"CubeRoot", L"CubeRoot"), + make_pair(L"Abs", L"AbsoluteValue") }; static vector> s_noParenEngineKeyResourceMap = { // Programmer mode functions make_pair(L"9", L"LeftShift"), make_pair(L"10", L"RightShift"), + make_pair(L"LogBaseX", L"Logx"), // Y Root scientific function make_pair(L"16", L"YRoot") @@ -521,12 +554,12 @@ unordered_map LocalizationService::GetTokenToReadableNameMap() unordered_map tokenToReadableNameMap{}; auto resProvider = AppResourceProvider::GetInstance(); - static const wstring openParen = resProvider.GetCEngineString(StringReference(s_openParenResourceKey))->Data(); + static const wstring openParen = resProvider->GetCEngineString(StringReference(s_openParenResourceKey))->Data(); for (const auto& keyPair : s_parenEngineKeyResourceMap) { - wstring engineStr = resProvider.GetCEngineString(StringReference(keyPair.first.c_str()))->Data(); - wstring automationName = resProvider.GetResourceString(StringReference(keyPair.second.c_str()))->Data(); + wstring engineStr = resProvider->GetCEngineString(StringReference(keyPair.first.c_str()))->Data(); + wstring automationName = resProvider->GetResourceString(StringReference(keyPair.second.c_str()))->Data(); tokenToReadableNameMap.emplace(engineStr + openParen, automationName); } @@ -534,15 +567,15 @@ unordered_map LocalizationService::GetTokenToReadableNameMap() for (const auto& keyPair : s_noParenEngineKeyResourceMap) { - wstring engineStr = resProvider.GetCEngineString(StringReference(keyPair.first.c_str()))->Data(); - wstring automationName = resProvider.GetResourceString(StringReference(keyPair.second.c_str()))->Data(); + wstring engineStr = resProvider->GetCEngineString(StringReference(keyPair.first.c_str()))->Data(); + wstring automationName = resProvider->GetResourceString(StringReference(keyPair.second.c_str()))->Data(); tokenToReadableNameMap.emplace(engineStr, automationName); } s_noParenEngineKeyResourceMap.clear(); // Also replace hyphens with "minus" - wstring minusText = resProvider.GetResourceString(L"minus")->Data(); + wstring minusText = resProvider->GetResourceString(L"minus")->Data(); tokenToReadableNameMap.emplace(L"-", minusText); return tokenToReadableNameMap; @@ -559,7 +592,7 @@ String ^ LocalizationService::GetNarratorReadableToken(String ^ rawToken) } else { - static const String ^ openParen = AppResourceProvider::GetInstance().GetCEngineString(StringReference(s_openParenResourceKey)); + static const String ^ openParen = AppResourceProvider::GetInstance()->GetCEngineString(StringReference(s_openParenResourceKey)); return ref new String(itr->second.c_str()) + L" " + openParen; } } diff --git a/src/CalcViewModel/Common/LocalizationService.h b/src/CalcViewModel/Common/LocalizationService.h index 6c5d0c51..d6921371 100644 --- a/src/CalcViewModel/Common/LocalizationService.h +++ b/src/CalcViewModel/Common/LocalizationService.h @@ -58,10 +58,11 @@ namespace CalculatorApp Windows::Globalization::NumberFormatting::DecimalFormatter ^ GetRegionalSettingsAwareDecimalFormatter() const; Windows::Globalization::DateTimeFormatting::DateTimeFormatter ^ GetRegionalSettingsAwareDateTimeFormatter(_In_ Platform::String ^ format) const; - Windows::Globalization::DateTimeFormatting::DateTimeFormatter ^ GetRegionalSettingsAwareDateTimeFormatter( - _In_ Platform::String ^ format, - _In_ Platform::String ^ calendarIdentifier, - _In_ Platform::String ^ clockIdentifier) const; + Windows::Globalization::DateTimeFormatting::DateTimeFormatter + ^ GetRegionalSettingsAwareDateTimeFormatter( + _In_ Platform::String ^ format, + _In_ Platform::String ^ calendarIdentifier, + _In_ Platform::String ^ clockIdentifier) const; Windows::Globalization::NumberFormatting::CurrencyFormatter ^ GetRegionalSettingsAwareCurrencyFormatter() const; diff --git a/src/CalcViewModel/Common/LocalizationSettings.h b/src/CalcViewModel/Common/LocalizationSettings.h index addc0c39..7c160c45 100644 --- a/src/CalcViewModel/Common/LocalizationSettings.h +++ b/src/CalcViewModel/Common/LocalizationSettings.h @@ -169,20 +169,21 @@ namespace CalculatorApp } } - Platform::String ^ GetEnglishValueFromLocalizedDigits(const std::wstring& localizedString) const + Platform::String ^ GetEnglishValueFromLocalizedDigits(Platform::String ^ localizedString) const { if (m_resolvedName == L"en-US") { - return ref new Platform::String(localizedString.c_str()); + return localizedString; } size_t i = 0; - size_t length = localizedString.size(); + auto localizedStringData = localizedString->Data(); + size_t length = localizedString->Length(); std::unique_ptr englishString(new wchar_t[length + 1]); // +1 for the null termination for (; i < length; ++i) { - wchar_t ch = localizedString[i]; + wchar_t ch = localizedStringData[i]; if (!IsEnUsDigit(ch)) { for (int j = 0; j < 10; ++j) @@ -281,18 +282,17 @@ namespace CalculatorApp return m_numberGrouping; } - void RemoveGroupSeparators(const wchar_t* value, const size_t length, std::wstring* rawValue) const + Platform::String ^ RemoveGroupSeparators(Platform::String ^ source) const { - rawValue->clear(); - rawValue->reserve(length); - - for (size_t i = 0; i < length; i++) + std::wstringstream stream; + for (auto c = source->Begin(); c < source->End(); ++c) { - if (value[i] != L' ' && value[i] != m_numberGroupSeparator) + if (*c != L' ' && *c != m_numberGroupSeparator) { - rawValue->append(1, value[i]); + stream << *c; } } + return ref new Platform::String(stream.str().c_str()); } Platform::String ^ GetCalendarIdentifier() const diff --git a/src/CalcViewModel/Common/LocalizationStringUtil.h b/src/CalcViewModel/Common/LocalizationStringUtil.h index 1a360bdb..0e3d9dff 100644 --- a/src/CalcViewModel/Common/LocalizationStringUtil.h +++ b/src/CalcViewModel/Common/LocalizationStringUtil.h @@ -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 @@ -9,50 +9,78 @@ namespace CalculatorApp { namespace Common { - class LocalizationStringUtil + class LocalizationStringUtilInternal { public: - static std::wstring GetLocalizedString(const wchar_t* pMessage, ...) + static Platform::String ^ GetLocalizedString(Platform::String ^ pMessage, ...) { std::wstring returnString = L""; const UINT32 length = 1024; std::unique_ptr spBuffer = std::unique_ptr(new wchar_t[length]); va_list args = NULL; va_start(args, pMessage); - DWORD fmtReturnVal = FormatMessage(FORMAT_MESSAGE_FROM_STRING, pMessage, 0, 0, spBuffer.get(), length, &args); + DWORD fmtReturnVal = FormatMessage(FORMAT_MESSAGE_FROM_STRING, pMessage->Data(), 0, 0, spBuffer.get(), length, &args); va_end(args); if (fmtReturnVal != 0) { - returnString = spBuffer.get(); + return ref new Platform::String(spBuffer.get()); } - - return returnString; - } - - template - static Platform::String^ GetLocalizedNarratorAnnouncement(Platform::String^ resourceKey, Platform::String^& formatVariable, T*... params) - { - EnsureInitialization(resourceKey, formatVariable); - return StringReference(GetLocalizedString(formatVariable->Data(), params...).c_str()); - } - - private: - static void EnsureInitialization(Platform::String^ resourceKey, Platform::String^& formatVariable) - { - if (resourceKey == nullptr || resourceKey->IsEmpty()) + else { - return; + return ref new Platform::String(); } - - // If the formatVariable already has a value, we don't need to set it again. Simply return. - if (formatVariable != nullptr && !formatVariable->IsEmpty()) - { - return; - } - - formatVariable = AppResourceProvider::GetInstance().GetResourceString(resourceKey); } }; + + public + ref class LocalizationStringUtil sealed + { + public: + static Platform::String + ^ GetLocalizedString(Platform::String ^ pMessage) + { + return LocalizationStringUtilInternal::GetLocalizedString(pMessage); + } + + static Platform::String + ^ GetLocalizedString( + Platform::String ^ pMessage, + Platform::String ^ param1) + { + return LocalizationStringUtilInternal::GetLocalizedString(pMessage, param1->Data()); + } + + static Platform::String + ^ GetLocalizedString( + Platform::String ^ pMessage, + Platform::String ^ param1, + Platform::String ^ param2) + { + return LocalizationStringUtilInternal::GetLocalizedString(pMessage, param1->Data(), param2->Data()); + } + + static Platform::String + ^ GetLocalizedString( + Platform::String ^ pMessage, + Platform::String ^ param1, + Platform::String ^ param2, + Platform::String + ^ param3) + { + return LocalizationStringUtilInternal::GetLocalizedString(pMessage, param1->Data(), param2->Data(), param3->Data()); + } + + static Platform::String + ^ GetLocalizedString( + Platform::String ^ pMessage, + Platform::String ^ param1, + Platform::String ^ param2, + Platform::String ^ param3, + Platform::String ^ param4) + { + return LocalizationStringUtilInternal::GetLocalizedString(pMessage, param1->Data(), param2->Data(), param3->Data(), param4->Data()); + } + }; } } diff --git a/src/CalcViewModel/Common/NavCategory.cpp b/src/CalcViewModel/Common/NavCategory.cpp index 43e912ae..a15ee7dd 100644 --- a/src/CalcViewModel/Common/NavCategory.cpp +++ b/src/CalcViewModel/Common/NavCategory.cpp @@ -46,7 +46,7 @@ static constexpr int DATA_ID = 13; static constexpr int PRESSURE_ID = 14; static constexpr int ANGLE_ID = 15; static constexpr int CURRENCY_ID = 16; -static constexpr int GRAPHING_ID = 17; +static constexpr int GRAPHING_ID = 17; // ^^^ THESE CONSTANTS SHOULD NEVER CHANGE ^^^ // The order of items in this list determines the order of items in the menu. @@ -57,14 +57,6 @@ static constexpr array s_categoryManifest = { L"\uE8EF", CategoryGroupType::Calculator, MyVirtualKey::Number1, - SUPPORTS_ALL }, - NavCategoryInitializer{ ViewMode::Graphing, - GRAPHING_ID, - L"Graphing", - L"GraphingCalculatorMode", - L"\uF770", - CategoryGroupType::Calculator, - MyVirtualKey::Number5, SUPPORTS_ALL }, NavCategoryInitializer{ ViewMode::Scientific, SCIENTIFIC_ID, @@ -82,6 +74,14 @@ static constexpr array s_categoryManifest = { CategoryGroupType::Calculator, MyVirtualKey::Number3, SUPPORTS_ALL }, + NavCategoryInitializer{ ViewMode::Graphing, + GRAPHING_ID, + L"Graphing", + L"GraphingCalculatorMode", + L"\uF770", + CategoryGroupType::Calculator, + MyVirtualKey::Number5, + SUPPORTS_ALL }, NavCategoryInitializer{ ViewMode::Date, DATE_ID, L"Date", @@ -169,7 +169,7 @@ static constexpr array s_categoryManifest = { L"\uE945", CategoryGroupType::Converter, MyVirtualKey::None, - POSITIVE_ONLY }, + SUPPORTS_NEGATIVE }, NavCategoryInitializer{ ViewMode::Data, DATA_ID, L"Data", @@ -193,7 +193,7 @@ static constexpr array s_categoryManifest = { L"\uF515", CategoryGroupType::Converter, MyVirtualKey::None, - POSITIVE_ONLY } }; + SUPPORTS_NEGATIVE } }; // This function should only be used when storing the mode to app data. int NavCategory::Serialize(ViewMode mode) @@ -238,9 +238,7 @@ bool NavCategory::IsValidViewMode(ViewMode mode) bool NavCategory::IsCalculatorViewMode(ViewMode mode) { // Historically, Calculator modes are Standard, Scientific, and Programmer. - return !IsDateCalculatorViewMode(mode) - && !IsGraphingCalculatorViewMode(mode) - && IsModeInCategoryGroup(mode, CategoryGroupType::Calculator); + return !IsDateCalculatorViewMode(mode) && !IsGraphingCalculatorViewMode(mode) && IsModeInCategoryGroup(mode, CategoryGroupType::Calculator); } bool NavCategory::IsGraphingCalculatorViewMode(ViewMode mode) @@ -383,33 +381,28 @@ NavCategoryGroup::NavCategoryGroup(const NavCategoryGroupInitializer& groupIniti m_GroupType = groupInitializer.type; auto resProvider = AppResourceProvider::GetInstance(); - String ^ headerResourceKey = StringReference(groupInitializer.headerResourceKey); - String ^ modeResourceKey = StringReference(groupInitializer.modeResourceKey); - String ^ automationResourceKey = StringReference(groupInitializer.automationResourceKey); - m_Name = resProvider.GetResourceString(headerResourceKey); - String ^ groupMode = resProvider.GetResourceString(modeResourceKey); - String ^ automationName = resProvider.GetResourceString(automationResourceKey); + m_Name = resProvider->GetResourceString(StringReference(groupInitializer.headerResourceKey)); + String ^ groupMode = resProvider->GetResourceString(StringReference(groupInitializer.modeResourceKey)); + String ^ automationName = resProvider->GetResourceString(StringReference(groupInitializer.automationResourceKey)); - String ^ navCategoryHeaderAutomationNameFormat = resProvider.GetResourceString(L"NavCategoryHeader_AutomationNameFormat"); - m_AutomationName = - ref new String(LocalizationStringUtil::GetLocalizedString(navCategoryHeaderAutomationNameFormat->Data(), automationName->Data()).c_str()); + String ^ navCategoryHeaderAutomationNameFormat = resProvider->GetResourceString(L"NavCategoryHeader_AutomationNameFormat"); + m_AutomationName = LocalizationStringUtil::GetLocalizedString(navCategoryHeaderAutomationNameFormat, automationName); - String ^ navCategoryItemAutomationNameFormat = resProvider.GetResourceString(L"NavCategoryItem_AutomationNameFormat"); + String ^ navCategoryItemAutomationNameFormat = resProvider->GetResourceString(L"NavCategoryItem_AutomationNameFormat"); for (const NavCategoryInitializer& categoryInitializer : s_categoryManifest) { if (categoryInitializer.groupType == groupInitializer.type) { String ^ nameResourceKey = StringReference(categoryInitializer.nameResourceKey); - String ^ categoryName = resProvider.GetResourceString(nameResourceKey + "Text"); - String ^ categoryAutomationName = ref new String( - LocalizationStringUtil::GetLocalizedString(navCategoryItemAutomationNameFormat->Data(), categoryName->Data(), m_Name->Data()).c_str()); + String ^ categoryName = resProvider->GetResourceString(nameResourceKey + "Text"); + String ^ categoryAutomationName = LocalizationStringUtil::GetLocalizedString(navCategoryItemAutomationNameFormat, categoryName, m_Name); m_Categories->Append(ref new NavCategory( categoryName, categoryAutomationName, StringReference(categoryInitializer.glyph), - resProvider.GetResourceString(nameResourceKey + "AccessKey"), + resProvider->GetResourceString(nameResourceKey + "AccessKey"), groupMode, categoryInitializer.viewMode, categoryInitializer.supportsNegative)); diff --git a/src/CalcViewModel/Common/NumberBase.h b/src/CalcViewModel/Common/NumberBase.h new file mode 100644 index 00000000..4e15efa1 --- /dev/null +++ b/src/CalcViewModel/Common/NumberBase.h @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once +namespace CalculatorApp::Common +{ +public + enum class NumberBase + { + Unknown = -1, + HexBase = 5, + DecBase = 6, + OctBase = 7, + BinBase = 8 + }; +}; diff --git a/src/CalcViewModel/Common/TraceLogger.cpp b/src/CalcViewModel/Common/TraceLogger.cpp index 65375549..845b010b 100644 --- a/src/CalcViewModel/Common/TraceLogger.cpp +++ b/src/CalcViewModel/Common/TraceLogger.cpp @@ -10,6 +10,7 @@ using namespace CalculatorApp; using namespace CalculatorApp::Common; using namespace Concurrency; using namespace std; +using namespace Platform; using namespace winrt; using namespace winrt::Windows::Foundation; using namespace winrt::Windows::Foundation::Diagnostics; @@ -57,47 +58,43 @@ namespace CalculatorApp TraceLogger::TraceLogger() : g_calculatorProvider( - L"MicrosoftCalculator", - LoggingChannelOptions(GUID{ 0x4f50731a, 0x89cf, 0x4782, 0xb3, 0xe0, 0xdc, 0xe8, 0xc9, 0x4, 0x76, 0xba }), - GUID{ 0x905ca09, 0x610e, 0x401e, 0xb6, 0x50, 0x2f, 0x21, 0x29, 0x80, 0xb9, 0xe0 }) + L"MicrosoftCalculator", + LoggingChannelOptions(GUID{ 0x4f50731a, 0x89cf, 0x4782, 0xb3, 0xe0, 0xdc, 0xe8, 0xc9, 0x4, 0x76, 0xba }), + GUID{ 0x905ca09, 0x610e, 0x401e, 0xb6, 0x50, 0x2f, 0x21, 0x29, 0x80, 0xb9, 0xe0 }) , // Unique providerID {0905CA09-610E-401E-B650-2F212980B9E0} m_appLaunchActivity{ nullptr } { CoCreateGuid(&sessionGuid); } - TraceLogger::~TraceLogger() + TraceLogger ^ TraceLogger::GetInstance() { - } - - TraceLogger& TraceLogger::GetInstance() - { - static TraceLogger s_selfInstance; + static TraceLogger ^ s_selfInstance = ref new TraceLogger(); return s_selfInstance; } - bool TraceLogger::GetTraceLoggingProviderEnabled() const + bool TraceLogger::GetTraceLoggingProviderEnabled() { return g_calculatorProvider.Enabled(); } #pragma region Tracing methods - void TraceLogger::LogLevel1Event(wstring_view eventName, LoggingFields fields) const + void TraceLogger::LogLevel1Event(wstring_view eventName, LoggingFields fields) { g_calculatorProvider.LogEvent(eventName, fields, LoggingLevel::Verbose, LoggingOptions(MICROSOFT_KEYWORD_LEVEL_1)); } - void TraceLogger::LogLevel2Event(wstring_view eventName, LoggingFields fields) const + void TraceLogger::LogLevel2Event(wstring_view eventName, LoggingFields fields) { g_calculatorProvider.LogEvent(eventName, fields, LoggingLevel::Verbose, LoggingOptions(MICROSOFT_KEYWORD_LEVEL_2)); } - void TraceLogger::LogLevel3Event(wstring_view eventName, LoggingFields fields) const + void TraceLogger::LogLevel3Event(wstring_view eventName, LoggingFields fields) { g_calculatorProvider.LogEvent(eventName, fields, LoggingLevel::Verbose, LoggingOptions(MICROSOFT_KEYWORD_LEVEL_3)); } - unique_ptr TraceLogger::CreateTraceActivity(wstring_view eventName, LoggingFields fields) const + unique_ptr TraceLogger::CreateTraceActivity(wstring_view eventName, LoggingFields fields) { return make_unique(g_calculatorProvider, eventName, fields); } @@ -117,7 +114,7 @@ namespace CalculatorApp return true; } - void TraceLogger::LogVisualStateChanged(ViewMode mode, wstring_view state, bool isAlwaysOnTop) const + void TraceLogger::LogVisualStateChanged(ViewMode mode, String ^ state, bool isAlwaysOnTop) { if (!GetTraceLoggingProviderEnabled()) { @@ -127,7 +124,7 @@ namespace CalculatorApp LoggingFields fields{}; fields.AddGuid(L"SessionGuid", sessionGuid); fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data()); - fields.AddString(L"VisualState", state); + fields.AddString(L"VisualState", state->Data()); fields.AddBoolean(L"IsAlwaysOnTop", isAlwaysOnTop); fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE); LogLevel2Event(EVENT_NAME_VISUAL_STATE_CHANGED, fields); @@ -152,7 +149,7 @@ namespace CalculatorApp LogLevel2Event(EVENT_NAME_WINDOW_ON_CREATED, fields); } - void TraceLogger::LogModeChange(ViewMode mode) const + void TraceLogger::LogModeChange(ViewMode mode) { if (!GetTraceLoggingProviderEnabled()) return; @@ -167,7 +164,7 @@ namespace CalculatorApp } } - void TraceLogger::LogHistoryItemLoad(ViewMode mode, int historyListSize, int loadedIndex) const + void TraceLogger::LogHistoryItemLoad(ViewMode mode, int historyListSize, int loadedIndex) { if (!GetTraceLoggingProviderEnabled()) { @@ -183,7 +180,7 @@ namespace CalculatorApp LogLevel2Event(EVENT_NAME_HISTORY_ITEM_LOAD, fields); } - void TraceLogger::LogMemoryItemLoad(ViewMode mode, int memoryListSize, int loadedIndex) const + void TraceLogger::LogMemoryItemLoad(ViewMode mode, int memoryListSize, int loadedIndex) { if (!GetTraceLoggingProviderEnabled()) { @@ -199,7 +196,7 @@ namespace CalculatorApp LogLevel2Event(EVENT_NAME_MEMORY_ITEM_LOAD, fields); } - void TraceLogger::LogError(ViewMode mode, wstring_view functionName, wstring_view errorString) + void TraceLogger::LogError(ViewMode mode, Platform::String ^ functionName, Platform::String ^ errorString) { if (!GetTraceLoggingProviderEnabled()) return; @@ -207,13 +204,13 @@ namespace CalculatorApp LoggingFields fields{}; fields.AddGuid(L"SessionGuid", sessionGuid); fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data()); - fields.AddString(L"FunctionName", functionName); - fields.AddString(L"Message", errorString); + fields.AddString(L"FunctionName", functionName->Data()); + fields.AddString(L"Message", errorString->Data()); fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE); LogLevel2Event(EVENT_NAME_EXCEPTION, fields); } - void TraceLogger::LogStandardException(ViewMode mode, wstring_view functionName, const exception& e) const + void TraceLogger::LogStandardException(ViewMode mode, wstring_view functionName, const exception& e) { if (!GetTraceLoggingProviderEnabled()) return; @@ -229,7 +226,7 @@ namespace CalculatorApp LogLevel2Event(EVENT_NAME_EXCEPTION, fields); } - void TraceLogger::LogWinRTException(ViewMode mode, wstring_view functionName, hresult_error const& e) const + void TraceLogger::LogWinRTException(ViewMode mode, wstring_view functionName, hresult_error const& e) { if (!GetTraceLoggingProviderEnabled()) return; @@ -244,7 +241,7 @@ namespace CalculatorApp LogLevel2Event(EVENT_NAME_EXCEPTION, fields); } - void TraceLogger::LogPlatformException(ViewMode mode, wstring_view functionName, Platform::Exception ^ e) const + void TraceLogger::LogPlatformException(ViewMode mode, wstring_view functionName, Platform::Exception ^ e) { if (!GetTraceLoggingProviderEnabled()) return; @@ -291,7 +288,7 @@ namespace CalculatorApp } } - void TraceLogger::UpdateWindowCount(size_t windowCount) + void TraceLogger::UpdateWindowCount(uint64 windowCount) { if (windowCount == 0) { @@ -301,6 +298,11 @@ namespace CalculatorApp currentWindowCount = windowCount; } + void TraceLogger::DecreaseWindowCount() + { + currentWindowCount = 0; + } + void TraceLogger::LogButtonUsage() { if (!GetTraceLoggingProviderEnabled()) @@ -348,7 +350,7 @@ namespace CalculatorApp LogLevel2Event(EVENT_NAME_DATE_CALCULATION_MODE_USED, fields); } - void TraceLogger::LogConverterInputReceived(ViewMode mode) const + void TraceLogger::LogConverterInputReceived(ViewMode mode) { if (!GetTraceLoggingProviderEnabled()) return; @@ -360,7 +362,7 @@ namespace CalculatorApp LogLevel2Event(EVENT_NAME_CONVERTER_INPUT_RECEIVED, fields); } - void TraceLogger::LogNavBarOpened() const + void TraceLogger::LogNavBarOpened() { if (!GetTraceLoggingProviderEnabled()) return; @@ -371,7 +373,7 @@ namespace CalculatorApp LogLevel2Event(EVENT_NAME_NAV_BAR_OPENED, fields); } - void TraceLogger::LogInputPasted(ViewMode mode) const + void TraceLogger::LogInputPasted(ViewMode mode) { if (!GetTraceLoggingProviderEnabled()) return; diff --git a/src/CalcViewModel/Common/TraceLogger.h b/src/CalcViewModel/Common/TraceLogger.h index d8a4289e..fa24f8e0 100644 --- a/src/CalcViewModel/Common/TraceLogger.h +++ b/src/CalcViewModel/Common/TraceLogger.h @@ -28,33 +28,31 @@ namespace CalculatorApp } }; - class TraceLogger +public + ref class TraceLogger sealed { public: - TraceLogger(_In_ TraceLogger const&) = delete; - TraceLogger const& operator=(_In_ TraceLogger const&) = delete; - ~TraceLogger(); - static TraceLogger& GetInstance(); - bool GetTraceLoggingProviderEnabled() const; - - void LogModeChange(CalculatorApp::Common::ViewMode mode) const; - void LogHistoryItemLoad(CalculatorApp::Common::ViewMode mode, int historyListSize, int loadedIndex) const; - void LogMemoryItemLoad(CalculatorApp::Common::ViewMode mode, int memoryListSize, int loadedIndex) const; + static TraceLogger ^ GetInstance(); + bool GetTraceLoggingProviderEnabled(); + void LogModeChange(CalculatorApp::Common::ViewMode mode); + void LogHistoryItemLoad(CalculatorApp::Common::ViewMode mode, int historyListSize, int loadedIndex); + void LogMemoryItemLoad(CalculatorApp::Common::ViewMode mode, int memoryListSize, int loadedIndex); void UpdateButtonUsage(CalculatorApp::NumbersAndOperatorsEnum button, CalculatorApp::Common::ViewMode mode); void LogButtonUsage(); void LogDateCalculationModeUsed(bool AddSubtractMode); - void UpdateWindowCount(size_t windowCount = 0); + void UpdateWindowCount(uint64 windowCount); + void DecreaseWindowCount(); bool IsWindowIdInLog(int windowId); - void LogVisualStateChanged(CalculatorApp::Common::ViewMode mode, std::wstring_view state, bool isAlwaysOnTop = false) const; + void LogVisualStateChanged(CalculatorApp::Common::ViewMode mode, Platform::String ^ state, bool isAlwaysOnTop); void LogWindowCreated(CalculatorApp::Common::ViewMode mode, int windowId); - void LogConverterInputReceived(CalculatorApp::Common::ViewMode mode) const; - void LogNavBarOpened() const; - - void LogError(CalculatorApp::Common::ViewMode mode, std::wstring_view functionName, std::wstring_view errorString); - void LogStandardException(CalculatorApp::Common::ViewMode mode, std::wstring_view functionName, _In_ const std::exception& e) const; - void LogWinRTException(CalculatorApp::Common::ViewMode mode, std::wstring_view functionName, _In_ winrt::hresult_error const& e) const; - void LogPlatformException(CalculatorApp::Common::ViewMode mode, std::wstring_view functionName, _In_ Platform::Exception ^ e) const; - void LogInputPasted(CalculatorApp::Common::ViewMode mode) const; + void LogConverterInputReceived(CalculatorApp::Common::ViewMode mode); + void LogNavBarOpened(); + void LogError(CalculatorApp::Common::ViewMode mode, Platform::String ^ functionName, Platform::String ^ errorString); + internal : + void LogStandardException(CalculatorApp::Common::ViewMode mode, std::wstring_view functionName, _In_ const std::exception& e); + void LogWinRTException(CalculatorApp::Common::ViewMode mode, std::wstring_view functionName, _In_ winrt::hresult_error const& e); + void LogPlatformException(CalculatorApp::Common::ViewMode mode, std::wstring_view functionName, _In_ Platform::Exception ^ e); + void LogInputPasted(CalculatorApp::Common::ViewMode mode); private: // Create an instance of TraceLogger @@ -64,11 +62,11 @@ namespace CalculatorApp // sampling is involved in Microsoft's diagnostic data collection process. // These keywords provide additional input into how frequently an event might be sampled. // The lower the level of the keyword, the higher the possibility that the corresponding event may be sampled. - void LogLevel1Event(std::wstring_view eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields) const; - void LogLevel2Event(std::wstring_view eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields) const; - void LogLevel3Event(std::wstring_view eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields) const; + void LogLevel1Event(std::wstring_view eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields); + void LogLevel2Event(std::wstring_view eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields); + void LogLevel3Event(std::wstring_view eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields); - std::unique_ptr CreateTraceActivity(std::wstring_view activityName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields) const; + std::unique_ptr CreateTraceActivity(std::wstring_view activityName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields); winrt::Windows::Foundation::Diagnostics::LoggingChannel g_calculatorProvider; @@ -76,7 +74,7 @@ namespace CalculatorApp std::vector windowIdLog; GUID sessionGuid; - size_t currentWindowCount = 0; + uint64 currentWindowCount = 0; winrt::Windows::Foundation::Diagnostics::LoggingActivity m_appLaunchActivity; }; diff --git a/src/CalcViewModel/Common/Utils.cpp b/src/CalcViewModel/Common/Utils.cpp index 65f5c96d..27c32541 100644 --- a/src/CalcViewModel/Common/Utils.cpp +++ b/src/CalcViewModel/Common/Utils.cpp @@ -10,7 +10,6 @@ #include "Common/AppResourceProvider.h" #include "Common/ExpressionCommandSerializer.h" #include "Common/ExpressionCommandDeserializer.h" -#include "ViewState.h" using namespace CalculatorApp; using namespace CalculatorApp::Common; @@ -50,8 +49,8 @@ String ^ Utils::GetStringValue(String ^ input) double Utils::GetDoubleFromWstring(wstring input) { - wchar_t unWantedChars[] = { L' ', L',', 8234, 8235, 8236, 8237 }; - wstring ws = RemoveUnwantedCharsFromWstring(input, unWantedChars, 6); + constexpr wchar_t unWantedChars[] = { L' ', L',', 8234, 8235, 8236, 8237 }; + wstring ws = RemoveUnwantedCharsFromString(input, unWantedChars); return stod(ws); } @@ -83,47 +82,26 @@ bool Utils::IsLastCharacterTarget(_In_ wstring const& input, _In_ wchar_t target return !input.empty() && input.back() == target; } -// 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) - { - input.erase(remove(input.begin(), input.end(), unwantedChars[i]), input.end()); - } - return input; -} - void Utils::SerializeCommandsAndTokens( - _In_ shared_ptr>> const& tokens, - _In_ shared_ptr>> const& commands, + _In_ shared_ptr>> const& tokens, + _In_ shared_ptr>> const& commands, DataWriter ^ writer) { - unsigned int commandsSize; - IFTPlatformException(commands->GetSize(&commandsSize)); - // Save the size of the commands vector - writer->WriteUInt32(commandsSize); + writer->WriteUInt32(static_cast(commands->size())); SerializeCommandVisitor cmdVisitor(writer); - for (unsigned int i = 0; i < commandsSize; ++i) + for (const auto& exprCmd : *commands) { - shared_ptr exprCmd; - IFTPlatformException(commands->GetAt(i, &exprCmd)); - CalculationManager::CommandType commandType = exprCmd->GetCommandType(); writer->WriteInt32(static_cast(commandType)); exprCmd->Accept(cmdVisitor); } - unsigned int tokensSize; - IFTPlatformException(tokens->GetSize(&tokensSize)); - writer->WriteUInt32(tokensSize); + writer->WriteUInt32(static_cast(tokens->size())); - for (unsigned int i = 0; i < tokensSize; ++i) + for (const auto& eachToken : *tokens) { - pair eachToken; - IFTPlatformException(tokens->GetAt(i, &eachToken)); - auto stringData = ref new Platform::String(eachToken.first.c_str()); auto intData = eachToken.second; writer->WriteUInt32(writer->MeasureString(stringData)); @@ -132,9 +110,9 @@ void Utils::SerializeCommandsAndTokens( } } -const shared_ptr>> Utils::DeserializeCommands(DataReader ^ reader) +const shared_ptr>> Utils::DeserializeCommands(DataReader ^ reader) { - shared_ptr>> commandVector = make_shared>>(); + auto commandVector = make_shared>>(); auto commandVectorSize = reader->ReadUInt32(); CommandDeserializer cmdDeserializer(reader); @@ -143,26 +121,23 @@ const shared_ptr>> Utils::Deseri auto commandTypeInt = reader->ReadInt32(); CalculationManager::CommandType commandType = static_cast(commandTypeInt); shared_ptr exprCmd = cmdDeserializer.Deserialize(commandType); - commandVector->Append(exprCmd); + commandVector->push_back(exprCmd); } return commandVector; } -const shared_ptr>> Utils::DeserializeTokens(DataReader ^ reader) +const shared_ptr>> Utils::DeserializeTokens(DataReader ^ reader) { - shared_ptr>> tokenVector = make_shared>>(); + auto tokenVector = make_shared>>(); auto tokensSize = reader->ReadUInt32(); for (unsigned int i = 0; i < tokensSize; ++i) { - pair eachToken; auto stringDataLen = reader->ReadUInt32(); auto stringData = reader->ReadString(stringDataLen); auto intData = reader->ReadInt32(); - eachToken.first = stringData->Data(); - eachToken.second = intData; - tokenVector->Append(eachToken); + tokenVector->emplace_back(stringData->Data(), intData); } return tokenVector; diff --git a/src/CalcViewModel/Common/Utils.h b/src/CalcViewModel/Common/Utils.h index 48261aef..4bdfbcf9 100644 --- a/src/CalcViewModel/Common/Utils.h +++ b/src/CalcViewModel/Common/Utils.h @@ -3,7 +3,6 @@ #pragma once -#include "CalcManager/CalculatorVector.h" #include "CalcManager/ExpressionCommandInterface.h" #include "DelegateCommand.h" #include "GraphingInterfaces/GraphingEnums.h" @@ -210,7 +209,7 @@ public: private: \ static Windows::UI::Xaml::DependencyProperty ^ s_##n##Property; \ \ -public: +private: // Utilities for DependencyProperties namespace Utils @@ -401,27 +400,34 @@ namespace Utils void IFTPlatformException(HRESULT hr); 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); + + // Return wstring after removing characters specified by unwantedChars array + template + std::wstring RemoveUnwantedCharsFromString(std::wstring inputString, const wchar_t (&unwantedChars)[N]) + { + for (const wchar_t unwantedChar : unwantedChars) + { + inputString.erase(std::remove(inputString.begin(), inputString.end(), unwantedChar), inputString.end()); + } + return inputString; + } + double GetDoubleFromWstring(std::wstring input); int GetWindowId(); void RunOnUIThreadNonblocking(std::function&& function, _In_ Windows::UI::Core::CoreDispatcher ^ currentDispatcher); void SerializeCommandsAndTokens( - _In_ std::shared_ptr>> const& tokens, - _In_ std::shared_ptr>> const& commands, + _In_ std::shared_ptr>> const& tokens, + _In_ std::shared_ptr>> const& commands, Windows::Storage::Streams::DataWriter ^ writer); - const std::shared_ptr>> DeserializeCommands(Windows::Storage::Streams::DataReader ^ reader); - const std::shared_ptr>> DeserializeTokens(Windows::Storage::Streams::DataReader ^ reader); + const std::shared_ptr>> DeserializeCommands(Windows::Storage::Streams::DataReader ^ reader); + const std::shared_ptr>> DeserializeTokens(Windows::Storage::Streams::DataReader ^ reader); Windows::Foundation::DateTime GetUniversalSystemTime(); bool IsDateTimeOlderThan(Windows::Foundation::DateTime dateTime, const long long duration); - concurrency::task WriteFileToFolder( - Windows::Storage::IStorageFolder ^ folder, - Platform::String ^ fileName, - Platform::String ^ contents, - Windows::Storage::CreationCollisionOption collisionOption); - concurrency::task ReadFileFromFolder(Windows::Storage::IStorageFolder ^ folder, Platform::String ^ fileName); + concurrency::task WriteFileToFolder(Windows::Storage::IStorageFolder^ folder, Platform::String^ fileName, Platform::String^ contents, Windows::Storage::CreationCollisionOption collisionOption); + concurrency::task ReadFileFromFolder(Windows::Storage::IStorageFolder^ folder, Platform::String^ fileName); bool AreColorsEqual(const Windows::UI::Color& color1, const Windows::UI::Color& color2); diff --git a/src/CalcViewModel/DataLoaders/CurrencyDataLoader.cpp b/src/CalcViewModel/DataLoaders/CurrencyDataLoader.cpp index 5180de47..d098885e 100644 --- a/src/CalcViewModel/DataLoaders/CurrencyDataLoader.cpp +++ b/src/CalcViewModel/DataLoaders/CurrencyDataLoader.cpp @@ -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" @@ -132,8 +132,8 @@ CurrencyDataLoader::CurrencyDataLoader(_In_ unique_ptr clie m_ratioFormatter->IsDecimalPointAlwaysDisplayed = true; m_ratioFormatter->FractionDigits = FORMATTER_RATE_FRACTION_PADDING; - m_ratioFormat = AppResourceProvider::GetInstance().GetResourceString(L"CurrencyFromToRatioFormat")->Data(); - m_timestampFormat = AppResourceProvider::GetInstance().GetResourceString(L"CurrencyTimestampFormat")->Data(); + m_ratioFormat = AppResourceProvider::GetInstance()->GetResourceString(L"CurrencyFromToRatioFormat"); + m_timestampFormat = AppResourceProvider::GetInstance()->GetResourceString(L"CurrencyTimestampFormat"); } CurrencyDataLoader::~CurrencyDataLoader() @@ -300,16 +300,18 @@ pair CurrencyDataLoader::GetCurrencyRatioEquality(_In_ const U double ratio = (iter2->second).ratio; double rounded = RoundCurrencyRatio(ratio); - wstring digitSymbol = wstring{ LocalizationSettings::GetInstance().GetDigitSymbolFromEnUsDigit(L'1') }; - wstring roundedFormat = m_ratioFormatter->Format(rounded)->Data(); + auto digit = LocalizationSettings::GetInstance().GetDigitSymbolFromEnUsDigit(L'1'); + auto digitSymbol = ref new String(&digit, 1); + auto roundedFormat = m_ratioFormatter->Format(rounded); - wstring ratioString = LocalizationStringUtil::GetLocalizedString( - m_ratioFormat.c_str(), digitSymbol.c_str(), unit1.abbreviation.c_str(), roundedFormat.c_str(), unit2.abbreviation.c_str()); + auto ratioString = LocalizationStringUtil::GetLocalizedString( + m_ratioFormat, digitSymbol, StringReference(unit1.abbreviation.c_str()), roundedFormat, StringReference(unit2.abbreviation.c_str())); - wstring accessibleRatioString = LocalizationStringUtil::GetLocalizedString( - m_ratioFormat.c_str(), digitSymbol.c_str(), unit1.accessibleName.c_str(), roundedFormat.c_str(), unit2.accessibleName.c_str()); + auto accessibleRatioString = + LocalizationStringUtil::GetLocalizedString( + m_ratioFormat, digitSymbol, StringReference(unit1.accessibleName.c_str()), roundedFormat, StringReference(unit2.accessibleName.c_str())); - return make_pair(ratioString, accessibleRatioString); + return make_pair(ratioString->Data(), accessibleRatioString->Data()); } } } @@ -349,12 +351,12 @@ future CurrencyDataLoader::TryLoadDataFromCacheAsync() } catch (Exception ^ ex) { - TraceLogger::GetInstance().LogPlatformException(ViewMode::Currency, __FUNCTIONW__, ex); + TraceLogger::GetInstance()->LogPlatformException(ViewMode::Currency, __FUNCTIONW__, ex); co_return false; } catch (const exception& e) { - TraceLogger::GetInstance().LogStandardException(ViewMode::Currency, __FUNCTIONW__, e); + TraceLogger::GetInstance()->LogStandardException(ViewMode::Currency, __FUNCTIONW__, e); co_return false; } catch (...) @@ -459,12 +461,12 @@ future CurrencyDataLoader::TryLoadDataFromWebAsync() } catch (Exception ^ ex) { - TraceLogger::GetInstance().LogPlatformException(ViewMode::Currency, __FUNCTIONW__, ex); + TraceLogger::GetInstance()->LogPlatformException(ViewMode::Currency, __FUNCTIONW__, ex); co_return false; } catch (const exception& e) { - TraceLogger::GetInstance().LogStandardException(ViewMode::Currency, __FUNCTIONW__, e); + TraceLogger::GetInstance()->LogStandardException(ViewMode::Currency, __FUNCTIONW__, e); co_return false; } catch (...) @@ -480,7 +482,7 @@ future CurrencyDataLoader::TryLoadDataFromWebOverrideAsync() if (!didLoad) { m_loadStatus = CurrencyLoadStatus::FailedToLoad; - TraceLogger::GetInstance().LogError(ViewMode::Currency, L"CurrencyDataLoader::TryLoadDataFromWebOverrideAsync", L"UserRequestedRefreshFailed"); + TraceLogger::GetInstance()->LogError(ViewMode::Currency, L"CurrencyDataLoader::TryLoadDataFromWebOverrideAsync", L"UserRequestedRefreshFailed"); } co_return didLoad; @@ -747,21 +749,19 @@ void CurrencyDataLoader::UpdateDisplayedTimestamp() } wstring CurrencyDataLoader::GetCurrencyTimestamp() { - wstring timestamp = L""; - DateTime epoch{}; if (m_cacheTimestamp.UniversalTime != epoch.UniversalTime) { - DateTimeFormatter ^ dateFormatter = ref new DateTimeFormatter(L"{month.abbreviated} {day.integer}, {year.full}"); - wstring date = dateFormatter->Format(m_cacheTimestamp)->Data(); + DateTimeFormatter ^ dateFormatter = ref new DateTimeFormatter(L"shortdate"); + auto date = dateFormatter->Format(m_cacheTimestamp); DateTimeFormatter ^ timeFormatter = ref new DateTimeFormatter(L"shorttime"); - wstring time = timeFormatter->Format(m_cacheTimestamp)->Data(); + auto time = timeFormatter->Format(m_cacheTimestamp); - timestamp = LocalizationStringUtil::GetLocalizedString(m_timestampFormat.c_str(), date.c_str(), time.c_str()); + return LocalizationStringUtil::GetLocalizedString(m_timestampFormat, date, time)->Data(); } - return timestamp; + return L""; } #pragma optimize("", off) // Turn off optimizations to work around DevDiv 393321 diff --git a/src/CalcViewModel/DataLoaders/CurrencyDataLoader.h b/src/CalcViewModel/DataLoaders/CurrencyDataLoader.h index 7a28c6c7..f4b5082d 100644 --- a/src/CalcViewModel/DataLoaders/CurrencyDataLoader.h +++ b/src/CalcViewModel/DataLoaders/CurrencyDataLoader.h @@ -124,9 +124,9 @@ namespace CalculatorApp std::shared_ptr m_vmCallback; Windows::Globalization::NumberFormatting::DecimalFormatter ^ m_ratioFormatter; - std::wstring m_ratioFormat; + Platform::String ^ m_ratioFormat; Windows::Foundation::DateTime m_cacheTimestamp; - std::wstring m_timestampFormat; + Platform::String ^ m_timestampFormat; CurrencyLoadStatus m_loadStatus; diff --git a/src/CalcViewModel/DataLoaders/UnitConverterDataLoader.cpp b/src/CalcViewModel/DataLoaders/UnitConverterDataLoader.cpp index e69b8e2c..f90260d4 100644 --- a/src/CalcViewModel/DataLoaders/UnitConverterDataLoader.cpp +++ b/src/CalcViewModel/DataLoaders/UnitConverterDataLoader.cpp @@ -953,7 +953,7 @@ void UnitConverterDataLoader::GetConversionData(_In_ unordered_mapData(); + return AppResourceProvider::GetInstance()->GetResourceString(stringId)->Data(); } void UnitConverterDataLoader::GetExplicitConversionData(_In_ unordered_map>& unitToUnitConversionList) diff --git a/src/CalcViewModel/DateCalculatorViewModel.cpp b/src/CalcViewModel/DateCalculatorViewModel.cpp index e89c136a..20ee012b 100644 --- a/src/CalcViewModel/DateCalculatorViewModel.cpp +++ b/src/CalcViewModel/DateCalculatorViewModel.cpp @@ -45,13 +45,13 @@ DateCalculatorViewModel::DateCalculatorViewModel() , m_StrDateResult(L"") , m_StrDateResultAutomationName(L"") { - const auto& localizationSettings = LocalizationSettings::GetInstance(); + const auto & localizationSettings = LocalizationSettings::GetInstance(); // Initialize Date Output format instances InitializeDateOutputFormats(localizationSettings.GetCalendarIdentifier()); // Initialize Date Calc engine - m_dateCalcEngine = make_shared(localizationSettings.GetCalendarIdentifier()); + m_dateCalcEngine = ref new 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 @@ -111,20 +111,20 @@ void DateCalculatorViewModel::OnPropertyChanged(_In_ String ^ prop) void DateCalculatorViewModel::OnInputsChanged() { - DateDifference dateDiff; - if (m_IsDateDiffMode) { DateTime clippedFromDate = ClipTime(FromDate, true); DateTime clippedToDate = ClipTime(ToDate, true); // Calculate difference between two dates - if (m_dateCalcEngine->TryGetDateDifference(clippedFromDate, clippedToDate, m_daysOutputFormat, &dateDiff)) + auto dateDiff = m_dateCalcEngine->TryGetDateDifference(clippedFromDate, clippedToDate, m_daysOutputFormat); + if (dateDiff != nullptr) { - DateDiffResultInDays = dateDiff; - if (m_dateCalcEngine->TryGetDateDifference(clippedFromDate, clippedToDate, m_allDateUnitsOutputFormat, &dateDiff)) + DateDiffResultInDays = dateDiff->Value; + dateDiff = m_dateCalcEngine->TryGetDateDifference(clippedFromDate, clippedToDate, m_allDateUnitsOutputFormat); + if (dateDiff != nullptr) { - DateDiffResult = dateDiff; + DateDiffResult = dateDiff->Value; } else { @@ -140,26 +140,28 @@ void DateCalculatorViewModel::OnInputsChanged() } else { + DateDifference dateDiff; dateDiff.day = DaysOffset; dateDiff.month = MonthsOffset; dateDiff.year = YearsOffset; - DateTime dateTimeResult; + IBox ^ dateTimeResult; if (m_IsAddMode) { // Add number of Days, Months and Years to a Date - IsOutOfBound = !m_dateCalcEngine->AddDuration(StartDate, dateDiff, &dateTimeResult); + dateTimeResult = m_dateCalcEngine->AddDuration(StartDate, dateDiff); } else { // Subtract number of Days, Months and Years from a Date - IsOutOfBound = !m_dateCalcEngine->SubtractDuration(StartDate, dateDiff, &dateTimeResult); + dateTimeResult = m_dateCalcEngine->SubtractDuration(StartDate, dateDiff); } + IsOutOfBound = dateTimeResult == nullptr; if (!m_isOutOfBound) { - DateResult = dateTimeResult; + DateResult = dateTimeResult->Value; } } } @@ -172,17 +174,16 @@ void DateCalculatorViewModel::UpdateDisplayResult() { IsDiffInDays = false; StrDateDiffResultInDays = L""; - StrDateDiffResult = AppResourceProvider::GetInstance().GetResourceString(L"CalculationFailed"); + StrDateDiffResult = AppResourceProvider::GetInstance()->GetResourceString(L"CalculationFailed"); } else if (m_dateDiffResultInDays.day == 0) { // to and from dates the same IsDiffInDays = true; StrDateDiffResultInDays = L""; - StrDateDiffResult = AppResourceProvider::GetInstance().GetResourceString(L"Date_SameDates"); + StrDateDiffResult = AppResourceProvider::GetInstance()->GetResourceString(L"Date_SameDates"); } - else if (m_dateDiffResult == DateDifferenceUnknown || - (m_dateDiffResult.year == 0 && m_dateDiffResult.month == 0 && m_dateDiffResult.week == 0)) + else if (m_dateDiffResult == DateDifferenceUnknown || (m_dateDiffResult.year == 0 && m_dateDiffResult.month == 0 && m_dateDiffResult.week == 0)) { IsDiffInDays = true; StrDateDiffResultInDays = L""; @@ -206,7 +207,7 @@ void DateCalculatorViewModel::UpdateDisplayResult() if (m_isOutOfBound) { // Display Date out of bound message - StrDateResult = AppResourceProvider::GetInstance().GetResourceString(L"Date_OutOfBoundMessage"); + StrDateResult = AppResourceProvider::GetInstance()->GetResourceString(L"Date_OutOfBoundMessage"); } else { @@ -218,16 +219,14 @@ void DateCalculatorViewModel::UpdateDisplayResult() void DateCalculatorViewModel::UpdateStrDateDiffResultAutomationName() { - String ^ automationFormat = AppResourceProvider::GetInstance().GetResourceString(L"Date_DifferenceResultAutomationName"); - wstring localizedAutomationName = LocalizationStringUtil::GetLocalizedString(automationFormat->Data(), StrDateDiffResult->Data()); - StrDateDiffResultAutomationName = ref new String(localizedAutomationName.c_str()); + String ^ automationFormat = AppResourceProvider::GetInstance()->GetResourceString(L"Date_DifferenceResultAutomationName"); + StrDateDiffResultAutomationName = LocalizationStringUtil::GetLocalizedString(automationFormat, StrDateDiffResult); } void DateCalculatorViewModel::UpdateStrDateResultAutomationName() { - String ^ automationFormat = AppResourceProvider::GetInstance().GetResourceString(L"Date_ResultingDateAutomationName"); - wstring localizedAutomationName = LocalizationStringUtil::GetLocalizedString(automationFormat->Data(), StrDateResult->Data()); - StrDateResultAutomationName = ref new String(localizedAutomationName.c_str()); + String ^ automationFormat = AppResourceProvider::GetInstance()->GetResourceString(L"Date_ResultingDateAutomationName"); + StrDateResultAutomationName = LocalizationStringUtil::GetLocalizedString(automationFormat, StrDateResult); } void DateCalculatorViewModel::InitializeDateOutputFormats(_In_ String ^ calendarIdentifier) @@ -247,21 +246,21 @@ String ^ DateCalculatorViewModel::GetDateDiffString() const { wstring result; bool addDelimiter = false; - AppResourceProvider resourceLoader = AppResourceProvider::GetInstance(); + AppResourceProvider ^ resourceLoader = AppResourceProvider::GetInstance(); auto yearCount = m_dateDiffResult.year; if (yearCount > 0) { result += GetLocalizedNumberString(yearCount)->Data(); - result += L" "; + result += L' '; if (yearCount > 1) { - result += resourceLoader.GetResourceString(L"Date_Years")->Data(); + result += resourceLoader->GetResourceString(L"Date_Years")->Data(); } else { - result += resourceLoader.GetResourceString(L"Date_Year")->Data(); + result += resourceLoader->GetResourceString(L"Date_Year")->Data(); } // set the flags to add a delimiter whenever the next unit is added @@ -281,15 +280,15 @@ String ^ DateCalculatorViewModel::GetDateDiffString() const } result += GetLocalizedNumberString(monthCount)->Data(); - result += L" "; + result += L' '; if (monthCount > 1) { - result += resourceLoader.GetResourceString(L"Date_Months")->Data(); + result += resourceLoader->GetResourceString(L"Date_Months")->Data(); } else { - result += resourceLoader.GetResourceString(L"Date_Month")->Data(); + result += resourceLoader->GetResourceString(L"Date_Month")->Data(); } } @@ -306,15 +305,15 @@ String ^ DateCalculatorViewModel::GetDateDiffString() const } result += GetLocalizedNumberString(weekCount)->Data(); - result += L" "; + result += L' '; if (weekCount > 1) { - result += resourceLoader.GetResourceString(L"Date_Weeks")->Data(); + result += resourceLoader->GetResourceString(L"Date_Weeks")->Data(); } else { - result += resourceLoader.GetResourceString(L"Date_Week")->Data(); + result += resourceLoader->GetResourceString(L"Date_Week")->Data(); } } @@ -331,15 +330,15 @@ String ^ DateCalculatorViewModel::GetDateDiffString() const } result += GetLocalizedNumberString(dayCount)->Data(); - result += L" "; + result += L' '; if (dayCount > 1) { - result += resourceLoader.GetResourceString(L"Date_Days")->Data(); + result += resourceLoader->GetResourceString(L"Date_Days")->Data(); } else { - result += resourceLoader.GetResourceString(L"Date_Day")->Data(); + result += resourceLoader->GetResourceString(L"Date_Day")->Data(); } } @@ -349,16 +348,16 @@ String ^ DateCalculatorViewModel::GetDateDiffString() const String ^ DateCalculatorViewModel::GetDateDiffStringInDays() const { wstring result = GetLocalizedNumberString(m_dateDiffResultInDays.day)->Data(); - result += L" "; + result += L' '; // Display the result as '1 day' or 'N days' if (m_dateDiffResultInDays.day > 1) { - result += AppResourceProvider::GetInstance().GetResourceString(L"Date_Days")->Data(); + result += AppResourceProvider::GetInstance()->GetResourceString(L"Date_Days")->Data(); } else { - result += AppResourceProvider::GetInstance().GetResourceString(L"Date_Day")->Data(); + result += AppResourceProvider::GetInstance()->GetResourceString(L"Date_Day")->Data(); } return ref new String(result.data()); diff --git a/src/CalcViewModel/DateCalculatorViewModel.h b/src/CalcViewModel/DateCalculatorViewModel.h index c1cce242..d9e73f4b 100644 --- a/src/CalcViewModel/DateCalculatorViewModel.h +++ b/src/CalcViewModel/DateCalculatorViewModel.h @@ -176,7 +176,7 @@ namespace CalculatorApp CalculatorApp::Common::DateCalculation::DateDifference m_dateDiffResultInDays; // Private members - std::shared_ptr m_dateCalcEngine; + CalculatorApp::Common::DateCalculation::DateCalculationEngine ^ m_dateCalcEngine; CalculatorApp::Common::DateCalculation::DateUnit m_daysOutputFormat; CalculatorApp::Common::DateCalculation::DateUnit m_allDateUnitsOutputFormat; Windows::Globalization::DateTimeFormatting::DateTimeFormatter ^ m_dateTimeFormatter; diff --git a/src/CalcViewModel/HistoryItemViewModel.cpp b/src/CalcViewModel/HistoryItemViewModel.cpp index 63d5e966..3512e7d6 100644 --- a/src/CalcViewModel/HistoryItemViewModel.cpp +++ b/src/CalcViewModel/HistoryItemViewModel.cpp @@ -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" @@ -13,8 +13,8 @@ using namespace Platform; HistoryItemViewModel::HistoryItemViewModel( String ^ expression, String ^ result, - _In_ const shared_ptr>>& spTokens, - _In_ const shared_ptr>>& spCommands) + _In_ const shared_ptr>>& spTokens, + _In_ const shared_ptr>>& spCommands) : m_expression(expression) , m_result(result) , m_spTokens(spTokens) @@ -27,47 +27,17 @@ HistoryItemViewModel::HistoryItemViewModel( String ^ HistoryItemViewModel::GetAccessibleExpressionFromTokens( - _In_ shared_ptr>> const& spTokens, + _In_ shared_ptr>> const& spTokens, _In_ String ^ fallbackExpression) { // updating accessibility names for expression and result wstringstream accExpression{}; accExpression << L""; - unsigned int nTokens; - HRESULT hr = spTokens->GetSize(&nTokens); - if (SUCCEEDED(hr)) + for (const auto& tokenItem : *spTokens) { - pair tokenItem; - for (unsigned int i = 0; i < nTokens; i++) - { - hr = spTokens->GetAt(i, &tokenItem); - if (FAILED(hr)) - { - break; - } - - wstring token = tokenItem.first; - accExpression << LocalizationService::GetNarratorReadableToken(StringReference(token.c_str()))->Data(); - } + accExpression << LocalizationService::GetNarratorReadableToken(StringReference(tokenItem.first.c_str()))->Data(); } - if (SUCCEEDED(hr)) - { - wstring expressionSuffix{}; - hr = spTokens->GetExpressionSuffix(&expressionSuffix); - if (SUCCEEDED(hr)) - { - accExpression << expressionSuffix; - } - } - - if (FAILED(hr)) - { - return LocalizationService::GetNarratorReadableString(fallbackExpression); - } - else - { - return ref new String(accExpression.str().c_str()); - } + return ref new String(accExpression.str().c_str()); } diff --git a/src/CalcViewModel/HistoryItemViewModel.h b/src/CalcViewModel/HistoryItemViewModel.h index fae51e69..cc479518 100644 --- a/src/CalcViewModel/HistoryItemViewModel.h +++ b/src/CalcViewModel/HistoryItemViewModel.h @@ -3,7 +3,6 @@ #pragma once -#include "CalcManager/CalculatorVector.h" #include "CalcManager/ExpressionCommandInterface.h" namespace CalculatorApp @@ -17,15 +16,15 @@ namespace CalculatorApp HistoryItemViewModel( Platform::String ^ expression, Platform::String ^ result, - _In_ std::shared_ptr>> const& spTokens, - _In_ std::shared_ptr>> const& spCommands); + _In_ std::shared_ptr>> const& spTokens, + _In_ std::shared_ptr>> const& spCommands); - std::shared_ptr>> const& GetTokens() + std::shared_ptr>> const& GetTokens() { return m_spTokens; } - std::shared_ptr>> const& GetCommands() + std::shared_ptr>> const& GetCommands() { return m_spCommands; } @@ -62,7 +61,7 @@ namespace CalculatorApp private : static Platform::String ^ GetAccessibleExpressionFromTokens( - _In_ std::shared_ptr>> const& spTokens, + _In_ std::shared_ptr>> const& spTokens, _In_ Platform::String ^ fallbackExpression); private: @@ -70,8 +69,8 @@ namespace CalculatorApp Platform::String ^ m_accExpression; Platform::String ^ m_accResult; Platform::String ^ m_result; - std::shared_ptr>> m_spTokens; - std::shared_ptr>> m_spCommands; + std::shared_ptr>> m_spTokens; + std::shared_ptr>> m_spCommands; }; } } diff --git a/src/CalcViewModel/HistoryViewModel.cpp b/src/CalcViewModel/HistoryViewModel.cpp index 8da5007a..58bd726d 100644 --- a/src/CalcViewModel/HistoryViewModel.cpp +++ b/src/CalcViewModel/HistoryViewModel.cpp @@ -120,7 +120,7 @@ void HistoryViewModel::ShowItem(_In_ HistoryItemViewModel ^ e) { unsigned int index; Items->IndexOf(e, &index); - TraceLogger::GetInstance().LogHistoryItemLoad((ViewMode)m_currentMode, ItemSize, (int)(index)); + TraceLogger::GetInstance()->LogHistoryItemLoad((ViewMode)m_currentMode, ItemSize, (int)(index)); HistoryItemClicked(e); } @@ -164,7 +164,11 @@ void HistoryViewModel::OnClearCommand(_In_ Platform::Object ^ e) UpdateItemSize(); } - MakeHistoryClearedNarratorAnnouncement(HistoryResourceKeys::HistoryCleared, m_localizedHistoryCleared); + if (m_localizedHistoryCleared == nullptr) + { + m_localizedHistoryCleared = AppResourceProvider::GetInstance()->GetResourceString(HistoryResourceKeys::HistoryCleared); + } + HistoryAnnouncement = CalculatorAnnouncement::GetHistoryClearedAnnouncement(m_localizedHistoryCleared); } } @@ -263,16 +267,16 @@ void HistoryViewModel::ClearHistory() void HistoryViewModel::SaveHistory() { ApplicationDataContainer ^ historyContainer = GetHistoryContainer(m_currentMode); - auto currentHistoryVector = m_calculatorManager->GetHistoryItems(m_currentMode); + auto const& currentHistoryVector = m_calculatorManager->GetHistoryItems(m_currentMode); bool failure = false; int index = 0; Platform::String ^ serializedHistoryItem; - for (auto iter = currentHistoryVector.begin(); iter != currentHistoryVector.end(); ++iter) + for (auto const& item : currentHistoryVector) { try { - serializedHistoryItem = SerializeHistoryItem(*iter); + serializedHistoryItem = SerializeHistoryItem(item); historyContainer->Values->Insert(index.ToString(), serializedHistoryItem); } catch (Platform::Exception ^) @@ -370,10 +374,3 @@ void HistoryViewModel::UpdateItemSize() { ItemSize = Items->Size; } - -void HistoryViewModel::MakeHistoryClearedNarratorAnnouncement(String ^ resourceKey, String ^ &formatVariable) -{ - String ^ announcement = LocalizationStringUtil::GetLocalizedNarratorAnnouncement(resourceKey, formatVariable); - - HistoryAnnouncement = CalculatorAnnouncement::GetHistoryClearedAnnouncement(announcement); -} diff --git a/src/CalcViewModel/HistoryViewModel.h b/src/CalcViewModel/HistoryViewModel.h index 4ed61d92..75321d39 100644 --- a/src/CalcViewModel/HistoryViewModel.h +++ b/src/CalcViewModel/HistoryViewModel.h @@ -68,8 +68,6 @@ namespace CalculatorApp void UpdateHistoryVectorLength(_In_ int newValue, _In_ CalculationManager::CALCULATOR_MODE cMode); bool IsValid(_In_ CalculationManager::HISTORYITEM item); - void MakeHistoryClearedNarratorAnnouncement(Platform::String ^ resourceKey, Platform::String ^ &formatVariable); - friend class CalculatorDisplay; void UpdateItemSize(); }; diff --git a/src/CalcViewModel/StandardCalculatorViewModel.cpp b/src/CalcViewModel/StandardCalculatorViewModel.cpp index af2c7bc4..8c5b93c2 100644 --- a/src/CalcViewModel/StandardCalculatorViewModel.cpp +++ b/src/CalcViewModel/StandardCalculatorViewModel.cpp @@ -14,6 +14,7 @@ using namespace CalculatorApp::Common; using namespace CalculatorApp::Common::Automation; using namespace CalculatorApp::ViewModel; using namespace CalculationManager; +using namespace concurrency; using namespace Platform; using namespace Platform::Collections; using namespace std; @@ -25,6 +26,7 @@ using namespace Windows::UI::Popups; using namespace Windows::Storage::Streams; using namespace Windows::Foundation::Collections; using namespace Utils; +using namespace concurrency; constexpr int StandardModePrecision = 16; constexpr int ScientificModePrecision = 32; @@ -73,12 +75,11 @@ StandardCalculatorViewModel::StandardCalculatorViewModel() , m_MemorizedNumbers(ref new Vector()) , m_IsMemoryEmpty(true) , m_IsFToEChecked(false) - , m_isShiftChecked(false) , m_IsShiftProgrammerChecked(false) , m_valueBitLength(BitLength::BitLengthQWord) , m_isBitFlipChecked(false) - , m_isBinaryBitFlippingEnabled(false) - , m_CurrentRadixType(RADIX_TYPE::DEC_RADIX) + , m_IsBinaryBitFlippingEnabled(false) + , m_CurrentRadixType(NumberBase::DecBase) , m_CurrentAngleType(NumbersAndOperatorsEnum::Degree) , m_Announcement(nullptr) , m_OpenParenthesisCount(0) @@ -92,17 +93,20 @@ StandardCalculatorViewModel::StandardCalculatorViewModel() , m_localizedMemoryCleared(nullptr) , m_localizedOpenParenthesisCountChangedAutomationFormat(nullptr) , m_localizedNoRightParenthesisAddedFormat(nullptr) + , m_TokenPosition(-1) + , m_isLastOperationHistoryLoad(false) { WeakReference calculatorViewModel(this); + auto appResourceProvider = AppResourceProvider::GetInstance(); m_calculatorDisplay.SetCallback(calculatorViewModel); - m_expressionAutomationNameFormat = AppResourceProvider::GetInstance().GetResourceString(CalculatorResourceKeys::CalculatorExpression); - m_localizedCalculationResultAutomationFormat = AppResourceProvider::GetInstance().GetResourceString(CalculatorResourceKeys::CalculatorResults); + m_expressionAutomationNameFormat = appResourceProvider->GetResourceString(CalculatorResourceKeys::CalculatorExpression); + m_localizedCalculationResultAutomationFormat = appResourceProvider->GetResourceString(CalculatorResourceKeys::CalculatorResults); m_localizedCalculationResultDecimalAutomationFormat = - AppResourceProvider::GetInstance().GetResourceString(CalculatorResourceKeys::CalculatorResults_DecimalSeparator_Announced); - m_localizedHexaDecimalAutomationFormat = AppResourceProvider::GetInstance().GetResourceString(CalculatorResourceKeys::HexButton); - m_localizedDecimalAutomationFormat = AppResourceProvider::GetInstance().GetResourceString(CalculatorResourceKeys::DecButton); - m_localizedOctalAutomationFormat = AppResourceProvider::GetInstance().GetResourceString(CalculatorResourceKeys::OctButton); - m_localizedBinaryAutomationFormat = AppResourceProvider::GetInstance().GetResourceString(CalculatorResourceKeys::BinButton); + appResourceProvider->GetResourceString(CalculatorResourceKeys::CalculatorResults_DecimalSeparator_Announced); + m_localizedHexaDecimalAutomationFormat = appResourceProvider->GetResourceString(CalculatorResourceKeys::HexButton); + m_localizedDecimalAutomationFormat = appResourceProvider->GetResourceString(CalculatorResourceKeys::DecButton); + m_localizedOctalAutomationFormat = appResourceProvider->GetResourceString(CalculatorResourceKeys::OctButton); + m_localizedBinaryAutomationFormat = appResourceProvider->GetResourceString(CalculatorResourceKeys::BinButton); // Initialize the Automation Name CalculationResultAutomationName = GetLocalizedStringFormat(m_localizedCalculationResultAutomationFormat, m_DisplayValue); @@ -128,9 +132,6 @@ StandardCalculatorViewModel::StandardCalculatorViewModel() IsDecimalEnabled = true; AreHistoryShortcutsEnabled = true; AreProgrammerRadixOperatorsEnabled = false; - - m_tokenPosition = -1; - m_isLastOperationHistoryLoad = false; } String ^ StandardCalculatorViewModel::LocalizeDisplayValue(_In_ wstring const& displayValue, _In_ bool isError) @@ -166,7 +167,7 @@ String ^ StandardCalculatorViewModel::CalculateNarratorDisplayValue(_In_ wstring } // In Programmer modes using non-base10, we want the strings to be read as literal digits. - if (IsProgrammer && CurrentRadixType != RADIX_TYPE::DEC_RADIX) + if (IsProgrammer && CurrentRadixType != NumberBase::DecBase) { localizedValue = GetNarratorStringReadRawNumbers(localizedValue); } @@ -193,13 +194,13 @@ String ^ StandardCalculatorViewModel::GetNarratorStringReadRawNumbers(_In_ Strin return ref new String(wss.str().c_str()); } -void StandardCalculatorViewModel::SetPrimaryDisplay(_In_ wstring const& displayStringValue, _In_ bool isError) +void StandardCalculatorViewModel::SetPrimaryDisplay(_In_ String ^ displayStringValue, _In_ bool isError) { - String ^ localizedDisplayStringValue = LocalizeDisplayValue(displayStringValue, isError); + String ^ localizedDisplayStringValue = LocalizeDisplayValue(displayStringValue->Data(), isError); // Set this variable before the DisplayValue is modified, Otherwise the DisplayValue will // not match what the narrator is saying - m_CalculationResultAutomationName = CalculateNarratorDisplayValue(displayStringValue, localizedDisplayStringValue, isError); + m_CalculationResultAutomationName = CalculateNarratorDisplayValue(displayStringValue->Data(), localizedDisplayStringValue, isError); AreAlwaysOnTopResultsUpdated = false; if (DisplayValue != localizedDisplayStringValue) @@ -240,10 +241,13 @@ void StandardCalculatorViewModel::SetOpenParenthesisCountNarratorAnnouncement() wstring localizedParenthesisCount = to_wstring(m_OpenParenthesisCount).c_str(); LocalizationSettings::GetInstance().LocalizeDisplayValue(&localizedParenthesisCount); - String ^ announcement = LocalizationStringUtil::GetLocalizedNarratorAnnouncement( - CalculatorResourceKeys::OpenParenthesisCountAutomationFormat, - m_localizedOpenParenthesisCountChangedAutomationFormat, - localizedParenthesisCount.c_str()); + if (m_localizedOpenParenthesisCountChangedAutomationFormat == nullptr) + { + m_localizedOpenParenthesisCountChangedAutomationFormat = + AppResourceProvider::GetInstance()->GetResourceString(CalculatorResourceKeys::OpenParenthesisCountAutomationFormat); + } + String ^ announcement = + LocalizationStringUtil::GetLocalizedString(m_localizedOpenParenthesisCountChangedAutomationFormat, StringReference(localizedParenthesisCount.c_str())); Announcement = CalculatorAnnouncement::GetOpenParenthesisCountChangedAnnouncement(announcement); } @@ -255,10 +259,13 @@ void StandardCalculatorViewModel::OnNoRightParenAdded() void StandardCalculatorViewModel::SetNoParenAddedNarratorAnnouncement() { - String ^ announcement = - LocalizationStringUtil::GetLocalizedNarratorAnnouncement(CalculatorResourceKeys::NoParenthesisAdded, m_localizedNoRightParenthesisAddedFormat); + if (m_localizedNoRightParenthesisAddedFormat == nullptr) + { + m_localizedNoRightParenthesisAddedFormat = + AppResourceProvider::GetInstance()->GetResourceString(CalculatorResourceKeys::NoParenthesisAdded); + } - Announcement = CalculatorAnnouncement::GetNoRightParenthesisAddedAnnouncement(announcement); + Announcement = CalculatorAnnouncement::GetNoRightParenthesisAddedAnnouncement(m_localizedNoRightParenthesisAddedFormat); } void StandardCalculatorViewModel::DisableButtons(CommandType selectedExpressionCommandType) @@ -290,8 +297,8 @@ void StandardCalculatorViewModel::DisableButtons(CommandType selectedExpressionC } void StandardCalculatorViewModel::SetExpressionDisplay( - _Inout_ shared_ptr>> const& tokens, - _Inout_ shared_ptr>> const& commands) + _Inout_ shared_ptr>> const& tokens, + _Inout_ shared_ptr>> const& commands) { m_tokens = tokens; m_commands = commands; @@ -306,11 +313,11 @@ void StandardCalculatorViewModel::SetExpressionDisplay( } void StandardCalculatorViewModel::SetHistoryExpressionDisplay( - _Inout_ shared_ptr>> const& tokens, - _Inout_ shared_ptr>> const& commands) + _Inout_ shared_ptr>> const& tokens, + _Inout_ shared_ptr>> const& commands) { - m_tokens = make_shared>>(*tokens); - m_commands = make_shared>>(*commands); + m_tokens = make_shared>>(*tokens); + m_commands = make_shared>>(*commands); IsEditingEnabled = false; // Setting the History Item Load Mode so that UI does not get updated with recalculation of every token @@ -320,12 +327,11 @@ void StandardCalculatorViewModel::SetHistoryExpressionDisplay( m_isLastOperationHistoryLoad = true; } -void StandardCalculatorViewModel::SetTokens(_Inout_ shared_ptr>> const& tokens) +void StandardCalculatorViewModel::SetTokens(_Inout_ shared_ptr>> const& tokens) { AreTokensUpdated = false; - unsigned int nTokens = 0; - tokens->GetSize(&nTokens); + const size_t nTokens = tokens->size(); if (nTokens == 0) { @@ -333,51 +339,48 @@ void StandardCalculatorViewModel::SetTokens(_Inout_ shared_ptr currentToken; const auto& localizer = LocalizationSettings::GetInstance(); const wstring separator = L" "; for (unsigned int i = 0; i < nTokens; ++i) { - if (SUCCEEDED(tokens->GetAt(i, ¤tToken))) + auto currentToken = (*tokens)[i]; + + Common::TokenType type; + bool isEditable = currentToken.second != -1; + localizer.LocalizeDisplayValue(&(currentToken.first)); + + if (!isEditable) { - Common::TokenType type; - bool isEditable = (currentToken.second == -1) ? false : true; - localizer.LocalizeDisplayValue(&(currentToken.first)); + type = currentToken.first == separator ? TokenType::Separator : TokenType::Operator; + } + else + { + const shared_ptr& command = m_commands->at(currentToken.second); + type = command->GetCommandType() == CommandType::OperandCommand ? TokenType::Operand : TokenType::Operator; + } - if (!isEditable) + auto currentTokenString = StringReference(currentToken.first.c_str()); + if (i < m_ExpressionTokens->Size) + { + auto existingItem = m_ExpressionTokens->GetAt(i); + if (type == existingItem->Type && existingItem->Token->Equals(currentTokenString)) { - type = currentToken.first == separator ? TokenType::Separator : TokenType::Operator; - } - else - { - shared_ptr command; - IFTPlatformException(m_commands->GetAt(static_cast(currentToken.second), &command)); - type = command->GetCommandType() == CommandType::OperandCommand ? TokenType::Operand : TokenType::Operator; - } - - auto currentTokenString = ref new String(currentToken.first.c_str()); - if (i < m_ExpressionTokens->Size) - { - auto existingItem = m_ExpressionTokens->GetAt(i); - if (type == existingItem->Type && existingItem->Token->Equals(currentTokenString)) - { - existingItem->TokenPosition = i; - existingItem->IsTokenEditable = isEditable; - existingItem->CommandIndex = 0; - } - else - { - auto expressionToken = ref new DisplayExpressionToken(currentTokenString, i, isEditable, type); - m_ExpressionTokens->InsertAt(i, expressionToken); - } + existingItem->TokenPosition = i; + existingItem->IsTokenEditable = isEditable; + existingItem->CommandIndex = 0; } else { auto expressionToken = ref new DisplayExpressionToken(currentTokenString, i, isEditable, type); - m_ExpressionTokens->Append(expressionToken); + m_ExpressionTokens->InsertAt(i, expressionToken); } } + else + { + auto expressionToken = ref new DisplayExpressionToken(currentTokenString, i, isEditable, type); + m_ExpressionTokens->Append(expressionToken); + } } while (m_ExpressionTokens->Size != nTokens) @@ -451,7 +454,7 @@ void StandardCalculatorViewModel::FtoEButtonToggled() void StandardCalculatorViewModel::HandleUpdatedOperandData(Command cmdenum) { - DisplayExpressionToken ^ displayExpressionToken = ExpressionTokens->GetAt(m_tokenPosition); + DisplayExpressionToken ^ displayExpressionToken = ExpressionTokens->GetAt(m_TokenPosition); if (displayExpressionToken == nullptr) { return; @@ -579,7 +582,7 @@ void StandardCalculatorViewModel::HandleUpdatedOperandData(Command cmdenum) } String ^ updatedData = ref new String(temp); - UpdateOperand(m_tokenPosition, updatedData); + UpdateOperand(m_TokenPosition, updatedData); displayExpressionToken->Token = updatedData; IsOperandUpdatedUsingViewModel = true; displayExpressionToken->CommandIndex = commandIndex; @@ -608,7 +611,7 @@ void StandardCalculatorViewModel::OnButtonPressed(Object ^ parameter) { m_standardCalculatorManager.SendCommand(Command::CommandCLEAR); - if (!IsRecoverableCommand((int)numOpEnum)) + if (!IsRecoverableCommand(static_cast(numOpEnum))) { return; } @@ -618,7 +621,7 @@ void StandardCalculatorViewModel::OnButtonPressed(Object ^ parameter) && numOpEnum != NumbersAndOperatorsEnum::IsProgrammerMode && numOpEnum != NumbersAndOperatorsEnum::FToE && (numOpEnum != NumbersAndOperatorsEnum::Degree) && (numOpEnum != NumbersAndOperatorsEnum::Radians) && (numOpEnum != NumbersAndOperatorsEnum::Grads)) { - if (!m_keyPressed) + if (!m_KeyPressed) { SaveEditedCommand(m_selectedExpressionToken->TokenPosition, cmdenum); } @@ -671,29 +674,24 @@ void StandardCalculatorViewModel::OnButtonPressed(Object ^ parameter) m_isLastOperationHistoryLoad = false; } - TraceLogger::GetInstance().UpdateButtonUsage(numOpEnum, GetCalculatorMode()); + TraceLogger::GetInstance()->UpdateButtonUsage(numOpEnum, GetCalculatorMode()); m_standardCalculatorManager.SendCommand(cmdenum); } } } -int StandardCalculatorViewModel::GetNumberBase() +RADIX_TYPE StandardCalculatorViewModel::GetRadixTypeFromNumberBase(NumberBase base) { - if (CurrentRadixType == HEX_RADIX) + switch (base) { - return HexBase; - } - else if (CurrentRadixType == DEC_RADIX) - { - return DecBase; - } - else if (CurrentRadixType == OCT_RADIX) - { - return OctBase; - } - else - { - return BinBase; + case NumberBase::BinBase: + return RADIX_TYPE::BIN_RADIX; + case NumberBase::HexBase: + return RADIX_TYPE::HEX_RADIX; + case NumberBase::OctBase: + return RADIX_TYPE::OCT_RADIX; + default: + return RADIX_TYPE::DEC_RADIX; } } @@ -701,7 +699,7 @@ void StandardCalculatorViewModel::OnCopyCommand(Object ^ parameter) { CopyPasteManager::CopyToClipboard(GetRawDisplayValue()); - String ^ announcement = AppResourceProvider::GetInstance().GetResourceString(CalculatorResourceKeys::DisplayCopied); + String ^ announcement = AppResourceProvider::GetInstance()->GetResourceString(CalculatorResourceKeys::DisplayCopied); Announcement = CalculatorAnnouncement::GetDisplayCopiedAnnouncement(announcement); } @@ -709,8 +707,8 @@ void StandardCalculatorViewModel::OnPasteCommand(Object ^ parameter) { auto that(this); ViewMode mode; - int NumberBase = -1; BitLength bitLengthType = BitLength::BitLengthUnknown; + NumberBase numberBase = NumberBase::Unknown; if (IsScientific) { mode = ViewMode::Scientific; @@ -718,8 +716,8 @@ void StandardCalculatorViewModel::OnPasteCommand(Object ^ parameter) else if (IsProgrammer) { mode = ViewMode::Programmer; - NumberBase = GetNumberBase(); bitLengthType = m_valueBitLength; + numberBase = CurrentRadixType; } else { @@ -732,7 +730,7 @@ void StandardCalculatorViewModel::OnPasteCommand(Object ^ parameter) } // Ensure that the paste happens on the UI thread - CopyPasteManager::GetStringToPaste(mode, NavCategory::GetGroupType(mode), NumberBase, bitLengthType) + create_task(CopyPasteManager::GetStringToPaste(mode, NavCategory::GetGroupType(mode), numberBase, bitLengthType)) .then([that, mode](String ^ pastedString) { that->OnPaste(pastedString); }, concurrency::task_continuation_context::use_current()); } @@ -744,13 +742,13 @@ CalculationManager::Command StandardCalculatorViewModel::ConvertToOperatorsEnum( void StandardCalculatorViewModel::OnPaste(String ^ pastedString) { // If pastedString is invalid("NoOp") then display pasteError else process the string - if (pastedString == StringReference(CopyPasteManager::PasteErrorString)) + if (CopyPasteManager::IsErrorMessage(pastedString)) { this->DisplayPasteError(); return; } - TraceLogger::GetInstance().LogInputPasted(GetCalculatorMode()); + TraceLogger::GetInstance()->LogInputPasted(GetCalculatorMode()); bool isFirstLegalChar = true; m_standardCalculatorManager.SendCommand(Command::CommandCENTR); bool sendNegate = false; @@ -766,9 +764,10 @@ void StandardCalculatorViewModel::OnPaste(String ^ pastedString) while (it != pastedString->End()) { bool sendCommand = true; - bool canSendNegate = false; + auto buttonInfo = MapCharacterToButtonId(*it); - NumbersAndOperatorsEnum mappedNumOp = MapCharacterToButtonId(*it, canSendNegate); + NumbersAndOperatorsEnum mappedNumOp = buttonInfo.buttonId; + bool canSendNegate = buttonInfo.canSendNegate; if (mappedNumOp == NumbersAndOperatorsEnum::None) { @@ -870,7 +869,7 @@ void StandardCalculatorViewModel::OnPaste(String ^ pastedString) if (mappedNumOp == NumbersAndOperatorsEnum::Exp) { // Check the following item - switch (MapCharacterToButtonId(*(it + 1), canSendNegate)) + switch (MapCharacterToButtonId(*(it + 1)).buttonId) { case NumbersAndOperatorsEnum::Subtract: { @@ -896,10 +895,13 @@ void StandardCalculatorViewModel::OnClearMemoryCommand(Object ^ parameter) { m_standardCalculatorManager.MemorizedNumberClearAll(); - TraceLogger::GetInstance().UpdateButtonUsage(NumbersAndOperatorsEnum::MemoryClear, GetCalculatorMode()); + TraceLogger::GetInstance()->UpdateButtonUsage(NumbersAndOperatorsEnum::MemoryClear, GetCalculatorMode()); - String ^ announcement = LocalizationStringUtil::GetLocalizedNarratorAnnouncement(CalculatorResourceKeys::MemoryCleared, m_localizedMemoryCleared); - Announcement = CalculatorAnnouncement::GetMemoryClearedAnnouncement(announcement); + if (m_localizedMemoryCleared == nullptr) + { + m_localizedMemoryCleared = AppResourceProvider::GetInstance()->GetResourceString(CalculatorResourceKeys::MemoryCleared); + } + Announcement = CalculatorAnnouncement::GetMemoryClearedAnnouncement(m_localizedMemoryCleared); } void StandardCalculatorViewModel::OnPinUnpinCommand(Object ^ parameter) @@ -917,10 +919,11 @@ void StandardCalculatorViewModel::SetViewPinnedState(bool pinned) IsCurrentViewPinned = pinned; } -NumbersAndOperatorsEnum StandardCalculatorViewModel::MapCharacterToButtonId(const wchar_t ch, bool& canSendNegate) +ButtonInfo StandardCalculatorViewModel::MapCharacterToButtonId(char16 ch) { - NumbersAndOperatorsEnum mappedValue = NumbersAndOperatorsEnum::None; - canSendNegate = false; + ButtonInfo result; + result.buttonId = NumbersAndOperatorsEnum::None; + result.canSendNegate = false; switch (ch) { @@ -934,107 +937,127 @@ NumbersAndOperatorsEnum StandardCalculatorViewModel::MapCharacterToButtonId(cons case '7': case '8': case '9': - mappedValue = NumbersAndOperatorsEnum::Zero + static_cast(ch - L'0'); - canSendNegate = true; + result.buttonId = NumbersAndOperatorsEnum::Zero + static_cast(ch - L'0'); + result.canSendNegate = true; break; case '*': - mappedValue = NumbersAndOperatorsEnum::Multiply; + result.buttonId = NumbersAndOperatorsEnum::Multiply; break; case '+': - mappedValue = NumbersAndOperatorsEnum::Add; + result.buttonId = NumbersAndOperatorsEnum::Add; break; case '-': - mappedValue = NumbersAndOperatorsEnum::Subtract; + result.buttonId = NumbersAndOperatorsEnum::Subtract; break; case '/': - mappedValue = NumbersAndOperatorsEnum::Divide; + result.buttonId = NumbersAndOperatorsEnum::Divide; + break; + + case '^': + if (IsScientific) + { + result.buttonId = NumbersAndOperatorsEnum::XPowerY; + } + break; + + case '%': + if (IsScientific || IsProgrammer) + { + result.buttonId = NumbersAndOperatorsEnum::Mod; + } break; case '=': - mappedValue = NumbersAndOperatorsEnum::Equals; + result.buttonId = NumbersAndOperatorsEnum::Equals; break; case '(': - mappedValue = NumbersAndOperatorsEnum::OpenParenthesis; + result.buttonId = NumbersAndOperatorsEnum::OpenParenthesis; break; case ')': - mappedValue = NumbersAndOperatorsEnum::CloseParenthesis; + result.buttonId = NumbersAndOperatorsEnum::CloseParenthesis; break; case 'a': case 'A': - mappedValue = NumbersAndOperatorsEnum::A; + result.buttonId = NumbersAndOperatorsEnum::A; break; case 'b': case 'B': - mappedValue = NumbersAndOperatorsEnum::B; + result.buttonId = NumbersAndOperatorsEnum::B; break; case 'c': case 'C': - mappedValue = NumbersAndOperatorsEnum::C; + result.buttonId = NumbersAndOperatorsEnum::C; break; case 'd': case 'D': - mappedValue = NumbersAndOperatorsEnum::D; + result.buttonId = NumbersAndOperatorsEnum::D; break; case 'e': case 'E': // Only allow scientific notation in scientific mode if (IsProgrammer) { - mappedValue = NumbersAndOperatorsEnum::E; + result.buttonId = NumbersAndOperatorsEnum::E; } else { - mappedValue = NumbersAndOperatorsEnum::Exp; + result.buttonId = NumbersAndOperatorsEnum::Exp; } break; case 'f': case 'F': - mappedValue = NumbersAndOperatorsEnum::F; + result.buttonId = NumbersAndOperatorsEnum::F; break; default: // For the decimalSeparator, we need to respect the user setting. if (ch == m_decimalSeparator) { - mappedValue = NumbersAndOperatorsEnum::Decimal; + result.buttonId = NumbersAndOperatorsEnum::Decimal; } break; } - if (mappedValue == NumbersAndOperatorsEnum::None) + if (result.buttonId == NumbersAndOperatorsEnum::None) { if (LocalizationSettings::GetInstance().IsLocalizedDigit(ch)) { - mappedValue = - NumbersAndOperatorsEnum::Zero + static_cast(ch - LocalizationSettings::GetInstance().GetDigitSymbolFromEnUsDigit('0')); - canSendNegate = true; + result.buttonId = NumbersAndOperatorsEnum::Zero + + static_cast(ch - LocalizationSettings::GetInstance().GetDigitSymbolFromEnUsDigit('0')); + result.canSendNegate = true; } } // Negate cannot be sent for leading zeroes - if (NumbersAndOperatorsEnum::Zero == mappedValue) + if (NumbersAndOperatorsEnum::Zero == result.buttonId) { - canSendNegate = false; + result.canSendNegate = false; } - return mappedValue; + return result; +} +void StandardCalculatorViewModel::OnInputChanged() +{ + IsInputEmpty = m_standardCalculatorManager.IsInputEmpty(); } void StandardCalculatorViewModel::OnMemoryButtonPressed() { m_standardCalculatorManager.MemorizeNumber(); - TraceLogger::GetInstance().UpdateButtonUsage(NumbersAndOperatorsEnum::Memory, GetCalculatorMode()); - - String ^ announcement = LocalizationStringUtil::GetLocalizedNarratorAnnouncement( - CalculatorResourceKeys::MemorySave, m_localizedMemorySavedAutomationFormat, m_DisplayValue->Data()); + TraceLogger::GetInstance()->UpdateButtonUsage(NumbersAndOperatorsEnum::Memory, GetCalculatorMode()); + if (m_localizedMemorySavedAutomationFormat == nullptr) + { + m_localizedMemorySavedAutomationFormat = AppResourceProvider::GetInstance()->GetResourceString(CalculatorResourceKeys::MemorySave); + } + String ^ announcement = LocalizationStringUtil::GetLocalizedString(m_localizedMemorySavedAutomationFormat, m_DisplayValue); Announcement = CalculatorAnnouncement::GetMemoryItemAddedAnnouncement(announcement); } @@ -1048,9 +1071,12 @@ void StandardCalculatorViewModel::OnMemoryItemChanged(unsigned int indexOfMemory wstring localizedIndex = to_wstring(indexOfMemory + 1); LocalizationSettings::GetInstance().LocalizeDisplayValue(&localizedIndex); - String ^ announcement = LocalizationStringUtil::GetLocalizedNarratorAnnouncement( - CalculatorResourceKeys::MemoryItemChanged, m_localizedMemoryItemChangedAutomationFormat, localizedIndex.c_str(), localizedValue->Data()); - + if (m_localizedMemoryItemChangedAutomationFormat == nullptr) + { + m_localizedMemoryItemChangedAutomationFormat = AppResourceProvider::GetInstance()->GetResourceString(CalculatorResourceKeys::MemoryItemChanged); + } + String ^ announcement = + LocalizationStringUtil::GetLocalizedString(m_localizedMemoryItemChangedAutomationFormat, StringReference(localizedIndex.c_str()), localizedValue); Announcement = CalculatorAnnouncement::GetMemoryItemChangedAnnouncement(announcement); } } @@ -1064,7 +1090,7 @@ void StandardCalculatorViewModel::OnMemoryItemPressed(Object ^ memoryItemPositio HideMemoryClicked(); auto mode = IsStandard ? ViewMode::Standard : IsScientific ? ViewMode::Scientific : ViewMode::Programmer; - TraceLogger::GetInstance().LogMemoryItemLoad(mode, MemorizedNumbers->Size, boxedPosition->Value); + TraceLogger::GetInstance()->LogMemoryItemLoad(mode, MemorizedNumbers->Size, boxedPosition->Value); } } @@ -1075,7 +1101,7 @@ void StandardCalculatorViewModel::OnMemoryAdd(Object ^ memoryItemPosition) if (MemorizedNumbers) { auto boxedPosition = safe_cast ^>(memoryItemPosition); - TraceLogger::GetInstance().UpdateButtonUsage(NumbersAndOperatorsEnum::MemoryAdd, GetCalculatorMode()); + TraceLogger::GetInstance()->UpdateButtonUsage(NumbersAndOperatorsEnum::MemoryAdd, GetCalculatorMode()); m_standardCalculatorManager.MemorizedNumberAdd(boxedPosition->Value); } } @@ -1086,7 +1112,7 @@ void StandardCalculatorViewModel::OnMemorySubtract(Object ^ memoryItemPosition) if (MemorizedNumbers) { auto boxedPosition = safe_cast ^>(memoryItemPosition); - TraceLogger::GetInstance().UpdateButtonUsage(NumbersAndOperatorsEnum::MemorySubtract, GetCalculatorMode()); + TraceLogger::GetInstance()->UpdateButtonUsage(NumbersAndOperatorsEnum::MemorySubtract, GetCalculatorMode()); m_standardCalculatorManager.MemorizedNumberSubtract(boxedPosition->Value); } } @@ -1112,13 +1138,17 @@ void StandardCalculatorViewModel::OnMemoryClear(_In_ Object ^ memoryItemPosition { IsMemoryEmpty = true; } - TraceLogger::GetInstance().UpdateButtonUsage(NumbersAndOperatorsEnum::MemoryClear, GetCalculatorMode()); + TraceLogger::GetInstance()->UpdateButtonUsage(NumbersAndOperatorsEnum::MemoryClear, GetCalculatorMode()); wstring localizedIndex = to_wstring(boxedPosition->Value + 1); LocalizationSettings::GetInstance().LocalizeDisplayValue(&localizedIndex); - String ^ announcement = LocalizationStringUtil::GetLocalizedNarratorAnnouncement( - CalculatorResourceKeys::MemoryItemCleared, m_localizedMemoryItemClearedAutomationFormat, localizedIndex.c_str()); + if (m_localizedMemoryItemClearedAutomationFormat == nullptr) + { + m_localizedMemoryItemClearedAutomationFormat = AppResourceProvider::GetInstance()->GetResourceString(CalculatorResourceKeys::MemoryItemCleared); + } + String ^ announcement = + LocalizationStringUtil::GetLocalizedString(m_localizedMemoryItemClearedAutomationFormat, StringReference(localizedIndex.c_str())); Announcement = CalculatorAnnouncement::GetMemoryClearedAnnouncement(announcement); } @@ -1155,7 +1185,7 @@ void StandardCalculatorViewModel::OnPropertyChanged(String ^ propertyname) } else if (propertyname == IsBitFlipCheckedPropertyName) { - TraceLogger::GetInstance().UpdateButtonUsage( + TraceLogger::GetInstance()->UpdateButtonUsage( IsBitFlipChecked ? NumbersAndOperatorsEnum::BitflipButton : NumbersAndOperatorsEnum::FullKeypadButton, ViewMode::Programmer); } } @@ -1198,9 +1228,7 @@ String ^ StandardCalculatorViewModel::GetRawDisplayValue() } else { - wstring rawValue; - LocalizationSettings::GetInstance().RemoveGroupSeparators(DisplayValue->Data(), DisplayValue->Length(), &rawValue); - return ref new String(rawValue.c_str()); + return LocalizationSettings::GetInstance().RemoveGroupSeparators(DisplayValue); } } @@ -1209,16 +1237,14 @@ String ^ StandardCalculatorViewModel::GetRawDisplayValue() // 'displayValue' is a localized string containing a numerical value to be displayed to the user. String ^ StandardCalculatorViewModel::GetLocalizedStringFormat(String ^ format, String ^ displayValue) { - String ^ localizedString = ref new String(LocalizationStringUtil::GetLocalizedString(format->Data(), displayValue->Data()).c_str()); - return localizedString; + return LocalizationStringUtil::GetLocalizedString(format, displayValue); } void StandardCalculatorViewModel::ResetDisplay() { AreHEXButtonsEnabled = false; - CurrentRadixType = (int)RADIX_TYPE::DEC_RADIX; + CurrentRadixType = NumberBase::DecBase; m_standardCalculatorManager.SetRadix(DEC_RADIX); - ProgModeRadixChange(); } void StandardCalculatorViewModel::SetPrecision(int32_t precision) @@ -1226,17 +1252,16 @@ void StandardCalculatorViewModel::SetPrecision(int32_t precision) m_standardCalculatorManager.SetPrecision(precision); } -void StandardCalculatorViewModel::SwitchProgrammerModeBase(RADIX_TYPE radixType) +void StandardCalculatorViewModel::SwitchProgrammerModeBase(NumberBase numberBase) { if (IsInError) { m_standardCalculatorManager.SendCommand(Command::CommandCLEAR); } - AreHEXButtonsEnabled = (radixType == RADIX_TYPE::HEX_RADIX); - CurrentRadixType = (int)radixType; - m_standardCalculatorManager.SetRadix(radixType); - ProgModeRadixChange(); + AreHEXButtonsEnabled = numberBase == NumberBase::HexBase; + CurrentRadixType = numberBase; + m_standardCalculatorManager.SetRadix(GetRadixTypeFromNumberBase(numberBase)); } void StandardCalculatorViewModel::SetMemorizedNumbersString() @@ -1261,72 +1286,66 @@ ANGLE_TYPE GetAngleTypeFromCommand(Command command) void StandardCalculatorViewModel::SaveEditedCommand(_In_ unsigned int tokenPosition, _In_ Command command) { - pair token; bool handleOperand = false; - int nOpCode = static_cast(command); - wstring updatedToken = L""; + wstring updatedToken; - shared_ptr tokenCommand; - IFTPlatformException(m_tokens->GetAt(tokenPosition, &token)); + const pair& token = m_tokens->at(tokenPosition); + const shared_ptr& tokenCommand = m_commands->at(token.second); - unsigned int tokenCommandIndex = token.second; - IFTPlatformException(m_commands->GetAt(tokenCommandIndex, &tokenCommand)); - - if (IsUnaryOp(nOpCode) && command != Command::CommandSIGN) + if (IsUnaryOp(command) && command != Command::CommandSIGN) { int angleCmd = static_cast(m_standardCalculatorManager.GetCurrentDegreeMode()); ANGLE_TYPE angleType = GetAngleTypeFromCommand(static_cast(angleCmd)); - if (IsTrigOp(nOpCode)) + if (IsTrigOp(command)) { shared_ptr spUnaryCommand = dynamic_pointer_cast(tokenCommand); - spUnaryCommand->SetCommands(angleCmd, nOpCode); + spUnaryCommand->SetCommands(angleCmd, static_cast(command)); } else { shared_ptr spUnaryCommand = dynamic_pointer_cast(tokenCommand); - spUnaryCommand->SetCommand(nOpCode); + spUnaryCommand->SetCommand(static_cast(command)); } - switch (nOpCode) + switch (command) { - case static_cast(Command::CommandASIN): + case Command::CommandASIN: updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandSIN), true, angleType); break; - case static_cast(Command::CommandACOS): + case Command::CommandACOS: updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandCOS), true, angleType); break; - case static_cast(Command::CommandATAN): + case Command::CommandATAN: updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandTAN), true, angleType); break; - case static_cast(Command::CommandASINH): + case Command::CommandASINH: updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandSINH), true, angleType); break; - case static_cast(Command::CommandACOSH): + case Command::CommandACOSH: updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandCOSH), true, angleType); break; - case static_cast(Command::CommandATANH): + case Command::CommandATANH: updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandTANH), true, angleType); break; - case static_cast(Command::CommandPOWE): + case Command::CommandPOWE: updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(Command::CommandLN), true, angleType); break; default: - updatedToken = CCalcEngine::OpCodeToUnaryString(nOpCode, false, angleType); + updatedToken = CCalcEngine::OpCodeToUnaryString(static_cast(command), false, angleType); } if ((token.first.length() > 0) && (token.first[token.first.length() - 1] == L'(')) { - wstring chOpenBrace = L"("; - updatedToken.append(chOpenBrace); + updatedToken += L'('; } } - else if (IsBinOp(nOpCode)) + else if (IsBinOp(command)) { shared_ptr spBinaryCommand = dynamic_pointer_cast(tokenCommand); - spBinaryCommand->SetCommand(nOpCode); - updatedToken = CCalcEngine::OpCodeToString(nOpCode); + spBinaryCommand->SetCommand(static_cast(command)); + updatedToken = CCalcEngine::OpCodeToString(static_cast(command)); } - else if (IsOpnd(nOpCode) || command == Command::CommandBACK) + else if (IsOpnd(command) || command == Command::CommandBACK) { HandleUpdatedOperandData(command); handleOperand = true; @@ -1335,8 +1354,8 @@ void StandardCalculatorViewModel::SaveEditedCommand(_In_ unsigned int tokenPosit { if (tokenCommand->GetCommandType() == CommandType::UnaryCommand) { - shared_ptr spSignCommand = make_shared(nOpCode); - IFTPlatformException(m_commands->InsertAt(tokenCommandIndex + 1, spSignCommand)); + shared_ptr spSignCommand = make_shared(static_cast(command)); + m_commands->insert(m_commands->begin() + token.second + 1, spSignCommand); } else { @@ -1349,12 +1368,8 @@ void StandardCalculatorViewModel::SaveEditedCommand(_In_ unsigned int tokenPosit if (!handleOperand) { - IFTPlatformException(m_commands->SetAt(tokenCommandIndex, tokenCommand)); - - pair selectedToken; - IFTPlatformException(m_tokens->GetAt(tokenPosition, &selectedToken)); - selectedToken.first = updatedToken; - IFTPlatformException(m_tokens->SetAt(tokenPosition, selectedToken)); + (*m_commands)[token.second] = tokenCommand; + (*m_tokens)[tokenPosition].first = updatedToken; DisplayExpressionToken ^ displayExpressionToken = ExpressionTokens->GetAt(tokenPosition); displayExpressionToken->Token = ref new Platform::String(updatedToken.c_str()); @@ -1372,30 +1387,21 @@ void StandardCalculatorViewModel::Recalculate(bool fromHistory) { // Recalculate Command currentDegreeMode = m_standardCalculatorManager.GetCurrentDegreeMode(); - shared_ptr>> savedCommands = make_shared>>(); - + shared_ptr>> savedCommands = make_shared>>(); vector currentCommands; - unsigned int commandListCount; - m_commands->GetSize(&commandListCount); - for (unsigned int i = 0; i < commandListCount; i++) - { - shared_ptr command; - IFTPlatformException(m_commands->GetAt(i, &command)); - savedCommands->Append(command); + for (const auto& command : *m_commands) + { + savedCommands->push_back(command); CommandType commandType = command->GetCommandType(); if (commandType == CommandType::UnaryCommand) { shared_ptr spCommand = dynamic_pointer_cast(command); - shared_ptr> unaryCommands = spCommand->GetCommands(); - unsigned int unaryCommandCount; - unaryCommands->GetSize(&unaryCommandCount); + const shared_ptr>& unaryCommands = spCommand->GetCommands(); - int nUCode; - for (unsigned int j = 0; j < unaryCommandCount; ++j) + for (int nUCode : *unaryCommands) { - IFTPlatformException(unaryCommands->GetAt(j, &nUCode)); currentCommands.push_back(nUCode); } } @@ -1415,15 +1421,11 @@ void StandardCalculatorViewModel::Recalculate(bool fromHistory) if (commandType == CommandType::OperandCommand) { shared_ptr spCommand = dynamic_pointer_cast(command); - shared_ptr> opndCommands = spCommand->GetCommands(); - unsigned int opndCommandCount; - opndCommands->GetSize(&opndCommandCount); + const shared_ptr>& opndCommands = spCommand->GetCommands(); bool fNeedIDCSign = spCommand->IsNegative(); - int nOCode; - for (unsigned int j = 0; j < opndCommandCount; ++j) + for (int nOCode : *opndCommands) { - IFTPlatformException(opndCommands->GetAt(j, &nOCode)); currentCommands.push_back(nOCode); if (fNeedIDCSign && nOCode != IDC_0) @@ -1434,16 +1436,12 @@ void StandardCalculatorViewModel::Recalculate(bool fromHistory) } } } - shared_ptr>> savedTokens = make_shared>>(); - unsigned int tokenCount; - IFTPlatformException(m_tokens->GetSize(&tokenCount)); + shared_ptr>> savedTokens = make_shared>>(); - for (unsigned int i = 0; i < tokenCount; ++i) + for (const auto& currentToken : *m_tokens) { - pair currentToken; - IFTPlatformException(m_tokens->GetAt(i, ¤tToken)); - savedTokens->Append(currentToken); + savedTokens->push_back(currentToken); } m_standardCalculatorManager.Reset(false); @@ -1458,10 +1456,10 @@ void StandardCalculatorViewModel::Recalculate(bool fromHistory) } m_standardCalculatorManager.SendCommand(currentDegreeMode); - size_t currentCommandsSize = currentCommands.size(); - for (size_t i = 0; i < currentCommandsSize; i++) + + for (int command : currentCommands) { - m_standardCalculatorManager.SendCommand(static_cast(currentCommands[i])); + m_standardCalculatorManager.SendCommand(static_cast(command)); } if (fromHistory) // This is for the cases where the expression is loaded from history @@ -1481,47 +1479,34 @@ void StandardCalculatorViewModel::Recalculate(bool fromHistory) CommandType StandardCalculatorViewModel::GetSelectedTokenType(_In_ unsigned int tokenPosition) { - pair token; - shared_ptr tokenCommand; - IFTPlatformException(m_tokens->GetAt(tokenPosition, &token)); - + const pair& token = m_tokens->at(tokenPosition); unsigned int tokenCommandIndex = token.second; - IFTPlatformException(m_commands->GetAt(tokenCommandIndex, &tokenCommand)); + const shared_ptr& tokenCommand = m_commands->at(tokenCommandIndex); return tokenCommand->GetCommandType(); } -bool StandardCalculatorViewModel::IsOpnd(int nOpCode) +bool StandardCalculatorViewModel::IsOpnd(Command command) { - static Command opnd[] = { Command::Command0, Command::Command1, Command::Command2, Command::Command3, Command::Command4, Command::Command5, + static constexpr Command opnd[] = { Command::Command0, Command::Command1, Command::Command2, Command::Command3, Command::Command4, Command::Command5, Command::Command6, Command::Command7, Command::Command8, Command::Command9, Command::CommandPNT }; - for (unsigned int i = 0; i < size(opnd); i++) - { - if (nOpCode == static_cast(opnd[i])) - { - return true; - } - } - return false; + return find(begin(opnd), end(opnd), command) != end(opnd); } -bool StandardCalculatorViewModel::IsUnaryOp(int nOpCode) +bool StandardCalculatorViewModel::IsUnaryOp(Command command) { - static Command unaryOp[] = { Command::CommandSQRT, Command::CommandFAC, Command::CommandSQR, Command::CommandLOG, + static constexpr Command unaryOp[] = { Command::CommandSQRT, Command::CommandFAC, Command::CommandSQR, Command::CommandLOG, Command::CommandPOW10, Command::CommandPOWE, Command::CommandLN, Command::CommandREC, Command::CommandSIGN, Command::CommandSINH, Command::CommandASINH, Command::CommandCOSH, Command::CommandACOSH, Command::CommandTANH, Command::CommandATANH, Command::CommandCUB }; - for (unsigned int i = 0; i < size(unaryOp); i++) + if (find(begin(unaryOp), end(unaryOp), command) != end(unaryOp)) { - if (nOpCode == static_cast(unaryOp[i])) - { - return true; - } + return true; } - if (IsTrigOp(nOpCode)) + if (IsTrigOp(command)) { return true; } @@ -1529,80 +1514,50 @@ bool StandardCalculatorViewModel::IsUnaryOp(int nOpCode) return false; } -bool StandardCalculatorViewModel::IsTrigOp(int nOpCode) +bool StandardCalculatorViewModel::IsTrigOp(Command command) { - static Command trigOp[] = { + static constexpr Command trigOp[] = { Command::CommandSIN, Command::CommandCOS, Command::CommandTAN, Command::CommandASIN, Command::CommandACOS, Command::CommandATAN }; - for (unsigned int i = 0; i < size(trigOp); i++) - { - if (nOpCode == static_cast(trigOp[i])) - { - return true; - } - } - return false; + return find(begin(trigOp), end(trigOp), command) != end(trigOp); } -bool StandardCalculatorViewModel::IsBinOp(int nOpCode) +bool StandardCalculatorViewModel::IsBinOp(Command command) { - static Command binOp[] = { Command::CommandADD, Command::CommandSUB, Command::CommandMUL, Command::CommandDIV, + static constexpr Command binOp[] = { Command::CommandADD, Command::CommandSUB, Command::CommandMUL, Command::CommandDIV, Command::CommandEXP, Command::CommandROOT, Command::CommandMOD, Command::CommandPWR }; - for (unsigned int i = 0; i < size(binOp); i++) - { - if (nOpCode == static_cast(binOp[i])) - { - return true; - } - } - return false; + return find(begin(binOp), end(binOp), command) != end(binOp); } -bool StandardCalculatorViewModel::IsRecoverableCommand(int nOpCode) +bool StandardCalculatorViewModel::IsRecoverableCommand(Command command) { - if (IsOpnd(nOpCode)) + if (IsOpnd(command)) { return true; } // Programmer mode, bit flipping - int minBinPos = static_cast(Command::CommandBINEDITSTART); - int maxBinPos = static_cast(Command::CommandBINEDITEND); - if (minBinPos <= nOpCode && nOpCode <= maxBinPos) + if (Command::CommandBINEDITSTART <= command && command <= Command::CommandBINEDITEND) { return true; } - static Command recoverableCommands[] = { Command::CommandA, Command::CommandB, Command::CommandC, Command::CommandD, Command::CommandE, Command::CommandF }; + static constexpr Command recoverableCommands[] = { Command::CommandA, Command::CommandB, Command::CommandC, + Command::CommandD, Command::CommandE, Command::CommandF }; - for (unsigned int i = 0; i < size(recoverableCommands); i++) - { - if (nOpCode == static_cast(recoverableCommands[i])) - { - return true; - } - } - return false; + return find(begin(recoverableCommands), end(recoverableCommands), command) != end(recoverableCommands); } size_t StandardCalculatorViewModel::LengthWithoutPadding(wstring str) { - size_t count = 0; - for (size_t i = 0; i < str.length(); i++) - { - if (str[i] != L' ') - { - count++; - } - } - return count; + return str.length() - count(str.begin(), str.end(), L' '); } wstring StandardCalculatorViewModel::AddPadding(wstring binaryString) { - if (LocalizationSettings::GetInstance().GetEnglishValueFromLocalizedDigits(binaryString) == L"0") + if (LocalizationSettings::GetInstance().GetEnglishValueFromLocalizedDigits(StringReference(binaryString.c_str())) == L"0") { return binaryString; } @@ -1611,12 +1566,7 @@ wstring StandardCalculatorViewModel::AddPadding(wstring binaryString) { pad = 0; } - wstring padString = L""; - for (size_t i = 0; i < pad; i++) - { - padString += L"0"; - } - return padString + binaryString; + return wstring(pad, L'0') + binaryString; } void StandardCalculatorViewModel::UpdateProgrammerPanelDisplay() @@ -1699,20 +1649,18 @@ NumbersAndOperatorsEnum StandardCalculatorViewModel::ConvertIntegerToNumbersAndO void StandardCalculatorViewModel::UpdateOperand(int pos, String ^ text) { - pair p; - m_tokens->GetAt(pos, &p); + pair p = m_tokens->at(pos); - String ^ englishString = LocalizationSettings::GetInstance().GetEnglishValueFromLocalizedDigits(text->Data()); + String ^ englishString = LocalizationSettings::GetInstance().GetEnglishValueFromLocalizedDigits(text); p.first = englishString->Data(); int commandPos = p.second; - shared_ptr exprCmd; - m_commands->GetAt(commandPos, &exprCmd); + const shared_ptr& exprCmd = m_commands->at(commandPos); auto operandCommand = std::dynamic_pointer_cast(exprCmd); if (operandCommand != nullptr) { - shared_ptr> commands = make_shared>(); + shared_ptr> commands = make_shared>(); size_t length = p.first.length(); if (length > 0) { @@ -1750,33 +1698,29 @@ void StandardCalculatorViewModel::UpdateOperand(int pos, String ^ text) continue; } } - commands->Append(num); + commands->push_back(num); } } else { - commands->Append(0); + commands->push_back(0); } operandCommand->SetCommands(commands); } } -void StandardCalculatorViewModel::UpdatecommandsInRecordingMode() +void StandardCalculatorViewModel::UpdateCommandsInRecordingMode() { - vector savedCommands = m_standardCalculatorManager.GetSavedCommands(); - shared_ptr> commands = make_shared>(); + shared_ptr> commands = make_shared>(); bool isDecimal = false; bool isNegative = false; bool isExpMode = false; bool ePlusMode = false; bool eMinusMode = false; - int num = 0; - Command val; - for (unsigned int i = 0; i < savedCommands.size(); ++i) + for (const auto savedCommand : m_standardCalculatorManager.GetSavedCommands()) { - val = safe_cast(savedCommands[i]); - num = static_cast(val); + const Command val = static_cast(savedCommand); if (val == Command::CommandSIGN) { isNegative = true; @@ -1811,27 +1755,27 @@ void StandardCalculatorViewModel::UpdatecommandsInRecordingMode() isExpMode = false; ePlusMode = false; eMinusMode = false; - commands->Clear(); + commands->clear(); continue; } - commands->Append(num); + commands->push_back(static_cast(val)); } - unsigned int size = 0; - commands->GetSize(&size); - if (size > 0) + if (!commands->empty()) { shared_ptr sp = make_shared(commands, isNegative, isDecimal, isExpMode); - m_commands->Append(sp); + m_commands->push_back(sp); } Recalculate(); } void StandardCalculatorViewModel::OnMaxDigitsReached() { - String ^ announcement = LocalizationStringUtil::GetLocalizedNarratorAnnouncement( - CalculatorResourceKeys::MaxDigitsReachedFormat, m_localizedMaxDigitsReachedAutomationFormat, m_CalculationResultAutomationName->Data()); - + if (m_localizedMaxDigitsReachedAutomationFormat == nullptr) + { + m_localizedMaxDigitsReachedAutomationFormat = AppResourceProvider::GetInstance()->GetResourceString(CalculatorResourceKeys::MaxDigitsReachedFormat); + } + String ^ announcement = LocalizationStringUtil::GetLocalizedString(m_localizedMaxDigitsReachedAutomationFormat, m_CalculationResultAutomationName); Announcement = CalculatorAnnouncement::GetMaxDigitsReachedAnnouncement(announcement); } @@ -1849,11 +1793,14 @@ NarratorAnnouncement ^ StandardCalculatorViewModel::GetDisplayUpdatedNarratorAnn } else { - announcement = LocalizationStringUtil::GetLocalizedNarratorAnnouncement( - CalculatorResourceKeys::ButtonPressFeedbackFormat, + if (m_localizedButtonPressFeedbackAutomationFormat == nullptr) + { + m_localizedButtonPressFeedbackAutomationFormat = AppResourceProvider::GetInstance()->GetResourceString(CalculatorResourceKeys::ButtonPressFeedbackFormat); + } + announcement = LocalizationStringUtil::GetLocalizedString( m_localizedButtonPressFeedbackAutomationFormat, - m_CalculationResultAutomationName->Data(), - m_feedbackForButtonPress->Data()); + m_CalculationResultAutomationName, + m_feedbackForButtonPress); } // Make sure we don't accidentally repeat an announcement. @@ -1902,3 +1849,11 @@ void StandardCalculatorViewModel::ValueBitLength::set(CalculatorApp::Common::Bit SetMemorizedNumbersString(); } } + +void StandardCalculatorViewModel::SelectHistoryItem(HistoryItemViewModel ^ item) +{ + SetHistoryExpressionDisplay(item->GetTokens(), item->GetCommands()); + SetExpressionDisplay(item->GetTokens(), item->GetCommands()); + SetPrimaryDisplay(item->Result, false); + IsFToEEnabled = false; +} diff --git a/src/CalcViewModel/StandardCalculatorViewModel.h b/src/CalcViewModel/StandardCalculatorViewModel.h index 77480dd8..d9c0ce3a 100644 --- a/src/CalcViewModel/StandardCalculatorViewModel.h +++ b/src/CalcViewModel/StandardCalculatorViewModel.h @@ -10,6 +10,7 @@ #include "HistoryViewModel.h" #include "MemoryItemViewModel.h" #include "Common/BitLength.h" +#include "Common/NumberBase.h" namespace CalculatorFunctionalTests { @@ -19,7 +20,6 @@ namespace CalculatorFunctionalTests namespace CalculatorUnitTests { class MultiWindowUnitTests; - class TimerTests; } namespace CalculatorApp @@ -30,55 +30,64 @@ namespace CalculatorApp namespace ViewModel { #define ASCII_0 48 - public - delegate void HideMemoryClickedHandler(); - public - delegate void ProgModeRadixChangeHandler(); + public delegate void HideMemoryClickedHandler(); + + public value struct ButtonInfo + { + NumbersAndOperatorsEnum buttonId; + bool canSendNegate; + }; [Windows::UI::Xaml::Data::Bindable] public ref class StandardCalculatorViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged { public: StandardCalculatorViewModel(); void UpdateOperand(int pos, Platform::String ^ text); - void UpdatecommandsInRecordingMode(); - int GetNumberBase(); + void UpdateCommandsInRecordingMode(); OBSERVABLE_OBJECT_CALLBACK(OnPropertyChanged); OBSERVABLE_PROPERTY_RW(Platform::String ^, DisplayValue); - OBSERVABLE_PROPERTY_RW(HistoryViewModel ^, HistoryVM); - OBSERVABLE_NAMED_PROPERTY_RW(bool, IsInError); - OBSERVABLE_PROPERTY_RW(bool, IsOperatorCommand); - OBSERVABLE_PROPERTY_RW(Platform::String ^, DisplayStringExpression); + OBSERVABLE_PROPERTY_R(HistoryViewModel ^, HistoryVM); + OBSERVABLE_PROPERTY_RW(bool, IsAlwaysOnTop); + OBSERVABLE_PROPERTY_R(bool, IsBinaryBitFlippingEnabled); + PROPERTY_R(bool, IsOperandUpdatedUsingViewModel); + PROPERTY_R(int, TokenPosition); + PROPERTY_R(bool, IsOperandTextCompletelySelected); + PROPERTY_R(bool, KeyPressed); + PROPERTY_R(Platform::String ^, SelectedExpressionLastData); + OBSERVABLE_NAMED_PROPERTY_R(bool, IsInError); + OBSERVABLE_PROPERTY_R(bool, IsOperatorCommand); + OBSERVABLE_PROPERTY_R(Platform::String ^, DisplayStringExpression); OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector ^, ExpressionTokens); - OBSERVABLE_PROPERTY_RW(Platform::String ^, DecimalDisplayValue); - OBSERVABLE_PROPERTY_RW(Platform::String ^, HexDisplayValue); - OBSERVABLE_PROPERTY_RW(Platform::String ^, OctalDisplayValue); - OBSERVABLE_NAMED_PROPERTY_RW(Platform::String ^, BinaryDisplayValue); + OBSERVABLE_PROPERTY_R(Platform::String ^, DecimalDisplayValue); + OBSERVABLE_PROPERTY_R(Platform::String ^, HexDisplayValue); + OBSERVABLE_PROPERTY_R(Platform::String ^, OctalDisplayValue); + OBSERVABLE_NAMED_PROPERTY_R(Platform::String ^, BinaryDisplayValue); OBSERVABLE_NAMED_PROPERTY_R(Windows::Foundation::Collections::IVector ^, BinaryDigits); - OBSERVABLE_PROPERTY_RW(Platform::String ^, HexDisplayValue_AutomationName); - OBSERVABLE_PROPERTY_RW(Platform::String ^, DecDisplayValue_AutomationName); - OBSERVABLE_PROPERTY_RW(Platform::String ^, OctDisplayValue_AutomationName); - OBSERVABLE_PROPERTY_RW(Platform::String ^, BinDisplayValue_AutomationName); - OBSERVABLE_PROPERTY_RW(bool, IsBinaryOperatorEnabled); - OBSERVABLE_PROPERTY_RW(bool, IsUnaryOperatorEnabled); - OBSERVABLE_PROPERTY_RW(bool, IsNegateEnabled); + OBSERVABLE_PROPERTY_R(Platform::String ^, HexDisplayValue_AutomationName); + OBSERVABLE_PROPERTY_R(Platform::String ^, DecDisplayValue_AutomationName); + OBSERVABLE_PROPERTY_R(Platform::String ^, OctDisplayValue_AutomationName); + OBSERVABLE_PROPERTY_R(Platform::String ^, BinDisplayValue_AutomationName); + OBSERVABLE_PROPERTY_R(bool, IsBinaryOperatorEnabled); + OBSERVABLE_PROPERTY_R(bool, IsUnaryOperatorEnabled); + OBSERVABLE_PROPERTY_R(bool, IsNegateEnabled); OBSERVABLE_PROPERTY_RW(bool, IsDecimalEnabled); - OBSERVABLE_PROPERTY_RW(bool, IsCurrentViewPinned); - OBSERVABLE_PROPERTY_RW(Windows::Foundation::Collections::IVector ^, MemorizedNumbers); + OBSERVABLE_PROPERTY_R(bool, IsCurrentViewPinned); + OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IVector ^, MemorizedNumbers); 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); - OBSERVABLE_PROPERTY_RW(Platform::String ^, CalculationResultAutomationName); - OBSERVABLE_PROPERTY_RW(Platform::String ^, CalculationExpressionAutomationName); - OBSERVABLE_PROPERTY_RW(bool, IsShiftProgrammerChecked); - OBSERVABLE_PROPERTY_RW(int, CurrentRadixType); - OBSERVABLE_PROPERTY_RW(bool, AreTokensUpdated); - OBSERVABLE_PROPERTY_RW(bool, AreAlwaysOnTopResultsUpdated); + OBSERVABLE_PROPERTY_R(bool, IsFToEChecked); + OBSERVABLE_PROPERTY_R(bool, IsFToEEnabled); + OBSERVABLE_PROPERTY_R(bool, AreHEXButtonsEnabled); + OBSERVABLE_PROPERTY_R(Platform::String ^, CalculationResultAutomationName); + OBSERVABLE_PROPERTY_R(Platform::String ^, CalculationExpressionAutomationName); + OBSERVABLE_PROPERTY_R(bool, IsShiftProgrammerChecked); + OBSERVABLE_PROPERTY_R(CalculatorApp::Common::NumberBase, CurrentRadixType); + OBSERVABLE_PROPERTY_R(bool, AreTokensUpdated); + OBSERVABLE_PROPERTY_R(bool, AreAlwaysOnTopResultsUpdated); OBSERVABLE_PROPERTY_RW(bool, AreHistoryShortcutsEnabled); - OBSERVABLE_PROPERTY_RW(bool, AreProgrammerRadixOperatorsEnabled); - OBSERVABLE_PROPERTY_RW(CalculatorApp::Common::Automation::NarratorAnnouncement ^, Announcement); + OBSERVABLE_PROPERTY_R(bool, AreProgrammerRadixOperatorsEnabled); + OBSERVABLE_PROPERTY_R(bool, IsInputEmpty); + OBSERVABLE_PROPERTY_R(CalculatorApp::Common::Automation::NarratorAnnouncement ^, Announcement); OBSERVABLE_PROPERTY_R(unsigned int, OpenParenthesisCount); COMMAND_FOR_METHOD(CopyCommand, StandardCalculatorViewModel::OnCopyCommand); @@ -90,23 +99,6 @@ namespace CalculatorApp COMMAND_FOR_METHOD(MemorySubtract, StandardCalculatorViewModel::OnMemorySubtract); event HideMemoryClickedHandler ^ HideMemoryClicked; - event ProgModeRadixChangeHandler ^ ProgModeRadixChange; - - property bool IsShiftChecked - { - bool get() - { - return m_isShiftChecked; - } - void set(bool value) - { - if (m_isShiftChecked != value) - { - m_isShiftChecked = value; - RaisePropertyChanged(L"IsShiftChecked"); - } - } - } property bool IsBitFlipChecked { @@ -125,29 +117,8 @@ namespace CalculatorApp } } } - static property Platform::String ^ IsBitFlipCheckedPropertyName - { - Platform::String ^ get() - { - return Platform::StringReference(L"IsBitFlipChecked"); - } - } - - property bool IsBinaryBitFlippingEnabled - { - bool get() - { - return m_isBinaryBitFlippingEnabled; - } - void set(bool value) - { - if (m_isBinaryBitFlippingEnabled != value) - { - m_isBinaryBitFlippingEnabled = value; - RaisePropertyChanged(L"IsBinaryBitFlippingEnabled"); - } - } - } + static property Platform::String + ^ IsBitFlipCheckedPropertyName { Platform::String ^ get() { return Platform::StringReference(L"IsBitFlipChecked"); } } property CalculatorApp::Common::BitLength ValueBitLength { @@ -226,29 +197,8 @@ namespace CalculatorApp } } } - static property Platform::String ^ IsProgrammerPropertyName - { - Platform::String ^ get() - { - return Platform::StringReference(L"IsProgrammer"); - } - } - - property bool IsAlwaysOnTop - { - bool get() - { - return m_isAlwaysOnTop; - } - void set(bool value) - { - if (m_isAlwaysOnTop != value) - { - m_isAlwaysOnTop = value; - RaisePropertyChanged(L"IsAlwaysOnTop"); - } - } - } + static property Platform::String + ^ IsProgrammerPropertyName { Platform::String ^ get() { return Platform::StringReference(L"IsProgrammer"); } } property bool IsEditingEnabled { @@ -300,65 +250,12 @@ namespace CalculatorApp } } - property int TokenPosition - { - int get() - { - return m_tokenPosition; - } - void set(int value) - { - m_tokenPosition = value; - } - } - - property Platform::String^ SelectedExpressionLastData - { - Platform::String^ get() { return m_selectedExpressionLastData; } - void set(Platform::String^ value) { m_selectedExpressionLastData = value; } - } - - property bool KeyPressed - { - bool get() - { - return m_keyPressed; - } - void set(bool value) - { - m_keyPressed = value; - } - } - - property bool IsOperandUpdatedUsingViewModel - { - bool get() - { - return m_operandUpdated; - } - void set(bool value) - { - m_operandUpdated = value; - } - } - - property bool IsOperandTextCompletelySelected - { - bool get() - { - return m_completeTextSelection; - } - void set(bool value) - { - m_completeTextSelection = value; - } - } - - internal : void OnPaste(Platform::String ^ pastedString); + internal : + void OnPaste(Platform::String ^ pastedString); void OnCopyCommand(Platform::Object ^ parameter); void OnPasteCommand(Platform::Object ^ parameter); - NumbersAndOperatorsEnum MapCharacterToButtonId(const wchar_t ch, bool& canSendNegate); + ButtonInfo MapCharacterToButtonId(char16 ch); // Memory feature related methods. They are internal because they need to called from the MainPage code-behind void OnMemoryButtonPressed(); @@ -368,15 +265,8 @@ namespace CalculatorApp void OnMemoryClear(_In_ Platform::Object ^ memoryItemPosition); void OnPinUnpinCommand(Platform::Object ^ parameter); - void SetPrimaryDisplay(_In_ std::wstring const& displayString, _In_ bool isError); + void OnInputChanged(); void DisplayPasteError(); - void SetTokens(_Inout_ std::shared_ptr>> const& tokens); - void SetExpressionDisplay( - _Inout_ std::shared_ptr>> const& tokens, - _Inout_ std::shared_ptr>> const& commands); - void SetHistoryExpressionDisplay( - _Inout_ std::shared_ptr>> const& tokens, - _Inout_ std::shared_ptr>> const& commands); void SetParenthesisCount(_In_ unsigned int parenthesisCount); void SetOpenParenthesisCountNarratorAnnouncement(); void OnNoRightParenAdded(); @@ -393,14 +283,11 @@ namespace CalculatorApp void Recalculate(bool fromHistory = false); bool IsOperator(CalculationManager::Command cmdenum); void FtoEButtonToggled(); - void SwitchProgrammerModeBase(RADIX_TYPE calculatorBase); + void SwitchProgrammerModeBase(CalculatorApp::Common::NumberBase calculatorBase); void SetMemorizedNumbersString(); void SwitchAngleType(NumbersAndOperatorsEnum num); void ResetDisplay(); - RADIX_TYPE GetCurrentRadixType() - { - return (RADIX_TYPE)m_CurrentRadixType; - } + void SetPrecision(int32_t precision); void UpdateMaxIntDigits() { @@ -410,12 +297,21 @@ namespace CalculatorApp { return m_CurrentAngleType; } - + void SelectHistoryItem(HistoryItemViewModel ^ item); private: void SetMemorizedNumbers(const std::vector& memorizedNumbers); void UpdateProgrammerPanelDisplay(); void HandleUpdatedOperandData(CalculationManager::Command cmdenum); + void SetPrimaryDisplay(_In_ Platform::String ^ displayStringValue, _In_ bool isError); + void SetExpressionDisplay( + _Inout_ std::shared_ptr>> const& tokens, + _Inout_ std::shared_ptr>> const& commands); + void SetHistoryExpressionDisplay( + _Inout_ std::shared_ptr>> const& tokens, + _Inout_ std::shared_ptr>> const& commands); + void SetTokens(_Inout_ std::shared_ptr>> const& tokens); NumbersAndOperatorsEnum ConvertIntegerToNumbersAndOperatorsEnum(unsigned int parameter); + static RADIX_TYPE GetRadixTypeFromNumberBase(CalculatorApp::Common::NumberBase base); NumbersAndOperatorsEnum m_CurrentAngleType; wchar_t m_decimalSeparator; CalculatorDisplay m_calculatorDisplay; @@ -443,15 +339,9 @@ namespace CalculatorApp bool m_isStandard; bool m_isScientific; bool m_isProgrammer; - bool m_isAlwaysOnTop; - bool m_isBinaryBitFlippingEnabled; bool m_isBitFlipChecked; - bool m_isShiftChecked; bool m_isRtlLanguage; - int m_tokenPosition; - bool m_keyPressed; bool m_operandUpdated; - bool m_completeTextSelection; bool m_isLastOperationHistoryLoad; CalculatorApp::Common::BitLength m_valueBitLength; Platform::String ^ m_selectedExpressionLastData; @@ -473,15 +363,15 @@ namespace CalculatorApp std::wstring AddPadding(std::wstring); size_t LengthWithoutPadding(std::wstring); - std::shared_ptr>> m_tokens; - std::shared_ptr>> m_commands; + std::shared_ptr>> m_tokens; + std::shared_ptr>> m_commands; // Token types - bool IsUnaryOp(int nOpCode); - bool IsBinOp(int nOpcode); - bool IsTrigOp(int nOpCode); - bool IsOpnd(int nOpCode); - bool IsRecoverableCommand(int nOpCode); + bool IsUnaryOp(CalculationManager::Command command); + bool IsBinOp(CalculationManager::Command command); + bool IsTrigOp(CalculationManager::Command command); + bool IsOpnd(CalculationManager::Command command); + bool IsRecoverableCommand(CalculationManager::Command command); CalculationManager::CommandType GetSelectedTokenType(_In_ unsigned int); void SaveEditedCommand(_In_ unsigned int index, _In_ CalculationManager::Command command); @@ -494,7 +384,6 @@ namespace CalculatorApp friend class CalculatorDisplay; friend class CalculatorFunctionalTests::HistoryTests; friend class CalculatorUnitTests::MultiWindowUnitTests; - friend class CalculatorUnitTests::TimerTests; }; } } diff --git a/src/CalcViewModel/UnitConverterViewModel.cpp b/src/CalcViewModel/UnitConverterViewModel.cpp index e57b0dc3..bab3c786 100644 --- a/src/CalcViewModel/UnitConverterViewModel.cpp +++ b/src/CalcViewModel/UnitConverterViewModel.cpp @@ -137,12 +137,12 @@ UnitConverterViewModel::UnitConverterViewModel(const shared_ptrFractionDigits; auto resourceLoader = AppResourceProvider::GetInstance(); - m_localizedValueFromFormat = resourceLoader.GetResourceString(UnitConverterResourceKeys::ValueFromFormat); - m_localizedValueToFormat = resourceLoader.GetResourceString(UnitConverterResourceKeys::ValueToFormat); - m_localizedConversionResultFormat = resourceLoader.GetResourceString(UnitConverterResourceKeys::ConversionResultFormat); - m_localizedValueFromDecimalFormat = resourceLoader.GetResourceString(UnitConverterResourceKeys::ValueFromDecimalFormat); - m_localizedInputUnitName = resourceLoader.GetResourceString(UnitConverterResourceKeys::InputUnit_Name); - m_localizedOutputUnitName = resourceLoader.GetResourceString(UnitConverterResourceKeys::OutputUnit_Name); + m_localizedValueFromFormat = resourceLoader->GetResourceString(UnitConverterResourceKeys::ValueFromFormat); + m_localizedValueToFormat = resourceLoader->GetResourceString(UnitConverterResourceKeys::ValueToFormat); + m_localizedConversionResultFormat = resourceLoader->GetResourceString(UnitConverterResourceKeys::ConversionResultFormat); + m_localizedValueFromDecimalFormat = resourceLoader->GetResourceString(UnitConverterResourceKeys::ValueFromDecimalFormat); + m_localizedInputUnitName = resourceLoader->GetResourceString(UnitConverterResourceKeys::InputUnit_Name); + m_localizedOutputUnitName = resourceLoader->GetResourceString(UnitConverterResourceKeys::OutputUnit_Name); Unit1AutomationName = m_localizedInputUnitName; Unit2AutomationName = m_localizedOutputUnitName; @@ -390,7 +390,7 @@ String ^ UnitConverterViewModel::ConvertToLocalizedString(const std::wstring& st void UnitConverterViewModel::DisplayPasteError() { - String ^ errorMsg = AppResourceProvider::GetInstance().GetCEngineString(StringReference(SIDS_DOMAIN)); /*SIDS_DOMAIN is for "invalid input"*/ + String ^ errorMsg = AppResourceProvider::GetInstance()->GetCEngineString(StringReference(SIDS_DOMAIN)); /*SIDS_DOMAIN is for "invalid input"*/ Value1 = errorMsg; Value2 = errorMsg; m_relocalizeStringOnSwitch = false; @@ -476,10 +476,10 @@ void UnitConverterViewModel::OnButtonPressed(Platform::Object ^ parameter) return; } - static const vector OPERANDS = { UCM::Command::Zero, UCM::Command::One, UCM::Command::Two, UCM::Command::Three, UCM::Command::Four, + static constexpr UCM::Command OPERANDS[] = { UCM::Command::Zero, UCM::Command::One, UCM::Command::Two, UCM::Command::Three, UCM::Command::Four, UCM::Command::Five, UCM::Command::Six, UCM::Command::Seven, UCM::Command::Eight, UCM::Command::Nine }; - if (find(begin(OPERANDS), end(OPERANDS), command) != OPERANDS.end()) + if (find(begin(OPERANDS), end(OPERANDS), command) != end(OPERANDS)) { if (m_isInputBlocked) { @@ -494,7 +494,7 @@ void UnitConverterViewModel::OnButtonPressed(Platform::Object ^ parameter) m_model->SendCommand(command); - TraceLogger::GetInstance().LogConverterInputReceived(Mode); + TraceLogger::GetInstance()->LogConverterInputReceived(Mode); } void UnitConverterViewModel::OnCopyCommand(Platform::Object ^ parameter) @@ -515,8 +515,10 @@ void UnitConverterViewModel::OnPasteCommand(Platform::Object ^ parameter) // Ensure that the paste happens on the UI thread // EventWriteClipboardPaste_Start(); // Any converter ViewMode is fine here. - CopyPasteManager::GetStringToPaste(m_Mode, NavCategory::GetGroupType(m_Mode)) - .then([this](String ^ pastedString) { OnPaste(pastedString); }, concurrency::task_continuation_context::use_current()); + + auto that(this); + create_task(CopyPasteManager::GetStringToPaste(m_Mode, NavCategory::GetGroupType(m_Mode), NumberBase::Unknown, BitLength::BitLengthUnknown)) + .then([that](String ^ pastedString) { that->OnPaste(pastedString); }, concurrency::task_continuation_context::use_current()); } void UnitConverterViewModel::InitializeView() @@ -650,7 +652,7 @@ void UnitConverterViewModel::OnCurrencyDataLoadFinished(bool didLoad) ResetCategory(); StringReference key = didLoad ? UnitConverterResourceKeys::CurrencyRatesUpdated : UnitConverterResourceKeys::CurrencyRatesUpdateFailed; - String ^ announcement = AppResourceProvider::GetInstance().GetResourceString(key); + String ^ announcement = AppResourceProvider::GetInstance()->GetResourceString(key); Announcement = CalculatorAnnouncement::GetUpdateCurrencyRatesAnnouncement(announcement); } @@ -665,17 +667,18 @@ void UnitConverterViewModel::RefreshCurrencyRatios() m_isCurrencyDataLoaded = false; IsCurrencyLoadingVisible = true; - String ^ announcement = AppResourceProvider::GetInstance().GetResourceString(UnitConverterResourceKeys::UpdatingCurrencyRates); + String ^ announcement = AppResourceProvider::GetInstance()->GetResourceString(UnitConverterResourceKeys::UpdatingCurrencyRates); Announcement = CalculatorAnnouncement::GetUpdateCurrencyRatesAnnouncement(announcement); - auto refreshTask = create_task([this] { return m_model->RefreshCurrencyRatios().get(); }); + auto that(this); + auto refreshTask = create_task([that] { return that->m_model->RefreshCurrencyRatios().get(); }); refreshTask.then( - [this](const pair& refreshResult) { + [that](const pair& refreshResult) { bool didLoad = refreshResult.first; wstring timestamp = refreshResult.second; - OnCurrencyTimestampUpdated(timestamp, false /*isWeekOldData*/); - OnCurrencyDataLoadFinished(didLoad); + that->OnCurrencyTimestampUpdated(timestamp, false /*isWeekOldData*/); + that->OnCurrencyDataLoadFinished(didLoad); }, task_continuation_context::use_current()); } @@ -878,22 +881,22 @@ NumbersAndOperatorsEnum UnitConverterViewModel::MapCharacterToButtonId(const wch void UnitConverterViewModel::OnPaste(String ^ stringToPaste) { // If pastedString is invalid("NoOp") then display pasteError else process the string - if (stringToPaste == StringReference(CopyPasteManager::PasteErrorString)) + if (CopyPasteManager::IsErrorMessage(stringToPaste)) { this->DisplayPasteError(); return; } - TraceLogger::GetInstance().LogInputPasted(Mode); + TraceLogger::GetInstance()->LogInputPasted(Mode); bool isFirstLegalChar = true; bool sendNegate = false; - wstring accumulation = L""; + wstring accumulation; - for (auto it = stringToPaste->Begin(); it != stringToPaste->End(); it++) + for (const auto ch : stringToPaste) { bool canSendNegate = false; - NumbersAndOperatorsEnum op = MapCharacterToButtonId(*it, canSendNegate); + NumbersAndOperatorsEnum op = MapCharacterToButtonId(ch, canSendNegate); if (NumbersAndOperatorsEnum::None != op) { @@ -929,7 +932,7 @@ void UnitConverterViewModel::OnPaste(String ^ stringToPaste) } } - accumulation += *it; + accumulation += ch; UpdateInputBlocked(accumulation); if (m_isInputBlocked) { @@ -954,8 +957,7 @@ String ^ UnitConverterViewModel::GetLocalizedAutomationName(_In_ String ^ displa format = m_localizedValueFromDecimalFormat; } - wstring localizedResult = LocalizationStringUtil::GetLocalizedString(format->Data(), displayvalue->Data(), unitname->Data()); - return ref new String(localizedResult.c_str()); + return LocalizationStringUtil::GetLocalizedString(format, displayvalue, unitname); } String @@ -965,11 +967,7 @@ String _In_ String ^ toValue, _In_ String ^ toUnit) { - String ^ localizedString = - ref new String(LocalizationStringUtil::GetLocalizedString( - m_localizedConversionResultFormat->Data(), fromValue->Data(), fromUnit->Data(), toValue->Data(), toUnit->Data()) - .c_str()); - return localizedString; + return LocalizationStringUtil::GetLocalizedString(m_localizedConversionResultFormat, fromValue, fromUnit, toValue, toUnit); } void UnitConverterViewModel::UpdateValue1AutomationName() @@ -990,9 +988,9 @@ void UnitConverterViewModel::UpdateValue2AutomationName() void UnitConverterViewModel::OnMaxDigitsReached() { - String ^ format = AppResourceProvider::GetInstance().GetResourceString(UnitConverterResourceKeys::MaxDigitsReachedFormat); - const wstring& announcement = LocalizationStringUtil::GetLocalizedString(format->Data(), m_lastAnnouncedConversionResult->Data()); - Announcement = CalculatorAnnouncement::GetMaxDigitsReachedAnnouncement(StringReference(announcement.c_str())); + String ^ format = AppResourceProvider::GetInstance()->GetResourceString(UnitConverterResourceKeys::MaxDigitsReachedFormat); + auto announcement = LocalizationStringUtil::GetLocalizedString(format, m_lastAnnouncedConversionResult); + Announcement = CalculatorAnnouncement::GetMaxDigitsReachedAnnouncement(announcement); } bool UnitConverterViewModel::UnitsAreValid() @@ -1002,17 +1000,18 @@ bool UnitConverterViewModel::UnitsAreValid() void UnitConverterViewModel::StartConversionResultTimer() { - m_conversionResultTaskHelper = make_unique(CONVERSION_FINALIZED_DELAY_IN_MS, [this]() { - if (UnitsAreValid()) + auto that(this); + m_conversionResultTaskHelper = make_unique(CONVERSION_FINALIZED_DELAY_IN_MS, [that]() { + if (that->UnitsAreValid()) { - String ^ valueFrom = m_Value1Active ? m_Value1 : m_Value2; - String ^ valueTo = m_Value1Active ? m_Value2 : m_Value1; + String ^ valueFrom = that->m_Value1Active ? that->m_Value1 : that->m_Value2; + String ^ valueTo = that->m_Value1Active ? that->m_Value2 : that->m_Value1; } }); } String ^ SupplementaryResult::GetLocalizedAutomationName() { - auto format = AppResourceProvider::GetInstance().GetResourceString("SupplementaryUnit_AutomationName"); - return ref new String(LocalizationStringUtil::GetLocalizedString(format->Data(), this->Value->Data(), this->Unit->Name->Data()).c_str()); + auto format = AppResourceProvider::GetInstance()->GetResourceString("SupplementaryUnit_AutomationName"); + return LocalizationStringUtil::GetLocalizedString(format, this->Value, this->Unit->Name); } diff --git a/src/CalcViewModel/packages.config b/src/CalcViewModel/packages.config index cef4e13e..c148e5d7 100644 --- a/src/CalcViewModel/packages.config +++ b/src/CalcViewModel/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/src/CalcViewModel/pch.h b/src/CalcViewModel/pch.h index 575a1f0d..77e1094b 100644 --- a/src/CalcViewModel/pch.h +++ b/src/CalcViewModel/pch.h @@ -31,6 +31,8 @@ #include #include #include +#include + // C++\WinRT Headers #include "winrt/base.h" #include "winrt/Windows.Foundation.Diagnostics.h" diff --git a/src/Calculator/AboutFlyout.xaml.cpp b/src/Calculator/AboutFlyout.xaml.cpp index 87a15e69..9eab1afd 100644 --- a/src/Calculator/AboutFlyout.xaml.cpp +++ b/src/Calculator/AboutFlyout.xaml.cpp @@ -35,11 +35,11 @@ AboutFlyout::AboutFlyout() this->SetVersionString(); - Header->Text = resourceLoader.GetResourceString("AboutButton/Content"); + 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()); + LocalizationStringUtil::GetLocalizedString(resourceLoader->GetResourceString("AboutControlCopyright"), StringReference(to_wstring(BUILD_YEAR).c_str())); + AboutControlCopyrightRun->Text = copyrightText; } void AboutFlyout::FeedbackButton_Click(_In_ Object ^ sender, _In_ RoutedEventArgs ^ e) @@ -53,7 +53,7 @@ void AboutFlyout::FeedbackButton_Click(_In_ Object ^ sender, _In_ RoutedEventArg void AboutFlyout::SetVersionString() { PackageVersion version = Package::Current->Id->Version; - String ^ appName = AppResourceProvider::GetInstance().GetResourceString(L"AppName"); + String ^ appName = AppResourceProvider::GetInstance()->GetResourceString(L"AppName"); AboutFlyoutVersion->Text = appName + L" " + version.Major + L"." + version.Minor + L"." + version.Build + L"." + version.Revision; } diff --git a/src/Calculator/App.xaml b/src/Calculator/App.xaml index 208182b0..8b26d0e9 100644 --- a/src/Calculator/App.xaml +++ b/src/Calculator/App.xaml @@ -18,18 +18,37 @@ 0.5 #FF000000 #FF2B2B2B + #FF858585 + - - + + - + + + + + + - + + + 0,0,0,0 @@ -85,19 +106,39 @@ #FFE0E0E0 0.2 0.4 + #FF858585 + - - + + + + + + + + + @@ -153,11 +199,13 @@ + - + + @@ -165,9 +213,13 @@ - + + + + - + + @@ -191,6 +243,21 @@ 15 SemiBold + 64 + 24 + 24 + 16 + + 64 + 16 + 20 + 10 + + 38 + 12 + 16 + 8 + 12 15 24 @@ -200,13 +267,17 @@ 40 34 + 38 + 48 24 20 + 22 15 12 - 15 + 14 + 16 + + + + + - + + + + @@ -532,6 +643,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Calculator/Views/MainPage.xaml.cpp b/src/Calculator/Views/MainPage.xaml.cpp index efe539d0..e0071f42 100644 --- a/src/Calculator/Views/MainPage.xaml.cpp +++ b/src/Calculator/Views/MainPage.xaml.cpp @@ -10,6 +10,7 @@ #include "CalcViewModel/Common/AppResourceProvider.h" #include "Views/Memory.xaml.h" #include "Converters/BooleanToVisibilityConverter.h" +#include "CalcViewModel/Common/LocalizationStringUtil.h" #include "Common/AppLifecycleLogger.h" using namespace CalculatorApp; using namespace CalculatorApp::Common; @@ -266,7 +267,7 @@ void MainPage::OnPageLoaded(_In_ Object ^, _In_ RoutedEventArgs ^ args) // Delay load things later when we get a chance. this->Dispatcher->RunAsync( CoreDispatcherPriority::Normal, ref new DispatchedHandler([]() { - if (TraceLogger::GetInstance().IsWindowIdInLog(ApplicationView::GetApplicationViewIdForWindow(CoreWindow::GetForCurrentThread()))) + if (TraceLogger::GetInstance()->IsWindowIdInLog(ApplicationView::GetApplicationViewIdForWindow(CoreWindow::GetForCurrentThread()))) { AppLifecycleLogger::GetInstance().LaunchUIResponsive(); AppLifecycleLogger::GetInstance().LaunchVisibleComplete(); @@ -417,7 +418,7 @@ void MainPage::OnNavPaneOpening(_In_ MUXC::NavigationView ^ sender, _In_ Object void MainPage::OnNavPaneOpened(_In_ MUXC::NavigationView ^ sender, _In_ Object ^ args) { KeyboardShortcutManager::HonorShortcuts(false); - TraceLogger::GetInstance().LogNavBarOpened(); + TraceLogger::GetInstance()->LogNavBarOpened(); } void MainPage::OnNavPaneClosed(_In_ MUXC::NavigationView ^ sender, _In_ Object ^ args) @@ -537,25 +538,20 @@ void MainPage::SetHeaderAutomationName() String ^ name; if (NavCategory::IsDateCalculatorViewMode(mode)) { - name = resProvider.GetResourceString(L"HeaderAutomationName_Date"); + name = resProvider->GetResourceString(L"HeaderAutomationName_Date"); } else { - wstring full; + String ^ full; if (NavCategory::IsCalculatorViewMode(mode) || NavCategory::IsGraphingCalculatorViewMode(mode)) { - full = resProvider.GetResourceString(L"HeaderAutomationName_Calculator")->Data(); + full = resProvider->GetResourceString(L"HeaderAutomationName_Calculator"); } else if (NavCategory::IsConverterViewMode(mode)) { - full = resProvider.GetResourceString(L"HeaderAutomationName_Converter")->Data(); + full = resProvider->GetResourceString(L"HeaderAutomationName_Converter"); } - - string::size_type found = full.find(L"%1"); - wstring strMode = m_model->CategoryName->Data(); - full = full.replace(found, 2, strMode); - - name = ref new String(full.c_str()); + name = LocalizationStringUtil::GetLocalizedString(full, m_model->CategoryName); } AutomationProperties::SetName(Header, name); diff --git a/src/Calculator/Views/MainPage.xaml.h b/src/Calculator/Views/MainPage.xaml.h index eeb0a47a..f2c75d6a 100644 --- a/src/Calculator/Views/MainPage.xaml.h +++ b/src/Calculator/Views/MainPage.xaml.h @@ -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 @@ -80,9 +80,9 @@ public void AnnounceCategoryName(); CalculatorApp::Calculator ^ m_calculator; + GraphingCalculator^ m_graphingCalculator; CalculatorApp::UnitConverter ^ m_converter; CalculatorApp::DateCalculator ^ m_dateCalculator; - CalculatorApp::GraphingCalculator^ m_graphingCalculator; Windows::Foundation::EventRegistrationToken m_windowSizeEventToken; CalculatorApp::ViewModel::ApplicationViewModel ^ m_model; Windows::Foundation::EventRegistrationToken m_accessibilitySettingsToken; diff --git a/src/Calculator/Views/NumberPad.xaml b/src/Calculator/Views/NumberPad.xaml index 4fa2f2c1..72b4daf3 100644 --- a/src/Calculator/Views/NumberPad.xaml +++ b/src/Calculator/Views/NumberPad.xaml @@ -1,4 +1,4 @@ -Num9Button->Content = localizationSettings.GetDigitSymbolFromEnUsDigit('9'); } -void NumberPad::ProgModeRadixChange() +void NumberPad::OnCurrentRadixTypePropertyChanged(NumberBase /* oldValue */, NumberBase newValue) { Num0Button->IsEnabled = true; Num1Button->IsEnabled = true; @@ -64,10 +65,7 @@ void NumberPad::ProgModeRadixChange() Num8Button->IsEnabled = true; Num9Button->IsEnabled = true; - auto vm = safe_cast(this->DataContext); - RADIX_TYPE radixType = vm->GetCurrentRadixType(); - - if (radixType == RADIX_TYPE::BIN_RADIX) + if (newValue == NumberBase::BinBase) { Num2Button->IsEnabled = false; Num3Button->IsEnabled = false; @@ -78,7 +76,7 @@ void NumberPad::ProgModeRadixChange() Num8Button->IsEnabled = false; Num9Button->IsEnabled = false; } - else if (radixType == RADIX_TYPE::OCT_RADIX) + else if (newValue == NumberBase::OctBase) { Num8Button->IsEnabled = false; Num9Button->IsEnabled = false; diff --git a/src/Calculator/Views/NumberPad.xaml.h b/src/Calculator/Views/NumberPad.xaml.h index 119987d6..1dc10ce0 100644 --- a/src/Calculator/Views/NumberPad.xaml.h +++ b/src/Calculator/Views/NumberPad.xaml.h @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. // @@ -10,6 +10,8 @@ #include "Views/NumberPad.g.h" #include "CalcViewModel/Common/KeyboardShortcutManager.h" +#include "CalcViewModel/Common/NumberBase.h" +#include "CalcManager/Header Files/RadixType.h" namespace CalculatorApp { @@ -20,6 +22,7 @@ namespace CalculatorApp DEPENDENCY_PROPERTY_OWNER(NumberPad); DEPENDENCY_PROPERTY(Windows::UI::Xaml::Style ^, ButtonStyle); + DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(CalculatorApp::Common::NumberBase, CurrentRadixType, CalculatorApp::Common::NumberBase::DecBase); property bool IsErrorVisualState { @@ -27,9 +30,10 @@ namespace CalculatorApp void set(bool value); } - void ProgModeRadixChange(); - private: + void OnCurrentRadixTypePropertyChanged(CalculatorApp::Common::NumberBase oldValue, CalculatorApp::Common::NumberBase newValue); + + bool m_isErrorVisualState; }; } diff --git a/src/Calculator/Views/OperatorsPanel.xaml b/src/Calculator/Views/OperatorsPanel.xaml index d12719dd..1623792b 100644 --- a/src/Calculator/Views/OperatorsPanel.xaml +++ b/src/Calculator/Views/OperatorsPanel.xaml @@ -10,24 +10,26 @@ mc:Ignorable="d"> + x:Load="{x:Bind Model.IsStandard, Mode=OneWay}"/> + Visibility="{x:Bind Model.IsScientific, Mode=OneWay}" + IsEnabled="{x:Bind Model.IsScientific, Mode=OneWay}" + x:Load="False"/> + Visibility="{x:Bind Model.IsBinaryBitFlippingEnabled, Mode=OneWay}" + IsEnabled="{x:Bind Model.IsBinaryBitFlippingEnabled, Mode=OneWay}" + x:Load="False"/> + Visibility="{x:Bind Model.AreProgrammerRadixOperatorsEnabled, Mode=OneWay}" + IsEnabled="{x:Bind Model.AreProgrammerRadixOperatorsEnabled, Mode=OneWay}" + x:Load="False"/> diff --git a/src/Calculator/Views/OperatorsPanel.xaml.cpp b/src/Calculator/Views/OperatorsPanel.xaml.cpp index 44936dc5..810a8e20 100644 --- a/src/Calculator/Views/OperatorsPanel.xaml.cpp +++ b/src/Calculator/Views/OperatorsPanel.xaml.cpp @@ -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" @@ -71,6 +71,11 @@ void OperatorsPanel::EnsureProgrammerRadixOps() { this->FindName(L"ProgrammerRadixOperators"); } + + if (ProgrammerRadixOperators) + { + ProgrammerRadixOperators->checkDefaultBitShift(); + } } void OperatorsPanel::EnsureProgrammerBitFlipPanel() diff --git a/src/Calculator/Views/StateTriggers/ControlSizeTrigger.cpp b/src/Calculator/Views/StateTriggers/ControlSizeTrigger.cpp new file mode 100644 index 00000000..2fd641eb --- /dev/null +++ b/src/Calculator/Views/StateTriggers/ControlSizeTrigger.cpp @@ -0,0 +1,72 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "pch.h" +#include "ControlSizeTrigger.h" + +using namespace CalculatorApp::Views::StateTriggers; +using namespace Platform; +using namespace Windows::Foundation; +using namespace Windows::UI::Xaml; + +DEPENDENCY_PROPERTY_INITIALIZATION(ControlSizeTrigger, Source); +DEPENDENCY_PROPERTY_INITIALIZATION(ControlSizeTrigger, MinHeight); +DEPENDENCY_PROPERTY_INITIALIZATION(ControlSizeTrigger, MinWidth); + +ControlSizeTrigger::ControlSizeTrigger() +{ + SetActive(false); +} + +ControlSizeTrigger::~ControlSizeTrigger() +{ + UnregisterSizeChanged(Source); +} + +void ControlSizeTrigger::OnSourcePropertyChanged(FrameworkElement ^ oldValue, FrameworkElement ^ newValue) +{ + UnregisterSizeChanged(oldValue); + RegisterSizeChanged(newValue); +} + +void ControlSizeTrigger::RegisterSizeChanged(FrameworkElement ^ element) +{ + if (element == nullptr) + { + return; + } + + if (element != Source) + { + UnregisterSizeChanged(Source); + } + + m_sizeChangedToken = element->SizeChanged += ref new SizeChangedEventHandler(this, &ControlSizeTrigger::OnSizeChanged); + UpdateIsActive(element->RenderSize); +} + +void ControlSizeTrigger::UnregisterSizeChanged(FrameworkElement ^ element) +{ + if (element != nullptr && m_sizeChangedToken.Value != 0) + { + element->SizeChanged -= m_sizeChangedToken; + m_sizeChangedToken.Value = 0; + } +} + +void ControlSizeTrigger::OnSizeChanged(Object ^ sender, SizeChangedEventArgs ^ e) +{ + UpdateIsActive(e->NewSize); +} + +void ControlSizeTrigger::UpdateIsActive(Size sourceSize) +{ + if (MinHeight >= 0) + { + SetActive(sourceSize.Height >= MinHeight && (MinWidth < 0 || sourceSize.Width >= MinWidth)); + } + else + { + SetActive(MinWidth >= 0 && sourceSize.Width >= MinWidth); + } +} diff --git a/src/Calculator/Views/StateTriggers/ControlSizeTrigger.h b/src/Calculator/Views/StateTriggers/ControlSizeTrigger.h new file mode 100644 index 00000000..2d9197e9 --- /dev/null +++ b/src/Calculator/Views/StateTriggers/ControlSizeTrigger.h @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include "CalcViewModel/Common/Utils.h" + +namespace CalculatorApp::Views::StateTriggers +{ + public ref class ControlSizeTrigger sealed : public Windows::UI::Xaml::StateTriggerBase + { + public: + ControlSizeTrigger(); + + DEPENDENCY_PROPERTY_OWNER(ControlSizeTrigger); + + DEPENDENCY_PROPERTY_WITH_CALLBACK(Windows::UI::Xaml::FrameworkElement^, Source); + + DEPENDENCY_PROPERTY_WITH_DEFAULT(double, MinHeight, -1); + + DEPENDENCY_PROPERTY_WITH_DEFAULT(double, MinWidth, -1); + + private: + ~ControlSizeTrigger(); + + void OnSourcePropertyChanged(Windows::UI::Xaml::FrameworkElement^ oldValue, Windows::UI::Xaml::FrameworkElement^ newValue); + + void RegisterSizeChanged(Windows::UI::Xaml::FrameworkElement^ element); + void UnregisterSizeChanged(Windows::UI::Xaml::FrameworkElement^ element); + void OnSizeChanged(Platform::Object^ sender, Windows::UI::Xaml::SizeChangedEventArgs^ e); + + void UpdateIsActive(Windows::Foundation::Size sourceSize); + + private: + Windows::Foundation::EventRegistrationToken m_sizeChangedToken; + }; +} diff --git a/src/Calculator/Views/TitleBar.xaml b/src/Calculator/Views/TitleBar.xaml index 94d13fa1..cc5120be 100644 --- a/src/Calculator/Views/TitleBar.xaml +++ b/src/Calculator/Views/TitleBar.xaml @@ -54,6 +54,10 @@ AutomationProperties.AutomationId="ExitAlwaysOnTopButton" Click="AlwaysOnTopButton_Click" Content="" - Visibility="Collapsed"/> + Visibility="Collapsed"> + + + + diff --git a/src/Calculator/Views/TitleBar.xaml.cpp b/src/Calculator/Views/TitleBar.xaml.cpp index 6b8ab4d6..44f4a8c4 100644 --- a/src/Calculator/Views/TitleBar.xaml.cpp +++ b/src/Calculator/Views/TitleBar.xaml.cpp @@ -37,9 +37,9 @@ namespace CalculatorApp Loaded += ref new RoutedEventHandler(this, &TitleBar::OnLoaded); Unloaded += ref new RoutedEventHandler(this, &TitleBar::OnUnloaded); #ifdef IS_STORE_BUILD - AppName->Text = AppResourceProvider::GetInstance().GetResourceString(L"AppName"); + AppName->Text = AppResourceProvider::GetInstance()->GetResourceString(L"AppName"); #else - AppName->Text = AppResourceProvider::GetInstance().GetResourceString(L"DevAppName"); + AppName->Text = AppResourceProvider::GetInstance()->GetResourceString(L"DevAppName"); #endif // IS_STORE_BUILD } diff --git a/src/Calculator/Views/UnitConverter.xaml b/src/Calculator/Views/UnitConverter.xaml index ba533d3a..0e15b928 100644 --- a/src/Calculator/Views/UnitConverter.xaml +++ b/src/Calculator/Views/UnitConverter.xaml @@ -260,14 +260,6 @@ - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Grid.ColumnSpan="4"> @@ -475,8 +538,7 @@ Grid.Row="1" Grid.Column="1" HorizontalAlignment="{x:Bind FlowDirectionHorizontalAlignment}" - Style="{ThemeResource ValueContainerStyle}" - Visibility="{x:Bind Model.IsCurrencyLoadingVisible, Mode=OneWay, Converter={StaticResource BooleanToVisibilityNegationConverter}}"> + Style="{ThemeResource ValueContainerStyle}"> @@ -520,15 +582,13 @@ ItemTemplate="{StaticResource UnitTemplate}" ItemsSource="{Binding Units, Converter={StaticResource AlwaysSelectedConverter}}" SelectedItem="{Binding Unit1, Mode=TwoWay, Converter={StaticResource ValidSelectedItemConverter}}" - TabIndex="2" - Visibility="{x:Bind Model.IsCurrencyLoadingVisible, Mode=OneWay, Converter={StaticResource BooleanToVisibilityNegationConverter}}"/> + TabIndex="2"/> + Style="{ThemeResource ValueContainerStyle}"> @@ -572,8 +632,7 @@ ItemTemplate="{StaticResource UnitTemplate}" ItemsSource="{Binding Units, Converter={StaticResource AlwaysSelectedConverter}}" SelectedItem="{Binding Unit2, Mode=TwoWay, Converter={StaticResource ValidSelectedItemConverter}}" - TabIndex="4" - Visibility="{x:Bind Model.IsCurrencyLoadingVisible, Mode=OneWay, Converter={StaticResource BooleanToVisibilityNegationConverter}}"/> + TabIndex="4"/> + SizeChanged="SupplementaryResultsPanelInGrid_SizeChanged"> + RenderTransformOrigin="0.5,0.5" + XYFocusKeyboardNavigation="Enabled"> @@ -703,7 +762,7 @@ x:Uid="converterNegateButton" Grid.Row="4" Grid.Column="0" - Style="{StaticResource SymbolOperatorButtonStyle}" + Style="{StaticResource SymbolOperatorKeypadButtonStyle}" FontSize="16" ButtonId="Negate" Content="" diff --git a/src/Calculator/Views/UnitConverter.xaml.cpp b/src/Calculator/Views/UnitConverter.xaml.cpp index b92944ad..f74d0a55 100644 --- a/src/Calculator/Views/UnitConverter.xaml.cpp +++ b/src/Calculator/Views/UnitConverter.xaml.cpp @@ -40,8 +40,6 @@ using namespace Windows::UI::Xaml::Media; using namespace Windows::UI::Xaml::Navigation; using namespace Windows::UI::ViewManagement; -// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 - // Calculate number of 100-nanosecond intervals in 500 milliseconds. // There are 10,000 intervals in 1 ms. static const long long DURATION_500_MS = 10000 * 500; @@ -66,14 +64,14 @@ UnitConverter::UnitConverter() m_isAnimationEnabled = userSettings->AnimationsEnabled; auto resLoader = AppResourceProvider::GetInstance(); - m_chargesMayApplyText = resLoader.GetResourceString(L"DataChargesMayApply"); - m_failedToRefreshText = resLoader.GetResourceString(L"FailedToRefresh"); + m_chargesMayApplyText = resLoader->GetResourceString(L"DataChargesMayApply"); + m_failedToRefreshText = resLoader->GetResourceString(L"FailedToRefresh"); InitializeOfflineStatusTextBlock(); m_resultsFlyout = static_cast(Resources->Lookup(L"CalculationResultContextMenu")); - CopyMenuItem->Text = resLoader.GetResourceString(L"copyMenuItem"); - PasteMenuItem->Text = resLoader.GetResourceString(L"pasteMenuItem"); + CopyMenuItem->Text = resLoader->GetResourceString(L"copyMenuItem"); + PasteMenuItem->Text = resLoader->GetResourceString(L"pasteMenuItem"); } void UnitConverter::OnPropertyChanged(_In_ Object ^ sender, _In_ PropertyChangedEventArgs ^ e) @@ -165,7 +163,7 @@ void UnitConverter::SetFailedToRefreshStatus() void UnitConverter::InitializeOfflineStatusTextBlock() { auto resProvider = AppResourceProvider::GetInstance(); - std::wstring offlineStatusHyperlinkText = static_cast(resProvider.GetResourceString(L"OfflineStatusHyperlinkText"))->Data(); + std::wstring offlineStatusHyperlinkText = resProvider->GetResourceString(L"OfflineStatusHyperlinkText")->Data(); // The resource string has the 'NetworkSettings' hyperlink wrapped with '%HL%'. // Break the string and assign pieces appropriately. @@ -245,9 +243,9 @@ void UnitConverter::OnCopyMenuItemClicked(_In_ Object ^ sender, _In_ RoutedEvent void UnitConverter::OnPasteMenuItemClicked(_In_ Object ^ sender, _In_ RoutedEventArgs ^ e) { - CopyPasteManager::GetStringToPaste(Model->Mode, CategoryGroupType::Converter).then([this](String ^ pastedString) { - Model->OnPaste(pastedString); - }); + auto that(this); + create_task(CopyPasteManager::GetStringToPaste(Model->Mode, CategoryGroupType::Converter, NumberBase::Unknown, BitLength::BitLengthUnknown)) + .then([that](String ^ pastedString) { that->Model->OnPaste(pastedString); }); } void UnitConverter::AnimateConverter() @@ -291,12 +289,17 @@ void UnitConverter::SetDefaultFocus() void UnitConverter::CurrencyRefreshButton_Click(_In_ Object ^ /*sender*/, _In_ RoutedEventArgs ^ /*e*/) { - if (Model->NetworkBehavior == NetworkAccessBehavior::OptIn) + // If IsCurrencyLoadingVisible is true that means CurrencyRefreshButton_Click was recently called + // and is still executing. In this case there is no reason to process the click. + if (!Model->IsCurrencyLoadingVisible) { - m_meteredConnectionOverride = true; - } + if (Model->NetworkBehavior == NetworkAccessBehavior::OptIn) + { + m_meteredConnectionOverride = true; + } - Model->RefreshCurrencyRatios(); + Model->RefreshCurrencyRatios(); + } } void UnitConverter::OnDataContextChanged(_In_ FrameworkElement ^ sender, _In_ DataContextChangedEventArgs ^ args) @@ -320,15 +323,16 @@ void UnitConverter::OnIsDisplayVisibleChanged() { if (Model->IsCurrencyLoadingVisible) { + VisualStateManager::GoToState(this, L"CurrencyLoadingState", false); StartProgressRingWithDelay(); } else { HideProgressRing(); - if (m_isAnimationEnabled && Model->IsCurrencyCurrentCategory && !Model->CurrencyTimestamp->IsEmpty()) + if (Model->IsCurrencyCurrentCategory && !Model->CurrencyTimestamp->IsEmpty()) { - TimestampFadeInAnimation->Begin(); + VisualStateManager::GoToState(this, L"CurrencyLoadedState", m_isAnimationEnabled); } } } @@ -373,6 +377,5 @@ void CalculatorApp::UnitConverter::SupplementaryResultsPanelInGrid_SizeChanged(P void CalculatorApp::UnitConverter::OnVisualStateChanged(Platform::Object ^ sender, Windows::UI::Xaml::VisualStateChangedEventArgs ^ e) { auto mode = NavCategory::Deserialize(Model->CurrentCategory->GetModelCategory().id); - auto state = std::wstring(e->NewState->Name->Begin()); - TraceLogger::GetInstance().LogVisualStateChanged(mode, state); + TraceLogger::GetInstance()->LogVisualStateChanged(mode, e->NewState->Name, false); } diff --git a/src/Calculator/WindowFrameService.cpp b/src/Calculator/WindowFrameService.cpp index b710ed65..37ad911b 100644 --- a/src/Calculator/WindowFrameService.cpp +++ b/src/Calculator/WindowFrameService.cpp @@ -118,7 +118,7 @@ namespace CalculatorApp void WindowFrameService::OnConsolidated(_In_ ApplicationView ^ sender, _In_ ApplicationViewConsolidatedEventArgs ^ e) { - TraceLogger::GetInstance().UpdateWindowCount(); + TraceLogger::GetInstance()->DecreaseWindowCount(); auto parent = m_parent.Resolve(); if (parent != nullptr) { diff --git a/src/Calculator/packages.config b/src/Calculator/packages.config index d41e98b7..a33d8464 100644 --- a/src/Calculator/packages.config +++ b/src/Calculator/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/src/Calculator/pch.h b/src/Calculator/pch.h index ff02ef83..add4efde 100644 --- a/src/Calculator/pch.h +++ b/src/Calculator/pch.h @@ -39,16 +39,5 @@ #include "winrt/Windows.UI.ViewManagement.h" #include "winrt/Windows.UI.Xaml.h" -// The following namespaces exist as a convenience to resolve -// ambiguity for Windows types in the Windows::UI::Xaml::Automation::Peers -// namespace that only exist on RS3. -// Once the app switches to min version RS3, the namespaces can be removed. -// TODO - MSFT 12735088 -namespace StandardPeers = Windows::UI::Xaml::Automation::Peers; -namespace CalculatorApp::Common::Automation -{ -} -namespace CustomPeers = CalculatorApp::Common::Automation; - // Project Headers #include "App.xaml.h" diff --git a/src/CalculatorUITestFramework/CalculatorUITestFramework.csproj b/src/CalculatorUITestFramework/CalculatorUITestFramework.csproj index 8c096d59..cdf09478 100644 --- a/src/CalculatorUITestFramework/CalculatorUITestFramework.csproj +++ b/src/CalculatorUITestFramework/CalculatorUITestFramework.csproj @@ -6,8 +6,6 @@ - - diff --git a/src/CalculatorUITests/StandardModeFunctionalTests.cs b/src/CalculatorUITests/StandardModeFunctionalTests.cs index 2fed75fe..2418dff4 100644 --- a/src/CalculatorUITests/StandardModeFunctionalTests.cs +++ b/src/CalculatorUITests/StandardModeFunctionalTests.cs @@ -102,9 +102,9 @@ namespace CalculatorUITests page.StandardOperators.EqualButton.Click(); var historyItems = page.HistoryPanel.GetAllHistoryListViewItems(); - Assert.IsTrue(historyItems[0].Text.Equals("1 × 3 = 3", StringComparison.InvariantCultureIgnoreCase)); - Assert.IsTrue(historyItems[1].Text.Equals("2 Minus ( 3 = Minus (1", StringComparison.InvariantCultureIgnoreCase)); - Assert.IsTrue(historyItems[2].Text.Equals("-3 + -2.6 = Minus (5.6", StringComparison.InvariantCultureIgnoreCase)); + Assert.IsTrue(historyItems[0].Text.Equals("1 × 3= 3", StringComparison.InvariantCultureIgnoreCase)); + Assert.IsTrue(historyItems[1].Text.Equals("2 Minus ( 3= Minus (1", StringComparison.InvariantCultureIgnoreCase)); + Assert.IsTrue(historyItems[2].Text.Equals("-3 + -2.6= Minus (5.6", StringComparison.InvariantCultureIgnoreCase)); } @@ -165,14 +165,6 @@ namespace CalculatorUITests Assert.AreEqual("12", page.GetCalculatorResultText()); } - [TestMethod] - public void Operator_Cubed() - { - page.StandardOperators.NumberPad.Input(-3); - page.StandardOperators.XPower3Button.Click(); - Assert.AreEqual("-27", page.GetCalculatorResultText()); - } - [TestMethod] public void Operator_Percent() { @@ -242,13 +234,6 @@ namespace CalculatorUITests Assert.AreEqual("10", page.GetCalculatorResultText()); } - [TestMethod] - public void KeyboardInput_Cubed() - { - page.Header.SendKeys("3#"); - Assert.AreEqual("27", page.GetCalculatorResultText()); - } - [TestMethod] public void KeyboardInput_Percent() { diff --git a/src/CalculatorUnitTests/CalcInputTest.cpp b/src/CalculatorUnitTests/CalcInputTest.cpp index f817594e..d5cbaafa 100644 --- a/src/CalculatorUnitTests/CalcInputTest.cpp +++ b/src/CalculatorUnitTests/CalcInputTest.cpp @@ -309,7 +309,7 @@ namespace CalculatorEngineTests wstring maxStr{}; for (size_t i = 0; i < MAX_STRLEN + 1; i++) { - maxStr += L"1"; + maxStr += L'1'; m_calcInput.TryAddDigit(1, 10, false, maxStr, 64, 100); } auto result = m_calcInput.ToString(10); @@ -323,7 +323,7 @@ namespace CalculatorEngineTests bool exponentCapped = false; for (size_t i = 0; i < MAX_STRLEN + 1; i++) { - maxStr += L"1"; + maxStr += L'1'; if (!m_calcInput.TryAddDigit(1, 10, false, maxStr, 64, MAX_STRLEN + 25)) { exponentCapped = true; diff --git a/src/CalculatorUnitTests/CalculatorManagerTest.cpp b/src/CalculatorUnitTests/CalculatorManagerTest.cpp index 9696a898..8f782004 100644 --- a/src/CalculatorUnitTests/CalculatorManagerTest.cpp +++ b/src/CalculatorUnitTests/CalculatorManagerTest.cpp @@ -43,16 +43,13 @@ namespace CalculatorManagerTest m_isError = isError; } void SetExpressionDisplay( - _Inout_ std::shared_ptr>> const& tokens, - _Inout_ std::shared_ptr>> const& /*commands*/) override + _Inout_ std::shared_ptr>> const& tokens, + _Inout_ std::shared_ptr>> const& /*commands*/) override { m_expression.clear(); - unsigned int nTokens = 0; - std::pair currentPair; - tokens->GetSize(&nTokens); - for (unsigned int i = 0; i < nTokens; ++i) + + for (const auto& currentPair : *tokens) { - tokens->GetAt(i, ¤tPair); m_expression += currentPair.first; } } @@ -97,6 +94,10 @@ namespace CalculatorManagerTest m_maxDigitsCalledCount++; } + void InputChanged() override + { + } + int GetMaxDigitsCalledCount() { return m_maxDigitsCalledCount; @@ -179,6 +180,8 @@ namespace CalculatorManagerTest TEST_METHOD(CalculatorManagerTestScientificError); TEST_METHOD(CalculatorManagerTestScientificModeChange); + TEST_METHOD(CalculatorManagerTestProgrammer); + TEST_METHOD(CalculatorManagerTestModeChange); TEST_METHOD(CalculatorManagerTestMemory); @@ -325,10 +328,10 @@ namespace CalculatorManagerTest Command commands4[] = { Command::Command2, Command::CommandADD, Command::Command3, Command::CommandEQU, Command::Command4, Command::CommandEQU, Command::CommandNULL }; - TestDriver::Test(L"7", L"", commands4); + TestDriver::Test(L"7", L"4 + 3=", commands4); Command commands5[] = { Command::Command4, Command::CommandEQU, Command::CommandNULL }; - TestDriver::Test(L"4", L"", commands5); + TestDriver::Test(L"4", L"4=", commands5); Command commands6[] = { Command::Command2, Command::Command5, Command::Command6, Command::CommandSQRT, Command::CommandSQRT, Command::CommandSQRT, Command::CommandNULL }; @@ -336,21 +339,21 @@ namespace CalculatorManagerTest Command commands7[] = { Command::Command3, Command::CommandSUB, Command::Command6, Command::CommandEQU, Command::CommandMUL, Command::Command3, Command::CommandEQU, Command::CommandNULL }; - TestDriver::Test(L"-9", L"", commands7); + TestDriver::Test(L"-9", L"-3 \x00D7 3=", commands7); Command commands8[] = { Command::Command9, Command::CommandMUL, Command::Command6, Command::CommandSUB, Command::CommandCENTR, Command::Command8, Command::CommandEQU, Command::CommandNULL }; - TestDriver::Test(L"46", L"", commands8); + TestDriver::Test(L"46", L"9 \x00D7 6 - 8=", commands8); Command commands9[] = { Command::Command6, Command::CommandMUL, Command::Command6, Command::CommandPERCENT, Command::CommandEQU, Command::CommandNULL }; - TestDriver::Test(L"0.36", L"", commands9); + TestDriver::Test(L"0.36", L"6 \x00D7 0.06=", commands9); Command commands10[] = { Command::Command5, Command::Command0, Command::CommandADD, Command::Command2, Command::Command0, Command::CommandPERCENT, Command::CommandEQU, Command::CommandNULL }; - TestDriver::Test(L"60", L"", commands10); + TestDriver::Test(L"60", L"50 + 10=", commands10); Command commands11[] = { Command::Command4, Command::CommandADD, Command::CommandEQU, Command::CommandNULL }; - TestDriver::Test(L"8", L"", commands11); + TestDriver::Test(L"8", L"4 + 4=", commands11); Command commands12[] = { Command::Command5, Command::CommandADD, Command::CommandMUL, Command::Command3, Command::CommandNULL }; TestDriver::Test(L"3", L"5 \x00D7 ", commands12); @@ -361,7 +364,7 @@ namespace CalculatorManagerTest Command commands14[] = { Command::Command5, Command::Command0, Command::CommandADD, Command::Command2, Command::Command0, Command::CommandPERCENT, Command::CommandEQU, Command::CommandNULL }; - TestDriver::Test(L"60", L"", commands14); + TestDriver::Test(L"60", L"50 + 10=", commands14); Command commands15[] = { Command::Command0, Command::CommandDIV, Command::Command0, Command::CommandEQU, Command::CommandNULL }; TestDriver::Test(L"Result is undefined", L"0 \x00F7 ", commands15); @@ -405,10 +408,10 @@ namespace CalculatorManagerTest Command commands4[] = { Command::Command1, Command::CommandADD, Command::Command0, Command::CommandMUL, Command::Command2, Command::CommandEQU, Command::CommandNULL }; - TestDriver::Test(L"1", L"", commands4, true, true); + TestDriver::Test(L"1", L"1 + 0 \x00D7 2=", commands4, true, true); Command commands5[] = { Command::Command4, Command::CommandEQU, Command::CommandNULL }; - TestDriver::Test(L"4", L"", commands5, true, true); + TestDriver::Test(L"4", L"4=", commands5, true, true); Command commands6[] = { Command::Command2, Command::Command5, Command::Command6, Command::CommandSQRT, Command::CommandSQRT, Command::CommandSQRT, Command::CommandNULL }; @@ -430,7 +433,7 @@ namespace CalculatorManagerTest TestDriver::Test(L"50.05", L"50 + 1/(20) - ", commands10, true, true); Command commands11[] = { Command::Command4, Command::CommandADD, Command::CommandEQU, Command::CommandNULL }; - TestDriver::Test(L"8", L"", commands11, true, true); + TestDriver::Test(L"8", L"4 + 4=", commands11, true, true); Command commands12[] = { Command::Command5, Command::CommandADD, Command::CommandMUL, Command::Command3, Command::CommandNULL }; TestDriver::Test(L"3", L"5 \x00D7 ", commands12, true, true); @@ -441,7 +444,7 @@ namespace CalculatorManagerTest Command commands14[] = { Command::Command5, Command::Command0, Command::CommandADD, Command::Command2, Command::Command0, Command::CommandPERCENT, Command::CommandEQU, Command::CommandNULL }; - TestDriver::Test(L"60", L"", commands14, true, true); + TestDriver::Test(L"60", L"50 + 10=", commands14, true, true); Command commands15[] = { Command::Command0, Command::CommandDIV, Command::Command0, Command::CommandEQU, Command::CommandNULL }; TestDriver::Test(L"Result is undefined", L"0 \x00F7 ", commands15, true, true); @@ -495,9 +498,9 @@ namespace CalculatorManagerTest Command commands5[] = { Command::Command8, Command::CommandCUB, Command::CommandNULL }; TestDriver::Test(L"512", L"cube(8)", commands5, true, true); - /* - Command commands6[] = { Command::Command8, Command::CommandCUB, Command::CommandCUBEROOT, Command::CommandNULL }; - TestDriver::Test(L"8", L"cuberoot(cube(8))", commands6, true, true);*/ + + Command commands6[] = { Command::Command8, Command::CommandCUB, Command::CommandCUBEROOT, Command::CommandNULL }; + TestDriver::Test(L"8", L"cuberoot(cube(8))", commands6, true, true); Command commands7[] = { Command::Command1, Command::Command0, Command::CommandLOG, Command::CommandNULL }; TestDriver::Test(L"1", L"log(10)", commands7, true, true); @@ -552,6 +555,66 @@ namespace CalculatorManagerTest Command commands22[] = { Command::Command1, Command::Command0, Command::CommandPWR, Command::Command1, Command::CommandPNT, Command::Command2, Command::Command3, Command::Command4, Command::Command5, Command::Command6, Command::CommandADD, Command::CommandNULL }; TestDriver::Test(L"17.161687912241792074207286679393", L"10 ^ 1.23456 + ", commands22, true, true); + + Command commands23[] = { Command::Command1, Command::CommandSEC, Command::CommandNULL }; + TestDriver::Test(L"1.0001523280439076654284264342126", L"sec\x2080(1)", commands23, true, true); + + Command commands24[] = { Command::Command1, Command::CommandCSC, Command::CommandNULL }; + TestDriver::Test(L"57.298688498550183476612683735174", L"csc\x2080(1)", commands24, true, true); + + Command commands25[] = { Command::Command1, Command::CommandCOT, Command::CommandNULL }; + TestDriver::Test(L"57.289961630759424687278147537113", L"cot\x2080(1)", commands25, true, true); + + Command commands26[] = { Command::Command1, Command::CommandASEC, Command::CommandNULL }; + TestDriver::Test(L"0", L"sec\x2080\x207B\x00B9(1)", commands26, true, true); + + Command commands27[] = { Command::Command1, Command::CommandACSC, Command::CommandNULL }; + TestDriver::Test(L"90", L"csc\x2080\x207B\x00B9(1)", commands27, true, true); + + Command commands28[] = { Command::Command1, Command::CommandACOT, Command::CommandNULL }; + TestDriver::Test(L"45", L"cot\x2080\x207B\x00B9(1)", commands28, true, true); + + Command commands29[] = { Command::Command1, Command::CommandSECH, Command::CommandNULL }; + TestDriver::Test(L"0.64805427366388539957497735322615", L"sech(1)", commands29, true, true); + + Command commands30[] = { Command::Command1, Command::CommandCSCH, Command::CommandNULL }; + TestDriver::Test(L"0.85091812823932154513384276328718", L"csch(1)", commands30, true, true); + + Command commands31[] = { Command::Command1, Command::CommandCOTH, Command::CommandNULL }; + TestDriver::Test(L"1.3130352854993313036361612469308", L"coth(1)", commands31, true, true); + + Command commands32[] = { Command::Command1, Command::CommandASECH, Command::CommandNULL }; + TestDriver::Test(L"0", L"sech\x207B\x00B9(1)", commands32, true, true); + + Command commands33[] = { Command::Command1, Command::CommandACSCH, Command::CommandNULL }; + TestDriver::Test(L"0.88137358701954302523260932497979", L"csch\x207B\x00B9(1)", commands33, true, true); + + Command commands34[] = { Command::Command2, Command::CommandACOTH, Command::CommandNULL }; + TestDriver::Test(L"0.54930614433405484569762261846126", L"coth\x207B\x00B9(2)", commands34, true, true); + + Command commands35[] = { Command::Command8, Command::CommandPOW2, Command::CommandNULL }; + TestDriver::Test(L"256", L"2^(8)", commands35); + + Command commands36[] = { Command::CommandRand, Command::CommandCeil, Command::CommandNULL }; + TestDriver::Test(L"1", L"N/A", commands36); + + Command commands37[] = { Command::CommandRand, Command::CommandFloor, Command::CommandNULL }; + TestDriver::Test(L"0", L"N/A", commands37); + + Command commands38[] = { Command::CommandRand, Command::CommandSIGN, Command::CommandCeil, Command::CommandNULL }; + TestDriver::Test(L"0", L"N/A", commands38); + + Command commands39[] = { Command::CommandRand, Command::CommandSIGN, Command::CommandFloor, Command::CommandNULL }; + TestDriver::Test(L"-1", L"N/A", commands39); + + Command commands40[] = { Command::Command3, Command::CommandPNT, Command::Command8, Command::CommandFloor, Command::CommandNULL }; + TestDriver::Test(L"3", L"floor(3.8)", commands40); + + Command commands41[] = { Command::Command3, Command::CommandPNT, Command::Command8, Command::CommandCeil, Command::CommandNULL }; + TestDriver::Test(L"4", L"ceil(3.8)", commands41); + + Command commands42[] = { Command::Command3, Command::CommandLogBaseX, Command::Command5, Command::CommandADD, Command::CommandNULL }; + TestDriver::Test(L"1.464973520717927", L"3 base log 5 + ", commands42); } void CalculatorManagerTest::CalculatorManagerTestScientificParenthesis() @@ -576,7 +639,7 @@ namespace CalculatorManagerTest Command commands5[] = { Command::Command2, Command::CommandOPENP, Command::Command2, Command::CommandCLOSEP, Command::CommandADD, Command::CommandEQU, Command::CommandNULL }; - TestDriver::Test(L"4", L"", commands5, true, true); + TestDriver::Test(L"4", L"(2) + 2=", commands5, true, true); } void CalculatorManagerTest::CalculatorManagerTestScientificError() @@ -651,6 +714,41 @@ namespace CalculatorManagerTest TestDriver::Test(L"0", L"", commands8, true, false); } + void CalculatorManagerTest::CalculatorManagerTestProgrammer() + { + Command commands1[] = { Command::ModeProgrammer, Command::Command5, Command::Command3, Command::CommandNand, + Command::Command8, Command::Command3, Command::CommandAnd, Command::CommandNULL }; + TestDriver::Test(L"-18", L"53 NAND 83 AND ", commands1, true, false); + + Command commands2[] = { Command::ModeProgrammer, Command::Command5, Command::Command3, Command::CommandNor, + Command::Command8, Command::Command3, Command::CommandAnd, Command::CommandNULL }; + TestDriver::Test(L"-120", L"53 NOR 83 AND ", commands2, true, false); + + Command commands3[] = { Command::ModeProgrammer, Command::Command5, Command::CommandLSHF, + Command::Command1, Command::CommandAnd, Command::CommandNULL }; + TestDriver::Test(L"10", L"5 Lsh 1 AND ", commands3, true, false); + + Command commands5[] = { Command::ModeProgrammer, Command::Command5, Command::CommandRSHFL, + Command::Command1, Command::CommandAnd, Command::CommandNULL }; + TestDriver::Test(L"2", L"5 Rsh 1 AND ", commands5, true, false); + + Command commands6[] = { Command::ModeProgrammer, Command::CommandBINPOS63, Command::CommandRSHF, + Command::Command5, Command::Command6, Command::CommandAnd, Command::CommandNULL }; + TestDriver::Test(L"-128", L"-9223372036854775808 Rsh 56 AND ", commands6, true, false); + + Command commands7[] = { Command::ModeProgrammer, Command::Command1, Command::CommandROL, Command::CommandNULL }; + TestDriver::Test(L"2", L"RoL(1)", commands7, true, false); + + Command commands8[] = { Command::ModeProgrammer, Command::Command1, Command::CommandROR, Command::CommandNULL }; + TestDriver::Test(L"-9,223,372,036,854,775,808", L"RoR(1)", commands8, true, false); + + Command commands9[] = { Command::ModeProgrammer, Command::Command1, Command::CommandRORC, Command::CommandNULL }; + TestDriver::Test(L"0", L"RoR(1)", commands9, true, false); + + Command commands10[] = { Command::ModeProgrammer, Command::Command1, Command::CommandRORC, Command::CommandRORC, Command::CommandNULL }; + TestDriver::Test(L"-9,223,372,036,854,775,808", L"RoR(RoR(1))", commands10, true, false); + } + void CalculatorManagerTest::CalculatorManagerTestMemory() { Command scientificCalculatorTest52[] = { Command::Command1, Command::CommandSTORE, Command::CommandNULL }; diff --git a/src/CalculatorUnitTests/CalculatorUnitTests.vcxproj b/src/CalculatorUnitTests/CalculatorUnitTests.vcxproj index 5fadb811..712309c6 100644 --- a/src/CalculatorUnitTests/CalculatorUnitTests.vcxproj +++ b/src/CalculatorUnitTests/CalculatorUnitTests.vcxproj @@ -207,12 +207,10 @@ - - UnitTestApp.xaml @@ -238,7 +236,6 @@ - @@ -248,7 +245,6 @@ - @@ -272,7 +268,6 @@ - @@ -288,9 +283,6 @@ Designer - - - {311e866d-8b93-4609-a691-265941fee101} diff --git a/src/CalculatorUnitTests/CalculatorUnitTests.vcxproj.filters b/src/CalculatorUnitTests/CalculatorUnitTests.vcxproj.filters index 63c8bc40..dfafb3cd 100644 --- a/src/CalculatorUnitTests/CalculatorUnitTests.vcxproj.filters +++ b/src/CalculatorUnitTests/CalculatorUnitTests.vcxproj.filters @@ -9,7 +9,6 @@ - @@ -17,7 +16,6 @@ - @@ -33,20 +31,15 @@ - - Mocks - - - diff --git a/src/CalculatorUnitTests/CopyPasteManagerTest.cpp b/src/CalculatorUnitTests/CopyPasteManagerTest.cpp index 2c2a61cb..ee9eb1d7 100644 --- a/src/CalculatorUnitTests/CopyPasteManagerTest.cpp +++ b/src/CalculatorUnitTests/CopyPasteManagerTest.cpp @@ -6,12 +6,14 @@ #include "CalcViewModel/StandardCalculatorViewModel.h" #include "CalcViewModel/Common/CopyPasteManager.h" +#include "Helpers.h" using namespace CalculationManager; using namespace CalculatorApp; using namespace CalculatorApp::Common; using namespace CalculatorApp::ViewModel; using namespace Platform; +using namespace Platform::Collections; using namespace std; using namespace Windows::ApplicationModel::DataTransfer; using namespace Windows::ApplicationModel::Resources; @@ -39,9 +41,20 @@ namespace CalculatorUnitTests } \ } +#define VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS(ref, length, value, ...) \ + { \ + auto result = ref; \ + Assert::IsTrue(ref.maxLength == length, __VA_ARGS__); \ + Assert::IsTrue(ref.maxValue == value, __VA_ARGS__); \ + } + TEST_CLASS(CopyPasteManagerTest) { public: + CopyPasteManagerTest() + { + m_CopyPasteManager = ref new CopyPasteManager(); + } TEST_METHOD(FunctionalCopyPasteTest); TEST_METHOD(ValidateStandardPasteExpressionTest); TEST_METHOD(ValidateScientificPasteExpressionTest); @@ -54,35 +67,45 @@ namespace CalculatorUnitTests TEST_METHOD(ValidatePasteExpressionErrorStates) { wstring exp_TooLong = L""; - for (int i = 0; i < m_CopyPasteManager.MaxPasteableLength / 8; i++) + for (unsigned int i = 0; i < CopyPasteManager::MaxPasteableLength / 8; i++) { exp_TooLong += L"-1234567"; } VERIFY_ARE_EQUAL( - m_CopyPasteManager.ValidatePasteExpression(StringReference(exp_TooLong.c_str()), ViewMode::Standard, CategoryGroupType::Calculator, -1, BitLength::BitLengthUnknown), + m_CopyPasteManager->ValidatePasteExpression( + StringReference(exp_TooLong.c_str()), + ViewMode::Standard, + CategoryGroupType::Calculator, + NumberBase::Unknown, + BitLength::BitLengthUnknown), StringReference(exp_TooLong.c_str()), L"Verify ValidatePasteExpression handles expressions up to max length"); exp_TooLong += L"1"; VERIFY_ARE_EQUAL( - m_CopyPasteManager.ValidatePasteExpression( - StringReference(exp_TooLong.c_str()), ViewMode::Standard, CategoryGroupType::Calculator, -1, BitLength::BitLengthUnknown), + m_CopyPasteManager->ValidatePasteExpression( + StringReference(exp_TooLong.c_str()), + ViewMode::Standard, + CategoryGroupType::Calculator, + NumberBase::Unknown, + BitLength::BitLengthUnknown), StringReference(L"NoOp"), L"Verify ValidatePasteExpression returns NoOp for strings over max length"); VERIFY_ARE_EQUAL( - m_CopyPasteManager.ValidatePasteExpression( - StringReference(L""), ViewMode::Standard, CategoryGroupType::Calculator, -1, BitLength::BitLengthUnknown), + m_CopyPasteManager->ValidatePasteExpression( + StringReference(L""), ViewMode::Standard, CategoryGroupType::Calculator, NumberBase::Unknown, BitLength::BitLengthUnknown), StringReference(L"NoOp"), L"Verify empty string is invalid"); VERIFY_ARE_EQUAL( - m_CopyPasteManager.ValidatePasteExpression( - StringReference(L"123e456"), ViewMode::Standard, CategoryGroupType::Calculator, -1, BitLength::BitLengthUnknown), + m_CopyPasteManager->ValidatePasteExpression( + StringReference(L"1a23f456"), ViewMode::Standard, CategoryGroupType::Calculator, NumberBase::Unknown, BitLength::BitLengthUnknown), StringReference(L"NoOp"), L"Verify pasting unsupported strings for the current mode is invalid"); VERIFY_ARE_EQUAL( - m_CopyPasteManager.ValidatePasteExpression(StringReference(L"123"), ViewMode::None, CategoryGroupType::None, -1, BitLength::BitLengthUnknown), + m_CopyPasteManager->ValidatePasteExpression( + StringReference(L"123"), ViewMode::None, CategoryGroupType::None, NumberBase::Unknown, BitLength::BitLengthUnknown), StringReference(L"NoOp"), L"Verify pasting without a ViewMode or Category is invalid"); }; @@ -91,48 +114,57 @@ namespace CalculatorUnitTests { vector results = {}; - vector oneOperand = { L"123456" }; - VERIFY_ARE_EQUAL(m_CopyPasteManager.ExtractOperands(L"123456", ViewMode::Standard), oneOperand); - oneOperand = { L"123^456" }; - VERIFY_ARE_EQUAL(m_CopyPasteManager.ExtractOperands(L"123^456", ViewMode::Standard), oneOperand); + auto oneOperand = ref new Vector(); + oneOperand->Append(L"123456"); - vector twoOperands = { L"123", L"456" }; - VERIFY_ARE_EQUAL(m_CopyPasteManager.ExtractOperands(L"123+456", ViewMode::Standard), twoOperands); - VERIFY_ARE_EQUAL(m_CopyPasteManager.ExtractOperands(L"123-456", ViewMode::Standard), twoOperands); - VERIFY_ARE_EQUAL(m_CopyPasteManager.ExtractOperands(L"123*456", ViewMode::Standard), twoOperands); - VERIFY_ARE_EQUAL(m_CopyPasteManager.ExtractOperands(L"123/456", ViewMode::Standard), twoOperands); + VERIFY_VECTORS_ARE_EQUAL(CopyPasteManager::ExtractOperands(L"123456", ViewMode::Standard), oneOperand); + oneOperand->Clear(); + oneOperand->Append(L"123^456"); + VERIFY_VECTORS_ARE_EQUAL(CopyPasteManager::ExtractOperands(L"123^456", ViewMode::Standard), oneOperand); - vector expOperand = { L"123e456" }; - VERIFY_ARE_EQUAL(m_CopyPasteManager.ExtractOperands(L"123e456", ViewMode::Standard), expOperand); - expOperand = { L"123e4567" }; - VERIFY_ARE_EQUAL(m_CopyPasteManager.ExtractOperands(L"123e4567", ViewMode::Standard), expOperand); + auto twoOperands = ref new Vector(); + twoOperands->Append(L"123"); + twoOperands->Append(L"456"); + VERIFY_VECTORS_ARE_EQUAL(CopyPasteManager::ExtractOperands(L"123+456", ViewMode::Standard), twoOperands); + VERIFY_VECTORS_ARE_EQUAL(CopyPasteManager::ExtractOperands(L"123-456", ViewMode::Standard), twoOperands); + VERIFY_VECTORS_ARE_EQUAL(CopyPasteManager::ExtractOperands(L"123*456", ViewMode::Standard), twoOperands); + VERIFY_VECTORS_ARE_EQUAL(CopyPasteManager::ExtractOperands(L"123/456", ViewMode::Standard), twoOperands); - vector twoOperandsParens = { L"((45)", L"(-30))" }; - VERIFY_ARE_EQUAL(m_CopyPasteManager.ExtractOperands(L"((45)+(-30))", ViewMode::Scientific), twoOperandsParens); + auto expOperand = ref new Vector(); + expOperand->Append(L"123e456"); + VERIFY_VECTORS_ARE_EQUAL(CopyPasteManager::ExtractOperands(L"123e456", ViewMode::Standard), expOperand); + expOperand->Clear(); + expOperand->Append(L"123e4567"); + VERIFY_VECTORS_ARE_EQUAL(CopyPasteManager::ExtractOperands(L"123e4567", ViewMode::Standard), expOperand); + + auto twoOperandsParens = ref new Vector(); + twoOperandsParens->Append(L"((45)"); + twoOperandsParens->Append(L"(-30))"); + VERIFY_VECTORS_ARE_EQUAL(CopyPasteManager::ExtractOperands(L"((45)+(-30))", ViewMode::Scientific), twoOperandsParens); }; TEST_METHOD(ValidateExtractOperandsErrors) { - wstring exp_OperandLimit = L""; - for (int i = 0; i < m_CopyPasteManager.MaxOperandCount; i++) + auto exp_OperandLimit = ref new String(L""); + for (unsigned int i = 0; i < m_CopyPasteManager->MaxOperandCount; i++) { exp_OperandLimit += L"+1"; } VERIFY_ARE_EQUAL( - m_CopyPasteManager.ExtractOperands(exp_OperandLimit, ViewMode::Standard).size(), + CopyPasteManager::ExtractOperands(exp_OperandLimit, ViewMode::Standard)->Size, 100, L"Verify ExtractOperands handles up to MaxOperandCount operands"); exp_OperandLimit += L"+1"; VERIFY_ARE_EQUAL( - m_CopyPasteManager.ExtractOperands(exp_OperandLimit, ViewMode::Standard).size(), + CopyPasteManager::ExtractOperands(exp_OperandLimit, ViewMode::Standard)->Size, 0, L"Verify ExtractOperands returns empty vector on too many operands"); VERIFY_ARE_EQUAL( - m_CopyPasteManager.ExtractOperands(L"12e9999", ViewMode::Standard).size(), 1, L"Verify ExtractOperands handles up to 4 digit exponents"); + CopyPasteManager::ExtractOperands(L"12e9999", ViewMode::Standard)->Size, 1, L"Verify ExtractOperands handles up to 4 digit exponents"); VERIFY_ARE_EQUAL( - m_CopyPasteManager.ExtractOperands(L"12e10000", ViewMode::Standard).size(), + CopyPasteManager::ExtractOperands(L"12e10000", ViewMode::Standard)->Size, 0, L"Verify ExtractOperands returns empty vector when the exponent is too long"); }; @@ -140,410 +172,521 @@ namespace CalculatorUnitTests TEST_METHOD(ValidateExpressionRegExMatch) { VERIFY_IS_FALSE( - m_CopyPasteManager.ExpressionRegExMatch(vector{}, ViewMode::Standard, CategoryGroupType::Calculator, -1, BitLength::BitLengthUnknown), + m_CopyPasteManager->ExpressionRegExMatch( + ref new Vector(), ViewMode::Standard, CategoryGroupType::Calculator, NumberBase::Unknown, BitLength::BitLengthUnknown), L"Verify empty list of operands returns false."); VERIFY_IS_FALSE( - m_CopyPasteManager.ExpressionRegExMatch( - vector{ L"123" }, ViewMode::None, CategoryGroupType::Calculator, -1, BitLength::BitLengthUnknown), + m_CopyPasteManager->ExpressionRegExMatch( + ref new Vector({ L"123" }), + ViewMode::None, + CategoryGroupType::Calculator, + NumberBase::Unknown, + BitLength::BitLengthUnknown), L"Verify invalid ViewMode/CategoryGroups return false."); VERIFY_IS_FALSE( - m_CopyPasteManager.ExpressionRegExMatch( - vector{ L"123" }, ViewMode::Currency, CategoryGroupType::None, -1, BitLength::BitLengthUnknown), + m_CopyPasteManager->ExpressionRegExMatch( + ref new Vector({ L"123" }), + ViewMode::Currency, + CategoryGroupType::None, + NumberBase::Unknown, + BitLength::BitLengthUnknown), L"Verify invalid ViewMode/CategoryGroups return false."); Logger::WriteMessage(L"Verify operand lengths > max return false."); - VERIFY_IS_FALSE(m_CopyPasteManager.ExpressionRegExMatch( - vector{ L"12345678901234567" }, ViewMode::Standard, CategoryGroupType::Calculator, -1, BitLength::BitLengthUnknown)); - VERIFY_IS_FALSE(m_CopyPasteManager.ExpressionRegExMatch( - vector{ L"123456789012345678901234567890123" }, ViewMode::Scientific, CategoryGroupType::Calculator, -1, BitLength::BitLengthUnknown)); - VERIFY_IS_FALSE(m_CopyPasteManager.ExpressionRegExMatch( - vector{ L"12345678901234567" }, ViewMode::None, CategoryGroupType::Converter, -1, BitLength::BitLengthUnknown)); - VERIFY_IS_FALSE(m_CopyPasteManager.ExpressionRegExMatch( - vector{ L"11111111111111111" }, ViewMode::Programmer, CategoryGroupType::Calculator, HexBase, BitLength::BitLengthQWord)); - VERIFY_IS_FALSE(m_CopyPasteManager.ExpressionRegExMatch( - vector{ L"12345678901234567890" }, ViewMode::Programmer, CategoryGroupType::Calculator, DecBase, BitLength::BitLengthQWord)); - VERIFY_IS_FALSE(m_CopyPasteManager.ExpressionRegExMatch( - vector{ L"11111111111111111111111" }, ViewMode::Programmer, CategoryGroupType::Calculator, OctBase, BitLength::BitLengthQWord)); - VERIFY_IS_FALSE(m_CopyPasteManager.ExpressionRegExMatch( - vector{ L"10000000000000000000000000000000000000000000000000000000000000000" }, + VERIFY_IS_FALSE(m_CopyPasteManager->ExpressionRegExMatch( + ref new Vector({ L"12345678901234567" }), + ViewMode::Standard, + CategoryGroupType::Calculator, + NumberBase::Unknown, + BitLength::BitLengthUnknown)); + VERIFY_IS_FALSE(m_CopyPasteManager->ExpressionRegExMatch( + ref new Vector({ L"123456789012345678901234567890123" }), + ViewMode::Scientific, + CategoryGroupType::Calculator, + NumberBase::Unknown, + BitLength::BitLengthUnknown)); + VERIFY_IS_FALSE(m_CopyPasteManager->ExpressionRegExMatch( + ref new Vector({ L"12345678901234567" }), + ViewMode::None, + CategoryGroupType::Converter, + NumberBase::Unknown, + BitLength::BitLengthUnknown)); + VERIFY_IS_FALSE(m_CopyPasteManager->ExpressionRegExMatch( + ref new Vector({ L"11111111111111111" }), ViewMode::Programmer, CategoryGroupType::Calculator, - BinBase, + NumberBase::HexBase, + BitLength::BitLengthQWord)); + VERIFY_IS_FALSE(m_CopyPasteManager->ExpressionRegExMatch( + ref new Vector({ L"12345678901234567890" }), + ViewMode::Programmer, + CategoryGroupType::Calculator, + NumberBase::DecBase, + BitLength::BitLengthQWord)); + VERIFY_IS_FALSE(m_CopyPasteManager->ExpressionRegExMatch( + ref new Vector({ L"11111111111111111111111" }), + ViewMode::Programmer, + CategoryGroupType::Calculator, + NumberBase::OctBase, + BitLength::BitLengthQWord)); + VERIFY_IS_FALSE(m_CopyPasteManager->ExpressionRegExMatch( + ref new Vector({ L"10000000000000000000000000000000000000000000000000000000000000000" }), + ViewMode::Programmer, + CategoryGroupType::Calculator, + NumberBase::BinBase, BitLength::BitLengthQWord)); VERIFY_IS_FALSE( - m_CopyPasteManager.ExpressionRegExMatch( - vector{ L"9223372036854775808" }, ViewMode::Programmer, CategoryGroupType::Calculator, DecBase, BitLength::BitLengthQWord), + m_CopyPasteManager->ExpressionRegExMatch( + ref new Vector({ L"9223372036854775808" }), + ViewMode::Programmer, + CategoryGroupType::Calculator, + NumberBase::DecBase, + BitLength::BitLengthQWord), L"Verify operand values > max return false."); VERIFY_IS_TRUE( - m_CopyPasteManager.ExpressionRegExMatch( - vector{ L"((((((((((((((((((((123))))))))))))))))))))" }, + m_CopyPasteManager->ExpressionRegExMatch( + ref new Vector({ L"((((((((((((((((((((123))))))))))))))))))))" }), ViewMode::Scientific, CategoryGroupType::Calculator, - -1, + NumberBase::Unknown, BitLength::BitLengthUnknown), L"Verify sanitized operand is detected as within max length."); VERIFY_IS_TRUE( - m_CopyPasteManager.ExpressionRegExMatch( - vector{ L"9223372036854775807" }, ViewMode::Programmer, CategoryGroupType::Calculator, DecBase, BitLength::BitLengthQWord), + m_CopyPasteManager->ExpressionRegExMatch( + ref new Vector({ L"9223372036854775807" }), + ViewMode::Programmer, + CategoryGroupType::Calculator, + NumberBase::DecBase, + BitLength::BitLengthQWord), L"Verify operand values == max return true."); Logger::WriteMessage(L"Verify all operands must match patterns."); - VERIFY_IS_TRUE(m_CopyPasteManager.ExpressionRegExMatch( - vector{ L"123", L"456" }, ViewMode::Standard, CategoryGroupType::Calculator, -1, BitLength::BitLengthUnknown)); - VERIFY_IS_FALSE(m_CopyPasteManager.ExpressionRegExMatch( - vector{ L"123", L"1e23" }, ViewMode::Standard, CategoryGroupType::Calculator, -1, BitLength::BitLengthUnknown)); + VERIFY_IS_TRUE(m_CopyPasteManager->ExpressionRegExMatch( + ref new Vector({ L"123", L"456" }), + ViewMode::Standard, + CategoryGroupType::Calculator, + NumberBase::Unknown, + BitLength::BitLengthUnknown)); + VERIFY_IS_TRUE(m_CopyPasteManager->ExpressionRegExMatch( + ref new Vector({ L"123", L"1e23" }), + ViewMode::Standard, + CategoryGroupType::Calculator, + NumberBase::Unknown, + BitLength::BitLengthUnknown)); + VERIFY_IS_FALSE(m_CopyPasteManager->ExpressionRegExMatch( + ref new Vector({ L"123", L"fab10" }), + ViewMode::Standard, + CategoryGroupType::Calculator, + NumberBase::Unknown, + BitLength::BitLengthUnknown)); VERIFY_IS_TRUE( - m_CopyPasteManager.ExpressionRegExMatch( - vector{ L"1.23e+456", L"1.23e456", L".23e+456", L"123e-456", L"12e2", L"12e+2", L"12e-2", L"-12e2", L"-12e+2", L"-12e-2" }, + m_CopyPasteManager->ExpressionRegExMatch( + ref new Vector( + { L"1.23e+456", L"1.23e456", L".23e+456", L"123e-456", L"12e2", L"12e+2", L"12e-2", L"-12e2", L"-12e+2", L"-12e-2" }), ViewMode::Scientific, CategoryGroupType::Calculator, - -1, + NumberBase::Unknown, BitLength::BitLengthUnknown), L"Verify exponents are accepted in scientific mode."); VERIFY_IS_FALSE( - m_CopyPasteManager.ExpressionRegExMatch( - vector{ L"123", L"12345678901234567" }, ViewMode::Standard, CategoryGroupType::Calculator, -1, BitLength::BitLengthUnknown), + m_CopyPasteManager->ExpressionRegExMatch( + ref new Vector({ L"123", L"12345678901234567" }), + ViewMode::Standard, + CategoryGroupType::Calculator, + NumberBase::Unknown, + BitLength::BitLengthUnknown), L"Verify all operands must be within maxlength"); VERIFY_IS_FALSE( - m_CopyPasteManager.ExpressionRegExMatch( - vector{ L"123", L"9223372036854775808" }, + m_CopyPasteManager->ExpressionRegExMatch( + ref new Vector({ L"123", L"9223372036854775808" }), ViewMode::Programmer, CategoryGroupType::Calculator, - DecBase, + NumberBase::DecBase, BitLength::BitLengthQWord), L"Verify all operand must be within max value."); }; TEST_METHOD(ValidateGetMaxOperandLengthAndValue) { - pair standardModeMaximums = make_pair(m_CopyPasteManager.MaxStandardOperandLength, 0); - pair scientificModeMaximums = make_pair(m_CopyPasteManager.MaxScientificOperandLength, 0); - pair converterModeMaximums = make_pair(m_CopyPasteManager.MaxConverterInputLength, 0); - VERIFY_ARE_EQUAL( - m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Standard, CategoryGroupType::None, -1, BitLength::BitLengthUnknown), - standardModeMaximums, + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Standard, CategoryGroupType::None, NumberBase::Unknown, BitLength::BitLengthUnknown), + m_CopyPasteManager->MaxStandardOperandLength, + 0, L"Verify Standard mode maximum values"); - VERIFY_ARE_EQUAL( - m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Scientific, CategoryGroupType::None, -1, BitLength::BitLengthUnknown), - scientificModeMaximums, + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Scientific, CategoryGroupType::None, NumberBase::Unknown, BitLength::BitLengthUnknown), + m_CopyPasteManager->MaxScientificOperandLength, + 0, L"Verify Scientific mode maximum values"); - VERIFY_ARE_EQUAL( - m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::None, CategoryGroupType::Converter, -1, BitLength::BitLengthUnknown), - converterModeMaximums, + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::None, CategoryGroupType::Converter, NumberBase::Unknown, BitLength::BitLengthUnknown), + m_CopyPasteManager->MaxConverterInputLength, + 0, L"Verify Converter mode maximum values"); unsigned long long int ullQwordMax = UINT64_MAX; unsigned long long int ullDwordMax = UINT32_MAX; unsigned long long int ullWordMax = UINT16_MAX; unsigned long long int ullByteMax = UINT8_MAX; - Logger::WriteMessage(L"Verify Programmer Mode HexBase maximum values"); - VERIFY_ARE_EQUAL( - m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, HexBase, BitLength::BitLengthQWord), - make_pair((size_t)16u, ullQwordMax)); - VERIFY_ARE_EQUAL( - m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, HexBase, BitLength::BitLengthDWord), - make_pair((size_t)8u, ullDwordMax)); - VERIFY_ARE_EQUAL( - m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, HexBase, BitLength::BitLengthWord), - make_pair((size_t)4u, ullWordMax)); - VERIFY_ARE_EQUAL( - m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, HexBase, BitLength::BitLengthByte), - make_pair((size_t)2u, ullByteMax)); + Logger::WriteMessage(L"Verify Programmer Mode NumberBase::HexBase maximum values"); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Programmer, CategoryGroupType::None, NumberBase::HexBase, BitLength::BitLengthQWord), + 16u, + ullQwordMax); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Programmer, CategoryGroupType::None, NumberBase::HexBase, BitLength::BitLengthDWord), + 8u, + ullDwordMax); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Programmer, CategoryGroupType::None, NumberBase::HexBase, BitLength::BitLengthWord), + 4u, + ullWordMax); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Programmer, CategoryGroupType::None, NumberBase::HexBase, BitLength::BitLengthByte), + 2u, + ullByteMax); - Logger::WriteMessage(L"Verify Programmer Mode DecBase maximum values"); - VERIFY_ARE_EQUAL( - m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, DecBase, BitLength::BitLengthQWord), - make_pair((size_t)19u, ullQwordMax >> 1)); - VERIFY_ARE_EQUAL( - m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, DecBase, BitLength::BitLengthDWord), - make_pair((size_t)10u, ullDwordMax >> 1)); - VERIFY_ARE_EQUAL( - m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, DecBase, BitLength::BitLengthWord), - make_pair((size_t)5u, ullWordMax >> 1)); - VERIFY_ARE_EQUAL( - m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, DecBase, BitLength::BitLengthByte), - make_pair((size_t)3u, ullByteMax >> 1)); + Logger::WriteMessage(L"Verify Programmer Mode NumberBase::DecBase maximum values"); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Programmer, CategoryGroupType::None, NumberBase::DecBase, BitLength::BitLengthQWord), + 19u, + ullQwordMax >> 1); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Programmer, CategoryGroupType::None, NumberBase::DecBase, BitLength::BitLengthDWord), + 10u, + ullDwordMax >> 1); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Programmer, CategoryGroupType::None, NumberBase::DecBase, BitLength::BitLengthWord), + 5u, + ullWordMax >> 1); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Programmer, CategoryGroupType::None, NumberBase::DecBase, BitLength::BitLengthByte), + 3u, + ullByteMax >> 1); - Logger::WriteMessage(L"Verify Programmer Mode OctBase maximum values"); - VERIFY_ARE_EQUAL( - m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, OctBase, BitLength::BitLengthQWord), - make_pair((size_t)22u, ullQwordMax)); - VERIFY_ARE_EQUAL( - m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, OctBase, BitLength::BitLengthDWord), - make_pair((size_t)11u, ullDwordMax)); - VERIFY_ARE_EQUAL( - m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, OctBase, BitLength::BitLengthWord), - make_pair((size_t)6u, ullWordMax)); - VERIFY_ARE_EQUAL( - m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, OctBase, BitLength::BitLengthByte), - make_pair((size_t)3u, ullByteMax)); + Logger::WriteMessage(L"Verify Programmer Mode NumberBase::OctBase maximum values"); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Programmer, CategoryGroupType::None, NumberBase::OctBase, BitLength::BitLengthQWord), + 22u, + ullQwordMax); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Programmer, CategoryGroupType::None, NumberBase::OctBase, BitLength::BitLengthDWord), + 11u, + ullDwordMax); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Programmer, CategoryGroupType::None, NumberBase::OctBase, BitLength::BitLengthWord), + 6u, + ullWordMax); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Programmer, CategoryGroupType::None, NumberBase::OctBase, BitLength::BitLengthByte), + 3u, + ullByteMax); - Logger::WriteMessage(L"Verify Programmer Mode BinBase maximum values"); - VERIFY_ARE_EQUAL( - m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, BinBase, BitLength::BitLengthQWord), - make_pair((size_t)64u, ullQwordMax)); - VERIFY_ARE_EQUAL( - m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, BinBase, BitLength::BitLengthDWord), - make_pair((size_t)32u, ullDwordMax)); - VERIFY_ARE_EQUAL( - m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, BinBase, BitLength::BitLengthWord), - make_pair((size_t)16u, ullWordMax)); - VERIFY_ARE_EQUAL( - m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::Programmer, CategoryGroupType::None, BinBase, BitLength::BitLengthByte), - make_pair((size_t)8u, ullByteMax)); + Logger::WriteMessage(L"Verify Programmer Mode NumberBase::BinBase maximum values"); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Programmer, CategoryGroupType::None, NumberBase::BinBase, BitLength::BitLengthQWord), + 64u, + ullQwordMax); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Programmer, CategoryGroupType::None, NumberBase::BinBase, BitLength::BitLengthDWord), + 32u, + ullDwordMax); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Programmer, CategoryGroupType::None, NumberBase::BinBase, BitLength::BitLengthWord), + 16u, + ullWordMax); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::Programmer, CategoryGroupType::None, NumberBase::BinBase, BitLength::BitLengthByte), + 8u, + ullByteMax); Logger::WriteMessage(L"Verify invalid ViewModes/Categories return 0 for max values"); - VERIFY_ARE_EQUAL( - m_CopyPasteManager.GetMaxOperandLengthAndValue(ViewMode::None, CategoryGroupType::None, - 1, BitLength::BitLengthUnknown), - make_pair((size_t)0u, 0ull)); + VERIFY_MAXOPERANDLENGTHANDVALUE_ARE_EQUALS( + m_CopyPasteManager->GetMaxOperandLengthAndValue( + ViewMode::None, CategoryGroupType::None, NumberBase::Unknown, BitLength::BitLengthUnknown), + 0u, + 0ull); }; TEST_METHOD(ValidateSanitizeOperand) { - VERIFY_ARE_EQUAL(m_CopyPasteManager.SanitizeOperand(L"((1234"), L"1234"); - VERIFY_ARE_EQUAL(m_CopyPasteManager.SanitizeOperand(L"1234))"), L"1234"); - VERIFY_ARE_EQUAL(m_CopyPasteManager.SanitizeOperand(L"1234))"), L"1234"); - VERIFY_ARE_EQUAL(m_CopyPasteManager.SanitizeOperand(L"-1234"), L"1234"); - VERIFY_ARE_EQUAL(m_CopyPasteManager.SanitizeOperand(L"+1234"), L"1234"); - VERIFY_ARE_EQUAL(m_CopyPasteManager.SanitizeOperand(L"-(1234)"), L"1234"); - VERIFY_ARE_EQUAL(m_CopyPasteManager.SanitizeOperand(L"+(1234)"), L"1234"); - VERIFY_ARE_EQUAL(m_CopyPasteManager.SanitizeOperand(L"12-34"), L"1234"); - VERIFY_ARE_EQUAL(m_CopyPasteManager.SanitizeOperand(L"((((1234))))"), L"1234"); - VERIFY_ARE_EQUAL(m_CopyPasteManager.SanitizeOperand(L"1'2'3'4"), L"1234"); - VERIFY_ARE_EQUAL(m_CopyPasteManager.SanitizeOperand(L"'''''1234''''"), L"1234"); - VERIFY_ARE_EQUAL(m_CopyPasteManager.SanitizeOperand(L"1_2_3_4"), L"1234"); - VERIFY_ARE_EQUAL(m_CopyPasteManager.SanitizeOperand(L"______1234___"), L"1234"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->SanitizeOperand(L"((1234"), L"1234"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->SanitizeOperand(L"1234))"), L"1234"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->SanitizeOperand(L"1234))"), L"1234"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->SanitizeOperand(L"-1234"), L"1234"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->SanitizeOperand(L"+1234"), L"1234"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->SanitizeOperand(L"-(1234)"), L"1234"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->SanitizeOperand(L"+(1234)"), L"1234"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->SanitizeOperand(L"12-34"), L"1234"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->SanitizeOperand(L"((((1234))))"), L"1234"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->SanitizeOperand(L"1'2'3'4"), L"1234"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->SanitizeOperand(L"'''''1234''''"), L"1234"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->SanitizeOperand(L"1_2_3_4"), L"1234"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->SanitizeOperand(L"______1234___"), L"1234"); }; // Using unicode literals here until the encoding issues get figured out TEST_METHOD(ValidatePrefixCurrencySymbols) { // ¥5 - VERIFY_ARE_EQUAL(m_CopyPasteManager.RemoveUnwantedCharsFromWstring(L"\u00A5\u0035"), L"5"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromString(L"\u00A5\u0035"), L"5"); // ¤5 - VERIFY_ARE_EQUAL(m_CopyPasteManager.RemoveUnwantedCharsFromWstring(L"\u00A4\u0035"), L"5"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromString(L"\u00A4\u0035"), L"5"); // ₵5 - VERIFY_ARE_EQUAL(m_CopyPasteManager.RemoveUnwantedCharsFromWstring(L"\u20B5\u0035"), L"5"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromString(L"\u20B5\u0035"), L"5"); // $5 - VERIFY_ARE_EQUAL(m_CopyPasteManager.RemoveUnwantedCharsFromWstring(L"\u0024\u0035"), L"5"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromString(L"\u0024\u0035"), L"5"); // ₡5 - VERIFY_ARE_EQUAL(m_CopyPasteManager.RemoveUnwantedCharsFromWstring(L"\u20A1\u0035"), L"5"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromString(L"\u20A1\u0035"), L"5"); // ₩5 - VERIFY_ARE_EQUAL(m_CopyPasteManager.RemoveUnwantedCharsFromWstring(L"\u20A9\u0035"), L"5"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromString(L"\u20A9\u0035"), L"5"); // ₪5 - VERIFY_ARE_EQUAL(m_CopyPasteManager.RemoveUnwantedCharsFromWstring(L"\u20AA\u0035"), L"5"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromString(L"\u20AA\u0035"), L"5"); // ₦5 - VERIFY_ARE_EQUAL(m_CopyPasteManager.RemoveUnwantedCharsFromWstring(L"\u20A6\u0035"), L"5"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromString(L"\u20A6\u0035"), L"5"); // ₹5 - VERIFY_ARE_EQUAL(m_CopyPasteManager.RemoveUnwantedCharsFromWstring(L"\u20B9\u0035"), L"5"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromString(L"\u20B9\u0035"), L"5"); // £5 - VERIFY_ARE_EQUAL(m_CopyPasteManager.RemoveUnwantedCharsFromWstring(L"\u00A3\u0035"), L"5"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromString(L"\u00A3\u0035"), L"5"); // €5 - VERIFY_ARE_EQUAL(m_CopyPasteManager.RemoveUnwantedCharsFromWstring(L"\u20AC\u0035"), L"5"); + VERIFY_ARE_EQUAL(m_CopyPasteManager->RemoveUnwantedCharsFromString(L"\u20AC\u0035"), L"5"); }; TEST_METHOD(ValidateTryOperandToULL) { - unsigned long long int result = 0; + IBox ^ result = nullptr; - Logger::WriteMessage(L"Verify TryOperandToULL HexBase conversion"); - VERIFY_IS_TRUE(m_CopyPasteManager.TryOperandToULL(L"1234", HexBase, result)); - VERIFY_ARE_EQUAL(result, 0x1234ull); - VERIFY_IS_TRUE(m_CopyPasteManager.TryOperandToULL(L"FF", HexBase, result)); - VERIFY_ARE_EQUAL(result, 0xFFull); - VERIFY_IS_TRUE(m_CopyPasteManager.TryOperandToULL(L"FFFFFFFFFFFFFFFF", HexBase, result)); - VERIFY_ARE_EQUAL(result, 0xFFFF'FFFF'FFFF'FFFF); - VERIFY_IS_TRUE(m_CopyPasteManager.TryOperandToULL(L"0xFFFFFFFFFFFFFFFF", HexBase, result)); - VERIFY_ARE_EQUAL(result, 0xFFFF'FFFF'FFFF'FFFF); - VERIFY_IS_TRUE(m_CopyPasteManager.TryOperandToULL(L"0XFFFFFFFFFFFFFFFF", HexBase, result)); - VERIFY_ARE_EQUAL(result, 0xFFFF'FFFF'FFFF'FFFF); - VERIFY_IS_TRUE(m_CopyPasteManager.TryOperandToULL(L"0X0FFFFFFFFFFFFFFFF", HexBase, result)); - VERIFY_ARE_EQUAL(result, 0xFFFF'FFFF'FFFF'FFFF); + Logger::WriteMessage(L"Verify TryOperandToULL NumberBase::HexBase conversion"); + result = CopyPasteManager::TryOperandToULL(L"1234", NumberBase::HexBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 0x1234ull); + result = CopyPasteManager::TryOperandToULL(L"FF", NumberBase::HexBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 0xFFull); + result = CopyPasteManager::TryOperandToULL(L"FFFFFFFFFFFFFFFF", NumberBase::HexBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 0xFFFF'FFFF'FFFF'FFFF); + result = CopyPasteManager::TryOperandToULL(L"0xFFFFFFFFFFFFFFFF", NumberBase::HexBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 0xFFFF'FFFF'FFFF'FFFF); + result = CopyPasteManager::TryOperandToULL(L"0XFFFFFFFFFFFFFFFF", NumberBase::HexBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 0xFFFF'FFFF'FFFF'FFFF); + result = CopyPasteManager::TryOperandToULL(L"0X0FFFFFFFFFFFFFFFF", NumberBase::HexBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 0xFFFF'FFFF'FFFF'FFFF); - Logger::WriteMessage(L"Verify TryOperandToULL DecBase conversion"); - VERIFY_IS_TRUE(m_CopyPasteManager.TryOperandToULL(L"1234", DecBase, result)); - VERIFY_ARE_EQUAL(result, 1234ull); - VERIFY_IS_TRUE(m_CopyPasteManager.TryOperandToULL(L"18446744073709551615", DecBase, result)); - VERIFY_ARE_EQUAL(result, 0xFFFF'FFFF'FFFF'FFFF); - VERIFY_IS_TRUE(m_CopyPasteManager.TryOperandToULL(L"018446744073709551615", DecBase, result)); - VERIFY_ARE_EQUAL(result, 0xFFFF'FFFF'FFFF'FFFF); + Logger::WriteMessage(L"Verify TryOperandToULL NumberBase::DecBase conversion"); + result = CopyPasteManager::TryOperandToULL(L"1234", NumberBase::DecBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 1234ull); + result = CopyPasteManager::TryOperandToULL(L"18446744073709551615", NumberBase::DecBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 0xFFFF'FFFF'FFFF'FFFF); + result = CopyPasteManager::TryOperandToULL(L"018446744073709551615", NumberBase::DecBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 0xFFFF'FFFF'FFFF'FFFF); - Logger::WriteMessage(L"Verify TryOperandToULL OctBase conversion"); - VERIFY_IS_TRUE(m_CopyPasteManager.TryOperandToULL(L"777", OctBase, result)); - VERIFY_ARE_EQUAL(result, 0777ull); - VERIFY_IS_TRUE(m_CopyPasteManager.TryOperandToULL(L"0777", OctBase, result)); - VERIFY_ARE_EQUAL(result, 0777ull); - VERIFY_IS_TRUE(m_CopyPasteManager.TryOperandToULL(L"1777777777777777777777", OctBase, result)); - VERIFY_ARE_EQUAL(result, 0xFFFF'FFFF'FFFF'FFFF); - VERIFY_IS_TRUE(m_CopyPasteManager.TryOperandToULL(L"01777777777777777777777", OctBase, result)); - VERIFY_ARE_EQUAL(result, 0xFFFF'FFFF'FFFF'FFFF); + Logger::WriteMessage(L"Verify TryOperandToULL NumberBase::OctBase conversion"); + result = CopyPasteManager::TryOperandToULL(L"777", NumberBase::OctBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 0777ull); + result = CopyPasteManager::TryOperandToULL(L"0777", NumberBase::OctBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 0777ull); + result = CopyPasteManager::TryOperandToULL(L"1777777777777777777777", NumberBase::OctBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 0xFFFF'FFFF'FFFF'FFFF); + result = CopyPasteManager::TryOperandToULL(L"01777777777777777777777", NumberBase::OctBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 0xFFFF'FFFF'FFFF'FFFF); - Logger::WriteMessage(L"Verify TryOperandToULL BinBase conversion"); - VERIFY_IS_TRUE(m_CopyPasteManager.TryOperandToULL(L"1111", BinBase, result)); - VERIFY_ARE_EQUAL(result, 0b1111ull); - VERIFY_IS_TRUE(m_CopyPasteManager.TryOperandToULL(L"0010", BinBase, result)); - VERIFY_ARE_EQUAL(result, 0b10ull); - VERIFY_IS_TRUE(m_CopyPasteManager.TryOperandToULL(L"1111111111111111111111111111111111111111111111111111111111111111", BinBase, result)); - VERIFY_ARE_EQUAL(result, 0xFFFF'FFFF'FFFF'FFFF); - VERIFY_IS_TRUE(m_CopyPasteManager.TryOperandToULL(L"01111111111111111111111111111111111111111111111111111111111111111", BinBase, result)); - VERIFY_ARE_EQUAL(result, 0xFFFF'FFFF'FFFF'FFFF); - - Logger::WriteMessage(L"Verify TryOperandToULL invalid numberBase defaults to DecBase"); - VERIFY_IS_TRUE(m_CopyPasteManager.TryOperandToULL(L"1234", 128, result)); - VERIFY_ARE_EQUAL(result, 1234ull); + Logger::WriteMessage(L"Verify TryOperandToULL NumberBase::BinBase conversion"); + result = CopyPasteManager::TryOperandToULL(L"1111", NumberBase::BinBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 0b1111ull); + result = CopyPasteManager::TryOperandToULL(L"0010", NumberBase::BinBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 0b10ull); + result = CopyPasteManager::TryOperandToULL(L"1111111111111111111111111111111111111111111111111111111111111111", NumberBase::BinBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 0xFFFF'FFFF'FFFF'FFFF); + result = CopyPasteManager::TryOperandToULL(L"01111111111111111111111111111111111111111111111111111111111111111", NumberBase::BinBase); + VERIFY_IS_NOT_NULL(result); + VERIFY_ARE_EQUAL(result->Value, 0xFFFF'FFFF'FFFF'FFFF); Logger::WriteMessage(L"Verify TryOperandToULL returns false when input is invalid or strtoull throws exceptions"); // Max values + 1 - VERIFY_IS_FALSE(m_CopyPasteManager.TryOperandToULL(L"0xFFFFFFFFFFFFFFFFF1", HexBase, result)); - VERIFY_IS_FALSE(m_CopyPasteManager.TryOperandToULL(L"18446744073709551616", DecBase, result)); - VERIFY_IS_FALSE(m_CopyPasteManager.TryOperandToULL(L"2000000000000000000000", OctBase, result)); - VERIFY_IS_FALSE(m_CopyPasteManager.TryOperandToULL(L"11111111111111111111111111111111111111111111111111111111111111111", BinBase, result)); + VERIFY_IS_NULL(CopyPasteManager::TryOperandToULL(L"0xFFFFFFFFFFFFFFFFF1", NumberBase::HexBase)); + VERIFY_IS_NULL(CopyPasteManager::TryOperandToULL(L"18446744073709551616", NumberBase::DecBase)); + VERIFY_IS_NULL(CopyPasteManager::TryOperandToULL(L"2000000000000000000000", NumberBase::OctBase)); + VERIFY_IS_NULL( + CopyPasteManager::TryOperandToULL(L"11111111111111111111111111111111111111111111111111111111111111111", NumberBase::BinBase)); // Invalid values/characters - VERIFY_IS_FALSE(m_CopyPasteManager.TryOperandToULL(L"-1", DecBase, result)); - VERIFY_IS_FALSE(m_CopyPasteManager.TryOperandToULL(L"5555", BinBase, result)); - VERIFY_IS_FALSE(m_CopyPasteManager.TryOperandToULL(L"xyz", BinBase, result)); + VERIFY_IS_NULL(CopyPasteManager::TryOperandToULL(L"-1", NumberBase::DecBase)); + VERIFY_IS_NULL(CopyPasteManager::TryOperandToULL(L"5555", NumberBase::BinBase)); + VERIFY_IS_NULL(CopyPasteManager::TryOperandToULL(L"xyz", NumberBase::BinBase)); }; TEST_METHOD(ValidateStandardScientificOperandLength) { - VERIFY_ARE_EQUAL(m_CopyPasteManager.StandardScientificOperandLength(L""), 0); - VERIFY_ARE_EQUAL(m_CopyPasteManager.StandardScientificOperandLength(L"0.2"), 1); - VERIFY_ARE_EQUAL(m_CopyPasteManager.StandardScientificOperandLength(L"1.2"), 2); - VERIFY_ARE_EQUAL(m_CopyPasteManager.StandardScientificOperandLength(L"0."), 0); - VERIFY_ARE_EQUAL(m_CopyPasteManager.StandardScientificOperandLength(L"12345"), 5); - VERIFY_ARE_EQUAL(m_CopyPasteManager.StandardScientificOperandLength(L"-12345"), 6); + VERIFY_ARE_EQUAL(m_CopyPasteManager->StandardScientificOperandLength(L""), 0); + VERIFY_ARE_EQUAL(m_CopyPasteManager->StandardScientificOperandLength(L"0.2"), 1); + VERIFY_ARE_EQUAL(m_CopyPasteManager->StandardScientificOperandLength(L"1.2"), 2); + VERIFY_ARE_EQUAL(m_CopyPasteManager->StandardScientificOperandLength(L"0."), 0); + VERIFY_ARE_EQUAL(m_CopyPasteManager->StandardScientificOperandLength(L"12345"), 5); + VERIFY_ARE_EQUAL(m_CopyPasteManager->StandardScientificOperandLength(L"-12345"), 6); }; TEST_METHOD(ValidateProgrammerOperandLength) { - VERIFY_ARE_EQUAL(m_CopyPasteManager.ProgrammerOperandLength(L"1001", BinBase), 4); - VERIFY_ARE_EQUAL(m_CopyPasteManager.ProgrammerOperandLength(L"1001b", BinBase), 4); - VERIFY_ARE_EQUAL(m_CopyPasteManager.ProgrammerOperandLength(L"1001B", BinBase), 4); - VERIFY_ARE_EQUAL(m_CopyPasteManager.ProgrammerOperandLength(L"0b1001", BinBase), 4); - VERIFY_ARE_EQUAL(m_CopyPasteManager.ProgrammerOperandLength(L"0B1001", BinBase), 4); - VERIFY_ARE_EQUAL(m_CopyPasteManager.ProgrammerOperandLength(L"0y1001", BinBase), 4); - VERIFY_ARE_EQUAL(m_CopyPasteManager.ProgrammerOperandLength(L"0Y1001", BinBase), 4); - VERIFY_ARE_EQUAL(m_CopyPasteManager.ProgrammerOperandLength(L"0b", BinBase), 1); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"1001", NumberBase::BinBase), 4); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"1001b", NumberBase::BinBase), 4); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"1001B", NumberBase::BinBase), 4); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0b1001", NumberBase::BinBase), 4); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0B1001", NumberBase::BinBase), 4); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0y1001", NumberBase::BinBase), 4); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0Y1001", NumberBase::BinBase), 4); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0b", NumberBase::BinBase), 1); - VERIFY_ARE_EQUAL(m_CopyPasteManager.ProgrammerOperandLength(L"123456", OctBase), 6); - VERIFY_ARE_EQUAL(m_CopyPasteManager.ProgrammerOperandLength(L"0t123456", OctBase), 6); - VERIFY_ARE_EQUAL(m_CopyPasteManager.ProgrammerOperandLength(L"0T123456", OctBase), 6); - VERIFY_ARE_EQUAL(m_CopyPasteManager.ProgrammerOperandLength(L"0o123456", OctBase), 6); - VERIFY_ARE_EQUAL(m_CopyPasteManager.ProgrammerOperandLength(L"0O123456", OctBase), 6); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"123456", NumberBase::OctBase), 6); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0t123456", NumberBase::OctBase), 6); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0T123456", NumberBase::OctBase), 6); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0o123456", NumberBase::OctBase), 6); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0O123456", NumberBase::OctBase), 6); - VERIFY_ARE_EQUAL(m_CopyPasteManager.ProgrammerOperandLength(L"", DecBase), 0); - VERIFY_ARE_EQUAL(m_CopyPasteManager.ProgrammerOperandLength(L"-", DecBase), 0); - VERIFY_ARE_EQUAL(m_CopyPasteManager.ProgrammerOperandLength(L"12345", DecBase), 5); - VERIFY_ARE_EQUAL(m_CopyPasteManager.ProgrammerOperandLength(L"-12345", DecBase), 5); - VERIFY_ARE_EQUAL(m_CopyPasteManager.ProgrammerOperandLength(L"0n12345", DecBase), 5); - VERIFY_ARE_EQUAL(m_CopyPasteManager.ProgrammerOperandLength(L"0N12345", DecBase), 5); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"", NumberBase::DecBase), 0); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"-", NumberBase::DecBase), 0); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"12345", NumberBase::DecBase), 5); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"-12345", NumberBase::DecBase), 5); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0n12345", NumberBase::DecBase), 5); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0N12345", NumberBase::DecBase), 5); - VERIFY_ARE_EQUAL(m_CopyPasteManager.ProgrammerOperandLength(L"123ABC", HexBase), 6); - VERIFY_ARE_EQUAL(m_CopyPasteManager.ProgrammerOperandLength(L"0x123ABC", HexBase), 6); - VERIFY_ARE_EQUAL(m_CopyPasteManager.ProgrammerOperandLength(L"0X123ABC", HexBase), 6); - VERIFY_ARE_EQUAL(m_CopyPasteManager.ProgrammerOperandLength(L"123ABCh", HexBase), 6); - VERIFY_ARE_EQUAL(m_CopyPasteManager.ProgrammerOperandLength(L"123ABCH", HexBase), 6); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"123ABC", NumberBase::HexBase), 6); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0x123ABC", NumberBase::HexBase), 6); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"0X123ABC", NumberBase::HexBase), 6); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"123ABCh", NumberBase::HexBase), 6); + VERIFY_ARE_EQUAL(m_CopyPasteManager->ProgrammerOperandLength(L"123ABCH", NumberBase::HexBase), 6); }; private: - CopyPasteManager m_CopyPasteManager; + CopyPasteManager ^ m_CopyPasteManager; String^ ValidateStandardPasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Standard, -1/*number base*/, BitLength::BitLengthUnknown); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Standard, NumberBase::Unknown, BitLength::BitLengthUnknown); } String^ ValidateScientificPasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Scientific, -1/*number base*/, BitLength::BitLengthUnknown); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Scientific, NumberBase::Unknown, BitLength::BitLengthUnknown); } String^ ValidateConverterPasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::None, CategoryGroupType::Converter, -1/*number base*/, BitLength::BitLengthUnknown); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::None, CategoryGroupType::Converter, NumberBase::Unknown, BitLength::BitLengthUnknown); } String^ ValidateProgrammerHexQwordPasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, HexBase/*number base*/, BitLength::BitLengthQWord); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, NumberBase::HexBase, BitLength::BitLengthQWord); } String^ ValidateProgrammerHexDwordPasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, HexBase/*number base*/, BitLength::BitLengthDWord); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, NumberBase::HexBase, BitLength::BitLengthDWord); } String^ ValidateProgrammerHexWordPasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, HexBase/*number base*/, BitLength::BitLengthWord); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, NumberBase::HexBase, BitLength::BitLengthWord); } String^ ValidateProgrammerHexBytePasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, HexBase/*number base*/, BitLength::BitLengthByte); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, NumberBase::HexBase, BitLength::BitLengthByte); } String^ ValidateProgrammerDecQwordPasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, DecBase/*number base*/, BitLength::BitLengthQWord); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, NumberBase::DecBase, BitLength::BitLengthQWord); } String^ ValidateProgrammerDecDwordPasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, DecBase/*number base*/, BitLength::BitLengthDWord); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, NumberBase::DecBase, BitLength::BitLengthDWord); } String^ ValidateProgrammerDecWordPasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, DecBase/*number base*/, BitLength::BitLengthWord); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, NumberBase::DecBase, BitLength::BitLengthWord); } String^ ValidateProgrammerDecBytePasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, DecBase/*number base*/, BitLength::BitLengthByte); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, NumberBase::DecBase, BitLength::BitLengthByte); } String^ ValidateProgrammerOctQwordPasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, OctBase/*number base*/, BitLength::BitLengthQWord); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, NumberBase::OctBase, BitLength::BitLengthQWord); } String^ ValidateProgrammerOctDwordPasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, OctBase/*number base*/, BitLength::BitLengthDWord); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, NumberBase::OctBase, BitLength::BitLengthDWord); } String^ ValidateProgrammerOctWordPasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, OctBase/*number base*/, BitLength::BitLengthWord); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, NumberBase::OctBase, BitLength::BitLengthWord); } String^ ValidateProgrammerOctBytePasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, OctBase/*number base*/, BitLength::BitLengthByte); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, NumberBase::OctBase, BitLength::BitLengthByte); } String^ ValidateProgrammerBinQwordPasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, BinBase/*number base*/, BitLength::BitLengthQWord); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, NumberBase::BinBase, BitLength::BitLengthQWord); } String^ ValidateProgrammerBinDwordPasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, BinBase/*number base*/, BitLength::BitLengthDWord); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, NumberBase::BinBase, BitLength::BitLengthDWord); } String^ ValidateProgrammerBinWordPasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, BinBase/*number base*/, BitLength::BitLengthWord); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, NumberBase::BinBase, BitLength::BitLengthWord); } String^ ValidateProgrammerBinBytePasteExpression(_In_ String^ pastedText) { - return m_CopyPasteManager.ValidatePasteExpression(pastedText, ViewMode::Programmer, BinBase/*number base*/, BitLength::BitLengthByte); + return m_CopyPasteManager->ValidatePasteExpression(pastedText, ViewMode::Programmer, NumberBase::BinBase, BitLength::BitLengthByte); } }; @@ -584,7 +727,8 @@ namespace CalculatorUnitTests void CopyPasteManagerTest::FunctionalCopyPasteTest() { // Doesn't have test where converter is involved. Will add such a test later. - StandardCalculatorViewModel ^ scvm = ref new StandardCalculatorViewModel(); + StandardCalculatorViewModel ^ scvm = nullptr; + scvm = ref new StandardCalculatorViewModel(); scvm->IsStandard = true; String ^ inputs[] = { L"123", L"12345", L"123+456", L"1,234", L"1 2 3", L"\n\r1,234\n", L"\n 1+\n2 ", L"1\"2" }; @@ -600,37 +744,38 @@ namespace CalculatorUnitTests void CopyPasteManagerTest::ValidateStandardPasteExpressionTest() { - String ^ positiveInput[] = { L"123", - L"+123", - L"-133", - L"12345.", - L"+12.34", - L"12.345", - L"012.034", - L"-23.032", - L"-.123", - L".1234", - L"012.012", - L"123+456", - L"123+-234", - L"123*-345", - L"123*4*-3", - L"123*+4*-3", - L"1,234", - L"1 2 3", - L"\n\r1,234\n", - L"\f\n1+2\t\r\v\x85", - L"\n 1+\n2 ", - L"1\"2", - L"1234567891234567" /*boundary condition <=16 digits*/, - L"2+2=", - L"2+2= " }; - String ^ negativeInput[] = { L"(123)+(456)", L"1.2e23" /*unsigned exponent*/, - L"12345e-23", L"abcdef", - L"xyz", L"ABab", - L"e+234", L"12345678912345678" /*boundary condition: greater than 16 digits*/, - L"SIN(2)", L"2+2==", - L"2=+2" }; + String ^ positiveInput[] = { + L"123", + L"+123", + L"-133", + L"12345.", + L"+12.34", + L"12.345", + L"012.034", + L"-23.032", + L"-.123", + L".1234", + L"012.012", + L"123+456", + L"123+-234", + L"123*-345", + L"123*4*-3", + L"123*+4*-3", + L"1,234", + L"1 2 3", + L"\n\r1,234\n", + L"\f\n1+2\t\r\v\x85", + L"\n 1+\n2 ", + L"1\"2", + L"1234567891234567" /*boundary condition <=16 digits*/, + L"2+2=", + L"2+2= ", + L"1.2e23", + L"12345e-23", + + }; + String ^ negativeInput[] = { L"(123)+(456)", L"abcdef", L"xyz", L"ABab", L"e+234", L"12345678912345678" /*boundary condition: greater than 16 digits*/, + L"SIN(2)", L"2+2==", L"2=+2", L"2%2", L"10^2" }; ASSERT_POSITIVE_TESTCASES(ValidateStandardPasteExpression, positiveInput); ASSERT_NEGATIVE_TESTCASES(ValidateStandardPasteExpression, negativeInput); @@ -668,15 +813,14 @@ namespace CalculatorUnitTests "-(432+3232)", "-(+(-3213)+(-2312))", "-(-(432+3232))", - L"1.2e23"/*unsigned exponent*/ }; - String ^ negativeInput[] = { L"abcdef", - L"xyz", - L"ABab", - L"e+234", - L"123456789123456781234567890123456" /*boundary condition: greater than 32 digits*/, - L"SIN(2)", - L"2+2==", - L"2=+2" }; + L"1.2e23" /*unsigned exponent*/, + L"12^2", + L"-12.12^-2", + L"61%99" + L"-6.1%99" }; + String + ^ negativeInput[] = { L"abcdef", L"xyz", L"ABab", L"e+234", L"123456789123456781234567890123456" /*boundary condition: greater than 32 digits*/, + L"SIN(2)", L"2+2==", L"2=+2" }; ASSERT_POSITIVE_TESTCASES(ValidateScientificPasteExpression, positiveInput); ASSERT_NEGATIVE_TESTCASES(ValidateScientificPasteExpression, negativeInput); @@ -710,7 +854,10 @@ namespace CalculatorUnitTests L"1234ul", L"1234ULL", L"2+2=", - L"2+2= " }; + L"2+2= ", + L"A4C3%12", + L"1233%AB", + L"FFC1%F2" }; String ^ qwordNegativeInput[] = { L"+123", L"1.23" /*floating number*/, L"1''2", @@ -906,7 +1053,8 @@ namespace CalculatorUnitTests L"1234ul", L"1234ULL", L"2+2=", - L"2+2= " }; + L"2+2= ", + L"823%21" }; String ^ qwordNegativeInput[] = { L"1.23", L"1''2", L"'123", @@ -1058,9 +1206,9 @@ namespace CalculatorUnitTests void CopyPasteManagerTest::ValidateProgrammerOctPasteExpressionTest() { - String ^ qwordPositiveInput[] = { L"123", L"123+456", L"1,234", L"1 2 3", L"1'2'3'4", L"1_2_3_4", L"\n\r1,234\n", L"\f\n1+2\t\r\v\x85", - L"\n 1+\n2 ", L"1\"2", L"(123)+(456)", L"0t1234", L"0T1234", L"0o1234", L"0O1234", L"1234u", - L"1234ul", L"1234ULL", L"2+2=", L"2+2= " }; + String ^ qwordPositiveInput[] = { L"123", L"123+456", L"1,234", L"1 2 3", L"1'2'3'4", L"1_2_3_4", L"\n\r1,234\n", L"\f\n1+2\t\r\v\x85", + L"\n 1+\n2 ", L"1\"2", L"(123)+(456)", L"0t1234", L"0T1234", L"0o1234", L"0O1234", L"1234u", + L"1234ul", L"1234ULL", L"2+2=", L"2+2= ", L"127%71" }; String ^ qwordNegativeInput[] = { L"+123", L"1.23", L"1''2", @@ -1084,7 +1232,8 @@ namespace CalculatorUnitTests L"1234uu", L"1234ulll", L"2+2==", - L"2=+2" }; + L"2=+2", + L"89%12" }; ASSERT_POSITIVE_TESTCASES(ValidateProgrammerOctQwordPasteExpression, qwordPositiveInput); ASSERT_NEGATIVE_TESTCASES(ValidateProgrammerOctQwordPasteExpression, qwordNegativeInput); @@ -1217,7 +1366,8 @@ namespace CalculatorUnitTests L"1111ULL", L"1010101010101010101010101011110110100100101010101001010101001010" /*boundary condition: max allowed digits 64*/, L"1+10=", - L"1+10= " }; + L"1+10= ", + L"1001%10" }; String ^ qwordNegativeInput[] = { L"+10101", L"1.01", diff --git a/src/CalculatorUnitTests/DateCalculatorUnitTests.cpp b/src/CalculatorUnitTests/DateCalculatorUnitTests.cpp index 9d100749..3d51ef81 100644 --- a/src/CalculatorUnitTests/DateCalculatorUnitTests.cpp +++ b/src/CalculatorUnitTests/DateCalculatorUnitTests.cpp @@ -27,8 +27,6 @@ namespace DateCalculationUnitTests const int c_subtractCases = 3; const int c_dateDiff = 14; - DateCalculationEngine m_DateCalcEngine(CalendarIdentifiers::Gregorian); - typedef struct { SYSTEMTIME startDate; @@ -45,10 +43,382 @@ namespace DateCalculationUnitTests DateTimeTestCase datetimeSubtractCase[c_subtractCases]; // Test Class - TEST_CLASS(DateCalculatorUnitTests){ public: TEST_CLASS_INITIALIZE(TestClassSetup){ /* Test Case Data */ + TEST_CLASS(DateCalculatorUnitTests) + { + static DateCalculationEngine ^ m_DateCalcEngine; - // Dates - DD.MM.YYYY - /*31.12.9999*/ date[0].wYear = 9999; + public: + TEST_CLASS_INITIALIZE(TestClassSetup) + { + m_DateCalcEngine = ref new DateCalculationEngine(CalendarIdentifiers::Gregorian); + + /* Test Case Data */ + + // Dates - DD.MM.YYYY + /*31.12.9999*/ + date[0].wYear = 9999; + date[0].wMonth = 12; + date[0].wDayOfWeek = 5; + date[0].wDay = 31; + date[0].wHour = 0; + date[0].wMinute = 0; + date[0].wSecond = 0; + date[0].wMilliseconds = 0; + /*30.12.9999*/ date[1].wYear = 9999; + date[1].wMonth = 12; + date[1].wDayOfWeek = 4; + date[1].wDay = 30; + date[1].wHour = 0; + date[1].wMinute = 0; + date[1].wSecond = 0; + date[1].wMilliseconds = 0; + /*31.12.9998*/ date[2].wYear = 9998; + date[2].wMonth = 12; + date[2].wDayOfWeek = 4; + date[2].wDay = 31; + date[2].wHour = 0; + date[2].wMinute = 0; + date[2].wSecond = 0; + date[2].wMilliseconds = 0; + /*01.01.1601*/ date[3].wYear = 1601; + date[3].wMonth = 1; + date[3].wDayOfWeek = 1; + date[3].wDay = 1; + date[3].wHour = 0; + date[3].wMinute = 0; + date[3].wSecond = 0; + date[3].wMilliseconds = 0; + /*02.01.1601*/ date[4].wYear = 1601; + date[4].wMonth = 1; + date[4].wDayOfWeek = 2; + date[4].wDay = 2; + date[4].wHour = 0; + date[4].wMinute = 0; + date[4].wSecond = 0; + date[4].wMilliseconds = 0; + /*10.05.2008*/ date[5].wYear = 2008; + date[5].wMonth = 5; + date[5].wDayOfWeek = 6; + date[5].wDay = 10; + date[5].wHour = 0; + date[5].wMinute = 0; + date[5].wSecond = 0; + date[5].wMilliseconds = 0; + /*10.03.2008*/ date[6].wYear = 2008; + date[6].wMonth = 3; + date[6].wDayOfWeek = 1; + date[6].wDay = 10; + date[6].wHour = 0; + date[6].wMinute = 0; + date[6].wSecond = 0; + date[6].wMilliseconds = 0; + /*29.02.2008*/ date[7].wYear = 2008; + date[7].wMonth = 2; + date[7].wDayOfWeek = 5; + date[7].wDay = 29; + date[7].wHour = 0; + date[7].wMinute = 0; + date[7].wSecond = 0; + date[7].wMilliseconds = 0; + /*28.02.2007*/ date[8].wYear = 2007; + date[8].wMonth = 2; + date[8].wDayOfWeek = 3; + date[8].wDay = 28; + date[8].wHour = 0; + date[8].wMinute = 0; + date[8].wSecond = 0; + date[8].wMilliseconds = 0; + /*10.03.2007*/ date[9].wYear = 2007; + date[9].wMonth = 3; + date[9].wDayOfWeek = 6; + date[9].wDay = 10; + date[9].wHour = 0; + date[9].wMinute = 0; + date[9].wSecond = 0; + date[9].wMilliseconds = 0; + /*10.05.2007*/ date[10].wYear = 2007; + date[10].wMonth = 5; + date[10].wDayOfWeek = 4; + date[10].wDay = 10; + date[10].wHour = 0; + date[10].wMinute = 0; + date[10].wSecond = 0; + date[10].wMilliseconds = 0; + /*29.01.2008*/ date[11].wYear = 2008; + date[11].wMonth = 1; + date[11].wDayOfWeek = 2; + date[11].wDay = 29; + date[11].wHour = 0; + date[11].wMinute = 0; + date[11].wSecond = 0; + date[11].wMilliseconds = 0; + /*28.01.2007*/ date[12].wYear = 2007; + date[12].wMonth = 1; + date[12].wDayOfWeek = 0; + date[12].wDay = 28; + date[12].wHour = 0; + date[12].wMinute = 0; + date[12].wSecond = 0; + date[12].wMilliseconds = 0; + /*31.01.2008*/ date[13].wYear = 2008; + date[13].wMonth = 1; + date[13].wDayOfWeek = 4; + date[13].wDay = 31; + date[13].wHour = 0; + date[13].wMinute = 0; + date[13].wSecond = 0; + date[13].wMilliseconds = 0; + /*31.03.2008*/ date[14].wYear = 2008; + date[14].wMonth = 3; + date[14].wDayOfWeek = 1; + date[14].wDay = 31; + date[14].wHour = 0; + date[14].wMinute = 0; + date[14].wSecond = 0; + date[14].wMilliseconds = 0; + + // Date Differences + dateDifference[0].year = 1; + dateDifference[0].month = 1; + dateDifference[1].month = 1; + dateDifference[1].day = 10; + dateDifference[2].day = 2; + /*date[2]-[0]*/ dateDifference[3].week = 52; + dateDifference[3].day = 1; + /*date[2]-[0]*/ dateDifference[4].year = 1; + dateDifference[5].day = 365; + dateDifference[6].month = 1; + dateDifference[7].month = 1; + dateDifference[7].day = 2; + dateDifference[8].day = 31; + dateDifference[9].month = 11; + dateDifference[9].day = 1; + dateDifference[10].year = 8398; + dateDifference[10].month = 11; + dateDifference[10].day = 30; + dateDifference[11].year = 2008; + dateDifference[12].year = 7991; + dateDifference[12].month = 11; + dateDifference[13].week = 416998; + dateDifference[13].day = 1; + + /* Test Cases */ + + // Date Difference test cases + datetimeDifftest[0].startDate = date[0]; + datetimeDifftest[0].endDate = date[3]; + datetimeDifftest[0].dateDiff = dateDifference[10]; + datetimeDifftest[1].startDate = date[0]; + datetimeDifftest[1].endDate = date[2]; + datetimeDifftest[1].dateDiff = dateDifference[5]; + datetimeDifftest[2].startDate = date[0]; + datetimeDifftest[2].endDate = date[2]; + datetimeDifftest[2].dateDiff = dateDifference[4]; + datetimeDifftest[3].startDate = date[0]; + datetimeDifftest[3].endDate = date[2]; + datetimeDifftest[3].dateDiff = dateDifference[3]; + datetimeDifftest[4].startDate = date[14]; + datetimeDifftest[4].endDate = date[7]; + datetimeDifftest[4].dateDiff = dateDifference[7]; + datetimeDifftest[5].startDate = date[14]; + datetimeDifftest[5].endDate = date[7]; + datetimeDifftest[5].dateDiff = dateDifference[8]; + datetimeDifftest[6].startDate = date[11]; + datetimeDifftest[6].endDate = date[8]; + datetimeDifftest[6].dateDiff = dateDifference[9]; + datetimeDifftest[7].startDate = date[13]; + datetimeDifftest[7].endDate = date[0]; + datetimeDifftest[7].dateDiff = dateDifference[12]; + datetimeDifftest[8].startDate = date[13]; + datetimeDifftest[8].endDate = date[0]; + datetimeDifftest[8].dateDiff = dateDifference[13]; + + // Date Add Out of Bound test cases (Negative tests) + /*OutofBound*/ datetimeBoundAdd[0].startDate = date[1]; + datetimeBoundAdd[0].endDate = date[0]; + datetimeBoundAdd[0].dateDiff = dateDifference[2]; // on Add date[0] not used + /*OutofBound*/ datetimeBoundAdd[1].startDate = date[2]; + datetimeBoundAdd[1].endDate = date[0]; + datetimeBoundAdd[1].dateDiff = dateDifference[11]; // on Add date[0] not used + + // Date Subtract Out of Bound test cases (Negative tests) + /*OutofBound*/ datetimeBoundSubtract[0].startDate = date[3]; + datetimeBoundSubtract[0].endDate = date[0]; + datetimeBoundSubtract[0].dateDiff = dateDifference[2]; // on subtract date[0] not used + /*OutofBound*/ datetimeBoundSubtract[1].startDate = date[14]; + datetimeBoundSubtract[1].endDate = date[0]; + datetimeBoundSubtract[1].dateDiff = dateDifference[11]; // on subtract date[0] not used + + // Date Add test cases (Positive tests) + datetimeAddCase[0].startDate = date[13]; + datetimeAddCase[0].endDate = date[7]; + datetimeAddCase[0].dateDiff = dateDifference[6]; // add + datetimeAddCase[1].startDate = date[14]; + datetimeAddCase[1].endDate = date[5]; + datetimeAddCase[1].dateDiff = dateDifference[1]; // add + datetimeAddCase[2].startDate = date[13]; + datetimeAddCase[2].endDate = date[6]; + datetimeAddCase[2].dateDiff = dateDifference[1]; // add + + // Date Subtract test cases (Positive tests) + datetimeSubtractCase[0].startDate = date[14]; + datetimeSubtractCase[0].endDate = date[7]; + datetimeSubtractCase[0].dateDiff = dateDifference[6]; // subtract + datetimeSubtractCase[1].startDate = date[6]; + datetimeSubtractCase[1].endDate = date[11]; + datetimeSubtractCase[1].dateDiff = dateDifference[1]; // subtract + datetimeSubtractCase[2].startDate = date[9]; + datetimeSubtractCase[2].endDate = date[12]; + datetimeSubtractCase[2].dateDiff = dateDifference[1]; // subtract + } + + /* Duration Between Two Date Tests -- Timediff obtained after calculation should be checked to be identical */ + TEST_METHOD(TestDateDiff) + { + // TODO - MSFT 10331900, fix this test + + // for (int testIndex = 0; testIndex < c_diffTestCase; testIndex++) + //{ + // DateDifference diff; + // DateUnit dateOutputFormat; + + // switch (testIndex) + // { + // case 0: + // case 2: + // dateOutputFormat = DateUnit::Year | DateUnit::Month | DateUnit::Day; + // break; + // case 1: + // dateOutputFormat = DateUnit::Day; + // break; + // case 3: + // case 8: + // dateOutputFormat = DateUnit::Week | DateUnit::Day; + // break; + // case 7: + // dateOutputFormat = DateUnit::Year | DateUnit::Month | DateUnit::Day; + // break; + // case 4: + // case 6: + // dateOutputFormat = DateUnit::Month | DateUnit::Day; + // break; + // case 5: + // dateOutputFormat = DateUnit::Day; + // break; + // } + + // // Calculate the difference + // m_DateCalcEngine->TryGetDateDifference(DateUtils::SystemTimeToDateTime(datetimeDifftest[testIndex].startDate), + // DateUtils::SystemTimeToDateTime(datetimeDifftest[testIndex].endDate), dateOutputFormat, &diff); + + // // Assert for the result + // bool areIdentical = true; + // if (diff.year != datetimeDifftest[testIndex].dateDiff.year || + // diff.month != datetimeDifftest[testIndex].dateDiff.month || + // diff.week != datetimeDifftest[testIndex].dateDiff.week || + // diff.day != datetimeDifftest[testIndex].dateDiff.day) + // { + // areIdentical = false; + // } + + // VERIFY_IS_TRUE(areIdentical); + //} + } + + /*Add Out of bound Tests*/ + TEST_METHOD(TestAddOob) + { + // TODO - MSFT 10331900, fix this test + + // for (int testIndex = 0; testIndex< c_numAddOobDate; testIndex++) + //{ + // DateTime endDate; + + // // Add Duration + // bool isValid = m_DateCalcEngine->AddDuration(DateUtils::SystemTimeToDateTime(datetimeBoundAdd[testIndex].startDate), + // datetimeBoundAdd[testIndex].dateDiff, &endDate); + + // // Assert for the result + // VERIFY_IS_FALSE(isValid); + //} + } + + /*Subtract Out of bound Tests*/ + TEST_METHOD(TestSubtractOob) + { + for (int testIndex = 0; testIndex < c_numSubtractOobDate; testIndex++) + { + // Subtract Duration + auto endDate = m_DateCalcEngine->SubtractDuration( + DateUtils::SystemTimeToDateTime(datetimeBoundSubtract[testIndex].startDate), datetimeBoundSubtract[testIndex].dateDiff); + + // Assert for the result + VERIFY_IS_NULL(endDate); + } + } + + // Add Tests + TEST_METHOD(TestAddition) + { + // TODO - MSFT 10331900, fix this test + + // for (int testIndex = 0; testIndex < c_addCases; testIndex++) + //{ + // DateTime endDate; + + // // Add Duration + // bool isValid = m_DateCalcEngine->AddDuration(DateUtils::SystemTimeToDateTime(datetimeAddCase[testIndex].startDate), + // datetimeAddCase[testIndex].dateDiff, &endDate); + + // // Assert for the result + // VERIFY_IS_TRUE(isValid); + + // SYSTEMTIME systemTime = DateUtils::DateTimeToSystemTime(endDate); + // if (systemTime.wYear != datetimeAddCase[testIndex].endDate.wYear || + // systemTime.wMonth != datetimeAddCase[testIndex].endDate.wMonth || + // systemTime.wDay != datetimeAddCase[testIndex].endDate.wDay || + // systemTime.wDayOfWeek != datetimeAddCase[testIndex].endDate.wDayOfWeek) + // { + // isValid = false; + // } + + // VERIFY_IS_TRUE(isValid); + //} + } + + // Subtract Tests + TEST_METHOD(TestSubtraction) + { + // TODO - MSFT 10331900, fix this test + + // for (int testIndex = 0; testIndex < c_subtractCases; testIndex++) + //{ + // DateTime endDate; + + // // Subtract Duration + // bool isValid = m_DateCalcEngine->SubtractDuration(DateUtils::SystemTimeToDateTime(datetimeSubtractCase[testIndex].startDate), + // datetimeSubtractCase[testIndex].dateDiff, &endDate); + + // // assert for the result + // VERIFY_IS_TRUE(isValid); + + // SYSTEMTIME systemTime = DateUtils::DateTimeToSystemTime(endDate); + // if (systemTime.wYear != datetimeSubtractCase[testIndex].endDate.wYear || + // systemTime.wMonth != datetimeSubtractCase[testIndex].endDate.wMonth || + // systemTime.wDay != datetimeSubtractCase[testIndex].endDate.wDay || + // systemTime.wDayOfWeek != datetimeSubtractCase[testIndex].endDate.wDayOfWeek) + // { + // isValid = false; + // } + + // VERIFY_IS_TRUE(isValid); + //} + } + }; + + TEST_CLASS(DateCalculatorViewModelTests){ public: TEST_CLASS_INITIALIZE(TestClassSetup){ /* Test Case Data */ + // Dates - DD.MM.YYYY + /*31.12.9999*/ date[0].wYear = 9999; date[0].wMonth = 12; date[0].wDayOfWeek = 5; date[0].wDay = 31; @@ -264,374 +634,6 @@ namespace DateCalculationUnitTests datetimeSubtractCase[2].dateDiff = dateDifference[1]; // subtract } -/* Duration Between Two Date Tests -- Timediff obtained after calculation should be checked to be identical */ -TEST_METHOD(TestDateDiff) -{ - // TODO - MSFT 10331900, fix this test - - // for (int testIndex = 0; testIndex < c_diffTestCase; testIndex++) - //{ - // DateDifference diff; - // DateUnit dateOutputFormat; - - // switch (testIndex) - // { - // case 0: - // case 2: - // dateOutputFormat = DateUnit::Year | DateUnit::Month | DateUnit::Day; - // break; - // case 1: - // dateOutputFormat = DateUnit::Day; - // break; - // case 3: - // case 8: - // dateOutputFormat = DateUnit::Week | DateUnit::Day; - // break; - // case 7: - // dateOutputFormat = DateUnit::Year | DateUnit::Month | DateUnit::Day; - // break; - // case 4: - // case 6: - // dateOutputFormat = DateUnit::Month | DateUnit::Day; - // break; - // case 5: - // dateOutputFormat = DateUnit::Day; - // break; - // } - - // // Calculate the difference - // m_DateCalcEngine.TryGetDateDifference(DateUtils::SystemTimeToDateTime(datetimeDifftest[testIndex].startDate), - // DateUtils::SystemTimeToDateTime(datetimeDifftest[testIndex].endDate), dateOutputFormat, &diff); - - // // Assert for the result - // bool areIdentical = true; - // if (diff.year != datetimeDifftest[testIndex].dateDiff.year || - // diff.month != datetimeDifftest[testIndex].dateDiff.month || - // diff.week != datetimeDifftest[testIndex].dateDiff.week || - // diff.day != datetimeDifftest[testIndex].dateDiff.day) - // { - // areIdentical = false; - // } - - // VERIFY_IS_TRUE(areIdentical); - //} -} - -/*Add Out of bound Tests*/ -TEST_METHOD(TestAddOob) -{ - // TODO - MSFT 10331900, fix this test - - // for (int testIndex = 0; testIndex< c_numAddOobDate; testIndex++) - //{ - // DateTime endDate; - - // // Add Duration - // bool isValid = m_DateCalcEngine.AddDuration(DateUtils::SystemTimeToDateTime(datetimeBoundAdd[testIndex].startDate), - // datetimeBoundAdd[testIndex].dateDiff, &endDate); - - // // Assert for the result - // VERIFY_IS_FALSE(isValid); - //} -} - -/*Subtract Out of bound Tests*/ -TEST_METHOD(TestSubtractOob) -{ - for (int testIndex = 0; testIndex < c_numSubtractOobDate; testIndex++) - { - DateTime endDate; - - // Subtract Duration - bool isValid = m_DateCalcEngine.SubtractDuration( - DateUtils::SystemTimeToDateTime(datetimeBoundSubtract[testIndex].startDate), datetimeBoundSubtract[testIndex].dateDiff, &endDate); - - // Assert for the result - VERIFY_IS_FALSE(isValid); - } -} - -// Add Tests -TEST_METHOD(TestAddition) -{ - // TODO - MSFT 10331900, fix this test - - // for (int testIndex = 0; testIndex < c_addCases; testIndex++) - //{ - // DateTime endDate; - - // // Add Duration - // bool isValid = m_DateCalcEngine.AddDuration(DateUtils::SystemTimeToDateTime(datetimeAddCase[testIndex].startDate), - // datetimeAddCase[testIndex].dateDiff, &endDate); - - // // Assert for the result - // VERIFY_IS_TRUE(isValid); - - // SYSTEMTIME systemTime = DateUtils::DateTimeToSystemTime(endDate); - // if (systemTime.wYear != datetimeAddCase[testIndex].endDate.wYear || - // systemTime.wMonth != datetimeAddCase[testIndex].endDate.wMonth || - // systemTime.wDay != datetimeAddCase[testIndex].endDate.wDay || - // systemTime.wDayOfWeek != datetimeAddCase[testIndex].endDate.wDayOfWeek) - // { - // isValid = false; - // } - - // VERIFY_IS_TRUE(isValid); - //} -} - -// Subtract Tests -TEST_METHOD(TestSubtraction) -{ - // TODO - MSFT 10331900, fix this test - - // for (int testIndex = 0; testIndex < c_subtractCases; testIndex++) - //{ - // DateTime endDate; - - // // Subtract Duration - // bool isValid = m_DateCalcEngine.SubtractDuration(DateUtils::SystemTimeToDateTime(datetimeSubtractCase[testIndex].startDate), - // datetimeSubtractCase[testIndex].dateDiff, &endDate); - - // // assert for the result - // VERIFY_IS_TRUE(isValid); - - // SYSTEMTIME systemTime = DateUtils::DateTimeToSystemTime(endDate); - // if (systemTime.wYear != datetimeSubtractCase[testIndex].endDate.wYear || - // systemTime.wMonth != datetimeSubtractCase[testIndex].endDate.wMonth || - // systemTime.wDay != datetimeSubtractCase[testIndex].endDate.wDay || - // systemTime.wDayOfWeek != datetimeSubtractCase[testIndex].endDate.wDayOfWeek) - // { - // isValid = false; - // } - - // VERIFY_IS_TRUE(isValid); - //} -} - -private: -} -; - -TEST_CLASS(DateCalculatorViewModelTests){ public: TEST_CLASS_INITIALIZE(TestClassSetup){ /* Test Case Data */ - - // Dates - DD.MM.YYYY - /*31.12.9999*/ date[0].wYear = 9999; -date[0].wMonth = 12; -date[0].wDayOfWeek = 5; -date[0].wDay = 31; -date[0].wHour = 0; -date[0].wMinute = 0; -date[0].wSecond = 0; -date[0].wMilliseconds = 0; -/*30.12.9999*/ date[1].wYear = 9999; -date[1].wMonth = 12; -date[1].wDayOfWeek = 4; -date[1].wDay = 30; -date[1].wHour = 0; -date[1].wMinute = 0; -date[1].wSecond = 0; -date[1].wMilliseconds = 0; -/*31.12.9998*/ date[2].wYear = 9998; -date[2].wMonth = 12; -date[2].wDayOfWeek = 4; -date[2].wDay = 31; -date[2].wHour = 0; -date[2].wMinute = 0; -date[2].wSecond = 0; -date[2].wMilliseconds = 0; -/*01.01.1601*/ date[3].wYear = 1601; -date[3].wMonth = 1; -date[3].wDayOfWeek = 1; -date[3].wDay = 1; -date[3].wHour = 0; -date[3].wMinute = 0; -date[3].wSecond = 0; -date[3].wMilliseconds = 0; -/*02.01.1601*/ date[4].wYear = 1601; -date[4].wMonth = 1; -date[4].wDayOfWeek = 2; -date[4].wDay = 2; -date[4].wHour = 0; -date[4].wMinute = 0; -date[4].wSecond = 0; -date[4].wMilliseconds = 0; -/*10.05.2008*/ date[5].wYear = 2008; -date[5].wMonth = 5; -date[5].wDayOfWeek = 6; -date[5].wDay = 10; -date[5].wHour = 0; -date[5].wMinute = 0; -date[5].wSecond = 0; -date[5].wMilliseconds = 0; -/*10.03.2008*/ date[6].wYear = 2008; -date[6].wMonth = 3; -date[6].wDayOfWeek = 1; -date[6].wDay = 10; -date[6].wHour = 0; -date[6].wMinute = 0; -date[6].wSecond = 0; -date[6].wMilliseconds = 0; -/*29.02.2008*/ date[7].wYear = 2008; -date[7].wMonth = 2; -date[7].wDayOfWeek = 5; -date[7].wDay = 29; -date[7].wHour = 0; -date[7].wMinute = 0; -date[7].wSecond = 0; -date[7].wMilliseconds = 0; -/*28.02.2007*/ date[8].wYear = 2007; -date[8].wMonth = 2; -date[8].wDayOfWeek = 3; -date[8].wDay = 28; -date[8].wHour = 0; -date[8].wMinute = 0; -date[8].wSecond = 0; -date[8].wMilliseconds = 0; -/*10.03.2007*/ date[9].wYear = 2007; -date[9].wMonth = 3; -date[9].wDayOfWeek = 6; -date[9].wDay = 10; -date[9].wHour = 0; -date[9].wMinute = 0; -date[9].wSecond = 0; -date[9].wMilliseconds = 0; -/*10.05.2007*/ date[10].wYear = 2007; -date[10].wMonth = 5; -date[10].wDayOfWeek = 4; -date[10].wDay = 10; -date[10].wHour = 0; -date[10].wMinute = 0; -date[10].wSecond = 0; -date[10].wMilliseconds = 0; -/*29.01.2008*/ date[11].wYear = 2008; -date[11].wMonth = 1; -date[11].wDayOfWeek = 2; -date[11].wDay = 29; -date[11].wHour = 0; -date[11].wMinute = 0; -date[11].wSecond = 0; -date[11].wMilliseconds = 0; -/*28.01.2007*/ date[12].wYear = 2007; -date[12].wMonth = 1; -date[12].wDayOfWeek = 0; -date[12].wDay = 28; -date[12].wHour = 0; -date[12].wMinute = 0; -date[12].wSecond = 0; -date[12].wMilliseconds = 0; -/*31.01.2008*/ date[13].wYear = 2008; -date[13].wMonth = 1; -date[13].wDayOfWeek = 4; -date[13].wDay = 31; -date[13].wHour = 0; -date[13].wMinute = 0; -date[13].wSecond = 0; -date[13].wMilliseconds = 0; -/*31.03.2008*/ date[14].wYear = 2008; -date[14].wMonth = 3; -date[14].wDayOfWeek = 1; -date[14].wDay = 31; -date[14].wHour = 0; -date[14].wMinute = 0; -date[14].wSecond = 0; -date[14].wMilliseconds = 0; - -// Date Differences -dateDifference[0].year = 1; -dateDifference[0].month = 1; -dateDifference[1].month = 1; -dateDifference[1].day = 10; -dateDifference[2].day = 2; -/*date[2]-[0]*/ dateDifference[3].week = 52; -dateDifference[3].day = 1; -/*date[2]-[0]*/ dateDifference[4].year = 1; -dateDifference[5].day = 365; -dateDifference[6].month = 1; -dateDifference[7].month = 1; -dateDifference[7].day = 2; -dateDifference[8].day = 31; -dateDifference[9].month = 11; -dateDifference[9].day = 1; -dateDifference[10].year = 8398; -dateDifference[10].month = 11; -dateDifference[10].day = 30; -dateDifference[11].year = 2008; -dateDifference[12].year = 7991; -dateDifference[12].month = 11; -dateDifference[13].week = 416998; -dateDifference[13].day = 1; - -/* Test Cases */ - -// Date Difference test cases -datetimeDifftest[0].startDate = date[0]; -datetimeDifftest[0].endDate = date[3]; -datetimeDifftest[0].dateDiff = dateDifference[10]; -datetimeDifftest[1].startDate = date[0]; -datetimeDifftest[1].endDate = date[2]; -datetimeDifftest[1].dateDiff = dateDifference[5]; -datetimeDifftest[2].startDate = date[0]; -datetimeDifftest[2].endDate = date[2]; -datetimeDifftest[2].dateDiff = dateDifference[4]; -datetimeDifftest[3].startDate = date[0]; -datetimeDifftest[3].endDate = date[2]; -datetimeDifftest[3].dateDiff = dateDifference[3]; -datetimeDifftest[4].startDate = date[14]; -datetimeDifftest[4].endDate = date[7]; -datetimeDifftest[4].dateDiff = dateDifference[7]; -datetimeDifftest[5].startDate = date[14]; -datetimeDifftest[5].endDate = date[7]; -datetimeDifftest[5].dateDiff = dateDifference[8]; -datetimeDifftest[6].startDate = date[11]; -datetimeDifftest[6].endDate = date[8]; -datetimeDifftest[6].dateDiff = dateDifference[9]; -datetimeDifftest[7].startDate = date[13]; -datetimeDifftest[7].endDate = date[0]; -datetimeDifftest[7].dateDiff = dateDifference[12]; -datetimeDifftest[8].startDate = date[13]; -datetimeDifftest[8].endDate = date[0]; -datetimeDifftest[8].dateDiff = dateDifference[13]; - -// Date Add Out of Bound test cases (Negative tests) -/*OutofBound*/ datetimeBoundAdd[0].startDate = date[1]; -datetimeBoundAdd[0].endDate = date[0]; -datetimeBoundAdd[0].dateDiff = dateDifference[2]; // on Add date[0] not used -/*OutofBound*/ datetimeBoundAdd[1].startDate = date[2]; -datetimeBoundAdd[1].endDate = date[0]; -datetimeBoundAdd[1].dateDiff = dateDifference[11]; // on Add date[0] not used - -// Date Subtract Out of Bound test cases (Negative tests) -/*OutofBound*/ datetimeBoundSubtract[0].startDate = date[3]; -datetimeBoundSubtract[0].endDate = date[0]; -datetimeBoundSubtract[0].dateDiff = dateDifference[2]; // on subtract date[0] not used -/*OutofBound*/ datetimeBoundSubtract[1].startDate = date[14]; -datetimeBoundSubtract[1].endDate = date[0]; -datetimeBoundSubtract[1].dateDiff = dateDifference[11]; // on subtract date[0] not used - -// Date Add test cases (Positive tests) -datetimeAddCase[0].startDate = date[13]; -datetimeAddCase[0].endDate = date[7]; -datetimeAddCase[0].dateDiff = dateDifference[6]; // add -datetimeAddCase[1].startDate = date[14]; -datetimeAddCase[1].endDate = date[5]; -datetimeAddCase[1].dateDiff = dateDifference[1]; // add -datetimeAddCase[2].startDate = date[13]; -datetimeAddCase[2].endDate = date[6]; -datetimeAddCase[2].dateDiff = dateDifference[1]; // add - -// Date Subtract test cases (Positive tests) -datetimeSubtractCase[0].startDate = date[14]; -datetimeSubtractCase[0].endDate = date[7]; -datetimeSubtractCase[0].dateDiff = dateDifference[6]; // subtract -datetimeSubtractCase[1].startDate = date[6]; -datetimeSubtractCase[1].endDate = date[11]; -datetimeSubtractCase[1].dateDiff = dateDifference[1]; // subtract -datetimeSubtractCase[2].startDate = date[9]; -datetimeSubtractCase[2].endDate = date[12]; -datetimeSubtractCase[2].dateDiff = dateDifference[1]; // subtract -} - TEST_METHOD(DateCalcViewModelInitializationTest) { auto viewModel = ref new DateCalculatorViewModel(); @@ -683,7 +685,6 @@ TEST_METHOD(DateCalcViewModelAddSubtractInitTest) TEST_METHOD(DateCalcViewModelDateDiffDaylightSavingTimeTest) { auto viewModel = ref new DateCalculatorViewModel(); - viewModel->IsDateDiffMode = true; VERIFY_IS_TRUE(viewModel->IsDateDiffMode); @@ -922,8 +923,6 @@ TEST_METHOD(DateCalcViewModelDateDiffFromDateHigherThanToDate) // contains the DayOfWeek, Day, Month, and Year TEST_METHOD(DateCalcViewModelAddSubtractResultAutomationNameTest) { - auto viewModel = ref new DateCalculatorViewModel(); - auto cal = ref new Calendar(); cal->Year = 2007; cal->Month = 5; @@ -934,6 +933,8 @@ TEST_METHOD(DateCalcViewModelAddSubtractResultAutomationNameTest) cal->Second = 0; DateTime startDate = cal->GetDateTime(); + auto viewModel = ref new DateCalculatorViewModel(); + viewModel->StartDate = startDate; viewModel->IsDateDiffMode = false; @@ -955,7 +956,7 @@ TEST_METHOD(DateCalcViewModelAddSubtractResultAutomationNameTest) TEST_METHOD(JaEraTransitionAddition) { - auto viewModel = make_unique(CalendarIdentifiers::Japanese); + auto engine = ref new DateCalculationEngine(CalendarIdentifiers::Japanese); auto cal = ref new Calendar(); // The Showa period ended in Jan 1989. @@ -973,10 +974,9 @@ TEST_METHOD(JaEraTransitionAddition) DateDifference yearDuration; yearDuration.year = 1; - DateTime actualYearResult; - viewModel->AddDuration(startTime, yearDuration, &actualYearResult); + auto actualYearResult = engine->AddDuration(startTime, yearDuration); - VERIFY_ARE_EQUAL(expectedYearResult.UniversalTime, actualYearResult.UniversalTime); + VERIFY_ARE_EQUAL(expectedYearResult.UniversalTime, actualYearResult->Value.UniversalTime); cal->Year = 1989; cal->Month = 2; @@ -987,15 +987,14 @@ TEST_METHOD(JaEraTransitionAddition) DateDifference monthDuration; monthDuration.month = 1; - DateTime actualMonthResult; - viewModel->AddDuration(startTime, monthDuration, &actualMonthResult); + auto actualMonthResult = engine->AddDuration(startTime, monthDuration); - VERIFY_ARE_EQUAL(expectedMonthResult.UniversalTime, actualMonthResult.UniversalTime); + VERIFY_ARE_EQUAL(expectedMonthResult.UniversalTime, actualMonthResult->Value.UniversalTime); } TEST_METHOD(JaEraTransitionSubtraction) { - auto viewModel = make_unique(CalendarIdentifiers::Japanese); + auto engine = ref new DateCalculationEngine(CalendarIdentifiers::Japanese); auto cal = ref new Calendar(); // The Showa period ended in Jan 1989. @@ -1013,10 +1012,9 @@ TEST_METHOD(JaEraTransitionSubtraction) DateDifference yearDuration; yearDuration.year = 1; - DateTime actualYearResult; - viewModel->SubtractDuration(startTime, yearDuration, &actualYearResult); + auto actualYearResult = engine->SubtractDuration(startTime, yearDuration); - VERIFY_ARE_EQUAL(expectedYearResult.UniversalTime, actualYearResult.UniversalTime); + VERIFY_ARE_EQUAL(expectedYearResult.UniversalTime, actualYearResult->Value.UniversalTime); cal->Year = 1989; cal->Month = 1; @@ -1027,15 +1025,14 @@ TEST_METHOD(JaEraTransitionSubtraction) DateDifference monthDuration; monthDuration.month = 1; - DateTime actualMonthResult; - viewModel->SubtractDuration(startTime, monthDuration, &actualMonthResult); + auto actualMonthResult = engine->SubtractDuration(startTime, monthDuration); - VERIFY_ARE_EQUAL(expectedMonthResult.UniversalTime, actualMonthResult.UniversalTime); + VERIFY_ARE_EQUAL(expectedMonthResult.UniversalTime, actualMonthResult->Value.UniversalTime); } TEST_METHOD(JaEraTransitionDifference) { - auto viewModel = make_unique(CalendarIdentifiers::Japanese); + auto engine = ref new DateCalculationEngine(CalendarIdentifiers::Japanese); auto cal = ref new Calendar(); // The Showa period ended in Jan 8, 1989. Pick 2 days across that boundary @@ -1049,10 +1046,12 @@ TEST_METHOD(JaEraTransitionDifference) cal->Day = 20; auto endTime = cal->GetDateTime(); - DateDifference diff; - VERIFY_IS_TRUE(viewModel->TryGetDateDifference(startTime, endTime, DateUnit::Day, &diff)); - VERIFY_ARE_EQUAL(diff.day, 19); + auto diff = engine->TryGetDateDifference(startTime, endTime, DateUnit::Day); + VERIFY_IS_NOT_NULL(diff); + VERIFY_ARE_EQUAL(diff->Value.day, 19); } } ; + +DateCalculationEngine ^ DateCalculatorUnitTests::m_DateCalcEngine; } diff --git a/src/CalculatorUnitTests/Helpers.h b/src/CalculatorUnitTests/Helpers.h index 01b449e9..672dd556 100644 --- a/src/CalculatorUnitTests/Helpers.h +++ b/src/CalculatorUnitTests/Helpers.h @@ -1,10 +1,11 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" #pragma once #include "CalcViewModel/Common/CalculatorButtonUser.h" +#include namespace CalculatorUnitTests { @@ -95,3 +96,15 @@ namespace CalculatorUnitTests { \ Assert::IsTrue(__expectedGreater >= __expectedLess, __VA_ARGS__); \ } + +template +void VERIFY_VECTORS_ARE_EQUAL(Windows::Foundation::Collections::IVector ^ vecA, Windows::Foundation::Collections::IVector ^ vecB, ...) +{ + if (vecA->Size != vecB->Size) + Assert::Fail(); + + for (unsigned int i = 0; i < vecA->Size; ++i) + { + VERIFY_ARE_EQUAL(vecA->GetAt(i), vecB->GetAt(i), __VA_ARGS__); + } +}; diff --git a/src/CalculatorUnitTests/HistoryTests.cpp b/src/CalculatorUnitTests/HistoryTests.cpp index f4713c12..becf1b4b 100644 --- a/src/CalculatorUnitTests/HistoryTests.cpp +++ b/src/CalculatorUnitTests/HistoryTests.cpp @@ -75,7 +75,7 @@ namespace CalculatorFunctionalTests { m_standardViewModel->SetHistoryExpressionDisplay(e->GetTokens(), e->GetCommands()); m_standardViewModel->SetExpressionDisplay(e->GetTokens(), e->GetCommands()); - m_standardViewModel->SetPrimaryDisplay(e->Result->Data(), false /*IsError*/); + m_standardViewModel->SetPrimaryDisplay(e->Result, false /*IsError*/); m_standardViewModel->IsFToEEnabled = false; } diff --git a/src/CalculatorUnitTests/NavCategoryUnitTests.cpp b/src/CalculatorUnitTests/NavCategoryUnitTests.cpp index fe583b79..72927c1f 100644 --- a/src/CalculatorUnitTests/NavCategoryUnitTests.cpp +++ b/src/CalculatorUnitTests/NavCategoryUnitTests.cpp @@ -257,9 +257,26 @@ namespace CalculatorUnitTests void NavCategoryUnitTests::GetIndex() { // Index is the 0-based ordering of modes - vector orderedModes = { ViewMode::Standard, ViewMode::Scientific, ViewMode::Programmer, ViewMode::Date, ViewMode::Graphing, - ViewMode::Currency, ViewMode::Area, ViewMode::Speed, ViewMode::Time, ViewMode::Power, - ViewMode::Data, ViewMode::Pressure, ViewMode::Angle }; + ViewMode orderedModes[] = { + ViewMode::Standard, + ViewMode::Scientific, + ViewMode::Programmer, + ViewMode::Date, + ViewMode::Graphing, + ViewMode::Currency, + ViewMode::Volume, + ViewMode::Length, + ViewMode::Weight, + ViewMode::Temperature, + ViewMode::Energy, + ViewMode::Area, + ViewMode::Speed, + ViewMode::Time, + ViewMode::Power, + ViewMode::Data, + ViewMode::Pressure, + ViewMode::Angle + }; auto orderedModesSize = size(orderedModes); for (size_t index = 0; index < orderedModesSize; index++) @@ -359,7 +376,7 @@ namespace CalculatorUnitTests NavCategoryGroup ^ calculatorGroup = menuOptions->GetAt(0); VERIFY_ARE_EQUAL(CategoryGroupType::Calculator, calculatorGroup->GroupType); - IObservableVector ^ calculatorCategories = calculatorGroup->Categories; + IObservableVector^ calculatorCategories = calculatorGroup->Categories; VERIFY_ARE_EQUAL(5, calculatorCategories->Size); ValidateNavCategory(calculatorCategories, 0u, ViewMode::Standard, 1); ValidateNavCategory(calculatorCategories, 1u, ViewMode::Scientific, 2); diff --git a/src/CalculatorUnitTests/StandardViewModelUnitTests.cpp b/src/CalculatorUnitTests/StandardViewModelUnitTests.cpp index 6a82173e..6bf7dff8 100644 --- a/src/CalculatorUnitTests/StandardViewModelUnitTests.cpp +++ b/src/CalculatorUnitTests/StandardViewModelUnitTests.cpp @@ -24,7 +24,9 @@ namespace CalculatorUnitTests void CompareVector(IVector ^ vecA, IVector ^ vecB) { if (vecA->Size != vecB->Size) + { Assert::Fail(); + } for (unsigned int i = 0; i < vecA->Size; ++i) { @@ -371,27 +373,25 @@ namespace CalculatorUnitTests /// Low-level test of character mapping TEST_METHOD(VerifyCorrectCharacterMapping) { - bool canSendNegate = false; - // Valid numbers - NumbersAndOperatorsEnum n = m_viewModel->MapCharacterToButtonId(L'0', canSendNegate); + NumbersAndOperatorsEnum n = m_viewModel->MapCharacterToButtonId(L'0').buttonId; ValidateNumbersAndOperatorsAreEqual(n, NumbersAndOperatorsEnum::Zero); - n = m_viewModel->MapCharacterToButtonId(L'1', canSendNegate); + n = m_viewModel->MapCharacterToButtonId(L'1').buttonId; ValidateNumbersAndOperatorsAreEqual(n, NumbersAndOperatorsEnum::One); // Valid operators - n = m_viewModel->MapCharacterToButtonId(L'+', canSendNegate); + n = m_viewModel->MapCharacterToButtonId(L'+').buttonId; ValidateNumbersAndOperatorsAreEqual(n, NumbersAndOperatorsEnum::Add); - n = m_viewModel->MapCharacterToButtonId(L'=', canSendNegate); + n = m_viewModel->MapCharacterToButtonId(L'=').buttonId; ValidateNumbersAndOperatorsAreEqual(n, NumbersAndOperatorsEnum::Equals); - n = m_viewModel->MapCharacterToButtonId(L'a', canSendNegate); + n = m_viewModel->MapCharacterToButtonId(L'a').buttonId; ValidateNumbersAndOperatorsAreEqual(n, NumbersAndOperatorsEnum::A); // Invalid character - n = m_viewModel->MapCharacterToButtonId(L'$', canSendNegate); + n = m_viewModel->MapCharacterToButtonId(L'$').buttonId; ValidateNumbersAndOperatorsAreEqual(n, NumbersAndOperatorsEnum::None); } @@ -509,7 +509,7 @@ namespace CalculatorUnitTests VERIFY_ARE_EQUAL(Utils::GetStringValue(m_viewModel->DecimalDisplayValue), StringReference(L"15")); VERIFY_ARE_EQUAL(Utils::GetStringValue(m_viewModel->OctalDisplayValue), StringReference(L"17")); VERIFY_ARE_EQUAL(Utils::GetStringValue(m_viewModel->BinaryDisplayValue), StringReference(L"1111")); - auto val = ref new PC::Vector(64, false); + auto val = ref new Platform::Collections::Vector(64, false); val->SetAt(0, true); val->SetAt(1, true); val->SetAt(2, true); @@ -562,7 +562,7 @@ namespace CalculatorUnitTests VERIFY_ARE_EQUAL(Utils::GetStringValue(m_viewModel->DecimalDisplayValue), StringReference(L"123,456,789")); VERIFY_ARE_EQUAL(Utils::GetStringValue(m_viewModel->OctalDisplayValue), StringReference(L"726 746 425")); VERIFY_ARE_EQUAL(Utils::GetStringValue(m_viewModel->BinaryDisplayValue), StringReference(L"0111 0101 1011 1100 1101 0001 0101")); - auto val = ref new PC::Vector(64, false); + auto val = ref new Platform::Collections::Vector(64, false); val->SetAt(0, true); val->SetAt(2, true); val->SetAt(4, true); @@ -599,7 +599,7 @@ namespace CalculatorUnitTests Utils::GetStringValue(m_viewModel->BinaryDisplayValue), StringReference(L"1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1110")); VERIFY_ARE_EQUAL(m_viewModel->DisplayValue, StringReference(L"-2")); - auto val = ref new PC::Vector(64, true); + auto val = ref new Platform::Collections::Vector(64, true); val->SetAt(0, false); CompareVector(m_viewModel->BinaryDigits, val); } @@ -889,13 +889,13 @@ namespace CalculatorUnitTests }; ValidateViewModelByCommands(m_viewModel, items, true); m_viewModel->OnMemoryButtonPressed(); - m_viewModel->SwitchProgrammerModeBase(RADIX_TYPE::OCT_RADIX); + m_viewModel->SwitchProgrammerModeBase(NumberBase::OctBase); MemoryItemViewModel ^ memorySlotOct = (MemoryItemViewModel ^) m_viewModel->MemorizedNumbers->GetAt(0); VERIFY_ARE_EQUAL(Platform::StringReference(L"377"), Utils::GetStringValue(memorySlotOct->Value)); - m_viewModel->SwitchProgrammerModeBase(RADIX_TYPE::DEC_RADIX); + m_viewModel->SwitchProgrammerModeBase(NumberBase::DecBase); MemoryItemViewModel ^ memorySlotDec = (MemoryItemViewModel ^) m_viewModel->MemorizedNumbers->GetAt(0); VERIFY_ARE_EQUAL(Platform::StringReference(L"255"), Utils::GetStringValue(memorySlotDec->Value)); - m_viewModel->SwitchProgrammerModeBase(RADIX_TYPE::BIN_RADIX); + m_viewModel->SwitchProgrammerModeBase(NumberBase::BinBase); MemoryItemViewModel ^ memorySlotBin = (MemoryItemViewModel ^) m_viewModel->MemorizedNumbers->GetAt(0); VERIFY_ARE_EQUAL(Platform::StringReference(L"1111 1111"), Utils::GetStringValue(memorySlotBin->Value)); } diff --git a/src/CalculatorUnitTests/pch.h b/src/CalculatorUnitTests/pch.h index 64d58bcd..b4137b22 100644 --- a/src/CalculatorUnitTests/pch.h +++ b/src/CalculatorUnitTests/pch.h @@ -48,39 +48,7 @@ #include "winrt/Windows.Globalization.DateTimeFormatting.h" #include "winrt/Windows.System.UserProfile.h" -namespace CalculatorApp -{ - namespace WF = Windows::Foundation; - namespace WUC = Windows::UI::Core; - namespace WX = Windows::UI::Xaml; - namespace WXC = Windows::UI::Xaml::Controls; - namespace WXCP = Windows::UI::Xaml::Controls::Primitives; - namespace P = Platform; - namespace PC = Platform::Collections; - namespace WXI = Windows::UI::Xaml::Input; - namespace WFC = Windows::Foundation::Collections; - namespace WS = Windows::System; - namespace WAR = Windows::ApplicationModel::Resources; - namespace WXMA = Windows::UI::Xaml::Media::Animation; - namespace WXD = Windows::UI::Xaml::Data; - namespace WXInt = Windows::UI::Xaml::Interop; - namespace WXM = Windows::UI::Xaml::Markup; - namespace WXA = Windows::UI::Xaml::Automation; -} - -// The following namespaces exist as a convenience to resolve -// ambiguity for Windows types in the Windows::UI::Xaml::Automation::Peers -// namespace that only exist on RS3. -// Once the app switches to min version RS3, the namespaces can be removed. -// TODO - MSFT 12735088 -namespace StandardPeers = Windows::UI::Xaml::Automation::Peers; -namespace CalculatorApp::Common::Automation -{ -} -namespace CustomPeers = CalculatorApp::Common::Automation; - // CalcManager Headers -#include "CalcManager/CalculatorVector.h" #include "CalcManager/ExpressionCommand.h" #include "CalcManager/CalculatorResource.h" #include "CalcManager/CalculatorManager.h" diff --git a/src/GraphControl/GraphControl.vcxproj.filters b/src/GraphControl/GraphControl.vcxproj.filters index d62288ff..c0669912 100644 --- a/src/GraphControl/GraphControl.vcxproj.filters +++ b/src/GraphControl/GraphControl.vcxproj.filters @@ -71,7 +71,5 @@ - - \ No newline at end of file diff --git a/src/Settings.XamlStyler b/src/Settings.XamlStyler index 6fc7c481..07bd12eb 100644 --- a/src/Settings.XamlStyler +++ b/src/Settings.XamlStyler @@ -18,7 +18,8 @@ "FontFamily, FontSize, LineHeight, FontWeight, FontStyle, FontStretch", "*:*, *", "PageSource, PageIndex, Offset, Color, TargetName, Property, Value, StartPoint, EndPoint", - "mc:Ignorable, d:IsDataSource, d:LayoutOverrides, d:IsStaticText" + "mc:Ignorable, d:IsDataSource, d:LayoutOverrides, d:IsStaticText", + "IsEnabled, x:Load, Load" ], "OrderAttributesByName": true, "PutEndingBracketOnNewLine": false,