mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
[code] Cleaned Script and ScriptStore classes, created accordion.h
A Script object now contains its AutoImport marker, its name and its content. The ScripStore methods have better names and the optimization is cleaner. Change-Id: I1b21af2d23f1c9a34f984309512b0c01b2f1c320
This commit is contained in:
@@ -18,7 +18,7 @@ const Image * App::Descriptor::icon() {
|
||||
}
|
||||
|
||||
App::Snapshot::Snapshot() {
|
||||
m_scriptStore.addFactorialScript();
|
||||
m_scriptStore.addNewScript(ScriptStore::DefaultScript::Factorial);
|
||||
}
|
||||
|
||||
App * App::Snapshot::unpack(Container * container) {
|
||||
@@ -26,7 +26,7 @@ App * App::Snapshot::unpack(Container * container) {
|
||||
}
|
||||
|
||||
void App::Snapshot::reset() {
|
||||
m_scriptStore.deleteAll();
|
||||
m_scriptStore.deleteAllScripts();
|
||||
}
|
||||
|
||||
App::Descriptor * App::Snapshot::descriptor() {
|
||||
|
||||
@@ -9,7 +9,7 @@ EditorController::EditorController() :
|
||||
}
|
||||
|
||||
void EditorController::setScript(Script script){
|
||||
m_view.setText(script.editableContent(), script.bufferSize());
|
||||
m_view.setText(script.editableContent(), script.contentBufferSize());
|
||||
}
|
||||
|
||||
bool EditorController::handleEvent(Ion::Events::Event event) {
|
||||
|
||||
@@ -10,6 +10,8 @@ class EditorController : public ViewController {
|
||||
public:
|
||||
EditorController();
|
||||
void setScript(Script script);
|
||||
|
||||
/* ViewController */
|
||||
View * view() override { return &m_view; }
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
void didBecomeFirstResponder() override;
|
||||
|
||||
@@ -89,7 +89,7 @@ void MenuController::renameScriptAtIndex(int i) {
|
||||
}
|
||||
|
||||
void MenuController::deleteScriptAtIndex(int i) {
|
||||
m_scriptStore->deleteScript(i);
|
||||
m_scriptStore->deleteScriptAtIndex(i);
|
||||
m_selectableTableView.reloadData();
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ int MenuController::typeAtLocation(int i, int j) {
|
||||
void MenuController::willDisplayCellForIndex(HighlightCell * cell, int index) {
|
||||
if (index < m_scriptStore->numberOfScripts()) {
|
||||
EvenOddEditableTextCell * myCell = static_cast<EvenOddEditableTextCell *>(cell);
|
||||
myCell->editableTextCell()->textField()->setText(m_scriptStore->nameOfScript(index));
|
||||
myCell->editableTextCell()->textField()->setText(m_scriptStore->scriptAtIndex(index).name());
|
||||
myCell->setEven(index%2 == 0);
|
||||
} else {
|
||||
assert(index == m_scriptStore->numberOfScripts());
|
||||
@@ -169,7 +169,7 @@ bool MenuController::textFieldDidReceiveEvent(TextField * textField, Ion::Events
|
||||
}
|
||||
|
||||
bool MenuController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) {
|
||||
if (m_scriptStore->renameScript(m_selectableTableView.selectedRow(), text)) {
|
||||
if (m_scriptStore->renameScriptAtIndex(m_selectableTableView.selectedRow(), text)) {
|
||||
int currentRow = m_selectableTableView.selectedRow();
|
||||
if (event == Ion::Events::Down && currentRow < numberOfRows() - 1) {
|
||||
m_selectableTableView.selectCellAtLocation(m_selectableTableView.selectedColumn(), currentRow + 1);
|
||||
|
||||
@@ -2,21 +2,35 @@
|
||||
|
||||
namespace Code {
|
||||
|
||||
Script::Script(char * textBuffer, size_t sizeOfBuffer) :
|
||||
m_bufferSize(sizeOfBuffer),
|
||||
m_textBuffer(textBuffer)
|
||||
Script::Script(const char * marker, const char * name, size_t nameBufferSize, const char * content, size_t contentBufferSize) :
|
||||
m_marker(marker),
|
||||
m_name(name),
|
||||
m_nameBufferSize(nameBufferSize),
|
||||
m_content(content),
|
||||
m_contentBufferSize(contentBufferSize)
|
||||
{
|
||||
}
|
||||
|
||||
const char * Script::readOnlyContent() const {
|
||||
return m_textBuffer;
|
||||
bool Script::isNull() const {
|
||||
if (m_marker == nullptr) {
|
||||
assert(m_name == nullptr);
|
||||
assert(m_nameBufferSize == 0);
|
||||
assert(m_content == nullptr);
|
||||
assert(m_contentBufferSize == 0);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
char * Script::editableContent() {
|
||||
return m_textBuffer;
|
||||
}
|
||||
size_t Script::bufferSize() const {
|
||||
return m_bufferSize;
|
||||
bool Script::autoimport() const {
|
||||
assert(!isNull());
|
||||
assert(m_marker != nullptr);
|
||||
if (m_marker[0] == AutoImportationMarker) {
|
||||
return true;
|
||||
}
|
||||
assert (m_marker[0] == NoAutoImportationMarker);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -7,13 +7,62 @@ namespace Code {
|
||||
|
||||
class Script {
|
||||
public:
|
||||
Script(char * textBuffer = nullptr, size_t sizeOfBuffer = 0);
|
||||
const char * readOnlyContent() const;
|
||||
char * editableContent();
|
||||
size_t bufferSize() const;
|
||||
Script(const char * marker = nullptr, const char * name = nullptr, size_t nameBufferSize = 0, const char * content = nullptr, size_t contentBufferSize = 0);
|
||||
bool isNull() const;
|
||||
bool autoimport() const;
|
||||
|
||||
const char * name() const {
|
||||
assert(!isNull());
|
||||
assert(m_name != nullptr);
|
||||
return m_name;
|
||||
}
|
||||
|
||||
char * editableName() {
|
||||
assert(!isNull());
|
||||
assert(m_name != nullptr);
|
||||
return const_cast<char *>(m_name);
|
||||
}
|
||||
|
||||
/* nameBufferSize() might not be equal to strlen(name()): There might be free
|
||||
* space (chars equal to ScriptStore::FreeSpaceMarker), that is used to edit
|
||||
* the script name. */
|
||||
size_t nameBufferSize() const {
|
||||
assert(!isNull());
|
||||
return m_nameBufferSize;
|
||||
}
|
||||
|
||||
const char * content() const {
|
||||
assert(!isNull());
|
||||
assert(m_content != nullptr);
|
||||
return m_content;
|
||||
}
|
||||
|
||||
char * editableContent() {
|
||||
assert(!isNull());
|
||||
assert(m_content != nullptr);
|
||||
return const_cast<char *>(m_content);
|
||||
}
|
||||
|
||||
/* contentBufferSize() might not be equal to strlen(name()): There might be
|
||||
* free space (chars equal to ScriptStore::FreeSpaceMarker), that is used to
|
||||
* edit the script content. */
|
||||
size_t contentBufferSize() const {
|
||||
assert(!isNull());
|
||||
return m_contentBufferSize;
|
||||
}
|
||||
|
||||
static constexpr int NumberOfStringsPerScript = 3;
|
||||
static constexpr char AutoImportationMarker = 2;
|
||||
static constexpr char NoAutoImportationMarker = 3;
|
||||
static constexpr char DefaultAutoImportationMarker = AutoImportationMarker;
|
||||
/* We made sure that these chars are not used in ion/include/ion/charset.h,
|
||||
* nor used in the ScriptStore. */
|
||||
private:
|
||||
size_t m_bufferSize;
|
||||
char * m_textBuffer;
|
||||
const char * m_marker;
|
||||
const char * m_name;
|
||||
size_t m_nameBufferSize;
|
||||
const char * m_content;
|
||||
size_t m_contentBufferSize;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ ScriptParameterController::ScriptParameterController(Responder * parentResponder
|
||||
}
|
||||
|
||||
void ScriptParameterController::setScript(int i){
|
||||
m_editorController.setScript(m_scriptStore->editableScript(i));
|
||||
m_editorController.setScript(m_scriptStore->scriptAtIndex(i, ScriptStore::EditableZone::Content));
|
||||
m_currentScriptIndex = i;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,355 +7,138 @@ namespace Code {
|
||||
constexpr char ScriptStore::k_defaultScriptName[];
|
||||
|
||||
ScriptStore::ScriptStore() :
|
||||
m_numberOfScripts(0),
|
||||
m_lastEditedStringPosition(0)
|
||||
m_accordion(m_scriptData, k_scriptDataSize)
|
||||
{
|
||||
for (int i = 0; i<k_historySize; i ++) {
|
||||
m_history[i] = FreeSpaceMarker;
|
||||
}
|
||||
}
|
||||
|
||||
Script ScriptStore::editableScript(int i) {
|
||||
assert(i >= 0 && i < numberOfScripts());
|
||||
cleanAndMoveFreeSpaceAfterScriptContent(i);
|
||||
int beginningOfScriptContent = indexOfScriptContent(i);
|
||||
const Script ScriptStore::scriptAtIndex(int index, EditableZone zone) {
|
||||
assert(index >= 0 && index < numberOfScripts());
|
||||
size_t nameBufferSize = 0;
|
||||
size_t contentBufferSize = 0;
|
||||
int accordionIndex;
|
||||
|
||||
// Compute the size of the script, including the free space of m_history
|
||||
int sizeOfEditableScript = 0;
|
||||
for (int j=beginningOfScriptContent; j<k_historySize-1; j++) {
|
||||
if (m_history[j] == FreeSpaceMarker && m_history[j+1] != FreeSpaceMarker) {
|
||||
// Move the Free Space at the end of the correct string.
|
||||
switch (zone) {
|
||||
case EditableZone::None:
|
||||
break;
|
||||
case EditableZone::Name:
|
||||
accordionIndex = accordionIndexOfNameOfScriptAtIndex(index);
|
||||
nameBufferSize = m_accordion.sizeOfEditableBufferAtIndex(accordionIndex);
|
||||
break;
|
||||
case EditableZone::Content:
|
||||
accordionIndex = accordionIndexOfContentOfScriptAtIndex(index);
|
||||
contentBufferSize = m_accordion.sizeOfEditableBufferAtIndex(accordionIndex);
|
||||
break;
|
||||
}
|
||||
sizeOfEditableScript++;
|
||||
}
|
||||
return Script(&m_history[beginningOfScriptContent], sizeOfEditableScript);
|
||||
|
||||
// Compute the positions and lengths of the Script Marker, Name and Content.
|
||||
const char * marker = m_accordion.bufferAtIndex(accordionIndexOfMarkersOfScriptAtIndex(index));
|
||||
const char * name = m_accordion.bufferAtIndex(accordionIndexOfNameOfScriptAtIndex(index));
|
||||
if (nameBufferSize == 0) {
|
||||
nameBufferSize = strlen(name);
|
||||
}
|
||||
const char * content = m_accordion.bufferAtIndex(accordionIndexOfContentOfScriptAtIndex(index));
|
||||
if (contentBufferSize == 0) {
|
||||
contentBufferSize = strlen(content);
|
||||
}
|
||||
return Script(marker, name, nameBufferSize, content, contentBufferSize);
|
||||
}
|
||||
|
||||
Script ScriptStore::script(int i) {
|
||||
assert(i >= 0 && i < numberOfScripts());
|
||||
cleanFreeSpace();
|
||||
int beginningOfScriptContent = indexOfScriptContent(i);
|
||||
return Script(&m_history[beginningOfScriptContent], strlen(&m_history[beginningOfScriptContent]) + 1);
|
||||
}
|
||||
|
||||
Script ScriptStore::script(const char * name) {
|
||||
cleanFreeSpace();
|
||||
for (int i=0; i<numberOfScripts(); i++) {
|
||||
const char * nameScripti = nameOfScript(i);
|
||||
if (strcmp(nameScripti, name) == 0) {
|
||||
return script(i);
|
||||
const Script ScriptStore::scriptNamed(const char * name) {
|
||||
for (int i = 0; i < numberOfScripts(); i++) {
|
||||
int accordionIndex = accordionIndexOfNameOfScriptAtIndex(i);
|
||||
const char * currentScriptName = m_accordion.bufferAtIndex(accordionIndex);
|
||||
if (strcmp(currentScriptName, name) == 0) {
|
||||
return scriptAtIndex(i);
|
||||
}
|
||||
}
|
||||
return Script();
|
||||
}
|
||||
|
||||
char * ScriptStore::nameOfScript(int i) {
|
||||
cleanFreeSpace();
|
||||
return &m_history[indexOfScriptName(i)];
|
||||
int ScriptStore::numberOfScripts() {
|
||||
return (m_accordion.numberOfBuffers())/Script::NumberOfStringsPerScript;
|
||||
}
|
||||
|
||||
char * ScriptStore::editableNameOfScript(int i) {
|
||||
assert (i >= 0 && i < numberOfScripts());
|
||||
cleanAndMoveFreeSpaceAfterScriptName(i);
|
||||
return &m_history[indexOfScriptName(i)];
|
||||
}
|
||||
|
||||
int ScriptStore::sizeOfEditableNameOfScript(int i) {
|
||||
// Compute the size of the name of the script, including the free space of m_history
|
||||
int sizeOfEditableNameScript = 0;
|
||||
for (int j=indexOfScriptName(i); j<k_historySize-1; j++) {
|
||||
if (m_history[j] == FreeSpaceMarker && m_history[j+1] != FreeSpaceMarker) {
|
||||
bool ScriptStore::addNewScript(DefaultScript defaultScript) {
|
||||
const char autoImportationString[2] = {Script::DefaultAutoImportationMarker, 0};
|
||||
if (!m_accordion.appendBuffer(autoImportationString)) {
|
||||
return false;
|
||||
}
|
||||
const char * name = nullptr;
|
||||
switch (defaultScript) {
|
||||
case DefaultScript::Empty:
|
||||
name = k_defaultScriptName;
|
||||
break;
|
||||
case DefaultScript::Mandelbrot:
|
||||
name = "mandelbrot.py";
|
||||
break;
|
||||
case DefaultScript::Factorial:
|
||||
name = "factorial.py";
|
||||
break;
|
||||
}
|
||||
sizeOfEditableNameScript++;
|
||||
}
|
||||
return sizeOfEditableNameScript;
|
||||
}
|
||||
|
||||
int ScriptStore::numberOfScripts() const {
|
||||
return m_numberOfScripts;
|
||||
}
|
||||
|
||||
bool ScriptStore::addNewScript() {
|
||||
int sizeFreeSpace = sizeOfFreeSpace();
|
||||
if (sizeFreeSpace < 4) {
|
||||
if (!m_accordion.appendBuffer(name)) {
|
||||
// Delete the Auto Importation Marker
|
||||
m_accordion.deleteLastBuffer();
|
||||
return false;
|
||||
}
|
||||
cleanAndMoveFreeSpaceAfterScriptContent(numberOfScripts()-1);
|
||||
int beginningNewScript = indexOfFirstFreeSpaceMarker();
|
||||
m_history[beginningNewScript] = AutoImportationMarker;
|
||||
if (copyName(beginningNewScript + 1)) {
|
||||
if (copyEmptyScriptOnFreeSpace()) {
|
||||
m_numberOfScripts++;
|
||||
m_lastEditedStringPosition = indexOfScriptContent(numberOfScripts()-1);
|
||||
return true;
|
||||
}
|
||||
bool didCopy = false;
|
||||
switch (defaultScript) {
|
||||
case DefaultScript::Empty:
|
||||
didCopy = copyEmptyScriptOnFreeSpace();
|
||||
break;
|
||||
case DefaultScript::Mandelbrot:
|
||||
didCopy = copyMandelbrotScriptOnFreeSpace();
|
||||
break;
|
||||
case DefaultScript::Factorial:
|
||||
didCopy = copyFactorialScriptOnFreeSpace();
|
||||
break;
|
||||
}
|
||||
for (int i = beginningNewScript; i<k_historySize; i++) {
|
||||
m_history[i] = FreeSpaceMarker;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ScriptStore::addFactorialScript() {
|
||||
int sizeFreeSpace = sizeOfFreeSpace();
|
||||
if (sizeFreeSpace < 4) {
|
||||
return false;
|
||||
}
|
||||
cleanAndMoveFreeSpaceAfterScriptContent(numberOfScripts()-1);
|
||||
int beginningNewScript = indexOfFirstFreeSpaceMarker();
|
||||
m_history[beginningNewScript] = AutoImportationMarker;
|
||||
if (copyName(beginningNewScript + 1, "factorial.py")) {
|
||||
if (copyFactorialScriptOnFreeSpace()) {
|
||||
m_numberOfScripts++;
|
||||
m_lastEditedStringPosition = indexOfScriptContent(numberOfScripts()-1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (int i = beginningNewScript; i<k_historySize; i++) {
|
||||
m_history[i] = FreeSpaceMarker;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ScriptStore::addMandelbrotScript() {
|
||||
int sizeFreeSpace = sizeOfFreeSpace();
|
||||
if (sizeFreeSpace < 5) {
|
||||
return false;
|
||||
}
|
||||
cleanAndMoveFreeSpaceAfterScriptContent(numberOfScripts()-1);
|
||||
int beginningNewScript = indexOfFirstFreeSpaceMarker();
|
||||
m_history[beginningNewScript] = AutoImportationMarker;
|
||||
if (copyName(beginningNewScript + 1, "mandelbrot.py")) {
|
||||
if (copyMandelbrotScriptOnFreeSpace()) {
|
||||
m_numberOfScripts++;
|
||||
m_lastEditedStringPosition = indexOfScriptContent(numberOfScripts()-1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (int i = beginningNewScript; i<k_historySize; i++) {
|
||||
m_history[i] = FreeSpaceMarker;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ScriptStore::renameScript(int i, const char * newName) {
|
||||
assert (i >= 0 && i < numberOfScripts());
|
||||
cleanAndMoveFreeSpaceAfterScriptName(i);
|
||||
if (strlen(newName) <= sizeOfEditableNameOfScript(i)) {
|
||||
copyName(indexOfScriptName(i), newName);
|
||||
if (didCopy) {
|
||||
return true;
|
||||
}
|
||||
// Delete the Auto Importation Marker and the Name Of the Script
|
||||
m_accordion.deleteLastBuffer();
|
||||
m_accordion.deleteLastBuffer();
|
||||
return false;
|
||||
}
|
||||
|
||||
void ScriptStore::deleteScript(int i) {
|
||||
assert (i >= 0 && i < numberOfScripts());
|
||||
cleanAndMoveFreeSpaceAfterScriptContent(i);
|
||||
int indexOfCharToDelete = indexOfScript(i);
|
||||
while (m_history[indexOfCharToDelete] != FreeSpaceMarker && indexOfCharToDelete < k_historySize) {
|
||||
m_history[indexOfCharToDelete] = FreeSpaceMarker;
|
||||
indexOfCharToDelete++;
|
||||
}
|
||||
m_numberOfScripts--;
|
||||
bool ScriptStore::renameScriptAtIndex(int index, const char * newName) {
|
||||
assert (index >= 0 && index < numberOfScripts());
|
||||
int accordionIndex = accordionIndexOfNameOfScriptAtIndex(index);
|
||||
return m_accordion.replaceBufferAtIndex(accordionIndex, newName);
|
||||
}
|
||||
|
||||
void ScriptStore::deleteAll() {
|
||||
for (int i = 0; i<k_historySize; i++){
|
||||
m_history[i] = FreeSpaceMarker;
|
||||
}
|
||||
m_numberOfScripts = 0;
|
||||
void ScriptStore::deleteScriptAtIndex(int index) {
|
||||
assert (index >= 0 && index < numberOfScripts());
|
||||
int accordionIndex = accordionIndexOfContentOfScriptAtIndex(index);
|
||||
// We delete in reverse order because we want the indexes to stay true.
|
||||
m_accordion.deleteBufferAtIndex(accordionIndex);
|
||||
m_accordion.deleteBufferAtIndex(accordionIndex-1);
|
||||
m_accordion.deleteBufferAtIndex(accordionIndex-2);
|
||||
}
|
||||
|
||||
void ScriptStore::deleteAllScripts() {
|
||||
m_accordion.deleteAll();
|
||||
}
|
||||
|
||||
const char * ScriptStore::contentOfScript(const char * name) {
|
||||
int filenameIndex = indexBeginningFilename(name);
|
||||
const char * filename = &name[filenameIndex];
|
||||
return script(filename).readOnlyContent();
|
||||
Script script = scriptNamed(name);
|
||||
if (script.isNull()) {
|
||||
return nullptr;
|
||||
}
|
||||
return script.content();
|
||||
}
|
||||
|
||||
bool ScriptStore::copyName(int position, const char * name) {
|
||||
if (name) {
|
||||
int len = strlen(name);
|
||||
if (len > sizeOfFreeSpace() - 1) { // We keep at keast one free char.
|
||||
return false;
|
||||
}
|
||||
memcpy(&m_history[position], name, len+1);
|
||||
return true;
|
||||
} else {
|
||||
int len = strlen(k_defaultScriptName);
|
||||
if (len > sizeOfFreeSpace() - 1) { // We keep at keast one free char.
|
||||
return false;
|
||||
}
|
||||
memcpy(&m_history[position], k_defaultScriptName, len+1);
|
||||
return true;
|
||||
|
||||
}
|
||||
int ScriptStore::accordionIndexOfMarkersOfScriptAtIndex(int index) const {
|
||||
return index * Script::NumberOfStringsPerScript;
|
||||
}
|
||||
|
||||
int ScriptStore::indexOfScript(int i) const {
|
||||
assert (i >= 0 && i < numberOfScripts());
|
||||
int currentScriptNumber = 0;
|
||||
int beginningOfScript = 0;
|
||||
while (m_history[beginningOfScript] == FreeSpaceMarker && beginningOfScript < k_historySize) {
|
||||
beginningOfScript++;
|
||||
}
|
||||
if (i == 0) {
|
||||
return beginningOfScript;
|
||||
}
|
||||
bool goingThroughName = true;
|
||||
for (int j=beginningOfScript; j<k_historySize; j++) {
|
||||
if (m_history[j] == 0) {
|
||||
if (goingThroughName) {
|
||||
goingThroughName = false;
|
||||
} else {
|
||||
goingThroughName = true;
|
||||
currentScriptNumber++;
|
||||
if (currentScriptNumber == i) {
|
||||
j++;
|
||||
while (m_history[j] == FreeSpaceMarker && j < beginningOfScript) {
|
||||
j++;
|
||||
}
|
||||
return j;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(false);
|
||||
return 0;
|
||||
int ScriptStore::accordionIndexOfNameOfScriptAtIndex(int index) const {
|
||||
return index * Script::NumberOfStringsPerScript + 1;
|
||||
}
|
||||
|
||||
int ScriptStore::indexOfScriptName(int i) const {
|
||||
assert (i >= 0 && i < numberOfScripts());
|
||||
return indexOfScript(i)+1;
|
||||
}
|
||||
|
||||
|
||||
int ScriptStore::indexOfScriptContent(int i) const {
|
||||
assert (i >= 0 && i < numberOfScripts());
|
||||
int indexOfScriptContent = indexOfScriptName(i);
|
||||
while (m_history[indexOfScriptContent] != 0 && indexOfScriptContent<k_historySize) {
|
||||
indexOfScriptContent++;
|
||||
}
|
||||
indexOfScriptContent++;
|
||||
return indexOfScriptContent;
|
||||
}
|
||||
|
||||
int ScriptStore::lastIndexOfScript(int i) const {
|
||||
assert (i >= 0 && i < numberOfScripts());
|
||||
int indexOfPrgm = indexOfScriptContent(i);
|
||||
int lastIndexOfScript = indexOfPrgm + strlen(&m_history[indexOfPrgm]);
|
||||
return lastIndexOfScript;
|
||||
}
|
||||
|
||||
int ScriptStore::indexOfFirstFreeSpaceMarker() const {
|
||||
for (int i=0; i<k_historySize; i++) {
|
||||
if (m_history[i] == FreeSpaceMarker) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ScriptStore::sizeOfFreeSpace() const {
|
||||
int sizeOfFreeSpace = 0;
|
||||
for (int i=0; i<k_historySize; i++) {
|
||||
if (m_history[i] == FreeSpaceMarker) {
|
||||
sizeOfFreeSpace++;
|
||||
} else {
|
||||
if (sizeOfFreeSpace > 0) {
|
||||
return sizeOfFreeSpace;
|
||||
}
|
||||
}
|
||||
}
|
||||
return sizeOfFreeSpace;
|
||||
}
|
||||
|
||||
void ScriptStore::cleanFreeSpace() {
|
||||
if (m_history[m_lastEditedStringPosition] == FreeSpaceMarker
|
||||
|| m_history[m_lastEditedStringPosition] == AutoImportationMarker
|
||||
|| m_history[m_lastEditedStringPosition] == NoAutoImportationMarker)
|
||||
{
|
||||
return;
|
||||
}
|
||||
int indexOfCharToChangeIntoFreeSpaceMarker = m_lastEditedStringPosition
|
||||
+ strlen (&m_history[m_lastEditedStringPosition]) + 1;
|
||||
while (m_history[indexOfCharToChangeIntoFreeSpaceMarker] != FreeSpaceMarker
|
||||
&& indexOfCharToChangeIntoFreeSpaceMarker<k_historySize)
|
||||
{
|
||||
m_history[indexOfCharToChangeIntoFreeSpaceMarker] = FreeSpaceMarker;
|
||||
indexOfCharToChangeIntoFreeSpaceMarker ++;
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptStore::moveFreeSpaceAfterScriptContent(int i) {
|
||||
assert (i >= 0 && i < numberOfScripts());
|
||||
int indexOfFreeSpace = indexOfFirstFreeSpaceMarker();
|
||||
int newFreeSpacePosition = lastIndexOfScript(i) + 1;
|
||||
if (indexOfFreeSpace < newFreeSpacePosition) {
|
||||
newFreeSpacePosition -= sizeOfFreeSpace();
|
||||
}
|
||||
moveFreeSpaceAtPosition(newFreeSpacePosition);
|
||||
}
|
||||
|
||||
void ScriptStore::moveFreeSpaceAfterScriptName(int i) {
|
||||
assert (i >= 0 && i < numberOfScripts());
|
||||
int newFreeSpacePosition = indexOfScriptName(i);
|
||||
while (m_history[newFreeSpacePosition] != 0 && newFreeSpacePosition < k_historySize) {
|
||||
newFreeSpacePosition++;
|
||||
}
|
||||
newFreeSpacePosition++;
|
||||
moveFreeSpaceAtPosition(newFreeSpacePosition);
|
||||
}
|
||||
|
||||
void ScriptStore::moveFreeSpaceAtPosition(int i) {
|
||||
assert (i >= 0 && i < k_historySize);
|
||||
int indexOfFreeSpace = indexOfFirstFreeSpaceMarker();
|
||||
if (indexOfFreeSpace != i){
|
||||
|
||||
// First, move the chars that would be overriden by the free space.
|
||||
int freeSpaceSize = sizeOfFreeSpace();
|
||||
int len, src, dst;
|
||||
// The indexes depend on the relative positions of the free space and the
|
||||
// new destination.
|
||||
if (indexOfFreeSpace > i) {
|
||||
len = indexOfFreeSpace - i;
|
||||
src = i;
|
||||
dst = i + freeSpaceSize;
|
||||
} else {
|
||||
src = indexOfFreeSpace + freeSpaceSize;
|
||||
len = i + freeSpaceSize - src;
|
||||
dst = indexOfFreeSpace;
|
||||
}
|
||||
memmove(&m_history[dst], &m_history[src], len);
|
||||
|
||||
// Then move the free space.
|
||||
for (int j = i ; j<i+freeSpaceSize; j++) {
|
||||
m_history[j] = FreeSpaceMarker;
|
||||
}
|
||||
}
|
||||
|
||||
m_lastEditedStringPosition = i-1;
|
||||
while (m_lastEditedStringPosition > 0
|
||||
&& m_history[m_lastEditedStringPosition-1] != 0
|
||||
&& m_history[m_lastEditedStringPosition-1] != AutoImportationMarker
|
||||
&& m_history[m_lastEditedStringPosition-1] != NoAutoImportationMarker)
|
||||
{
|
||||
m_lastEditedStringPosition--;
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptStore::cleanAndMoveFreeSpaceAfterScriptContent(int i) {
|
||||
if (i >= 0 && i<numberOfScripts()){
|
||||
cleanFreeSpace();
|
||||
moveFreeSpaceAfterScriptContent(i);
|
||||
}
|
||||
}
|
||||
void ScriptStore::cleanAndMoveFreeSpaceAfterScriptName(int i) {
|
||||
if (i >= 0 && i<numberOfScripts()){
|
||||
cleanFreeSpace();
|
||||
moveFreeSpaceAfterScriptName(i);
|
||||
}
|
||||
int ScriptStore::accordionIndexOfContentOfScriptAtIndex(int index) const {
|
||||
return index * Script::NumberOfStringsPerScript + 2;
|
||||
}
|
||||
|
||||
bool ScriptStore::copyMandelbrotScriptOnFreeSpace() {
|
||||
@@ -383,47 +166,21 @@ for x in range(320):
|
||||
# Draw a pixel colored in 'col' at position (x,y)
|
||||
kandinsky.set_pixel(x,y,col))";
|
||||
|
||||
int len = strlen(script);
|
||||
if (len + 1 > sizeOfFreeSpace() - 1) { // We keep at keast one free char.
|
||||
return false;
|
||||
}
|
||||
memcpy(&m_history[indexOfFirstFreeSpaceMarker()], script, len+1);
|
||||
return true;
|
||||
return m_accordion.appendBuffer(script);
|
||||
}
|
||||
|
||||
bool ScriptStore::copyFactorialScriptOnFreeSpace() {
|
||||
const char script[] = R"(def factorial(n):
|
||||
if n == 0:
|
||||
return 1
|
||||
else:
|
||||
return n * factorial(n-1)
|
||||
)";
|
||||
return n * factorial(n-1))";
|
||||
|
||||
int len = strlen(script);
|
||||
if (len + 1 > sizeOfFreeSpace() - 1) { // We keep at keast one free char.
|
||||
return false;
|
||||
}
|
||||
memcpy(&m_history[indexOfFirstFreeSpaceMarker()], script, len+1);
|
||||
return true;
|
||||
return m_accordion.appendBuffer(script);
|
||||
}
|
||||
|
||||
bool ScriptStore::copyEmptyScriptOnFreeSpace() {
|
||||
const char script[] = "\0";
|
||||
|
||||
int len = 1;
|
||||
if (len > sizeOfFreeSpace() - 1) { // We keep at keast one free char.
|
||||
return false;
|
||||
}
|
||||
memcpy(&m_history[indexOfFirstFreeSpaceMarker()], script, len);
|
||||
return true;
|
||||
}
|
||||
|
||||
int ScriptStore::indexBeginningFilename(const char * path) {
|
||||
int beginningFilename = strlen(path)-1;
|
||||
while (beginningFilename > 0 && path[beginningFilename - 1] != '\\') {
|
||||
beginningFilename--;
|
||||
}
|
||||
return beginningFilename;
|
||||
return m_accordion.appendBuffer(script);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,74 +2,49 @@
|
||||
#define CODE_SCRIPT_STORE_H
|
||||
|
||||
#include "script.h"
|
||||
#include <escher/accordion.h>
|
||||
#include <python/port/port.h>
|
||||
|
||||
namespace Code {
|
||||
|
||||
class ScriptStore : public MicroPython::ScriptProvider {
|
||||
public:
|
||||
enum class EditableZone {
|
||||
None,
|
||||
Name,
|
||||
Content
|
||||
};
|
||||
|
||||
enum class DefaultScript {
|
||||
Empty,
|
||||
Mandelbrot,
|
||||
Factorial
|
||||
};
|
||||
|
||||
ScriptStore();
|
||||
Script editableScript(int i);
|
||||
/* editableScript moves the free space of m_history at the end of the
|
||||
* ith script. It returns a Script object that points to the beginning of the
|
||||
* wanted script and has a length taking into account both the script and the
|
||||
* free space. */
|
||||
Script script(int i);
|
||||
/* script returns a Script object that points to the beginning of the
|
||||
* ith script and has the length of the script. */
|
||||
Script script(const char * name);
|
||||
/* script(const char * name) looks for a script that has the right name and
|
||||
* returns it. If there is no such script, it returns an empty Script. */
|
||||
char * nameOfScript(int i);
|
||||
char * editableNameOfScript(int i);
|
||||
int sizeOfEditableNameOfScript(int i);
|
||||
int numberOfScripts() const;
|
||||
bool addNewScript();
|
||||
bool addMandelbrotScript();
|
||||
bool addFactorialScript();
|
||||
bool renameScript(int i, const char * newName);
|
||||
void deleteScript(int i);
|
||||
void deleteAll();
|
||||
const Script scriptAtIndex(int index, EditableZone zone = EditableZone::None);
|
||||
const Script scriptNamed(const char * name);
|
||||
int numberOfScripts();
|
||||
bool addNewScript(DefaultScript defaultScript = DefaultScript::Empty);
|
||||
bool renameScriptAtIndex(int index, const char * newName);
|
||||
void deleteScriptAtIndex(int index);
|
||||
void deleteAllScripts();
|
||||
|
||||
/* MicroPython::ScriptProvider */
|
||||
const char * contentOfScript(const char * name) override;
|
||||
|
||||
private:
|
||||
static constexpr char FreeSpaceMarker = 0x01;
|
||||
static constexpr char AutoImportationMarker = 0x02;
|
||||
static constexpr char NoAutoImportationMarker = 0x03;
|
||||
/* We made sure that these chars are not used in ion/include/ion/charset.h */
|
||||
static constexpr int k_historySize = 1024;
|
||||
static constexpr char k_defaultScriptName[] = ".py";
|
||||
bool copyName(int position, const char * name = nullptr);
|
||||
int indexOfScript(int i) const;
|
||||
int indexOfScriptName(int i) const;
|
||||
int indexOfScriptContent(int i) const;
|
||||
int lastIndexOfScript(int i) const;
|
||||
int indexOfFirstFreeSpaceMarker() const;
|
||||
int sizeOfFreeSpace() const;
|
||||
void cleanFreeSpace();
|
||||
void moveFreeSpaceAfterScriptContent(int i);
|
||||
void moveFreeSpaceAfterScriptName(int i);
|
||||
void moveFreeSpaceAtPosition(int i);
|
||||
void cleanAndMoveFreeSpaceAfterScriptContent(int i);
|
||||
void cleanAndMoveFreeSpaceAfterScriptName(int i);
|
||||
static constexpr size_t k_scriptDataSize = 1024;
|
||||
int accordionIndexOfScriptAtIndex(int index) const;
|
||||
int accordionIndexOfMarkersOfScriptAtIndex(int index) const;
|
||||
int accordionIndexOfNameOfScriptAtIndex(int index) const;
|
||||
int accordionIndexOfContentOfScriptAtIndex(int index) const;
|
||||
bool copyMandelbrotScriptOnFreeSpace();
|
||||
bool copyFactorialScriptOnFreeSpace();
|
||||
bool copyEmptyScriptOnFreeSpace();
|
||||
int indexBeginningFilename(const char * path);
|
||||
char m_history[k_historySize];
|
||||
/* The m_history variable sequentially stores scripts as text buffers.
|
||||
* Each script is stored as follow:
|
||||
* - First, a char that says whether the script should be automatically
|
||||
* imported in the console.
|
||||
* - Then, the name of the script.
|
||||
* - Finally, the content of the script.
|
||||
* The free bytes of m_history contain the FreeSpaceMarker. By construction,
|
||||
* there is always at least one free byte, and the free space is always
|
||||
* continuous. */
|
||||
int m_numberOfScripts;
|
||||
int m_lastEditedStringPosition;
|
||||
char m_scriptData[k_scriptDataSize];
|
||||
Accordion m_accordion;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
SFLAGS += -Iescher/include
|
||||
|
||||
objs += $(addprefix escher/src/,\
|
||||
accordion.o\
|
||||
alternate_empty_view_controller.o\
|
||||
app.o\
|
||||
buffer_text_view.o\
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef ESCHER_H
|
||||
#define ESCHER_H
|
||||
|
||||
#include <escher/accordion.h>
|
||||
#include <escher/alternate_empty_view_controller.h>
|
||||
#include <escher/alternate_empty_view_delegate.h>
|
||||
#include <escher/app.h>
|
||||
|
||||
51
escher/include/escher/accordion.h
Normal file
51
escher/include/escher/accordion.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#ifndef ESCHER_ACCORDION_H
|
||||
#define ESCHER_ACCORDION_H
|
||||
|
||||
/* Accordion sequentially stores null-terminated char buffers. It moves the free
|
||||
* space at the end of a buffer if it will be edited. */
|
||||
|
||||
class Accordion {
|
||||
public:
|
||||
Accordion(char * buffer, int bufferSize);
|
||||
int numberOfBuffers();
|
||||
const char * bufferAtIndex(int index);
|
||||
char * editableBufferAtIndex(int index);
|
||||
int sizeOfEditableBufferAtIndex(int index);
|
||||
/* sizeOfEditableBufferAtIndex appends the free space at the end of the buffer
|
||||
* and returns the length of the buffer plus the free space, minus one free
|
||||
* space char that we never edit in order to keep track of the position of the
|
||||
* last edited buffer. */
|
||||
bool appendBuffer(const char * buffer);
|
||||
bool replaceBufferAtIndex(int index, const char * buffer);
|
||||
void deleteBufferAtIndex(int index);
|
||||
void deleteLastBuffer();
|
||||
void deleteAll();
|
||||
private:
|
||||
static constexpr char k_freeSpaceMarker = 0x01;
|
||||
int startOfBufferAtIndex(int index);
|
||||
int endOfBufferAtIndex(int index);
|
||||
int startOfFreeSpace();
|
||||
int freeSpaceSize();
|
||||
void cleanFreeSpace();
|
||||
/* When a buffer is edited, there is garbage after the first null char of the
|
||||
* buffer. cleanFreeSpace() declares the space after this null char as free,
|
||||
* by marking it with the FreeSpaceMarker. Because we always keep at least one
|
||||
* Free Space char out of the editable zone, cleanFreeSpace() just needs to
|
||||
* put FreeSpaceMarkers after the first null char of the last edited Buffer,
|
||||
* until the first FreeSpaceMarker char.
|
||||
* WARNING: We have to call cleanFreeSpace() before any operation on m_history,
|
||||
* otherwise m_history might contain garbage chars. */
|
||||
void moveFreeSpaceAtPosition(int i);
|
||||
void moveFreeSpaceAtEndOfBufferAtIndex(int index);
|
||||
void moveFreeSpaceAtEndOfHistory();
|
||||
int m_historySize;
|
||||
char * m_history;
|
||||
/* The m_history variable sequentially stores null-terminated char buffers.
|
||||
* It also contains free space, which is marked with the FreeSpaceMarker. By
|
||||
* construction, there is always at least one free byte, and the free space is
|
||||
* always continuous. */
|
||||
int m_numberOfBuffers;
|
||||
int m_startOfLastEditedBuffer;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -7,7 +7,7 @@ class TextAreaDelegate {
|
||||
public:
|
||||
virtual bool textAreaShouldFinishEditing(TextArea * textArea, Ion::Events::Event event) = 0;
|
||||
virtual bool textAreaDidReceiveEvent(TextArea * textArea, Ion::Events::Event event) = 0;
|
||||
virtual Toolbox * toolboxForTextArea(TextArea * textFied) = 0;
|
||||
virtual Toolbox * toolboxForTextArea(TextArea * textArea) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
228
escher/src/accordion.cpp
Normal file
228
escher/src/accordion.cpp
Normal file
@@ -0,0 +1,228 @@
|
||||
#include <escher/accordion.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
Accordion::Accordion(char * buffer, int bufferSize) :
|
||||
m_historySize(bufferSize),
|
||||
m_history(buffer),
|
||||
m_numberOfBuffers(0),
|
||||
m_startOfLastEditedBuffer(0)
|
||||
{
|
||||
for (int i = 0; i < m_historySize; i ++) {
|
||||
m_history[i] = k_freeSpaceMarker;
|
||||
}
|
||||
}
|
||||
|
||||
int Accordion::numberOfBuffers() {
|
||||
return m_numberOfBuffers;
|
||||
}
|
||||
|
||||
const char * Accordion::bufferAtIndex(int index) {
|
||||
assert(index >= 0 && index < numberOfBuffers());
|
||||
cleanFreeSpace();
|
||||
int startOfBuffer = startOfBufferAtIndex(index);
|
||||
return &m_history[startOfBuffer];
|
||||
}
|
||||
|
||||
char * Accordion::editableBufferAtIndex(int index) {
|
||||
assert(index >= 0 && index < numberOfBuffers());
|
||||
cleanFreeSpace();
|
||||
moveFreeSpaceAtEndOfBufferAtIndex(index);
|
||||
int startOfBuffer = startOfBufferAtIndex(index);
|
||||
return &m_history[startOfBuffer];
|
||||
}
|
||||
|
||||
int Accordion::sizeOfEditableBufferAtIndex(int index) {
|
||||
assert(index >= 0 && index < numberOfBuffers());
|
||||
cleanFreeSpace();
|
||||
moveFreeSpaceAtEndOfBufferAtIndex(index);
|
||||
int length = 0;
|
||||
for (int i = startOfBufferAtIndex(index); i < m_historySize-1; i++) {
|
||||
if (m_history[i] == k_freeSpaceMarker && m_history[i+1] != k_freeSpaceMarker) {
|
||||
break;
|
||||
}
|
||||
length++;
|
||||
// We do not count one Free Space Marker, in order to always have at a
|
||||
// Free Space of sizeat least one.
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
bool Accordion::appendBuffer(const char * buffer) {
|
||||
cleanFreeSpace();
|
||||
moveFreeSpaceAtEndOfHistory();
|
||||
int len = strlen(buffer);
|
||||
if (len + 1 > freeSpaceSize() - 1) { // We keep at keast one Free char.
|
||||
return false;
|
||||
}
|
||||
m_startOfLastEditedBuffer = startOfFreeSpace();
|
||||
memcpy(&m_history[m_startOfLastEditedBuffer], buffer, len+1);
|
||||
m_numberOfBuffers++;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Accordion::replaceBufferAtIndex(int index, const char * buffer) {
|
||||
assert(index >= 0 && index < numberOfBuffers());
|
||||
cleanFreeSpace();
|
||||
int len = strlen(buffer);
|
||||
if (len < sizeOfEditableBufferAtIndex(index)) {
|
||||
int startOfOldBuffer = startOfBufferAtIndex(index);
|
||||
memcpy(&m_history[startOfOldBuffer], buffer, len+1);
|
||||
m_startOfLastEditedBuffer = startOfOldBuffer;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Accordion::deleteBufferAtIndex(int index) {
|
||||
assert(index >= 0 && index < numberOfBuffers());
|
||||
cleanFreeSpace();
|
||||
moveFreeSpaceAtEndOfBufferAtIndex(index);
|
||||
int i = startOfBufferAtIndex(index);
|
||||
while (i < m_historySize && m_history[i] != k_freeSpaceMarker) {
|
||||
m_history[i] = k_freeSpaceMarker;
|
||||
i++;
|
||||
}
|
||||
m_numberOfBuffers--;
|
||||
}
|
||||
|
||||
void Accordion::deleteLastBuffer() {
|
||||
cleanFreeSpace();
|
||||
if (m_numberOfBuffers > 0) {
|
||||
deleteBufferAtIndex(m_numberOfBuffers-1);
|
||||
}
|
||||
}
|
||||
|
||||
void Accordion::deleteAll() {
|
||||
cleanFreeSpace();
|
||||
for (int i = 0; i < m_historySize; i++){
|
||||
m_history[i] = k_freeSpaceMarker;
|
||||
}
|
||||
m_numberOfBuffers = 0;
|
||||
}
|
||||
|
||||
int Accordion::startOfBufferAtIndex(int index) {
|
||||
assert(index >= 0 && index < numberOfBuffers());
|
||||
cleanFreeSpace();
|
||||
int bufferCount = 0;
|
||||
int startOfBuffer = 0;
|
||||
while (m_history[startOfBuffer] == k_freeSpaceMarker && startOfBuffer < m_historySize) {
|
||||
startOfBuffer++;
|
||||
}
|
||||
for (int i = startOfBuffer; i < m_historySize; i++) {
|
||||
if (bufferCount == index) {
|
||||
while (m_history[i] == k_freeSpaceMarker && i < m_historySize) {
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
if (m_history[i] == 0) {
|
||||
bufferCount++;
|
||||
}
|
||||
}
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Accordion::endOfBufferAtIndex(int index) {
|
||||
assert(index >= 0 && index < numberOfBuffers());
|
||||
cleanFreeSpace();
|
||||
int startOfBuffer = startOfBufferAtIndex(index);
|
||||
for (int i = startOfBuffer; i < m_historySize; i++) {
|
||||
if (m_history[i] == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Accordion::startOfFreeSpace() {
|
||||
cleanFreeSpace();
|
||||
for (int i = 0; i < m_historySize; i++) {
|
||||
if (m_history[i] == k_freeSpaceMarker) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Accordion::freeSpaceSize() {
|
||||
cleanFreeSpace();
|
||||
int sizeOfFreeSpace = 0;
|
||||
int freeSpaceStart = startOfFreeSpace();
|
||||
for (int i = freeSpaceStart; i < m_historySize; i++) {
|
||||
if (m_history[i] == k_freeSpaceMarker) {
|
||||
sizeOfFreeSpace++;
|
||||
} else {
|
||||
return sizeOfFreeSpace;
|
||||
}
|
||||
}
|
||||
return sizeOfFreeSpace;
|
||||
}
|
||||
|
||||
void Accordion::cleanFreeSpace() {
|
||||
if (m_history[m_startOfLastEditedBuffer] == k_freeSpaceMarker) {
|
||||
return;
|
||||
}
|
||||
int indexOfCharToChangeIntoFreeSpaceMarker = m_startOfLastEditedBuffer
|
||||
+ strlen(&m_history[m_startOfLastEditedBuffer]) + 1;
|
||||
while (m_history[indexOfCharToChangeIntoFreeSpaceMarker] != k_freeSpaceMarker
|
||||
&& indexOfCharToChangeIntoFreeSpaceMarker < m_historySize)
|
||||
{
|
||||
m_history[indexOfCharToChangeIntoFreeSpaceMarker] = k_freeSpaceMarker;
|
||||
indexOfCharToChangeIntoFreeSpaceMarker ++;
|
||||
}
|
||||
}
|
||||
|
||||
void Accordion::moveFreeSpaceAtPosition(int i) {
|
||||
assert(i >= 0 && i <= m_historySize);
|
||||
cleanFreeSpace();
|
||||
int freeSpaceStart = startOfFreeSpace();
|
||||
if (freeSpaceStart != i){
|
||||
|
||||
// First, move the chars that would be overriden by the free space.
|
||||
// The indexes depend on the relative positions of the free space and the
|
||||
// new destination.
|
||||
int sizeFreeSpace = freeSpaceSize();
|
||||
int len, src, dst, newFreeSpaceStart;
|
||||
if (freeSpaceStart > i) {
|
||||
len = freeSpaceStart - i;
|
||||
src = i;
|
||||
dst = i + sizeFreeSpace;
|
||||
newFreeSpaceStart = i;
|
||||
} else {
|
||||
src = freeSpaceStart + sizeFreeSpace;
|
||||
len = i - src;
|
||||
dst = freeSpaceStart;
|
||||
newFreeSpaceStart = i-sizeFreeSpace;
|
||||
}
|
||||
memmove(&m_history[dst], &m_history[src], len);
|
||||
|
||||
// Then move the free space.
|
||||
for (int j = newFreeSpaceStart ; j < newFreeSpaceStart+sizeFreeSpace; j++) {
|
||||
m_history[j] = k_freeSpaceMarker;
|
||||
}
|
||||
}
|
||||
|
||||
m_startOfLastEditedBuffer = i-1;
|
||||
while (m_startOfLastEditedBuffer > 0 && m_history[m_startOfLastEditedBuffer-1] != 0 ) {
|
||||
m_startOfLastEditedBuffer--;
|
||||
}
|
||||
}
|
||||
|
||||
void Accordion::moveFreeSpaceAtEndOfBufferAtIndex(int index) {
|
||||
assert(index >= 0 && index < numberOfBuffers());
|
||||
cleanFreeSpace();
|
||||
int endOfBuffer = endOfBufferAtIndex(index);
|
||||
moveFreeSpaceAtPosition(endOfBuffer+1);
|
||||
}
|
||||
|
||||
void Accordion::moveFreeSpaceAtEndOfHistory() {
|
||||
cleanFreeSpace();
|
||||
if (m_numberOfBuffers > 0) {
|
||||
moveFreeSpaceAtEndOfBufferAtIndex(m_numberOfBuffers-1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -323,6 +323,7 @@ TextArea::TextArea(Responder * parentResponder, char * textBuffer,
|
||||
|
||||
void TextArea::setText(char * textBuffer, size_t textBufferSize) {
|
||||
m_contentView.setText(textBuffer, textBufferSize);
|
||||
m_contentView.moveCursorGeo(0, 0);
|
||||
}
|
||||
|
||||
bool TextArea::TextArea::handleEvent(Ion::Events::Event event) {
|
||||
|
||||
Reference in New Issue
Block a user