mirror of https://github.com/WerWolv/ImHex
Fixes for next release. (#2429)
Attempt to fix WerWolv's strange off by one problem when using the mouse. Added a popup question for files that contain long lines (>1024 bytes). Also improved the handling of large lines, so it won't stall the app. May also contain other smaller issue fixes.
This commit is contained in:
parent
790c19a1cd
commit
52952652de
|
|
@ -1048,6 +1048,7 @@
|
|||
"hex.builtin.view.pattern_editor.menu.edit.copy": "Copy",
|
||||
"hex.builtin.view.pattern_editor.shortcut.copy": "Copy Selection to the Clipboard",
|
||||
"hex.builtin.view.pattern_editor.shortcut.cut": "Copy Selection to the Clipboard and Delete it",
|
||||
"hex.builtin.view.pattern_editor.warning_paste_large": "The clipboard contains a large amount of data. Are you sure you want to paste it?",
|
||||
"hex.builtin.view.pattern_editor.shortcut.paste": "Paste Clipboard Contents at the Cursor Position",
|
||||
"hex.builtin.view.pattern_editor.menu.edit.paste": "Paste",
|
||||
"hex.builtin.view.pattern_editor.menu.edit.undo": "Undo",
|
||||
|
|
|
|||
|
|
@ -324,16 +324,19 @@ namespace hex::ui {
|
|||
std::string m_colors;
|
||||
std::string m_flags;
|
||||
bool m_colorized = false;
|
||||
i32 m_lineMaxColumn;
|
||||
i32 m_lineTextSize;
|
||||
|
||||
Line() : m_chars(), m_colors(), m_flags(), m_colorized(false), m_lineMaxColumn(-1) {}
|
||||
Line() : m_chars(), m_colors(), m_flags(), m_colorized(false), m_lineTextSize(-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(getMaxCharColumn()) {}
|
||||
Line(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) {}
|
||||
m_chars(line), m_colors(std::string(line.size(), 0x00)), m_flags(std::string(line.size(), 0x00)), m_colorized(false), m_lineTextSize(
|
||||
getLineTextSize()) {}
|
||||
Line(const Line &line) : m_chars(line.m_chars), m_colors(line.m_colors), m_flags(line.m_flags), m_colorized(line.m_colorized), m_lineTextSize(line.m_lineTextSize) {}
|
||||
|
||||
i32 getCharacterColumn(i32 index) const;
|
||||
i32 getMaxCharColumn() const;
|
||||
i32 getCharColumn(i32 stringIndex) const;
|
||||
i32 getColumnIndex(i32 column) const;
|
||||
i32 getLineTextSize();
|
||||
i32 getStringTextSize(const std::string &str) const;
|
||||
LineIterator begin();
|
||||
LineIterator end();
|
||||
Line &operator=(const Line &line);
|
||||
|
|
@ -500,7 +503,7 @@ namespace hex::ui {
|
|||
void drawText(Coordinates &lineStart, u64 i, u32 tokenLength, char color);
|
||||
void postRender(const char *title, ImVec2 position, float lineNo);
|
||||
ImVec2 calculateCharAdvance() const;
|
||||
float textDistanceToLineStart(const Coordinates &from) const;
|
||||
float textDistanceToLineStart(const Coordinates &from);
|
||||
// Highlighting
|
||||
public:
|
||||
void colorize();
|
||||
|
|
@ -529,6 +532,7 @@ namespace hex::ui {
|
|||
void copy();
|
||||
void cut();
|
||||
void paste();
|
||||
void doPaste(const char *clipText);
|
||||
void deleteChar();
|
||||
void insertText(const std::string &value);
|
||||
void insertText(const char *value);
|
||||
|
|
@ -621,9 +625,9 @@ namespace hex::ui {
|
|||
Coordinates lineCoordsToIndexCoords(const Coordinates &coordinates) const;
|
||||
i32 lineCoordinatesToIndex(const Coordinates &coordinates) const;
|
||||
Coordinates getCharacterCoordinates(i32 line, i32 index);
|
||||
i32 getLineCharacterCount(i32 line);
|
||||
i32 getLineCharColumn(i32 lineIndex, i32 stringIndex);
|
||||
u64 getLineByteCount(i32 line) const;
|
||||
i32 getLineMaxColumn(i32 line);
|
||||
i32 getLineMaxCharColumn(i32 lineIndex);
|
||||
|
||||
public:
|
||||
FindReplaceHandler m_findReplaceHandler;
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
#include <ui/text_editor.hpp>
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
#include <regex>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
#include <wolv/utils/string.hpp>
|
||||
#include <popups/popup_question.hpp>
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
#include "imgui.h"
|
||||
|
||||
|
|
@ -227,6 +225,7 @@ namespace hex::ui {
|
|||
m_lines.resize(1);
|
||||
m_lines[0].clear();
|
||||
} else {
|
||||
m_lines.clear();
|
||||
m_lines.resize(lineCount);
|
||||
u64 i = 0;
|
||||
for (auto line: vectorString) {
|
||||
|
|
@ -276,7 +275,7 @@ namespace hex::ui {
|
|||
--end.m_line;
|
||||
if (end.m_line >= (i32) m_lines.size())
|
||||
end.m_line = isEmpty() ? 0 : (i32) m_lines.size() - 1;
|
||||
end.m_column = getLineMaxColumn(end.m_line);
|
||||
end.m_column = getLineMaxCharColumn(end.m_line);
|
||||
|
||||
u.m_removedSelection = Selection(start, end);
|
||||
u.m_removed = getText(u.m_removedSelection);
|
||||
|
|
@ -530,7 +529,7 @@ namespace hex::ui {
|
|||
setCursorPosition(pos);
|
||||
auto &line = m_lines[pos.m_line];
|
||||
|
||||
if (pos.m_column == getLineMaxColumn(pos.m_line)) {
|
||||
if (pos.m_column == getLineMaxCharColumn(pos.m_line)) {
|
||||
if (pos.m_line == (i32) m_lines.size() - 1)
|
||||
return;
|
||||
|
||||
|
|
@ -589,7 +588,7 @@ namespace hex::ui {
|
|||
advance(u.m_removedSelection.m_end);
|
||||
|
||||
auto &prevLine = m_lines[pos.m_line - 1];
|
||||
auto prevSize = getLineMaxColumn(pos.m_line - 1);
|
||||
auto prevSize = getLineMaxCharColumn(pos.m_line - 1);
|
||||
if (prevSize == 0)
|
||||
prevLine = line;
|
||||
else
|
||||
|
|
@ -684,34 +683,45 @@ namespace hex::ui {
|
|||
refreshSearchResults();
|
||||
}
|
||||
|
||||
void TextEditor::doPaste(const char *clipText) {
|
||||
UndoRecord u;
|
||||
if (clipText != nullptr) {
|
||||
auto clipTextStr = wolv::util::preprocessText(clipText);
|
||||
|
||||
u.m_before = m_state;
|
||||
|
||||
if (hasSelection()) {
|
||||
u.m_removed = getSelectedText();
|
||||
u.m_removedSelection = m_state.m_selection;
|
||||
deleteSelection();
|
||||
}
|
||||
|
||||
u.m_added = clipTextStr;
|
||||
u.m_addedSelection.m_start = setCoordinates(m_state.m_cursorPosition);
|
||||
insertText(clipTextStr);
|
||||
|
||||
u.m_addedSelection.m_end = setCoordinates(m_state.m_cursorPosition);
|
||||
u.m_after = m_state;
|
||||
addUndo(u);
|
||||
}
|
||||
refreshSearchResults();
|
||||
}
|
||||
|
||||
void TextEditor::paste() {
|
||||
if (m_readOnly)
|
||||
return;
|
||||
|
||||
auto clipText = ImGui::GetClipboardText();
|
||||
const char *clipText = ImGui::GetClipboardText();
|
||||
if (clipText != nullptr) {
|
||||
auto len = strlen(clipText);
|
||||
if (len > 0) {
|
||||
std::string text = wolv::util::preprocessText(clipText);
|
||||
UndoRecord u;
|
||||
u.m_before = m_state;
|
||||
|
||||
if (hasSelection()) {
|
||||
u.m_removed = getSelectedText();
|
||||
u.m_removedSelection = m_state.m_selection;
|
||||
deleteSelection();
|
||||
}
|
||||
|
||||
u.m_added = text;
|
||||
u.m_addedSelection.m_start = setCoordinates(m_state.m_cursorPosition);
|
||||
insertText(text);
|
||||
|
||||
u.m_addedSelection.m_end = setCoordinates(m_state.m_cursorPosition);
|
||||
u.m_after = m_state;
|
||||
addUndo(u);
|
||||
auto stringVector = wolv::util::splitString(clipText, "\n", false);
|
||||
if (std::any_of(stringVector.begin(), stringVector.end(), [](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);
|
||||
}, [] {});
|
||||
} else {
|
||||
doPaste(clipText);
|
||||
}
|
||||
}
|
||||
refreshSearchResults();
|
||||
}
|
||||
|
||||
bool TextEditor::canUndo() {
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ namespace hex::ui {
|
|||
return;
|
||||
|
||||
auto lindex = m_state.m_cursorPosition.m_line;
|
||||
auto lineMaxColumn = getLineMaxColumn(lindex);
|
||||
auto lineMaxColumn = getLineMaxCharColumn(lindex);
|
||||
auto column = std::min(m_state.m_cursorPosition.m_column, lineMaxColumn);
|
||||
|
||||
while (amount-- > 0) {
|
||||
|
|
@ -167,7 +167,7 @@ namespace hex::ui {
|
|||
return;
|
||||
|
||||
auto lindex = m_state.m_cursorPosition.m_line;
|
||||
auto lineMaxColumn = getLineMaxColumn(lindex);
|
||||
auto lineMaxColumn = getLineMaxCharColumn(lindex);
|
||||
auto column = std::min(m_state.m_cursorPosition.m_column, lineMaxColumn);
|
||||
|
||||
while (amount-- > 0) {
|
||||
|
|
@ -247,7 +247,7 @@ namespace hex::ui {
|
|||
else {
|
||||
postIdx = postfix.find_first_not_of(" ");
|
||||
if (postIdx == std::string::npos)
|
||||
home = getLineMaxColumn(oldPos.m_line);
|
||||
home = getLineMaxCharColumn(oldPos.m_line);
|
||||
else if (postIdx == 0)
|
||||
home = 0;
|
||||
else
|
||||
|
|
@ -262,7 +262,7 @@ namespace hex::ui {
|
|||
else {
|
||||
postIdx = postfix.find_first_not_of(" ");
|
||||
if (postIdx == std::string::npos)
|
||||
home = getLineMaxColumn(oldPos.m_line);
|
||||
home = getLineMaxCharColumn(oldPos.m_line);
|
||||
else
|
||||
home = oldPos.m_column + postIdx;
|
||||
}
|
||||
|
|
@ -288,7 +288,7 @@ namespace hex::ui {
|
|||
void TextEditor::moveEnd(bool select) {
|
||||
resetCursorBlinkTime();
|
||||
auto oldPos = m_state.m_cursorPosition;
|
||||
setCursorPosition(setCoordinates(m_state.m_cursorPosition.m_line, getLineMaxColumn(oldPos.m_line)));
|
||||
setCursorPosition(setCoordinates(m_state.m_cursorPosition.m_line, getLineMaxCharColumn(oldPos.m_line)));
|
||||
|
||||
if (m_state.m_cursorPosition != oldPos) {
|
||||
if (select) {
|
||||
|
|
@ -339,7 +339,7 @@ namespace hex::ui {
|
|||
else
|
||||
result.m_line = std::clamp(line, 0, lineCount - 1);
|
||||
|
||||
auto maxColumn = getLineMaxColumn(result.m_line) + 1;
|
||||
auto maxColumn = getLineMaxCharColumn(result.m_line) + 1;
|
||||
if (column < 0 && maxColumn + column >= 0)
|
||||
result.m_column = maxColumn + column;
|
||||
else
|
||||
|
|
|
|||
|
|
@ -287,18 +287,52 @@ namespace hex::ui {
|
|||
continue;
|
||||
}
|
||||
auto colors = m_lines[lineNo].m_colors;
|
||||
u64 colorsSize = std::min((u64)std::floor(textEditorSize.x / m_charAdvance.x), (u64) colors.size());
|
||||
u64 i = ImGui::GetScrollX() / m_charAdvance.x;
|
||||
u64 maxI = i + colorsSize;
|
||||
auto lineSize = line.getLineTextSize();
|
||||
i64 colorsSize = std::min((u64)textEditorSize.x, (u64) lineSize);
|
||||
i64 start = ImGui::GetScrollX();
|
||||
i64 textSize = 0;
|
||||
Coordinates head = Coordinates(lineNo, start / m_charAdvance.x);
|
||||
textSize = textDistanceToLineStart(head);
|
||||
auto maxColumn = line.getCharColumn(line.size());
|
||||
if (textSize < start) {
|
||||
while (textSize < start && head.m_column < maxColumn) {
|
||||
head.m_column += 1;
|
||||
textSize = textDistanceToLineStart(head);
|
||||
}
|
||||
} else {
|
||||
while (textSize > start && head.m_column > 0) {
|
||||
head.m_column -= 1;
|
||||
textSize = textDistanceToLineStart(head);
|
||||
}
|
||||
}
|
||||
Coordinates current = Coordinates(lineNo, (start + colorsSize) / m_charAdvance.x);
|
||||
textSize = textDistanceToLineStart(current);
|
||||
if (textSize < start + colorsSize) {
|
||||
while (textSize < start + colorsSize && current.m_column < maxColumn) {
|
||||
current.m_column += 1;
|
||||
textSize = textDistanceToLineStart(current);
|
||||
}
|
||||
} else {
|
||||
while (textSize > start + colorsSize && current.m_column > 0) {
|
||||
current.m_column -= 1;
|
||||
textSize = textDistanceToLineStart(current);
|
||||
}
|
||||
}
|
||||
|
||||
u64 i = line.getColumnIndex(head.m_column);
|
||||
u64 maxI = line.getColumnIndex(current.m_column);
|
||||
while (i < maxI) {
|
||||
char color = std::clamp(colors[i], (char) PaletteIndex::Default, (char) ((u8) PaletteIndex::Max - 1));
|
||||
auto index = colors.find_first_not_of(color, i);
|
||||
index -= i;
|
||||
if (index == std::string::npos)
|
||||
index = maxI;
|
||||
else
|
||||
index -= i;
|
||||
|
||||
u32 tokenLength = std::clamp((u64) index,(u64) 1, maxI - i);
|
||||
if (m_updateFocus)
|
||||
setFocus();
|
||||
auto lineStart = setCoordinates(lineNo, i);
|
||||
auto lineStart = setCoordinates(lineNo, line.getCharColumn(i));
|
||||
|
||||
drawText(lineStart, i, tokenLength, color);
|
||||
|
||||
|
|
@ -571,10 +605,17 @@ namespace hex::ui {
|
|||
return ImVec2(fontSize, ImGui::GetTextLineHeightWithSpacing() * m_lineSpacing);
|
||||
}
|
||||
|
||||
float TextEditor::textDistanceToLineStart(const Coordinates &aFrom) const {
|
||||
float TextEditor::textDistanceToLineStart(const Coordinates &aFrom) {
|
||||
auto &line = m_lines[aFrom.m_line];
|
||||
i32 colIndex = lineCoordinatesToIndex(aFrom);
|
||||
auto substr = line.m_chars.substr(0, colIndex);
|
||||
return ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, substr.c_str(), nullptr, nullptr).x;
|
||||
auto substr1 = line.m_chars.substr(0, colIndex);
|
||||
auto substr2 =line.m_chars.substr(colIndex, line.m_chars.size() - colIndex);
|
||||
if (substr2.size() < substr1.size()) {
|
||||
auto distanceToEnd = line.getStringTextSize(substr2.c_str());
|
||||
line.m_lineTextSize = line.getLineTextSize();
|
||||
return line.m_lineTextSize - distanceToEnd;
|
||||
}
|
||||
|
||||
return line.getStringTextSize(substr1.c_str());
|
||||
}
|
||||
}
|
||||
|
|
@ -156,7 +156,7 @@ namespace hex::ui {
|
|||
m_colors = line.m_colors;
|
||||
m_flags = line.m_flags;
|
||||
m_colorized = line.m_colorized;
|
||||
m_lineMaxColumn = line.m_lineMaxColumn;
|
||||
m_lineTextSize = line.m_lineTextSize;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -165,7 +165,7 @@ namespace hex::ui {
|
|||
m_colors = std::move(line.m_colors);
|
||||
m_flags = std::move(line.m_flags);
|
||||
m_colorized = line.m_colorized;
|
||||
m_lineMaxColumn = line.m_lineMaxColumn;
|
||||
m_lineTextSize = line.m_lineTextSize;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -198,7 +198,7 @@ namespace hex::ui {
|
|||
m_colors.push_back(0x00);
|
||||
m_flags.push_back(0x00);
|
||||
m_colorized = false;
|
||||
m_lineMaxColumn = -1;
|
||||
m_lineTextSize = -1;
|
||||
}
|
||||
|
||||
bool TextEditor::Line::empty() const {
|
||||
|
|
@ -278,12 +278,7 @@ namespace hex::ui {
|
|||
void TextEditor::Line::append(LineIterator begin, LineIterator end) {
|
||||
if (begin.m_charsIter < end.m_charsIter) {
|
||||
m_chars.append(begin.m_charsIter, end.m_charsIter);
|
||||
std::string charsAppended(begin.m_charsIter, end.m_charsIter);
|
||||
|
||||
if (m_lineMaxColumn < 0)
|
||||
m_lineMaxColumn = this->getMaxCharColumn();
|
||||
|
||||
m_lineMaxColumn += TextEditor::getStringCharacterCount(charsAppended);
|
||||
m_lineTextSize = -1;
|
||||
}
|
||||
if (begin.m_colorsIter < end.m_colorsIter)
|
||||
m_colors.append(begin.m_colorsIter, end.m_colorsIter);
|
||||
|
|
@ -317,12 +312,7 @@ namespace hex::ui {
|
|||
m_colors.insert(iter.m_colorsIter, beginLine.m_colorsIter, endLine.m_colorsIter);
|
||||
m_flags.insert(iter.m_flagsIter, beginLine.m_flagsIter, endLine.m_flagsIter);
|
||||
m_colorized = false;
|
||||
std::string charsInserted(beginLine.m_charsIter, endLine.m_charsIter);
|
||||
|
||||
if (m_lineMaxColumn < 0)
|
||||
m_lineMaxColumn = this->getMaxCharColumn();
|
||||
|
||||
m_lineMaxColumn += TextEditor::getStringCharacterCount(charsInserted);
|
||||
m_lineTextSize = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -331,12 +321,7 @@ namespace hex::ui {
|
|||
m_colors.erase(begin.m_colorsIter);
|
||||
m_flags.erase(begin.m_flagsIter);
|
||||
m_colorized = false;
|
||||
std::string charsErased(begin.m_charsIter, end().m_charsIter);
|
||||
|
||||
if (m_lineMaxColumn < 0)
|
||||
m_lineMaxColumn = this->getMaxCharColumn();
|
||||
|
||||
m_lineMaxColumn -= TextEditor::getStringCharacterCount(charsErased);
|
||||
m_lineTextSize = -1;
|
||||
}
|
||||
|
||||
void TextEditor::Line::erase(LineIterator begin, u64 count) {
|
||||
|
|
@ -346,12 +331,7 @@ namespace hex::ui {
|
|||
m_colors.erase(begin.m_colorsIter, begin.m_colorsIter + count);
|
||||
m_flags.erase(begin.m_flagsIter, begin.m_flagsIter + count);
|
||||
m_colorized = false;
|
||||
std::string charsErased(begin.m_charsIter, begin.m_charsIter + count);
|
||||
|
||||
if (m_lineMaxColumn < 0)
|
||||
m_lineMaxColumn = this->getMaxCharColumn();
|
||||
|
||||
m_lineMaxColumn -= TextEditor::getStringCharacterCount(charsErased);
|
||||
m_lineTextSize = -1;
|
||||
}
|
||||
|
||||
void TextEditor::Line::erase(u64 start, u64 length) {
|
||||
|
|
@ -374,7 +354,7 @@ namespace hex::ui {
|
|||
m_colors.clear();
|
||||
m_flags.clear();
|
||||
m_colorized = false;
|
||||
m_lineMaxColumn = 0;
|
||||
m_lineTextSize = -1;
|
||||
}
|
||||
|
||||
void TextEditor::Line::setLine(const std::string &text) {
|
||||
|
|
@ -382,7 +362,7 @@ namespace hex::ui {
|
|||
m_colors = std::string(text.size(), 0x00);
|
||||
m_flags = std::string(text.size(), 0x00);
|
||||
m_colorized = false;
|
||||
m_lineMaxColumn = -1;
|
||||
m_lineTextSize = -1;
|
||||
}
|
||||
|
||||
void TextEditor::Line::setLine(const Line &text) {
|
||||
|
|
@ -390,7 +370,7 @@ namespace hex::ui {
|
|||
m_colors = text.m_colors;
|
||||
m_flags = text.m_flags;
|
||||
m_colorized = text.m_colorized;
|
||||
m_lineMaxColumn = text.m_lineMaxColumn;
|
||||
m_lineTextSize = text.m_lineTextSize;
|
||||
}
|
||||
|
||||
bool TextEditor::Line::needsUpdate() const {
|
||||
|
|
@ -520,7 +500,7 @@ namespace hex::ui {
|
|||
m_state.m_cursorPosition = screenPosToCoordinates(ImGui::GetMousePos());
|
||||
auto line = m_state.m_cursorPosition.m_line;
|
||||
m_state.m_selection.m_start = setCoordinates(line, 0);
|
||||
m_state.m_selection.m_end = setCoordinates(line, getLineMaxColumn(line));
|
||||
m_state.m_selection.m_end = setCoordinates(line, getLineMaxCharColumn(line));
|
||||
}
|
||||
|
||||
m_lastClick = -1.0f;
|
||||
|
|
@ -824,7 +804,7 @@ namespace hex::ui {
|
|||
editor->m_state.m_cursorPosition = editor->m_state.m_selection.m_start;
|
||||
if (editor->isStartOfLine()) {
|
||||
editor->m_state.m_cursorPosition.m_line--;
|
||||
editor->m_state.m_cursorPosition.m_column = editor->getLineMaxColumn(editor->m_state.m_cursorPosition.m_line);
|
||||
editor->m_state.m_cursorPosition.m_column = editor->getLineMaxCharColumn(editor->m_state.m_cursorPosition.m_line);
|
||||
} else
|
||||
editor->m_state.m_cursorPosition.m_column--;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,37 @@
|
|||
#include <ui/text_editor.hpp>
|
||||
#include <hex/helpers/scaling.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
namespace hex::ui {
|
||||
|
||||
i32 TextEditor::Line::getColumnIndex(i32 column) const {
|
||||
|
||||
i32 idx = 0;
|
||||
for (i32 col = 0; idx < (i32) size() && col < column; ++col)
|
||||
idx += TextEditor::utf8CharLength(m_chars[idx]);
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
i32 TextEditor::Line::getCharColumn(i32 stringIndex) const {
|
||||
i32 limit = std::max(0, std::min(stringIndex, (i32) size()));
|
||||
|
||||
i32 col = 0;
|
||||
for (i32 idx = 0; idx < limit; col++)
|
||||
idx += TextEditor::utf8CharLength(m_chars[idx]);
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
i32 TextEditor::Line::getStringTextSize(const std::string &str) const {
|
||||
return ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, str.c_str(), nullptr, nullptr).x;
|
||||
}
|
||||
|
||||
i32 TextEditor::Line::getLineTextSize() {
|
||||
m_lineTextSize = getStringTextSize(m_chars);
|
||||
return m_lineTextSize;
|
||||
}
|
||||
|
||||
// https://en.wikipedia.org/wiki/UTF-8
|
||||
// We assume that the char is a standalone character (<128) or a leading byte of an UTF-8 code sequence (non-10xxxxxx code)
|
||||
i32 TextEditor::utf8CharLength(u8 c) {
|
||||
|
|
@ -27,20 +57,18 @@ namespace hex::ui {
|
|||
return count;
|
||||
}
|
||||
|
||||
i32 TextEditor::getLineCharacterCount(i32 lineIndex) {
|
||||
i32 TextEditor::getLineCharColumn(i32 lineIndex, i32 stringIndex) {
|
||||
if (lineIndex >= (i64) m_lines.size() || lineIndex < 0)
|
||||
return 0;
|
||||
Line &line = m_lines[lineIndex];
|
||||
if (line.m_lineMaxColumn != -1)
|
||||
return line.m_lineMaxColumn;
|
||||
else {
|
||||
auto str = line.m_chars;
|
||||
i32 count = 0;
|
||||
for (u32 idx = 0; idx < str.size(); count++)
|
||||
idx += TextEditor::utf8CharLength(str[idx]);
|
||||
line.m_lineMaxColumn = count;
|
||||
return count;
|
||||
}
|
||||
return line.getCharColumn(stringIndex);
|
||||
}
|
||||
|
||||
i32 TextEditor::getLineMaxCharColumn(i32 lineIndex) {
|
||||
if (lineIndex >= (i64) m_lines.size() || lineIndex < 0)
|
||||
return 0;
|
||||
Line &line = m_lines[lineIndex];
|
||||
return line.getCharColumn(line.size());
|
||||
}
|
||||
|
||||
// "Borrowed" from ImGui source
|
||||
|
|
@ -83,24 +111,13 @@ namespace hex::ui {
|
|||
return size;
|
||||
}
|
||||
|
||||
static i32 utf8CharCount(const std::string &line, i32 start, i32 numChars) {
|
||||
if (line.empty())
|
||||
return 0;
|
||||
|
||||
i32 index = 0;
|
||||
for (i32 column = 0; start + index < (i32) line.size() && column < numChars; ++column)
|
||||
index += TextEditor::utf8CharLength(line[start + index]);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
TextEditor::Coordinates TextEditor::screenPosToCoordinates(const ImVec2 &position) {
|
||||
ImVec2 local = position - ImGui::GetCursorScreenPos();
|
||||
i32 lineNo = std::max(0, (i32) floor(local.y / m_charAdvance.y));
|
||||
if (local.x < (m_leftMargin - 2) || lineNo >= (i32) m_lines.size() || m_lines[lineNo].empty())
|
||||
if (local.x < (m_leftMargin - 2_scaled) || lineNo >= (i32) m_lines.size() || m_lines[lineNo].empty())
|
||||
return setCoordinates(std::min(lineNo, (i32) m_lines.size() - 1), 0);
|
||||
std::string line = m_lines[lineNo].m_chars;
|
||||
local.x -= (m_leftMargin - 5);
|
||||
local.x -= (m_leftMargin - 5_scaled);
|
||||
i32 count = 0;
|
||||
u64 length;
|
||||
i32 increase;
|
||||
|
|
@ -123,7 +140,7 @@ namespace hex::ui {
|
|||
return Invalid;
|
||||
|
||||
const auto &line = m_lines[coordinates.m_line];
|
||||
return Coordinates(coordinates.m_line,utf8CharCount(line.m_chars, 0, coordinates.m_column));
|
||||
return Coordinates(coordinates.m_line,line.getColumnIndex(coordinates.m_column));
|
||||
}
|
||||
|
||||
i32 TextEditor::lineCoordinatesToIndex(const Coordinates &coordinates) const {
|
||||
|
|
@ -131,29 +148,14 @@ namespace hex::ui {
|
|||
return -1;
|
||||
|
||||
const auto &line = m_lines[coordinates.m_line];
|
||||
return utf8CharCount(line.m_chars, 0, coordinates.m_column);
|
||||
}
|
||||
|
||||
i32 TextEditor::Line::getCharacterColumn(i32 index) const {
|
||||
i32 col = 0;
|
||||
i32 i = 0;
|
||||
while (i < index && i < (i32) size()) {
|
||||
auto c = m_chars[i];
|
||||
i += TextEditor::utf8CharLength(c);
|
||||
col++;
|
||||
}
|
||||
return col;
|
||||
}
|
||||
|
||||
i32 TextEditor::Line::getMaxCharColumn() const {
|
||||
return getCharacterColumn(size());
|
||||
return line.getColumnIndex(coordinates.m_column);
|
||||
}
|
||||
|
||||
TextEditor::Coordinates TextEditor::getCharacterCoordinates(i32 lineIndex, i32 strIndex) {
|
||||
if (lineIndex < 0 || lineIndex >= (i32) m_lines.size())
|
||||
return Coordinates(0, 0);
|
||||
auto &line = m_lines[lineIndex];
|
||||
return setCoordinates(lineIndex, line.getCharacterColumn(strIndex));
|
||||
return setCoordinates(lineIndex, line.getCharColumn(strIndex));
|
||||
}
|
||||
|
||||
u64 TextEditor::getLineByteCount(i32 lineIndex) const {
|
||||
|
|
@ -164,10 +166,6 @@ namespace hex::ui {
|
|||
return line.size();
|
||||
}
|
||||
|
||||
i32 TextEditor::getLineMaxColumn(i32 lineIndex) {
|
||||
return getLineCharacterCount(lineIndex);
|
||||
}
|
||||
|
||||
TextEditor::Coordinates TextEditor::stringIndexToCoordinates(i32 strIndex, const std::string &input) {
|
||||
if (strIndex < 0 || strIndex > (i32) input.size())
|
||||
return TextEditor::Coordinates(0, 0);
|
||||
|
|
|
|||
Loading…
Reference in New Issue