Merge branch 'master' into f7

This commit is contained in:
Émilie Feral
2019-06-13 12:12:55 -04:00
11 changed files with 155 additions and 80 deletions

View File

@@ -12,14 +12,14 @@ Zeros = "Zéros"
Tangent = "Tangente"
Intersection = "Intersection"
Preimage = "Antécédent"
SelectLowerBound = "Selectionner la borne inférieure"
SelectUpperBound = "Selectionner la borne supérieure"
SelectLowerBound = "Sélectionner la borne inférieure"
SelectUpperBound = "Sélectionner la borne supérieure"
NoMaximumFound = "Aucun maximum trouvé"
NoMinimumFound = "Aucun minimum trouvé"
NoZeroFound = "Aucun zéro trouvé"
NoIntersectionFound = "Aucune intersection trouvée"
NoPreimageFound = "Aucun antécédent trouvé"
DerivativeFunctionColumn = "Colonne de la fonction derivée"
HideDerivativeColumn = "Masquer la fonction derivée"
DerivativeFunctionColumn = "Colonne de la fonction dérivée"
HideDerivativeColumn = "Masquer la fonction dérivée"
AllowedCharactersAZaz09 = "Caractères autorisés : A-Z, a-z, 0-9, _"
ReservedName = "Nom réservé"

View File

@@ -20,6 +20,6 @@ Cartesian = "Algébrique "
Polar = "Exponentielle "
Brightness = "Luminosité"
SoftwareVersion = "Version du logiciel"
SerialNumber = "Numéro serie"
SerialNumber = "Numéro série"
UpdatePopUp = "Rappel mise à jour"
BetaPopUp = "Rappel version bêta"

View File

@@ -79,7 +79,7 @@ SolutionsController::SolutionsController(Responder * parentResponder, EquationSt
{
m_delta2Layout = HorizontalLayout::Builder(VerticalOffsetLayout::Builder(CodePointLayout::Builder('2', KDFont::SmallFont), VerticalOffsetLayoutNode::Position::Superscript), LayoutHelper::String("-4ac", 4, KDFont::SmallFont));
const char * deltaB = "Δ=b";
static_cast<HorizontalLayout&>(m_delta2Layout).addOrMergeChildAtIndex(LayoutHelper::String(deltaB, 3, KDFont::SmallFont), 0, false);
static_cast<HorizontalLayout&>(m_delta2Layout).addOrMergeChildAtIndex(LayoutHelper::String(deltaB, strlen(deltaB), KDFont::SmallFont), 0, false);
for (int i = 0; i < EquationStore::k_maxNumberOfExactSolutions; i++) {
m_exactValueCells[i].setParentResponder(m_contentView.selectableTableView());
}

View File

@@ -90,6 +90,20 @@ Responder * HistogramController::tabController() const {
return (parentResponder()->parentResponder()->parentResponder()->parentResponder());
}
void pad(char * buffer, int bufferSize, int * currentNumberOfChar, int maxGlyphLengthWithPadding) {
assert(*currentNumberOfChar <= bufferSize);
size_t currentGlyphLength = UTF8Helper::StringGlyphLength(buffer, *currentNumberOfChar);
bool addedPadding = false;
while (currentGlyphLength < maxGlyphLengthWithPadding && *currentNumberOfChar < bufferSize) {
*currentNumberOfChar = *currentNumberOfChar + UTF8Decoder::CodePointToChars(' ', buffer + *currentNumberOfChar, bufferSize - *currentNumberOfChar);
addedPadding = true;
currentGlyphLength++;
}
if (addedPadding) {
buffer[*currentNumberOfChar-1] = 0;
}
}
void HistogramController::reloadBannerView() {
if (selectedSeriesIndex() < 0) {
return;
@@ -107,7 +121,7 @@ void HistogramController::reloadBannerView() {
// Add lower bound
if (selectedSeriesIndex() >= 0) {
double lowerBound = m_store->startOfBarAtIndex(selectedSeriesIndex(), *m_selectedBarIndex);
numberOfChar += PoincareHelpers::ConvertFloatToText<double>(lowerBound, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
numberOfChar += PoincareHelpers::ConvertFloatToText<double>(lowerBound, buffer+numberOfChar, bufferSize-numberOfChar, Constant::LargeNumberOfSignificantDigits);
}
numberOfChar+= UTF8Decoder::CodePointToChars(';', buffer + numberOfChar, bufferSize - numberOfChar);
@@ -115,15 +129,12 @@ void HistogramController::reloadBannerView() {
// Add upper bound
if (selectedSeriesIndex() >= 0) {
double upperBound = m_store->endOfBarAtIndex(selectedSeriesIndex(), *m_selectedBarIndex);
numberOfChar += PoincareHelpers::ConvertFloatToText<double>(upperBound, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
numberOfChar += PoincareHelpers::ConvertFloatToText<double>(upperBound, buffer+numberOfChar, bufferSize-numberOfChar, Constant::LargeNumberOfSignificantDigits);
}
numberOfChar+= UTF8Decoder::CodePointToChars('[', buffer + numberOfChar, bufferSize - numberOfChar);
// Padding
for (int i = numberOfChar; i < k_maxIntervalLegendLength; i++) {
numberOfChar+= UTF8Decoder::CodePointToChars(' ', buffer + numberOfChar, bufferSize - numberOfChar);
}
buffer[k_maxIntervalLegendLength] = 0;
pad(buffer, bufferSize, &numberOfChar, k_maxIntervalLegendLength);
m_view.bannerView()->intervalView()->setText(buffer);
// Add Size Data
@@ -135,13 +146,10 @@ void HistogramController::reloadBannerView() {
double size = 0;
if (selectedSeriesIndex() >= 0) {
size = m_store->heightOfBarAtIndex(selectedSeriesIndex(), *m_selectedBarIndex);
numberOfChar += PoincareHelpers::ConvertFloatToText<double>(size, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
numberOfChar += PoincareHelpers::ConvertFloatToText<double>(size, buffer+numberOfChar, bufferSize-numberOfChar, Constant::LargeNumberOfSignificantDigits);
}
// Padding
for (int i = numberOfChar; i < k_maxLegendLength; i++) {
numberOfChar+= UTF8Decoder::CodePointToChars(' ', buffer + numberOfChar, bufferSize - numberOfChar);
}
buffer[k_maxLegendLength] = 0;
pad(buffer, bufferSize, &numberOfChar, k_maxLegendLength);
m_view.bannerView()->sizeView()->setText(buffer);
// Add Frequency Data
@@ -152,13 +160,10 @@ void HistogramController::reloadBannerView() {
numberOfChar += legendLength;
if (selectedSeriesIndex() >= 0) {
double frequency = size/m_store->sumOfOccurrences(selectedSeriesIndex());
numberOfChar += PoincareHelpers::ConvertFloatToText<double>(frequency, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
numberOfChar += PoincareHelpers::ConvertFloatToText<double>(frequency, buffer+numberOfChar, bufferSize - numberOfChar, Constant::LargeNumberOfSignificantDigits);
}
// Padding
for (int i = numberOfChar; i < k_maxLegendLength; i++) {
numberOfChar+= UTF8Decoder::CodePointToChars(' ', buffer + numberOfChar, bufferSize - numberOfChar);
}
buffer[k_maxLegendLength] = 0;
pad(buffer, bufferSize, &numberOfChar, k_maxLegendLength);
m_view.bannerView()->frequencyView()->setText(buffer);
m_view.bannerView()->reload();

View File

@@ -6,7 +6,7 @@
namespace TextInputHelpers {
const char * CursorPositionInCommand(const char * text);
const char * CursorPositionInCommand(const char * text, const char * stoppingPosition = nullptr);
/* Returns the pointer to the char that should be right of the cursor, which is
* the first char between :
* - The first EmptyChar (which is the position of the first argument)

View File

@@ -34,47 +34,62 @@ static inline void InsertSpacesAtLocation(int spacesCount, char * buffer, int bu
}
bool TextArea::handleEventWithText(const char * text, bool indentation, bool forceCursorRightOfText) {
constexpr int bufferSize = TextField::maxBufferSize();
char buffer[bufferSize];
size_t textLength = strlcpy(buffer, text, bufferSize);
// Add indentation spaces
if (*text == 0) {
return false;
}
/* Compute the indentation. If the text cannot be inserted with the
* indentation, stop here. */
int spacesCount = 0;
int totalIndentationSize = 0;
int textLen = strlen(text);
char * insertionPosition = const_cast<char *>(cursorLocation());
if (indentation) {
// Compute the indentation
int spacesCount = indentationBeforeCursor();
const char * teaxtAreaBuffer = contentView()->text();
if (cursorLocation() > teaxtAreaBuffer && UTF8Helper::PreviousCodePointIs(teaxtAreaBuffer, cursorLocation(), ':')) {
spacesCount = indentationBeforeCursor();
const char * textAreaBuffer = contentView()->text();
if (insertionPosition > textAreaBuffer && UTF8Helper::PreviousCodePointIs(textAreaBuffer, insertionPosition, ':')) {
spacesCount += k_indentationSpaces;
}
// Check the text will not overflow the buffer
int totalIndentationSize = UTF8Helper::CountOccurrences(text, '\n') * spacesCount;
if (contentView()->getText()->textLength() + textLength + totalIndentationSize >= contentView()->getText()->bufferSize() || textLength == 0) {
totalIndentationSize = UTF8Helper::CountOccurrences(text, '\n') * spacesCount;
if (contentView()->getText()->textLength() + textLen + totalIndentationSize >= contentView()->getText()->bufferSize()) {
return false;
}
UTF8Helper::PerformAtCodePoints(
buffer, '\n',
[](int codePointOffset, void * text, int indentation) {
int offset = codePointOffset + UTF8Decoder::CharSizeOfCodePoint('\n');
InsertSpacesAtLocation(indentation, (char *)text + offset, TextField::maxBufferSize() - offset); //TODO
},
[](int c1, void * c2, int c3) {},
(void *)buffer,
spacesCount);
}
const char * cursorPositionInCommand = TextInputHelpers::CursorPositionInCommand(buffer);
// Remove the Empty code points
UTF8Helper::RemoveCodePoint(buffer, UCodePointEmpty, &cursorPositionInCommand);
// Insert the text
if (insertTextAtLocation(buffer, cursorLocation())) {
// Set the cursor location
const char * nextCursorLocation = cursorLocation() + (forceCursorRightOfText ? strlen(buffer) : cursorPositionInCommand - buffer);
setCursorLocation(nextCursorLocation);
if (!insertTextAtLocation(text, insertionPosition)) {
return true;
}
// Insert the indentation
if (indentation) {
UTF8Helper::PerformAtCodePoints(
insertionPosition,
'\n',
[](int codePointOffset, void * text, int indentation, int bufferLength) {
int offset = codePointOffset + UTF8Decoder::CharSizeOfCodePoint('\n');
InsertSpacesAtLocation(indentation, (char *)text + offset, bufferLength);
},
[](int c1, void * c2, int c3, int c4) {},
(void *)insertionPosition,
spacesCount,
contentView()->getText()->bufferSize() - (insertionPosition - contentView()->getText()->text()),
UCodePointNull,
true,
nullptr,
insertionPosition + textLen);
}
const char * endOfInsertedText = insertionPosition + textLen + totalIndentationSize;
const char * cursorPositionInCommand = TextInputHelpers::CursorPositionInCommand(insertionPosition, endOfInsertedText);
// Remove the Empty code points
UTF8Helper::RemoveCodePoint(insertionPosition, UCodePointEmpty, &cursorPositionInCommand, endOfInsertedText);
// Set the cursor location
const char * nextCursorLocation = forceCursorRightOfText ? endOfInsertedText : cursorPositionInCommand;
setCursorLocation(nextCursorLocation);
return true;
}
@@ -136,14 +151,14 @@ int TextArea::indentationBeforeCursor() const {
* indentation size when encountering spaces, reset it to 0 when encountering
* another code point, until reaching the beginning of the line. */
UTF8Helper::PerformAtCodePoints(const_cast<TextArea *>(this)->contentView()->text(), ' ',
[](int codePointOffset, void * indentationSize, int context){
[](int codePointOffset, void * indentationSize, int context1, int context2){
int * castedSize = (int *) indentationSize;
*castedSize = *castedSize + 1;
},
[](int codePointOffset, void * indentationSize, int context){
[](int codePointOffset, void * indentationSize, int context1, int context2){
*((int *) indentationSize) = 0;
},
&indentationSize, 0, '\n', false, cursorLocation());
&indentationSize, 0, -1, '\n', false, cursorLocation());
return indentationSize;
}
@@ -380,10 +395,10 @@ bool TextArea::TextArea::ContentView::insertTextAtLocation(const char * text, co
// Scan for \n and 0
const char * nullLocation = UTF8Helper::PerformAtCodePoints(
text, '\n',
[](int codePointOffset, void * lineBreak, int indentation) {
[](int codePointOffset, void * lineBreak, int context1, int context2) {
*((bool *)lineBreak) = true;
},
[](int c1, void * c2, int c3) { },
[](int c1, void * c2, int c3, int c4) { },
&lineBreak, 0);
assert(UTF8Helper::CodePointIs(nullLocation, 0));

View File

@@ -4,11 +4,12 @@
namespace TextInputHelpers {
const char * CursorPositionInCommand(const char * text) {
const char * CursorPositionInCommand(const char * text, const char * stoppingPosition) {
assert(stoppingPosition == nullptr || text <= stoppingPosition);
UTF8Decoder decoder(text);
const char * currentPointer = text;
CodePoint codePoint = decoder.nextCodePoint();
while (codePoint != UCodePointNull) {
while ((stoppingPosition == nullptr || currentPointer < stoppingPosition) && codePoint != UCodePointNull) {
if (codePoint == UCodePointEmpty) {
return currentPointer;
}

View File

@@ -40,6 +40,7 @@ tests += $(addprefix ion/test/,\
keyboard.cpp\
storage.cpp\
utf8_decoder.cpp\
utf8_helper.cpp\
)
TEST_EXT_FLASH_REPROGRAM ?= 0

View File

@@ -24,7 +24,7 @@ void CopyAndRemoveCodePoint(char * dst, size_t dstSize, const char * src, CodePo
/* Remove all code points c. and update an index that should be lower if code
* points where removed before it. Ensure null-termination of dst. */
void RemoveCodePoint(char * buffer, CodePoint c, const char * * indexToDUpdate = nullptr);
void RemoveCodePoint(char * buffer, CodePoint c, const char * * indexToDUpdate = nullptr, const char * stoppingPosition = nullptr);
/* Copy src into dst until end of dst or code point c, with null termination. Return the length of the copy */
size_t CopyUntilCodePoint(char * dst, size_t dstSize, const char * src, CodePoint c);
@@ -50,8 +50,19 @@ size_t CopyUntilCodePoint(char * dst, size_t dstSize, const char * src, CodePoin
* ^start of string ^r ^initialPosition
*
* */
typedef void (*CodePointAction)(int codePointOffset, void * contextPointer, int contextInt);
const char * PerformAtCodePoints(const char * string, CodePoint c, CodePointAction actionCodePoint, CodePointAction actionOtherCodePoint, void * contextPointer, int contextInt, CodePoint stoppingCodePoint = UCodePointNull, bool goingRight = true, const char * initialPosition = nullptr);
typedef void (*CodePointAction)(int codePointOffset, void * contextPointer, int contextInt1, int contextInt2);
const char * PerformAtCodePoints(
const char * string,
CodePoint c,
CodePointAction actionCodePoint,
CodePointAction actionOtherCodePoint,
void * contextPointer,
int contextInt1,
int contextInt2 = -1,
CodePoint stoppingCodePoint = UCodePointNull,
bool goingRight = true,
const char * initialPosition = nullptr,
const char * stoppingPosition = nullptr);
bool PreviousCodePointIs(const char * buffer, const char * location, CodePoint c);
bool CodePointIs(const char * location, CodePoint c);
@@ -68,6 +79,10 @@ int RemovePreviousCodePoint(const char * text, char * location, CodePoint * c);
const char * CodePointAtGlyphOffset(const char * buffer, int position);
size_t GlyphOffsetAtCodePoint(const char * buffer, const char * position);
/* Return the number of glyphs in a string.
* For instance, strlen("∑") = 3 but StringGlyphLength("∑") = 1 */
size_t StringGlyphLength(const char * s, int maxSize = -1);
};
#endif

View File

@@ -110,7 +110,7 @@ void CopyAndRemoveCodePoint(char * dst, size_t dstSize, const char * src, CodePo
*(dst + minInt(bufferIndex, dstSize - 1)) = 0;
}
void RemoveCodePoint(char * buffer, CodePoint c, const char * * pointerToUpdate) {
void RemoveCodePoint(char * buffer, CodePoint c, const char * * pointerToUpdate, const char * stoppingPosition) {
UTF8Decoder decoder(buffer);
const char * currentPointer = buffer;
CodePoint codePoint = decoder.nextCodePoint();
@@ -118,7 +118,7 @@ void RemoveCodePoint(char * buffer, CodePoint c, const char * * pointerToUpdate)
size_t bufferIndex = 0;
size_t codePointCharSize = UTF8Decoder::CharSizeOfCodePoint(c);
while (codePoint != UCodePointNull) {
while (codePoint != UCodePointNull && (stoppingPosition == nullptr || currentPointer < stoppingPosition)) {
if (codePoint != c) {
int copySize = nextPointer - currentPointer;
memmove(buffer + bufferIndex, currentPointer, copySize);
@@ -131,7 +131,16 @@ void RemoveCodePoint(char * buffer, CodePoint c, const char * * pointerToUpdate)
codePoint = decoder.nextCodePoint();
nextPointer = decoder.stringPosition();
}
*(buffer + bufferIndex) = 0;
if (codePoint == UCodePointNull) {
*(buffer + bufferIndex) = 0;
} else {
assert(stoppingPosition != nullptr);
// Find the null-terminating code point
const char * nullTermination = CodePointSearch(currentPointer, UCodePointNull);
/* Copy what remains of the buffer after the stopping position for code
* point removal */
memmove(buffer + bufferIndex, stoppingPosition, nullTermination - stoppingPosition + 1);
}
}
size_t CopyUntilCodePoint(char * dst, size_t dstSize, const char * src, CodePoint c) {
@@ -150,7 +159,7 @@ size_t CopyUntilCodePoint(char * dst, size_t dstSize, const char * src, CodePoin
return copySize;
}
const char * PerformAtCodePoints(const char * s, CodePoint c, CodePointAction actionCodePoint, CodePointAction actionOtherCodePoint, void * contextPointer, int contextInt, CodePoint stoppingCodePoint, bool goingRight, const char * initialPosition) {
const char * PerformAtCodePoints(const char * s, CodePoint c, CodePointAction actionCodePoint, CodePointAction actionOtherCodePoint, void * contextPointer, int contextInt1, int contextInt2, CodePoint stoppingCodePoint, bool goingRight, const char * initialPosition, const char * stoppingPosition) {
/* If we are decoding towards the left, we must have a starting position. If
* we are decoding towards the right, the starting position is the start of
* string. */
@@ -162,22 +171,22 @@ const char * PerformAtCodePoints(const char * s, CodePoint c, CodePointAction ac
* translations. We can do a classic char search. */
if (goingRight) {
const char * i = s;
while (*i != stoppingCodePoint && *i != 0) {
while (*i != stoppingCodePoint && *i != 0 && i != stoppingPosition) {
if (*i == c) {
actionCodePoint(i - s, contextPointer, contextInt);
actionCodePoint(i - s, contextPointer, contextInt1, contextInt2);
} else {
actionOtherCodePoint(i - s, contextPointer, contextInt);
actionOtherCodePoint(i - s, contextPointer, contextInt1, contextInt2);
}
i++;
}
return i;
}
const char * i = initialPosition - 1;
while (i >= s && *i != stoppingCodePoint) {
while (i >= s && *i != stoppingCodePoint && i != stoppingPosition) {
if (*i == c) {
actionCodePoint(i - s, contextPointer, contextInt);
actionCodePoint(i - s, contextPointer, contextInt1, contextInt2);
} else {
actionOtherCodePoint(i - s, contextPointer, contextInt);
actionOtherCodePoint(i - s, contextPointer, contextInt1, contextInt2);
}
i--;
}
@@ -188,11 +197,11 @@ const char * PerformAtCodePoints(const char * s, CodePoint c, CodePointAction ac
UTF8Decoder decoder(s);
const char * codePointPointer = decoder.stringPosition();
CodePoint codePoint = decoder.nextCodePoint();
while (codePoint != stoppingCodePoint && codePoint != UCodePointNull) {
while (codePoint != stoppingCodePoint && codePoint != UCodePointNull && codePointPointer != stoppingPosition) {
if (codePoint == c) {
actionCodePoint(codePointPointer - s, contextPointer, contextInt);
actionCodePoint(codePointPointer - s, contextPointer, contextInt1, contextInt2);
} else {
actionOtherCodePoint(codePointPointer - s, contextPointer, contextInt);
actionOtherCodePoint(codePointPointer - s, contextPointer, contextInt1, contextInt2);
}
codePointPointer = decoder.stringPosition();
codePoint = decoder.nextCodePoint();
@@ -206,11 +215,11 @@ const char * PerformAtCodePoints(const char * s, CodePoint c, CodePointAction ac
UTF8Decoder decoder(s, initialPosition);
CodePoint codePoint = decoder.previousCodePoint();
const char * codePointPointer = decoder.stringPosition();
while (codePointPointer >= s && codePoint != stoppingCodePoint) {
while (codePointPointer >= s && codePoint != stoppingCodePoint && codePointPointer != stoppingPosition) {
if (codePoint == c) {
actionCodePoint(codePointPointer - s, contextPointer, contextInt);
actionCodePoint(codePointPointer - s, contextPointer, contextInt1, contextInt2);
} else {
actionOtherCodePoint(codePointPointer - s, contextPointer, contextInt);
actionOtherCodePoint(codePointPointer - s, contextPointer, contextInt1, contextInt2);
}
if (codePointPointer > s) {
codePoint = decoder.previousCodePoint();
@@ -326,5 +335,20 @@ size_t GlyphOffsetAtCodePoint(const char * buffer, const char * position) {
return glyphIndex;
}
size_t StringGlyphLength(const char * s, int maxSize) {
if (maxSize == 0) {
return 0;
}
UTF8Decoder decoder(s);
CodePoint codePoint = decoder.nextCodePoint();
size_t glyphIndex = 0;
while (codePoint != UCodePointNull && (maxSize < 0 || ((decoder.stringPosition() - s) <= maxSize))) {
if (!codePoint.isCombining()) {
glyphIndex++;
}
codePoint = decoder.nextCodePoint();
}
return glyphIndex;
}
};
}

14
ion/test/utf8_helper.cpp Normal file
View File

@@ -0,0 +1,14 @@
#include <quiz.h>
#include <ion/unicode/utf8_helper.h>
void assert_string_glyph_length_is(const char * string, int maxSize, size_t result) {
quiz_assert(UTF8Helper::StringGlyphLength(string, maxSize) == result);
}
QUIZ_CASE(ion_utf8_helper_glyph_length) {
assert_string_glyph_length_is("123", -1, 3);
assert_string_glyph_length_is("1ᴇ3", -1, 3);
assert_string_glyph_length_is("∑∫𝐢", -1, 3);
assert_string_glyph_length_is("123", 2, 2);
assert_string_glyph_length_is("1ᴇ3", 2, 1);
}