Merge Upsilon-dev

This commit is contained in:
Laury
2022-03-23 22:02:27 +01:00
102 changed files with 2991 additions and 2218 deletions

View File

@@ -219,3 +219,8 @@ run: compile
translations:
@echo "TRANSLATIONS"
$(Q) ${PYTHON} build/utilities/translate.py
.PHONY: translations_clean
translations_clean:
@echo "TRANSLATIONS CLEAN"
$(Q) ${PYTHON} build/utilities/translations_clean.py

View File

@@ -266,7 +266,8 @@ bool AppsContainer::processEvent(Ion::Events::Event event) {
}
if (event == Ion::Events::BrightnessPlus || event == Ion::Events::BrightnessMinus) {
int delta = Ion::Backlight::MaxBrightness/GlobalPreferences::NumberOfBrightnessStates;
int direction = (event == Ion::Events::BrightnessPlus) ? Ion::Backlight::NumberOfStepsPerShortcut*delta : -delta*Ion::Backlight::NumberOfStepsPerShortcut;
int NumberOfStepsPerShortcut = GlobalPreferences::sharedGlobalPreferences()->brightnessShortcut();
int direction = (event == Ion::Events::BrightnessPlus) ? NumberOfStepsPerShortcut*delta : -delta*NumberOfStepsPerShortcut;
GlobalPreferences::sharedGlobalPreferences()->setBrightnessLevel(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()+direction);
}
return false;
@@ -353,6 +354,8 @@ bool AppsContainer::updateBatteryState() {
}
void AppsContainer::refreshPreferences() {
m_suspendTimer.reset(GlobalPreferences::sharedGlobalPreferences()->idleBeforeSuspendSeconds()*1000/Timer::TickDuration);
m_backlightDimmingTimer.reset(GlobalPreferences::sharedGlobalPreferences()->idleBeforeDimmingSeconds()*1000/Timer::TickDuration);
m_window.refreshPreferences();
}

View File

@@ -1,39 +1,26 @@
#include "backlight_dimming_timer.h"
#include "global_preferences.h"
#include <ion/backlight.h>
#include <ion/events.h>
#include <apps/apps_container.h>
BacklightDimmingTimer::BacklightDimmingTimer() :
Timer(k_idleBeforeDimmingDuration/Timer::TickDuration)
Timer(GlobalPreferences::sharedGlobalPreferences()->idleBeforeDimmingSeconds()*1000/Timer::TickDuration)
{
}
bool BacklightDimmingTimer::fire() {
if (m_dimerExecutions == 0) {
m_brightnessLevel = GlobalPreferences::sharedGlobalPreferences()->brightnessLevel();
m_dimerSteps = m_brightnessLevel / decreaseBy;
m_timeToSleep = decreasetime / m_dimerSteps;
m_period = m_timeToSleep / Timer::TickDuration;
if (m_period == 0) {
m_period = 1;
bool BacklightDimmingTimer::fire(){
int i = Ion::Backlight::brightness();
while (i > 0){
int t = 20;
Ion::Events::Event e = Ion::Events::getEvent(&t);
AppsContainer::sharedAppsContainer()->dispatchEvent(e);
if (e.isKeyboardEvent()){
return false;
}
resetTimer();
Ion::Backlight::setBrightness(i);
i -= 15;
}
if (m_dimerExecutions < m_dimerSteps) {
m_nextbrightness = (m_brightnessLevel-k_dimBacklightBrightness)/m_dimerSteps * (m_dimerSteps-m_dimerExecutions);
Ion::Backlight::setBrightness(m_nextbrightness);
resetTimer();
} else if (m_dimerExecutions == m_dimerSteps) {
Ion::Backlight::setBrightness(k_dimBacklightBrightness);
}
m_dimerExecutions++;
return false;
}
void BacklightDimmingTimer::reset() {
m_dimerExecutions = 0;
m_period = k_idleBeforeDimmingDuration / Timer::TickDuration;
resetTimer();
}
void BacklightDimmingTimer::resetTimer() {
BacklightDimmingTimer::m_numberOfTicksBeforeFire = BacklightDimmingTimer::m_period;
}

View File

@@ -6,19 +6,8 @@
class BacklightDimmingTimer : public Timer {
public:
BacklightDimmingTimer();
void reset();
private:
constexpr static int k_idleBeforeDimmingDuration = 30*1000; // In miliseconds
constexpr static int k_dimBacklightBrightness = 0;
constexpr static int decreaseBy = 15;
constexpr static int decreasetime = 1*1000; // In miliseconds
int m_dimerExecutions = 0;
int m_brightnessLevel;
int m_dimerSteps;
int m_nextbrightness;
float m_timeToSleep; // In miliseconds
bool fire() override;
void resetTimer();
};
#endif

View File

@@ -1,3 +1,2 @@
CodeAppCapital = "PYTHON"
ConsolePrompt = ">>> "
ScriptParameters = "..."

View File

@@ -186,14 +186,11 @@ PythonTurtlePosition = "Aktuelle (x,y) Position zurückgeben"
PythonTurtleReset = "Die Zeichnung zurücksetzen"
PythonTurtleRight = "Um ein Grad nach rechts drehen"
PythonTurtleSetheading = "Ausrichtung auf einen Grad setzen"
PythonTurtleSetposition = "Den Igel auf Position setzen"
PythonTurtleShowturtle = "Den Igel anzeigen"
PythonTurtleSpeed = "Zeichengeschwindigkeit von 0 bis 10"
PythonTurtleWrite = "Einen Text anzeigen"
PythonUniform = "Fließkommazahl in [a,b]"
PythonImportTime = "Time-Modul importieren"
PythonTimePrefix = "Zeitmodul-Funktionspräfix"
PythonTimeSleep = "Warte für n Sekunden"
PythonMonotonic = "Monotone Zeit zurückgeben"
PythonFileOpen = "Öffnet eine Datei"
PythonFileSeekable = "Kann Datei durchsucht werden?"

View File

@@ -172,7 +172,6 @@ PythonTurtlePosition = "Return the current (x,y) location"
PythonTurtleReset = "Reset the drawing"
PythonTurtleRight = "Turn right by a degrees"
PythonTurtleSetheading = "Set the orientation to a degrees"
PythonTurtleSetposition = "Positioning the turtle"
PythonTurtleShowturtle = "Show the turtle"
PythonTurtleSpeed = "Drawing speed between 0 and 10"
PythonTurtleWrite = "Display a text"
@@ -192,8 +191,6 @@ PythonSysImplementation = "Information about Python"
PythonSysModules = "Dictionary of loaded modules"
PythonSysVersion = "Python language version (string)"
PythonSysVersioninfo = "Python language version (tuple)"
PythonTimePrefix = "time module function prefix"
PythonTimeSleep = "Wait for n second"
PythonMonotonic = "Return monotonic time"
PythonFileOpen = "Opens a file"
PythonFileSeekable = "Tells if seek can be used on a file"

View File

@@ -172,7 +172,6 @@ PythonTurtlePosition = "Return the current (x,y) location"
PythonTurtleReset = "Reset the drawing"
PythonTurtleRight = "Turn right by a degrees"
PythonTurtleSetheading = "Set the orientation to a degrees"
PythonTurtleSetposition = "Colocar la tortuga"
PythonTurtleShowturtle = "Show the turtle"
PythonTurtleSpeed = "Drawing speed between 0 and 10"
PythonTurtleWrite = "Display a text"
@@ -192,8 +191,6 @@ PythonSysImplementation = "Information about Python"
PythonSysModules = "Dictionary of loaded modules"
PythonSysVersion = "Python language version (string)"
PythonSysVersioninfo = "Python language version (tuple)"
PythonTimePrefix = "time module function prefix"
PythonTimeSleep = "Esperar n segundos"
PythonMonotonic = "Tiempo monótono de retorno"
PythonFileOpen = "Opens a file"
PythonFileSeekable = "Tells if seek can be used on a file"

View File

@@ -172,7 +172,6 @@ PythonTurtlePosition = "Renvoie la position (x,y)"
PythonTurtleReset = "Réinitialise le dessin"
PythonTurtleRight = "Pivote de a degrés vers la droite"
PythonTurtleSetheading = "Met un cap de a degrés"
PythonTurtleSetposition = "Positionne la tortue"
PythonTurtleShowturtle = "Affiche la tortue"
PythonTurtleSpeed = "Vitesse du tracé entre 0 et 10"
PythonTurtleWrite = "Affiche un texte"
@@ -192,8 +191,6 @@ PythonSysImplementation = "Information sur Python"
PythonSysModules = "Dictionnaire des modules chargés"
PythonSysVersion = "Version du langage Python (string)"
PythonSysVersioninfo = "Version du langage Python (tuple)"
PythonTimePrefix = "Préfixe fonction du module temps"
PythonTimeSleep = "Attendre n secondes"
PythonMonotonic = "Retourne le temps monotone"
PythonFileOpen = "Ouvre un fichier"
PythonFileSeekable = "Indique si seek peut être utilisé"

View File

@@ -1,213 +1,210 @@
PythonPound = "Megjegyzés"
PythonPercent = "Modulo"
Python1J = "Képzeletbeli i"
PythonLF = "Enter"
PythonTab = "Táblázat"
PythonAmpersand = "Logikus és"
PythonSymbolExp = "logikus exkluzív vagy pedig"
PythonVerticalBar = "logikus vagy pedig"
PythonImag = "z képzeletbeli része"
PythonReal = "z valódi része"
PythonSingleQuote = "apostróf"
PythonAbs = "Abszolút érték/nagyság"
PythonAcos = "Ív (arc) koszinusz"
PythonAcosh = "Hiperbolikus arc koszinusz"
PythonAppend = "Lista végére hozzáadni x-et"
PythonArrow = "(x,y) nyíla (x+dx,y+dy) nyílához"
PythonAsin = "Ív (arc) szinusz"
PythonAsinh = "Hiperbolikus ív (arc) szinusz"
PythonAtan = "Ív (arc) érintö (tan)"
PythonAtan2 = "atan(y/x) sámolása"
PythonAtanh = "Hiperbolikus ív (arc) érintö (atan)"
PythonAxis = "Tengelyeket (xmin,xmax,ymin,ymax)-ra állitani"
PythonBar = "Az x lista oszlopdiagramja"
PythonBin = "Egész szám konvertálása binárisra"
PythonCeil = "Mennyezet"
PythonChoice = "Véletlenszerü szám a listában"
PythonClear = "A lista ürítése"
PythonCmathFunction = "cmath modul funkció elötag"
PythonColor = "Rgb (pzk) szín allítása"
PythonColorBlack = "Fekete szín"
PythonColorBlue = "Kék szín"
PythonColorBrown = "Barna szín"
PythonColorGreen = "Zöld szín"
PythonColorGray = "Szürke szín"
PythonColorOrange = "Narancssárga szín"
PythonColorPink = "Rózsaszín szín"
PythonColorPurple = "Lila szín"
PythonColorRed = "Piros szín"
PythonColorWhite = "Fehér szín"
PythonColorYellow = "Sárga szín"
PythonComplex = "A + ib visszaadása"
PythonCopySign = "X visszaadása y jelével"
PythonCos = "Koszinusz"
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"
PythonDrawCircle = "Rajzolj egy kört"
PythonDrawLine = "Húzzon egy vonalat "
PythonDrawString = "Szöveg megjelenítése (x, y)-en"
PythonErf = "Hiba funkció"
PythonErfc = "Kiegészítö hiba funkció"
PythonEval = "Visszaadja az értékelt kifejezést"
PythonExp = "Exponenciális függvény"
PythonExpm1 = "exp(x)-1 sámitása"
PythonFactorial = "x faktorál"
PythonFabs = "Abszolút érték"
PythonFillRect = "Téglalap töltése"
PythonFillCircle = "Kitölti a kört"
PythonFillPolygon = "Kitölti a poligont"
PythonFloat = "Konvertálása tizedes számra"
PythonFloor = "Egész része"
PythonFmod = "a modulo b"
PythonFrExp = "X mantissája és kiállítója"
PythonGamma = "Gamma funkció"
PythonGetKeys = "Billentyűk lenyomva"
PythonGetPalette = "Téma paletta beszerzése"
PythonGetPixel = "Visszatéríti (x,y) színét"
PythonGetrandbits = "Váletlenszám visszatérítése k biten"
PythonGrid = "Rács megjelenítése/elrejtése"
PythonHex = "Decimális szám konvertálása hexadecimális számra"
PythonHist = "x hisztográmiája"
PythonImportCmath = "cmath modul importálása"
PythonImportIon = "Ion modul importálása"
PythonImportKandinsky = "Kandinsky modul importálása"
PythonImportRandom = "Véletlenszerü modul importálása"
PythonImportMath = "math modul importálása"
PythonImportMatplotlibPyplot = "matplotlib.pyplot modul importálása"
PythonImportNumpy = "ulab.numpy modul importálása"
PythonImportScipy = "ulab.scipy modul importálása"
PythonImportTurtle = "turtle modul importálása"
PythonImportTime = "time modul importálása"
PythonIndex = "Az elsö x esemény indexe"
PythonInput = "Irjon egy értéket (számot)"
PythonInsert = "x-et i. pozícióra helyezze a listában"
PythonInt = "egész számra konvertálás"
PythonIonFunction = "ion modul funkció elötag"
PythonIsFinite = "x véges-e"
PythonIsInfinite = "x végtelen-e"
PythonIsKeyDown = "True-t válaszol ha a k gomb le van nyomva"
PythonBattery = "Az akkumulátor feszültségének visszaadása"
PythonBatteryLevel = "Az akkumulátor töltöttségi szintjének visszaadása"
PythonBatteryIscharging = "Visszaadja, ha az akkumulátor töltődik"
PythonSetBrightness = "Fényerőszint beállítása"
PythonGetBrightness = "Get brightness level"
PythonIsNaN = "Ellenörizze hogy x nem NaN"
PythonKandinskyFunction = "kandinsky modul funkció elötag"
PythonLdexp = "frexp ellentéte : x*(2**i)"
PythonLength = "Egy targy hossza"
PythonLgamma = "Gamma funkció logaritmusa"
PythonLog = "a alapú logaritmus"
PythonLog10 = "Decimális logaritmus"
PythonLog2 = "Bináris logaritmus"
PythonMathFunction = "math modul funkció elötag"
PythonMatplotlibPyplotFunction = "matplotlib.pyplot elötag"
PythonMax = "Maximum"
PythonMin = "Minimum"
PythonModf = "x-nek tört és egész részei"
PythonMonotonic = "Az óra értékét adja vissza"
PythonNumpyFunction = "numpy elötag"
PythonNumpyFftFunction = "numpy.fft elötag"
PythonNumpyLinalgFunction = "numpy.linalg elötag"
PythonScipyFunction = "scipy elötag"
PythonScipyLinalgFunction = "scipy.linalg elötag"
PythonScipyOptimizeFunction = "scipy.optimize elötag"
PythonScipySignalFunction = "scipy.signal elötag"
PythonScipySpecialFunction = "scipy.special elötag"
PythonOct = "Decimális szám konvertálása octális számra"
PythonPhase = "z fázisa"
PythonPlot = "y-t jelöli x függvényében"
PythonPolar = "Verctorizálni"
PythonPop = "Az utolsó elemet el törölni"
PythonPower = "x y. kitevö"
PythonPrint = "Ki irni a elemeket"
PythonRadians = "Fokról radiánra konvertálni"
PythonRandint = "Véletlen egész szám [a;b] -ban"
PythonRandom = "Decimális szám [0;1] -ban"
PythonRandomFunction = "random modul funkció elötag"
PythonRandrange = "Véletlen szám range(start,stop)-ban"
PythonRangeStartStop = "start-tol stop-ig listája"
PythonRangeStop = "0 tol stop-ig lista"
PythonRect = "Algebrai számra konvertálni"
PythonRemove = "Elsö x elöfordulását törolni"
PythonReverse = "A lista elemeit megfordítani (másik irány)"
PythonRound = "N számjegyre kerekítni"
PythonScatter = "(x,y) halmaza"
PythonSeed = "Inicializálni a véletlenszám-választót"
PythonSetPixel = "Az (x,y) pixel-t ki szinezni"
PythonShow = "Mutassa az ábrát"
PythonSin = "Szinusz"
PythonSinh = "Hiperbolikus szinusz"
PythonSleep = "t másodpercre meg állitani a programmot"
PythonLocalTime = "Idő konvertálása csomóvá"
PythonMktime = "A tuple konvertálása az időben"
PythonTime = "Az aktuális időbélyeg letöltése"
PythonSetLocaltime = "Idő beállítása egy csomóból"
PythonRTCmode = "Aktuális RTC mód"
PythonSetRTCmode = "RTC mód beállítása"
PythonSort = "A listát rendezni"
PythonSqrt = "Négyzetgyök"
PythonSum = "Összeadni a lista elemeit"
PythonTan = "Érintö (tan)"
PythonTanh = "Hiperbolikus érintö (tan)"
PythonText = "(x,y) nél egy szöveget irni"
PythonTimeFunction = "time funkció elötag"
PythonTrunc = "Egész csonka (?)"
PythonTurtleBackward = "x pixelt hátra"
PythonTurtleCircle = "r pixel sugarú kört rajzolni"
PythonTurtleColor = "Toll szinét beállitani"
PythonTurtleColorMode = "Szin módot 1.0-ra vagy 255-ra állitani"
PythonTurtleForward = "x pixelt elölre"
PythonTurtleFunction = "turtle modul funkció elötag"
PythonTurtleGoto = "Menjen a (x,y) koordinátákra"
PythonTurtleHeading = "Visszaadja az aktuális irányt"
PythonTurtleHideturtle = "A teknös elrejtése"
PythonTurtleIsdown = "True-t válaszol ha a toll irás pozícióban van"
PythonTurtleLeft = "a fokkot forduljon balra"
PythonTurtlePendown = "Húzza le a tollat"
PythonTurtlePensize = "Állítsa a vonalvastagságot x pixelre"
PythonTurtlePenup = "Húzza fel a tollat"
PythonTurtlePosition = "Az aktuális (x,y) pozíciót visszaadása"
PythonTurtleReset = "Visszaállitani a rajzot (torléssel)"
PythonTurtleRight = "a fokkot forduljon jobbra"
PythonTurtleSetheading = "a fokokra állítja be az irányt"
PythonTurtleSetposition = "A teknös pozicioját allitja"
PythonTurtleShowturtle = "A teknöst meg mutatni"
PythonTurtleSpeed = "Rajzolási sebesség 0 és 10 között"
PythonTurtleWrite = "Szöveg irás"
PythonUniform = "Lebegöpontos szám [a,b] -ban"
PythonImportTime = "time modul importálása"
PythonTimePrefix = "time funkció elötag"
PythonTimeSleep = "n másodpercet várni"
PythonMonotonic = "Meg fordítani a monoton idö"
PythonFileOpen = "Fájl megnyitása"
PythonFileSeekable = "Seek-et lehete használni"
PythonFileSeek = "A kurzort áthelyezni"
PythonFileTell = "Visszaadja a kurzor helye"
PythonFileClose = "Bezárni egy fájlt"
PythonFileClosed = "True ha a fájl bezárva"
PythonFileRead = "Olvas 16 bájtig"
PythonFileWrite = "b-t irjon a fájlba"
PythonFileReadline = "Olvas egy sort vagy 16 bájtig"
PythonFileReadlines = "Olvas több sort"
PythonFileTruncate = "A fájl átméretezése"
PythonFileWritelines = "Irjon több sort"
PythonFileName = "A fájl neve"
PythonFileMode = "A fájl nyitott módja"
PythonFileReadable = "read-et lehete használni"
PythonFileWritable = "write-ot lehete használni"
PythonImportOs = "os modul importálása"
PythonOsUname = "Rendszer informaciók"
PythonOsGetlogin = "Get username"
PythonOsRemove = "Fájl törlése"
PythonOsRename = "Fájl átnevezése"
PythonOsListdir = "Fájlok listája"
PythonImportSys = "sys modul importálása"
PythonSysExit = "Terminate current program"
PythonSysPrintexception = "Print exception"
PythonSysByteorder = "The byte order of the system"
PythonSysImplementation = "Information about Python"
PythonSysModules = "Dictionary of loaded modules"
PythonSysVersion = "Python language version (string)"
PythonSysVersioninfo = "Python language version (tuple)"
PythonPound = "Megjegyzés"
PythonPercent = "Modulo"
Python1J = "Képzeletbeli i"
PythonLF = "Enter"
PythonTab = "Táblázat"
PythonAmpersand = "Logikus és"
PythonSymbolExp = "logikus exkluzív vagy pedig"
PythonVerticalBar = "logikus vagy pedig"
PythonImag = "z képzeletbeli része"
PythonReal = "z valódi része"
PythonSingleQuote = "apostróf"
PythonAbs = "Abszolút érték/nagyság"
PythonAcos = "Ív (arc) koszinusz"
PythonAcosh = "Hiperbolikus arc koszinusz"
PythonAppend = "Lista végére hozzáadni x-et"
PythonArrow = "(x,y) nyíla (x+dx,y+dy) nyílához"
PythonAsin = "Ív (arc) szinusz"
PythonAsinh = "Hiperbolikus ív (arc) szinusz"
PythonAtan = "Ív (arc) érintö (tan)"
PythonAtan2 = "atan(y/x) sámolása"
PythonAtanh = "Hiperbolikus ív (arc) érintö (atan)"
PythonAxis = "Tengelyeket (xmin,xmax,ymin,ymax)-ra állitani"
PythonBar = "Az x lista oszlopdiagramja"
PythonBin = "Egész szám konvertálása binárisra"
PythonCeil = "Mennyezet"
PythonChoice = "Véletlenszerü szám a listában"
PythonClear = "A lista ürítése"
PythonCmathFunction = "cmath modul funkció elötag"
PythonColor = "Rgb (pzk) szín allítása"
PythonColorBlack = "Fekete szín"
PythonColorBlue = "Kék szín"
PythonColorBrown = "Barna szín"
PythonColorGreen = "Zöld szín"
PythonColorGray = "Szürke szín"
PythonColorOrange = "Narancssárga szín"
PythonColorPink = "Rózsaszín szín"
PythonColorPurple = "Lila szín"
PythonColorRed = "Piros szín"
PythonColorWhite = "Fehér szín"
PythonColorYellow = "Sárga szín"
PythonComplex = "A + ib visszaadása"
PythonCopySign = "X visszaadása y jelével"
PythonCos = "Koszinusz"
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"
PythonDrawCircle = "Rajzolj egy kört"
PythonDrawLine = "Húzzon egy vonalat "
PythonDrawString = "Szöveg megjelenítése (x, y)-en"
PythonErf = "Hiba funkció"
PythonErfc = "Kiegészítö hiba funkció"
PythonEval = "Visszaadja az értékelt kifejezést"
PythonExp = "Exponenciális függvény"
PythonExpm1 = "exp(x)-1 sámitása"
PythonFactorial = "x faktorál"
PythonFabs = "Abszolút érték"
PythonFillRect = "Téglalap töltése"
PythonFillCircle = "Kitölti a kört"
PythonFillPolygon = "Kitölti a poligont"
PythonFloat = "Konvertálása tizedes számra"
PythonFloor = "Egész része"
PythonFmod = "a modulo b"
PythonFrExp = "X mantissája és kiállítója"
PythonGamma = "Gamma funkció"
PythonGetKeys = "Billentyűk lenyomva"
PythonGetPalette = "Téma paletta beszerzése"
PythonGetPixel = "Visszatéríti (x,y) színét"
PythonGetrandbits = "Váletlenszám visszatérítése k biten"
PythonGrid = "Rács megjelenítése/elrejtése"
PythonHex = "Decimális szám konvertálása hexadecimális számra"
PythonHist = "x hisztográmiája"
PythonImportCmath = "cmath modul importálása"
PythonImportIon = "Ion modul importálása"
PythonImportKandinsky = "Kandinsky modul importálása"
PythonImportRandom = "Véletlenszerü modul importálása"
PythonImportMath = "math modul importálása"
PythonImportMatplotlibPyplot = "matplotlib.pyplot modul importálása"
PythonImportNumpy = "ulab.numpy modul importálása"
PythonImportScipy = "ulab.scipy modul importálása"
PythonImportTurtle = "turtle modul importálása"
PythonImportTime = "time modul importálása"
PythonIndex = "Az elsö x esemény indexe"
PythonInput = "Irjon egy értéket (számot)"
PythonInsert = "x-et i. pozícióra helyezze a listában"
PythonInt = "egész számra konvertálás"
PythonIonFunction = "ion modul funkció elötag"
PythonIsFinite = "x véges-e"
PythonIsInfinite = "x végtelen-e"
PythonIsKeyDown = "True-t válaszol ha a k gomb le van nyomva"
PythonBattery = "Az akkumulátor feszültségének visszaadása"
PythonBatteryLevel = "Az akkumulátor töltöttségi szintjének visszaadása"
PythonBatteryIscharging = "Visszaadja, ha az akkumulátor töltődik"
PythonSetBrightness = "Fényerőszint beállítása"
PythonGetBrightness = "Get brightness level"
PythonIsNaN = "Ellenörizze hogy x nem NaN"
PythonKandinskyFunction = "kandinsky modul funkció elötag"
PythonLdexp = "frexp ellentéte : x*(2**i)"
PythonLength = "Egy targy hossza"
PythonLgamma = "Gamma funkció logaritmusa"
PythonLog = "a alapú logaritmus"
PythonLog10 = "Decimális logaritmus"
PythonLog2 = "Bináris logaritmus"
PythonMathFunction = "math modul funkció elötag"
PythonMatplotlibPyplotFunction = "matplotlib.pyplot elötag"
PythonMax = "Maximum"
PythonMin = "Minimum"
PythonModf = "x-nek tört és egész részei"
PythonMonotonic = "Az óra értékét adja vissza"
PythonNumpyFunction = "numpy elötag"
PythonNumpyFftFunction = "numpy.fft elötag"
PythonNumpyLinalgFunction = "numpy.linalg elötag"
PythonScipyFunction = "scipy elötag"
PythonScipyLinalgFunction = "scipy.linalg elötag"
PythonScipyOptimizeFunction = "scipy.optimize elötag"
PythonScipySignalFunction = "scipy.signal elötag"
PythonScipySpecialFunction = "scipy.special elötag"
PythonOct = "Decimális szám konvertálása octális számra"
PythonPhase = "z fázisa"
PythonPlot = "y-t jelöli x függvényében"
PythonPolar = "Verctorizálni"
PythonPop = "Az utolsó elemet el törölni"
PythonPower = "x y. kitevö"
PythonPrint = "Ki irni a elemeket"
PythonRadians = "Fokról radiánra konvertálni"
PythonRandint = "Véletlen egész szám [a;b] -ban"
PythonRandom = "Decimális szám [0;1] -ban"
PythonRandomFunction = "random modul funkció elötag"
PythonRandrange = "Véletlen szám range(start,stop)-ban"
PythonRangeStartStop = "start-tol stop-ig listája"
PythonRangeStop = "0 tol stop-ig lista"
PythonRect = "Algebrai számra konvertálni"
PythonRemove = "Elsö x elöfordulását törolni"
PythonReverse = "A lista elemeit megfordítani (másik irány)"
PythonRound = "N számjegyre kerekítni"
PythonScatter = "(x,y) halmaza"
PythonSeed = "Inicializálni a véletlenszám-választót"
PythonSetPixel = "Az (x,y) pixel-t ki szinezni"
PythonShow = "Mutassa az ábrát"
PythonSin = "Szinusz"
PythonSinh = "Hiperbolikus szinusz"
PythonSleep = "t másodpercre meg állitani a programmot"
PythonLocalTime = "Idő konvertálása csomóvá"
PythonMktime = "A tuple konvertálása az időben"
PythonTime = "Az aktuális időbélyeg letöltése"
PythonSetLocaltime = "Idő beállítása egy csomóból"
PythonRTCmode = "Aktuális RTC mód"
PythonSetRTCmode = "RTC mód beállítása"
PythonSort = "A listát rendezni"
PythonSqrt = "Négyzetgyök"
PythonSum = "Összeadni a lista elemeit"
PythonTan = "Érintö (tan)"
PythonTanh = "Hiperbolikus érintö (tan)"
PythonText = "(x,y) nél egy szöveget irni"
PythonTimeFunction = "time funkció elötag"
PythonTrunc = "Egész csonka (?)"
PythonTurtleBackward = "x pixelt hátra"
PythonTurtleCircle = "r pixel sugarú kört rajzolni"
PythonTurtleColor = "Toll szinét beállitani"
PythonTurtleColorMode = "Szin módot 1.0-ra vagy 255-ra állitani"
PythonTurtleForward = "x pixelt elölre"
PythonTurtleFunction = "turtle modul funkció elötag"
PythonTurtleGoto = "Menjen a (x,y) koordinátákra"
PythonTurtleHeading = "Visszaadja az aktuális irányt"
PythonTurtleHideturtle = "A teknös elrejtése"
PythonTurtleIsdown = "True-t válaszol ha a toll irás pozícióban van"
PythonTurtleLeft = "a fokkot forduljon balra"
PythonTurtlePendown = "Húzza le a tollat"
PythonTurtlePensize = "Állítsa a vonalvastagságot x pixelre"
PythonTurtlePenup = "Húzza fel a tollat"
PythonTurtlePosition = "Az aktuális (x,y) pozíciót visszaadása"
PythonTurtleReset = "Visszaállitani a rajzot (torléssel)"
PythonTurtleRight = "a fokkot forduljon jobbra"
PythonTurtleSetheading = "a fokokra állítja be az irányt"
PythonTurtleShowturtle = "A teknöst meg mutatni"
PythonTurtleSpeed = "Rajzolási sebesség 0 és 10 között"
PythonTurtleWrite = "Szöveg irás"
PythonUniform = "Lebegöpontos szám [a,b] -ban"
PythonImportTime = "time modul importálása"
PythonMonotonic = "Meg fordítani a monoton idö"
PythonFileOpen = "Fájl megnyitása"
PythonFileSeekable = "Seek-et lehete használni"
PythonFileSeek = "A kurzort áthelyezni"
PythonFileTell = "Visszaadja a kurzor helye"
PythonFileClose = "Bezárni egy fájlt"
PythonFileClosed = "True ha a fájl bezárva"
PythonFileRead = "Olvas 16 bájtig"
PythonFileWrite = "b-t irjon a fájlba"
PythonFileReadline = "Olvas egy sort vagy 16 bájtig"
PythonFileReadlines = "Olvas több sort"
PythonFileTruncate = "A fájl átméretezése"
PythonFileWritelines = "Irjon több sort"
PythonFileName = "A fájl neve"
PythonFileMode = "A fájl nyitott módja"
PythonFileReadable = "read-et lehete használni"
PythonFileWritable = "write-ot lehete használni"
PythonImportOs = "os modul importálása"
PythonOsUname = "Rendszer informaciók"
PythonOsGetlogin = "Get username"
PythonOsRemove = "Fájl törlése"
PythonOsRename = "Fájl átnevezése"
PythonOsListdir = "Fájlok listája"
PythonImportSys = "sys modul importálása"
PythonSysExit = "Terminate current program"
PythonSysPrintexception = "Print exception"
PythonSysByteorder = "The byte order of the system"
PythonSysImplementation = "Information about Python"
PythonSysModules = "Dictionary of loaded modules"
PythonSysVersion = "Python language version (string)"
PythonSysVersioninfo = "Python language version (tuple)"

View File

@@ -186,14 +186,11 @@ PythonTurtlePosition = "Fornisce posizione corrente (x,y)"
PythonTurtleReset = "Azzera il disegno"
PythonTurtleRight = "Ruota di a gradi a destra"
PythonTurtleSetheading = "Imposta l'orientamento per a gradi"
PythonTurtleSetposition = "Posiziona la tartaruga"
PythonTurtleShowturtle = "Mostra la tartaruga"
PythonTurtleSpeed = "Velocità di disegno (x tra 0 e 10)"
PythonTurtleWrite = "Mostra un testo"
PythonUniform = "Numero decimale tra [a,b]"
PythonImportTime = "Import time module"
PythonTimePrefix = "time module function prefix"
PythonTimeSleep = "Wait for n second"
PythonMonotonic = "Return monotonic time"
PythonFileOpen = "Opens a file"
PythonFileSeekable = "Tells if seek can be used on a file"

View File

@@ -187,14 +187,11 @@ PythonTurtlePosition = "Zet huidige (x,y) locatie terug"
PythonTurtleReset = "Reset de tekening"
PythonTurtleRight = "Ga rechtsaf met a graden"
PythonTurtleSetheading = "Zet de oriëntatie op a graden"
PythonTurtleSetposition = "Plaats de schildpad"
PythonTurtleShowturtle = "Laat de schildpad zien"
PythonTurtleSpeed = "Tekensnelheid tussen 0 and 10"
PythonTurtleWrite = "Display a text"
PythonUniform = "Decimaal getal in [a,b]"
PythonImportTime = "Import time module"
PythonTimePrefix = "time module function prefix"
PythonTimeSleep = "Wait for n second"
PythonMonotonic = "Return monotonic time"
PythonFileOpen = "Opens a file"
PythonFileSeekable = "Tells if seek can be used on a file"

View File

@@ -172,7 +172,6 @@ PythonTurtlePosition = "Devolve a posição atual (x,y)"
PythonTurtleReset = "Reiniciar o desenho"
PythonTurtleRight = "Virar à esquerda por a graus"
PythonTurtleSetheading = "Definir a orientação por a graus"
PythonTurtleSetposition = "Posicionamento da tartaruga"
PythonTurtleShowturtle = "Mostrar o turtle"
PythonTurtleSpeed = "Velocidade do desenho entre 0 e 10"
PythonTurtleWrite = "Mostrar um texto"
@@ -192,8 +191,6 @@ PythonSysImplementation = "Information about Python"
PythonSysModules = "Dictionary of loaded modules"
PythonSysVersion = "Python language version (string)"
PythonSysVersioninfo = "Python language version (tuple)"
PythonTimePrefix = "time module function prefix"
PythonTimeSleep = "Wait for n second"
PythonMonotonic = "Return monotonic time"
PythonFileOpen = "Opens a file"
PythonFileSeekable = "Tells if seek can be used on a file"

View File

@@ -114,52 +114,6 @@ PythonCommandIsInfinite = "isinf(x)"
PythonCommandIsNaN = "isnan(x)"
PythonCommandKandinskyFunction = "kandinsky.function"
PythonCommandKandinskyFunctionWithoutArg = "kandinsky.\x11"
PythonCommandKeyLeft = "KEY_LEFT"
PythonCommandKeyUp = "KEY_UP"
PythonCommandKeyDown = "KEY_DOWN"
PythonCommandKeyRight = "KEY_RIGHT"
PythonCommandKeyOk = "KEY_OK"
PythonCommandKeyBack = "KEY_BACK"
PythonCommandKeyHome = "KEY_HOME"
PythonCommandKeyOnOff = "KEY_ONOFF"
PythonCommandKeyShift = "KEY_SHIFT"
PythonCommandKeyAlpha = "KEY_ALPHA"
PythonCommandKeyXnt = "KEY_XNT"
PythonCommandKeyVar = "KEY_VAR"
PythonCommandKeyToolbox = "KEY_TOOLBOX"
PythonCommandKeyBackspace = "KEY_BACKSPACE"
PythonCommandKeyExp = "KEY_EXP"
PythonCommandKeyLn = "KEY_LN"
PythonCommandKeyLog = "KEY_LOG"
PythonCommandKeyImaginary = "KEY_IMAGINARY"
PythonCommandKeyComma = "KEY_COMMA"
PythonCommandKeyPower = "KEY_POWER"
PythonCommandKeySine = "KEY_SINE"
PythonCommandKeyCosine = "KEY_COSINE"
PythonCommandKeyTangent = "KEY_TANGENT"
PythonCommandKeyPi = "KEY_PI"
PythonCommandKeySqrt = "KEY_SQRT"
PythonCommandKeySquare = "KEY_SQUARE"
PythonCommandKeySeven = "KEY_SEVEN"
PythonCommandKeyEight = "KEY_EIGHT"
PythonCommandKeyNine = "KEY_NINE"
PythonCommandKeyLeftParenthesis = "KEY_LEFTPARENTHESIS"
PythonCommandKeyRightParenthesis = "KEY_RIGHTPARENTHESIS"
PythonCommandKeyFour = "KEY_FOUR"
PythonCommandKeyFive = "KEY_FIVE"
PythonCommandKeySix = "KEY_SIX"
PythonCommandKeyMultiplication = "KEY_MULTIPLICATION"
PythonCommandKeyDivision = "KEY_DIVISION"
PythonCommandKeyOne = "KEY_ONE"
PythonCommandKeyTwo = "KEY_TWO"
PythonCommandKeyThree = "KEY_THREE"
PythonCommandKeyPlus = "KEY_PLUS"
PythonCommandKeyMinus = "KEY_MINUS"
PythonCommandKeyZero = "KEY_ZERO"
PythonCommandKeyDot = "KEY_DOT"
PythonCommandKeyEe = "KEY_EE"
PythonCommandKeyAns = "KEY_ANS"
PythonCommandKeyExe = "KEY_EXE"
PythonCommandIsKeyDown = "keydown(k)"
PythonCommandBattery = "battery()"
PythonCommandBatteryLevel = "battery_level()"
@@ -403,16 +357,8 @@ PythonTurtleCommandPosition = "position()"
PythonTurtleCommandReset = "reset()"
PythonTurtleCommandRight = "right(a)"
PythonTurtleCommandSetheading = "setheading(a)"
PythonTurtleCommandSetposition = "setposition(x,[y])"
PythonTurtleCommandShowturtle = "showturtle()"
PythonTurtleCommandSpeed = "speed(x)"
PythonTurtleCommandWhite = "'white'"
PythonTurtleCommandYellow = "'yellow'"
PythonTimeModule = "time"
PythonTimeCommandImportFrom = "from time import *"
PythonTimeCommandSleep = "sleep()"
PythonTimeCommandSleepDemo = "sleep(n)"
PythonTimeCommandMonotonic = "monotonic()"
PythonCommandFileOpen = "open(name, [mode])"
PythonCommandFileOpenWithoutArg = "open(\x11)"
PythonCommandFileSeek = "file.seek(offset, [whence])"

View File

@@ -26,7 +26,9 @@ void EditorView::resetSelection() {
}
void EditorView::scrollViewDidChangeOffset(ScrollViewDataSource * scrollViewDataSource) {
m_gutterView.setOffset(scrollViewDataSource->offset().y());
if (m_gutterView.setOffsetAndNeedResize(scrollViewDataSource->offset().y())) {
internalLayoutSubviews(true);
}
}
View * EditorView::subviewAtIndex(int index) {
@@ -42,8 +44,12 @@ void EditorView::didBecomeFirstResponder() {
}
void EditorView::layoutSubviews(bool force) {
m_gutterView.setOffset(0);
KDCoordinate gutterWidth = m_gutterView.minimalSizeForOptimalDisplay().width();
m_gutterView.setOffsetAndNeedResize(0); // Whatever the return is, we layout the editor view
internalLayoutSubviews(force);
}
void EditorView::internalLayoutSubviews(bool force) {
KDCoordinate gutterWidth = m_gutterView.computeWidth();
m_gutterView.setFrame(KDRect(0, 0, gutterWidth, bounds().height()), force);
m_textArea.setFrame(KDRect(
@@ -67,23 +73,23 @@ void EditorView::GutterView::drawRect(KDContext * ctx, KDRect rect) const {
KDCoordinate firstLine = m_offset / glyphSize.height();
KDCoordinate firstLinePixelOffset = m_offset - firstLine * glyphSize.height();
char lineNumber[k_lineNumberCharLength];
char lineNumberBuffer[m_numberOfDigits + 1];
int numberOfLines = bounds().height() / glyphSize.height() + 1;
for (int i=0; i<numberOfLines; i++) {
// Only the first two digits are displayed
int lineNumberValue = (i + firstLine + 1) % 100;
int lineNumberValue = (i + firstLine + 1);
Poincare::Integer line(lineNumberValue);
if (firstLine < 10 || lineNumberValue >= 10) {
line.serialize(lineNumber, k_lineNumberCharLength);
} else {
// Add a leading "0"
lineNumber[0] = '0';
line.serialize(lineNumber + 1, k_lineNumberCharLength - 1);
int lineDigits = computeNumberOfDigitsFor(lineNumberValue);
for (int j=0; j < m_numberOfDigits - lineDigits; j++) {
lineNumberBuffer[j] = ' ';
}
KDCoordinate leftPadding = (2 - strlen(lineNumber)) * glyphSize.width();
line.serialize(lineNumberBuffer + (m_numberOfDigits - lineDigits), m_numberOfDigits + 1);
ctx->drawString(
lineNumber,
KDPoint(k_margin + leftPadding, i*glyphSize.height() - firstLinePixelOffset),
lineNumberBuffer,
KDPoint(k_margin, i*glyphSize.height() - firstLinePixelOffset),
m_font,
textColor,
backgroundColor
@@ -91,18 +97,36 @@ void EditorView::GutterView::drawRect(KDContext * ctx, KDRect rect) const {
}
}
void EditorView::GutterView::setOffset(KDCoordinate offset) {
bool EditorView::GutterView::setOffsetAndNeedResize(KDCoordinate offset) {
if (m_offset == offset) {
return;
return false;
}
m_offset = offset;
int numberOfDigits = computeMaxNumberOfDigits();
if (numberOfDigits != m_numberOfDigits) {
m_numberOfDigits = numberOfDigits;
return true;
}
markRectAsDirty(bounds());
return false;
}
int EditorView::GutterView::computeWidth() {
return 2 * k_margin + (m_numberOfDigits) * m_font->glyphSize().width();
}
KDSize EditorView::GutterView::minimalSizeForOptimalDisplay() const {
int numberOfChars = 2; // TODO: Could be computed
return KDSize(2 * k_margin + numberOfChars * m_font->glyphSize().width(), 0);
int EditorView::GutterView::computeMaxNumberOfDigits() {
return computeNumberOfDigitsFor((bounds().height() / m_font->glyphSize().height() + 1) + (m_offset / m_font->glyphSize().height()));
}
int EditorView::GutterView::computeNumberOfDigitsFor(int value) {
int digits = 1;
while (value >= pow(10, digits)) {
digits++;
}
return digits;
}
}

View File

@@ -29,6 +29,7 @@ public:
void unloadSyntaxHighlighter() { m_textArea.unloadSyntaxHighlighter(); };
void scrollViewDidChangeOffset(ScrollViewDataSource * scrollViewDataSource) override;
void didBecomeFirstResponder() override;
void internalLayoutSubviews(bool force);
private:
int numberOfSubviews() const override { return 2; }
View * subviewAtIndex(int index) override;
@@ -36,15 +37,21 @@ private:
class GutterView : public View {
public:
GutterView(const KDFont * font) : View(), m_font(font), m_offset(0) {}
GutterView(const KDFont * font) : View(), m_font(font), m_offset(0), m_numberOfDigits(2) {}
void drawRect(KDContext * ctx, KDRect rect) const override;
void setOffset(KDCoordinate offset);
KDSize minimalSizeForOptimalDisplay() const override;
bool setOffsetAndNeedResize(KDCoordinate offset); // Return true if the gutter view need to be resized
int computeWidth();
int computeMaxNumberOfDigits();
static int computeNumberOfDigitsFor(int value);
private:
static constexpr KDCoordinate k_margin = 2;
static constexpr int k_lineNumberCharLength = 3;
const KDFont * m_font;
KDCoordinate m_offset;
int m_numberOfDigits;
};
PythonTextArea m_textArea;

View File

@@ -41,6 +41,25 @@ void GlobalPreferences::setBrightnessLevel(int brightnessLevel) {
brightnessLevel = brightnessLevel < 0 ? 0 : brightnessLevel;
brightnessLevel = brightnessLevel > Ion::Backlight::MaxBrightness ? Ion::Backlight::MaxBrightness : brightnessLevel;
m_brightnessLevel = brightnessLevel;
Ion::Backlight::setBrightness(m_brightnessLevel);
}
}
void GlobalPreferences::setIdleBeforeSuspendSeconds(int idleBeforeSuspendSeconds) {
if (m_idleBeforeSuspendSeconds != idleBeforeSuspendSeconds) {
idleBeforeSuspendSeconds = idleBeforeSuspendSeconds < 5 ? 5 : idleBeforeSuspendSeconds;
idleBeforeSuspendSeconds = idleBeforeSuspendSeconds > 7200 ? 7200 : idleBeforeSuspendSeconds;
m_idleBeforeSuspendSeconds = idleBeforeSuspendSeconds;
}
}
void GlobalPreferences::setIdleBeforeDimmingSeconds(int idleBeforeDimmingSeconds) {
if (m_idleBeforeDimmingSeconds != idleBeforeDimmingSeconds) {
idleBeforeDimmingSeconds = idleBeforeDimmingSeconds < 3 ? 3 : idleBeforeDimmingSeconds;
idleBeforeDimmingSeconds = idleBeforeDimmingSeconds > 1200 ? 1200 : idleBeforeDimmingSeconds;
m_idleBeforeDimmingSeconds = idleBeforeDimmingSeconds;
}
}
void GlobalPreferences::setBrightnessShortcut(int brightnessShortcut){
m_brightnessShortcut = brightnessShortcut;
}

View File

@@ -45,6 +45,12 @@ public:
const KDFont * font() const { return m_font; }
void setFont(const KDFont * font) { m_font = font; }
constexpr static int NumberOfBrightnessStates = 15;
int idleBeforeSuspendSeconds() const { return m_idleBeforeSuspendSeconds; }
void setIdleBeforeSuspendSeconds(int m_idleBeforeSuspendSeconds);
int idleBeforeDimmingSeconds() const { return m_idleBeforeDimmingSeconds; }
void setIdleBeforeDimmingSeconds(int m_idleBeforeDimmingSeconds);
int brightnessShortcut() const { return m_brightnessShortcut; }
void setBrightnessShortcut(int m_BrightnessShortcut);
private:
static_assert(I18n::NumberOfLanguages > 0, "I18n::NumberOfLanguages is not superior to 0"); // There should already have been an error when processing an empty EPSILON_I18N flag
static_assert(I18n::NumberOfCountries > 0, "I18n::NumberOfCountries is not superior to 0"); // There should already have been an error when processing an empty EPSILON_COUNTRIES flag
@@ -60,6 +66,9 @@ private:
m_syntaxhighlighting(true),
m_cursorSaving(true),
m_brightnessLevel(Ion::Backlight::MaxBrightness),
m_idleBeforeSuspendSeconds(55),
m_idleBeforeDimmingSeconds(45),
m_brightnessShortcut(4),
m_font(KDFont::LargeFont) {}
I18n::Language m_language;
I18n::Country m_country;
@@ -74,6 +83,9 @@ private:
bool m_syntaxhighlighting;
bool m_cursorSaving;
int m_brightnessLevel;
int m_idleBeforeSuspendSeconds;
int m_idleBeforeDimmingSeconds;
int m_brightnessShortcut;
const KDFont * m_font;
};

View File

@@ -41,7 +41,7 @@ bool ListParameterController::handleEvent(Ion::Events::Event event) {
}
if (event == Ion::Events::Right) {
int selectedR = selectedRow();
if (selectedR == 0 || selectedR == 1) {
if (selectedR == 0 || selectedR == 1 || selectedR == 3) {
// Go in the submenu
return handleEnterOnRow(selectedR);
}

View File

@@ -5,40 +5,42 @@ namespace Reader {
// List of available Symbols
static constexpr char const * k_SymbolsCommands[] = {
"times", "div", "forall", "partial", "exists", "pm", "approx", "infty", "neq", "equiv", "leq", "geq",
"leftarrow", "uparrow", "rightarrow", "downarrow", "leftrightarrow", "updownarrow", "Leftarrow", "Uparrow", "Rightarrow", "Downarrow",
"Alpha", "Beta", "Gamma", "Delta", "Epsilon", "Zeta", "Eta", "Theta", "Iota", "Kappa", "Lambda",
"times", "div", "forall", "partial", "exists", "pm", "approx", "infty", "neq", "equiv", "leq", "geq",
"leftarrow", "uparrow", "rightarrow", "downarrow","leftrightarrow", "updownarrow", "Leftarrow", "Uparrow", "Rightarrow", "Downarrow",
"nwarrow", "nearrow", "swarrow", "searrow", "in", "cdot", "cdots", "ldots",
"Alpha", "Beta", "Gamma", "Delta", "Epsilon", "Zeta", "Eta", "Theta", "Iota", "Kappa", "Lambda",
"Mu", "Nu", "Xi", "Omicron", "Pi", "Rho", "Sigma", "Tau", "Upsilon", "Phi", "Chi", "Psi","Omega",
"alpha", "beta", "gamma", "delta", "epsilon", "zeta", "eta", "theta", "iota", "kappa", "lambda",
"alpha", "beta", "gamma", "delta", "epsilon", "zeta", "eta", "theta", "iota", "kappa", "lambda",
"mu", "nu", "xi", "omicron", "pi", "rho", "sigma", "tau", "upsilon", "phi", "chi", "psi", "omega",
"sim",
};
// List of the available Symbol's CodePoints in the same order of the Symbol's list
static constexpr uint32_t const k_SymbolsCodePoints[] = {
0xd7, 0xf7, 0x2200, 0x2202, 0x2203, 0xb1, 0x2248, 0x221e, 0x2260, 0x2261, 0x2264, 0x2265,
0x2190, 0x2191, 0x2192, 0x2193, 0x2194, 0x2195, 0x21d0, 0x21d1, 0x21d2, 0x21d3,
0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398, 0x399, 0x39a, 0x39b,
0x39c, 0x39d, 0x39e, 0x39f, 0x3a0, 0x3a1, 0x3a3, 0x3a4, 0x3a5, 0x3a6, 0x3a7, 0x3a8, 0x3a9,
0x3b1, 0x3b2, 0x3b3, 0x3b4, 0x3b5, 0x3b6, 0x3b7, 0x3b8, 0x3b9, 0x3ba, 0x3bb,
0xd7, 0xf7, 0x2200, 0x2202, 0x2203, 0xb1, 0x2248, 0x221e, 0x2260, 0x2261, 0x2264, 0x2265,
0x2190, 0x2191, 0x2192, 0x2193, 0x2194, 0x2195, 0x21d0, 0x21d1, 0x21d2, 0x21d3,
0x2196, 0x2197, 0x2198, 0x2199, 0x454, 0xb7, 0x2505, 0x2026,
0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398, 0x399, 0x39a, 0x39b,
0x39c, 0x39d, 0x39e, 0x39f, 0x3a0, 0x3a1, 0x3a3, 0x3a4, 0x3a5, 0x3a6, 0x3a7, 0x3a8, 0x3a9,
0x3b1, 0x3b2, 0x3b3, 0x3b4, 0x3b5, 0x3b6, 0x3b7, 0x3b8, 0x3b9, 0x3ba, 0x3bb,
0x3bc, 0x3bd, 0x3be, 0x3bf, 0x3c0, 0x3c1, 0x3c3, 0x3c4, 0x3c5, 0x3c6, 0x3c7, 0x3c8, 0x3c9,
0x7e,
};
// List of available Function Commands that don't require a specific handling
static constexpr char const * k_FunctionCommands[] = {
"arccos", "arcsin", "arctan", "arg", "cos", "cosh", "cot", "coth",
"csc", "deg", "det", "dim", "exp", "gcd", "hom", "inf",
"ker", "lg", "lim", "liminf", "limsup", "ln", "log", "max",
"arccos", "arcsin", "arctan", "arg", "cos", "cosh", "cot", "coth",
"csc", "deg", "det", "dim", "exp", "gcd", "hom", "inf",
"ker", "lg", "lim", "liminf", "limsup", "ln", "log", "max",
"min", "Pr", "sec", "sin", "sinh", "sup", "tan", "tanh"
};
TexParser::TexParser(const char * text, const char * endOfText) :
m_text(text),
TexParser::TexParser(const char * text, const char * endOfText) :
m_text(text),
m_endOfText(endOfText),
m_hasError(false)
{
}
Layout TexParser::getLayout() {
@@ -78,7 +80,7 @@ Layout TexParser::popBlock() {
Layout TexParser::popText(char stop) {
HorizontalLayout layout = HorizontalLayout::Builder();
const char * start = m_text;
while (m_text < m_endOfText && *m_text != stop) {
switch (*m_text) {
// TODO: Factorize this code
@@ -121,7 +123,7 @@ Layout TexParser::popText(char stop) {
if (start != m_text) {
layout.addOrMergeChildAtIndex(LayoutHelper::String(start, m_text - start), layout.numberOfChildren(), false);
}
m_text ++;
if (layout.numberOfChildren() == 1) {
@@ -149,7 +151,7 @@ Layout TexParser::popCommand() {
if (isCommandEnded(*(m_text + strlen(k_fracCommand)))) {
m_text += strlen(k_fracCommand);
return popFracCommand();
}
}
}
if (strncmp(k_leftCommand, m_text, strlen(k_leftCommand)) == 0) {
if (isCommandEnded(*(m_text + strlen(k_leftCommand)))) {
@@ -199,20 +201,20 @@ Layout TexParser::popCommand() {
return LayoutHelper::String(k_FunctionCommands[i], strlen(k_FunctionCommands[i]));
}
}
}
}
m_hasError = true;
m_hasError = true;
return EmptyLayout::Builder();
}
// Expressions
Layout TexParser::popCeilCommand() {
Layout ceil = popBlock();
Layout ceil = popBlock();
return CeilingLayout::Builder(ceil);
}
Layout TexParser::popFloorCommand() {
Layout floor = popBlock();
Layout floor = popBlock();
return FloorLayout::Builder(floor);
}
@@ -255,7 +257,7 @@ Layout TexParser::popSpaceCommand() {
Layout TexParser::popOverrightarrowCommand() {
return VectorLayout::Builder(popBlock());
}
Layout TexParser::popSymbolCommand(int SymbolIndex) {
uint32_t codePoint = k_SymbolsCodePoints[SymbolIndex];
return CodePointLayout::Builder(codePoint);

View File

@@ -17,6 +17,5 @@ NEnd = "Endwert"
TermSum = "Summe der Terme"
SelectFirstTerm = "Erster Term "
SelectLastTerm = "Letzter Term "
ValueNotReachedBySequence = "Wert wird von Folge nicht erreicht"
NColumn = "n-te Spalte"
FirstTermIndex = "Anfangsindex"

View File

@@ -17,6 +17,5 @@ NEnd = "N end"
TermSum = "Sum of terms"
SelectFirstTerm = "Select First Term "
SelectLastTerm = "Select last term "
ValueNotReachedBySequence = "Value not reached by sequence"
NColumn = "n column"
FirstTermIndex = "First term index"

View File

@@ -17,6 +17,5 @@ NEnd = "N fin"
TermSum = "Suma de términos"
SelectFirstTerm = "Seleccionar el primer término "
SelectLastTerm = "Seleccionar el último término "
ValueNotReachedBySequence = "No se alcanza este valor"
NColumn = "Columna n"
FirstTermIndex = "Índice del primer término"

View File

@@ -17,6 +17,5 @@ NEnd = "N fin"
TermSum = "Somme des termes"
SelectFirstTerm = "Sélectionner le premier terme "
SelectLastTerm = "Sélectionner le dernier terme "
ValueNotReachedBySequence = "Valeur non atteinte par la suite"
NColumn = "Colonne n"
FirstTermIndex = "Indice premier terme"

View File

@@ -1,22 +1,21 @@
SequenceApp = "Szekvenciák"
SequenceAppCapital = "SZEKVENCIÁK"
SequenceTab = "Szekvenciák"
AddSequence = "Szekvencia hozzáadása"
ChooseSequenceType = "Válassza ki a sorozat típusát"
SequenceType = "Szekvencia típusa"
Explicit = "Explicit kifejezés"
SingleRecurrence = "Rekurzív elsö sorrend"
DoubleRecurrence = "Rekurzív második sorrend"
SequenceOptions = "Szekvencia opciók"
SequenceColor = "Szekvencia színe"
DeleteSequence = "Sorozat törlése"
NoSequence = "Nincs sorrend"
NoActivatedSequence = "Nincs szekvencia bekapcsolva"
NStart = "N start"
NEnd = "N vég"
TermSum = "A kifejezés összege"
SelectFirstTerm = "Elsö kifejezés kiválasztása "
SelectLastTerm = "Utolsó kifejezés kiválasztása "
ValueNotReachedBySequence = "Az értéket nem érte el a sorozat"
NColumn = "n oszlop"
FirstTermIndex = "Elsö kifejezés index"
SequenceApp = "Szekvenciák"
SequenceAppCapital = "SZEKVENCIÁK"
SequenceTab = "Szekvenciák"
AddSequence = "Szekvencia hozzáadása"
ChooseSequenceType = "Válassza ki a sorozat típusát"
SequenceType = "Szekvencia típusa"
Explicit = "Explicit kifejezés"
SingleRecurrence = "Rekurzív elsö sorrend"
DoubleRecurrence = "Rekurzív második sorrend"
SequenceOptions = "Szekvencia opciók"
SequenceColor = "Szekvencia színe"
DeleteSequence = "Sorozat törlése"
NoSequence = "Nincs sorrend"
NoActivatedSequence = "Nincs szekvencia bekapcsolva"
NStart = "N start"
NEnd = "N vég"
TermSum = "A kifejezés összege"
SelectFirstTerm = "Elsö kifejezés kiválasztása "
SelectLastTerm = "Utolsó kifejezés kiválasztása "
NColumn = "n oszlop"
FirstTermIndex = "Elsö kifejezés index"

View File

@@ -17,6 +17,5 @@ NEnd = "N finale"
TermSum = "Somma dei termini"
SelectFirstTerm = "Selezionare il primo termine "
SelectLastTerm = "Selezionare l'ultimo termine "
ValueNotReachedBySequence = "Valore non raggiunto dalla successione"
NColumn = "Colonna n"
FirstTermIndex = "Indice del primo termine"

View File

@@ -17,6 +17,5 @@ NEnd = "N einde"
TermSum = "Som van termen"
SelectFirstTerm = "Selecteer eerste term "
SelectLastTerm = "Selecteer laatste term "
ValueNotReachedBySequence = "Waarde niet bereikt door de rij"
NColumn = "n-kolom"
FirstTermIndex = "Eerste termindex"

View File

@@ -17,6 +17,5 @@ NEnd = "N fim"
TermSum = "Soma dos termos"
SelectFirstTerm = "Selecionar primeiro termo "
SelectLastTerm = "Selecionar último termo "
ValueNotReachedBySequence = "O valor não é alcançado pela sequência"
NColumn = "Coluna n"
FirstTermIndex = "Índice do primeiro termo"

View File

@@ -24,38 +24,18 @@ const char * ListParameterController::title() {
bool ListParameterController::handleEvent(Ion::Events::Event event) {
bool hasAdditionalRow = hasInitialRankRow();
#if FUNCTION_COLOR_CHOICE
if (event == Ion::Events::OK || event == Ion::Events::EXE || (event == Ion::Events::Right && selectedRow() == 1)) {
#else
if (event == Ion::Events::OK || event == Ion::Events::EXE || (event == Ion::Events::Right && selectedRow() == 0)) {
#endif
int selectedRowIndex = selectedRow();
#if FUNCTION_COLOR_CHOICE
if (selectedRowIndex == 0) {
return handleEnterOnRow(selectedRowIndex);
}
if (selectedRowIndex == 1) {
#else
if (selectedRowIndex == 0) {
#endif
StackViewController * stack = (StackViewController *)(parentResponder());
m_typeParameterController.setRecord(m_record);
stack->push(&m_typeParameterController);
return true;
}
#if FUNCTION_COLOR_CHOICE
if (selectedRowIndex == 2+hasAdditionalRow) {
#else
if (selectedRowIndex == 1+hasAdditionalRow) {
#endif
if (selectedRowIndex == 1+hasAdditionalRow || selectedRowIndex == 2+hasAdditionalRow) {
return handleEnterOnRow(selectedRowIndex-hasAdditionalRow-1);
}
#if FUNCTION_COLOR_CHOICE
if (selectedRowIndex == 3+hasAdditionalRow) {
#else
if (selectedRowIndex == 2+hasAdditionalRow) {
#endif
App::app()->localContext()->resetCache();
return handleEnterOnRow(selectedRowIndex-hasAdditionalRow-1);
}

View File

@@ -25,11 +25,7 @@ public:
HighlightCell * reusableCell(int index, int type) override;
void willDisplayCellForIndex(HighlightCell * cell, int index) override;
private:
#if FUNCTION_COLOR_CHOICE
constexpr static int k_totalNumberOfCell = 5;
#else
constexpr static int k_totalNumberOfCell = 4;
#endif
int totalNumberOfCells() const override;
Shared::Sequence * sequence() { return static_cast<Shared::Sequence *>(function().pointer()); }
bool hasInitialRankRow() const;

View File

@@ -26,6 +26,7 @@ app_settings_src = $(addprefix apps/settings/,\
sub_menu/math_options_controller.cpp \
sub_menu/selectable_view_with_messages.cpp \
sub_menu/usb_protection_controller.cpp \
sub_menu/brightness_controller.cpp\
)
SFLAGS += -DOMEGA_STATE="$(OMEGA_STATE)"

View File

@@ -32,6 +32,7 @@ Real = "Reell "
Cartesian = "Kartesisch "
Polar = "Polar "
Brightness = "Helligkeit"
BrightnessSettings = "Helligkeitseinstellungen"
SoftwareVersion = "Epsilon version"
UpsilonVersion = "Upsilon version"
OmegaVersion = "Omega version"
@@ -62,7 +63,6 @@ SymbolFunction = "Ausdrucksformat "
SymbolDefaultFunction = "Standardl "
SymbolArgFunction = "Leer "
SymbolArgDefaultFunction = "Argument "
PythonFont = "Python Schriftart"
MemUse = "Speicher"
DateTime = "Datum/Uhrzeit"
ActivateClock = "Uhr aktivieren"
@@ -80,3 +80,7 @@ USBProtectionLevel = "Akzeptierte Updates"
USBDefaultLevel = "Basierend auf Upsilon"
USBLowLevel = "Basierend auf Omega"
USBParanoidLevel = "Nichts"
Normal = "Normal"
IdleTimeBeforeDimming = "Abdunkeln nach (s)"
IdleTimeBeforeSuspend = "Anhalten nach (s)"
BrightnessShortcut = "Tastenkombinationsschritte"

View File

@@ -32,6 +32,7 @@ Real = "Real "
Cartesian = "Cartesian "
Polar = "Polar "
Brightness = "Brightness"
BrightnessSettings = "Brightness settings"
SoftwareVersion = "Epsilon version"
UpsilonVersion = "Upsilon version"
OmegaVersion = "Omega version"
@@ -62,7 +63,6 @@ SymbolFunction = "Expression format "
SymbolDefaultFunction = "Default "
SymbolArgFunction = "Empty "
SymbolArgDefaultFunction = "Argument "
PythonFont = "Python Font"
MemUse = "Memory"
DateTime = "Date/time"
ActivateClock = "Activate clock"
@@ -80,3 +80,7 @@ USBProtectionLevel = "Updates accepted"
USBDefaultLevel = "Based on Upsilon"
USBLowLevel = "Based on Omega"
USBParanoidLevel = "None"
Normal = "Normal"
IdleTimeBeforeDimming = "Dim after (s)"
IdleTimeBeforeSuspend = "Suspend after (s)"
BrightnessShortcut = "Shortcut steps"

View File

@@ -32,6 +32,7 @@ Real = "Real "
Cartesian = "Binómica "
Polar = "Polar "
Brightness = "Brillo"
BrightnessSettings = "Configuración de brillo"
SoftwareVersion = "Versión de Epsilon"
UpsilonVersion = "Versión de Upsilon"
OmegaVersion = "Versión de Omega"
@@ -62,7 +63,6 @@ SymbolFunction = "Formato expresión "
SymbolDefaultFunction = "Defecto "
SymbolArgFunction = "Vacío "
SymbolArgDefaultFunction = "Argumento "
PythonFont = "Fuente Python"
MemUse = "Memoria"
DateTime = "Fecha/Hora"
ActivateClock = "Activar el reloj"
@@ -80,3 +80,7 @@ USBProtectionLevel = "Actualizaciones aceptadas"
USBDefaultLevel = "Basado en Upsilon"
USBLowLevel = "Basado en Omega"
USBParanoidLevel = "Ninguno"
Normal = "Normal"
IdleTimeBeforeDimming = "Oscurecer después de (s)"
IdleTimeBeforeSuspend = "Suspender después de (s)"
BrightnessShortcut = "Pasos de acceso directo"

View File

@@ -32,6 +32,7 @@ Real = "Réel "
Cartesian = "Algébrique "
Polar = "Exponentielle "
Brightness = "Luminosité"
BrightnessSettings = "Paramètres de luminosité"
SoftwareVersion = "Version d'Epsilon"
UpsilonVersion = "Version d'Upsilon"
OmegaVersion = "Version d'Omega"
@@ -62,7 +63,6 @@ SymbolFunction = "Format expression "
SymbolDefaultFunction = "Défaut "
SymbolArgFunction = "Vide "
SymbolArgDefaultFunction = "Arguments "
PythonFont = "Police Python"
MemUse = "Mémoire"
DateTime = "Date/heure"
ActivateClock = "Activer horloge"
@@ -80,3 +80,7 @@ USBProtectionLevel = "Mise à jour acceptées"
USBDefaultLevel = "Basées sur Upsilon"
USBLowLevel = "Basées sur Omega"
USBParanoidLevel = "Aucune"
Normal = "Normale"
IdleTimeBeforeDimming = "Assombrir après (s)"
IdleTimeBeforeSuspend = "Éteindre après (s)"
BrightnessShortcut = "Étapes du raccourci"

View File

@@ -1,82 +1,86 @@
SettingsApp = "Beállítások"
SettingsAppCapital = "BEÁLLÍTÁSOK"
AngleUnit = "Szögmérö"
DisplayMode = "Eredmény formátuma"
EditionMode = "Írás formátuma"
EditionLinear = "Lineáris"
Edition2D = "Természetes"
ComplexFormat = "Komplex formátum"
ExamMode = "Vizsga mód"
ExamModeActive = "A vizsgamód újraaktiválása"
ToDeactivateExamMode1 = "a vizsga mód kikapcsoláshoz"
ToDeactivateExamMode2 = "csatlakoztassa a számológépet a számítógéphez"
ToDeactivateExamMode3 = "vagy egy konnektorhoz."
# --------------------- Please do not edit these messages ---------------------
ExamModeWarning1 = "Vigyázat: a használt szoftver nem"
ExamModeWarning2 = "hivatalos, Numworks nem garantálja"
ExamModeWarning3 = "a vizsgálati mód megfelelőségét."
AboutWarning1 = "Vigyázat: a használt szoftver"
AboutWarning2 = "nem hivatalos. A NumWorks nem"
AboutWarning3 = "vállal felelösséget az"
AboutWarning4 = "esetleges károkért."
# -----------------------------------------------------------------------------
About = "Apropó"
Degrees = "Fokok "
Gradians = "Gradiens "
Radian = "Radián "
Decimal = "Tizedes "
Scientific = "Tudományos "
Engineering = "Mérnökség "
SignificantFigures = "Tizedes számok "
Real = "Valódi "
Cartesian = "Kartéziánus "
Polar = "Poláris "
Brightness = "Fényerö"
SoftwareVersion = "Epsilon verzió"
UpsilonVersion = "Upsilon verzió"
OmegaVersion = "Omega verzió"
Username = "Felhasználónév"
MicroPythonVersion = "µPython verzió"
FontSizes = "Python betü méret"
LargeFont = "Nagy "
SmallFont = "Kicsi "
SerialNumber = "Sorozatszám"
UpdatePopUp = "Frissítés figyelmeztetés"
BetaPopUp = "Béta figyelmeztetés"
Contributors = "Közremüködök"
Battery = "Akkumulátor"
Accessibility = "Több vizuális beállitások"
AccessibilityInvertColors = "Invertált színek"
AccessibilityMagnify = "Nagyító"
AccessibilityGamma = "Gamma korrekció"
AccessibilityGammaRed = "Piros gamma"
AccessibilityGammaGreen = "Zöld gamma"
AccessibilityGammaBlue = "Kék gamma"
MathOptions = "Matematikai beállítások"
SymbolMultiplication = "Szorzás"
SymbolMultiplicationCross = "Kereszt "
SymbolMultiplicationMiddleDot = "Pont "
SymbolMultiplicationStar = "Csillag "
SymbolMultiplicationAutoSymbol = "Automatitus "
SymbolFunction = "Kifejezés "
SymbolDefaultFunction = "Alap "
SymbolArgFunction = "Üres "
SymbolArgDefaultFunction = "Argumentummal "
PythonFont = "Python Betütipus"
MemUse = "Memória"
DateTime = "Dátum/óra"
ActivateClock = "Óra bekapcsolása"
Date = "Datum"
Time = "Óra"
RTCWarning1 = "Amikor a számológép alvómódban van, az óra"
RTCWarning2 = "használása az elemet gyorsabban meríti ki."
SyntaxHighlighting = "Szintaxis kiemelés"
CursorSaving = "Kurzor mentése"
USBExplanation1 = "Az USB-védelem megvédi"
USBExplanation2 = "a számológépet a nem"
USBExplanation3 = "szándékos reteszeléstől"
USBProtection = "USB védelem"
USBProtectionLevel = "Elfogadott frissítések"
USBDefaultLevel = "Upsilon alapján"
USBLowLevel = "Omega alapján"
USBParanoidLevel = "Egyik sem"
SettingsApp = "Beállítások"
SettingsAppCapital = "BEÁLLÍTÁSOK"
AngleUnit = "Szögmérö"
DisplayMode = "Eredmény formátuma"
EditionMode = "Írás formátuma"
EditionLinear = "Lineáris"
Edition2D = "Természetes"
ComplexFormat = "Komplex formátum"
ExamMode = "Vizsga mód"
ExamModeActive = "A vizsgamód újraaktiválása"
ToDeactivateExamMode1 = "a vizsga mód kikapcsoláshoz"
ToDeactivateExamMode2 = "csatlakoztassa a számológépet a számítógéphez"
ToDeactivateExamMode3 = "vagy egy konnektorhoz."
# --------------------- Please do not edit these messages ---------------------
ExamModeWarning1 = "Vigyázat: a használt szoftver nem"
ExamModeWarning2 = "hivatalos, Numworks nem garantálja"
ExamModeWarning3 = "a vizsgálati mód megfelelőségét."
AboutWarning1 = "Vigyázat: a használt szoftver"
AboutWarning2 = "nem hivatalos. A NumWorks nem"
AboutWarning3 = "vállal felelösséget az"
AboutWarning4 = "esetleges károkért."
# -----------------------------------------------------------------------------
About = "Apropó"
Degrees = "Fokok "
Gradians = "Gradiens "
Radian = "Radián "
Decimal = "Tizedes "
Scientific = "Tudományos "
Engineering = "Mérnökség "
SignificantFigures = "Tizedes számok "
Real = "Valódi "
Cartesian = "Kartéziánus "
Polar = "Poláris "
Brightness = "Fényerö"
BrightnessSettings = "Fényerő beállításai"
SoftwareVersion = "Epsilon verzió"
UpsilonVersion = "Upsilon verzió"
OmegaVersion = "Omega verzió"
Username = "Felhasználónév"
MicroPythonVersion = "µPython verzió"
FontSizes = "Python betü méret"
LargeFont = "Nagy "
SmallFont = "Kicsi "
SerialNumber = "Sorozatszám"
UpdatePopUp = "Frissítés figyelmeztetés"
BetaPopUp = "Béta figyelmeztetés"
Contributors = "Közremüködök"
Battery = "Akkumulátor"
Accessibility = "Több vizuális beállitások"
AccessibilityInvertColors = "Invertált színek"
AccessibilityMagnify = "Nagyító"
AccessibilityGamma = "Gamma korrekció"
AccessibilityGammaRed = "Piros gamma"
AccessibilityGammaGreen = "Zöld gamma"
AccessibilityGammaBlue = "Kék gamma"
MathOptions = "Matematikai beállítások"
SymbolMultiplication = "Szorzás"
SymbolMultiplicationCross = "Kereszt "
SymbolMultiplicationMiddleDot = "Pont "
SymbolMultiplicationStar = "Csillag "
SymbolMultiplicationAutoSymbol = "Automatitus "
SymbolFunction = "Kifejezés "
SymbolDefaultFunction = "Alap "
SymbolArgFunction = "Üres "
SymbolArgDefaultFunction = "Argumentummal "
MemUse = "Memória"
DateTime = "Dátum/óra"
ActivateClock = "Óra bekapcsolása"
Date = "Datum"
Time = "Óra"
RTCWarning1 = "Amikor a számológép alvómódban van, az óra"
RTCWarning2 = "használása az elemet gyorsabban meríti ki."
SyntaxHighlighting = "Szintaxis kiemelés"
CursorSaving = "Kurzor mentése"
USBExplanation1 = "Az USB-védelem megvédi"
USBExplanation2 = "a számológépet a nem"
USBExplanation3 = "szándékos reteszeléstől"
USBProtection = "USB védelem"
USBProtectionLevel = "Elfogadott frissítések"
USBDefaultLevel = "Upsilon alapján"
USBLowLevel = "Omega alapján"
USBParanoidLevel = "Egyik sem"
Normal = "Normale"
IdleTimeBeforeDimming = "Assombrir après (s)"
IdleTimeBeforeSuspend = "Éteindre après (s)"
BrightnessShortcut = "Parancsikon lépések"

View File

@@ -32,6 +32,7 @@ Real = "Reale "
Cartesian = "Algebrico "
Polar = "Esponenziale "
Brightness = "Luminosità"
BrightnessSettings = "Impostazioni di luminosità"
SoftwareVersion = "Epsilon version"
UpsilonVersion = "Upsilon version"
OmegaVersion = "Omega version"
@@ -62,7 +63,6 @@ SymbolFunction = "Expression format "
SymbolDefaultFunction = "Default "
SymbolArgFunction = "Empty "
SymbolArgDefaultFunction = "Argument "
PythonFont = "Python Font"
MemUse = "Memory"
DateTime = "Date/time"
ActivateClock = "Activate clock"
@@ -80,3 +80,7 @@ USBProtectionLevel = "Aggiornamenti accettati"
USBDefaultLevel = "Basato su Upsilon"
USBLowLevel = "A base di Omega"
USBParanoidLevel = "Nessuno"
Normal = "Normale"
IdleTimeBeforeDimming = "Scurisci dopo (s)"
IdleTimeBeforeSuspend = "Sospendi dopo (s)"
BrightnessShortcut = "Passaggi di scelta rapida"

View File

@@ -32,6 +32,7 @@ Real = "Reëel "
Cartesian = "Cartesisch "
Polar = "Polair "
Brightness = "Helderheid"
BrightnessSettings = "Helderheidsinstellingen"
SoftwareVersion = "Epsilon version"
UpsilonVersion = "Upsilon version"
OmegaVersion = "Omega version"
@@ -62,7 +63,6 @@ SymbolFunction = "Expression format "
SymbolDefaultFunction = "Default "
SymbolArgFunction = "Empty "
SymbolArgDefaultFunction = "Argument "
PythonFont = "Python Font"
MemUse = "Memory"
DateTime = "Date/time"
ActivateClock = "Activate clock"
@@ -80,3 +80,7 @@ USBProtectionLevel = "Updates geaccepteerd"
USBDefaultLevel = "Gebaseerd op Upsilon"
USBLowLevel = "Op basis van Omega"
USBParanoidLevel = "Geen"
Normal = "Normaal"
IdleTimeBeforeDimming = "Donkerder maken na (s)"
IdleTimeBeforeSuspend = "Suspend after (s)"
BrightnessShortcut = "Snelkoppelingsstappen"

View File

@@ -32,6 +32,7 @@ Real = "Real "
Cartesian = "Cartesiana "
Polar = "Polar "
Brightness = "Brilho"
BrightnessSettings = "Configurações de brilho"
SoftwareVersion = "Versão do Epsilon"
UpsilonVersion = "Versão do Upsilon"
OmegaVersion = "Versão do Omega"
@@ -62,7 +63,6 @@ SymbolFunction = "Formato expressão "
SymbolDefaultFunction = "Padrão "
SymbolArgFunction = "Vazio "
SymbolArgDefaultFunction = "Argumento "
PythonFont = "Fonte Python"
MemUse = "Memória"
DateTime = "Date/time"
ActivateClock = "Activate clock"
@@ -80,3 +80,7 @@ USBProtectionLevel = "Atualizações aceitas"
USBDefaultLevel = "Baseado em Upsilon"
USBLowLevel = "Baseado em Ômega"
USBParanoidLevel = "Nenhum"
Normal = "Normal"
IdleTimeBeforeDimming = "Diminuir depois (s)"
IdleTimeBeforeSuspend = "Suspender depois (s)"
BrightnessShortcut = "Passos de atalho"

View File

@@ -19,6 +19,7 @@ constexpr SettingsMessageTree s_usbProtectionChildren[2] = {SettingsMessageTree(
constexpr SettingsMessageTree s_usbProtectionLevelChildren[3] = {SettingsMessageTree(I18n::Message::USBDefaultLevel), SettingsMessageTree(I18n::Message::USBLowLevel), SettingsMessageTree(I18n::Message::USBParanoidLevel)};
constexpr SettingsMessageTree s_symbolFunctionChildren[3] = {SettingsMessageTree(I18n::Message::SymbolDefaultFunction), SettingsMessageTree(I18n::Message::SymbolArgDefaultFunction), SettingsMessageTree(I18n::Message::SymbolArgFunction)};
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_brightnessChildren[4] = {SettingsMessageTree(I18n::Message::Brightness), SettingsMessageTree(I18n::Message::IdleTimeBeforeDimming), SettingsMessageTree(I18n::Message::IdleTimeBeforeSuspend), SettingsMessageTree(I18n::Message::BrightnessShortcut)};
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[18] = {SettingsMessageTree(I18n::Message::LaurianFournier), SettingsMessageTree(I18n::Message::YannCouturier), SettingsMessageTree(I18n::Message::DavidLuca), SettingsMessageTree(I18n::Message::LoicE), SettingsMessageTree(I18n::Message::VictorKretz), 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)};
@@ -32,10 +33,10 @@ constexpr SettingsMessageTree s_modelAboutChildren[10] = {SettingsMessageTree(I1
MainController::MainController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate) :
ViewController(parentResponder),
m_brightnessCell(I18n::Message::Default, KDFont::LargeFont),
m_popUpCell(I18n::Message::Default, KDFont::LargeFont),
m_selectableTableView(this),
m_mathOptionsController(this, inputEventHandlerDelegate),
m_brightnessController(this, inputEventHandlerDelegate),
m_localizationController(this, Metric::CommonTopMargin, LocalizationController::Mode::Language),
m_accessibilityController(this),
m_dateTimeController(this),
@@ -63,13 +64,6 @@ void MainController::didBecomeFirstResponder() {
bool MainController::handleEvent(Ion::Events::Event event) {
GlobalPreferences * globalPreferences = GlobalPreferences::sharedGlobalPreferences();
if (event == Ion::Events::BrightnessPlus || event == Ion::Events::BrightnessMinus){
int delta = Ion::Backlight::MaxBrightness/GlobalPreferences::NumberOfBrightnessStates;
int direction = (event == Ion::Events::BrightnessPlus) ? Ion::Backlight::NumberOfStepsPerShortcut*delta : -delta*Ion::Backlight::NumberOfStepsPerShortcut;
GlobalPreferences::sharedGlobalPreferences()->setBrightnessLevel(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()+direction);
m_selectableTableView.reloadCellAtLocation(m_selectableTableView.selectedColumn(), 1);
return true;
}
if (model()->childAtIndex(selectedRow())->numberOfChildren() == 0) {
if (model()->childAtIndex(selectedRow())->label() == promptMessage()) {
if (event == Ion::Events::OK || event == Ion::Events::EXE || event == Ion::Events::Right) {
@@ -79,16 +73,6 @@ bool MainController::handleEvent(Ion::Events::Event event) {
}
return false;
}
if (model()->childAtIndex(selectedRow())->label() == I18n::Message::Brightness) {
if (event == Ion::Events::Right || event == Ion::Events::Left || event == Ion::Events::Plus || event == Ion::Events::Minus) {
int delta = Ion::Backlight::MaxBrightness/GlobalPreferences::NumberOfBrightnessStates;
int direction = (event == Ion::Events::Right || event == Ion::Events::Plus) ? delta : -delta;
globalPreferences->setBrightnessLevel(globalPreferences->brightnessLevel()+direction);
m_selectableTableView.reloadCellAtLocation(m_selectableTableView.selectedColumn(), m_selectableTableView.selectedRow());
return true;
}
return false;
}
if (model()->childAtIndex(selectedRow())->label() == I18n::Message::Language || model()->childAtIndex(selectedRow())->label() == I18n::Message::Country) {
if (event == Ion::Events::OK || event == Ion::Events::EXE || event == Ion::Events::Right) {
m_localizationController.setMode(model()->childAtIndex(selectedRow())->label() == I18n::Message::Language ? LocalizationController::Mode::Language : LocalizationController::Mode::Country);
@@ -107,6 +91,8 @@ bool MainController::handleEvent(Ion::Events::Event event) {
subController = &m_examModeController;
} else if (title == I18n::Message::About) {
subController = &m_aboutController;
} else if (title == I18n::Message::BrightnessSettings) {
subController = &m_brightnessController;
} else if (title == I18n::Message::Accessibility) {
subController = &m_accessibilityController;
} else if (title == I18n::Message::DateTime) {
@@ -140,11 +126,7 @@ KDCoordinate MainController::rowHeight(int j) {
}
KDCoordinate MainController::cumulatedHeightFromIndex(int j) {
KDCoordinate height = j * rowHeight(0);
if (j > k_indexOfBrightnessCell) {
height += CellWithSeparator::k_margin;
}
return height;
return j * rowHeight(0);
}
int MainController::indexFromCumulatedHeight(KDCoordinate offsetY) {
@@ -161,11 +143,8 @@ HighlightCell * MainController::reusableCell(int index, int type) {
return &m_cells[index];
}
assert(index == 0);
if (type == 2) {
return &m_popUpCell;
}
assert(type == 1);
return &m_brightnessCell;
assert(type == 2);
return &m_popUpCell;
}
int MainController::reusableCellCount(int type) {

View File

@@ -13,6 +13,7 @@
#include "sub_menu/math_options_controller.h"
#include "sub_menu/preferences_controller.h"
#include "sub_menu/usb_protection_controller.h"
#include "sub_menu/brightness_controller.h"
namespace Settings {
@@ -31,6 +32,7 @@ extern const Shared::SettingsMessageTree s_contributorsChildren[18];
extern const Shared::SettingsMessageTree s_modelAboutChildren[10];
extern const Shared::SettingsMessageTree s_usbProtectionChildren[2];
extern const Shared::SettingsMessageTree s_usbProtectionLevelChildren[3];
extern const Shared::SettingsMessageTree s_brightnessChildren[4];
extern const Shared::SettingsMessageTree s_model;
class MainController : public ViewController, public ListViewDataSource, public SelectableTableViewDataSource {
@@ -66,12 +68,12 @@ private:
StackViewController * stackController() const;
I18n::Message promptMessage() const;
bool hasPrompt() const { return promptMessage() != I18n::Message::Default; }
constexpr static int k_numberOfSimpleChevronCells = 9;
constexpr static int k_numberOfSimpleChevronCells = 10;
MessageTableCellWithChevronAndMessage m_cells[k_numberOfSimpleChevronCells];
MessageTableCellWithGaugeWithSeparator m_brightnessCell;
MessageTableCellWithSwitch m_popUpCell;
SelectableTableView m_selectableTableView;
MathOptionsController m_mathOptionsController;
BrightnessController m_brightnessController;
LocalizationController m_localizationController;
AccessibilityController m_accessibilityController;
DateTimeController m_dateTimeController;

View File

@@ -8,7 +8,7 @@ namespace Settings {
constexpr SettingsMessageTree s_modelMenu[] =
{SettingsMessageTree(I18n::Message::MathOptions, s_modelMathOptionsChildren),
SettingsMessageTree(I18n::Message::Brightness),
SettingsMessageTree(I18n::Message::BrightnessSettings, s_brightnessChildren),
SettingsMessageTree(I18n::Message::DateTime, s_modelDateTimeChildren),
SettingsMessageTree(I18n::Message::Language),
SettingsMessageTree(I18n::Message::Country),

View File

@@ -9,7 +9,7 @@ namespace Settings {
constexpr SettingsMessageTree s_modelMenu[] =
{SettingsMessageTree(I18n::Message::MathOptions, s_modelMathOptionsChildren),
SettingsMessageTree(I18n::Message::Brightness),
SettingsMessageTree(I18n::Message::BrightnessSettings, s_brightnessChildren),
SettingsMessageTree(I18n::Message::DateTime, s_modelDateTimeChildren),
SettingsMessageTree(I18n::Message::Language),
SettingsMessageTree(I18n::Message::Country),

View File

@@ -8,14 +8,14 @@ using namespace Shared;
constexpr SettingsMessageTree s_modelMenu[] =
{SettingsMessageTree(I18n::Message::MathOptions, s_modelMathOptionsChildren),
SettingsMessageTree(I18n::Message::Brightness),
SettingsMessageTree(I18n::Message::BrightnessSettings, s_brightnessChildren),
SettingsMessageTree(I18n::Message::DateTime, s_modelDateTimeChildren),
SettingsMessageTree(I18n::Message::Language),
SettingsMessageTree(I18n::Message::Country),
SettingsMessageTree(I18n::Message::ExamMode, ExamModeConfiguration::s_modelExamChildren),
#ifdef HAS_CODE
SettingsMessageTree(I18n::Message::CodeApp, s_codeChildren),
#endif
#endif
SettingsMessageTree(I18n::Message::UpdatePopUp),
SettingsMessageTree(I18n::Message::Accessibility, s_accessibilityChildren),
SettingsMessageTree(I18n::Message::UsbSetting, s_usbProtectionChildren),

View File

@@ -0,0 +1,142 @@
#include "brightness_controller.h"
#include "../../global_preferences.h"
#include "../../apps_container.h"
#include "../../shared/poincare_helpers.h"
#include <assert.h>
#include <cmath>
#include "../app.h"
#include <apps/shared/text_field_delegate_app.h>
#include <poincare/integer.h>
using namespace Poincare;
using namespace Shared;
namespace Settings {
BrightnessController::BrightnessController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate) :
GenericSubController(parentResponder),
m_brightnessCell(I18n::Message::Brightness, KDFont::LargeFont),
m_editableCellIdleBeforeDimmingSeconds(&m_selectableTableView, inputEventHandlerDelegate, this),
m_editableCellIdleBeforeSuspendSeconds(&m_selectableTableView, inputEventHandlerDelegate, this),
m_BrightnessShortcutCell(&m_selectableTableView, inputEventHandlerDelegate, this)
{
m_editableCellIdleBeforeDimmingSeconds.setMessage(I18n::Message::IdleTimeBeforeDimming);
m_editableCellIdleBeforeDimmingSeconds.setMessageFont(KDFont::LargeFont);
m_editableCellIdleBeforeSuspendSeconds.setMessage(I18n::Message::IdleTimeBeforeSuspend);
m_editableCellIdleBeforeSuspendSeconds.setMessageFont(KDFont::LargeFont);
m_BrightnessShortcutCell.setMessage(I18n::Message::BrightnessShortcut);
m_BrightnessShortcutCell.setMessageFont(KDFont::LargeFont);
}
HighlightCell * BrightnessController::reusableCell(int index, int type) {
HighlightCell * editableCell[] = {
&m_brightnessCell,
&m_editableCellIdleBeforeDimmingSeconds,
&m_editableCellIdleBeforeSuspendSeconds,
&m_BrightnessShortcutCell
};
return editableCell[index];
}
int BrightnessController::reusableCellCount(int type) {
switch(type) {
case 0:
case 1:
return k_totalNumberOfCell;
default:
assert(false);
return 0;
}
}
void BrightnessController::willDisplayCellForIndex(HighlightCell * cell, int index) {
if(index == 0){
MessageTableCellWithGauge * myGaugeCell = (MessageTableCellWithGauge *)cell;
GaugeView * myGauge = (GaugeView *)myGaugeCell->accessoryView();
myGauge->setLevel((float)GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()/(float)Ion::Backlight::MaxBrightness);
return;
} else {
MessageTableCellWithEditableText * myCell = (MessageTableCellWithEditableText *)cell;
GenericSubController::willDisplayCellForIndex(myCell, index);
char buffer[5];
int val;
switch(index){
case 1:{
val = GlobalPreferences::sharedGlobalPreferences()->idleBeforeDimmingSeconds();
break;
}
case 2:{
val = GlobalPreferences::sharedGlobalPreferences()->idleBeforeSuspendSeconds();
break;
}
case 3:{
val = GlobalPreferences::sharedGlobalPreferences()->brightnessShortcut();
break;
}
default:
assert(false);
}
Poincare::Integer(val).serialize(buffer, 5);
myCell->setAccessoryText(buffer);
}
}
bool BrightnessController::handleEvent(Ion::Events::Event event) {
if ((selectedRow() == 0) && (event == Ion::Events::Right || event == Ion::Events::Left || event == Ion::Events::Plus || event == Ion::Events::Minus)) {
int delta = Ion::Backlight::MaxBrightness/GlobalPreferences::NumberOfBrightnessStates;
int direction = (event == Ion::Events::Right || event == Ion::Events::Plus) ? delta : -delta;
GlobalPreferences::sharedGlobalPreferences()->setBrightnessLevel(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()+direction);
m_selectableTableView.reloadCellAtLocation(m_selectableTableView.selectedColumn(), m_selectableTableView.selectedRow());
return true;
}
if (event == Ion::Events::BrightnessPlus || event == Ion::Events::BrightnessMinus){
int delta = Ion::Backlight::MaxBrightness/GlobalPreferences::NumberOfBrightnessStates;
int NumberOfStepsPerShortcut = GlobalPreferences::sharedGlobalPreferences()->brightnessShortcut();
int direction = (event == Ion::Events::BrightnessPlus) ? NumberOfStepsPerShortcut*delta : -delta*NumberOfStepsPerShortcut;
GlobalPreferences::sharedGlobalPreferences()->setBrightnessLevel(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()+direction);
m_selectableTableView.reloadCellAtLocation(m_selectableTableView.selectedColumn(), 0);
return true;
}
return false;
}
bool BrightnessController::textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) {
return ((event == Ion::Events::Up && selectedRow() > 0) || (event == Ion::Events::Down && selectedRow() < k_totalNumberOfCell - 1))
|| TextFieldDelegate::textFieldShouldFinishEditing(textField, event);
}
bool BrightnessController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) {
double floatBody;
if (textFieldDelegateApp()->hasUndefinedValue(text, floatBody)) {
return false;
}
int val = std::round(floatBody);
switch (selectedRow()) {
case 1:
GlobalPreferences::sharedGlobalPreferences()->setIdleBeforeDimmingSeconds(val);
m_editableCellIdleBeforeDimmingSeconds.setAccessoryText(text);
break;
case 2:
GlobalPreferences::sharedGlobalPreferences()->setIdleBeforeSuspendSeconds(val);
m_editableCellIdleBeforeSuspendSeconds.setAccessoryText(text);
break;
case 3:{
if(val > GlobalPreferences::NumberOfBrightnessStates){ val = GlobalPreferences::NumberOfBrightnessStates;
} else if (val < 0){val = 0;}
GlobalPreferences::sharedGlobalPreferences()->setBrightnessShortcut(val);
m_BrightnessShortcutCell.setAccessoryText(text);
break;
}
default:
assert(false);
}
AppsContainer * myContainer = AppsContainer::sharedAppsContainer();
myContainer->refreshPreferences();
m_selectableTableView.reloadCellAtLocation(0, selectedRow());
if (event == Ion::Events::Up || event == Ion::Events::Down || event == Ion::Events::OK) {
m_selectableTableView.handleEvent(event);
}
return true;
}
}

View File

@@ -0,0 +1,33 @@
#ifndef SETTINGS_BRIGHTNESS_CONTROLLER_H
#define SETTINGS_BRIGHTNESS_CONTROLLER_H
#include "generic_sub_controller.h"
#include "preferences_controller.h"
#include "../message_table_cell_with_editable_text_with_separator.h"
#include "../../shared/parameter_text_field_delegate.h"
#include "../message_table_cell_with_gauge_with_separator.h"
namespace Settings {
class BrightnessController : public GenericSubController, public Shared::ParameterTextFieldDelegate {
public:
BrightnessController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate);
TELEMETRY_ID("BrightnessSettings");
HighlightCell * reusableCell(int index, int type) override;
int reusableCellCount(int type) override;
void willDisplayCellForIndex(HighlightCell * cell, int index) override;
bool handleEvent(Ion::Events::Event event) override;
bool textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) override;
bool textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) override;
protected:
constexpr static int k_totalNumberOfCell = 4;
private:
MessageTableCellWithGauge m_brightnessCell;
MessageTableCellWithEditableText m_editableCellIdleBeforeDimmingSeconds;
MessageTableCellWithEditableText m_editableCellIdleBeforeSuspendSeconds;
MessageTableCellWithEditableText m_BrightnessShortcutCell;
};
}
#endif

View File

@@ -1,12 +1,8 @@
ActivateDeactivate = "Aktivieren/Deaktivieren"
ActivateDutchExamMode = "Prüfungsmodus starten NL"
ActivateExamMode = "Prüfungsmodus starten"
ActiveExamModeMessage1 = "Alle Ihre Daten werden "
ActiveExamModeMessage2 = "gelöscht, wenn Sie den "
ActiveExamModeMessage3 = "Prüfungsmodus einschalten."
ActiveDutchExamModeMessage1 = "Alle Daten werden gelöscht, wenn"
ActiveDutchExamModeMessage2 = "Sie den Prüfungsmodus einschalten. "
ActiveDutchExamModeMessage3 = "Python wird nicht verfügbar sein."
Axis = "Achse"
Cancel = "Abbrechen"
ClearColumn = "Spalte löschen"
@@ -39,7 +35,6 @@ ExitExamMode2 = "Prüfungsmodus verlassen?"
Exponential = "Exponentielle"
FillWithFormula = "Mit einer Formel füllen"
ForbiddenValue = "Verbotener Wert"
FunctionColumn = "0(0) Spalte"
FunctionOptions = "Funktionsoptionen"
Goto = "Gehe zu"
GraphTab = "Graph"
@@ -59,7 +54,6 @@ Navigate = "Navigieren"
NEnd = "N Endwert"
Next = "Nächste"
NoDataToPlot = "Keine Daten zum Zeichnen"
NoFunctionToDelete = "Keine Funktion zum Löschen"
NoValueToCompute = "Keine Größe zum Berechnen"
NStart = "N Startwert"
Ok = "Bestätigen"
@@ -78,7 +72,6 @@ StandardDeviation = "Standardabweichung"
Step = "Schrittwert"
StorageMemoryFull1 = "Der Speicher ist voll. Löschen Sie"
StorageMemoryFull2 = "einige Daten, dann erneut versuchen."
StoreExpressionNotAllowed = "'store' ist verboten"
SyntaxError = "Syntaxfehler"
Sym = "sym"
TEnd = "T Endwert"
@@ -91,11 +84,15 @@ ValuesTab = "Tabelle"
Warning = "Achtung"
XEnd = "X Endwert"
XStart = "X Startwert"
Zoom = "Zoom"
Developers = "Entwickler"
BetaTesters = "Beta-Tester"
ExamModeMode = "Modus"
ExamModeModeStandard = "Standard "
ExamModeModeNoSym = "Kein Symbol "
ExamModeModeNoSymNoText = "Kein Symbol kein Text "
ExamModeModeDutch = "Niederländisch "
ColorRed = "Rot "
ColorBlue = "Blau "
ColorGreen = "Grün "
ColorYellow = "Gelb "
ColorPurple = "Violett "
ColorPink = "Rosa "
ColorOrange = "Orange "

View File

@@ -1,12 +1,8 @@
ActivateDeactivate = "Turn on/off"
ActivateExamMode = "Activate exam mode"
ActivateDutchExamMode = "Activate Dutch exam mode"
ActiveExamModeMessage1 = "All your data will be "
ActiveExamModeMessage2 = "deleted when you activate "
ActiveExamModeMessage3 = "the exam mode."
ActiveDutchExamModeMessage1 = "All your data will be deleted when"
ActiveDutchExamModeMessage2 = "you activate the exam mode. Python"
ActiveDutchExamModeMessage3 = "application will be unavailable."
Axis = "Axes"
Cancel = "Cancel"
ClearColumn = "Clear column"
@@ -39,7 +35,6 @@ ExitExamMode2 = "mode?"
Exponential = "Exponential"
FillWithFormula = "Fill with a formula"
ForbiddenValue = "Forbidden value"
FunctionColumn = "0(0) column"
FunctionOptions = "Function options"
Goto = "Go to"
GraphTab = "Graph"
@@ -58,7 +53,6 @@ NameTooLong = "This name is too long"
Navigate = "Navigate"
Next = "Next"
NoDataToPlot = "No data to draw"
NoFunctionToDelete = "No function to delete"
NoValueToCompute = "No values to calculate"
NEnd = "N end"
NStart = "N start"
@@ -74,7 +68,6 @@ SortValues = "Sort by increasing values"
SortSizes = "Sort by increasing frequencies"
SquareSum = "Sum of squares"
StandardDeviation = "Standard deviation"
StoreExpressionNotAllowed = "'store' is not allowed"
StatTab = "Stats"
Step = "Step"
StorageMemoryFull1 = "The memory is full."
@@ -91,11 +84,15 @@ ValuesTab = "Table"
Warning = "Warning"
XEnd = "X end"
XStart = "X start"
Zoom = "Zoom"
Developers = "Developers"
BetaTesters = "Beta testers"
ExamModeMode = "Mode"
ExamModeModeStandard = "Standard "
ExamModeModeNoSym = "No sym "
ExamModeModeNoSymNoText = "No sym no text "
ExamModeModeDutch = "Dutch "
ColorRed = "Red "
ColorBlue = "Blue "
ColorGreen = "Green "
ColorYellow = "Yellow "
ColorPurple = "Purple "
ColorPink = "Pink "
ColorOrange = "Orange "

View File

@@ -1,12 +1,8 @@
ActivateDeactivate = "Activar/Desactivar"
ActivateExamMode = "Activar el modo examen"
ActivateDutchExamMode = "Activar el modo examen NL"
ActiveExamModeMessage1 = "Todos sus datos se "
ActiveExamModeMessage2 = "eliminaran al activar "
ActiveExamModeMessage3 = "el modo examen."
ActiveDutchExamModeMessage1 = "Todos sus datos se eliminaran al"
ActiveDutchExamModeMessage2 = "activar el modo examen. La aplicación"
ActiveDutchExamModeMessage3 = "Python ya no estará disponible."
Axis = "Ejes"
Cancel = "Cancelar"
ClearColumn = "Borrar la columna"
@@ -39,7 +35,6 @@ ExitExamMode2 = "examen ?"
Exponential = "Exponencial"
FillWithFormula = "Rellenar con una fórmula"
ForbiddenValue = "Valor prohibido"
FunctionColumn = "Columna 0(0)"
FunctionOptions = "Opciones de la función"
Goto = "Ir a"
GraphTab = "Gráfico"
@@ -59,7 +54,6 @@ Navigate = "Navegar"
NEnd = "N fin"
Next = "Siguiente"
NoDataToPlot = "Ningunos datos que dibujar"
NoFunctionToDelete = "Ninguna función que eliminar"
NoValueToCompute = "Ninguna medida que calcular"
NStart = "N inicio"
Ok = "Confirmar"
@@ -78,7 +72,6 @@ StatTab = "Medidas"
Step = "Incremento"
StorageMemoryFull1 = "La memoria está llena."
StorageMemoryFull2 = "Borre datos e intente de nuevo."
StoreExpressionNotAllowed = "'store' no está permitido"
SyntaxError = "Error sintáctico"
Sym = "sim"
TEnd = "T fin"
@@ -91,11 +84,15 @@ ValuesTab = "Tabla"
Warning = "Cuidado"
XEnd = "X fin"
XStart = "X inicio"
Zoom = "Zoom"
Developers = "Desarrolladores"
BetaTesters = "Probadores beta"
ExamModeMode = "Modo"
ExamModeModeStandard = "Estándar "
ExamModeModeNoSym = "Sin simbólico "
ExamModeModeNoSymNoText = "Sin simbólico sin texto "
ExamModeModeDutch = "Holandés "
ColorRed = "Rojo "
ColorBlue = "Azul "
ColorGreen = "Verde "
ColorYellow = "Amarillo "
ColorPurple = "Púrpura "
ColorPink = "Rosa "
ColorOrange = "Naranja "

View File

@@ -1,12 +1,8 @@
ActivateDeactivate = "Activer/Désactiver"
ActivateExamMode = "Activer le mode examen"
ActivateDutchExamMode = "Activer le mode examen NL"
ActiveExamModeMessage1 = "Toutes vos données seront "
ActiveExamModeMessage2 = "supprimées si vous activez "
ActiveExamModeMessage3 = "le mode examen."
ActiveDutchExamModeMessage1 = "Toutes vos données seront supprimées "
ActiveDutchExamModeMessage2 = "si vous activez le mode examen."
ActiveDutchExamModeMessage3 = "Python sera inaccessible."
Axis = "Axes"
Cancel = "Annuler"
ClearColumn = "Effacer la colonne"
@@ -39,7 +35,6 @@ ExitExamMode2 = "du mode examen ?"
Exponential = "Exponentielle"
FillWithFormula = "Remplir avec une formule"
ForbiddenValue = "Valeur interdite"
FunctionColumn = "Colonne 0(0)"
FunctionOptions = "Options de la fonction"
Goto = "Aller à"
GraphTab = "Graphique"
@@ -59,7 +54,6 @@ Navigate = "Naviguer"
Next = "Suivant"
NEnd = "N fin"
NoDataToPlot = "Aucune donnée à tracer"
NoFunctionToDelete = "Pas de fonction à supprimer"
NoValueToCompute = "Aucune grandeur à calculer"
NStart = "N début"
Ok = "Valider"
@@ -78,7 +72,6 @@ StatTab = "Stats"
Step = "Pas"
StorageMemoryFull1 = "La mémoire est pleine."
StorageMemoryFull2 = "Effacez des données et réessayez."
StoreExpressionNotAllowed = "'store' n'est pas autorisé"
SyntaxError = "Attention à la syntaxe"
Sym = "sym"
TEnd = "T fin"
@@ -91,11 +84,15 @@ ValuesTab = "Tableau"
Warning = "Attention"
XEnd = "X fin"
XStart = "X début"
Zoom = "Zoom"
Developers = "Développeurs"
BetaTesters = "Beta testeurs"
ExamModeMode = "Mode"
ExamModeModeStandard = "Standard "
ExamModeModeNoSym = "Sans symbolique "
ExamModeModeNoSymNoText = "Sans symbolique ni texte "
ExamModeModeDutch = "Dutch "
ColorRed = "Rouge "
ColorBlue = "Bleu "
ColorGreen = "Vert "
ColorYellow = "Jaune "
ColorPurple = "Violet "
ColorPink = "Rose "
ColorOrange = "Orange "

View File

@@ -1,101 +1,98 @@
ActivateDeactivate = "Ki/Be kapcsolás"
ActivateExamMode = "A vizsgálati mód aktiválása"
ActivateDutchExamMode = "A holland vizsga mód aktiválása"
ActiveExamModeMessage1 = "Az összes adatod"
ActiveExamModeMessage2 = "törölve lesz ha"
ActiveExamModeMessage3 = "a vizsga módot aktiválja."
ActiveDutchExamModeMessage1 = "Az összes adatod törölve lesz"
ActiveDutchExamModeMessage2 = "ha a vizsga módot aktiválja. A"
ActiveDutchExamModeMessage3 = "Python alkalmazás használhatatlan lesz."
Axis = "Tengelyek"
Cancel = "Mégse"
ClearColumn = "Oszlop törlése"
ColumnOptions = "Oszlop opciók"
ConfirmDiscard1 = "Minden változtatást elvetünk"
ConfirmDiscard2 = ""
CopyColumnInList = "Az oszlopot egy listába másolni"
Country = "Ország"
CountryCA = "Kanada "
CountryDE = "Németország "
CountryES = "Spanyolország "
CountryFR = "Franciaország "
CountryGB = "Egyesült Királyság "
CountryIT = "Olaszország "
CountryNL = "Hollandia "
CountryPT = "Portugália "
CountryUS = "Egyesült Államok "
CountryWW = "Nemzetközi "
CountryWarning1 = "Ez a beállítás meghatározza az"
CountryWarning2 = "alkalmazott tematikus konvenciókat."
DataNotSuitable = "Az adatok nem felelnek meg"
DataTab = "Adatok"
Deg = "deg"
Deviation = "Varianca"
DisplayValues = "Értékek mutatása"
Empty = "Üres"
Eng = "eng"
ExitExamMode1 = "Kilépni a vizsga "
ExitExamMode2 = "módból?"
Exponential = "Exponenciális"
FillWithFormula = "Töltse ki egy képlettel"
ForbiddenValue = "Tiltott érték"
FunctionColumn = "0(0) oszlop"
FunctionOptions = "Funkció opciók"
Goto = "Menj ..."
GraphTab = "Grafikon"
HardwareTestLaunch1 = "A hardverteszt indítása :"
HardwareTestLaunch2 = "Nyomjon a reset gombra a"
HardwareTestLaunch3 = "teszt megállításához (ez"
HardwareTestLaunch4 = "az adatokat törölni fogja)"
IntervalSet = "Állítsa be az intervallumot"
Language = "Nyelv"
LowBattery = "Majdnem kimerült az elem"
Mean = "középérték"
Move = " Odébb rakni: "
NameCannotStartWithNumber = "Egy név nem kezdöthet számmal"
NameTaken = "Ez a név foglalt"
NameTooLong = "Ez a név túl hosszú"
Navigate = "Hajózik"
Next = "következö"
NEnd = "N vége"
NoDataToPlot = "Nincs rajzolható adat"
NoFunctionToDelete = "Nincs törölhetö függvény"
NoValueToCompute = "Nincs számítható érték"
NStart = "N kezdete"
Ok = "Érvényesítés"
Or = " vagy "
Orthonormal = "Ortonormált"
Plot = "Grafikon rajzolása"
PoolMemoryFull1 = "A memória megtelt."
PoolMemoryFull2 = "Kérem próbálja újra."
Rename = "Átnevezés"
Sci = "sci"
SortValues = "Rendezés értékek növelésével"
SortSizes = "Rendezés növekvő frekvenciák szerint"
SquareSum = "Négyzetek összege"
StandardDeviation = "Alap eltérés"
StatTab = "Statisztikák"
Step = "Lépés"
StorageMemoryFull1 = "A memória megtelt."
StorageMemoryFull2 = "Törlöljön adatokat és próbálkozzon újra."
StoreExpressionNotAllowed = "'szore' nem engedélyezett"
SyntaxError = "Szintaxis hiba"
Sym = "sym"
TEnd = "T vég"
ThetaEnd = "θ vége"
ThetaStart = "θ kezdete"
TStart = "T kezdete"
ToZoom = "Nagyítani : "
UndefinedValue = "Meghatározatlan adat"
ValuesTab = "Táblázat"
Warning = "Figyelem"
XEnd = "X vége"
XStart = "X kezdete"
Zoom = "Nagyítás"
Developers = "Kifejlesztök"
BetaTesters = "Béta tesztelök"
ExamModeMode = "Üzemmód"
ExamModeModeStandard = "Normál "
ExamModeModeNoSym = "Szimbólikus nélkül "
ExamModeModeNoSymNoText = "Szimbólikus és szöveg nélkül "
ExamModeModeDutch = "Holland "
ActivateDeactivate = "Ki/Be kapcsolás"
ActivateExamMode = "A vizsgálati mód aktiválása"
ActiveExamModeMessage1 = "Az összes adatod"
ActiveExamModeMessage2 = "törölve lesz ha"
ActiveExamModeMessage3 = "a vizsga módot aktiválja."
Axis = "Tengelyek"
Cancel = "Mégse"
ClearColumn = "Oszlop törlése"
ColumnOptions = "Oszlop opciók"
ConfirmDiscard1 = "Minden változtatást elvetünk"
ConfirmDiscard2 = ""
CopyColumnInList = "Az oszlopot egy listába másolni"
Country = "Ország"
CountryCA = "Kanada "
CountryDE = "Németország "
CountryES = "Spanyolország "
CountryFR = "Franciaország "
CountryGB = "Egyesült Királyság "
CountryIT = "Olaszország "
CountryNL = "Hollandia "
CountryPT = "Portugália "
CountryUS = "Egyesült Államok "
CountryWW = "Nemzetközi "
CountryWarning1 = "Ez a beállítás meghatározza az"
CountryWarning2 = "alkalmazott tematikus konvenciókat."
DataNotSuitable = "Az adatok nem felelnek meg"
DataTab = "Adatok"
Deg = "deg"
Deviation = "Varianca"
DisplayValues = "Értékek mutatása"
Empty = "Üres"
Eng = "eng"
ExitExamMode1 = "Kilépni a vizsga "
ExitExamMode2 = "módból?"
Exponential = "Exponenciális"
FillWithFormula = "Töltse ki egy képlettel"
ForbiddenValue = "Tiltott érték"
FunctionOptions = "Funkció opciók"
Goto = "Menj ..."
GraphTab = "Grafikon"
HardwareTestLaunch1 = "A hardverteszt indítása :"
HardwareTestLaunch2 = "Nyomjon a reset gombra a"
HardwareTestLaunch3 = "teszt megállításához (ez"
HardwareTestLaunch4 = "az adatokat törölni fogja)"
IntervalSet = "Állítsa be az intervallumot"
Language = "Nyelv"
LowBattery = "Majdnem kimerült az elem"
Mean = "középérték"
Move = " Odébb rakni: "
NameCannotStartWithNumber = "Egy név nem kezdöthet számmal"
NameTaken = "Ez a név foglalt"
NameTooLong = "Ez a név túl hosszú"
Navigate = "Hajózik"
Next = "következö"
NEnd = "N vége"
NoDataToPlot = "Nincs rajzolható adat"
NoValueToCompute = "Nincs számítható érték"
NStart = "N kezdete"
Ok = "Érvényesítés"
Or = " vagy "
Orthonormal = "Ortonormált"
Plot = "Grafikon rajzolása"
PoolMemoryFull1 = "A memória megtelt."
PoolMemoryFull2 = "Kérem próbálja újra."
Rename = "Átnevezés"
Sci = "sci"
SortValues = "Rendezés értékek növelésével"
SortSizes = "Rendezés növekvő frekvenciák szerint"
SquareSum = "Négyzetek összege"
StandardDeviation = "Alap eltérés"
StatTab = "Statisztikák"
Step = "Lépés"
StorageMemoryFull1 = "A memória megtelt."
StorageMemoryFull2 = "Törlöljön adatokat és próbálkozzon újra."
SyntaxError = "Szintaxis hiba"
Sym = "sym"
TEnd = "T vég"
ThetaEnd = "θ vége"
ThetaStart = "θ kezdete"
TStart = "T kezdete"
ToZoom = "Nagyítani : "
UndefinedValue = "Meghatározatlan adat"
ValuesTab = "Táblázat"
Warning = "Figyelem"
XEnd = "X vége"
XStart = "X kezdete"
ExamModeMode = "Üzemmód"
ExamModeModeStandard = "Normál "
ExamModeModeNoSym = "Szimbólikus nélkül "
ExamModeModeNoSymNoText = "Szimbólikus és szöveg nélkül "
ExamModeModeDutch = "Holland "
ColorRed = "Piros "
ColorBlue = "Kék "
ColorGreen = "Zöld "
ColorYellow = "Sárga "
ColorPurple = "Lila "
ColorPink = "Rózsaszín "
ColorOrange = "Narancssárga "

View File

@@ -1,12 +1,8 @@
ActivateDeactivate = "Attivare/Disattivare"
ActivateExamMode = "Attiva modalità d'esame"
ActivateDutchExamMode = "Attiva modalità d'esame NL"
ActiveExamModeMessage1 = "Tutti i tuoi dati saranno "
ActiveExamModeMessage2 = "cancellati se attivi "
ActiveExamModeMessage3 = "la modalità d'esame."
ActiveDutchExamModeMessage1 = "Tutti i tuoi dati saranno cancellati"
ActiveDutchExamModeMessage2 = "se attivi la modalità d'esame."
ActiveDutchExamModeMessage3 = "L'app Python sarà inaccessibile."
Axis = "Assi"
Cancel = "Annullare"
ClearColumn = "Cancella la colonna"
@@ -39,7 +35,6 @@ ExitExamMode2 = "dalla modalità d'esame ?"
Exponential = "Esponenziale"
FillWithFormula = "Compilare con una formula"
ForbiddenValue = "Valore non consentito"
FunctionColumn = "Colonna 0(0)"
FunctionOptions = "Opzioni della funzione"
Goto = "Andare a"
GraphTab = "Grafico"
@@ -59,7 +54,6 @@ Navigate = "Navigare"
Next = "Successivo"
NEnd = "N finale"
NoDataToPlot = "Nessun dato da tracciare"
NoFunctionToDelete = "Nessuna funzione da cancellare"
NoValueToCompute = "Nessun valore da calcolare"
NStart = "N iniziale"
Ok = "Conferma"
@@ -78,7 +72,6 @@ StatTab = "Stats"
Step = "Passo"
StorageMemoryFull1 = "La memoria è piena."
StorageMemoryFull2 = "Cancellate i dati e riprovate."
StoreExpressionNotAllowed = "'store' non è consentito"
SyntaxError = "Sintassi errata"
Sym = "sym"
TEnd = "T finale"
@@ -91,11 +84,15 @@ ValuesTab = "Tabella"
Warning = "Attenzione"
XEnd = "X finale"
XStart = "X iniziale"
Zoom = "Zoom"
Developers = "Developers"
BetaTesters = "Beta testers"
ExamModeMode = "Modalità"
ExamModeModeStandard = "Standard "
ExamModeModeNoSym = "Nessun simbolo "
ExamModeModeNoSymNoText = "Nessun simbolo nessun testo "
ExamModeModeDutch = "Olandese "
ColorRed = "Rosso "
ColorBlue = "Blu "
ColorGreen = "Verde "
ColorYellow = "Giallo "
ColorPurple = "Viola "
ColorPink = "Rosa "
ColorOrange = "Arancia "

View File

@@ -1,12 +1,8 @@
ActivateDeactivate = "Zet aan/uit"
ActivateExamMode = "Internationale examenst."
ActivateDutchExamMode = "Nederlandse examenstand"
ActiveExamModeMessage1 = "Al je gegevens worden "
ActiveExamModeMessage2 = "gewist wanneer je de "
ActiveExamModeMessage3 = "examenstand activeert."
ActiveDutchExamModeMessage1 = "Al je gegevens worden gewist wanneer"
ActiveDutchExamModeMessage2 = "je de examenstand activeert. De Python"
ActiveDutchExamModeMessage3 = "applicatie wordt uitgeschakeld."
Axis = "Assen"
Cancel = "Annuleer"
ClearColumn = "Wis kolom"
@@ -39,7 +35,6 @@ ExitExamMode2 = "examenstand?"
Exponential = "Exponentieel"
FillWithFormula = "Vul met een formule"
ForbiddenValue = "Verboden waarde"
FunctionColumn = "0(0) kolom"
FunctionOptions = "Functie-opties"
Goto = "Ga naar"
GraphTab = "Grafiek"
@@ -58,7 +53,6 @@ NameTooLong = "Deze naam is te lang"
Navigate = "Navigeren"
Next = "Volgende"
NoDataToPlot = "Geen gegevens om te plotten"
NoFunctionToDelete = "Geen functie om te verwijderen"
NoValueToCompute = "Geen waarden om te berekenen"
NEnd = "N einde"
NStart = "N begin"
@@ -74,7 +68,6 @@ SortValues = "Sorteer waarden oplopend"
SortSizes = "Sorteer frequenties oplopend"
SquareSum = "Som van kwadraten"
StandardDeviation = "Standaardafwijking"
StoreExpressionNotAllowed = "'opslaan' is niet toegestaan"
StatTab = "Stats"
Step = "Stap"
StorageMemoryFull1 = "Het geheugen is vol."
@@ -91,11 +84,15 @@ ValuesTab = "Tabel"
Warning = "Waarschuwing"
XEnd = "X einde"
XStart = "X begin"
Zoom = "Zoom"
Developers = "Developers"
BetaTesters = "Beta testers"
ExamModeMode = "Mode"
ExamModeModeStandard = "Standaard "
ExamModeModeNoSym = "Geen sym "
ExamModeModeNoSymNoText = "Geen sym geen tekst "
ExamModeModeDutch = "Nederlands "
ColorRed = "rood"
ColorBlue = "Blauw"
ColorGreen = "Groente"
ColorYellow = "Geel"
ColorPurple = "Purper"
ColorPink = "Roze"
ColorOrange = "Oranje"

View File

@@ -1,12 +1,8 @@
ActivateDeactivate = "Ativar/Desativar"
ActivateExamMode = "Ativar o modo de exame"
ActivateDutchExamMode = "Ativar o modo de exame NL"
ActiveExamModeMessage1 = "Todos os seus dados serão "
ActiveExamModeMessage2 = "apagados se ativar "
ActiveExamModeMessage3 = "o modo de exame."
ActiveDutchExamModeMessage1 = "Todos os seus dados serão apagados "
ActiveDutchExamModeMessage2 = "se ativar o modo de exame. A"
ActiveDutchExamModeMessage3 = "aplicação Python estará indisponível."
Axis = "Eixos"
Cancel = "Cancelar"
ClearColumn = "Excluir coluna"
@@ -39,7 +35,6 @@ ExitExamMode2 = "exame ?"
Exponential = "Exponencial"
FillWithFormula = "Preencher com uma fórmula"
ForbiddenValue = "Valor proibido"
FunctionColumn = "Coluna 0(0)"
FunctionOptions = "Opções de função"
Goto = "Ir para"
GraphTab = "Gráfico"
@@ -59,7 +54,6 @@ Navigate = "Navegar"
NEnd = "N fim"
Next = "Seguinte"
NoDataToPlot = "Não há dados para desenhar"
NoFunctionToDelete = "Sem função para eliminar"
NoValueToCompute = "Não há dados para calcular"
NStart = "N início"
Ok = "Confirmar"
@@ -78,7 +72,6 @@ StatTab = "Estat"
Step = "Passo"
StorageMemoryFull1 = "A memória esta cheia."
StorageMemoryFull2 = "Apage dados e tente novamente."
StoreExpressionNotAllowed = "'store' não está permitido"
SyntaxError = "Erro de sintaxe"
Sym = "sim"
TEnd = "T fim"
@@ -91,11 +84,15 @@ ValuesTab = "Tabela"
Warning = "Atenção"
XEnd = "X fim"
XStart = "X início"
Zoom = "Zoom"
Developers = "Desenvolvedores"
BetaTesters = "Testadores beta"
ExamModeMode = "Modo"
ExamModeModeStandard = "Padrão "
ExamModeModeNoSym = "Sem sym "
ExamModeModeNoSymNoText = "Sem sym sem texto "
ExamModeModeDutch = "holandês "
ColorRed = "Vermelho "
ColorBlue = "Azul "
ColorGreen = "Verde "
ColorYellow = "Amarelo "
ColorPurple = "Roxa "
ColorPink = "Cor de rosa "
ColorOrange = "Laranja "

View File

@@ -25,7 +25,6 @@ UnitMassGramKiloSymbol = "_kg"
UnitMassGramSymbol = "_g"
UnitMassGramMilliSymbol = "_mg"
UnitMassGramMicroSymbol = "_μg"
UnitMassGramNanoSymbol = "_ng"
UnitMassTonneSymbol = "_t"
UnitMassOunceSymbol = "_oz"
UnitMassPoundSymbol = "_lb"
@@ -122,7 +121,6 @@ DeterminantCommandWithArg = "det(M)"
DiffCommandWithArg = "diff(f(x),x,a)"
DiffCommand = "diff(\x11,x,\x11)"
DimensionCommandWithArg = "dim(M)"
DiscriminantFormulaDegree2 = "Δ=b^2-4ac"
DotCommandWithArg = "dot(u,v)"
E = "e"
Equal = "="
@@ -352,7 +350,6 @@ PVenceslasDuet = "@Citorva"
CyprienMejat = "Cyprien Méjat"
PCyprienMejat = "@A2drien"
SpeedOfLight = "2.99792458·10^8_m_s^-1"
YearLight = "9.461·10^15_m"
Boltzmann = "1.380649·10^-23_J_K^-1"
StefanBoltzmann = "5.670374419·10^-8_W_m^-2_K^-4"
VacuumImpedance = "376.730313668_Ω"

View File

@@ -29,6 +29,8 @@ app_shared_src = $(addprefix apps/shared/,\
buffer_function_title_cell.cpp \
buffer_text_view_with_text_field.cpp \
button_with_separator.cpp \
color_cell.cpp \
color_parameter_controller.cpp \
cursor_view.cpp \
editable_cell_table_view_controller.cpp \
expression_field_delegate_app.cpp \

View File

@@ -0,0 +1,51 @@
#include "color_cell.h"
namespace Shared {
constexpr const I18n::Message MessageTableCellWithColor::k_textForIndex[Palette::numberOfDataColors()];
constexpr const uint8_t colorMask[MessageTableCellWithColor::ColorView::k_colorSize][MessageTableCellWithColor::ColorView::k_colorSize] = { // FIXME Can't link with constexpr static
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
{0xFF, 0xFF, 0xFF, 0xE1, 0x0C, 0x00, 0x00, 0x0C, 0xE1, 0xFF, 0xFF, 0xFF},
{0xFF, 0xFF, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0xFF, 0xFF},
{0xFF, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0xFF},
{0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xFF},
{0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF},
{0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF},
{0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xFF},
{0xFF, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0xFF},
{0xFF, 0xFF, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0xFF, 0xFF},
{0xFF, 0xFF, 0xFF, 0xE1, 0x0C, 0x00, 0x00, 0x0C, 0xE1, 0xFF, 0xFF, 0xFF},
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
};
MessageTableCellWithColor::MessageTableCellWithColor() :
MessageTableCell(),
m_accessoryView()
{}
View * MessageTableCellWithColor::accessoryView() const {
return (View *)&m_accessoryView;
}
void MessageTableCellWithColor::setColor(int i) {
m_accessoryView.setColor(i);
MessageTextView * label = (MessageTextView*)(labelView());
return label->setMessage(k_textForIndex[i]);
}
MessageTableCellWithColor::ColorView::ColorView() :
m_index(0)
{}
void MessageTableCellWithColor::ColorView::drawRect(KDContext * ctx, KDRect rect) const {
KDColor Buffer[MessageTableCellWithColor::ColorView::k_colorSize*MessageTableCellWithColor::ColorView::k_colorSize];
KDRect Frame(bounds().x(), bounds().y() + bounds().height()/2 - k_colorSize/2, k_colorSize, k_colorSize);
ctx->blendRectWithMask(Frame, Palette::DataColor[m_index], (const uint8_t *)colorMask, Buffer);
}
KDSize MessageTableCellWithColor::ColorView::minimalSizeForOptimalDisplay() const {
return KDSize(k_colorSize, k_colorSize);
}
}

42
apps/shared/color_cell.h Normal file
View File

@@ -0,0 +1,42 @@
#ifndef SHARED_COLOR_CELL_CONTROLLER_H
#define SHARED_COLOR_CELL_CONTROLLER_H
#include <escher.h>
#include <apps/i18n.h>
namespace Shared {
class MessageTableCellWithColor : public MessageTableCell {
public:
MessageTableCellWithColor();
View * accessoryView() const override;
void setColor(int i);
int color() { return m_accessoryView.color(); }
constexpr static I18n::Message k_textForIndex[Palette::numberOfDataColors()] = {
I18n::Message::ColorRed,
I18n::Message::ColorBlue,
I18n::Message::ColorGreen,
I18n::Message::ColorYellow,
I18n::Message::ColorPurple,
I18n::Message::ColorBlue,
I18n::Message::ColorPink,
I18n::Message::ColorOrange
};
class ColorView : public TransparentView {
public:
ColorView();
void setColor(int i) { m_index = i; }
int color() { return m_index; }
void drawRect(KDContext * ctx, KDRect rect) const override;
KDSize minimalSizeForOptimalDisplay() const override;
constexpr static KDCoordinate k_colorSize = 12;
private:
int m_index;
};
private:
ColorView m_accessoryView;
};
}
#endif

View File

@@ -0,0 +1,86 @@
#include "color_parameter_controller.h"
#include "function_app.h"
#include "../apps_container.h"
#include <assert.h>
namespace Shared {
ColorParameterController::ColorParameterController(Responder * parentResponder, I18n::Message title) :
ViewController(parentResponder),
m_selectableTableView(this),
m_record(),
m_title(title)
{}
void ColorParameterController::viewWillAppear() {
ViewController::viewWillAppear();
// Restore the selected color
KDColor FunctionColor = function()->color();
uint8_t cellXPosition = 0;
// TODO: Improve this if possible
for (uint8_t i = 0; i < sizeof(Palette::DataColor)/sizeof(Palette::DataColor[0]); i++) {
if (Palette::DataColor[i] == FunctionColor) {
cellXPosition = i;
break;
}
}
assert(Palette::DataColor[cellXPosition] == FunctionColor);
selectCellAtLocation(0, cellXPosition);
m_selectableTableView.reloadData();
}
void ColorParameterController::didBecomeFirstResponder() {
Container::activeApp()->setFirstResponder(&m_selectableTableView);
}
bool ColorParameterController::handleEvent(Ion::Events::Event event) {
StackViewController * stack = (StackViewController *)(parentResponder());
if (event == Ion::Events::Left) {
stack->pop();
return true;
}
if (event == Ion::Events::OK || event == Ion::Events::EXE) {
handleEnterOnRow(selectedRow());
stack->pop();
return true;
}
return false;
}
KDCoordinate ColorParameterController::cellHeight() {
return Metric::ParameterCellHeight;
}
HighlightCell * ColorParameterController::reusableCell(int index) {
assert(index < numberOfRows());
return &m_cells[index];
}
void ColorParameterController::willDisplayCellForIndex(HighlightCell * cell, int index) {
MessageTableCellWithColor * myCell = (MessageTableCellWithColor *)cell;
myCell->setColor(index);
myCell->setMessageFont(KDFont::LargeFont);
cell->reloadCell();
}
bool ColorParameterController::handleEnterOnRow(int rowIndex) {
function()->setColor(Palette::DataColor[rowIndex]);
return true;
}
void ColorParameterController::setRecord(Ion::Storage::Record record) {
m_record = record;
selectCellAtLocation(0, 0);
}
ExpiringPointer<Function> ColorParameterController::function() {
return functionStore()->modelForRecord(m_record);
}
FunctionStore * ColorParameterController::functionStore() {
return FunctionApp::app()->functionStore();
}
}

View File

@@ -0,0 +1,44 @@
#ifndef SHARED_COLOR_PARAM_CONTROLLER_H
#define SHARED_COLOR_PARAM_CONTROLLER_H
#include <escher.h>
#include "function_store.h"
#include "color_cell.h"
#include <apps/i18n.h>
namespace Shared {
class ColorParameterController : public ViewController, public SimpleListViewDataSource, public SelectableTableViewDataSource {
public:
ColorParameterController(Responder * parentResponder, I18n::Message title);
View * view() override { return &m_selectableTableView; }
void viewWillAppear() override;
void didBecomeFirstResponder() override;
const char * title() override { return I18n::translate(m_title); }
bool handleEvent(Ion::Events::Event event) override;
TELEMETRY_ID("ColorParameter");
void setRecord(Ion::Storage::Record record);
int numberOfRows() const override { return Palette::numberOfDataColors(); }
KDCoordinate cellHeight() override;
HighlightCell * reusableCell(int index) override;
int reusableCellCount() const override { return Palette::numberOfDataColors(); } // FIXME Display issue
void willDisplayCellForIndex(HighlightCell * cell, int index);
private:
bool handleEnterOnRow(int rowIndex);
FunctionStore * functionStore();
ExpiringPointer<Function> function();
SelectableTableView m_selectableTableView;
Ion::Storage::Record m_record;
I18n::Message m_title;
MessageTableCellWithColor m_cells[Palette::numberOfDataColors()];
};
}
#endif

View File

@@ -55,6 +55,10 @@ void Function::setActive(bool active) {
}
}
void Function::setColor(KDColor color) {
recordData()->setColor(color);
}
int Function::printValue(double cursorT, double cursorX, double cursorY, char * buffer, int bufferSize, int precision, Poincare::Context * context) {
return PoincareHelpers::ConvertFloatToText<double>(cursorY, buffer, bufferSize, precision);
}

View File

@@ -36,6 +36,7 @@ public:
bool isActive() const;
KDColor color() const;
void setActive(bool active);
void setColor(KDColor color);
// Definition Interval
virtual bool shouldClipTRangeToXRange() const { return true; } // Returns true if the function will not be displayed if t is outside x range.
@@ -76,6 +77,7 @@ protected:
KDColor color() const {
return KDColor::RGB16(m_color);
}
void setColor(KDColor color) { m_color = color; }
bool isActive() const { return m_active; }
void setActive(bool active) { m_active = active; }
private:

View File

@@ -8,12 +8,12 @@ ListParameterController::ListParameterController(Responder * parentResponder, I1
ViewController(parentResponder),
m_selectableTableView(this, this, this, tableDelegate),
m_record(),
#if FUNCTION_COLOR_CHOICE
m_colorCell(functionColorMessage),
#endif
m_colorCell(),
m_enableCell(I18n::Message::ActivateDeactivate),
m_deleteCell(deleteFunctionMessage)
m_deleteCell(deleteFunctionMessage),
m_colorParameterController(parentResponder, functionColorMessage)
{
m_colorCell.setMessage(functionColorMessage);
}
const char * ListParameterController::title() {
@@ -38,6 +38,16 @@ void ListParameterController::willDisplayCellForIndex(HighlightCell * cell, int
if (cell == &m_enableCell) {
SwitchView * switchView = (SwitchView *)m_enableCell.accessoryView();
switchView->setState(function()->isActive());
} else if(cell == &m_colorCell) {
int index = -1;
KDColor color = function()->color();
for(int i = 0; i < Palette::numberOfDataColors(); i++) {
if(color == Palette::DataColor[i]) {
index = i;
}
}
assert(index >= 0);
m_colorCell.setSubtitle(MessageTableCellWithColor::k_textForIndex[index]);
}
}
@@ -64,11 +74,7 @@ int ListParameterController::indexFromCumulatedHeight(KDCoordinate offsetY) {
HighlightCell * ListParameterController::reusableCell(int index, int type) {
assert(index == 0);
assert(index < totalNumberOfCells());
#if FUNCTION_COLOR_CHOICE
HighlightCell * cells[] = {&m_colorCell, &m_enableCell, &m_deleteCell};
#else
HighlightCell * cells[] = {&m_enableCell, &m_deleteCell};
#endif
return cells[type];
}
@@ -78,22 +84,17 @@ int ListParameterController::typeAtLocation(int i, int j) {
bool ListParameterController::handleEnterOnRow(int rowIndex) {
switch (rowIndex) {
#if FUNCTION_COLOR_CHOICE
case 0:
/* TODO: implement function color choice */
case 0: {
StackViewController * stack = (StackViewController *)(parentResponder());
m_colorParameterController.setRecord(m_record);
stack->push(&m_colorParameterController);
return true;
}
case 1:
#else
case 0:
#endif
function()->setActive(!function()->isActive());
m_selectableTableView.reloadData();
return true;
#if FUNCTION_COLOR_CHOICE
case 2:
#else
case 1:
#endif
case 2:
{
assert(functionStore()->numberOfModels() > 0);
functionStore()->removeModel(m_record);

View File

@@ -3,6 +3,7 @@
#include <escher.h>
#include "function_store.h"
#include "color_parameter_controller.h"
#include <apps/i18n.h>
namespace Shared {
@@ -31,22 +32,17 @@ public:
protected:
virtual bool handleEnterOnRow(int rowIndex);
virtual int totalNumberOfCells() const {
#if FUNCTION_COLOR_CHOICE
return 3;
#else
return 2;
#endif
}
FunctionStore * functionStore();
ExpiringPointer<Function> function();
SelectableTableView m_selectableTableView;
Ion::Storage::Record m_record;
private:
#if FUNCTION_COLOR_CHOICE
MessageTableCellWithChevron m_colorCell;
#endif
MessageTableCellWithChevronAndMessage m_colorCell;
MessageTableCellWithSwitch m_enableCell;
MessageTableCell m_deleteCell;
ColorParameterController m_colorParameterController;
};
}

View File

@@ -8,7 +8,6 @@ Values3 = "Werte V3"
Frequencies1 = "Häufigkeiten N1"
Frequencies2 = "Häufigkeiten N2"
Frequencies3 = "Häufigkeiten N3"
ImportList = "Laden einer Liste"
Interval = " Intervall"
Frequency = " Häufigkeit:"
RelativeFrequency = "Relative:"

View File

@@ -8,7 +8,6 @@ Values3 = "Value V3"
Frequencies1 = "Frequency N1"
Frequencies2 = "Frequency N2"
Frequencies3 = "Frequency N3"
ImportList = "Import from a list"
Interval = " Interval "
Frequency = " Frequency:"
RelativeFrequency = "Relative:"

View File

@@ -8,7 +8,6 @@ Values3 = "Valores V3"
Frequencies1 = "Frecuencias N1"
Frequencies2 = "Frecuencias N2"
Frequencies3 = "Frecuencias N3"
ImportList = "Importar una lista"
Interval = " Intervalo"
Frequency = " Frecuencia:"
RelativeFrequency = "Relativa:"
@@ -24,4 +23,4 @@ StandardDeviationSigma = "Desviación típica σ"
SampleStandardDeviationS = "Desviación típica s"
SumValues = "Suma"
SumSquareValues = "Suma cuadrados"
InterquartileRange = "Rango intercuartilo"
InterquartileRange = "Rango intercuartilo"

View File

@@ -8,7 +8,6 @@ Values3 = "Valeurs V3"
Frequencies1 = "Effectifs N1"
Frequencies2 = "Effectifs N2"
Frequencies3 = "Effectifs N3"
ImportList = "Importer une liste"
Interval = " Intervalle "
Frequency = " Effectif:"
RelativeFrequency = "Fréquence:"

View File

@@ -1,27 +1,26 @@
StatsApp = "Statisztika"
StatsAppCapital = "STATISZTIKA"
HistogramTab = "Hisztogram"
BoxTab = "Doboz"
Values1 = "V1 értékek"
Values2 = "V2 értékek"
Values3 = "V3 értékek"
Frequencies1 = "N1 Frekvencia"
Frequencies2 = "N2 Frekvencia"
Frequencies3 = "N3 Frekvencia"
ImportList = "Importálás egy listáról"
Interval = "Intervallum"
Frequency = "Frekvencia:"
RelativeFrequency = "Relatív:"
HistogramSet = "Hisztogram beállítások"
RectangleWidth = "Tálca szélessége"
BarStart = "X kezdet"
FirstQuartile = "Elsö kvartilis"
Median = "Medián"
ThirdQuartile = "Harmadik kvartilis"
TotalFrequency = "Adatpontok száma "
Range = "Intervallum"
StandardDeviationSigma = "σ szórás"
SampleStandardDeviationS = "Minta std eltérés σ"
SumValues = "Értékek összege"
SumSquareValues = "Négyzetértékek összege"
InterquartileRange = "Interkvartilis tartomány"
StatsApp = "Statisztika"
StatsAppCapital = "STATISZTIKA"
HistogramTab = "Hisztogram"
BoxTab = "Doboz"
Values1 = "V1 értékek"
Values2 = "V2 értékek"
Values3 = "V3 értékek"
Frequencies1 = "N1 Frekvencia"
Frequencies2 = "N2 Frekvencia"
Frequencies3 = "N3 Frekvencia"
Interval = "Intervallum"
Frequency = "Frekvencia:"
RelativeFrequency = "Relatív:"
HistogramSet = "Hisztogram beállítások"
RectangleWidth = "Tálca szélessége"
BarStart = "X kezdet"
FirstQuartile = "Elsö kvartilis"
Median = "Medián"
ThirdQuartile = "Harmadik kvartilis"
TotalFrequency = "Adatpontok száma "
Range = "Intervallum"
StandardDeviationSigma = "σ szórás"
SampleStandardDeviationS = "Minta std eltérés σ"
SumValues = "Értékek összege"
SumSquareValues = "Négyzetértékek összege"
InterquartileRange = "Interkvartilis tartomány"

View File

@@ -8,7 +8,6 @@ Values3 = "Valori V3"
Frequencies1 = "Frequenze N1"
Frequencies2 = "Frequenze N2"
Frequencies3 = "Frequenze N3"
ImportList = "Importare una lista"
Interval = " Intervallo "
Frequency = " Frequenza:"
RelativeFrequency = "Relativa:"
@@ -24,4 +23,4 @@ StandardDeviationSigma = "Deviazione standard σ"
SampleStandardDeviationS = "Dev. std campionaria s"
SumValues = "Somma"
SumSquareValues = "Somma dei quadrati"
InterquartileRange = "Scarto interquartile"
InterquartileRange = "Scarto interquartile"

View File

@@ -8,7 +8,6 @@ Values3 = "Waarden V3"
Frequencies1 = "Frequenties N1"
Frequencies2 = "Frequenties N2"
Frequencies3 = "Frequenties N3"
ImportList = "Importeren uit een lijst"
Interval = " Interval "
Frequency = " Frequentie:"
RelativeFrequency = "Relatieve:"
@@ -24,4 +23,4 @@ StandardDeviationSigma = "Standaardafwijking σ"
SampleStandardDeviationS = "Standaardafwijking s"
SumValues = "Som"
SumSquareValues = "Som van kwadraten"
InterquartileRange = "Interkwartielafstand"
InterquartileRange = "Interkwartielafstand"

View File

@@ -8,7 +8,6 @@ Values3 = "Valores V3"
Frequencies1 = "Frequências N1"
Frequencies2 = "Frequências N2"
Frequencies3 = "Frequências N3"
ImportList = "Importar de uma lista"
Interval = " Intervalo"
Frequency = " Frequência:"
RelativeFrequency = "Relativa:"
@@ -24,4 +23,4 @@ StandardDeviationSigma = "Desvio padrão σ"
SampleStandardDeviationS = "Desvio padrão amostral s"
SumValues = "Somatório"
SumSquareValues = "Soma dos quadrados"
InterquartileRange = "Amplitude interquartil"
InterquartileRange = "Amplitude interquartil"

View File

@@ -2,7 +2,7 @@
#include "apps_container.h"
SuspendTimer::SuspendTimer() :
Timer(k_idleBeforeSuspendDuration/Timer::TickDuration)
Timer(GlobalPreferences::sharedGlobalPreferences()->idleBeforeSuspendSeconds()*1000/Timer::TickDuration)
{
}

View File

@@ -7,7 +7,6 @@ class SuspendTimer : public Timer {
public:
SuspendTimer();
private:
constexpr static int k_idleBeforeSuspendDuration = 5*60*1000; // In miliseconds
bool fire() override;
};

View File

@@ -1,6 +1,5 @@
Unit = "Einheiten"
UnitTimeMenu = "Zeit"
UnitTimeSecondMenu = "Sekunde"
UnitTimeSecond = "Sekunde"
UnitTimeSecondMilli = "Millisekunde"
UnitTimeSecondMicro = "Mikrosekunde"
@@ -12,7 +11,6 @@ UnitTimeWeek = "Woche"
UnitTimeMonth = "Monat"
UnitTimeYear = "Jahr"
UnitDistanceMenu = "Entfernung"
UnitDistanceMeterMenu = "Meter"
UnitDistanceMeterKilo = "Kilometer"
UnitDistanceMeter = "Meter"
UnitDistanceMeterMilli = "Millimeter"
@@ -31,9 +29,6 @@ UnitMassGramKilo = "Kilogramm"
UnitMassGram = "Gramm"
UnitMassGramMilli = "Milligramm"
UnitMassGramMicro = "Mikrogramm"
UnitMassGramNano = "Nanogramm"
UnitDistanceImperialMenu = "Angloamerikanisch"
UnitMassImperialMenu = "Angloamerikanisch"
UnitMassTonne = "Tonne"
UnitMassOunce = "Unze"
UnitMassPound = "Pfund"
@@ -423,7 +418,6 @@ EscapeVelocity = "Fluchtgeschwindigkeit"
EscapeVelocityFromEarth = "Von der Erde"
EscapeVelocityFromMoon = "Vom Mond"
EscapeVelocityFromSun = "Von der Sonne"
YearLightTag = "Lichtjahr"
Thermodynamics = "Thermodynamik"
BoltzmannTag = "Boltzmann Konstante"
AvogadroTag = "Avogadro-Konstante"
@@ -466,7 +460,6 @@ MoonMassTag = "Mond"
EarthMassTag = "Erde"
SunMassTag = "Sonne"
ParticleMass = "Partikel Masse"
AstronomicalMass = "Astronomische"
Radiuses = "Radien"
Length = "Länge"
Distances = "Entfernungen"

View File

@@ -1,6 +1,5 @@
Unit = "Units"
UnitTimeMenu = "Time"
UnitTimeSecondMenu = "Second"
UnitTimeSecond = "Second"
UnitTimeSecondMilli = "Millisecond"
UnitTimeSecondMicro = "Microsecond"
@@ -12,14 +11,12 @@ UnitTimeWeek = "Week"
UnitTimeMonth = "Month"
UnitTimeYear = "Year"
UnitDistanceMenu = "Distance"
UnitDistanceMeterMenu = "Meter"
UnitDistanceMeterKilo = "Kilometer"
UnitDistanceMeter = "Meter"
UnitDistanceMeterMilli = "Millimeter"
UnitDistanceMeterMicro = "Micrometer"
UnitDistanceMeterNano = "Nanometer"
UnitDistanceMeterPico = "Picometer"
UnitDistanceImperialMenu = "US Customary"
UnitDistanceInch = "Inch"
UnitDistanceFoot = "Foot"
UnitDistanceYard = "Yard"
@@ -27,13 +24,11 @@ UnitDistanceMile = "Mile"
UnitDistanceAstronomicalUnit = "Astronomical unit"
UnitDistanceLightYear = "Light year"
UnitDistanceParsec = "Parsec"
UnitMassImperialMenu = "US Customary"
UnitMassMenu = "Mass"
UnitMassGramKilo = "Kilogram"
UnitMassGram = "Gram"
UnitMassGramMilli = "Milligram"
UnitMassGramMicro = "Microgram"
UnitMassGramNano = "Nanogram"
UnitMassTonne = "Metric Ton"
UnitMassOunce = "Ounce"
UnitMassPound = "Pound"
@@ -423,7 +418,6 @@ EscapeVelocityFromEarth = "Of Earth"
EscapeVelocityFromMoon = "Of Moon"
EscapeVelocityFromSun = "Of Sun"
SpeedOfLightTag = "Speed of light"
YearLightTag = "One year light"
Thermodynamics = "Thermodynamics"
BoltzmannTag = "Boltzmann Constant"
AvogadroTag = "Avogadro Constant"
@@ -466,7 +460,6 @@ MoonMassTag = "Moon"
EarthMassTag = "Earth"
SunMassTag = "Sun"
ParticleMass = "Particles Mass"
AstronomicalMass = "Astronomical"
Radiuses = "Radiuses"
Length = "Length"
Distances = "Distances"

View File

@@ -1,6 +1,5 @@
Unit = "Units"
UnitTimeMenu = "Time"
UnitTimeSecondMenu = "Second"
UnitTimeSecond = "Second"
UnitTimeSecondMilli = "Millisecond"
UnitTimeSecondMicro = "Microsecond"
@@ -12,18 +11,15 @@ UnitTimeWeek = "Week"
UnitTimeMonth = "Month"
UnitTimeYear = "Year"
UnitDistanceMenu = "Distance"
UnitDistanceMeterMenu = "Meter"
UnitDistanceMeterKilo = "Kilometer"
UnitDistanceMeter = "Meter"
UnitDistanceMeterMilli = "Millimeter"
UnitDistanceMeterMicro = "Micrometer"
UnitDistanceMeterNano = "Nanometer"
UnitDistanceMeterPico = "Picometer"
UnitDistanceImperialMenu = "US Customary"
UnitDistanceAstronomicalUnit = "Astronomical unit"
UnitDistanceLightYear = "Light year"
UnitDistanceParsec = "Parsec"
UnitMassImperialMenu = "US Customary"
UnitDistanceMile = "Milla"
UnitDistanceYard = "Yardas"
UnitDistanceFoot = "Pie"
@@ -33,7 +29,6 @@ UnitMassGramKilo = "Kilogram"
UnitMassGram = "Gram"
UnitMassGramMilli = "Milligram"
UnitMassGramMicro = "Microgram"
UnitMassGramNano = "Nanogram"
UnitMassTonne = "Tonne"
UnitMassOunce = "Onza"
UnitMassPound = "Libra"
@@ -415,7 +410,6 @@ AlphaElementUbn = "Ubn - Unbinilio (120)"
Speed = "Velocidad"
SpeedOfLightTag = "Velocidad de la luz"
SpeedOfSound = "La velocidad del sonido"
YearLightTag = "Un año de luz"
Thermodynamics = "Termodinámica"
SpeedOfSound0Tag = "Nivel del mar, 20 ° C"
SpeedOfSoundWaterTag = "En el agua"
@@ -466,7 +460,6 @@ MoonMassTag = "Luna"
EarthMassTag = "Tierra"
SunMassTag = "Sol"
ParticleMass = "Misa de las partículas"
AstronomicalMass = "Astronómica"
Radiuses = "Radios"
Length = "Lenght"
Distances = "Distancias"

View File

@@ -1,6 +1,5 @@
Unit = "Unités"
UnitTimeMenu = "Temps"
UnitTimeSecondMenu = "Seconde"
UnitTimeSecond = "Seconde"
UnitTimeSecondMilli = "Milliseconde"
UnitTimeSecondMicro = "Microseconde"
@@ -12,14 +11,12 @@ UnitTimeWeek = "Semaine"
UnitTimeMonth = "Mois"
UnitTimeYear = "Année"
UnitDistanceMenu = "Distance"
UnitDistanceMeterMenu = "Mètre"
UnitDistanceMeterKilo = "Kilomètre"
UnitDistanceMeter = "Mètre"
UnitDistanceMeterMilli = "Millimètre"
UnitDistanceMeterMicro = "Micromètre"
UnitDistanceMeterNano = "Nanomètre"
UnitDistanceMeterPico = "Picomètre"
UnitDistanceImperialMenu = "US Customary"
UnitDistanceInch = "Inch"
UnitDistanceFoot = "Foot"
UnitDistanceYard = "Yard"
@@ -27,7 +24,6 @@ UnitDistanceMile = "Mile"
UnitDistanceAstronomicalUnit = "Unité astronomique"
UnitDistanceLightYear = "Année-lumière"
UnitDistanceParsec = "Parsec"
UnitMassImperialMenu = "US Customary"
UnitDistanceMile = "Mile"
UnitDistanceYard = "Yard"
UnitDistanceFoot = "Pied"
@@ -37,7 +33,6 @@ UnitMassGramKilo = "Kilogramme"
UnitMassGram = "Gramme"
UnitMassGramMilli = "Milligramme"
UnitMassGramMicro = "Microgramme"
UnitMassGramNano = "Nanogramme"
UnitMassTonne = "Tonne"
UnitMassOunce = "Once"
UnitMassPound = "Livre"
@@ -423,7 +418,6 @@ SpeedOfSoundWaterTag = "Dans l'eau"
SpeedOfSoundSteelTag = "Dans l'acier"
SpeedOfSoundGlassTag = "Dans le verre"
SpeedOfLightTag = "Vitesse de la lumière"
YearLightTag = "Année lumière"
Thermodynamics = "Thermodynamique"
BoltzmannTag = "Constante de Boltzmann"
AvogadroTag = "Constante d'Avogadro"
@@ -470,7 +464,6 @@ MoonMassTag = "Lune"
EarthMassTag = "Terre"
SunMassTag = "Soleil"
ParticleMass = "Masses des Particules"
AstronomicalMass = "Astronomiques"
Radiuses = "Rayons"
Length = "Longueur"
Distances = "Distances"

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,5 @@
Unit = "Unità"
UnitTimeMenu = "Tempo"
UnitTimeSecondMenu = "Secondo"
UnitTimeSecond = "Secondo"
UnitTimeSecondMilli = "Millisecondo"
UnitTimeSecondMicro = "Microsecondo"
@@ -12,18 +11,15 @@ UnitTimeWeek = "Settimana"
UnitTimeMonth = "Mese"
UnitTimeYear = "Anno"
UnitDistanceMenu = "Distanza"
UnitDistanceMeterMenu = "Metro"
UnitDistanceMeterKilo = "Chilometro"
UnitDistanceMeter = "Metro"
UnitDistanceMeterMilli = "Millimetro"
UnitDistanceMeterMicro = "Micrometro"
UnitDistanceMeterNano = "Nanometro"
UnitDistanceMeterPico = "Picometro"
UnitDistanceImperialMenu = "US Customary"
UnitDistanceAstronomicalUnit = "Unità astronomica"
UnitDistanceLightYear = "Anno luce"
UnitDistanceParsec = "Parsec"
UnitMassImperialMenu = "US Customary"
UnitDistanceMile = "Miglio"
UnitDistanceYard = "Yard"
UnitDistanceFoot = "Piede"
@@ -33,7 +29,6 @@ UnitMassGramKilo = "Kilogrammo"
UnitMassGram = "Grammo"
UnitMassGramMilli = "Milligrammo"
UnitMassGramMicro = "Microgrammo"
UnitMassGramNano = "Nanogrammo"
UnitMassTonne = "Tonnellata"
UnitMassOunce = "Oncia"
UnitMassPound = "Libbra"
@@ -423,7 +418,6 @@ EscapeVelocityFromEarth = "Della terra"
EscapeVelocityFromMoon = "Di luna"
EscapeVelocityFromSun = "Di sole"
SpeedOfLightTag = "Velocità della luce"
YearLightTag = "Un anno di luce"
Thermodynamics = "Termodinamica"
BoltzmannTag = "Costante di Boltzmann"
AvogadroTag = "Costanto di Avogadro"
@@ -466,7 +460,6 @@ MoonMassTag = "Luna"
EarthMassTag = "Terra"
SunMassTag = "Sole"
ParticleMass = "Massa delle particelle"
AstronomicalMass = "Astronomico"
Radiuses = "Raggi"
Length = "Lunghezza"
Distances = "Distanze"

View File

@@ -1,6 +1,5 @@
Unit = "Eenheden"
UnitTimeMenu = "Tijd"
UnitTimeSecondMenu = "Seconde"
UnitTimeSecond = "Seconde"
UnitTimeSecondMilli = "MilliSeconde"
UnitTimeSecondMicro = "Microseconde"
@@ -12,18 +11,15 @@ UnitTimeWeek = "Week"
UnitTimeMonth = "Maand"
UnitTimeYear = "Jaar"
UnitDistanceMenu = "Afstand"
UnitDistanceMeterMenu = "Meter"
UnitDistanceMeterKilo = "Kilometer"
UnitDistanceMeter = "Meter"
UnitDistanceMeterMilli = "Millimeter"
UnitDistanceMeterMicro = "Micrometer"
UnitDistanceMeterNano = "Nanometer"
UnitDistanceMeterPico = "Picometer"
UnitDistanceImperialMenu = "US Customary"
UnitDistanceAstronomicalUnit = "Astronomische eenheid"
UnitDistanceLightYear = "Lichtjaar"
UnitDistanceParsec = "Parsec"
UnitMassImperialMenu = "US Customary"
UnitDistanceMile = "Mijl"
UnitDistanceYard = "Yard"
UnitDistanceFoot = "Voet"
@@ -33,7 +29,6 @@ UnitMassGramKilo = "Kilogram"
UnitMassGram = "Gram"
UnitMassGramMilli = "Milligram"
UnitMassGramMicro = "Microgram"
UnitMassGramNano = "Nanogram"
UnitMassTonne = "Ton"
UnitMassOunce = "Ons"
UnitMassPound = "Pond"
@@ -423,7 +418,6 @@ EscapeVelocityFromEarth = "Van Aarde"
EscapeVelocityFromMoon = "Van Maan"
EscapeVelocityFromSun = "Van de zon"
SpeedOfLightTag = "Lichtsnelheid"
YearLightTag = "Een jaar licht"
Thermodynamics = "Thermodynamica"
BoltzmannTag = "Boltzmannconstante"
AvogadroTag = "Avogadroconstante"
@@ -466,7 +460,6 @@ MoonMassTag = "Maan"
EarthMassTag = "Aarde"
SunMassTag = "Zon"
ParticleMass = "Deeltjesmassa"
AstronomicalMass = "Astronomical"
Radiuses = "Radiuses"
Length = "Lengte"
Distances = "Afstanden"

View File

@@ -1,6 +1,5 @@
Unit = "Unidade"
UnitTimeMenu = "Tempo"
UnitTimeSecondMenu = "Segundo"
UnitTimeSecond = "Segundo"
UnitTimeSecondMilli = "Milisegundo"
UnitTimeSecondMicro = "Microsegundo"
@@ -12,18 +11,15 @@ UnitTimeWeek = "Semana"
UnitTimeMonth = "Mês"
UnitTimeYear = "Ano"
UnitDistanceMenu = "Distância"
UnitDistanceMeterMenu = "Metro"
UnitDistanceMeterKilo = "Quilómetro"
UnitDistanceMeter = "Metro"
UnitDistanceMeterMilli = "Milímetro"
UnitDistanceMeterMicro = "Micrómetro"
UnitDistanceMeterNano = "Nanómetro"
UnitDistanceMeterPico = "Picómetro"
UnitDistanceImperialMenu = "US Customary"
UnitDistanceAstronomicalUnit = "Unidade astronómica"
UnitDistanceLightYear = "Ano-luz"
UnitDistanceParsec = "Parsec"
UnitMassImperialMenu = "US Customary"
UnitDistanceMile = "Milha"
UnitDistanceYard = "Jarda"
UnitDistanceFoot = "Pé"
@@ -33,7 +29,6 @@ UnitMassGramKilo = "Quilograma"
UnitMassGram = "Grama"
UnitMassGramMilli = "Miligrama"
UnitMassGramMicro = "Micrograma"
UnitMassGramNano = "Nanograma"
UnitMassTonne = "Tonelada"
UnitMassOunce = "Onça"
UnitMassPound = "Libra"
@@ -423,7 +418,6 @@ EscapeVelocity = "Velocidade de Fuga"
EscapeVelocityFromEarth = "Fuga da Terra"
EscapeVelocityFromMoon = "De Lua"
EscapeVelocityFromSun = "Do Sol"
YearLightTag = "Luz de um ano"
Thermodynamics = "Termodinâmica"
BoltzmannTag = "Constante Boltzmann"
AvogadroTag = "Constante Avogadro"
@@ -466,7 +460,6 @@ MoonMassTag = "Lua"
EarthMassTag = "Terra"
SunMassTag = "Sol"
ParticleMass = "Massa de Partículas"
AstronomicalMass = "Astronômico"
Radiuses = "Raio"
Length = "Comprimento"
Distances = "Distâncias"

View File

@@ -6,9 +6,7 @@ ConnectedMessage4 = "Drücken Sie die Zurück-Taste am"
ConnectedMessage5 = "Taschenrechner oder Kabel abziehen,"
ConnectedMessage6 = "um die Verbindung zu trennen."
DfuStatus = "Status des Rechners:"
DfuStatusProtected = "GESCHÜTZT"
DfuStatusUnprotected = "UNGESCHÜTZT"
USBProtectionLevel0 = "Standardschutz"
USBProtectionLevel1 = "Omega Schutz"
USBProtectionLevel2 = "Systemschutz"
USBProtectionReactivated = "USB-Schutz wurde wieder aktiviert"

View File

@@ -6,9 +6,7 @@ ConnectedMessage4 = "Press the BACK key of your"
ConnectedMessage5 = "calculator or unplug it to"
ConnectedMessage6 = "disconnect it."
DfuStatus = "Calculator status:"
DfuStatusProtected = "PROTECTED"
DfuStatusUnprotected = "UNPROTECTED"
USBProtectionLevel0 = "Default Protection"
USBProtectionLevel1 = "Omega Protection"
USBProtectionLevel2 = "System Protection"
USBProtectionReactivated = "USB Protection reactivated"

View File

@@ -6,9 +6,7 @@ ConnectedMessage4 = "Pulse el botón RETURN de la"
ConnectedMessage5 = "calculadora o desenchúfela para"
ConnectedMessage6 = "desconectarla."
DfuStatus = "Estado de la calculadora:"
DfuStatusProtected = "PROTEGIDO"
DfuStatusUnprotected = "DESABRIGADO"
USBProtectionLevel0 = "Protección predeterminada"
USBProtectionLevel1 = "Protección Omega"
USBProtectionLevel2 = "Protección del sistema"
USBProtectionReactivated = "La protección de la calculadora ha sido reactivada"

View File

@@ -6,9 +6,7 @@ ConnectedMessage4 = "Appuyez sur la touche RETOUR"
ConnectedMessage5 = "de la calculatrice ou débranchez-la"
ConnectedMessage6 = "pour la déconnecter."
DfuStatus = "Etat de la calculatrice:"
DfuStatusProtected = "PROTÉGÉE"
DfuStatusUnprotected = "NON PROTÉGÉE"
USBProtectionLevel0 = "Default Protection"
USBProtectionLevel1 = "Omega Protection"
USBProtectionLevel2 = "System Protection"
USBProtectionReactivated = "La protection USB a été réactivée"

View File

@@ -1,14 +1,12 @@
USBConnected = "A SZÁMOLÓGÉP CSATLAKOZTATVA VAN"
ConnectedMessage1 = ""
ConnectedMessage2 = "Adat másolásához csatlakozzon"
ConnectedMessage3 = "fel getomega.dev/ide ra."
ConnectedMessage4 = "Nyomjon majd a VISSZA gombra"
ConnectedMessage5 = "vagy huzza ki a kábelt azért"
ConnectedMessage6 = "hogy a másolás véget érjen."
DfuStatus = "Számológép állapota:"
DfuStatusProtected = "VÉDETT"
DfuStatusUnprotected = "VÉDTELEN"
USBProtectionLevel0 = "Alapértelmezett védelem"
USBProtectionLevel1 = "Omega védelem"
USBProtectionLevel2 = "Rendszervédelem"
USBProtectionReactivated = "A védelem újra aktiválva"
USBConnected = "A SZÁMOLÓGÉP CSATLAKOZTATVA VAN"
ConnectedMessage1 = ""
ConnectedMessage2 = "Adat másolásához csatlakozzon"
ConnectedMessage3 = "fel getomega.dev/ide ra."
ConnectedMessage4 = "Nyomjon majd a VISSZA gombra"
ConnectedMessage5 = "vagy huzza ki a kábelt azért"
ConnectedMessage6 = "hogy a másolás véget érjen."
DfuStatus = "Számológép állapota:"
DfuStatusUnprotected = "VÉDTELEN"
USBProtectionLevel0 = "Alapértelmezett védelem"
USBProtectionLevel1 = "Omega védelem"
USBProtectionLevel2 = "Rendszervédelem"

View File

@@ -6,9 +6,7 @@ ConnectedMessage4 = "Premere sul tasto INDIETRO della"
ConnectedMessage5 = "calcolatrice o scollegatela per"
ConnectedMessage6 = "disconnetterla."
DfuStatus = "Stato della calcolatrice:"
DfuStatusProtected = "PROTETTO"
DfuStatusUnprotected = "INDIFESO"
USBProtectionLevel0 = "Protezione predefinita"
USBProtectionLevel1 = "Protezione Omega"
USBProtectionLevel2 = "Protezione del sistema"
USBProtectionReactivated = "Protezione riattivata"

View File

@@ -6,9 +6,7 @@ ConnectedMessage4 = "Druk op de TERUG toets van je"
ConnectedMessage5 = "rekenmachine of verwijder de"
ConnectedMessage6 = " kabel om hem los te koppelen."
DfuStatus = "Rekenmachine status:"
DfuStatusProtected = "BESCHERMD"
DfuStatusUnprotected = "NIET BESCHERMD"
USBProtectionLevel0 = "Standaardbeveiliging"
USBProtectionLevel1 = "Omega Bescherming"
USBProtectionLevel2 = "Systeembeveiliging"
USBProtectionReactivated = "USB-bescherming is geactiveerd"

View File

@@ -6,9 +6,7 @@ ConnectedMessage4 = "Pressione o botão RETURN na"
ConnectedMessage5 = "calculadora ou desligue-a para a"
ConnectedMessage6 = "desconectar."
DfuStatus = "Status da calculadora:"
DfuStatusProtected = "PROTEGIDO"
DfuStatusUnprotected = "DESPROTEGIDO"
USBProtectionLevel0 = "Proteção padrão"
USBProtectionLevel1 = "Proteção Ômega"
USBProtectionLevel2 = "Proteção do sistema"
USBProtectionReactivated = "Proteção reativada"

View File

@@ -0,0 +1,363 @@
#!/usr/bin/env python3
"""Remove all unused translations to save flash space."""
# Builtins imports
import os
import re
import argparse
# Initialize the parser
parser = argparse.ArgumentParser(
description="Remove unused translations from the i18n file to save flash \
space.", epilog="You can use this script without arguments"
)
# Add arguments to the parser
parser.add_argument("--base-path", default=".",
help="The base path of the files")
parser.add_argument("--no-recursive", default=False, action="store_true",
help="Disable finding the files recursively")
parser.add_argument("--dry-run", default=False, action="store_true",
help="Disable saving the i18n files")
# Parse command line arguments
args = parser.parse_args()
# Initialize the settings
BASE_PATH = args.base_path
FIND_RECURSIVE = not args.no_recursive
DRYRUN = args.dry_run
# Don't add / at the end of the path
IGNORE_PATHS = [
"./output", "./.git", "./.mypy_cache",
"./ion/src/simulator/external/sdl",
]
IGNORE_PATHS_CONTENTS = [
"__pycache__", ".png", ".esc", ".ttf", ".ico", ".jpg", ".jar", ".icn",
".bnr", ".i18n"
]
# If the key contain something that's in this list, keep it to prevent code breaking
KEEP_KEY_IF_CONTAIN = ["Language", "Country"]
def get_all_files_in_directory(directory: str)\
-> list[str]:
"""Get all files in the given directory recursively.
Args:
directory (str): The directory
Returns:
List[str]: The list of files in the directory
"""
# Initialize the list of files
files = []
# Iterate over all files in the directory
for i in os.listdir(directory):
# Add the current directory to the file name
i = f'{directory}/{i}'
# If the file is a directory
if FIND_RECURSIVE and os.path.isdir(i):
# Iter the directory and add the files to the list
files.extend(get_all_files_in_directory(i))
# Else the file is a file
else:
# Add the file to the list
files.append(i)
# Return the list of files
return files
def get_files(directory: str) -> list[str]:
"""Get all files in the directory recursively with ignoring list.
Args:
directory (str): The start directory
Returns:
List[str]: The list of files
"""
# Initialize the list of files
files = []
# Iterate over the directory
for filename in os.listdir(directory):
# Add the full path to the directory/file
filename = f'{directory}/{filename}'
# Exclude path in IGNORE_PATHS
if filename in IGNORE_PATHS:
continue
# Exclude paths in IGNORE_PATHS_CONTENTS
if any(extension in filename for extension in IGNORE_PATHS_CONTENTS):
continue
# If it is a directory, find recursively the files into it
if os.path.isdir(filename):
files.extend(get_files(filename))
else:
files.append(filename)
# Return the file list
return files
def get_keys_in_i18n_file(filename: str) -> list[list[str]]:
"""Return a list of keys in the file.
Args:
filename (str): The name of the file to read
Returns:
List[list[str]]: The keys in the file
"""
# Initialize the list of keys in the file
keys: list[list[str]] = []
# Open the file read only
with open(filename, 'r', encoding='utf-8') as file_read:
# Read the content of the file line by line
for line in file_read.readlines():
# Ignore commented lines
if re.match(r"^#(.*)$", line):
continue
# Ignore lines without =
if '=' not in line:
continue
# Get the key by spliting the line by =
key = line.split("=")[0]
# Remove spaces from the start of the key
while key[0] == " ":
key = key[1:]
# Remove spaces from the end of the key
while key[-1] == " ":
key = key[:-1]
# Get generic filename into a list separated by dots
generic_filename_list = filename.split(".")[:-2]
# Get if the locale is universal
locale = filename.split(".")[-2]
# Get the filename as string with a trailing dot at the end
generic_filename = "".join(f'{i}.' for i in generic_filename_list)
# Remove trailing dot from the end of the generic filename
generic_filename = generic_filename[:-1]
# Add the key and the generic filename to the list of keys
keys.append([key, generic_filename, locale])
return keys
def list_keys_in_i18n_file_list(i18n_files: list[str]) -> list[list[str]]:
"""List all keys in the i18n files.
Args:
i18n_files (list[str]): I18n files list
Returns:
List[list[str]]: The dictionnary of keys in the i18n files by
locale.
"""
# Initialize the list of keys in the i18n files
keys_dict: list[list[str]] = []
# Iterate on the file list
for actual_file in i18n_files:
# Get the keys in the file and add them to the list
keys_dict.extend(get_keys_in_i18n_file(actual_file))
# Return the dictionary of keys in the i18n files sorted by locale
return keys_dict
def extract_keys_from_line(line: str) -> list[str]:
"""Extract keys from a line.
Args:
line (str): The line to extract keys from
Returns:
list[str]: The extracted keys
"""
# Initialize the list of separator to separate the key from the part
keys_separator: list[str] = ["}", ":", ";", ",", " ", ")"]
# Initialize the list of keys
keys: list[str] = []
# Split the line by ::
line_splitted: list[str] = line.split("::")
# Initialize loop variables
# The last part (used inside the loop)
last_part: str = ""
# Mark the next line contain the key
save_next_line: bool = False
# The key part
key_parts: list[str] = []
# Iterate over the splitted line
for part in line_splitted:
# print(part)
if save_next_line:
key_parts.append(part)
save_next_line = False
# If the actual part is Message and the last part contain I18n
# (I18n::Message), the next part will contain the key name
# TODO: Improve catching
if part == "Message" and "I18n" in last_part:
save_next_line = True
# Save the current part into the last part
# (loop iteration is finished)
last_part = part
# Get the key from the key part
# TODO: Improve catching
# Iterate over all the keys in the line
for actual_key in key_parts:
# Initialize real key variable
key_real: str = actual_key
for separator_to_test in keys_separator:
key_separated: list[str] = key_real.split(separator_to_test)
# print(key_real, separator_to_test, key_separated)
# If the key was splitted, save the separated key
if len(key_separated) > 1:
key_real = key_separated[0]
if key_real:
keys.append(key_real)
return keys
def keys_from_file_list(files: list[str]) -> list[str]:
"""Get an array of keys from files.
Args:
files (list[str]): The list of files to read
Returns:
list[str]: The keys
"""
# Initialize the list of keys from the files
keys: list[str] = []
# Iterate over the file list
for filename in files:
# Read the file contents into "content" variable
with open(filename, 'r', encoding="utf-8") as file_obj:
# Store the contents of the file
content = file_obj.read()
# Iterate over the file contents
for line in content.split("\n"):
# Get if the line contains an I18n key
if "I18n::Message" in line:
# Extract the keys from the line
keys.extend(extract_keys_from_line(line))
return keys
def get_i18n_files(directory: str = '.') -> list[str]:
"""Get the list of i18n files in the given directory.
Args:
directory (str, optional): The directory to find the i18n files.
Defaults to '.'.
Returns:
list[str]: The list of i18n files in a dictionary of languages.
"""
# Get all files in the directory recursively
files = get_all_files_in_directory(directory)
# Return only i18n files
return [i for i in files if ".i18n" in i]
def get_unused_keys(file_keys: list[str], i18n_keys: list[list[str]]) -> list[list[str]]:
"""Get unused keys.
Args:
file_keys (list[str]): The keys in the source files
i18n_keys (list[list[str]]): The keys in the i18n files
Returns:
list[list[str]]: The unused keys
"""
# Initialize the list of unused keys
unused_keys: list[list[str]] = []
# Iterate over the i18n key definitions
for key_i18n_actual in i18n_keys:
# Get if the key is used, and mark it as used if it is in the kepping
# list
key_used = next(
(
True
for string_to_test in KEEP_KEY_IF_CONTAIN
if string_to_test in key_i18n_actual[0]
),
any(key_i18n_actual[0] == file_key for file_key in file_keys),
)
# If the key is not used, add it to the list
if not key_used:
if key_i18n_actual not in unused_keys:
print(f"{key_i18n_actual[0]} unused")
unused_keys.append(key_i18n_actual)
return unused_keys
def remove_keys_from_i18n_files(unused_keys: list[list[str]]):
"""Remove unused keys from i18n files.
Args:
unused_keys (list[list[str]]): The list of keys to remove
"""
# Initialize the dictionary of files
# (to prevent intensive writing to disk)
files_to_write: dict[str, str] = {}
# Iterate over the keys to remove
for key in unused_keys:
key_name_to_remove = key[0]
filename_generic = key[1]
locale = key[2]
# Get the filename of from the generic filename
filename = f'{filename_generic}.{locale}.i18n'
# If the file is not in the dictionary, add it
if filename not in files_to_write:
# Save the file contents
with open(filename, 'r', encoding='utf8') as file_read:
files_to_write[filename] = file_read.read()
# Split the file by new lines
file_splitted = files_to_write[filename].split("\n")
# Iterate over the file contents
for line, value in enumerate(file_splitted):
# Ignore lines without =
if '=' not in value:
continue
# Get the key from the line
key_to_check: str = value.split("=")[0]
# Remove spaces from the start of the key
while key_to_check[0] == " ":
key_to_check = key_to_check[1:]
# Remove spaces from the end of the key
while key_to_check[-1] == " ":
key_to_check = key_to_check[:-1]
# If the key is the key to remove, remove it
if key_to_check == key_name_to_remove:
del file_splitted[line]
break
file_str = "".join(line + "\n" for line in file_splitted)
# Remove double line return
while file_str[-2:] == '\n\n':
file_str = file_str[:-1]
files_to_write[filename] = file_str
# When the loop is end, write the files
for actual_file, content_to_write in files_to_write.items():
with open(actual_file, 'w', encoding='utf-8') as file_to_write:
file_to_write.write(content_to_write)
# print(actual_file, content_to_write)
def main():
"""Execute the program."""
# Get the file list
file_list = get_files(BASE_PATH)
# Get the keys in the file list
files_keys = keys_from_file_list(file_list)
# Get i18n files list
i18n_files = get_i18n_files(BASE_PATH)
# Get keys from i18n files
i18n_files_keys = list_keys_in_i18n_file_list(i18n_files)
# Get unused keys
unused_keys = get_unused_keys(files_keys, i18n_files_keys)
# If dryrun is disabled, remove the keys definitions from the i18n files
if not DRYRUN:
remove_keys_from_i18n_files(unused_keys)
main()

View File

@@ -17,7 +17,7 @@ public:
static constexpr int TickDuration = 300; // In Miliseconds
Timer(uint32_t period); // Period is in ticks
bool tick();
void reset();
void reset(uint32_t NewPeriod = -1);
protected:
virtual bool fire() = 0;
uint32_t m_period;

View File

@@ -16,6 +16,9 @@ bool Timer::tick() {
return false;
}
void Timer::reset() {
void Timer::reset(uint32_t NewPeriod) {
if(NewPeriod != -1){
m_period = NewPeriod;
}
m_numberOfTicksBeforeFire = m_period;
}

View File

@@ -12,7 +12,6 @@ bool isInitialized();
void shutdown();
void setBrightness(uint8_t b);
uint8_t brightness();
const int NumberOfStepsPerShortcut = 4;
}
}

View File

@@ -0,0 +1,218 @@
#ifndef ION_INTERNAL_STORAGE_H
#define ION_INTERNAL_STORAGE_H
#include <stddef.h>
#include <stdint.h>
#include "storage.h"
namespace Ion {
/* Storage : | Magic | Record1 | Record2 | ... | Magic |
* | Magic | Size1(uint16_t) | FullName1 | Body1 | Size2(uint16_t) | FullName2 | Body2 | ... | Magic |
*
* A record's fullName is baseName.extension. */
class StorageDelegate;
class InternalStorage {
public:
typedef uint16_t record_size_t;
static constexpr char eqExtension[] = "eq";
static constexpr char expExtension[] = "exp";
static constexpr char funcExtension[] = "func";
static constexpr char seqExtension[] = "seq";
constexpr static size_t k_storageSize = 60000;
static_assert(UINT16_MAX >= k_storageSize, "record_size_t not big enough");
constexpr static char k_dotChar = '.';
class Record {
/* A Record is identified by the CRC32 on its fullName because:
* - A record is identified by its fullName, which is unique
* - We cannot keep the address pointing to the fullName because if another
* record is modified, it might alter our record's fullName address.
* Keeping a buffer with the fullNames will waste memory as we cannot
* forsee the size of the fullNames. */
friend class Storage;
public:
enum class ErrorStatus {
None = 0,
NameTaken = 1,
NonCompliantName = 2,
NotEnoughSpaceAvailable = 3,
RecordDoesNotExist = 4
};
struct Data {
const void * buffer;
size_t size;
};
Record(const char * fullName = nullptr);
Record(const char * basename, const char * extension);
bool operator==(const Record & other) const {
return m_fullNameCRC32 == other.m_fullNameCRC32;
}
bool operator!=(const Record & other) const {
return !(*this == other);
}
#if ION_STORAGE_LOG
void log();
#endif
uint32_t checksum();
bool isNull() const {
return m_fullNameCRC32 == 0;
}
const char * fullName() const;
ErrorStatus setBaseNameWithExtension(const char * baseName, const char * extension);
ErrorStatus setName(const char * fullName);
Data value() const;
ErrorStatus setValue(Data data);
void destroy();
private:
Record(const char * basename, int basenameLength, const char * extension, int extensionLength);
uint32_t m_fullNameCRC32;
};
#if ION_STORAGE_LOG
void log();
#endif
size_t availableSize();
size_t putAvailableSpaceAtEndOfRecord(Record r);
void getAvailableSpaceFromEndOfRecord(Record r, size_t recordAvailableSpace);
uint32_t checksum();
// Delegate
void setDelegate(StorageDelegate * delegate) { m_delegate = delegate; }
void notifyChangeToDelegate(const Record r = Record()) const;
Record::ErrorStatus notifyFullnessToDelegate() const;
int numberOfRecordsWithExtension(const char * extension);
static bool FullNameHasExtension(const char * fullName, const char * extension, size_t extensionLength);
// Record creation
Record::ErrorStatus createRecordWithFullName(const char * fullName, const void * data, size_t size);
Record::ErrorStatus createRecordWithExtension(const char * baseName, const char * extension, const void * data, size_t size);
// Record getters
bool hasRecord(Record r) { return pointerOfRecord(r) != nullptr; }
Record recordWithExtensionAtIndex(const char * extension, int index);
Record recordNamed(const char * fullName);
Record recordBaseNamedWithExtension(const char * baseName, const char * extension);
Record recordBaseNamedWithExtensions(const char * baseName, const char * const extension[], size_t numberOfExtensions);
const char * extensionOfRecordBaseNamedWithExtensions(const char * baseName, int baseNameLength, const char * const extension[], size_t numberOfExtensions);
// Record destruction
void destroyAllRecords();
void destroyRecordWithBaseNameAndExtension(const char * baseName, const char * extension);
void destroyRecordsWithExtension(const char * extension);
// Useful
static bool FullNameCompliant(const char * name);
// Used by Python OS module
int numberOfRecords();
Record recordAtIndex(int index);
protected:
InternalStorage();
/* Getters on address in buffer */
char * pointerOfRecord(const Record record) const;
record_size_t sizeOfRecordStarting(char * start) const;
const char * fullNameOfRecordStarting(char * start) const;
const void * valueOfRecordStarting(char * start) const;
void destroyRecord(const Record record);
class RecordIterator {
public:
RecordIterator(char * start) : m_recordStart(start) {}
char * operator*() { return m_recordStart; }
RecordIterator& operator++();
bool operator!=(const RecordIterator& it) const { return m_recordStart != it.m_recordStart; }
private:
char * m_recordStart;
};
RecordIterator begin() const {
if (sizeOfRecordStarting((char *)m_buffer) == 0) {
return nullptr;
}
return RecordIterator((char *)m_buffer);
};
RecordIterator end() const { return RecordIterator(nullptr); }
mutable Record m_lastRecordRetrieved;
mutable char * m_lastRecordRetrievedPointer;
private:
constexpr static uint32_t Magic = 0xEE0BDDBA;
constexpr static size_t k_maxRecordSize = (1 << sizeof(record_size_t)*8);
/* Getters/Setters on recordID */
const char * fullNameOfRecord(const Record record);
Record::ErrorStatus setFullNameOfRecord(const Record record, const char * fullName);
Record::ErrorStatus setBaseNameWithExtensionOfRecord(const Record record, const char * baseName, const char * extension);
Record::Data valueOfRecord(const Record record);
Record::ErrorStatus setValueOfRecord(const Record record, Record::Data data);
/* Overriders */
size_t overrideSizeAtPosition(char * position, record_size_t size);
size_t overrideFullNameAtPosition(char * position, const char * fullName);
size_t overrideBaseNameWithExtensionAtPosition(char * position, const char * baseName, const char * extension);
size_t overrideValueAtPosition(char * position, const void * data, record_size_t size);
bool isFullNameTaken(const char * fullName, const Record * recordToExclude = nullptr);
bool isBaseNameWithExtensionTaken(const char * baseName, const char * extension, Record * recordToExclude = nullptr);
bool isNameOfRecordTaken(Record r, const Record * recordToExclude);
char * endBuffer();
size_t sizeOfBaseNameAndExtension(const char * baseName, const char * extension) const;
size_t sizeOfRecordWithBaseNameAndExtension(const char * baseName, const char * extension, size_t size) const;
size_t sizeOfRecordWithFullName(const char * fullName, size_t size) const;
bool slideBuffer(char * position, int delta);
Record privateRecordAndExtensionOfRecordBaseNamedWithExtensions(const char * baseName, const char * const extensions[], size_t numberOfExtensions, const char * * extensionResult = nullptr, int baseNameLength = -1);
uint32_t m_magicHeader;
char m_buffer[k_storageSize];
uint32_t m_magicFooter;
StorageDelegate * m_delegate;
};
/* Some apps memoize records and need to be notified when a record might have
* become invalid. For instance in the Graph app, if f(x) = A+x, and A changed,
* f(x) memoization which stores the reduced expression of f is outdated.
* We could have computed and compared the checksum of the storage to detect
* storage invalidity, but profiling showed that this slows down the execution
* (for example when scrolling the functions list).
* We thus decided to notify a delegate when the storage changes. */
class StorageDelegate {
public:
virtual void storageDidChangeForRecord(const InternalStorage::Record record) = 0;
virtual void storageIsFull() = 0;
};
// emscripten read and writes must be aligned.
class StorageHelper {
public:
static uint16_t unalignedShort(char * address) {
#if __EMSCRIPTEN__
uint8_t f1 = *(address);
uint8_t f2 = *(address+1);
uint16_t f = (uint16_t)f1 + (((uint16_t)f2)<<8);
return f;
#else
return *(uint16_t *)address;
#endif
}
static void writeUnalignedShort(uint16_t value, char * address) {
#if __EMSCRIPTEN__
*((uint8_t *)address) = (uint8_t)(value & ((1 << 8) - 1));
*((uint8_t *)address+1) = (uint8_t)(value >> 8);
#else
*((uint16_t *)address) = value;
#endif
}
};
}
#endif

View File

@@ -1,239 +1,50 @@
#ifndef ION_STORAGE_H
#define ION_STORAGE_H
#include <stddef.h>
#include <stdint.h>
#include "internal_storage.h"
namespace Ion {
/* Storage : | Magic | Record1 | Record2 | ... | Magic |
* | Magic | Size1(uint16_t) | FullName1 | Body1 | Size2(uint16_t) | FullName2 | Body2 | ... | Magic |
*
* A record's fullName is baseName.extension. */
class StorageDelegate;
class Storage {
class Storage : public InternalStorage {
public:
typedef uint16_t record_size_t;
using InternalStorage::Record;
constexpr static size_t k_storageSize = 60000;
static_assert(UINT16_MAX >= k_storageSize, "record_size_t not big enough");
using InternalStorage::expExtension;
using InternalStorage::funcExtension;
using InternalStorage::seqExtension;
using InternalStorage::eqExtension;
static Storage * sharedStorage();
constexpr static char k_dotChar = '.';
static constexpr char eqExtension[] = "eq";
static constexpr char expExtension[] = "exp";
static constexpr char funcExtension[] = "func";
static constexpr char seqExtension[] = "seq";
class Record {
/* A Record is identified by the CRC32 on its fullName because:
* - A record is identified by its fullName, which is unique
* - We cannot keep the address pointing to the fullName because if another
* record is modified, it might alter our record's fullName address.
* Keeping a buffer with the fullNames will waste memory as we cannot
* forsee the size of the fullNames. */
friend class Storage;
public:
enum class ErrorStatus {
None = 0,
NameTaken = 1,
NonCompliantName = 2,
NotEnoughSpaceAvailable = 3,
RecordDoesNotExist = 4
};
struct Data {
const void * buffer;
size_t size;
};
Record(const char * fullName = nullptr);
Record(const char * basename, const char * extension);
bool operator==(const Record & other) const {
return m_fullNameCRC32 == other.m_fullNameCRC32;
}
bool operator!=(const Record & other) const {
return !(*this == other);
}
#if ION_STORAGE_LOG
void log();
#endif
uint32_t checksum();
bool isNull() const {
return m_fullNameCRC32 == 0;
}
const char * fullName() const {
return Storage::sharedStorage()->fullNameOfRecord(*this);
}
ErrorStatus setBaseNameWithExtension(const char * baseName, const char * extension) {
return Storage::sharedStorage()->setBaseNameWithExtensionOfRecord(*this, baseName, extension);
}
ErrorStatus setName(const char * fullName) {
return Storage::sharedStorage()->setFullNameOfRecord(*this, fullName);
}
Data value() const {
return Storage::sharedStorage()->valueOfRecord(*this);
}
ErrorStatus setValue(Data data) {
return Storage::sharedStorage()->setValueOfRecord(*this, data);
}
void destroy() {
return Storage::sharedStorage()->destroyRecord(*this);
}
private:
Record(const char * basename, int basenameLength, const char * extension, int extensionLength);
uint32_t m_fullNameCRC32;
};
#if ION_STORAGE_LOG
void log();
#endif
size_t availableSize();
size_t putAvailableSpaceAtEndOfRecord(Record r);
void getAvailableSpaceFromEndOfRecord(Record r, size_t recordAvailableSpace);
uint32_t checksum();
// Delegate
void setDelegate(StorageDelegate * delegate) { m_delegate = delegate; }
void notifyChangeToDelegate(const Record r = Record()) const;
Record::ErrorStatus notifyFullnessToDelegate() const;
int numberOfRecordsWithExtension(const char * extension);
static bool FullNameHasExtension(const char * fullName, const char * extension, size_t extensionLength);
// Record creation
Record::ErrorStatus createRecordWithFullName(const char * fullName, const void * data, size_t size);
Record::ErrorStatus createRecordWithExtension(const char * baseName, const char * extension, const void * data, size_t size);
// Record getters
bool hasRecord(Record r) { return pointerOfRecord(r) != nullptr; }
bool hasRecord(Record r);
Record recordWithExtensionAtIndex(const char * extension, int index);
Record recordNamed(const char * fullName);
Record recordBaseNamedWithExtension(const char * baseName, const char * extension);
Record recordBaseNamedWithExtensions(const char * baseName, const char * const extension[], size_t numberOfExtensions);
const char * extensionOfRecordBaseNamedWithExtensions(const char * baseName, int baseNameLength, const char * const extension[], size_t numberOfExtensions);
// Record destruction
void destroyAllRecords();
void destroyRecordWithBaseNameAndExtension(const char * baseName, const char * extension);
void destroyRecordsWithExtension(const char * extension);
// Useful
static bool FullNameCompliant(const char * name);
// Used by Python OS module
int numberOfRecords();
Record recordAtIndex(int index); // Unlike realRecordAtIndex, this ignore trash
Record recordAtIndex(int index);
void destroyRecord(Record record);
// Trash
void reinsertTrash(const char * extension);
void emptyTrash();
private:
constexpr static uint32_t Magic = 0xEE0BDDBA;
constexpr static size_t k_maxRecordSize = (1 << sizeof(record_size_t)*8);
Storage():
InternalStorage() {}
Storage();
/* Getters/Setters on recordID */
const char * fullNameOfRecord(const Record record);
Record::ErrorStatus setFullNameOfRecord(const Record record, const char * fullName);
Record::ErrorStatus setBaseNameWithExtensionOfRecord(const Record record, const char * baseName, const char * extension);
Record::Data valueOfRecord(const Record record);
Record::ErrorStatus setValueOfRecord(const Record record, Record::Data data);
void destroyRecord(const Record record);
void realDestroyRecord(const Record record);
/* Getters on address in buffer */
char * pointerOfRecord(const Record record) const;
record_size_t sizeOfRecordStarting(char * start) const;
const char * fullNameOfRecordStarting(char * start) const;
const void * valueOfRecordStarting(char * start) const;
/* Trash */
void emptyTrash();
Storage::Record realRecordAtIndex(int index);
int realNumberOfRecords();
/* Overriders */
size_t overrideSizeAtPosition(char * position, record_size_t size);
size_t overrideFullNameAtPosition(char * position, const char * fullName);
size_t overrideBaseNameWithExtensionAtPosition(char * position, const char * baseName, const char * extension);
size_t overrideValueAtPosition(char * position, const void * data, record_size_t size);
size_t realAvailableSize();
bool isFullNameTaken(const char * fullName, const Record * recordToExclude = nullptr);
bool isBaseNameWithExtensionTaken(const char * baseName, const char * extension, Record * recordToExclude = nullptr);
bool isNameOfRecordTaken(Record r, const Record * recordToExclude);
char * endBuffer();
size_t sizeOfBaseNameAndExtension(const char * baseName, const char * extension) const;
size_t sizeOfRecordWithBaseNameAndExtension(const char * baseName, const char * extension, size_t size) const;
size_t sizeOfRecordWithFullName(const char * fullName, size_t size) const;
bool slideBuffer(char * position, int delta);
class RecordIterator {
public:
RecordIterator(char * start) : m_recordStart(start) {}
char * operator*() { return m_recordStart; }
RecordIterator& operator++();
bool operator!=(const RecordIterator& it) const { return m_recordStart != it.m_recordStart; }
private:
char * m_recordStart;
};
RecordIterator begin() const {
if (sizeOfRecordStarting((char *)m_buffer) == 0) {
return nullptr;
}
return RecordIterator((char *)m_buffer);
};
RecordIterator end() const { return RecordIterator(nullptr); }
Record privateRecordAndExtensionOfRecordBaseNamedWithExtensions(const char * baseName, const char * const extensions[], size_t numberOfExtensions, const char * * extensionResult = nullptr, int baseNameLength = -1);
uint32_t m_magicHeader;
char m_buffer[k_storageSize];
Record m_trashRecord;
uint32_t m_magicFooter;
StorageDelegate * m_delegate;
mutable Record m_lastRecordRetrieved;
mutable char * m_lastRecordRetrievedPointer;
};
/* Some apps memoize records and need to be notified when a record might have
* become invalid. For instance in the Graph app, if f(x) = A+x, and A changed,
* f(x) memoization which stores the reduced expression of f is outdated.
* We could have computed and compared the checksum of the storage to detect
* storage invalidity, but profiling showed that this slows down the execution
* (for example when scrolling the functions list).
* We thus decided to notify a delegate when the storage changes. */
class StorageDelegate {
public:
virtual void storageDidChangeForRecord(const Storage::Record record) = 0;
virtual void storageIsFull() = 0;
};
// emscripten read and writes must be aligned.
class StorageHelper {
public:
static uint16_t unalignedShort(char * address) {
#if __EMSCRIPTEN__
uint8_t f1 = *(address);
uint8_t f2 = *(address+1);
uint16_t f = (uint16_t)f1 + (((uint16_t)f2)<<8);
return f;
#else
return *(uint16_t *)address;
#endif
}
static void writeUnalignedShort(uint16_t value, char * address) {
#if __EMSCRIPTEN__
*((uint8_t *)address) = (uint8_t)(value & ((1 << 8) - 1));
*((uint8_t *)address+1) = (uint8_t)(value >> 8);
#else
*((uint16_t *)address) = value;
#endif
}
};
}

View File

@@ -236,6 +236,8 @@ SECTIONS {
. = ALIGN(4);
*(.rodata._ZN3Ion6Device13ExternalFlash*)
/* 'start' dependencies */
*(.rodata._ZN3Ion6Device8Keyboard6ConfigL10ColumnGPIOE*)
*(.rodata._ZN3Ion6Device8Keyboard6ConfigL7RowGPIOE*)
*(.rodata._ZN3Ion6Device4RegsL5GPIOAE)
*(.rodata._ZN3Ion6Device4RegsL5GPIOBE)
*(.rodata._ZN3Ion6Device3LED6ConfigL7RGBPinsE)

View File

@@ -0,0 +1,647 @@
#include <ion.h>
#include <string.h>
#include <assert.h>
#include <new>
#include <ion/internal_storage.h>
#if ION_STORAGE_LOG
#include <iostream>
#endif
namespace Ion {
/* We want to implement a simple singleton pattern, to make sure the storage is
* initialized on first use, therefore preventing the static init order fiasco.
* That being said, we rely on knowing where the storage resides in the device's
* memory at compile time. Indeed, we want to advertise the static storage's
* memory address in the PlatformInfo structure (so that we can read and write
* it in DFU).
* Using a "static Storage storage;" variable makes it a local symbol at best,
* preventing the PlatformInfo from retrieving its address. And making the
* Storage variable global yields the static init fiasco issue. We're working
* around both issues by creating a global staticStorageArea buffer, and by
* placement-newing the Storage into that area on first use. */
/* The InternalStorage is handle all records. Then the "normal" Storage handle
* a trash */
constexpr char InternalStorage::expExtension[];
constexpr char InternalStorage::funcExtension[];
constexpr char InternalStorage::seqExtension[];
constexpr char InternalStorage::eqExtension[];
// RECORD
const char * InternalStorage::Record::fullName() const {
return Storage::sharedStorage()->fullNameOfRecord(*this);
}
InternalStorage::Record::ErrorStatus InternalStorage::Record::setBaseNameWithExtension(const char * baseName, const char * extension) {
return Storage::sharedStorage()->setBaseNameWithExtensionOfRecord(*this, baseName, extension);
}
InternalStorage::Record::ErrorStatus InternalStorage::Record::setName(const char * fullName) {
return Storage::sharedStorage()->setFullNameOfRecord(*this, fullName);
}
InternalStorage::Record::Data InternalStorage::Record::value() const {
return Storage::sharedStorage()->valueOfRecord(*this);
}
InternalStorage::Record::ErrorStatus InternalStorage::Record::setValue(Data data) {
return Storage::sharedStorage()->setValueOfRecord(*this, data);
}
void InternalStorage::Record::destroy() {
return Storage::sharedStorage()->destroyRecord(*this);
}
InternalStorage::Record::Record(const char * fullName) {
if (fullName == nullptr) {
m_fullNameCRC32 = 0;
return;
}
const char * dotChar = UTF8Helper::CodePointSearch(fullName, k_dotChar);
// If no extension, return empty record
if (*dotChar == 0 || *(dotChar+1) == 0) {
m_fullNameCRC32 = 0;
return;
}
new (this) Record(fullName, dotChar - fullName, dotChar+1, (fullName + strlen(fullName)) - (dotChar+1));
}
InternalStorage::Record::Record(const char * baseName, const char * extension) {
if (baseName == nullptr) {
assert(extension == nullptr);
m_fullNameCRC32 = 0;
return;
}
new (this) Record(baseName, strlen(baseName), extension, strlen(extension));
}
#if ION_STORAGE_LOG
void InternalStorage::Record::log() {
std::cout << "Name: " << fullName() << std::endl;
std::cout << " Value (" << value().size << "): " << (char *)value().buffer << "\n\n" << std::endl;
}
#endif
uint32_t InternalStorage::Record::checksum() {
uint32_t crc32Results[2];
crc32Results[0] = m_fullNameCRC32;
Data data = value();
crc32Results[1] = Ion::crc32Byte((const uint8_t *)data.buffer, data.size);
return Ion::crc32Word(crc32Results, 2);
}
InternalStorage::Record::Record(const char * basename, int basenameLength, const char * extension, int extensionLength) {
assert(basename != nullptr);
assert(extension != nullptr);
// We compute the CRC32 of the CRC32s of the basename and the extension
uint32_t crc32Results[2];
crc32Results[0] = Ion::crc32Byte((const uint8_t *)basename, basenameLength);
crc32Results[1] = Ion::crc32Byte((const uint8_t *)extension, extensionLength);
m_fullNameCRC32 = Ion::crc32Word(crc32Results, 2);
}
// STORAGE
#if ION_STORAGE_LOG
void InternalStorage::log() {
for (char * p : *this) {
const char * currentName = fullNameOfRecordStarting(p);
Record(currentName).log();
}
}
#endif
size_t InternalStorage::availableSize() {
/* TODO maybe do: availableSize(char ** endBuffer) to get the endBuffer if it
* is needed after calling availableSize */
assert(k_storageSize >= (endBuffer() - m_buffer) + sizeof(record_size_t));
return k_storageSize-(endBuffer()-m_buffer)-sizeof(record_size_t);
}
size_t InternalStorage::putAvailableSpaceAtEndOfRecord(InternalStorage::Record r) {
char * p = pointerOfRecord(r);
size_t previousRecordSize = sizeOfRecordStarting(p);
size_t availableStorageSize = availableSize();
char * nextRecord = p + previousRecordSize;
memmove(nextRecord + availableStorageSize,
nextRecord,
(m_buffer + k_storageSize - availableStorageSize) - nextRecord);
size_t newRecordSize = previousRecordSize + availableStorageSize;
overrideSizeAtPosition(p, (record_size_t)newRecordSize);
return newRecordSize;
}
void InternalStorage::getAvailableSpaceFromEndOfRecord(Record r, size_t recordAvailableSpace) {
char * p = pointerOfRecord(r);
size_t previousRecordSize = sizeOfRecordStarting(p);
char * nextRecord = p + previousRecordSize;
memmove(nextRecord - recordAvailableSpace,
nextRecord,
m_buffer + k_storageSize - nextRecord);
overrideSizeAtPosition(p, (record_size_t)(previousRecordSize - recordAvailableSpace));
}
uint32_t InternalStorage::checksum() {
return Ion::crc32Byte((const uint8_t *) m_buffer, endBuffer()-m_buffer);
}
void InternalStorage::notifyChangeToDelegate(const Record record) const {
m_lastRecordRetrieved = Record(nullptr);
m_lastRecordRetrievedPointer = nullptr;
if (m_delegate != nullptr) {
m_delegate->storageDidChangeForRecord(record);
}
}
InternalStorage::Record::ErrorStatus InternalStorage::notifyFullnessToDelegate() const {
if (m_delegate != nullptr) {
m_delegate->storageIsFull();
}
return Record::ErrorStatus::NotEnoughSpaceAvailable;
}
InternalStorage::Record::ErrorStatus InternalStorage::createRecordWithFullName(const char * fullName, const void * data, size_t size) {
size_t recordSize = sizeOfRecordWithFullName(fullName, size);
if (recordSize >= k_maxRecordSize || recordSize > availableSize()) {
return notifyFullnessToDelegate();
}
if (isFullNameTaken(fullName)) {
return Record::ErrorStatus::NameTaken;
}
// Find the end of data
char * newRecordAddress = endBuffer();
char * newRecord = newRecordAddress;
// Fill totalSize
newRecord += overrideSizeAtPosition(newRecord, (record_size_t)recordSize);
// Fill name
newRecord += overrideFullNameAtPosition(newRecord, fullName);
// Fill data
newRecord += overrideValueAtPosition(newRecord, data, size);
// Next Record is null-sized
overrideSizeAtPosition(newRecord, 0);
Record r = Record(fullName);
notifyChangeToDelegate(r);
m_lastRecordRetrieved = r;
m_lastRecordRetrievedPointer = newRecordAddress;
return Record::ErrorStatus::None;
}
InternalStorage::Record::ErrorStatus InternalStorage::createRecordWithExtension(const char * baseName, const char * extension, const void * data, size_t size) {
size_t recordSize = sizeOfRecordWithBaseNameAndExtension(baseName, extension, size);
if (recordSize >= k_maxRecordSize || recordSize > availableSize()) {
return notifyFullnessToDelegate();
}
if (isBaseNameWithExtensionTaken(baseName, extension)) {
return Record::ErrorStatus::NameTaken;
}
// Find the end of data
char * newRecordAddress = endBuffer();
char * newRecord = newRecordAddress;
// Fill totalSize
newRecord += overrideSizeAtPosition(newRecord, (record_size_t)recordSize);
// Fill name
newRecord += overrideBaseNameWithExtensionAtPosition(newRecord, baseName, extension);
// Fill data
newRecord += overrideValueAtPosition(newRecord, data, size);
// Next Record is null-sized
overrideSizeAtPosition(newRecord, 0);
Record r = Record(fullNameOfRecordStarting(newRecordAddress));
notifyChangeToDelegate(r);
m_lastRecordRetrieved = r;
m_lastRecordRetrievedPointer = newRecordAddress;
return Record::ErrorStatus::None;
}
int InternalStorage::numberOfRecordsWithExtension(const char * extension) {
int count = 0;
size_t extensionLength = strlen(extension);
for (char * p : *this) {
const char * name = fullNameOfRecordStarting(p);
if (FullNameHasExtension(name, extension, extensionLength)) {
count++;
}
}
return count;
}
int InternalStorage::numberOfRecords() {
int count = 0;
for (char * p : *this) {
const char * name = fullNameOfRecordStarting(p);
count++;
}
return count;
}
InternalStorage::Record InternalStorage::recordAtIndex(int index) {
int currentIndex = -1;
const char * name = nullptr;
char * recordAddress = nullptr;
for (char * p : *this) {
const char * currentName = fullNameOfRecordStarting(p);
currentIndex++;
if (currentIndex == index) {
recordAddress = p;
name = currentName;
break;
}
}
if (name == nullptr) {
return Record();
}
Record r = Record(name);
m_lastRecordRetrieved = r;
m_lastRecordRetrievedPointer = recordAddress;
return Record(name);
}
InternalStorage::Record InternalStorage::recordWithExtensionAtIndex(const char * extension, int index) {
int currentIndex = -1;
const char * name = nullptr;
size_t extensionLength = strlen(extension);
char * recordAddress = nullptr;
for (char * p : *this) {
const char * currentName = fullNameOfRecordStarting(p);
if (FullNameHasExtension(currentName, extension, extensionLength)) {
currentIndex++;
}
if (currentIndex == index) {
recordAddress = p;
name = currentName;
break;
}
}
if (name == nullptr) {
return Record();
}
Record r = Record(name);
m_lastRecordRetrieved = r;
m_lastRecordRetrievedPointer = recordAddress;
return Record(name);
}
InternalStorage::Record InternalStorage::recordNamed(const char * fullName) {
if (fullName == nullptr) {
return Record();
}
Record r = Record(fullName);
char * p = pointerOfRecord(r);
if (p != nullptr) {
return r;
}
return Record();
}
InternalStorage::Record InternalStorage::recordBaseNamedWithExtension(const char * baseName, const char * extension) {
const char * extensions[1] = {extension};
return recordBaseNamedWithExtensions(baseName, extensions, 1);
}
InternalStorage::Record InternalStorage::recordBaseNamedWithExtensions(const char * baseName, const char * const extensions[], size_t numberOfExtensions) {
return privateRecordAndExtensionOfRecordBaseNamedWithExtensions(baseName, extensions, numberOfExtensions);
}
const char * InternalStorage::extensionOfRecordBaseNamedWithExtensions(const char * baseName, int baseNameLength, const char * const extensions[], size_t numberOfExtensions) {
const char * result = nullptr;
privateRecordAndExtensionOfRecordBaseNamedWithExtensions(baseName, extensions, numberOfExtensions, &result, baseNameLength);
return result;
}
void InternalStorage::destroyAllRecords() {
overrideSizeAtPosition(m_buffer, 0);
notifyChangeToDelegate();
}
void InternalStorage::destroyRecordWithBaseNameAndExtension(const char * baseName, const char * extension) {
recordBaseNamedWithExtension(baseName, extension).destroy();
}
void InternalStorage::destroyRecordsWithExtension(const char * extension) {
size_t extensionLength = strlen(extension);
char * currentRecordStart = (char *)m_buffer;
bool didChange = false;
while (currentRecordStart != nullptr && sizeOfRecordStarting(currentRecordStart) != 0) {
const char * currentFullName = fullNameOfRecordStarting(currentRecordStart);
if (FullNameHasExtension(currentFullName, extension, extensionLength)) {
Record currentRecord(currentFullName);
currentRecord.destroy();
didChange = true;
continue;
}
currentRecordStart = *(RecordIterator(currentRecordStart).operator++());
}
if (didChange) {
notifyChangeToDelegate();
}
}
InternalStorage::InternalStorage() :
m_magicHeader(Magic),
m_buffer(),
m_magicFooter(Magic),
m_delegate(nullptr),
m_lastRecordRetrieved(nullptr),
m_lastRecordRetrievedPointer(nullptr)
{
assert(m_magicHeader == Magic);
assert(m_magicFooter == Magic);
// Set the size of the first record to 0
overrideSizeAtPosition(m_buffer, 0);
}
// PRIVATE
const char * InternalStorage::fullNameOfRecord(const Record record) {
char * p = pointerOfRecord(record);
if (p != nullptr) {
return fullNameOfRecordStarting(p);
}
return nullptr;
}
InternalStorage::Record::ErrorStatus InternalStorage::setFullNameOfRecord(const Record record, const char * fullName) {
if (!FullNameCompliant(fullName)) {
return Record::ErrorStatus::NonCompliantName;
}
if (isFullNameTaken(fullName, &record)) {
return Record::ErrorStatus::NameTaken;
}
size_t nameSize = strlen(fullName) + 1;
char * p = pointerOfRecord(record);
if (p != nullptr) {
size_t previousNameSize = strlen(fullNameOfRecordStarting(p))+1;
record_size_t previousRecordSize = sizeOfRecordStarting(p);
size_t newRecordSize = previousRecordSize-previousNameSize+nameSize;
if (newRecordSize >= k_maxRecordSize || !slideBuffer(p+sizeof(record_size_t)+previousNameSize, nameSize-previousNameSize)) {
return notifyFullnessToDelegate();
}
overrideSizeAtPosition(p, newRecordSize);
overrideFullNameAtPosition(p+sizeof(record_size_t), fullName);
notifyChangeToDelegate(record);
m_lastRecordRetrieved = record;
m_lastRecordRetrievedPointer = p;
return Record::ErrorStatus::None;
}
return Record::ErrorStatus::RecordDoesNotExist;
}
InternalStorage::Record::ErrorStatus InternalStorage::setBaseNameWithExtensionOfRecord(Record record, const char * baseName, const char * extension) {
if (isBaseNameWithExtensionTaken(baseName, extension, &record)) {
return Record::ErrorStatus::NameTaken;
}
size_t nameSize = sizeOfBaseNameAndExtension(baseName, extension);
char * p = pointerOfRecord(record);
if (p != nullptr) {
size_t previousNameSize = strlen(fullNameOfRecordStarting(p))+1;
record_size_t previousRecordSize = sizeOfRecordStarting(p);
size_t newRecordSize = previousRecordSize-previousNameSize+nameSize;
if (newRecordSize >= k_maxRecordSize || !slideBuffer(p+sizeof(record_size_t)+previousNameSize, nameSize-previousNameSize)) {
return notifyFullnessToDelegate();
}
overrideSizeAtPosition(p, newRecordSize);
char * fullNamePosition = p + sizeof(record_size_t);
overrideBaseNameWithExtensionAtPosition(fullNamePosition, baseName, extension);
// Recompute the CRC32
record = Record(fullNamePosition);
notifyChangeToDelegate(record);
m_lastRecordRetrieved = record;
m_lastRecordRetrievedPointer = p;
return Record::ErrorStatus::None;
}
return Record::ErrorStatus::RecordDoesNotExist;
}
InternalStorage::Record::Data InternalStorage::valueOfRecord(const Record record) {
char * p = pointerOfRecord(record);
if (p != nullptr) {
const char * fullName = fullNameOfRecordStarting(p);
record_size_t size = sizeOfRecordStarting(p);
const void * value = valueOfRecordStarting(p);
return {.buffer = value, .size = size-strlen(fullName)-1-sizeof(record_size_t)};
}
return {.buffer= nullptr, .size= 0};
}
InternalStorage::Record::ErrorStatus InternalStorage::setValueOfRecord(Record record, Record::Data data) {
char * p = pointerOfRecord(record);
/* TODO: if data.buffer == p, assert that size hasn't change and do not do any
* memcopy, but still notify the delegate. Beware of scripts and the accordion
* routine.*/
if (p != nullptr) {
record_size_t previousRecordSize = sizeOfRecordStarting(p);
const char * fullName = fullNameOfRecordStarting(p);
size_t newRecordSize = sizeOfRecordWithFullName(fullName, data.size);
if (newRecordSize >= k_maxRecordSize || !slideBuffer(p+previousRecordSize, newRecordSize-previousRecordSize)) {
return notifyFullnessToDelegate();
}
record_size_t fullNameSize = strlen(fullName)+1;
overrideSizeAtPosition(p, newRecordSize);
overrideValueAtPosition(p+sizeof(record_size_t)+fullNameSize, data.buffer, data.size);
notifyChangeToDelegate(record);
m_lastRecordRetrieved = record;
m_lastRecordRetrievedPointer = p;
return Record::ErrorStatus::None;
}
return Record::ErrorStatus::RecordDoesNotExist;
}
void InternalStorage::destroyRecord(Record record) {
if (record.isNull()) {
return;
}
char * p = pointerOfRecord(record);
if (p != nullptr) {
record_size_t previousRecordSize = sizeOfRecordStarting(p);
slideBuffer(p+previousRecordSize, -previousRecordSize);
notifyChangeToDelegate();
}
}
char * InternalStorage::pointerOfRecord(const Record record) const {
if (record.isNull()) {
return nullptr;
}
if (!m_lastRecordRetrieved.isNull() && record == m_lastRecordRetrieved) {
assert(m_lastRecordRetrievedPointer != nullptr);
return m_lastRecordRetrievedPointer;
}
for (char * p : *this) {
Record currentRecord(fullNameOfRecordStarting(p));
if (record == currentRecord) {
m_lastRecordRetrieved = record;
m_lastRecordRetrievedPointer = p;
return p;
}
}
return nullptr;
}
InternalStorage::record_size_t InternalStorage::sizeOfRecordStarting(char * start) const {
return StorageHelper::unalignedShort(start);
}
const char * InternalStorage::fullNameOfRecordStarting(char * start) const {
return start+sizeof(record_size_t);
}
const void * InternalStorage::valueOfRecordStarting(char * start) const {
char * currentChar = start+sizeof(record_size_t);
size_t fullNameLength = strlen(currentChar);
return currentChar+fullNameLength+1;
}
size_t InternalStorage::overrideSizeAtPosition(char * position, record_size_t size) {
StorageHelper::writeUnalignedShort(size, position);
return sizeof(record_size_t);
}
size_t InternalStorage::overrideFullNameAtPosition(char * position, const char * fullName) {
return strlcpy(position, fullName, strlen(fullName)+1) + 1;
}
size_t InternalStorage::overrideBaseNameWithExtensionAtPosition(char * position, const char * baseName, const char * extension) {
size_t result = strlcpy(position, baseName, strlen(baseName)+1); // strlcpy copies the null terminating char
assert(UTF8Decoder::CharSizeOfCodePoint(k_dotChar) == 1);
*(position+result) = k_dotChar; // Replace the null terminating char with a dot
result++;
result += strlcpy(position+result, extension, strlen(extension)+1);
return result+1;
}
size_t InternalStorage::overrideValueAtPosition(char * position, const void * data, record_size_t size) {
memcpy(position, data, size);
return size;
}
bool InternalStorage::isFullNameTaken(const char * fullName, const Record * recordToExclude) {
Record r = Record(fullName);
return isNameOfRecordTaken(r, recordToExclude);
}
bool InternalStorage::isBaseNameWithExtensionTaken(const char * baseName, const char * extension, Record * recordToExclude) {
Record r = Record(baseName, extension);
return isNameOfRecordTaken(r, recordToExclude);
}
bool InternalStorage::isNameOfRecordTaken(Record r, const Record * recordToExclude) {
if (r == Record()) {
/* If the CRC32 of fullName is 0, we want to refuse the name as it would
* interfere with our escape case in the Record constructor, when the given
* name is nullptr. */
return true;
}
for (char * p : *this) {
Record s(fullNameOfRecordStarting(p));
if (recordToExclude && s == *recordToExclude) {
continue;
}
if (s == r) {
return true;
}
}
return false;
}
bool InternalStorage::FullNameCompliant(const char * fullName) {
// We check that there is one dot and one dot only.
const char * dotChar = UTF8Helper::CodePointSearch(fullName, k_dotChar);
if (*dotChar == 0) {
return false;
}
if (*(UTF8Helper::CodePointSearch(dotChar+1, k_dotChar)) == 0) {
return true;
}
return false;
}
bool InternalStorage::FullNameHasExtension(const char * fullName, const char * extension, size_t extensionLength) {
if (fullName == nullptr) {
return false;
}
size_t fullNameLength = strlen(fullName);
if (fullNameLength > extensionLength) {
const char * ext = fullName + fullNameLength - extensionLength;
if (UTF8Helper::PreviousCodePointIs(fullName, ext, k_dotChar) && strcmp(ext, extension) == 0) {
return true;
}
}
return false;
}
char * InternalStorage::endBuffer() {
char * currentBuffer = m_buffer;
for (char * p : *this) {
currentBuffer += sizeOfRecordStarting(p);
}
return currentBuffer;
}
size_t InternalStorage::sizeOfBaseNameAndExtension(const char * baseName, const char * extension) const {
// +1 for the dot and +1 for the null terminating char
return strlen(baseName)+1+strlen(extension)+1;
}
size_t InternalStorage::sizeOfRecordWithBaseNameAndExtension(const char * baseName, const char * extension, size_t dataSize) const {
return sizeOfBaseNameAndExtension(baseName, extension) + dataSize + sizeof(record_size_t);
}
size_t InternalStorage::sizeOfRecordWithFullName(const char * fullName, size_t dataSize) const {
size_t nameSize = strlen(fullName)+1;
return nameSize+dataSize+sizeof(record_size_t);
}
bool InternalStorage::slideBuffer(char * position, int delta) {
if (delta > (int)availableSize()) {
return false;
}
memmove(position+delta, position, endBuffer()+sizeof(record_size_t)-position);
return true;
}
InternalStorage::Record InternalStorage::privateRecordAndExtensionOfRecordBaseNamedWithExtensions(const char * baseName, const char * const extensions[], size_t numberOfExtensions, const char * * extensionResult, int baseNameLength) {
size_t nameLength = baseNameLength < 0 ? strlen(baseName) : baseNameLength;
{
const char * lastRetrievedRecordFullName = fullNameOfRecordStarting(m_lastRecordRetrievedPointer);
if (m_lastRecordRetrievedPointer != nullptr && strncmp(baseName, lastRetrievedRecordFullName, nameLength) == 0) {
for (size_t i = 0; i < numberOfExtensions; i++) {
if (strcmp(lastRetrievedRecordFullName+nameLength+1 /*+1 to pass the dot*/, extensions[i]) == 0) {
assert(UTF8Helper::CodePointIs(lastRetrievedRecordFullName + nameLength, '.'));
if (extensionResult != nullptr) {
*extensionResult = extensions[i];
}
return m_lastRecordRetrieved;
}
}
}
}
for (char * p : *this) {
const char * currentName = fullNameOfRecordStarting(p);
if (strncmp(baseName, currentName, nameLength) == 0) {
for (size_t i = 0; i < numberOfExtensions; i++) {
if (strcmp(currentName+nameLength+1 /*+1 to pass the dot*/, extensions[i]) == 0) {
assert(UTF8Helper::CodePointIs(currentName + nameLength, '.'));
if (extensionResult != nullptr) {
*extensionResult = extensions[i];
}
return Record(currentName);
}
}
}
}
if (extensionResult != nullptr) {
*extensionResult = nullptr;
}
return Record();
}
InternalStorage::RecordIterator & InternalStorage::RecordIterator::operator++() {
assert(m_recordStart);
record_size_t size = StorageHelper::unalignedShort(m_recordStart);
char * nextRecord = m_recordStart+size;
record_size_t newRecordSize = StorageHelper::unalignedShort(nextRecord);
m_recordStart = (newRecordSize == 0 ? nullptr : nextRecord);
return *this;
}
}

View File

@@ -1,291 +1,67 @@
#include <ion.h>
#include <string.h>
#include <ion/storage.h>
#include <assert.h>
#include <new>
#if ION_STORAGE_LOG
#include<iostream>
#endif
#include <string.h>
#include <ion/unicode/utf8_helper.h>
namespace Ion {
/* We want to implement a simple singleton pattern, to make sure the storage is
* initialized on first use, therefore preventing the static init order fiasco.
* That being said, we rely on knowing where the storage resides in the device's
* memory at compile time. Indeed, we want to advertise the static storage's
* memory address in the PlatformInfo structure (so that we can read and write
* it in DFU).
* Using a "static Storage storage;" variable makes it a local symbol at best,
* preventing the PlatformInfo from retrieving its address. And making the
* Storage variable global yields the static init fiasco issue. We're working
* around both issues by creating a global staticStorageArea buffer, and by
* placement-newing the Storage into that area on first use. */
uint32_t staticStorageArea[sizeof(Storage)/sizeof(uint32_t)] = {0};
constexpr char Storage::expExtension[];
constexpr char Storage::funcExtension[];
constexpr char Storage::seqExtension[];
constexpr char Storage::eqExtension[];
Storage * Storage::sharedStorage() {
static Storage * storage = new (staticStorageArea) Storage();
return storage;
}
// RECORD
Storage::Record::Record(const char * fullName) {
if (fullName == nullptr) {
m_fullNameCRC32 = 0;
return;
}
const char * dotChar = UTF8Helper::CodePointSearch(fullName, k_dotChar);
// If no extension, return empty record
if (*dotChar == 0 || *(dotChar+1) == 0) {
m_fullNameCRC32 = 0;
return;
}
new (this) Record(fullName, dotChar - fullName, dotChar+1, (fullName + strlen(fullName)) - (dotChar+1));
}
Storage::Record::Record(const char * baseName, const char * extension) {
if (baseName == nullptr) {
assert(extension == nullptr);
m_fullNameCRC32 = 0;
return;
}
new (this) Record(baseName, strlen(baseName), extension, strlen(extension));
}
#if ION_STORAGE_LOG
void Storage::Record::log() {
std::cout << "Name: " << fullName() << std::endl;
std::cout << " Value (" << value().size << "): " << (char *)value().buffer << "\n\n" << std::endl;
}
#endif
uint32_t Storage::Record::checksum() {
uint32_t crc32Results[2];
crc32Results[0] = m_fullNameCRC32;
Data data = value();
crc32Results[1] = Ion::crc32Byte((const uint8_t *)data.buffer, data.size);
return Ion::crc32Word(crc32Results, 2);
}
Storage::Record::Record(const char * basename, int basenameLength, const char * extension, int extensionLength) {
assert(basename != nullptr);
assert(extension != nullptr);
// We compute the CRC32 of the CRC32s of the basename and the extension
uint32_t crc32Results[2];
crc32Results[0] = Ion::crc32Byte((const uint8_t *)basename, basenameLength);
crc32Results[1] = Ion::crc32Byte((const uint8_t *)extension, extensionLength);
m_fullNameCRC32 = Ion::crc32Word(crc32Results, 2);
}
// STORAGE
#if ION_STORAGE_LOG
void Storage::log() {
for (char * p : *this) {
const char * currentName = fullNameOfRecordStarting(p);
Record(currentName).log();
}
}
#endif
size_t Storage::availableSize() {
if (m_trashRecord != NULL) {
return realAvailableSize() + sizeof(record_size_t) + m_trashRecord.value().size;
if (m_trashRecord != Record()) {
int bufferSize = 0;
for (char * p : *this) {
if (Record(fullNameOfRecordStarting(p)) != m_trashRecord) {
bufferSize += sizeOfRecordStarting(p);
}
}
return k_storageSize-bufferSize-sizeof(record_size_t);
} else {
return realAvailableSize();
return InternalStorage::availableSize();
}
}
size_t Storage::realAvailableSize() {
/* TODO maybe do: availableSize(char ** endBuffer) to get the endBuffer if it
* is needed after calling availableSize */
assert(k_storageSize >= (endBuffer() - m_buffer) + sizeof(record_size_t));
return k_storageSize-(endBuffer()-m_buffer)-sizeof(record_size_t);
}
size_t Storage::putAvailableSpaceAtEndOfRecord(Storage::Record r) {
char * p = pointerOfRecord(r);
size_t previousRecordSize = sizeOfRecordStarting(p);
size_t availableStorageSize = realAvailableSize();
char * nextRecord = p + previousRecordSize;
memmove(nextRecord + availableStorageSize,
nextRecord,
(m_buffer + k_storageSize - availableStorageSize) - nextRecord);
size_t newRecordSize = previousRecordSize + availableStorageSize;
overrideSizeAtPosition(p, (record_size_t)newRecordSize);
return newRecordSize;
size_t Storage::putAvailableSpaceAtEndOfRecord(Record r) {
emptyTrash();
return InternalStorage::putAvailableSpaceAtEndOfRecord(r);
}
void Storage::getAvailableSpaceFromEndOfRecord(Record r, size_t recordAvailableSpace) {
char * p = pointerOfRecord(r);
size_t previousRecordSize = sizeOfRecordStarting(p);
char * nextRecord = p + previousRecordSize;
memmove(nextRecord - recordAvailableSpace,
nextRecord,
m_buffer + k_storageSize - nextRecord);
overrideSizeAtPosition(p, (record_size_t)(previousRecordSize - recordAvailableSpace));
emptyTrash();
InternalStorage::getAvailableSpaceFromEndOfRecord(r, recordAvailableSpace);
}
uint32_t Storage::checksum() {
return Ion::crc32Byte((const uint8_t *) m_buffer, endBuffer()-m_buffer);
}
void Storage::notifyChangeToDelegate(const Record record) const {
m_lastRecordRetrieved = Record(nullptr);
m_lastRecordRetrievedPointer = nullptr;
if (m_delegate != nullptr) {
m_delegate->storageDidChangeForRecord(record);
int Storage::numberOfRecordsWithExtension(const char * extension) {
int trashRecord = 0;
if (FullNameHasExtension(m_trashRecord.fullName(), extension, strlen(extension))) {
trashRecord = 1;
}
}
Storage::Record::ErrorStatus Storage::notifyFullnessToDelegate() const {
if (m_delegate != nullptr) {
m_delegate->storageIsFull();
}
return Record::ErrorStatus::NotEnoughSpaceAvailable;
return InternalStorage::numberOfRecordsWithExtension(extension) - trashRecord;
}
Storage::Record::ErrorStatus Storage::createRecordWithFullName(const char * fullName, const void * data, size_t size) {
emptyTrash();
size_t recordSize = sizeOfRecordWithFullName(fullName, size);
if (recordSize >= k_maxRecordSize || recordSize > availableSize()) {
return notifyFullnessToDelegate();
}
if (isFullNameTaken(fullName)) {
return Record::ErrorStatus::NameTaken;
}
// Find the end of data
char * newRecordAddress = endBuffer();
char * newRecord = newRecordAddress;
// Fill totalSize
newRecord += overrideSizeAtPosition(newRecord, (record_size_t)recordSize);
// Fill name
newRecord += overrideFullNameAtPosition(newRecord, fullName);
// Fill data
newRecord += overrideValueAtPosition(newRecord, data, size);
// Next Record is null-sized
overrideSizeAtPosition(newRecord, 0);
Record r = Record(fullName);
notifyChangeToDelegate(r);
m_lastRecordRetrieved = r;
m_lastRecordRetrievedPointer = newRecordAddress;
return Record::ErrorStatus::None;
return InternalStorage::createRecordWithFullName(fullName, data, size);
}
Storage::Record::ErrorStatus Storage::createRecordWithExtension(const char * baseName, const char * extension, const void * data, size_t size) {
emptyTrash();
size_t recordSize = sizeOfRecordWithBaseNameAndExtension(baseName, extension, size);
if (recordSize >= k_maxRecordSize || recordSize > availableSize()) {
return notifyFullnessToDelegate();
}
if (isBaseNameWithExtensionTaken(baseName, extension)) {
return Record::ErrorStatus::NameTaken;
}
// Find the end of data
char * newRecordAddress = endBuffer();
char * newRecord = newRecordAddress;
// Fill totalSize
newRecord += overrideSizeAtPosition(newRecord, (record_size_t)recordSize);
// Fill name
newRecord += overrideBaseNameWithExtensionAtPosition(newRecord, baseName, extension);
// Fill data
newRecord += overrideValueAtPosition(newRecord, data, size);
// Next Record is null-sized
overrideSizeAtPosition(newRecord, 0);
Record r = Record(fullNameOfRecordStarting(newRecordAddress));
notifyChangeToDelegate(r);
m_lastRecordRetrieved = r;
m_lastRecordRetrievedPointer = newRecordAddress;
return Record::ErrorStatus::None;
return InternalStorage::createRecordWithExtension(baseName, extension, data, size);
}
int Storage::numberOfRecordsWithExtension(const char * extension) {
int count = 0;
size_t extensionLength = strlen(extension);
for (char * p : *this) {
const char * name = fullNameOfRecordStarting(p);
if (FullNameHasExtension(name, extension, extensionLength) && Record(name) != m_trashRecord) {
count++;
}
}
return count;
bool Storage::hasRecord(Record r) {
return InternalStorage::hasRecord(r) && r != m_trashRecord;
}
int Storage::numberOfRecords() {
return realNumberOfRecords() - (m_trashRecord == NULL ? 0 : 1);
}
int Storage::realNumberOfRecords() {
int count = 0;
for (char * p : *this) {
const char * name = fullNameOfRecordStarting(p);
count++;
}
return count;
}
Storage::Record Storage::realRecordAtIndex(int index) {
int currentIndex = -1;
const char * name = nullptr;
char * recordAddress = nullptr;
for (char * p : *this) {
const char * currentName = fullNameOfRecordStarting(p);
currentIndex++;
if (currentIndex == index) {
recordAddress = p;
name = currentName;
break;
}
}
if (name == nullptr) {
return Record();
}
Record r = Record(name);
m_lastRecordRetrieved = r;
m_lastRecordRetrievedPointer = recordAddress;
return Record(name);
}
Storage::Record Storage::recordAtIndex(int index) {
int currentIndex = -1;
const char * name = nullptr;
char * recordAddress = nullptr;
for (char * p : *this) {
const char * currentName = fullNameOfRecordStarting(p);
Record r = Record(currentName);
if (r == m_trashRecord) {
continue;
}
currentIndex++;
if (currentIndex == index) {
recordAddress = p;
name = currentName;
break;
}
}
if (name == nullptr) {
return Record();
}
Record r = Record(name);
m_lastRecordRetrieved = r;
m_lastRecordRetrievedPointer = recordAddress;
return Record(name);
}
void Storage::emptyTrash() {
if (m_trashRecord != NULL) {
realDestroyRecord(m_trashRecord);
m_trashRecord = NULL;
}
void Storage::destroyRecord(Record record) {
emptyTrash();
m_trashRecord = record;
}
Storage::Record Storage::recordWithExtensionAtIndex(const char * extension, int index) {
@@ -307,397 +83,98 @@ Storage::Record Storage::recordWithExtensionAtIndex(const char * extension, int
if (name == nullptr) {
return Record();
}
Record r = Record(name);
Storage::Record r = Record(name);
m_lastRecordRetrieved = r;
m_lastRecordRetrievedPointer = recordAddress;
return Record(name);
}
Storage::Record Storage::recordNamed(const char * fullName) {
if (fullName == nullptr) {
return Record();
}
Record r = Record(fullName);
char * p = pointerOfRecord(r);
if (p != nullptr) {
return r;
}
return Record();
Storage::Record r = InternalStorage::recordNamed(fullName);
return r == m_trashRecord ? Record() : r;
}
Storage::Record Storage::recordBaseNamedWithExtension(const char * baseName, const char * extension) {
const char * extensions[1] = {extension};
return recordBaseNamedWithExtensions(baseName, extensions, 1);
Storage::Record r = InternalStorage::recordBaseNamedWithExtension(baseName, extension);
return r == m_trashRecord ? Record() : r;
}
Storage::Record Storage::recordBaseNamedWithExtensions(const char * baseName, const char * const extensions[], size_t numberOfExtensions) {
return privateRecordAndExtensionOfRecordBaseNamedWithExtensions(baseName, extensions, numberOfExtensions);
Storage::Record Storage::recordBaseNamedWithExtensions(const char * baseName, const char * const extension[], size_t numberOfExtensions) {
Storage::Record r = InternalStorage::recordBaseNamedWithExtensions(baseName, extension, numberOfExtensions);
return r == m_trashRecord ? Record() : r;
}
const char * Storage::extensionOfRecordBaseNamedWithExtensions(const char * baseName, int baseNameLength, const char * const extensions[], size_t numberOfExtensions) {
const char * result = nullptr;
privateRecordAndExtensionOfRecordBaseNamedWithExtensions(baseName, extensions, numberOfExtensions, &result, baseNameLength);
return result;
}
void Storage::destroyAllRecords() {
overrideSizeAtPosition(m_buffer, 0);
notifyChangeToDelegate();
}
void Storage::destroyRecordWithBaseNameAndExtension(const char * baseName, const char * extension) {
recordBaseNamedWithExtension(baseName, extension).destroy();
}
void Storage::destroyRecordsWithExtension(const char * extension) {
size_t extensionLength = strlen(extension);
char * currentRecordStart = (char *)m_buffer;
bool didChange = false;
while (currentRecordStart != nullptr && sizeOfRecordStarting(currentRecordStart) != 0) {
const char * currentFullName = fullNameOfRecordStarting(currentRecordStart);
if (FullNameHasExtension(currentFullName, extension, extensionLength)) {
Record currentRecord(currentFullName);
currentRecord.destroy();
didChange = true;
continue;
}
currentRecordStart = *(RecordIterator(currentRecordStart).operator++());
}
if (didChange) {
notifyChangeToDelegate();
}
}
// PRIVATE
Storage::Storage() :
m_magicHeader(Magic),
m_buffer(),
m_magicFooter(Magic),
m_delegate(nullptr),
m_lastRecordRetrieved(nullptr),
m_lastRecordRetrievedPointer(nullptr),
m_trashRecord(NULL)
{
assert(m_magicHeader == Magic);
assert(m_magicFooter == Magic);
// Set the size of the first record to 0
overrideSizeAtPosition(m_buffer, 0);
}
const char * Storage::fullNameOfRecord(const Record record) {
char * p = pointerOfRecord(record);
if (p != nullptr) {
return fullNameOfRecordStarting(p);
}
return nullptr;
}
Storage::Record::ErrorStatus Storage::setFullNameOfRecord(const Record record, const char * fullName) {
if (!FullNameCompliant(fullName)) {
return Record::ErrorStatus::NonCompliantName;
}
if (isFullNameTaken(fullName, &record)) {
return Record::ErrorStatus::NameTaken;
}
size_t nameSize = strlen(fullName) + 1;
char * p = pointerOfRecord(record);
if (p != nullptr) {
size_t previousNameSize = strlen(fullNameOfRecordStarting(p))+1;
record_size_t previousRecordSize = sizeOfRecordStarting(p);
size_t newRecordSize = previousRecordSize-previousNameSize+nameSize;
if (newRecordSize >= k_maxRecordSize || !slideBuffer(p+sizeof(record_size_t)+previousNameSize, nameSize-previousNameSize)) {
return notifyFullnessToDelegate();
}
overrideSizeAtPosition(p, newRecordSize);
overrideFullNameAtPosition(p+sizeof(record_size_t), fullName);
notifyChangeToDelegate(record);
m_lastRecordRetrieved = record;
m_lastRecordRetrievedPointer = p;
return Record::ErrorStatus::None;
}
return Record::ErrorStatus::RecordDoesNotExist;
}
Storage::Record::ErrorStatus Storage::setBaseNameWithExtensionOfRecord(Record record, const char * baseName, const char * extension) {
if (isBaseNameWithExtensionTaken(baseName, extension, &record)) {
return Record::ErrorStatus::NameTaken;
}
size_t nameSize = sizeOfBaseNameAndExtension(baseName, extension);
char * p = pointerOfRecord(record);
if (p != nullptr) {
size_t previousNameSize = strlen(fullNameOfRecordStarting(p))+1;
record_size_t previousRecordSize = sizeOfRecordStarting(p);
size_t newRecordSize = previousRecordSize-previousNameSize+nameSize;
if (newRecordSize >= k_maxRecordSize || !slideBuffer(p+sizeof(record_size_t)+previousNameSize, nameSize-previousNameSize)) {
return notifyFullnessToDelegate();
}
overrideSizeAtPosition(p, newRecordSize);
char * fullNamePosition = p + sizeof(record_size_t);
overrideBaseNameWithExtensionAtPosition(fullNamePosition, baseName, extension);
// Recompute the CRC32
record = Record(fullNamePosition);
notifyChangeToDelegate(record);
m_lastRecordRetrieved = record;
m_lastRecordRetrievedPointer = p;
return Record::ErrorStatus::None;
}
return Record::ErrorStatus::RecordDoesNotExist;
}
Storage::Record::Data Storage::valueOfRecord(const Record record) {
char * p = pointerOfRecord(record);
if (p != nullptr) {
const char * fullName = fullNameOfRecordStarting(p);
record_size_t size = sizeOfRecordStarting(p);
const void * value = valueOfRecordStarting(p);
return {.buffer = value, .size = size-strlen(fullName)-1-sizeof(record_size_t)};
}
return {.buffer= nullptr, .size= 0};
}
Storage::Record::ErrorStatus Storage::setValueOfRecord(Record record, Record::Data data) {
char * p = pointerOfRecord(record);
/* TODO: if data.buffer == p, assert that size hasn't change and do not do any
* memcopy, but still notify the delegate. Beware of scripts and the accordion
* routine.*/
if (p != nullptr) {
record_size_t previousRecordSize = sizeOfRecordStarting(p);
const char * fullName = fullNameOfRecordStarting(p);
size_t newRecordSize = sizeOfRecordWithFullName(fullName, data.size);
if (newRecordSize >= k_maxRecordSize || !slideBuffer(p+previousRecordSize, newRecordSize-previousRecordSize)) {
return notifyFullnessToDelegate();
}
record_size_t fullNameSize = strlen(fullName)+1;
overrideSizeAtPosition(p, newRecordSize);
overrideValueAtPosition(p+sizeof(record_size_t)+fullNameSize, data.buffer, data.size);
notifyChangeToDelegate(record);
m_lastRecordRetrieved = record;
m_lastRecordRetrievedPointer = p;
return Record::ErrorStatus::None;
}
return Record::ErrorStatus::RecordDoesNotExist;
}
void Storage::reinsertTrash(const char * extension) {
if (m_trashRecord != NULL) {
char * p = pointerOfRecord(m_trashRecord);
const char * fullName = fullNameOfRecordStarting(p);
if (FullNameHasExtension(fullName, extension, strlen(extension))) {
m_trashRecord = NULL;
}
}
}
void Storage::destroyRecord(Record record) {
emptyTrash();
m_trashRecord = record;
}
void Storage::realDestroyRecord(Record record) {
if (record.isNull()) {
return;
}
char * p = pointerOfRecord(record);
if (p != nullptr) {
record_size_t previousRecordSize = sizeOfRecordStarting(p);
slideBuffer(p+previousRecordSize, -previousRecordSize);
notifyChangeToDelegate();
}
}
char * Storage::pointerOfRecord(const Record record) const {
if (record.isNull()) {
return nullptr;
}
if (!m_lastRecordRetrieved.isNull() && record == m_lastRecordRetrieved) {
assert(m_lastRecordRetrievedPointer != nullptr);
return m_lastRecordRetrievedPointer;
}
for (char * p : *this) {
Record currentRecord(fullNameOfRecordStarting(p));
if (record == currentRecord) {
m_lastRecordRetrieved = record;
m_lastRecordRetrievedPointer = p;
return p;
}
}
return nullptr;
}
Storage::record_size_t Storage::sizeOfRecordStarting(char * start) const {
return StorageHelper::unalignedShort(start);
}
const char * Storage::fullNameOfRecordStarting(char * start) const {
return start+sizeof(record_size_t);
}
const void * Storage::valueOfRecordStarting(char * start) const {
char * currentChar = start+sizeof(record_size_t);
size_t fullNameLength = strlen(currentChar);
return currentChar+fullNameLength+1;
}
size_t Storage::overrideSizeAtPosition(char * position, record_size_t size) {
StorageHelper::writeUnalignedShort(size, position);
return sizeof(record_size_t);
}
size_t Storage::overrideFullNameAtPosition(char * position, const char * fullName) {
return strlcpy(position, fullName, strlen(fullName)+1) + 1;
}
size_t Storage::overrideBaseNameWithExtensionAtPosition(char * position, const char * baseName, const char * extension) {
size_t result = strlcpy(position, baseName, strlen(baseName)+1); // strlcpy copies the null terminating char
assert(UTF8Decoder::CharSizeOfCodePoint(k_dotChar) == 1);
*(position+result) = k_dotChar; // Replace the null terminating char with a dot
result++;
result += strlcpy(position+result, extension, strlen(extension)+1);
return result+1;
}
size_t Storage::overrideValueAtPosition(char * position, const void * data, record_size_t size) {
memcpy(position, data, size);
return size;
}
bool Storage::isFullNameTaken(const char * fullName, const Record * recordToExclude) {
Record r = Record(fullName);
return isNameOfRecordTaken(r, recordToExclude);
}
bool Storage::isBaseNameWithExtensionTaken(const char * baseName, const char * extension, Record * recordToExclude) {
Record r = Record(baseName, extension);
return isNameOfRecordTaken(r, recordToExclude);
}
bool Storage::isNameOfRecordTaken(Record r, const Record * recordToExclude) {
if (r == Record()) {
/* If the CRC32 of fullName is 0, we want to refuse the name as it would
* interfere with our escape case in the Record constructor, when the given
* name is nullptr. */
return true;
}
for (char * p : *this) {
Record s(fullNameOfRecordStarting(p));
if (recordToExclude && s == *recordToExclude) {
continue;
}
if (s == r && s != m_trashRecord) {
return true;
}
}
return false;
}
bool Storage::FullNameCompliant(const char * fullName) {
// We check that there is one dot and one dot only.
const char * dotChar = UTF8Helper::CodePointSearch(fullName, k_dotChar);
if (*dotChar == 0) {
return false;
}
if (*(UTF8Helper::CodePointSearch(dotChar+1, k_dotChar)) == 0) {
return true;
}
return false;
}
bool Storage::FullNameHasExtension(const char * fullName, const char * extension, size_t extensionLength) {
if (fullName == nullptr) {
return false;
}
size_t fullNameLength = strlen(fullName);
if (fullNameLength > extensionLength) {
const char * ext = fullName + fullNameLength - extensionLength;
if (UTF8Helper::PreviousCodePointIs(fullName, ext, k_dotChar) && strcmp(ext, extension) == 0) {
return true;
}
}
return false;
}
char * Storage::endBuffer() {
char * currentBuffer = m_buffer;
for (char * p : *this) {
currentBuffer += sizeOfRecordStarting(p);
}
return currentBuffer;
}
size_t Storage::sizeOfBaseNameAndExtension(const char * baseName, const char * extension) const {
// +1 for the dot and +1 for the null terminating char
return strlen(baseName)+1+strlen(extension)+1;
}
size_t Storage::sizeOfRecordWithBaseNameAndExtension(const char * baseName, const char * extension, size_t dataSize) const {
return sizeOfBaseNameAndExtension(baseName, extension) + dataSize + sizeof(record_size_t);
}
size_t Storage::sizeOfRecordWithFullName(const char * fullName, size_t dataSize) const {
size_t nameSize = strlen(fullName)+1;
return nameSize+dataSize+sizeof(record_size_t);
}
bool Storage::slideBuffer(char * position, int delta) {
if (delta > (int)realAvailableSize()) {
emptyTrash();
if (delta > (int)realAvailableSize()) {
return false;
}
}
memmove(position+delta, position, endBuffer()+sizeof(record_size_t)-position);
return true;
}
Storage::Record Storage::privateRecordAndExtensionOfRecordBaseNamedWithExtensions(const char * baseName, const char * const extensions[], size_t numberOfExtensions, const char * * extensionResult, int baseNameLength) {
const char * Storage::extensionOfRecordBaseNamedWithExtensions(const char * baseName, int baseNameLength, const char * const extension[], size_t numberOfExtensions) {
size_t nameLength = baseNameLength < 0 ? strlen(baseName) : baseNameLength;
{
const char * lastRetrievedRecordFullName = fullNameOfRecordStarting(m_lastRecordRetrievedPointer);
if (m_lastRecordRetrievedPointer != nullptr && strncmp(baseName, lastRetrievedRecordFullName, nameLength) == 0 && Record(lastRetrievedRecordFullName) == m_trashRecord) {
if (m_lastRecordRetrievedPointer != nullptr && strncmp(baseName, lastRetrievedRecordFullName, nameLength) == 0 && Record(lastRetrievedRecordFullName) != m_trashRecord) {
for (size_t i = 0; i < numberOfExtensions; i++) {
if (strcmp(lastRetrievedRecordFullName+nameLength+1 /*+1 to pass the dot*/, extensions[i]) == 0) {
if (strcmp(lastRetrievedRecordFullName+nameLength+1 /*+1 to pass the dot*/, extension[i]) == 0) {
assert(UTF8Helper::CodePointIs(lastRetrievedRecordFullName + nameLength, '.'));
if (extensionResult != nullptr) {
*extensionResult = extensions[i];
}
return m_lastRecordRetrieved;
return extension[i];
}
}
}
}
for (char * p : *this) {
const char * currentName = fullNameOfRecordStarting(p);
if (strncmp(baseName, currentName, nameLength) == 0) {
if (Record(currentName) == m_trashRecord) {
continue;
}
if (strncmp(baseName, currentName, nameLength) == 0 && Record(currentName) != m_trashRecord) {
for (size_t i = 0; i < numberOfExtensions; i++) {
if (strcmp(currentName+nameLength+1 /*+1 to pass the dot*/, extensions[i]) == 0) {
if (strcmp(currentName+nameLength+1 /*+1 to pass the dot*/, extension[i]) == 0) {
assert(UTF8Helper::CodePointIs(currentName + nameLength, '.'));
if (extensionResult != nullptr) {
*extensionResult = extensions[i];
}
return Record(currentName);
return extension[i];
}
}
}
}
if (extensionResult != nullptr) {
*extensionResult = nullptr;
return nullptr;
}
int Storage::numberOfRecords() {
return InternalStorage::numberOfRecords() - (m_trashRecord != NULL ? 1 : 0);
}
InternalStorage::Record Storage::recordAtIndex(int index) {
int currentIndex = -1;
const char * name = nullptr;
char * recordAddress = nullptr;
for (char * p : *this) {
const char * currentName = fullNameOfRecordStarting(p);
if (Record(currentName) != m_trashRecord) {
currentIndex++;
if (currentIndex == index) {
recordAddress = p;
name = currentName;
break;
}
}
}
return Record();
if (name == nullptr) {
return Record();
}
Record r = Record(name);
m_lastRecordRetrieved = r;
m_lastRecordRetrievedPointer = recordAddress;
return Record(name);
}
Storage::RecordIterator & Storage::RecordIterator::operator++() {
assert(m_recordStart);
record_size_t size = StorageHelper::unalignedShort(m_recordStart);
char * nextRecord = m_recordStart+size;
record_size_t newRecordSize = StorageHelper::unalignedShort(nextRecord);
m_recordStart = (newRecordSize == 0 ? nullptr : nextRecord);
return *this;
void Storage::reinsertTrash(const char * extension) {
if (!m_trashRecord.isNull()) {
char * p = pointerOfRecord(m_trashRecord);
const char * fullName = fullNameOfRecordStarting(p);
if (FullNameHasExtension(fullName, extension, strlen(extension))) {
m_trashRecord = Record();
}
}
}
void Storage::emptyTrash() {
if (!m_trashRecord.isNull()) {
InternalStorage::destroyRecord(m_trashRecord);
m_trashRecord = Record();
}
}
}

View File

@@ -324,7 +324,9 @@ uint32_t ExtendedCodePoints[] = {
0x3c7, // χ // GREEK SMALL LETTER KHI
0x3c8, // ψ // GREEK SMALL LETTER PSI
0x3c9, // ω // GREEK SMALL LETTER OMEGA
0x454, // є // CYRILLIC SMALL LETTER UKRAINIAN LE
0x1d07, // ᴇ // LATIN LETTER SMALL CAPITAL E
0x2026, // … // HORIZONTAL ELLIPSIS
0x212f, // // SCRIPT SMALL E
0x2190, // ← // BACKWARD ARROW (leftarrow)
0x2191, // ↑ // TOP ARROW (uparrow)
@@ -332,6 +334,10 @@ uint32_t ExtendedCodePoints[] = {
0x2193, // ↓ // BOTTOM ARROW (downarrow)
0x2194, // ↔ // BACKWARD FORWARD ARROW (leftrightarrow)
0x2195, // ↕ // TOP BOTTOM ARROW (updownarrow)
0x2196, // ↖ // NORDWEST ARROW (nwarrow)
0x2197, // ↗ // NORDEST ARROW (nearrow)
0x2198, // ↘ // SOUTHWEST ARROW (swarrow)
0x2199, // ↙ // SOUTHEST ARROW (searrow)
0x21d0, // ⇐ // DOUBLE BACKWARD ARROW (Leftarrow)
0x21d1, // ⇑ // DOUBLE TOP ARROW (Uparrow)
0x21d2, // ⇒ // DOUBLE FORWARD ARROW (Rightarrow)
@@ -348,6 +354,7 @@ uint32_t ExtendedCodePoints[] = {
0x2261, // ≡ // IS CONGRUENT TO
0x2264, // ≤ // LESS-THAN OR EQUAL TO
0x2265, // ≥ // GREATER-THAN OR EQUAL TO
0x2505, // ┅ // BOX DRAWING EQU HEAVY DASH HORIZONTAL
0xFFFD, // <20> // REPLACEMENT CHARACTER
0x1d422, // 𝐢 // MATHEMATICAL BOLD SMALL I"
};

Some files were not shown because too many files have changed in this diff Show More