Files
text_editor/src/text_editor/text_editor.h
Krzosa Karol de06ea05cc Hooks sketch
2026-01-08 10:15:02 +01:00

377 lines
9.2 KiB
C++

struct Buffer;
struct View;
struct Window;
struct BufferID { Int id; Buffer *o; };
struct ViewID { Int id; View *o; };
struct WindowID { Int id; Window *o; };
union Range { struct { Int min; Int max; }; Int e[2]; };
struct Caret { union { Range range; Int pos[2]; }; Int ifront;};
struct XY { Int col; Int line; };
typedef void Function();
struct FunctionData {
String name;
Function *function;
};
struct Edit {
Range range;
String16 string;
};
struct HistoryEntry {
Array<Edit> edits;
Array<Caret> carets;
double time;
};
struct Buffer {
BufferID id;
String name;
Int begin_frame_change_id;
Int change_id;
Int user_change_id;
Int file_mod_time;
union {
U16 *data;
char16_t*str;
};
Int len;
Int cap;
Array<Int> line_starts;
Array<HistoryEntry> undo_stack;
Array<HistoryEntry> redo_stack;
int edit_phase;
struct {
unsigned no_history : 1;
unsigned no_line_starts : 1;
unsigned dirty : 1;
unsigned changed_on_disk : 1;
unsigned temp : 1;
unsigned dont_try_to_save_in_bulk_ops : 1;
unsigned close : 1;
unsigned special : 1;
unsigned is_dir : 1;
};
};
enum HookKind {
HookKind_Invalid,
HookKind_AppInit,
HookKind_AppUpdate,
HookKind_AppExit,
HookKind_Binding,
HookKind_BeforeLayoutWindow,
HookKind_HandleLayoutWindow,
HookKind_AfterLayoutWindow,
HookKind_BeforeRenderWindow,
HookKind_HandleRenderWindow,
HookKind_AfterRenderWindow,
HookKind_BeforeBufferSave,
HookKind_HandleBufferSave,
HookKind_AfterBufferSave,
HookKind_BeforeBufferOpen,
HookKind_HandleBufferOpen,
HookKind_AfterBufferOpen,
HookKind_ViewUpdate,
};
// Global hooks, per (window, view, buffer) hooks
struct HookParam {
struct Hook *hook;
Buffer *buffer;
View *view;
Window *window;
};
typedef void HookFunction(HookParam *param);
struct Hook {
HookKind kind;
String name;
String doc;
HookFunction *function;
// HookKind_Binding
String binding;
struct Trigger *trigger;
};
struct CommandData {
String name;
String binding;
Function *function;
String doc;
struct Trigger *trigger;
};
enum ViewKind {
ViewKind_Normal,
ViewKind_FuzzySearch,
ViewKind_ActiveSearch,
};
struct View {
ViewID id;
BufferID active_buffer;
ViewKind kind;
Vec2I scroll;
Array<Caret> carets;
// window | view
Caret main_caret_on_begin_frame;
bool update_scroll;
String hook_cmd;
Array<CommandData> hooks;
uint64_t prev_search_line_hash;
struct {
unsigned close : 1;
unsigned special : 1;
};
};
struct GotoCrumb {
ViewID view_id;
Caret caret;
double time;
};
struct Window {
WindowID id;
ViewID active_view;
Rect2I total_rect;
Rect2I document_rect;
Rect2I scrollbar_rect;
Rect2I line_numbers_rect;
Rect2I resizer_rect;
Font *font;
double mouse_scroller_offset;
int z;
double weight;
Caret search_bar_anchor;
GotoCrumb begin_frame_crumb;
Array<GotoCrumb> goto_history;
Array<GotoCrumb> goto_redo;
ViewID active_goto_list;
Int goto_list_pos;
struct {
uint32_t draw_scrollbar : 1;
uint32_t draw_line_numbers : 1;
uint32_t secondary_window_style : 1;
uint32_t draw_line_highlight : 1;
uint32_t visible : 1;
uint32_t primary : 1;
uint32_t close : 1;
uint32_t sync_visibility_with_focus : 1;
uint32_t lose_focus_on_escape : 1;
uint32_t lose_visibility_on_escape : 1;
uint32_t jump_history : 1;
uint32_t skip_checkpoint : 1;
};
};
struct Scroller {
Rect2 rect;
double begin;
double end;
Int line_count;
};
struct BSet {
struct Window *window;
View *view;
Buffer *buffer;
};
#define EVENT_KINDS \
X(EVENT_NONE) \
X(EVENT_UPDATE) \
X(EVENT_QUIT) \
X(EVENT_MOUSE_LEFT) \
X(EVENT_MOUSE_RIGHT) \
X(EVENT_MOUSE_MIDDLE) \
X(EVENT_MOUSE_X1) \
X(EVENT_MOUSE_X2) \
X(EVENT_MOUSE_LEFT_UP) \
X(EVENT_MOUSE_RIGHT_UP) \
X(EVENT_MOUSE_MIDDLE_UP) \
X(EVENT_MOUSE_X1_UP) \
X(EVENT_MOUSE_X2_UP) \
X(EVENT_MOUSE_WHEEL) \
X(EVENT_KEY_PRESS) \
X(EVENT_TEXT_INPUT) \
X(EVENT_DROP_FILE)
enum EventKind {
#define X(TYPE) TYPE,
EVENT_KINDS
#undef X
EVENT_KIND_COUNT,
EVENT_KIND_INVALID = 111,
};
const char *EventKindStrings[] = {
#define X(TYPE) #TYPE,
EVENT_KINDS
#undef X
};
#define EVENT_FIELDS \
X(EventKind, Int, kind) \
X(SDL_Keycode, Int, key) \
X(int16_t, Int, xwindow) \
X(int16_t, Int, ywindow) \
X(int16_t, Int, xmouse) \
X(int16_t, Int, ymouse) \
X(uint8_t, Int, clicks) \
X(uint8_t, Int, shift) \
X(uint8_t, Int, ctrl) \
X(uint8_t, Int, alt) \
X(uint8_t, Int, super) \
X(float, Float, xwheel) \
X(float, Float, ywheel) \
X(char *, String, text)
#define EVENT_FIELD_COUNT 14
struct Event {
#define X(TYPE, KIND, NAME) TYPE NAME;
EVENT_FIELDS
#undef X
};
struct FuzzyPair {
int32_t index;
float rating;
};
enum VariableType {
VariableType_Invalid,
VariableType_Color,
VariableType_String,
VariableType_Int,
VariableType_Float,
};
struct Variable {
VariableType type;
String name;
union {
void *addr;
Color *color;
Int *i;
double *f;
String *string;
};
};
struct Register_Variable {
Register_Variable(Array<Variable> *variables, VariableType type, String name, void *addr) {
Add(variables, {type, name, {addr}});
}
};
#define RegisterVariable(type, name, ...) \
type name = __VA_ARGS__; \
Register_Variable var_##name(&Variables, VariableType_##type, #name, &name)
enum OpenKind {
OpenKind_Invalid,
OpenKind_Skip,
OpenKind_Exec,
OpenKind_BackgroundExec,
OpenKind_Goto,
OpenKind_Command,
OpenKind_Set,
};
typedef uint32_t ResolveOpenMeta;
enum {
ResolveOpenMeta_Normal = 0,
ResolveOpenMeta_DontError = 2,
ResolveOpenMeta_DontExec = 4, // dont error +
};
struct ResolvedOpen {
OpenKind kind;
String path;
Int line, col;
bool existing_buffer;
};
struct Register_Command { Register_Command(Array<CommandData> *fucs, Function *function, String name, String binding, String doc = "") { if (StartsWith(name, "CMD_")) name = Skip(name, sizeof("CMD_") - 1); Add(fucs, {name, binding, function, doc}); } };
#define RegisterCommand(name, ...) Register_Command RC__##name(&CommandFunctions, name, #name, __VA_ARGS__)
struct Register_Function {
Register_Function(Array<FunctionData> *functions, String name, Function *f) {
int64_t pos = 0;
if (Seek(name, "_", &pos, 0)) {
name = Skip(name, pos + 1);
}
Add(functions, {name, f});
}
};
#define RegisterFunction(functions, name) Register_Function RF__##name(functions, #name, name)
void AddHook(Array<CommandData> *arr, String name, String binding, Function *function);
constexpr int DIR_RIGHT = 0;
constexpr int DIR_LEFT = 1;
constexpr int DIR_DOWN = 2;
constexpr int DIR_UP = 3;
constexpr int DIR_COUNT = 4;
constexpr bool CTRL_PRESSED = true;
constexpr bool SHIFT_PRESS = true;
constexpr bool KILL_SELECTION = true;
constexpr Int LAST_LINE = INT64_MAX;
BSet GetBSet(struct Window *window);
BSet GetBSet(WindowID window_id);
void Append(View *view, String16 string, bool scroll_to_end_if_cursor_on_last_line);
void Append(View *view, String string, bool scroll_to_end_if_cursor_on_last_line);
void ReplaceWithoutMovingCarets(Buffer *buffer, Range range, String16 string);
void ReportDebugf(const char *fmt, ...);
void ReportConsolef(const char *fmt, ...);
void ReportErrorf(const char *fmt, ...);
void ReportWarningf(const char *fmt, ...);
void Appendf(View *view, const char *fmt, ...);
View *CreateView(BufferID active_buffer);
void EvalCommand(String command);
void EvalCommand(String16 command);
Rect2I GetVisibleCells(Window *window);
ResolvedOpen ResolveOpen(Allocator scratch, String path, ResolveOpenMeta meta);
BSet Open(String path, ResolveOpenMeta meta = ResolveOpenMeta_Normal);
BSet Open(String16 path, ResolveOpenMeta meta = ResolveOpenMeta_Normal);
void CenterView(WindowID window);
void TrimWhitespace(Buffer *buffer, bool trim_lines_with_caret = false);
void JumpTempBuffer(BSet *set, String buffer_name = "");
void CommandWindowLayout(Rect2I *rect, Int wx, Int wy);
void CommandWindowInit();
void SearchWindowLayout(Rect2I *rect, Int wx, Int wy);
void SearchWindowInit();
void StatusWindowInit();
void StatusWindowLayout(Rect2I *rect, Int wx, Int wy);
void DebugWindowInit();
void DebugWindowLayout(Rect2I *rect, Int wx, Int wy);
void BuildWindowInit();
void BuildWindowLayout(Rect2I *rect, Int wx, Int wy);
View *FindView(BufferID buffer_id, View *default_view = NULL);
bool operator==(BufferID a, BufferID b) { return a.id == b.id; }
bool operator==(ViewID a, ViewID b) { return a.id == b.id; }
bool operator!=(BufferID a, BufferID b) { return a.id != b.id; }
bool operator!=(ViewID a, ViewID b) { return a.id != b.id; }
bool operator==(WindowID a, WindowID b) { return a.id == b.id; }
bool operator!=(WindowID a, WindowID b) { return a.id != b.id; }