diff --git a/.gitignore b/.gitignore index 80d64f53..2100dfc1 100644 --- a/.gitignore +++ b/.gitignore @@ -290,4 +290,5 @@ __pycache__/ # Calculator specific Generated Files/ !/build/config/TRexDefs/** +!src/Calculator/TemporaryKey.pfx !src/CalculatorUnitTests/CalculatorUnitTests_TemporaryKey.pfx \ No newline at end of file diff --git a/build/pipelines/azure-pipelines.loc.yaml b/build/pipelines/azure-pipelines.loc.yaml index d2bef95e..d1ef8552 100644 --- a/build/pipelines/azure-pipelines.loc.yaml +++ b/build/pipelines/azure-pipelines.loc.yaml @@ -15,30 +15,33 @@ name: $(BuildDefinitionName)_$(date:yyMM).$(date:dd)$(rev:rrr) jobs: - job: Localize pool: - name: Package ES Custom Demands Lab A - demands: - - ClientAlias -equals PKGESUTILAPPS - workspace: - clean: outputs + vmImage: vs2017-win2016 + variables: + skipComponentGovernanceDetection: true steps: - - checkout: self - clean: true - - task: PkgESSetupBuild@10 - displayName: Initialize Package ES + - task: MicrosoftTDBuild.tdbuild-task.tdbuild-task.TouchdownBuildTask@1 + displayName: Send resources to Touchdown Build inputs: - productName: Calculator - branchVersion: true + teamId: 86 + authId: d3dd8113-65b3-4526-bdca-a00a7d1c37ba + authKey: $(LocServiceKey) + isPreview: false + relativePathRoot: src/Calculator/Resources/en-US/ + resourceFilePath: '*.resw' + outputDirectoryRoot: src/Calculator/Resources/ - - task: PkgESTouchdownLocService@10 - displayName: Package ES Touchdown Loc Service + - script: | + cd $(Build.SourcesDirectory) + git add -A + git diff --cached --exit-code + echo '##vso[task.setvariable variable=hasChanges]%errorlevel%' + git diff --cached > $(Build.ArtifactStagingDirectory)\LocalizedStrings.patch + displayName: Check for changes and create patch file + + - task: PublishPipelineArtifact@0 + displayName: Publish patch file as artifact + condition: eq(variables['hasChanges'], '1') inputs: - IsCallToServiceStepSelected: true - IsCheckedInFileSelected: true - CheckinFilesAtOriginFilePath: true - GitLocPath: Loc/Resources - LocConfigFile: build/config/LocConfigPackageEs.xml - AuthenticationMode: OAuth - ClientApplicationID: d3dd8113-65b3-4526-bdca-a00a7d1c37ba - ApplicationKeyID: $(LocServiceKey) - SendToLoc: true + artifactName: Patch + targetPath: $(Build.ArtifactStagingDirectory) \ No newline at end of file diff --git a/build/pipelines/azure-pipelines.release.yaml b/build/pipelines/azure-pipelines.release.yaml index 78b4fd90..a4507e21 100644 --- a/build/pipelines/azure-pipelines.release.yaml +++ b/build/pipelines/azure-pipelines.release.yaml @@ -9,8 +9,8 @@ pr: none variables: versionMajor: 10 - versionMinor: 1902 - versionBuild: $[counter('10.1902.*', 0)] + versionMinor: 1903 + versionBuild: $[counter('10.1903.*', 0)] versionPatch: 0 name: '$(versionMajor).$(versionMinor).$(versionBuild).$(versionPatch)' diff --git a/build/pipelines/templates/build-app-internal.yaml b/build/pipelines/templates/build-app-internal.yaml index 8a75dcec..2de18a01 100644 --- a/build/pipelines/templates/build-app-internal.yaml +++ b/build/pipelines/templates/build-app-internal.yaml @@ -29,7 +29,7 @@ jobs: downloadDirectory: $(Build.SourcesDirectory) vstsFeed: WindowsApps vstsFeedPackage: calculator-internals - vstsPackageVersion: 0.0.7 + vstsPackageVersion: 0.0.10 - template: ./build-single-architecture.yaml parameters: diff --git a/build/pipelines/templates/prepare-release-internalonly.yaml b/build/pipelines/templates/prepare-release-internalonly.yaml index 6bb3b6cb..bf302a4b 100644 --- a/build/pipelines/templates/prepare-release-internalonly.yaml +++ b/build/pipelines/templates/prepare-release-internalonly.yaml @@ -87,7 +87,7 @@ jobs: downloadDirectory: $(Build.SourcesDirectory) vstsFeed: WindowsApps vstsFeedPackage: calculator-internals - vstsPackageVersion: 0.0.7 + vstsPackageVersion: 0.0.10 - task: PkgESStoreBrokerPackage@10 displayName: Create StoreBroker Packages diff --git a/docs/Roadmap.md b/docs/Roadmap.md index 93b1428e..0b969c5c 100644 --- a/docs/Roadmap.md +++ b/docs/Roadmap.md @@ -9,6 +9,7 @@ In 2019, the Windows Calculator team is focused on: * Iterating upon the existing app design based on the latest [Fluent Design guidelines](https://developer.microsoft.com/en-us/windows/apps/design) * Improving testing and diagnostics within the project * Investigating new features with a focus on addressing top user feedback, including: + * Adding graphing mode * Adding the ability for users to pin Calculator on top of other windows * Providing additional customization options * [Your feature idea here] - please review our [new feature development process](https://github.com/Microsoft/calculator/blob/master/docs/NewFeatureProcess.md) to get started! diff --git a/src/CalcManager/CEngine/History.cpp b/src/CalcManager/CEngine/History.cpp index 8dda170e..e5bb746b 100644 --- a/src/CalcManager/CEngine/History.cpp +++ b/src/CalcManager/CEngine/History.cpp @@ -136,7 +136,7 @@ void CHistoryCollector::AddBinOpToHistory(int nOpCode, bool fNoRepetition) } // This is expected to be called when a binary op in the last say 1+2+ is changing to another one say 1+2* (+ changed to *) -// It needs to know by this change a Precedence inversion happened. i.e. previous op was lower or equal to its previous op, but the new +// It needs to know by this change a Precedence inversion happened. i.e. previous op was lower or equal to its previous op, but the new // one isn't. (Eg. 1*2* to 1*2^). It can add explicit brackets to ensure the precedence is inverted. (Eg. (1*2) ^) void CHistoryCollector::ChangeLastBinOp(int nOpCode, bool fPrecInvToHigher) { @@ -203,7 +203,7 @@ bool CHistoryCollector::FOpndAddedToHistory() // AddUnaryOpToHistory // -// This is does the postfix to prefix translation of the input and adds the text to the history. Eg. doing 2 + 4 (sqrt), +// 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) @@ -297,7 +297,7 @@ void CHistoryCollector::AddUnaryOpToHistory(int nOpCode, bool fInv, ANGLE_TYPE a } // Called after = with the result of the equation -// Responsible for clearing the top line of current running history display, as well as adding yet another element to +// Responsible for clearing the top line of current running history display, as well as adding yet another element to // history of equations void CHistoryCollector::CompleteHistoryLine(wstring_view numStr) { @@ -413,37 +413,39 @@ int CHistoryCollector::AddCommand(_In_ const std::shared_ptr return nCommands - 1; } -// To Update the operands in the Expression according to the current Radix +// To Update the operands in the Expression according to the current Radix void CHistoryCollector::UpdateHistoryExpression(uint32_t radix, int32_t precision) { - if (m_spTokens != nullptr) + if (m_spTokens == nullptr) { - unsigned int size; - IFT(m_spTokens->GetSize(&size)); + return; + } - for (unsigned int i = 0; i < size; ++i) + unsigned int size; + IFT(m_spTokens->GetSize(&size)); + + for (unsigned int i = 0; i < size; ++i) + { + std::pair token; + IFT(m_spTokens->GetAt(i, &token)); + int commandPosition = token.second; + if (commandPosition != -1) { - std::pair token; - IFT(m_spTokens->GetAt(i, &token)); - int commandPosition = token.second; - if (commandPosition != -1) + std::shared_ptr expCommand; + IFT(m_spCommands->GetAt(commandPosition, &expCommand)); + if (expCommand != nullptr && CalculationManager::CommandType::OperandCommand == expCommand->GetCommandType()) { - std::shared_ptr expCommand; - IFT(m_spCommands->GetAt(commandPosition, &expCommand)); - if (expCommand != nullptr && CalculationManager::CommandType::OperandCommand == expCommand->GetCommandType()) + std::shared_ptr opndCommand = std::static_pointer_cast(expCommand); + if (opndCommand != nullptr) { - std::shared_ptr opndCommand = std::static_pointer_cast(expCommand); - if (opndCommand != nullptr) - { - token.first = opndCommand->GetString(radix, precision); - IFT(m_spTokens->SetAt(i, token)); - opndCommand->SetCommands(GetOperandCommandsFromString(token.first)); - } + token.first = opndCommand->GetString(radix, precision); + IFT(m_spTokens->SetAt(i, token)); + opndCommand->SetCommands(GetOperandCommandsFromString(token.first)); } } } - SetExpressionDisplay(); } + SetExpressionDisplay(); } void CHistoryCollector::SetDecimalSymbol(wchar_t decimalSymbol) diff --git a/src/CalcManager/CEngine/scicomm.cpp b/src/CalcManager/CEngine/scicomm.cpp index cf23cf66..a99397da 100644 --- a/src/CalcManager/CEngine/scicomm.cpp +++ b/src/CalcManager/CEngine/scicomm.cpp @@ -36,7 +36,7 @@ namespace { static BYTE rgbPrec[] = { 0,0, IDC_OR,0, IDC_XOR,0, IDC_AND,1, IDC_ADD,2, IDC_SUB,2, IDC_RSHF,3, IDC_LSHF,3, IDC_MOD,3, IDC_DIV,3, IDC_MUL,3, IDC_PWR,4, IDC_ROOT, 4 }; - int iPrec; + unsigned int iPrec; iPrec = 0; while ((iPrec < size(rgbPrec)) && (nopCode != rgbPrec[iPrec])) @@ -947,7 +947,7 @@ wstring_view CCalcEngine::OpCodeToUnaryString(int nOpCode, bool fInv, ANGLE_TYPE // Try to lookup the ID in the UFNE table int ids = 0; int iufne = nOpCode - IDC_UNARYFIRST; - if (iufne >= 0 && iufne < size(rgUfne)) + if (iufne >= 0 && (size_t)iufne < size(rgUfne)) { if (fInv) { diff --git a/src/CalcManager/CEngine/sciset.cpp b/src/CalcManager/CEngine/sciset.cpp index 99f0b0b6..95451dc9 100644 --- a/src/CalcManager/CEngine/sciset.cpp +++ b/src/CalcManager/CEngine/sciset.cpp @@ -56,7 +56,7 @@ LONG CCalcEngine::DwWordBitWidthFromeNumWidth(NUM_WIDTH /*numwidth*/) static constexpr int nBitMax[] = { 64, 32, 16, 8 }; LONG wmax = nBitMax[0]; - if (m_numwidth >= 0 && m_numwidth < size(nBitMax)) + if (m_numwidth >= 0 && (size_t)m_numwidth < size(nBitMax)) { wmax = nBitMax[m_numwidth]; } @@ -69,7 +69,7 @@ uint32_t CCalcEngine::NRadixFromRadixType(RADIX_TYPE radixtype) uint32_t radix = 10; // convert special bases into symbolic values - if (radixtype >= 0 && radixtype < size(rgnRadish)) + if (radixtype >= 0 && (size_t)radixtype < size(rgnRadish)) { radix = rgnRadish[radixtype]; } diff --git a/src/CalcManager/CalculatorHistory.cpp b/src/CalcManager/CalculatorHistory.cpp index d32bbe07..c7b308c1 100644 --- a/src/CalcManager/CalculatorHistory.cpp +++ b/src/CalcManager/CalculatorHistory.cpp @@ -8,7 +8,6 @@ using namespace std; using namespace CalculationManager; CalculatorHistory::CalculatorHistory(size_t maxSize) : - m_mode(eMode), m_maxHistorySize(maxSize) {} @@ -35,15 +34,13 @@ unsigned int CalculatorHistory::AddToHistory(_In_ shared_ptr const &spHistoryItem) { - int lastIndex; - if (m_historyItems.size() >= m_maxHistorySize) { m_historyItems.erase(m_historyItems.begin()); } m_historyItems.push_back(spHistoryItem); - lastIndex = static_cast(m_historyItems.size() - 1); + unsigned int lastIndex = static_cast(m_historyItems.size() - 1); return lastIndex; } diff --git a/src/CalcManager/CalculatorHistory.h b/src/CalcManager/CalculatorHistory.h index 6a27d266..583a004c 100644 --- a/src/CalcManager/CalculatorHistory.h +++ b/src/CalcManager/CalculatorHistory.h @@ -43,7 +43,6 @@ namespace CalculationManager private: std::vector> m_historyItems; - CALCULATOR_MODE m_mode; const size_t m_maxHistorySize; }; } diff --git a/src/CalcManager/CalculatorManager.cpp b/src/CalcManager/CalculatorManager.cpp index 0f6ccd49..ddb28a6b 100644 --- a/src/CalcManager/CalculatorManager.cpp +++ b/src/CalcManager/CalculatorManager.cpp @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" @@ -24,15 +24,15 @@ namespace CalculationManager { CalculatorManager::CalculatorManager(_In_ ICalcDisplay* displayCallback, _In_ IResourceProvider* resourceProvider) : m_displayCallback(displayCallback), + m_currentCalculatorEngine(nullptr), m_resourceProvider(resourceProvider), + m_inHistoryItemLoadMode(false), + m_persistedPrimaryValue(), + m_isExponentialFormat(false), m_currentDegreeMode(Command::CommandNULL), m_savedDegreeMode(Command::CommandDEG), - m_isExponentialFormat(false), - m_persistedPrimaryValue(), - m_currentCalculatorEngine(nullptr), - m_pStdHistory(new CalculatorHistory(CM_STD, MAX_HISTORY_ITEMS)), - m_pSciHistory(new CalculatorHistory(CM_SCI, MAX_HISTORY_ITEMS)), - m_inHistoryItemLoadMode(false) + m_pStdHistory(new CalculatorHistory(MAX_HISTORY_ITEMS)), + m_pSciHistory(new CalculatorHistory(MAX_HISTORY_ITEMS)) { CCalcEngine::InitialOneTimeOnlySetup(*m_resourceProvider); } @@ -292,7 +292,7 @@ namespace CalculationManager break; case Command::CommandFE: m_isExponentialFormat = !m_isExponentialFormat; - // fall through + [[fallthrough]]; default: m_currentCalculatorEngine->ProcessCommand(static_cast(command)); break; @@ -308,7 +308,10 @@ namespace CalculationManager unsigned char CalculatorManager::MapCommandForSerialize(Command command) { unsigned int commandToSave = static_cast(command); - commandToSave > UCHAR_MAX ? commandToSave -= UCHAR_MAX : commandToSave; + if (commandToSave > UCHAR_MAX) + { + commandToSave -= UCHAR_MAX; + } return static_cast(commandToSave); } @@ -360,7 +363,7 @@ namespace CalculationManager /// Serialized Rational of primary display void CalculatorManager::DeSerializePrimaryDisplay(const vector &serializedPrimaryDisplay) { - if (serializedPrimaryDisplay.size() == 0) + if (serializedPrimaryDisplay.empty()) { return; } @@ -490,22 +493,25 @@ namespace CalculationManager void CalculatorManager::MemorizeNumber() { m_savedCommands.push_back(MEMORY_COMMAND_TO_UNSIGNED_CHAR(MemoryCommand::MemorizeNumber)); - if (!(m_currentCalculatorEngine->FInErrorState())) + + if (m_currentCalculatorEngine->FInErrorState()) { - m_currentCalculatorEngine->ProcessCommand(IDC_STORE); - - auto memoryObjectPtr = m_currentCalculatorEngine->PersistedMemObject(); - if (memoryObjectPtr != nullptr) - { - m_memorizedNumbers.insert(m_memorizedNumbers.begin(), *memoryObjectPtr); - } - - if (m_memorizedNumbers.size() > m_maximumMemorySize) - { - m_memorizedNumbers.resize(m_maximumMemorySize); - } - this->SetMemorizedNumbersString(); + return; } + + m_currentCalculatorEngine->ProcessCommand(IDC_STORE); + + auto memoryObjectPtr = m_currentCalculatorEngine->PersistedMemObject(); + if (memoryObjectPtr != nullptr) + { + m_memorizedNumbers.insert(m_memorizedNumbers.begin(), *memoryObjectPtr); + } + + if (m_memorizedNumbers.size() > m_maximumMemorySize) + { + m_memorizedNumbers.resize(m_maximumMemorySize); + } + this->SetMemorizedNumbersString(); } /// @@ -516,11 +522,14 @@ namespace CalculationManager void CalculatorManager::MemorizedNumberLoad(_In_ unsigned int indexOfMemory) { SaveMemoryCommand(MemoryCommand::MemorizedNumberLoad, indexOfMemory); - if (!(m_currentCalculatorEngine->FInErrorState())) + + if (m_currentCalculatorEngine->FInErrorState()) { - this->MemorizedNumberSelect(indexOfMemory); - m_currentCalculatorEngine->ProcessCommand(IDC_RECALL); + return; } + + this->MemorizedNumberSelect(indexOfMemory); + m_currentCalculatorEngine->ProcessCommand(IDC_RECALL); } /// @@ -532,24 +541,27 @@ namespace CalculationManager void CalculatorManager::MemorizedNumberAdd(_In_ unsigned int indexOfMemory) { SaveMemoryCommand(MemoryCommand::MemorizedNumberAdd, indexOfMemory); - if (!(m_currentCalculatorEngine->FInErrorState())) + + if (m_currentCalculatorEngine->FInErrorState()) { - if (m_memorizedNumbers.empty()) - { - this->MemorizeNumber(); - } - else - { - this->MemorizedNumberSelect(indexOfMemory); - m_currentCalculatorEngine->ProcessCommand(IDC_MPLUS); - - this->MemorizedNumberChanged(indexOfMemory); - - this->SetMemorizedNumbersString(); - } - - m_displayCallback->MemoryItemChanged(indexOfMemory); + return; } + + if (m_memorizedNumbers.empty()) + { + this->MemorizeNumber(); + } + else + { + this->MemorizedNumberSelect(indexOfMemory); + m_currentCalculatorEngine->ProcessCommand(IDC_MPLUS); + + this->MemorizedNumberChanged(indexOfMemory); + + this->SetMemorizedNumbersString(); + } + + m_displayCallback->MemoryItemChanged(indexOfMemory); } void CalculatorManager::MemorizedNumberClear(_In_ unsigned int indexOfMemory) @@ -570,27 +582,30 @@ namespace CalculationManager void CalculatorManager::MemorizedNumberSubtract(_In_ unsigned int indexOfMemory) { SaveMemoryCommand(MemoryCommand::MemorizedNumberSubtract, indexOfMemory); - if (!(m_currentCalculatorEngine->FInErrorState())) + + if (m_currentCalculatorEngine->FInErrorState()) { - // To add negative of the number on display to the memory -x = x - 2x - if (m_memorizedNumbers.empty()) - { - this->MemorizeNumber(); - this->MemorizedNumberSubtract(0); - this->MemorizedNumberSubtract(0); - } - else - { - this->MemorizedNumberSelect(indexOfMemory); - m_currentCalculatorEngine->ProcessCommand(IDC_MMINUS); - - this->MemorizedNumberChanged(indexOfMemory); - - this->SetMemorizedNumbersString(); - } - - m_displayCallback->MemoryItemChanged(indexOfMemory); + return; } + + // To add negative of the number on display to the memory -x = x - 2x + if (m_memorizedNumbers.empty()) + { + this->MemorizeNumber(); + this->MemorizedNumberSubtract(0); + this->MemorizedNumberSubtract(0); + } + else + { + this->MemorizedNumberSelect(indexOfMemory); + m_currentCalculatorEngine->ProcessCommand(IDC_MMINUS); + + this->MemorizedNumberChanged(indexOfMemory); + + this->SetMemorizedNumbersString(); + } + + m_displayCallback->MemoryItemChanged(indexOfMemory); } /// @@ -613,11 +628,13 @@ namespace CalculationManager /// Index of the target memory void CalculatorManager::MemorizedNumberSelect(_In_ unsigned int indexOfMemory) { - if (!(m_currentCalculatorEngine->FInErrorState())) + if (m_currentCalculatorEngine->FInErrorState()) { - auto memoryObject = m_memorizedNumbers.at(indexOfMemory); - m_currentCalculatorEngine->PersistedMemObject(memoryObject); + return; } + + auto memoryObject = m_memorizedNumbers.at(indexOfMemory); + m_currentCalculatorEngine->PersistedMemObject(memoryObject); } /// @@ -627,13 +644,15 @@ namespace CalculationManager /// Index of the target memory void CalculatorManager::MemorizedNumberChanged(_In_ unsigned int indexOfMemory) { - if (!(m_currentCalculatorEngine->FInErrorState())) + if (m_currentCalculatorEngine->FInErrorState()) { - auto memoryObject = m_currentCalculatorEngine->PersistedMemObject(); - if (memoryObject != nullptr) - { - m_memorizedNumbers.at(indexOfMemory) = *memoryObject; - } + return; + } + + auto memoryObject = m_currentCalculatorEngine->PersistedMemObject(); + if (memoryObject != nullptr) + { + m_memorizedNumbers.at(indexOfMemory) = *memoryObject; } } diff --git a/src/CalcManager/CalculatorManager.h b/src/CalcManager/CalculatorManager.h index 4d8099f1..479485d0 100644 --- a/src/CalcManager/CalculatorManager.h +++ b/src/CalcManager/CalculatorManager.h @@ -42,7 +42,7 @@ namespace CalculationManager MemorizedNumberClear = 335 }; - class CalculatorManager sealed : public ICalcDisplay + class CalculatorManager final : public ICalcDisplay { private: ICalcDisplay* const m_displayCallback; @@ -141,7 +141,7 @@ namespace CalculationManager std::shared_ptr const& GetHistoryItem(_In_ unsigned int uIdx); bool RemoveHistoryItem(_In_ unsigned int uIdx); void ClearHistory(); - const size_t MaxHistorySize() const { return m_pHistory->MaxHistorySize(); } + size_t MaxHistorySize() const { return m_pHistory->MaxHistorySize(); } CalculationManager::Command GetCurrentDegreeMode(); void SetHistory(_In_ CALCULATOR_MODE eMode, _In_ std::vector> const& history); void SetInHistoryItemLoadMode(_In_ bool isHistoryItemLoadMode); diff --git a/src/CalcManager/ExpressionCommand.cpp b/src/CalcManager/ExpressionCommand.cpp index 08ee293c..0b68a374 100644 --- a/src/CalcManager/ExpressionCommand.cpp +++ b/src/CalcManager/ExpressionCommand.cpp @@ -98,8 +98,8 @@ void CBinaryCommand::Accept(_In_ ISerializeCommandVisitor &commandVisitor) COpndCommand::COpndCommand(shared_ptr> const &commands, bool fNegative, bool fDecimal, bool fSciFmt) : m_commands(commands), m_fNegative(fNegative), - m_fDecimal(fDecimal), m_fSciFmt(fSciFmt), + m_fDecimal(fDecimal), m_fInitialized(false), m_value{} {} diff --git a/src/CalcManager/Ratpack/conv.cpp b/src/CalcManager/Ratpack/conv.cpp index 02c6e052..d23d41b5 100644 --- a/src/CalcManager/Ratpack/conv.cpp +++ b/src/CalcManager/Ratpack/conv.cpp @@ -612,6 +612,7 @@ PNUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precis break; } // Drop through in the 'e'-as-a-digit case + [[fallthrough]]; default: state = machine[state][NZ]; break; @@ -646,7 +647,7 @@ PNUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precis break; case LD: pnumret->exp++; - // Fall through + [[fallthrough]]; case DD: { curChar = NormalizeCharDigit(curChar, radix); @@ -1270,7 +1271,7 @@ PNUMBER RatToNumber(_In_ PRAT prat, uint32_t radix, int32_t precision) // Convert p and q of rational form from internal base to requested base. // Scale by largest power of BASEX possible. long scaleby = min(temprat->pp->exp, temprat->pq->exp); - scaleby = max(scaleby, 0); + scaleby = max(scaleby, 0l); temprat->pp->exp -= scaleby; temprat->pq->exp -= scaleby; diff --git a/src/CalcManager/Ratpack/logic.cpp b/src/CalcManager/Ratpack/logic.cpp index 0403f0a3..71f33d4e 100644 --- a/src/CalcManager/Ratpack/logic.cpp +++ b/src/CalcManager/Ratpack/logic.cpp @@ -16,7 +16,7 @@ #include "pch.h" #include "ratpak.h" - +using namespace std; void lshrat( _Inout_ PRAT *pa, _In_ PRAT b, uint32_t radix, int32_t precision) diff --git a/src/CalcManager/Ratpack/ratpak.h b/src/CalcManager/Ratpack/ratpak.h index 4c582d99..d2ce3c53 100644 --- a/src/CalcManager/Ratpack/ratpak.h +++ b/src/CalcManager/Ratpack/ratpak.h @@ -225,7 +225,7 @@ memmove( (x)->pp->mant, &((x)->pp->mant[trim]), sizeof(MANTTYPE)*((x)->pp->cdigi (x)->pp->cdigit -= trim; \ (x)->pp->exp += trim; \ } \ - trim = min((x)->pp->exp,(x)->pq->exp);\ + trim = std::min((x)->pp->exp,(x)->pq->exp);\ (x)->pp->exp -= trim;\ (x)->pq->exp -= trim;\ } diff --git a/src/CalcManager/UnitConverter.cpp b/src/CalcManager/UnitConverter.cpp index bb1df9d6..0548719a 100644 --- a/src/CalcManager/UnitConverter.cpp +++ b/src/CalcManager/UnitConverter.cpp @@ -109,22 +109,8 @@ CategorySelectionInitializer UnitConverter::SetCurrentCategory(const Category& i vector& unitVector = m_categoryToUnits[m_currentCategory]; for (unsigned int i = 0; i < unitVector.size(); i++) { - if (unitVector[i].id == m_fromType.id) - { - unitVector[i].isConversionSource = true; - } - else - { - unitVector[i].isConversionSource = false; - } - if (unitVector[i].id == m_toType.id) - { - unitVector[i].isConversionTarget = true; - } - else - { - unitVector[i].isConversionTarget = false; - } + unitVector[i].isConversionSource = (unitVector[i].id == m_fromType.id); + unitVector[i].isConversionTarget = (unitVector[i].id == m_toType.id); } m_currentCategory = input; if (!m_currentCategory.supportsNegative && m_currentDisplay.front() == L'-') @@ -156,15 +142,17 @@ Category UnitConverter::GetCurrentCategory() /// Unit struct we are converting to void UnitConverter::SetCurrentUnitTypes(const Unit& fromType, const Unit& toType) { - if (CheckLoad()) + if (!CheckLoad()) { - m_fromType = fromType; - m_toType = toType; - Calculate(); - - UpdateCurrencySymbols(); - UpdateViewModel(); + return; } + + m_fromType = fromType; + m_toType = toType; + Calculate(); + + UpdateCurrencySymbols(); + UpdateViewModel(); } /// @@ -181,22 +169,24 @@ void UnitConverter::SetCurrentUnitTypes(const Unit& fromType, const Unit& toType /// void UnitConverter::SwitchActive(const wstring& newValue) { - if (CheckLoad()) + if (!CheckLoad()) { - swap(m_fromType, m_toType); - swap(m_currentHasDecimal, m_returnHasDecimal); - m_returnDisplay = m_currentDisplay; - m_currentDisplay = newValue; - m_currentHasDecimal = (m_currentDisplay.find(L'.') != m_currentDisplay.npos); - m_switchedActive = true; + return; + } - if (m_currencyDataLoader != nullptr && m_vmCurrencyCallback != nullptr) - { - shared_ptr currencyDataLoader = GetCurrencyConverterDataLoader(); - const pair currencyRatios = currencyDataLoader->GetCurrencyRatioEquality(m_fromType, m_toType); + swap(m_fromType, m_toType); + swap(m_currentHasDecimal, m_returnHasDecimal); + m_returnDisplay = m_currentDisplay; + m_currentDisplay = newValue; + m_currentHasDecimal = (m_currentDisplay.find(L'.') != m_currentDisplay.npos); + m_switchedActive = true; - m_vmCurrencyCallback->CurrencyRatiosCallback(currencyRatios.first, currencyRatios.second); - } + if (m_currencyDataLoader != nullptr && m_vmCurrencyCallback != nullptr) + { + shared_ptr currencyDataLoader = GetCurrencyConverterDataLoader(); + const pair currencyRatios = currencyDataLoader->GetCurrencyRatioEquality(m_fromType, m_toType); + + m_vmCurrencyCallback->CurrencyRatiosCallback(currencyRatios.first, currencyRatios.second); } } @@ -291,55 +281,53 @@ wstring UnitConverter::ConversionDataToString(ConversionData d, const wchar_t * /// wstring UnitConverter::Serialize() { - if (CheckLoad()) - { - wstringstream out(wstringstream::out); - const wchar_t * delimiter = L";"; - - out << UnitToString(m_fromType, delimiter) << "|"; - out << UnitToString(m_toType, delimiter) << "|"; - out << CategoryToString(m_currentCategory, delimiter) << "|"; - out << std::to_wstring(m_currentHasDecimal) << delimiter << std::to_wstring(m_returnHasDecimal) << delimiter << std::to_wstring(m_switchedActive) << delimiter; - out << m_currentDisplay << delimiter << m_returnDisplay << delimiter << "|"; - wstringstream categoryString(wstringstream::out); - wstringstream categoryToUnitString(wstringstream::out); - wstringstream unitToUnitToDoubleString(wstringstream::out); - for (const Category& c : m_categories) - { - categoryString << CategoryToString(c, delimiter) << ","; - } - - for (const auto& cur : m_categoryToUnits) - { - categoryToUnitString << CategoryToString(cur.first, delimiter) << "["; - for (const Unit& u : cur.second) - { - categoryToUnitString << UnitToString(u, delimiter) << ","; - } - categoryToUnitString << "[" << "]"; - } - - for (const auto& cur : m_ratioMap) - { - unitToUnitToDoubleString << UnitToString(cur.first, delimiter) << "["; - for (const auto& curConversion : cur.second) - { - unitToUnitToDoubleString << UnitToString(curConversion.first, delimiter) << ":"; - unitToUnitToDoubleString << ConversionDataToString(curConversion.second, delimiter) << ":,"; - } - unitToUnitToDoubleString << "[" << "]"; - } - - out << categoryString.str() << "|"; - out << categoryToUnitString.str() << "|"; - out << unitToUnitToDoubleString.str() << "|"; - wstring test = out.str(); - return test; - } - else + if (!CheckLoad()) { return wstring(); } + + wstringstream out(wstringstream::out); + const wchar_t * delimiter = L";"; + + out << UnitToString(m_fromType, delimiter) << "|"; + out << UnitToString(m_toType, delimiter) << "|"; + out << CategoryToString(m_currentCategory, delimiter) << "|"; + out << std::to_wstring(m_currentHasDecimal) << delimiter << std::to_wstring(m_returnHasDecimal) << delimiter << std::to_wstring(m_switchedActive) << delimiter; + out << m_currentDisplay << delimiter << m_returnDisplay << delimiter << "|"; + wstringstream categoryString(wstringstream::out); + wstringstream categoryToUnitString(wstringstream::out); + wstringstream unitToUnitToDoubleString(wstringstream::out); + for (const Category& c : m_categories) + { + categoryString << CategoryToString(c, delimiter) << ","; + } + + for (const auto& cur : m_categoryToUnits) + { + categoryToUnitString << CategoryToString(cur.first, delimiter) << "["; + for (const Unit& u : cur.second) + { + categoryToUnitString << UnitToString(u, delimiter) << ","; + } + categoryToUnitString << "[" << "]"; + } + + for (const auto& cur : m_ratioMap) + { + unitToUnitToDoubleString << UnitToString(cur.first, delimiter) << "["; + for (const auto& curConversion : cur.second) + { + unitToUnitToDoubleString << UnitToString(curConversion.first, delimiter) << ":"; + unitToUnitToDoubleString << ConversionDataToString(curConversion.second, delimiter) << ":,"; + } + unitToUnitToDoubleString << "[" << "]"; + } + + out << categoryString.str() << "|"; + out << categoryToUnitString.str() << "|"; + out << unitToUnitToDoubleString.str() << "|"; + wstring test = out.str(); + return test; } /// @@ -349,55 +337,58 @@ wstring UnitConverter::Serialize() void UnitConverter::DeSerialize(const wstring& serializedData) { Reset(); - if (!serializedData.empty()) + + if (serializedData.empty()) { - vector outerTokens = StringToVector(serializedData, L"|"); - assert(outerTokens.size() == EXPECTEDSERIALIZEDTOKENCOUNT); - m_fromType = StringToUnit(outerTokens[0]); - m_toType = StringToUnit(outerTokens[1]); - m_currentCategory = StringToCategory(outerTokens[2]); - vector stateDataTokens = StringToVector(outerTokens[3], L";"); - assert(stateDataTokens.size() == EXPECTEDSTATEDATATOKENCOUNT); - m_currentHasDecimal = (stateDataTokens[0].compare(L"1") == 0); - m_returnHasDecimal = (stateDataTokens[1].compare(L"1") == 0); - m_switchedActive = (stateDataTokens[2].compare(L"1") == 0); - m_currentDisplay = stateDataTokens[3]; - m_returnDisplay = stateDataTokens[4]; - vector categoryListTokens = StringToVector(outerTokens[4], L","); - for (wstring token : categoryListTokens) - { - m_categories.push_back(StringToCategory(token)); - } - vector unitVectorTokens = StringToVector(outerTokens[5], L"]"); - for (wstring unitVector : unitVectorTokens) - { - vector mapcomponents = StringToVector(unitVector, L"["); - assert(mapcomponents.size() == EXPECTEDMAPCOMPONENTTOKENCOUNT); - Category key = StringToCategory(mapcomponents[0]); - vector units = StringToVector(mapcomponents[1], L","); - for (wstring unit : units) - { - m_categoryToUnits[key].push_back(StringToUnit(unit)); - } - } - vector ratioMapTokens = StringToVector(outerTokens[6], L"]"); - for (wstring token : ratioMapTokens) - { - vector ratioMapComponentTokens = StringToVector(token, L"["); - assert(ratioMapComponentTokens.size() == EXPECTEDMAPCOMPONENTTOKENCOUNT); - Unit key = StringToUnit(ratioMapComponentTokens[0]); - vector ratioMapList = StringToVector(ratioMapComponentTokens[1], L","); - for (wstring subtoken : ratioMapList) - { - vector ratioMapSubComponentTokens = StringToVector(subtoken, L":"); - assert(ratioMapSubComponentTokens.size() == EXPECTEDMAPCOMPONENTTOKENCOUNT); - Unit subkey = StringToUnit(ratioMapSubComponentTokens[0]); - ConversionData conversion = StringToConversionData(ratioMapSubComponentTokens[1]); - m_ratioMap[key][subkey] = conversion; - } - } - UpdateViewModel(); + return; } + + vector outerTokens = StringToVector(serializedData, L"|"); + assert(outerTokens.size() == EXPECTEDSERIALIZEDTOKENCOUNT); + m_fromType = StringToUnit(outerTokens[0]); + m_toType = StringToUnit(outerTokens[1]); + m_currentCategory = StringToCategory(outerTokens[2]); + vector stateDataTokens = StringToVector(outerTokens[3], L";"); + assert(stateDataTokens.size() == EXPECTEDSTATEDATATOKENCOUNT); + m_currentHasDecimal = (stateDataTokens[0].compare(L"1") == 0); + m_returnHasDecimal = (stateDataTokens[1].compare(L"1") == 0); + m_switchedActive = (stateDataTokens[2].compare(L"1") == 0); + m_currentDisplay = stateDataTokens[3]; + m_returnDisplay = stateDataTokens[4]; + vector categoryListTokens = StringToVector(outerTokens[4], L","); + for (wstring token : categoryListTokens) + { + m_categories.push_back(StringToCategory(token)); + } + vector unitVectorTokens = StringToVector(outerTokens[5], L"]"); + for (wstring unitVector : unitVectorTokens) + { + vector mapcomponents = StringToVector(unitVector, L"["); + assert(mapcomponents.size() == EXPECTEDMAPCOMPONENTTOKENCOUNT); + Category key = StringToCategory(mapcomponents[0]); + vector units = StringToVector(mapcomponents[1], L","); + for (wstring unit : units) + { + m_categoryToUnits[key].push_back(StringToUnit(unit)); + } + } + vector ratioMapTokens = StringToVector(outerTokens[6], L"]"); + for (wstring token : ratioMapTokens) + { + vector ratioMapComponentTokens = StringToVector(token, L"["); + assert(ratioMapComponentTokens.size() == EXPECTEDMAPCOMPONENTTOKENCOUNT); + Unit key = StringToUnit(ratioMapComponentTokens[0]); + vector ratioMapList = StringToVector(ratioMapComponentTokens[1], L","); + for (wstring subtoken : ratioMapList) + { + vector ratioMapSubComponentTokens = StringToVector(subtoken, L":"); + assert(ratioMapSubComponentTokens.size() == EXPECTEDMAPCOMPONENTTOKENCOUNT); + Unit subkey = StringToUnit(ratioMapSubComponentTokens[0]); + ConversionData conversion = StringToConversionData(ratioMapSubComponentTokens[1]); + m_ratioMap[key][subkey] = conversion; + } + } + UpdateViewModel(); } /// @@ -406,15 +397,17 @@ void UnitConverter::DeSerialize(const wstring& serializedData) /// wstring holding the serialized data. If it does not have expected number of parameters, we will ignore it void UnitConverter::RestoreUserPreferences(const wstring& userPreferences) { - if (!userPreferences.empty()) + if (userPreferences.empty()) { - vector outerTokens = StringToVector(userPreferences, L"|"); - if (outerTokens.size() == 3) - { - m_fromType = StringToUnit(outerTokens[0]); - m_toType = StringToUnit(outerTokens[1]); - m_currentCategory = StringToCategory(outerTokens[2]); - } + return; + } + + vector outerTokens = StringToVector(userPreferences, L"|"); + if (outerTokens.size() == 3) + { + m_fromType = StringToUnit(outerTokens[0]); + m_toType = StringToUnit(outerTokens[1]); + m_currentCategory = StringToCategory(outerTokens[2]); } } @@ -503,144 +496,146 @@ wstring UnitConverter::Unquote(const wstring& s) /// Command enum representing the command that was entered void UnitConverter::SendCommand(Command command) { - if (CheckLoad()) + if (!CheckLoad()) { - // TODO: Localization of characters - bool clearFront = false; - if (m_currentDisplay == L"0") + return; + } + + // TODO: Localization of characters + bool clearFront = false; + if (m_currentDisplay == L"0") + { + clearFront = true; + } + bool clearBack = false; + if ((m_currentHasDecimal && m_currentDisplay.size() - 1 >= MAXIMUMDIGITSALLOWED) || (!m_currentHasDecimal && m_currentDisplay.size() >= MAXIMUMDIGITSALLOWED)) + { + clearBack = true; + } + if (command != Command::Negate && m_switchedActive) + { + ClearValues(); + m_switchedActive = false; + clearFront = true; + clearBack = false; + } + switch (command) + { + case Command::Zero: + m_currentDisplay += L"0"; + break; + + case Command::One: + m_currentDisplay += L"1"; + break; + + case Command::Two: + m_currentDisplay += L"2"; + break; + + case Command::Three: + m_currentDisplay += L"3"; + break; + + case Command::Four: + m_currentDisplay += L"4"; + break; + + case Command::Five: + m_currentDisplay += L"5"; + break; + + case Command::Six: + m_currentDisplay += L"6"; + break; + + case Command::Seven: + m_currentDisplay += L"7"; + break; + + case Command::Eight: + m_currentDisplay += L"8"; + break; + + case Command::Nine: + m_currentDisplay += L"9"; + break; + + case Command::Decimal: + clearFront = false; + clearBack = false; + if (!m_currentHasDecimal) { - clearFront = true; + m_currentDisplay += L"."; + m_currentHasDecimal = true; } - bool clearBack = false; - if ((m_currentHasDecimal && m_currentDisplay.size() - 1 >= MAXIMUMDIGITSALLOWED) || (!m_currentHasDecimal && m_currentDisplay.size() >= MAXIMUMDIGITSALLOWED)) + break; + + case Command::Backspace: + clearFront = false; + clearBack = false; + if ((m_currentDisplay.front() != '-' && m_currentDisplay.size() > 1) || m_currentDisplay.size() > 2) { - clearBack = true; - } - if (command != Command::Negate && m_switchedActive) - { - ClearValues(); - m_switchedActive = false; - clearFront = true; - clearBack = false; - } - switch (command) - { - case Command::Zero: - m_currentDisplay += L"0"; - break; - - case Command::One: - m_currentDisplay += L"1"; - break; - - case Command::Two: - m_currentDisplay += L"2"; - break; - - case Command::Three: - m_currentDisplay += L"3"; - break; - - case Command::Four: - m_currentDisplay += L"4"; - break; - - case Command::Five: - m_currentDisplay += L"5"; - break; - - case Command::Six: - m_currentDisplay += L"6"; - break; - - case Command::Seven: - m_currentDisplay += L"7"; - break; - - case Command::Eight: - m_currentDisplay += L"8"; - break; - - case Command::Nine: - m_currentDisplay += L"9"; - break; - - case Command::Decimal: - clearFront = false; - clearBack = false; - if (!m_currentHasDecimal) + if (m_currentDisplay.back() == '.') { - m_currentDisplay += L"."; - m_currentHasDecimal = true; + m_currentHasDecimal = false; } - break; + m_currentDisplay.pop_back(); + } + else + { + m_currentDisplay = L"0"; + m_currentHasDecimal = false; + } + break; - case Command::Backspace: - clearFront = false; - clearBack = false; - if ((m_currentDisplay.front() != '-' && m_currentDisplay.size() > 1) || m_currentDisplay.size() > 2) + case Command::Negate: + clearFront = false; + clearBack = false; + if (m_currentCategory.supportsNegative) + { + if (m_currentDisplay.front() == '-') { - if (m_currentDisplay.back() == '.') - { - m_currentHasDecimal = false; - } - m_currentDisplay.pop_back(); + m_currentDisplay.erase(0, 1); } else { - m_currentDisplay = L"0"; - m_currentHasDecimal = false; + m_currentDisplay.insert(0, 1, '-'); } - break; - - case Command::Negate: - clearFront = false; - clearBack = false; - if (m_currentCategory.supportsNegative) - { - if (m_currentDisplay.front() == '-') - { - m_currentDisplay.erase(0, 1); - } - else - { - m_currentDisplay.insert(0, 1, '-'); - } - } - break; - - case Command::Clear: - clearFront = false; - clearBack = false; - ClearValues(); - break; - - case Command::Reset: - clearFront = false; - clearBack = false; - ClearValues(); - Reset(); - break; - - default: - break; } + break; + case Command::Clear: + clearFront = false; + clearBack = false; + ClearValues(); + break; - if (clearFront) - { - m_currentDisplay.erase(0, 1); - } - if (clearBack) - { - m_currentDisplay.erase(m_currentDisplay.size() - 1, 1); - m_vmCallback->MaxDigitsReached(); - } + case Command::Reset: + clearFront = false; + clearBack = false; + ClearValues(); + Reset(); + break; - Calculate(); - - UpdateViewModel(); + default: + break; } + + + if (clearFront) + { + m_currentDisplay.erase(0, 1); + } + if (clearBack) + { + m_currentDisplay.erase(m_currentDisplay.size() - 1, 1); + m_vmCallback->MaxDigitsReached(); + } + + Calculate(); + + UpdateViewModel(); } /// @@ -844,47 +839,49 @@ void UnitConverter::Reset() ClearValues(); m_switchedActive = false; - if (!m_categories.empty()) + if (m_categories.empty()) { - m_currentCategory = m_categories[0]; + return; + } - m_categoryToUnits.clear(); - m_ratioMap.clear(); - bool readyCategoryFound = false; - for (const Category& category : m_categories) + m_currentCategory = m_categories[0]; + + m_categoryToUnits.clear(); + m_ratioMap.clear(); + bool readyCategoryFound = false; + for (const Category& category : m_categories) + { + shared_ptr activeDataLoader = GetDataLoaderForCategory(category); + if (activeDataLoader == nullptr) { - shared_ptr activeDataLoader = GetDataLoaderForCategory(category); - if (activeDataLoader == nullptr) - { - // The data loader is different depending on the category, e.g. currency data loader - // is different from the static data loader. - // If there is no data loader for this category, continue. - continue; - } - - vector units = activeDataLoader->LoadOrderedUnits(category); - m_categoryToUnits[category] = units; - - // Just because the units are empty, doesn't mean the user can't select this category, - // we just want to make sure we don't let an unready category be the default. - if (!units.empty()) - { - for (Unit u : units) - { - m_ratioMap[u] = activeDataLoader->LoadOrderedRatios(u); - } - - if (!readyCategoryFound) - { - m_currentCategory = category; - readyCategoryFound = true; - } - } + // The data loader is different depending on the category, e.g. currency data loader + // is different from the static data loader. + // If there is no data loader for this category, continue. + continue; } - InitializeSelectedUnits(); - Calculate(); + vector units = activeDataLoader->LoadOrderedUnits(category); + m_categoryToUnits[category] = units; + + // Just because the units are empty, doesn't mean the user can't select this category, + // we just want to make sure we don't let an unready category be the default. + if (!units.empty()) + { + for (Unit u : units) + { + m_ratioMap[u] = activeDataLoader->LoadOrderedRatios(u); + } + + if (!readyCategoryFound) + { + m_currentCategory = category; + readyCategoryFound = true; + } + } } + + InitializeSelectedUnits(); + Calculate(); } /// @@ -1029,22 +1026,24 @@ void UnitConverter::Calculate() /// wstring to trim void UnitConverter::TrimString(wstring& returnString) { - if (returnString.find(L'.') != m_returnDisplay.npos) + if (returnString.find(L'.') == m_returnDisplay.npos) { - wstring::iterator iter; - for (iter = returnString.end() - 1; ;iter--) + return; + } + + wstring::iterator iter; + for (iter = returnString.end() - 1; ;iter--) + { + if (*iter != L'0') { - if (*iter != L'0') - { - returnString.erase(iter + 1, returnString.end()); - break; - } - } - if (*(returnString.end()-1) == L'.') - { - returnString.erase(returnString.end()-1, returnString.end()); + returnString.erase(iter + 1, returnString.end()); + break; } } + if (*(returnString.end()-1) == L'.') + { + returnString.erase(returnString.end()-1, returnString.end()); + } } /// diff --git a/src/CalcManager/pch.h b/src/CalcManager/pch.h index 4690713c..ff0ca451 100644 --- a/src/CalcManager/pch.h +++ b/src/CalcManager/pch.h @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #pragma once @@ -7,6 +7,10 @@ #define WIN32_LEAN_AND_MEAN #endif +// Windows headers define min/max macros. +// Disable it for project code. +#define NOMINMAX + #include #include #include diff --git a/src/CalcViewModel/ApplicationViewModel.cpp b/src/CalcViewModel/ApplicationViewModel.cpp index 4df5bac3..f99ce036 100644 --- a/src/CalcViewModel/ApplicationViewModel.cpp +++ b/src/CalcViewModel/ApplicationViewModel.cpp @@ -32,14 +32,11 @@ using namespace Windows::UI::Xaml::Data; using namespace Windows::UI::Xaml::Input; using namespace Windows::UI::Xaml::Media; -namespace CalculatorApp::ViewModel::ApplicationViewModelProperties +namespace { - StringReference Mode(L"Mode"); - StringReference PreviousMode(L"PreviousMode"); - StringReference ClearMemoryVisibility(L"ClearMemoryVisibility"); - StringReference AppBarVisibility(L"AppBarVisibility"); - StringReference CategoryName(L"CategoryName"); - StringReference Categories(L"Categories"); + StringReference CategoriesPropertyName(L"Categories"); + StringReference ClearMemoryVisibilityPropertyName(L"ClearMemoryVisibility"); + StringReference AppBarVisibilityPropertyName(L"AppBarVisibility"); } ApplicationViewModel::ApplicationViewModel() : @@ -60,7 +57,7 @@ void ApplicationViewModel::Mode::set(ViewMode value) PreviousMode = m_mode; m_mode = value; OnModeChanged(); - RaisePropertyChanged(ApplicationViewModelProperties::Mode); + RaisePropertyChanged(ModePropertyName); } } @@ -69,7 +66,7 @@ void ApplicationViewModel::Categories::set(IObservableVector^ if (m_categories != value) { m_categories = value; - RaisePropertyChanged(ApplicationViewModelProperties::Categories); + RaisePropertyChanged(CategoriesPropertyName); } } @@ -163,11 +160,11 @@ void ApplicationViewModel::OnModeChanged() // // Save the changed mode, so that the new window launches in this mode. // Don't save until after we have adjusted to the new mode, so we don't save a mode that fails to load. - ApplicationData::Current->LocalSettings->Values->Insert(ApplicationViewModelProperties::Mode, NavCategory::Serialize(m_mode)); + ApplicationData::Current->LocalSettings->Values->Insert(ModePropertyName, NavCategory::Serialize(m_mode)); TraceLogger::GetInstance().LogModeChangeEnd(m_mode, ApplicationView::GetApplicationViewIdForWindow(CoreWindow::GetForCurrentThread())); - RaisePropertyChanged(ApplicationViewModelProperties::ClearMemoryVisibility); - RaisePropertyChanged(ApplicationViewModelProperties::AppBarVisibility); + RaisePropertyChanged(ClearMemoryVisibilityPropertyName); + RaisePropertyChanged(AppBarVisibilityPropertyName); } void ApplicationViewModel::OnCopyCommand(Object^ parameter) diff --git a/src/CalcViewModel/ApplicationViewModel.h b/src/CalcViewModel/ApplicationViewModel.h index a8d459f7..f13e00ad 100644 --- a/src/CalcViewModel/ApplicationViewModel.h +++ b/src/CalcViewModel/ApplicationViewModel.h @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #pragma once @@ -11,16 +11,6 @@ namespace CalculatorApp { namespace ViewModel { - namespace ApplicationViewModelProperties - { - extern Platform::StringReference Mode; - extern Platform::StringReference PreviousMode; - extern Platform::StringReference ClearMemoryVisibility; - extern Platform::StringReference AppBarVisibility; - extern Platform::StringReference CategoryName; - extern Platform::StringReference Categories; - } - [Windows::UI::Xaml::Data::Bindable] public ref class ApplicationViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged { @@ -32,9 +22,9 @@ namespace CalculatorApp OBSERVABLE_OBJECT(); OBSERVABLE_PROPERTY_RW(StandardCalculatorViewModel^, CalculatorViewModel); OBSERVABLE_PROPERTY_RW(DateCalculatorViewModel^, DateCalcViewModel); - OBSERVABLE_PROPERTY_RW(CalculatorApp::ViewModel::UnitConverterViewModel^, ConverterViewModel); + OBSERVABLE_PROPERTY_RW(UnitConverterViewModel^, ConverterViewModel); OBSERVABLE_PROPERTY_RW(CalculatorApp::Common::ViewMode, PreviousMode); - OBSERVABLE_PROPERTY_RW(Platform::String^, CategoryName); + OBSERVABLE_NAMED_PROPERTY_RW(Platform::String^, CategoryName); COMMAND_FOR_METHOD(CopyCommand, ApplicationViewModel::OnCopyCommand); COMMAND_FOR_METHOD(PasteCommand, ApplicationViewModel::OnPasteCommand); @@ -48,6 +38,13 @@ namespace CalculatorApp void set(CalculatorApp::Common::ViewMode value); } + static property Platform::String^ ModePropertyName + { + Platform::String^ get() + { + return Platform::StringReference(L"Mode"); + } + } property Windows::Foundation::Collections::IObservableVector^ Categories { diff --git a/src/CalcViewModel/Common/CopyPasteManager.cpp b/src/CalcViewModel/Common/CopyPasteManager.cpp index c11630c4..00f13b52 100644 --- a/src/CalcViewModel/Common/CopyPasteManager.cpp +++ b/src/CalcViewModel/Common/CopyPasteManager.cpp @@ -139,7 +139,7 @@ String^ CopyPasteManager::ValidatePasteExpression(String^ pastedText, ViewMode m String^ englishString = LocalizationSettings::GetInstance().GetEnglishValueFromLocalizedDigits(pasteExpression); // Removing the spaces, comma separator from the pasteExpression to allow pasting of expressions like 1 + 2+1,333 - pasteExpression = Utils::RemoveUnwantedCharsFromWstring(englishString->Data()); + pasteExpression = RemoveUnwantedCharsFromWstring(englishString->Data()); // If the last character is an = sign, remove it from the pasteExpression to allow evaluating the result on paste. if (!pasteExpression.empty() && pasteExpression.back() == L'=') @@ -567,3 +567,21 @@ size_t CopyPasteManager::ProgrammerOperandLength(const wstring& operand, int num return len; } + +// return wstring after removing characters like space, comma, double quotes, and monetary prefix currency symbols supported by the Windows keyboard: +// yen or yuan(¥) - 165 +// unspecified currency sign(¤) - 164 +// Ghanaian cedi(₵) - 8373 +// dollar or peso($) - 36 +// colón(₡) - 8353 +// won(₩) - 8361 +// shekel(₪) - 8362 +// naira(₦) - 8358 +// Indian rupee(₹) - 8377 +// pound(£) - 163 +// euro(€) - 8364 +wstring CopyPasteManager::RemoveUnwantedCharsFromWstring(const wstring& input) +{ + wchar_t unWantedChars[] = { L' ', L',', L'"', 165, 164, 8373, 36, 8353, 8361, 8362, 8358, 8377, 163, 8364, 8234, 8235, 8236, 8237 }; + return Utils::RemoveUnwantedCharsFromWstring(input, unWantedChars, 18); +} diff --git a/src/CalcViewModel/Common/CopyPasteManager.h b/src/CalcViewModel/Common/CopyPasteManager.h index 1da4af4e..9a886154 100644 --- a/src/CalcViewModel/Common/CopyPasteManager.h +++ b/src/CalcViewModel/Common/CopyPasteManager.h @@ -58,6 +58,7 @@ namespace CalculatorApp static size_t OperandLength(std::wstring operand, CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, int programmerNumberBase = -1); static size_t StandardScientificOperandLength(std::wstring operand); static size_t ProgrammerOperandLength(const std::wstring& operand, int numberBase); + static std::wstring RemoveUnwantedCharsFromWstring(const std::wstring& input); static constexpr size_t MaxStandardOperandLength = 16; static constexpr size_t MaxScientificOperandLength = 32; diff --git a/src/CalcViewModel/Common/DateCalculator.cpp b/src/CalcViewModel/Common/DateCalculator.cpp index 6a4ba944..e179a052 100644 --- a/src/CalcViewModel/Common/DateCalculator.cpp +++ b/src/CalcViewModel/Common/DateCalculator.cpp @@ -12,6 +12,7 @@ using namespace CalculatorApp::Common::DateCalculation; DateCalculationEngine::DateCalculationEngine(_In_ String^ calendarIdentifier) { m_calendar = ref new Calendar(); + m_calendar->ChangeTimeZone("UTC"); m_calendar->ChangeCalendarSystem(calendarIdentifier); } diff --git a/src/CalcViewModel/Common/Utils.cpp b/src/CalcViewModel/Common/Utils.cpp index 1f024f58..c8a9ef00 100644 --- a/src/CalcViewModel/Common/Utils.cpp +++ b/src/CalcViewModel/Common/Utils.cpp @@ -80,7 +80,13 @@ void Utils::RunOnUIThreadNonblocking(std::function&& function, _In_ Core } } -//return wstring after removing characters specified by unwantedChars array +// Returns if the last character of a wstring is the target wchar_t +bool Utils::IsLastCharacterTarget(_In_ wstring const &input, _In_ wchar_t target) +{ + return !input.empty() && input.back() == target; +} + +// Return wstring after removing characters specified by unwantedChars array wstring Utils::RemoveUnwantedCharsFromWstring(wstring input, _In_reads_(size) wchar_t* unwantedChars, unsigned int size) { for (unsigned int i = 0; i < size; ++i) diff --git a/src/CalcViewModel/Common/Utils.h b/src/CalcViewModel/Common/Utils.h index eee37d68..10279350 100644 --- a/src/CalcViewModel/Common/Utils.h +++ b/src/CalcViewModel/Common/Utils.h @@ -42,10 +42,16 @@ }\ } private: t m_##n; public: -#define NAMED_OBSERVABLE_PROPERTY_RW(t, n)\ +#define OBSERVABLE_NAMED_PROPERTY_R(t, n)\ + OBSERVABLE_PROPERTY_R(t, n)\ + internal: static property Platform::String^ n##PropertyName {\ + Platform::String^ get() { return Platform::StringReference(L#n); }\ + } public: + +#define OBSERVABLE_NAMED_PROPERTY_RW(t, n)\ OBSERVABLE_PROPERTY_RW(t, n)\ - private: property Platform::StringReference n##_PropertyName {\ - Platform::StringReference get() { return Platform::StringReference(L#n); }\ + internal: static property Platform::String^ n##PropertyName {\ + Platform::String^ get() { return Platform::StringReference(L#n); }\ } public: #define OBSERVABLE_PROPERTY_FIELD(n) m_##n diff --git a/src/CalcViewModel/DateCalculatorViewModel.cpp b/src/CalcViewModel/DateCalculatorViewModel.cpp index e705c983..fd4bb71b 100644 --- a/src/CalcViewModel/DateCalculatorViewModel.cpp +++ b/src/CalcViewModel/DateCalculatorViewModel.cpp @@ -22,14 +22,14 @@ using namespace Windows::Globalization; using namespace Windows::Globalization::DateTimeFormatting; using namespace Windows::System::UserProfile; -namespace CalculatorApp::ViewModel::DateCalculatorViewModelProperties +namespace { - StringReference StrDateDiffResult(L"StrDateDiffResult"); - StringReference StrDateDiffResultAutomationName(L"StrDateDiffResultAutomationName"); - StringReference StrDateDiffResultInDays(L"StrDateDiffResultInDays"); - StringReference StrDateResult(L"StrDateResult"); - StringReference StrDateResultAutomationName(L"StrDateResultAutomationName"); - StringReference IsDiffInDays(L"IsDiffInDays"); + StringReference StrDateDiffResultPropertyName(L"StrDateDiffResult"); + StringReference StrDateDiffResultAutomationNamePropertyName(L"StrDateDiffResultAutomationName"); + StringReference StrDateDiffResultInDaysPropertyName(L"StrDateDiffResultInDays"); + StringReference StrDateResultPropertyName(L"StrDateResult"); + StringReference StrDateResultAutomationNamePropertyName(L"StrDateResultAutomationName"); + StringReference IsDiffInDaysPropertyName(L"IsDiffInDays"); } DateCalculatorViewModel::DateCalculatorViewModel() : @@ -43,11 +43,7 @@ DateCalculatorViewModel::DateCalculatorViewModel() : m_StrDateDiffResultAutomationName(L""), m_StrDateDiffResultInDays(L""), m_StrDateResult(L""), - m_StrDateResultAutomationName(L""), - m_fromDate({ 0 }), - m_toDate({ 0 }), - m_startDate({ 0 }), - m_dateResult({ 0 }) + m_StrDateResultAutomationName(L"") { const auto& localizationSettings = LocalizationSettings::GetInstance(); @@ -56,24 +52,24 @@ DateCalculatorViewModel::DateCalculatorViewModel() : // Initialize Date Calc engine m_dateCalcEngine = make_shared(localizationSettings.GetCalendarIdentifier()); - // Initialize dates of DatePicker controls to today's date auto calendar = ref new Calendar(); + // We force the timezone to UTC, in order to avoid being affected by Daylight Saving Time + // when we calculate the difference between 2 dates. + calendar->ChangeTimeZone("UTC"); auto today = calendar->GetDateTime(); // FromDate and ToDate should be clipped (adjusted to a consistent hour in UTC) - m_fromDate = today; - m_toDate = today; - FromDate = ClipTime(today); - ToDate = ClipTime(today); + m_fromDate = ClipTime(today); + m_toDate = ClipTime(today); // StartDate should not be clipped - StartDate = today; + m_startDate = today; m_dateResult = today; // Initialize the list separator delimiter appended with a space at the end, e.g. ", " // This will be used for date difference formatting: Y years, M months, W weeks, D days - m_listSeparator = ref new String((localizationSettings.GetListSeparator() + L" ").c_str()); + m_listSeparator = localizationSettings.GetListSeparator() + L" "; // Initialize the output results UpdateDisplayResult(); @@ -86,15 +82,6 @@ DateCalculatorViewModel::DateCalculatorViewModel() : m_offsetValues->Append(ref new String(numberStr.c_str())); } - /* In the ClipTime function, we used to change timezone to UTC before clipping the time. - The comment from the previous developers said this was done to eliminate the effects of - Daylight Savings Time. We can't think of a good reason why this change in timezone is - necessary and did find bugs related to the change, therefore, we have removed the - change. Just in case, we will see if the clipped time is ever a different day from the - original day, which would hopefully indicate the change in timezone was actually - necessary. We will collect telemetry if we find this case. If we don't see any - telemetry events after the application has been used for some time, we will feel safe - and can remove this function. */ DayOfWeek trueDayOfWeek = calendar->DayOfWeek; DateTime clippedTime = ClipTime(today); @@ -110,18 +97,18 @@ DateCalculatorViewModel::DateCalculatorViewModel() : void DateCalculatorViewModel::OnPropertyChanged(_In_ String^ prop) { - if (prop == DateCalculatorViewModelProperties::StrDateDiffResult) + if (prop == StrDateDiffResultPropertyName) { UpdateStrDateDiffResultAutomationName(); } - else if (prop == DateCalculatorViewModelProperties::StrDateResult) + else if (prop == StrDateResultPropertyName) { UpdateStrDateResultAutomationName(); } - else if (prop != DateCalculatorViewModelProperties::StrDateDiffResultAutomationName - && prop != DateCalculatorViewModelProperties::StrDateDiffResultInDays - && prop != DateCalculatorViewModelProperties::StrDateResultAutomationName - && prop != DateCalculatorViewModelProperties::IsDiffInDays) + else if (prop != StrDateDiffResultAutomationNamePropertyName + && prop != StrDateDiffResultInDaysPropertyName + && prop != StrDateResultAutomationNamePropertyName + && prop != IsDiffInDaysPropertyName) { OnInputsChanged(); } @@ -181,8 +168,8 @@ void DateCalculatorViewModel::UpdateDisplayResult() StrDateDiffResult = AppResourceProvider::GetInstance().GetResourceString(L"Date_SameDates"); } else if ((m_dateDiffResult.year == 0) && - (m_dateDiffResult.month == 0) && - (m_dateDiffResult.week == 0)) + (m_dateDiffResult.month == 0) && + (m_dateDiffResult.week == 0)) { IsDiffInDays = true; StrDateDiffResultInDays = L""; @@ -245,22 +232,23 @@ void DateCalculatorViewModel::InitializeDateOutputFormats(_In_ String^ calendarI String^ DateCalculatorViewModel::GetDateDiffString() const { - String^ result = L""; + wstring result; bool addDelimiter = false; AppResourceProvider resourceLoader = AppResourceProvider::GetInstance(); auto yearCount = m_dateDiffResult.year; if (yearCount > 0) { - result = String::Concat(GetLocalizedNumberString(yearCount), L" "); + result += GetLocalizedNumberString(yearCount)->Data(); + result += L" "; if (yearCount > 1) { - result = String::Concat(result, resourceLoader.GetResourceString(L"Date_Years")); + result += resourceLoader.GetResourceString(L"Date_Years")->Data(); } else { - result = String::Concat(result, resourceLoader.GetResourceString(L"Date_Year")); + result += resourceLoader.GetResourceString(L"Date_Year")->Data(); } // set the flags to add a delimiter whenever the next unit is added @@ -272,22 +260,23 @@ String^ DateCalculatorViewModel::GetDateDiffString() const { if (addDelimiter) { - result = String::Concat(result, m_listSeparator); + result += m_listSeparator; } else { addDelimiter = true; } - result = String::Concat(result, String::Concat(GetLocalizedNumberString(monthCount), L" ")); + result += GetLocalizedNumberString(monthCount)->Data(); + result += L" "; if (monthCount > 1) { - result = String::Concat(result, resourceLoader.GetResourceString(L"Date_Months")); + result += resourceLoader.GetResourceString(L"Date_Months")->Data(); } else { - result = String::Concat(result, resourceLoader.GetResourceString(L"Date_Month")); + result += resourceLoader.GetResourceString(L"Date_Month")->Data(); } } @@ -296,22 +285,23 @@ String^ DateCalculatorViewModel::GetDateDiffString() const { if (addDelimiter) { - result = String::Concat(result, m_listSeparator); + result += m_listSeparator; } else { addDelimiter = true; } - result = String::Concat(result, String::Concat(GetLocalizedNumberString(weekCount), L" ")); + result += GetLocalizedNumberString(weekCount)->Data(); + result += L" "; if (weekCount > 1) { - result = String::Concat(result, resourceLoader.GetResourceString(L"Date_Weeks")); + result += resourceLoader.GetResourceString(L"Date_Weeks")->Data(); } else { - result = String::Concat(result, resourceLoader.GetResourceString(L"Date_Week")); + result += resourceLoader.GetResourceString(L"Date_Week")->Data(); } } @@ -320,43 +310,45 @@ String^ DateCalculatorViewModel::GetDateDiffString() const { if (addDelimiter) { - result = String::Concat(result, m_listSeparator); + result += m_listSeparator; } else { addDelimiter = true; } - result = String::Concat(result, String::Concat(GetLocalizedNumberString(dayCount), L" ")); + result += GetLocalizedNumberString(dayCount)->Data(); + result += L" "; if (dayCount > 1) { - result = String::Concat(result, resourceLoader.GetResourceString(L"Date_Days")); + result += resourceLoader.GetResourceString(L"Date_Days")->Data(); } else { - result = String::Concat(result, resourceLoader.GetResourceString(L"Date_Day")); + result += resourceLoader.GetResourceString(L"Date_Day")->Data(); } } - return result; + return ref new String(result.data()); } String^ DateCalculatorViewModel::GetDateDiffStringInDays() const { - String^ strDateUnit; + wstring result = GetLocalizedNumberString(m_dateDiffResultInDays.day)->Data(); + result += L" "; // Display the result as '1 day' or 'N days' if (m_dateDiffResultInDays.day > 1) { - strDateUnit = AppResourceProvider::GetInstance().GetResourceString(L"Date_Days"); + result += AppResourceProvider::GetInstance().GetResourceString(L"Date_Days")->Data(); } else { - strDateUnit = AppResourceProvider::GetInstance().GetResourceString(L"Date_Day"); + result += AppResourceProvider::GetInstance().GetResourceString(L"Date_Day")->Data(); } - return String::Concat(GetLocalizedNumberString(m_dateDiffResultInDays.day), String::Concat(L" ", strDateUnit)); + return ref new String(result.data()); } void DateCalculatorViewModel::OnCopyCommand(Platform::Object^ parameter) @@ -378,13 +370,14 @@ String^ DateCalculatorViewModel::GetLocalizedNumberString(int value) const return ref new String(numberStr.c_str()); } -// Adjusts the given DateTime to 12AM of the same day +// Adjusts the given DateTime to 12AM (UTC) of the same day DateTime DateCalculatorViewModel::ClipTime(DateTime dateTime) { auto calendar = ref new Calendar(); + calendar->ChangeTimeZone("UTC"); calendar->SetDateTime(dateTime); - calendar->Period = 1; - calendar->Hour = 12; + calendar->Period = calendar->FirstPeriodInThisDay; + calendar->Hour = calendar->FirstHourInThisPeriod; calendar->Minute = 0; calendar->Second = 0; calendar->Nanosecond = 0; diff --git a/src/CalcViewModel/DateCalculatorViewModel.h b/src/CalcViewModel/DateCalculatorViewModel.h index 5eea6186..181b84b5 100644 --- a/src/CalcViewModel/DateCalculatorViewModel.h +++ b/src/CalcViewModel/DateCalculatorViewModel.h @@ -23,8 +23,8 @@ namespace CalculatorApp // Input Properties OBSERVABLE_PROPERTY_RW(bool, IsDateDiffMode); OBSERVABLE_PROPERTY_RW(bool, IsAddMode); - OBSERVABLE_PROPERTY_RW(bool, IsDiffInDays); // If diff is only in days or the dates are the same, - // then show only one result and avoid redundancy + OBSERVABLE_PROPERTY_R(bool, IsDiffInDays); // If diff is only in days or the dates are the same, + // then show only one result and avoid redundancy OBSERVABLE_PROPERTY_RW(int, DaysOffset); OBSERVABLE_PROPERTY_RW(int, MonthsOffset); @@ -82,11 +82,11 @@ namespace CalculatorApp } // Output Properties - OBSERVABLE_PROPERTY_RW(Platform::String^, StrDateDiffResult); - OBSERVABLE_PROPERTY_RW(Platform::String^, StrDateDiffResultAutomationName); - OBSERVABLE_PROPERTY_RW(Platform::String^, StrDateDiffResultInDays); - OBSERVABLE_PROPERTY_RW(Platform::String^, StrDateResult); - OBSERVABLE_PROPERTY_RW(Platform::String^, StrDateResultAutomationName); + OBSERVABLE_PROPERTY_R(Platform::String^, StrDateDiffResult); + OBSERVABLE_PROPERTY_R(Platform::String^, StrDateDiffResultAutomationName); + OBSERVABLE_PROPERTY_R(Platform::String^, StrDateDiffResultInDays); + OBSERVABLE_PROPERTY_R(Platform::String^, StrDateResult); + OBSERVABLE_PROPERTY_R(Platform::String^, StrDateResultAutomationName); COMMAND_FOR_METHOD(CopyCommand, DateCalculatorViewModel::OnCopyCommand); @@ -104,8 +104,6 @@ namespace CalculatorApp Platform::String^ GetLocalizedNumberString(int value) const; static Windows::Foundation::DateTime ClipTime(Windows::Foundation::DateTime dateTime); - static void CheckClipTimeSameDay(Windows::Globalization::Calendar^ reference); - property bool IsOutOfBound { bool get() { return m_isOutOfBound; } @@ -146,7 +144,7 @@ namespace CalculatorApp CalculatorApp::Common::DateCalculation::DateUnit m_daysOutputFormat; CalculatorApp::Common::DateCalculation::DateUnit m_allDateUnitsOutputFormat; Windows::Globalization::DateTimeFormatting::DateTimeFormatter^ m_dateTimeFormatter; - Platform::String^ m_listSeparator; + std::wstring m_listSeparator; }; } } diff --git a/src/CalcViewModel/StandardCalculatorViewModel.cpp b/src/CalcViewModel/StandardCalculatorViewModel.cpp index 7f4b6332..c01c4789 100644 --- a/src/CalcViewModel/StandardCalculatorViewModel.cpp +++ b/src/CalcViewModel/StandardCalculatorViewModel.cpp @@ -30,40 +30,34 @@ constexpr int StandardModePrecision = 16; constexpr int ScientificModePrecision = 32; constexpr int ProgrammerModePrecision = 64; -namespace CalculatorApp::ViewModel +namespace { - namespace CalculatorViewModelProperties - { - StringReference IsMemoryEmpty(L"IsMemoryEmpty"); - StringReference IsScientific(L"IsScientific"); - StringReference IsStandard(L"IsStandard"); - StringReference IsProgrammer(L"IsProgrammer"); - StringReference DisplayValue(L"DisplayValue"); - StringReference IsInError(L"IsInError"); - StringReference BinaryDisplayValue(L"BinaryDisplayValue"); - StringReference OpenParenthesisCount(L"OpenParenthesisCount"); - } + StringReference IsStandardPropertyName(L"IsStandard"); + StringReference IsScientificPropertyName(L"IsScientific"); + StringReference IsProgrammerPropertyName(L"IsProgrammer"); + StringReference DisplayValuePropertyName(L"DisplayValue"); + StringReference CalculationResultAutomationNamePropertyName(L"CalculationResultAutomationName"); +} - namespace CalculatorResourceKeys - { - StringReference CalculatorExpression(L"Format_CalculatorExpression"); - StringReference CalculatorResults(L"Format_CalculatorResults"); - StringReference CalculatorResults_DecimalSeparator_Announced(L"Format_CalculatorResults_Decimal"); - StringReference HexButton(L"Format_HexButtonValue"); - StringReference DecButton(L"Format_DecButtonValue"); - StringReference OctButton(L"Format_OctButtonValue"); - StringReference BinButton(L"Format_BinButtonValue"); - StringReference LeftParenthesisAutomationFormat(L"Format_OpenParenthesisAutomationNamePrefix"); - StringReference OpenParenthesisCountAutomationFormat(L"Format_OpenParenthesisCountAutomationNamePrefix"); - StringReference NoParenthesisAdded(L"NoRightParenthesisAdded_Announcement"); - StringReference MaxDigitsReachedFormat(L"Format_MaxDigitsReached"); - StringReference ButtonPressFeedbackFormat(L"Format_ButtonPressAuditoryFeedback"); - StringReference MemorySave(L"Format_MemorySave"); - StringReference MemoryItemChanged(L"Format_MemorySlotChanged"); - StringReference MemoryItemCleared(L"Format_MemorySlotCleared"); - StringReference MemoryCleared(L"Memory_Cleared"); - StringReference DisplayCopied(L"Display_Copied"); - } +namespace CalculatorResourceKeys +{ + StringReference CalculatorExpression(L"Format_CalculatorExpression"); + StringReference CalculatorResults(L"Format_CalculatorResults"); + StringReference CalculatorResults_DecimalSeparator_Announced(L"Format_CalculatorResults_Decimal"); + StringReference HexButton(L"Format_HexButtonValue"); + StringReference DecButton(L"Format_DecButtonValue"); + StringReference OctButton(L"Format_OctButtonValue"); + StringReference BinButton(L"Format_BinButtonValue"); + StringReference LeftParenthesisAutomationFormat(L"Format_OpenParenthesisAutomationNamePrefix"); + StringReference OpenParenthesisCountAutomationFormat(L"Format_OpenParenthesisCountAutomationNamePrefix"); + StringReference NoParenthesisAdded(L"NoRightParenthesisAdded_Announcement"); + StringReference MaxDigitsReachedFormat(L"Format_MaxDigitsReached"); + StringReference ButtonPressFeedbackFormat(L"Format_ButtonPressAuditoryFeedback"); + StringReference MemorySave(L"Format_MemorySave"); + StringReference MemoryItemChanged(L"Format_MemorySlotChanged"); + StringReference MemoryItemCleared(L"Format_MemorySlotCleared"); + StringReference MemoryCleared(L"Memory_Cleared"); + StringReference DisplayCopied(L"Display_Copied"); } StandardCalculatorViewModel::StandardCalculatorViewModel() : @@ -584,8 +578,7 @@ void StandardCalculatorViewModel::HandleUpdatedOperandData(Command cmdenum) bool StandardCalculatorViewModel::IsOperator(Command cmdenum) { - if ((cmdenum == Command::Command0) || (cmdenum == Command::Command1) || (cmdenum == Command::Command2) || (cmdenum == Command::Command3) || (cmdenum == Command::Command4) || (cmdenum == Command::Command5) - || (cmdenum == Command::Command6) || (cmdenum == Command::Command7) || (cmdenum == Command::Command8) || (cmdenum == Command::Command9) || (cmdenum == Command::CommandPNT) || (cmdenum == Command::CommandBACK) + if ((cmdenum >= Command::Command0 && cmdenum <= Command::Command9) || (cmdenum == Command::CommandPNT) || (cmdenum == Command::CommandBACK) || (cmdenum == Command::CommandEXP) || (cmdenum == Command::CommandFE) || (cmdenum == Command::ModeBasic) || (cmdenum == Command::ModeProgrammer) || (cmdenum == Command::ModeScientific) || (cmdenum == Command::CommandINV) || (cmdenum == Command::CommandCENTR) || (cmdenum == Command::CommandDEG) || (cmdenum == Command::CommandRAD) || (cmdenum == Command::CommandGRAD) || ((cmdenum >= Command::CommandBINEDITSTART) && (cmdenum <= Command::CommandBINEDITEND))) @@ -658,8 +651,7 @@ void StandardCalculatorViewModel::OnButtonPressed(Object^ parameter) { m_CurrentAngleType = numOpEnum; } - if ((cmdenum == Command::Command0) || (cmdenum == Command::Command1) || (cmdenum == Command::Command2) || (cmdenum == Command::Command3) || (cmdenum == Command::Command4) || (cmdenum == Command::Command5) - || (cmdenum == Command::Command6) || (cmdenum == Command::Command7) || (cmdenum == Command::Command8) || (cmdenum == Command::Command9) || (cmdenum == Command::CommandPNT) || (cmdenum == Command::CommandBACK) || (cmdenum == Command::CommandEXP)) + if ((cmdenum >= Command::Command0 && cmdenum <= Command::Command9) || (cmdenum == Command::CommandPNT) || (cmdenum == Command::CommandBACK) || (cmdenum == Command::CommandEXP)) { IsOperatorCommand = false; } @@ -1276,30 +1268,30 @@ void StandardCalculatorViewModel::Deserialize(Array^ state) void StandardCalculatorViewModel::OnPropertyChanged(String^ propertyname) { - if (propertyname == CalculatorViewModelProperties::IsScientific) + if (propertyname == IsScientificPropertyName) { if (IsScientific) { OnButtonPressed(NumbersAndOperatorsEnum::IsScientificMode); } } - else if (propertyname == CalculatorViewModelProperties::IsProgrammer) + else if (propertyname == IsProgrammerPropertyName) { if (IsProgrammer) { OnButtonPressed(NumbersAndOperatorsEnum::IsProgrammerMode); } } - else if (propertyname == CalculatorViewModelProperties::IsStandard) + else if (propertyname == IsStandardPropertyName) { if (IsStandard) { OnButtonPressed(NumbersAndOperatorsEnum::IsStandardMode); } } - else if (propertyname == CalculatorViewModelProperties::DisplayValue) + else if (propertyname == DisplayValuePropertyName) { - RaisePropertyChanged(CalculationResultAutomationName_PropertyName); + RaisePropertyChanged(CalculationResultAutomationNamePropertyName); Announcement = GetDisplayUpdatedNarratorAnnouncement(); } } @@ -1648,7 +1640,7 @@ bool StandardCalculatorViewModel::IsOpnd(int nOpCode) Command::CommandPNT }; - for (int i = 0; i < size(opnd); i++) + for (unsigned int i = 0; i < size(opnd); i++) { if (nOpCode == static_cast(opnd[i])) { @@ -1679,7 +1671,7 @@ bool StandardCalculatorViewModel::IsUnaryOp(int nOpCode) Command::CommandCUB }; - for (int i = 0; i < size(unaryOp); i++) + for (unsigned int i = 0; i < size(unaryOp); i++) { if (nOpCode == static_cast(unaryOp[i])) { @@ -1706,7 +1698,7 @@ bool StandardCalculatorViewModel::IsTrigOp(int nOpCode) Command::CommandATAN }; - for (int i = 0; i < size(trigOp); i++) + for (unsigned int i = 0; i < size(trigOp); i++) { if (nOpCode == static_cast(trigOp[i])) { @@ -1729,7 +1721,7 @@ bool StandardCalculatorViewModel::IsBinOp(int nOpCode) Command::CommandPWR }; - for (int i = 0; i < size(binOp); i++) + for (unsigned int i = 0; i < size(binOp); i++) { if (nOpCode == static_cast(binOp[i])) { @@ -1763,7 +1755,7 @@ bool StandardCalculatorViewModel::IsRecoverableCommand(int nOpCode) Command::CommandF }; - for (int i = 0; i < size(recoverableCommands); i++) + for (unsigned int i = 0; i < size(recoverableCommands); i++) { if (nOpCode == static_cast(recoverableCommands[i])) { diff --git a/src/CalcViewModel/StandardCalculatorViewModel.h b/src/CalcViewModel/StandardCalculatorViewModel.h index d7d3abde..ba6dc82b 100644 --- a/src/CalcViewModel/StandardCalculatorViewModel.h +++ b/src/CalcViewModel/StandardCalculatorViewModel.h @@ -31,13 +31,6 @@ namespace CalculatorApp #define ASCII_0 48 public delegate void HideMemoryClickedHandler(); public delegate void ProgModeRadixChangeHandler(); - namespace CalculatorViewModelProperties - { - extern Platform::StringReference IsMemoryEmpty; - extern Platform::StringReference IsInError; - extern Platform::StringReference BinaryDisplayValue; - extern Platform::StringReference OpenParenthesisCount; - } [Windows::UI::Xaml::Data::Bindable] public ref class StandardCalculatorViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged @@ -52,14 +45,14 @@ namespace CalculatorApp OBSERVABLE_OBJECT_CALLBACK(OnPropertyChanged); OBSERVABLE_PROPERTY_RW(Platform::String^, DisplayValue); OBSERVABLE_PROPERTY_RW(HistoryViewModel^, HistoryVM); - OBSERVABLE_PROPERTY_RW(bool, IsInError); + OBSERVABLE_NAMED_PROPERTY_RW(bool, IsInError); OBSERVABLE_PROPERTY_RW(bool, IsOperatorCommand); OBSERVABLE_PROPERTY_RW(Platform::String^, DisplayStringExpression); OBSERVABLE_PROPERTY_RW(Windows::Foundation::Collections::IVector^, ExpressionTokens); OBSERVABLE_PROPERTY_RW(Platform::String^, DecimalDisplayValue); OBSERVABLE_PROPERTY_RW(Platform::String^, HexDisplayValue); OBSERVABLE_PROPERTY_RW(Platform::String^, OctalDisplayValue); - OBSERVABLE_PROPERTY_RW(Platform::String^, BinaryDisplayValue); + OBSERVABLE_NAMED_PROPERTY_RW(Platform::String^, BinaryDisplayValue); OBSERVABLE_PROPERTY_RW(Platform::String^, HexDisplayValue_AutomationName); OBSERVABLE_PROPERTY_RW(Platform::String^, DecDisplayValue_AutomationName); OBSERVABLE_PROPERTY_RW(Platform::String^, OctDisplayValue_AutomationName); @@ -70,19 +63,19 @@ namespace CalculatorApp OBSERVABLE_PROPERTY_RW(bool, IsDecimalEnabled); OBSERVABLE_PROPERTY_RW(bool, IsCurrentViewPinned); OBSERVABLE_PROPERTY_RW(Windows::Foundation::Collections::IVector^, MemorizedNumbers); - OBSERVABLE_PROPERTY_RW(bool, IsMemoryEmpty); + OBSERVABLE_NAMED_PROPERTY_RW(bool, IsMemoryEmpty); OBSERVABLE_PROPERTY_RW(bool, IsFToEChecked); OBSERVABLE_PROPERTY_RW(bool, IsFToEEnabled); OBSERVABLE_PROPERTY_RW(bool, IsHyperbolicChecked); OBSERVABLE_PROPERTY_RW(bool, AreHEXButtonsEnabled); - NAMED_OBSERVABLE_PROPERTY_RW(Platform::String^, CalculationResultAutomationName); - NAMED_OBSERVABLE_PROPERTY_RW(Platform::String^, CalculationExpressionAutomationName); + OBSERVABLE_PROPERTY_RW(Platform::String^, CalculationResultAutomationName); + OBSERVABLE_PROPERTY_RW(Platform::String^, CalculationExpressionAutomationName); OBSERVABLE_PROPERTY_RW(bool, IsShiftProgrammerChecked); OBSERVABLE_PROPERTY_RW(bool, IsQwordEnabled); OBSERVABLE_PROPERTY_RW(bool, IsDwordEnabled); OBSERVABLE_PROPERTY_RW(bool, IsWordEnabled); OBSERVABLE_PROPERTY_RW(bool, IsByteEnabled); - OBSERVABLE_PROPERTY_RW(Platform::String^, OpenParenthesisCount); + OBSERVABLE_NAMED_PROPERTY_RW(Platform::String^, OpenParenthesisCount); OBSERVABLE_PROPERTY_RW(int, CurrentRadixType); OBSERVABLE_PROPERTY_RW(bool, AreTokensUpdated); OBSERVABLE_PROPERTY_RW(bool, AreHistoryShortcutsEnabled); diff --git a/src/CalcViewModel/UnitConverterViewModel.cpp b/src/CalcViewModel/UnitConverterViewModel.cpp index 7ae1eb2b..a04b584e 100644 --- a/src/CalcViewModel/UnitConverterViewModel.cpp +++ b/src/CalcViewModel/UnitConverterViewModel.cpp @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "pch.h" @@ -53,48 +53,40 @@ constexpr size_t SELECTED_TARGET_UNIT = 2; // x millisecond delay before we consider conversion to be final constexpr unsigned int CONVERSION_FINALIZED_DELAY_IN_MS = 1000; +const wregex regexTrimSpacesStart = wregex(L"^\\s+"); +const wregex regexTrimSpacesEnd = wregex(L"\\s+$"); -namespace CalculatorApp::ViewModel +namespace { - namespace UnitConverterViewModelProperties - { - StringReference CurrentCategory(L"CurrentCategory"); - StringReference Unit1(L"Unit1"); - StringReference Unit2(L"Unit2"); - StringReference Value1Active(L"Value1Active"); - StringReference Value2Active(L"Value2Active"); - StringReference Value1(L"Value1"); - StringReference Value2(L"Value2"); - StringReference Value1AutomationName(L"Value1AutomationName"); - StringReference Value2AutomationName(L"Value2AutomationName"); - StringReference SupplementaryVisibility(L"SupplementaryVisibility"); - StringReference SupplementaryResults(L"SupplementaryResults"); - StringReference Unit1AutomationName(L"Unit1AutomationName"); - StringReference Unit2AutomationName(L"Unit2AutomationName"); - StringReference CurrencySymbol1(L"CurrencySymbol1"); - StringReference CurrencySymbol2(L"CurrencySymbol2"); - StringReference CurrencySymbolVisibility(L"CurrencySymbolVisibility"); - StringReference CurrencyRatioEquality(L"CurrencyRatioEquality"); - StringReference CurrencyRatioEqualityAutomationName(L"CurrencyRatioEqualityAutomationName"); - StringReference NetworkBehavior(L"NetworkBehavior"); - StringReference CurrencyDataLoadFailed(L"CurrencyDataLoadFailed"); - StringReference CurrencyDataIsWeekOld(L"CurrencyDataIsWeekOld"); - StringReference IsCurrencyLoadingVisible(L"IsCurrencyLoadingVisible"); - } + StringReference CurrentCategoryPropertyName(L"CurrentCategory"); + StringReference Unit1AutomationNamePropertyName(L"Unit1AutomationName"); + StringReference Unit2AutomationNamePropertyName(L"Unit2AutomationName"); + StringReference Unit1PropertyName(L"Unit1"); + StringReference Unit2PropertyName(L"Unit2"); + StringReference Value1PropertyName(L"Value1"); + StringReference Value2PropertyName(L"Value2"); + StringReference Value1ActivePropertyName(L"Value1Active"); + StringReference Value2ActivePropertyName(L"Value2Active"); + StringReference Value1AutomationNamePropertyName(L"Value1AutomationName"); + StringReference Value2AutomationNamePropertyName(L"Value2AutomationName"); + StringReference CurrencySymbol1PropertyName(L"CurrencySymbol1"); + StringReference CurrencySymbol2PropertyName(L"CurrencySymbol2"); + StringReference CurrencySymbolVisibilityPropertyName(L"CurrencySymbolVisibility"); + StringReference SupplementaryVisibilityPropertyName(L"SupplementaryVisibility"); +} - namespace UnitConverterResourceKeys - { - StringReference ValueFromFormat(L"Format_ValueFrom"); - StringReference ValueFromDecimalFormat(L"Format_ValueFrom_Decimal"); - StringReference ValueToFormat(L"Format_ValueTo"); - StringReference ConversionResultFormat(L"Format_ConversionResult"); - StringReference InputUnit_Name(L"InputUnit_Name"); - StringReference OutputUnit_Name(L"OutputUnit_Name"); - StringReference MaxDigitsReachedFormat(L"Format_MaxDigitsReached"); - StringReference UpdatingCurrencyRates(L"UpdatingCurrencyRates"); - StringReference CurrencyRatesUpdated(L"CurrencyRatesUpdated"); - StringReference CurrencyRatesUpdateFailed(L"CurrencyRatesUpdateFailed"); - } +namespace CalculatorApp::ViewModel::UnitConverterResourceKeys +{ + StringReference ValueFromFormat(L"Format_ValueFrom"); + StringReference ValueFromDecimalFormat(L"Format_ValueFrom_Decimal"); + StringReference ValueToFormat(L"Format_ValueTo"); + StringReference ConversionResultFormat(L"Format_ConversionResult"); + StringReference InputUnit_Name(L"InputUnit_Name"); + StringReference OutputUnit_Name(L"OutputUnit_Name"); + StringReference MaxDigitsReachedFormat(L"Format_MaxDigitsReached"); + StringReference UpdatingCurrencyRates(L"UpdatingCurrencyRates"); + StringReference CurrencyRatesUpdated(L"CurrencyRatesUpdated"); + StringReference CurrencyRatesUpdateFailed(L"CurrencyRatesUpdateFailed"); } UnitConverterViewModel::UnitConverterViewModel(const shared_ptr& model) : @@ -202,12 +194,10 @@ void UnitConverterViewModel::BuildUnitList(const vector& modelUnitLis m_Units->Clear(); for (const UCM::Unit& modelUnit : modelUnitList) { - if (modelUnit.isWhimsical) + if (!modelUnit.isWhimsical) { - continue; + m_Units->Append(ref new Unit(modelUnit)); } - - m_Units->Append(ref new Unit(modelUnit)); } if (m_Units->Size == 0) @@ -281,8 +271,8 @@ void UnitConverterViewModel::OnSwitchActive(Platform::Object^ unused) Utils::Swap(&m_localizedValueFromFormat, &m_localizedValueToFormat); Utils::Swap(&m_Unit1AutomationName, &m_Unit2AutomationName); - RaisePropertyChanged(UnitConverterViewModelProperties::Unit1AutomationName); - RaisePropertyChanged(UnitConverterViewModelProperties::Unit2AutomationName); + RaisePropertyChanged(Unit1AutomationNamePropertyName); + RaisePropertyChanged(Unit2AutomationNamePropertyName); m_isInputBlocked = false; m_model->SwitchActive(m_valueFromUnlocalized); @@ -348,10 +338,15 @@ String^ UnitConverterViewModel::ConvertToLocalizedString(const std::wstring& str if (pos != wstring::npos) { currencyResult.erase(pos, currencyCode.length()); - pos = currencyResult.find(L'\u00a0'); // non-breaking space - if (pos != wstring::npos) + std::wsmatch sm; + if (regex_search(currencyResult, sm, regexTrimSpacesStart)) { - currencyResult.erase(pos, 1); + currencyResult.erase(sm.prefix().length(), sm.length()); + } + + if (regex_search(currencyResult, sm, regexTrimSpacesEnd)) + { + currencyResult.erase(sm.prefix().length(), sm.length()); } } @@ -556,13 +551,13 @@ void UnitConverterViewModel::OnPropertyChanged(Platform::String^ prop) { static bool isCategoryChanging = false; - if (prop->Equals(UnitConverterViewModelProperties::CurrentCategory)) + if (prop == CurrentCategoryPropertyName) { isCategoryChanging = true; CategoryChanged->Execute(nullptr); isCategoryChanging = false; } - else if (prop->Equals(UnitConverterViewModelProperties::Unit1) || prop->Equals(UnitConverterViewModelProperties::Unit2)) + else if (prop == Unit1PropertyName || prop == Unit2PropertyName) { // Category changes will handle updating units after they've both been updated. // This event should only be used to update units from explicit user interaction. @@ -571,7 +566,7 @@ void UnitConverterViewModel::OnPropertyChanged(Platform::String^ prop) UnitChanged->Execute(nullptr); } // Get the localized automation name for each CalculationResults field - if (prop->Equals(UnitConverterViewModelProperties::Unit1)) + if (prop == Unit1PropertyName) { UpdateValue1AutomationName(); } @@ -580,15 +575,15 @@ void UnitConverterViewModel::OnPropertyChanged(Platform::String^ prop) UpdateValue2AutomationName(); } } - else if (prop->Equals(UnitConverterViewModelProperties::Value1)) + else if (prop == Value1PropertyName) { UpdateValue1AutomationName(); } - else if (prop->Equals(UnitConverterViewModelProperties::Value2)) + else if (prop == Value2PropertyName) { UpdateValue2AutomationName(); } - else if (prop->Equals(UnitConverterViewModelProperties::Value1Active) || prop->Equals(UnitConverterViewModelProperties::Value2Active)) + else if (prop == Value1ActivePropertyName || prop == Value2ActivePropertyName) { // if one of the values is activated, and as a result both are true, it means // that we're trying to switch. @@ -600,11 +595,11 @@ void UnitConverterViewModel::OnPropertyChanged(Platform::String^ prop) UpdateValue1AutomationName(); UpdateValue2AutomationName(); } - else if (prop->Equals(UnitConverterViewModelProperties::SupplementaryResults)) + else if (prop == SupplementaryResultsPropertyName) { - RaisePropertyChanged(UnitConverterViewModelProperties::SupplementaryVisibility); + RaisePropertyChanged(SupplementaryVisibilityPropertyName); } - else if (prop->Equals(UnitConverterViewModelProperties::Value1AutomationName)) + else if (prop == Value1AutomationNamePropertyName) { m_isValue1Updating = false; if (!m_isValue2Updating) @@ -612,7 +607,7 @@ void UnitConverterViewModel::OnPropertyChanged(Platform::String^ prop) AnnounceConversionResult(); } } - else if (prop->Equals(UnitConverterViewModelProperties::Value2AutomationName)) + else if (prop == Value2AutomationNamePropertyName) { m_isValue2Updating = false; if (!m_isValue1Updating) @@ -620,9 +615,9 @@ void UnitConverterViewModel::OnPropertyChanged(Platform::String^ prop) AnnounceConversionResult(); } } - else if (prop->Equals(UnitConverterViewModelProperties::CurrencySymbol1) || prop->Equals(UnitConverterViewModelProperties::CurrencySymbol2)) + else if (prop == CurrencySymbol1PropertyName || prop == CurrencySymbol2PropertyName) { - RaisePropertyChanged(UnitConverterViewModelProperties::CurrencySymbolVisibility); + RaisePropertyChanged(CurrencySymbolVisibilityPropertyName); } } @@ -643,10 +638,8 @@ String^ UnitConverterViewModel::Serialize() String^ serializedData = ref new String(wstring(out.str()).c_str()); return serializedData; } - else - { - return nullptr; - } + + return nullptr; } void UnitConverterViewModel::Deserialize(Platform::String^ state) @@ -849,7 +842,7 @@ void UnitConverterViewModel::RefreshSupplementaryResults() } m_cacheMutex.unlock(); - RaisePropertyChanged(UnitConverterViewModelProperties::SupplementaryResults); + RaisePropertyChanged(SupplementaryResultsPropertyName); //EventWriteConverterSupplementaryResultsUpdated(); } @@ -879,14 +872,11 @@ void UnitConverterViewModel::UpdateInputBlocked(_In_ const wstring& currencyInpu { // currencyInput is in en-US and has the default decimal separator, so this is safe to do. auto posOfDecimal = currencyInput.find(L'.'); + m_isInputBlocked = false; if (posOfDecimal != wstring::npos && IsCurrencyCurrentCategory) { m_isInputBlocked = (posOfDecimal + static_cast(m_currencyMaxFractionDigits) + 1 == currencyInput.length()); } - else - { - m_isInputBlocked = false; - } } NumbersAndOperatorsEnum UnitConverterViewModel::MapCharacterToButtonId( @@ -988,7 +978,7 @@ void UnitConverterViewModel::OnPaste(String^ stringToPaste, ViewMode mode) } // Negate is only allowed if it's the first legal character, which is handled above. - if (NumbersAndOperatorsEnum::None != op && NumbersAndOperatorsEnum::Negate != op) + if (NumbersAndOperatorsEnum::Negate != op) { UCM::Command cmd = CommandFromButtonId(op); m_model->SendCommand(cmd); diff --git a/src/CalcViewModel/UnitConverterViewModel.h b/src/CalcViewModel/UnitConverterViewModel.h index bd7b8bd5..5a982384 100644 --- a/src/CalcViewModel/UnitConverterViewModel.h +++ b/src/CalcViewModel/UnitConverterViewModel.h @@ -138,25 +138,6 @@ namespace CalculatorApp return ref new Activatable(activatable); } - namespace UnitConverterViewModelProperties - { - extern Platform::StringReference CurrentCategory; - extern Platform::StringReference Unit1; - extern Platform::StringReference Unit2; - extern Platform::StringReference Value1Active; - extern Platform::StringReference Value2Active; - extern Platform::StringReference SupplementaryVisibility; - extern Platform::StringReference SupplementaryResults; - extern Platform::StringReference CurrencySymbol1; - extern Platform::StringReference CurrencySymbol2; - extern Platform::StringReference CurrencySymbolVisibility; - extern Platform::StringReference CurrencyRatioEquality; - extern Platform::StringReference NetworkBehavior; - extern Platform::StringReference CurrencyDataLoadFailed; - extern Platform::StringReference CurrencyDataIsWeekOld; - extern Platform::StringReference IsCurrencyLoadingVisible; - } - [Windows::UI::Xaml::Data::Bindable] public ref class UnitConverterViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged { @@ -176,7 +157,7 @@ namespace CalculatorApp OBSERVABLE_PROPERTY_RW(Platform::String^, CurrencySymbol2); OBSERVABLE_PROPERTY_RW(Unit^, Unit2); OBSERVABLE_PROPERTY_RW(Platform::String^, Value2); - OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector^, SupplementaryResults); + OBSERVABLE_NAMED_PROPERTY_R(Windows::Foundation::Collections::IObservableVector^, SupplementaryResults); OBSERVABLE_PROPERTY_RW(bool, Value1Active); OBSERVABLE_PROPERTY_RW(bool, Value2Active); OBSERVABLE_PROPERTY_RW(Platform::String^, Value1AutomationName); @@ -187,14 +168,14 @@ namespace CalculatorApp OBSERVABLE_PROPERTY_RW(bool, IsDecimalEnabled); OBSERVABLE_PROPERTY_RW(bool, IsDropDownOpen); OBSERVABLE_PROPERTY_RW(bool, IsDropDownEnabled); - OBSERVABLE_PROPERTY_RW(bool, IsCurrencyLoadingVisible); + OBSERVABLE_NAMED_PROPERTY_RW(bool, IsCurrencyLoadingVisible); OBSERVABLE_PROPERTY_RW(bool, IsCurrencyCurrentCategory); OBSERVABLE_PROPERTY_RW(Platform::String^, CurrencyRatioEquality); OBSERVABLE_PROPERTY_RW(Platform::String^, CurrencyRatioEqualityAutomationName); OBSERVABLE_PROPERTY_RW(Platform::String^, CurrencyTimestamp); - OBSERVABLE_PROPERTY_RW(CalculatorApp::NetworkAccessBehavior, NetworkBehavior); - OBSERVABLE_PROPERTY_RW(bool, CurrencyDataLoadFailed); - OBSERVABLE_PROPERTY_RW(bool, CurrencyDataIsWeekOld); + OBSERVABLE_NAMED_PROPERTY_RW(CalculatorApp::NetworkAccessBehavior, NetworkBehavior); + OBSERVABLE_NAMED_PROPERTY_RW(bool, CurrencyDataLoadFailed); + OBSERVABLE_NAMED_PROPERTY_RW(bool, CurrencyDataIsWeekOld); property Windows::UI::Xaml::Visibility SupplementaryVisibility { diff --git a/src/CalcViewModel/pch.h b/src/CalcViewModel/pch.h index 1d03c5e5..17128bc6 100644 --- a/src/CalcViewModel/pch.h +++ b/src/CalcViewModel/pch.h @@ -10,6 +10,10 @@ #define WIN32_LEAN_AND_MEAN #endif +// Windows headers define min/max macros. +// Disable it for project code. +#define NOMINMAX + #include #include diff --git a/src/Calculator/AboutFlyout.xaml b/src/Calculator/AboutFlyout.xaml index cfce6fbc..c2d82f47 100644 --- a/src/Calculator/AboutFlyout.xaml +++ b/src/Calculator/AboutFlyout.xaml @@ -38,7 +38,7 @@ - + SetVersionString(); Header->Text = resourceLoader.GetResourceString("AboutButton/Content"); + + auto copyrightText = LocalizationStringUtil::GetLocalizedString(resourceLoader.GetResourceString("AboutControlCopyright")->Data(), to_wstring(BUILD_YEAR).c_str()); + AboutControlCopyrightRun->Text = ref new String(copyrightText.c_str()); + } void AboutFlyout::FeedbackButton_Click(_In_ Object^ sender, _In_ RoutedEventArgs^ e) diff --git a/src/Calculator/Calculator.vcxproj b/src/Calculator/Calculator.vcxproj index f29fd3d4..e0a757f0 100644 --- a/src/Calculator/Calculator.vcxproj +++ b/src/Calculator/Calculator.vcxproj @@ -15,6 +15,10 @@ false 10.0 black + Always + TemporaryKey.pfx + true + False @@ -126,16 +130,6 @@ - - TemporaryKey.pfx - true - True - False - - - false - Never - /bigobj /await /std:c++17 @@ -360,7 +354,7 @@ Designer - + @@ -459,142 +453,138 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + Designer - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Calculator/Calculator.vcxproj.filters b/src/Calculator/Calculator.vcxproj.filters index f17fe368..2cd7dcde 100644 --- a/src/Calculator/Calculator.vcxproj.filters +++ b/src/Calculator/Calculator.vcxproj.filters @@ -413,6 +413,7 @@ + diff --git a/src/Calculator/Controls/CalculationResult.cpp b/src/Calculator/Controls/CalculationResult.cpp index 5ee59944..f12daff5 100644 --- a/src/Calculator/Controls/CalculationResult.cpp +++ b/src/Calculator/Controls/CalculationResult.cpp @@ -210,7 +210,7 @@ void CalculationResult::UpdateTextState() if (widthDiff > WIDTHCUTOFF) { - fontSizeChange = min(max(floor(WIDTHTOFONTSCALAR * widthDiff) - WIDTHTOFONTOFFSET, INCREMENTOFFSET), MAXFONTINCREMENT); + fontSizeChange = min(max(floor(WIDTHTOFONTSCALAR * widthDiff) - WIDTHTOFONTOFFSET, INCREMENTOFFSET), MAXFONTINCREMENT); } if (m_textBlock->ActualWidth < containerSize && abs(m_textBlock->FontSize - m_startingFontSize) > FONTTOLERANCE && !m_haveCalculatedMax) { diff --git a/src/Calculator/Resources/af-ZA/Resources.resw b/src/Calculator/Resources/af-ZA/Resources.resw index 1e563e89..03914db2 100644 --- a/src/Calculator/Resources/af-ZA/Resources.resw +++ b/src/Calculator/Resources/af-ZA/Resources.resw @@ -119,15 +119,27 @@ Sakrekenaar - {@Appx_ShortDisplayName@}{StringCategory="Feature Title"} + {@Appx_ShortDisplayName@}{StringCategory="Feature Title"} This is the title of the official application when published through Windows Store. + + + Sakrekenaar [Dev] + {@Appx_ShortDisplayName@}{StringCategory="Feature Title"} This is the name of the application when built by a user via GitHub. We use a different name to make it easier for users to distinguish the apps when both this version and the Store version are installed on the same device. Windows-Sakrekenaar {@Appx_DisplayName@}{StringCategory="Feature Title"} Name that shows up in the app store. It contains "Windows" to distinguish it from 3rd party calculator apps. + + Windows-Sakrekenaar [Dev] + {@Appx_DisplayName@}{StringCategory="Feature Title"} Name that shows up in the app store. It contains "Windows" to distinguish it from 3rd party calculator apps. This is the the version of the name used when the app is built by a user via GitHub. + Sakrekenaar - {@Appx_Description@} + {@Appx_Description@} This description is used for the official application when published through Windows Store. + + + Sakrekenaar [Dev] + {@Appx_Description@} This is the description of the application when built by a user via GitHub. We use a different description to make it easier for users to distinguish the apps when both this version and the Store version are installed on the same device. Kopieer @@ -2265,9 +2277,9 @@ Microsoft-Privaatheidstelling Displayed on a link to the Microsoft Privacy Statement on the About panel - - © 2018 Microsoft. Alle regte voorbehou. - Copyright statement, displayed on the About panel + + © %1 Microsoft. Alle regte voorbehou. + {Locked="%1"}. Copyright statement, displayed on the About panel. %1 = the current year (4 digits) Inligting oor @@ -2601,7 +2613,7 @@ x of - Auditory feedback for Screen Reader users. Users will hear "Display is 7 x or" when the button is pressed. XOR is a mathematical operation on two binary values. Here the feedback is "x or" in order to get the correct pronounciation. + Auditory feedback for Screen Reader users. Users will hear "Display is 7 x or" when the button is pressed. XOR is a mathematical operation on two binary values. Here the feedback is "x or" in order to get the correct pronunciation. en diff --git a/src/Calculator/Resources/am-ET/Resources.resw b/src/Calculator/Resources/am-ET/Resources.resw index 476e41bd..bf5de965 100644 --- a/src/Calculator/Resources/am-ET/Resources.resw +++ b/src/Calculator/Resources/am-ET/Resources.resw @@ -119,15 +119,27 @@ ማስሊያ - {@Appx_ShortDisplayName@}{StringCategory="Feature Title"} + {@Appx_ShortDisplayName@}{StringCategory="Feature Title"} This is the title of the official application when published through Windows Store. + + + ማስሊያ [Dev] + {@Appx_ShortDisplayName@}{StringCategory="Feature Title"} This is the name of the application when built by a user via GitHub. We use a different name to make it easier for users to distinguish the apps when both this version and the Store version are installed on the same device. Windows ማስሊያ {@Appx_DisplayName@}{StringCategory="Feature Title"} Name that shows up in the app store. It contains "Windows" to distinguish it from 3rd party calculator apps. + + Windows ማስሊያ [Dev] + {@Appx_DisplayName@}{StringCategory="Feature Title"} Name that shows up in the app store. It contains "Windows" to distinguish it from 3rd party calculator apps. This is the the version of the name used when the app is built by a user via GitHub. + ማስሊያ - {@Appx_Description@} + {@Appx_Description@} This description is used for the official application when published through Windows Store. + + + ማስሊያ [Dev] + {@Appx_Description@} This is the description of the application when built by a user via GitHub. We use a different description to make it easier for users to distinguish the apps when both this version and the Store version are installed on the same device. ቅዳ @@ -918,7 +930,7 @@ Screen reader prompt for the Calculator cos button on the scientific operator keypad - ሰያፍ + ሰዓት Screen reader prompt for the Calculator tan button on the scientific operator keypad @@ -1082,7 +1094,7 @@ Unit conversion category name called Power (eg. the power of an engine or a light bulb) - ቶሎታ + ፍጥነት Unit conversion category name called Speed @@ -1090,7 +1102,7 @@ Unit conversion category name called Time - ድምጽ መጠን + የድምጽ መጠን Unit conversion category name called Volume (eg. cups, teaspoons, milliliters) @@ -2265,9 +2277,9 @@ የ Microsoft ግላዊነት መግለጫ Displayed on a link to the Microsoft Privacy Statement on the About panel - - © 2018 Microsoft. ሁሉም መብቱ የተጠበቀ። - Copyright statement, displayed on the About panel + + © %1 Microsoft. ሁሉም መብቱ የተጠበቀ። + {Locked="%1"}. Copyright statement, displayed on the About panel. %1 = the current year (4 digits) ስለ @@ -2601,7 +2613,7 @@ x ወይም - Auditory feedback for Screen Reader users. Users will hear "Display is 7 x or" when the button is pressed. XOR is a mathematical operation on two binary values. Here the feedback is "x or" in order to get the correct pronounciation. + Auditory feedback for Screen Reader users. Users will hear "Display is 7 x or" when the button is pressed. XOR is a mathematical operation on two binary values. Here the feedback is "x or" in order to get the correct pronunciation. እና @@ -2616,7 +2628,7 @@ The timestamp of currency conversion ratios fetched from an online service. %1 is the date. %2 is the time. Example: "Updated Sep 28, 2016 5:42 PM" - የዝማኔ ክፍያዎች + የዝማኔ ፍጥነቶች The text displayed for a hyperlink button that refreshes currency converter ratios. @@ -2688,11 +2700,11 @@ AccessKey for the currency converter navbar item. {StringCategory="Accelerator"} - + D AccessKey for the data converter navbar item. {StringCategory="Accelerator"} - + E AccessKey for the energy converter navbar item. {StringCategory="Accelerator"} @@ -2708,7 +2720,7 @@ AccessKey for the pressure converter navbar item. {StringCategory="Accelerator"} - + S AccessKey for the speed converter navbar item. {StringCategory="Accelerator"} @@ -2716,7 +2728,7 @@ AccessKey for the time converter navbar item. {StringCategory="Accelerator"} - ድመ + AccessKey for the volume converter navbar item. {StringCategory="Accelerator"} @@ -2728,7 +2740,7 @@ AccessKey for the temperature converter navbar item. {StringCategory="Accelerator"} - አጽ + C Access key for the Clear history button.{StringCategory="Accelerator"} diff --git a/src/Calculator/Resources/ar-SA/Resources.resw b/src/Calculator/Resources/ar-SA/Resources.resw index aab109b7..296f7952 100644 --- a/src/Calculator/Resources/ar-SA/Resources.resw +++ b/src/Calculator/Resources/ar-SA/Resources.resw @@ -119,15 +119,27 @@ الحاسبة - {@Appx_ShortDisplayName@}{StringCategory="Feature Title"} + {@Appx_ShortDisplayName@}{StringCategory="Feature Title"} This is the title of the official application when published through Windows Store. + + + الحاسبة [Dev] + {@Appx_ShortDisplayName@}{StringCategory="Feature Title"} This is the name of the application when built by a user via GitHub. We use a different name to make it easier for users to distinguish the apps when both this version and the Store version are installed on the same device. الحاسبة في Windows {@Appx_DisplayName@}{StringCategory="Feature Title"} Name that shows up in the app store. It contains "Windows" to distinguish it from 3rd party calculator apps. + + الحاسبة في Windows [Dev] + {@Appx_DisplayName@}{StringCategory="Feature Title"} Name that shows up in the app store. It contains "Windows" to distinguish it from 3rd party calculator apps. This is the the version of the name used when the app is built by a user via GitHub. + الحاسبة - {@Appx_Description@} + {@Appx_Description@} This description is used for the official application when published through Windows Store. + + + الحاسبة [Dev] + {@Appx_Description@} This is the description of the application when built by a user via GitHub. We use a different description to make it easier for users to distinguish the apps when both this version and the Store version are installed on the same device. نسخ @@ -2266,9 +2278,9 @@ بيان الخصوصية الخاص بشركة Microsoft Displayed on a link to the Microsoft Privacy Statement on the About panel - - © 2018 Microsoft. جميع الحقوق محفوظة. - Copyright statement, displayed on the About panel + + © %1 Microsoft. جميع الحقوق محفوظة. + {Locked="%1"}. Copyright statement, displayed on the About panel. %1 = the current year (4 digits) حول @@ -2602,7 +2614,7 @@ x or - Auditory feedback for Screen Reader users. Users will hear "Display is 7 x or" when the button is pressed. XOR is a mathematical operation on two binary values. Here the feedback is "x or" in order to get the correct pronounciation. + Auditory feedback for Screen Reader users. Users will hear "Display is 7 x or" when the button is pressed. XOR is a mathematical operation on two binary values. Here the feedback is "x or" in order to get the correct pronunciation. و diff --git a/src/Calculator/Resources/az-Latn-AZ/CEngineStrings.resw b/src/Calculator/Resources/az-Latn-AZ/CEngineStrings.resw index 9c66f216..6fefcd56 100644 --- a/src/Calculator/Resources/az-Latn-AZ/CEngineStrings.resw +++ b/src/Calculator/Resources/az-Latn-AZ/CEngineStrings.resw @@ -150,7 +150,7 @@ Same 107 - Sıfırla bölmək mümkün deyil + Sıfra bölmək mümkün deyil Error string shown when a divide by zero condition happens during the calculation \ No newline at end of file diff --git a/src/Calculator/Resources/az-Latn-AZ/Resources.resw b/src/Calculator/Resources/az-Latn-AZ/Resources.resw index 32a24559..8cdfe566 100644 --- a/src/Calculator/Resources/az-Latn-AZ/Resources.resw +++ b/src/Calculator/Resources/az-Latn-AZ/Resources.resw @@ -119,15 +119,27 @@ Kalkulyator - {@Appx_ShortDisplayName@}{StringCategory="Feature Title"} + {@Appx_ShortDisplayName@}{StringCategory="Feature Title"} This is the title of the official application when published through Windows Store. + + + Kalkulyator [Dev] + {@Appx_ShortDisplayName@}{StringCategory="Feature Title"} This is the name of the application when built by a user via GitHub. We use a different name to make it easier for users to distinguish the apps when both this version and the Store version are installed on the same device. Windows Kalkulyator {@Appx_DisplayName@}{StringCategory="Feature Title"} Name that shows up in the app store. It contains "Windows" to distinguish it from 3rd party calculator apps. + + Windows Kalkulyator [Dev] + {@Appx_DisplayName@}{StringCategory="Feature Title"} Name that shows up in the app store. It contains "Windows" to distinguish it from 3rd party calculator apps. This is the the version of the name used when the app is built by a user via GitHub. + Kalkulyator - {@Appx_Description@} + {@Appx_Description@} This description is used for the official application when published through Windows Store. + + + Kalkulyator [Dev] + {@Appx_Description@} This is the description of the application when built by a user via GitHub. We use a different description to make it easier for users to distinguish the apps when both this version and the Store version are installed on the same device. Köçür @@ -2265,9 +2277,9 @@ Microsoft Məxfilik Bildirişi Displayed on a link to the Microsoft Privacy Statement on the About panel - - © 2018 Microsoft. Bütün hüquqlar qorunur. - Copyright statement, displayed on the About panel + + © %1 Microsoft. Bütün hüquqlar qorunur. + {Locked="%1"}. Copyright statement, displayed on the About panel. %1 = the current year (4 digits) Haqqında @@ -2601,7 +2613,7 @@ x, yaxud - Auditory feedback for Screen Reader users. Users will hear "Display is 7 x or" when the button is pressed. XOR is a mathematical operation on two binary values. Here the feedback is "x or" in order to get the correct pronounciation. + Auditory feedback for Screen Reader users. Users will hear "Display is 7 x or" when the button is pressed. XOR is a mathematical operation on two binary values. Here the feedback is "x or" in order to get the correct pronunciation. diff --git a/src/Calculator/Resources/be-BY/Resources.resw b/src/Calculator/Resources/be-BY/Resources.resw index d5f0cd53..bb36bc97 100644 --- a/src/Calculator/Resources/be-BY/Resources.resw +++ b/src/Calculator/Resources/be-BY/Resources.resw @@ -119,15 +119,27 @@ Калькулятар - {@Appx_ShortDisplayName@}{StringCategory="Feature Title"} + {@Appx_ShortDisplayName@}{StringCategory="Feature Title"} This is the title of the official application when published through Windows Store. + + + Калькулятар [Dev] + {@Appx_ShortDisplayName@}{StringCategory="Feature Title"} This is the name of the application when built by a user via GitHub. We use a different name to make it easier for users to distinguish the apps when both this version and the Store version are installed on the same device. Калькулятар Windows {@Appx_DisplayName@}{StringCategory="Feature Title"} Name that shows up in the app store. It contains "Windows" to distinguish it from 3rd party calculator apps. + + Калькулятар Windows [Dev] + {@Appx_DisplayName@}{StringCategory="Feature Title"} Name that shows up in the app store. It contains "Windows" to distinguish it from 3rd party calculator apps. This is the the version of the name used when the app is built by a user via GitHub. + Калькулятар - {@Appx_Description@} + {@Appx_Description@} This description is used for the official application when published through Windows Store. + + + Калькулятар [Dev] + {@Appx_Description@} This is the description of the application when built by a user via GitHub. We use a different description to make it easier for users to distinguish the apps when both this version and the Store version are installed on the same device. Капіяваць @@ -2265,9 +2277,9 @@ Заява аб канфідэнцыйнасці Microsoft Displayed on a link to the Microsoft Privacy Statement on the About panel - - © Microsoft, 2018. Усе правы абароненыя. - Copyright statement, displayed on the About panel + + © Microsoft, %1. Усе правы абароненыя. + {Locked="%1"}. Copyright statement, displayed on the About panel. %1 = the current year (4 digits) Інфармацыя @@ -2601,7 +2613,7 @@ выключальнае або - Auditory feedback for Screen Reader users. Users will hear "Display is 7 x or" when the button is pressed. XOR is a mathematical operation on two binary values. Here the feedback is "x or" in order to get the correct pronounciation. + Auditory feedback for Screen Reader users. Users will hear "Display is 7 x or" when the button is pressed. XOR is a mathematical operation on two binary values. Here the feedback is "x or" in order to get the correct pronunciation. пабітавае і @@ -2616,7 +2628,7 @@ The timestamp of currency conversion ratios fetched from an online service. %1 is the date. %2 is the time. Example: "Updated Sep 28, 2016 5:42 PM" - Абнавіць курсы + Абнавіць тарыфы The text displayed for a hyperlink button that refreshes currency converter ratios. @@ -2887,4 +2899,4 @@ Пагадненне аб выкарыстанні сэрвісаў Microsoft Displayed on a link to the Microsoft Services Agreement in the about this app information - \ No newline at end of file + diff --git a/src/Calculator/Resources/bg-BG/Resources.resw b/src/Calculator/Resources/bg-BG/Resources.resw index 3ef8f7fe..676ee4d4 100644 --- a/src/Calculator/Resources/bg-BG/Resources.resw +++ b/src/Calculator/Resources/bg-BG/Resources.resw @@ -119,15 +119,27 @@ Калкулатор - {@Appx_ShortDisplayName@}{StringCategory="Feature Title"} + {@Appx_ShortDisplayName@}{StringCategory="Feature Title"} This is the title of the official application when published through Windows Store. + + + Калкулатор [Dev] + {@Appx_ShortDisplayName@}{StringCategory="Feature Title"} This is the name of the application when built by a user via GitHub. We use a different name to make it easier for users to distinguish the apps when both this version and the Store version are installed on the same device. Калкулатор на Windows {@Appx_DisplayName@}{StringCategory="Feature Title"} Name that shows up in the app store. It contains "Windows" to distinguish it from 3rd party calculator apps. + + Калкулатор на Windows [Dev] + {@Appx_DisplayName@}{StringCategory="Feature Title"} Name that shows up in the app store. It contains "Windows" to distinguish it from 3rd party calculator apps. This is the the version of the name used when the app is built by a user via GitHub. + Калкулатор - {@Appx_Description@} + {@Appx_Description@} This description is used for the official application when published through Windows Store. + + + Калкулатор [Dev] + {@Appx_Description@} This is the description of the application when built by a user via GitHub. We use a different description to make it easier for users to distinguish the apps when both this version and the Store version are installed on the same device. Копиране @@ -2265,9 +2277,9 @@ Декларация за поверителност на Microsoft Displayed on a link to the Microsoft Privacy Statement on the About panel - - © 2018 Microsoft. Всички права запазени. - Copyright statement, displayed on the About panel + + © %1 Microsoft. Всички права запазени. + {Locked="%1"}. Copyright statement, displayed on the About panel. %1 = the current year (4 digits) Относно @@ -2601,7 +2613,7 @@ x или - Auditory feedback for Screen Reader users. Users will hear "Display is 7 x or" when the button is pressed. XOR is a mathematical operation on two binary values. Here the feedback is "x or" in order to get the correct pronounciation. + Auditory feedback for Screen Reader users. Users will hear "Display is 7 x or" when the button is pressed. XOR is a mathematical operation on two binary values. Here the feedback is "x or" in order to get the correct pronunciation. и diff --git a/src/Calculator/Resources/bn-BD/Resources.resw b/src/Calculator/Resources/bn-BD/Resources.resw index 3dec2e26..2836bc7a 100644 --- a/src/Calculator/Resources/bn-BD/Resources.resw +++ b/src/Calculator/Resources/bn-BD/Resources.resw @@ -119,15 +119,27 @@ ক্যালকুলেটর - {@Appx_ShortDisplayName@}{StringCategory="Feature Title"} + {@Appx_ShortDisplayName@}{StringCategory="Feature Title"} This is the title of the official application when published through Windows Store. + + + ক্যালকুলেটর [Dev] + {@Appx_ShortDisplayName@}{StringCategory="Feature Title"} This is the name of the application when built by a user via GitHub. We use a different name to make it easier for users to distinguish the apps when both this version and the Store version are installed on the same device. Windows ক্যালকুলেটর {@Appx_DisplayName@}{StringCategory="Feature Title"} Name that shows up in the app store. It contains "Windows" to distinguish it from 3rd party calculator apps. + + Windows ক্যালকুলেটর [Dev] + {@Appx_DisplayName@}{StringCategory="Feature Title"} Name that shows up in the app store. It contains "Windows" to distinguish it from 3rd party calculator apps. This is the the version of the name used when the app is built by a user via GitHub. + ক্যালকুলেটর - {@Appx_Description@} + {@Appx_Description@} This description is used for the official application when published through Windows Store. + + + ক্যালকুলেটর [Dev] + {@Appx_Description@} This is the description of the application when built by a user via GitHub. We use a different description to make it easier for users to distinguish the apps when both this version and the Store version are installed on the same device. প্রতিলিপি @@ -2265,9 +2277,9 @@ Microsoft গোপনীয়তার বিবৃতি Displayed on a link to the Microsoft Privacy Statement on the About panel - - © 2018 Microsoft. সর্বস্বত্ব সংরক্ষিত। - Copyright statement, displayed on the About panel + + © %1 Microsoft. সর্বস্বত্ব সংরক্ষিত। + {Locked="%1"}. Copyright statement, displayed on the About panel. %1 = the current year (4 digits) বিষয়ক @@ -2601,7 +2613,7 @@ x বা - Auditory feedback for Screen Reader users. Users will hear "Display is 7 x or" when the button is pressed. XOR is a mathematical operation on two binary values. Here the feedback is "x or" in order to get the correct pronounciation. + Auditory feedback for Screen Reader users. Users will hear "Display is 7 x or" when the button is pressed. XOR is a mathematical operation on two binary values. Here the feedback is "x or" in order to get the correct pronunciation. এবং @@ -2616,7 +2628,7 @@ The timestamp of currency conversion ratios fetched from an online service. %1 is the date. %2 is the time. Example: "Updated Sep 28, 2016 5:42 PM" - হালনাগাদ হার + হালনাগাদের হার The text displayed for a hyperlink button that refreshes currency converter ratios. diff --git a/src/Calculator/Resources/ca-ES/Resources.resw b/src/Calculator/Resources/ca-ES/Resources.resw index 6e9fd54f..63e2b9a5 100644 --- a/src/Calculator/Resources/ca-ES/Resources.resw +++ b/src/Calculator/Resources/ca-ES/Resources.resw @@ -1,4 +1,4 @@ - +