Made code faster and cleaned some code.

This commit is contained in:
paxcut
2026-01-16 08:25:33 -07:00
committed by paxcut
parent 0e2d7ee3bc
commit 219f588cbe
12 changed files with 928 additions and 1085 deletions

View File

@@ -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 &currentTokenId, 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 &currentTokenId, Location &location) {
void TextEditor::Lines::incrementTokenId(i32 &lineIndex, i32 &currentTokenId, Location &location) {
currentTokenId++;
m_curr = m_startToken + currentTokenId;
location = m_curr->location;
lineIndex = location.line - 1;
}
void TextEditor::Lines::moveToLocationColumn(i32 locationColumn, i32 &currentTokenId, Location &location) {
location.column = locationColumn;
location.length = 1;
if (currentTokenId = getTokenId(location); currentTokenId < 0)
void TextEditor::Lines::moveToStringIndex(i32 stringIndex, i32 &currentTokenId, 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 &currentTokenId, 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;

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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();
}
}

View File

@@ -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;
}

View File

@@ -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])