mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-04-03 05:57:40 -05:00
Made code faster and cleaned some code.
This commit is contained in:
@@ -3,21 +3,18 @@
|
||||
#include <pl/core/token.hpp>
|
||||
#include <wolv/utils/string.hpp>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
#include <hex/api/content_registry/pattern_language.hpp>
|
||||
#include <pl/core/preprocessor.hpp>
|
||||
#include <pl/api.hpp>
|
||||
|
||||
namespace hex::ui {
|
||||
using namespace pl::core;
|
||||
using Interval = TextEditor::Interval;
|
||||
using Token = pl::core::Token;
|
||||
using Coordinates = TextEditor::Coordinates;
|
||||
using Interval = TextEditor::Interval;
|
||||
using Token = pl::core::Token;
|
||||
using Coordinates = TextEditor::Coordinates;
|
||||
using RangeFromCoordinates = TextEditor::RangeFromCoordinates;
|
||||
using CodeFoldState = TextEditor::CodeFoldState;
|
||||
|
||||
/*
|
||||
std::pair<i32, i32> TextEditor::convertIndexToLineNumbers(Interval interval) {
|
||||
if (m_tokens[interval.m_start].location.source->mainSource && m_tokens[interval.m_end].location.source->mainSource)
|
||||
return std::make_pair(m_tokens[interval.m_start].location.line, m_tokens[interval.m_end].location.line);
|
||||
return std::make_pair(0, 0);
|
||||
}
|
||||
*/
|
||||
void TextEditor::Lines::skipAttribute() {
|
||||
|
||||
if (sequence(tkn::Separator::LeftBracket, tkn::Separator::LeftBracket)) {
|
||||
@@ -26,52 +23,17 @@ namespace hex::ui {
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Interval> TextEditor::Lines::searchRangeForBlocks(Interval interval) {
|
||||
m_curr = m_startToken + interval.m_start;
|
||||
std::vector<Interval> result;
|
||||
|
||||
u32 nestedLevel = 0;
|
||||
std::vector<i32> tokenStack;
|
||||
while (m_curr != m_startToken + interval.m_end) {
|
||||
|
||||
if (sequence(tkn::Separator::LeftBrace)) {
|
||||
auto tokenId = getTokenId(m_curr[-1].location);
|
||||
tokenStack.push_back(tokenId);
|
||||
nestedLevel++;
|
||||
} else if (sequence(tkn::Separator::RightBrace)) {
|
||||
nestedLevel--;
|
||||
|
||||
if (tokenStack.empty())
|
||||
return result;
|
||||
Interval range(tokenStack.back(), getTokenId(m_curr[-1].location));
|
||||
tokenStack.pop_back();
|
||||
|
||||
result.push_back(range);
|
||||
|
||||
if (nestedLevel == 0) {
|
||||
skipAttribute();
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (peek(tkn::Separator::EndOfProgram))
|
||||
return result;
|
||||
else
|
||||
next();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Interval TextEditor::Lines::findBlockInRange(Interval interval) {
|
||||
Interval result = NotValid;
|
||||
auto tokenStart = TokenIter(m_tokens.begin(), m_tokens.end());
|
||||
auto tokenStart = SafeTokenIterator(m_tokens.begin(), m_tokens.end());
|
||||
|
||||
bool foundKey = false;
|
||||
bool foundComment = false;
|
||||
m_curr = tokenStart + interval.m_start;
|
||||
while (interval.m_end >= getTokenId(m_curr->location)) {
|
||||
while (interval.m_end >= getTokenId()) {
|
||||
if (peek(tkn::Separator::EndOfProgram))
|
||||
return NotValid;
|
||||
if (result.m_start = getTokenId(m_curr->location); result.m_start < 0)
|
||||
if (result.m_start = getTokenId(); result.m_start < 0)
|
||||
return NotValid;
|
||||
|
||||
while (true) {
|
||||
@@ -115,10 +77,10 @@ namespace hex::ui {
|
||||
break;
|
||||
}
|
||||
if (foundKey || foundComment) {
|
||||
auto currentId = getTokenId(m_curr->location);
|
||||
auto currentId = getTokenId();
|
||||
if (peek(tkn::Separator::EndOfProgram) || (currentId > 0 && currentId < (i32) m_tokens.size())) {
|
||||
next(-1);
|
||||
if (result.m_end = getTokenId(m_curr->location); result.m_end < 0)
|
||||
if (result.m_end = getTokenId(); result.m_end < 0)
|
||||
return NotValid;
|
||||
|
||||
return result;
|
||||
@@ -133,19 +95,19 @@ namespace hex::ui {
|
||||
Coordinates TextEditor::Lines::findCommentEndCoord(i32 tokenId) {
|
||||
Coordinates result = Invalid;
|
||||
auto save = m_curr;
|
||||
m_curr = TokenIter(m_tokens.begin(), m_tokens.end()) + tokenId;
|
||||
m_curr = SafeTokenIterator(m_tokens.begin(), m_tokens.end()) + tokenId;
|
||||
if (peek(tkn::Literal::Comment)) {
|
||||
auto comment = getValue<Token::Comment>(0);
|
||||
if (comment != nullptr) {
|
||||
auto location = m_curr->location;
|
||||
if (comment->singleLine)
|
||||
return Coordinates(location.line - 1, location.column + location.length - 2);
|
||||
return {(i32) (location.line - 1), (i32) (location.column + location.length - 2)};
|
||||
|
||||
std::string commentText = comment->comment;
|
||||
auto vectorString = wolv::util::splitString(commentText, "\n");
|
||||
size_t lineCount = vectorString.size();
|
||||
auto endColumn = (lineCount == 1) ? location.column + location.length - 1 : vectorString.back().length() + 1;
|
||||
return Coordinates(location.line + lineCount - 2, endColumn);
|
||||
return {(i32)(location.line + lineCount - 2), (i32)endColumn};
|
||||
}
|
||||
|
||||
} else if (peek(tkn::Literal::DocComment)) {
|
||||
@@ -153,57 +115,24 @@ namespace hex::ui {
|
||||
if (docComment != nullptr) {
|
||||
auto location = m_curr->location;
|
||||
if (docComment->singleLine)
|
||||
return Coordinates(location.line - 1, location.column + location.length - 2);
|
||||
return {(i32)(location.line - 1), (i32)(location.column + location.length - 2)};
|
||||
|
||||
std::string commentText = docComment->comment;
|
||||
auto vectorString = wolv::util::splitString(commentText, "\n");
|
||||
size_t lineCount = vectorString.size();
|
||||
auto endColumn = (lineCount == 1) ? location.column + location.length - 1 : vectorString.back().length() + 1;
|
||||
return Coordinates(location.line + lineCount - 2, endColumn);
|
||||
return {(i32)(location.line + lineCount - 2), (i32)endColumn};
|
||||
}
|
||||
}
|
||||
m_curr = save;
|
||||
return result;
|
||||
}
|
||||
|
||||
std::set<Interval> TextEditor::Lines::blocksFromGlobal() {
|
||||
std::set<Interval> result;
|
||||
if (m_globalBlocks.size() == 1)
|
||||
return m_globalBlocks;
|
||||
auto globalsIter = m_globalBlocks.begin();
|
||||
bool absorbPreviousToken = false;
|
||||
while (globalsIter != m_globalBlocks.end()) {
|
||||
if (absorbPreviousToken && globalsIter->m_start > 0) {
|
||||
result.insert(Interval(globalsIter->m_start - 1, globalsIter->m_end));
|
||||
absorbPreviousToken = false;
|
||||
} else if (globalsIter->m_start == globalsIter->m_end) {
|
||||
absorbPreviousToken = true;
|
||||
} else
|
||||
result.insert(*globalsIter);
|
||||
auto nextIter = std::next(globalsIter);
|
||||
|
||||
if (nextIter != m_globalBlocks.end() && absorbPreviousToken) {
|
||||
result.insert(Interval(globalsIter->m_end, nextIter->m_start - 1));
|
||||
absorbPreviousToken = false;
|
||||
} else if (nextIter != m_globalBlocks.end() && globalsIter->m_end + 1 < nextIter->m_start - 1)
|
||||
result.insert(Interval(globalsIter->m_end + 1, nextIter->m_start - 1));
|
||||
else if (nextIter != m_globalBlocks.end() && globalsIter->m_end + 1 == nextIter->m_start - 1)
|
||||
absorbPreviousToken = true;
|
||||
else if (globalsIter->m_end + 1 < (i32) m_tokens.size() - 1)
|
||||
result.insert(Interval(globalsIter->m_end + 1, (i32) m_tokens.size() - 1));
|
||||
|
||||
globalsIter++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//comments imports and includes
|
||||
void TextEditor::Lines::nonDelimitedFolds() {
|
||||
//auto allBlocks = blocksFromGlobal();
|
||||
auto size = m_tokens.size();
|
||||
if (size > 0) {
|
||||
Interval block = {0,static_cast<i32>(size-1)};
|
||||
//for (auto block: allBlocks) {
|
||||
while (true) {
|
||||
auto interval = findBlockInRange(block);
|
||||
|
||||
@@ -227,10 +156,10 @@ namespace hex::ui {
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<Coordinates, Coordinates> TextEditor::Lines::getDelimiterLineNumbers(i32 start, i32 end, const std::string &delimiters) {
|
||||
std::pair<Coordinates, Coordinates> result = {Invalid, Invalid};
|
||||
RangeFromCoordinates TextEditor::Lines::getDelimiterLineNumbers(i32 start, i32 end, const std::string &delimiters) {
|
||||
RangeFromCoordinates result = {Invalid, Invalid};
|
||||
Coordinates first = Invalid;
|
||||
auto tokenStart = TokenIter(m_tokens.begin(), m_tokens.end());
|
||||
auto tokenStart = SafeTokenIterator(m_tokens.begin(), m_tokens.end());
|
||||
m_curr = tokenStart + start;
|
||||
Token::Separator openSeparator = Token::Separator::EndOfProgram;
|
||||
Token::Separator closeSeparator = Token::Separator::EndOfProgram;
|
||||
@@ -261,7 +190,7 @@ namespace hex::ui {
|
||||
Location location2;
|
||||
auto save = m_curr;
|
||||
while (peek(tkn::Literal::Comment, -1) || peek(tkn::Literal::DocComment, -1)) {
|
||||
if (getTokenId(m_curr->location) == 0)
|
||||
if (getTokenId() == 0)
|
||||
break;
|
||||
next(-1);
|
||||
}
|
||||
@@ -305,26 +234,43 @@ namespace hex::ui {
|
||||
}
|
||||
|
||||
void TextEditor::Lines::advanceToNextLine(i32 &lineIndex, i32 ¤tTokenId, Location &location) {
|
||||
if (lineIndex = nextLine(lineIndex); lineIndex >= size())
|
||||
i32 tempLineIndex;
|
||||
if (tempLineIndex = nextLine(lineIndex); lineIndex == tempLineIndex) {
|
||||
lineIndex++;
|
||||
currentTokenId = -1;
|
||||
location = Location::Empty();
|
||||
return;
|
||||
}
|
||||
lineIndex = tempLineIndex;
|
||||
currentTokenId = m_firstTokenIdOfLine[lineIndex];
|
||||
m_curr = m_startToken + currentTokenId;
|
||||
location = m_curr->location;
|
||||
}
|
||||
|
||||
void TextEditor::Lines::advanceTokenId(i32 &lineIndex, i32 ¤tTokenId, Location &location) {
|
||||
void TextEditor::Lines::incrementTokenId(i32 &lineIndex, i32 ¤tTokenId, Location &location) {
|
||||
currentTokenId++;
|
||||
m_curr = m_startToken + currentTokenId;
|
||||
location = m_curr->location;
|
||||
lineIndex = location.line - 1;
|
||||
}
|
||||
|
||||
void TextEditor::Lines::moveToLocationColumn(i32 locationColumn, i32 ¤tTokenId, Location &location) {
|
||||
location.column = locationColumn;
|
||||
location.length = 1;
|
||||
if (currentTokenId = getTokenId(location); currentTokenId < 0)
|
||||
void TextEditor::Lines::moveToStringIndex(i32 stringIndex, i32 ¤tTokenId, Location &location) {
|
||||
auto curr = m_curr;
|
||||
i32 tempTokenId;
|
||||
auto &line = operator[](location.line - 1);
|
||||
while (stringIndex > line.columnIndex(m_curr->location.column) + (i32) m_curr->location.length && m_curr->location.line == location.line)
|
||||
next();
|
||||
if (peek(tkn::Separator::EndOfProgram))
|
||||
return;
|
||||
m_curr = m_startToken + currentTokenId;
|
||||
|
||||
if (tempTokenId = getTokenId(); tempTokenId < 0) {
|
||||
m_curr = curr;
|
||||
location = curr->location;
|
||||
} else {
|
||||
location = m_curr->location;
|
||||
currentTokenId = tempTokenId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void TextEditor::Lines::resetToTokenId(i32 &lineIndex, i32 ¤tTokenId, Location &location) {
|
||||
@@ -333,47 +279,55 @@ namespace hex::ui {
|
||||
lineIndex = location.line - 1;
|
||||
}
|
||||
|
||||
i32 TextEditor::Lines::findNextDelimiter(bool openOnly) {
|
||||
while (!peek(tkn::Separator::EndOfProgram)) {
|
||||
|
||||
if (peek(tkn::Separator::LeftBrace) || peek(tkn::Separator::LeftBracket) || peek(tkn::Separator::LeftParenthesis) || peek(tkn::Operator::BoolLessThan))
|
||||
return getTokenId();
|
||||
if (!openOnly) {
|
||||
if (peek(tkn::Separator::RightBrace) || peek(tkn::Separator::RightBracket) || peek(tkn::Separator::RightParenthesis) || peek(tkn::Operator::BoolGreaterThan))
|
||||
return getTokenId();
|
||||
}
|
||||
next();
|
||||
}
|
||||
return getTokenId();
|
||||
}
|
||||
|
||||
TextEditor::CodeFoldBlocks TextEditor::Lines::foldPointsFromSource() {
|
||||
auto code = getText();
|
||||
if (code.empty())
|
||||
return m_foldPoints;
|
||||
std::unique_ptr<pl::PatternLanguage> runtime = std::make_unique<pl::PatternLanguage>();
|
||||
ContentRegistry::PatternLanguage::configureRuntime(*runtime, nullptr);
|
||||
std::ignore = runtime->preprocessString(code, pl::api::Source::DefaultSource);
|
||||
m_tokens = runtime->getInternals().preprocessor->getResult();
|
||||
const u32 tokenCount = m_tokens.size();
|
||||
if (tokenCount == 0)
|
||||
return m_foldPoints;
|
||||
loadFirstTokenIdOfLine();
|
||||
if (m_firstTokenIdOfLine.empty())
|
||||
return m_foldPoints;
|
||||
m_foldPoints.clear();
|
||||
nonDelimitedFolds();
|
||||
std::string blockDelimiters = "{[(<";
|
||||
std::string openDelimiters = "{[(<";
|
||||
size_t topLine = 0;
|
||||
i32 bottomLine = size();
|
||||
m_startToken = TokenIter(m_tokens.begin(), m_tokens.end());
|
||||
m_startToken = SafeTokenIterator(m_tokens.begin(), m_tokens.end());
|
||||
m_curr = m_startToken;
|
||||
auto location = m_curr->location;
|
||||
i32 lineIndex = topLine;
|
||||
i32 currentTokenId = 0;
|
||||
while (lineIndex < bottomLine) {
|
||||
auto line = operator[](lineIndex);
|
||||
if (line.empty()) {
|
||||
advanceToNextLine(lineIndex, currentTokenId, location);
|
||||
if (lineIndex >= bottomLine) {
|
||||
return m_foldPoints;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
while (currentTokenId < (i32) tokenCount) {
|
||||
|
||||
if (size_t columnIndex = line.m_chars.find_first_of(blockDelimiters, location.column - 1); columnIndex != std::string::npos) {
|
||||
std::string openDelimiter = std::string(1, line[columnIndex]);
|
||||
moveToLocationColumn(columnIndex + 1, currentTokenId, location);
|
||||
if (currentTokenId = findNextDelimiter(true); !peek(tkn::Separator::EndOfProgram)) {
|
||||
if (currentTokenId < 0) {
|
||||
return m_foldPoints;
|
||||
}
|
||||
auto line = operator[](m_curr->location.line - 1);
|
||||
size_t stringIndex = line.columnIndex(m_curr->location.column);
|
||||
std::string openDelimiter = std::string(1, line[stringIndex - 1]);
|
||||
location = m_curr->location;
|
||||
|
||||
if (m_curr[0].getFormattedType() != "Operator" && m_curr[0].getFormattedType() != "Separator") {
|
||||
if (currentTokenId >= (i32) m_tokens.size()) {
|
||||
return m_foldPoints;
|
||||
}
|
||||
advanceTokenId(lineIndex, currentTokenId, location);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto idx = blockDelimiters.find(openDelimiter); idx != std::string::npos) {
|
||||
if (auto idx = openDelimiters.find(openDelimiter); idx != std::string::npos) {
|
||||
if (idx == 3) {
|
||||
if (currentTokenId == 0) {
|
||||
return m_foldPoints;
|
||||
@@ -386,7 +340,7 @@ namespace hex::ui {
|
||||
return m_foldPoints;
|
||||
}
|
||||
|
||||
if (currentTokenId = getTokenId(m_curr->location); currentTokenId < 0) {
|
||||
if (currentTokenId = getTokenId(); currentTokenId < 0) {
|
||||
return m_foldPoints;
|
||||
}
|
||||
resetToTokenId(lineIndex, currentTokenId, location);
|
||||
@@ -404,18 +358,15 @@ namespace hex::ui {
|
||||
if (lineBased.first.getLine() != lineBased.second.getLine())
|
||||
m_foldPoints[lineBased.first] = lineBased.second;
|
||||
|
||||
if (currentTokenId = getTokenId(m_tokens[end.first].location); currentTokenId < 0 || currentTokenId >= (i32) m_tokens.size()) {
|
||||
if (currentTokenId = getTokenId(m_startToken + end.first); currentTokenId < 0 || currentTokenId >= (i32) m_tokens.size()) {
|
||||
return m_foldPoints;
|
||||
}
|
||||
advanceTokenId(lineIndex, currentTokenId, location);
|
||||
incrementTokenId(lineIndex, currentTokenId, location);
|
||||
} else {
|
||||
return m_foldPoints;
|
||||
}
|
||||
} else {
|
||||
advanceToNextLine(lineIndex, currentTokenId, location);
|
||||
if (lineIndex >= bottomLine) {
|
||||
return m_foldPoints;
|
||||
}
|
||||
return m_foldPoints;
|
||||
}
|
||||
}
|
||||
return m_foldPoints;
|
||||
@@ -425,8 +376,9 @@ namespace hex::ui {
|
||||
std::pair<i32, char> TextEditor::Lines::findMatchingDelimiter(i32 from) {
|
||||
std::string blockDelimiters = "{}[]()<>";
|
||||
std::pair<i32, char> result = std::make_pair(-1, '\0');
|
||||
auto tokenStart = TokenIter(m_tokens.begin(), m_tokens.end());
|
||||
if (from >= (i32) m_tokens.size())
|
||||
auto tokenStart = SafeTokenIterator(m_tokens.begin(), m_tokens.end());
|
||||
const i32 tokenCount = m_tokens.size();
|
||||
if (from >= tokenCount)
|
||||
return result;
|
||||
m_curr = tokenStart + from;
|
||||
Location location = m_curr->location;
|
||||
@@ -445,44 +397,19 @@ namespace hex::ui {
|
||||
return result;
|
||||
m_curr = tokenStart + currentTokenId;
|
||||
location = m_curr->location;
|
||||
size_t lineIndex = location.line - 1;
|
||||
size_t bottomLine = size();
|
||||
while (lineIndex < bottomLine) {
|
||||
line = operator[](lineIndex);
|
||||
if (line.empty()) {
|
||||
i32 lineIndex = location.line - 1;
|
||||
while (currentTokenId < tokenCount) {
|
||||
|
||||
if (lineIndex = nextLine(lineIndex); lineIndex >= bottomLine)
|
||||
if (currentTokenId = findNextDelimiter(false); !peek(tkn::Separator::EndOfProgram)) {
|
||||
if (currentTokenId < 0) {
|
||||
return result;
|
||||
currentTokenId = m_firstTokenIdOfLine[lineIndex];
|
||||
m_curr = tokenStart + currentTokenId;
|
||||
location = m_curr->location;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto columnIndex = line.m_chars.find_first_of(blockDelimiters, location.column - 1); columnIndex != std::string::npos) {
|
||||
std::string currentChar = std::string(1, line[columnIndex]);
|
||||
location.column = columnIndex + 1;
|
||||
location.length = 1;
|
||||
|
||||
if (currentTokenId = getTokenId(location); currentTokenId < 0)
|
||||
return result;
|
||||
m_curr = tokenStart + currentTokenId;
|
||||
if (m_curr[0].getFormattedType() != "Operator" && m_curr[0].getFormattedType() != "Separator") {
|
||||
|
||||
if (currentTokenId >= (i32) m_tokens.size())
|
||||
return result;
|
||||
currentTokenId++;
|
||||
m_curr = tokenStart + currentTokenId;
|
||||
location = m_curr->location;
|
||||
lineIndex = location.line - 1;
|
||||
continue;
|
||||
}
|
||||
line = operator[](m_curr->location.line - 1);
|
||||
std::string currentChar = std::string(1, line[(u64)(m_curr->location.column - 1)]);
|
||||
location = m_curr->location;
|
||||
|
||||
if (auto idx = blockDelimiters.find(currentChar); idx != std::string::npos) {
|
||||
if (currentChar == closeDelimiter) {
|
||||
|
||||
if (currentTokenId = getTokenId(location); currentTokenId < 0)
|
||||
return result;
|
||||
return std::make_pair(currentTokenId, closeDelimiter[0]);
|
||||
} else {
|
||||
if (idx == 6 || idx == 7) {
|
||||
@@ -494,11 +421,10 @@ namespace hex::ui {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (currentTokenId = getTokenId(m_curr->location); currentTokenId < 0)
|
||||
if (currentTokenId = getTokenId(); currentTokenId < 0)
|
||||
return result;
|
||||
m_curr = tokenStart + currentTokenId;
|
||||
location = m_curr->location;
|
||||
lineIndex = location.line - 1;
|
||||
|
||||
resetToTokenId(lineIndex, currentTokenId, location);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -512,13 +438,10 @@ namespace hex::ui {
|
||||
if (lineBased.first.getLine() != lineBased.second.getLine())
|
||||
m_foldPoints[lineBased.first] = lineBased.second;
|
||||
|
||||
if (currentTokenId = getTokenId(m_tokens[end.first].location); currentTokenId < 0 || currentTokenId >= (i32) m_tokens.size())
|
||||
if (currentTokenId = getTokenId(tokenStart + end.first); currentTokenId < 0 || currentTokenId >= (i32) m_tokens.size())
|
||||
return result;
|
||||
|
||||
currentTokenId++;
|
||||
m_curr = tokenStart + currentTokenId;
|
||||
location = m_curr->location;
|
||||
lineIndex = location.line - 1;
|
||||
incrementTokenId(lineIndex, currentTokenId, location);
|
||||
} else
|
||||
return result;
|
||||
}
|
||||
@@ -526,23 +449,19 @@ namespace hex::ui {
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
|
||||
if (lineIndex = nextLine(lineIndex); lineIndex >= bottomLine)
|
||||
return result;
|
||||
currentTokenId = m_firstTokenIdOfLine[lineIndex];
|
||||
m_curr = tokenStart + currentTokenId;
|
||||
location = m_curr->location;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void TextEditor::saveCodeFoldStates() {
|
||||
m_lines.saveCodeFoldStates();
|
||||
}
|
||||
|
||||
void TextEditor::Lines::saveCodeFoldStates() {
|
||||
i32 codeFoldIndex = 0;
|
||||
std::vector<i32> closedFoldIncrements;
|
||||
Indices closedFoldIncrements;
|
||||
for (auto key: m_codeFoldKeys) {
|
||||
if (m_codeFoldState.contains(key) && !m_codeFoldState[key]) {
|
||||
closedFoldIncrements.push_back(codeFoldIndex);
|
||||
@@ -550,6 +469,10 @@ namespace hex::ui {
|
||||
} else
|
||||
codeFoldIndex++;
|
||||
}
|
||||
if (!m_hiddenLines.empty())
|
||||
m_hiddenLines.clear();
|
||||
if (closedFoldIncrements.empty())
|
||||
return;
|
||||
std::string result = "//+-#:";
|
||||
for (u32 i = 0; i < closedFoldIncrements.size(); ++i) {
|
||||
result += std::to_string(closedFoldIncrements[i]);
|
||||
@@ -557,37 +480,49 @@ namespace hex::ui {
|
||||
result += ",";
|
||||
}
|
||||
auto lineIndex = 0;
|
||||
HiddenLine hiddenLine(lineIndex, result);
|
||||
if (!m_hiddenLines.empty()) {
|
||||
m_hiddenLines[0] = hiddenLine;
|
||||
return;
|
||||
}
|
||||
m_hiddenLines.push_back(hiddenLine);
|
||||
m_hiddenLines.emplace_back(lineIndex, result);
|
||||
}
|
||||
|
||||
void TextEditor::applyCodeFoldStates() {
|
||||
m_lines.applyCodeFoldStates();
|
||||
}
|
||||
|
||||
void TextEditor::Lines::setCodeFoldState(CodeFoldState state) {
|
||||
m_codeFoldState = state;
|
||||
}
|
||||
|
||||
CodeFoldState TextEditor::Lines::getCodeFoldState() const {
|
||||
return m_codeFoldState;
|
||||
}
|
||||
|
||||
void TextEditor::Lines::applyCodeFoldStates() {
|
||||
|
||||
std::string commentLine;
|
||||
for (auto line: m_hiddenLines) {
|
||||
for (const auto& line: m_hiddenLines) {
|
||||
if (line.m_line.starts_with("//+-#:")) {
|
||||
commentLine = line.m_line;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (commentLine.size() < 6 || !commentLine.starts_with("//+-#:"))
|
||||
if (commentLine.size() < 6 || !commentLine.starts_with("//+-#:")) {
|
||||
for (auto key: m_codeFoldKeys)
|
||||
m_codeFoldState[key] = true;
|
||||
return;
|
||||
}
|
||||
auto states = commentLine.substr(6);
|
||||
auto stringVector = wolv::util::splitString(states, ",", true);
|
||||
auto count = stringVector.size();
|
||||
i32 count;
|
||||
StringVector stringVector;
|
||||
if (states.empty())
|
||||
count = 0;
|
||||
else {
|
||||
stringVector = wolv::util::splitString(states, ",", true);
|
||||
count = stringVector.size();
|
||||
}
|
||||
if (count == 1 && stringVector[0].empty())
|
||||
return;
|
||||
std::vector<i32> closedFoldIncrements(count);
|
||||
Indices closedFoldIncrements(count);
|
||||
i32 value = 0;
|
||||
for (u32 i = 0; i < count; ++i) {
|
||||
for (i32 i = 0; i < count; ++i) {
|
||||
auto stateStr = stringVector[i];
|
||||
std::from_chars(stateStr.data(), stateStr.data() + stateStr.size(), value);
|
||||
closedFoldIncrements[i] = value;
|
||||
@@ -607,8 +542,9 @@ namespace hex::ui {
|
||||
void TextEditor::Lines::closeCodeFold(const Range &key, bool userTriggered) {
|
||||
float topRow;
|
||||
|
||||
if (userTriggered)
|
||||
if (userTriggered) {
|
||||
topRow = m_topRow;
|
||||
}
|
||||
LineIndexToScreen lineIndexToScreen;
|
||||
bool needsDelimiter = lineNeedsDelimiter(key.m_start.m_line);
|
||||
auto lineIter = m_lineIndexToScreen.begin();
|
||||
@@ -712,7 +648,7 @@ namespace hex::ui {
|
||||
m_foldedLines[newFoldedLine.m_row] = newFoldedLine;
|
||||
currentFoldedLine = m_foldedLines[newFoldedLine.m_row];
|
||||
}
|
||||
std::map<i32, FoldedLine> updatedFoldedLines;
|
||||
FoldedLines updatedFoldedLines;
|
||||
for (auto &[row, foldedLine] : m_foldedLines) {
|
||||
if (row > currentFoldedLine.m_row) {
|
||||
foldedLine.m_row -= (key.m_end.m_line - key.m_start.m_line);
|
||||
@@ -730,12 +666,13 @@ namespace hex::ui {
|
||||
m_topRow = topRow;
|
||||
m_setTopRow = true;
|
||||
m_saveCodeFoldStateRequested = true;
|
||||
m_globalRowMaxChanged = true;
|
||||
}
|
||||
m_foldedLines[currentFoldedLine.m_row].loadSegments();
|
||||
}
|
||||
|
||||
void TextEditor::Lines::openCodeFold(const Range &key) {
|
||||
for (auto foldedLine : m_foldedLines) {
|
||||
for (const auto& foldedLine : m_foldedLines) {
|
||||
for (auto foldKey : foldedLine.second.m_keys) {
|
||||
if (foldKey.contains(key) && foldKey != key) {
|
||||
m_codeFoldState[key] = true;
|
||||
@@ -778,7 +715,7 @@ namespace hex::ui {
|
||||
}
|
||||
}
|
||||
if (erasedRow != -1) {
|
||||
std::map<i32, FoldedLine> updatedFoldedLines;
|
||||
FoldedLines updatedFoldedLines;
|
||||
for (auto &[row, foldedLine] : m_foldedLines) {
|
||||
if (row > erasedRow) {
|
||||
foldedLine.m_row += (key.m_end.m_line - key.m_start.m_line);
|
||||
@@ -790,6 +727,7 @@ namespace hex::ui {
|
||||
m_foldedLines = std::move(updatedFoldedLines);
|
||||
}
|
||||
m_saveCodeFoldStateRequested = true;
|
||||
m_globalRowMaxChanged = true;
|
||||
}
|
||||
|
||||
void TextEditor::openCodeFoldAt(Coordinates line) {
|
||||
@@ -814,7 +752,7 @@ namespace hex::ui {
|
||||
}
|
||||
if (count == 0)
|
||||
return;
|
||||
i32 id = getTokenId(m_curr->location);
|
||||
i32 id = getTokenId();
|
||||
|
||||
if (count > 0)
|
||||
m_curr += std::min(count,static_cast<i32>(m_tokens.size() - id));
|
||||
@@ -904,15 +842,13 @@ namespace hex::ui {
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
if (!isLocationValid(token.location))
|
||||
return false;
|
||||
return true;
|
||||
return isLocationValid(token.location);
|
||||
}
|
||||
|
||||
bool TextEditor::Lines::peek(const Token &token, const i32 index) {
|
||||
if (!isValid())
|
||||
return false;
|
||||
i32 id = getTokenId(m_curr->location);
|
||||
i32 id = getTokenId();
|
||||
if (id+index < 0 || id+index >= (i32)m_tokens.size())
|
||||
return false;
|
||||
return m_curr[index].type == token.type && m_curr[index] == token.value;
|
||||
|
||||
@@ -3,21 +3,23 @@
|
||||
#include <string>
|
||||
#include <regex>
|
||||
#include <cmath>
|
||||
#include <utility>
|
||||
#include <wolv/utils/string.hpp>
|
||||
#include <popups/popup_question.hpp>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
#include "imgui.h"
|
||||
|
||||
namespace hex::ui {
|
||||
using StringVector = TextEditor::StringVector;
|
||||
using Range = TextEditor::Range;
|
||||
using EditorState = TextEditor::EditorState;
|
||||
|
||||
|
||||
TextEditor::FindReplaceHandler::FindReplaceHandler() : m_matchCase(false), m_wholeWord(false), m_findRegEx(false) {}
|
||||
TextEditor::FindReplaceHandler::FindReplaceHandler() : m_matchCase(false), m_wholeWord(false), m_findRegEx(false), m_optionsChanged(false) {}
|
||||
|
||||
TextEditor::TextEditor() {
|
||||
m_lines.m_startTime = ImGui::GetTime() * 1000;
|
||||
m_lines.setLanguageDefinition(LanguageDefinition::HLSL());
|
||||
m_lines.m_unfoldedLines.push_back(Line());
|
||||
m_lines.m_unfoldedLines.emplace_back();
|
||||
m_lineSpacing = 1.0f;
|
||||
m_tabSize = 4;
|
||||
|
||||
@@ -25,8 +27,7 @@ namespace hex::ui {
|
||||
m_lines.m_state.m_selection.m_start = m_lines.m_state.m_selection.m_end = lineCoordinates( 0, 0);
|
||||
}
|
||||
|
||||
TextEditor::~TextEditor() {
|
||||
}
|
||||
TextEditor::~TextEditor() = default;
|
||||
|
||||
std::string TextEditor::Lines::getRange(const Range &rangeToGet) {
|
||||
std::string result;
|
||||
@@ -38,7 +39,7 @@ namespace hex::ui {
|
||||
result = m_unfoldedLines[selection.m_start.m_line].substr(columns.m_line, columns.m_column, Line::LinePart::Utf8);
|
||||
} else {
|
||||
auto lines = selection.getSelectedLines();
|
||||
std::vector<std::string> lineContents;
|
||||
StringVector lineContents;
|
||||
lineContents.push_back(m_unfoldedLines[lines.m_line].substr(columns.m_line, (u64) -1, Line::LinePart::Utf8));
|
||||
for (i32 i = lines.m_line + 1; i < lines.m_column; i++) {
|
||||
lineContents.push_back(m_unfoldedLines[i].m_chars);
|
||||
@@ -70,8 +71,8 @@ namespace hex::ui {
|
||||
firstLine.insert(firstLine.end(), lastLine.begin(), lastLine.end());
|
||||
firstLine.m_colorized = false;
|
||||
}
|
||||
if (lines.m_line+1 < lines.m_column)
|
||||
removeLines(lines.m_line+1,lines.m_column);
|
||||
if (lines.m_line + 1 < lines.m_column)
|
||||
removeLines(lines.m_line + 1, lines.m_column);
|
||||
else
|
||||
removeLine(lines.m_column);
|
||||
}
|
||||
@@ -88,7 +89,7 @@ namespace hex::ui {
|
||||
m_unfoldedLines[0].m_colors = std::string(text.size(), 0);
|
||||
m_unfoldedLines[0].m_flags = std::string(text.size(), 0);
|
||||
} else {
|
||||
m_unfoldedLines.push_back(Line(text));
|
||||
m_unfoldedLines.emplace_back(text);
|
||||
auto line = m_unfoldedLines.back();
|
||||
line.m_lineMaxColumn = line.maxColumn();
|
||||
}
|
||||
@@ -97,7 +98,7 @@ namespace hex::ui {
|
||||
|
||||
void TextEditor::appendLine(const std::string &value) {
|
||||
m_lines.appendLine(value);
|
||||
m_lines.setCursorPosition(m_lines.lineCoordinates((i32) m_lines.size() - 1, 0), false);
|
||||
m_lines.setCursorPosition(m_lines.lineCoordinates(m_lines.size() - 1, 0), false);
|
||||
m_lines.m_unfoldedLines.back().m_colorized = false;
|
||||
m_lines.ensureCursorVisible();
|
||||
m_lines.m_textChanged = true;
|
||||
@@ -147,7 +148,7 @@ namespace hex::ui {
|
||||
line.m_colorized = false;
|
||||
for (i32 i = 1; i < lineCount; i++) {
|
||||
insertLine(start.m_line + i, stringVector[i]);
|
||||
m_unfoldedLines[start.m_line + i].m_colorized =false;
|
||||
m_unfoldedLines[start.m_line + i].m_colorized = false;
|
||||
}
|
||||
m_textChanged = true;
|
||||
return lineCount;
|
||||
@@ -166,7 +167,6 @@ namespace hex::ui {
|
||||
}
|
||||
|
||||
void TextEditor::Lines::removeLines(i32 lineStart, i32 lineEnd) {
|
||||
|
||||
ErrorMarkers errorMarkers;
|
||||
for (auto &errorMarker : m_errorMarkers) {
|
||||
if (errorMarker.first.m_line <= lineStart || errorMarker.first.m_line > lineEnd + 1) {
|
||||
@@ -192,6 +192,7 @@ namespace hex::ui {
|
||||
breakpoints.insert(breakpoint);
|
||||
}
|
||||
}
|
||||
|
||||
m_breakpoints = std::move(breakpoints);
|
||||
|
||||
CodeFoldKeys folds;
|
||||
@@ -224,14 +225,15 @@ namespace hex::ui {
|
||||
}
|
||||
|
||||
// use clamp to ensure valid results instead of assert.
|
||||
auto start = std::clamp(lineStart, 0, (i32) size() - 1);
|
||||
auto end = std::clamp(lineEnd, 0, (i32) size());
|
||||
auto start = std::clamp(lineStart, 0, size() - 1);
|
||||
auto end = std::clamp(lineEnd, 0, size());
|
||||
if (start > end)
|
||||
std::swap(start, end);
|
||||
|
||||
m_unfoldedLines.erase(m_unfoldedLines.begin() + lineStart, m_unfoldedLines.begin() + lineEnd + 1);
|
||||
|
||||
m_textChanged = true;
|
||||
m_globalRowMaxChanged = true;
|
||||
}
|
||||
|
||||
void TextEditor::Lines::removeLine(i32 index) {
|
||||
@@ -239,7 +241,7 @@ namespace hex::ui {
|
||||
}
|
||||
|
||||
void TextEditor::Lines::insertLine(i32 index, const std::string &text) {
|
||||
if (index < 0 || index > (i32) size())
|
||||
if (index < 0 || index > size())
|
||||
return;
|
||||
auto &line = insertLine(index);
|
||||
line.append(text);
|
||||
@@ -248,14 +250,15 @@ namespace hex::ui {
|
||||
}
|
||||
|
||||
TextEditor::Line &TextEditor::Lines::insertLine(i32 index) {
|
||||
|
||||
m_globalRowMaxChanged = true;
|
||||
if (isEmpty())
|
||||
return *m_unfoldedLines.insert(m_unfoldedLines.begin(), Line());
|
||||
|
||||
if (index == (i32)size())
|
||||
if (index == size())
|
||||
return *m_unfoldedLines.insert(m_unfoldedLines.end(), Line());
|
||||
|
||||
TextEditor::Line &result = *m_unfoldedLines.insert(m_unfoldedLines.begin() + index, Line());
|
||||
|
||||
result.m_colorized = false;
|
||||
|
||||
ErrorMarkers errorMarkers;
|
||||
@@ -309,11 +312,10 @@ namespace hex::ui {
|
||||
}
|
||||
|
||||
void TextEditor::setText(const std::string &text, bool undo) {
|
||||
|
||||
UndoRecord u;
|
||||
if (!m_lines.m_readOnly && undo) {
|
||||
u.m_before = m_lines.m_state;
|
||||
u.m_removed = m_lines.getText(false);
|
||||
u.m_removed = m_lines.getText();
|
||||
u.m_removedRange.m_start = m_lines.lineCoordinates(0, 0);
|
||||
u.m_removedRange.m_end = m_lines.lineCoordinates(-1, -1);
|
||||
if (u.m_removedRange.m_start == Invalid || u.m_removedRange.m_end == Invalid)
|
||||
@@ -328,7 +330,7 @@ namespace hex::ui {
|
||||
m_lines.m_hiddenLines.clear();
|
||||
u64 i = 0;
|
||||
while (vectorString[i].starts_with("//+-")) {
|
||||
m_lines.m_hiddenLines.push_back(HiddenLine(i, vectorString[i])), i++;
|
||||
m_lines.m_hiddenLines.emplace_back(i, vectorString[i]), i++;
|
||||
}
|
||||
vectorString.erase(vectorString.begin(), vectorString.begin() + i);
|
||||
lineCount = vectorString.size();
|
||||
@@ -336,7 +338,7 @@ namespace hex::ui {
|
||||
m_lines.m_unfoldedLines.clear();
|
||||
m_lines.m_unfoldedLines.resize(lineCount);
|
||||
|
||||
for (auto line: vectorString) {
|
||||
for (const auto &line: vectorString) {
|
||||
auto &unfoldedLine = m_lines.m_unfoldedLines[i];
|
||||
|
||||
unfoldedLine.setLine(line);
|
||||
@@ -355,31 +357,29 @@ namespace hex::ui {
|
||||
m_lines.m_textChanged = true;
|
||||
if (!m_lines.m_readOnly && undo) {
|
||||
u.m_after = m_lines.m_state;
|
||||
std::vector<UndoRecord> v;
|
||||
UndoRecords v;
|
||||
v.push_back(u);
|
||||
m_lines.addUndo(v);
|
||||
}
|
||||
m_lines.setAllCodeFolds();
|
||||
applyCodeFoldStates();
|
||||
m_lines.m_useSavedFoldStatesRequested = true;
|
||||
m_lines.colorize();
|
||||
}
|
||||
|
||||
void TextEditor::enterCharacter(ImWchar character, bool shift) {
|
||||
|
||||
if (m_lines.m_readOnly)
|
||||
return;
|
||||
auto row = lineIndexToRow(m_lines.m_state.m_cursorPosition.m_line);
|
||||
if (m_lines.m_foldedLines.contains(row)) {
|
||||
auto foldedLine = m_lines.m_foldedLines[row];
|
||||
auto foldedCoords = m_lines.unfoldedToFoldedCoords(m_lines.m_state.m_cursorPosition);
|
||||
if (foldedLine.m_foldedLine.m_chars[foldedCoords.m_column] == '.') {
|
||||
auto keyCount = foldedLine.m_keys.size();
|
||||
for (u32 i = 0; i < keyCount; i++) {
|
||||
if (foldedCoords.m_column >= foldedLine.m_ellipsisIndices[i] &&
|
||||
foldedCoords.m_column <= foldedLine.m_ellipsisIndices[i] + 3) {
|
||||
m_lines.openCodeFold(m_lines.m_foldedLines[row].m_keys[i]);
|
||||
return;
|
||||
if (!m_lines.m_codeFoldsDisabled) {
|
||||
auto row = lineIndexToRow(m_lines.m_state.m_cursorPosition.m_line);
|
||||
if (m_lines.m_foldedLines.contains(row)) {
|
||||
auto foldedLine = m_lines.m_foldedLines[row];
|
||||
auto foldedCoords = m_lines.unfoldedToFoldedCoords(m_lines.m_state.m_cursorPosition);
|
||||
if (foldedLine.m_foldedLine.m_chars[foldedCoords.m_column] == '.') {
|
||||
auto keyCount = foldedLine.m_keys.size();
|
||||
for (u32 i = 0; i < keyCount; i++) {
|
||||
if (foldedCoords.m_column >= foldedLine.m_ellipsisIndices[i] &&
|
||||
foldedCoords.m_column <= foldedLine.m_ellipsisIndices[i] + 3) {
|
||||
m_lines.openCodeFold(m_lines.m_foldedLines[row].m_keys[i]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -454,7 +454,7 @@ namespace hex::ui {
|
||||
u.m_after = m_lines.m_state;
|
||||
|
||||
m_lines.m_state.m_selection = Range(start, end);
|
||||
std::vector<UndoRecord> v;
|
||||
UndoRecords v;
|
||||
v.push_back(u);
|
||||
m_lines.addUndo(v);
|
||||
|
||||
@@ -476,19 +476,16 @@ namespace hex::ui {
|
||||
u.m_addedRange.m_start = coord;
|
||||
|
||||
if (m_lines.m_unfoldedLines.empty())
|
||||
m_lines.m_unfoldedLines.push_back(Line());
|
||||
m_lines.m_unfoldedLines.emplace_back();
|
||||
|
||||
if (character == '\n') {
|
||||
m_lines.insertLine(coord.m_line + 1);
|
||||
auto &line = m_lines.m_unfoldedLines[coord.m_line];
|
||||
auto &newLine = m_lines.m_unfoldedLines[coord.m_line + 1];
|
||||
|
||||
if (m_lines.m_languageDefinition.m_autoIndentation)
|
||||
newLine.append(std::string(m_lines.m_leadingLineSpaces[coord.m_line], ' '));
|
||||
|
||||
//if (m_languageDefinition.m_autoIndentation)
|
||||
// for (u64 it = 0; it < line.size() && isascii(line[it]) && isblank(line[it]); ++it)
|
||||
// newLine.push_back(line[it]);
|
||||
|
||||
const u64 whitespaceSize = newLine.size();
|
||||
i32 charStart;
|
||||
i32 charPosition;
|
||||
@@ -538,9 +535,9 @@ namespace hex::ui {
|
||||
}
|
||||
u.m_addedRange.m_end = m_lines.lineCoordinates(m_lines.m_state.m_cursorPosition);
|
||||
} else {
|
||||
std::string buf = "";
|
||||
std::string buf;
|
||||
imTextCharToUtf8(buf, character);
|
||||
if (buf.size() > 0) {
|
||||
if (!buf.empty()) {
|
||||
auto &line = m_lines.m_unfoldedLines[coord.m_line];
|
||||
auto charIndex = m_lines.lineCoordsIndex(coord);
|
||||
|
||||
@@ -597,7 +594,7 @@ namespace hex::ui {
|
||||
u.m_after = m_lines.m_state;
|
||||
m_lines.m_textChanged = true;
|
||||
|
||||
std::vector<UndoRecord> v;
|
||||
UndoRecords v;
|
||||
v.push_back(u);
|
||||
m_lines.addUndo(v);
|
||||
m_lines.colorize();
|
||||
@@ -659,7 +656,7 @@ namespace hex::ui {
|
||||
auto &line = m_lines.m_unfoldedLines[pos.m_line];
|
||||
|
||||
if (pos.m_column == line.maxColumn()) {
|
||||
if (pos.m_line == (i32) m_lines.size() - 1)
|
||||
if (pos.m_line == m_lines.size() - 1)
|
||||
return;
|
||||
|
||||
u.m_removed = '\n';
|
||||
@@ -688,7 +685,7 @@ namespace hex::ui {
|
||||
}
|
||||
|
||||
u.m_after = m_lines.m_state;
|
||||
std::vector<UndoRecord> v;
|
||||
UndoRecords v;
|
||||
v.push_back(u);
|
||||
m_lines.addUndo(v);
|
||||
m_lines.refreshSearchResults();
|
||||
@@ -773,7 +770,7 @@ namespace hex::ui {
|
||||
}
|
||||
|
||||
u.m_after = m_lines.m_state;
|
||||
std::vector<UndoRecord> v;
|
||||
UndoRecords v;
|
||||
v.push_back(u);
|
||||
m_lines.addUndo(v);
|
||||
m_lines.refreshSearchResults();
|
||||
@@ -786,7 +783,7 @@ namespace hex::ui {
|
||||
if (!m_lines.isEmpty()) {
|
||||
std::string str;
|
||||
const auto &line = m_lines.m_unfoldedLines[m_lines.lineCoordinates(m_lines.m_state.m_cursorPosition).m_line];
|
||||
std::copy(line.m_chars.begin(), line.m_chars.end(), std::back_inserter(str));
|
||||
std::ranges::copy(line.m_chars, std::back_inserter(str));
|
||||
ImGui::SetClipboardText(str.c_str());
|
||||
}
|
||||
}
|
||||
@@ -798,7 +795,7 @@ namespace hex::ui {
|
||||
} else {
|
||||
if (!m_lines.hasSelection()) {
|
||||
auto lineIndex = m_lines.lineCoordinates(m_lines.m_state.m_cursorPosition).m_line;
|
||||
if (lineIndex < 0 || lineIndex >= (i32) m_lines.size())
|
||||
if (lineIndex < 0 || lineIndex >= m_lines.size())
|
||||
return;
|
||||
setSelection(Range(m_lines.lineCoordinates(lineIndex, 0), m_lines.lineCoordinates(lineIndex + 1, 0)));
|
||||
}
|
||||
@@ -811,7 +808,7 @@ namespace hex::ui {
|
||||
m_lines.deleteSelection();
|
||||
|
||||
u.m_after = m_lines.m_state;
|
||||
std::vector<UndoRecord> v;
|
||||
UndoRecords v;
|
||||
v.push_back(u);
|
||||
m_lines.addUndo(v);
|
||||
}
|
||||
@@ -841,7 +838,7 @@ namespace hex::ui {
|
||||
m_lines.setCursorPosition(u.m_addedRange.m_end, false);
|
||||
setSelection(Range(u.m_addedRange.m_end, u.m_addedRange.m_end));
|
||||
u.m_after = m_lines.m_state;
|
||||
std::vector<UndoRecord> v;
|
||||
UndoRecords v;
|
||||
v.push_back(u);
|
||||
m_lines.addUndo(v);
|
||||
}
|
||||
@@ -855,7 +852,7 @@ namespace hex::ui {
|
||||
const char *clipText = ImGui::GetClipboardText();
|
||||
if (clipText != nullptr) {
|
||||
auto stringVector = wolv::util::splitString(clipText, "\n", false);
|
||||
if (std::any_of(stringVector.begin(), stringVector.end(), [](const std::string &s) { return s.size() > 1024; })) {
|
||||
if (std::ranges::any_of(stringVector, [](const std::string &s) { return s.size() > 1024; })) {
|
||||
ui::PopupQuestion::open("hex.builtin.view.pattern_editor.warning_paste_large"_lang, [this, clipText]() {
|
||||
this->doPaste(clipText);
|
||||
}, [] {});
|
||||
@@ -889,25 +886,18 @@ namespace hex::ui {
|
||||
m_lines.refreshSearchResults();
|
||||
}
|
||||
|
||||
std::string TextEditor::Lines::getText(bool includeHiddenLines) {
|
||||
std::string TextEditor::Lines::getText() {
|
||||
auto start = lineCoordinates(0, 0);
|
||||
auto size = m_unfoldedLines.size();
|
||||
auto line = m_unfoldedLines[size - 1];
|
||||
auto end = Coordinates( size - 1, line.m_lineMaxColumn);
|
||||
if (start == Invalid || end == Invalid)
|
||||
return "";
|
||||
std::string result;
|
||||
if (includeHiddenLines) {
|
||||
for (const auto &hiddenLine: m_hiddenLines) {
|
||||
result += hiddenLine.m_line + "\n";
|
||||
}
|
||||
}
|
||||
result += getRange(Range(start, end));
|
||||
return result;
|
||||
return getRange(Range(start, end));
|
||||
}
|
||||
|
||||
std::vector<std::string> TextEditor::getTextLines() const {
|
||||
std::vector<std::string> result;
|
||||
StringVector TextEditor::getTextLines() const {
|
||||
StringVector result;
|
||||
|
||||
result.reserve(m_lines.size());
|
||||
|
||||
@@ -933,11 +923,11 @@ namespace hex::ui {
|
||||
|
||||
TextEditor::UndoRecord::UndoRecord(
|
||||
std::string added,
|
||||
TextEditor::Range addedRange,
|
||||
Range addedRange,
|
||||
std::string removed,
|
||||
TextEditor::Range removedRange,
|
||||
TextEditor::EditorState &before,
|
||||
TextEditor::EditorState &after) : m_added(added), m_addedRange(addedRange), m_removed(removed), m_removedRange(removedRange), m_before(before), m_after(after) {}
|
||||
Range removedRange,
|
||||
EditorState before,
|
||||
EditorState after) : m_added(std::move(added)), m_addedRange(addedRange), m_removed(std::move(removed)), m_removedRange(removedRange), m_before(std::move(before)), m_after(std::move(after)) {}
|
||||
|
||||
void TextEditor::UndoRecord::undo(TextEditor *editor) {
|
||||
if (!m_added.empty()) {
|
||||
@@ -972,13 +962,13 @@ namespace hex::ui {
|
||||
}
|
||||
|
||||
void TextEditor::UndoAction::undo(TextEditor *editor) {
|
||||
for (i32 i = (i32) m_records.size() - 1; i >= 0; i--)
|
||||
m_records.at(i).undo(editor);
|
||||
for (auto &record : std::ranges::reverse_view(m_records))
|
||||
record.undo(editor);
|
||||
}
|
||||
|
||||
void TextEditor::UndoAction::redo(TextEditor *editor) {
|
||||
for (i32 i = 0; i < (i32) m_records.size(); i++)
|
||||
m_records.at(i).redo(editor);
|
||||
for (auto &record : m_records)
|
||||
record.redo(editor);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
namespace hex::ui {
|
||||
extern TextEditor::Palette s_paletteBase;
|
||||
|
||||
using Keys = TextEditor::Keys;
|
||||
|
||||
template<class InputIt1, class InputIt2, class BinaryPredicate>
|
||||
bool equals(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, BinaryPredicate p) {
|
||||
@@ -41,9 +41,9 @@ namespace hex::ui {
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<TextEditor::Range> TextEditor::Lines::getDeactivatedBlocks() {
|
||||
Keys TextEditor::Lines::getDeactivatedBlocks() {
|
||||
colorizeInternal();
|
||||
std::vector<Range> deactivatedBlocks;
|
||||
Keys deactivatedBlocks;
|
||||
if (isEmpty())
|
||||
return deactivatedBlocks;
|
||||
for (i32 i = 0; i < size(); ++i) {
|
||||
@@ -85,7 +85,6 @@ namespace hex::ui {
|
||||
if (isEmpty())
|
||||
return;
|
||||
|
||||
std::smatch results;
|
||||
std::string id;
|
||||
if (m_languageDefinition.m_tokenize == nullptr) {
|
||||
m_languageDefinition.m_tokenize = [](strConstIter, strConstIter, strConstIter &, strConstIter &, PaletteIndex &) { return false; };
|
||||
@@ -214,7 +213,7 @@ namespace hex::ui {
|
||||
auto withinString = false;
|
||||
auto withinBlockComment = false;
|
||||
auto withinNotDef = false;
|
||||
auto currentLine = endLine;
|
||||
i32 currentLine;
|
||||
auto commentLength = 0;
|
||||
auto matchedBracket = false;
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace hex::ui {
|
||||
|
||||
TextEditor::Coordinates TextEditor::Lines::rfind( const std::string &text, const Coordinates &from) {
|
||||
Coordinates result = Invalid;
|
||||
if (text.empty() || isEmpty() || from.m_line >= (i32) size() || from.m_line < 0)
|
||||
if (text.empty() || isEmpty() || from.m_line >= size() || from.m_line < 0)
|
||||
return result;
|
||||
for (i32 i = from.m_line; i >= 0; --i) {
|
||||
auto &line = m_unfoldedLines[i];
|
||||
@@ -48,9 +48,9 @@ namespace hex::ui {
|
||||
|
||||
TextEditor::Coordinates TextEditor::Lines::find(const std::string &text, const Coordinates &from) {
|
||||
Coordinates result = Invalid;
|
||||
if (text.empty() || isEmpty() || from.m_line >= (i32) size() || from.m_line < 0)
|
||||
if (text.empty() || isEmpty() || from.m_line >= size() || from.m_line < 0)
|
||||
return result;
|
||||
for (i32 i = from.m_line; i < (i32) size(); ++i) {
|
||||
for (i32 i = from.m_line; i < size(); ++i) {
|
||||
auto &line = m_unfoldedLines[i];
|
||||
auto index = line.m_chars.find(text, (i == from.m_line) ? from.m_column : 0);
|
||||
if (index != std::string::npos) {
|
||||
@@ -429,7 +429,6 @@ namespace hex::ui {
|
||||
m_setScroll = false;
|
||||
ImGui::SetScrollX(scroll.x);
|
||||
ImGui::SetScrollY(scroll.y);
|
||||
//m_updateFocus = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -461,9 +460,7 @@ namespace hex::ui {
|
||||
if (std::abs(m_line) > maxLine)
|
||||
return false;
|
||||
auto maxColumn = lines.lineMaxColumn(m_line);
|
||||
if (std::abs(m_column) > maxColumn)
|
||||
return false;
|
||||
return true;
|
||||
return std::abs(m_column) > maxColumn;
|
||||
}
|
||||
|
||||
TextEditor::Coordinates TextEditor::Coordinates::sanitize(Lines &lines) {
|
||||
@@ -492,7 +489,7 @@ namespace hex::ui {
|
||||
|
||||
TextEditor::Range::Coordinates TextEditor::Lines::lineCoordinates(i32 lineIndex, i32 column) {
|
||||
if (isEmpty())
|
||||
return Coordinates( 0, 0);
|
||||
return {0, 0};
|
||||
Coordinates result(lineIndex, column);
|
||||
|
||||
return result.sanitize(*this);
|
||||
@@ -516,11 +513,11 @@ namespace hex::ui {
|
||||
auto start = lineCoordinates(value.m_start);
|
||||
auto end = lineCoordinates(value.m_end);
|
||||
if (start == Invalid || end == Invalid)
|
||||
return Range(Invalid, Invalid);
|
||||
return {Invalid, Invalid};
|
||||
if (start > end) {
|
||||
std::swap(start, end);
|
||||
}
|
||||
return Range(start, end);
|
||||
return {start, end};
|
||||
}
|
||||
|
||||
void TextEditor::advance(Coordinates &coordinates) {
|
||||
@@ -542,7 +539,7 @@ namespace hex::ui {
|
||||
|
||||
TextEditor::Coordinates TextEditor::findWordStart(const Coordinates &from) {
|
||||
Coordinates at = m_lines.lineCoordinates(from);
|
||||
if (at.m_line >= (i32) m_lines.size())
|
||||
if (at.m_line >= m_lines.size())
|
||||
return at;
|
||||
|
||||
auto &line = m_lines.m_unfoldedLines[at.m_line];
|
||||
@@ -564,7 +561,7 @@ namespace hex::ui {
|
||||
|
||||
TextEditor::Coordinates TextEditor::findWordEnd(const Coordinates &from) {
|
||||
Coordinates at = m_lines.lineCoordinates(from);
|
||||
if (at.m_line >= (i32) m_lines.size())
|
||||
if (at.m_line >= m_lines.size())
|
||||
return at;
|
||||
|
||||
auto &line = m_lines.m_unfoldedLines[at.m_line];
|
||||
@@ -587,7 +584,7 @@ namespace hex::ui {
|
||||
|
||||
TextEditor::Coordinates TextEditor::Lines::findNextWord(const Coordinates &from) {
|
||||
Coordinates at = unfoldedToFoldedCoords(from);
|
||||
if (at.m_line >= (i32) size())
|
||||
if (at.m_line >= size())
|
||||
return from;
|
||||
|
||||
auto &line = operator[](at.m_line);
|
||||
@@ -608,7 +605,7 @@ namespace hex::ui {
|
||||
|
||||
TextEditor::Coordinates TextEditor::Lines::findPreviousWord(const Coordinates &from) {
|
||||
Coordinates at = unfoldedToFoldedCoords(from);
|
||||
if (at.m_line >= (i32) size())
|
||||
if (at.m_line >= size())
|
||||
return from;
|
||||
|
||||
auto &line = operator[](at.m_line);
|
||||
@@ -628,13 +625,9 @@ namespace hex::ui {
|
||||
return foldedToUnfoldedCoords(lineIndexCoords(at.m_line + 1, charIndex));
|
||||
}
|
||||
|
||||
u32 TextEditor::Line::skipSpaces(i32 index) {
|
||||
auto charIndex = index;
|
||||
u32 s = 0;
|
||||
while (charIndex < (i32) m_chars.size() && m_chars[charIndex] == ' ' && m_colors[charIndex] == 0x00) {
|
||||
++s;
|
||||
++charIndex;
|
||||
}
|
||||
u32 TextEditor::Line::skipSpaces(i32 charIndex) {
|
||||
u32 s;
|
||||
for (s = 0; charIndex < (i32) m_chars.size() && m_chars[charIndex] == ' ' && m_flags[charIndex] == 0x00; ++s, ++charIndex);
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -793,7 +786,7 @@ namespace hex::ui {
|
||||
result = start;
|
||||
auto lineIndex = start.m_line;
|
||||
auto row = lines->lineIndexToRow(lineIndex);
|
||||
auto maxLineIndex = (i32) lines->size() - 1;
|
||||
auto maxLineIndex = lines->size() - 1;
|
||||
auto charIndex = lines->lineCoordsIndex(start);
|
||||
std::string line;
|
||||
std::string colors;
|
||||
@@ -888,8 +881,8 @@ namespace hex::ui {
|
||||
else
|
||||
i = 0;
|
||||
}
|
||||
if ((i32) (direction * i) >= (i32) ((line.size() - 1) * (1 + direction) / 2)) {
|
||||
if (lines->rowToLineIndex(row) == (i64) maxLineIndex * (1 + direction) / 2) {
|
||||
if ((direction * i) >= (i32) ((line.size() - 1) * (1 + direction) / 2)) {
|
||||
if (lines->rowToLineIndex(row) == (i64) maxLineIndex * ((1 + direction) >> 1)) {
|
||||
if (m_active) {
|
||||
m_active = false;
|
||||
m_changed = true;
|
||||
|
||||
@@ -2,14 +2,13 @@
|
||||
#include "fonts/fonts.hpp"
|
||||
#include <ui/text_editor.hpp>
|
||||
#include <hex/helpers/scaling.hpp>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
#include <wolv/utils/string.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
namespace hex::ui {
|
||||
TextEditor::Palette s_paletteBase = TextEditor::getDarkPalette();
|
||||
|
||||
using Keys = TextEditor::Keys;
|
||||
|
||||
inline void TextUnformattedColored(const ImU32 &color, const char *text) {
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, color);
|
||||
@@ -104,7 +103,7 @@ namespace hex::ui {
|
||||
}
|
||||
return !line.ends_with('{');
|
||||
}
|
||||
return m_foldedLines[row].firstLineNeedsDelimiter();
|
||||
return m_foldedLines.at(row).firstLineNeedsDelimiter();
|
||||
}
|
||||
|
||||
bool TextEditor::FoldedLine::firstLineNeedsDelimiter() {
|
||||
@@ -172,14 +171,14 @@ namespace hex::ui {
|
||||
}
|
||||
|
||||
bool TextEditor::Lines::isEndOfLine(const Coordinates &coordinates) {
|
||||
if (coordinates.m_line < (i32) size())
|
||||
if (coordinates.m_line < size())
|
||||
return m_unfoldedLines[coordinates.m_line].isEndOfLine(coordinates.m_column);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TextEditor::Lines::isEndOfFile(const Coordinates &coordinates) {
|
||||
if (coordinates.m_line < (i32) size())
|
||||
if (coordinates.m_line < size())
|
||||
return isLastLine(coordinates.m_line) && isEndOfLine(coordinates);
|
||||
|
||||
return true;
|
||||
@@ -212,29 +211,35 @@ namespace hex::ui {
|
||||
}
|
||||
|
||||
float TextEditor::Lines::getGlobalRowMax() {
|
||||
auto maxRow = size() - 1.0f;
|
||||
std::vector<Range> spanningIntervals;
|
||||
if (m_codeFoldKeys.empty())
|
||||
float maxRow = size() - 1.0f;
|
||||
if (m_codeFoldsDisabled || m_foldedLines.empty() || m_codeFoldKeys.empty())
|
||||
return std::floor(maxRow);
|
||||
for (auto key1 = m_codeFoldKeys.begin(); key1 != m_codeFoldKeys.end(); ++key1) {
|
||||
auto key2 = std::next(key1);
|
||||
while (key2 != m_codeFoldKeys.end() && (!key2->contains(*key1) || (m_codeFoldState.contains(*key2) && m_codeFoldState[*key2]))) {
|
||||
++key2;
|
||||
}
|
||||
if (key2 == m_codeFoldKeys.end())
|
||||
spanningIntervals.push_back(*key1);
|
||||
}
|
||||
|
||||
for (auto key: spanningIntervals) {
|
||||
if (m_codeFoldState.contains(key) && !m_codeFoldState[key]) {
|
||||
if ((key.m_end.m_line - key.m_start.m_line - 1) < maxRow) {
|
||||
maxRow -= ((key.m_end.m_line - key.m_start.m_line));
|
||||
if (m_globalRowMaxChanged) {
|
||||
Keys spanningIntervals;
|
||||
|
||||
for (auto key1 = m_codeFoldKeys.begin(); key1 != m_codeFoldKeys.end(); ++key1) {
|
||||
auto key2 = std::next(key1);
|
||||
while (key2 != m_codeFoldKeys.end() && (!key2->contains(*key1) || (m_codeFoldState.contains(*key2) && m_codeFoldState[*key2]))) {
|
||||
++key2;
|
||||
}
|
||||
if (key2 == m_codeFoldKeys.end())
|
||||
spanningIntervals.push_back(*key1);
|
||||
}
|
||||
|
||||
for (auto key: spanningIntervals) {
|
||||
if (m_codeFoldState.contains(key) && !m_codeFoldState[key]) {
|
||||
if ((key.m_end.m_line - key.m_start.m_line - 1) < maxRow) {
|
||||
maxRow -= ((key.m_end.m_line - key.m_start.m_line));
|
||||
} else
|
||||
break;
|
||||
} else
|
||||
break;
|
||||
} else
|
||||
m_codeFoldState[key] = true;
|
||||
m_codeFoldState[key] = true;
|
||||
}
|
||||
m_cachedGlobalRowMax = std::floor(maxRow);
|
||||
m_globalRowMaxChanged = false;
|
||||
}
|
||||
return std::floor(maxRow);
|
||||
return m_cachedGlobalRowMax;
|
||||
}
|
||||
|
||||
float TextEditor::getMaxLineNumber() {
|
||||
@@ -245,7 +250,7 @@ namespace hex::ui {
|
||||
float currentLineNumber = m_topLineNumber;
|
||||
for (auto range: m_lines.m_codeFoldKeys) {
|
||||
|
||||
if (m_lines.m_codeFoldState.contains(range) && m_lines.m_codeFoldState[range] == false) {
|
||||
if (m_lines.m_codeFoldState.contains(range) && !m_lines.m_codeFoldState[range]) {
|
||||
|
||||
if ((range.m_start.m_line - currentLineNumber) < maxLineNumber)
|
||||
maxLineNumber += ((range.m_end.m_line - range.m_start.m_line));
|
||||
@@ -264,7 +269,7 @@ namespace hex::ui {
|
||||
|
||||
if (interval.m_start.m_line > result)
|
||||
break;
|
||||
if (m_lines.m_codeFoldState.contains(interval) && m_lines.m_codeFoldState[interval] == false)
|
||||
if (m_lines.m_codeFoldState.contains(interval) && !m_lines.m_codeFoldState[interval])
|
||||
result += (interval.m_end.m_line- interval.m_start.m_line);
|
||||
else
|
||||
m_lines.m_codeFoldState[interval] = true;
|
||||
@@ -372,12 +377,12 @@ namespace hex::ui {
|
||||
auto row = lineIndexToRow(pos.m_line);
|
||||
|
||||
if (m_unfoldIfNeeded && m_foldedLines.contains(row) && !m_codeFoldsDisabled) {
|
||||
auto foldedLine = m_foldedLines[row];
|
||||
auto foldedLine = m_foldedLines.at(row);
|
||||
auto foldedCoords = unfoldedToFoldedCoords(pos);
|
||||
auto keyCount = foldedLine.m_keys.size();
|
||||
for (u32 i = 0; i < keyCount; i++) {
|
||||
if (foldedCoords.m_column >= foldedLine.m_ellipsisIndices[i] && foldedCoords.m_column <= foldedLine.m_ellipsisIndices[i] + 3) {
|
||||
openCodeFold(m_foldedLines[row].m_keys[i]);
|
||||
openCodeFold(m_foldedLines.at(row).m_keys[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -468,18 +473,18 @@ namespace hex::ui {
|
||||
}
|
||||
|
||||
float TextEditor::Lines::rowToLineIndex(i32 row) {
|
||||
if (m_codeFoldsDisabled)
|
||||
if (m_codeFoldsDisabled || m_foldedLines.empty() || m_rowToLineIndex.empty())
|
||||
return row;
|
||||
if (m_rowToLineIndex.contains(row))
|
||||
return m_rowToLineIndex[row];
|
||||
return m_rowToLineIndex.at(row);
|
||||
return -1.0f;
|
||||
}
|
||||
|
||||
float TextEditor::Lines::lineIndexToRow(i32 lineIndex) {
|
||||
if (m_codeFoldsDisabled)
|
||||
if (m_codeFoldsDisabled || m_foldedLines.empty() || m_lineIndexToRow.empty())
|
||||
return lineIndex;
|
||||
if (m_lineIndexToRow.contains(lineIndex))
|
||||
return m_lineIndexToRow[lineIndex];
|
||||
return m_lineIndexToRow.at(lineIndex);
|
||||
return -1.0f;
|
||||
}
|
||||
|
||||
@@ -495,12 +500,12 @@ namespace hex::ui {
|
||||
} else {
|
||||
auto &rowFoldSymbols = lines->m_rowToFoldSymbol;
|
||||
auto row = lines->lineIndexToRow(key.m_end.m_line);
|
||||
if (isOpen() && endHovered() && rowFoldSymbols.contains(row) && rowFoldSymbols[row] != Lines::FoldSymbol::Square) {
|
||||
if (isOpen() && endHovered() && rowFoldSymbols.contains(row) && rowFoldSymbols[row] != FoldSymbol::Square) {
|
||||
lines->m_codeFoldHighlighted = key;
|
||||
codeFoldEndCursorBox.callback();
|
||||
}
|
||||
row = lines->lineIndexToRow(key.m_start.m_line);
|
||||
if (startHovered() && rowFoldSymbols.contains(row) && rowFoldSymbols[row] != Lines::FoldSymbol::Square) {
|
||||
if (startHovered() && rowFoldSymbols.contains(row) && rowFoldSymbols[row] != FoldSymbol::Square) {
|
||||
lines->m_codeFoldHighlighted = key;
|
||||
codeFoldStartCursorBox.callback();
|
||||
}
|
||||
@@ -534,9 +539,6 @@ namespace hex::ui {
|
||||
m_codeFolds.clear();
|
||||
m_rowToFoldSymbol.clear();
|
||||
|
||||
//m_foldsAreInstalled = !m_codeFoldKeys.empty();
|
||||
|
||||
|
||||
for (auto [key, isOpen]: m_codeFoldState){
|
||||
auto index = m_codeFoldKeys.find(key);
|
||||
if (index->m_start != key.m_start || index->m_end != key.m_end)
|
||||
@@ -593,11 +595,13 @@ namespace hex::ui {
|
||||
if (m_useSavedFoldStatesRequested) {
|
||||
applyCodeFoldStates();
|
||||
m_useSavedFoldStatesRequested = false;
|
||||
} else
|
||||
} else if (m_saveCodeFoldStateRequested) {
|
||||
saveCodeFoldStates();
|
||||
m_saveCodeFoldStateRequested = false;
|
||||
}
|
||||
|
||||
m_foldedLines.clear();
|
||||
std::vector<Range> closedFolds = removeEmbeddedFolds();
|
||||
Keys closedFolds = removeEmbeddedFolds();
|
||||
for (auto closedFold : closedFolds) {
|
||||
closeCodeFold(closedFold, false);
|
||||
auto row = lineIndexToRow(closedFold.m_start.m_line);
|
||||
@@ -667,11 +671,11 @@ namespace hex::ui {
|
||||
|
||||
bool triggered = false;
|
||||
std::map<Range, CodeFold> detectedFolds;
|
||||
for (auto key = m_codeFoldKeys.rbegin(); key != m_codeFoldKeys.rend(); key++) {
|
||||
if (m_codeFolds[*key].trigger())
|
||||
for (auto key : std::ranges::views::reverse(m_codeFoldKeys)) {
|
||||
if (m_codeFolds[key].trigger())
|
||||
triggered = true;
|
||||
if (m_codeFolds[*key].isDetected())
|
||||
detectedFolds.insert({*key, m_codeFolds[*key]});
|
||||
if (m_codeFolds[key].isDetected())
|
||||
detectedFolds.insert({key, m_codeFolds[key]});
|
||||
}
|
||||
if (detectedFolds.empty()) {
|
||||
m_codeFoldHighlighted = NoCodeFoldSelected;
|
||||
@@ -697,12 +701,12 @@ namespace hex::ui {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<TextEditor::Range> TextEditor::Lines::removeEmbeddedFolds() {
|
||||
std::vector<Range> closedFolds;
|
||||
Keys TextEditor::Lines::removeEmbeddedFolds() {
|
||||
Keys closedFolds;
|
||||
for (auto key : m_codeFoldKeys) {
|
||||
if (m_codeFoldState.contains(key) && !m_codeFoldState[key]) {
|
||||
bool replace = false;
|
||||
std::vector<Range> keysToErase;
|
||||
Keys keysToErase;
|
||||
for (auto closedFold : closedFolds) {
|
||||
if (key.contains(closedFold)) {
|
||||
replace = true;
|
||||
@@ -724,30 +728,30 @@ namespace hex::ui {
|
||||
}
|
||||
|
||||
void TextEditor::Lines::getRowSegments() {
|
||||
m_rowToSegments.clear();
|
||||
m_rowToFoldSegments.clear();
|
||||
m_multiLinesToRow.clear();
|
||||
m_rowCodeFoldTooltips.clear();
|
||||
std::vector<Range> closedFolds = removeEmbeddedFolds();
|
||||
Keys closedFolds = removeEmbeddedFolds();
|
||||
|
||||
for (auto key : closedFolds) {
|
||||
auto row = lineIndexToRow(key.m_start.m_line);
|
||||
if (m_rowToSegments.contains(row))
|
||||
if (m_rowToFoldSegments.contains(row) || !m_foldedLines.contains(row))
|
||||
continue;
|
||||
for (i32 i = key.m_start.m_line; i < key.m_end.m_line; i++)
|
||||
m_multiLinesToRow[i] = row;
|
||||
auto lineIndex = rowToLineIndex(row);
|
||||
auto foldedLine = m_foldedLines[row];
|
||||
auto foldedLine = m_foldedLines.at(row);
|
||||
i32 count = foldedLine.m_keys.size();
|
||||
if (count == 0)
|
||||
continue;
|
||||
for (i32 i = 0; i < count; i++) {
|
||||
Interval sgm = {foldedLine.m_foldedSegments[2 * i].m_column, foldedLine.m_foldedSegments[2 * i + 1].m_column};
|
||||
m_rowToSegments[row].push_back({foldedLine.m_keys[i].m_start, indexScreenPosition(lineIndex, sgm)});
|
||||
m_rowToFoldSegments[row].push_back({foldedLine.m_keys[i].m_start, indexScreenPosition(lineIndex, sgm)});
|
||||
ImVec2 screenPosEnd = indexCoordsToScreen(lineCoordinates(lineIndex, foldedLine.m_ellipsisIndices[i]));
|
||||
m_rowCodeFoldTooltips[row].push_back(TextEditor::CodeFoldTooltip(this, foldedLine.m_keys[i],ImRect(screenPosEnd, screenPosEnd + ImVec2(Ellipsis.lineTextSize(), m_charAdvance.y))));
|
||||
m_rowCodeFoldTooltips[row].emplace_back(this, foldedLine.m_keys[i],ImRect(screenPosEnd, screenPosEnd + ImVec2(Ellipsis.lineTextSize(), m_charAdvance.y)));
|
||||
}
|
||||
Interval sgm = {foldedLine.m_foldedSegments[2 * count].m_column, foldedLine.m_foldedSegments[2 * count + 1].m_column};
|
||||
m_rowToSegments[row].push_back({foldedLine.m_keys[count - 1].m_end, indexScreenPosition(lineIndex, sgm)});
|
||||
m_rowToFoldSegments[row].push_back({foldedLine.m_keys[count - 1].m_end, indexScreenPosition(lineIndex, sgm)});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -756,14 +760,14 @@ namespace hex::ui {
|
||||
}
|
||||
|
||||
ImVec2 TextEditor::Line::intervalToScreen(Interval stringIndices) const {
|
||||
return ImVec2(textSize(stringIndices.m_start), textSize(stringIndices.m_end));
|
||||
return {(float) textSize(stringIndices.m_start), (float) textSize(stringIndices.m_end)};
|
||||
}
|
||||
|
||||
ImVec2 TextEditor::Lines::lineIndexToScreen(i32 lineIndex, Interval stringIndices) {
|
||||
auto &line = operator[](lineIndex);
|
||||
auto startPos = m_lineIndexToScreen[lineIndex].x;
|
||||
auto increments = line.intervalToScreen(stringIndices);
|
||||
return ImVec2(startPos + increments.x, startPos + increments.y);
|
||||
return {startPos + increments.x, startPos + increments.y};
|
||||
}
|
||||
|
||||
ImVec2 TextEditor::Lines::indexCoordsToScreen(Coordinates indexCoords) {
|
||||
@@ -776,7 +780,7 @@ namespace hex::ui {
|
||||
if (hovered && ImGui::IsMouseClicked(0)) {
|
||||
auto codeFoldKeys = m_lines->m_codeFoldKeys;
|
||||
auto codeFoldState = m_lines->m_codeFoldState;
|
||||
std::vector<Range> keysToOpen;
|
||||
Keys keysToOpen;
|
||||
auto key = codeFoldKeys.begin();
|
||||
for (; key != codeFoldKeys.end(); key++) {
|
||||
if (*key == m_key)
|
||||
@@ -795,8 +799,8 @@ namespace hex::ui {
|
||||
keysToOpen.push_back(*key);
|
||||
key++;
|
||||
}
|
||||
for (auto openKey = keysToOpen.rbegin(); openKey != keysToOpen.rend(); openKey++)
|
||||
m_lines->openCodeFold(*openKey);
|
||||
for (auto openKey : std::ranges::views::reverse(keysToOpen))
|
||||
m_lines->openCodeFold(openKey);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -857,20 +861,18 @@ namespace hex::ui {
|
||||
std::pair<char,char> delimiters = {' ',' '};
|
||||
if (m_lines->m_codeFoldDelimiters.contains(key))
|
||||
delimiters = m_lines->m_codeFoldDelimiters[key];
|
||||
std::string delimiterOpen(1,delimiters.first);
|
||||
std::string delimiterClose(1,delimiters.second);
|
||||
Line lineStart = m_lines->m_unfoldedLines[key.m_start.m_line];
|
||||
Line lineEnd = m_lines->m_unfoldedLines[key.m_end.m_line];
|
||||
|
||||
bool isIfDef;
|
||||
std::string lineStartFirstNonSpace = lineStart.m_chars.substr(m_lines->m_leadingLineSpaces[key.m_start.m_line], 2);
|
||||
bool isSingleLineComment = lineStartFirstNonSpace == "//";
|
||||
|
||||
bool isIfDef = false;
|
||||
if (key.m_start.m_line > 0 && key.m_end.m_line < m_lines->size()) {
|
||||
std::string prevLine = m_lines->m_unfoldedLines[key.m_start.m_line - 1].m_chars;
|
||||
if (prevLine.starts_with("#ifdef") || prevLine.starts_with("#ifndef")) {
|
||||
if (prevLine.starts_with("#ifdef") || prevLine.starts_with("#ifndef"))
|
||||
isIfDef = true;
|
||||
} else
|
||||
isIfDef = false;
|
||||
} else
|
||||
isIfDef = false;
|
||||
}
|
||||
|
||||
bool appendClosingLine = true;
|
||||
Line bracket;
|
||||
@@ -890,9 +892,9 @@ namespace hex::ui {
|
||||
appendClosingLine = false;
|
||||
m_foldedLine = lineStart.subLine(0, 9);
|
||||
m_type = FoldType::AddsFirstLine;
|
||||
} else if (lineStart.m_chars.starts_with("//")) {
|
||||
} else if (isSingleLineComment) {
|
||||
appendClosingLine = false;
|
||||
m_foldedLine = lineStart.subLine(0, 1);
|
||||
m_foldedLine = lineStart.subLine(m_lines->m_leadingLineSpaces[key.m_start.m_line], 1);
|
||||
m_type = FoldType::AddsFirstLine;
|
||||
}else if (isIfDef) {
|
||||
appendClosingLine = false;
|
||||
@@ -981,12 +983,12 @@ namespace hex::ui {
|
||||
std::string delimiters;
|
||||
delimiters += delimiterPair.first;
|
||||
delimiters += delimiterPair.second;
|
||||
if (delimiters == "" || (delimiters != "{}" && delimiters != "[]" && delimiters != "()" && delimiters != "<>")) {
|
||||
if (delimiters.empty() || (delimiters != "{}" && delimiters != "[]" && delimiters != "()" && delimiters != "<>")) {
|
||||
auto lineStart = m_lines->m_unfoldedLines[key.m_start.m_line].m_chars;
|
||||
if (lineStart.starts_with("import") || lineStart.starts_with("#include")) {
|
||||
auto lineEnd = m_lines->m_unfoldedLines[key.m_end.m_line];
|
||||
auto columnStart = lineStart.find_first_of(" ");
|
||||
return Range(m_lines->lineCoordinates(key.m_start.m_line, columnStart), m_lines->lineCoordinates(key.m_end.m_line, lineEnd.maxColumn()));
|
||||
auto columnStart = lineStart.find(' ');
|
||||
return {m_lines->lineCoordinates(key.m_start.m_line, columnStart), m_lines->lineCoordinates(key.m_end.m_line, lineEnd.maxColumn())};
|
||||
}
|
||||
return key;
|
||||
}
|
||||
@@ -1003,7 +1005,6 @@ namespace hex::ui {
|
||||
while (true) {
|
||||
Coordinates nextCoordinates = m_lines->lineCoordinates(openDelimiterCoordinates.m_line, openDelimiterCoordinates.m_column + columnIndex);
|
||||
if (openDelimiterCoordinates.m_column < openDelimiterLine.maxColumn() && openDelimiterLine[(u64) nextCoordinates.m_column] == delimiters[0]) {
|
||||
//auto saveNearCursor = m_editor->m_lines.m_matchedDelimiter.m_nearCursor;
|
||||
if (m_lines->m_matchedDelimiter.coordinatesNearDelimiter(m_lines, nextCoordinates)) {
|
||||
auto result = m_lines->m_matchedDelimiter.findMatchingDelimiter(m_lines, nextCoordinates, false);
|
||||
if (result.m_line == key.m_end.m_line) {
|
||||
@@ -1020,7 +1021,7 @@ namespace hex::ui {
|
||||
}
|
||||
if (!found)
|
||||
closeDelimiterCoordinates = m_lines->rfind(delimiters.substr(1,1), m_lines->lineCoordinates(key.m_end.m_line, -1));
|
||||
return Range(openDelimiterCoordinates, closeDelimiterCoordinates);
|
||||
return {openDelimiterCoordinates, closeDelimiterCoordinates};
|
||||
}
|
||||
|
||||
void TextEditor::FoldedLine::loadSegments() {
|
||||
@@ -1078,8 +1079,8 @@ namespace hex::ui {
|
||||
|
||||
void TextEditor::Lines::removeKeys() {
|
||||
for (auto &[row,foldedLine] : m_foldedLines) {
|
||||
for (auto i = foldedLine.m_keysToRemove.rbegin(); i != foldedLine.m_keysToRemove.rend(); i++) {
|
||||
openCodeFold(*i);
|
||||
for (auto i : std::ranges::views::reverse(foldedLine.m_keysToRemove)) {
|
||||
openCodeFold(i);
|
||||
}
|
||||
foldedLine.m_keysToRemove.clear();
|
||||
if (foldedLine.m_keys.empty()) {
|
||||
@@ -1160,10 +1161,6 @@ namespace hex::ui {
|
||||
m_lines.setRowToLineIndexMap();
|
||||
m_lines.getRowSegments();
|
||||
}
|
||||
if (m_lines.m_saveCodeFoldStateRequested) {
|
||||
saveCodeFoldStates();
|
||||
m_lines.m_saveCodeFoldStateRequested = false;
|
||||
}
|
||||
|
||||
bool focused = ImGui::IsWindowFocused();
|
||||
while (std::floor(row) <= maxDisplayedRow) {
|
||||
@@ -1179,7 +1176,7 @@ namespace hex::ui {
|
||||
}
|
||||
|
||||
lineIndex = rowToLineIndex((i32) row);
|
||||
if (lineIndex >= (i32) m_lines.size() || lineIndex < 0)
|
||||
if (lineIndex >= m_lines.size() || lineIndex < 0)
|
||||
break;
|
||||
|
||||
if (m_showLineNumbers) {
|
||||
@@ -1212,7 +1209,7 @@ namespace hex::ui {
|
||||
m_topLineNumber = 1;
|
||||
lineIndex = 0;
|
||||
if (m_lines.m_unfoldedLines.empty())
|
||||
m_lines.m_unfoldedLines.push_back(Line());
|
||||
m_lines.m_unfoldedLines.emplace_back();
|
||||
m_lines.m_state.m_cursorPosition = lineCoordinates( 0, 0);
|
||||
if (m_showLineNumbers) {
|
||||
if (!m_lines.m_ignoreImGuiChild)
|
||||
@@ -1224,10 +1221,6 @@ namespace hex::ui {
|
||||
if (m_showCursor)
|
||||
drawCursor(0,textEditorSize, true, drawList);
|
||||
ImGui::Dummy(m_lines.m_charAdvance);
|
||||
|
||||
//auto lineStart = m_lines.lineCoordinates(lineIndex, 0);
|
||||
//drawText(lineStart, 0, 0);
|
||||
//m_lines.m_rowToLineIndex.clear();
|
||||
}
|
||||
|
||||
if (m_lines.m_scrollToCursor)
|
||||
@@ -1238,9 +1231,6 @@ namespace hex::ui {
|
||||
|
||||
i64 TextEditor::drawColoredText(i32 lineIndex, const ImVec2 &textEditorSize) {
|
||||
auto line = m_lines[lineIndex];
|
||||
//if (line.m_chars.starts_with("//+-#:") && lineIndex == (i32) m_lines.size() - 1) {
|
||||
// return 0;
|
||||
//}
|
||||
|
||||
if (line.empty()) {
|
||||
ImGui::Dummy(m_lines.m_charAdvance);
|
||||
@@ -1306,13 +1296,10 @@ namespace hex::ui {
|
||||
}
|
||||
|
||||
bool TextEditor::Lines::isMultiLineRow(i32 row) {
|
||||
return (m_foldedLines.contains(row) && m_foldedLines[row].m_keys.size() > 0);
|
||||
return (m_foldedLines.contains(row) && !m_foldedLines.at(row).m_keys.empty());
|
||||
}
|
||||
|
||||
void TextEditor::preRender() {
|
||||
//static ImVec2 previous = {0,0};
|
||||
//static bool update = true;
|
||||
//if (update) {
|
||||
m_lines.m_charAdvance = calculateCharAdvance();
|
||||
m_lines.m_leftMargin = m_lines.m_charAdvance.x;
|
||||
for (i32 i = 0; i < (i32) PaletteIndex::Max; ++i) {
|
||||
@@ -1321,12 +1308,6 @@ namespace hex::ui {
|
||||
m_palette[i] = ImGui::ColorConvertFloat4ToU32(color);
|
||||
}
|
||||
m_lines.m_numberOfLinesDisplayed = getPageSize();
|
||||
//if (previous == m_lines.m_charAdvance) {
|
||||
// update = false;
|
||||
// } else {
|
||||
// update = true;
|
||||
// previous = m_lines.m_charAdvance;
|
||||
// }
|
||||
}
|
||||
|
||||
void TextEditor::drawSelection(float lineIndex, ImDrawList *drawList) {
|
||||
@@ -1334,8 +1315,8 @@ namespace hex::ui {
|
||||
auto lineStartScreenPos = m_lines.getLineStartScreenPos(0,row);
|
||||
Range lineCoords;
|
||||
if (m_lines.isMultiLineRow(row)) {
|
||||
lineCoords.m_start = m_lines.lineCoordinates(m_lines.m_foldedLines[row].m_full.m_start.m_line, 0);
|
||||
lineCoords.m_end = m_lines.lineCoordinates(m_lines.m_foldedLines[row].m_full.m_end.m_line, -1);
|
||||
lineCoords.m_start = m_lines.lineCoordinates(m_lines.m_foldedLines.at(row).m_full.m_start.m_line, 0);
|
||||
lineCoords.m_end = m_lines.lineCoordinates(m_lines.m_foldedLines.at(row).m_full.m_end.m_line, -1);
|
||||
} else {
|
||||
lineCoords = Range(m_lines.lineCoordinates(lineIndex, 0), m_lines.lineCoordinates(lineIndex, -1));
|
||||
}
|
||||
@@ -1367,13 +1348,13 @@ namespace hex::ui {
|
||||
auto start = lineStartScreenPos;
|
||||
ImVec2 end = lineStartScreenPos + ImVec2(m_lines.m_lineNumberFieldWidth + contentSize.x, m_lines.m_charAdvance.y);
|
||||
auto center = lineNumberStartScreenPos + ImVec2(m_lines.m_lineNumberFieldWidth - 2 * m_lines.m_charAdvance.x + 1_scaled, 0);
|
||||
if (m_lines.m_rowToSegments.contains(row)) {
|
||||
if (m_lines.m_rowToFoldSegments.contains(row)) {
|
||||
bool circlesDrawn = false;
|
||||
for (auto segments : m_lines.m_rowToSegments[row]) {
|
||||
if (segments.m_foldEnd.m_line != lineIndex && m_lines.m_breakpoints.count(segments.m_foldEnd.m_line + 1) > 0)
|
||||
for (auto segments : m_lines.m_rowToFoldSegments[row]) {
|
||||
if (segments.m_foldEnd.m_line != lineIndex && m_lines.m_breakpoints.contains(segments.m_foldEnd.m_line + 1))
|
||||
start.x = segments.m_segment.m_start;
|
||||
if (m_lines.m_breakpoints.count(segments.m_foldEnd.m_line + 1) > 0) {
|
||||
if (segments == m_lines.m_rowToSegments[row].back())
|
||||
if (m_lines.m_breakpoints.contains(segments.m_foldEnd.m_line + 1)) {
|
||||
if (segments == m_lines.m_rowToFoldSegments[row].back())
|
||||
end.x = lineNumberStartScreenPos.x + contentSize.x + m_lines.m_lineNumberFieldWidth;
|
||||
else
|
||||
end.x = segments.m_segment.m_end;
|
||||
@@ -1390,7 +1371,7 @@ namespace hex::ui {
|
||||
auto key = Range(segmentStart, keyValue);
|
||||
if (m_lines.m_codeFoldState.contains(key) && !m_lines.m_codeFoldState[key]) {
|
||||
for (i32 i = key.m_start.m_line + 1; i < key.m_end.m_line; i++) {
|
||||
if (m_lines.m_breakpoints.count(i + 1) > 0) {
|
||||
if (m_lines.m_breakpoints.contains(i + 1)) {
|
||||
start.x = segments.m_segment.m_end;
|
||||
end.x = start.x + Ellipsis.lineTextSize();
|
||||
drawList->AddRectFilled(start, end, m_palette[(i32) PaletteIndex::Breakpoint]);
|
||||
@@ -1404,7 +1385,7 @@ namespace hex::ui {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (m_lines.m_breakpoints.count(lineIndex + 1) > 0) {
|
||||
} else if (m_lines.m_breakpoints.contains(lineIndex + 1)) {
|
||||
end = ImVec2(lineNumberStartScreenPos.x + contentSize.x + m_lines.m_lineNumberFieldWidth, lineStartScreenPos.y + m_lines.m_charAdvance.y);
|
||||
drawList->AddRectFilled(start, end, m_palette[(i32) PaletteIndex::Breakpoint]);
|
||||
drawList->AddCircleFilled(center + ImVec2(0, m_lines.m_charAdvance.y) / 2, m_lines.m_charAdvance.y / 3, m_palette[(i32) PaletteIndex::Breakpoint]);
|
||||
@@ -1477,8 +1458,8 @@ namespace hex::ui {
|
||||
if (key.contains(lineCoords) && m_lines.m_codeFoldState.contains(key) && !m_lines.m_codeFoldState[key]) {
|
||||
row = m_lines.m_multiLinesToRow[lineIndex + 1];
|
||||
i32 multilineLineIndex = rowToLineIndex(row);
|
||||
if (m_lines.m_rowToSegments.contains(row) && m_lines.m_rowToSegments[row].size() > 1) {
|
||||
Segment result = *std::find_if(m_lines.m_rowToSegments[row].begin(), m_lines.m_rowToSegments[row].end(), [&](const Segment &segment) {
|
||||
if (m_lines.m_rowToFoldSegments.contains(row) && m_lines.m_rowToFoldSegments[row].size() > 1) {
|
||||
FoldSegment result = *std::find_if(m_lines.m_rowToFoldSegments[row].begin(), m_lines.m_rowToFoldSegments[row].end(), [&](const FoldSegment &segment) {
|
||||
return segment.m_foldEnd == key.m_end;
|
||||
});
|
||||
lineStartScreenPos = ImVec2(result.m_segment.m_start + m_lines.m_unfoldedLines[0].stringTextSize(std::string(m_lines.m_leadingLineSpaces[key.m_end.m_line], ' ')), m_lines.m_lineIndexToScreen[multilineLineIndex].y);
|
||||
@@ -1523,8 +1504,8 @@ namespace hex::ui {
|
||||
if (gotoKey != Invalid) {
|
||||
std::string errorLineColumn;
|
||||
bool found = false;
|
||||
for (auto text: m_lines.m_clickableText) {
|
||||
if (lineText.find(text) == 0) {
|
||||
for (const auto &text: m_lines.m_clickableText) {
|
||||
if (lineText.starts_with(text)) {
|
||||
errorLineColumn = lineText.substr(text.size());
|
||||
if (!errorLineColumn.empty()) {
|
||||
found = true;
|
||||
@@ -1534,7 +1515,7 @@ namespace hex::ui {
|
||||
}
|
||||
if (found) {
|
||||
i32 currLine = 0, currColumn = 0;
|
||||
if (auto idx = errorLineColumn.find(":"); idx != std::string::npos) {
|
||||
if (auto idx = errorLineColumn.find(':'); idx != std::string::npos) {
|
||||
auto errorLine = errorLineColumn.substr(0, idx);
|
||||
if (!errorLine.empty())
|
||||
currLine = std::stoi(errorLine) - 1;
|
||||
@@ -1684,7 +1665,7 @@ namespace hex::ui {
|
||||
|
||||
ImVec2 TextEditor::calculateCharAdvance() const {
|
||||
const float fontSize = ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, "#", nullptr, nullptr).x;
|
||||
return ImVec2(fontSize, GImGui->FontSize * m_lineSpacing);
|
||||
return {fontSize, GImGui->FontSize * m_lineSpacing};
|
||||
}
|
||||
|
||||
float TextEditor::Lines::textDistanceToLineStart(const Coordinates &aFrom) {
|
||||
@@ -1700,7 +1681,6 @@ namespace hex::ui {
|
||||
return line.m_lineMaxColumn - distanceToEnd;
|
||||
}
|
||||
return line.stringTextSize(substr1.c_str());
|
||||
//return ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, substr.c_str(), nullptr, nullptr).x;
|
||||
}
|
||||
|
||||
void TextEditor::drawCodeFolds(float lineIndex, ImDrawList *drawList) {
|
||||
@@ -1711,7 +1691,7 @@ namespace hex::ui {
|
||||
if (m_lines.m_codeFoldHighlighted != NoCodeFoldSelected) {
|
||||
Range key1, key2;
|
||||
if (m_lines.m_foldedLines.contains(row)) {
|
||||
auto &foldedLine = m_lines.m_foldedLines[row];
|
||||
auto &foldedLine = m_lines.m_foldedLines.at(row);
|
||||
if (m_lines.m_codeFoldValueMap.contains(foldedLine.m_full.m_start))
|
||||
key1 = Range(m_lines.m_codeFoldValueMap[foldedLine.m_full.m_start], foldedLine.m_full.m_start);
|
||||
else
|
||||
@@ -1723,40 +1703,40 @@ namespace hex::ui {
|
||||
|
||||
if (m_lines.m_codeFoldHighlighted == key1) {
|
||||
if (m_lines.m_codeFoldState.contains(m_lines.m_codeFoldHighlighted) && !m_lines.m_codeFoldState[m_lines.m_codeFoldHighlighted])
|
||||
state = Lines::FoldSymbol::Square;
|
||||
state = FoldSymbol::Square;
|
||||
else {
|
||||
if (codeFoldKeyLine == key1.m_start.m_line)
|
||||
state = Lines::FoldSymbol::Down;
|
||||
state = FoldSymbol::Down;
|
||||
else if (codeFoldKeyLine == key1.m_end.m_line)
|
||||
state = Lines::FoldSymbol::Up;
|
||||
state = FoldSymbol::Up;
|
||||
}
|
||||
} else if (m_lines.m_codeFoldHighlighted == key2) {
|
||||
if (m_lines.m_codeFoldState.contains(key2) && !m_lines.m_codeFoldState[key2])
|
||||
state = Lines::FoldSymbol::Square;
|
||||
state = FoldSymbol::Square;
|
||||
else {
|
||||
if (lineIndexToRow(codeFoldKeyLine) == lineIndexToRow(key2.m_start.m_line))
|
||||
state = Lines::FoldSymbol::Down;
|
||||
state = FoldSymbol::Down;
|
||||
else if (codeFoldKeyLine == key2.m_end.m_line)
|
||||
state = Lines::FoldSymbol::Up;
|
||||
state = FoldSymbol::Up;
|
||||
}
|
||||
}
|
||||
} else if (m_lines.m_codeFoldHighlighted.m_start.m_line == codeFoldKeyLine) {
|
||||
if (m_lines.m_codeFoldState.contains(m_lines.m_codeFoldHighlighted) && m_lines.m_codeFoldState[m_lines.m_codeFoldHighlighted])
|
||||
state = Lines::FoldSymbol::Down;
|
||||
state = FoldSymbol::Down;
|
||||
else
|
||||
state = Lines::FoldSymbol::Square;
|
||||
state = FoldSymbol::Square;
|
||||
} else if (m_lines.m_codeFoldHighlighted.m_end.m_line == codeFoldKeyLine) {
|
||||
if (m_lines.m_codeFoldState.contains(m_lines.m_codeFoldHighlighted) && m_lines.m_codeFoldState[m_lines.m_codeFoldHighlighted])
|
||||
state = Lines::FoldSymbol::Up;
|
||||
state = FoldSymbol::Up;
|
||||
else
|
||||
state = Lines::FoldSymbol::Square;
|
||||
state = FoldSymbol::Square;
|
||||
}
|
||||
}
|
||||
|
||||
i32 lineColor;
|
||||
Interval highlightedRowInterval = Interval(m_lines.lineIndexToRow(m_lines.m_codeFoldHighlighted.m_start.m_line), m_lines.lineIndexToRow(m_lines.m_codeFoldHighlighted.m_end.m_line));
|
||||
|
||||
if (highlightedRowInterval.contains(row) && (state == Lines::FoldSymbol::Line ||
|
||||
if (highlightedRowInterval.contains(row) && (state == FoldSymbol::Line ||
|
||||
row == highlightedRowInterval.m_start || row == highlightedRowInterval.m_end))
|
||||
lineColor = ImGui::ColorConvertFloat4ToU32(ImGui::GetStyle().Colors[ImGuiCol_ScrollbarGrabActive]);
|
||||
else
|
||||
@@ -1783,20 +1763,20 @@ namespace hex::ui {
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
void TextEditor::renderCodeFolds(i32 row, ImDrawList *drawList, i32 color, Lines::FoldSymbol state) {
|
||||
void TextEditor::renderCodeFolds(i32 row, ImDrawList *drawList, i32 color, FoldSymbol state) {
|
||||
auto boxSize = m_lines.m_charAdvance.x + (((u32)m_lines.m_charAdvance.x % 2) ? 2.0f : 1.0f);
|
||||
auto verticalMargin = m_lines.m_charAdvance.y - boxSize;
|
||||
auto horizontalMargin = m_lines.m_lineNumberFieldWidth - (boxSize - 1) / 2;
|
||||
auto lineStartScreenPos = m_lines.getLineStartScreenPos(horizontalMargin, row);
|
||||
auto numberLineStartScreenPos = ImVec2(m_lines.m_lineNumbersStartPos.x + m_lines.m_lineNumberFieldWidth, lineStartScreenPos.y);
|
||||
|
||||
if (state == Lines::FoldSymbol::Square) {
|
||||
if (state == FoldSymbol::Square) {
|
||||
renderSquare(numberLineStartScreenPos, drawList, boxSize - 1, verticalMargin, color);
|
||||
renderPlus(numberLineStartScreenPos, drawList, boxSize, std::floor(verticalMargin / 2), color);
|
||||
} else if (state == Lines::FoldSymbol::Down) {
|
||||
} else if (state == FoldSymbol::Down) {
|
||||
renderPointingDown(numberLineStartScreenPos, drawList, boxSize - 1, verticalMargin, color);
|
||||
renderMinus(numberLineStartScreenPos, drawList, boxSize, std::floor(verticalMargin / 4), color);
|
||||
} else if (state == Lines::FoldSymbol::Up) {
|
||||
} else if (state == FoldSymbol::Up) {
|
||||
renderPointingUp(numberLineStartScreenPos, drawList, boxSize - 1, verticalMargin, color);
|
||||
renderMinus(numberLineStartScreenPos, drawList, boxSize, std::floor(3 * verticalMargin / 4), color);
|
||||
} else {
|
||||
@@ -1898,4 +1878,8 @@ namespace hex::ui {
|
||||
drawList->AddLine(p1 + py, p2, color, 1.0f);
|
||||
drawList->AddLine(p1 + px + py, p2, color, 1.0f);
|
||||
}
|
||||
|
||||
bool TextEditor::areEqual(const std::pair<Range, CodeFold> &a, const std::pair<Range, CodeFold> &b) {
|
||||
return a.first == b.first && a.second.isOpen() == b.second.isOpen();
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
#include <ui/text_editor.hpp>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
#include <wolv/utils/string.hpp>
|
||||
#include <hex/api/content_registry/pattern_language.hpp>
|
||||
#include <pl/api.hpp>
|
||||
#include <pl/core/preprocessor.hpp>
|
||||
|
||||
@@ -17,6 +16,7 @@ namespace hex::ui {
|
||||
using Range = TextEditor::Range;
|
||||
using FindReplaceHandler = TextEditor::FindReplaceHandler;
|
||||
using CodeFold = TextEditor::CodeFold;
|
||||
using EditorState = TextEditor::EditorState;
|
||||
|
||||
|
||||
bool Interval::contains(i32 value, bool inclusive) const {
|
||||
@@ -30,13 +30,11 @@ namespace hex::ui {
|
||||
if (gap == 0 || gap == 1)
|
||||
return true;
|
||||
gap = other.m_start - m_end;
|
||||
if (gap == 0 || gap == 1)
|
||||
return true;
|
||||
return false;
|
||||
return gap == 0 || gap == 1;
|
||||
}
|
||||
|
||||
bool Coordinates::operator==(const Coordinates &o) const {
|
||||
return m_line == o.m_line && m_column == o.m_column;
|
||||
return m_line == o.m_line && m_column == o.m_column;
|
||||
}
|
||||
|
||||
bool Coordinates::operator!=(const Coordinates &o) const {
|
||||
@@ -64,11 +62,11 @@ namespace hex::ui {
|
||||
}
|
||||
|
||||
Coordinates Coordinates::operator+(const Coordinates &o) const {
|
||||
return Coordinates(m_line + o.m_line, m_column + o.m_column);
|
||||
return {m_line + o.m_line, m_column + o.m_column};
|
||||
}
|
||||
|
||||
Coordinates Coordinates::operator-(const Coordinates &o) const {
|
||||
return Coordinates(m_line - o.m_line, m_column - o.m_column);
|
||||
return {m_line - o.m_line, m_column - o.m_column};
|
||||
}
|
||||
|
||||
bool Range::operator==(const Range &o) const {
|
||||
@@ -79,13 +77,13 @@ namespace hex::ui {
|
||||
}
|
||||
|
||||
Coordinates Range::getSelectedLines() {
|
||||
return Coordinates(m_start.m_line, m_end.m_line);
|
||||
return {m_start.m_line, m_end.m_line};
|
||||
}
|
||||
|
||||
Coordinates Range::getSelectedColumns() {
|
||||
if (isSingleLine())
|
||||
return Coordinates(m_start.m_column, m_end.m_column - m_start.m_column);
|
||||
return Coordinates(m_start.m_column, m_end.m_column);
|
||||
return {m_start.m_column, m_end.m_column - m_start.m_column};
|
||||
return {m_start.m_column, m_end.m_column};
|
||||
}
|
||||
|
||||
bool Range::isSingleLine() {
|
||||
@@ -174,7 +172,7 @@ namespace hex::ui {
|
||||
return *this;
|
||||
}
|
||||
|
||||
LineIterator LineIterator::operator=(const LineIterator &other) {
|
||||
LineIterator &LineIterator::operator=(const LineIterator &other) {
|
||||
m_charsIter = other.m_charsIter;
|
||||
m_colorsIter = other.m_colorsIter;
|
||||
m_flagsIter = other.m_flagsIter;
|
||||
@@ -235,14 +233,7 @@ namespace hex::ui {
|
||||
return iter;
|
||||
}
|
||||
|
||||
Line &Line::operator=(const Line &line) {
|
||||
m_chars = line.m_chars;
|
||||
m_colors = line.m_colors;
|
||||
m_flags = line.m_flags;
|
||||
m_colorized = line.m_colorized;
|
||||
m_lineMaxColumn = line.m_lineMaxColumn;
|
||||
return *this;
|
||||
}
|
||||
Line &Line::operator=(const Line &line) = default;
|
||||
|
||||
Line &Line::operator=(Line &&line) noexcept {
|
||||
m_chars = std::move(line.m_chars);
|
||||
@@ -536,24 +527,18 @@ namespace hex::ui {
|
||||
return !m_colorized;
|
||||
}
|
||||
|
||||
Interval &Interval::operator=(const Interval &interval) {
|
||||
Interval &Interval::operator=(const Interval &interval) = default;
|
||||
|
||||
Interval &Interval::operator=(Interval &&interval) noexcept {
|
||||
m_start = interval.m_start;
|
||||
m_end = interval.m_end;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Interval &Interval::operator=(Interval &&interval) noexcept {
|
||||
m_start = std::move(interval.m_start);
|
||||
m_end = std::move(interval.m_end);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool TextEditor::ActionableBox::trigger() {
|
||||
auto mousePos = ImGui::GetMousePos();
|
||||
if (mousePos.x <= m_box.Min.x || mousePos.x >= m_box.Max.x ||
|
||||
mousePos.y < m_box.Min.y || mousePos.y > m_box.Max.y)
|
||||
return false;
|
||||
return true;
|
||||
return !(mousePos.x <= m_box.Min.x || mousePos.x >= m_box.Max.x ||
|
||||
mousePos.y < m_box.Min.y || mousePos.y > m_box.Max.y);
|
||||
}
|
||||
|
||||
void TextEditor::ActionableBox::shiftBoxVertically(float lineCount, float lineHeight) {
|
||||
@@ -639,7 +624,7 @@ namespace hex::ui {
|
||||
if (m_readOnly)
|
||||
return;
|
||||
|
||||
m_undoBuffer.resize((u64) (m_undoIndex + 1));
|
||||
m_undoBuffer.resize(m_undoIndex + 1);
|
||||
m_undoBuffer.back() = UndoAction(value);
|
||||
m_undoIndex++;
|
||||
}
|
||||
@@ -806,9 +791,7 @@ namespace hex::ui {
|
||||
auto matchedCoords = m_matchedDelimiter.m_matched;
|
||||
Line::Flags nearFlag(m_unfoldedLines[nearCoords.m_line].m_flags[nearCoords.m_column]);
|
||||
Line::Flags matchedFlag(m_unfoldedLines[matchedCoords.m_line].m_flags[matchedCoords.m_column]);
|
||||
if (nearFlag.m_bits.matchedDelimiter && matchedFlag.m_bits.matchedDelimiter)
|
||||
return true;
|
||||
return false;
|
||||
return nearFlag.m_bits.matchedDelimiter && matchedFlag.m_bits.matchedDelimiter;
|
||||
}
|
||||
|
||||
// the index here is array index so zero based
|
||||
@@ -1084,7 +1067,7 @@ namespace hex::ui {
|
||||
}
|
||||
if (textLoc == std::string::npos)
|
||||
return false;
|
||||
TextEditor::EditorState state;
|
||||
EditorState state;
|
||||
state.m_selection = Range(lines->stringIndexCoords(textLoc, textSrc), lines->stringIndexCoords(textLoc + matchBytes, textSrc));
|
||||
state.m_cursorPosition = state.m_selection.m_end;
|
||||
if (!m_matches.empty() && state == m_matches.back())
|
||||
@@ -1122,7 +1105,7 @@ namespace hex::ui {
|
||||
lines->ensureCursorVisible();
|
||||
return;
|
||||
}
|
||||
TextEditor::EditorState state = m_matches.back();
|
||||
EditorState state = m_matches.back();
|
||||
|
||||
while (state.m_cursorPosition < startingPos) {
|
||||
if (!findNext(lines, byteIndex)) {
|
||||
@@ -1138,8 +1121,7 @@ namespace hex::ui {
|
||||
|
||||
lines->m_state = saveState;
|
||||
lines->ensureCursorVisible();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool FindReplaceHandler::replace(Lines *lines, bool right) {
|
||||
@@ -1179,7 +1161,7 @@ namespace hex::ui {
|
||||
ImGui::SetKeyboardFocusHere(0);
|
||||
|
||||
u.m_after = state;
|
||||
m_undoBuffer.push_back(u);
|
||||
m_undoBuffer.emplace_back(std::move(u));
|
||||
lines->m_textChanged = true;
|
||||
|
||||
return true;
|
||||
@@ -1225,7 +1207,7 @@ namespace hex::ui {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CodeFold::isOpen() {
|
||||
bool CodeFold::isOpen() const {
|
||||
return lines->m_codeFoldState[key];
|
||||
}
|
||||
|
||||
@@ -1251,11 +1233,11 @@ namespace hex::ui {
|
||||
if (index < 0)
|
||||
index += size();
|
||||
auto row = lineIndexToRow(index);
|
||||
if (row < 0 || row >= getGlobalRowMax())
|
||||
if (row < 0 || row > getGlobalRowMax())
|
||||
throw std::out_of_range("Line index out of range");
|
||||
if (!m_foldedLines.contains(row) || m_foldedLines.at(row).m_full.m_start.m_line != index)
|
||||
return m_unfoldedLines.at(index);
|
||||
return const_cast<Line &>(m_foldedLines.at(row).m_foldedLine);
|
||||
return m_foldedLines.at(row).m_foldedLine;
|
||||
}
|
||||
|
||||
Line &Lines::operator[](i32 index) {
|
||||
@@ -1266,13 +1248,14 @@ namespace hex::ui {
|
||||
if (index < 0)
|
||||
index += size();
|
||||
i32 row = lineIndexToRow(index);
|
||||
if (getGlobalRowMax() != 0)
|
||||
row = std::clamp(row,0, (i32)(getGlobalRowMax()-1));
|
||||
i32 globalRowMax = getGlobalRowMax();
|
||||
if (globalRowMax > 0)
|
||||
row = std::clamp(row,0, globalRowMax);
|
||||
else
|
||||
row = 0;
|
||||
if (!m_foldedLines.contains(row) || m_foldedLines[row].m_full.m_start.m_line != index)
|
||||
return m_unfoldedLines.at(index);
|
||||
return const_cast<Line &>(m_foldedLines[row].m_foldedLine);
|
||||
return m_foldedLines[row].m_foldedLine;
|
||||
}
|
||||
|
||||
i32 Lines::size() const {
|
||||
@@ -1292,17 +1275,10 @@ namespace hex::ui {
|
||||
}
|
||||
|
||||
i32 TextEditor::getTotalLines() const {
|
||||
return (i32) m_lines.size();
|
||||
return m_lines.size();
|
||||
}
|
||||
|
||||
using CodeFoldBlocks = TextEditor::CodeFoldBlocks;
|
||||
//static std::chrono::steady_clock::time_point currentTime1;
|
||||
void TextEditor::Lines::setAllCodeFolds() {
|
||||
//std::chrono::steady_clock::time_point beforeLoop;
|
||||
//std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
|
||||
//std::chrono::duration<double, std::milli> time_span = now - currentTime1;
|
||||
//auto lastCharInputTime = time_span.count();
|
||||
//log::debug("Before loading 1st id of line : {} ms", lastCharInputTime);
|
||||
CodeFoldBlocks intervals = foldPointsFromSource();
|
||||
m_codeFoldKeys.clear();
|
||||
m_codeFolds.clear();
|
||||
@@ -1341,13 +1317,9 @@ namespace hex::ui {
|
||||
m_codeFoldKeyLineMap.insert(std::make_pair(interval.m_start.m_line,interval.m_start));
|
||||
m_codeFoldValueLineMap.insert(std::make_pair(interval.m_end.m_line,interval.m_end));
|
||||
}
|
||||
//currentTime1 = std::chrono::steady_clock::now();
|
||||
//time_span = currentTime1 - now;
|
||||
//lastCharInputTime = time_span.count();
|
||||
// log::debug("After loading 1st id of line : {} ms", lastCharInputTime);
|
||||
}
|
||||
|
||||
void TextEditor::Lines::readHiddenLines() {
|
||||
void TextEditor::Lines::removeHiddenLinesFromPattern() {
|
||||
m_hiddenLines.clear();
|
||||
i32 lineIndex = 0;
|
||||
const auto totalLines = (i32)m_unfoldedLines.size();
|
||||
@@ -1359,7 +1331,7 @@ namespace hex::ui {
|
||||
auto lines = wolv::util::splitString(hiddenLinesText, "\n");
|
||||
for (i32 i = 0; i < lineIndex; i++) {
|
||||
HiddenLine hiddenLine(i, m_unfoldedLines[i].m_chars);
|
||||
m_hiddenLines.push_back(hiddenLine);
|
||||
m_hiddenLines.emplace_back(std::move(hiddenLine));
|
||||
m_useSavedFoldStatesRequested = true;
|
||||
}
|
||||
deleteSelection();
|
||||
@@ -1367,7 +1339,7 @@ namespace hex::ui {
|
||||
setAllCodeFolds();
|
||||
}
|
||||
|
||||
void TextEditor::Lines::writeHiddenLines() {
|
||||
void TextEditor::Lines::addHiddenLinesToPattern() {
|
||||
if (m_hiddenLines.empty())
|
||||
return;
|
||||
for (const auto &hiddenLine : m_hiddenLines) {
|
||||
@@ -1388,7 +1360,7 @@ namespace hex::ui {
|
||||
|
||||
void TextEditor::codeFoldCollapse(i32 level, bool recursive, bool all) {
|
||||
|
||||
for (auto [key, codeFold]: m_lines.m_codeFolds) {
|
||||
for (const auto& [key, codeFold]: m_lines.m_codeFolds) {
|
||||
if (key.containsLine(m_lines.m_state.m_cursorPosition.m_line) || all) {
|
||||
if (getCodeFoldLevel(key.m_start.m_line) >= level || level == 0) {
|
||||
if (m_lines.m_codeFoldState.contains(key) && m_lines.m_codeFoldState[key]) {
|
||||
@@ -1412,7 +1384,7 @@ namespace hex::ui {
|
||||
}
|
||||
|
||||
void TextEditor::codeFoldExpand(i32 level, bool recursive, bool all) {
|
||||
for (auto [key, codeFold]: m_lines.m_codeFolds) {
|
||||
for (const auto& [key, codeFold]: m_lines.m_codeFolds) {
|
||||
if (key.containsLine(m_lines.m_state.m_cursorPosition.m_line) || all) {
|
||||
if (getCodeFoldLevel(key.m_start.m_line) >= level || level == 0) {
|
||||
if (m_lines.m_codeFoldState.contains(key) && !m_lines.m_codeFoldState[key]) {
|
||||
@@ -1448,42 +1420,11 @@ namespace hex::ui {
|
||||
}
|
||||
if (source == nullptr)
|
||||
return false;
|
||||
i32 line = location.line - 1;
|
||||
i32 col = location.column - 1;
|
||||
i32 length = location.length;
|
||||
|
||||
if ( line < 0 || line >= (i32) size())
|
||||
return false;
|
||||
|
||||
if ( col < 0 || col > (i32) operator[](line).size())
|
||||
return false;
|
||||
if (length < 0)
|
||||
return false;
|
||||
if (length > (i32) operator[](line).size()-col)
|
||||
length -= (i32)( operator[](line).size()-col);
|
||||
while (line + 1 < size() && m_firstTokenIdOfLine[line] == m_firstTokenIdOfLine[line + 1]) {
|
||||
length -= (i32) operator[](line).size();
|
||||
line++;
|
||||
}
|
||||
|
||||
|
||||
if (length > (i32) operator[](line).size()-col && m_firstTokenIdOfLine[line + 1] != -1)
|
||||
return false;
|
||||
return true;
|
||||
return location > m_tokens.front().location && location < m_tokens.back().location;
|
||||
}
|
||||
|
||||
void TextEditor::Lines::loadFirstTokenIdOfLine() {
|
||||
auto code = getText();
|
||||
if (code.empty())
|
||||
return;
|
||||
std::unique_ptr<pl::PatternLanguage> runtime = std::make_unique<pl::PatternLanguage>();
|
||||
ContentRegistry::PatternLanguage::configureRuntime(*runtime, nullptr);
|
||||
std::ignore = runtime->preprocessString(code, pl::api::Source::DefaultSource);
|
||||
m_tokens = runtime->getInternals().preprocessor->getResult();
|
||||
const u32 tokenCount = m_tokens.size();
|
||||
if (tokenCount == 0)
|
||||
return;
|
||||
|
||||
m_firstTokenIdOfLine.clear();
|
||||
u32 tokenId = 0;
|
||||
u32 lineIndex = m_tokens.at(tokenId).location.line - 1;
|
||||
@@ -1512,7 +1453,6 @@ namespace hex::ui {
|
||||
auto commentStartLine = m_tokens.at(tokenId).location.line - 1;
|
||||
std::string value = m_tokens.at(tokenId).getFormattedValue();
|
||||
auto commentEndLine = commentStartLine + std::count(value.begin(), value.end(), '\n');
|
||||
//m_firstTokenIdOfLine.at(commentStartLine) = commentTokenId;
|
||||
for (u32 i = commentStartLine; i <= commentEndLine; i++) {
|
||||
m_firstTokenIdOfLine.at(i) = commentTokenId;
|
||||
}
|
||||
@@ -1525,43 +1465,8 @@ namespace hex::ui {
|
||||
currentLine = lineIndex;
|
||||
}
|
||||
|
||||
// if (lineIndex > currentLine) {
|
||||
// m_firstTokenIdOfLine[lineIndex] = tokenId;
|
||||
// }
|
||||
// }
|
||||
|
||||
if (tokenCount > 0 && (u32) m_firstTokenIdOfLine.back() != tokenCount - 1)
|
||||
m_firstTokenIdOfLine.push_back(tokenCount - 1);
|
||||
/*
|
||||
i32 lastTokenIdRestored;
|
||||
bool lastTokenIdChanged;
|
||||
i32 savedLineIndex;
|
||||
lineIndex = 0;
|
||||
while (lineIndex < (i32) size()) {
|
||||
if (m_firstTokenIdOfLine[lineIndex] == -1 && (operator[](lineIndex).empty() || operator[](lineIndex).m_chars.find_first_not_of(" ") == std::string::npos || operator[](lineIndex).m_chars.starts_with("#"))) {
|
||||
if (lastTokenIdChanged)
|
||||
savedLineIndex = lineIndex;
|
||||
lastTokenIdChanged = false;
|
||||
lineIndex++;
|
||||
} else if (m_firstTokenIdOfLine[lineIndex] != -1 && !operator[](lineIndex).empty() && operator[](lineIndex).m_chars.find_first_not_of(" ") != std::string::npos && !operator[](lineIndex).m_chars.starts_with("#")) {
|
||||
tokenId = m_firstTokenIdOfLine[lineIndex];
|
||||
if (tokenId != lastTokenIdRestored)
|
||||
lastTokenIdChanged = true;
|
||||
lineIndex++;
|
||||
} else if (m_firstTokenIdOfLine[lineIndex] == -1 && !operator[](lineIndex).empty() && operator[](lineIndex).m_chars.find_first_not_of(" ") != std::string::npos && !operator[](lineIndex).m_chars.starts_with("#")) {
|
||||
m_firstTokenIdOfLine[lineIndex] = tokenId;
|
||||
if (!lastTokenIdChanged) {
|
||||
for (i32 i = savedLineIndex; i < lineIndex; i++)
|
||||
m_firstTokenIdOfLine[i] = tokenId;
|
||||
}
|
||||
if (tokenId != lastTokenIdRestored) {
|
||||
lastTokenIdRestored = tokenId;
|
||||
lastTokenIdChanged = true;
|
||||
}
|
||||
lineIndex++;
|
||||
} else
|
||||
lineIndex ++;
|
||||
}*/
|
||||
|
||||
}
|
||||
|
||||
@@ -1572,6 +1477,25 @@ namespace hex::ui {
|
||||
return m_tokens[tokenId].location;
|
||||
}
|
||||
|
||||
i32 TextEditor::Lines::getTokenId(hex::ui::TextEditor::SafeTokenIterator tokenIterator) {
|
||||
auto start = m_tokens.data();
|
||||
auto m_start = &tokenIterator.front();
|
||||
auto m_end = &tokenIterator.back();
|
||||
if (m_start < start || start > m_end) {
|
||||
throw std::out_of_range("iterator out of range");
|
||||
}
|
||||
return m_start - start;
|
||||
}
|
||||
|
||||
i32 TextEditor::Lines::getTokenId() {
|
||||
auto start = m_tokens.data();
|
||||
auto m_start = &m_curr.front();
|
||||
auto m_end = &m_curr.back();
|
||||
if (m_start < start || start > m_end) {
|
||||
throw std::out_of_range("iterator out of range");
|
||||
}
|
||||
return m_start - start;
|
||||
}
|
||||
|
||||
// Get the token index for a given location.
|
||||
i32 TextEditor::Lines::getTokenId(pl::core::Location location) {
|
||||
@@ -1597,9 +1521,9 @@ namespace hex::ui {
|
||||
return -1;
|
||||
|
||||
for (i32 i = tokenStart; i <= tokenEnd; i++) {
|
||||
auto length = m_tokens[i].location.length;
|
||||
if (m_tokens[i].location.column + length + (length == 0) > location.column)
|
||||
return i;
|
||||
auto location2 = m_tokens[i].location;
|
||||
if (location2.column <= location.column && location2.column + location2.length >= location.column)
|
||||
return i + 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
namespace hex::ui {
|
||||
|
||||
|
||||
using Coordinates = TextEditor::Coordinates;
|
||||
using Coordinates = TextEditor::Coordinates;
|
||||
using Segments = TextEditor::Segments;
|
||||
|
||||
TextEditor::Line TextEditor::Line::trim(TrimMode trimMode) {
|
||||
if (m_chars.empty())
|
||||
@@ -59,12 +60,11 @@ namespace hex::ui {
|
||||
}
|
||||
|
||||
i32 TextEditor::Line::stringTextSize(const std::string &str) const {
|
||||
i32 result = 0;
|
||||
if (str.empty())
|
||||
return 0;
|
||||
if (ImGui::GetFont() == nullptr) {
|
||||
fonts::CodeEditor().push();
|
||||
result = ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, str.c_str(), nullptr, nullptr).x;
|
||||
i32 result = ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, str.c_str(), nullptr, nullptr).x;
|
||||
fonts::CodeEditor().pop();
|
||||
return result;
|
||||
}
|
||||
@@ -184,15 +184,13 @@ namespace hex::ui {
|
||||
auto lineSize = m_lines.size();
|
||||
if (position.y > m_lines.getLineStartScreenPos(0, lineIndexToRow(lineSize - 1)).y + m_lines.m_charAdvance.y)
|
||||
return m_lines.lineCoordinates( -1, -1);
|
||||
//if (position.y > m_lines.m_lineIndexToScreen[lineSize - 1].y + m_charAdvance.y)
|
||||
// return m_lines.lineCoordinates( -1, -1);
|
||||
|
||||
auto local = position - m_lines.m_cursorScreenPosition;
|
||||
auto row = screenPosToRow(position);
|
||||
|
||||
Coordinates result = lineCoordinates(0,0);
|
||||
i32 lineIndex= rowToLineIndex((i32) std::floor(row));
|
||||
if (lineIndex < 0 || lineIndex >= (i32) m_lines.size())
|
||||
if (lineIndex < 0 || lineIndex >= m_lines.size())
|
||||
return Invalid;
|
||||
result.m_line = lineIndex;
|
||||
if (m_lines.m_codeFoldKeyLineMap.contains(lineIndex) || m_lines.m_codeFoldValueLineMap.contains(lineIndex)) {
|
||||
@@ -204,7 +202,6 @@ namespace hex::ui {
|
||||
|
||||
|
||||
auto &line = m_lines[result.m_line].m_chars;
|
||||
//local.x -= (m_leftMargin - 5_scaled);
|
||||
i32 count = 0;
|
||||
u64 length;
|
||||
i32 increase;
|
||||
@@ -218,7 +215,7 @@ namespace hex::ui {
|
||||
result = m_lines.lineIndexCoords(lineIndex + 1, count - increase);
|
||||
result = m_lines.foldedToUnfoldedCoords(result);
|
||||
if (result == Invalid)
|
||||
return Coordinates(0, 0);
|
||||
return {0, 0};
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -239,13 +236,13 @@ namespace hex::ui {
|
||||
}
|
||||
|
||||
Coordinates TextEditor::Lines::lineIndexCoords(i32 lineNumber, i32 stringIndex) {
|
||||
if (lineNumber < 1 || lineNumber > (i32) size())
|
||||
if (lineNumber < 1 || lineNumber > size())
|
||||
return lineCoordinates( 0, 0);
|
||||
auto &line = operator[](lineNumber - 1);
|
||||
return lineCoordinates(lineNumber - 1, line.indexColumn(stringIndex));
|
||||
}
|
||||
|
||||
std::vector<Coordinates> TextEditor::Lines::unfoldedEllipsisCoordinates(Range delimiterCoordinates) {
|
||||
Segments TextEditor::Lines::unfoldedEllipsisCoordinates(Range delimiterCoordinates) {
|
||||
|
||||
auto lineStart = m_unfoldedLines[delimiterCoordinates.m_start.m_line];
|
||||
auto row = lineIndexToRow(delimiterCoordinates.m_start.m_line);
|
||||
@@ -281,7 +278,7 @@ namespace hex::ui {
|
||||
|
||||
auto totalUnfoldedSpan = unfoldedSpan1 + unfoldedSpan2 + unfoldedSpan3;
|
||||
if (totalUnfoldedSpan < 2.0f) {
|
||||
std::vector<Coordinates> unfoldedEllipsisCoordinates(2);
|
||||
Segments unfoldedEllipsisCoordinates(2);
|
||||
unfoldedEllipsisCoordinates[0] = lineCoordinates( delimiterCoordinates.m_start.m_line, delimiterCoordinates.m_start.m_column + 1);
|
||||
unfoldedEllipsisCoordinates[1] = delimiterCoordinates.m_end;
|
||||
return unfoldedEllipsisCoordinates;
|
||||
@@ -289,7 +286,7 @@ namespace hex::ui {
|
||||
|
||||
float spanFragment = totalUnfoldedSpan / 2.0f;
|
||||
|
||||
std::vector<Coordinates> unfoldedEllipsisCoordinates(4);
|
||||
Segments unfoldedEllipsisCoordinates(4);
|
||||
if (adddsBothEnds) {
|
||||
unfoldedEllipsisCoordinates[0] = lineCoordinates(delimiterCoordinates.m_start.m_line, delimiterCoordinates.m_start.m_column + 1);
|
||||
unfoldedEllipsisCoordinates[3] = delimiterCoordinates.m_end;
|
||||
@@ -369,7 +366,7 @@ namespace hex::ui {
|
||||
if (foundIndex % 2) {
|
||||
|
||||
Range delimiterRange = foldedLine.findDelimiterCoordinates(key);
|
||||
std::vector<Coordinates> unfoldedEllipsisCoordinates = this->unfoldedEllipsisCoordinates(delimiterRange);
|
||||
Segments unfoldedEllipsisCoordinates = this->unfoldedEllipsisCoordinates(delimiterRange);
|
||||
|
||||
if (unfoldedEllipsisCoordinates.size() > 2)
|
||||
return unfoldedEllipsisCoordinates[coords.m_column - foldedLine.m_ellipsisIndices[foundIndex / 2]];
|
||||
@@ -401,9 +398,9 @@ namespace hex::ui {
|
||||
Coordinates TextEditor::nextCoordinate(TextEditor::Coordinates coordinate) {
|
||||
auto line = m_lines[coordinate.m_line];
|
||||
if (line.isEndOfLine(coordinate.m_column))
|
||||
return Coordinates(coordinate.m_line + 1, 0);
|
||||
return {coordinate.m_line + 1, 0};
|
||||
else
|
||||
return Coordinates(coordinate.m_line,coordinate.m_column + 1);
|
||||
return {coordinate.m_line,coordinate.m_column + 1};
|
||||
}
|
||||
bool TextEditor::testfoldMaps(TextEditor::Range toTest) {
|
||||
bool result = true;
|
||||
@@ -454,7 +451,7 @@ namespace hex::ui {
|
||||
if (foundIndex % 2) {
|
||||
result.m_column = foldedLine.m_ellipsisIndices[foundIndex / 2];
|
||||
Range delimiterRange = foldedLine.findDelimiterCoordinates(key);
|
||||
std::vector<Coordinates> unfoldedEllipsisCoordinates = this->unfoldedEllipsisCoordinates(delimiterRange);
|
||||
Segments unfoldedEllipsisCoordinates = this->unfoldedEllipsisCoordinates(delimiterRange);
|
||||
|
||||
if (unfoldedEllipsisCoordinates.size() > 2) {
|
||||
if (coords == unfoldedEllipsisCoordinates[0])
|
||||
|
||||
Reference in New Issue
Block a user