This commit is contained in:
2025-12-07 01:35:33 +03:00
commit 6cc0a613dc
342 changed files with 166529 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,457 @@
#pragma once
#include "imgui.h"
#include <array>
#include <map>
#include <memory>
#include <regex>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
class TextEditor
{
public:
enum class PaletteIndex
{
Default,
Keyword,
Number,
String,
CharLiteral,
Punctuation,
Preprocessor,
Identifier,
KnownIdentifier,
PreprocIdentifier,
Comment,
MultiLineComment,
Background,
Cursor,
Selection,
ErrorMarker,
Breakpoint,
LineNumber,
CurrentLineFill,
CurrentLineFillInactive,
CurrentLineEdge,
Max
};
enum class SelectionMode
{
Normal,
Word,
Line
};
struct Breakpoint
{
int mLine;
bool mEnabled;
std::string mCondition;
Breakpoint() : mLine(-1), mEnabled(false)
{
}
};
// Represents a character coordinate from the user's point of view,
// i. e. consider an uniform grid (assuming fixed-width font) on the
// screen as it is rendered, and each cell has its own coordinate, starting from 0.
// Tabs are counted as [1..mTabSize] count empty spaces, depending on
// how many space is necessary to reach the next tab stop.
// For example, coordinate (1, 5) represents the character 'B' in a line "\tABC", when mTabSize
// = 4, because it is rendered as " ABC" on the screen.
struct Coordinates
{
int mLine, mColumn;
Coordinates() : mLine(0), mColumn(0)
{
}
Coordinates(int aLine, int aColumn) : mLine(aLine), mColumn(aColumn)
{
assert(aLine >= 0);
assert(aColumn >= 0);
}
static Coordinates Invalid()
{
static Coordinates invalid(-1, -1);
return invalid;
}
bool operator==(const Coordinates &o) const
{
return mLine == o.mLine && mColumn == o.mColumn;
}
bool operator!=(const Coordinates &o) const
{
return mLine != o.mLine || mColumn != o.mColumn;
}
bool operator<(const Coordinates &o) const
{
if (mLine != o.mLine)
return mLine < o.mLine;
return mColumn < o.mColumn;
}
bool operator>(const Coordinates &o) const
{
if (mLine != o.mLine)
return mLine > o.mLine;
return mColumn > o.mColumn;
}
bool operator<=(const Coordinates &o) const
{
if (mLine != o.mLine)
return mLine < o.mLine;
return mColumn <= o.mColumn;
}
bool operator>=(const Coordinates &o) const
{
if (mLine != o.mLine)
return mLine > o.mLine;
return mColumn >= o.mColumn;
}
};
struct Identifier
{
Coordinates mLocation;
std::string mDeclaration;
};
typedef std::string String;
typedef std::unordered_map<std::string, Identifier> Identifiers;
typedef std::unordered_set<std::string> Keywords;
typedef std::map<int, std::string> ErrorMarkers;
typedef std::unordered_set<int> Breakpoints;
typedef std::array<ImU32, (unsigned)PaletteIndex::Max> Palette;
typedef uint8_t Char;
struct Glyph
{
Char mChar;
PaletteIndex mColorIndex = PaletteIndex::Default;
bool mComment : 1;
bool mMultiLineComment : 1;
bool mPreprocessor : 1;
Glyph(Char aChar, PaletteIndex aColorIndex)
: mChar(aChar), mColorIndex(aColorIndex), mComment(false), mMultiLineComment(false),
mPreprocessor(false)
{
}
};
typedef std::vector<Glyph> Line;
typedef std::vector<Line> Lines;
struct LanguageDefinition
{
typedef std::pair<std::string, PaletteIndex> TokenRegexString;
typedef std::vector<TokenRegexString> TokenRegexStrings;
typedef bool (*TokenizeCallback)(const char *in_begin, const char *in_end,
const char *&out_begin, const char *&out_end,
PaletteIndex &paletteIndex);
std::string mName;
Keywords mKeywords;
Identifiers mIdentifiers;
Identifiers mPreprocIdentifiers;
std::string mCommentStart, mCommentEnd, mSingleLineComment;
char mPreprocChar;
bool mAutoIndentation;
TokenizeCallback mTokenize;
TokenRegexStrings mTokenRegexStrings;
bool mCaseSensitive;
LanguageDefinition()
: mPreprocChar('#'), mAutoIndentation(true), mTokenize(nullptr), mCaseSensitive(true)
{
}
static const LanguageDefinition &CPlusPlus();
static const LanguageDefinition &HLSL();
static const LanguageDefinition &GLSL();
static const LanguageDefinition &C();
static const LanguageDefinition &SQL();
static const LanguageDefinition &AngelScript();
static const LanguageDefinition &Lua();
};
TextEditor();
~TextEditor();
void SetLanguageDefinition(const LanguageDefinition &aLanguageDef);
const LanguageDefinition &GetLanguageDefinition() const
{
return mLanguageDefinition;
}
const Palette &GetPalette() const
{
return mPaletteBase;
}
void SetPalette(const Palette &aValue);
void SetErrorMarkers(const ErrorMarkers &aMarkers)
{
mErrorMarkers = aMarkers;
}
void SetBreakpoints(const Breakpoints &aMarkers)
{
mBreakpoints = aMarkers;
}
void Render(const char *aTitle, const ImVec2 &aSize = ImVec2(), bool aBorder = false);
void SetText(const std::string &aText);
std::string GetText() const;
void SetTextLines(const std::vector<std::string> &aLines);
std::vector<std::string> GetTextLines() const;
std::string GetSelectedText() const;
std::string GetCurrentLineText() const;
int GetTotalLines() const
{
return (int)mLines.size();
}
bool IsOverwrite() const
{
return mOverwrite;
}
void SetReadOnly(bool aValue);
bool IsReadOnly() const
{
return mReadOnly;
}
bool IsTextChanged() const
{
return mTextChanged;
}
bool IsCursorPositionChanged() const
{
return mCursorPositionChanged;
}
bool IsColorizerEnabled() const
{
return mColorizerEnabled;
}
void SetColorizerEnable(bool aValue);
Coordinates GetCursorPosition() const
{
return GetActualCursorCoordinates();
}
void SetCursorPosition(const Coordinates &aPosition);
inline void SetHandleMouseInputs(bool aValue)
{
mHandleMouseInputs = aValue;
}
inline bool IsHandleMouseInputsEnabled() const
{
return mHandleKeyboardInputs;
}
inline void SetHandleKeyboardInputs(bool aValue)
{
mHandleKeyboardInputs = aValue;
}
inline bool IsHandleKeyboardInputsEnabled() const
{
return mHandleKeyboardInputs;
}
inline void SetImGuiChildIgnored(bool aValue)
{
mIgnoreImGuiChild = aValue;
}
inline bool IsImGuiChildIgnored() const
{
return mIgnoreImGuiChild;
}
inline void SetShowWhitespaces(bool aValue)
{
mShowWhitespaces = aValue;
}
inline bool IsShowingWhitespaces() const
{
return mShowWhitespaces;
}
void SetTabSize(int aValue);
inline int GetTabSize() const
{
return mTabSize;
}
void InsertText(const std::string &aValue);
void InsertText(const char *aValue);
void MoveUp(int aAmount = 1, bool aSelect = false);
void MoveDown(int aAmount = 1, bool aSelect = false);
void MoveLeft(int aAmount = 1, bool aSelect = false, bool aWordMode = false);
void MoveRight(int aAmount = 1, bool aSelect = false, bool aWordMode = false);
void MoveTop(bool aSelect = false);
void MoveBottom(bool aSelect = false);
void MoveHome(bool aSelect = false);
void MoveEnd(bool aSelect = false);
void SetSelectionStart(const Coordinates &aPosition);
void SetSelectionEnd(const Coordinates &aPosition);
void SetSelection(const Coordinates &aStart, const Coordinates &aEnd,
SelectionMode aMode = SelectionMode::Normal);
void SelectWordUnderCursor();
void SelectAll();
bool HasSelection() const;
void Copy();
void Cut();
void Paste();
void Delete();
bool CanUndo() const;
bool CanRedo() const;
void Undo(int aSteps = 1);
void Redo(int aSteps = 1);
static const Palette &GetDarkPalette();
static const Palette &GetLightPalette();
static const Palette &GetRetroBluePalette();
private:
typedef std::vector<std::pair<std::regex, PaletteIndex>> RegexList;
struct EditorState
{
Coordinates mSelectionStart;
Coordinates mSelectionEnd;
Coordinates mCursorPosition;
};
class UndoRecord
{
public:
UndoRecord()
{
}
~UndoRecord()
{
}
UndoRecord(const std::string &aAdded, const TextEditor::Coordinates aAddedStart,
const TextEditor::Coordinates aAddedEnd,
const std::string &aRemoved, const TextEditor::Coordinates aRemovedStart,
const TextEditor::Coordinates aRemovedEnd,
TextEditor::EditorState &aBefore, TextEditor::EditorState &aAfter);
void Undo(TextEditor *aEditor);
void Redo(TextEditor *aEditor);
std::string mAdded;
Coordinates mAddedStart;
Coordinates mAddedEnd;
std::string mRemoved;
Coordinates mRemovedStart;
Coordinates mRemovedEnd;
EditorState mBefore;
EditorState mAfter;
};
typedef std::vector<UndoRecord> UndoBuffer;
void ProcessInputs();
void Colorize(int aFromLine = 0, int aCount = -1);
void ColorizeRange(int aFromLine = 0, int aToLine = 0);
void ColorizeInternal();
float TextDistanceToLineStart(const Coordinates &aFrom) const;
void EnsureCursorVisible();
int GetPageSize() const;
std::string GetText(const Coordinates &aStart, const Coordinates &aEnd) const;
Coordinates GetActualCursorCoordinates() const;
Coordinates SanitizeCoordinates(const Coordinates &aValue) const;
void Advance(Coordinates &aCoordinates) const;
void DeleteRange(const Coordinates &aStart, const Coordinates &aEnd);
int InsertTextAt(Coordinates &aWhere, const char *aValue);
void AddUndo(UndoRecord &aValue);
Coordinates ScreenPosToCoordinates(const ImVec2 &aPosition) const;
Coordinates FindWordStart(const Coordinates &aFrom) const;
Coordinates FindWordEnd(const Coordinates &aFrom) const;
Coordinates FindNextWord(const Coordinates &aFrom) const;
int GetCharacterIndex(const Coordinates &aCoordinates) const;
int GetCharacterColumn(int aLine, int aIndex) const;
int GetLineCharacterCount(int aLine) const;
int GetLineMaxColumn(int aLine) const;
bool IsOnWordBoundary(const Coordinates &aAt) const;
void RemoveLine(int aStart, int aEnd);
void RemoveLine(int aIndex);
Line &InsertLine(int aIndex);
void EnterCharacter(ImWchar aChar, bool aShift);
void Backspace();
void DeleteSelection();
std::string GetWordUnderCursor() const;
std::string GetWordAt(const Coordinates &aCoords) const;
ImU32 GetGlyphColor(const Glyph &aGlyph) const;
void HandleKeyboardInputs();
void HandleMouseInputs();
void Render();
float mLineSpacing;
Lines mLines;
EditorState mState;
UndoBuffer mUndoBuffer;
int mUndoIndex;
int mTabSize;
bool mOverwrite;
bool mReadOnly;
bool mWithinRender;
bool mScrollToCursor;
bool mScrollToTop;
bool mTextChanged;
bool mColorizerEnabled;
float mTextStart; // position (in pixels) where a code line starts relative to the left of the
// TextEditor.
int mLeftMargin;
bool mCursorPositionChanged;
int mColorRangeMin, mColorRangeMax;
SelectionMode mSelectionMode;
bool mHandleKeyboardInputs;
bool mHandleMouseInputs;
bool mIgnoreImGuiChild;
bool mShowWhitespaces;
Palette mPaletteBase;
Palette mPalette;
LanguageDefinition mLanguageDefinition;
RegexList mRegexList;
bool mCheckComments;
Breakpoints mBreakpoints;
ErrorMarkers mErrorMarkers;
ImVec2 mCharAdvance;
Coordinates mInteractiveStart, mInteractiveEnd;
std::string mLineBuffer;
uint64_t mStartTime;
float mLastClick;
};