diff --git a/.gitmodules b/.gitmodules index 134e135f693..02641c8d556 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "apps/rpn"] path = apps/rpn url = https://github.com/Omega-Numworks/Omega-RPN.git -[submodule "apps/atom"] - path = apps/atom - url = https://github.com/Omega-Numworks/Omega-Atom.git +[submodule "apps/atomic"] + path = apps/atomic + url = https://github.com/Omega-Numworks/Omega-Atomic.git diff --git a/README.fr.md b/README.fr.md index 98c4ecc3d3f..0eda582df08 100644 --- a/README.fr.md +++ b/README.fr.md @@ -1,4 +1,4 @@ -

+

cc by-nc-sa 4.0 @@ -155,7 +155,7 @@ Pour contribuer, merci de lire le [Wiki](https://github.com/Omega-Numworks/Omega * [Omega Themes](https://github.com/Omega-Numworks/Omega-Themes) * [Omega Website](https://github.com/Omega-Numworks/Omega-Website) * [Omega RPN `APP`](https://github.com/Omega-Numworks/Omega-RPN) -* [Omega Atom `APP`](https://github.com/Omega-Numworks/Omega-Atom) +* [Omega Atomic `APP`](https://github.com/Omega-Numworks/Omega-Atomic) * [Omega Design](https://github.com/Omega-Numworks/Omega-Design) * [Omega Discord Bot](https://github.com/Omega-Numworks/Omega-Discord-Bot) * [Omega App Template `BETA`](https://github.com/Omega-Numworks/Omega-App-Template) diff --git a/README.md b/README.md index 0bf964083c1..2620c8f49cf 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -

+

cc by-nc-sa 4.0 @@ -154,7 +154,7 @@ To contribute, please refer to the [Wiki](https://github.com/Omega-Numworks/Omeg * [Omega Themes](https://github.com/Omega-Numworks/Omega-Themes) * [Omega Website](https://github.com/Omega-Numworks/Omega-Website) * [Omega RPN `APP`](https://github.com/Omega-Numworks/Omega-RPN) -* [Omega Atom `APP`](https://github.com/Omega-Numworks/Omega-Atom) +* [Omega Atomic `APP`](https://github.com/Omega-Numworks/Omega-Atomic) * [Omega Design](https://github.com/Omega-Numworks/Omega-Design) * [Omega Discord Bot](https://github.com/Omega-Numworks/Omega-Discord-Bot) * [Omega App Template `BETA`](https://github.com/Omega-Numworks/Omega-App-Template) diff --git a/apps/Makefile b/apps/Makefile index c27cc6465c8..69f88165e38 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -110,6 +110,7 @@ $(BUILD_DIR)/apps/i18n.h: $(BUILD_DIR)/apps/i18n.cpp $(eval $(call depends_on_image,apps/title_bar_view.cpp,apps/exam_icon.png)) $(call object_for,$(apps_src) $(tests_src)): $(BUILD_DIR)/apps/i18n.h +$(call object_for,$(apps_src) $(tests_src)): $(BUILD_DIR)/apps/home/apps_layout.h $(call object_for,$(apps_src) $(tests_src)): $(BUILD_DIR)/python/port/genhdr/qstrdefs.generated.h apps_tests_src = $(app_calculation_test_src) $(app_code_test_src) $(app_graph_test_src) $(app_probability_test_src) $(app_regression_test_src) $(app_sequence_test_src) $(app_shared_test_src) $(app_statistics_test_src) $(app_settings_test_src) $(app_solver_test_src) diff --git a/apps/apps_container.cpp b/apps/apps_container.cpp index 0bbe77d117c..acf3feb383d 100644 --- a/apps/apps_container.cpp +++ b/apps/apps_container.cpp @@ -8,6 +8,8 @@ #include #include +#include + extern "C" { #include } @@ -218,6 +220,13 @@ bool AppsContainer::dispatchEvent(Ion::Events::Event event) { return didProcessEvent || alphaLockWantsRedraw; } +static constexpr Ion::Events::Event switch_events[] = { + Ion::Events::ShiftSeven, Ion::Events::ShiftEight, Ion::Events::ShiftNine, + Ion::Events::ShiftFour, Ion::Events::ShiftFive, Ion::Events::ShiftSix, + Ion::Events::ShiftOne, Ion::Events::ShiftTwo, Ion::Events::ShiftThree, + Ion::Events::ShiftZero, Ion::Events::ShiftDot, Ion::Events::ShiftEE +}; + bool AppsContainer::processEvent(Ion::Events::Event event) { // Warning: if the window is dirtied, you need to call window()->redraw() if (event == Ion::Events::USBPlug) { @@ -242,6 +251,15 @@ bool AppsContainer::processEvent(Ion::Events::Event event) { switchTo(appSnapshotAtIndex(1)); return true; } + + for(int i = 0; i < std::min((int) (sizeof(switch_events) / sizeof(Ion::Events::Event)), APPS_CONTAINER_SNAPSHOT_COUNT); i++) { + if (event == switch_events[i]) { + m_window.redraw(true); + switchTo(appSnapshotAtIndex(i+1)); + return true; + } + } + if (event == Ion::Events::OnOff) { suspend(true); return true; diff --git a/apps/atom b/apps/atom deleted file mode 160000 index 8f710a9d3fa..00000000000 --- a/apps/atom +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 8f710a9d3fa4daedde14ba489e418dbac5d590c5 diff --git a/apps/atomic b/apps/atomic new file mode 160000 index 00000000000..69f7a06ba53 --- /dev/null +++ b/apps/atomic @@ -0,0 +1 @@ +Subproject commit 69f7a06ba53eaae9ba2ab8f0c0318e2f77455f4d diff --git a/apps/calculation/expression_field.cpp b/apps/calculation/expression_field.cpp index a190a9558d1..b96c4b1fed6 100644 --- a/apps/calculation/expression_field.cpp +++ b/apps/calculation/expression_field.cpp @@ -17,7 +17,8 @@ bool ExpressionField::handleEvent(Ion::Events::Event event) { event == Ion::Events::Power || event == Ion::Events::Square || event == Ion::Events::Division || - event == Ion::Events::Sto)) { + event == Ion::Events::Sto || + event == Ion::Events::EE)) { handleEventWithText(Poincare::Symbol::k_ans); } return(::ExpressionField::handleEvent(event)); diff --git a/apps/code/Makefile b/apps/code/Makefile index de11dcb4c66..92646ed6122 100644 --- a/apps/code/Makefile +++ b/apps/code/Makefile @@ -15,6 +15,7 @@ app_code_src = $(addprefix apps/code/,\ sandbox_controller.cpp \ script_name_cell.cpp \ script_parameter_controller.cpp \ + toolbox_ion_keys.cpp \ ) app_code_test_src = $(addprefix apps/code/,\ diff --git a/apps/code/app.cpp b/apps/code/app.cpp index 4db851b222b..f56559c7c84 100644 --- a/apps/code/app.cpp +++ b/apps/code/app.cpp @@ -124,6 +124,10 @@ Toolbox * App::toolboxForInputEventHandler(InputEventHandler * textInput) { return &m_toolbox; } +Code::toolboxIonKeys * App::toolboxIonKeys() { + return &m_toolboxIonKeys; +} + VariableBoxController * App::variableBoxForInputEventHandler(InputEventHandler * textInput) { return &m_variableBoxController; } diff --git a/apps/code/app.h b/apps/code/app.h index 494f5c0f8c7..82a0ad0dd11 100644 --- a/apps/code/app.h +++ b/apps/code/app.h @@ -10,6 +10,7 @@ #include "python_toolbox.h" #include "variable_box_controller.h" #include "../shared/shared_app.h" +#include "toolbox_ion_keys.h" namespace Code { @@ -77,6 +78,8 @@ class App : public Shared::InputEventHandlerDelegateApp { static constexpr int k_pythonHeapSize = 100000; + Code::toolboxIonKeys * toolboxIonKeys(); + private: /* Python delegate: * MicroPython requires a heap. To avoid dynamic allocation, we keep a working @@ -93,6 +96,7 @@ class App : public Shared::InputEventHandlerDelegateApp { StackViewController m_codeStackViewController; PythonToolbox m_toolbox; VariableBoxController m_variableBoxController; + Code::toolboxIonKeys m_toolboxIonKeys; }; } diff --git a/apps/code/base.fr.i18n b/apps/code/base.fr.i18n index b9006a2d0a6..46d7109ad38 100644 --- a/apps/code/base.fr.i18n +++ b/apps/code/base.fr.i18n @@ -12,4 +12,4 @@ ImportedModulesAndScripts = "Modules et scripts importés" NoWordAvailableHere = "Aucun mot disponible à cet endroit." ScriptInProgress = "Script en cours" ScriptOptions = "Options de script" -ScriptSize = "Script size" +ScriptSize = "Taille du script" diff --git a/apps/code/catalog.de.i18n b/apps/code/catalog.de.i18n index f1c208068f7..9cb321ab8e4 100644 --- a/apps/code/catalog.de.i18n +++ b/apps/code/catalog.de.i18n @@ -45,6 +45,7 @@ PythonCosh = "Hyperbolic cosine" PythonCount = "Zählt wie oft x vorkommt" PythonDegrees = "x von Radian zu Grad umwandeln" PythonDivMod = "Quotient und Rest" +PythonDrawLine = "Draw a line" PythonDrawString = "Schreibt Text bei (x,y)" PythonErf = "Fehlerfunktion" PythonErfc = "Complementary error function" @@ -86,52 +87,6 @@ PythonIsInfinite = "Prüft ob x unendlich ist" PythonIsNaN = "Prüft ob x NaN ist" PythonIsKeyDown = "true wenn k gedrückt ist" PythonKandinskyFunction = "kandinsky module function prefix" -PythonKeyLeft = "Linke Pfeiltaste" -PythonKeyUp = "Pfeiltaste nach oben" -PythonKeyDown = "Pfeiltaste nach unten" -PythonKeyRight = "Rechte Pfeiltaste" -PythonKeyOk = "OK Taste" -PythonKeyBack = "ZURÜCK Taste" -PythonKeyHome = "HOME Taste" -PythonKeyOnOff = "AN/AUS Taste" -PythonKeyShift = "SHIFT Taste" -PythonKeyAlpha = "ALPHA Taste" -PythonKeyXnt = "X,N,T Taste" -PythonKeyVar = "VAR Taste" -PythonKeyToolbox = "WERKZEUGBOX Taste" -PythonKeyBackspace = "LÖSCHEN Taste" -PythonKeyExp = "EXPONENTIAL Taste" -PythonKeyLn = "NATURAL LOGARITHM Taste" -PythonKeyLog = "DECIMAL LOGARITHM Taste" -PythonKeyImaginary = "IMAGINÄRES I Taste" -PythonKeyComma = "KOMMA Taste" -PythonKeyPower = "HOCH Taste" -PythonKeySine = "SINUS Taste" -PythonKeyCosine = "COSINUS Taste" -PythonKeyTangent = "TANGENZ Taste" -PythonKeyPi = "PI Taste" -PythonKeySqrt = "WURZEL Taste" -PythonKeySquare = "QUADRAT Taste" -PythonKeySeven = "7 Taste" -PythonKeyEight = "8 Taste" -PythonKeyNine = "9 Taste" -PythonKeyLeftParenthesis = "LEFT PARENTHESIS key" -PythonKeyRightParenthesis = "RIGHT PARENTHESIS key" -PythonKeyFour = "4 Taste" -PythonKeyFive = "5 Taste" -PythonKeySix = "6 Taste" -PythonKeyMultiplication = "MULTIPLIKATIONSTASTE" -PythonKeyDivision = "DIVISIONSTASTE" -PythonKeyOne = "1 Taste" -PythonKeyTwo = "2 Taste" -PythonKeyThree = "3 Taste" -PythonKeyPlus = "PLUS Taste" -PythonKeyMinus = "MINUS Taste" -PythonKeyZero = "0 Taste" -PythonKeyDot = "PUNKT Taste" -PythonKeyEe = "10 HOCH X Taste" -PythonKeyAns = "ANS Taste" -PythonKeyExe = "EXE Taste" PythonLdexp = "Return x*(2**i), inverse of frexp" PythonLength = "Length of an object" PythonLgamma = "Log-gamma function" diff --git a/apps/code/catalog.en.i18n b/apps/code/catalog.en.i18n index cd115b9aa5b..819887dbbef 100644 --- a/apps/code/catalog.en.i18n +++ b/apps/code/catalog.en.i18n @@ -45,6 +45,7 @@ PythonCosh = "Hyperbolic cosine" PythonCount = "Count the occurrences of x" PythonDegrees = "Convert x from radians to degrees" PythonDivMod = "Quotient and remainder" +PythonDrawLine = "Draw a line" PythonDrawString = "Display a text from pixel (x,y)" PythonErf = "Error function" PythonErfc = "Complementary error function" @@ -81,52 +82,6 @@ PythonIsInfinite = "Check if x is infinity" PythonIsKeyDown = "Return True if the k key is down" PythonIsNaN = "Check if x is a NaN" PythonKandinskyFunction = "kandinsky module function prefix" -PythonKeyLeft = "LEFT ARROW key" -PythonKeyUp = "UP ARROW key" -PythonKeyDown = "DOWN ARROW key" -PythonKeyRight = "RIGHT ARROW key" -PythonKeyOk = "OK key" -PythonKeyBack = "BACK key" -PythonKeyHome = "HOME key" -PythonKeyOnOff = "ON/OFF key" -PythonKeyShift = "SHIFT key" -PythonKeyAlpha = "ALPHA key" -PythonKeyXnt = "X,N,T key" -PythonKeyVar = "VAR key" -PythonKeyToolbox = "TOOLBOX key" -PythonKeyBackspace = "BACKSPACE key" -PythonKeyExp = "EXPONENTIAL key" -PythonKeyLn = "NATURAL LOGARITHM key" -PythonKeyLog = "DECIMAL LOGARITHM key" -PythonKeyImaginary = "IMAGINARY I key" -PythonKeyComma = "COMMA key" -PythonKeyPower = "POWER key" -PythonKeySine = "SINE key" -PythonKeyCosine = "COSINE key" -PythonKeyTangent = "TANGENT key" -PythonKeyPi = "PI key" -PythonKeySqrt = "SQUARE ROOT key" -PythonKeySquare = "SQUARE key" -PythonKeySeven = "7 key" -PythonKeyEight = "8 key" -PythonKeyNine = "9 key" -PythonKeyLeftParenthesis = "LEFT PARENTHESIS key" -PythonKeyRightParenthesis = "RIGHT PARENTHESIS key" -PythonKeyFour = "4 key" -PythonKeyFive = "5 key" -PythonKeySix = "6 key" -PythonKeyMultiplication = "MULTIPLICATION key" -PythonKeyDivision = "DIVISION key" -PythonKeyOne = "1 key" -PythonKeyTwo = "2 key" -PythonKeyThree = "3 key" -PythonKeyPlus = "PLUS key" -PythonKeyMinus = "MINUS key" -PythonKeyZero = "0 key" -PythonKeyDot = "DOT key" -PythonKeyEe = "10 POWER X key" -PythonKeyAns = "ANS key" -PythonKeyExe = "EXE key" PythonLdexp = "Return x*(2**i), inverse of frexp" PythonLength = "Length of an object" PythonLgamma = "Log-gamma function" diff --git a/apps/code/catalog.es.i18n b/apps/code/catalog.es.i18n index ee8b58f598b..960dd7eb9bc 100644 --- a/apps/code/catalog.es.i18n +++ b/apps/code/catalog.es.i18n @@ -45,6 +45,7 @@ PythonCosh = "Hyperbolic cosine" PythonCount = "Count the occurrences of x" PythonDegrees = "Convert x from radians to degrees" PythonDivMod = "Quotient and remainder" +PythonDrawLine = "Draw a line" PythonDrawString = "Display a text from pixel (x,y)" PythonErf = "Error function" PythonErfc = "Complementary error function" @@ -81,52 +82,6 @@ PythonIsInfinite = "Check if x is infinity" PythonIsKeyDown = "Return True if the k key is down" PythonIsNaN = "Check if x is a NaN" PythonKandinskyFunction = "kandinsky module function prefix" -PythonKeyLeft = "LEFT ARROW key" -PythonKeyUp = "UP ARROW key" -PythonKeyDown = "DOWN ARROW key" -PythonKeyRight = "RIGHT ARROW key" -PythonKeyOk = "OK key" -PythonKeyBack = "BACK key" -PythonKeyHome = "HOME key" -PythonKeyOnOff = "ON/OFF key" -PythonKeyShift = "SHIFT key" -PythonKeyAlpha = "ALPHA key" -PythonKeyXnt = "X,N,T key" -PythonKeyVar = "VAR key" -PythonKeyToolbox = "TOOLBOX key" -PythonKeyBackspace = "BACKSPACE key" -PythonKeyExp = "EXPONENTIAL key" -PythonKeyLn = "NATURAL LOGARITHM key" -PythonKeyLog = "DECIMAL LOGARITHM key" -PythonKeyImaginary = "IMAGINARY I key" -PythonKeyComma = "COMMA key" -PythonKeyPower = "POWER key" -PythonKeySine = "SINE key" -PythonKeyCosine = "COSINE key" -PythonKeyTangent = "TANGENT key" -PythonKeyPi = "PI key" -PythonKeySqrt = "SQUARE ROOT key" -PythonKeySquare = "SQUARE key" -PythonKeySeven = "7 key" -PythonKeyEight = "8 key" -PythonKeyNine = "9 key" -PythonKeyLeftParenthesis = "LEFT PARENTHESIS key" -PythonKeyRightParenthesis = "RIGHT PARENTHESIS key" -PythonKeyFour = "4 key" -PythonKeyFive = "5 key" -PythonKeySix = "6 key" -PythonKeyMultiplication = "MULTIPLICATION key" -PythonKeyDivision = "DIVISION key" -PythonKeyOne = "1 key" -PythonKeyTwo = "2 key" -PythonKeyThree = "3 key" -PythonKeyPlus = "PLUS key" -PythonKeyMinus = "MINUS key" -PythonKeyZero = "0 key" -PythonKeyDot = "DOT key" -PythonKeyEe = "10 POWER X key" -PythonKeyAns = "ANS key" -PythonKeyExe = "EXE key" PythonLdexp = "Return x*(2**i), inverse of frexp" PythonLength = "Length of an object" PythonLgamma = "Log-gamma function" diff --git a/apps/code/catalog.fr.i18n b/apps/code/catalog.fr.i18n index 3a7d94eb896..756ef882e0f 100644 --- a/apps/code/catalog.fr.i18n +++ b/apps/code/catalog.fr.i18n @@ -45,6 +45,7 @@ PythonCosh = "Cosinus hyperbolique" PythonCount = "Compte les occurrences de x" PythonDegrees = "Conversion de radians en degrés" PythonDivMod = "Quotient et reste" +PythonDrawLine = "Trace une ligne" PythonDrawString = "Affiche un texte au pixel (x,y)" PythonErf = "Fonction d'erreur" PythonErfc = "Fonction d'erreur complémentaire" @@ -81,52 +82,6 @@ PythonIsInfinite = "Teste si x est infini" PythonIsKeyDown = "Renvoie True si touche k enfoncée" PythonIsNaN = "Teste si x est NaN" PythonKandinskyFunction = "Préfixe fonction module kandinsky" -PythonKeyLeft = "Touche FLECHE GAUCHE" -PythonKeyUp = "Touche FLECHE HAUT" -PythonKeyDown = "Touche FLECHE BAS" -PythonKeyRight = "Touche FLECHE DROITE" -PythonKeyOk = "Touche OK" -PythonKeyBack = "Touche RETOUR" -PythonKeyHome = "Touche HOME" -PythonKeyOnOff = "Touche ON/OFF" -PythonKeyShift = "Touche SHIFT" -PythonKeyAlpha = "Touche ALPHA" -PythonKeyXnt = "Touche X,N,T" -PythonKeyVar = "Touche VAR" -PythonKeyToolbox = "Touche BOITE A OUTILS" -PythonKeyBackspace = "Touche EFFACER" -PythonKeyExp = "Touche EXPONENTIELLE" -PythonKeyLn = "Touche LOGARITHME NEPERIEN" -PythonKeyLog = "Touche LOGARITHME DECIMAL" -PythonKeyImaginary = "Touche I IMAGINAIRE" -PythonKeyComma = "Touche VIRGULE" -PythonKeyPower = "Touche PUISSANCE" -PythonKeySine = "Touche SINUS" -PythonKeyCosine = "Touche COSINUS" -PythonKeyTangent = "Touche TANGENTE" -PythonKeyPi = "Touche PI" -PythonKeySqrt = "Touche RACINE CARREE" -PythonKeySquare = "Touche CARRE" -PythonKeySeven = "Touche 7" -PythonKeyEight = "Touche 8" -PythonKeyNine = "Touche 9" -PythonKeyLeftParenthesis = "Touche PARENTHESE GAUCHE" -PythonKeyRightParenthesis = "Touche PARENTHESE DROITE" -PythonKeyFour = "Touche 4" -PythonKeyFive = "Touche 5" -PythonKeySix = "Touche 6" -PythonKeyMultiplication = "Touche MULTIPLICATION" -PythonKeyDivision = "Touche DIVISION" -PythonKeyOne = "Touche 1" -PythonKeyTwo = "Touche 2" -PythonKeyThree = "Touche 3" -PythonKeyPlus = "Touche PLUS" -PythonKeyMinus = "Touche MOINS" -PythonKeyZero = "Touche 0" -PythonKeyDot = "Touche POINT" -PythonKeyEe = "Touche 10 PUISSANCE X" -PythonKeyAns = "Touche ANS" -PythonKeyExe = "Touche EXE" PythonLdexp = "Inverse de frexp : x*(2**i)" PythonLength = "Longueur d'un objet" PythonLgamma = "Logarithme de la fonction gamma" @@ -210,12 +165,12 @@ PythonFileSeek = "Déplace le curseur interne" PythonFileTell = "Donne la posititon du curseur" PythonFileClose = "Ferme un fichier" PythonFileClosed = "True si le fichier a été fermé" -PythonFileRead = "Lis jusqu'à size bytes" -PythonFileWrite = "Écris b dans le fichier" -PythonFileReadline = "Lis une ligne ou jusqu'à size bytes" -PythonFileReadlines = "Lis une liste de lignes" +PythonFileRead = "Lit jusqu'à size bytes" +PythonFileWrite = "Écrit b dans le fichier" +PythonFileReadline = "Lit une ligne ou jusqu'à size bytes" +PythonFileReadlines = "Lit une liste de lignes" PythonFileTruncate = "Redimensionne le fichier" -PythonFileWritelines = "Écris une liste de lignes" +PythonFileWritelines = "Écrit une liste de lignes" PythonFileName = "Nom du fichier" PythonFileMode = "Mode d'ouverture du fichier" PythonFileReadable = "Indique si read peut être utilisé" diff --git a/apps/code/catalog.hu.i18n b/apps/code/catalog.hu.i18n index 6871a7dcfbe..a837db91b58 100644 --- a/apps/code/catalog.hu.i18n +++ b/apps/code/catalog.hu.i18n @@ -45,6 +45,7 @@ PythonCosh = "Hiperbolikus koszinusz" PythonCount = "Számolja az x elöfordulását" PythonDegrees = "x konvertálása radiánokrol fokokra" PythonDivMod = "Hányados és maradék" +PythonDrawLine = "Húzzon egy vonalat " PythonDrawString = "Szöveg megjelenítése (x, y)-en" PythonErf = "Hiba funkció" PythonErfc = "Kiegészítö hiba funkció" @@ -81,52 +82,6 @@ PythonIsInfinite = "x végtelen-e" PythonIsKeyDown = "True-t válaszol ha a k gomb le van nyomva" PythonIsNaN = "Ellenörizze hogy x nem NaN" PythonKandinskyFunction = "kandinsky modul funkció elötag" -PythonKeyLeft = "BAL NYÍL gomb" -PythonKeyUp = "FEL NYÍL gomb" -PythonKeyDown = "LE NYÍL gomb" -PythonKeyRight = "JOBB NYÍL gomb" -PythonKeyOk = "OK gomb" -PythonKeyBack = "VISSZA gomb" -PythonKeyHome = "HOME gomb" -PythonKeyOnOff = "ON/OFF gomb" -PythonKeyShift = "SHIFT gomb" -PythonKeyAlpha = "ALPHA gomb" -PythonKeyXnt = "X,N,T gomb" -PythonKeyVar = "VAR gomb" -PythonKeyToolbox = "TOOLBOX gomb" -PythonKeyBackspace = "TÖRLÉS gomb" -PythonKeyExp = "EXPONENCIÁLIS gomb" -PythonKeyLn = "NEPERIAI LOGARITHM gomb" -PythonKeyLog = "DECIMÁLIS LOGARITHM gomb" -PythonKeyImaginary = "KÉPZELETBELI I gomb" -PythonKeyComma = "VESSZÖ gomb" -PythonKeyPower = "KIÁLLÍTÓ gomb" -PythonKeySine = "SZINUSZ gomb" -PythonKeyCosine = "KOSZINUSZ gomb" -PythonKeyTangent = "TANGENS gomb" -PythonKeyPi = "PI gomb" -PythonKeySqrt = "NÉGYZETGYÖK gomb" -PythonKeySquare = "NÉGYZET gomb" -PythonKeySeven = "7 gomb" -PythonKeyEight = "8 gomb" -PythonKeyNine = "9 gomb" -PythonKeyLeftParenthesis = "BAL ZÁRÓJEL gomb" -PythonKeyRightParenthesis = "JOB ZÁRÓJEL gomb" -PythonKeyFour = "4 gomb" -PythonKeyFive = "5 gomb" -PythonKeySix = "6 gomb" -PythonKeyMultiplication = "SZOZÁS gomb" -PythonKeyDivision = "OSZTÁS gomb" -PythonKeyOne = "1 gomb" -PythonKeyTwo = "2 gomb" -PythonKeyThree = "3 gomb" -PythonKeyPlus = "PLUS gomb" -PythonKeyMinus = "MINUS gomb" -PythonKeyZero = "0 gomb" -PythonKeyDot = "PONT gomb" -PythonKeyEe = "10 X KITEVÖ gomb" -PythonKeyAns = "ANS gomb" -PythonKeyExe = "EXE gomb" PythonLdexp = "frexp ellentéte : x*(2**i)" PythonLength = "Egy targy hossza" PythonLgamma = "Gamma funkció logaritmusa" diff --git a/apps/code/catalog.it.i18n b/apps/code/catalog.it.i18n index 27a7ea40845..94eacc262f0 100644 --- a/apps/code/catalog.it.i18n +++ b/apps/code/catalog.it.i18n @@ -45,6 +45,7 @@ PythonCosh = "Coseno iperbolico" PythonCount = "Conta le ricorrenze di x" PythonDegrees = "Conversione di radianti in gradi" PythonDivMod = "Quoziente e resto" +PythonDrawLine = "Disegna una linea" PythonDrawString = "Visualizza il testo dal pixel x,y" PythonErf = "Funzione d'errore" PythonErfc = "Funzione d'errore complementare" @@ -86,52 +87,6 @@ PythonIsInfinite = "Testa se x est infinito" PythonIsKeyDown = "Restituisce True premendo tasto k" PythonIsNaN = "Testa se x è NaN" PythonKandinskyFunction = "Prefisso funzione modulo kandinsky" -PythonKeyLeft = "Tasto FRECCIA SINISTRA" -PythonKeyUp = "Tasto FRECCIA ALTO" -PythonKeyDown = "Tasto FRECCIA BASSO" -PythonKeyRight = "Tasto FRECCIA DESTRA" -PythonKeyOk = "Tasto OK" -PythonKeyBack = "Tasto INDIETRO" -PythonKeyHome = "Tasto CASA" -PythonKeyOnOff = "Tasto ON/OFF" -PythonKeyShift = "Tasto SHIFT" -PythonKeyAlpha = "Tasto ALPHA" -PythonKeyXnt = "Tasto X,N,T" -PythonKeyVar = "Tasto VAR" -PythonKeyToolbox = "Tasto TOOLBOX" -PythonKeyBackspace = "Tasto CANCELLA" -PythonKeyExp = "Tasto ESPONENZIALE" -PythonKeyLn = "Tasto LOGARITMO NEPERIANO" -PythonKeyLog = "Tasto LOGARITMO DECIMALE" -PythonKeyImaginary = "Tasto I IMMAGINE" -PythonKeyComma = "Tasto VIRGOLA" -PythonKeyPower = "Tasto POTENZA" -PythonKeySine = "Tasto SENO" -PythonKeyCosine = "Tasto COSENO" -PythonKeyTangent = "Tasto TANGENTE" -PythonKeyPi = "Tasto PI" -PythonKeySqrt = "Tasto RADICE QUADRATA" -PythonKeySquare = "Tasto QUADRATO" -PythonKeySeven = "Tasto 7" -PythonKeyEight = "Tasto 8" -PythonKeyNine = "Tasto 9" -PythonKeyLeftParenthesis = "Tasto PARENTESI SINISTRA" -PythonKeyRightParenthesis = "Tasto PARENTESI DESTRA" -PythonKeyFour = "Tasto 4" -PythonKeyFive = "Tasto 5" -PythonKeySix = "Tasto 6" -PythonKeyMultiplication = "Tasto MOLTIPLICAZIONE" -PythonKeyDivision = "Tasto DIVISIONE" -PythonKeyOne = "Tasto 1" -PythonKeyTwo = "Tasto 2" -PythonKeyThree = "Tasto 3" -PythonKeyPlus = "Tasto PIÙ" -PythonKeyMinus = "Tasto MENO" -PythonKeyZero = "Tasto 0" -PythonKeyDot = "Tasto PUNTO" -PythonKeyEe = "Tasto 10 POTENZA X" -PythonKeyAns = "Tasto ANS" -PythonKeyExe = "Tasto EXE" PythonLdexp = "Inversa di frexp : x*(2**i)" PythonLength = "Longhezza di un oggetto" PythonLgamma = "Logaritmo della funzione gamma" diff --git a/apps/code/catalog.nl.i18n b/apps/code/catalog.nl.i18n index b3ec4225723..1ee1f667ccb 100644 --- a/apps/code/catalog.nl.i18n +++ b/apps/code/catalog.nl.i18n @@ -45,6 +45,7 @@ PythonCosh = "Cosinus hyperbolicus" PythonCount = "Tel voorkomen van x" PythonDegrees = "Zet x om van radialen naar graden" PythonDivMod = "Quotiënt en rest" +PythonDrawLine = "Teken een lijn" PythonDrawString = "Geef een tekst weer van pixel (x,y)" PythonErf = "Error functie" PythonErfc = "Complementaire error functie" @@ -86,52 +87,6 @@ PythonIsInfinite = "Controleer of x oneindig is" PythonIsKeyDown = "Geef True als k toets omlaag is" PythonIsNaN = "Controleer of x geen getal is" PythonKandinskyFunction = "kandinsky module voorvoegsel" -PythonKeyLeft = "PIJL NAAR LINKS toets" -PythonKeyUp = "PIJL OMHOOG toets" -PythonKeyDown = "PIJL OMLAAG toets" -PythonKeyRight = "PIJL NAAR RECHTS toets" -PythonKeyOk = "OK toets" -PythonKeyBack = "TERUG toets" -PythonKeyHome = "HOME toets" -PythonKeyOnOff = "AAN/UIT toets" -PythonKeyShift = "SHIFT toets" -PythonKeyAlpha = "ALPHA toets" -PythonKeyXnt = "X,N,T toets" -PythonKeyVar = "VAR toets" -PythonKeyToolbox = "TOOLBOX toets" -PythonKeyBackspace = "BACKSPACE toets" -PythonKeyExp = "EXPONENTIEEL toets" -PythonKeyLn = "NATUURLIJKE LOGARITME toets" -PythonKeyLog = "BRIGGSE LOGARITME toets" -PythonKeyImaginary = "IMAGINAIRE I toets" -PythonKeyComma = "KOMMA toets" -PythonKeyPower = "MACHT toets" -PythonKeySine = "SINUS toets" -PythonKeyCosine = "COSINUS toets" -PythonKeyTangent = "TANGENS toets" -PythonKeyPi = "PI toets" -PythonKeySqrt = "VIERKANTSWORTEL toets" -PythonKeySquare = "KWADRAAT toets" -PythonKeySeven = "7 toets" -PythonKeyEight = "8 toets" -PythonKeyNine = "9 toets" -PythonKeyLeftParenthesis = "HAAKJE OPENEN toets" -PythonKeyRightParenthesis = "HAAKJE SLUITEN toets" -PythonKeyFour = "4 toets" -PythonKeyFive = "5 toets" -PythonKeySix = "6 toets" -PythonKeyMultiplication = "VERMENIGVULDIGEN toets" -PythonKeyDivision = "DELEN toets" -PythonKeyOne = "1 toets" -PythonKeyTwo = "2 toets" -PythonKeyThree = "3 toets" -PythonKeyPlus = "PLUS toets" -PythonKeyMinus = "MIN toets" -PythonKeyZero = "0 toets" -PythonKeyDot = "PUNT toets" -PythonKeyEe = "10 TOT DE MACHT X toets" -PythonKeyAns = "ANS toets" -PythonKeyExe = "EXE toets" PythonLdexp = "Geeft x*(2**i), inversie van frexp" PythonLength = "Lengte van een object" PythonLgamma = "Log-gammafunctie" diff --git a/apps/code/catalog.pt.i18n b/apps/code/catalog.pt.i18n index de29d19d465..a17ea0ad5c0 100644 --- a/apps/code/catalog.pt.i18n +++ b/apps/code/catalog.pt.i18n @@ -45,6 +45,7 @@ PythonCosh = "Cosseno hiperbólico" PythonCount = "Contar as ocorrências de x" PythonDegrees = "Converter x de radianos para graus" PythonDivMod = "Quociente e resto" +PythonDrawLine = "Desenhe uma linha" PythonDrawString = "Mostrar o texto do pixel (x,y)" PythonErf = "Função erro" PythonErfc = "Função erro complementar" @@ -81,52 +82,6 @@ PythonIsInfinite = "Verificar se x é infinito" PythonIsKeyDown = "Devolve True se tecla k pressionada" PythonIsNaN = "Verificar se x é um NaN" PythonKandinskyFunction = "Prefixo da função do módulo kandinsky" -PythonKeyLeft = "tecla SETA ESQUERDA" -PythonKeyUp = "tecla SETA CIMA " -PythonKeyDown = "tecla SETA BAIXO" -PythonKeyRight = "tecla SETA DIREITA" -PythonKeyOk = "tecla OK" -PythonKeyBack = "tecla VOLTAR" -PythonKeyHome = "tecla HOME" -PythonKeyOnOff = "tecla ON/OFF" -PythonKeyShift = "tecla SHIFT" -PythonKeyAlpha = "tecla ALPHA" -PythonKeyXnt = "tecla X,N,T" -PythonKeyVar = "tecla VAR" -PythonKeyToolbox = "tecla CAIXA DE FERRAMENTAS" -PythonKeyBackspace = "tecla APAGAR" -PythonKeyExp = "tecla EXPONENCIAL" -PythonKeyLn = "tecla LOGARITMO NATURAL" -PythonKeyLog = "tecla LOGARITMO DECIMAL" -PythonKeyImaginary = "tecla I IMAGINÁRIO" -PythonKeyComma = "tecla VÍRGULA" -PythonKeyPower = "tecla EXPOENTE" -PythonKeySine = "tecla SENO" -PythonKeyCosine = "tecla COSSENO" -PythonKeyTangent = "tecla TANGENTE" -PythonKeyPi = "tecla PI" -PythonKeySqrt = "tecla RAIZ QUADRADA" -PythonKeySquare = "tecla AO QUADRADO" -PythonKeySeven = "tecla 7" -PythonKeyEight = "tecla 8" -PythonKeyNine = "tecla 9" -PythonKeyLeftParenthesis = "tecla PARÊNTESE ESQUERDO" -PythonKeyRightParenthesis = "tecla PARÊNTESE DIREITO" -PythonKeyFour = "tecla 4" -PythonKeyFive = "tecla 5" -PythonKeySix = "tecla 6" -PythonKeyMultiplication = "tecla MULTIPLICAÇÃO" -PythonKeyDivision = "tecla DIVISÃO" -PythonKeyOne = "tecla 1" -PythonKeyTwo = "tecla 2" -PythonKeyThree = "tecla 3" -PythonKeyPlus = "tecla MAIS" -PythonKeyMinus = "tecla MENOS" -PythonKeyZero = "tecla 0" -PythonKeyDot = "tecla PONTO" -PythonKeyEe = "tecla 10 expoente X" -PythonKeyAns = "tecla ANS" -PythonKeyExe = "tecla EXE" PythonLdexp = "Devolve x*(2**i), inverso de frexp" PythonLength = "Comprimento de um objeto" PythonLgamma = "Logaritmo da função gama" diff --git a/apps/code/catalog.universal.i18n b/apps/code/catalog.universal.i18n index 001c5834909..39d1ff3b494 100644 --- a/apps/code/catalog.universal.i18n +++ b/apps/code/catalog.universal.i18n @@ -50,6 +50,7 @@ PythonCommandCount = "list.count(x)" PythonCommandCountWithoutArg = ".count(\x11)" PythonCommandDegrees = "degrees(x)" PythonCommandDivMod = "divmod(a,b)" +PythonCommandDrawLine = "draw_line(x1,y1,x2,y2,color)" PythonCommandDrawString = "draw_string(\"text\",x,y)" PythonCommandConstantE = "e" PythonCommandErf = "erf(x)" diff --git a/apps/code/python_toolbox.cpp b/apps/code/python_toolbox.cpp index 2a0ba410d8e..34aa96bfac3 100644 --- a/apps/code/python_toolbox.cpp +++ b/apps/code/python_toolbox.cpp @@ -5,6 +5,7 @@ extern "C" { #include #include } +#include "app.h" namespace Code { @@ -192,6 +193,7 @@ const ToolboxMessageTree KandinskyModuleChildren[] = { ToolboxMessageTree::Leaf(I18n::Message::PythonCommandSetPixel, I18n::Message::PythonSetPixel), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColor, I18n::Message::PythonColor), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandDrawString, I18n::Message::PythonDrawString), + ToolboxMessageTree::Leaf(I18n::Message::PythonCommandDrawLine, I18n::Message::PythonDrawLine), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandFillRect, I18n::Message::PythonFillRect) }; @@ -200,52 +202,7 @@ const ToolboxMessageTree IonModuleChildren[] = { ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportFromIon, I18n::Message::PythonImportIon, false), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandIonFunction, I18n::Message::PythonIonFunction, false, I18n::Message::PythonCommandIonFunctionWithoutArg), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandIsKeyDown, I18n::Message::PythonIsKeyDown), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyLeft, I18n::Message::PythonKeyLeft, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyUp, I18n::Message::PythonKeyUp, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyDown, I18n::Message::PythonKeyDown, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyRight, I18n::Message::PythonKeyRight, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyOk, I18n::Message::PythonKeyOk, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyBack, I18n::Message::PythonKeyBack, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyHome, I18n::Message::PythonKeyHome, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyOnOff, I18n::Message::PythonKeyOnOff, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyShift, I18n::Message::PythonKeyShift, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyAlpha, I18n::Message::PythonKeyAlpha, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyXnt, I18n::Message::PythonKeyXnt, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyVar, I18n::Message::PythonKeyVar, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyToolbox, I18n::Message::PythonKeyToolbox, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyBackspace, I18n::Message::PythonKeyBackspace, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyExp, I18n::Message::PythonKeyExp, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyLn, I18n::Message::PythonKeyLn, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyLog, I18n::Message::PythonKeyLog, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyImaginary, I18n::Message::PythonKeyImaginary, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyComma, I18n::Message::PythonKeyComma, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyPower, I18n::Message::PythonKeyPower, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeySine, I18n::Message::PythonKeySine, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyCosine, I18n::Message::PythonKeyCosine, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyTangent, I18n::Message::PythonKeyTangent, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyPi, I18n::Message::PythonKeyPi, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeySqrt, I18n::Message::PythonKeySqrt, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeySquare, I18n::Message::PythonKeySquare, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeySeven, I18n::Message::PythonKeySeven, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyEight, I18n::Message::PythonKeyEight, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyNine, I18n::Message::PythonKeyNine, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyLeftParenthesis, I18n::Message::PythonKeyLeftParenthesis, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyRightParenthesis, I18n::Message::PythonKeyRightParenthesis, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyFour, I18n::Message::PythonKeyFour, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyFive, I18n::Message::PythonKeyFive, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeySix, I18n::Message::PythonKeySix, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyMultiplication, I18n::Message::PythonKeyMultiplication, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyDivision, I18n::Message::PythonKeyDivision, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyOne, I18n::Message::PythonKeyOne, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyTwo, I18n::Message::PythonKeyTwo, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyThree, I18n::Message::PythonKeyThree, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyPlus, I18n::Message::PythonKeyPlus, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyMinus, I18n::Message::PythonKeyMinus, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyZero, I18n::Message::PythonKeyZero, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyDot, I18n::Message::PythonKeyDot, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyEe, I18n::Message::PythonKeyEe, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyAns, I18n::Message::PythonKeyAns, false), - ToolboxMessageTree::Leaf(I18n::Message::PythonCommandKeyExe, I18n::Message::PythonKeyExe, false) + ToolboxMessageTree::Leaf(I18n::Message::IonSelector, I18n::Message::IonSelector) }; const ToolboxMessageTree TimeModuleChildren[] = { @@ -315,6 +272,7 @@ const ToolboxMessageTree catalogChildren[] = { ToolboxMessageTree::Leaf(I18n::Message::PythonCommandCosh, I18n::Message::PythonCosh), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandDegrees, I18n::Message::PythonDegrees), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandDivMod, I18n::Message::PythonDivMod), + ToolboxMessageTree::Leaf(I18n::Message::PythonCommandDrawLine, I18n::Message::PythonDrawLine), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandDrawString, I18n::Message::PythonDrawString), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandConstantE, I18n::Message::PythonConstantE, false), ToolboxMessageTree::Leaf(I18n::Message::PythonCommandErf, I18n::Message::PythonErf), @@ -536,6 +494,11 @@ KDCoordinate PythonToolbox::rowHeight(int j) { bool PythonToolbox::selectLeaf(int selectedRow) { m_selectableTableView.deselectTable(); ToolboxMessageTree * node = (ToolboxMessageTree *)m_messageTreeModel->childAtIndex(selectedRow); + if(node->insertedText() == I18n::Message::IonSelector){ + App::app()->toolboxIonKeys()->setSender(sender()); + Container::activeApp()->displayModalViewController(static_cast(App::app()->toolboxIonKeys()), 0.f, 0.f, Metric::PopUpTopMargin, Metric::PopUpLeftMargin, 0, Metric::PopUpRightMargin); + return true; + } const char * editedText = I18n::translate(node->insertedText()); // strippedEditedText array needs to be in the same scope as editedText char strippedEditedText[k_maxMessageSize]; diff --git a/apps/code/toolbox.universal.i18n b/apps/code/toolbox.universal.i18n index 72bd47ef965..4dd5345def6 100644 --- a/apps/code/toolbox.universal.i18n +++ b/apps/code/toolbox.universal.i18n @@ -57,3 +57,5 @@ PythonCommandDef = "def \x11():\n " PythonCommandDefWithArg = "def function(x):" PythonCommandReturn = "return " RandomModule = "random" +IonSelector = "Key selector" +PressAKey = "Press a key" diff --git a/apps/code/toolbox_ion_keys.cpp b/apps/code/toolbox_ion_keys.cpp new file mode 100644 index 00000000000..b3e67f63f04 --- /dev/null +++ b/apps/code/toolbox_ion_keys.cpp @@ -0,0 +1,50 @@ +#include "toolbox_ion_keys.h" +#include +#include +#include +extern "C" { +#include +#include +} +extern const mp_rom_map_elem_t modion_module_globals_table[48]; + +namespace Code { + toolboxIonKeys::toolboxIonKeys() : + ViewController(nullptr), + m_view() + { + } + + bool toolboxIonKeys::handleEvent(Ion::Events::Event e) { + Ion::Keyboard::State state = Ion::Keyboard::scan(); + for(uint16_t i = 0; i < sizeof(modion_module_globals_table)/sizeof(_mp_rom_map_elem_t); i++){ + _mp_rom_map_elem_t element = modion_module_globals_table[i]; + if(mp_obj_is_small_int(element.value)){ + int key = mp_obj_get_int(element.value); + if(state.keyDown(static_cast(key))){ + m_sender->handleEventWithText(qstr_str(MP_OBJ_QSTR_VALUE(element.key)), true); + } + } + } + Container::activeApp()->dismissModalViewController(); + AppsContainer::sharedAppsContainer()->redrawWindow(); + return true; + } + + toolboxIonKeys::toolboxIonView::toolboxIonView(): + View() + { + } + + void toolboxIonKeys::toolboxIonView::drawRect(KDContext * ctx, KDRect rect) const { + ctx->fillRect(rect, Palette::GrayBright); + ctx->strokeRect(rect, Palette::GrayDark); + ctx->drawString(I18n::translate(I18n::Message::PressAKey),KDPoint(rect.left()+80, rect.top()+20)); + + } + + View * toolboxIonKeys::view(){ + return &m_view; + } + +} diff --git a/apps/code/toolbox_ion_keys.h b/apps/code/toolbox_ion_keys.h new file mode 100644 index 00000000000..4efe2036d9e --- /dev/null +++ b/apps/code/toolbox_ion_keys.h @@ -0,0 +1,21 @@ +#include + +namespace Code { + + class toolboxIonKeys : public ViewController { + public : + toolboxIonKeys(); + View * view() override; + bool handleEvent(Ion::Events::Event e) override; + void setSender(InputEventHandler * sender) { m_sender = sender; } + private : + class toolboxIonView : public View { + public : + toolboxIonView(); + void drawRect(KDContext * ctx, KDRect rect) const override; + }; + toolboxIonView m_view; + InputEventHandler * m_sender; + }; + +} diff --git a/apps/external/archive.cpp b/apps/external/archive.cpp index 5636f0ef61f..8f3d000bf7c 100644 --- a/apps/external/archive.cpp +++ b/apps/external/archive.cpp @@ -55,29 +55,43 @@ bool fileAtIndex(size_t index, File &entry) { * TAR files are comprised of a set of records aligned to 512 bytes boundary * followed by data. */ - while (index-- > 0) { + + for(;;) { + // Calculate the size size = 0; for (int i = 0; i < 11; i++) size = size * 8 + (tar->size[i] - '0'); + + // Check if we found our file. + if (index == 0) { + // If yes, check for sanity and for exam mode stuff + if (!isSane(tar) || isExamModeAndFileNotExecutable(tar)) { + return false; + } - // Move to the next TAR header. - unsigned stride = (sizeof(TarHeader) + size + 511); - stride = (stride >> 9) << 9; - tar = reinterpret_cast(reinterpret_cast(tar) + stride); - - // Sanity check. - if (!isSane(tar) || isExamModeAndFileNotExecutable(tar)) { - return false; + // File entry found, copy data out. + entry.name = tar->name; + entry.data = reinterpret_cast(tar) + sizeof(TarHeader); + entry.dataLength = size; + entry.isExecutable = (tar->mode[4] & 0x01) == 1; + + return true; + } else { + // move to the next TAR header. + unsigned stride = (sizeof(TarHeader) + size + 511); + stride = (stride >> 9) << 9; + tar = reinterpret_cast(reinterpret_cast(tar) + stride); + + // Sanity check. + if (!isSane(tar)) { + return false; + } } + index--; } - - // File entry found, copy data out. - entry.name = tar->name; - entry.data = reinterpret_cast(tar) + sizeof(TarHeader); - entry.dataLength = size; - entry.isExecutable = (tar->mode[4] & 0x01) == 1; - - return true; + + // Achievement unlock: How did we get there ? + return false; } extern "C" void (* const apiPointers[])(void); diff --git a/apps/home/apps_layout.csv b/apps/home/apps_layout.csv index 64469620c74..77e47e4b882 100644 --- a/apps/home/apps_layout.csv +++ b/apps/home/apps_layout.csv @@ -1,2 +1,2 @@ -Default,calculation,rpn,graph,code,statistics,probability,solver,atom,sequence,regression,settings -HidePython,calculation,rpn,graph,code,statistics,probability,solver,atom,sequence,regression,settings \ No newline at end of file +Default,calculation,rpn,graph,code,statistics,probability,solver,atomic,sequence,regression,settings +HidePython,calculation,rpn,graph,code,statistics,probability,solver,atomic,sequence,regression,settings diff --git a/apps/main.cpp b/apps/main.cpp index 3a22fda5c77..d501a0d9a57 100644 --- a/apps/main.cpp +++ b/apps/main.cpp @@ -53,8 +53,12 @@ void ion_main(int argc, const char * const argv[]) { const char * appNames[] = {"home", EPSILON_APPS_NAMES}; for (int j = 0; j < AppsContainer::sharedAppsContainer()->numberOfApps(); j++) { App::Snapshot * snapshot = AppsContainer::sharedAppsContainer()->appSnapshotAtIndex(j); - int cmp = strcmp(argv[i]+2, appNames[j]); - if (cmp == '-') { + // Compare name in order to find if the firsts chars which are different are NULL and '-' + // -> check if the app name is in the argv + const char * s1 = argv[i]+2; + const char * s2 = appNames[j]; + while (*s1 != '\0' && (*s1 == *s2)) {s1++; s2++;} + if (*s2 == '\0' && *s1 == '-') { snapshot->setOpt(argv[i]+2+strlen(appNames[j])+1, argv[i+1]); break; } diff --git a/apps/settings/main_controller.cpp b/apps/settings/main_controller.cpp index 75b598d87b2..6b65f15d3ea 100644 --- a/apps/settings/main_controller.cpp +++ b/apps/settings/main_controller.cpp @@ -19,12 +19,8 @@ constexpr SettingsMessageTree s_symbolFunctionChildren[3] = {SettingsMessageTree constexpr SettingsMessageTree s_modelMathOptionsChildren[6] = {SettingsMessageTree(I18n::Message::AngleUnit, s_modelAngleChildren), SettingsMessageTree(I18n::Message::DisplayMode, s_modelFloatDisplayModeChildren), SettingsMessageTree(I18n::Message::EditionMode, s_modelEditionModeChildren), SettingsMessageTree(I18n::Message::SymbolFunction, s_symbolFunctionChildren), SettingsMessageTree(I18n::Message::ComplexFormat, s_modelComplexFormatChildren), SettingsMessageTree(I18n::Message::SymbolMultiplication, s_symbolChildren)}; constexpr SettingsMessageTree s_modelFontChildren[2] = {SettingsMessageTree(I18n::Message::LargeFont), SettingsMessageTree(I18n::Message::SmallFont)}; constexpr SettingsMessageTree s_accessibilityChildren[6] = {SettingsMessageTree(I18n::Message::AccessibilityInvertColors), SettingsMessageTree(I18n::Message::AccessibilityMagnify),SettingsMessageTree(I18n::Message::AccessibilityGamma),SettingsMessageTree(I18n::Message::AccessibilityGammaRed),SettingsMessageTree(I18n::Message::AccessibilityGammaGreen),SettingsMessageTree(I18n::Message::AccessibilityGammaBlue)}; -constexpr SettingsMessageTree s_contributorsChildren[20] = {SettingsMessageTree(I18n::Message::Developers), SettingsMessageTree(I18n::Message::QuentinGuidee), SettingsMessageTree(I18n::Message::SandraSimmons), SettingsMessageTree(I18n::Message::JoachimLeFournis), SettingsMessageTree(I18n::Message::JeanBaptisteBoric), SettingsMessageTree(I18n::Message::MaximeFriess), SettingsMessageTree(I18n::Message::David), SettingsMessageTree(I18n::Message::DamienNicolet), SettingsMessageTree(I18n::Message::EvannDreumont), SettingsMessageTree(I18n::Message::SzaboLevente), SettingsMessageTree(I18n::Message::VenceslasDuet), SettingsMessageTree(I18n::Message::CharlotteThomas), SettingsMessageTree(I18n::Message::AntoninLoubiere), SettingsMessageTree(I18n::Message::BetaTesters), SettingsMessageTree(I18n::Message::CyprienMejat), SettingsMessageTree(I18n::Message::TimeoArnouts), SettingsMessageTree(I18n::Message::JulieC), SettingsMessageTree(I18n::Message::LelahelHideux), SettingsMessageTree(I18n::Message::Madil), SettingsMessageTree(I18n::Message::HilaireLeRoux)}; -#ifdef OMEGA_USERNAME +constexpr SettingsMessageTree s_contributorsChildren[23] = {SettingsMessageTree(I18n::Message::Developers), SettingsMessageTree(I18n::Message::QuentinGuidee), SettingsMessageTree(I18n::Message::JoachimLeFournis), SettingsMessageTree(I18n::Message::MaximeFriess), SettingsMessageTree(I18n::Message::JeanBaptisteBoric), SettingsMessageTree(I18n::Message::SandraSimmons), SettingsMessageTree(I18n::Message::David), SettingsMessageTree(I18n::Message::DamienNicolet), SettingsMessageTree(I18n::Message::EvannDreumont), SettingsMessageTree(I18n::Message::SzaboLevente), SettingsMessageTree(I18n::Message::VenceslasDuet), SettingsMessageTree(I18n::Message::CharlotteThomas), SettingsMessageTree(I18n::Message::AntoninLoubiere), SettingsMessageTree(I18n::Message::CyprienMejat), SettingsMessageTree(I18n::Message::BetaTesters), SettingsMessageTree(I18n::Message::TimeoArnouts), SettingsMessageTree(I18n::Message::JulieC), SettingsMessageTree(I18n::Message::LelahelHideux), SettingsMessageTree(I18n::Message::Madil), SettingsMessageTree(I18n::Message::HilaireLeRoux), SettingsMessageTree(I18n::Message::HectorNussbaumer), SettingsMessageTree(I18n::Message::RaphaelDyda), SettingsMessageTree(I18n::Message::ThibautC)}; constexpr SettingsMessageTree s_modelAboutChildren[8] = {SettingsMessageTree(I18n::Message::Username), SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::OmegaVersion), SettingsMessageTree(I18n::Message::MicroPythonVersion), SettingsMessageTree(I18n::Message::MemUse), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId), SettingsMessageTree(I18n::Message::Contributors, s_contributorsChildren)}; -#else -constexpr SettingsMessageTree s_modelAboutChildren[7] = {SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::OmegaVersion), SettingsMessageTree(I18n::Message::MicroPythonVersion), SettingsMessageTree(I18n::Message::MemUse), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId), SettingsMessageTree(I18n::Message::Contributors, s_contributorsChildren)}; -#endif MainController::MainController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate) : ViewController(parentResponder), diff --git a/apps/settings/main_controller.h b/apps/settings/main_controller.h index 7ef06c84a67..fd638a0cd9e 100644 --- a/apps/settings/main_controller.h +++ b/apps/settings/main_controller.h @@ -24,12 +24,8 @@ extern const Shared::SettingsMessageTree s_modelMathOptionsChildren[6]; extern const Shared::SettingsMessageTree s_modelFontChildren[2]; extern const Shared::SettingsMessageTree s_modelDateTimeChildren[3]; extern const Shared::SettingsMessageTree s_accessibilityChildren[6]; -extern const Shared::SettingsMessageTree s_contributorsChildren[20]; -#ifdef OMEGA_USERNAME +extern const Shared::SettingsMessageTree s_contributorsChildren[23]; extern const Shared::SettingsMessageTree s_modelAboutChildren[8]; -#else -extern const Shared::SettingsMessageTree s_modelAboutChildren[7]; -#endif extern const Shared::SettingsMessageTree s_model; class MainController : public ViewController, public ListViewDataSource, public SelectableTableViewDataSource { diff --git a/apps/settings/sub_menu/about_controller.cpp b/apps/settings/sub_menu/about_controller.cpp index a295eb02934..e2fe3f5a611 100644 --- a/apps/settings/sub_menu/about_controller.cpp +++ b/apps/settings/sub_menu/about_controller.cpp @@ -29,7 +29,7 @@ AboutController::AboutController(Responder * parentResponder) : } bool AboutController::handleEvent(Ion::Events::Event event) { - I18n::Message childLabel = m_messageTreeModel->childAtIndex(selectedRow())->label(); + I18n::Message childLabel = m_messageTreeModel->childAtIndex(selectedRow()+(!hasUsernameCell()))->label(); /* We hide here the activation hardware test app: in the menu "about", by * clicking on '6' on the last row. */ if ((event == Ion::Events::Six || event == Ion::Events::LowerT || event == Ion::Events::UpperT) && childLabel == I18n::Message::FccId) { @@ -39,8 +39,9 @@ bool AboutController::handleEvent(Ion::Events::Event event) { if (event == Ion::Events::OK || event == Ion::Events::EXE || event == Ion::Events::Right) { if (childLabel == I18n::Message::Contributors) { GenericSubController * subController = &m_contributorsController; - subController->setMessageTreeModel(m_messageTreeModel->childAtIndex(selectedRow())); + subController->setMessageTreeModel(m_messageTreeModel->childAtIndex(selectedRow()+(!hasUsernameCell()))); StackViewController * stack = stackController(); + m_lastSelect = selectedRow(); stack->push(subController); return true; } @@ -96,11 +97,15 @@ bool AboutController::handleEvent(Ion::Events::Event event) { return GenericSubController::handleEvent(event); } +int AboutController::numberOfRows() const { + return m_messageTreeModel->numberOfChildren() - (!hasUsernameCell()); +} + HighlightCell * AboutController::reusableCell(int index, int type) { assert(index >= 0); if (type == 0) { - assert(index < k_totalNumberOfCell-1); - return &m_cells[index]; + assert(index < k_totalNumberOfCell-1-(!hasUsernameCell())); + return &m_cells[index+(!hasUsernameCell())]; } assert(index == 0); return &m_contributorsCell; @@ -113,7 +118,7 @@ int AboutController::typeAtLocation(int i, int j) { int AboutController::reusableCellCount(int type) { switch (type) { case 0: - return k_totalNumberOfCell-1; + return k_totalNumberOfCell-1-(!hasUsernameCell()); case 1: return 1; default: @@ -122,13 +127,18 @@ int AboutController::reusableCellCount(int type) { } } +bool AboutController::hasUsernameCell() const { + return (*Ion::username()) != 0; +} + void AboutController::willDisplayCellForIndex(HighlightCell * cell, int index) { - GenericSubController::willDisplayCellForIndex(cell, index); + int i = index + (!hasUsernameCell()); + GenericSubController::willDisplayCellForIndex(cell, i); assert(index >= 0 && index < k_totalNumberOfCell); - if (m_messageTreeModel->childAtIndex(index)->label() == I18n::Message::Contributors) { + if (m_messageTreeModel->childAtIndex(i)->label() == I18n::Message::Contributors) { MessageTableCellWithChevronAndMessage * myTextCell = (MessageTableCellWithChevronAndMessage *)cell; myTextCell->setSubtitle(I18n::Message::Default); - } else if (m_messageTreeModel->childAtIndex(index)->label() == I18n::Message::MemUse) { + } else if (m_messageTreeModel->childAtIndex(i)->label() == I18n::Message::MemUse) { char memUseBuffer[15]; int len = Poincare::Integer((int)((float) (Ion::Storage::k_storageSize - Ion::Storage::sharedStorage()->availableSize()) / 1024.f)).serialize(memUseBuffer, 4); memUseBuffer[len] = 'k'; @@ -146,17 +156,16 @@ void AboutController::willDisplayCellForIndex(HighlightCell * cell, int index) { MessageTableCellWithBuffer * myCell = (MessageTableCellWithBuffer *)cell; static const char * mpVersion = MICROPY_VERSION_STRING; static const char * messages[] = { -#ifdef OMEGA_USERNAME Ion::username(), -#endif Ion::softwareVersion(), Ion::omegaVersion(), mpVersion, "", Ion::serialNumber(), - Ion::fccId() + Ion::fccId(), + "" }; - myCell->setAccessoryText(messages[index]); + myCell->setAccessoryText(messages[i]); } } diff --git a/apps/settings/sub_menu/about_controller.h b/apps/settings/sub_menu/about_controller.h index e94a6e2aa67..beef15d95cb 100644 --- a/apps/settings/sub_menu/about_controller.h +++ b/apps/settings/sub_menu/about_controller.h @@ -20,12 +20,10 @@ class AboutController : public GenericSubController { int reusableCellCount(int type) override; void willDisplayCellForIndex(HighlightCell * cell, int index) override; int typeAtLocation(int i, int j) override; + int numberOfRows() const override; private: -#ifdef OMEGA_USERNAME constexpr static int k_totalNumberOfCell = 8; -#else - constexpr static int k_totalNumberOfCell = 7; -#endif + bool hasUsernameCell() const; ContributorsController m_contributorsController; MessageTableCellWithChevronAndMessage m_contributorsCell; //SelectableViewWithMessages m_view; diff --git a/apps/settings/sub_menu/contributors_controller.cpp b/apps/settings/sub_menu/contributors_controller.cpp index 19fc88895ee..26bab3326a5 100644 --- a/apps/settings/sub_menu/contributors_controller.cpp +++ b/apps/settings/sub_menu/contributors_controller.cpp @@ -28,13 +28,13 @@ int ContributorsController::reusableCellCount(int type) { return k_totalNumberOfCell; } -constexpr static int s_numberOfDevelopers = 12; +constexpr static int s_numberOfDevelopers = 13; constexpr static I18n::Message s_developersUsernames[s_numberOfDevelopers] = { I18n::Message::PQuentinGuidee, - I18n::Message::PSandraSimmons, I18n::Message::PJoachimLeFournis, - I18n::Message::PJeanBaptisteBoric, I18n::Message::PMaximeFriess, + I18n::Message::PJeanBaptisteBoric, + I18n::Message::PSandraSimmons, I18n::Message::PDavid, I18n::Message::PDamienNicolet, I18n::Message::PEvannDreumont, @@ -42,16 +42,19 @@ constexpr static I18n::Message s_developersUsernames[s_numberOfDevelopers] = { I18n::Message::PVenceslasDuet, I18n::Message::PCharlotteThomas, I18n::Message::PAntoninLoubiere, + I18n::Message::PCyprienMejat, }; -constexpr static int s_numberOfBetaTesters = 6; +constexpr static int s_numberOfBetaTesters = 8; constexpr static I18n::Message s_betaTestersUsernames[s_numberOfBetaTesters] = { - I18n::Message::PCyprienMejat, I18n::Message::PTimeoArnouts, I18n::Message::PJulieC, I18n::Message::PLelahelHideux, I18n::Message::PMadil, I18n::Message::PHilaireLeRoux, + I18n::Message::PHectorNussbaumer, + I18n::Message::PRaphaelDyda, + I18n::Message::PThibautC, }; void ContributorsController::willDisplayCellForIndex(HighlightCell * cell, int index) { diff --git a/apps/settings/sub_menu/generic_sub_controller.h b/apps/settings/sub_menu/generic_sub_controller.h index c149a250857..d48336d9fe5 100644 --- a/apps/settings/sub_menu/generic_sub_controller.h +++ b/apps/settings/sub_menu/generic_sub_controller.h @@ -23,8 +23,9 @@ class GenericSubController : public ViewController, public ListViewDataSource, p void setMessageTreeModel(const MessageTree * messageTreeModel); void viewDidDisappear() override; protected: + int m_lastSelect = 0; StackViewController * stackController() const; - virtual int initialSelectedRow() const { return 0; } + virtual int initialSelectedRow() const { return m_lastSelect; } constexpr static KDCoordinate k_topBottomMargin = 13; SelectableTableView m_selectableTableView; MessageTree * m_messageTreeModel; diff --git a/apps/settings/sub_menu/math_options_controller.cpp b/apps/settings/sub_menu/math_options_controller.cpp index b1a239506f3..50566ba60ff 100644 --- a/apps/settings/sub_menu/math_options_controller.cpp +++ b/apps/settings/sub_menu/math_options_controller.cpp @@ -25,6 +25,7 @@ bool MathOptionsController::handleEvent(Ion::Events::Event event) { subController = &m_preferencesController; subController->setMessageTreeModel(m_messageTreeModel->childAtIndex(selectedRow())); StackViewController * stack = stackController(); + m_lastSelect = selectedRow(); stack->push(subController); return true; } diff --git a/apps/shared.universal.i18n b/apps/shared.universal.i18n index 97c75c00e60..fb927a65962 100644 --- a/apps/shared.universal.i18n +++ b/apps/shared.universal.i18n @@ -343,7 +343,7 @@ CyprienMejat = "Cyprien Méjat" PCyprienMejat = "@A2drien" TimeoArnouts = "Timéo Arnouts" PTimeoArnouts = "@Dogm" -JulieC = "Julie C" +JulieC = "Julie C." PJulieC = "@windows9x95" LelahelHideux = "Lélahel Hideux" PLelahelHideux = "@Lelahelry" @@ -351,6 +351,12 @@ Madil = "Madil" PMadil = "@le-grand-mannitout" HilaireLeRoux = "Hilaire Le Roux" PHilaireLeRoux = "@0Babass2" +HectorNussbaumer = "Hector Nussbaumer" +PHectorNussbaumer = "@Sycorax" +RaphaelDyda = "Raphaël Dyda" +PRaphaelDyda = "@Trixciel" +ThibautC = "Thibaut C." +PThibautC = "@Tibo_C" SpeedOfLight = "2.99792458·10^8_m_s^-1" YearLight = "9.461·10^15_m" Boltzmann = "1.380649·10^-23_J_K^-1" diff --git a/build/config.mak b/build/config.mak index a45c7d936dc..444542c7198 100644 --- a/build/config.mak +++ b/build/config.mak @@ -5,11 +5,11 @@ DEBUG ?= 0 HOME_DISPLAY_EXTERNALS ?= 1 EPSILON_VERSION ?= 15.3.1 -OMEGA_VERSION ?= 1.21.0 +OMEGA_VERSION ?= 1.22.0 # OMEGA_USERNAME ?= N/A OMEGA_STATE ?= public -EPSILON_APPS ?= calculation rpn graph code statistics probability solver atom sequence regression settings external -SUBMODULES_APPS = atom rpn +EPSILON_APPS ?= calculation rpn graph code statistics probability solver atomic sequence regression settings external +SUBMODULES_APPS = atomic rpn EPSILON_I18N ?= en fr nl pt it de es hu EPSILON_COUNTRIES ?= WW CA DE ES FR GB IT NL PT US EPSILON_GETOPT ?= 0 diff --git a/build/device/dfu.py b/build/device/dfu.py index bcb566b6331..bac05e3e5d7 100644 --- a/build/device/dfu.py +++ b/build/device/dfu.py @@ -4,6 +4,8 @@ # This work is licensed under the MIT license, see the file LICENSE for # details. +# This script has been modified by NumWorks contributors + """This module implements enough functionality to program the STM32F4xx over DFU, without requiring dfu-util. See app note AN3156 for a description of the DFU protocol. diff --git a/build/device/usb/__init__.py b/build/device/usb/__init__.py old mode 100755 new mode 100644 index 6d510457722..13c2fbf3220 --- a/build/device/usb/__init__.py +++ b/build/device/usb/__init__.py @@ -1,17 +1,32 @@ -# Copyright (C) 2009-2017 Wander Lairson Costa -# Copyright (C) 2017-2018 Robert Wlodarczyk +# Copyright 2009-2017 Wander Lairson Costa +# Copyright 2009-2021 PyUSB contributors # -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: # -# http://www.apache.org/licenses/LICENSE-2.0 +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. # -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. r"""PyUSB - Easy USB access in Python @@ -33,8 +48,19 @@ __author__ = 'Wander Lairson Costa' # Use Semantic Versioning, http://semver.org/ -version_info = (1, 0, 2) -__version__ = '%d.%d.%d' % version_info +try: + from usb._version import version as __version__ +except ImportError: + __version__ = '0.0.0' + +def _get_extended_version_info(version): + import re + m = re.match(r'(\d+)\.(\d+)\.(\d+)[.-]?(.*)', version) + major, minor, patch, suffix = m.groups() + return int(major), int(minor), int(patch), suffix + +extended_version_info = _get_extended_version_info(__version__) +version_info = extended_version_info[:3] __all__ = ['legacy', 'control', 'core', 'backend', 'util', 'libloader'] diff --git a/build/device/usb/_debug.py b/build/device/usb/_debug.py old mode 100755 new mode 100644 index 8c2a2b1aa21..a4ca7e82e4a --- a/build/device/usb/_debug.py +++ b/build/device/usb/_debug.py @@ -1,17 +1,32 @@ -# Copyright (C) 2009-2017 Wander Lairson Costa -# Copyright (C) 2017-2018 Robert Wlodarczyk +# Copyright 2009-2017 Wander Lairson Costa +# Copyright 2009-2021 PyUSB contributors # -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: # -# http://www.apache.org/licenses/LICENSE-2.0 +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. # -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. __author__ = 'Wander Lairson Costa' diff --git a/build/device/usb/_interop.py b/build/device/usb/_interop.py old mode 100755 new mode 100644 index 96b019365bf..5729f910eda --- a/build/device/usb/_interop.py +++ b/build/device/usb/_interop.py @@ -1,17 +1,32 @@ -# Copyright (C) 2009-2017 Wander Lairson Costa -# Copyright (C) 2017-2018 Robert Wlodarczyk +# Copyright 2009-2017 Wander Lairson Costa +# Copyright 2009-2021 PyUSB contributors # -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: # -# http://www.apache.org/licenses/LICENSE-2.0 +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. # -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # All the hacks necessary to assure compatibility across all # supported versions come here. @@ -81,5 +96,5 @@ def as_array(data=None): # When you pass a unicode string or a character sequence, # you get a TypeError if the first parameter does not match a = array.array('B') - a.fromstring(data) # deprecated since 3.2 + a.frombytes(data.encode('utf-8')) return a diff --git a/build/device/usb/_lookup.py b/build/device/usb/_lookup.py old mode 100755 new mode 100644 index 82170b744da..68695de0e13 --- a/build/device/usb/_lookup.py +++ b/build/device/usb/_lookup.py @@ -1,17 +1,32 @@ -# Copyright (C) 2009-2017 Wander Lairson Costa -# Copyright (C) 2017-2018 Robert Wlodarczyk +# Copyright 2009-2017 Wander Lairson Costa +# Copyright 2009-2021 PyUSB contributors # -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: # -# http://www.apache.org/licenses/LICENSE-2.0 +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. # -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. r"""usb._lookups - Lookup tables for USB """ diff --git a/build/device/usb/_objfinalizer.py b/build/device/usb/_objfinalizer.py old mode 100755 new mode 100644 index ad873607400..dededa85381 --- a/build/device/usb/_objfinalizer.py +++ b/build/device/usb/_objfinalizer.py @@ -1,19 +1,34 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2009-2017 Wander Lairson Costa -# Copyright (C) 2017-2018 Robert Wlodarczyk +# Copyright 2009-2017 Wander Lairson Costa +# Copyright 2009-2021 PyUSB contributors # -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: # -# http://www.apache.org/licenses/LICENSE-2.0 +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. # -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import sys diff --git a/build/device/usb/backend/__init__.py b/build/device/usb/backend/__init__.py old mode 100755 new mode 100644 index 2ff11806928..f28e4940f6a --- a/build/device/usb/backend/__init__.py +++ b/build/device/usb/backend/__init__.py @@ -1,17 +1,32 @@ -# Copyright (C) 2009-2017 Wander Lairson Costa -# Copyright (C) 2017-2018 Robert Wlodarczyk +# Copyright 2009-2017 Wander Lairson Costa +# Copyright 2009-2021 PyUSB contributors # -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: # -# http://www.apache.org/licenses/LICENSE-2.0 +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. # -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. r"""usb.backend - Backend interface. @@ -62,7 +77,7 @@ def get_backend(): __author__ = 'Wander Lairson Costa' -__all__ = ['IBackend', 'libusb01', 'libusb10', 'openusb'] +__all__ = ['IBackend', 'libusb0', 'libusb1', 'openusb'] def _not_implemented(func): raise NotImplementedError(func.__name__) @@ -196,7 +211,7 @@ def set_interface_altsetting(self, dev_handle, intf, altsetting): This method should only be called when the interface has more than one alternate setting. The dev_handle is the value returned by the - open_device() method. intf and altsetting are respectivelly the + open_device() method. intf and altsetting are respectively the bInterfaceNumber and bAlternateSetting fields of the related interface. """ _not_implemented(self.set_interface_altsetting) @@ -268,7 +283,7 @@ def intr_write(self, dev_handle, ep, intf, data, timeout): _not_implemented(self.intr_write) def intr_read(self, dev_handle, ep, intf, size, timeout): - r"""Perform an interrut read. + r"""Perform an interrupt read. dev_handle is the value returned by the open_device() method. The ep parameter is the bEndpointAddress field whose endpoint diff --git a/build/device/usb/backend/libusb0.py b/build/device/usb/backend/libusb0.py old mode 100755 new mode 100644 index ff04475f5ec..c2183af8ddd --- a/build/device/usb/backend/libusb0.py +++ b/build/device/usb/backend/libusb0.py @@ -1,24 +1,40 @@ -# Copyright (C) 2009-2017 Wander Lairson Costa -# Copyright (C) 2017-2018 Robert Wlodarczyk +# Copyright 2009-2017 Wander Lairson Costa +# Copyright 2009-2021 PyUSB contributors # -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: # -# http://www.apache.org/licenses/LICENSE-2.0 +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. # -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from ctypes import * +import errno import os import usb.backend import usb.util import sys -from usb.core import USBError +from usb.core import USBError, USBTimeoutError from usb._debug import methodtrace import usb._interop as _interop import logging @@ -30,6 +46,8 @@ _logger = logging.getLogger('usb.backend.libusb0') +_USBFS_MAXDRIVERNAME = 255 + # usb.h if sys.platform.find('bsd') != -1 or sys.platform.find('mac') != -1 or \ @@ -350,6 +368,14 @@ def _setup_prototypes(lib): # linux only + # int usb_get_driver_np(usb_dev_handle *dev, + # int interface, + # char *name, + # unsigned int namelen); + if hasattr(lib, 'usb_get_driver_np'): + lib.usb_get_driver_np.argtypes = \ + [_usb_dev_handle, c_int, c_char_p, c_uint] + # int usb_detach_kernel_driver_np(usb_dev_handle *dev, int interface); if hasattr(lib, 'usb_detach_kernel_driver_np'): lib.usb_detach_kernel_driver_np.argtypes = [_usb_dev_handle, c_int] @@ -415,6 +441,9 @@ def _check(ret): errmsg = os.strerror(-ret) else: return ret + + if ret is not None and -ret == errno.ETIMEDOUT: + raise USBTimeoutError(errmsg, ret, -ret) raise USBError(errmsg, ret) def _has_iso_transfer(): @@ -588,8 +617,35 @@ def clear_halt(self, dev_handle, ep): def reset_device(self, dev_handle): _check(_lib.usb_reset(dev_handle)) + @methodtrace(_logger) + def is_kernel_driver_active(self, dev_handle, intf): + if not hasattr(_lib, 'usb_get_driver_np'): + raise NotImplementedError(self.is_kernel_driver_active.__name__) + from errno import ENODATA + buf = usb.util.create_buffer(_USBFS_MAXDRIVERNAME + 1) + name, length = buf.buffer_info() + length *= buf.itemsize + # based on the implementation of libusb_kernel_driver_active + # (see libusb/os/linux_usbfs.c @@ op_kernel_driver_active): + # usb_get_driver_np fails with ENODATA when no kernel driver is bound, + # and if 'usbfs' is bound that means that a userspace program is + # controlling the device (e.g. using this very library) + try: + _check(_lib.usb_get_driver_np( + dev_handle, + intf, + cast(name, c_char_p), + length)) + return cast(name, c_char_p).value != b'usbfs' + except USBError as err: + if err.backend_error_code == -ENODATA: + return False + raise err + @methodtrace(_logger) def detach_kernel_driver(self, dev_handle, intf): + if not hasattr(_lib, 'usb_detach_kernel_driver_np'): + raise NotImplementedError(self.detach_kernel_driver.__name__) _check(_lib.usb_detach_kernel_driver_np(dev_handle, intf)) def __write(self, fn, dev_handle, ep, intf, data, timeout): diff --git a/build/device/usb/backend/libusb1.py b/build/device/usb/backend/libusb1.py old mode 100755 new mode 100644 index de30c256a7a..6615d68b780 --- a/build/device/usb/backend/libusb1.py +++ b/build/device/usb/backend/libusb1.py @@ -1,17 +1,32 @@ -# Copyright (C) 2009-2017 Wander Lairson Costa -# Copyright (C) 2017-2018 Robert Wlodarczyk +# Copyright 2009-2017 Wander Lairson Costa +# Copyright 2009-2021 PyUSB contributors # -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: # -# http://www.apache.org/licenses/LICENSE-2.0 +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. # -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from ctypes import * import usb.util @@ -22,14 +37,14 @@ import usb._objfinalizer as _objfinalizer import errno import math -from usb.core import USBError +from usb.core import USBError, USBTimeoutError import usb.libloader __author__ = 'Wander Lairson Costa' __all__ = [ 'get_backend', - 'LIBUSB_SUCESS', + 'LIBUSB_SUCCESS', 'LIBUSB_ERROR_IO', 'LIBUSB_ERROR_INVALID_PARAM', 'LIBUSB_ERROR_ACCESS', @@ -42,14 +57,14 @@ 'LIBUSB_ERROR_INTERRUPTED', 'LIBUSB_ERROR_NO_MEM', 'LIBUSB_ERROR_NOT_SUPPORTED', - 'LIBUSB_ERROR_OTHER' + 'LIBUSB_ERROR_OTHER', 'LIBUSB_TRANSFER_COMPLETED', 'LIBUSB_TRANSFER_ERROR', 'LIBUSB_TRANSFER_TIMED_OUT', 'LIBUSB_TRANSFER_CANCELLED', 'LIBUSB_TRANSFER_STALL', 'LIBUSB_TRANSFER_NO_DEVICE', - 'LIBUSB_TRANSFER_OVERFLOW' + 'LIBUSB_TRANSFER_OVERFLOW', ] _logger = logging.getLogger('usb.backend.libusb1') @@ -256,6 +271,7 @@ def _get_iso_packet_list(transfer): return list_type.from_address(addressof(transfer.iso_packet_desc)) _lib = None +_lib_object = None def _load_library(find_library=None): # Windows backend uses stdcall calling convention @@ -582,6 +598,8 @@ def _check(ret): if ret < 0: if ret == LIBUSB_ERROR_NOT_SUPPORTED: raise NotImplementedError(_strerror(ret)) + elif ret == LIBUSB_ERROR_TIMEOUT: + raise USBTimeoutError(_strerror(ret), ret, _libusb_errno[ret]) else: raise USBError(_strerror(ret), ret, _libusb_errno[ret]) @@ -700,7 +718,8 @@ def __init__(self, lib): @methodtrace(_logger) def _finalize_object(self): - self.lib.libusb_exit(self.ctx) + if self.ctx: + self.lib.libusb_exit(self.ctx) @methodtrace(_logger) @@ -936,12 +955,13 @@ def __read(self, fn, dev_handle, ep, intf, buff, timeout): return transferred.value def get_backend(find_library=None): - global _lib + global _lib, _lib_object try: - if _lib is None: + if _lib_object is None: _lib = _load_library(find_library=find_library) _setup_prototypes(_lib) - return _LibUSB(_lib) + _lib_object = _LibUSB(_lib) + return _lib_object except usb.libloader.LibraryException: # exception already logged (if any) _logger.error('Error loading libusb 1.0 backend', exc_info=False) diff --git a/build/device/usb/backend/openusb.py b/build/device/usb/backend/openusb.py old mode 100755 new mode 100644 index 55e75c9941b..11e419ac958 --- a/build/device/usb/backend/openusb.py +++ b/build/device/usb/backend/openusb.py @@ -1,17 +1,32 @@ -# Copyright (C) 2009-2017 Wander Lairson Costa -# Copyright (C) 2017-2018 Robert Wlodarczyk +# Copyright 2009-2017 Wander Lairson Costa +# Copyright 2009-2021 PyUSB contributors # -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: # -# http://www.apache.org/licenses/LICENSE-2.0 +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. # -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from ctypes import * import ctypes.util @@ -24,7 +39,7 @@ import usb._objfinalizer as _objfinalizer import usb.util as util import usb.libloader -from usb.core import USBError +from usb.core import USBError, USBTimeoutError __author__ = 'Wander Lairson Costa' @@ -458,7 +473,7 @@ def _setup_prototypes(lib): POINTER(_openusb_intr_request) ] - lib.openusb_bulk_xfer.restype = c_int32 + lib.openusb_intr_xfer.restype = c_int32 # int32_t openusb_bulk_xfer(openusb_dev_handle_t dev, # uint8_t ifc, @@ -491,7 +506,11 @@ def _check(ret): ret = ret.value if ret != 0: - raise USBError(_lib.openusb_strerror(ret), ret, _openusb_errno[ret]) + if ret == OPENUSB_IO_TIMEOUT: + raise USBTimeoutError(_lib.openusb_strerror(ret), ret, _openusb_errno[ret]) + else: + raise USBError(_lib.openusb_strerror(ret), ret, _openusb_errno[ret]) + return ret class _Context(_objfinalizer.AutoFinalizedObject): @@ -726,6 +745,7 @@ def get_backend(find_library=None): _lib = _load_library(find_library) _setup_prototypes(_lib) _ctx = _Context() + _logger.warning('OpenUSB backend deprecated (https://github.com/pyusb/pyusb/issues/284)') return _OpenUSB() except usb.libloader.LibraryException: # exception already logged (if any) diff --git a/build/device/usb/control.py b/build/device/usb/control.py old mode 100755 new mode 100644 index 53b18826d2f..f46ced1bfa3 --- a/build/device/usb/control.py +++ b/build/device/usb/control.py @@ -1,17 +1,32 @@ -# Copyright (C) 2009-2017 Wander Lairson Costa -# Copyright (C) 2017-2018 Robert Wlodarczyk +# Copyright 2009-2017 Wander Lairson Costa +# Copyright 2009-2021 PyUSB contributors # -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: # -# http://www.apache.org/licenses/LICENSE-2.0 +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. # -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. r"""usb.control - USB standard control requests @@ -152,13 +167,18 @@ def get_descriptor(dev, desc_size, desc_type, desc_index, wIndex = 0): util.CTRL_TYPE_STANDARD, util.CTRL_RECIPIENT_DEVICE) - return dev.ctrl_transfer( + desc = dev.ctrl_transfer( bmRequestType = bmRequestType, bRequest = 0x06, wValue = wValue, wIndex = wIndex, data_or_wLength = desc_size) + if len(desc) < 2: + raise USBError('Invalid descriptor') + + return desc + def set_descriptor(dev, desc, desc_type, desc_index, wIndex = None): r"""Update an existing descriptor or add a new one. diff --git a/build/device/usb/core.py b/build/device/usb/core.py old mode 100755 new mode 100644 index 39685fe1bb1..7546de2bc2e --- a/build/device/usb/core.py +++ b/build/device/usb/core.py @@ -1,17 +1,32 @@ -# Copyright (C) 2009-2017 Wander Lairson Costa -# Copyright (C) 2017-2018 Robert Wlodarczyk +# Copyright 2009-2017 Wander Lairson Costa +# Copyright 2009-2021 PyUSB contributors # -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: # -# http://www.apache.org/licenses/LICENSE-2.0 +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. # -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. r"""usb.core - Core USB features. @@ -27,8 +42,8 @@ __author__ = 'Wander Lairson Costa' -__all__ = [ 'Device', 'Configuration', 'Interface', 'Endpoint', 'find', - 'show_devices' ] +__all__ = [ 'Device', 'Configuration', 'Interface', 'Endpoint', 'USBError', + 'USBTimeoutError', 'NoBackendError', 'find', 'show_devices' ] import usb.util as util import copy @@ -45,10 +60,19 @@ _DEFAULT_TIMEOUT = 1000 +_sentinel = object() + def _set_attr(input, output, fields): for f in fields: setattr(output, f, getattr(input, f)) +def _try_getattr(object, name): + try: + attr = getattr(object, name) + except : + attr = _sentinel + return attr + def _try_get_string(dev, index, langid = None, default_str_i0 = "", default_access_error = "Error Accessing String"): """ try to get a string, but return a string no matter what @@ -182,6 +206,8 @@ def managed_set_interface(self, device, intf, alt): i = util.find_descriptor(cfg, bInterfaceNumber=intf, bAlternateSetting=alt) else: i = util.find_descriptor(cfg, bInterfaceNumber=intf) + if i is None: + raise ValueError('No matching interface (' + str(intf) + ',' + str(alt) + ')') self.managed_claim_interface(device, i) @@ -270,6 +296,14 @@ def __init__(self, strerror, error_code = None, errno = None): IOError.__init__(self, errno, strerror) self.backend_error_code = error_code +class USBTimeoutError(USBError): + r"""Exception class for connection timeout errors. + + Backends must raise this exception when a call on a USB connection returns + a timeout error code. + """ + pass + class NoBackendError(ValueError): r"Exception class when a valid backend is not found." pass @@ -1247,7 +1281,7 @@ def is_printer(dev): def device_iter(**kwargs): for dev in backend.enumerate_devices(): d = Device(dev, backend) - tests = (val == getattr(d, key) for key, val in kwargs.items()) + tests = (val == _try_getattr(d, key) for key, val in kwargs.items()) if _interop._all(tests) and (custom_match is None or custom_match(d)): yield d diff --git a/build/device/usb/legacy.py b/build/device/usb/legacy.py old mode 100755 new mode 100644 index ae84ae1b0de..67d1d175d51 --- a/build/device/usb/legacy.py +++ b/build/device/usb/legacy.py @@ -1,17 +1,32 @@ -# Copyright (C) 2009-2017 Wander Lairson Costa -# Copyright (C) 2017-2018 Robert Wlodarczyk +# Copyright 2009-2017 Wander Lairson Costa +# Copyright 2009-2021 PyUSB contributors # -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: # -# http://www.apache.org/licenses/LICENSE-2.0 +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. # -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import usb.core as core import usb.util as util diff --git a/build/device/usb/libloader.py b/build/device/usb/libloader.py old mode 100755 new mode 100644 index 07fa85a9dae..b4bea55df61 --- a/build/device/usb/libloader.py +++ b/build/device/usb/libloader.py @@ -1,19 +1,34 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2009-2017 Wander Lairson Costa -# Copyright (C) 2017-2018 Robert Wlodarczyk +# Copyright 2009-2017 Wander Lairson Costa +# Copyright 2009-2021 PyUSB contributors # -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: # -# http://www.apache.org/licenses/LICENSE-2.0 +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. # -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import ctypes import ctypes.util diff --git a/build/device/usb/util.py b/build/device/usb/util.py old mode 100755 new mode 100644 index ff9ec81e0c6..0f3967efbd2 --- a/build/device/usb/util.py +++ b/build/device/usb/util.py @@ -1,17 +1,32 @@ -# Copyright (C) 2009-2017 Wander Lairson Costa -# Copyright (C) 2017-2018 Robert Wlodarczyk +# Copyright 2009-2017 Wander Lairson Costa +# Copyright 2009-2021 PyUSB contributors # -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: # -# http://www.apache.org/licenses/LICENSE-2.0 +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. # -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. r"""usb.util - Utility functions. @@ -286,32 +301,28 @@ def get_string(dev, index, langid = None): The return value is the unicode string present in the descriptor, or None if the requested index was zero. - - It is a ValueError to request a real string (index not zero), if: the - device's langid tuple is empty, or with an explicit langid the device does - not support. """ if 0 == index: return None from usb.control import get_descriptor - langids = dev.langids - if 0 == len(langids): - raise ValueError("The device has no langid") if langid is None: + langids = dev.langids + if 0 == len(langids): + raise ValueError("The device has no langid" + " (permission issue, no string descriptors supported or device error)") langid = langids[0] - elif langid not in langids: - raise ValueError("The device does not support the specified langid") buf = get_descriptor( dev, - 255, # Maximum descriptor size + 254, # maximum even length DESC_TYPE_STRING, index, langid ) + blen = buf[0] & 0xfe # should be even, ignore any trailing byte (see #154) if hexversion >= 0x03020000: - return buf[2:buf[0]].tobytes().decode('utf-16-le') + return buf[2:blen].tobytes().decode('utf-16-le') else: - return buf[2:buf[0]].tostring().decode('utf-16-le') + return buf[2:blen].tostring().decode('utf-16-le') diff --git a/build/targets.simulator.windows.mak b/build/targets.simulator.windows.mak index eef0ca30ea3..c0aa03b8f48 100644 --- a/build/targets.simulator.windows.mak +++ b/build/targets.simulator.windows.mak @@ -1,4 +1,4 @@ PHONY: %_run -t %_run: $(BUILD_DIR)/%.$(EXE) +%_run: $(BUILD_DIR)/%.$(EXE) $(call rule_label,EXE) $(Q) ./$^ diff --git a/escher/image/inliner.c b/escher/image/inliner.c index 289fec639a0..c2e9d489448 100644 --- a/escher/image/inliner.c +++ b/escher/image/inliner.c @@ -104,6 +104,12 @@ int main(int argc, char * argv[]) { FILE * implementation = fopen(implementationPath, "w"); generateImplementationFromImage(implementation, lowerSnakeCaseName, camelCaseName, width, height, colorType, rowPointers); fclose(implementation); + + for (int i=0; i(SDL_AndroidGetJNIEnv()); jobject activity = static_cast(SDL_AndroidGetActivity()); - jclass j_class = env->FindClass("com/numworks/calculator/EpsilonActivity"); + jclass j_class = env->FindClass("io/github/omega/simulator/OmegaActivity"); jmethodID j_methodId = env->GetMethodID(j_class,"hapticFeedbackIsEnabled", "()Z"); return env->CallObjectMethod(activity, j_methodId); diff --git a/ion/src/simulator/shared/clipboard.cpp b/ion/src/simulator/shared/clipboard.cpp index 896def716db..9c3303691e3 100644 --- a/ion/src/simulator/shared/clipboard.cpp +++ b/ion/src/simulator/shared/clipboard.cpp @@ -25,6 +25,14 @@ const char * read() { return nullptr; } + char * cursor = &buffer[0]; + while(*cursor) { + if(*cursor == '\r' && *(cursor + 1) == '\n') { + memmove(cursor, cursor + 1, strlen(cursor)); + } + cursor++; + } + /* If version has not changed, the user has not copied any text since the * last call to write. A copy of the text already exists in * Escher::Clipboard, and has been translated to best suit the current app : diff --git a/poincare/Makefile b/poincare/Makefile index 45d66bdc971..eca0b7ed8d8 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -12,6 +12,7 @@ poincare_src += $(addprefix poincare/src/,\ grid_layout.cpp \ horizontal_layout.cpp \ integral_layout.cpp \ + kmat.cpp \ layout_cursor.cpp \ layout.cpp \ layout_node.cpp \ diff --git a/poincare/include/poincare/expression_node.h b/poincare/include/poincare/expression_node.h index 305c0099e4d..5a5dbccb241 100644 --- a/poincare/include/poincare/expression_node.h +++ b/poincare/include/poincare/expression_node.h @@ -79,6 +79,7 @@ class ExpressionNode : public TreeNode { Integral, InvBinom, InvNorm, + KMat, LeastCommonMultiple, Logarithm, MatrixTrace, diff --git a/poincare/include/poincare/kmat.h b/poincare/include/poincare/kmat.h new file mode 100644 index 00000000000..d0e5df23a9a --- /dev/null +++ b/poincare/include/poincare/kmat.h @@ -0,0 +1,57 @@ +#ifndef POINCARE_KMAT_H +#define POINCARE_KMAT_H + +#include +#include + +namespace Poincare { + +class KMatNode final : public ExpressionNode { +public: + + // TreeNode + size_t size() const override { return sizeof(KMatNode); } + int numberOfChildren() const override; +#if POINCARE_TREE_LOG + void logNodeName(std::ostream & stream) const override { + stream << "KMat"; + } +#endif + + // Properties + Type type() const override { return Type::KMat; } + +private: + // Layout + Layout createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; + int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override; + + // Simplification + Expression shallowReduce(ReductionContext reductionContext) override; + LayoutShape leftLayoutShape() const override { return LayoutShape::MoreLetters; }; + LayoutShape rightLayoutShape() const override { return LayoutShape::BoundaryPunctuation; } + + // Evaluation + Evaluation approximate(SinglePrecision p, ApproximationContext approximationContext) const override { return templatedApproximate(approximationContext); } + Evaluation approximate(DoublePrecision p, ApproximationContext approximationContext) const override { return templatedApproximate(approximationContext); } + template + Evaluation templatedApproximate(ApproximationContext approximationContext) const { + return Complex::Undefined(); + } +}; + +class KMat final : public Expression { +public: + KMat(const KMatNode * n) : Expression(n) {} + static KMat Builder(Expression child0, Expression child1, Expression child2) { return TreeHandle::FixedArityBuilder({child0, child1, child2}); } + + + static constexpr Expression::FunctionHelper s_functionHelper = Expression::FunctionHelper("kmat", 3, &UntypedBuilderThreeChildren); + + Expression shallowReduce(ExpressionNode::ReductionContext reductionContext); + +}; + +} + +#endif diff --git a/poincare/include/poincare_nodes.h b/poincare/include/poincare_nodes.h index c0d3a853e15..a3f8499953b 100644 --- a/poincare/include/poincare_nodes.h +++ b/poincare/include/poincare_nodes.h @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include diff --git a/poincare/src/kmat.cpp b/poincare/src/kmat.cpp new file mode 100644 index 00000000000..45a7a891c34 --- /dev/null +++ b/poincare/src/kmat.cpp @@ -0,0 +1,70 @@ +#include +#include +#include +#include +#include +#include "parsing/token.h" +#include +#include +#include +#include +#include +#include +#include + +namespace Poincare { + +constexpr Expression::FunctionHelper KMat::s_functionHelper; + +int KMatNode::numberOfChildren() const { return KMat::s_functionHelper.numberOfChildren(); } + +Layout KMatNode::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return LayoutHelper::Prefix(KMat(this), floatDisplayMode, numberOfSignificantDigits, KMat::s_functionHelper.name()); +} + +int KMatNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const { + return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, KMat::s_functionHelper.name()); +} + +Expression KMatNode::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + return KMat(this).shallowReduce(reductionContext); +} + +Expression KMat::shallowReduce(ExpressionNode::ReductionContext reductionContext) { + Expression c0 = childAtIndex(0); + Expression c1 = childAtIndex(1); + if (c0.type() == ExpressionNode::Type::Rational) { + Rational r0 = static_cast(c0); + if (!r0.isInteger() || r0.signedIntegerNumerator().isNegative()) { + return replaceWithUndefinedInPlace(); + } + } + if (c1.type() == ExpressionNode::Type::Rational) { + Rational r1 = static_cast(c1); + if (!r1.isInteger() || r1.signedIntegerNumerator().isNegative()) { + return replaceWithUndefinedInPlace(); + } + } + if (c0.type() != ExpressionNode::Type::Rational || c1.type() != ExpressionNode::Type::Rational) { + return *this; + } + + Rational r0 = static_cast(c0); + Rational r1 = static_cast(c1); + + Integer w = r0.signedIntegerNumerator(); + Integer h = r1.signedIntegerNumerator(); + uint32_t size = *Integer::Multiplication(w,h).digits(); + Matrix matrix = Matrix::Builder(); + matrix.addChildAtIndexInPlace(childAtIndex(2).clone(), 0, 0); + for (uint32_t i = 1; i < size; i++) { + matrix.addChildAtIndexInPlace(childAtIndex(2).clone(), matrix.numberOfChildren(), matrix.numberOfChildren()); + } + matrix.setDimensions(*w.digits(), *h.digits()); + replaceWithInPlace(matrix); + return std::move(matrix); +} + + + +} diff --git a/poincare/src/parsing/parser.cpp b/poincare/src/parsing/parser.cpp index 135082316ba..55090711e25 100644 --- a/poincare/src/parsing/parser.cpp +++ b/poincare/src/parsing/parser.cpp @@ -71,7 +71,8 @@ Expression Parser::parseUntil(Token::Type stoppingType) { &Parser::parseTimes, // Token::Times &Parser::parseSlash, // Token::Slash &Parser::parseImplicitTimes, // Token::ImplicitTimes - &Parser::parseCaret, // Token::Power + &Parser::parseCaret, // Token::Power, + &Parser::parseSingleQuote, // Token::SingleQuote &Parser::parseBang, // Token::Bang &Parser::parseCaretWithParenthesis, // Token::CaretWithParenthesis &Parser::parseMatrix, // Token::LeftBracket @@ -333,6 +334,15 @@ void Parser::parseLeftSystemParenthesis(Expression & leftHandSide, Token::Type s defaultParseLeftParenthesis(true, leftHandSide, stoppingType); } +void Parser::parseSingleQuote(Expression & leftHandSide, Token::Type stoppingType) { + if (leftHandSide.isUninitialized()) { + m_status = Status::Error; // Left-hand side missing + } else { + leftHandSide = Derivative::Builder(leftHandSide, Symbol::Builder('x'), Symbol::Builder('x')); + } + isThereImplicitMultiplication(); +} + void Parser::parseBang(Expression & leftHandSide, Token::Type stoppingType) { if (leftHandSide.isUninitialized()) { m_status = Status::Error; // Left-hand side missing diff --git a/poincare/src/parsing/parser.h b/poincare/src/parsing/parser.h index e6fe72f5883..f68a6a9a5f8 100644 --- a/poincare/src/parsing/parser.h +++ b/poincare/src/parsing/parser.h @@ -56,6 +56,7 @@ class Parser { void parseMatrix(Expression & leftHandSide, Token::Type stoppingType = (Token::Type)0); void parseLeftParenthesis(Expression & leftHandSide, Token::Type stoppingType = (Token::Type)0); void parseLeftSystemParenthesis(Expression & leftHandSide, Token::Type stoppingType = (Token::Type)0); + void parseSingleQuote(Expression & leftHandSide, Token::Type stoppingType = (Token::Type)0); void parseBang(Expression & leftHandSide, Token::Type stoppingType = (Token::Type)0); void parsePlus(Expression & leftHandSide, Token::Type stoppingType = (Token::Type)0); void parseMinus(Expression & leftHandSide, Token::Type stoppingType = (Token::Type)0); @@ -125,6 +126,7 @@ class Parser { &InvBinom::s_functionHelper, &MatrixInverse::s_functionHelper, &InvNorm::s_functionHelper, + &KMat::s_functionHelper, &LeastCommonMultiple::s_functionHelper, &NaperianLogarithm::s_functionHelper, &CommonLogarithm::s_functionHelper, diff --git a/poincare/src/parsing/token.h b/poincare/src/parsing/token.h index 93273004187..162c12cd8f3 100644 --- a/poincare/src/parsing/token.h +++ b/poincare/src/parsing/token.h @@ -39,6 +39,7 @@ class Token { * the ImplicitTimes Token Type is defined here with the desired precedence, * in order to allow the Parser to insert such Tokens where needed. */ Caret, + SingleQuote, Bang, CaretWithParenthesis, LeftBracket, diff --git a/poincare/src/parsing/tokenizer.cpp b/poincare/src/parsing/tokenizer.cpp index c1c66a18464..eca290fb8e6 100644 --- a/poincare/src/parsing/tokenizer.cpp +++ b/poincare/src/parsing/tokenizer.cpp @@ -206,6 +206,9 @@ Token Tokenizer::popToken() { } return Token(Token::Caret); } + if (c == '\'') { + return Token(Token::SingleQuote); + } if (c == '!') { return Token(Token::Bang); } diff --git a/poincare/src/tree_handle.cpp b/poincare/src/tree_handle.cpp index 992e22cee67..ea171237109 100644 --- a/poincare/src/tree_handle.cpp +++ b/poincare/src/tree_handle.cpp @@ -325,6 +325,8 @@ template IntegralLayout TreeHandle::FixedArityBuilder(const Tuple &); template InvNorm TreeHandle::FixedArityBuilder(const Tuple &); template LeastCommonMultiple TreeHandle::NAryBuilder(const Tuple &); +template KMat TreeHandle::FixedArityBuilder(const Tuple &); +template LeastCommonMultiple TreeHandle::FixedArityBuilder(const Tuple &); template LeftParenthesisLayout TreeHandle::FixedArityBuilder(const Tuple &); template LeftSquareBracketLayout TreeHandle::FixedArityBuilder(const Tuple &); template Logarithm TreeHandle::FixedArityBuilder >(const Tuple &); diff --git a/python/port/genhdr/qstrdefs.in.h b/python/port/genhdr/qstrdefs.in.h index 6660d8c548f..c580bcb8ea4 100644 --- a/python/port/genhdr/qstrdefs.in.h +++ b/python/port/genhdr/qstrdefs.in.h @@ -373,10 +373,13 @@ Q(KEY_EXE) // Kandinsky QSTRs Q(kandinsky) Q(color) +Q(draw_line) Q(draw_string) Q(fill_rect) Q(get_pixel) Q(set_pixel) +Q(large_font) +Q(small_font) Q(wait_vblank) Q(get_keys) diff --git a/python/port/mod/ion/modion_table.cpp b/python/port/mod/ion/modion_table.cpp index b1d861f51e2..7e6a53bdd33 100644 --- a/python/port/mod/ion/modion_table.cpp +++ b/python/port/mod/ion/modion_table.cpp @@ -16,7 +16,7 @@ const mp_obj_fun_builtin_fixed_t modion_keyboard_keydown_obj = { {(mp_fun_0_t)modion_keyboard_keydown} }; -STATIC const mp_rom_map_elem_t modion_module_globals_table[] = { +extern "C" const mp_rom_map_elem_t modion_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ion) }, { MP_ROM_QSTR(MP_QSTR_keydown), MP_ROM_PTR(&modion_keyboard_keydown_obj) }, { MP_ROM_QSTR(MP_QSTR_KEY_LEFT), MP_OBJ_NEW_SMALL_INT(Ion::Keyboard::Key::Left) }, diff --git a/python/port/mod/kandinsky/modkandinsky.cpp b/python/port/mod/kandinsky/modkandinsky.cpp index 41d163ce66e..201b482359c 100644 --- a/python/port/mod/kandinsky/modkandinsky.cpp +++ b/python/port/mod/kandinsky/modkandinsky.cpp @@ -61,8 +61,22 @@ mp_obj_t modkandinsky_draw_string(size_t n_args, const mp_obj_t * args) { KDPoint point(mp_obj_get_int(args[1]), mp_obj_get_int(args[2])); KDColor textColor = (n_args >= 4) ? MicroPython::Color::Parse(args[3]) : KDColorBlack; KDColor backgroundColor = (n_args >= 5) ? MicroPython::Color::Parse(args[4]) : KDColorWhite; + const KDFont * font = (n_args >= 6) ? ((mp_obj_is_true(args[5])) ? KDFont::SmallFont : KDFont::LargeFont) : KDFont::LargeFont; MicroPython::ExecutionEnvironment::currentExecutionEnvironment()->displaySandbox(); - KDIonContext::sharedContext()->drawString(text, point, KDFont::LargeFont, textColor, backgroundColor); + KDIonContext::sharedContext()->drawString(text, point, font, textColor, backgroundColor); + return mp_const_none; +} + +mp_obj_t modkandinsky_draw_line(size_t n_args, const mp_obj_t * args) { + mp_int_t x1 = mp_obj_get_int(args[0]); + mp_int_t y1 = mp_obj_get_int(args[1]); + mp_int_t x2 = mp_obj_get_int(args[2]); + mp_int_t y2 = mp_obj_get_int(args[3]); + KDPoint p1 = KDPoint(x1, y1); + KDPoint p2 = KDPoint(x2, y2); + KDColor color = MicroPython::Color::Parse(args[4]); + MicroPython::ExecutionEnvironment::currentExecutionEnvironment()->displaySandbox(); + KDIonContext::sharedContext()->drawLine(p1, p2, color); return mp_const_none; } diff --git a/python/port/mod/kandinsky/modkandinsky.h b/python/port/mod/kandinsky/modkandinsky.h index 12fd2cbc198..acb47d6f8ee 100644 --- a/python/port/mod/kandinsky/modkandinsky.h +++ b/python/port/mod/kandinsky/modkandinsky.h @@ -4,6 +4,7 @@ mp_obj_t modkandinsky_color(size_t n_args, const mp_obj_t *args); mp_obj_t modkandinsky_get_pixel(mp_obj_t x, mp_obj_t y); mp_obj_t modkandinsky_set_pixel(mp_obj_t x, mp_obj_t y, mp_obj_t color); mp_obj_t modkandinsky_draw_string(size_t n_args, const mp_obj_t *args); +mp_obj_t modkandinsky_draw_line(size_t n_args, const mp_obj_t *args); mp_obj_t modkandinsky_fill_rect(size_t n_args, const mp_obj_t *args); mp_obj_t modkandinsky_wait_vblank(); mp_obj_t modkandinsky_get_keys(); diff --git a/python/port/mod/kandinsky/modkandinsky_table.c b/python/port/mod/kandinsky/modkandinsky_table.c index 565d44e71a4..5bbb2e640ce 100644 --- a/python/port/mod/kandinsky/modkandinsky_table.c +++ b/python/port/mod/kandinsky/modkandinsky_table.c @@ -3,7 +3,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modkandinsky_color_obj, 1, 3, modkandinsky_color); STATIC MP_DEFINE_CONST_FUN_OBJ_2(modkandinsky_get_pixel_obj, modkandinsky_get_pixel); STATIC MP_DEFINE_CONST_FUN_OBJ_3(modkandinsky_set_pixel_obj, modkandinsky_set_pixel); -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modkandinsky_draw_string_obj, 3, 5, modkandinsky_draw_string); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modkandinsky_draw_string_obj, 3, 6, modkandinsky_draw_string); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modkandinsky_draw_line_obj, 5, 5, modkandinsky_draw_line); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modkandinsky_fill_rect_obj, 5, 5, modkandinsky_fill_rect); STATIC MP_DEFINE_CONST_FUN_OBJ_0(modkandinsky_wait_vblank_obj, modkandinsky_wait_vblank); STATIC MP_DEFINE_CONST_FUN_OBJ_0(modkandinsky_get_keys_obj, modkandinsky_get_keys); @@ -14,7 +15,10 @@ STATIC const mp_rom_map_elem_t modkandinsky_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_get_pixel), (mp_obj_t)&modkandinsky_get_pixel_obj }, { MP_ROM_QSTR(MP_QSTR_set_pixel), (mp_obj_t)&modkandinsky_set_pixel_obj }, { MP_ROM_QSTR(MP_QSTR_draw_string), (mp_obj_t)&modkandinsky_draw_string_obj }, + { MP_ROM_QSTR(MP_QSTR_draw_line), (mp_obj_t)&modkandinsky_draw_line_obj }, { MP_ROM_QSTR(MP_QSTR_fill_rect), (mp_obj_t)&modkandinsky_fill_rect_obj }, + { MP_ROM_QSTR(MP_QSTR_large_font), mp_const_true }, + { MP_ROM_QSTR(MP_QSTR_small_font), mp_const_false }, { MP_ROM_QSTR(MP_QSTR_wait_vblank), (mp_obj_t)&modkandinsky_wait_vblank_obj }, { MP_ROM_QSTR(MP_QSTR_get_keys), (mp_obj_t)&modkandinsky_get_keys_obj }, }; diff --git a/python/port/mpconfigport.h b/python/port/mpconfigport.h index a55925d826b..fa3d71da6a4 100644 --- a/python/port/mpconfigport.h +++ b/python/port/mpconfigport.h @@ -146,3 +146,10 @@ extern const struct _mp_obj_module_t modturtle_module; { MP_ROM_QSTR(MP_QSTR_os), MP_ROM_PTR(&modos_module) }, \ { MP_ROM_QSTR(MP_QSTR_turtle), MP_ROM_PTR(&modturtle_module) }, \ +// Enable setjmp in debug mode. This is to avoid some optimizations done +// specifically for x86_64 using inline assembly, which makes the debug binary +// crash with an illegal instruction +#ifndef NDEBUG + #define MICROPY_NLR_SETJMP 1 +#endif + diff --git a/themes/icons.json b/themes/icons.json index d16c64c857c..3dc1ae52da1 100644 --- a/themes/icons.json +++ b/themes/icons.json @@ -2,7 +2,7 @@ "apps/exam_icon.png" : "exam_icon.png", "apps/on_boarding/logo_icon.png" : "logo_icon.png", - "apps/atom/atom_icon.png" : "apps/atom_icon.png", + "apps/atomic/atomic_icon.png" : "apps/atomic_icon.png", "apps/calculation/calculation_icon.png" : "apps/calculation_icon.png", "apps/code/code_icon.png" : "apps/code_icon.png", "apps/external/external_icon.png" : "apps/external_icon.png", diff --git a/themes/themes/local/epsilon_dark.json b/themes/themes/local/epsilon_dark.json index 012dd654d2c..9121a7efe36 100644 --- a/themes/themes/local/epsilon_dark.json +++ b/themes/themes/local/epsilon_dark.json @@ -132,17 +132,19 @@ "Atom": { "Unknown": "eeeeee", "Text": "000000", - "AlkaliMetal": "ffaa00", - "AlkaliEarthMetal": "f6f200", - "Lanthanide": "ffaa8b", - "Actinide": "deaacd", - "TransitionMetal": "de999c", - "PostTransitionMetal": "9cbaac", - "Metalloid": "52ce8b", - "Halogen": "00debd", - "ReactiveNonmetal": "00ee00", - "NobleGas": "8baaff", - "TableLines": "323532" + "AlkaliMetal": "CC9E7E", + "AlkaliEarthMetal": "D69477", + "Lanthanide": "A5DDAD", + "Actinide": "96D481", + "TransitionMetal": "99C6E7", + "PostTransitionMetal": "D69877", + "Metalloid": "D6B071", + "Halogen": "84ABE3", + "ReactiveNonmetal": "DBC377", + "NobleGas": "8FC2E6", + "TableLines": "323532", + "Highlight": "000000", + "Background": "d9d9d9" } } } diff --git a/themes/themes/local/epsilon_light.json b/themes/themes/local/epsilon_light.json index 91423fa142e..679b244564d 100644 --- a/themes/themes/local/epsilon_light.json +++ b/themes/themes/local/epsilon_light.json @@ -132,17 +132,19 @@ "Atom": { "Unknown": "eeeeee", "Text": "000000", - "AlkaliMetal": "ffaa00", - "AlkaliEarthMetal": "f6f200", - "Lanthanide": "ffaa8b", - "Actinide": "deaacd", - "TransitionMetal": "de999c", - "PostTransitionMetal": "9cbaac", - "Metalloid": "52ce8b", - "Halogen": "00debd", - "ReactiveNonmetal": "00ee00", - "NobleGas": "8baaff", - "TableLines": "323532" + "AlkaliMetal": "CC9E7E", + "AlkaliEarthMetal": "D69477", + "Lanthanide": "A5DDAD", + "Actinide": "96D481", + "TransitionMetal": "99C6E7", + "PostTransitionMetal": "D69877", + "Metalloid": "D6B071", + "Halogen": "84ABE3", + "ReactiveNonmetal": "DBC377", + "NobleGas": "8FC2E6", + "TableLines": "323532", + "Highlight": "000000", + "Background": "d9d9d9" } } } diff --git a/themes/themes/local/epsilon_light/apps/atom_icon.png b/themes/themes/local/epsilon_light/apps/atomic_icon.png similarity index 100% rename from themes/themes/local/epsilon_light/apps/atom_icon.png rename to themes/themes/local/epsilon_light/apps/atomic_icon.png diff --git a/themes/themes/local/omega_dark.json b/themes/themes/local/omega_dark.json index 0426dc2f9a0..adf64c2c507 100644 --- a/themes/themes/local/omega_dark.json +++ b/themes/themes/local/omega_dark.json @@ -132,17 +132,19 @@ "Atom": { "Unknown": "eeeeee", "Text": "000000", - "AlkaliMetal": "ffaa00", - "AlkaliEarthMetal": "f6f200", - "Lanthanide": "ffaa8b", - "Actinide": "deaacd", - "TransitionMetal": "de999c", - "PostTransitionMetal": "9cbaac", - "Metalloid": "52ce8b", - "Halogen": "00debd", - "ReactiveNonmetal": "00ee00", - "NobleGas": "8baaff", - "TableLines": "323532" + "AlkaliMetal": "CC9E7E", + "AlkaliEarthMetal": "D69477", + "Lanthanide": "A5DDAD", + "Actinide": "96D481", + "TransitionMetal": "99C6E7", + "PostTransitionMetal": "D69877", + "Metalloid": "D6B071", + "Halogen": "84ABE3", + "ReactiveNonmetal": "DBC377", + "NobleGas": "8FC2E6", + "TableLines": "323532", + "Highlight": "000000", + "Background": "d9d9d9" } } } diff --git a/themes/themes/local/omega_dark/apps/atom_icon.png b/themes/themes/local/omega_dark/apps/atomic_icon.png similarity index 100% rename from themes/themes/local/omega_dark/apps/atom_icon.png rename to themes/themes/local/omega_dark/apps/atomic_icon.png diff --git a/themes/themes/local/omega_light.json b/themes/themes/local/omega_light.json index 1e4ecf3da86..4381ce63450 100644 --- a/themes/themes/local/omega_light.json +++ b/themes/themes/local/omega_light.json @@ -132,17 +132,19 @@ "Atom": { "Unknown": "eeeeee", "Text": "000000", - "AlkaliMetal": "ffaa00", - "AlkaliEarthMetal": "f6f200", - "Lanthanide": "ffaa8b", - "Actinide": "deaacd", - "TransitionMetal": "de999c", - "PostTransitionMetal": "9cbaac", - "Metalloid": "52ce8b", - "Halogen": "00debd", - "ReactiveNonmetal": "00ee00", - "NobleGas": "8baaff", - "TableLines": "323532" + "AlkaliMetal": "CC9E7E", + "AlkaliEarthMetal": "D69477", + "Lanthanide": "A5DDAD", + "Actinide": "96D481", + "TransitionMetal": "99C6E7", + "PostTransitionMetal": "D69877", + "Metalloid": "D6B071", + "Halogen": "84ABE3", + "ReactiveNonmetal": "DBC377", + "NobleGas": "8FC2E6", + "TableLines": "323532", + "Highlight": "000000", + "Background": "d9d9d9" } } } diff --git a/themes/themes/local/omega_light/apps/atom_icon.png b/themes/themes/local/omega_light/apps/atomic_icon.png similarity index 100% rename from themes/themes/local/omega_light/apps/atom_icon.png rename to themes/themes/local/omega_light/apps/atomic_icon.png