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

@@ -4,6 +4,7 @@
#include <pl/helpers/safe_iterator.hpp>
#include <ui/text_editor.hpp>
#include <hex/helpers/types.hpp>
#include <utility>
namespace hex::plugin::builtin {
class ViewPatternEditor;
@@ -48,13 +49,13 @@ namespace hex::plugin::builtin {
bool operator>=(const TokenInterval &other) const {
return m_end >= other.m_end;
}
bool contains(const TokenInterval &other) const {
[[nodiscard]] bool contains(const TokenInterval &other) const {
return other.m_start >= m_start && other.m_end <= m_end;
}
bool contains(i32 value) const {
[[nodiscard]] bool contains(i32 value) const {
return value >= m_start && value <= m_end;
}
bool contiguous(const TokenInterval &other) const {
[[nodiscard]] bool contiguous(const TokenInterval &other) const {
auto highEndDiff = m_start - other.m_end;
auto lowEndDiff = other.m_start - m_end;
return highEndDiff == 0 || highEndDiff == 1 || lowEndDiff == 0 || lowEndDiff == 1;
@@ -75,10 +76,11 @@ namespace hex::plugin::builtin {
using OrderedBlocks = std::map<TokenInterval,std::string>;
using Scopes = std::set<TokenInterval>;
using Location = pl::core::Location;
using VectorString = std::vector<std::string>;
using TokenIter = pl::hlp::SafeIterator<std::vector<Token>::const_iterator>;
using StringVector = std::vector<std::string>;
using StringSet = std::set<std::string>;
using SafeTokenIterator = pl::hlp::SafeIterator<std::vector<Token>::const_iterator>;
using VariableScopes = std::map<std::string,Scopes>;
using Inheritances = std::map<std::string,VectorString>;
using Inheritances = std::map<std::string,StringSet>;
using IdentifierTypeColor = std::map<Identifier::IdentifierType,ui::TextEditor::PaletteIndex>;
using TokenTypeColor = std::map<Token::Type,ui::TextEditor::PaletteIndex>;
using TokenColor = std::map<i32, ui::TextEditor::PaletteIndex>;
@@ -88,17 +90,18 @@ namespace hex::plugin::builtin {
using CompileErrors = std::vector<CompileError>;
using TokenSequence = std::vector<Token>;
using TokenIdVector = std::vector<i32>;
using TokenIdSet = std::set<i32>;
using Instances = std::map<std::string,std::vector<i32>>;
using CodeFoldBlocks = ui::TextEditor::CodeFoldBlocks;
struct ParentDefinition;
struct Definition {
Definition()= default;
Definition(IdentifierType identifierType, std::string typeStr,i32 tokenId, Location location) : idType(identifierType), typeStr(typeStr), tokenIndex(tokenId),location(location) {}
IdentifierType idType;
Definition(IdentifierType identifierType, std::string typeStr,i32 tokenId, Location location) : idType(identifierType), typeStr(std::move(typeStr)), tokenIndex(tokenId),location(location) {}
IdentifierType idType{};
std::string typeStr;
i32 tokenIndex;
Location location;
i32 tokenIndex{};
Location location{};
};
struct ParentDefinition {
@@ -114,13 +117,13 @@ namespace hex::plugin::builtin {
private:
TextHighlighter *m_textHighlighter;
Types definedTypes;
VectorString usedNamespaces;
StringVector usedNamespaces;
ParsedImports parsedImports;
Str2StrMap importedHeaders;
TokenSequence fullTokens;
std::string editedText;
CompileErrors compileErrors;
VectorString linesOfColors;
StringVector linesOfColors;
public:
RequiredInputs() : m_textHighlighter(nullptr) {};
explicit RequiredInputs(TextHighlighter *textHighlighter) : m_textHighlighter(textHighlighter) {}
@@ -140,9 +143,9 @@ namespace hex::plugin::builtin {
inline static const Coordinates Invalid = Coordinates(0x80000000, 0x80000000);
private:
VectorString m_lines;
StringVector m_lines;
TokenIdVector m_firstTokenIdOfLine;
ViewPatternEditor *m_viewPatternEditor;
ViewPatternEditor *m_viewPatternEditor{};
TokenColor m_tokenColors;
@@ -166,14 +169,15 @@ namespace hex::plugin::builtin {
Str2StrMap m_typeDefMap;
Str2StrMap m_typeDefInvMap;
VectorString m_UDTs;
std::set<i32> m_taggedIdentifiers;
std::set<i32> m_memberChains;
std::set<i32> m_scopeChains;
StringVector m_UDTs;
TokenIdSet m_taggedIdentifiers;
TokenIdSet m_memberChains;
TokenIdSet m_scopeChains;
TokenIdSet m_identifierTokenIds;
RequiredInputs m_requiredInputs;
TokenIter m_curr;
TokenIter m_startToken, m_originalPosition, m_partOriginalPosition;
SafeTokenIterator m_curr;
SafeTokenIterator m_startToken, m_originalPosition, m_partOriginalPosition;
VariableScopes m_UDTBlocks;
VariableScopes m_functionBlocks;
@@ -187,17 +191,13 @@ namespace hex::plugin::builtin {
constexpr static u32 Normal = 0;
constexpr static u32 Not = 1;
//std::atomic<bool> m_needsToUpdateColors = true;
//std::atomic<bool> m_wasInterrupted = false;
//std::atomic<bool> m_interrupt = false;
//std::atomic<bool> m_completed = false;
pl::PatternLanguage *getPatternLanguage();
void updateRequiredInputs();
RequiredInputs& getRequiredInputs();
ViewPatternEditor* getViewPatternEditor();
void setViewPatternEditor(ViewPatternEditor *viewPatternEditor);
void setTokenIds();
TextHighlighter();
~TextHighlighter();
explicit TextHighlighter(ViewPatternEditor *viewPatternEditor) : m_viewPatternEditor(viewPatternEditor) {}
@@ -298,8 +298,8 @@ namespace hex::plugin::builtin {
bool findIdentifierDefinition(Definition &result, const std::string &optionalIdentifierName = "", std::string optionalName = "", bool optional = false);
/// To deal with the Parent keyword
std::optional<Definition> setChildrenTypes();
bool findParentTypes(VectorString &parentTypes, const std::string &optionalName="");
bool findAllParentTypes(VectorString &parentTypes, std::vector<Identifier *> &identifiers, std::string &optionalFullName);
bool findParentTypes(StringVector &parentTypes, const std::string &optionalName="");
bool findAllParentTypes(StringVector &parentTypes, std::vector<Identifier *> &identifiers, std::string &optionalFullName);
bool tryParentType(const std::string &parentType, std::string &variableName, std::optional<Definition> &result, std::vector<Identifier *> &identifiers);
/// Convenience function
bool isTokenIdValid(i32 tokenId);
@@ -312,6 +312,8 @@ namespace hex::plugin::builtin {
pl::core::Location getLocation(i32 tokenId);
/// Calculate the token index of a source code, line and column numbers
i32 getTokenId(pl::core::Location location);
i32 getTokenId(SafeTokenIterator tokenIterator);
i32 getTokenId();
/// Calculate the function or template argument position from token indices
i32 getArgumentNumber(i32 start,i32 arg);
/// Calculate the token index of a function or template argument position
@@ -322,18 +324,18 @@ namespace hex::plugin::builtin {
/// The following functions were copied from the parser and some were modified
template<typename T> T *getValue(const i32 index);
template<typename T> T *getValue(i32 index);
void next(i32 count = 1);
bool begin();
void partBegin();
void reset();
void partReset();
bool resetIfFailed(const bool value) ;
bool resetIfFailed(bool value) ;
template<auto S = Normal> bool sequenceImpl();
template<auto S = Normal> bool matchOne(const Token &token);
template<auto S = Normal> bool sequenceImpl(const auto &... args);
template<auto S = Normal> bool sequence(const Token &token, const auto &... args);
bool isValid();
bool peek(const Token &token, const i32 index = 0);
bool peek(const Token &token, i32 index = 0);
};
}

View File

@@ -140,7 +140,7 @@ namespace hex::plugin::builtin {
PerProvider<ui::TextEditor::Coordinates> m_cursorPosition;
PerProvider<ImVec2> m_scroll;
PerProvider<ImVec2> m_consoleScroll;
PerProvider<ui::TextEditor::CodeFoldState> m_codeFoldState;
PerProvider<ui::TextEditor::Coordinates> m_consoleCursorPosition;
PerProvider<ui::TextEditor::Range> m_selection;
PerProvider<ui::TextEditor::Range> m_consoleSelection;

View File

@@ -1,7 +1,6 @@
#include <algorithm>
#include <content/text_highlighting/pattern_language.hpp>
#include <pl/core/ast/ast_node_type_decl.hpp>
#include <pl/core/ast/ast_node_enum.hpp>
#include <pl/core/tokens.hpp>
#include <hex/helpers/utils.hpp>
#include <wolv/utils/string.hpp>
@@ -26,6 +25,7 @@ namespace hex::plugin::builtin {
using TokenInterval = TextHighlighter::TokenInterval;
using CodeFoldBlocks = TextHighlighter::CodeFoldBlocks;
using Coordinates = TextHighlighter::Coordinates;
using StringSet = TextHighlighter::StringSet;
void TextHighlighter::next(i32 count) {
if (m_viewPatternEditor->interrupted()) {
@@ -34,7 +34,7 @@ namespace hex::plugin::builtin {
}
if (count == 0)
return;
i32 id = getTokenId(m_curr->location);
i32 id = getTokenId();
i32 maxChange;
if (count > 0)
maxChange = std::min(count,static_cast<i32>(m_requiredInputs.fullTokens.size() - id));
@@ -48,12 +48,12 @@ namespace hex::plugin::builtin {
}
void TextHighlighter::RequiredInputs::setTypes() {
auto &types = m_textHighlighter->getPatternLanguage()->getInternals().parser.get()->getTypes();
auto &types = m_textHighlighter->getPatternLanguage()->getInternals().parser->getTypes();
std::ranges::copy(types.begin(), types.end(), std::inserter(definedTypes, definedTypes.begin()));
}
void TextHighlighter::RequiredInputs::setNamespaces() {
auto &namespaces = m_textHighlighter->getPatternLanguage()->getInternals().preprocessor.get()->getNamespaces();
auto &namespaces = m_textHighlighter->getPatternLanguage()->getInternals().preprocessor->getNamespaces();
usedNamespaces.resize(namespaces.size());
std::ranges::copy(namespaces, usedNamespaces.begin());
}
@@ -78,14 +78,14 @@ namespace hex::plugin::builtin {
if (editor == nullptr)
return;
fullTokens.clear();
auto &result = m_textHighlighter->getPatternLanguage()->getInternals().preprocessor.get()->getResult();
auto &result = m_textHighlighter->getPatternLanguage()->getInternals().preprocessor->getResult();
std::ranges::copy(result.begin(),result.end(),std::back_inserter(fullTokens));
editedText = editor->getText();
m_textHighlighter->loadText();;
linesOfColors.clear();
for (auto &line : m_textHighlighter->m_lines)
linesOfColors.push_back(std::string(line.size(), ' '));
linesOfColors.emplace_back(line.size(), ' ');
}
void TextHighlighter::RequiredInputs::setCompileErrors() {
@@ -202,15 +202,13 @@ namespace hex::plugin::builtin {
return false;
return false;
}
if (!isLocationValid(token.location))
return false;
return true;
return isLocationValid(token.location);
}
bool TextHighlighter::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_requiredInputs.fullTokens.size())
return false;
return m_curr[index].type == token.type && m_curr[index] == token.value;
@@ -239,14 +237,14 @@ namespace hex::plugin::builtin {
return false;
}
TextHighlighter::TextHighlighter() {}
TextHighlighter::~TextHighlighter() {}
TextHighlighter::TextHighlighter() = default;
TextHighlighter::~TextHighlighter() = default;
// Returns a chain of identifiers like a.b.c or a::b::c
bool TextHighlighter::getFullName(std::string &identifierName, std::vector<Identifier *> &identifiers, bool preserveCurr) {
Identifier *identifier = nullptr;
if (!peek(tkn::Literal::Identifier) || getTokenId(m_curr->location) < 1)
if (!peek(tkn::Literal::Identifier) || getTokenId() < 1)
return getIdentifierName(identifierName, identifier);
forwardIdentifierName(identifierName, identifiers, preserveCurr);
@@ -374,7 +372,7 @@ namespace hex::plugin::builtin {
while (m_curr != m_startToken + interval.m_end) {
if (sequence(tkn::Separator::LeftBrace)) {
auto tokenId = getTokenId(m_curr[-1].location);
auto tokenId = getTokenId() - 1;
tokenStack.push_back(tokenId);
nestedLevel++;
} else if (sequence(tkn::Separator::RightBrace)) {
@@ -382,7 +380,7 @@ namespace hex::plugin::builtin {
if (tokenStack.empty())
return result;
TokenInterval range(tokenStack.back(), getTokenId(m_curr[-1].location));
TokenInterval range(tokenStack.back(), getTokenId() - 1);
tokenStack.pop_back();
result.push_back(range);
@@ -405,7 +403,7 @@ namespace hex::plugin::builtin {
OrderedBlocks &tokenRangeInv, bool fullName, VariableScopes *blocks) {
bool addArgumentBlock = !fullName;
if (getTokenId(m_curr->location) < 1)
if (getTokenId() < 1)
return false;
std::string name;
if (fullName) {
@@ -417,7 +415,7 @@ namespace hex::plugin::builtin {
if (!getIdentifierName(name, identifier))
return false;
std::string nameSpace;
findNamespace(nameSpace, getTokenId(m_curr->location));
findNamespace(nameSpace, getTokenId());
if (!nameSpace.empty())
name = fmt::format("{}::{}", nameSpace, name);
}
@@ -433,7 +431,7 @@ namespace hex::plugin::builtin {
if (!getFullName(identifierName, identifiers, false))
break;
if (std::ranges::find(m_inheritances[name], identifierName) == m_inheritances[name].end())
m_inheritances[name].push_back(identifierName);
m_inheritances[name].insert(identifierName);
skipTemplate(200);
next(2);
}
@@ -442,7 +440,7 @@ namespace hex::plugin::builtin {
m_curr = saveCurr;
if (peek(tkn::ValueType::Auto))
next(-1);
i32 index1 = getTokenId(m_curr->location);
i32 index1 = getTokenId();
bool result = true;
for (const auto &keyword: keywords)
result = result && !peek(keyword);
@@ -455,7 +453,7 @@ namespace hex::plugin::builtin {
//if (peek(tkn::Separator::EndOfProgram),-1)
// return false;
i32 index2 = getTokenId(m_curr->location);
i32 index2 = getTokenId();
if (index2 > index1 && index2 < tokenCount) {
if (fullName) {
@@ -483,42 +481,36 @@ namespace hex::plugin::builtin {
Identifier *identifier;
IdentifierType identifierType;
m_startToken = TokenIter(m_requiredInputs.fullTokens.begin(), m_requiredInputs.fullTokens.end());
auto endToken = TokenIter(m_requiredInputs.fullTokens.end(), m_requiredInputs.fullTokens.end());
for (m_curr = m_startToken; endToken > m_curr; next()) {
auto curr = m_curr;
m_startToken = SafeTokenIterator(m_requiredInputs.fullTokens.begin(), m_requiredInputs.fullTokens.end());
for (auto tokenId : m_identifierTokenIds) {
m_curr = m_startToken + tokenId;
if (identifier = getValue<Identifier>(0); identifier != nullptr) {
identifierType = identifier->getType();
auto& name = identifier->get();
if (peek(tkn::Literal::Identifier)) {
if (identifier = getValue<Identifier>(0); identifier != nullptr) {
identifierType = identifier->getType();
auto& name = identifier->get();
if (identifierType == identifierTypeToSearch) {
switch (identifierType) {
case IdentifierType::Function:
if (!m_functionTokenRange.contains(name))
getTokenRange({tkn::Keyword::Function}, m_functionTokenRange, m_namespaceTokenRange, false, &m_functionBlocks);
break;
case IdentifierType::NameSpace:
if (std::ranges::find(m_requiredInputs.usedNamespaces, name) == m_requiredInputs.usedNamespaces.end())
m_requiredInputs.usedNamespaces.push_back(name);
getTokenRange({tkn::Keyword::Namespace}, m_functionTokenRange, m_namespaceTokenRange, true, nullptr);
break;
case IdentifierType::UDT:
if (!m_UDTTokenRange.contains(name))
getTokenRange({tkn::Keyword::Struct, tkn::Keyword::Union, tkn::Keyword::Enum, tkn::Keyword::Bitfield}, m_UDTTokenRange, m_namespaceTokenRange, false, &m_UDTBlocks);
break;
case IdentifierType::Attribute:
linkAttribute();
break;
default:
break;
}
if (identifierType == identifierTypeToSearch) {
switch (identifierType) {
case IdentifierType::Function:
if (!m_functionTokenRange.contains(name))
getTokenRange({tkn::Keyword::Function}, m_functionTokenRange, m_namespaceTokenRange, false, &m_functionBlocks);
break;
case IdentifierType::NameSpace:
if (std::ranges::find(m_requiredInputs.usedNamespaces, name) == m_requiredInputs.usedNamespaces.end())
m_requiredInputs.usedNamespaces.push_back(name);
getTokenRange({tkn::Keyword::Namespace}, m_functionTokenRange, m_namespaceTokenRange, true, nullptr);
break;
case IdentifierType::UDT:
if (!m_UDTTokenRange.contains(name))
getTokenRange({tkn::Keyword::Struct, tkn::Keyword::Union, tkn::Keyword::Enum, tkn::Keyword::Bitfield}, m_UDTTokenRange, m_namespaceTokenRange, false, &m_UDTBlocks);
break;
case IdentifierType::Attribute:
linkAttribute();
break;
default:
break;
}
}
} else if (peek(tkn::Separator::EndOfProgram))
return;
m_curr = curr;
}
}
}
@@ -529,7 +521,7 @@ namespace hex::plugin::builtin {
if (!isValid())
return;
i32 tokenId = getTokenId(m_curr->location);
i32 tokenId = getTokenId();
auto tokenCount = m_requiredInputs.fullTokens.size();
if (tokenId == -1 || tokenId >= (i32) tokenCount-1)
@@ -559,12 +551,12 @@ namespace hex::plugin::builtin {
if (peek(tkn::Separator::Dot,1) && peek(tkn::Literal::Identifier,2) )
m_memberChains.insert(getTokenId(m_curr->location));
m_memberChains.insert(getTokenId());
else if (peek(tkn::Operator::ScopeResolution,1) && peek(tkn::Literal::Identifier,2))
m_scopeChains.insert(getTokenId(m_curr->location));
m_scopeChains.insert(getTokenId());
else
m_taggedIdentifiers.insert(getTokenId(m_curr->location));
m_taggedIdentifiers.insert(getTokenId());
}
next(increment);
skipCount++;
@@ -636,7 +628,7 @@ namespace hex::plugin::builtin {
if (findIdentifierDefinition(definition, currentName)) {
variableParentType = definition.typeStr;
auto tokenIndex = getTokenId(m_curr->location);
auto tokenIndex = getTokenId();
setIdentifierColor(tokenIndex, definition.idType);
skipArray(200, true);
next();
@@ -651,7 +643,7 @@ namespace hex::plugin::builtin {
if (findIdentifierDefinition(result, currentName, variableParentType)) {
variableParentType = result.typeStr;
auto tokenIndex = getTokenId(m_curr->location);
auto tokenIndex = getTokenId();
setIdentifierColor(tokenIndex, result.idType);
skipArray(200, true);
next();
@@ -671,7 +663,7 @@ namespace hex::plugin::builtin {
variableParentType = currentName;
if (!nameSpace.empty() && !variableParentType.contains(nameSpace))
variableParentType = nameSpace + variableParentType;
variableParentType.insert(0, nameSpace);
else if (findNamespace(nameSpace) && !variableParentType.contains(nameSpace))
variableParentType = fmt::format("{}::{}", nameSpace, variableParentType);
@@ -680,7 +672,7 @@ namespace hex::plugin::builtin {
if (findIdentifierDefinition(result, currentName, variableParentType)) {
variableParentType = result.typeStr;
auto tokenIndex = getTokenId(m_curr->location);
auto tokenIndex = getTokenId();
setIdentifierColor(tokenIndex, result.idType);
skipArray(200, true);
next();
@@ -720,7 +712,7 @@ namespace hex::plugin::builtin {
bool TextHighlighter::findIdentifierDefinition( Definition &result, const std::string &optionalIdentifierName, std::string optionalName, bool setInstances) {
auto curr = m_curr;
bool isFunction = false;
auto tokenId = getTokenId(m_curr->location);
auto tokenId = getTokenId();
std::vector<Definition> definitions;
std::string name = optionalName;
result.idType = IdentifierType::Unknown;
@@ -843,7 +835,7 @@ namespace hex::plugin::builtin {
if (auto *keyword = std::get_if<Keyword>(&m_requiredInputs.fullTokens.at(startingLineTokenIndex).value);
keyword != nullptr && *keyword == Keyword::Import) {
while (index < vectorString.size()) {
auto tokenIndex = getTokenId(m_curr->location);
auto tokenIndex = getTokenId();
setIdentifierColor(tokenIndex, IdentifierType::NameSpace);
next(2);
index++;
@@ -858,12 +850,12 @@ namespace hex::plugin::builtin {
if (findIdentifierDefinition(definition, currentName)) {
variableParentType = definition.typeStr;
auto tokenIndex = getTokenId(m_curr->location);
auto tokenIndex = getTokenId();
setIdentifierColor(tokenIndex, definition.idType);
skipArray(200, true);
next();
} else {
auto tokenIndex = getTokenId(m_curr->location);
auto tokenIndex = getTokenId();
setIdentifierColor(tokenIndex, IdentifierType::Unknown);
skipArray(200, true);
next();
@@ -878,7 +870,7 @@ namespace hex::plugin::builtin {
if (findIdentifierDefinition(result, currentName, variableParentType) && !brokenChain) {
variableParentType = result.typeStr;
auto tokenIndex = getTokenId(m_curr->location);
auto tokenIndex = getTokenId();
setIdentifierColor(tokenIndex, result.idType);
skipArray(200, true);
next();
@@ -901,7 +893,7 @@ namespace hex::plugin::builtin {
if (!templateName.empty() && findIdentifierDefinition(result, currentName, templateName) ) {
variableParentType = result.typeStr;
m_curr = saveCurr;
auto tokenIndex = getTokenId(m_curr->location);
auto tokenIndex = getTokenId();
setIdentifierColor(tokenIndex, result.idType);
skipArray(200, true);
next();
@@ -922,7 +914,7 @@ namespace hex::plugin::builtin {
if (!typeName.empty() && findIdentifierDefinition(result, currentName, typeName)) {
variableParentType = result.typeStr;
m_curr = saveCurr;
auto tokenIndex = getTokenId(m_curr->location);
auto tokenIndex = getTokenId();
setIdentifierColor(tokenIndex, result.idType);
skipArray(200, true);
next();
@@ -931,7 +923,7 @@ namespace hex::plugin::builtin {
}
} else {
brokenChain = true;
auto tokenIndex = getTokenId(m_curr->location);
auto tokenIndex = getTokenId();
setIdentifierColor(tokenIndex, IdentifierType::Unknown);
skipArray(200, true);
next();
@@ -1036,7 +1028,7 @@ namespace hex::plugin::builtin {
return true;
}
i32 index = getTokenId(m_curr->location);
i32 index = getTokenId();
if (index < (i32) tokenCount - 1 && index > 2) {
auto nextToken = m_curr[1];
@@ -1068,7 +1060,7 @@ namespace hex::plugin::builtin {
// finds the name of the token range that the given or the current token index is in.
bool TextHighlighter::findScope(std::string &name, const UnorderedBlocks &map, i32 optionalTokenId) {
auto tokenId = optionalTokenId ==-1 ? getTokenId(m_curr->location) : optionalTokenId;
auto tokenId = optionalTokenId ==-1 ? getTokenId() : optionalTokenId;
for (const auto &[scopeName, range]: map) {
@@ -1085,7 +1077,7 @@ namespace hex::plugin::builtin {
nameSpace = "";
for (auto [interval, name]: m_namespaceTokenRange) {
i32 tokenId = optionalTokenId == -1 ? getTokenId(m_curr->location) : optionalTokenId;
i32 tokenId = optionalTokenId == -1 ? getTokenId() : optionalTokenId;
if (tokenId > interval.m_start && tokenId < interval.m_end) {
@@ -1288,8 +1280,8 @@ namespace hex::plugin::builtin {
} else {
auto curr = m_curr;
for (const auto &[name, range] : m_UDTTokenRange) {
auto startToken = TokenIter(m_requiredInputs.fullTokens.begin()+range.m_start,m_requiredInputs.fullTokens.begin()+range.m_end);
auto endToken = TokenIter(m_requiredInputs.fullTokens.begin()+range.m_end,m_requiredInputs.fullTokens.end());
auto startToken = SafeTokenIterator(m_requiredInputs.fullTokens.begin() + range.m_start, m_requiredInputs.fullTokens.begin() + range.m_end);
auto endToken = SafeTokenIterator(m_requiredInputs.fullTokens.begin() + range.m_end, m_requiredInputs.fullTokens.end());
for ( m_curr = startToken; endToken > m_curr; next()) {
if (auto *identifier = std::get_if<Identifier>(&m_curr->value); identifier != nullptr) {
@@ -1467,14 +1459,9 @@ namespace hex::plugin::builtin {
// od every instance of the variable name in the code.
void TextHighlighter::setInitialColors() {
m_startToken = m_originalPosition = m_partOriginalPosition = TokenIter(m_requiredInputs.fullTokens.begin(), m_requiredInputs.fullTokens.end());
auto endToken = TokenIter(m_requiredInputs.fullTokens.end(), m_requiredInputs.fullTokens.end());
for (m_curr = m_startToken; endToken > m_curr; next()) {
if (peek(tkn::Separator::EndOfProgram))
return;
m_startToken = m_originalPosition = m_partOriginalPosition = SafeTokenIterator(m_requiredInputs.fullTokens.begin(), m_requiredInputs.fullTokens.end());
for (auto tokenId : m_identifierTokenIds) {
m_curr = m_startToken + tokenId;
if (auto identifier = getValue<Identifier>(0); identifier != nullptr) {
if (auto identifierType = identifier->getType(); identifierType != IdentifierType::Unknown && identifierType != IdentifierType::MemberUnknown &&identifierType != IdentifierType::FunctionUnknown && identifierType != IdentifierType::ScopeResolutionUnknown)
@@ -1483,104 +1470,111 @@ namespace hex::plugin::builtin {
}
}
void TextHighlighter::setTokenIds() {
m_identifierTokenIds.clear();
m_startToken = m_originalPosition = m_partOriginalPosition = SafeTokenIterator(m_requiredInputs.fullTokens.begin(), m_requiredInputs.fullTokens.end());
auto endToken = SafeTokenIterator(m_requiredInputs.fullTokens.end(), m_requiredInputs.fullTokens.end());
m_curr = m_startToken;
while (endToken > m_curr) {
if (sequence(tkn::Literal::Identifier)) {
auto tokenId = getTokenId() - 1;
m_identifierTokenIds.insert(tokenId);
} else
next();
}
}
void TextHighlighter::loadInstances() {
std::map<std::string, std::vector<i32>> instances;
m_startToken = m_originalPosition = m_partOriginalPosition = TokenIter(m_requiredInputs.fullTokens.begin(), m_requiredInputs.fullTokens.end());
auto endToken = TokenIter(m_requiredInputs.fullTokens.end(), m_requiredInputs.fullTokens.end());
for (m_curr = m_startToken; endToken > m_curr; next()) {
m_startToken = m_originalPosition = m_partOriginalPosition = SafeTokenIterator(m_requiredInputs.fullTokens.begin(), m_requiredInputs.fullTokens.end());
for (auto identifierTokenId : m_identifierTokenIds) {
m_curr = m_startToken + identifierTokenId;
std::string name;
if (peek(tkn::Literal::Identifier)) {
std::string name;
if (auto identifier = getValue<Identifier>(0); identifier != nullptr) {
auto identifierType = identifier->getType();
if (auto identifier = getValue<Identifier>(0); identifier != nullptr) {
name = identifier->get();
if (auto identifierType = identifier->getType(); identifierType != IdentifierType::Unknown && identifierType != IdentifierType::MemberUnknown &&
identifierType != IdentifierType::FunctionUnknown && identifierType != IdentifierType::ScopeResolutionUnknown) {
name = identifier->get();
if (identifierType == IdentifierType::Typedef) {
auto curr = m_curr;
//std::string typeName = "";
skipTemplate(200, true);
next();
if (sequence(tkn::Operator::Assign, tkn::Literal::Identifier)) {
next(-1);
i32 fullNameTokenId = getTokenId(m_curr->location);
std::vector<Identifier *> identifiers;
std::string typeName;
if (!getFullName(typeName, identifiers, false)) {
auto identifier2 = getValue<Identifier>(0);
if (identifier2 != nullptr) {
typeName = identifier2->get();
}
} else {
auto count = std::count(typeName.begin(), typeName.end(), ':') >> 1;
for (auto i = 0; i < count; i++) {
setIdentifierColor(fullNameTokenId, IdentifierType::NameSpace);
fullNameTokenId += 2;
}
}
setIdentifierColor(fullNameTokenId, IdentifierType::UDT);
if (!m_typeDefMap.contains(name) && !typeName.empty()) {
m_typeDefMap[name] = typeName;
m_typeDefInvMap[typeName] = name;
}
auto start = m_curr;
skipTemplate(200, true);
auto end = m_curr;
for (m_curr = start; end > m_curr; next()) {
if (auto identifier2 = getValue<Identifier>(0); identifier2 != nullptr) {
auto tokenId = getTokenId(m_curr->location);
setIdentifierColor(tokenId, IdentifierType::TemplateArgument);
}
}
if (identifierType == IdentifierType::Typedef) {
auto curr = m_curr;
skipTemplate(200, true);
next();
if (sequence(tkn::Operator::Assign, tkn::Literal::Identifier)) {
next(-1);
i32 fullNameTokenId = getTokenId();
std::vector<Identifier *> identifiers;
std::string typeName;
if (!getFullName(typeName, identifiers, false)) {
auto identifier2 = getValue<Identifier>(0);
if (identifier2 != nullptr) {
typeName = identifier2->get();
}
m_curr = curr;
}
} else {
name = identifier->get();
auto curr = m_curr;
auto tokenIndex = getTokenId(m_curr->location);
skipArray(200, true);
next();
bool chainStarted = false;
while (sequence(tkn::Operator::ScopeResolution, tkn::Literal::Identifier)) {
if (identifier = getValue<Identifier>(-1); identifier != nullptr)
name += "::" + identifier->get();
std::string nameSpace;
if (!chainStarted) {
chainStarted = true;
m_scopeChains.insert(tokenIndex);
} else if (findNamespace(nameSpace) && !nameSpace.empty()) {
m_scopeChains.insert(tokenIndex);
}
curr = m_curr;
}
while (sequence(tkn::Separator::Dot, tkn::Literal::Identifier)) {
if (identifier = getValue<Identifier>(-1); identifier != nullptr)
name += "." + identifier->get();
if (!chainStarted) {
chainStarted = true;
m_memberChains.insert(tokenIndex);
}
skipArray(200, true);
curr = m_curr;
}
if (peek(tkn::Literal::Identifier)) {
std::string nameScape;
if (findNamespace(nameScape) && !nameScape.empty() && std::ranges::find(m_UDTs,(nameScape + "::" + name)) != m_UDTs.end()) {
m_scopeChains.insert(tokenIndex);
} else {
auto count = std::count(typeName.begin(), typeName.end(), ':') >> 1;
for (auto i = 0; i < count; i++) {
setIdentifierColor(fullNameTokenId, IdentifierType::NameSpace);
fullNameTokenId += 2;
}
}
setIdentifierColor(fullNameTokenId, IdentifierType::UDT);
if (!m_typeDefMap.contains(name) && !typeName.empty()) {
m_typeDefMap[name] = typeName;
m_typeDefInvMap[typeName] = name;
}
auto start = m_curr;
skipTemplate(200, true);
auto end = m_curr;
for (m_curr = start; end > m_curr; next()) {
if (auto identifier2 = getValue<Identifier>(0); identifier2 != nullptr) {
auto tokenId = getTokenId();
setIdentifierColor(tokenId, IdentifierType::TemplateArgument);
}
}
m_curr = curr;
}
m_curr = curr;
} else {
name = identifier->get();
auto curr = m_curr;
auto tokenIndex = getTokenId();
skipArray(200, true);
next();
bool chainStarted = false;
while (sequence(tkn::Operator::ScopeResolution, tkn::Literal::Identifier)) {
if (identifier = getValue<Identifier>(-1); identifier != nullptr)
name += "::" + identifier->get();
std::string nameSpace;
if (!chainStarted) {
chainStarted = true;
m_scopeChains.insert(tokenIndex);
} else if (findNamespace(nameSpace) && !nameSpace.empty()) {
m_scopeChains.insert(tokenIndex);
}
curr = m_curr;
}
while (sequence(tkn::Separator::Dot, tkn::Literal::Identifier)) {
if (identifier = getValue<Identifier>(-1); identifier != nullptr)
name += "." + identifier->get();
if (!chainStarted) {
chainStarted = true;
m_memberChains.insert(tokenIndex);
}
skipArray(200, true);
curr = m_curr;
}
if (peek(tkn::Literal::Identifier)) {
std::string nameScape;
if (findNamespace(nameScape) && !nameScape.empty() && std::ranges::find(m_UDTs, (nameScape + "::" + name)) != m_UDTs.end()) {
m_scopeChains.insert(tokenIndex);
}
}
m_curr = curr;
}
auto id = getTokenId(m_curr->location);
auto id = getTokenId();
if (instances.contains(name)) {
auto &nameInstances = instances[name];
@@ -1589,8 +1583,7 @@ namespace hex::plugin::builtin {
nameInstances.push_back(id);
} else
instances[name].push_back(id);
} else if (peek(tkn::Separator::EndOfProgram))
break;
}
}
m_instances = std::move(instances);
}
@@ -1603,6 +1596,26 @@ namespace hex::plugin::builtin {
return m_requiredInputs.fullTokens.at(tokenId).location;
}
i32 TextHighlighter::getTokenId(SafeTokenIterator tokenIterator) {
auto start = &m_requiredInputs.fullTokens[0];
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 TextHighlighter::getTokenId() {
auto start = &m_requiredInputs.fullTokens[0];
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 TextHighlighter::getTokenId(pl::core::Location location) {
@@ -1626,8 +1639,9 @@ namespace hex::plugin::builtin {
if (tokenStart == -1 || tokenEnd == -1 || tokenStart >= (i32) tokenCount)
return -1;
for (i32 i = tokenStart; i <= tokenEnd; i++) {
if (m_requiredInputs.fullTokens.at(i).location.column >= location.column)
return i;
auto location2 = m_requiredInputs.fullTokens[i].location;
if (location2.column <= location.column && location2.column + location2.length >= location.column)
return i + 1;
}
return -1;
}
@@ -1637,7 +1651,7 @@ namespace hex::plugin::builtin {
if (tokenId == -1) {
constToken = &m_curr[0];
tokenId = getTokenId(m_curr->location);
tokenId = getTokenId();
} else
constToken = &m_requiredInputs.fullTokens.at(tokenId);
@@ -1650,7 +1664,7 @@ namespace hex::plugin::builtin {
void TextHighlighter::setColor(i32 tokenId, const IdentifierType &type) {
if (tokenId == -1)
tokenId = getTokenId(m_curr->location);
tokenId = getTokenId();
setIdentifierColor(tokenId, type);
}
@@ -1661,22 +1675,17 @@ namespace hex::plugin::builtin {
taggedIdentifiers.push_back(index);
}
m_taggedIdentifiers.clear();
m_startToken = m_originalPosition = m_partOriginalPosition = TokenIter(m_requiredInputs.fullTokens.begin(), m_requiredInputs.fullTokens.end());
auto endToken = TokenIter(m_requiredInputs.fullTokens.end(), m_requiredInputs.fullTokens.end());
m_startToken = m_originalPosition = m_partOriginalPosition = SafeTokenIterator(m_requiredInputs.fullTokens.begin(), m_requiredInputs.fullTokens.end());
m_curr = m_startToken;
while (endToken > m_curr) {
if (peek(tkn::Separator::EndOfProgram))
return;
i32 tokenId = getTokenId(m_curr->location);
for (auto tokenId : m_identifierTokenIds) {
m_curr = m_startToken + tokenId;
if (!taggedIdentifiers.empty() && tokenId > taggedIdentifiers.back()) {
next(taggedIdentifiers.back() - tokenId);
taggedIdentifiers.pop_back();
}
if (sequence(tkn::Keyword::Import, tkn::Literal::Identifier)) {
next(-1);
if (peek(tkn::Keyword::Import, -1)) {
do {
if (auto identifier = const_cast<Identifier *>(getValue<Token::Identifier>(0)); identifier != nullptr) {
setIdentifierColor(-1, IdentifierType::NameSpace);
@@ -1698,97 +1707,81 @@ namespace hex::plugin::builtin {
}
}
}
if (peek(tkn::Separator::EndOfProgram))
return;
if (peek(tkn::Literal::Identifier)) {
auto identifier = getValue<Token::Identifier>(0);
Token::Identifier::IdentifierType identifierType;
if (identifier == nullptr) {
next();
continue;
}
identifierType = identifier->getType();
std::string variableName = identifier->get();
if (m_tokenColors.contains(tokenId) && (m_tokenColors.at(tokenId) != ui::TextEditor::PaletteIndex::Default && identifierType != IdentifierType::Unknown)) {
next();
continue;
}
Definition definition;
std::string nameSpace;
if (peek(tkn::Keyword::Parent, -2)) {
auto save = m_curr;
next(-2);
while (peek(tkn::Keyword::Parent, -2))
next(-2);
auto optional = setChildrenTypes();
if (optional.has_value())
setIdentifierColor(-1, optional->idType);
else {
m_curr = save;
setIdentifierColor(-1, IdentifierType::Unknown);
next();
continue;
}
m_curr = save;
next();
continue;
}
if (peek(tkn::Operator::ScopeResolution, 1)) {
if (std::ranges::find(m_requiredInputs.usedNamespaces, variableName) != m_requiredInputs.usedNamespaces.end()) {
setIdentifierColor(-1, IdentifierType::NameSpace);
next();
continue;
}
}
if (peek(tkn::Operator::ScopeResolution, -1)) {
auto save = m_curr;
next(-2);
if (auto parentIdentifier = const_cast<Identifier *>(getValue<Token::Identifier>(0)); parentIdentifier != nullptr) {
next(2);
if (parentIdentifier->getType() == IdentifierType::UDT) {
auto parentName = parentIdentifier->get();
auto typeName = findIdentifierType(variableName, parentName);
setIdentifierColor(-1, typeName);
}
}
m_curr = save;
next();
continue;
}
if (findIdentifierDefinition(definition)) {
identifierType = definition.idType;
setIdentifierColor(-1, identifierType);
next();
continue;
}
if (findNamespace(nameSpace,tokenId)) {
auto fullName = nameSpace + "::" + variableName;
auto typeName = findIdentifierType(fullName, "");
if (typeName != IdentifierType::Unknown) {
setIdentifierColor(-1, typeName);
next();
continue;
}
}
if (std::ranges::find(m_UDTs, variableName) != m_UDTs.end()) {
if (m_typeDefMap.contains(variableName))
setIdentifierColor(-1, IdentifierType::Typedef);
else
setIdentifierColor(-1, IdentifierType::UDT);
next();
continue;
}
if (peek(tkn::Keyword::From, -1)) {
setIdentifierColor(-1, IdentifierType::GlobalVariable);
next();
continue;
}
setIdentifierColor(-1, IdentifierType::Unknown);
next();
auto identifier = getValue<Token::Identifier>(0);
Token::Identifier::IdentifierType identifierType;
if (identifier == nullptr) {
continue;
}
next();
identifierType = identifier->getType();
std::string variableName = identifier->get();
if (m_tokenColors.contains(tokenId) && (m_tokenColors.at(tokenId) != ui::TextEditor::PaletteIndex::Default && identifierType != IdentifierType::Unknown)) {
continue;
}
Definition definition;
std::string nameSpace;
if (peek(tkn::Keyword::Parent, -2)) {
auto save = m_curr;
next(-2);
while (peek(tkn::Keyword::Parent, -2))
next(-2);
auto optional = setChildrenTypes();
if (optional.has_value())
setIdentifierColor(-1, optional->idType);
else {
m_curr = save;
setIdentifierColor(-1, IdentifierType::Unknown);
continue;
}
m_curr = save;
continue;
}
if (peek(tkn::Operator::ScopeResolution, 1)) {
if (std::ranges::find(m_requiredInputs.usedNamespaces, variableName) != m_requiredInputs.usedNamespaces.end()) {
setIdentifierColor(-1, IdentifierType::NameSpace);
continue;
}
}
if (peek(tkn::Operator::ScopeResolution, -1)) {
auto save = m_curr;
next(-2);
if (auto parentIdentifier = const_cast<Identifier *>(getValue<Token::Identifier>(0)); parentIdentifier != nullptr) {
next(2);
if (parentIdentifier->getType() == IdentifierType::UDT) {
auto parentName = parentIdentifier->get();
auto typeName = findIdentifierType(variableName, parentName);
setIdentifierColor(-1, typeName);
}
}
m_curr = save;
continue;
}
if (findIdentifierDefinition(definition)) {
identifierType = definition.idType;
setIdentifierColor(-1, identifierType);
continue;
}
if (findNamespace(nameSpace,tokenId)) {
auto fullName = nameSpace + "::" + variableName;
auto typeName = findIdentifierType(fullName, "");
if (typeName != IdentifierType::Unknown) {
setIdentifierColor(-1, typeName);
continue;
}
}
if (std::ranges::find(m_UDTs, variableName) != m_UDTs.end()) {
if (m_typeDefMap.contains(variableName))
setIdentifierColor(-1, IdentifierType::Typedef);
else
setIdentifierColor(-1, IdentifierType::UDT);
continue;
}
if (peek(tkn::Keyword::From, -1)) {
setIdentifierColor(-1, IdentifierType::GlobalVariable);
continue;
}
setIdentifierColor(-1, IdentifierType::Unknown);
}
}
@@ -1804,7 +1797,7 @@ namespace hex::plugin::builtin {
continue;
std::string &lineOfColors = m_requiredInputs.linesOfColors[line];//std::string(m_lines[line].size(), 0);
for (auto tokenIndex = m_firstTokenIdOfLine.at(line); tokenIndex < m_firstTokenIdOfLine.at(nextLine(line)); tokenIndex++) {
Token *token = const_cast<Token *>(&m_requiredInputs.fullTokens.at(tokenIndex));
auto *token = const_cast<Token *>(&m_requiredInputs.fullTokens.at(tokenIndex));
if (m_tokenColors.contains(tokenIndex) && token->type == Token::Type::Identifier) {
u8 color = (u8) m_tokenColors.at(tokenIndex);
u32 tokenLength = token->location.length;
@@ -1834,7 +1827,7 @@ namespace hex::plugin::builtin {
auto definitions = m_UDTVariables[inheritance];
if (definitions.empty())
definitions = m_ImportedUDTVariables[inheritance];
for (const auto &[variableName, variableDefinitions]: definitions) {
for (auto [variableName, variableDefinitions]: definitions) {
auto tokenRange = m_UDTTokenRange[name];
u32 tokenIndex = tokenRange.m_start;
for (auto token = tokenRange.m_start; token < tokenRange.m_end; token++) {
@@ -1860,7 +1853,7 @@ namespace hex::plugin::builtin {
// Get the string of the argument type. This works on function arguments and non-type template arguments.
std::string TextHighlighter::getArgumentTypeName(i32 rangeStart, Token delimiter2) {
auto curr = m_curr;
i32 parameterIndex = getArgumentNumber(rangeStart, getTokenId(m_curr->location));
i32 parameterIndex = getArgumentNumber(rangeStart, getTokenId());
Token delimiter;
std::string typeStr;
@@ -1918,16 +1911,14 @@ namespace hex::plugin::builtin {
}
if (length > (i32) m_lines[line].size()-col && m_firstTokenIdOfLine[line + 1] != -1)
return false;
return true;
return !(length > (i32) m_lines[line].size()-col && m_firstTokenIdOfLine[line + 1] != -1);
}
// Find the string of the variable type. This works on function variables, views,
// local variables as well as on calculated pointers and pattern variables.
std::string TextHighlighter::getVariableTypeName() {
auto curr = m_curr;
auto varTokenId = getTokenId(m_curr->location);
auto varTokenId = getTokenId();
if (!isTokenIdValid(varTokenId))
return "";
@@ -1983,11 +1974,11 @@ namespace hex::plugin::builtin {
// Definitions of global variables and placed variables.
void TextHighlighter::loadGlobalDefinitions(Scopes tokenRangeSet, std::vector<IdentifierType> identifierTypes, Variables &variables) {
m_startToken = m_originalPosition = m_partOriginalPosition = TokenIter(m_requiredInputs.fullTokens.begin(), m_requiredInputs.fullTokens.end());
m_startToken = m_originalPosition = m_partOriginalPosition = SafeTokenIterator(m_requiredInputs.fullTokens.begin(), m_requiredInputs.fullTokens.end());
for (auto range: tokenRangeSet) {
auto startToken = TokenIter(m_requiredInputs.fullTokens.begin()+range.m_start,m_requiredInputs.fullTokens.begin()+range.m_end);
auto endToken = TokenIter(m_requiredInputs.fullTokens.begin()+range.m_end,m_requiredInputs.fullTokens.end());
auto startToken = SafeTokenIterator(m_requiredInputs.fullTokens.begin() + range.m_start, m_requiredInputs.fullTokens.begin() + range.m_end);
auto endToken = SafeTokenIterator(m_requiredInputs.fullTokens.begin() + range.m_end, m_requiredInputs.fullTokens.end());
for ( m_curr = startToken; endToken > m_curr; next()) {
@@ -2001,7 +1992,7 @@ namespace hex::plugin::builtin {
if (typeStr.empty())
continue;
i32 tokenId = getTokenId(m_curr->location);
i32 tokenId = getTokenId();
Definition definition(identifierType, typeStr, tokenId, m_curr->location);
variables[identifierName].push_back(definition);
continue;
@@ -2077,7 +2068,7 @@ namespace hex::plugin::builtin {
if (typeStr.empty())
continue;
Definition definition(identifierType, typeStr, getTokenId(m_curr->location), m_curr->location);
Definition definition(identifierType, typeStr, getTokenId(), m_curr->location);
variableMap[name][identifierName].push_back(definition);
continue;
}
@@ -2104,7 +2095,7 @@ namespace hex::plugin::builtin {
auto identifierName = identifier->get();
if (!name.ends_with(identifierName))
continue;
types[name] = ParentDefinition(identifierType, getTokenId(m_curr->location), m_curr->location);
types[name] = ParentDefinition(identifierType, getTokenId(), m_curr->location);
}
}
@@ -2167,7 +2158,7 @@ namespace hex::plugin::builtin {
}
m_lines = wolv::util::splitString(m_requiredInputs.editedText, "\n");
m_lines.push_back("");
m_lines.emplace_back("");
m_firstTokenIdOfLine.clear();
u32 tokenId = 0;
@@ -2433,10 +2424,10 @@ namespace hex::plugin::builtin {
// Parser labels global variables that are not placed as
// function variables.
void TextHighlighter::fixGlobalVariables() {
m_startToken = m_originalPosition = m_partOriginalPosition = TokenIter(m_requiredInputs.fullTokens.begin(), m_requiredInputs.fullTokens.end());
m_startToken = m_originalPosition = m_partOriginalPosition = SafeTokenIterator(m_requiredInputs.fullTokens.begin(), m_requiredInputs.fullTokens.end());
for (auto range: m_globalTokenRange) {
auto startToken = TokenIter(m_requiredInputs.fullTokens.begin() + range.m_start, m_requiredInputs.fullTokens.begin() + range.m_end);
auto endToken = TokenIter(m_requiredInputs.fullTokens.begin() + range.m_end, m_requiredInputs.fullTokens.end());
auto startToken = SafeTokenIterator(m_requiredInputs.fullTokens.begin() + range.m_start, m_requiredInputs.fullTokens.begin() + range.m_end);
auto endToken = SafeTokenIterator(m_requiredInputs.fullTokens.begin() + range.m_end, m_requiredInputs.fullTokens.end());
for (m_curr = startToken; endToken > m_curr; next()) {
@@ -2480,6 +2471,7 @@ namespace hex::plugin::builtin {
void TextHighlighter::processSource() {
m_UDTVariables.clear();
m_UDTTokenRange.clear();
setTokenIds();
getTokenRanges(IdentifierType::UDT);
loadVariableDefinitions(m_UDTTokenRange, tkn::Operator::BoolLessThan, tkn::Operator::BoolGreaterThan,
{IdentifierType::TemplateArgument}, true, m_UDTVariables);
@@ -2510,6 +2502,7 @@ namespace hex::plugin::builtin {
if (m_requiredInputs.fullTokens.size() > 1) {
m_globalTokenRange.insert(TokenInterval(0, m_requiredInputs.fullTokens.size() - 1));
setTokenIds();
getTokenRanges(IdentifierType::NameSpace);
getTokenRanges(IdentifierType::UDT);
getTokenRanges(IdentifierType::Function);
@@ -2543,5 +2536,7 @@ namespace hex::plugin::builtin {
log::debug("TextHighlighter::highlightSourceCode: Out of range error: {}", e.what());
return;
}
return;
}
}

View File

@@ -1476,7 +1476,8 @@ namespace hex::plugin::builtin {
TaskManager::createBackgroundTask("HighlightSourceCode", [this,provider](auto &) { m_textHighlighter.get(provider).highlightSourceCode(); });
} else if (m_changesWereColored && !m_allStepsCompleted) {
m_textHighlighter.get(provider).setRequestedIdentifierColors();
m_textEditor.get(provider).getLines().readHiddenLines();
m_textEditor.get(provider).getLines().setAllCodeFolds();
m_textEditor.get(provider).getLines().applyCodeFoldStates();
m_allStepsCompleted = true;
}
@@ -1642,7 +1643,7 @@ namespace hex::plugin::builtin {
this->evaluatePattern(code, provider);
m_textEditor.get(provider).setText(code, true);
m_textEditor.get(provider).readHiddenLines();
m_textEditor.get(provider).removeHiddenLinesFromPattern();
m_sourceCode.get(provider) = code;
if (trackFile) {
m_changeTracker.get(provider) = wolv::io::ChangeTracker(file);
@@ -1657,7 +1658,7 @@ namespace hex::plugin::builtin {
ContentRegistry::PatternLanguage::configureRuntime(*m_editorRuntime, nullptr);
const auto &ast = m_editorRuntime->parseString(code, pl::api::Source::DefaultSource);
m_textEditor.get(provider).setLongestLineLength(m_editorRuntime->getInternals().preprocessor.get()->getLongestLineLength());
m_textEditor.get(provider).setLongestLineLength(m_editorRuntime->getInternals().preprocessor->getLongestLineLength());
auto &patternVariables = m_patternVariables.get(provider);
auto oldPatternVariables = std::move(patternVariables);
@@ -1840,6 +1841,7 @@ namespace hex::plugin::builtin {
return;
m_textEditor.get(provider).setText(wolv::util::preprocessText(code));
m_textEditor.get(provider).removeHiddenLinesFromPattern();
m_sourceCode.get(provider) = code;
m_hasUnevaluatedChanges.get(provider) = true;
});
@@ -1874,11 +1876,12 @@ namespace hex::plugin::builtin {
EventProviderChanged::subscribe(this, [this](prv::Provider *oldProvider, prv::Provider *newProvider) {
if (oldProvider != nullptr) {
m_sourceCode.get(oldProvider) = m_textEditor.get(oldProvider).getText(true);
m_sourceCode.get(oldProvider) = m_textEditor.get(oldProvider).getText();
m_scroll.get(oldProvider) = m_textEditor.get(oldProvider).getScroll();
m_cursorPosition.get(oldProvider) = m_textEditor.get(oldProvider).getCursorPosition();
m_selection.get(oldProvider) = m_textEditor.get(oldProvider).getSelection();
m_breakpoints.get(oldProvider) = m_textEditor.get(oldProvider).getBreakpoints();
m_codeFoldState.get(oldProvider) = m_textEditor.get(oldProvider).getLines().getCodeFoldState();
m_consoleCursorPosition.get(oldProvider) = m_consoleEditor.get(oldProvider).getCursorPosition();
m_consoleSelection.get(oldProvider) = m_consoleEditor.get(oldProvider).getSelection();
m_consoleLongestLineLength.get(oldProvider) = m_consoleEditor.get(oldProvider).getLongestLineLength();
@@ -1891,6 +1894,7 @@ namespace hex::plugin::builtin {
m_textEditor.get(newProvider).setScroll(m_scroll.get(newProvider));
m_textEditor.get(newProvider).setSelection(m_selection.get(newProvider));
m_textEditor.get(newProvider).setBreakpoints(m_breakpoints.get(newProvider));
m_textEditor.get(newProvider).getLines().setCodeFoldState(m_codeFoldState.get(newProvider));
m_textEditor.get(newProvider).setTextChanged(false);
m_hasUnevaluatedChanges.get(newProvider) = true;
m_consoleEditor.get(newProvider).setText(wolv::util::combineStrings(m_console.get(newProvider), "\n"));
@@ -2340,15 +2344,19 @@ namespace hex::plugin::builtin {
m_sourceCode.get(provider) = sourceCode;
if (provider == ImHexApi::Provider::get())
if (provider == ImHexApi::Provider::get()) {
m_textEditor.get(provider).setText(sourceCode);
m_textEditor.get(provider).removeHiddenLinesFromPattern();
}
m_hasUnevaluatedChanges.get(provider) = true;
return true;
},
.store = [this](prv::Provider *provider, const std::fs::path &basePath, const Tar &tar) {
if (provider == ImHexApi::Provider::get())
if (provider == ImHexApi::Provider::get()) {
m_textEditor.get(provider).addHiddenLinesToPattern();
m_sourceCode.get(provider) = m_textEditor.get(provider).getText();
}
const auto &sourceCode = m_sourceCode.get(provider);
@@ -2599,12 +2607,12 @@ namespace hex::plugin::builtin {
// Wait until evaluation has finished
while (m_runningEvaluators > 0) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::this_thread::sleep_for(std::chrono::milliseconds(100ll));
}
auto lock = std::scoped_lock(ContentRegistry::PatternLanguage::getRuntimeLock());
auto evaluationResult = m_lastEvaluationResult.load();
int evaluationResult = m_lastEvaluationResult.load();
nlohmann::json result = {
{ "handle", provider->getID() },
@@ -2623,7 +2631,7 @@ namespace hex::plugin::builtin {
// Wait until evaluation has finished
while (m_runningEvaluators > 0) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::this_thread::sleep_for(std::chrono::milliseconds(100ll));
}
auto lock = std::scoped_lock(ContentRegistry::PatternLanguage::getRuntimeLock());
@@ -2647,7 +2655,7 @@ namespace hex::plugin::builtin {
// Wait until evaluation has finished
while (m_runningEvaluators > 0) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::this_thread::sleep_for(std::chrono::milliseconds(100ll));
}
auto lock = std::scoped_lock(ContentRegistry::PatternLanguage::getRuntimeLock());
@@ -2679,6 +2687,7 @@ namespace hex::plugin::builtin {
m_changeEventAcknowledgementPending.get(provider) = true;
hex::ui::BannerButton::open(ICON_VS_INFO, "hex.builtin.provider.file.reload_changes", ImColor(66, 104, 135), "hex.builtin.provider.file.reload_changes.reload", [this, provider] {
m_changeEventAcknowledgementPending.get(provider) = false;
loadPatternFile(m_changeTracker.get(provider).getPath(), provider, true);
});
}
@@ -2741,7 +2750,8 @@ namespace hex::plugin::builtin {
fs::DialogMode::Save, { {"Pattern File", "hexpat"}, {"Pattern Import File", "pat"} },
[this, provider, trackFile](const auto &path) {
wolv::io::File file(path, wolv::io::File::Mode::Create);
file.writeString(wolv::util::trim(m_textEditor.get(provider).getText(true)));
m_textEditor.get(provider).addHiddenLinesToPattern();
file.writeString(wolv::util::trim(m_textEditor.get(provider).getText()));
m_patternFileDirty.get(provider) = false;
auto loadedPath = m_changeTracker.get(provider).getPath();
if ((loadedPath.empty() && loadedPath != path) || (!loadedPath.empty() && !trackFile) || loadedPath == path)
@@ -2764,7 +2774,8 @@ namespace hex::plugin::builtin {
wolv::io::File file(path, wolv::io::File::Mode::Create);
if (file.isValid() && trackFile) {
if (isPatternDirty(provider)) {
file.writeString(wolv::util::trim(m_textEditor.get(provider).getText(true)));
m_textEditor.get(provider).addHiddenLinesToPattern();
file.writeString(wolv::util::trim(m_textEditor.get(provider).getText()));
m_patternFileDirty.get(provider) = false;
}
return;

View File

@@ -1,6 +1,7 @@
#pragma once
#include <string>
#include <utility>
#include <vector>
#include <array>
#include <memory>
@@ -62,8 +63,8 @@ namespace hex::ui {
bool operator>=(const Coordinates &o) const;
Coordinates operator+(const Coordinates &o) const;
Coordinates operator-(const Coordinates &o) const;
i32 getLine() const { return m_line; }
i32 getColumn() const { return m_column; }
[[nodiscard]] i32 getLine() const { return m_line; }
[[nodiscard]] i32 getColumn() const { return m_column; }
private:
i32 m_line, m_column;
@@ -84,11 +85,11 @@ namespace hex::ui {
Coordinates getEnd() { return m_end; }
bool isSingleLine();
enum class EndsInclusive : u8 { None = 0, Start = 2, End = 1, Both = 3 };
bool contains(const Coordinates &coordinates, EndsInclusive endsInclusive = EndsInclusive::Both) const;
bool contains(const Range &range, EndsInclusive endsInclusive = EndsInclusive::Both) const;
bool containsLine(i32 value, EndsInclusive endsInclusive = EndsInclusive::Both) const;
bool containsColumn(i32 value, EndsInclusive endsInclusive = EndsInclusive::Both) const;
bool overlaps(const Range &o, EndsInclusive endsInclusive = EndsInclusive::Both) const;
[[nodiscard]] bool contains(const Coordinates &coordinates, EndsInclusive endsInclusive = EndsInclusive::Both) const;
[[nodiscard]] bool contains(const Range &range, EndsInclusive endsInclusive = EndsInclusive::Both) const;
[[nodiscard]] bool containsLine(i32 value, EndsInclusive endsInclusive = EndsInclusive::Both) const;
[[nodiscard]] bool containsColumn(i32 value, EndsInclusive endsInclusive = EndsInclusive::Both) const;
[[nodiscard]] bool overlaps(const Range &o, EndsInclusive endsInclusive = EndsInclusive::Both) const;
bool operator==(const Range &o) const;
bool operator!=(const Range &o) const;
bool operator<(const Range &o) const {
@@ -118,7 +119,7 @@ namespace hex::ui {
Interval() : m_start(0), m_end(0) {}
Interval(i32 start, i32 end) : m_start(start), m_end(end) {
if (m_start > m_end) std::swap(m_start, m_end);}
Interval(const Interval &other) : m_start(other.m_start), m_end(other.m_end) {}
Interval(const Interval &other) = default;
explicit Interval(ImVec2 vec) : m_start((i32)vec.x), m_end((i32)vec.y) {
if (m_start > m_end) std::swap(m_start, m_end);}
@@ -130,11 +131,11 @@ namespace hex::ui {
bool operator!=(const Interval &other) const { return m_start != other.m_start || m_end != other.m_end; }
bool operator<=(const Interval &other) const { return other.m_end >= m_end; }
bool operator>=(const Interval &other) const { return m_end >= other.m_end; }
bool contains_or_equals(const Interval &other) const { return other.m_start >= m_start && other.m_end <= m_end; }
bool contains(const Interval &other) const { return (other.m_start >= m_start && other.m_end < m_end) || (other.m_start > m_start && other.m_end <= m_end); }
bool contains(i32 value, bool inclusive = true) const;
bool contiguous(const Interval &other) const;
operator ImVec2() const { return ImVec2((float)m_start, (float)m_end); }
[[nodiscard]] bool contains_or_equals(const Interval &other) const { return other.m_start >= m_start && other.m_end <= m_end; }
[[nodiscard]] bool contains(const Interval &other) const { return (other.m_start >= m_start && other.m_end < m_end) || (other.m_start > m_start && other.m_end <= m_end); }
[[nodiscard]] bool contains(i32 value, bool inclusive = true) const;
[[nodiscard]] bool contiguous(const Interval &other) const;
explicit operator ImVec2() const { return {(float)m_start, (float)m_end}; }
private:
i32 m_start;
i32 m_end;
@@ -144,8 +145,8 @@ namespace hex::ui {
public:
friend class TextEditor;
bool operator==(const EditorState &o) const;
EditorState() : m_selection(), m_cursorPosition() {}
EditorState(const Range &selection, const Coordinates &cursorPosition) : m_selection(selection), m_cursorPosition(cursorPosition) {}
EditorState() = default;
EditorState(Range selection, Coordinates cursorPosition) : m_selection(selection), m_cursorPosition(cursorPosition) {}
private:
Range m_selection;
Coordinates m_cursorPosition;
@@ -153,10 +154,12 @@ namespace hex::ui {
class UndoRecord;
using Matches = std::vector<EditorState>;
using UndoRecords = std::vector<UndoRecord>;
class FindReplaceHandler {
public:
FindReplaceHandler();
using Matches = std::vector<EditorState>;
Matches &getMatches() { return m_matches; }
bool findNext(Lines *lines, u64 &byteIndex);
bool findNext(TextEditor *editor, u64 &byteIndex) { return findNext(&editor->m_lines, byteIndex); };
@@ -177,17 +180,17 @@ namespace hex::ui {
void findAllMatches(TextEditor *editor, std::string findWord) { findAllMatches(&editor->m_lines, findWord); };
u32 findPosition(Lines *lines, Coordinates pos, bool isNext);
u32 findPosition(TextEditor *editor, Coordinates pos, bool isNext) { return findPosition(&editor->m_lines, pos, isNext); };
bool getMatchCase() const { return m_matchCase; }
[[nodiscard]] bool getMatchCase() const { return m_matchCase; }
void setMatchCase(Lines *lines, bool matchCase);
void setMatchCase(TextEditor *editor, bool matchCase) { setMatchCase(&editor->m_lines, matchCase); };
bool getWholeWord() const { return m_wholeWord; }
[[nodiscard]] bool getWholeWord() const { return m_wholeWord; }
void setWholeWord(Lines *lines, bool wholeWord);
void setWholeWord(TextEditor *editor, bool wholeWord) { setWholeWord(&editor->m_lines, wholeWord); };
bool getFindRegEx() const { return m_findRegEx; }
[[nodiscard]] bool getFindRegEx() const { return m_findRegEx; }
void setFindRegEx(Lines *lines, bool findRegEx);
void setFindRegEx(TextEditor *editor, bool findRegEx) { setFindRegEx(&editor->m_lines, findRegEx); };
void resetMatches();
std::vector<UndoRecord> m_undoBuffer;
UndoRecords m_undoBuffer;
private:
std::string m_findWord;
std::string m_replaceWord;
@@ -198,22 +201,24 @@ namespace hex::ui {
Matches m_matches;
};
enum class PaletteIndex {
enum class PaletteIndex : u8 {
Default, Identifier, Directive, Operator, Separator, BuiltInType, Keyword, NumericLiteral, StringLiteral, CharLiteral, Cursor, Background, LineNumber, Selection, Breakpoint, ErrorMarker, PreprocessorDeactivated,
CurrentLineFill, CurrentLineFillInactive, CurrentLineEdge, ErrorText, WarningText, DebugText, DefaultText, Attribute, PatternVariable, LocalVariable, CalculatedPointer, TemplateArgument, Function, View,
FunctionVariable, FunctionParameter, UserDefinedType, PlacedVariable, GlobalVariable, NameSpace, TypeDef, UnkIdentifier, DocComment, DocBlockComment, BlockComment, GlobalDocComment, Comment, PreprocIdentifier, Max
};
using Token = pl::core::Token;
using TokenIter = pl::hlp::SafeIterator<std::vector<Token>::const_iterator>;
using Location = pl::core::Location;
using RegexList = std::vector<std::pair<std::regex, PaletteIndex>>;
using Keywords = std::unordered_set<std::string>;
using ErrorMarkers = std::map<Coordinates, std::pair<i32, std::string>>;
using Breakpoints = std::unordered_set<u32>;
using Palette = std::array<ImU32, (u64) PaletteIndex::Max>;
using Glyph = u8;
using CodeFoldBlocks = std::map<Coordinates,Coordinates>;
using Token = pl::core::Token;
using Tokens = std::vector<Token>;
using SafeTokenIterator = pl::hlp::SafeIterator<Tokens::const_iterator>;
using Location = pl::core::Location;
using RegexList = std::vector<std::pair<std::regex, PaletteIndex>>;
using Keywords = std::unordered_set<std::string>;
using ErrorMarkers = std::map<Coordinates, std::pair<i32, std::string>>;
using Breakpoints = std::unordered_set<u32>;
using Palette = std::array<ImU32, (u64) PaletteIndex::Max>;
using Glyph = u8;
using CodeFoldBlocks = std::map<Coordinates,Coordinates>;
using GlobalBlocks = std::set<Interval>;
struct Identifier { Coordinates m_location; std::string m_declaration;};
using Identifiers = std::unordered_map<std::string, Identifier>;
@@ -223,7 +228,7 @@ namespace hex::ui {
ActionableBox() : m_box(ImRect(ImVec2(0, 0), ImVec2(0, 0))) {};
explicit ActionableBox(const ImRect &box) : m_box(box) {}
ImRect &getBox() const { return const_cast<ImRect &>(m_box);}
[[nodiscard]] ImRect &getBox() const { return const_cast<ImRect &>(m_box);}
virtual bool trigger();
virtual void callback() {}
virtual ~ActionableBox() = default;
@@ -274,12 +279,12 @@ namespace hex::ui {
bool startHovered();
bool endHovered();
bool isDetected();
bool isOpen();
[[nodiscard]] bool isOpen() const;
void open();
void close();
void moveFold(float lineCount, float lineHeight);
private:
Lines *lines;
Lines *lines = nullptr;
Range key;
CursorChangeBox codeFoldStartCursorBox;
ActionableBox codeFoldEndActionBox;
@@ -302,14 +307,16 @@ namespace hex::ui {
using ErrorGotoBoxes = std::map<Coordinates, ErrorGotoBox>;
using CursorBoxes = std::map<Coordinates, CursorChangeBox>;
using ErrorHoverBoxes = std::map<Coordinates, ErrorHoverBox>;
using Keys = std::vector<Range>;
using CodeFoldKeys = std::set<Range>;
using CodeFoldDelimiters = std::map<Range,std::pair<char,char>>;
using Segments = std::vector<Coordinates>;
using CodeFoldKeyMap = std::map<Coordinates,Coordinates>;
using CodeFoldKeyLineMap = std::multimap<i32,Coordinates>;
using CodeFoldState = std::map<Range,bool>;
// using RowsToCodeFoldMap = std::map<u32,Interval>;
using Indices = std::vector<i32>;
using LineIndexToScreen = std::map<i32,ImVec2>;
using MultiLinesToRow = std::map<i32,i32>;
using IndexMap = std::map<i32,i32>;
using RowCodeFoldTooltips = std::map<i32,std::vector<CodeFoldTooltip>>;
enum class TrimMode : u8 { TrimNone = 0, TrimEnd = 1, TrimStart = 2, TrimBoth = 3 };
@@ -322,12 +329,12 @@ namespace hex::ui {
public:
friend class hex::ui::TextEditor;
friend class hex::ui::TextEditor::Lines;
LineIterator(const LineIterator &other) : m_charsIter(other.m_charsIter), m_colorsIter(other.m_colorsIter), m_flagsIter(other.m_flagsIter) {}
LineIterator(const LineIterator &other) = default;
LineIterator() = default;
char operator*();
LineIterator &operator++();
LineIterator operator=(const LineIterator &other);
LineIterator &operator=(const LineIterator &other);
bool operator!=(const LineIterator &other) const;
bool operator==(const LineIterator &other) const;
LineIterator operator+(i32 n);
@@ -359,20 +366,20 @@ namespace hex::ui {
};
union Flags {
Flags(char value) : m_value(value) {}
Flags(FlagBits bits) : m_bits(bits) {}
explicit Flags(char value) : m_value(value) {}
explicit Flags(FlagBits bits) : m_bits(bits) {}
FlagBits m_bits;
char m_value;
};
enum class LinePart { Chars, Utf8, Colors, Flags };
enum class LinePart : u8 { Chars, Utf8, Colors, Flags };
Line() : m_chars(""), m_colors(""), m_flags(""), m_colorized(false), m_lineMaxColumn(-1) {}
explicit Line(const char *line) { Line(std::string(line)); }
explicit Line(const std::string &line) : m_chars(line), m_colors(std::string(line.size(), 0x00)), m_flags(std::string(line.size(), 0x00)), m_colorized(false), m_lineMaxColumn(maxColumn()) {}
Line() : m_lineMaxColumn(-1) {}
explicit Line(const char *line) : Line(std::string(line)) {}
explicit Line(const std::string &line) : m_chars(line), m_colors(std::string(line.size(), 0x00)), m_flags(std::string(line.size(), 0x00)), m_lineMaxColumn(maxColumn()) {}
Line(const Line &line) : m_chars(std::string(line.m_chars)), m_colors(std::string(line.m_colors)), m_flags(std::string(line.m_flags)), m_colorized(line.m_colorized), m_lineMaxColumn(line.m_lineMaxColumn) {}
Line(Line &&line) noexcept : m_chars(std::move(line.m_chars)), m_colors(std::move(line.m_colors)), m_flags(std::move(line.m_flags)), m_colorized(line.m_colorized), m_lineMaxColumn(line.m_lineMaxColumn) {}
Line(std::string chars, std::string colors, std::string flags) : m_chars(std::move(chars)), m_colors(std::move(colors)), m_flags(std::move(flags)), m_colorized(false), m_lineMaxColumn(maxColumn()) {}
Line(std::string chars, std::string colors, std::string flags) : m_chars(std::move(chars)), m_colors(std::move(colors)), m_flags(std::move(flags)), m_lineMaxColumn(maxColumn()) {}
bool operator==(const Line &o) const;
bool operator!=(const Line &o) const;
@@ -382,7 +389,7 @@ namespace hex::ui {
[[nodiscard]] i32 columnIndex(i32 column) const;
[[nodiscard]] i32 textSize() const;
[[nodiscard]] i32 textSize(u32 index) const;
ImVec2 intervalToScreen(Interval stringIndices) const;
[[nodiscard]] ImVec2 intervalToScreen(Interval stringIndices) const;
i32 lineTextSize(TrimMode trimMode = TrimMode::TrimNone);
[[nodiscard]] i32 stringTextSize(const std::string &str) const;
i32 textSizeIndex(float textSize, i32 position);
@@ -403,19 +410,19 @@ namespace hex::ui {
[[nodiscard]] std::string substr(u64 start, u64 length = (u64) -1, LinePart part = LinePart::Chars) const;
Line subLine(u64 start, u64 length = (u64) -1);
char operator[](u64 index) const;
char at(u64 index) const;
[[nodiscard]] char at(u64 index) const;
// C++ can't overload functions based on return type, so use any type other
// than u64 to avoid ambiguity.
std::string operator[](i64 column) const;
std::string at(i64 column) const;
[[nodiscard]] std::string at(i64 column) const;
void setNeedsUpdate(bool needsUpdate);
void append(const char *text);
void append(const char text);
void append(char text);
void append(const std::string &text);
void append(const Line &line);
void append(LineIterator begin, LineIterator end);
void insert(LineIterator iter, const std::string &text);
void insert(LineIterator iter, const char text);
void insert(LineIterator iter, char text);
void insert(LineIterator iter, strConstIter beginString, strConstIter endString);
void insert(LineIterator iter, const Line &line);
void insert(LineIterator iter, LineIterator beginLine, LineIterator endLine);
@@ -461,16 +468,16 @@ namespace hex::ui {
Range findDelimiterCoordinates(Range key);
private:
Line m_foldedLine;
Lines *m_lines;
Lines *m_lines{};
Range m_full;
i32 m_row;
i32 m_row{};
FoldType m_type = FoldType::Invalid;
std::string m_brackets;
std::vector<Range> m_keys;
std::vector<Range> m_keysToRemove;
std::vector<i32> m_ellipsisIndices;
std::vector<Coordinates> m_foldedSegments;
std::vector<Coordinates> m_unfoldedSegments;
Keys m_keys;
Keys m_keysToRemove;
Indices m_ellipsisIndices;
Segments m_foldedSegments;
Segments m_unfoldedSegments;
Coordinates m_cursorPosition;
Range m_selection;
bool m_built = false;
@@ -480,7 +487,7 @@ namespace hex::ui {
public:
friend class Lines;
friend class TextEditor;
MatchedDelimiter() : m_active(false), m_changed(false), m_nearCursor(0, 0), m_matched(0, 0) {}
MatchedDelimiter() : m_nearCursor(0, 0), m_matched(0, 0) {}
MatchedDelimiter(bool active, bool changed, const Coordinates &nearCursor, const Coordinates &matched) : m_active(active), m_changed(changed), m_nearCursor(nearCursor), m_matched(matched) {}
bool checkPosition(Lines *lines, Coordinates &from);
@@ -494,15 +501,15 @@ namespace hex::ui {
private:
bool m_active = false;
bool m_changed = false;
Coordinates m_nearCursor = {};
Coordinates m_matched = {};
Coordinates m_nearCursor{};
Coordinates m_matched{};
};
class Segment {
class FoldSegment {
public:
friend class TextEditor;
Segment(Coordinates foldEnd, const Interval &segment) : m_foldEnd(foldEnd), m_segment(segment) {}
bool operator==(const Segment &o) const {
FoldSegment(Coordinates foldEnd, const Interval &segment) : m_foldEnd(foldEnd), m_segment(segment) {}
bool operator==(const FoldSegment &o) const {
return m_foldEnd == o.m_foldEnd && m_segment == o.m_segment;
}
private:
@@ -511,9 +518,9 @@ namespace hex::ui {
};
struct LanguageDefinition {
typedef std::pair<std::string, PaletteIndex> TokenRegexString;
typedef std::vector<TokenRegexString> TokenRegexStrings;
typedef bool(*TokenizeCallback)(strConstIter in_begin, strConstIter in_end, strConstIter &out_begin, strConstIter &out_end, PaletteIndex &paletteIndex);
using TokenRegexString = std::pair<std::string, PaletteIndex>;
using TokenRegexStrings = std::vector<TokenRegexString>;
using TokenizeCallback = bool (*)(strConstIter, strConstIter, strConstIter &, strConstIter &, PaletteIndex &);
std::string m_name;
Keywords m_keywords;
@@ -522,12 +529,11 @@ namespace hex::ui {
std::string m_singleLineComment, m_commentEnd, m_commentStart, m_globalDocComment, m_docComment, m_blockDocComment;
char m_preprocChar = '#';
bool m_autoIndentation = true;
TokenizeCallback m_tokenize;
TokenizeCallback m_tokenize = {};
TokenRegexStrings m_tokenRegexStrings;
bool m_caseSensitive = true;
LanguageDefinition() : m_keywords({}), m_identifiers({}), m_preprocIdentifiers({}),
m_tokenize(nullptr), m_tokenRegexStrings({}) {}
LanguageDefinition() : m_keywords({}), m_identifiers({}), m_preprocIdentifiers({}), m_tokenRegexStrings({}) {}
static const LanguageDefinition &CPlusPlus();
static const LanguageDefinition &HLSL();
@@ -544,14 +550,14 @@ namespace hex::ui {
class UndoRecord {
public:
friend class TextEditor;
UndoRecord() {}
~UndoRecord() {}
UndoRecord() = default;
~UndoRecord() = default;
UndoRecord( std::string added,
Range addedRange,
std::string removed,
Range removedRange,
EditorState &before,
EditorState &after);
EditorState before,
EditorState after);
void undo(TextEditor *editor);
void redo(TextEditor *editor);
@@ -564,13 +570,11 @@ namespace hex::ui {
EditorState m_after;
};
using UndoRecords = std::vector<UndoRecord>;
class UndoAction {
public:
UndoAction() {}
~UndoAction() {}
explicit UndoAction(const UndoRecords &records) : m_records(records) {}
UndoAction() = default;
~UndoAction() = default;
explicit UndoAction(UndoRecords records) : m_records(std::move(records)) {}
void undo(TextEditor *editor);
void redo(TextEditor *editor);
private:
@@ -581,25 +585,31 @@ namespace hex::ui {
public:
friend class Lines;
HiddenLine() = default;
HiddenLine(i32 lineIndex, const std::string &lineContent) : m_lineIndex(lineIndex), m_line(lineContent) {}
HiddenLine(i32 lineIndex, std::string lineContent) : m_lineIndex(lineIndex), m_line(std::move(lineContent)) {}
private:
i32 m_lineIndex;
i32 m_lineIndex{};
std::string m_line;
};
using CodeFolds = std::map<Range,CodeFold>;
using Segments = std::vector<Segment>;
using RowToSegments = std::map<i32,Segments>;
using UndoBuffer = std::vector<UndoAction>;
using RowToFoldedLine = std::map<i32,FoldedLine>;
enum class FoldSymbol : u8 { Line, Up, Down, Square };
using CodeFolds = std::map<Range, CodeFold>;
using FoldSegments = std::vector<FoldSegment>;
using RowToFoldSegments = std::map<i32, FoldSegments>;
using UndoBuffer = std::vector<UndoAction>;
using FoldedLines = std::map<i32, FoldedLine>;
using UnfoldedLines = std::vector<Line>;
using HiddenLines = std::vector<HiddenLine>;
using FoldSymbols = std::map<i32, FoldSymbol>;
using StringVector = std::vector<std::string>;
using RangeFromCoordinates = std::pair<Coordinates, Coordinates>;
bool areEqual(const std::pair<Range,CodeFold> &a, const std::pair<Range,CodeFold> &b);
class Lines {
public:
friend class TextEditor;
Lines() : m_unfoldedLines({}), m_foldedLines({}), m_hiddenLines({}), m_matchedDelimiter(), m_colorizerEnabled(true), m_defines({}) {}
enum class FoldSymbol { Line, Up, Down, Square };
Lines() : m_unfoldedLines({}), m_foldedLines({}), m_hiddenLines({}), m_defines({}) {}
Line &at(i32 index);
Line &operator[](i32 index);
@@ -621,7 +631,6 @@ namespace hex::ui {
void clearCursorBoxes() { m_cursorBoxes.clear(); }
void clearCodeFolds();
void addClickableText(std::string text) { m_clickableText.push_back(text); }
//void setErrorMarkers(const ErrorMarkers &markers) { m_errorMarkers = markers; }
Breakpoints &getBreakpoints() { return m_breakpoints; }
void saveCodeFoldStates();
void applyCodeFoldStates();
@@ -642,7 +651,7 @@ namespace hex::ui {
void moveUp(i32 amount, bool select);
void moveHome(bool select);
void moveEnd(bool select);
std::vector<Range> removeEmbeddedFolds();
Keys removeEmbeddedFolds();
bool isLastLine(i32 lineIndex);
bool isLastLine();
Coordinates find(const std::string &text, const Coordinates &start);
@@ -654,17 +663,17 @@ namespace hex::ui {
friend bool Range::Coordinates::isValid(Lines &lines);
friend TextEditor::Coordinates Range::Coordinates::sanitize(Lines &lines);
void appendLine(const std::string &value);
void readHiddenLines();
void writeHiddenLines();
void removeHiddenLinesFromPattern();
void addHiddenLinesToPattern();
void setSelection(const Range &selection);
Range getSelection() const;
ImVec2 getLineStartScreenPos(float leftMargin, float lineNumber);
ImVec2 &getCharAdvance() { return m_charAdvance; }
std::vector<Range> getDeactivatedBlocks();
Keys getDeactivatedBlocks();
std::string getSelectedText();
void deleteSelection();
inline void setTextChanged(bool value) { m_textChanged = value; }
inline bool isTextChanged() { return m_textChanged; }
void setTextChanged(bool value) { m_textChanged = value; }
bool isTextChanged() { return m_textChanged; }
void setLanguageDefinition(const LanguageDefinition &aLanguageDef);
const LanguageDefinition &getLanguageDefinition() const { return m_languageDefinition; }
TextEditor::PaletteIndex getColorIndexFromFlags(Line::Flags flags);
@@ -681,8 +690,8 @@ namespace hex::ui {
void openCodeFold(const Range &key);
void removeKeys();
ImVec2 indexCoordsToScreen(Coordinates indexCoords);
inline void setImGuiChildIgnored(bool value) { m_ignoreImGuiChild = value; }
inline bool isImGuiChildIgnored() const { return m_ignoreImGuiChild; }
void setImGuiChildIgnored(bool value) { m_ignoreImGuiChild = value; }
bool isImGuiChildIgnored() const { return m_ignoreImGuiChild; }
ImVec2 lineIndexToScreen(i32 lineIndex, Interval stringIndices);
void printCodeFold(const Range &key);
void resetCursorBlinkTime();
@@ -691,7 +700,7 @@ namespace hex::ui {
void setCursorPosition(const Coordinates &position, bool unfoldIfNeeded = true, bool scrollToCursor = true);
void setFocusAtCoords(const Coordinates &coords, bool ensureVisible = false);
void ensureCursorVisible();
std::vector<Coordinates> unfoldedEllipsisCoordinates(Range delimiterCoordinates);
Segments unfoldedEllipsisCoordinates(Range delimiterCoordinates);
Coordinates unfoldedToFoldedCoords(const Coordinates &coords);
Coordinates foldedToUnfoldedCoords(const Coordinates &coords);
void setScrollY();
@@ -699,59 +708,61 @@ namespace hex::ui {
Coordinates findNextWord(const Coordinates &from);
Line &insertLine(i32 index);
void deleteRange(const Range &rangeToDelete);
inline void clearBreakpointsChanged() { m_breakPointsChanged = false; }
inline bool isBreakpointsChanged() { return m_breakPointsChanged; }
void clearBreakpointsChanged() { m_breakPointsChanged = false; }
bool isBreakpointsChanged() { return m_breakPointsChanged; }
Coordinates stringIndexCoords(i32 strIndex, const std::string &input);
void refreshSearchResults();
inline void setReadOnly(bool value) { m_readOnly = value; }
void setReadOnly(bool value) { m_readOnly = value; }
void removeLines(i32 start, i32 end);
void removeLine(i32 index);
float textDistanceToLineStart(const Coordinates &from);
std::string getText(bool addHiddenLines = false);
std::string getText();
void setCursorPosition();
void ensureSelectionNotFolded();
bool hasSelection();
i32 insertTextAtCursor(const std::string &value);
void addUndo(std::vector<UndoRecord> value);
void addUndo(UndoRecords value);
void insertText(const std::string &value);
void insertText(const char *value);
Interval findBlockInRange(Interval interval);
std::vector<Interval> searchRangeForBlocks(Interval interval);
std::pair<Coordinates ,Coordinates> getDelimiterLineNumbers(i32 start, i32 end, const std::string &delimiters);
RangeFromCoordinates getDelimiterLineNumbers(i32 start, i32 end, const std::string &delimiters);
void nonDelimitedFolds();
std::pair<i32,i32> convertIndexToLineNumbers(Interval interval);
std::pair<i32,char> findMatchingDelimiter(i32 from);
CodeFoldBlocks foldPointsFromSource();
Coordinates findCommentEndCoord(i32 tokenId);
std::set<Interval> blocksFromGlobal();
void skipAttribute();
bool isTokenIdValid(i32 tokenId);
bool isLocationValid(Location location);
pl::core::Location getLocation(i32 tokenId);
i32 getTokenId(pl::core::Location location);
i32 getTokenId(SafeTokenIterator tokenIterator);
i32 getTokenId();
void loadFirstTokenIdOfLine();
i32 nextLine(i32 line);
void setAllCodeFolds();
void setCodeFoldState(CodeFoldState states);
CodeFoldState getCodeFoldState() const;
void advanceToNextLine(i32 &lineIndex, i32 &currentTokenId, Location &location);
void advanceTokenId(i32 &lineIndex, i32 &currentTokenId, Location &location);
void moveToLocationColumn(i32 locationColumn, i32 &currentTokenId, Location &location);
void incrementTokenId(i32 &lineIndex, i32 &currentTokenId, Location &location);
void moveToStringIndex(i32 stringIndex, i32 &currentTokenId, Location &location);
void resetToTokenId(i32 &lineIndex, i32 &currentTokenId, Location &location);
i32 findNextDelimiter(bool openOnly);
constexpr static u32 Normal = 0;
constexpr static u32 Not = 1;
template<typename T> T *getValue(const i32 index);
template<typename T> T *getValue(i32 index);
void next(i32 count = 1);
bool begin();
void partBegin();
void reset();
void partReset();
bool resetIfFailed(const bool value);
bool resetIfFailed(bool value);
template<auto S = Normal> bool sequenceImpl();
template<auto S = Normal> bool matchOne(const Token &token);
template<auto S = Normal> bool sequenceImpl(const auto &... args);
template<auto S = Normal> bool sequence(const Token &token, const auto &... args);
bool isValid();
bool peek(const Token &token, const i32 index = 0);
bool peek(const Token &token, i32 index = 0);
friend bool Coordinates::operator==(const Coordinates &o) const;
friend bool Coordinates::operator!=(const Coordinates &o) const;
@@ -763,53 +774,53 @@ namespace hex::ui {
friend Coordinates Coordinates::operator-(const Coordinates &o) const;
private:
std::vector<Line> m_unfoldedLines;
RowToFoldedLine m_foldedLines;
std::vector<HiddenLine> m_hiddenLines;
std::map<i32,FoldSymbol> m_rowToFoldSymbol = {};
MatchedDelimiter m_matchedDelimiter = {};
UnfoldedLines m_unfoldedLines;
FoldedLines m_foldedLines;
HiddenLines m_hiddenLines;
FoldSymbols m_rowToFoldSymbol;
MatchedDelimiter m_matchedDelimiter{};
bool m_colorizerEnabled = true;
std::vector<std::string> m_defines;
StringVector m_defines;
FindReplaceHandler m_findReplaceHandler;
RowToSegments m_rowToSegments = {};
EditorState m_state = {};
UndoBuffer m_undoBuffer = {};
std::vector<i32> m_leadingLineSpaces = {};
RowToFoldSegments m_rowToFoldSegments;
EditorState m_state;
UndoBuffer m_undoBuffer;
Indices m_leadingLineSpaces;
i32 m_undoIndex = 0;
bool m_updateFlags = true;
Breakpoints m_breakpoints = {};
ErrorMarkers m_errorMarkers = {};
ErrorHoverBoxes m_errorHoverBoxes = {};
ErrorGotoBoxes m_errorGotoBoxes = {};
CursorBoxes m_cursorBoxes = {};
CodeFoldKeys m_codeFoldKeys = {};
CodeFolds m_codeFolds = {};
CodeFoldKeyMap m_codeFoldKeyMap = {};
CodeFoldKeyMap m_codeFoldValueMap = {};
CodeFoldKeyLineMap m_codeFoldKeyLineMap = {};
CodeFoldKeyLineMap m_codeFoldValueLineMap = {};
CodeFoldDelimiters m_codeFoldDelimiters = {};
Range m_codeFoldHighlighted = {};
CodeFoldState m_codeFoldState = {};
Breakpoints m_breakpoints;
ErrorMarkers m_errorMarkers;
ErrorHoverBoxes m_errorHoverBoxes;
ErrorGotoBoxes m_errorGotoBoxes;
CursorBoxes m_cursorBoxes;
CodeFoldKeys m_codeFoldKeys;
CodeFolds m_codeFolds;
CodeFoldKeyMap m_codeFoldKeyMap;
CodeFoldKeyMap m_codeFoldValueMap;
CodeFoldKeyLineMap m_codeFoldKeyLineMap;
CodeFoldKeyLineMap m_codeFoldValueLineMap;
CodeFoldDelimiters m_codeFoldDelimiters;
Range m_codeFoldHighlighted;
CodeFoldState m_codeFoldState;
bool m_codeFoldsDisabled = false;
std::map<i32,i32> m_rowToLineIndex = {};
std::map<i32,i32> m_lineIndexToRow = {};
ImVec2 m_cursorScreenPosition = {};
ImVec2 m_lineNumbersStartPos = {};
LineIndexToScreen m_lineIndexToScreen = {};
MultiLinesToRow m_multiLinesToRow = {};
RowCodeFoldTooltips m_rowCodeFoldTooltips = {};
Range m_interactiveSelection = {};
std::vector<std::string> m_clickableText;
IndexMap m_rowToLineIndex;
IndexMap m_lineIndexToRow;
ImVec2 m_cursorScreenPosition;
ImVec2 m_lineNumbersStartPos;
LineIndexToScreen m_lineIndexToScreen;
IndexMap m_multiLinesToRow;
RowCodeFoldTooltips m_rowCodeFoldTooltips;
Range m_interactiveSelection;
StringVector m_clickableText;
float m_topRow = 0.0F;
bool m_setTopRow = false;
bool m_restoreSavedFolds = true;
ImVec2 m_charAdvance = {};
ImVec2 m_charAdvance;
float m_leftMargin = 0.0F;
float m_topMargin = 0.0F;
float m_lineNumberFieldWidth = 0.0F;
bool m_textChanged = false;
LanguageDefinition m_languageDefinition = {};
LanguageDefinition m_languageDefinition;
RegexList m_regexList;
float m_numberOfLinesDisplayed = 0;
bool m_withinRender = false;
@@ -818,7 +829,7 @@ namespace hex::ui {
std::string m_title;
bool m_unfoldIfNeeded = false;
bool m_scrollToCursor = false;
Coordinates m_focusAtCoords = {};
Coordinates m_focusAtCoords;
bool m_updateFocus = false;
float m_oldTopMargin = 0.0F;
float m_scrollYIncrement = 0.0F;
@@ -826,17 +837,18 @@ namespace hex::ui {
bool m_breakPointsChanged = false;
bool m_readOnly = false;
u64 m_startTime = 0;
bool m_codeFoldStateLoaded = false;
bool m_codeFoldsChanged = false;
bool m_saveCodeFoldStateRequested = false;
bool m_useSavedFoldStatesRequested = false;
bool m_foldsAreInstalled = false;
std::vector<Token> m_tokens;
TokenIter m_curr;
TokenIter m_startToken, m_originalPosition, m_partOriginalPosition;
Tokens m_tokens;
SafeTokenIterator m_curr;
SafeTokenIterator m_startToken, m_originalPosition, m_partOriginalPosition;
bool m_interrupt = false;
std::vector<i32> m_firstTokenIdOfLine;
Indices m_firstTokenIdOfLine;
CodeFoldBlocks m_foldPoints;
std::set<Interval> m_globalBlocks;
GlobalBlocks m_globalBlocks;
i32 m_cachedGlobalRowMax{};
bool m_globalRowMaxChanged = true;
};
private:
@@ -871,11 +883,11 @@ namespace hex::ui {
float rowToLineIndex(i32 row);
float lineIndexToRow(i32 lineNumber);
void clearErrorMarkers();
void clearActionables() {return m_lines.clearActionables();}
void clearActionables() { m_lines.clearActionables();}
void saveCodeFoldStates();
void applyCodeFoldStates();
void readHiddenLines() { m_lines.readHiddenLines(); };
void writeHiddenLines() { m_lines.writeHiddenLines(); };
void removeHiddenLinesFromPattern() { m_lines.removeHiddenLinesFromPattern(); };
void addHiddenLinesToPattern() { m_lines.addHiddenLinesToPattern(); };
// Highlighting
private:
@@ -889,7 +901,7 @@ namespace hex::ui {
void renderSquare(ImVec2 lineStartScreenPos, ImDrawList *drawList, float boxSize, float verticalMargin, i32 color);
void renderMinus(ImVec2 lineStartScreenPos, ImDrawList *drawList, float boxSize, float verticalMargin, i32 color);
void renderPlus(ImVec2 lineStartScreenPos, ImDrawList *drawList, float boxSize, float verticalMargin, i32 color);
void renderCodeFolds(i32 row, ImDrawList *drawList, i32 color, Lines::FoldSymbol state);
void renderCodeFolds(i32 row, ImDrawList *drawList, i32 color, FoldSymbol state);
void drawLineNumbers(float lineNumber);
void drawBreakpoints(float lineIndex, const ImVec2 &contentSize, ImDrawList *drawList, std::string title);
void drawCodeFolds(float lineIndex, ImDrawList *drawList);
@@ -931,12 +943,12 @@ namespace hex::ui {
bool isOverwrite() const { return m_overwrite; }
void setText(const std::string &text, bool undo = false);
void setImGuiChildIgnored(bool value) { m_lines.setImGuiChildIgnored(value); }
std::vector<std::string> getTextLines() const;
StringVector getTextLines() const;
void setLanguageDefinition(const LanguageDefinition &aLanguageDef) { m_lines.setLanguageDefinition(aLanguageDef); }
std::string getLineText(i32 line);
void setTextChanged(bool value) { m_lines.setTextChanged(value); }
std::string getText(bool addHiddenLines = false) { return m_lines.getText(addHiddenLines); }
void addUndo(std::vector<UndoRecord> value) { m_lines.addUndo(value); }
std::string getText() { return m_lines.getText(); }
void addUndo(UndoRecords value) { m_lines.addUndo(value); }
bool isTextChanged() { return m_lines.isTextChanged(); }
void setHandleMouseInputs(bool value) { m_handleMouseInputs = value; }
bool isHandleMouseInputsEnabled() const { return m_handleKeyboardInputs; }
@@ -967,7 +979,7 @@ namespace hex::ui {
void moveEnd(bool select = false);
void moveToMatchedDelimiter(bool select = false);
void setCursorPosition(const Coordinates &position, bool unfoldIfNeeded = true, bool scrollToCursor = true) {
return m_lines.setCursorPosition(position, unfoldIfNeeded, scrollToCursor);
m_lines.setCursorPosition(position, unfoldIfNeeded, scrollToCursor);
};
void setScroll(ImVec2 scroll);
ImVec2 getScroll() const {return m_scroll;}
@@ -995,8 +1007,8 @@ namespace hex::ui {
void codeFoldCollapse(i32 level=1, bool recursive=false, bool all=false);
i32 getCodeFoldLevel(i32 line) const;
void resetFoldedSelections();
void computeLPSArray(const std::string &pattern, std::vector<i32> & lps);
std::vector<i32> KMPSearch(const std::string& text, const std::string& pattern);
void computeLPSArray(const std::string &pattern, Indices & lps);
Indices KMPSearch(const std::string& text, const std::string& pattern);
bool isEmpty();
// utf8
@@ -1011,7 +1023,7 @@ namespace hex::ui {
Coordinates lineCoordsToIndexCoords(const Coordinates &coordinates);
private:
float m_lineSpacing = 1.0F;
Lines m_lines = {};
Lines m_lines;
float m_newTopMargin = 0.0F;
bool m_topMarginChanged = false;
i32 m_tabSize = 4;
@@ -1027,7 +1039,7 @@ namespace hex::ui {
TextEditor *m_sourceCodeEditor = nullptr;
float m_shiftedScrollY = 0;
bool m_setScroll = false;
ImVec2 m_scroll = {};
ImVec2 m_scroll;
float m_scrollOffset = 0;
float m_maxScroll =0;
bool m_scrollFromLines = false;

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