[haiku-commits] haiku: hrev56067 - in src: kits/shared apps/deskcalc

  • From: waddlesplash <waddlesplash@xxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Mon, 25 Apr 2022 20:57:24 +0000 (UTC)

hrev56067 adds 1 changeset to branch 'master'
old head: cda13c638de522f03857eb7d671251d2db5b9781
new head: d39b5bfd0c2ab90f6eaefbffc006ae1f6c430b9f
overview: 
https://git.haiku-os.org/haiku/log/?qt=range&q=d39b5bfd0c2a+%5Ecda13c638de5

----------------------------------------------------------------------------

d39b5bfd0c2a: DeskCalc: make input Locale-aware
  
  Accepts input with separators based on user's Locale.  For example,
  with a European locale, "1.234,56" is valid input. With a US locale,
  "1,234.56" is accepted.  The grouping separator is ignored and
  removed, and the decimal separator is kept.
  
  Supports multi-byte decimal separator and grouping separators.
  
  The keypad localization is based on the user's Language setting,
  but the separators come from the Formatting. Thus if the Language
  is set to English, but the Formatting is set to, for example,
  German, the keypad will show '.', but when pressed it will emit
  ',' to match the number Formatting. Otherwise the keypad breaks
  the localized formatting.
  
  Fixes #8503
  
  Change-Id: I0d112bdca67a4e4898e37062102343194ed47f8f
  Reviewed-on: https://review.haiku-os.org/c/haiku/+/4965
  Reviewed-by: Jérôme Duval <jerome.duval@xxxxxxxxx>
  Reviewed-by: waddlesplash <waddlesplash@xxxxxxxxx>
  Tested-by: Commit checker robot <no-reply+buildbot@xxxxxxxxxxxx>

                                       [ Dale Cieslak <dcieslak@xxxxxxxxx> ]

----------------------------------------------------------------------------

Revision:    hrev56067
Commit:      d39b5bfd0c2ab90f6eaefbffc006ae1f6c430b9f
URL:         https://git.haiku-os.org/haiku/commit/?id=d39b5bfd0c2a
Author:      Dale Cieslak <dcieslak@xxxxxxxxx>
Date:        Tue Mar  1 00:18:53 2022 UTC
Committer:   waddlesplash <waddlesplash@xxxxxxxxx>
Commit-Date: Mon Apr 25 20:57:20 2022 UTC

Ticket:      https://dev.haiku-os.org/ticket/8503

----------------------------------------------------------------------------

3 files changed, 77 insertions(+), 11 deletions(-)
headers/private/shared/ExpressionParser.h |  2 +
src/apps/deskcalc/CalcView.cpp            | 13 +++++
src/kits/shared/ExpressionParser.cpp      | 73 +++++++++++++++++++++++----

----------------------------------------------------------------------------

diff --git a/headers/private/shared/ExpressionParser.h 
b/headers/private/shared/ExpressionParser.h
index b180b87e17..4f33840cd9 100644
--- a/headers/private/shared/ExpressionParser.h
+++ b/headers/private/shared/ExpressionParser.h
@@ -50,6 +50,8 @@ class ExpressionParser {
                        int64                           EvaluateToInt64(const 
char* expressionString);
                        double                          EvaluateToDouble(const 
char* expressionString);
 
+                       status_t                        SetSeparators(BString 
decimal, BString group);
+
  private:
                        struct Token;
                        class Tokenizer;
diff --git a/src/apps/deskcalc/CalcView.cpp b/src/apps/deskcalc/CalcView.cpp
index aa2191e783..4cc7fa5b7f 100644
--- a/src/apps/deskcalc/CalcView.cpp
+++ b/src/apps/deskcalc/CalcView.cpp
@@ -31,9 +31,11 @@
 #include <Clipboard.h>
 #include <File.h>
 #include <Font.h>
+#include <Locale.h>
 #include <MenuItem.h>
 #include <Message.h>
 #include <MessageRunner.h>
+#include <NumberFormat.h>
 #include <Point.h>
 #include <PopUpMenu.h>
 #include <Region.h>
@@ -1100,8 +1102,14 @@ CalcView::_EvaluateThread(void* data)
        BString result;
        status_t status = acquire_sem(calcView->fEvaluateSemaphore);
        if (status == B_OK) {
+               BLocale locale;
+               BNumberFormat format(&locale);
+
                ExpressionParser parser;
                parser.SetDegreeMode(calcView->fOptions->degree_mode);
+               parser.SetSeparators(format.GetSeparator(B_DECIMAL_SEPARATOR),
+                       format.GetSeparator(B_GROUPING_SEPARATOR));
+
                BString expression(calcView->fExpressionTextView->Text());
                try {
                        result = parser.Evaluate(expression.String());
@@ -1301,6 +1309,11 @@ CalcView::_PressKey(int key)
                        static_cast<BTextView*>(fExpressionTextView)->Select(
                                endSelection + labelLen + 1, endSelection + 
labelLen + 1);
                }
+       } else if (strcmp(fKeypad[key].code, ".") == 0) {
+               BLocale locale;
+               BNumberFormat format(&locale);
+
+               
fExpressionTextView->Insert(format.GetSeparator(B_DECIMAL_SEPARATOR));
        } else {
                // check for evaluation order
                if (fKeypad[key].code[0] == '\n') {
diff --git a/src/kits/shared/ExpressionParser.cpp 
b/src/kits/shared/ExpressionParser.cpp
index 078e060752..2378502aba 100644
--- a/src/kits/shared/ExpressionParser.cpp
+++ b/src/kits/shared/ExpressionParser.cpp
@@ -97,7 +97,9 @@ class ExpressionParser::Tokenizer {
                  fCurrentChar(NULL),
                  fCurrentToken(),
                  fReuseToken(false),
-                 fHexSupport(false)
+                 fHexSupport(false),
+                 fDecimalSeparator("."),
+                 fGroupSeparator(",")
        {
        }
 
@@ -128,12 +130,13 @@ class ExpressionParser::Tokenizer {
                while (*fCurrentChar != 0 && isspace(*fCurrentChar))
                        fCurrentChar++;
 
-               if (*fCurrentChar == 0)
-                       return fCurrentToken = Token("", 0, _CurrentPos(), 
TOKEN_END_OF_LINE);
+               int32 decimalLen = fDecimalSeparator.Length();
+               int32 groupLen = fGroupSeparator.Length();
 
-               bool decimal = *fCurrentChar == '.' || *fCurrentChar == ',';
+               if (*fCurrentChar == 0 || decimalLen == 0)
+                       return fCurrentToken = Token("", 0, _CurrentPos(), 
TOKEN_END_OF_LINE);
 
-               if (decimal || isdigit(*fCurrentChar)) {
+               if (*fCurrentChar == fDecimalSeparator[0] || 
isdigit(*fCurrentChar)) {
                        if (fHexSupport && *fCurrentChar == '0' && 
fCurrentChar[1] == 'x')
                                return _ParseHexNumber();
 
@@ -142,16 +145,30 @@ class ExpressionParser::Tokenizer {
                        const char* begin = fCurrentChar;
 
                        // optional digits before the comma
-                       while (isdigit(*fCurrentChar)) {
-                               temp << *fCurrentChar;
-                               fCurrentChar++;
+                       while (isdigit(*fCurrentChar) ||
+                               (groupLen > 0 && *fCurrentChar == 
fGroupSeparator[0])) {
+                               if (groupLen > 0 && *fCurrentChar == 
fGroupSeparator[0]) {
+                                       int i = 0;
+                                       while (i < groupLen && *fCurrentChar == 
fGroupSeparator[i]) {
+                                               fCurrentChar++;
+                                               i++;
+                                       }
+                               } else {
+                                       temp << *fCurrentChar;
+                                       fCurrentChar++;
+                               }
                        }
 
                        // optional post comma part
                        // (required if there are no digits before the comma)
-                       if (*fCurrentChar == '.' || *fCurrentChar == ',') {
+                       if (*fCurrentChar == fDecimalSeparator[0]) {
+                               int i = 0;
+                               while (i < decimalLen && *fCurrentChar == 
fDecimalSeparator[i]) {
+                                       fCurrentChar++;
+                                       i++;
+                               }
+
                                temp << '.';
-                               fCurrentChar++;
 
                                // optional post comma digits
                                while (isdigit(*fCurrentChar)) {
@@ -258,6 +275,22 @@ class ExpressionParser::Tokenizer {
                fReuseToken = true;
        }
 
+       BString DecimalSeparator()
+       {
+               return fDecimalSeparator;
+       }
+
+       BString GroupSeparator()
+       {
+               return fGroupSeparator;
+       }
+
+       void SetSeparators(BString decimal, BString group)
+       {
+               fDecimalSeparator = decimal;
+               fGroupSeparator = group;
+       }
+
  private:
        static bool _IsHexDigit(char c)
        {
@@ -306,6 +339,8 @@ class ExpressionParser::Tokenizer {
        Token           fCurrentToken;
        bool            fReuseToken;
        bool            fHexSupport;
+       BString         fDecimalSeparator;
+       BString         fGroupSeparator;
 };
 
 
@@ -356,7 +391,9 @@ ExpressionParser::Evaluate(const char* expressionString)
        if (value == 0)
                return BString("0");
 
-       char* buffer = value.toFixPtStringExp(kMaxDecimalPlaces, '.', 0, 0);
+       char* buffer = value.toFixPtStringExp(kMaxDecimalPlaces,
+                                               '.', 0, 0);
+
        if (buffer == NULL)
                throw ParseException("out of memory", 0);
 
@@ -365,11 +402,13 @@ ExpressionParser::Evaluate(const char* expressionString)
        if (strchr(buffer, '.')) {
                while (buffer[lastChar] == '0')
                        lastChar--;
+
                if (buffer[lastChar] == '.')
                        lastChar--;
        }
 
        BString result(buffer, lastChar + 1);
+       result.Replace(".", fTokenizer->DecimalSeparator(), 1);
        free(buffer);
        return result;
 }
@@ -792,3 +831,15 @@ ExpressionParser::_EatToken(int32 type)
                throw ParseException(temp.String(), token.position);
        }
 }
+
+
+status_t
+ExpressionParser::SetSeparators(BString decimal, BString group)
+{
+       if (decimal == group)
+               return B_ERROR;
+
+       fTokenizer->SetSeparators(decimal, group);
+
+       return B_OK;
+}


Other related posts:

  • » [haiku-commits] haiku: hrev56067 - in src: kits/shared apps/deskcalc - waddlesplash