diff --git a/apps/code/python_toolbox.cpp b/apps/code/python_toolbox.cpp index c9d7d80ce..1498a58bf 100644 --- a/apps/code/python_toolbox.cpp +++ b/apps/code/python_toolbox.cpp @@ -289,8 +289,9 @@ bool PythonToolbox::selectLeaf(ToolboxMessageTree * selectedMessageTree) { m_selectableTableView.deselectTable(); ToolboxMessageTree * node = selectedMessageTree; const char * editedText = I18n::translate(node->insertedText()); - char strippedEditedText[strlen(editedText)+1]; - Shared::ToolboxHelpers::TextToInsertForCommandMessage(node->insertedText(), strippedEditedText); + int strippedEditedTextMaxLength = strlen(editedText)+1; + char strippedEditedText[strippedEditedTextMaxLength]; + Shared::ToolboxHelpers::TextToInsertForCommandMessage(node->insertedText(), strippedEditedText, strippedEditedTextMaxLength); m_action(sender(), const_cast(strippedEditedText)); app()->dismissModalViewController(); return true; diff --git a/apps/code/variable_box_controller.cpp b/apps/code/variable_box_controller.cpp index 657284ff2..9684642aa 100644 --- a/apps/code/variable_box_controller.cpp +++ b/apps/code/variable_box_controller.cpp @@ -119,8 +119,9 @@ void VariableBoxController::ContentViewController::willDisplayCellForIndex(Highl } void VariableBoxController::ContentViewController::insertTextInCaller(const char * text) { - char commandBuffer[strlen(text)+1]; - Shared::ToolboxHelpers::TextToInsertForCommandText(text, commandBuffer); + int commandBufferMaxSize = strlen(text)+1; + char commandBuffer[commandBufferMaxSize]; + Shared::ToolboxHelpers::TextToInsertForCommandText(text, commandBuffer, commandBufferMaxSize); if (m_textFieldCaller != nullptr) { if (!m_textFieldCaller->isEditing()) { m_textFieldCaller->setEditing(true); diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp index f7a37dd10..1ce07b16e 100644 --- a/apps/math_toolbox.cpp +++ b/apps/math_toolbox.cpp @@ -36,7 +36,8 @@ const ToolboxMessageTree arithmeticChildren[4] = { ToolboxMessageTree(I18n::Message::QuoCommandWithArg, I18n::Message::Quotient, I18n::Message::QuoCommandWithArg)}; #if MATRICES_ARE_DEFINED -const ToolboxMessageTree matricesChildren[5] = { +const ToolboxMessageTree matricesChildren[6] = { + ToolboxMessageTree(I18n::Message::MatrixCommandWithArg, I18n::Message::NewMatrix, I18n::Message::MatrixCommandWithArg), ToolboxMessageTree(I18n::Message::InverseCommandWithArg, I18n::Message::Inverse, I18n::Message::InverseCommandWithArg), ToolboxMessageTree(I18n::Message::DeterminantCommandWithArg, I18n::Message::Determinant, I18n::Message::DeterminantCommandWithArg), ToolboxMessageTree(I18n::Message::TransposeCommandWithArg, I18n::Message::Transpose, I18n::Message::TransposeCommandWithArg), @@ -88,7 +89,7 @@ const ToolboxMessageTree menu[10] = { ToolboxMessageTree(I18n::Message::Probability, I18n::Message::Default, I18n::Message::Default, probabilityChildren, 2), ToolboxMessageTree(I18n::Message::Arithmetic, I18n::Message::Default, I18n::Message::Default, arithmeticChildren, 4), #if MATRICES_ARE_DEFINED - ToolboxMessageTree(I18n::Message::Matrices, I18n::Message::Default, I18n::Message::Default, matricesChildren, 5), + ToolboxMessageTree(I18n::Message::Matrices, I18n::Message::Default, I18n::Message::Default, matricesChildren, 6), #endif #if LIST_ARE_DEFINED ToolboxMessageTree(I18n::Message::Lists, I18n::Message::Default, I18n::Message::Default, listesChildren, 5), @@ -119,8 +120,9 @@ void MathToolbox::actionForEditableExpressionView(void * sender, ToolboxMessageT EditableExpressionView * expressionLayoutEditorSender = static_cast(sender); // Translate the message and replace the arguments with Empty chars. const char * textToInsert = I18n::translate(messageTree->insertedText()); + int strippedTextToInsertMaxLength = strlen(textToInsert); char strippedTextToInsert[strlen(textToInsert)]; - Shared::ToolboxHelpers::TextToParseIntoLayoutForCommandMessage(messageTree->insertedText(), strippedTextToInsert); + Shared::ToolboxHelpers::TextToParseIntoLayoutForCommandMessage(messageTree->insertedText(), strippedTextToInsert, strippedTextToInsertMaxLength); // Create the layout Expression * resultExpression = Expression::parse(strippedTextToInsert); if (resultExpression == nullptr) { @@ -156,9 +158,10 @@ void MathToolbox::actionForTextfield(void * sender, ToolboxMessageTree * message textFieldSender->setEditing(true); } const char * textToInsert = I18n::translate(messageTree->insertedText()); - char strippedTextToInsert[strlen(textToInsert)]; + int textToInsertLength = strlen(textToInsert); + char strippedTextToInsert[textToInsertLength]; // Translate the message and remove the arguments. - Shared::ToolboxHelpers::TextToInsertForCommandMessage(messageTree->insertedText(), strippedTextToInsert); + Shared::ToolboxHelpers::TextToInsertForCommandMessage(messageTree->insertedText(), strippedTextToInsert, textToInsertLength); textFieldSender->insertTextAtLocation(strippedTextToInsert, textFieldSender->cursorLocation()); int newCursorLocation = textFieldSender->cursorLocation() + Shared::ToolboxHelpers::CursorIndexInCommand(strippedTextToInsert); textFieldSender->setCursorLocation(newCursorLocation); diff --git a/apps/shared.universal.i18n b/apps/shared.universal.i18n index 5ab160c94..1f06a778b 100644 --- a/apps/shared.universal.i18n +++ b/apps/shared.universal.i18n @@ -32,6 +32,7 @@ LcmCommandWithArg = "lcm(p,q)" LeftIntegralFirstLegend = "P(X≤" LeftIntegralSecondLegend = ")=" LogCommandWithArg = "log(x,a)" +MatrixCommandWithArg = "[[1,2][3,4]]" MaxCommandWithArg = "max(L)" MinCommandWithArg = "min(L)" Mu = "μ" diff --git a/apps/shared/toolbox_helpers.cpp b/apps/shared/toolbox_helpers.cpp index a1da1475f..268162c8d 100644 --- a/apps/shared/toolbox_helpers.cpp +++ b/apps/shared/toolbox_helpers.cpp @@ -1,6 +1,8 @@ #include "toolbox_helpers.h" #include +#include #include +#include namespace Shared { namespace ToolboxHelpers { @@ -10,28 +12,42 @@ int CursorIndexInCommand(const char * text) { if (text[i] == '(' || text[i] == '\'') { return i + 1; } + if (text[i] == ']') { + return (i - 1) > 0 ? i - 1 : 0; + } } return strlen(text); } -void TextToInsertForCommandMessage(I18n::Message message, char * buffer) { +void TextToInsertForCommandMessage(I18n::Message message, char * buffer, int bufferSize) { const char * messageText = I18n::translate(message); - TextToInsertForCommandText(messageText, buffer); + TextToInsertForCommandText(messageText, buffer, bufferSize); } -void TextToInsertForCommandText(const char * command, char * buffer) { +void TextToInsertForCommandText(const char * command, char * buffer, int bufferSize) { int currentNewTextIndex = 0; + int numberOfOpenParentheses = 0; int numberOfOpenBrackets = 0; bool insideQuote = false; size_t commandLength = strlen(command); for (size_t i = 0; i < commandLength; i++) { if (command[i] == ')') { + numberOfOpenParentheses--; + } + if (command[i] == ']') { numberOfOpenBrackets--; } - if ((numberOfOpenBrackets == 0 || command[i] == ',') && (!insideQuote || command[i] == '\'')) { + if (((numberOfOpenParentheses == 0 && numberOfOpenBrackets == 0) + || command[i] == ',' + || (numberOfOpenBrackets > 0 && (command[i] == ',' || command[i] == '[' || command[i] == ']'))) + && (!insideQuote || command[i] == '\'')) { + assert(currentNewTextIndex < bufferSize); buffer[currentNewTextIndex++] = command[i]; } if (command[i] == '(') { + numberOfOpenParentheses++; + } + if (command[i] == '[') { numberOfOpenBrackets++; } if (command[i] == '\'') { @@ -41,12 +57,23 @@ void TextToInsertForCommandText(const char * command, char * buffer) { buffer[currentNewTextIndex] = 0; } -void TextToParseIntoLayoutForCommandMessage(I18n::Message message, char * buffer) { +void TextToParseIntoLayoutForCommandMessage(I18n::Message message, char * buffer, int bufferSize) { + if (message == I18n::Message::MatrixCommandWithArg) { + assert(bufferSize >= 6); + // Handle a new matrix command. + buffer[0] = '['; + buffer[1] = '['; + buffer[2] = Ion::Charset::Empty; + buffer[3] = ']'; + buffer[4] = ']'; + buffer[5] = 0; + return; + } const char * messageText = I18n::translate(message); - TextToInsertForCommandText(messageText, buffer); + TextToInsertForCommandText(messageText, buffer, bufferSize); size_t bufferLength = strlen(buffer); for (size_t i = 0; i < bufferLength; i++) { - if (buffer[i] == '(' || buffer[i] == ',') { + if (buffer[i] == '(' || buffer[i] == '[' || buffer[i] == ',') { // Shift the buffer to make room for the new char. Use memmove to avoid // overwritting. memmove(&buffer[i+2], &buffer[i+1], bufferLength - (i+1) + 1); diff --git a/apps/shared/toolbox_helpers.h b/apps/shared/toolbox_helpers.h index 98539614d..d051f5847 100644 --- a/apps/shared/toolbox_helpers.h +++ b/apps/shared/toolbox_helpers.h @@ -13,11 +13,11 @@ int CursorIndexInCommand(const char * text); * - The end of the text */ -void TextToInsertForCommandMessage(I18n::Message message, char * buffer); -void TextToInsertForCommandText(const char * command, char * buffer); +void TextToInsertForCommandMessage(I18n::Message message, char * buffer, int bufferSize); +void TextToInsertForCommandText(const char * command, char * buffer, int bufferSize); /* Removes the arguments from a command: - * - Removes text between parentheses, except commas */ -void TextToParseIntoLayoutForCommandMessage(I18n::Message message, char * buffer); + * - Removes text between parentheses or brackets, except commas */ +void TextToParseIntoLayoutForCommandMessage(I18n::Message message, char * buffer, int bufferSize); /* Removes the arguments from a command and replaces them with empty chars. */ } diff --git a/apps/toolbox.de.i18n b/apps/toolbox.de.i18n index a8b6fd1b6..6312f3aad 100644 --- a/apps/toolbox.de.i18n +++ b/apps/toolbox.de.i18n @@ -7,6 +7,7 @@ ComplexNumber = "Komplexen Zahlen" Probability = "Kombinatorik" Arithmetic = "Arithmetisch" Matrices = "Matrizen" +NewMatrix = "Neue Matrix" Lists = "Listen" Approximation = "Approximation" HyperbolicTrigonometry = "Hyperbelfunktionen" diff --git a/apps/toolbox.en.i18n b/apps/toolbox.en.i18n index b1a6e3533..e8103814b 100644 --- a/apps/toolbox.en.i18n +++ b/apps/toolbox.en.i18n @@ -7,6 +7,7 @@ ComplexNumber = "Complex numbers" Probability = "Combinatorics" Arithmetic = "Arithmetic" Matrices = "Matrix" +NewMatrix = "New matrix" Lists = "List" Approximation = "Approximation" HyperbolicTrigonometry = "Hyperbolic trigonometry" diff --git a/apps/toolbox.es.i18n b/apps/toolbox.es.i18n index 90ecf326a..a78d837d4 100644 --- a/apps/toolbox.es.i18n +++ b/apps/toolbox.es.i18n @@ -7,6 +7,7 @@ ComplexNumber = "Numeros complejos" Probability = "Combinatoria" Arithmetic = "Aritmetica" Matrices = "Matriz" +NewMatrix = "Nueva matriz" Lists = "Listas" Approximation = "Aproximacion" HyperbolicTrigonometry = "Trigonometria hiperbolica" diff --git a/apps/toolbox.fr.i18n b/apps/toolbox.fr.i18n index d8cb4b190..d944d0415 100644 --- a/apps/toolbox.fr.i18n +++ b/apps/toolbox.fr.i18n @@ -7,6 +7,7 @@ ComplexNumber = "Nombres complexes" Probability = "Denombrement" Arithmetic = "Arithmetique" Matrices = "Matrices" +NewMatrix = "Nouvelle matrice" Lists = "Listes" Approximation = "Approximation" HyperbolicTrigonometry = "Trigonometrie hyperbolique" diff --git a/apps/toolbox.pt.i18n b/apps/toolbox.pt.i18n index aa1ad1d81..45ade5d5e 100644 --- a/apps/toolbox.pt.i18n +++ b/apps/toolbox.pt.i18n @@ -7,6 +7,7 @@ ComplexNumber = "Numeros complexos" Probability = "Combinatoria" Arithmetic = "Aritmetica" Matrices = "Matrizes" +NewMatrix = "Nova matriz" Lists = "Listas" Approximation = "Aproximacao" HyperbolicTrigonometry = "Funcoes hiperbolicas" diff --git a/escher/src/editable_expression_view.cpp b/escher/src/editable_expression_view.cpp index 78bed4b2b..01159a81a 100644 --- a/escher/src/editable_expression_view.cpp +++ b/escher/src/editable_expression_view.cpp @@ -1,5 +1,6 @@ #include #include +#include #include EditableExpressionView::EditableExpressionView(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, EditableExpressionViewDelegate * delegate) : @@ -150,6 +151,9 @@ void EditableExpressionView::insertLayoutAtCursor(Poincare::ExpressionLayout * l } KDSize previousSize = minimalSizeForOptimalDisplay(); m_expressionViewWithCursor.cursor()->addLayout(layout); + if (layout->isMatrix() && pointedLayout->hasAncestor(layout)) { + static_cast(layout)->addGreySquares(); + } m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(pointedLayout); m_expressionViewWithCursor.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right); reload(); diff --git a/poincare/src/layout/matrix_layout.h b/poincare/src/layout/matrix_layout.h index b931bb51b..8208d11b3 100644 --- a/poincare/src/layout/matrix_layout.h +++ b/poincare/src/layout/matrix_layout.h @@ -29,6 +29,8 @@ public: /* Special matrix method */ void newRowOrColumnAtIndex(int index); + void addGreySquares(); + protected: void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; KDSize computeSize() override; @@ -37,7 +39,6 @@ private: void childWasReplacedAtIndex(int index); bool isRowEmpty(int index) const; bool isColumnEmpty(int index) const; - void addGreySquares(); void removeGreySquares(); bool hasGreySquares() const; };