Files
text_editor/src/text_editor/text_editor.h

376 lines
9.1 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;};
union XY {
struct {Int col; Int line;};
struct {Int x; Int y; };
};
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;
};
typedef void CMDFunction();
struct Command {
String name;
String docs;
CMDFunction *function;
String binding; // DONT USE, only for ParseKeyCached
struct Trigger *trigger;
};
enum UIAction {
UIAction_Null,
UIAction_Cancel,
UIAction_Yes,
UIAction_No,
};
struct ExecArgs {
String exe;
String cmd;
String cwd;
Array<String> env;
ViewID output_view; // poll_process
struct {
U32 poll_process : 1;
U32 open_stdin : 1;
U32 scroll_to_end : 1;
};
};
struct Process {
bool is_valid;
int exit_code;
char platform[6 * 8];
Int id;
ExecArgs args; // memory for exe and all that is invalid
};
enum OpenKind {
OpenKind_Invalid,
OpenKind_Skip,
OpenKind_Exec,
OpenKind_Goto,
OpenKind_Command,
#if PLUGIN_CONFIG
OpenKind_Set,
#endif
};
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;
struct {
U32 existing_buffer : 1;
U32 exec_in_background : 1;
U32 use_python_shell : 1;
};
};
struct Buffer {
BufferID id;
String name;
Int 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;
Array<Command> commands;
struct {
uint32_t no_history : 1;
uint32_t no_line_starts : 1;
uint32_t dirty : 1;
uint32_t changed_on_disk : 1;
uint32_t temp : 1;
uint32_t dont_try_to_save_in_bulk_ops : 1;
uint32_t close : 1;
uint32_t special : 1;
#if PLUGIN_DIRECTORY_NAVIGATION
uint32_t is_dir : 1;
#endif
};
};
struct View {
ViewID id;
BufferID active_buffer;
Vec2I scroll;
Array<Caret> carets;
// window | view
Caret main_caret_on_begin_frame;
bool update_scroll;
UIAction ui_action;
Array<Command> commands;
Function *update_hook;
uint64_t prev_search_line_hash;
struct {
uint32_t close : 1;
uint32_t 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; // maybe move to view @todo
GotoCrumb begin_frame_crumb;
Array<GotoCrumb> goto_history;
Array<GotoCrumb> goto_redo;
ViewID active_goto_list;
Int goto_list_pos;
String ui_query_file;
void (*after_resolve_open_hook)(Window *window, ResolvedOpen *resolved);
Array<Command> commands;
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)
void AddCommand(Array<Command> *arr, String name, struct Trigger *trigger, CMDFunction *function);
struct Register_Command {
Register_Command(Array<Command> *funcs, CMDFunction *function, String name, String binding, String docs = "") {
int64_t pos = 0;
if (Seek(name, "_", &pos, 0)) {
name = Skip(name, pos + 1);
}
Command cmd = {};
cmd.name = name;
cmd.binding = binding;
cmd.function = function;
cmd.docs = docs;
Reserve(funcs, 512);
Add(funcs, cmd);
}
};
#define RegisterCommand(name, binding, docs) Register_Command RC__##name(&GlobalCommands, name, #name, binding, docs)
#define RegisterCoroutineCommand(name, binding, docs, ...) void CMD_##name() {\
RemoveCoroutine(#name);\
CCtx *data = AddCoroutine(name);\
__VA_ARGS__\
ResumeCoroutine(data);\
}\
Register_Command RC__##name(&GlobalCommands, CMD_##name, #name, binding, docs)
#define RegisterFunction(functions, name) Register_Function RF__##name(functions, #name, name)
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});
}
};
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 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 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, Window *window, 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 = "");
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; }