DeskCalc: Fix Locale-aware display

Expression parser was made aware of Locale-specific separators in
hrev56067. However, the Expression view was still using only '.' as
separator. This change passes the Locale-specific decimal separator
to the ExpressionTextView class and uses that to parse the value for
display.

Fixes #17754

Change-Id: I7386eed51afe929a9b3eee69334f9199a3d06c4a
Reviewed-on: https://review.haiku-os.org/c/haiku/+/5338
Reviewed-by: Jérôme Duval <jerome.duval@gmail.com>
This commit is contained in:
Dale Cieslak 2022-05-23 22:21:24 -07:00 committed by Jérôme Duval
parent 956f45070d
commit 143253c873
3 changed files with 28 additions and 21 deletions

View File

@ -456,8 +456,12 @@ CalcView::MessageReceived(BMessage* message)
const char* result;
if (message->FindString("error", &result) == B_OK)
fExpressionTextView->SetText(result);
else if (message->FindString("value", &result) == B_OK)
fExpressionTextView->SetValue(result);
else if (message->FindString("value", &result) == B_OK) {
BLocale locale;
BNumberFormat format(&locale);
fExpressionTextView->SetValue(result, format.GetSeparator(B_DECIMAL_SEPARATOR));
}
// stop the message runner
delete fEvaluateMessageRunner;

View File

@ -191,7 +191,7 @@ ExpressionTextView::SetExpression(const char* expression)
void
ExpressionTextView::SetValue(BString value)
ExpressionTextView::SetValue(BString value, BString decimalSeparator)
{
// save the value
fCurrentValue = value;
@ -202,6 +202,8 @@ ExpressionTextView::SetValue(BString value)
GetFontAndColor(&font, &mode);
float stringWidth = font.StringWidth(value);
uint decimalSeparatorWidth = decimalSeparator.CountChars();
// make the string shorter if it does not fit in the view
float viewWidth = Frame().Width()
- floorf(be_control_look->DefaultLabelSpacing() / 2);
@ -213,10 +215,10 @@ ExpressionTextView::SetValue(BString value)
// calculate the value of the exponent
int32 exponent = 0;
int32 offset = value.FindFirst('.');
int32 offset = value.FindFirst(decimalSeparator);
if (offset == B_ERROR) {
exponent = value.CountChars() - 1 - firstDigit;
value.Insert('.', 1, firstDigit + 1);
exponent = value.CountChars() - decimalSeparatorWidth - firstDigit;
value.InsertChars(decimalSeparator, firstDigit + 1);
} else {
if (offset == firstDigit + 1) {
// if the value is 0.01 or larger then scientific notation
@ -226,7 +228,7 @@ ExpressionTextView::SetValue(BString value)
exponent = 0;
} else {
// remove the period
value.Remove(offset, 1);
value.Remove(offset, decimalSeparatorWidth);
// check for negative exponent value
exponent = 0;
@ -236,7 +238,7 @@ ExpressionTextView::SetValue(BString value)
}
// add the period
value.Insert('.', 1, firstDigit + 1);
value.InsertChars(decimalSeparator, firstDigit + 1);
}
} else {
// if the period + 1 digit fits in the view scientific notation
@ -248,8 +250,8 @@ ExpressionTextView::SetValue(BString value)
exponent = 0;
else {
// move the period
value.Remove(offset, 1);
value.Insert('.', 1, firstDigit + 1);
value.Remove(offset, decimalSeparatorWidth);
value.InsertChars(decimalSeparator, firstDigit + 1);
exponent = offset - (firstDigit + 1);
}
@ -271,15 +273,15 @@ ExpressionTextView::SetValue(BString value)
stringWidth = font.StringWidth(value);
char lastRemovedDigit = '0';
while (offset > firstDigit && stringWidth > viewWidth) {
if (value[offset] != '.')
if (value.CharAt(offset) != decimalSeparator)
lastRemovedDigit = value[offset];
value.Remove(offset--, 1);
stringWidth = font.StringWidth(value);
}
// no need to keep the period if no digits follow
if (value[offset] == '.') {
value.Remove(offset, 1);
if (value.CharAt(offset) == decimalSeparator) {
value.Remove(offset, decimalSeparatorWidth);
offset--;
}
@ -287,7 +289,7 @@ ExpressionTextView::SetValue(BString value)
int digit = (int)lastRemovedDigit - '0'; // ascii to int
if (digit >= 5) {
for (; offset >= firstDigit; offset--) {
if (value[offset] == '.')
if (value.CharAt(offset) == decimalSeparator)
continue;
digit = (int)(value[offset]) - '0' + 1; // ascii to int + 1
@ -298,9 +300,10 @@ ExpressionTextView::SetValue(BString value)
}
if (digit == 10) {
// carry over, shift the result
if (value[firstDigit + 1] == '.') {
value.SetByteAt(firstDigit + 1, '0');
value.SetByteAt(firstDigit, '.');
if (value.CharAt(firstDigit + 1) == decimalSeparator) {
value.SetByteAt(firstDigit + decimalSeparatorWidth, '0');
value.RemoveChars(firstDigit, decimalSeparatorWidth);
value.InsertChars(decimalSeparator, firstDigit);
}
value.Insert('1', 1, firstDigit);
@ -329,14 +332,14 @@ ExpressionTextView::SetValue(BString value)
}
// clean up decimal part if we have one
if (value.FindFirst('.') != B_ERROR) {
if (value.FindFirst(decimalSeparator) != B_ERROR) {
// remove trailing zeros
while (value[offset] == '0')
value.Remove(offset--, 1);
// no need to keep the period if no digits follow
if (value[offset] == '.')
value.Remove(offset, 1);
if (value.CharAt(offset) == decimalSeparator)
value.Remove(offset, decimalSeparatorWidth);
}
}

View File

@ -43,7 +43,7 @@ class ExpressionTextView : public InputTextView {
void AddKeypadLabel(const char* label);
void SetExpression(const char* expression);
void SetValue(BString value);
void SetValue(BString value, BString decimalSeparator = ".");
void BackSpace();
void Clear();