diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 859bebaa..db98fc73 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -6,36 +6,45 @@ labels: '' assignees: '' --- - +- Search existing issues and make sure this issue is not already filed. +--> **Describe the bug** - + **Steps To Reproduce** - +4. See error +--> **Expected behavior** - + **Screenshots** - + -**Device and Application Information (please complete the following information):** +**Device and Application Information** - OS Build: - Architecture: - Application Version: - - **Additional context** - + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 3611d4ed..0032d0b7 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -2,42 +2,42 @@ name: Feature request about: Propose a new feature in the app title: '' -labels: '' +labels: 'Enhancement' assignees: '' --- **Problem Statement** - + **Evidence or User Insights** - + **Proposal** - + **Goals** - + **Non-Goals** - + **Low-Fidelity Concept** - \ No newline at end of file + diff --git a/.github/ISSUE_TEMPLATE/localization_suggestion.md b/.github/ISSUE_TEMPLATE/localization_suggestion.md new file mode 100644 index 00000000..dd47f61d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/localization_suggestion.md @@ -0,0 +1,54 @@ +--- +name: Localization Suggestion +about: Report a problem or suggested change to Calculator's localized content. +title: '[Localization] ' +labels: 'Area: World-Readiness' +assignees: '' +--- + + +**Describe the bug** + + +**Steps To Reproduce** + + +**Expected behavior** + + +**Screenshots** + + +**Device and Application Information** + - OS Build: + - Architecture: + - Application Version: + - Region: + - Dev Version Installed: + + + +**Additional context** + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9bab5f16..63702de4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,7 +3,8 @@ The Calculator team encourages community feedback and contributions. Thank you f making Calculator better! There are several ways you can get involved. ## Reporting issues and suggesting new features -If Calculator is not working properly, please file a report in the [Feedback Hub](https://insider.windows.com/en-us/fb/?contextid=130&newFeedback=True). +If Calculator is not working properly, please file a report in the +[Feedback Hub](https://insider.windows.com/en-us/fb/?contextid=130&newFeedback=True). Feedback Hub reports automatically include diagnostic data, such as the version of Calculator you're using. @@ -17,21 +18,38 @@ all community interactions must abide by the [Code of Conduct](CODE_OF_CONDUCT.m ## Finding issues you can help with Looking for something to work on? -[Issues marked *good first issue*](https://github.com/Microsoft/calculator/labels/good%20first%20issue) +Issues marked [``good first issue``](https://github.com/Microsoft/calculator/labels/good%20first%20issue) are a good place to start. -You can also check [the *help wanted* tag](https://github.com/Microsoft/calculator/labels/help%20wanted) -to find other issues to help with. +You can also check the [``help wanted``](https://github.com/Microsoft/calculator/labels/help%20wanted) tag to find +other issues to help with. If you're interested in working on a fix, leave a comment to let everyone know and to help +avoid duplicated effort from others. ## Contributions we accept We welcome your contributions to the Calculator project, especially to fix bugs and to make -improvements which address the top issues reported by Calculator users. +improvements which address the top issues reported by Calculator users. Some general guidelines: -We have a high bar for new features and changes to the user experience. We prefer to evaluate -*prototypes* to ensure that the design meets users' needs before we start discussing implementation -details and reviewing code. We follow a [user-centered process for developing features](docs/NewFeatureProcess.md). -New features need sponsorship from the Calculator team, but we welcome community contributions at -many stages of the process. +* **DO** create one pull request per Issue, and ensure that the Issue is linked in the pull request. +* **DO** follow our [Coding and Style](#style-guidelines) guidelines, and keep code changes as small as possible. +* **DO** include corresponding tests whenever possible. +* **DO** check for additional occurrences of the same problem in other parts of the codebase before submitting your PR. +* **DO** [link the issue](https://github.com/blog/957-introducing-issue-mentions) you are addressing in the + pull request. +* **DO** write a good description for your pull request. More detail is better. Describe *why* the change is being + made and *why* you have chosen a particular solution. Describe any manual testing you performed to validate your change. +* **DO NOT** submit a PR unless it is linked to an Issue marked + [`triage approved`](https://github.com/Microsoft/calculator/issues?q=is%3Aissue+is%3Aopen+label%3A%22Triage%3A+Approved%22). + This enables us to have a discussion on the idea before anyone invests time in an implementation. +* **DO NOT** merge multiple changes into one PR unless they have the same root cause. +* **DO NOT** submit pure formatting/typo changes to code that has not been modified otherwise. + +We follow a [user-centered process for developing features](docs/NewFeatureProcess.md). New features +need sponsorship from the Calculator team, but we welcome community contributions at many stages of +the process. + +> Submitting a pull request for an approved Issue is not a guarantee it will be approved. +> The change must meet our high bar for code quality, architecture, and performance, as well as +> [other requirements](#docs/NewFeatureProcess.md#technical-review). ## Making changes to the code @@ -41,7 +59,8 @@ To learn how to build the code and run tests, follow the instructions in the [RE ### Style guidelines The code in this project uses several different coding styles, depending on the age and history of the code. Please attempt to match the style of surrounding code as much as possible. In new -components, prefer the patterns described in the [C++ core guidelines](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines) +components, prefer the patterns described in the +[C++ core guidelines](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines) and the [modern C++/WinRT language projections](https://docs.microsoft.com/en-us/windows/uwp/cpp-and-winrt-apis/). ### Testing @@ -61,18 +80,9 @@ to group your changes into a small number of commits which we can review one at When completing a pull request, we will generally squash your changes into a single commit. Please let us know if your pull request needs to be merged as separate commits. -## Submitting a pull request and participating in code review -Writing a good description for your pull request is crucial to help reviewers and future -maintainers understand your change. More detail is better. -- [Link the issue you're addressing in the pull request](https://github.com/blog/957-introducing-issue-mentions). -- Describe *why* the change is being made and *why* you've chosen a particular solution. -- Describe any manual testing you performed to validate your change. - -Please submit one pull request per issue. Large pull requests which have unrelated changes can be -difficult to review. - +## Review Process After submitting a pull request, members of the calculator team will review your code. We will -assign the request to an appropriate reviewer within two days. Any member of the community may +assign the request to an appropriate reviewer. Any member of the community may participate in the review, but at least one member of the Calculator team will ultimately approve the request. diff --git a/docs/NewFeatureProcess.md b/docs/NewFeatureProcess.md index 66c9a635..2a84aa27 100644 --- a/docs/NewFeatureProcess.md +++ b/docs/NewFeatureProcess.md @@ -1,7 +1,8 @@ # New feature process ## Where do I submit my idea for a new feature? -The easiest way to submit new feature requests is through [Feedback Hub](https://insider.windows.com/en-us/fb/?contextid=130). +The easiest way to submit new feature requests is through +[Feedback Hub](https://insider.windows.com/en-us/fb/?contextid=130). In Feedback Hub, any Windows user (even if they aren't on GitHub) can upvote suggestions. The Calculator team reviews these suggestions regularly, and when we're ready to work on an idea we create [feature pitch issues here on GitHub](https://github.com/Microsoft/calculator/issues?q=is%3Aissue+is%3Aopen+project%3AMicrosoft%2Fcalculator%2F1). @@ -12,73 +13,45 @@ product. The [Feature Tracking board](https://github.com/Microsoft/calculator/pr all the features we're working on and where they're at in the process. ## Do I need to follow this process? Can I just start coding and submit a PR? -You *do not* need to follow this process for bug fixes, performance improvements, or changes to the -development tools. To contribute these changes, [discuss the proposed change in an issue](https://github.com/Microsoft/calculator/issues/new) +You **do not** need to follow this process for bug fixes, performance improvements, or changes to the +development tools. To contribute these changes, +[discuss the proposed change in an issue](https://github.com/Microsoft/calculator/issues/new) and then submit a pull request. -You *do* need to follow this process for any change which "users will notice". This applies +You **do** need to follow this process for any change which "users will notice". This applies especially to new features and major visual changes. ## Step 1: Feature pitch -The feature pitch concisely describes a point of view on the problem the new feature should solve. -It will typically include these sections: +Feature pitches are submitted as issues on GitHub using the +[Feature Request template](https://github.com/Microsoft/calculator/issues/new?assignees=&labels=&template=feature_request.md&title=). +We encourage discussion on open issues, and as discussion progresses we will edit the issue description to refine the +idea until it is ready for review. -* **Problem Statement**: What problem are we trying to solve? Who’s the target audience? Is there a - customer need or pain point we need to remedy? Is there a business goal or metric we are trying - to improve? Do we have a hypothesis we want to prove or disprove? -* **Evidence or User Insights**: Why should we do this? Potential sources of data: Feedback Hub, - other GitHub issues, other anecdotes from listening to customers in person or online, request - from another team, telemetry data, user research, market or competitive research -* **Proposal**: How will the solution/feature help us solve the problem? How will it meet the - target audience’s needs? If there are business goals or metrics, how does this improve them? -* **Goals**: What you want to accomplish with this feature. Typical examples include “User Can - *perform some task*” -* **Non-Goals**: Things we are explicitly not doing or supporting or that are out of scope, - including reasons why. -* **Low-Fidelity Concept**: Show as much of the experience as needed to explain the idea. This - can be as simple as a napkin drawing but can also be a code prototype, a PowerPoint walkthrough, - or a design comp. - -The low-fidelity concept should be kept simple at this stage and refined during the pre-production -process. - -Feature pitches are submitted as issues on GitHub. We encourage discussion on open issues, and as -discussion progresses we will edit the issue description to refine the idea. +We review pitches regularly, and will approve or close issues based on whether they broadly align with the +[Calculator roadmap](https://github.com/Microsoft/calculator/blob/master/docs/Roadmap.md). Approved pitches are moved +into [pre-production](https://github.com/Microsoft/calculator/projects/1) on the feature tracking board. ## Step 2: Pre-production -In the pre-production phase, we experiment with a variety of ways to address the goals described in -the feature pitch. The output of this phase is a specification which demonstrates how the feature -will work, supported by design renderings and code prototypes as needed. Sometimes we'll learn new -things about a feature proposal during pre-production, and we'll edit or close the original pitch. +For most features, the output of this phase is a specification which describes how the feature will work, supported by +design renderings and code prototypes as needed. The original issue will continue to track the overall progress of the +feature, but we will create and iterate on spec documentation in the +[Calculator Spec repo](https://github.com/Microsoft/calculator-specs). Sometimes we'll learn new things about a feature +proposal during pre-production, and we'll edit or close the original pitch. -We welcome community participation in the pre-production process. The GitHub issue will be the -primary place to share progress updates. - -The best ideas often come from trying many ideas during the pre-production phase. To enable rapid +We welcome community participation throughout pre-production. The best ideas often come from trying many ideas during +the pre-production phase. To enable rapid experimentation, we encourage developing and sharing rough ideas—maybe even with pencil and paper—before making designs pixel-perfect or making code robust and maintainable. -### Spec review -Once there is a high-fidelity design which addresses the goals described in the original pitch, the -Microsoft product team will review the prototype and ensure all items on this checklist are -addressed: - -- [ ] Is there a high-fidelity design which gives reviewers a clear idea of how the feature will - look and function when implemented? -- [ ] Has the plan been shared with the community (documented on the wiki and updates posted in the - original issue) and have others been given an opportunity to provide suggestions? -- [ ] Are [Fluent design principles](https://docs.microsoft.com/en-us/windows/uwp/design/fluent-design-system/) - followed? If we do something which deviates from the guidelines, do we have a good reason? -- [ ] Does the design include provisions for [all users](https://docs.microsoft.com/en-us/windows/uwp/design/accessibility/designing-inclusive-software) - and [all cultures](https://docs.microsoft.com/en-us/windows/uwp/design/globalizing/guidelines-and-checklist-for-globalizing-your-app)? -- [ ] Is it technically feasible to build this feature? Take a look at the "before committing" - checklist below and identify any issues which are likely to be blockers. +After the [spec review](https://github.com/Microsoft/calculator-specs#spec-review) is completed, we will move the issue +into [production](https://github.com/Microsoft/calculator/projects/1) on the feature tracking board. In _some_ cases, +all of the details of an idea can be captured concisely in original feature pitch. When that happens, we may move ideas +directly into production. ## Step 3: Production -A feature can be implemented by the original proposer, a Microsoft team member, or by other -community members. Code contributions and testing help are greatly appreciated. Please let us know -in the issue comments if you're actively working on a feature so we can ensure it's assigned to -you. +A feature can be implemented by the original submitter, a Microsoft team member, or by other +community members. Code contributions and testing help are greatly appreciated. Please let everyone know if you're +actively working on a feature to help avoid duplicated efforts from others. You might be able to reuse code written during the prototype process, although there will typically be more work required to make the solution robust. Once the code is ready, you can begin @@ -122,7 +95,8 @@ new features, the Microsoft team considers at least these items: - [ ] Run the perf tests to measure any increase in startup time. Move work out of the startup path if possible. - [ ] If the change adds additional logging: - - [ ] All logging should use [TraceLogging](https://docs.microsoft.com/en-us/windows/desktop/tracelogging/trace-logging-about). + - [ ] All logging should use + [TraceLogging](https://docs.microsoft.com/en-us/windows/desktop/tracelogging/trace-logging-about). - [ ] Unnecessary log events should be removed, or configured so that they are collected only when needed to debug issues or measure feature usage. - [ ] If the change reads user data from files or app settings: diff --git a/src/CalcManager/CEngine/calc.cpp b/src/CalcManager/CEngine/calc.cpp index 9d1ca9de..0e4979f2 100644 --- a/src/CalcManager/CEngine/calc.cpp +++ b/src/CalcManager/CEngine/calc.cpp @@ -25,13 +25,18 @@ static constexpr wstring_view DEFAULT_NUMBER_STR = L"0"; // Read strings for keys, errors, trig types, etc. // These will be copied from the resources to local memory. -array CCalcEngine::s_engineStrings; +unordered_map CCalcEngine::s_engineStrings; void CCalcEngine::LoadEngineStrings(CalculationManager::IResourceProvider& resourceProvider) { - for (size_t i = 0; i < s_engineStrings.size(); i++) + for (const auto& sid : g_sids) { - s_engineStrings[i] = resourceProvider.GetCEngineString(g_sids[i]); + auto locKey = wstring{ sid }; + auto locString = resourceProvider.GetCEngineString(locKey); + if (!locString.empty()) + { + s_engineStrings[locKey] = locString; + } } } @@ -168,7 +173,7 @@ void CCalcEngine::SettingsChanged() m_HistoryCollector.SetDecimalSymbol(m_decimalSeparator); // put the new decimal symbol into the table used to draw the decimal key - s_engineStrings[IDS_DECIMAL] = m_decimalSeparator; + s_engineStrings[SIDS_DECIMAL_SEPARATOR] = m_decimalSeparator; // we need to redraw to update the decimal point button numChanged = true; diff --git a/src/CalcManager/CEngine/scicomm.cpp b/src/CalcManager/CEngine/scicomm.cpp index f17938bf..d450a70d 100644 --- a/src/CalcManager/CEngine/scicomm.cpp +++ b/src/CalcManager/CEngine/scicomm.cpp @@ -16,13 +16,6 @@ #include "Header Files/CalcEngine.h" #include "Header Files/CalcUtils.h" -#define IDC_RADSIN IDC_UNARYLAST+1 -#define IDC_RADCOS IDC_UNARYLAST+2 -#define IDC_RADTAN IDC_UNARYLAST+3 -#define IDC_GRADSIN IDC_UNARYLAST+4 -#define IDC_GRADCOS IDC_UNARYLAST+5 -#define IDC_GRADTAN IDC_UNARYLAST+6 - using namespace std; using namespace CalcEngine; @@ -463,45 +456,12 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam) m_HistoryCollector.AddOpndToHistory(m_numberString, m_currentVal); } - do { - - if (m_nOpCode) /* Is there a valid operation around? */ - { - /* If this is the first EQU in a string, set m_holdVal=m_currentVal */ - /* Otherwise let m_currentVal=m_holdVal. This keeps m_currentVal constant */ - /* through all EQUs in a row. */ - if (m_bNoPrevEqu) - { - m_holdVal = m_currentVal; - } - else - { - m_currentVal = m_holdVal; - DisplayNum(); // to update the m_numberString - m_HistoryCollector.AddBinOpToHistory(m_nOpCode, false); - m_HistoryCollector.AddOpndToHistory(m_numberString, m_currentVal); // Adding the repeated last op to history - } - - // Do the current or last operation. - m_currentVal = DoOperation(m_nOpCode, m_currentVal, m_lastVal); - m_nPrevOpCode = m_nOpCode; - m_lastVal = m_currentVal; - - /* Check for errors. If this wasn't done, DisplayNum */ - /* would immediately overwrite any error message. */ - if (!m_bError) - DisplayNum(); - - /* No longer the first EQU. */ - m_bNoPrevEqu = false; - } - else if (!m_bError) - DisplayNum(); - - if (m_precedenceOpCount == 0 || !m_fPrecedence) - break; - - m_nOpCode = m_nPrecOp[--m_precedenceOpCount]; + // Evaluate the precedence stack. + ResolveHighestPrecedenceOperation(); + while (m_fPrecedence && m_precedenceOpCount > 0) + { + m_precedenceOpCount--; + m_nOpCode = m_nPrecOp[m_precedenceOpCount]; m_lastVal = m_precedenceVals[m_precedenceOpCount]; // Precedence Inversion check @@ -514,7 +474,9 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam) m_HistoryCollector.PopLastOpndStart(); m_bNoPrevEqu = true; - } while (m_precedenceOpCount >= 0); + + ResolveHighestPrecedenceOperation(); + } if (!m_bError) { @@ -789,6 +751,48 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam) } +// Helper function to resolve one item on the precedence stack. +void CCalcEngine::ResolveHighestPrecedenceOperation() +{ + // Is there a valid operation around? + if (m_nOpCode) + { + // If this is the first EQU in a string, set m_holdVal=m_currentVal + // Otherwise let m_currentVal=m_holdVal. This keeps m_currentVal constant + // through all EQUs in a row. + if (m_bNoPrevEqu) + { + m_holdVal = m_currentVal; + } + else + { + m_currentVal = m_holdVal; + DisplayNum(); // to update the m_numberString + m_HistoryCollector.AddBinOpToHistory(m_nOpCode, false); + m_HistoryCollector.AddOpndToHistory(m_numberString, m_currentVal); // Adding the repeated last op to history + } + + // Do the current or last operation. + m_currentVal = DoOperation(m_nOpCode, m_currentVal, m_lastVal); + m_nPrevOpCode = m_nOpCode; + m_lastVal = m_currentVal; + + // Check for errors. If this wasn't done, DisplayNum + // would immediately overwrite any error message. + if (!m_bError) + { + DisplayNum(); + } + + // No longer the first EQU. + m_bNoPrevEqu = false; + } + else if (!m_bError) + { + DisplayNum(); + } +} + // CheckAndAddLastBinOpToHistory // // This is a very confusing helper routine to add the last entered binary operator to the history. This is expected to @@ -857,155 +861,94 @@ void CCalcEngine::DisplayAnnounceBinaryOperator() // Unary operator Function Name table Element // since unary operators button names aren't exactly friendly for history purpose, // we have this separate table to get its localized name and for its Inv function if it exists. -typedef struct +struct FunctionNameElement { - int idsFunc; // index of string for the unary op function. Can be NULL, in which case it same as button name - int idsFuncInv; // index of string for Inv of unary op. Can be NULL, in case it is same as idsFunc - bool fDontUseInExpEval; // true if this cant be used in reverse direction as well, ie. during expression evaluation -} UFNE; + wstring degreeString; // Used by default if there are no rad or grad specific strings. + wstring inverseDegreeString; // Will fall back to degreeString if empty + + wstring radString; + wstring inverseRadString; // Will fall back to radString if empty + + wstring gradString; + wstring inverseGradString; // Will fall back to gradString if empty + + bool hasAngleStrings = ((!radString.empty()) || (!inverseRadString.empty()) || (!gradString.empty()) || (!inverseGradString.empty())); +}; // Table for each unary operator -static const UFNE rgUfne[] = +static const std::unordered_map unaryOperatorStringTable = { - /* IDC_CHOP */{ 0, IDS_FRAC, false }, - /* IDC_ROL */{ 0, 0, true }, - /* IDC_ROR */{ 0, 0, true }, + { IDC_CHOP, { L"", SIDS_FRAC} }, - /* IDC_COM */{ 0, 0, true }, - /* IDC_SIN */{ IDS_SIND, IDS_ASIND, false }, // default in this table is degrees for sin,cos & tan - /* IDC_COS */{ IDS_COSD, IDS_ACOSD, false }, - /* IDC_TAN */{ IDS_TAND, IDS_ATAND, false }, + { IDC_SIN, { SIDS_SIND, SIDS_ASIND, SIDS_SINR, SIDS_ASINR, SIDS_SING, SIDS_ASING } }, + { IDC_COS, { SIDS_COSD, SIDS_ACOSD, SIDS_COSR, SIDS_ACOSR, SIDS_COSG, SIDS_ACOSG } }, + { IDC_TAN, { SIDS_TAND, SIDS_ATAND, SIDS_TANR, SIDS_ATANR, SIDS_TANG, SIDS_ATANG } }, - /* IDC_SINH */{ 0, IDS_ASINH, false }, - /* IDC_COSH */{ 0, IDS_ACOSH, false }, - /* IDC_TANH */{ 0, IDS_ATANH, false }, + { IDC_SINH, { L"", SIDS_ASINH } }, + { IDC_COSH, { L"", SIDS_ACOSH } }, + { IDC_TANH, { L"", SIDS_ATANH } }, - /* IDC_LN */{ 0, IDS_POWE, false }, - /* IDC_LOG */{ 0, 0, false }, - /* IDC_SQRT */{ 0, 0, false }, - /* IDC_SQR */{ IDS_SQR, 0, false }, - /* IDC_CUB */{ IDS_CUBE, 0, false }, - /* IDC_FAC */{ IDS_FACT, 0, false }, - /* IDC_REC */{ IDS_REC, 0, false }, - /* IDC_DMS */{ 0, IDS_DEGREES, false }, - /* IDC_CUBEROOT */{ 0, 0, false }, - /* IDC_POW10 */{ 0, 0, false }, - /* IDC_PERCENT */{ 0, 0, false }, - - /* IDC_RADSIN */{ IDS_SINR, IDS_ASINR, false }, - /* IDC_RADCOS */{ IDS_COSR, IDS_ACOSR, false }, - /* IDC_RADTAN */{ IDS_TANR, IDS_ATANR, false }, - /* IDC_GRADCOS */{ IDS_SING, IDS_ASING, false }, - /* IDC_GRADCOS */{ IDS_COSG, IDS_ACOSG, false }, - /* IDC_GRADTAN */{ IDS_TANG, IDS_ATANG, false }, + { IDC_LN , { L"", SIDS_POWE } }, + { IDC_SQR, { SIDS_SQR } }, + { IDC_CUB, { SIDS_CUBE } }, + { IDC_FAC, { SIDS_FACT } }, + { IDC_REC, { SIDS_RECIPROC } }, + { IDC_DMS, { L"", SIDS_DEGREES } }, + { IDC_SIGN, { SIDS_NEGATE } }, + { IDC_DEGREES, { SIDS_DEGREES } } }; wstring_view CCalcEngine::OpCodeToUnaryString(int nOpCode, bool fInv, ANGLE_TYPE angletype) { - // Special cases for Sign and Degrees - if (IDC_SIGN == nOpCode) - { - return GetString(IDS_NEGATE); - } - if (IDC_DEGREES == nOpCode) - { - return GetString(IDS_DEGREES); - } - - // Correct the trigonometric functions with type of angle argument they take - if (ANGLE_RAD == angletype) - { - switch (nOpCode) - { - case IDC_SIN: - nOpCode = IDC_RADSIN; - break; - case IDC_COS: - nOpCode = IDC_RADCOS; - break; - case IDC_TAN: - nOpCode = IDC_RADTAN; - break; - } - } - else if (ANGLE_GRAD == angletype) - { - switch (nOpCode) - { - case IDC_SIN: - nOpCode = IDC_GRADSIN; - break; - case IDC_COS: - nOpCode = IDC_GRADCOS; - break; - case IDC_TAN: - nOpCode = IDC_GRADTAN; - break; - } - } - // Try to lookup the ID in the UFNE table - int ids = 0; - int iufne = nOpCode - IDC_UNARYFIRST; - if (iufne >= 0 && (size_t)iufne < size(rgUfne)) + wstring ids = L""; + + if (auto pair = unaryOperatorStringTable.find(nOpCode); pair != unaryOperatorStringTable.end()) { - if (fInv) + const FunctionNameElement& element = pair->second; + if (!element.hasAngleStrings || ANGLE_DEG == angletype) { - ids = rgUfne[iufne].idsFuncInv; + if (fInv) + { + ids = element.inverseDegreeString; + } + + if (ids.empty()) + { + ids = element.degreeString; + } } - if (0 == ids) + else if (ANGLE_RAD == angletype) { - ids = rgUfne[iufne].idsFunc; + if (fInv) + { + ids = element.inverseRadString; + } + if (ids.empty()) + { + ids = element.radString; + } } + else if (ANGLE_GRAD == angletype) + { + if (fInv) + { + ids = element.inverseGradString; + } + if (ids.empty()) + { + ids = element.gradString; + } + } + } + + if (!ids.empty()) + { + return GetString(ids); } // If we didn't find an ID in the table, use the op code. - if (0 == ids) - { - ids = IdStrFromCmdId(nOpCode); - } - - return GetString(ids); -} - -// -// Sets the Angle Mode for special unary op IDC's which are used to index to the table rgUfne -// and returns the equivalent plain IDC for trigonometric function. If it isn't a trigonometric function -// returns the passed in idc itself. -int CCalcEngine::IdcSetAngleTypeDecMode(int idc) -{ - int idcAngleCmd = IDM_DEG; - - switch (idc) - { - case IDC_RADSIN: - idcAngleCmd = IDM_RAD; - idc = IDC_SIN; - break; - case IDC_RADCOS: - idcAngleCmd = IDM_RAD; - idc = IDC_COS; - break; - case IDC_RADTAN: - idcAngleCmd = IDM_RAD; - idc = IDC_TAN; - break; - case IDC_GRADSIN: - idcAngleCmd = IDM_GRAD; - idc = IDC_SIN; - break; - case IDC_GRADCOS: - idcAngleCmd = IDM_GRAD; - idc = IDC_COS; - break; - case IDC_GRADTAN: - idcAngleCmd = IDM_GRAD; - idc = IDC_TAN; - break; - } - ProcessCommand(idcAngleCmd); - return idc; - + return OpCodeToString(nOpCode); } bool CCalcEngine::IsCurrentTooBigForTrig() diff --git a/src/CalcManager/Header Files/CalcEngine.h b/src/CalcManager/Header Files/CalcEngine.h index 0ad8252f..db906e51 100644 --- a/src/CalcManager/Header Files/CalcEngine.h +++ b/src/CalcManager/Header Files/CalcEngine.h @@ -72,7 +72,8 @@ public: // Static methods for the instance static void InitialOneTimeOnlySetup(CalculationManager::IResourceProvider& resourceProvider); // Once per load time to call to initialize all shared global variables // returns the ptr to string representing the operator. Mostly same as the button, but few special cases for x^y etc. - static std::wstring_view GetString(int ids) { return s_engineStrings[ids]; } + static std::wstring_view GetString(int ids) { return s_engineStrings[std::to_wstring(ids)]; } + static std::wstring_view GetString(std::wstring ids) { return s_engineStrings[ids]; } static std::wstring_view OpCodeToString(int nOpCode) { return GetString(IdStrFromCmdId(nOpCode)); } static std::wstring_view OpCodeToUnaryString(int nOpCode, bool fInv, ANGLE_TYPE angletype); @@ -123,12 +124,13 @@ private: std::array m_chopNumbers; // word size enforcement std::array m_maxDecimalValueStrings; // maximum values represented by a given word width based off m_chopNumbers - static std::array s_engineStrings; // the string table shared across all instances + static std::unordered_map s_engineStrings; // the string table shared across all instances wchar_t m_decimalSeparator; wchar_t m_groupSeparator; private: void ProcessCommandWorker(OpCode wParam); + void ResolveHighestPrecedenceOperation(); void HandleErrorCommand(OpCode idc); void HandleMaxDigitsReached(); void DisplayNum(void); @@ -145,12 +147,11 @@ private: bool TryToggleBit(CalcEngine::Rational& rat, uint32_t wbitno); void CheckAndAddLastBinOpToHistory(bool addToHistory = true); - int IdcSetAngleTypeDecMode(int idc); void InitChopNumbers(); static void LoadEngineStrings(CalculationManager::IResourceProvider& resourceProvider); - static int IdStrFromCmdId(int id) { return id - IDC_FIRSTCONTROL + IDS_FIRSTENGSTR; } + static int IdStrFromCmdId(int id) { return id - IDC_FIRSTCONTROL + IDS_ENGINESTR_FIRST; } static std::vector DigitGroupingStringToGroupingVector(std::wstring_view groupingString); std::wstring GroupDigits(std::wstring_view delimiter, std::vector const& grouping, std::wstring_view displayString, bool isNumNegative = false); diff --git a/src/CalcManager/Header Files/EngineStrings.h b/src/CalcManager/Header Files/EngineStrings.h index 2ada6bba..37f11483 100644 --- a/src/CalcManager/Header Files/EngineStrings.h +++ b/src/CalcManager/Header Files/EngineStrings.h @@ -13,327 +13,279 @@ * Created: 13-Feb-2008 * \****************************************************************************/ -#define IDS_FIRSTENGSTR IDS_ENGINESTR_FIRST - -#define IDS_DECIMAL 4 - -// All unary op function names for easy history reading -// This is where the first string after all the commands in order have been placed, should be placed -// keeping in consecutive helps us to allocate 1 string table and index them -#define IDS_FNSZFIRST (IDC_F -IDC_FIRSTCONTROL)+1 - -#define IDS_FRAC IDS_FNSZFIRST - -#define IDS_SIND IDS_FNSZFIRST+1 -#define IDS_COSD IDS_FNSZFIRST+2 -#define IDS_TAND IDS_FNSZFIRST+3 -#define IDS_ASIND IDS_FNSZFIRST+4 -#define IDS_ACOSD IDS_FNSZFIRST+5 -#define IDS_ATAND IDS_FNSZFIRST+6 - -#define IDS_SINR IDS_FNSZFIRST+7 -#define IDS_COSR IDS_FNSZFIRST+8 -#define IDS_TANR IDS_FNSZFIRST+9 -#define IDS_ASINR IDS_FNSZFIRST+10 -#define IDS_ACOSR IDS_FNSZFIRST+11 -#define IDS_ATANR IDS_FNSZFIRST+12 - -#define IDS_SING IDS_FNSZFIRST+13 -#define IDS_COSG IDS_FNSZFIRST+14 -#define IDS_TANG IDS_FNSZFIRST+15 -#define IDS_ASING IDS_FNSZFIRST+16 -#define IDS_ACOSG IDS_FNSZFIRST+17 -#define IDS_ATANG IDS_FNSZFIRST+18 - -#define IDS_ASINH IDS_FNSZFIRST+19 -#define IDS_ACOSH IDS_FNSZFIRST+20 -#define IDS_ATANH IDS_FNSZFIRST+21 -#define IDS_POWE IDS_FNSZFIRST+22 -#define IDS_POW10 IDS_FNSZFIRST+23 -#define IDS_SQRT IDS_FNSZFIRST+24 -#define IDS_SQR IDS_FNSZFIRST+25 -#define IDS_CUBE IDS_FNSZFIRST+26 -#define IDS_CUBERT IDS_FNSZFIRST+27 -#define IDS_FACT IDS_FNSZFIRST+28 -#define IDS_REC IDS_FNSZFIRST+29 -#define IDS_DEGREES IDS_FNSZFIRST+30 -#define IDS_NEGATE IDS_FNSZFIRST+31 -#define IDS_RSH IDS_FNSZFIRST+32 - -#define IDS_FNSZLAST IDS_RSH - -#define IDS_ERRORS_FIRST IDS_FNSZLAST+1 +inline constexpr auto IDS_ERRORS_FIRST = 99; // This is the list of error strings corresponding to SCERR_DIVIDEZERO.. -#define IDS_DIVBYZERO IDS_ERRORS_FIRST -#define IDS_DOMAIN IDS_ERRORS_FIRST+1 -#define IDS_UNDEFINED IDS_ERRORS_FIRST+2 -#define IDS_POS_INFINITY IDS_ERRORS_FIRST+3 -#define IDS_NEG_INFINITY IDS_ERRORS_FIRST+4 -#define IDS_NOMEM IDS_ERRORS_FIRST+6 -#define IDS_TOOMANY IDS_ERRORS_FIRST+7 -#define IDS_OVERFLOW IDS_ERRORS_FIRST+8 -#define IDS_NORESULT IDS_ERRORS_FIRST+9 -#define IDS_INSUFFICIENT_DATA IDS_ERRORS_FIRST+10 +inline constexpr auto IDS_DIVBYZERO = IDS_ERRORS_FIRST; +inline constexpr auto IDS_DOMAIN = IDS_ERRORS_FIRST + 1; +inline constexpr auto IDS_UNDEFINED = IDS_ERRORS_FIRST + 2; +inline constexpr auto IDS_POS_INFINITY = IDS_ERRORS_FIRST + 3; +inline constexpr auto IDS_NEG_INFINITY = IDS_ERRORS_FIRST + 4; +inline constexpr auto IDS_NOMEM = IDS_ERRORS_FIRST + 6; +inline constexpr auto IDS_TOOMANY = IDS_ERRORS_FIRST + 7; +inline constexpr auto IDS_OVERFLOW = IDS_ERRORS_FIRST + 8; +inline constexpr auto IDS_NORESULT = IDS_ERRORS_FIRST + 9; +inline constexpr auto IDS_INSUFFICIENT_DATA = IDS_ERRORS_FIRST + 10; -#define CSTRINGSENGMAX IDS_INSUFFICIENT_DATA+1 +inline constexpr auto CSTRINGSENGMAX = IDS_INSUFFICIENT_DATA + 1; // Arithmetic expression evaluator error strings -#define IDS_ERR_UNK_CH CSTRINGSENGMAX+1 -#define IDS_ERR_UNK_FN CSTRINGSENGMAX+2 -#define IDS_ERR_UNEX_NUM CSTRINGSENGMAX+3 -#define IDS_ERR_UNEX_CH CSTRINGSENGMAX+4 -#define IDS_ERR_UNEX_SZ CSTRINGSENGMAX+5 -#define IDS_ERR_MISMATCH_CLOSE CSTRINGSENGMAX+6 -#define IDS_ERR_UNEX_END CSTRINGSENGMAX+7 -#define IDS_ERR_SG_INV_ERROR CSTRINGSENGMAX+8 -#define IDS_ERR_INPUT_OVERFLOW CSTRINGSENGMAX+9 -#define IDS_ERR_OUTPUT_OVERFLOW CSTRINGSENGMAX+10 +inline constexpr auto IDS_ERR_UNK_CH = CSTRINGSENGMAX + 1; +inline constexpr auto IDS_ERR_UNK_FN = CSTRINGSENGMAX + 2; +inline constexpr auto IDS_ERR_UNEX_NUM = CSTRINGSENGMAX + 3; +inline constexpr auto IDS_ERR_UNEX_CH = CSTRINGSENGMAX + 4; +inline constexpr auto IDS_ERR_UNEX_SZ = CSTRINGSENGMAX + 5; +inline constexpr auto IDS_ERR_MISMATCH_CLOSE = CSTRINGSENGMAX + 6; +inline constexpr auto IDS_ERR_UNEX_END = CSTRINGSENGMAX + 7; +inline constexpr auto IDS_ERR_SG_INV_ERROR = CSTRINGSENGMAX + 8; +inline constexpr auto IDS_ERR_INPUT_OVERFLOW = CSTRINGSENGMAX + 9; +inline constexpr auto IDS_ERR_OUTPUT_OVERFLOW = CSTRINGSENGMAX + 10; - -#define SIDS_PLUS_MINUS L"0" -#define SIDS_CLEAR L"1" -#define SIDS_CE L"2" -#define SIDS_BACKSPACE L"3" -#define SIDS_DECIMAL_SEPARATOR L"4" -#define SIDS_EMPTY_STRING L"5" -#define SIDS_AND L"6" -#define SIDS_OR L"7" -#define SIDS_XOR L"8" -#define SIDS_LSH L"9" -#define SIDS_RSH L"10" -#define SIDS_DIVIDE L"11" -#define SIDS_MULTIPLY L"12" -#define SIDS_PLUS L"13" -#define SIDS_MINUS L"14" -#define SIDS_MOD L"15" -#define SIDS_YROOT L"16" -#define SIDS_POW_HAT L"17" -#define SIDS_INT L"18" -#define SIDS_ROL L"19" -#define SIDS_ROR L"20" -#define SIDS_NOT L"21" -#define SIDS_SIN L"22" -#define SIDS_COS L"23" -#define SIDS_TAN L"24" -#define SIDS_SINH L"25" -#define SIDS_COSH L"26" -#define SIDS_TANH L"27" -#define SIDS_LN L"28" -#define SIDS_LOG L"29" -#define SIDS_SQRT L"30" -#define SIDS_XPOW2 L"31" -#define SIDS_XPOW3 L"32" -#define SIDS_NFACTORIAL L"33" -#define SIDS_RECIPROCAL L"34" -#define SIDS_DMS L"35" -#define SIDS_CUBEROOT L"36" -#define SIDS_POWTEN L"37" -#define SIDS_PERCENT L"38" -#define SIDS_SCIENTIFIC_NOTATION L"39" -#define SIDS_PI L"40" -#define SIDS_EQUAL L"41" -#define SIDS_MC L"42" -#define SIDS_MR L"43" -#define SIDS_MS L"44" -#define SIDS_MPLUS L"45" -#define SIDS_MMINUS L"46" -#define SIDS_EXP L"47" -#define SIDS_OPEN_PAREN L"48" -#define SIDS_CLOSE_PAREN L"49" -#define SIDS_0 L"50" -#define SIDS_1 L"51" -#define SIDS_2 L"52" -#define SIDS_3 L"53" -#define SIDS_4 L"54" -#define SIDS_5 L"55" -#define SIDS_6 L"56" -#define SIDS_7 L"57" -#define SIDS_8 L"58" -#define SIDS_9 L"59" -#define SIDS_A L"60" -#define SIDS_B L"61" -#define SIDS_C L"62" -#define SIDS_D L"63" -#define SIDS_E L"64" -#define SIDS_F L"65" -#define SIDS_FRAC L"66" -#define SIDS_SIND L"67" -#define SIDS_COSD L"68" -#define SIDS_TAND L"69" -#define SIDS_ASIND L"70" -#define SIDS_ACOSD L"71" -#define SIDS_ATAND L"72" -#define SIDS_SINR L"73" -#define SIDS_COSR L"74" -#define SIDS_TANR L"75" -#define SIDS_ASINR L"76" -#define SIDS_ACOSR L"77" -#define SIDS_ATANR L"78" -#define SIDS_SING L"79" -#define SIDS_COSG L"80" -#define SIDS_TANG L"81" -#define SIDS_ASING L"82" -#define SIDS_ACOSG L"83" -#define SIDS_ATANG L"84" -#define SIDS_ASINH L"85" -#define SIDS_ACOSH L"86" -#define SIDS_ATANH L"87" -#define SIDS_POWE L"88" -#define SIDS_POWTEN2 L"89" -#define SIDS_SQRT2 L"90" -#define SIDS_SQR L"91" -#define SIDS_CUBE L"92" -#define SIDS_CUBERT L"93" -#define SIDS_FACT L"94" -#define SIDS_RECIPROC L"95" -#define SIDS_DEGREES L"96" -#define SIDS_NEGATE L"97" -#define SIDS_RSH2 L"98" -#define SIDS_DIVIDEBYZERO L"99" -#define SIDS_DOMAIN L"100" -#define SIDS_UNDEFINED L"101" -#define SIDS_POS_INFINITY L"102" -#define SIDS_NEG_INFINITY L"103" -#define SIDS_ABORTED L"104" -#define SIDS_NOMEM L"105" -#define SIDS_TOOMANY L"106" -#define SIDS_OVERFLOW L"107" -#define SIDS_NORESULT L"108" -#define SIDS_INSUFFICIENT_DATA L"109" +// Resource keys for CEngineStrings.resw +inline constexpr auto SIDS_PLUS_MINUS = L"0"; +inline constexpr auto SIDS_CLEAR = L"1"; +inline constexpr auto SIDS_CE = L"2"; +inline constexpr auto SIDS_BACKSPACE = L"3"; +inline constexpr auto SIDS_DECIMAL_SEPARATOR = L"4"; +inline constexpr auto SIDS_EMPTY_STRING = L"5"; +inline constexpr auto SIDS_AND = L"6"; +inline constexpr auto SIDS_OR = L"7"; +inline constexpr auto SIDS_XOR = L"8"; +inline constexpr auto SIDS_LSH = L"9"; +inline constexpr auto SIDS_RSH = L"10"; +inline constexpr auto SIDS_DIVIDE = L"11"; +inline constexpr auto SIDS_MULTIPLY = L"12"; +inline constexpr auto SIDS_PLUS = L"13"; +inline constexpr auto SIDS_MINUS = L"14"; +inline constexpr auto SIDS_MOD = L"15"; +inline constexpr auto SIDS_YROOT = L"16"; +inline constexpr auto SIDS_POW_HAT = L"17"; +inline constexpr auto SIDS_INT = L"18"; +inline constexpr auto SIDS_ROL = L"19"; +inline constexpr auto SIDS_ROR = L"20"; +inline constexpr auto SIDS_NOT = L"21"; +inline constexpr auto SIDS_SIN = L"22"; +inline constexpr auto SIDS_COS = L"23"; +inline constexpr auto SIDS_TAN = L"24"; +inline constexpr auto SIDS_SINH = L"25"; +inline constexpr auto SIDS_COSH = L"26"; +inline constexpr auto SIDS_TANH = L"27"; +inline constexpr auto SIDS_LN = L"28"; +inline constexpr auto SIDS_LOG = L"29"; +inline constexpr auto SIDS_SQRT = L"30"; +inline constexpr auto SIDS_XPOW2 = L"31"; +inline constexpr auto SIDS_XPOW3 = L"32"; +inline constexpr auto SIDS_NFACTORIAL = L"33"; +inline constexpr auto SIDS_RECIPROCAL = L"34"; +inline constexpr auto SIDS_DMS = L"35"; +inline constexpr auto SIDS_CUBEROOT = L"36"; +inline constexpr auto SIDS_POWTEN = L"37"; +inline constexpr auto SIDS_PERCENT = L"38"; +inline constexpr auto SIDS_SCIENTIFIC_NOTATION = L"39"; +inline constexpr auto SIDS_PI = L"40"; +inline constexpr auto SIDS_EQUAL = L"41"; +inline constexpr auto SIDS_MC = L"42"; +inline constexpr auto SIDS_MR = L"43"; +inline constexpr auto SIDS_MS = L"44"; +inline constexpr auto SIDS_MPLUS = L"45"; +inline constexpr auto SIDS_MMINUS = L"46"; +inline constexpr auto SIDS_EXP = L"47"; +inline constexpr auto SIDS_OPEN_PAREN = L"48"; +inline constexpr auto SIDS_CLOSE_PAREN = L"49"; +inline constexpr auto SIDS_0 = L"50"; +inline constexpr auto SIDS_1 = L"51"; +inline constexpr auto SIDS_2 = L"52"; +inline constexpr auto SIDS_3 = L"53"; +inline constexpr auto SIDS_4 = L"54"; +inline constexpr auto SIDS_5 = L"55"; +inline constexpr auto SIDS_6 = L"56"; +inline constexpr auto SIDS_7 = L"57"; +inline constexpr auto SIDS_8 = L"58"; +inline constexpr auto SIDS_9 = L"59"; +inline constexpr auto SIDS_A = L"60"; +inline constexpr auto SIDS_B = L"61"; +inline constexpr auto SIDS_C = L"62"; +inline constexpr auto SIDS_D = L"63"; +inline constexpr auto SIDS_E = L"64"; +inline constexpr auto SIDS_F = L"65"; +inline constexpr auto SIDS_FRAC = L"66"; +inline constexpr auto SIDS_SIND = L"67"; +inline constexpr auto SIDS_COSD = L"68"; +inline constexpr auto SIDS_TAND = L"69"; +inline constexpr auto SIDS_ASIND = L"70"; +inline constexpr auto SIDS_ACOSD = L"71"; +inline constexpr auto SIDS_ATAND = L"72"; +inline constexpr auto SIDS_SINR = L"73"; +inline constexpr auto SIDS_COSR = L"74"; +inline constexpr auto SIDS_TANR = L"75"; +inline constexpr auto SIDS_ASINR = L"76"; +inline constexpr auto SIDS_ACOSR = L"77"; +inline constexpr auto SIDS_ATANR = L"78"; +inline constexpr auto SIDS_SING = L"79"; +inline constexpr auto SIDS_COSG = L"80"; +inline constexpr auto SIDS_TANG = L"81"; +inline constexpr auto SIDS_ASING = L"82"; +inline constexpr auto SIDS_ACOSG = L"83"; +inline constexpr auto SIDS_ATANG = L"84"; +inline constexpr auto SIDS_ASINH = L"85"; +inline constexpr auto SIDS_ACOSH = L"86"; +inline constexpr auto SIDS_ATANH = L"87"; +inline constexpr auto SIDS_POWE = L"88"; +inline constexpr auto SIDS_POWTEN2 = L"89"; +inline constexpr auto SIDS_SQRT2 = L"90"; +inline constexpr auto SIDS_SQR = L"91"; +inline constexpr auto SIDS_CUBE = L"92"; +inline constexpr auto SIDS_CUBERT = L"93"; +inline constexpr auto SIDS_FACT = L"94"; +inline constexpr auto SIDS_RECIPROC = L"95"; +inline constexpr auto SIDS_DEGREES = L"96"; +inline constexpr auto SIDS_NEGATE = L"97"; +inline constexpr auto SIDS_RSH2 = L"98"; +inline constexpr auto SIDS_DIVIDEBYZERO = L"99"; +inline constexpr auto SIDS_DOMAIN = L"100"; +inline constexpr auto SIDS_UNDEFINED = L"101"; +inline constexpr auto SIDS_POS_INFINITY = L"102"; +inline constexpr auto SIDS_NEG_INFINITY = L"103"; +inline constexpr auto SIDS_ABORTED = L"104"; +inline constexpr auto SIDS_NOMEM = L"105"; +inline constexpr auto SIDS_TOOMANY = L"106"; +inline constexpr auto SIDS_OVERFLOW = L"107"; +inline constexpr auto SIDS_NORESULT = L"108"; +inline constexpr auto SIDS_INSUFFICIENT_DATA = L"109"; // 110 is skipped by CSTRINGSENGMAX -#define SIDS_ERR_UNK_CH L"111" -#define SIDS_ERR_UNK_FN L"112" -#define SIDS_ERR_UNEX_NUM L"113" -#define SIDS_ERR_UNEX_CH L"114" -#define SIDS_ERR_UNEX_SZ L"115" -#define SIDS_ERR_MISMATCH_CLOSE L"116" -#define SIDS_ERR_UNEX_END L"117" -#define SIDS_ERR_SG_INV_ERROR L"118" -#define SIDS_ERR_INPUT_OVERFLOW L"119" -#define SIDS_ERR_OUTPUT_OVERFLOW L"120" +inline constexpr auto SIDS_ERR_UNK_CH = L"111"; +inline constexpr auto SIDS_ERR_UNK_FN = L"112"; +inline constexpr auto SIDS_ERR_UNEX_NUM = L"113"; +inline constexpr auto SIDS_ERR_UNEX_CH = L"114"; +inline constexpr auto SIDS_ERR_UNEX_SZ = L"115"; +inline constexpr auto SIDS_ERR_MISMATCH_CLOSE = L"116"; +inline constexpr auto SIDS_ERR_UNEX_END = L"117"; +inline constexpr auto SIDS_ERR_SG_INV_ERROR = L"118"; +inline constexpr auto SIDS_ERR_INPUT_OVERFLOW = L"119"; +inline constexpr auto SIDS_ERR_OUTPUT_OVERFLOW = L"120"; -__declspec(selectany) std::wstring g_sids[] = +// Include the resource key ID from above into this vector to load it into memory for the engine to use +inline constexpr std::array g_sids = { - std::wstring(SIDS_PLUS_MINUS), - std::wstring(SIDS_C), - std::wstring(SIDS_CE), - std::wstring(SIDS_BACKSPACE), - std::wstring(SIDS_DECIMAL_SEPARATOR), - std::wstring(SIDS_EMPTY_STRING), - std::wstring(SIDS_AND), - std::wstring(SIDS_OR), - std::wstring(SIDS_XOR), - std::wstring(SIDS_LSH), - std::wstring(SIDS_RSH), - std::wstring(SIDS_DIVIDE), - std::wstring(SIDS_MULTIPLY), - std::wstring(SIDS_PLUS), - std::wstring(SIDS_MINUS), - std::wstring(SIDS_MOD), - std::wstring(SIDS_YROOT), - std::wstring(SIDS_POW_HAT), - std::wstring(SIDS_INT), - std::wstring(SIDS_ROL), - std::wstring(SIDS_ROR), - std::wstring(SIDS_NOT), - std::wstring(SIDS_SIN), - std::wstring(SIDS_COS), - std::wstring(SIDS_TAN), - std::wstring(SIDS_SINH), - std::wstring(SIDS_COSH), - std::wstring(SIDS_TANH), - std::wstring(SIDS_LN), - std::wstring(SIDS_LOG), - std::wstring(SIDS_SQRT), - std::wstring(SIDS_XPOW2), - std::wstring(SIDS_XPOW3), - std::wstring(SIDS_NFACTORIAL), - std::wstring(SIDS_RECIPROCAL), - std::wstring(SIDS_DMS), - std::wstring(SIDS_CUBEROOT), - std::wstring(SIDS_POWTEN), - std::wstring(SIDS_PERCENT), - std::wstring(SIDS_SCIENTIFIC_NOTATION), - std::wstring(SIDS_PI), - std::wstring(SIDS_EQUAL), - std::wstring(SIDS_MC), - std::wstring(SIDS_MR), - std::wstring(SIDS_MS), - std::wstring(SIDS_MPLUS), - std::wstring(SIDS_MMINUS), - std::wstring(SIDS_EXP), - std::wstring(SIDS_OPEN_PAREN), - std::wstring(SIDS_CLOSE_PAREN), - std::wstring(SIDS_0), - std::wstring(SIDS_1), - std::wstring(SIDS_2), - std::wstring(SIDS_3), - std::wstring(SIDS_4), - std::wstring(SIDS_5), - std::wstring(SIDS_6), - std::wstring(SIDS_7), - std::wstring(SIDS_8), - std::wstring(SIDS_9), - std::wstring(SIDS_A), - std::wstring(SIDS_B), - std::wstring(SIDS_C), - std::wstring(SIDS_D), - std::wstring(SIDS_E), - std::wstring(SIDS_F), - std::wstring(SIDS_FRAC), - std::wstring(SIDS_SIND), - std::wstring(SIDS_COSD), - std::wstring(SIDS_TAND), - std::wstring(SIDS_ASIND), - std::wstring(SIDS_ACOSD), - std::wstring(SIDS_ATAND), - std::wstring(SIDS_SINR), - std::wstring(SIDS_COSR), - std::wstring(SIDS_TANR), - std::wstring(SIDS_ASINR), - std::wstring(SIDS_ACOSR), - std::wstring(SIDS_ATANR), - std::wstring(SIDS_SING), - std::wstring(SIDS_COSG), - std::wstring(SIDS_TANG), - std::wstring(SIDS_ASING), - std::wstring(SIDS_ACOSG), - std::wstring(SIDS_ATANG), - std::wstring(SIDS_ASINH), - std::wstring(SIDS_ACOSH), - std::wstring(SIDS_ATANH), - std::wstring(SIDS_POWE), - std::wstring(SIDS_POWTEN2), - std::wstring(SIDS_SQRT2), - std::wstring(SIDS_SQR), - std::wstring(SIDS_CUBE), - std::wstring(SIDS_CUBERT), - std::wstring(SIDS_FACT), - std::wstring(SIDS_RECIPROC), - std::wstring(SIDS_DEGREES), - std::wstring(SIDS_NEGATE), - std::wstring(SIDS_RSH), - std::wstring(SIDS_DIVIDEBYZERO), - std::wstring(SIDS_DOMAIN), - std::wstring(SIDS_UNDEFINED), - std::wstring(SIDS_POS_INFINITY), - std::wstring(SIDS_NEG_INFINITY), - std::wstring(SIDS_ABORTED), - std::wstring(SIDS_NOMEM), - std::wstring(SIDS_TOOMANY), - std::wstring(SIDS_OVERFLOW), - std::wstring(SIDS_NORESULT), - std::wstring(SIDS_INSUFFICIENT_DATA), - std::wstring(SIDS_ERR_UNK_CH), - std::wstring(SIDS_ERR_UNK_FN), - std::wstring(SIDS_ERR_UNEX_NUM), - std::wstring(SIDS_ERR_UNEX_CH), - std::wstring(SIDS_ERR_UNEX_SZ), - std::wstring(SIDS_ERR_MISMATCH_CLOSE), - std::wstring(SIDS_ERR_UNEX_END), - std::wstring(SIDS_ERR_SG_INV_ERROR), - std::wstring(SIDS_ERR_INPUT_OVERFLOW), - std::wstring(SIDS_ERR_OUTPUT_OVERFLOW) + SIDS_PLUS_MINUS, + SIDS_C, + SIDS_CE, + SIDS_BACKSPACE, + SIDS_DECIMAL_SEPARATOR, + SIDS_EMPTY_STRING, + SIDS_AND, + SIDS_OR, + SIDS_XOR, + SIDS_LSH, + SIDS_RSH, + SIDS_DIVIDE, + SIDS_MULTIPLY, + SIDS_PLUS, + SIDS_MINUS, + SIDS_MOD, + SIDS_YROOT, + SIDS_POW_HAT, + SIDS_INT, + SIDS_ROL, + SIDS_ROR, + SIDS_NOT, + SIDS_SIN, + SIDS_COS, + SIDS_TAN, + SIDS_SINH, + SIDS_COSH, + SIDS_TANH, + SIDS_LN, + SIDS_LOG, + SIDS_SQRT, + SIDS_XPOW2, + SIDS_XPOW3, + SIDS_NFACTORIAL, + SIDS_RECIPROCAL, + SIDS_DMS, + SIDS_CUBEROOT, + SIDS_POWTEN, + SIDS_PERCENT, + SIDS_SCIENTIFIC_NOTATION, + SIDS_PI, + SIDS_EQUAL, + SIDS_MC, + SIDS_MR, + SIDS_MS, + SIDS_MPLUS, + SIDS_MMINUS, + SIDS_EXP, + SIDS_OPEN_PAREN, + SIDS_CLOSE_PAREN, + SIDS_0, + SIDS_1, + SIDS_2, + SIDS_3, + SIDS_4, + SIDS_5, + SIDS_6, + SIDS_7, + SIDS_8, + SIDS_9, + SIDS_A, + SIDS_B, + SIDS_C, + SIDS_D, + SIDS_E, + SIDS_F, + SIDS_FRAC, + SIDS_SIND, + SIDS_COSD, + SIDS_TAND, + SIDS_ASIND, + SIDS_ACOSD, + SIDS_ATAND, + SIDS_SINR, + SIDS_COSR, + SIDS_TANR, + SIDS_ASINR, + SIDS_ACOSR, + SIDS_ATANR, + SIDS_SING, + SIDS_COSG, + SIDS_TANG, + SIDS_ASING, + SIDS_ACOSG, + SIDS_ATANG, + SIDS_ASINH, + SIDS_ACOSH, + SIDS_ATANH, + SIDS_POWE, + SIDS_POWTEN2, + SIDS_SQRT2, + SIDS_SQR, + SIDS_CUBE, + SIDS_CUBERT, + SIDS_FACT, + SIDS_RECIPROC, + SIDS_DEGREES, + SIDS_NEGATE, + SIDS_RSH, + SIDS_DIVIDEBYZERO, + SIDS_DOMAIN, + SIDS_UNDEFINED, + SIDS_POS_INFINITY, + SIDS_NEG_INFINITY, + SIDS_ABORTED, + SIDS_NOMEM, + SIDS_TOOMANY, + SIDS_OVERFLOW, + SIDS_NORESULT, + SIDS_INSUFFICIENT_DATA, + SIDS_ERR_UNK_CH, + SIDS_ERR_UNK_FN, + SIDS_ERR_UNEX_NUM, + SIDS_ERR_UNEX_CH, + SIDS_ERR_UNEX_SZ, + SIDS_ERR_MISMATCH_CLOSE, + SIDS_ERR_UNEX_END, + SIDS_ERR_SG_INV_ERROR, + SIDS_ERR_INPUT_OVERFLOW, + SIDS_ERR_OUTPUT_OVERFLOW }; diff --git a/src/CalcViewModel/UnitConverterViewModel.cpp b/src/CalcViewModel/UnitConverterViewModel.cpp index a04b584e..76d9aa3a 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" @@ -394,7 +394,7 @@ String^ UnitConverterViewModel::ConvertToLocalizedString(const std::wstring& str void UnitConverterViewModel::DisplayPasteError() { - String^ errorMsg = AppResourceProvider::GetInstance().GetCEngineString(SIDS_DOMAIN); /*SIDS_DOMAIN is for "invalid input"*/ + String^ errorMsg = AppResourceProvider::GetInstance().GetCEngineString(StringReference(SIDS_DOMAIN)); /*SIDS_DOMAIN is for "invalid input"*/ Value1 = errorMsg; Value2 = errorMsg; m_relocalizeStringOnSwitch = false; diff --git a/src/Calculator/App.xaml b/src/Calculator/App.xaml index 51c2846d..cec835fb 100644 --- a/src/Calculator/App.xaml +++ b/src/Calculator/App.xaml @@ -134,10 +134,6 @@ 15 - 72 - 46 - 28 - - - - - - - - - - - - + - -