diff --git a/.gitignore b/.gitignore
index 415b87da..0167a23c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -291,6 +291,9 @@ __pycache__/
Generated Files/
src/GraphControl/GraphingImplOverrides.props
src/CalcViewModel/DataLoaders/DataLoaderConstants.h
-!/build/config/TRexDefs/**
-!src/Calculator/TemporaryKey.pfx
-!src/CalculatorUnitTests/CalculatorUnitTests_TemporaryKey.pfx
\ No newline at end of file
+!src/Calculator/WindowsDev_TemporaryKey.pfx
+!src/CalculatorUnitTests/WindowsDev_TemporaryKey.pfx
+!src/x64
+!src/x86
+!src/out
+!src/ARM
\ No newline at end of file
diff --git a/README.md b/README.md
index 386e871d..08d59ee6 100644
--- a/README.md
+++ b/README.md
@@ -51,6 +51,10 @@ We also welcome [issues submitted on GitHub](https://github.com/Microsoft/calcul
## Roadmap
For information regarding Windows Calculator plans and release schedule, please see the [Windows Calculator Roadmap](docs/Roadmap.md).
+### Graphing Mode
+Adding graphing calculator functionality [is on the project roadmap](https://github.com/Microsoft/calculator/issues/338) and we hope that this project can create a great end-user experience around graphing. To that end, the UI from the official in-box Windows Calculator is currently part of this repository, although the proprietary Microsoft-built graphing engine, which also drives graphing in Microsoft Mathematics and OneNote, is not. Community members can still be involved in the creation of the UI, however developer builds will not have graphing functionality due to the use of a [mock implementation of the engine](/src/GraphingImpl/Mocks) built on top of a
+[common graphing API](/src/GraphingInterfaces).
+
## Diagnostic Data
This project collects usage data and sends it to Microsoft to help improve our products and services.
Read our [privacy statement](https://go.microsoft.com/fwlink/?LinkId=521839) to learn more.
diff --git a/build/config/LocConfigPackageEs.xml b/build/config/LocConfigPackageEs.xml
deleted file mode 100644
index d566c7cf..00000000
--- a/build/config/LocConfigPackageEs.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/build/config/SignConfig.xml b/build/config/SignConfig.xml
deleted file mode 100644
index eb298e87..00000000
--- a/build/config/SignConfig.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/build/config/TRexDefs/amd64/performance.xml b/build/config/TRexDefs/amd64/performance.xml
deleted file mode 100644
index e6b6b40e..00000000
--- a/build/config/TRexDefs/amd64/performance.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
- RS_APPS_VALIDATE AMD64 Desktop WinPerf Test Run
- 134858
- paxeedev
- true
- true
- Performance_AMD64.testlist
-
-
-
- VSTS\IsReliabilityRun
- True
-
-
-
-
- AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
- _AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
-
-
-
\ No newline at end of file
diff --git a/build/config/TRexDefs/amd64/rs4_release.xml b/build/config/TRexDefs/amd64/rs4_release.xml
deleted file mode 100644
index 78a52df9..00000000
--- a/build/config/TRexDefs/amd64/rs4_release.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
- RS4_RELEASE AMD64 DesktopVM Test Run
- 139642
- paxeedev
- true
- true
- Desktop_AMD64.testlist
- rs4_release
-
-
- AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
- _AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
-
-
-
\ No newline at end of file
diff --git a/build/config/TRexDefs/amd64/rs5_release.xml b/build/config/TRexDefs/amd64/rs5_release.xml
deleted file mode 100644
index 7fbccdc2..00000000
--- a/build/config/TRexDefs/amd64/rs5_release.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
- RS5_RELEASE AMD64 DesktopVM Test Run
- 139642
- paxeedev
- true
- true
- Desktop_AMD64.testlist
- rs5_release
-
-
- AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
- _AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
-
-
-
\ No newline at end of file
diff --git a/build/config/TRexDefs/amd64/rs_apps_validate.xml b/build/config/TRexDefs/amd64/rs_apps_validate.xml
deleted file mode 100644
index a90ca288..00000000
--- a/build/config/TRexDefs/amd64/rs_apps_validate.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
-
-
- RS_APPS_VALIDATE AMD64 DesktopVM Test Run
- 139642
- paxeedev
- true
- true
- Desktop_AMD64.testlist
- rs_apps_validate
-
-
- AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
- _AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
-
-
-
- RS_APPS_VALIDATE AMD64 WCOS Test Run
- 153648
- paxeedev
- true
- true
- WCOS_AMD64.testlist
- rs_apps_validate
-
-
- AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
- _AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
-
-
-
\ No newline at end of file
diff --git a/build/config/TRexDefs/arm/performance.xml b/build/config/TRexDefs/arm/performance.xml
deleted file mode 100644
index 5fde2b8a..00000000
--- a/build/config/TRexDefs/arm/performance.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
-
- RS_PRERELEASE ARM WindowsCore WinPerf Test Run
- 135258
- paxeedev
- true
- true
- Performance_ARM.testlist
-
-
-
- VSTS\IsReliabilityRun
- True
-
-
-
-
- AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
- _AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
-
-
-
\ No newline at end of file
diff --git a/build/config/TRexDefs/arm/rs_apps_validate.xml b/build/config/TRexDefs/arm/rs_apps_validate.xml
deleted file mode 100644
index 277c9761..00000000
--- a/build/config/TRexDefs/arm/rs_apps_validate.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/build/config/TRexDefs/x86/rs4_release.xml b/build/config/TRexDefs/x86/rs4_release.xml
deleted file mode 100644
index 7f3f2cbf..00000000
--- a/build/config/TRexDefs/x86/rs4_release.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
- RS_APPS_VALIDATE x86 DesktopVM Test Run
- 139643
- paxeedev
- true
- true
- Desktop_x86.testlist
- rs4_release
-
-
- AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
- _AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
-
-
-
\ No newline at end of file
diff --git a/build/config/TRexDefs/x86/rs5_release.xml b/build/config/TRexDefs/x86/rs5_release.xml
deleted file mode 100644
index 205a9c09..00000000
--- a/build/config/TRexDefs/x86/rs5_release.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
- RS_APPS_VALIDATE x86 DesktopVM Test Run
- 139643
- paxeedev
- true
- true
- Desktop_x86.testlist
- rs5_release
-
-
- AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
- _AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
-
-
-
\ No newline at end of file
diff --git a/build/config/TRexDefs/x86/rs_apps_validate.xml b/build/config/TRexDefs/x86/rs_apps_validate.xml
deleted file mode 100644
index 130dc8f7..00000000
--- a/build/config/TRexDefs/x86/rs_apps_validate.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-
-
-
-
-
- RS_APPS_VALIDATE x86 DesktopVM Test Run
- 139643
- paxeedev
- true
- true
- Desktop_x86.testlist
- rs_apps_validate
-
-
- AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
- _AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
-
-
-
-
- RS_PRERELEASE x86 WindowsCoreVM Test Run
- 153715
- paxeedev
- true
- true
- WCOS_x86.testlist
- rs_apps_validate
-
-
- AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
- _AlternatePackageRoot
- \\pkges\release\TAEF\validation.taef.provenance\1812.20007-develop\UniversalTestPackages;\\edge-svcs\Release\MITALite\Apps_eng.mitalite_ci\Latest.tst
-
-
-
-
-
\ No newline at end of file
diff --git a/build/config/TestLists/ARM/Desktop_ARM.testlist b/build/config/TestLists/ARM/Desktop_ARM.testlist
deleted file mode 100644
index cf0e5b66..00000000
--- a/build/config/TestLists/ARM/Desktop_ARM.testlist
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "$schema": "http://universaltest/schema/testlist-2.json",
- "TestMDs": [
- {
- "FilePath": "Calculator.UITests\\Prebuilt\\Test\\arm\\fre\\Calculator.UITests.testmd",
- "ExecutionProfile": "All"
- },
- {
- "FilePath": "CalculatorUnitTests\\Prebuilt\\Test\\arm\\fre\\CalculatorUnitTests.testmd",
- }
- ]
-}
\ No newline at end of file
diff --git a/build/config/TestLists/ARM/Performance_ARM.testlist b/build/config/TestLists/ARM/Performance_ARM.testlist
deleted file mode 100644
index 2ec2d933..00000000
--- a/build/config/TestLists/ARM/Performance_ARM.testlist
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "$schema": "http://universaltest/schema/testlist-2.json",
- "TestMDs": [
- {
- "FilePath": "Calculator.UITests\\Prebuilt\\Test\\arm\\fre\\Calculator.UITests.testmd",
- "ExecutionProfile": "Performance"
- }
- ]
-}
\ No newline at end of file
diff --git a/build/config/TestLists/ARM/WCOS_ARM.testlist b/build/config/TestLists/ARM/WCOS_ARM.testlist
deleted file mode 100644
index cf0e5b66..00000000
--- a/build/config/TestLists/ARM/WCOS_ARM.testlist
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "$schema": "http://universaltest/schema/testlist-2.json",
- "TestMDs": [
- {
- "FilePath": "Calculator.UITests\\Prebuilt\\Test\\arm\\fre\\Calculator.UITests.testmd",
- "ExecutionProfile": "All"
- },
- {
- "FilePath": "CalculatorUnitTests\\Prebuilt\\Test\\arm\\fre\\CalculatorUnitTests.testmd",
- }
- ]
-}
\ No newline at end of file
diff --git a/build/config/TestLists/ARM64/Desktop_ARM64.testlist b/build/config/TestLists/ARM64/Desktop_ARM64.testlist
deleted file mode 100644
index a2e620ca..00000000
--- a/build/config/TestLists/ARM64/Desktop_ARM64.testlist
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "$schema": "http://universaltest/schema/testlist-2.json",
- "TestMDs": [
- {
- "FilePath": "Calculator.UITests\\Prebuilt\\Test\\arm64\\fre\\Calculator.UITests.testmd",
- "ExecutionProfile": "All"
- },
- {
- "FilePath": "CalculatorUnitTests\\Prebuilt\\Test\\arm64\\fre\\CalculatorUnitTests.testmd",
- }
- ]
-}
\ No newline at end of file
diff --git a/build/config/TestLists/ARM64/WCOS_ARM64.testlist b/build/config/TestLists/ARM64/WCOS_ARM64.testlist
deleted file mode 100644
index a2e620ca..00000000
--- a/build/config/TestLists/ARM64/WCOS_ARM64.testlist
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "$schema": "http://universaltest/schema/testlist-2.json",
- "TestMDs": [
- {
- "FilePath": "Calculator.UITests\\Prebuilt\\Test\\arm64\\fre\\Calculator.UITests.testmd",
- "ExecutionProfile": "All"
- },
- {
- "FilePath": "CalculatorUnitTests\\Prebuilt\\Test\\arm64\\fre\\CalculatorUnitTests.testmd",
- }
- ]
-}
\ No newline at end of file
diff --git a/build/config/rs_apps_utils.json b/build/config/rs_apps_utils.json
deleted file mode 100644
index 9c16d817..00000000
--- a/build/config/rs_apps_utils.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- "Branch": [
- {
- "collection":"microsoft",
- "project":"OS",
- "repo":"os",
- "name":"official/rs_apps_utils",
- "CheckinFiles": [
- {
- "source":"vpack/app/calculator.app.man",
- "path": "/redist/mspartners/ipa/Calculator",
- "type": "File"
- },
- {
- "source":"vpack/app/calculator.app.man",
- "path": "/onecoreuap/redist/mspartners/ipa/Calculator",
- "type": "File"
- }
- ]
- }
- ],
- "Email": [
- {
- "sendTo":"paxeedev",
- "sendOnErrorOnly": "True"
- }
- ]
-}
\ No newline at end of file
diff --git a/build/config/rs_apps_validate.json b/build/config/rs_apps_validate.json
deleted file mode 100644
index 3fbe98b5..00000000
--- a/build/config/rs_apps_validate.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- "Branch": [
- {
- "collection":"microsoft",
- "project":"OS",
- "repo":"os",
- "name":"official/rs_apps_validate",
- "CheckinFiles": [
- {
- "source":"vpack/app/calculator.app.man",
- "path": "/redist/mspartners/ipa/Calculator",
- "type": "File"
- },
- {
- "source":"vpack/app/calculator.app.man",
- "path": "/onecoreuap/redist/mspartners/ipa/Calculator",
- "type": "File"
- }
- ]
- }
- ],
- "Email": [
- {
- "sendTo":"paxeedev",
- "sendOnErrorOnly": "True"
- }
- ]
-}
\ No newline at end of file
diff --git a/build/pipelines/azure-pipelines.ci.yaml b/build/pipelines/azure-pipelines.ci.yaml
index 3f7faf16..2d55627a 100644
--- a/build/pipelines/azure-pipelines.ci.yaml
+++ b/build/pipelines/azure-pipelines.ci.yaml
@@ -6,11 +6,11 @@
trigger:
- master
-- servicing/*
+- release/*
- feature/*
pr:
- master
-- servicing/*
+- release/*
- feature/*
name: 0.$(Date:yyMM).$(DayOfMonth)$(Rev:rr).0
@@ -23,6 +23,7 @@ jobs:
- template: ./templates/build-app-public.yaml
parameters:
platform: x86
+ condition: not(eq(variables['Build.Reason'], 'PullRequest'))
- template: ./templates/build-app-public.yaml
parameters:
diff --git a/build/pipelines/azure-pipelines.release.yaml b/build/pipelines/azure-pipelines.release.yaml
index 33e10c63..f7c54551 100644
--- a/build/pipelines/azure-pipelines.release.yaml
+++ b/build/pipelines/azure-pipelines.release.yaml
@@ -4,13 +4,20 @@
# Store and the Windows image. This pipeline relies on Microsoft-internal resources to run.
#
+schedules:
+- cron: "0 7 * * *"
+ displayName: Daily midnight build
+ branches:
+ include:
+ - master
+
trigger: none
pr: none
variables:
versionMajor: 10
- versionMinor: 1910
- versionBuild: $[counter('10.1910.*', 0)]
+ versionMinor: 2012
+ versionBuild: $[counter('10.2012.*', 0)]
versionPatch: 0
name: '$(versionMajor).$(versionMinor).$(versionBuild).$(versionPatch)'
@@ -30,11 +37,6 @@ jobs:
platform: ARM
condition: not(eq(variables['Build.Reason'], 'PullRequest'))
-- template: ./templates/build-app-internal.yaml
- parameters:
- platform: ARM64
- condition: not(eq(variables['Build.Reason'], 'PullRequest'))
-
- template: ./templates/run-ui-tests.yaml
parameters:
platform: x64
@@ -54,5 +56,7 @@ jobs:
platform: x86
- template: ./templates/package-appxbundle.yaml
+ parameters:
+ signBundle: true
- template: ./templates/prepare-release-internalonly.yaml
diff --git a/build/pipelines/templates/build-app-internal.yaml b/build/pipelines/templates/build-app-internal.yaml
index 51eb1d28..9c55b30a 100644
--- a/build/pipelines/templates/build-app-internal.yaml
+++ b/build/pipelines/templates/build-app-internal.yaml
@@ -16,20 +16,18 @@ jobs:
variables:
BuildConfiguration: Release
BuildPlatform: ${{ parameters.platform }}
- workspace:
- clean: outputs
steps:
- checkout: self
- clean: true
+ fetchDepth: 1
- task: UniversalPackages@0
displayName: Download internals package
inputs:
command: download
downloadDirectory: $(Build.SourcesDirectory)
- vstsFeed: WindowsApps
+ vstsFeed: WindowsInboxApps
vstsFeedPackage: calculator-internals
- vstsPackageVersion: 0.0.31
+ vstsPackageVersion: 0.0.53
- template: ./build-single-architecture.yaml
parameters:
diff --git a/build/pipelines/templates/build-app-public.yaml b/build/pipelines/templates/build-app-public.yaml
index c256e74d..70f18e5b 100644
--- a/build/pipelines/templates/build-app-public.yaml
+++ b/build/pipelines/templates/build-app-public.yaml
@@ -14,10 +14,8 @@ jobs:
variables:
BuildConfiguration: Release
BuildPlatform: ${{ parameters.platform }}
- workspace:
- clean: outputs
steps:
- checkout: self
- clean: true
+ fetchDepth: 1
- template: ./build-single-architecture.yaml
\ No newline at end of file
diff --git a/build/pipelines/templates/build-single-architecture.yaml b/build/pipelines/templates/build-single-architecture.yaml
index a3e1d46c..49056df1 100644
--- a/build/pipelines/templates/build-single-architecture.yaml
+++ b/build/pipelines/templates/build-single-architecture.yaml
@@ -5,11 +5,10 @@ parameters:
extraMsBuildArgs: ''
steps:
- - task: NuGetToolInstaller@0
- displayName: Use NuGet 5.0.2
+ - task: NuGetToolInstaller@1
+ displayName: Use NuGet 5.x
inputs:
- versionSpec: 5.0.2
- checkLatest: true
+ versionSpec: 5.x
# In most accounts, you can just use 'NuGetCommand' instead of this GUID.
# In the microsoft.visualstudio.com account, NuGetCommand is ambiguous so the GUID is needed.
@@ -17,7 +16,7 @@ steps:
displayName: NuGet restore src/Calculator.sln
inputs:
command: custom
- arguments: restore src/Calculator.sln -Verbosity Detailed -NonInteractive
+ arguments: restore src/Calculator.sln -Verbosity Detailed
- task: PowerShell@2
displayName: Set version number in AppxManifest
@@ -33,7 +32,6 @@ steps:
msbuildArgs: /bl:$(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\Calculator.binlog /p:OutDir=$(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\ /p:GenerateProjectSpecificOutputFolder=true /p:AppVersion=$(Build.BuildNumber) /t:Publish /p:PublishDir=$(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\publish\ ${{ parameters.extraMsBuildArgs }}
platform: $(BuildPlatform)
configuration: $(BuildConfiguration)
- clean: true
maximumCpuCount: true
- task: PublishBuildArtifacts@1
diff --git a/build/pipelines/templates/package-appxbundle.yaml b/build/pipelines/templates/package-appxbundle.yaml
index 1e06d20d..f8de83ce 100644
--- a/build/pipelines/templates/package-appxbundle.yaml
+++ b/build/pipelines/templates/package-appxbundle.yaml
@@ -1,30 +1,29 @@
# This template contains a job which takes .appx packages which were built separately for each
# architecture (arm, x86, etc.) and combines them into a single .appxbundle.
+parameters:
+ signBundle: false
+
jobs:
- job: Package
dependsOn:
- Buildx64
- Buildx86
- BuildARM
- - BuildARM64
condition: |
and
(
in(dependencies.Buildx64.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'),
in(dependencies.Buildx86.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'),
- in(dependencies.BuildARM.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'),
- in(dependencies.BuildARM64.result, 'Succeeded', 'SucceededWithIssues', 'Skipped')
+ in(dependencies.BuildARM.result, 'Succeeded', 'SucceededWithIssues', 'Skipped')
)
pool:
vmImage: windows-2019
- workspace:
- clean: outputs
variables:
skipComponentGovernanceDetection: true
steps:
- checkout: self
- clean: true
+ fetchDepth: 1
- task: DownloadBuildArtifacts@0
displayName: Download all .appx artifacts
@@ -59,4 +58,44 @@ jobs:
displayName: Publish AppxBundle artifact
inputs:
artifactName: appxBundle
- pathToPublish: $(Build.ArtifactStagingDirectory)\appxBundle
\ No newline at end of file
+ pathToPublish: $(Build.ArtifactStagingDirectory)\appxBundle
+
+ - ${{ if eq(parameters.signBundle, true) }}:
+ - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1
+ displayName: Send appxbundle to code signing service
+ inputs:
+ ConnectedServiceName: Essential Experiences Codesign
+ FolderPath: $(Build.ArtifactStagingDirectory)\appxBundle
+ Pattern: Microsoft.WindowsCalculator_8wekyb3d8bbwe.appxbundle
+ signConfigType: inlineSignParams
+ inlineOperation: |
+ [
+ {
+ "CertTemplateName": "WINMSAPP1ST",
+ "CertSubjectName": "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US",
+ "KeyCode": "Dynamic",
+ "OperationCode": "SigntoolvNextSign",
+ "Parameters": {
+ "OpusName": "Microsoft",
+ "OpusInfo": "http://www.microsoft.com",
+ "FileDigest": "/fd \"SHA256\"",
+ "TimeStamp": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
+ },
+ "ToolName": "sign",
+ "ToolVersion": "1.0"
+ },
+ {
+ "CertTemplateName": "WINMSAPP1ST",
+ "CertSubjectName": "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US",
+ "KeyCode": "Dynamic",
+ "OperationCode": "SigntoolvNextVerify",
+ "Parameters": {},
+ "ToolName": "sign",
+ "ToolVersion": "1.0"
+ }
+ ]
+ - task: PublishBuildArtifacts@1
+ displayName: Publish AppxBundleSigned artifact
+ inputs:
+ pathtoPublish: $(Build.ArtifactStagingDirectory)\appxBundle
+ artifactName: appxBundleSigned
\ No newline at end of file
diff --git a/build/pipelines/templates/prepare-release-internalonly.yaml b/build/pipelines/templates/prepare-release-internalonly.yaml
index 9c7a45ea..b14d5979 100644
--- a/build/pipelines/templates/prepare-release-internalonly.yaml
+++ b/build/pipelines/templates/prepare-release-internalonly.yaml
@@ -2,8 +2,6 @@
# Windows using Microsoft-internal systems. It relies on Microsoft-internal resources and will not
# work outside of Microsoft.
# Specifically, this job:
-# - Signs the bundle using a secure system. If you want to build your own, use SignTool following
-# the example in the continuous integration pipeline.
# - Builds VPacks for including the app in the Windows OS build. Azure DevOps Universal Packages
# offers similar capabilities.
# - Creates StoreBroker packages containing Microsoft Store assets. Although the Store assets for
@@ -14,7 +12,7 @@ jobs:
- job: WindowsInternalRelease
dependsOn: Package
pool:
- name: Package ES Lab E
+ name: Package ES Standard Build
workspace:
clean: outputs
variables:
@@ -39,36 +37,21 @@ jobs:
env:
XES_DISABLEPROV: true
- - task: NuGetToolInstaller@0
- displayName: Use NuGet 4.7.1
+ - task: NuGetToolInstaller@1
+ displayName: Use NuGet 5.x
inputs:
- versionSpec: 4.7.1
- checkLatest: true
+ versionSpec: 5.x
- task: DownloadBuildArtifacts@0
- displayName: Download appxBundle artifact
+ displayName: Download appxBundleSigned artifact
inputs:
- artifactName: appxBundle
-
- - task: PkgESCodeSign@10
- displayName: Send bundle to Package ES code signing service
- env:
- SYSTEM_ACCESSTOKEN: $(System.AccessToken)
- inputs:
- signConfigXml: build\config\SignConfig.xml
- inPathRoot: $(Build.ArtifactStagingDirectory)\appxBundle
- outPathRoot: $(Build.ArtifactStagingDirectory)\appxBundleSigned
-
- - task: PublishBuildArtifacts@1
- displayName: Publish AppxBundleSigned artifact
- inputs:
- pathtoPublish: $(Build.ArtifactStagingDirectory)\appxBundleSigned
- artifactName: AppxBundleSigned
+ artifactName: appxBundleSigned
- task: CopyFiles@2
displayName: Copy signed AppxBundle to vpack staging folder
inputs:
sourceFolder: $(Build.ArtifactStagingDirectory)\appxBundleSigned
+ contents: Microsoft.WindowsCalculator_8wekyb3d8bbwe.appxbundle
targetFolder: $(Build.ArtifactStagingDirectory)\vpack\appxBundle
- task: PkgESVPack@10
@@ -81,6 +64,8 @@ jobs:
pushPkgName: calculator.app
version: $(versionMajor).$(versionMinor).$(versionBuild)
owner: paxeeapps
+ provData: false
+
- task: PublishBuildArtifacts@1
displayName: Publish vpack\app artifact with vpack manifest
@@ -88,16 +73,14 @@ jobs:
pathtoPublish: $(XES_VPACKMANIFESTDIRECTORY)\$(XES_VPACKMANIFESTNAME)
artifactName: vpack\app
- # TODO (macool): create and push internal test packages and test config
-
- task: UniversalPackages@0
displayName: Download internals package
inputs:
command: download
downloadDirectory: $(Build.SourcesDirectory)
- vstsFeed: WindowsApps
+ vstsFeed: WindowsInboxApps
vstsFeedPackage: calculator-internals
- vstsPackageVersion: 0.0.22
+ vstsPackageVersion: 0.0.53
- powershell: |
# Just modify this line to indicate where your en-us PDP file is. Leave the other lines alone.
@@ -151,6 +134,8 @@ jobs:
skipPolling: true
targetPublishMode: Immediate
logPath: '$(SBLogPath)'
+ deletePackages: true
+ numberOfPackagesToKeep: 0
- task: PkgESStoreBrokerAeroUpload@10
displayName: Upload to Aero flighting dashboard
diff --git a/build/pipelines/templates/run-ui-tests.yaml b/build/pipelines/templates/run-ui-tests.yaml
index 0e2d7656..347a3a8b 100644
--- a/build/pipelines/templates/run-ui-tests.yaml
+++ b/build/pipelines/templates/run-ui-tests.yaml
@@ -47,4 +47,6 @@ jobs:
vsTestVersion: 16.0
runSettingsFile: $(Build.ArtifactStagingDirectory)/drop/Release/${{ parameters.platform }}/publish/${{ parameters.runsettingsFileName }}
platform: ${{ parameters.platform }}
- configuration: Release
\ No newline at end of file
+ configuration: Release
+ ${{ if eq(variables['Build.Reason'], 'PullRequest') }}:
+ testFiltercriteria: Priority=0
diff --git a/docs/ManualTests.md b/docs/ManualTests.md
index ddc38ac1..884f0aef 100644
--- a/docs/ManualTests.md
+++ b/docs/ManualTests.md
@@ -260,17 +260,19 @@ Steps:
4. While in the Menu: Check the About Page
*Expected: Everything in the about page fits into its window*
5. For Scientific Mode: At a Larger Scale
-*Expected: All buttons are present and the up arrow is grayed out.*
+*Expected: All buttons are present and the 2nd button is grayed out.*
6. For Scientific Mode: At a Smaller Scale
-*Expected: All buttons are present and the up arrow is able to be toggled.*
+*Expected: All buttons are present and the 2nd button is able to be toggled.*
7. For Programmer Mode: At a Any Scale
-*Expected: All buttons are present and the up arrow is able to be toggled.*
+*Expected: All buttons are present and the 2nd button is able to be toggled.*
8. For Converter Mode: While Scaling
*Expected: The number pad and input areas move around each other gracefully.*
-9. Changing Language: Open Settings app > Time & language > Region & language > Add a language > Select a Right to Left (RTL) language such as Hebrew > Install the associated files> Set it to the system default.
-10. Set the system number format preference: Open a Run dialog (WIN + R) > type ‘intl.cpl’ > Enter > In the format dropdown list > Select Hebrew > Apply.
-11. Initiating the change: Package has completed installing > Sign out > Sign in. (This change to the app may also require a reinstallation of the build)
-12. Repeat Steps 2-6 again in a (RTL) language.
+9. For Graphing Mode: While Scaling
+*Expected: The number pad, graph area, and input areas move around each other gracefully.*
+10. Changing Language: Open Settings app > Time & language > Region & language > Add a language > Select a Right to Left (RTL) language such as Hebrew > Install the associated files> Set it to the system default.
+11. Set the system number format preference: Open a Run dialog (WIN + R) > type ‘intl.cpl’ > Enter > In the format dropdown list > Select Hebrew > Apply.
+12. Initiating the change: Package has completed installing > Sign out > Sign in. (This change to the app may also require a reinstallation of the build)
+13. Repeat Steps 2-6 again in a (RTL) language.
*Expected: No elements fall out of intended boundaries.*
@@ -302,11 +304,60 @@ Verify the following:
11. "Bin" Binary:
*Expected: A B C D E F 2 3 4 5 6 7 8 9 are inactive. A maximum of 64 characters can be entered.*
+**Graphing Mode Test: Verify Graphing mode functions**
+Steps:
+1. Launch the "Calculator" app
+2. Navigate to "Graphing" Calculator
+3. Enter a function of x in the input field
+*Expected: Function is plotted in the graph area. Line color matches the colored square next to the input field*
+4. Select the "+" button below the function input and enter more functions in the fields that appear
+*Expected: All functions are plotted in the graph area and match the colors of the input field squares*
+5. Select the colored square for any function
+*Expected: Visibility of the function in the graph is toggled off/on*
+6. Select the "Zoom In", "Zoom Out", and "Reset View' buttons in the graph area
+*Expected: Both X and Y axes zoom in, out, and revert to default settings, respectively*
+7. Select the Trace button, then click + drag the graph until the red square is near a graphed function
+*Expected: Closest (X, Y) coordinates of the function to the red square are displayed with a black dot to indicate the location*
+8. Enter "y=mx+b" into a function input field, then select "Variables" button
+*Expected: y=x+1 function is plotted in the graph, "Variables" modal window shows two variables "m" and "b" with values set to 1.*
+9. Adjust the value, minimum, maximum, and step for each variable
+*Expected: y=mx+b graph adjusts to the new values for m and b, step size changes the increments of the slider for each value*
+10. Share the graph via OneNote, Outlook/Mail, Twitter, and Feedback Hub
+*Expected: Modifiable message that contains an image of the graph customized for the chosen application opens*
+11. Verify Key Graph Features tab shows the correct information for the following functions:
+ *(Note: IP = Inflection Points, VA = Vertical Asymptotes, HA = Horizontal Asymptotes, OA = Oblique Asymptotes)*
+ a. **y=x**
+ *Expected: Domain: ⁅𝑥∈ℝ⁆; Range: ⁅y∈ℝ⁆; X/Y Intercepts: (0)/(0); Max: none; Min: none; IP: none; VA: none; HA: none; OA: none; Parity: Odd; Monotonicity: (-∞, ∞) Increasing*
+ b. **y=1/x**
+ *Expected: Domain: ⁅𝑥≠0⁆; Range: ⁅y∈ℝ\{0}⁆; X/Y Intercepts: ø/ø; Max: none; Min: none; IP: none; VA: x=0; HA: y=0; OA: none; Parity: Odd; Monotonicity: (0, ∞) Decreasing, (-∞, 0) Increasing*
+ c. **y=x^2**
+ *Expected: Domain: ⁅𝑥∈ℝ⁆; Range: ⁅y∈{0, ∞)⁆; X/Y Intercepts: (0)/(0); Max: none; Min: (0,0); IP: none; VA: none; HA: none; OA: none; Parity: Even; Monotonicity: (0, ∞) Increasing, (-∞, 0) Decreasing*
+ d. **y=x^3**
+ *Expected: Domain: ⁅𝑥∈ℝ⁆; Range: ⁅y∈ℝ⁆; X/Y Intercepts: (0)/(0); Max: none; Min: none; IP: (0,0); VA: none; HA: none; OA: none; Parity: Odd; Monotonicity: (-∞, ∞) Increasing*
+ e. **y=e^x**
+ *Expected: Domain: ⁅𝑥∈ℝ⁆; Range: ⁅y∈(0, ∞)⁆; X/Y Intercepts: ø/(1); Max: none; Min: none; IP: none; VA: none; HA: y=0; OA: none; Parity: none; Monotonicity: (-∞, ∞) Increasing*
+ f. **y=ln(x)**
+ *Expected: Domain: ⁅𝑥>0⁆; Range: ⁅y∈ℝ⁆; X/Y Intercepts: (1)/ø; Max: none; Min: none; IP: none; VA: x=0; HA: none; OA: none; Parity: none; Monotonicity: (0, ∞) Increasing*
+ g. **y=sin(x)**
+ *Expected: Domain: ⁅𝑥∈ℝ⁆; Range: ⁅𝑦∈[−1,1]⁆; X/Y Intercepts: (⁅𝜋n1,n1∈ℤ⁆)/(0); Max: ⁅(2𝜋n1+𝜋/2,1),n1∈ℤ⁆; Min: ⁅(2𝜋n1+3𝜋/2,−1),n1∈ℤ⁆; IP: ⁅(𝜋n1,0),n1∈ℤ⁆; VA: none; HA: none; OA: none; Parity: Odd; Monotonicity: ⁅(2𝜋n1+𝜋/2,2𝜋n1+3𝜋/2),n1∈ℤ⁆ Decreasing; ⁅(2𝜋n1+3𝜋/2,2𝜋n1+5𝜋/2),n1∈ℤ⁆ Increasing; Period: 2𝜋*
+ h. **y=cos(x)**
+ *Expected: Domain: ⁅𝑥∈ℝ⁆; Range: ⁅𝑦∈[−1,1]⁆; X/Y Intercepts: (⁅𝜋n1+𝜋/2,n1∈ℤ⁆)/(1); Max: ⁅(2𝜋n1,1),n1∈ℤ⁆; Min: ⁅(2𝜋n1+𝜋,-1),n1∈ℤ⁆; IP: ⁅(𝜋n1+𝜋/2,0),n1∈ℤ⁆; VA: none; HA: none; OA: none; Parity: Even; Monotonicity: ⁅(2𝜋n1+𝜋,2𝜋n1+2𝜋),n1∈ℤ⁆ Increasing, ⁅(2𝜋n1,2𝜋n1+𝜋),n1∈ℤ⁆ Decreasing; Period: 2𝜋*
+ i. **y=tan(x)**
+ *Expected: Domain: ⁅x≠𝜋n1+𝜋/2,∀n1∈ℤ⁆; Range: ⁅𝑦∈ℝ⁆; X/Y Intercepts: (x=𝜋n1, n1 ∈ℤ)/(0); Max: none; Min: none; IP: x=𝜋n1, n1 ∈ℤ; VA: x=𝜋n1+𝜋/2, n1∈ℤ; HA: none; OA: none; Parity: Odd; Monotonicity: ⁅(𝜋n1+𝜋/2,𝜋n1+3𝜋/2),n1∈ℤ⁆ Increasing; Period: 𝜋*
+ j. **y=sqrt(25-x^2)**
+ *Expected: Domain: ⁅x∈[-5,5]⁆; Range: ⁅𝑦∈[0,5]⁆; X/Y Intercepts: (5),(-5)/(5); Max: (0,5); Min: (-5,0) and (5,0); IP: none; VA: none; HA: none; OA: none; Parity: Even; Monotonicity: (0,5) Decreasing, (-5,0) Increasing*
+ k. **y=(-3x^2+2)/(x-1)**
+ *Expected: Domain: ⁅x≠1⁆; Range: ⁅𝑦∈(-∞, -2√3 - 6}U{2√3 -6,∞⁆; X/Y Intercepts: (-√6/3),(√6/3)/(-2); Max: ⁅(√3/3+1,-2√3−6)⁆; Min: ⁅(−√3/3+1,2√3−6)⁆; IP: none; VA: x=1; HA: none; OA: y=-3x-3; Parity: none; Monotonicity: (√3/3+1,∞) Decreasing, (1,√3/3+1,) Increasing(-√3/3+1,1), Increasing, (-∞,-√3/3+1) Decreasing*
+ l. **y=sin(sin(x))** ("too complex" error test)
+ *Expected: Domain: ⁅𝑥∈ℝ⁆; Range: Unable to calculate range for this function; X/Y Intercepts: none; Max: none; Min: none; IP: none; VA: none; HA: none; OA: none; Parity: odd; Monotonicity: Unable to determine the monotonicity of the function*
+ *These features are too complex for Calculator to calculate: Range, X Intercept, Period, Minima, Maxima, Inflection Points, Monotonicity*
+ m. **y=mx+b**
+ *Expected: Analysis is not supported for this function*
**Date Calculation Test: Verify dates can be calculated.**
Steps:
-1. Launch the "Calculator" app.
-2. Navigate to "Date Calculation" Calculator.
+1. Launch the "Calculator" app
+2. Navigate to "Date Calculation" Calculator
3. With "Difference between dates" Selected
Change the various date input fields
*Expected: From and To reflect dates input respectively.*
@@ -332,80 +383,88 @@ Steps:
1. Launch the "Calculator" app.
For All Applicable Modes verify the following (note: only 11-15 and 20 work in Always-on-Top mode):
-2. Press **Alt +1** to Enter "Standard" mode
+2. Press **Alt +1** to enter "Standard" mode
*Expected: Move to "Standard" screen.*
-3. Press **Alt +2** to Enter "Scientific" mode
+3. Press **Alt +2** to enter "Scientific" mode
*Expected: Move to "Scientific" screen.*
-4. Press **Alt +3** to Enter "Programmer" mode
+4. Press **Alt +3** to enter "Programmer" mode
*Expected: Move to "Programming" screen.*
-5. Press **Alt +4** to Enter "Date Calculation" mode
+5. Press **Alt +4** to enter "Date Calculation" mode
*Expected: Move to "Date Calculation" screen.*
-6. Press **Ctrl +M** to Store in Memory
-7. Press **Ctrl +P** to Add to Active Memory
-8. Press **Ctrl +Q** to Subtract form Active Memory
-9. Press **Ctrl +R** to Recall from Memory
-10. Press **Ctrl +L** to Clear from Memory
-11. Press **Delete** to Clear Current Input 'CE'
-12. Press **Esc** to Full Clear Input 'C'
-13. Press **F9** to Toggle '±'
-14. Press **R** to Select '1/x'
-15. Press **@** to Select '√'
-16. Press **Ctrl + H** to Toggle History Panel
+6 Press **Alt +5** to enter "Graphing" mode
+*Expected: Move to "Graphing" screen.*
+7. Press **Ctrl +M** to Store in Memory
+8. Press **Ctrl +P** to Add to Active Memory
+9. Press **Ctrl +Q** to Subtract form Active Memory
+10. Press **Ctrl +R** to Recall from Memory
+11. Press **Ctrl +L** to Clear from Memory
+12. Press **Delete** to Clear Current Input 'CE'
+13. Press **Esc** to Full Clear Input 'C'
+14. Press **F9** to Toggle '±'
+15. Press **R** to Select '1/x'
+16. Press **@** to Select '√'
+17. Press **Ctrl + H** to Toggle History Panel
*Expected: Function when in small scale window.*
-17. Press **Up arrow** to Move up History Panel
+18. Press **Up arrow** to Move up History Panel
*Expected: Function when in small scale window.*
-18. Press **Down arrow** to Move Down History Panel
+19. Press **Down arrow** to Move Down History Panel
*Expected: Function when in small scale window.*
-19. Press **Ctrl + Shift + D** to Clear History Panel
+20. Press **Ctrl + Shift + D** to Clear History Panel
*Expected: Function when in small scale window.*
-20. Press **Spacebar** to Repeat Last Input
+21. Press **Spacebar** to Repeat Last Input
Verify the following in Scientific Mode
-21. Press **F3** to Select 'DEG'
-22. Press **F4** to Select 'RAD'
-23. Press **F5** to Select 'GRAD'
-24. Press **Ctrl +G** to Select '10ˣ'
-25. Press **Ctrl +Y** to Select 'y√x'
-26. Press **Shift +O** to Select 'sin-1'
-27. Press **Shift + S** to Select 'cos-1'
-28. Press **Shift +T** to Select 'tan-1'
-29. Press **Ctrl +O** to Select 'Cosh'
-30. Press **Ctrl +S** to Select 'Sinh'
-31. Press **Ctrl +T** to Select 'Tanh'
-32. Press **D** to Select 'Mod'
-33. Press **L** to Select 'log'
-34. Press **M** to Select 'dms'
-35. Press **N** to Select 'ln'
-36. Press **Ctrl +N** to Select 'ex'
-37. Press **O** to Select 'Cos'
-38. Press **P** to Select 'π'
-39. Press **Q** to Select 'x²'
-40. Press **S** to Select 'Sin'
-41. Press **T** to Select 'Tan'
-42. Press **V** to Toggle 'F-E'
-43. Press **X** to Select 'Exp'
-44. Press **Y** or **^** to Select 'xʸ'
-45. Press **#** to Select 'x³'
-46. Press **!** to Select 'n!'
+22. Press **F3** to Select 'DEG'
+23. Press **F4** to Select 'RAD'
+24. Press **F5** to Select 'GRAD'
+25. Press **Ctrl +G** to Select '10ˣ'
+26. Press **Ctrl +Y** to Select 'y√x'
+27. Press **Shift +O** to Select 'sin-1'
+28. Press **Shift + S** to Select 'cos-1'
+29. Press **Shift +T** to Select 'tan-1'
+30. Press **Ctrl +O** to Select 'Cosh'
+31. Press **Ctrl +S** to Select 'Sinh'
+32. Press **Ctrl +T** to Select 'Tanh'
+33. Press **D** to Select 'Mod'
+34. Press **L** to Select 'log'
+35. Press **M** to Select 'dms'
+36. Press **N** to Select 'ln'
+37. Press **Ctrl +N** to Select 'ex'
+38. Press **O** to Select 'Cos'
+39. Press **P** to Select 'π'
+40. Press **Q** to Select 'x²'
+41. Press **S** to Select 'Sin'
+42. Press **T** to Select 'Tan'
+43. Press **V** to Toggle 'F-E'
+44. Press **X** to Select 'Exp'
+45. Press **Y** or **^** to Select 'xʸ'
+46. Press **#** to Select 'x³'
+47. Press **!** to Select 'n!'
Verify the following in Programmer Mode
-47. Press **F2** to Select 'DWORD'
-48. Press **F3** to Select 'WORD'
-49. Press **F4** to Select 'BYTE'
-50. Press **F5** to Select 'HEX'
-51. Press **F6** to Select 'DEC'
-52. Press **F7** to Select 'OCT'
-53. Press **F8** to Select 'BIN'
-54. Press **F12** to Select 'QWORD'
-55. Press **A-F** to Input in HEX
-56. Press **J** to Select 'RoL'
-57. Press **K** to Select 'RoR'
-58. Press **<** to Select 'Lsh'
-59. Press **>** to Select 'Rsh'
-60. Press **%** to Select 'Mod'
-61. Press **|** to Select 'Or'
-62. Press **~** to Select 'Not'
-63. Press **&** to Select 'And'
+48. Press **F2** to Select 'DWORD'
+49. Press **F3** to Select 'WORD'
+50. Press **F4** to Select 'BYTE'
+51. Press **F5** to Select 'HEX'
+52. Press **F6** to Select 'DEC'
+53. Press **F7** to Select 'OCT'
+54. Press **F8** to Select 'BIN'
+55. Press **F12** to Select 'QWORD'
+56. Press **A-F** to Input in HEX
+57. Press **J** to Select 'RoL'
+58. Press **K** to Select 'RoR'
+59. Press **<** to Select 'Lsh'
+60. Press **>** to Select 'Rsh'
+61. Press **%** to Select 'Mod'
+62. Press **|** to Select 'Or'
+63. Press **~** to Select 'Not'
+64. Press **&** to Select 'And'
+
+ Verify the following in Graphing Mode
+65. Press **x** to Select 'x'
+66. Press **y** to Select 'y'
+67. Press **Ctrl +[Numpad+]** to Select 'Zoom In'
+68. Press **Ctrl +[Numpad-]** to Select 'Zoom Out'
## Localization Tests
diff --git a/docs/Roadmap.md b/docs/Roadmap.md
index 0b969c5c..59a4e547 100644
--- a/docs/Roadmap.md
+++ b/docs/Roadmap.md
@@ -4,15 +4,12 @@ Windows Calculator is under active development by Microsoft.
## Focus
-In 2019, the Windows Calculator team is focused on:
-* Refining our open source development process on GitHub
-* Iterating upon the existing app design based on the latest [Fluent Design guidelines](https://developer.microsoft.com/en-us/windows/apps/design)
-* Improving testing and diagnostics within the project
-* Investigating new features with a focus on addressing top user feedback, including:
- * Adding graphing mode
- * Adding the ability for users to pin Calculator on top of other windows
- * Providing additional customization options
- * [Your feature idea here] - please review our [new feature development process](https://github.com/Microsoft/calculator/blob/master/docs/NewFeatureProcess.md) to get started!
+In 2020, the Windows Calculator team is focused on:
+* Iterating upon the existing app design based on the latest guidelines for [Fluent Design](https://developer.microsoft.com/en-us/windows/apps/design), [Windows 10X dual-screen devices](https://docs.microsoft.com/en-us/dual-screen/windows/), and [WinUI 3.0](https://github.com/microsoft/microsoft-ui-xaml).
+* Unblocking community contributions by identifying and addressing bottlenecks affecting developers, including migrating portions of the codebase to C# ([#893](https://github.com/microsoft/calculator/issues/893)) and adding a settings page ([#596](https://github.com/microsoft/calculator/issues/596)).
+* Addressing top user pain points, including clearing up confusion around how Standard Calculator behaves ([#138](https://github.com/microsoft/calculator/issues/138)) and fixing hidden characters in copied results ([#504](https://github.com/microsoft/calculator/issues/504)).
+* Investigating unit converter improvements ([#379](https://github.com/microsoft/calculator/issues/379), [#589](https://github.com/microsoft/calculator/issues/589) and [#594](https://github.com/microsoft/calculator/issues/594))
+* [Your feature idea here] - please review our [new feature development process](https://github.com/Microsoft/calculator/blob/master/docs/NewFeatureProcess.md) to get started!
We welcome contributions of all kinds from the community, but especially those that support the efforts above. Please see our [contributing guidelines](https://github.com/Microsoft/calculator/blob/master/CONTRIBUTING.md) for more information on how to get involved.
diff --git a/nuget.config b/nuget.config
index 0286336f..6ef7f342 100644
--- a/nuget.config
+++ b/nuget.config
@@ -3,4 +3,4 @@
-
\ No newline at end of file
+
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
deleted file mode 100644
index ef903269..00000000
--- a/src/CMakeLists.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-cmake_minimum_required(VERSION 3.13)
-project(calculator CXX)
-set(CMAKE_CXX_STANDARD 17)
-
-if(CMAKE_CXX_COMPILER MATCHES ".*clang")
- # Clang disagress with libstdc++ about constexpr-ness of wstring_view
- # See https://github.com/Microsoft/calculator/pull/321
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
-endif()
-
-add_subdirectory(CalcManager)
diff --git a/src/CalcManager/CEngine/CMakeLists.txt b/src/CalcManager/CEngine/CMakeLists.txt
deleted file mode 100644
index ba4348ff..00000000
--- a/src/CalcManager/CEngine/CMakeLists.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-target_sources(CalcManager PRIVATE
- calc.cpp
- CalcInput.cpp
- CalcUtils.cpp
- History.cpp
- Number.cpp
- Rational.cpp
- RationalMath.cpp
- scicomm.cpp
- scidisp.cpp
- scifunc.cpp
- scioper.cpp
- sciset.cpp
-)
diff --git a/src/CalcManager/CEngine/History.cpp b/src/CalcManager/CEngine/History.cpp
index d3a32ebb..ea73e18c 100644
--- a/src/CalcManager/CEngine/History.cpp
+++ b/src/CalcManager/CEngine/History.cpp
@@ -210,7 +210,7 @@ bool CHistoryCollector::FOpndAddedToHistory()
// This is does the postfix to prefix translation of the input and adds the text to the history. Eg. doing 2 + 4 (sqrt),
// this routine will ensure the last sqrt call unary operator, actually goes back in history and wraps 4 in sqrt(4)
//
-void CHistoryCollector::AddUnaryOpToHistory(int nOpCode, bool fInv, ANGLE_TYPE angletype)
+void CHistoryCollector::AddUnaryOpToHistory(int nOpCode, bool fInv, AngleType angletype)
{
int iCommandEnd;
// When successfully applying a unary op, there should be an opnd already
@@ -230,15 +230,15 @@ void CHistoryCollector::AddUnaryOpToHistory(int nOpCode, bool fInv, ANGLE_TYPE a
else
{
CalculationManager::Command angleOpCode;
- if (angletype == ANGLE_DEG)
+ if (angletype == AngleType::Degrees)
{
angleOpCode = CalculationManager::Command::CommandDEG;
}
- else if (angletype == ANGLE_RAD)
+ else if (angletype == AngleType::Radians)
{
angleOpCode = CalculationManager::Command::CommandRAD;
}
- else // (angletype == ANGLE_GRAD)
+ else // (angletype == AngleType::Gradians)
{
angleOpCode = CalculationManager::Command::CommandGRAD;
}
diff --git a/src/CalcManager/CEngine/Rational.cpp b/src/CalcManager/CEngine/Rational.cpp
index 8eb4a91a..c703f61d 100644
--- a/src/CalcManager/CEngine/Rational.cpp
+++ b/src/CalcManager/CEngine/Rational.cpp
@@ -460,7 +460,7 @@ namespace CalcEngine
return !(lhs < rhs);
}
- wstring Rational::ToString(uint32_t radix, NUMOBJ_FMT fmt, int32_t precision) const
+ wstring Rational::ToString(uint32_t radix, NumberFormat fmt, int32_t precision) const
{
PRAT rat = this->ToPRAT();
wstring result{};
diff --git a/src/CalcManager/CEngine/RationalMath.cpp b/src/CalcManager/CEngine/RationalMath.cpp
index 4b1a4b8a..00b628ab 100644
--- a/src/CalcManager/CEngine/RationalMath.cpp
+++ b/src/CalcManager/CEngine/RationalMath.cpp
@@ -147,7 +147,7 @@ Rational RationalMath::Abs(Rational const& rat)
return Rational{ Number{ 1, rat.P().Exp(), rat.P().Mantissa() }, Number{ 1, rat.Q().Exp(), rat.Q().Mantissa() } };
}
-Rational RationalMath::Sin(Rational const& rat, ANGLE_TYPE angletype)
+Rational RationalMath::Sin(Rational const& rat, AngleType angletype)
{
PRAT prat = rat.ToPRAT();
@@ -167,7 +167,7 @@ Rational RationalMath::Sin(Rational const& rat, ANGLE_TYPE angletype)
return result;
}
-Rational RationalMath::Cos(Rational const& rat, ANGLE_TYPE angletype)
+Rational RationalMath::Cos(Rational const& rat, AngleType angletype)
{
PRAT prat = rat.ToPRAT();
@@ -187,7 +187,7 @@ Rational RationalMath::Cos(Rational const& rat, ANGLE_TYPE angletype)
return result;
}
-Rational RationalMath::Tan(Rational const& rat, ANGLE_TYPE angletype)
+Rational RationalMath::Tan(Rational const& rat, AngleType angletype)
{
PRAT prat = rat.ToPRAT();
@@ -207,7 +207,7 @@ Rational RationalMath::Tan(Rational const& rat, ANGLE_TYPE angletype)
return result;
}
-Rational RationalMath::ASin(Rational const& rat, ANGLE_TYPE angletype)
+Rational RationalMath::ASin(Rational const& rat, AngleType angletype)
{
PRAT prat = rat.ToPRAT();
@@ -227,7 +227,7 @@ Rational RationalMath::ASin(Rational const& rat, ANGLE_TYPE angletype)
return result;
}
-Rational RationalMath::ACos(Rational const& rat, ANGLE_TYPE angletype)
+Rational RationalMath::ACos(Rational const& rat, AngleType angletype)
{
PRAT prat = rat.ToPRAT();
@@ -247,7 +247,7 @@ Rational RationalMath::ACos(Rational const& rat, ANGLE_TYPE angletype)
return result;
}
-Rational RationalMath::ATan(Rational const& rat, ANGLE_TYPE angletype)
+Rational RationalMath::ATan(Rational const& rat, AngleType angletype)
{
PRAT prat = rat.ToPRAT();
diff --git a/src/CalcManager/CEngine/calc.cpp b/src/CalcManager/CEngine/calc.cpp
index c5775379..dd70fb63 100644
--- a/src/CalcManager/CEngine/calc.cpp
+++ b/src/CalcManager/CEngine/calc.cpp
@@ -73,7 +73,7 @@ CCalcEngine::CCalcEngine(
, m_bRecord(false)
, m_bSetCalcState(false)
, m_input(DEFAULT_DEC_SEPARATOR)
- , m_nFE(FMT_FLOAT)
+ , m_nFE(NumberFormat::Float)
, m_memoryValue{ make_unique() }
, m_holdVal{}
, m_currentVal{}
@@ -94,8 +94,8 @@ CCalcEngine::CCalcEngine(
, m_nPrecOp()
, m_precedenceOpCount(0)
, m_nLastCom(0)
- , m_angletype(ANGLE_DEG)
- , m_numwidth(QWORD_WIDTH)
+ , m_angletype(AngleType::Degrees)
+ , m_numwidth(NUM_WIDTH::QWORD_WIDTH)
, m_HistoryCollector(pCalcDisplay, pHistoryDisplay, DEFAULT_DEC_SEPARATOR)
, m_groupSeparator(DEFAULT_GRP_SEPARATOR)
{
@@ -105,7 +105,7 @@ CCalcEngine::CCalcEngine(
m_maxTrigonometricNum = RationalMath::Pow(10, 100);
- SetRadixTypeAndNumWidth(DEC_RADIX, m_numwidth);
+ SetRadixTypeAndNumWidth(RadixType::Decimal, m_numwidth);
SettingsChanged();
DisplayNum();
}
@@ -128,10 +128,20 @@ void CCalcEngine::InitChopNumbers()
auto maxVal = m_chopNumbers[i] / 2;
maxVal = RationalMath::Integer(maxVal);
- m_maxDecimalValueStrings[i] = maxVal.ToString(10, FMT_FLOAT, m_precision);
+ m_maxDecimalValueStrings[i] = maxVal.ToString(10, NumberFormat::Float, m_precision);
}
}
+CalcEngine::Rational CCalcEngine::GetChopNumber() const
+{
+ return m_chopNumbers[static_cast(m_numwidth)];
+}
+
+std::wstring CCalcEngine::GetMaxDecimalValueString() const
+{
+ return m_maxDecimalValueStrings[static_cast(m_numwidth)];
+}
+
// Gets the number in memory for UI to keep it persisted and set it again to a different instance
// of CCalcEngine. Otherwise it will get destructed with the CalcEngine
unique_ptr CCalcEngine::PersistedMemObject()
diff --git a/src/CalcManager/CEngine/scicomm.cpp b/src/CalcManager/CEngine/scicomm.cpp
index f7509ab3..20e60a29 100644
--- a/src/CalcManager/CEngine/scicomm.cpp
+++ b/src/CalcManager/CEngine/scicomm.cpp
@@ -35,19 +35,16 @@ namespace
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;
+ IDC_PWR,4, IDC_ROOT,4, IDC_LOGBASEY,4 };
- iPrec = 0;
- while ((iPrec < size(rgbPrec)) && (nopCode != rgbPrec[iPrec]))
+ for (unsigned int iPrec = 0; iPrec < size(rgbPrec); iPrec += 2)
{
- iPrec += 2;
+ if (nopCode == rgbPrec[iPrec])
+ {
+ return rgbPrec[iPrec + 1];
+ }
}
- if (iPrec >= size(rgbPrec))
- {
- iPrec = 0;
- }
- return rgbPrec[iPrec + 1];
+ return 0;
}
}
@@ -104,8 +101,6 @@ void CCalcEngine::ProcessCommand(OpCode wParam)
void CCalcEngine::ProcessCommandWorker(OpCode wParam)
{
- int nx, ni;
-
// Save the last command. Some commands are not saved in this manor, these
// commands are:
// Inv, Deg, Rad, Grad, Stat, FE, MClear, Back, and Exp. The excluded
@@ -163,14 +158,11 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
DisplayNum(); // Causes 3.000 to shrink to 3. on first op.
}
}
- else
+ else if (IsDigitOpCode(wParam) || wParam == IDC_PNT)
{
- if (IsDigitOpCode(wParam) || wParam == IDC_PNT)
- {
- m_bRecord = true;
- m_input.Clear();
- CheckAndAddLastBinOpToHistory();
- }
+ m_bRecord = true;
+ m_input.Clear();
+ CheckAndAddLastBinOpToHistory();
}
// Interpret digit keys.
@@ -185,7 +177,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
return;
}
- if (!m_input.TryAddDigit(iValue, m_radix, m_fIntegerMode, m_maxDecimalValueStrings[m_numwidth], m_dwWordBitWidth, m_cIntDigitsSav))
+ if (!m_input.TryAddDigit(iValue, m_radix, m_fIntegerMode, GetMaxDecimalValueString(), m_dwWordBitWidth, m_cIntDigitsSav))
{
HandleErrorCommand(wParam);
HandleMaxDigitsReached();
@@ -203,7 +195,6 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
// Change the operation if last input was operation.
if (IsBinOpCode(m_nLastCom))
{
- int nPrev;
bool fPrecInvToHigher = false; // Is Precedence Inversion from lower to higher precedence happening ??
m_nOpCode = (int)wParam;
@@ -214,9 +205,9 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
// Here * is m_nPrevOpCode, m_currentVal is 2 (by 1*2), m_nLastCom is +, m_nOpCode is ^
if (m_fPrecedence && 0 != m_nPrevOpCode)
{
- nPrev = NPrecedenceOfOp(m_nPrevOpCode);
- nx = NPrecedenceOfOp(m_nLastCom);
- ni = NPrecedenceOfOp(m_nOpCode);
+ int nPrev = NPrecedenceOfOp(m_nPrevOpCode);
+ int nx = NPrecedenceOfOp(m_nLastCom);
+ int ni = NPrecedenceOfOp(m_nOpCode);
if (nx <= nPrev && ni > nPrev) // condition for Precedence Inversion
{
fPrecInvToHigher = true;
@@ -243,8 +234,8 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
{
DoPrecedenceCheckAgain:
- nx = NPrecedenceOfOp((int)wParam);
- ni = NPrecedenceOfOp(m_nOpCode);
+ int nx = NPrecedenceOfOp((int)wParam);
+ int ni = NPrecedenceOfOp(m_nOpCode);
if ((nx > ni) && m_fPrecedence)
{
@@ -492,8 +483,8 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
m_lastVal = m_precedenceVals[m_precedenceOpCount];
// Precedence Inversion check
- ni = NPrecedenceOfOp(m_nPrevOpCode);
- nx = NPrecedenceOfOp(m_nOpCode);
+ int ni = NPrecedenceOfOp(m_nPrevOpCode);
+ int nx = NPrecedenceOfOp(m_nOpCode);
if (ni <= nx)
{
m_HistoryCollector.EnclosePrecInversionBrackets();
@@ -518,20 +509,15 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
case IDC_OPENP:
case IDC_CLOSEP:
- nx = 0;
- if (wParam == IDC_OPENP)
- {
- nx = 1;
- }
// -IF- the Paren holding array is full and we try to add a paren
// -OR- the paren holding array is empty and we try to remove a
// paren
// -OR- the precedence holding array is full
- if ((m_openParenCount >= MAXPRECDEPTH && nx) || (!m_openParenCount && !nx)
+ if ((m_openParenCount >= MAXPRECDEPTH && (wParam == IDC_OPENP)) || (!m_openParenCount && (wParam != IDC_OPENP))
|| ((m_precedenceOpCount >= MAXPRECDEPTH && m_nPrecOp[m_precedenceOpCount - 1] != 0)))
{
- if (!m_openParenCount && !nx)
+ if (!m_openParenCount && (wParam != IDC_OPENP))
{
m_pCalcDisplay->OnNoRightParenAdded();
}
@@ -540,7 +526,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
break;
}
- if (nx)
+ if (wParam == IDC_OPENP)
{
CheckAndAddLastBinOpToHistory();
m_HistoryCollector.AddOpenBraceToHistory();
@@ -588,8 +574,8 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
for (m_nOpCode = m_nPrecOp[--m_precedenceOpCount]; m_nOpCode; m_nOpCode = m_nPrecOp[--m_precedenceOpCount])
{
// Precedence Inversion check
- ni = NPrecedenceOfOp(m_nPrevOpCode);
- nx = NPrecedenceOfOp(m_nOpCode);
+ int ni = NPrecedenceOfOp(m_nPrevOpCode);
+ int nx = NPrecedenceOfOp(m_nOpCode);
if (ni <= nx)
{
m_HistoryCollector.EnclosePrecInversionBrackets();
@@ -633,7 +619,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
case IDM_OCT:
case IDM_BIN:
{
- SetRadixTypeAndNumWidth((RADIX_TYPE)(wParam - IDM_HEX), (NUM_WIDTH)-1);
+ SetRadixTypeAndNumWidth((RadixType)(wParam - IDM_HEX), (NUM_WIDTH)-1);
m_HistoryCollector.UpdateHistoryExpression(m_radix, m_precision);
break;
}
@@ -649,20 +635,20 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
}
// Compat. mode BaseX: Qword, Dword, Word, Byte
- SetRadixTypeAndNumWidth((RADIX_TYPE)-1, (NUM_WIDTH)(wParam - IDM_QWORD));
+ SetRadixTypeAndNumWidth((RadixType)-1, (NUM_WIDTH)(wParam - IDM_QWORD));
break;
case IDM_DEG:
case IDM_RAD:
case IDM_GRAD:
- m_angletype = static_cast(wParam - IDM_DEG);
+ m_angletype = static_cast(wParam - IDM_DEG);
break;
case IDC_SIGN:
{
if (m_bRecord)
{
- if (m_input.TryToggleSign(m_fIntegerMode, m_maxDecimalValueStrings[m_numwidth]))
+ if (m_input.TryToggleSign(m_fIntegerMode, GetMaxDecimalValueString()))
{
DisplayNum();
}
@@ -780,7 +766,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
break;
case IDC_FE:
// Toggle exponential notation display.
- m_nFE = NUMOBJ_FMT(!(int)m_nFE);
+ m_nFE = NumberFormat(!(int)m_nFE);
DisplayNum();
break;
@@ -952,7 +938,7 @@ static const std::unordered_map operatorStringTable =
{ 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 } },
@@ -962,7 +948,7 @@ static const std::unordered_map operatorStringTable =
{ IDC_SIGN, { SIDS_NEGATE } },
{ IDC_DEGREES, { SIDS_DEGREES } },
{ IDC_POW2, { SIDS_TWOPOWX } },
- { IDC_LOGBASEX, { SIDS_LOGBASEX } },
+ { IDC_LOGBASEY, { SIDS_LOGBASEY } },
{ IDC_ABS, { SIDS_ABS } },
{ IDC_CEIL, { SIDS_CEIL } },
{ IDC_FLOOR, { SIDS_FLOOR } },
@@ -971,11 +957,11 @@ static const std::unordered_map operatorStringTable =
{ 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} },
+ { 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)
+wstring_view CCalcEngine::OpCodeToUnaryString(int nOpCode, bool fInv, AngleType angletype)
{
// Try to lookup the ID in the UFNE table
wstring ids = L"";
@@ -983,7 +969,7 @@ wstring_view CCalcEngine::OpCodeToUnaryString(int nOpCode, bool fInv, ANGLE_TYPE
if (auto pair = operatorStringTable.find(nOpCode); pair != operatorStringTable.end())
{
const FunctionNameElement& element = pair->second;
- if (!element.hasAngleStrings || ANGLE_DEG == angletype)
+ if (!element.hasAngleStrings || AngleType::Degrees == angletype)
{
if (fInv)
{
@@ -995,7 +981,7 @@ wstring_view CCalcEngine::OpCodeToUnaryString(int nOpCode, bool fInv, ANGLE_TYPE
ids = element.degreeString;
}
}
- else if (ANGLE_RAD == angletype)
+ else if (AngleType::Radians == angletype)
{
if (fInv)
{
@@ -1006,7 +992,7 @@ wstring_view CCalcEngine::OpCodeToUnaryString(int nOpCode, bool fInv, ANGLE_TYPE
ids = element.radString;
}
}
- else if (ANGLE_GRAD == angletype)
+ else if (AngleType::Gradians == angletype)
{
if (fInv)
{
@@ -1059,7 +1045,7 @@ bool CCalcEngine::IsCurrentTooBigForTrig()
return m_currentVal >= m_maxTrigonometricNum;
}
-int CCalcEngine::GetCurrentRadix()
+uint32_t CCalcEngine::GetCurrentRadix()
{
return m_radix;
}
@@ -1108,7 +1094,7 @@ wstring CCalcEngine::GetStringForDisplay(Rational const& rat, uint32_t radix)
if ((radix == 10) && fMsb)
{
// If high bit is set, then get the decimal number in negative 2's complement form.
- tempRat = -((tempRat ^ m_chopNumbers[m_numwidth]) + 1);
+ tempRat = -((tempRat ^ GetChopNumber()) + 1);
}
result = tempRat.ToString(radix, m_nFE, m_precision);
diff --git a/src/CalcManager/CEngine/scidisp.cpp b/src/CalcManager/CEngine/scidisp.cpp
index 632969fd..0074c77a 100644
--- a/src/CalcManager/CEngine/scidisp.cpp
+++ b/src/CalcManager/CEngine/scidisp.cpp
@@ -67,10 +67,10 @@ CalcEngine::Rational CCalcEngine::TruncateNumForIntMath(CalcEngine::Rational con
{
// if negative make positive by doing a twos complement
result = -(result)-1;
- result ^= m_chopNumbers[m_numwidth];
+ result ^= GetChopNumber();
}
- result &= m_chopNumbers[m_numwidth];
+ result &= GetChopNumber();
return result;
}
@@ -85,7 +85,7 @@ void CCalcEngine::DisplayNum(void)
// called.
//
if (m_bRecord || gldPrevious.value != m_currentVal || gldPrevious.precision != m_precision || gldPrevious.radix != m_radix || gldPrevious.nFE != (int)m_nFE
- || gldPrevious.bUseSep != true || gldPrevious.numwidth != m_numwidth || gldPrevious.fIntMath != m_fIntegerMode || gldPrevious.bRecord != m_bRecord)
+ || !gldPrevious.bUseSep || gldPrevious.numwidth != m_numwidth || gldPrevious.fIntMath != m_fIntegerMode || gldPrevious.bRecord != m_bRecord)
{
gldPrevious.precision = m_precision;
gldPrevious.radix = m_radix;
diff --git a/src/CalcManager/CEngine/scifunc.cpp b/src/CalcManager/CEngine/scifunc.cpp
index 15ef164b..b767968a 100644
--- a/src/CalcManager/CEngine/scifunc.cpp
+++ b/src/CalcManager/CEngine/scifunc.cpp
@@ -42,7 +42,7 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
}
else
{
- result = rat ^ m_chopNumbers[m_numwidth];
+ result = rat ^ GetChopNumber();
}
break;
diff --git a/src/CalcManager/CEngine/scioper.cpp b/src/CalcManager/CEngine/scioper.cpp
index 6ea3956b..fdb9a7c0 100644
--- a/src/CalcManager/CEngine/scioper.cpp
+++ b/src/CalcManager/CEngine/scioper.cpp
@@ -29,11 +29,11 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa
break;
case IDC_NAND:
- result = (result & rhs) ^ m_chopNumbers[m_numwidth];
+ result = (result & rhs) ^ GetChopNumber();
break;
case IDC_NOR:
- result = (result | rhs) ^ m_chopNumbers[m_numwidth];
+ result = (result | rhs) ^ GetChopNumber();
break;
case IDC_RSHF:
@@ -53,10 +53,10 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa
{
result = Integer(result);
- auto tempRat = m_chopNumbers[m_numwidth] >> holdVal;
+ auto tempRat = GetChopNumber() >> holdVal;
tempRat = Integer(tempRat);
- result |= tempRat ^ m_chopNumbers[m_numwidth];
+ result |= tempRat ^ GetChopNumber();
}
break;
}
@@ -105,7 +105,7 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa
if (fMsb)
{
- result = (rhs ^ m_chopNumbers[m_numwidth]) + 1;
+ result = (rhs ^ GetChopNumber()) + 1;
iNumeratorSign = -1;
}
@@ -115,7 +115,7 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa
if (fMsb)
{
- temp = (temp ^ m_chopNumbers[m_numwidth]) + 1;
+ temp = (temp ^ GetChopNumber()) + 1;
iDenominatorSign = -1;
}
@@ -158,8 +158,8 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa
result = Root(rhs, result);
break;
- case IDC_LOGBASEX:
- result = (Log(result) / Log(rhs));
+ case IDC_LOGBASEY:
+ result = (Log(rhs) / Log(result));
break;
}
}
diff --git a/src/CalcManager/CEngine/sciset.cpp b/src/CalcManager/CEngine/sciset.cpp
index 676ab0eb..cb143559 100644
--- a/src/CalcManager/CEngine/sciset.cpp
+++ b/src/CalcManager/CEngine/sciset.cpp
@@ -9,7 +9,7 @@ using namespace std;
// To be called when either the radix or num width changes. You can use -1 in either of these values to mean
// dont change that.
-void CCalcEngine::SetRadixTypeAndNumWidth(RADIX_TYPE radixtype, NUM_WIDTH numwidth)
+void CCalcEngine::SetRadixTypeAndNumWidth(RadixType radixtype, NUM_WIDTH numwidth)
{
// When in integer mode, the number is represented in 2's complement form. When a bit width is changing, we can
// change the number representation back to sign, abs num form in ratpak. Soon when display sees this, it will
@@ -24,19 +24,19 @@ void CCalcEngine::SetRadixTypeAndNumWidth(RADIX_TYPE radixtype, NUM_WIDTH numwid
if (fMsb)
{
// If high bit is set, then get the decimal number in -ve 2'scompl form.
- auto tempResult = m_currentVal ^ m_chopNumbers[m_numwidth];
+ auto tempResult = m_currentVal ^ GetChopNumber();
m_currentVal = -(tempResult + 1);
}
}
- if (radixtype >= HEX_RADIX && radixtype <= BIN_RADIX)
+ if (radixtype >= RadixType::Hex && radixtype <= RadixType::Binary)
{
m_radix = NRadixFromRadixType(radixtype);
// radixtype is not even saved
}
- if (numwidth >= QWORD_WIDTH && numwidth <= BYTE_WIDTH)
+ if (numwidth >= NUM_WIDTH::QWORD_WIDTH && numwidth <= NUM_WIDTH::BYTE_WIDTH)
{
m_numwidth = numwidth;
m_dwWordBitWidth = DwWordBitWidthFromeNumWidth(numwidth);
@@ -50,29 +50,36 @@ void CCalcEngine::SetRadixTypeAndNumWidth(RADIX_TYPE radixtype, NUM_WIDTH numwid
DisplayNum();
}
-int32_t CCalcEngine::DwWordBitWidthFromeNumWidth(NUM_WIDTH /*numwidth*/)
+int32_t CCalcEngine::DwWordBitWidthFromeNumWidth(NUM_WIDTH numwidth)
{
- static constexpr int nBitMax[] = { 64, 32, 16, 8 };
- int32_t wmax = nBitMax[0];
-
- if (m_numwidth >= 0 && (size_t)m_numwidth < size(nBitMax))
+ switch (numwidth)
{
- wmax = nBitMax[m_numwidth];
+ case NUM_WIDTH::DWORD_WIDTH:
+ return 32;
+ case NUM_WIDTH::WORD_WIDTH:
+ return 16;
+ case NUM_WIDTH::BYTE_WIDTH:
+ return 8;
+ case NUM_WIDTH::QWORD_WIDTH:
+ default:
+ return 64;
}
- return wmax;
}
-uint32_t CCalcEngine::NRadixFromRadixType(RADIX_TYPE radixtype)
+uint32_t CCalcEngine::NRadixFromRadixType(RadixType radixtype)
{
- static constexpr uint32_t rgnRadish[4] = { 16, 10, 8, 2 }; /* Number bases in the same order as radixtype */
- uint32_t radix = 10;
-
- // convert special bases into symbolic values
- if (radixtype >= 0 && (size_t)radixtype < size(rgnRadish))
+ switch (radixtype)
{
- radix = rgnRadish[radixtype];
+ case RadixType::Hex:
+ return 16;
+ case RadixType::Octal:
+ return 8;
+ case RadixType::Binary:
+ return 2;
+ case RadixType::Decimal:
+ default:
+ return 10;
}
- return radix;
}
// Toggles a given bit into the number representation. returns true if it changed it actually.
@@ -141,7 +148,7 @@ void CCalcEngine::UpdateMaxIntDigits()
// if in integer mode you still have to honor the max digits you can enter based on bit width
if (m_fIntegerMode)
{
- m_cIntDigitsSav = static_cast(m_maxDecimalValueStrings[m_numwidth].length()) - 1;
+ m_cIntDigitsSav = static_cast(GetMaxDecimalValueString().length()) - 1;
// This is the max digits you can enter a decimal in fixed width mode aka integer mode -1. The last digit
// has to be checked separately
}
diff --git a/src/CalcManager/CMakeLists.txt b/src/CalcManager/CMakeLists.txt
deleted file mode 100644
index c02bc78d..00000000
--- a/src/CalcManager/CMakeLists.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-add_library(CalcManager
- CalculatorHistory.cpp
- CalculatorManager.cpp
- ExpressionCommand.cpp
- pch.cpp
- UnitConverter.cpp
-)
-target_include_directories(CalcManager PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
-
-add_subdirectory(Ratpack)
-add_subdirectory(CEngine)
diff --git a/src/CalcManager/CalcManager.vcxproj b/src/CalcManager/CalcManager.vcxproj
index b30b3976..80940c6a 100644
--- a/src/CalcManager/CalcManager.vcxproj
+++ b/src/CalcManager/CalcManager.vcxproj
@@ -132,29 +132,9 @@
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
+
false
+ true
@@ -366,4 +346,4 @@
-
\ No newline at end of file
+
diff --git a/src/CalcManager/CalculatorHistory.cpp b/src/CalcManager/CalculatorHistory.cpp
index 6c9a002b..467cd420 100644
--- a/src/CalcManager/CalculatorHistory.cpp
+++ b/src/CalcManager/CalculatorHistory.cpp
@@ -41,21 +41,13 @@ unsigned int CalculatorHistory::AddToHistory(
_In_ shared_ptr>> const& commands,
wstring_view result)
{
- unsigned int addedIndex;
shared_ptr spHistoryItem = make_shared();
spHistoryItem->historyItemVector.spTokens = tokens;
spHistoryItem->historyItemVector.spCommands = commands;
-
- // to be changed when pszexp is back
- 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';
+ spHistoryItem->historyItemVector.expression = GetGeneratedExpression(*tokens);
spHistoryItem->historyItemVector.result = wstring(result);
- addedIndex = AddItem(spHistoryItem);
-
- return addedIndex;
+ return AddItem(spHistoryItem);
}
unsigned int CalculatorHistory::AddItem(_In_ shared_ptr const& spHistoryItem)
@@ -66,19 +58,18 @@ unsigned int CalculatorHistory::AddItem(_In_ shared_ptr const& spHi
}
m_historyItems.push_back(spHistoryItem);
- unsigned int lastIndex = static_cast(m_historyItems.size() - 1);
- return lastIndex;
+ return static_cast(m_historyItems.size() - 1);
}
bool CalculatorHistory::RemoveItem(unsigned int uIdx)
{
- if (uIdx > m_historyItems.size() - 1)
+ if (uIdx < m_historyItems.size())
{
- return false;
+ m_historyItems.erase(m_historyItems.begin() + uIdx);
+ return true;
}
- m_historyItems.erase(m_historyItems.begin() + uIdx);
- return true;
+ return false;
}
vector> const& CalculatorHistory::GetHistory()
diff --git a/src/CalcManager/CalculatorHistory.h b/src/CalcManager/CalculatorHistory.h
index e8c874a0..2c849906 100644
--- a/src/CalcManager/CalculatorHistory.h
+++ b/src/CalcManager/CalculatorHistory.h
@@ -7,12 +7,6 @@
namespace CalculationManager
{
- enum CALCULATOR_MODE
- {
- CM_STD = 0,
- CM_SCI,
- };
-
struct HISTORYITEMVECTOR
{
std::shared_ptr>> spTokens;
diff --git a/src/CalcManager/CalculatorManager.cpp b/src/CalcManager/CalculatorManager.cpp
index 8d6f1e51..a5e2f18c 100644
--- a/src/CalcManager/CalculatorManager.cpp
+++ b/src/CalcManager/CalculatorManager.cpp
@@ -10,16 +10,11 @@ using namespace std;
using namespace CalcEngine;
static constexpr size_t MAX_HISTORY_ITEMS = 20;
-static constexpr size_t SERIALIZED_NUMBER_MINSIZE = 3;
#ifndef _MSC_VER
#define __pragma(x)
#endif
-// Converts Memory Command enum value to unsigned char,
-// while ignoring Warning C4309: 'conversion' : truncation of constant value
-#define MEMORY_COMMAND_TO_UNSIGNED_CHAR(c) __pragma(warning(push)) __pragma(warning(disable : 4309)) static_cast(c) __pragma(warning(pop))
-
namespace CalculationManager
{
CalculatorManager::CalculatorManager(_In_ ICalcDisplay* displayCallback, _In_ IResourceProvider* resourceProvider)
@@ -30,9 +25,9 @@ namespace CalculationManager
, m_persistedPrimaryValue()
, m_isExponentialFormat(false)
, m_currentDegreeMode(Command::CommandNULL)
- , m_savedDegreeMode(Command::CommandDEG)
, m_pStdHistory(new CalculatorHistory(MAX_HISTORY_ITEMS))
, m_pSciHistory(new CalculatorHistory(MAX_HISTORY_ITEMS))
+ , m_pHistory(nullptr)
{
CCalcEngine::InitialOneTimeOnlySetup(*m_resourceProvider);
}
@@ -131,7 +126,6 @@ namespace CalculationManager
///
void CalculatorManager::Reset(bool clearMemory /* = true*/)
{
- m_savedCommands.clear();
SetStandardMode();
if (m_scientificCalculatorEngine)
@@ -238,13 +232,6 @@ namespace CalculationManager
m_currentCalculatorEngine->ProcessCommand(static_cast(command));
}
- m_savedCommands.clear(); // Clear the previous command history
-
- if (command != Command::CommandEQU && command != Command::CommandCLEAR)
- {
- m_savedCommands.push_back(MapCommandForSerialize(command));
- }
- m_savedDegreeMode = m_currentDegreeMode;
InputChanged();
return;
}
@@ -254,11 +241,6 @@ namespace CalculationManager
m_currentDegreeMode = command;
}
- if (command != Command::CommandFE)
- {
- m_savedCommands.push_back(MapCommandForSerialize(command)); // Save the commands in the m_savedCommands
- }
-
switch (command)
{
case Command::CommandASIN:
@@ -324,37 +306,6 @@ namespace CalculationManager
InputChanged();
}
- ///
- /// Convert Command to unsigned char.
- /// Since some Commands are higher than 255, they are saved after subtracting 255
- /// The smallest Command is CommandSIGN = 80, thus, subtracted value does not overlap with other values.
- ///
- /// Enum Command
- unsigned char CalculatorManager::MapCommandForSerialize(Command command)
- {
- unsigned int commandToSave = static_cast(command);
- if (commandToSave > UCHAR_MAX)
- {
- commandToSave -= UCHAR_MAX;
- }
- return static_cast(commandToSave);
- }
-
- ///
- /// Convert Command to unsigned int
- /// The command that is smaller than 80, CommandSIGN, can be converted back to original value by adding 255.
- ///
- /// unsigned char value represent the saved command
- unsigned int CalculatorManager::MapCommandForDeSerialize(unsigned char command)
- {
- unsigned int commandToLoad = command;
- if (command < static_cast(Command::CommandSIGN))
- {
- commandToLoad += UCHAR_MAX;
- }
- return commandToLoad;
- }
-
///
/// Load the persisted value that is saved in memory of CalcEngine
///
@@ -371,8 +322,6 @@ namespace CalculationManager
///
void CalculatorManager::MemorizeNumber()
{
- m_savedCommands.push_back(MEMORY_COMMAND_TO_UNSIGNED_CHAR(MemoryCommand::MemorizeNumber));
-
if (m_currentCalculatorEngine->FInErrorState())
{
return;
@@ -400,8 +349,6 @@ namespace CalculationManager
/// Index of the target memory
void CalculatorManager::MemorizedNumberLoad(_In_ unsigned int indexOfMemory)
{
- SaveMemoryCommand(MemoryCommand::MemorizedNumberLoad, indexOfMemory);
-
if (m_currentCalculatorEngine->FInErrorState())
{
return;
@@ -420,8 +367,6 @@ namespace CalculationManager
/// Index of the target memory
void CalculatorManager::MemorizedNumberAdd(_In_ unsigned int indexOfMemory)
{
- SaveMemoryCommand(MemoryCommand::MemorizedNumberAdd, indexOfMemory);
-
if (m_currentCalculatorEngine->FInErrorState())
{
return;
@@ -448,7 +393,6 @@ namespace CalculationManager
{
if (indexOfMemory < m_memorizedNumbers.size())
{
- SaveMemoryCommand(MemoryCommand::MemorizedNumberClear, indexOfMemory);
m_memorizedNumbers.erase(m_memorizedNumbers.begin() + indexOfMemory);
}
}
@@ -461,8 +405,6 @@ namespace CalculationManager
/// Index of the target memory
void CalculatorManager::MemorizedNumberSubtract(_In_ unsigned int indexOfMemory)
{
- SaveMemoryCommand(MemoryCommand::MemorizedNumberSubtract, indexOfMemory);
-
if (m_currentCalculatorEngine->FInErrorState())
{
return;
@@ -494,7 +436,6 @@ namespace CalculationManager
///
void CalculatorManager::MemorizedNumberClearAll()
{
- m_savedCommands.push_back(MEMORY_COMMAND_TO_UNSIGNED_CHAR(MemoryCommand::MemorizedNumberClearAll));
m_memorizedNumbers.clear();
m_currentCalculatorEngine->ProcessCommand(IDC_MCLEAR);
@@ -536,24 +477,14 @@ namespace CalculationManager
}
}
- void CalculatorManager::SaveMemoryCommand(_In_ MemoryCommand command, _In_ unsigned int indexOfMemory)
- {
- m_savedCommands.push_back(MEMORY_COMMAND_TO_UNSIGNED_CHAR(command));
- if (indexOfMemory > UCHAR_MAX)
- {
- throw invalid_argument("Unexpected value. IndexOfMemory is bigger than the biggest unsigned char");
- }
- m_savedCommands.push_back(static_cast(indexOfMemory));
- }
-
vector> const& CalculatorManager::GetHistoryItems()
{
return m_pHistory->GetHistory();
}
- vector> const& CalculatorManager::GetHistoryItems(_In_ CALCULATOR_MODE mode)
+ vector> const& CalculatorManager::GetHistoryItems(_In_ CalculatorMode mode)
{
- return (mode == CM_STD) ? m_pStdHistory->GetHistory() : m_pSciHistory->GetHistory();
+ return (mode == CalculatorMode::Standard) ? m_pStdHistory->GetHistory() : m_pSciHistory->GetHistory();
}
shared_ptr const& CalculatorManager::GetHistoryItem(_In_ unsigned int uIdx)
@@ -576,20 +507,20 @@ namespace CalculationManager
m_pHistory->ClearHistory();
}
- void CalculatorManager::SetRadix(RADIX_TYPE iRadixType)
+ void CalculatorManager::SetRadix(RadixType iRadixType)
{
switch (iRadixType)
{
- case RADIX_TYPE::HEX_RADIX:
+ case RadixType::Hex:
m_currentCalculatorEngine->ProcessCommand(IDC_HEX);
break;
- case RADIX_TYPE::DEC_RADIX:
+ case RadixType::Decimal:
m_currentCalculatorEngine->ProcessCommand(IDC_DEC);
break;
- case RADIX_TYPE::OCT_RADIX:
+ case RadixType::Octal:
m_currentCalculatorEngine->ProcessCommand(IDC_OCT);
break;
- case RADIX_TYPE::BIN_RADIX:
+ case RadixType::Binary:
m_currentCalculatorEngine->ProcessCommand(IDC_BIN);
break;
default:
@@ -603,7 +534,7 @@ namespace CalculationManager
vector resultVector;
for (auto const& memoryItem : m_memorizedNumbers)
{
- int radix = m_currentCalculatorEngine->GetCurrentRadix();
+ auto radix = m_currentCalculatorEngine->GetCurrentRadix();
wstring stringValue = m_currentCalculatorEngine->GetStringForDisplay(memoryItem, radix);
if (!stringValue.empty())
@@ -623,30 +554,6 @@ namespace CalculationManager
return m_currentDegreeMode;
}
- void CalculatorManager::SetHistory(_In_ CALCULATOR_MODE eMode, _In_ vector> const& history)
- {
- CalculatorHistory* pHistory = nullptr;
-
- switch (eMode)
- {
- case CM_STD:
- pHistory = m_pStdHistory.get();
- break;
- case CM_SCI:
- pHistory = m_pSciHistory.get();
- break;
- }
-
- if (pHistory)
- {
- pHistory->ClearHistory();
- for (auto const& historyItem : history)
- {
- pHistory->AddItem(historyItem);
- }
- }
- }
-
wstring CalculatorManager::GetResultForRadix(uint32_t radix, int32_t precision, bool groupDigitsPerRadix)
{
return m_currentCalculatorEngine ? m_currentCalculatorEngine->GetCurrentResultForRadix(radix, precision, groupDigitsPerRadix) : L"";
@@ -669,7 +576,7 @@ namespace CalculationManager
bool CalculatorManager::IsEngineRecording()
{
- return m_currentCalculatorEngine->FInRecordingState() ? true : false;
+ return m_currentCalculatorEngine->FInRecordingState();
}
bool CalculatorManager::IsInputEmpty()
diff --git a/src/CalcManager/CalculatorManager.h b/src/CalcManager/CalculatorManager.h
index dd30c16a..88a8457b 100644
--- a/src/CalcManager/CalculatorManager.h
+++ b/src/CalcManager/CalculatorManager.h
@@ -15,9 +15,8 @@ namespace CalculationManager
enum class CalculatorMode
{
- StandardMode,
- ScientificMode,
- ProgrammerMode,
+ Standard = 0,
+ Scientific,
};
enum class CalculatorPrecision
@@ -45,6 +44,7 @@ namespace CalculationManager
class CalculatorManager final : public ICalcDisplay
{
private:
+ static const unsigned int m_maximumMemorySize = 100;
ICalcDisplay* const m_displayCallback;
CCalcEngine* m_currentCalculatorEngine;
std::unique_ptr m_scientificCalculatorEngine;
@@ -55,21 +55,8 @@ namespace CalculationManager
std::vector m_memorizedNumbers;
CalcEngine::Rational m_persistedPrimaryValue;
-
bool m_isExponentialFormat;
-
- static const unsigned int m_maximumMemorySize = 100;
-
- // For persistence
- std::vector m_savedCommands;
- std::vector m_savedPrimaryValue;
- std::vector m_currentSerializedMemory;
Command m_currentDegreeMode;
- Command m_savedDegreeMode;
- unsigned char MapCommandForSerialize(Command command);
- unsigned int MapCommandForDeSerialize(unsigned char command);
-
- void SaveMemoryCommand(_In_ MemoryCommand command, _In_ unsigned int indexOfMemory);
void MemorizedNumberSelect(_In_ unsigned int);
void MemorizedNumberChanged(_In_ unsigned int);
@@ -113,11 +100,7 @@ namespace CalculationManager
bool IsEngineRecording();
bool IsInputEmpty();
- const std::vector& GetSavedCommands() const
- {
- return m_savedCommands;
- }
- void SetRadix(RADIX_TYPE iRadixType);
+ void SetRadix(RadixType iRadixType);
void SetMemorizedNumbersString();
std::wstring GetResultForRadix(uint32_t radix, int32_t precision, bool groupDigitsPerRadix);
void SetPrecision(int32_t precision);
@@ -125,7 +108,7 @@ namespace CalculationManager
wchar_t DecimalSeparator();
std::vector> const& GetHistoryItems();
- std::vector> const& GetHistoryItems(_In_ CalculationManager::CALCULATOR_MODE mode);
+ std::vector> const& GetHistoryItems(_In_ CalculatorMode mode);
std::shared_ptr const& GetHistoryItem(_In_ unsigned int uIdx);
bool RemoveHistoryItem(_In_ unsigned int uIdx);
void ClearHistory();
@@ -134,7 +117,6 @@ namespace CalculationManager
return m_pHistory->MaxHistorySize();
}
CalculationManager::Command GetCurrentDegreeMode();
- void SetHistory(_In_ CALCULATOR_MODE eMode, _In_ std::vector> const& history);
void SetInHistoryItemLoadMode(_In_ bool isHistoryItemLoadMode);
};
}
diff --git a/src/CalcManager/CalculatorVector.h b/src/CalcManager/CalculatorVector.h
new file mode 100644
index 00000000..4a139c8e
--- /dev/null
+++ b/src/CalcManager/CalculatorVector.h
@@ -0,0 +1,156 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#pragma once
+
+#include
+#include
+#include "winerror_cross_platform.h"
+#include "Ratpack/CalcErr.h"
+#include // for std::out_of_range
+#include "sal_cross_platform.h" // for SAL
+
+template
+class CalculatorVector
+{
+public:
+ ResultCode GetAt(_In_opt_ unsigned int index, _Out_ TType* item)
+ {
+ try
+ {
+ *item = m_vector.at(index);
+ }
+ catch (const std::out_of_range& /*ex*/)
+ {
+ return E_BOUNDS;
+ }
+ return S_OK;
+ }
+
+ ResultCode GetSize(_Out_ unsigned int* size)
+ {
+ *size = static_cast(m_vector.size());
+ return S_OK;
+ }
+
+ ResultCode SetAt(_In_ unsigned int index, _In_opt_ TType item)
+ {
+ try
+ {
+ m_vector[index] = item;
+ }
+ catch (const std::out_of_range& /*ex*/)
+ {
+ return E_BOUNDS;
+ }
+ return S_OK;
+ }
+
+ ResultCode RemoveAt(_In_ unsigned int index)
+ {
+ if (index < m_vector.size())
+ {
+ m_vector.erase(m_vector.begin() + index);
+ }
+ else
+ {
+ return E_BOUNDS;
+ }
+ return S_OK;
+ }
+
+ ResultCode InsertAt(_In_ unsigned int index, _In_ TType item)
+ {
+ try
+ {
+ auto iter = m_vector.begin() + index;
+ m_vector.insert(iter, item);
+ }
+ catch (const std::bad_alloc& /*ex*/)
+ {
+ return E_OUTOFMEMORY;
+ }
+ return S_OK;
+ }
+
+ ResultCode Truncate(_In_ unsigned int index)
+ {
+ if (index < m_vector.size())
+ {
+ auto startIter = m_vector.begin() + index;
+ m_vector.erase(startIter, m_vector.end());
+ }
+ else
+ {
+ return E_BOUNDS;
+ }
+ return S_OK;
+ }
+
+ ResultCode Append(_In_opt_ TType item)
+ {
+ try
+ {
+ m_vector.push_back(item);
+ }
+ catch (const std::bad_alloc& /*ex*/)
+ {
+ return E_OUTOFMEMORY;
+ }
+ return S_OK;
+ }
+
+ ResultCode RemoveAtEnd()
+ {
+ m_vector.erase(--(m_vector.end()));
+ return S_OK;
+ }
+
+ ResultCode Clear()
+ {
+ m_vector.clear();
+ return S_OK;
+ }
+
+ ResultCode GetString(_Out_ std::wstring* expression)
+ {
+ unsigned int nTokens = 0;
+ ResultCode hr = this->GetSize(&nTokens);
+ if (SUCCEEDED(hr))
+ {
+
+ std::pair currentPair;
+ for (unsigned int i = 0; i < nTokens; i++)
+ {
+ hr = this->GetAt(i, ¤tPair);
+ if (SUCCEEDED(hr))
+ {
+ expression->append(currentPair.first);
+
+ if (i != (nTokens - 1))
+ {
+ expression->append(L" ");
+ }
+ }
+ }
+
+ std::wstring expressionSuffix{};
+ hr = GetExpressionSuffix(&expressionSuffix);
+ if (SUCCEEDED(hr))
+ {
+ expression->append(expressionSuffix);
+ }
+ }
+
+ return hr;
+ }
+
+ ResultCode GetExpressionSuffix(_Out_ std::wstring* suffix)
+ {
+ *suffix = L" =";
+ return S_OK;
+ }
+
+private:
+ std::vector m_vector;
+};
diff --git a/src/CalcManager/Command.h b/src/CalcManager/Command.h
index 4331ddf7..ab095189 100644
--- a/src/CalcManager/Command.h
+++ b/src/CalcManager/Command.h
@@ -69,10 +69,6 @@ namespace CalculationManager
CommandNULL = 0,
- // No new command should not be added before CommandSign, 80
- // If it is needed, the following two functions need to be revised too.
- // CalculatorManager::MapCommandForSerialize(Command command);
- // CalculatorManager::MapCommandForDeSerialize(unsigned char command);
CommandSIGN = 80,
CommandCLEAR = 81,
CommandCENTR = 82,
@@ -172,7 +168,7 @@ namespace CalculationManager
CommandCeil = 415,
CommandROLC = 416,
CommandRORC = 417,
- CommandLogBaseX = 500,
+ CommandLogBaseY = 500,
CommandNand = 501,
CommandNor = 502,
diff --git a/src/CalcManager/ExpressionCommand.cpp b/src/CalcManager/ExpressionCommand.cpp
index 628805fb..d574c9da 100644
--- a/src/CalcManager/ExpressionCommand.cpp
+++ b/src/CalcManager/ExpressionCommand.cpp
@@ -277,7 +277,7 @@ wstring COpndCommand::GetString(uint32_t radix, int32_t precision)
{
if (m_fInitialized)
{
- return m_value.ToString(radix, eNUMOBJ_FMT::FMT_FLOAT, precision);
+ return m_value.ToString(radix, NumberFormat::Float, precision);
}
return wstring{};
diff --git a/src/CalcManager/Header Files/CCommand.h b/src/CalcManager/Header Files/CCommand.h
index f6d74d25..440c6283 100644
--- a/src/CalcManager/Header Files/CCommand.h
+++ b/src/CalcManager/Header Files/CCommand.h
@@ -166,7 +166,7 @@
#define IDC_LASTCONTROL IDC_CEIL
#define IDC_BINARYEXTENDEDFIRST 500
-#define IDC_LOGBASEX 500 // logx(y)
+#define IDC_LOGBASEY 500 // logy(x)
#define IDC_NAND 501 // Nand
#define IDC_NOR 502 // Nor
diff --git a/src/CalcManager/Header Files/CalcEngine.h b/src/CalcManager/Header Files/CalcEngine.h
index 26b80515..397b9cea 100644
--- a/src/CalcManager/Header Files/CalcEngine.h
+++ b/src/CalcManager/Header Files/CalcEngine.h
@@ -31,14 +31,13 @@
// The real exports follows later
// This is expected to be in same order as IDM_QWORD, IDM_DWORD etc.
-enum eNUM_WIDTH
+enum class NUM_WIDTH
{
QWORD_WIDTH, // Number width of 64 bits mode (default)
DWORD_WIDTH, // Number width of 32 bits mode
WORD_WIDTH, // Number width of 16 bits mode
BYTE_WIDTH // Number width of 16 bits mode
};
-typedef enum eNUM_WIDTH NUM_WIDTH;
static constexpr size_t NUM_WIDTH_LENGTH = 4;
namespace CalculationManager
@@ -78,7 +77,7 @@ public:
}
void SettingsChanged();
bool IsCurrentTooBigForTrig();
- int GetCurrentRadix();
+ uint32_t GetCurrentRadix();
std::wstring GetCurrentResultForRadix(uint32_t radix, int32_t precision, bool groupDigitsPerRadix);
void ChangePrecision(int32_t precision)
{
@@ -106,7 +105,7 @@ public:
{
return GetString(IdStrFromCmdId(nOpCode));
}
- static std::wstring_view OpCodeToUnaryString(int nOpCode, bool fInv, ANGLE_TYPE angletype);
+ static std::wstring_view OpCodeToUnaryString(int nOpCode, bool fInv, AngleType angletype);
static std::wstring_view OpCodeToBinaryString(int nOpCode, bool isIntegerMode);
private:
@@ -117,11 +116,11 @@ private:
int m_nOpCode; /* ID value of operation. */
int m_nPrevOpCode; // opcode which computed the number in m_currentVal. 0 if it is already bracketed or plain number or
// if it hasn't yet been computed
- bool m_bChangeOp; /* Flag for changing operation. */
+ bool m_bChangeOp; // Flag for changing operation
bool m_bRecord; // Global mode: recording or displaying
bool m_bSetCalcState; // Flag for setting the engine result state
CalcEngine::CalcInput m_input; // Global calc input object for decimal strings
- eNUMOBJ_FMT m_nFE; /* Scientific notation conversion flag. */
+ NumberFormat m_nFE; // Scientific notation conversion flag
CalcEngine::Rational m_maxTrigonometricNum;
std::unique_ptr m_memoryValue; // Current memory value.
@@ -148,7 +147,7 @@ private:
std::array m_nPrecOp; /* Holding array for precedence operations. */
size_t m_precedenceOpCount; /* Current number of precedence ops in holding. */
int m_nLastCom; // Last command entered.
- ANGLE_TYPE m_angletype; // Current Angle type when in dec mode. one of deg, rad or grad
+ AngleType m_angletype; // Current Angle type when in dec mode. one of deg, rad or grad
NUM_WIDTH m_numwidth; // one of qword, dword, word or byte mode.
int32_t m_dwWordBitWidth; // # of bits in currently selected word size
@@ -179,15 +178,17 @@ private:
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);
+ void SetRadixTypeAndNumWidth(RadixType radixtype, NUM_WIDTH numwidth);
int32_t DwWordBitWidthFromeNumWidth(NUM_WIDTH numwidth);
- uint32_t NRadixFromRadixType(RADIX_TYPE radixtype);
+ uint32_t NRadixFromRadixType(RadixType radixtype);
double GenerateRandomNumber();
bool TryToggleBit(CalcEngine::Rational& rat, uint32_t wbitno);
void CheckAndAddLastBinOpToHistory(bool addToHistory = true);
void InitChopNumbers();
+ CalcEngine::Rational GetChopNumber() const;
+ std::wstring GetMaxDecimalValueString() const;
static void LoadEngineStrings(CalculationManager::IResourceProvider& resourceProvider);
static int IdStrFromCmdId(int id)
diff --git a/src/CalcManager/Header Files/EngineStrings.h b/src/CalcManager/Header Files/EngineStrings.h
index 958c828b..7e093237 100644
--- a/src/CalcManager/Header Files/EngineStrings.h
+++ b/src/CalcManager/Header Files/EngineStrings.h
@@ -196,7 +196,7 @@ 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_LOGBASEY = L"LogBaseY";
inline constexpr auto SIDS_ABS = L"Abs";
inline constexpr auto SIDS_FLOOR = L"Floor";
inline constexpr auto SIDS_CEIL = L"Ceil";
@@ -352,7 +352,7 @@ inline constexpr std::array g_sids =
SIDS_COTH,
SIDS_ACOTH,
SIDS_TWOPOWX,
- SIDS_LOGBASEX,
+ SIDS_LOGBASEY,
SIDS_ABS,
SIDS_FLOOR,
SIDS_CEIL,
diff --git a/src/CalcManager/Header Files/History.h b/src/CalcManager/Header Files/History.h
index 66bac67f..f88f61c3 100644
--- a/src/CalcManager/Header Files/History.h
+++ b/src/CalcManager/Header Files/History.h
@@ -23,7 +23,7 @@ public:
void RemoveLastOpndFromHistory();
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 AddUnaryOpToHistory(int nOpCode, bool fInv, AngleType angletype);
void AddOpenBraceToHistory();
void AddCloseBraceToHistory();
void PushLastOpndStart(int ichOpndStart = -1);
diff --git a/src/CalcManager/Header Files/RadixType.h b/src/CalcManager/Header Files/RadixType.h
index 380d6afe..2ae0f90a 100644
--- a/src/CalcManager/Header Files/RadixType.h
+++ b/src/CalcManager/Header Files/RadixType.h
@@ -4,11 +4,10 @@
#pragma once
// This is expected to be in same order as IDM_HEX, IDM_DEC, IDM_OCT, IDM_BIN
-enum eRADIX_TYPE
+enum class RadixType
{
- HEX_RADIX,
- DEC_RADIX,
- OCT_RADIX,
- BIN_RADIX
+ Hex,
+ Decimal,
+ Octal,
+ Binary
};
-typedef enum eRADIX_TYPE RADIX_TYPE;
diff --git a/src/CalcManager/Header Files/Rational.h b/src/CalcManager/Header Files/Rational.h
index 8ded3c27..25df92bd 100644
--- a/src/CalcManager/Header Files/Rational.h
+++ b/src/CalcManager/Header Files/Rational.h
@@ -64,7 +64,7 @@ namespace CalcEngine
friend bool operator<=(Rational const& lhs, Rational const& rhs);
friend bool operator>=(Rational const& lhs, Rational const& rhs);
- std::wstring ToString(uint32_t radix, NUMOBJ_FMT format, int32_t precision) const;
+ std::wstring ToString(uint32_t radix, NumberFormat format, int32_t precision) const;
uint64_t ToUInt64_t() const;
private:
diff --git a/src/CalcManager/Header Files/RationalMath.h b/src/CalcManager/Header Files/RationalMath.h
index 59500573..f3ba56ec 100644
--- a/src/CalcManager/Header Files/RationalMath.h
+++ b/src/CalcManager/Header Files/RationalMath.h
@@ -22,12 +22,12 @@ namespace CalcEngine::RationalMath
Rational Invert(Rational const& rat);
Rational Abs(Rational const& rat);
- Rational Sin(Rational const& rat, ANGLE_TYPE angletype);
- Rational Cos(Rational const& rat, ANGLE_TYPE angletype);
- Rational Tan(Rational const& rat, ANGLE_TYPE angletype);
- Rational ASin(Rational const& rat, ANGLE_TYPE angletype);
- Rational ACos(Rational const& rat, ANGLE_TYPE angletype);
- Rational ATan(Rational const& rat, ANGLE_TYPE angletype);
+ Rational Sin(Rational const& rat, AngleType angletype);
+ Rational Cos(Rational const& rat, AngleType angletype);
+ Rational Tan(Rational const& rat, AngleType angletype);
+ Rational ASin(Rational const& rat, AngleType angletype);
+ Rational ACos(Rational const& rat, AngleType angletype);
+ Rational ATan(Rational const& rat, AngleType angletype);
Rational Sinh(Rational const& rat);
Rational Cosh(Rational const& rat);
diff --git a/src/CalcManager/NumberFormattingUtils.cpp b/src/CalcManager/NumberFormattingUtils.cpp
index ead9013f..63563972 100644
--- a/src/CalcManager/NumberFormattingUtils.cpp
+++ b/src/CalcManager/NumberFormattingUtils.cpp
@@ -50,15 +50,15 @@ namespace CalcManager::NumberFormattingUtils
/// the number
unsigned int GetNumberDigitsWholeNumberPart(double value)
{
- return value == 0 ? 1 : (1 + (int)log10(abs(value)));
+ return value == 0 ? 1u : static_cast(1 + max(0.0, log10(abs(value))));
}
///
/// Rounds the given double to the given number of significant digits
///
/// input double
- /// int number of significant digits to round to
- wstring RoundSignificantDigits(double num, int numSignificant)
+ /// unsigned int number of significant digits to round to
+ wstring RoundSignificantDigits(double num, unsigned int numSignificant)
{
wstringstream out(wstringstream::out);
out << fixed;
diff --git a/src/CalcManager/NumberFormattingUtils.h b/src/CalcManager/NumberFormattingUtils.h
index ab337eed..2f13ebfc 100644
--- a/src/CalcManager/NumberFormattingUtils.h
+++ b/src/CalcManager/NumberFormattingUtils.h
@@ -10,6 +10,6 @@ namespace CalcManager::NumberFormattingUtils
void TrimTrailingZeros(_Inout_ std::wstring& input);
unsigned int GetNumberDigits(std::wstring value);
unsigned int GetNumberDigitsWholeNumberPart(double value);
- std::wstring RoundSignificantDigits(double value, int numberSignificantDigits);
+ std::wstring RoundSignificantDigits(double value, unsigned int numberSignificantDigits);
std::wstring ToScientificNumber(double number);
}
diff --git a/src/CalcManager/Ratpack/CMakeLists.txt b/src/CalcManager/Ratpack/CMakeLists.txt
deleted file mode 100644
index 3fbd7ae3..00000000
--- a/src/CalcManager/Ratpack/CMakeLists.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-target_sources(CalcManager PRIVATE
- basex.cpp
- conv.cpp
- exp.cpp
- fact.cpp
- itrans.cpp
- itransh.cpp
- logic.cpp
- num.cpp
- rat.cpp
- support.cpp
- trans.cpp
- transh.cpp
-)
diff --git a/src/CalcManager/Ratpack/conv.cpp b/src/CalcManager/Ratpack/conv.cpp
index ab7aba05..4f7609de 100644
--- a/src/CalcManager/Ratpack/conv.cpp
+++ b/src/CalcManager/Ratpack/conv.cpp
@@ -303,17 +303,13 @@ PRAT numtorat(_In_ PNUMBER pin, uint32_t radix)
PNUMBER nRadixxtonum(_In_ PNUMBER a, uint32_t radix, int32_t precision)
{
- uint32_t bitmask;
- uint32_t cdigits;
- MANTTYPE* ptr;
-
PNUMBER sum = i32tonum(0, radix);
PNUMBER powofnRadix = i32tonum(BASEX, radix);
// A large penalty is paid for conversion of digits no one will see anyway.
// limit the digits to the minimum of the existing precision or the
// requested precision.
- cdigits = precision + 1;
+ uint32_t cdigits = precision + 1;
if (cdigits > (uint32_t)a->cdigit)
{
cdigits = (uint32_t)a->cdigit;
@@ -323,10 +319,10 @@ PNUMBER nRadixxtonum(_In_ PNUMBER a, uint32_t radix, int32_t precision)
numpowi32(&powofnRadix, a->exp + (a->cdigit - cdigits), radix, precision);
// Loop over all the relative digits from MSD to LSD
- for (ptr = &(a->mant[a->cdigit - 1]); cdigits > 0; ptr--, cdigits--)
+ for (MANTTYPE* ptr = &(a->mant[a->cdigit - 1]); cdigits > 0; ptr--, cdigits--)
{
// Loop over all the bits from MSB to LSB
- for (bitmask = BASEX / 2; bitmask > 0; bitmask /= 2)
+ for (uint32_t bitmask = BASEX / 2; bitmask > 0; bitmask /= 2)
{
addnum(&sum, sum, radix);
if (*ptr & bitmask)
@@ -368,9 +364,7 @@ PNUMBER numtonRadixx(_In_ PNUMBER a, uint32_t radix)
ptrdigit += a->cdigit - 1;
PNUMBER thisdigit = nullptr; // thisdigit holds the current digit of a
- // being summed into result.
- int32_t idigit; // idigit is the iterate of digits in a.
- for (idigit = 0; idigit < a->cdigit; idigit++)
+ for (int32_t idigit = 0; idigit < a->cdigit; idigit++)
{
mulnumx(&pnumret, num_radix);
// WARNING:
@@ -628,11 +622,10 @@ PNUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precis
MANTTYPE* pmant = pnumret->mant + numberString.length() - 1;
uint8_t state = START; // state is the state of the input state machine.
- wchar_t curChar;
for (const auto& c : numberString)
{
// If the character is the decimal separator, use L'.' for the purposes of the state machine.
- curChar = (c == g_decimalSeparator ? L'.' : c);
+ wchar_t curChar = (c == g_decimalSeparator ? L'.' : c);
// Switch states based on the character we encountered
switch (curChar)
@@ -1032,13 +1025,10 @@ int32_t numtoi32(_In_ PNUMBER pnum, uint32_t radix)
bool stripzeroesnum(_Inout_ PNUMBER pnum, int32_t starting)
{
- MANTTYPE* pmant;
- int32_t cdigits;
bool fstrip = false;
-
// point pmant to the LeastCalculatedDigit
- pmant = pnum->mant;
- cdigits = pnum->cdigit;
+ MANTTYPE* pmant = pnum->mant;
+ int32_t cdigits = pnum->cdigit;
// point pmant to the LSD
if (cdigits > starting)
{
@@ -1073,27 +1063,27 @@ bool stripzeroesnum(_Inout_ PNUMBER pnum, int32_t starting)
// FUNCTION: NumberToString
//
// ARGUMENTS: number representation
-// fmt, one of FMT_FLOAT FMT_SCIENTIFIC or
-// FMT_ENGINEERING
+// fmt, one of NumberFormat::Float, NumberFormat::Scientific or
+// NumberFormat::Engineering
// integer radix and int32_t precision value
//
// RETURN: String representation of number.
//
-// DESCRIPTION: Converts a number to it's string
+// DESCRIPTION: Converts a number to its string
// representation.
//
//-----------------------------------------------------------------------------
-wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_t precision)
+wstring NumberToString(_Inout_ PNUMBER& pnum, NumberFormat format, uint32_t radix, int32_t precision)
{
stripzeroesnum(pnum, precision + 2);
int32_t length = pnum->cdigit;
int32_t exponent = pnum->exp + length; // Actual number of digits to the left of decimal
- int32_t oldFormat = format;
- if (exponent > precision && format == FMT_FLOAT)
+ NumberFormat oldFormat = format;
+ if (exponent > precision && format == NumberFormat::Float)
{
// Force scientific mode to prevent user from assuming 33rd digit is exact.
- format = FMT_SCIENTIFIC;
+ format = NumberFormat::Scientific;
}
// Make length small enough to fit in pret.
@@ -1113,7 +1103,7 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_
divnum(&round, num_two, radix, precision);
// Make round number exponent one below the LSD for the number.
- if (exponent > 0 || format == FMT_FLOAT)
+ if (exponent > 0 || format == NumberFormat::Float)
{
round->exp = pnum->exp + pnum->cdigit - round->cdigit - precision;
}
@@ -1126,7 +1116,7 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_
round->sign = pnum->sign;
}
- if (format == FMT_FLOAT)
+ if (format == NumberFormat::Float)
{
// Figure out if the exponent will fill more space than the non-exponent field.
if ((length - exponent > precision) || (exponent > precision + 3))
@@ -1140,7 +1130,7 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_
{
// Case where too many zeros are to the right or left of the
// decimal pt. And we are forced to switch to scientific form.
- format = FMT_SCIENTIFIC;
+ format = NumberFormat::Scientific;
}
}
else if (length + abs(exponent) < precision && round)
@@ -1173,13 +1163,13 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_
int32_t eout = exponent - 1; // Displayed exponent.
MANTTYPE* pmant = pnum->mant + pnum->cdigit - 1;
// Case where too many digits are to the left of the decimal or
- // FMT_SCIENTIFIC or FMT_ENGINEERING was specified.
- if ((format == FMT_SCIENTIFIC) || (format == FMT_ENGINEERING))
+ // NumberFormat::Scientific or NumberFormat::Engineering was specified.
+ if ((format == NumberFormat::Scientific) || (format == NumberFormat::Engineering))
{
useSciForm = true;
if (eout != 0)
{
- if (format == FMT_ENGINEERING)
+ if (format == NumberFormat::Engineering)
{
exponent = (eout % 3);
eout -= exponent;
@@ -1280,7 +1270,7 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_
// ARGUMENTS:
// PRAT *representation of a number.
// i32 representation of base to dump to screen.
-// fmt, one of FMT_FLOAT FMT_SCIENTIFIC or FMT_ENGINEERING
+// fmt, one of NumberFormat::Float, NumberFormat::Scientific, or NumberFormat::Engineering
// precision uint32_t
//
// RETURN: string
@@ -1293,7 +1283,7 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_
// why a pointer to the rational is passed in.
//
//-----------------------------------------------------------------------------
-wstring RatToString(_Inout_ PRAT& prat, int format, uint32_t radix, int32_t precision)
+wstring RatToString(_Inout_ PRAT& prat, NumberFormat format, uint32_t radix, int32_t precision)
{
PNUMBER p = RatToNumber(prat, radix, precision);
diff --git a/src/CalcManager/Ratpack/exp.cpp b/src/CalcManager/Ratpack/exp.cpp
index 23257f73..b4020d45 100644
--- a/src/CalcManager/Ratpack/exp.cpp
+++ b/src/CalcManager/Ratpack/exp.cpp
@@ -63,7 +63,6 @@ void exprat(_Inout_ PRAT* px, uint32_t radix, int32_t precision)
{
PRAT pwr = nullptr;
PRAT pint = nullptr;
- int32_t intpwr;
if (rat_gt(*px, rat_max_exp, precision) || rat_lt(*px, rat_min_exp, precision))
{
@@ -76,7 +75,7 @@ void exprat(_Inout_ PRAT* px, uint32_t radix, int32_t precision)
intrat(&pint, radix, precision);
- intpwr = rattoi32(pint, radix, precision);
+ const int32_t intpwr = rattoi32(pint, radix, precision);
ratpowi32(&pwr, intpwr, precision);
subrat(px, pint, precision);
@@ -153,7 +152,6 @@ void _lograt(PRAT* px, int32_t precision)
void lograt(_Inout_ PRAT* px, int32_t precision)
{
- bool fneglog;
PRAT pwr = nullptr; // pwr is the large scaling factor.
PRAT offset = nullptr; // offset is the incremental scaling factor.
@@ -164,12 +162,10 @@ void lograt(_Inout_ PRAT* px, int32_t precision)
}
// Get number > 1, for scaling
- fneglog = rat_lt(*px, rat_one, precision);
+ bool fneglog = rat_lt(*px, rat_one, precision);
if (fneglog)
{
- // WARNING: This is equivalent to doing *px = 1 / *px
- PNUMBER pnumtemp = nullptr;
- pnumtemp = (*px)->pp;
+ PNUMBER pnumtemp = (*px)->pp;
(*px)->pp = (*px)->pq;
(*px)->pq = pnumtemp;
}
@@ -178,10 +174,7 @@ void lograt(_Inout_ PRAT* px, int32_t precision)
// log(x*2^(BASEXPWR*k)) = BASEXPWR*k*log(2)+log(x)
if (LOGRAT2(*px) > 1)
{
- // Take advantage of px's base BASEX to scale quickly down to
- // a reasonable range.
- int32_t intpwr;
- intpwr = LOGRAT2(*px) - 1;
+ const int32_t intpwr = LOGRAT2(*px) - 1;
(*px)->pq->exp += intpwr;
pwr = i32torat(intpwr * BASEXPWR);
mulrat(&pwr, ln_two, precision);
@@ -448,10 +441,9 @@ void powratcomp(_Inout_ PRAT* px, _In_ PRAT y, uint32_t radix, int32_t precision
{
// If power is an integer let ratpowi32 deal with it.
PRAT iy = nullptr;
- int32_t inty;
DUPRAT(iy, y);
subrat(&iy, podd, precision);
- inty = rattoi32(iy, radix, precision);
+ int32_t inty = rattoi32(iy, radix, precision);
PRAT plnx = nullptr;
DUPRAT(plnx, *px);
diff --git a/src/CalcManager/Ratpack/fact.cpp b/src/CalcManager/Ratpack/fact.cpp
index c026e536..f0905e4f 100644
--- a/src/CalcManager/Ratpack/fact.cpp
+++ b/src/CalcManager/Ratpack/fact.cpp
@@ -67,13 +67,9 @@ void _gamma(PRAT* pn, uint32_t radix, int32_t precision)
PRAT sum = nullptr;
PRAT err = nullptr;
PRAT mpy = nullptr;
- PRAT ratprec = nullptr;
- PRAT ratRadix = nullptr;
- int32_t oldprec;
// Set up constants and initial conditions
- oldprec = precision;
- ratprec = i32torat(oldprec);
+ PRAT ratprec = i32torat(precision);
// Find the best 'A' for convergence to the required precision.
a = i32torat(radix);
@@ -102,7 +98,7 @@ void _gamma(PRAT* pn, uint32_t radix, int32_t precision)
exprat(&tmp, radix, precision);
mulrat(&term, tmp, precision);
lograt(&term, precision);
- ratRadix = i32torat(radix);
+ const auto ratRadix = i32torat(radix);
DUPRAT(tmp, ratRadix);
lograt(&tmp, precision);
subrat(&term, tmp, precision);
@@ -173,7 +169,6 @@ void _gamma(PRAT* pn, uint32_t radix, int32_t precision)
mulrat(&sum, mpy, precision);
// And cleanup
- precision = oldprec;
destroyrat(ratprec);
destroyrat(err);
destroyrat(term);
diff --git a/src/CalcManager/Ratpack/itrans.cpp b/src/CalcManager/Ratpack/itrans.cpp
index 9bb94358..75e74785 100644
--- a/src/CalcManager/Ratpack/itrans.cpp
+++ b/src/CalcManager/Ratpack/itrans.cpp
@@ -17,17 +17,17 @@
//-----------------------------------------------------------------------------
#include "ratpak.h"
-void ascalerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, int32_t precision)
+void ascalerat(_Inout_ PRAT* pa, AngleType angletype, int32_t precision)
{
switch (angletype)
{
- case ANGLE_RAD:
+ case AngleType::Radians:
break;
- case ANGLE_DEG:
+ case AngleType::Degrees:
divrat(pa, two_pi, precision);
mulrat(pa, rat_360, precision);
break;
- case ANGLE_GRAD:
+ case AngleType::Gradians:
divrat(pa, two_pi, precision);
mulrat(pa, rat_400, precision);
break;
@@ -76,7 +76,7 @@ void _asinrat(PRAT* px, int32_t precision)
DESTROYTAYLOR();
}
-void asinanglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
+void asinanglerat(_Inout_ PRAT* pa, AngleType angletype, uint32_t radix, int32_t precision)
{
asinrat(pa, radix, precision);
@@ -164,7 +164,7 @@ void asinrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision)
//
//-----------------------------------------------------------------------------
-void acosanglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
+void acosanglerat(_Inout_ PRAT* pa, AngleType angletype, uint32_t radix, int32_t precision)
{
acosrat(pa, radix, precision);
@@ -249,7 +249,7 @@ void acosrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision)
//
//-----------------------------------------------------------------------------
-void atananglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
+void atananglerat(_Inout_ PRAT* pa, AngleType angletype, uint32_t radix, int32_t precision)
{
atanrat(pa, radix, precision);
diff --git a/src/CalcManager/Ratpack/logic.cpp b/src/CalcManager/Ratpack/logic.cpp
index c9094f33..197bda90 100644
--- a/src/CalcManager/Ratpack/logic.cpp
+++ b/src/CalcManager/Ratpack/logic.cpp
@@ -21,7 +21,6 @@ void lshrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision)
{
PRAT pwr = nullptr;
- int32_t intb;
intrat(pa, radix, precision);
if (!zernum((*pa)->pp))
@@ -32,7 +31,7 @@ void lshrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision)
// Don't attempt lsh of anything big
throw(CALC_E_DOMAIN);
}
- intb = rattoi32(b, radix, precision);
+ const int32_t intb = rattoi32(b, radix, precision);
DUPRAT(pwr, rat_two);
ratpowi32(&pwr, intb, precision);
mulrat(pa, pwr, precision);
@@ -44,7 +43,6 @@ void rshrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision)
{
PRAT pwr = nullptr;
- int32_t intb;
intrat(pa, radix, precision);
if (!zernum((*pa)->pp))
@@ -55,7 +53,7 @@ void rshrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision)
// Don't attempt rsh of anything big and negative.
throw(CALC_E_DOMAIN);
}
- intb = rattoi32(b, radix, precision);
+ const int32_t intb = rattoi32(b, radix, precision);
DUPRAT(pwr, rat_two);
ratpowi32(&pwr, intb, precision);
divrat(pa, pwr, precision);
diff --git a/src/CalcManager/Ratpack/num.cpp b/src/CalcManager/Ratpack/num.cpp
index c4561052..6055e41d 100644
--- a/src/CalcManager/Ratpack/num.cpp
+++ b/src/CalcManager/Ratpack/num.cpp
@@ -67,8 +67,7 @@ void _addnum(PNUMBER* pa, PNUMBER b, uint32_t radix)
MANTTYPE* pcha; // pcha is a pointer to the mantissa of a.
MANTTYPE* pchb; // pchb is a pointer to the mantissa of b.
MANTTYPE* pchc; // pchc is a pointer to the mantissa of c.
- int32_t cdigits; // cdigits is the max count of the digits results
- // used as a counter.
+ int32_t cdigits; // cdigits is the max count of the digits results used as a counter.
int32_t mexp; // mexp is the exponent of the result.
MANTTYPE da; // da is a single 'digit' after possible padding.
MANTTYPE db; // db is a single 'digit' after possible padding.
@@ -558,48 +557,34 @@ bool equnum(_In_ PNUMBER a, _In_ PNUMBER b)
bool lessnum(_In_ PNUMBER a, _In_ PNUMBER b)
{
- int32_t diff;
- MANTTYPE* pa;
- MANTTYPE* pb;
- int32_t cdigits;
- int32_t ccdigits;
- MANTTYPE da;
- MANTTYPE db;
-
- diff = (a->cdigit + a->exp) - (b->cdigit + b->exp);
+ int32_t diff = (a->cdigit + a->exp) - (b->cdigit + b->exp);
if (diff < 0)
{
// The exponent of a is less than b
return true;
}
- else
+ if (diff > 0)
{
- if (diff > 0)
+ return false;
+ }
+ MANTTYPE* pa = a->mant;
+ MANTTYPE* pb = b->mant;
+ pa += a->cdigit - 1;
+ pb += b->cdigit - 1;
+ int32_t cdigits = max(a->cdigit, b->cdigit);
+ int32_t ccdigits = cdigits;
+ for (; cdigits > 0; cdigits--)
+ {
+ MANTTYPE da = ((cdigits > (ccdigits - a->cdigit)) ? *pa-- : 0);
+ MANTTYPE db = ((cdigits > (ccdigits - b->cdigit)) ? *pb-- : 0);
+ diff = da - db;
+ if (diff)
{
- return false;
- }
- else
- {
- pa = a->mant;
- pb = b->mant;
- pa += a->cdigit - 1;
- pb += b->cdigit - 1;
- cdigits = max(a->cdigit, b->cdigit);
- ccdigits = cdigits;
- for (; cdigits > 0; cdigits--)
- {
- da = ((cdigits > (ccdigits - a->cdigit)) ? *pa-- : 0);
- db = ((cdigits > (ccdigits - b->cdigit)) ? *pb-- : 0);
- diff = da - db;
- if (diff)
- {
- return (diff < 0);
- }
- }
- // In this case, they are equal.
- return false;
+ return (diff < 0);
}
}
+ // In this case, they are equal.
+ return false;
}
//----------------------------------------------------------------------------
diff --git a/src/CalcManager/Ratpack/ratpak.h b/src/CalcManager/Ratpack/ratpak.h
index 18b2d024..0b3771f3 100644
--- a/src/CalcManager/Ratpack/ratpak.h
+++ b/src/CalcManager/Ratpack/ratpak.h
@@ -31,25 +31,20 @@ static constexpr uint32_t BASEX = 0x80000000; // Internal radix used in calculat
typedef uint32_t MANTTYPE;
typedef uint64_t TWO_MANTTYPE;
-enum eNUMOBJ_FMT
+enum class NumberFormat
{
- FMT_FLOAT, // returns floating point, or exponential if number is too big
- FMT_SCIENTIFIC, // always returns scientific notation
- FMT_ENGINEERING // always returns engineering notation such that exponent is a multiple of 3
-
+ Float, // returns floating point, or exponential if number is too big
+ Scientific, // always returns scientific notation
+ Engineering // always returns engineering notation such that exponent is a multiple of 3
};
-enum eANGLE_TYPE
+enum class AngleType
{
- ANGLE_DEG, // Calculate trig using 360 degrees per revolution
- ANGLE_RAD, // Calculate trig using 2 pi radians per revolution
- ANGLE_GRAD // Calculate trig using 400 gradients per revolution
-
+ Degrees, // Calculate trig using 360 degrees per revolution
+ Radians, // Calculate trig using 2 pi radians per revolution
+ Gradians // Calculate trig using 400 gradians per revolution
};
-typedef enum eNUMOBJ_FMT NUMOBJ_FMT;
-typedef enum eANGLE_TYPE ANGLE_TYPE;
-
//-----------------------------------------------------------------------------
//
// NUMBER type is a representation of a generic sized generic radix number
@@ -341,10 +336,10 @@ extern bool equnum(_In_ PNUMBER a, _In_ PNUMBER b); // returns true of a == b
extern bool lessnum(_In_ PNUMBER a, _In_ PNUMBER b); // returns true of a < b
extern bool zernum(_In_ PNUMBER a); // returns true of a == 0
extern bool zerrat(_In_ PRAT a); // returns true if a == 0/q
-extern std::wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_t precision);
+extern std::wstring NumberToString(_Inout_ PNUMBER& pnum, NumberFormat format, uint32_t radix, int32_t precision);
// returns a text representation of a PRAT
-extern std::wstring RatToString(_Inout_ PRAT& prat, int format, uint32_t radix, int32_t precision);
+extern std::wstring RatToString(_Inout_ PRAT& prat, NumberFormat format, uint32_t radix, int32_t precision);
// converts a PRAT into a PNUMBER
extern PNUMBER RatToNumber(_In_ PRAT prat, uint32_t radix, int32_t precision);
// flattens a PRAT by converting it to a PNUMBER and back to a PRAT
@@ -376,7 +371,7 @@ extern PRAT _createrat(void);
// returns a new rat structure with the acos of x->p/x->q taking into account
// angle type
-extern void acosanglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
+extern void acosanglerat(_Inout_ PRAT* px, AngleType angletype, uint32_t radix, int32_t precision);
// returns a new rat structure with the acosh of x->p/x->q
extern void acoshrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
@@ -386,7 +381,7 @@ extern void acosrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the asin of x->p/x->q taking into account
// angle type
-extern void asinanglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
+extern void asinanglerat(_Inout_ PRAT* px, AngleType angletype, uint32_t radix, int32_t precision);
extern void asinhrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the asinh of x->p/x->q
@@ -396,7 +391,7 @@ extern void asinrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the atan of x->p/x->q taking into account
// angle type
-extern void atananglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
+extern void atananglerat(_Inout_ PRAT* px, AngleType angletype, uint32_t radix, int32_t precision);
// returns a new rat structure with the atanh of x->p/x->q
extern void atanhrat(_Inout_ PRAT* px, int32_t precision);
@@ -412,7 +407,7 @@ extern void cosrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the cos of x->p/x->q taking into account
// angle type
-extern void cosanglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
+extern void cosanglerat(_Inout_ PRAT* px, AngleType angletype, uint32_t radix, int32_t precision);
// returns a new rat structure with the exp of x->p/x->q this should not be called explicitly.
extern void _exprat(_Inout_ PRAT* px, int32_t precision);
@@ -435,14 +430,14 @@ extern void sinrat(_Inout_ PRAT* px);
// returns a new rat structure with the sin of x->p/x->q taking into account
// angle type
-extern void sinanglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
+extern void sinanglerat(_Inout_ PRAT* px, AngleType angletype, uint32_t radix, int32_t precision);
extern void tanhrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
extern void tanrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the tan of x->p/x->q taking into account
// angle type
-extern void tananglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
+extern void tananglerat(_Inout_ PRAT* px, AngleType angletype, uint32_t radix, int32_t precision);
extern void _dupnum(_In_ PNUMBER dest, _In_ const NUMBER* const src);
diff --git a/src/CalcManager/Ratpack/support.cpp b/src/CalcManager/Ratpack/support.cpp
index 81c737f5..ef9e4106 100644
--- a/src/CalcManager/Ratpack/support.cpp
+++ b/src/CalcManager/Ratpack/support.cpp
@@ -596,15 +596,13 @@ void _dumprawrat(_In_ const wchar_t* varname, _In_ PRAT rat, wostream& out)
void _dumprawnum(_In_ const wchar_t* varname, _In_ PNUMBER num, wostream& out)
{
- int i;
-
out << L"NUMBER " << varname << L" = {\n";
out << L"\t" << num->sign << L",\n";
out << L"\t" << num->cdigit << L",\n";
out << L"\t" << num->exp << L",\n";
out << L"\t{ ";
- for (i = 0; i < num->cdigit; i++)
+ for (int i = 0; i < num->cdigit; i++)
{
out << L" " << num->mant[i] << L",";
}
@@ -681,10 +679,9 @@ void trimit(_Inout_ PRAT* px, int32_t precision)
{
if (!g_ftrueinfinite)
{
- int32_t trim;
PNUMBER pp = (*px)->pp;
PNUMBER pq = (*px)->pq;
- trim = g_ratio * (min((pp->cdigit + pp->exp), (pq->cdigit + pq->exp)) - 1) - precision;
+ int32_t trim = g_ratio * (min((pp->cdigit + pp->exp), (pq->cdigit + pq->exp)) - 1) - precision;
if (trim > g_ratio)
{
trim /= g_ratio;
diff --git a/src/CalcManager/Ratpack/trans.cpp b/src/CalcManager/Ratpack/trans.cpp
index e848155d..50055e22 100644
--- a/src/CalcManager/Ratpack/trans.cpp
+++ b/src/CalcManager/Ratpack/trans.cpp
@@ -16,17 +16,17 @@
#include "ratpak.h"
-void scalerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
+void scalerat(_Inout_ PRAT* pa, AngleType angletype, uint32_t radix, int32_t precision)
{
switch (angletype)
{
- case ANGLE_RAD:
+ case AngleType::Radians:
scale2pi(pa, radix, precision);
break;
- case ANGLE_DEG:
+ case AngleType::Degrees:
scale(pa, rat_360, radix, precision);
break;
- case ANGLE_GRAD:
+ case AngleType::Gradians:
scale(pa, rat_400, radix, precision);
break;
}
@@ -98,13 +98,13 @@ void sinrat(PRAT* px, uint32_t radix, int32_t precision)
_sinrat(px, precision);
}
-void sinanglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
+void sinanglerat(_Inout_ PRAT* pa, AngleType angletype, uint32_t radix, int32_t precision)
{
scalerat(pa, angletype, radix, precision);
switch (angletype)
{
- case ANGLE_DEG:
+ case AngleType::Degrees:
if (rat_gt(*pa, rat_180, precision))
{
subrat(pa, rat_360, precision);
@@ -112,7 +112,7 @@ void sinanglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t
divrat(pa, rat_180, precision);
mulrat(pa, pi, precision);
break;
- case ANGLE_GRAD:
+ case AngleType::Gradians:
if (rat_gt(*pa, rat_200, precision))
{
subrat(pa, rat_400, precision);
@@ -193,13 +193,13 @@ void cosrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision)
_cosrat(px, radix, precision);
}
-void cosanglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
+void cosanglerat(_Inout_ PRAT* pa, AngleType angletype, uint32_t radix, int32_t precision)
{
scalerat(pa, angletype, radix, precision);
switch (angletype)
{
- case ANGLE_DEG:
+ case AngleType::Degrees:
if (rat_gt(*pa, rat_180, precision))
{
PRAT ptmp = nullptr;
@@ -211,7 +211,7 @@ void cosanglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t
divrat(pa, rat_180, precision);
mulrat(pa, pi, precision);
break;
- case ANGLE_GRAD:
+ case AngleType::Gradians:
if (rat_gt(*pa, rat_200, precision))
{
PRAT ptmp = nullptr;
@@ -263,13 +263,13 @@ void tanrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision)
_tanrat(px, radix, precision);
}
-void tananglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
+void tananglerat(_Inout_ PRAT* pa, AngleType angletype, uint32_t radix, int32_t precision)
{
scalerat(pa, angletype, radix, precision);
switch (angletype)
{
- case ANGLE_DEG:
+ case AngleType::Degrees:
if (rat_gt(*pa, rat_180, precision))
{
subrat(pa, rat_180, precision);
@@ -277,7 +277,7 @@ void tananglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t
divrat(pa, rat_180, precision);
mulrat(pa, pi, precision);
break;
- case ANGLE_GRAD:
+ case AngleType::Gradians:
if (rat_gt(*pa, rat_200, precision))
{
subrat(pa, rat_200, precision);
diff --git a/src/CalcManager/UnitConverter.cpp b/src/CalcManager/UnitConverter.cpp
index ce0ebb81..3d4b1865 100644
--- a/src/CalcManager/UnitConverter.cpp
+++ b/src/CalcManager/UnitConverter.cpp
@@ -13,19 +13,19 @@ using namespace std;
using namespace UnitConversionManager;
using namespace CalcManager::NumberFormattingUtils;
-static constexpr uint32_t EXPECTEDSERIALIZEDCATEGORYTOKENCOUNT = 3;
-static constexpr uint32_t EXPECTEDSERIALIZEDUNITTOKENCOUNT = 6;
-static constexpr uint32_t EXPECTEDSTATEDATATOKENCOUNT = 5;
-static constexpr uint32_t EXPECTEDMAPCOMPONENTTOKENCOUNT = 2;
+static constexpr uint32_t EXPECTEDSERIALIZEDCATEGORYTOKENCOUNT = 3U;
+static constexpr uint32_t EXPECTEDSERIALIZEDUNITTOKENCOUNT = 6U;
+static constexpr uint32_t EXPECTEDSTATEDATATOKENCOUNT = 5U;
+static constexpr uint32_t EXPECTEDMAPCOMPONENTTOKENCOUNT = 2U;
-static constexpr int32_t MAXIMUMDIGITSALLOWED = 15;
-static constexpr int32_t OPTIMALDIGITSALLOWED = 7;
+static constexpr uint32_t MAXIMUMDIGITSALLOWED = 15U;
+static constexpr uint32_t OPTIMALDIGITSALLOWED = 7U;
static constexpr wchar_t LEFTESCAPECHAR = L'{';
static constexpr wchar_t RIGHTESCAPECHAR = L'}';
-static const double OPTIMALDECIMALALLOWED = pow(10, -1 * (OPTIMALDIGITSALLOWED - 1));
-static const double MINIMUMDECIMALALLOWED = pow(10, -1 * (MAXIMUMDIGITSALLOWED - 1));
+static const double OPTIMALDECIMALALLOWED = 1e-6; // pow(10, -1 * (OPTIMALDIGITSALLOWED - 1));
+static const double MINIMUMDECIMALALLOWED = 1e-14; // pow(10, -1 * (MAXIMUMDIGITSALLOWED - 1));
unordered_map quoteConversions;
unordered_map unquoteConversions;
@@ -109,7 +109,7 @@ CategorySelectionInitializer UnitConverter::SetCurrentCategory(const Category& i
{
if (m_currentCategory.id != input.id)
{
- for (auto& unit : m_categoryToUnits[m_currentCategory])
+ for (auto& unit : m_categoryToUnits[m_currentCategory.id])
{
unit.isConversionSource = (unit.id == m_fromType.id);
unit.isConversionTarget = (unit.id == m_toType.id);
@@ -121,7 +121,7 @@ CategorySelectionInitializer UnitConverter::SetCurrentCategory(const Category& i
}
}
- newUnitList = m_categoryToUnits[input];
+ newUnitList = m_categoryToUnits[input.id];
}
InitializeSelectedUnits();
@@ -149,6 +149,11 @@ void UnitConverter::SetCurrentUnitTypes(const Unit& fromType, const Unit& toType
return;
}
+ if (m_fromType != fromType)
+ {
+ m_switchedActive = true;
+ }
+
m_fromType = fromType;
m_toType = toType;
Calculate();
@@ -191,6 +196,11 @@ void UnitConverter::SwitchActive(const wstring& newValue)
}
}
+bool UnitConversionManager::UnitConverter::IsSwitchedActive() const
+{
+ return m_switchedActive;
+}
+
wstring UnitConverter::CategoryToString(const Category& c, wstring_view delimiter)
{
return Quote(std::to_wstring(c.id))
@@ -209,7 +219,7 @@ vector UnitConverter::StringToVector(wstring_view w, wstring_view delim
while (delimiterIndex != wstring_view::npos)
{
serializedTokens.emplace_back(w.substr(startIndex, delimiterIndex - startIndex));
- startIndex = delimiterIndex + (int)delimiter.size();
+ startIndex = delimiterIndex + static_cast(delimiter.size());
delimiterIndex = w.find(delimiter, startIndex);
}
if (addRemainder)
@@ -244,9 +254,9 @@ Unit UnitConverter::StringToUnit(wstring_view w)
serializedUnit.name = Unquote(tokenList[1]);
serializedUnit.accessibleName = serializedUnit.name;
serializedUnit.abbreviation = Unquote(tokenList[2]);
- serializedUnit.isConversionSource = (tokenList[3].compare(L"1") == 0);
- serializedUnit.isConversionTarget = (tokenList[4].compare(L"1") == 0);
- serializedUnit.isWhimsical = (tokenList[5].compare(L"1") == 0);
+ serializedUnit.isConversionSource = (tokenList[3] == L"1");
+ serializedUnit.isConversionTarget = (tokenList[4] == L"1");
+ serializedUnit.isWhimsical = (tokenList[5] == L"1");
return serializedUnit;
}
@@ -256,7 +266,7 @@ Category UnitConverter::StringToCategory(wstring_view w)
assert(tokenList.size() == EXPECTEDSERIALIZEDCATEGORYTOKENCOUNT);
Category serializedCategory;
serializedCategory.id = wcstol(Unquote(tokenList[0]).c_str(), nullptr, 10);
- serializedCategory.supportsNegative = (tokenList[1].compare(L"1") == 0);
+ serializedCategory.supportsNegative = (tokenList[1] == L"1");
serializedCategory.name = Unquote(tokenList[2]);
return serializedCategory;
}
@@ -283,7 +293,7 @@ void UnitConverter::RestoreUserPreferences(wstring_view userPreferences)
m_currentCategory = StringToCategory(outerTokens[2]);
// Only restore from the saved units if they are valid in the current available units.
- auto itr = m_categoryToUnits.find(m_currentCategory);
+ auto itr = m_categoryToUnits.find(m_currentCategory.id);
if (itr != m_categoryToUnits.end())
{
const auto& curUnits = itr->second;
@@ -559,7 +569,7 @@ future> UnitConverter::RefreshCurrencyRatios()
}
shared_future sharedLoadResult = loadDataResult.share();
- return async([this, currencyDataLoader, sharedLoadResult]() {
+ return async([currencyDataLoader, sharedLoadResult]() {
sharedLoadResult.wait();
bool didLoad = sharedLoadResult.get();
wstring timestamp;
@@ -618,10 +628,10 @@ vector> UnitConverter::CalculateSuggested()
newEntry.magnitude = log10(convertedValue);
newEntry.value = convertedValue;
newEntry.type = cur.first;
- if (newEntry.type.isWhimsical == false)
- intermediateVector.push_back(newEntry);
- else
+ if (newEntry.type.isWhimsical)
intermediateWhimsicalVector.push_back(newEntry);
+ else
+ intermediateVector.push_back(newEntry);
}
}
@@ -643,15 +653,15 @@ vector> UnitConverter::CalculateSuggested()
wstring roundedString;
if (abs(entry.value) < 100)
{
- roundedString = RoundSignificantDigits(entry.value, 2);
+ roundedString = RoundSignificantDigits(entry.value, 2U);
}
else if (abs(entry.value) < 1000)
{
- roundedString = RoundSignificantDigits(entry.value, 1);
+ roundedString = RoundSignificantDigits(entry.value, 1U);
}
else
{
- roundedString = RoundSignificantDigits(entry.value, 0);
+ roundedString = RoundSignificantDigits(entry.value, 0U);
}
if (stod(roundedString) != 0.0 || m_currentCategory.supportsNegative)
{
@@ -681,15 +691,15 @@ vector> UnitConverter::CalculateSuggested()
wstring roundedString;
if (abs(entry.value) < 100)
{
- roundedString = RoundSignificantDigits(entry.value, 2);
+ roundedString = RoundSignificantDigits(entry.value, 2U);
}
else if (abs(entry.value) < 1000)
{
- roundedString = RoundSignificantDigits(entry.value, 1);
+ roundedString = RoundSignificantDigits(entry.value, 1U);
}
else
{
- roundedString = RoundSignificantDigits(entry.value, 0);
+ roundedString = RoundSignificantDigits(entry.value, 0U);
}
// How to work out which is the best whimsical value to add to the vector?
@@ -713,10 +723,8 @@ vector> UnitConverter::CalculateSuggested()
///
void UnitConverter::ResetCategoriesAndRatios()
{
- m_categories = m_dataLoader->LoadOrderedCategories();
-
m_switchedActive = false;
-
+ m_categories = m_dataLoader->GetOrderedCategories();
if (m_categories.empty())
{
return;
@@ -738,8 +746,8 @@ void UnitConverter::ResetCategoriesAndRatios()
continue;
}
- vector units = activeDataLoader->LoadOrderedUnits(category);
- m_categoryToUnits[category] = units;
+ vector units = activeDataLoader->GetOrderedUnits(category);
+ m_categoryToUnits[category.id] = units;
// Just because the units are empty, doesn't mean the user can't select this category,
// we just want to make sure we don't let an unready category be the default.
@@ -789,7 +797,7 @@ void UnitConverter::InitializeSelectedUnits()
return;
}
- auto itr = m_categoryToUnits.find(m_currentCategory);
+ auto itr = m_categoryToUnits.find(m_currentCategory.id);
if (itr == m_categoryToUnits.end())
{
return;
@@ -800,8 +808,8 @@ void UnitConverter::InitializeSelectedUnits()
{
// Units may already have been initialized through UnitConverter::RestoreUserPreferences().
// Check if they have been, and if so, do not override restored units.
- bool isFromUnitValid = m_fromType != EMPTY_UNIT && find(curUnits.begin(), curUnits.end(), m_fromType) != curUnits.end();
- bool isToUnitValid = m_toType != EMPTY_UNIT && find(curUnits.begin(), curUnits.end(), m_toType) != curUnits.end();
+ const bool isFromUnitValid = m_fromType != EMPTY_UNIT && find(curUnits.begin(), curUnits.end(), m_fromType) != curUnits.end();
+ const bool isToUnitValid = m_toType != EMPTY_UNIT && find(curUnits.begin(), curUnits.end(), m_toType) != curUnits.end();
if (isFromUnitValid && isToUnitValid)
{
@@ -877,9 +885,9 @@ void UnitConverter::Calculate()
else
{
double currentValue = stod(m_currentDisplay);
- double returnValue = Convert(currentValue, conversionTable[m_toType]);
+ const double returnValue = Convert(currentValue, conversionTable[m_toType]);
- auto isCurrencyConverter = m_currencyDataLoader != nullptr && m_currencyDataLoader->SupportsCategory(this->m_currentCategory);
+ const auto isCurrencyConverter = m_currencyDataLoader != nullptr && m_currencyDataLoader->SupportsCategory(this->m_currentCategory);
if (isCurrencyConverter)
{
// We don't need to trim the value when it's a currency.
@@ -888,15 +896,15 @@ void UnitConverter::Calculate()
}
else
{
- int numPreDecimal = GetNumberDigitsWholeNumberPart(returnValue);
+ const unsigned int numPreDecimal = GetNumberDigitsWholeNumberPart(returnValue);
if (numPreDecimal > MAXIMUMDIGITSALLOWED || (returnValue != 0 && abs(returnValue) < MINIMUMDECIMALALLOWED))
{
m_returnDisplay = ToScientificNumber(returnValue);
}
else
{
- int currentNumberSignificantDigits = GetNumberDigits(m_currentDisplay);
- int precision = 0;
+ const unsigned int currentNumberSignificantDigits = GetNumberDigits(m_currentDisplay);
+ unsigned int precision;
if (abs(returnValue) < OPTIMALDECIMALALLOWED)
{
precision = MAXIMUMDIGITSALLOWED;
@@ -905,7 +913,8 @@ void UnitConverter::Calculate()
{
// Fewer digits are needed following the decimal if the number is large,
// we calculate the number of decimals necessary based on the number of digits in the integer part.
- precision = max(0, max(OPTIMALDIGITSALLOWED, min(MAXIMUMDIGITSALLOWED, currentNumberSignificantDigits)) - numPreDecimal);
+ auto numberDigits = max(OPTIMALDIGITSALLOWED, min(MAXIMUMDIGITSALLOWED, currentNumberSignificantDigits));
+ precision = numberDigits > numPreDecimal ? numberDigits - numPreDecimal : 0;
}
m_returnDisplay = RoundSignificantDigits(returnValue, precision);
diff --git a/src/CalcManager/UnitConverter.h b/src/CalcManager/UnitConverter.h
index 9d65324e..fe085dcb 100644
--- a/src/CalcManager/UnitConverter.h
+++ b/src/CalcManager/UnitConverter.h
@@ -6,8 +6,8 @@
#include
#include
#include
-#include "sal_cross_platform.h" // for SAL
-#include // for std::shared_ptr
+#include "sal_cross_platform.h" // for SAL
+#include // for std::shared_ptr
namespace UnitConversionManager
{
@@ -18,11 +18,11 @@ namespace UnitConversionManager
Unit()
{
}
- Unit(int id, std::wstring name, std::wstring abbreviation, bool isConversionSource, bool isConversionTarget, bool isWhimsical)
+ Unit(int id, std::wstring_view name, std::wstring abbreviation, bool isConversionSource, bool isConversionTarget, bool isWhimsical)
: id(id)
, name(name)
, accessibleName(name)
- , abbreviation(abbreviation)
+ , abbreviation(std::move(abbreviation))
, isConversionSource(isConversionSource)
, isConversionTarget(isConversionTarget)
, isWhimsical(isWhimsical)
@@ -31,23 +31,26 @@ namespace UnitConversionManager
Unit(
int id,
- std::wstring currencyName,
- std::wstring countryName,
+ std::wstring_view currencyName,
+ std::wstring_view countryName,
std::wstring abbreviation,
bool isRtlLanguage,
bool isConversionSource,
bool isConversionTarget)
: id(id)
- , abbreviation(abbreviation)
+ , abbreviation(std::move(abbreviation))
, isConversionSource(isConversionSource)
, isConversionTarget(isConversionTarget)
, isWhimsical(false)
{
- std::wstring nameValue1 = isRtlLanguage ? currencyName : countryName;
- std::wstring nameValue2 = isRtlLanguage ? countryName : currencyName;
+ auto nameValue1 = isRtlLanguage ? currencyName : countryName;
+ auto nameValue2 = isRtlLanguage ? countryName : currencyName;
- name = nameValue1 + L" - " + nameValue2;
- accessibleName = nameValue1 + L" " + nameValue2;
+ name = nameValue1;
+ name.append(L" - ").append(nameValue2);
+
+ accessibleName = nameValue1;
+ accessibleName.append(1, L' ').append(nameValue2);
}
int id;
@@ -84,7 +87,7 @@ namespace UnitConversionManager
Category(int id, std::wstring name, bool supportsNegative)
: id(id)
- , name(name)
+ , name(std::move(name))
, supportsNegative(supportsNegative)
{
}
@@ -113,15 +116,6 @@ namespace UnitConversionManager
}
};
- class CategoryHash
- {
- public:
- size_t operator()(const Category& x) const
- {
- return x.id;
- }
- };
-
struct SuggestedValueIntermediate
{
double magnitude;
@@ -168,7 +162,7 @@ namespace UnitConversionManager
std::unordered_map,
UnitConversionManager::UnitHash>
UnitToUnitToConversionDataMap;
- typedef std::unordered_map, UnitConversionManager::CategoryHash>
+ typedef std::unordered_map>
CategoryToUnitVectorMap;
class IViewModelCurrencyCallback
@@ -187,8 +181,8 @@ namespace UnitConversionManager
public:
virtual ~IConverterDataLoader(){};
virtual void LoadData() = 0; // prepare data if necessary before calling other functions
- virtual std::vector LoadOrderedCategories() = 0;
- virtual std::vector LoadOrderedUnits(const Category& c) = 0;
+ virtual std::vector GetOrderedCategories() = 0;
+ virtual std::vector GetOrderedUnits(const Category& c) = 0;
virtual std::unordered_map LoadOrderedRatios(const Unit& u) = 0;
virtual bool SupportsCategory(const Category& target) = 0;
};
@@ -229,6 +223,7 @@ namespace UnitConversionManager
virtual Category GetCurrentCategory() = 0;
virtual void SetCurrentUnitTypes(const Unit& fromType, const Unit& toType) = 0;
virtual void SwitchActive(const std::wstring& newValue) = 0;
+ virtual bool IsSwitchedActive() const = 0;
virtual std::wstring SaveUserPreferences() = 0;
virtual void RestoreUserPreferences(_In_ std::wstring_view userPreferences) = 0;
virtual void SendCommand(Command command) = 0;
@@ -252,6 +247,7 @@ namespace UnitConversionManager
Category GetCurrentCategory() override;
void SetCurrentUnitTypes(const Unit& fromType, const Unit& toType) override;
void SwitchActive(const std::wstring& newValue) override;
+ bool IsSwitchedActive() const override;
std::wstring SaveUserPreferences() override;
void RestoreUserPreferences(std::wstring_view userPreference) override;
void SendCommand(Command command) override;
diff --git a/src/CalcManager/pch.h b/src/CalcManager/pch.h
index 288bbc91..9c71ff3a 100644
--- a/src/CalcManager/pch.h
+++ b/src/CalcManager/pch.h
@@ -21,6 +21,6 @@
#include
#include
#include
-#include
+#include
#include
#include
diff --git a/src/CalcViewModel/ApplicationViewModel.cpp b/src/CalcViewModel/ApplicationViewModel.cpp
index efe9bca8..46855071 100644
--- a/src/CalcViewModel/ApplicationViewModel.cpp
+++ b/src/CalcViewModel/ApplicationViewModel.cpp
@@ -43,6 +43,7 @@ namespace
ApplicationViewModel::ApplicationViewModel()
: m_CalculatorViewModel(nullptr)
, m_DateCalcViewModel(nullptr)
+ , m_GraphingCalcViewModel(nullptr)
, m_ConverterViewModel(nullptr)
, m_PreviousMode(ViewMode::None)
, m_mode(ViewMode::None)
@@ -74,7 +75,7 @@ void ApplicationViewModel::Categories::set(IObservableVector
void ApplicationViewModel::Initialize(ViewMode mode)
{
- if (!NavCategory::IsValidViewMode(mode))
+ if (!NavCategory::IsValidViewMode(mode) || !NavCategory::IsViewModeEnabled(mode))
{
mode = ViewMode::Standard;
}
@@ -132,6 +133,13 @@ void ApplicationViewModel::OnModeChanged()
}
m_CalculatorViewModel->SetCalculatorType(m_mode);
}
+ else if (NavCategory::IsGraphingCalculatorViewMode(m_mode))
+ {
+ if (!m_GraphingCalcViewModel)
+ {
+ m_GraphingCalcViewModel = ref new GraphingCalculatorViewModel();
+ }
+ }
else if (NavCategory::IsDateCalculatorViewMode(m_mode))
{
if (!m_DateCalcViewModel)
@@ -182,7 +190,7 @@ void ApplicationViewModel::OnCopyCommand(Object ^ parameter)
{
DateCalcViewModel->OnCopyCommand(parameter);
}
- else
+ else if (NavCategory::IsCalculatorViewMode(m_mode))
{
CalculatorViewModel->OnCopyCommand(parameter);
}
@@ -223,7 +231,6 @@ task ApplicationViewModel::HandleToggleAlwaysOnTop(float width, float heig
localSettings->Values->Insert(HeightLocalSettings, height);
bool success = co_await ApplicationView::GetForCurrentView()->TryEnterViewModeAsync(ApplicationViewMode::Default);
- CalculatorViewModel->AreHistoryShortcutsEnabled = success;
CalculatorViewModel->HistoryVM->AreHistoryShortcutsEnabled = success;
CalculatorViewModel->IsAlwaysOnTop = !success;
IsAlwaysOnTop = !success;
@@ -252,7 +259,6 @@ task ApplicationViewModel::HandleToggleAlwaysOnTop(float width, float heig
}
bool success = co_await ApplicationView::GetForCurrentView()->TryEnterViewModeAsync(ApplicationViewMode::CompactOverlay, compactOptions);
- CalculatorViewModel->AreHistoryShortcutsEnabled = !success;
CalculatorViewModel->HistoryVM->AreHistoryShortcutsEnabled = !success;
CalculatorViewModel->IsAlwaysOnTop = success;
IsAlwaysOnTop = success;
diff --git a/src/CalcViewModel/ApplicationViewModel.h b/src/CalcViewModel/ApplicationViewModel.h
index 8a293eac..7e4238d8 100644
--- a/src/CalcViewModel/ApplicationViewModel.h
+++ b/src/CalcViewModel/ApplicationViewModel.h
@@ -5,6 +5,7 @@
#include "StandardCalculatorViewModel.h"
#include "DateCalculatorViewModel.h"
+#include "GraphingCalculator/GraphingCalculatorViewModel.h"
#include "UnitConverterViewModel.h"
namespace CalculatorApp
@@ -21,6 +22,7 @@ namespace CalculatorApp
OBSERVABLE_OBJECT();
OBSERVABLE_PROPERTY_RW(StandardCalculatorViewModel ^, CalculatorViewModel);
OBSERVABLE_PROPERTY_RW(DateCalculatorViewModel ^, DateCalcViewModel);
+ OBSERVABLE_PROPERTY_RW(GraphingCalculatorViewModel ^, GraphingCalcViewModel);
OBSERVABLE_PROPERTY_RW(UnitConverterViewModel ^, ConverterViewModel);
OBSERVABLE_PROPERTY_RW(CalculatorApp::Common::ViewMode, PreviousMode);
OBSERVABLE_PROPERTY_R(bool, IsAlwaysOnTop);
diff --git a/src/CalcViewModel/CalcViewModel.vcxproj b/src/CalcViewModel/CalcViewModel.vcxproj
index 49bc036f..c2a69b5c 100644
--- a/src/CalcViewModel/CalcViewModel.vcxproj
+++ b/src/CalcViewModel/CalcViewModel.vcxproj
@@ -122,29 +122,9 @@
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
- false
-
-
+
false
+ true
@@ -313,16 +293,13 @@
-
-
-
@@ -330,7 +307,6 @@
-
@@ -338,16 +314,19 @@
-
-
+
+
+
+
+
@@ -361,16 +340,13 @@
-
-
-
@@ -380,6 +356,9 @@
+
+
+
@@ -400,6 +379,12 @@
{311e866d-8b93-4609-a691-265941fee101}
+
+ {e727a92b-f149-492c-8117-c039a298719b}
+
+
+ {fc81ff41-02cd-4cd9-9bc5-45a1e39ac6ed}
+
@@ -420,16 +405,7 @@
-
-
-
-
-
-
- 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}.
-
-
-
+
\ No newline at end of file
diff --git a/src/CalcViewModel/CalcViewModel.vcxproj.filters b/src/CalcViewModel/CalcViewModel.vcxproj.filters
index ac5d41d3..b219806e 100644
--- a/src/CalcViewModel/CalcViewModel.vcxproj.filters
+++ b/src/CalcViewModel/CalcViewModel.vcxproj.filters
@@ -10,6 +10,9 @@
{0184f727-b8aa-4af8-a699-63f1b56e7853}
+
+ {cf7dca32-9727-4f98-83c3-1c0ca7dd1e0c}
+
@@ -23,18 +26,12 @@
Common
-
- Common
-
Common
Common
-
- Common
-
Common
@@ -50,9 +47,6 @@
Common
-
- Common
-
Common
@@ -80,9 +74,18 @@
DataLoaders
+
+ GraphingCalculator
+
+
+ GraphingCalculator
+
Common\Automation
+
+ GraphingCalculator
+
@@ -94,15 +97,9 @@
-
- Common
-
Common
-
- Common
-
Common
@@ -112,18 +109,12 @@
Common
-
- Common
-
Common
Common
-
- Common
-
Common
@@ -136,9 +127,6 @@
Common
-
- Common
-
Common
@@ -163,9 +151,6 @@
Common
-
- Common
-
Common\Automation
@@ -184,9 +169,6 @@
DataLoaders
-
- Common
-
DataLoaders
@@ -199,12 +181,29 @@
Common
+
+ GraphingCalculator
+
+
+ GraphingCalculator
+
+
+ Common
+
+
+ GraphingCalculator
+
+
+ GraphingCalculator
+
+
+ Common
+
DataLoaders
-
diff --git a/src/CalcViewModel/Common/Automation/INarratorAnnouncementHost.h b/src/CalcViewModel/Common/Automation/INarratorAnnouncementHost.h
new file mode 100644
index 00000000..9f947f41
--- /dev/null
+++ b/src/CalcViewModel/Common/Automation/INarratorAnnouncementHost.h
@@ -0,0 +1,27 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#pragma once
+#include "NarratorAnnouncement.h"
+
+// Declaration of the INarratorAnnouncementHost interface.
+// This interface exists to hide the concrete announcement host
+// being used. Depending on the version of the OS the app is running on,
+// the app may need a host that uses LiveRegionChanged or RaiseNotification.
+
+namespace CalculatorApp::Common::Automation
+{
+public
+ interface class INarratorAnnouncementHost
+ {
+ public:
+ // Is the host available on this OS.
+ bool IsHostAvailable();
+
+ // Make a new instance of a concrete host.
+ INarratorAnnouncementHost ^ MakeHost();
+
+ // Make an announcement using the concrete host's preferred method.
+ void Announce(NarratorAnnouncement ^ announcement);
+ };
+}
diff --git a/src/CalcViewModel/Common/Automation/LiveRegionHost.cpp b/src/CalcViewModel/Common/Automation/LiveRegionHost.cpp
new file mode 100644
index 00000000..0df3a96c
--- /dev/null
+++ b/src/CalcViewModel/Common/Automation/LiveRegionHost.cpp
@@ -0,0 +1,42 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#include "pch.h"
+#include "LiveRegionHost.h"
+
+using namespace CalculatorApp::Common::Automation;
+using namespace Windows::UI::Xaml::Automation;
+using namespace Windows::UI::Xaml::Automation::Peers;
+using namespace Windows::UI::Xaml::Controls;
+
+LiveRegionHost::LiveRegionHost()
+ : m_host(nullptr)
+{
+}
+
+bool LiveRegionHost::IsHostAvailable()
+{
+ // LiveRegion is always available.
+ return true;
+}
+
+INarratorAnnouncementHost ^ LiveRegionHost::MakeHost()
+{
+ return ref new LiveRegionHost();
+}
+
+void LiveRegionHost::Announce(NarratorAnnouncement ^ announcement)
+{
+ if (m_host == nullptr)
+ {
+ m_host = ref new TextBlock();
+ AutomationProperties::SetLiveSetting(m_host, AutomationLiveSetting::Assertive);
+ }
+
+ AutomationProperties::SetName(m_host, announcement->Announcement);
+ AutomationPeer ^ peer = FrameworkElementAutomationPeer::FromElement(m_host);
+ if (peer != nullptr)
+ {
+ peer->RaiseAutomationEvent(AutomationEvents::LiveRegionChanged);
+ }
+}
diff --git a/src/CalcViewModel/Common/Automation/LiveRegionHost.h b/src/CalcViewModel/Common/Automation/LiveRegionHost.h
new file mode 100644
index 00000000..fef7c714
--- /dev/null
+++ b/src/CalcViewModel/Common/Automation/LiveRegionHost.h
@@ -0,0 +1,33 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#pragma once
+#include "INarratorAnnouncementHost.h"
+
+// Declaration of the LiveRegionHost class.
+// This class announces NarratorAnnouncements using the LiveRegionChanged event.
+// This event is unreliable and should be deprecated in favor of the new
+// RaiseNotification API in RS3.
+
+namespace CalculatorApp::Common::Automation
+{
+ // This class exists so that the app can run on RS2 and use LiveRegions
+ // to host notifications on those builds.
+ // When the app switches to min version RS3, this class can be removed
+ // and the app will switch to using the Notification API.
+ // TODO - MSFT 12735088
+public
+ ref class LiveRegionHost sealed : public INarratorAnnouncementHost
+ {
+ public:
+ LiveRegionHost();
+
+ virtual bool IsHostAvailable();
+ virtual INarratorAnnouncementHost ^ MakeHost();
+
+ virtual void Announce(NarratorAnnouncement ^ announcement);
+
+ private:
+ Windows::UI::Xaml::UIElement ^ m_host;
+ };
+}
diff --git a/src/CalcViewModel/Common/Automation/NarratorAnnouncement.cpp b/src/CalcViewModel/Common/Automation/NarratorAnnouncement.cpp
index 940c88c9..5365937d 100644
--- a/src/CalcViewModel/Common/Automation/NarratorAnnouncement.cpp
+++ b/src/CalcViewModel/Common/Automation/NarratorAnnouncement.cpp
@@ -18,11 +18,18 @@ namespace CalculatorApp::Common::Automation
StringReference MemoryItemChanged(L"MemorySlotChanged");
StringReference MemoryItemAdded(L"MemorySlotAdded");
StringReference HistoryCleared(L"HistoryCleared");
+ StringReference HistorySlotCleared(L"HistorySlotCleared");
StringReference CategoryNameChanged(L"CategoryNameChanged");
StringReference UpdateCurrencyRates(L"UpdateCurrencyRates");
StringReference DisplayCopied(L"DisplayCopied");
StringReference OpenParenthesisCountChanged(L"OpenParenthesisCountChanged");
StringReference NoParenthesisAdded(L"NoParenthesisAdded");
+ StringReference GraphModeChanged(L"GraphModeChanged");
+ StringReference GraphViewChanged(L"GraphViewChanged");
+ StringReference FunctionRemoved(L"FunctionRemoved");
+ StringReference GraphViewBestFitChanged(L"GraphViewBestFitChanged");
+ StringReference AlwaysOnTop(L"AlwaysOnTop");
+ StringReference BitShiftRadioButtonContent(L"BitShiftRadioButtonContent");
}
}
@@ -99,6 +106,15 @@ NarratorAnnouncement ^ CalculatorAnnouncement::GetHistoryClearedAnnouncement(Str
announcement, CalculatorActivityIds::HistoryCleared, AutomationNotificationKind::ItemRemoved, AutomationNotificationProcessing::MostRecent);
}
+NarratorAnnouncement ^ CalculatorAnnouncement::GetHistorySlotClearedAnnouncement(String ^ announcement)
+{
+ return ref new NarratorAnnouncement(
+ announcement,
+ CalculatorActivityIds::HistorySlotCleared,
+ AutomationNotificationKind::ItemRemoved,
+ AutomationNotificationProcessing::ImportantMostRecent);
+}
+
NarratorAnnouncement ^ CalculatorAnnouncement::GetCategoryNameChangedAnnouncement(String ^ announcement)
{
return ref new NarratorAnnouncement(
@@ -140,3 +156,51 @@ NarratorAnnouncement ^ CalculatorAnnouncement::GetNoRightParenthesisAddedAnnounc
AutomationNotificationKind::ActionCompleted,
AutomationNotificationProcessing::ImportantMostRecent);
}
+
+NarratorAnnouncement ^ CalculatorAnnouncement::GetGraphModeChangedAnnouncement(String ^ announcement)
+{
+ return ref new NarratorAnnouncement(
+ announcement,
+ CalculatorActivityIds::GraphModeChanged,
+ AutomationNotificationKind::ActionCompleted,
+ AutomationNotificationProcessing::ImportantMostRecent);
+}
+
+NarratorAnnouncement ^ CalculatorAnnouncement::GetGraphViewChangedAnnouncement(String ^ announcement)
+{
+ return ref new NarratorAnnouncement(
+ announcement,
+ CalculatorActivityIds::GraphViewChanged,
+ AutomationNotificationKind::ActionCompleted,
+ AutomationNotificationProcessing::CurrentThenMostRecent);
+}
+
+NarratorAnnouncement ^ CalculatorAnnouncement::GetFunctionRemovedAnnouncement(String ^ announcement)
+{
+ return ref new NarratorAnnouncement(
+ announcement, CalculatorActivityIds::FunctionRemoved, AutomationNotificationKind::ItemRemoved, AutomationNotificationProcessing::MostRecent);
+}
+
+NarratorAnnouncement ^ CalculatorAnnouncement::GetGraphViewBestFitChangedAnnouncement(Platform::String ^ announcement)
+{
+ return ref new NarratorAnnouncement(
+ announcement,
+ CalculatorActivityIds::GraphViewBestFitChanged,
+ AutomationNotificationKind::ActionCompleted,
+ AutomationNotificationProcessing::MostRecent);
+}
+
+NarratorAnnouncement ^ CalculatorAnnouncement::GetAlwaysOnTopChangedAnnouncement(String ^ announcement)
+{
+ return ref new NarratorAnnouncement(
+ announcement, CalculatorActivityIds::AlwaysOnTop, AutomationNotificationKind::ActionCompleted, AutomationNotificationProcessing::ImportantMostRecent);
+}
+
+NarratorAnnouncement ^ CalculatorAnnouncement::GetBitShiftRadioButtonCheckedAnnouncement(String ^ announcement)
+{
+ return ref new NarratorAnnouncement(
+ announcement,
+ CalculatorActivityIds::BitShiftRadioButtonContent,
+ AutomationNotificationKind::ActionCompleted,
+ AutomationNotificationProcessing::ImportantMostRecent);
+}
diff --git a/src/CalcViewModel/Common/Automation/NarratorAnnouncement.h b/src/CalcViewModel/Common/Automation/NarratorAnnouncement.h
index fef7e260..a19de86f 100644
--- a/src/CalcViewModel/Common/Automation/NarratorAnnouncement.h
+++ b/src/CalcViewModel/Common/Automation/NarratorAnnouncement.h
@@ -57,6 +57,7 @@ public
static NarratorAnnouncement ^ GetMemoryItemAddedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement ^ GetHistoryClearedAnnouncement(Platform::String ^ announcement);
+ static NarratorAnnouncement ^ GetHistorySlotClearedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement ^ GetCategoryNameChangedAnnouncement(Platform::String ^ announcement);
@@ -66,5 +67,16 @@ public
static NarratorAnnouncement ^ GetOpenParenthesisCountChangedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement ^ GetNoRightParenthesisAddedAnnouncement(Platform::String ^ announcement);
+
+ static NarratorAnnouncement ^ GetGraphModeChangedAnnouncement(Platform::String ^ announcement);
+ static NarratorAnnouncement ^ GetGraphViewChangedAnnouncement(Platform::String ^ announcement);
+ static NarratorAnnouncement ^ GetGraphViewBestFitChangedAnnouncement(Platform::String ^ announcement);
+
+ static NarratorAnnouncement ^ GetFunctionRemovedAnnouncement(Platform::String ^ announcement);
+
+ static NarratorAnnouncement ^ GetAlwaysOnTopChangedAnnouncement(Platform::String ^ announcement);
+
+ static NarratorAnnouncement ^ GetBitShiftRadioButtonCheckedAnnouncement(Platform::String ^ announcement);
+
};
}
diff --git a/src/CalcViewModel/Common/Automation/NarratorAnnouncementHostFactory.cpp b/src/CalcViewModel/Common/Automation/NarratorAnnouncementHostFactory.cpp
new file mode 100644
index 00000000..a103c7e7
--- /dev/null
+++ b/src/CalcViewModel/Common/Automation/NarratorAnnouncementHostFactory.cpp
@@ -0,0 +1,61 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#include "pch.h"
+#include "NarratorAnnouncementHostFactory.h"
+#include "NotificationHost.h"
+#include "LiveRegionHost.h"
+
+using namespace CalculatorApp::Common::Automation;
+using namespace std;
+
+INarratorAnnouncementHost ^ NarratorAnnouncementHostFactory::s_hostProducer;
+vector NarratorAnnouncementHostFactory::s_hosts;
+
+// This static variable is used only to call the initialization function, to initialize the other static variables.
+int NarratorAnnouncementHostFactory::s_init = NarratorAnnouncementHostFactory::Initialize();
+int NarratorAnnouncementHostFactory::Initialize()
+{
+ RegisterHosts();
+ NarratorAnnouncementHostFactory::s_hostProducer = GetHostProducer();
+
+ return 0;
+}
+
+// For now, there are two type of announcement hosts.
+// We'd prefer to use Notification if it's available and fall back to LiveRegion
+// if not. The availability of the host depends on the version of the OS the app is running on.
+// When the app switches to min version RS3, the LiveRegionHost can be removed and we will always
+// use NotificationHost.
+// TODO - MSFT 12735088
+void NarratorAnnouncementHostFactory::RegisterHosts()
+{
+ // The host that will be used is the first available host,
+ // therefore, order of hosts is important here.
+ NarratorAnnouncementHostFactory::s_hosts = { ref new NotificationHost(), ref new LiveRegionHost() };
+}
+
+INarratorAnnouncementHost ^ NarratorAnnouncementHostFactory::GetHostProducer()
+{
+ for (INarratorAnnouncementHost ^ host : NarratorAnnouncementHostFactory::s_hosts)
+ {
+ if (host->IsHostAvailable())
+ {
+ return host;
+ }
+ }
+
+ assert(false && L"No suitable AnnouncementHost was found.");
+ return nullptr;
+}
+
+INarratorAnnouncementHost ^ NarratorAnnouncementHostFactory::MakeHost()
+{
+ if (NarratorAnnouncementHostFactory::s_hostProducer == nullptr)
+ {
+ assert(false && L"No host producer has been assigned.");
+ return nullptr;
+ }
+
+ return NarratorAnnouncementHostFactory::s_hostProducer->MakeHost();
+}
diff --git a/src/CalcViewModel/Common/Automation/NarratorAnnouncementHostFactory.h b/src/CalcViewModel/Common/Automation/NarratorAnnouncementHostFactory.h
new file mode 100644
index 00000000..4b739a79
--- /dev/null
+++ b/src/CalcViewModel/Common/Automation/NarratorAnnouncementHostFactory.h
@@ -0,0 +1,33 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#pragma once
+#include "INarratorAnnouncementHost.h"
+
+// Declaration of the NarratorAnnouncementHostFactory class.
+// This class exists to hide the construction of a concrete INarratorAnnouncementHost.
+// Depending on the version of the OS the app is running on, the factory will return
+// an announcement host appropriate for that version.
+
+namespace CalculatorApp::Common::Automation
+{
+ class NarratorAnnouncementHostFactory
+ {
+ public:
+ static INarratorAnnouncementHost ^ MakeHost();
+
+ private:
+ NarratorAnnouncementHostFactory()
+ {
+ }
+
+ static int Initialize();
+ static void RegisterHosts();
+ static INarratorAnnouncementHost ^ GetHostProducer();
+
+ private:
+ static int s_init;
+ static INarratorAnnouncementHost ^ s_hostProducer;
+ static std::vector s_hosts;
+ };
+}
diff --git a/src/CalcViewModel/Common/Automation/NotificationHost.cpp b/src/CalcViewModel/Common/Automation/NotificationHost.cpp
new file mode 100644
index 00000000..92bf846e
--- /dev/null
+++ b/src/CalcViewModel/Common/Automation/NotificationHost.cpp
@@ -0,0 +1,97 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#include "pch.h"
+#include "NotificationHost.h"
+
+using namespace CalculatorApp::Common::Automation;
+using namespace Windows::Foundation::Metadata;
+using namespace Windows::UI::Xaml::Automation;
+using namespace Windows::UI::Xaml::Automation::Peers;
+using namespace Windows::UI::Xaml::Controls;
+
+NotificationHost::NotificationHost()
+ : m_host(nullptr)
+{
+}
+
+bool NotificationHost::IsHostAvailable()
+{
+ return ApiInformation::IsMethodPresent(L"Windows.UI.Xaml.Automation.Peers.AutomationPeer", L"RaiseNotificationEvent");
+}
+
+INarratorAnnouncementHost ^ NotificationHost::MakeHost()
+{
+ return ref new NotificationHost();
+}
+
+void NotificationHost::Announce(NarratorAnnouncement ^ announcement)
+{
+ if (m_host == nullptr)
+ {
+ m_host = ref new TextBlock();
+ }
+
+ auto peer = FrameworkElementAutomationPeer::FromElement(m_host);
+ if (peer != nullptr)
+ {
+ peer->RaiseNotificationEvent(
+ GetWindowsNotificationKind(announcement->Kind),
+ GetWindowsNotificationProcessing(announcement->Processing),
+ announcement->Announcement,
+ announcement->ActivityId);
+ }
+}
+
+StandardPeers::AutomationNotificationKind NotificationHost::GetWindowsNotificationKind(CustomPeers::AutomationNotificationKind customKindType)
+{
+ switch (customKindType)
+ {
+ case CustomPeers::AutomationNotificationKind::ItemAdded:
+ return StandardPeers::AutomationNotificationKind::ItemAdded;
+
+ case CustomPeers::AutomationNotificationKind::ItemRemoved:
+ return StandardPeers::AutomationNotificationKind::ItemRemoved;
+
+ case CustomPeers::AutomationNotificationKind::ActionCompleted:
+ return StandardPeers::AutomationNotificationKind::ActionCompleted;
+
+ case CustomPeers::AutomationNotificationKind::ActionAborted:
+ return StandardPeers::AutomationNotificationKind::ActionAborted;
+
+ case CustomPeers::AutomationNotificationKind::Other:
+ return StandardPeers::AutomationNotificationKind::Other;
+
+ default:
+ assert(false && L"Unexpected AutomationNotificationKind");
+ }
+
+ return StandardPeers::AutomationNotificationKind::Other;
+}
+
+StandardPeers::AutomationNotificationProcessing
+NotificationHost::GetWindowsNotificationProcessing(CustomPeers::AutomationNotificationProcessing customProcessingType)
+{
+ switch (customProcessingType)
+ {
+ case CustomPeers::AutomationNotificationProcessing::ImportantAll:
+ return StandardPeers::AutomationNotificationProcessing::ImportantAll;
+
+ case CustomPeers::AutomationNotificationProcessing::ImportantMostRecent:
+ return StandardPeers::AutomationNotificationProcessing::ImportantMostRecent;
+
+ case CustomPeers::AutomationNotificationProcessing::All:
+ return StandardPeers::AutomationNotificationProcessing::All;
+
+ case CustomPeers::AutomationNotificationProcessing::MostRecent:
+ return StandardPeers::AutomationNotificationProcessing::MostRecent;
+
+ case CustomPeers::AutomationNotificationProcessing::CurrentThenMostRecent:
+ return StandardPeers::AutomationNotificationProcessing::CurrentThenMostRecent;
+
+ default:
+ assert(false && L"Unexpected AutomationNotificationProcessing");
+ }
+
+ return StandardPeers::AutomationNotificationProcessing::ImportantMostRecent;
+}
diff --git a/src/CalcViewModel/Common/Automation/NotificationHost.h b/src/CalcViewModel/Common/Automation/NotificationHost.h
new file mode 100644
index 00000000..d0a929c6
--- /dev/null
+++ b/src/CalcViewModel/Common/Automation/NotificationHost.h
@@ -0,0 +1,34 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#pragma once
+#include "INarratorAnnouncementHost.h"
+
+// Declaration of the NotificationHost class.
+// This class announces NarratorAnnouncements using the RaiseNotification API
+// available in RS3.
+
+namespace CalculatorApp::Common::Automation
+{
+public
+ ref class NotificationHost sealed : public INarratorAnnouncementHost
+ {
+ public:
+ NotificationHost();
+
+ virtual bool IsHostAvailable();
+ virtual INarratorAnnouncementHost ^ MakeHost();
+
+ virtual void Announce(NarratorAnnouncement ^ announcement);
+
+ private:
+ static Windows::UI::Xaml::Automation::Peers::AutomationNotificationKind
+ GetWindowsNotificationKind(CalculatorApp::Common::Automation::AutomationNotificationKind customKindType);
+
+ static Windows::UI::Xaml::Automation::Peers::AutomationNotificationProcessing
+ GetWindowsNotificationProcessing(CalculatorApp::Common::Automation::AutomationNotificationProcessing customProcessingType);
+
+ private:
+ Windows::UI::Xaml::UIElement ^ m_host;
+ };
+}
diff --git a/src/CalcViewModel/Common/BindableBase.cpp b/src/CalcViewModel/Common/BindableBase.cpp
deleted file mode 100644
index ccba7985..00000000
--- a/src/CalcViewModel/Common/BindableBase.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-#include "pch.h"
-#include "BindableBase.h"
-
-using namespace CalculatorApp::Common;
-
-using namespace Platform;
-using namespace Windows::UI::Xaml::Data;
-
-///
-/// Notifies listeners that a property value has changed.
-///
-/// Name of the property used to notify listeners.
-void BindableBase::OnPropertyChanged(String ^ propertyName)
-{
- PropertyChanged(this, ref new PropertyChangedEventArgs(propertyName));
-}
-
-Windows::UI::Xaml::Data::ICustomProperty ^ BindableBase::GetCustomProperty(Platform::String ^ name)
-{
- return nullptr;
-}
-
-Windows::UI::Xaml::Data::ICustomProperty ^ BindableBase::GetIndexedProperty(Platform::String ^ name, Windows::UI::Xaml::Interop::TypeName type)
-{
- return nullptr;
-}
-
-Platform::String ^ BindableBase::GetStringRepresentation()
-{
- return this->ToString();
-}
diff --git a/src/CalcViewModel/Common/BindableBase.h b/src/CalcViewModel/Common/BindableBase.h
deleted file mode 100644
index d1f958f5..00000000
--- a/src/CalcViewModel/Common/BindableBase.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-#pragma once
-
-namespace CalculatorApp
-{
- namespace Common
- {
- ///
- /// Implementation of to simplify models.
- ///
- [Windows::Foundation::Metadata::WebHostHidden] public ref class BindableBase : Windows::UI::Xaml::DependencyObject,
- Windows::UI::Xaml::Data::INotifyPropertyChanged,
- Windows::UI::Xaml::Data::ICustomPropertyProvider
- {
- public:
- virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler ^ PropertyChanged;
-
- public:
- // ICustomPropertyProvider
- virtual Windows::UI::Xaml::Data::ICustomProperty ^ GetCustomProperty(Platform::String ^ name);
- virtual Windows::UI::Xaml::Data::ICustomProperty ^ GetIndexedProperty(Platform::String ^ name, Windows::UI::Xaml::Interop::TypeName type);
- virtual Platform::String ^ GetStringRepresentation();
-
- property Windows::UI::Xaml::Interop::TypeName Type
- {
- virtual Windows::UI::Xaml::Interop::TypeName get()
- {
- return this->GetType();
- }
- }
-
- protected:
- virtual void OnPropertyChanged(Platform::String ^ propertyName);
- };
- }
-}
diff --git a/src/CalcViewModel/Common/CalculatorButtonUser.h b/src/CalcViewModel/Common/CalculatorButtonUser.h
index 113d34dc..a7b72189 100644
--- a/src/CalcViewModel/Common/CalculatorButtonUser.h
+++ b/src/CalcViewModel/Common/CalculatorButtonUser.h
@@ -109,7 +109,7 @@ public
InvCoth = (int) CM::Command::CommandACOTH,
CubeRoot = (int) CM::Command::CommandCUBEROOT,
TwoPowerX = (int) CM::Command::CommandPOW2,
- LogBaseX = (int) CM::Command::CommandLogBaseX,
+ LogBaseY = (int) CM::Command::CommandLogBaseY,
Nand = (int) CM::Command::CommandNand,
Nor = (int) CM::Command::CommandNor,
Abs = (int) CM::Command::CommandAbs,
@@ -120,7 +120,7 @@ public
RshL = (int)CM::Command::CommandRSHFL,
RolC = (int)CM::Command::CommandROLC,
RorC = (int)CM::Command::CommandRORC,
-
+
BINSTART = (int)CM::Command::CommandBINEDITSTART,
BINPOS0 = (int)CM::Command::CommandBINPOS0,
BINPOS1 = (int)CM::Command::CommandBINPOS1,
@@ -194,6 +194,15 @@ public
MemoryRecall = (int)CM::Command::CommandRECALL,
MemoryClear = (int)CM::Command::CommandMCLEAR,
BitflipButton = 1000,
- FullKeypadButton = 1001
+ FullKeypadButton = 1001,
+
+ // Buttons used in graphing calculator
+ LessThan,
+ LessThanOrEqualTo,
+ GreaterThan,
+ GreaterThanOrEqualTo,
+ X,
+ Y,
+ Submit
};
}
diff --git a/src/CalcViewModel/Common/ConversionResultTaskHelper.cpp b/src/CalcViewModel/Common/ConversionResultTaskHelper.cpp
deleted file mode 100644
index ec90228f..00000000
--- a/src/CalcViewModel/Common/ConversionResultTaskHelper.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-#include "pch.h"
-#include "ConversionResultTaskHelper.h"
-
-using namespace CalculatorApp::Common;
-using namespace concurrency;
-using namespace std;
-
-ConversionResultTaskHelper::ConversionResultTaskHelper(unsigned int delay, const function functionToRun)
- : m_delay{ delay }
- , m_storedFunction{ functionToRun }
-{
- auto token = m_cts.get_token();
- auto delayTask = CompleteAfter(delay);
- delayTask.then(
- [this, token]() {
- if (!token.is_canceled())
- {
- m_storedFunction();
- }
- },
- task_continuation_context::use_current());
-}
-
-ConversionResultTaskHelper::~ConversionResultTaskHelper()
-{
- m_cts.cancel();
-}
-
-#pragma optimize("", off)
-// Creates a task that completes after the specified delay.
-//
-// Taken from: How to: Create a Task that Completes After a Delay
-// https://msdn.microsoft.com/en-us/library/hh873170.aspx
-task ConversionResultTaskHelper::CompleteAfter(unsigned int timeout)
-{
- co_await winrt::resume_after(winrt::Windows::Foundation::TimeSpan{ std::chrono::duration(timeout) });
-};
-#pragma optimize("", on)
diff --git a/src/CalcViewModel/Common/ConversionResultTaskHelper.h b/src/CalcViewModel/Common/ConversionResultTaskHelper.h
deleted file mode 100644
index 2fe543c3..00000000
--- a/src/CalcViewModel/Common/ConversionResultTaskHelper.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-#pragma once
-
-namespace CalculatorApp
-{
- namespace Common
- {
- class ConversionResultTaskHelper
- {
- public:
- ConversionResultTaskHelper(unsigned int delay, const std::function functionToRun);
- ~ConversionResultTaskHelper();
-
- private:
- concurrency::task CompleteAfter(unsigned int timeout);
-
- unsigned int m_delay;
- concurrency::cancellation_token_source m_cts;
- const std::function m_storedFunction;
- };
- }
-}
diff --git a/src/CalcViewModel/Common/CopyPasteManager.cpp b/src/CalcViewModel/Common/CopyPasteManager.cpp
index ade3a3fb..ae24aad1 100644
--- a/src/CalcViewModel/Common/CopyPasteManager.cpp
+++ b/src/CalcViewModel/Common/CopyPasteManager.cpp
@@ -310,6 +310,9 @@ bool CopyPasteManager::ExpressionRegExMatch(
if (operandMatched)
{
+ // Remember the sign of the operand
+ bool isNegativeValue = operand->Data()[0] == L'-';
+
// 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.
auto operandValue = SanitizeOperand(operand);
@@ -332,7 +335,11 @@ bool CopyPasteManager::ExpressionRegExMatch(
break;
}
- if (operandAsULL->Value > maxOperandLengthAndValue.maxValue)
+ // Calculate how much we exceed the maxValue.
+ // In case we exceed it for 1 only, and working with negative number - that's a corner case for max signed values (e.g. -32768)
+ bool isOverflow = operandAsULL->Value > maxOperandLengthAndValue.maxValue;
+ bool isMaxNegativeValue = operandAsULL->Value - 1 == maxOperandLengthAndValue.maxValue;
+ if (isOverflow && !(isNegativeValue && isMaxNegativeValue))
{
expMatched = false;
break;
@@ -594,9 +601,11 @@ ULONG32 CopyPasteManager::ProgrammerOperandLength(Platform::String ^ operand, Nu
// Indian rupee(₹) - 8377
// pound(£) - 163
// euro(€) - 8364
+// non-breaking whitespace - 160
Platform::String ^ CopyPasteManager::RemoveUnwantedCharsFromString(Platform::String ^ input)
{
- constexpr wchar_t unWantedChars[] = { L' ', L',', L'"', 165, 164, 8373, 36, 8353, 8361, 8362, 8358, 8377, 163, 8364, 8234, 8235, 8236, 8237 };
+ constexpr wchar_t unWantedChars[] = { L' ', L',', L'"', 165, 164, 8373, 36, 8353, 8361, 8362, 8358, 8377, 163, 8364, 8234, 8235, 8236, 8237, 160 };
+ input = CalculatorApp::Common::LocalizationSettings::GetInstance().RemoveGroupSeparators(input);
return ref new String(Utils::RemoveUnwantedCharsFromString(input->Data(), unWantedChars).c_str());
}
diff --git a/src/CalcViewModel/Common/KeyboardShortcutManager.cpp b/src/CalcViewModel/Common/KeyboardShortcutManager.cpp
deleted file mode 100644
index 8990d5e8..00000000
--- a/src/CalcViewModel/Common/KeyboardShortcutManager.cpp
+++ /dev/null
@@ -1,850 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-#include "pch.h"
-#include "KeyboardShortcutManager.h"
-#include "AppResourceProvider.h"
-#include "ApplicationViewModel.h"
-#include "LocalizationSettings.h"
-
-using namespace Concurrency;
-using namespace Platform;
-using namespace std;
-using namespace Windows::ApplicationModel::Resources;
-using namespace Windows::UI::Xaml;
-using namespace Windows::UI::Xaml::Controls;
-using namespace Windows::Foundation;
-using namespace Windows::Foundation::Collections;
-using namespace Windows::UI::Core;
-using namespace Windows::UI::Xaml::Controls::Primitives;
-using namespace Windows::System;
-using namespace Utils;
-using namespace CalculatorApp;
-using namespace CalculatorApp::Common;
-using namespace CalculatorApp::ViewModel;
-
-namespace MUXC = Microsoft::UI::Xaml::Controls;
-
-DEPENDENCY_PROPERTY_INITIALIZATION(KeyboardShortcutManager, Character);
-DEPENDENCY_PROPERTY_INITIALIZATION(KeyboardShortcutManager, VirtualKey);
-DEPENDENCY_PROPERTY_INITIALIZATION(KeyboardShortcutManager, VirtualKeyControlChord);
-DEPENDENCY_PROPERTY_INITIALIZATION(KeyboardShortcutManager, VirtualKeyShiftChord);
-DEPENDENCY_PROPERTY_INITIALIZATION(KeyboardShortcutManager, VirtualKeyAltChord);
-DEPENDENCY_PROPERTY_INITIALIZATION(KeyboardShortcutManager, VirtualKeyControlShiftChord);
-DEPENDENCY_PROPERTY_INITIALIZATION(KeyboardShortcutManager, VirtualKeyInverseChord);
-DEPENDENCY_PROPERTY_INITIALIZATION(KeyboardShortcutManager, VirtualKeyControlInverseChord);
-
-static multimap> s_CharacterForButtons;
-static multimap> s_VirtualKeysForButtons;
-static multimap> s_VirtualKeyControlChordsForButtons;
-static multimap> s_VirtualKeyShiftChordsForButtons;
-static multimap> s_VirtualKeyAltChordsForButtons;
-static multimap> s_VirtualKeyControlShiftChordsForButtons;
-static multimap> s_VirtualKeyInverseChordsForButtons;
-static multimap> s_VirtualKeyControlInverseChordsForButtons;
-
-static multimap s_ShiftKeyPressed;
-static multimap s_ControlKeyPressed;
-static multimap s_ShiftButtonChecked;
-static multimap s_IsDropDownOpen;
-
-static reader_writer_lock s_keyboardShortcutMapLock;
-
-namespace CalculatorApp
-{
- namespace Common
- {
- // Lights up all of the buttons in the given range
- // The range is defined by a pair of iterators
- template
- void LightUpButtons(const T& buttons)
- {
- auto iterator = buttons.first;
- for (; iterator != buttons.second; ++iterator)
- {
- auto button = iterator->second.Resolve();
- if (button && button->IsEnabled)
- {
- LightUpButton(button);
- }
- }
- }
-
- void LightUpButton(ButtonBase ^ button)
- {
- // If the button is a toggle button then we don't need
- // to change the UI of the button
- if (dynamic_cast(button))
- {
- return;
- }
-
- // The button will go into the visual Pressed state with this call
- VisualStateManager::GoToState(button, "Pressed", true);
-
- // This timer will fire after lightUpTime and make the button
- // go back to the normal state.
- // This timer will only fire once after which it will be destroyed
- auto timer = ref new DispatcherTimer();
- TimeSpan lightUpTime{};
- lightUpTime.Duration = 500000L; // Half second (in 100-ns units)
- timer->Interval = lightUpTime;
-
- WeakReference timerWeakReference(timer);
- WeakReference buttonWeakReference(button);
- timer->Tick += ref new EventHandler