aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorDavid Moc <personal@cdatgoose.org>2026-05-31 03:47:04 +0200
committerDavid Moc <personal@cdatgoose.org>2026-05-31 03:47:04 +0200
commit6aeaa171dc1ca43392f53cbd02097f76e1b1c5a0 (patch)
treeb16f559f5a701123ebe7b15ecebb9325263b4a3c /include
parente930cc6bdc7f62befac063d7d9d016ffb0a64f1a (diff)
Hardened API, tetris, MD-View
Diffstat (limited to 'include')
-rw-r--r--include/app.h8
-rw-r--r--include/buffers.h36
-rw-r--r--include/completion.h19
-rw-r--r--include/ecex.h219
-rw-r--r--include/media.h21
-rw-r--r--include/path.h22
-rw-r--r--include/types.h124
7 files changed, 447 insertions, 2 deletions
diff --git a/include/app.h b/include/app.h
index cb09b04..a420f00 100644
--- a/include/app.h
+++ b/include/app.h
@@ -46,8 +46,8 @@ typedef struct app {
size_t prompt_input_len;
/*
- * File/path prompt completion state for find-file and write-file.
- * prompt_completion_query stores the original typed path/query while
+ * Prompt completion state for path prompts and buffer prompts.
+ * prompt_completion_query stores the original typed query while
* prompt_input is temporarily replaced with the selected candidate.
*/
int prompt_completion_active;
@@ -75,6 +75,10 @@ typedef struct app {
int current_mods;
+ buffer_t *mouse_capture_buffer;
+ int mouse_capture_button;
+ int mouse_capture_active;
+
/*
* GLFW sends key events and text events separately. When a printable
* key is consumed as part of a command sequence, suppress the matching
diff --git a/include/buffers.h b/include/buffers.h
index 503dfb8..148d718 100644
--- a/include/buffers.h
+++ b/include/buffers.h
@@ -75,4 +75,40 @@ int buffer_add_interactive_action(buffer_t *buffer,
ecex_interactive_line_action_t *buffer_interactive_action_at_line(buffer_t *buffer,
size_t line);
+int ecex_buffer_set_renderer(buffer_t *buffer,
+ ecex_buffer_render_fn fn,
+ void *userdata,
+ ecex_buffer_userdata_free_fn free_fn,
+ int flags);
+int ecex_buffer_clear_renderer(buffer_t *buffer);
+int ecex_buffer_has_renderer(buffer_t *buffer);
+void *ecex_buffer_renderer_userdata(buffer_t *buffer);
+int ecex_buffer_set_mouse_handler(buffer_t *buffer,
+ ecex_buffer_mouse_fn fn,
+ void *userdata,
+ ecex_buffer_userdata_free_fn free_fn);
+int ecex_buffer_clear_mouse_handler(buffer_t *buffer);
+int ecex_buffer_has_mouse_handler(buffer_t *buffer);
+void *ecex_buffer_mouse_userdata(buffer_t *buffer);
+int ecex_buffer_set_animation(buffer_t *buffer,
+ ecex_buffer_tick_fn fn,
+ void *userdata,
+ ecex_buffer_userdata_free_fn free_fn,
+ double fps);
+int ecex_buffer_set_animation_ms(buffer_t *buffer,
+ ecex_buffer_tick_ms_fn fn,
+ void *userdata,
+ ecex_buffer_userdata_free_fn free_fn,
+ int fps);
+int ecex_buffer_clear_animation(buffer_t *buffer);
+int ecex_buffer_is_animating(buffer_t *buffer);
+void *ecex_buffer_animation_userdata(buffer_t *buffer);
+int ecex_tick_animations(ecex_t *ed, double now_seconds);
+int ecex_buffer_replace_text(buffer_t *buffer, const char *text);
+void ecex_buffer_set_modified(buffer_t *buffer, int modified);
+int ecex_buffer_text_len(buffer_t *buffer);
+int ecex_buffer_scroll_line(buffer_t *buffer);
+int ecex_buffer_line_count_i(buffer_t *buffer);
+int ecex_buffer_line_copy(buffer_t *buffer, int line, char *out, int out_cap);
+
#endif
diff --git a/include/completion.h b/include/completion.h
new file mode 100644
index 0000000..86c41f0
--- /dev/null
+++ b/include/completion.h
@@ -0,0 +1,19 @@
+#ifndef ECEX_COMPLETION_H
+#define ECEX_COMPLETION_H
+
+#include <stddef.h>
+
+typedef struct ecex_completion_item {
+ char *value;
+ int score;
+ int is_dir;
+ size_t order;
+} ecex_completion_item_t;
+
+int ecex_ascii_strncasecmp(const char *a, const char *b, size_t n);
+int ecex_ascii_contains_ci(const char *haystack, const char *needle);
+int ecex_fuzzy_score(const char *candidate, const char *query);
+int ecex_completion_item_compare(const void *a, const void *b);
+void ecex_completion_items_free(ecex_completion_item_t *items, size_t count);
+
+#endif
diff --git a/include/ecex.h b/include/ecex.h
index cefee9b..efcbe5a 100644
--- a/include/ecex.h
+++ b/include/ecex.h
@@ -4,10 +4,93 @@
#include "types.h"
#include "buffers.h"
#include "eval.h"
+#include "path.h"
+#include "media.h"
+
+
+typedef struct ecex_config_command {
+ const char *name;
+ ecex_command_fn fn;
+} ecex_config_command_t;
+
+typedef struct ecex_config_keybind {
+ const char *key;
+ const char *command;
+} ecex_config_keybind_t;
+
+typedef struct ecex_config_mode_keybind {
+ const char *mode;
+ const char *key;
+ const char *command;
+} ecex_config_mode_keybind_t;
ecex_t *ecex_new(void);
void ecex_free(ecex_t *ed);
+/* Small runtime services exported to JIT configs/plugins. Prefer these over
+ * calling libc directly from config code; the tiny JIT resolver is intentionally
+ * conservative and host-exported wrappers are more reliable. */
+void *ecex_config_alloc(size_t size);
+void *ecex_config_calloc(size_t count, size_t size);
+void ecex_config_free(void *ptr);
+double ecex_time_seconds(void);
+void ecex_log(const char *message);
+void ecex_log_int(const char *message, int value);
+void ecex_log_double(const char *message, double value);
+void ecex_log_ptr(const char *message, const void *ptr);
+void ecex_mem_zero(void *ptr, size_t size);
+int ecex_i32_get(const int *items, size_t index);
+void ecex_i32_set(int *items, size_t index, int value);
+int ecex_prng_next_bounded(unsigned int *state, int bound);
+int ecex_random_bounded(int bound);
+int ecex_tetris_shape_cell(int piece, int rot, int col, int row);
+
+/* Host-owned variable registry for JIT plugins. Plugins can keep persistent
+ * scalar values, dynamic arrays, or static host buffers behind a stable owner
+ * pointer and a name instead of relying on fragile JIT struct/array storage. */
+void *ecex_var_get(ecex_t *ed, void *owner, const char *name);
+void *ecex_var_get_or_alloc(ecex_t *ed, void *owner, const char *name, size_t count, size_t elem_size);
+int ecex_var_bind_static(ecex_t *ed, void *owner, const char *name, void *data, size_t count, size_t elem_size);
+int ecex_var_free(ecex_t *ed, void *owner, const char *name);
+int ecex_var_free_owner(ecex_t *ed, void *owner);
+int ecex_var_i32_get(ecex_t *ed, void *owner, const char *name, size_t index, int fallback);
+int ecex_var_i32_set(ecex_t *ed, void *owner, const char *name, size_t index, int value);
+int ecex_var_i32(ecex_t *ed, void *owner, const char *name, int fallback);
+int ecex_var_i32_set_scalar(ecex_t *ed, void *owner, const char *name, int value);
+
+/* Host-owned object allocator for plugin state. Returned pointers are tracked
+ * by the editor and can be freed through the API. Prefer this for callback
+ * userdata over plugin/local allocations when the object has callback lifetime.
+ */
+void *ecex_object_alloc(ecex_t *ed, size_t size);
+void *ecex_object_calloc(ecex_t *ed, size_t count, size_t size);
+int ecex_object_free(ecex_t *ed, void *object);
+int ecex_object_valid(ecex_t *ed, void *object);
+int ecex_object_i32_get(ecex_t *ed, void *object, size_t byte_offset, int fallback);
+int ecex_object_i32_set(ecex_t *ed, void *object, size_t byte_offset, int value);
+void *ecex_object_ptr_get(ecex_t *ed, void *object, size_t byte_offset);
+int ecex_object_ptr_set(ecex_t *ed, void *object, size_t byte_offset, void *value);
+
+/* Host-owned text registry for plugins that need to render arbitrary text.
+ * Plugins copy text into host storage, then draw by owner/id. This avoids
+ * passing JIT-owned literals or stack strings into the normal text renderer. */
+int ecex_text_set(ecex_t *ed, void *owner, int id, const char *text, int len);
+int ecex_text_set_buffer_title(ecex_t *ed, void *owner, int id, buffer_t *buffer);
+int ecex_text_free(ecex_t *ed, void *owner, int id);
+int ecex_text_free_owner(ecex_t *ed, void *owner);
+
+int ecex_buffer_text_len(buffer_t *buffer);
+int ecex_buffer_scroll_line(buffer_t *buffer);
+int ecex_buffer_line_count_i(buffer_t *buffer);
+int ecex_buffer_line_copy(buffer_t *buffer, int line, char *out, int out_cap);
+int ecex_markdown_draw_line_from_buffer_i(ecex_draw_context_t *ctx, void *owner, buffer_t *buffer, int line, int y, int in_code);
+int ecex_markdown_body_y_i(ecex_draw_context_t *ctx);
+int ecex_draw_context_height_i(ecex_draw_context_t *ctx);
+int ecex_draw_context_line_height_i(ecex_draw_context_t *ctx);
+
+int ecex_register_file_handler(ecex_t *ed, const char *extension, ecex_file_handler_fn fn);
+int ecex_run_file_handlers(ecex_t *ed, buffer_t *buffer);
+
int ecex_reserve_buffers(ecex_t *ed, size_t needed);
int ecex_add_buffer(ecex_t *ed, buffer_t *buffer);
@@ -20,6 +103,7 @@ buffer_t *ecex_find_buffer(ecex_t *ed, const char *name);
int ecex_switch_buffer(ecex_t *ed, const char *name);
buffer_t *ecex_current_buffer(ecex_t *ed);
+buffer_t *ecex_other_buffer(ecex_t *ed);
ecex_window_t *ecex_current_window(ecex_t *ed);
size_t ecex_window_count(ecex_t *ed);
int ecex_sync_current_buffer(ecex_t *ed);
@@ -35,6 +119,9 @@ int ecex_balance_windows(ecex_t *ed);
int ecex_next_buffer(ecex_t *ed);
int ecex_previous_buffer(ecex_t *ed);
int ecex_kill_buffer(ecex_t *ed, const char *name);
+int ecex_kill_buffer_force(ecex_t *ed, const char *name);
+int ecex_has_modified_buffers(ecex_t *ed);
+int ecex_validate_bindings(ecex_t *ed);
int ecex_keep_jit_module(ecex_t *ed, void *module);
@@ -42,6 +129,12 @@ int ecex_set_config_path(ecex_t *ed, const char *path);
const char *ecex_config_path(ecex_t *ed);
int ecex_reload_config(ecex_t *ed);
+int ecex_config_register_commands(ecex_t *ed, const ecex_config_command_t *commands, size_t count);
+int ecex_config_bind_keys(ecex_t *ed, const ecex_config_keybind_t *bindings, size_t count);
+int ecex_config_bind_mode_keys(ecex_t *ed, const ecex_config_mode_keybind_t *bindings, size_t count);
+int ecex_config_define_modes(ecex_t *ed, const char *const *modes, size_t count);
+int ecex_apply_theme(ecex_t *ed, const ecex_theme_t *theme);
+
int ecex_register_command(ecex_t *ed, const char *name, ecex_command_fn fn);
int ecex_execute_command(ecex_t *ed, const char *name);
void ecex_set_clipboard_callbacks(ecex_t *ed,
@@ -77,6 +170,100 @@ int ecex_interactive_append_line(ecex_t *ed,
void *userdata);
int ecex_interactive_activate_current_line(ecex_t *ed);
+/*
+ * Attach an immediate-mode renderer to a buffer. The callback runs while the
+ * buffer's window is being drawn and may call ecex_draw_* functions with
+ * coordinates local to that window. Pass ECEX_RENDER_REPLACE_CONTENT to draw a
+ * fully custom buffer; pass ECEX_RENDER_OVERLAY to draw on top of normal text.
+ */
+int ecex_buffer_set_renderer(buffer_t *buffer,
+ ecex_buffer_render_fn fn,
+ void *userdata,
+ ecex_buffer_userdata_free_fn free_fn,
+ int flags);
+int ecex_buffer_clear_renderer(buffer_t *buffer);
+int ecex_buffer_has_renderer(buffer_t *buffer);
+void *ecex_buffer_renderer_userdata(buffer_t *buffer);
+
+/*
+ * Optional mouse/pointer input for rendered buffers. Coordinates are integer
+ * pixels local to the buffer window. Return nonzero from the callback when the
+ * event changes state and should trigger a redraw. Prefer this host-dispatched
+ * path over reading windowing-system globals from a plugin.
+ */
+int ecex_buffer_set_mouse_handler(buffer_t *buffer,
+ ecex_buffer_mouse_fn fn,
+ void *userdata,
+ ecex_buffer_userdata_free_fn free_fn);
+int ecex_buffer_clear_mouse_handler(buffer_t *buffer);
+int ecex_buffer_has_mouse_handler(buffer_t *buffer);
+void *ecex_buffer_mouse_userdata(buffer_t *buffer);
+
+/*
+ * Host-driven animation for rendered buffers. The editor calls tick_fn at up to
+ * fps while the main loop is alive; returning nonzero marks the frame dirty and
+ * triggers a redraw. Use this instead of timers, sleep, clock calls, or threads
+ * in CCDJIT plugins. fps <= 0 defaults to 60; values above 240 are clamped.
+ */
+int ecex_buffer_set_animation(buffer_t *buffer,
+ ecex_buffer_tick_fn fn,
+ void *userdata,
+ ecex_buffer_userdata_free_fn free_fn,
+ double fps);
+int ecex_buffer_set_animation_ms(buffer_t *buffer,
+ ecex_buffer_tick_ms_fn fn,
+ void *userdata,
+ ecex_buffer_userdata_free_fn free_fn,
+ int fps);
+int ecex_buffer_clear_animation(buffer_t *buffer);
+int ecex_buffer_is_animating(buffer_t *buffer);
+void *ecex_buffer_animation_userdata(buffer_t *buffer);
+int ecex_tick_animations(ecex_t *ed, double now_seconds);
+
+int ecex_buffer_replace_text(buffer_t *buffer, const char *text);
+void ecex_buffer_set_modified(buffer_t *buffer, int modified);
+
+/* Drawing helpers. x/y are local to the buffer window; ecex_draw_text uses
+ * top-left coordinates. ecex_draw_rgba expects tightly packed RGBA8 pixels. */
+void ecex_draw_set_color(ecex_draw_context_t *ctx, float r, float g, float b, float a);
+void ecex_draw_rect(ecex_draw_context_t *ctx, float x, float y, float w, float h);
+void ecex_draw_rect_outline(ecex_draw_context_t *ctx, float x, float y, float w, float h, float thickness);
+void ecex_draw_line(ecex_draw_context_t *ctx, float x1, float y1, float x2, float y2, float thickness);
+void ecex_draw_text(ecex_draw_context_t *ctx, float x, float y, const char *text);
+void ecex_draw_text_aligned(ecex_draw_context_t *ctx, float x, float y, float w, const char *text, int align);
+float ecex_draw_text_width(ecex_draw_context_t *ctx, const char *text);
+void ecex_draw_rgba(ecex_draw_context_t *ctx,
+ float x,
+ float y,
+ float w,
+ float h,
+ const unsigned char *rgba,
+ int image_w,
+ int image_h);
+
+/* CCDJIT-safe integer drawing wrappers. Prefer these from plugins when the
+ * JIT ABI is known to be fragile with float/double arguments. Colors are
+ * 0..255 RGBA and coordinates are integer pixels local to the buffer window. */
+void ecex_draw_color_rgba8(ecex_draw_context_t *ctx, int r, int g, int b, int a);
+void ecex_draw_rect_i(ecex_draw_context_t *ctx, int x, int y, int w, int h);
+void ecex_draw_rect_outline_i(ecex_draw_context_t *ctx, int x, int y, int w, int h, int thickness);
+void ecex_draw_line_i(ecex_draw_context_t *ctx, int x1, int y1, int x2, int y2, int thickness);
+void ecex_draw_text_i(ecex_draw_context_t *ctx, int x, int y, const char *text);
+void ecex_draw_text_id_i(ecex_draw_context_t *ctx, void *owner, int id, int x, int y);
+
+void ecex_draw_markdown_canvas_i(ecex_draw_context_t *ctx, void *owner, int title_id, int x, int y, int w, int line_h);
+void ecex_draw_markdown_text_i(ecex_draw_context_t *ctx, void *owner, int text_id, int x, int y, int w, int line_h, int style);
+/* Lower-arity Markdown helpers preferred by CCDJIT plugins. Some JIT call
+ * paths are fragile with 7+ arguments, so these derive layout from ctx. */
+void ecex_draw_markdown_canvas_auto_i(ecex_draw_context_t *ctx, void *owner, int title_id);
+void ecex_draw_markdown_line_auto_i(ecex_draw_context_t *ctx, void *owner, int text_id, int y, int style);
+
+/* CCDJIT-safe host-owned text helpers. Plugins pass integer ids instead of
+ * pointers to JIT-owned string literals/stack buffers. */
+void ecex_draw_label_i(ecex_draw_context_t *ctx, int x, int y, int label_id);
+void ecex_draw_stat_i(ecex_draw_context_t *ctx, int x, int y, int label_id, int value);
+void ecex_draw_tetris_preview_i(ecex_draw_context_t *ctx, int piece, int x, int y, int cell, int alpha);
+
int ecex_find_file(ecex_t *ed, const char *path);
int ecex_save_current_buffer(ecex_t *ed);
int ecex_write_current_buffer(ecex_t *ed, const char *path);
@@ -121,4 +308,36 @@ void ecex_set_search_bg_color(ecex_t *ed, float r, float g, float b);
void ecex_set_line_numbers_enabled(ecex_t *ed, int enabled);
void ecex_set_current_line_enabled(ecex_t *ed, int enabled);
+
+/*
+ * Small config/plugin convenience layer.
+ *
+ * Config files are still plain C and must export ecex_config_init(ecex_t *ed),
+ * but these macros make them safer to write: every registration/bind operation
+ * is checked and failures abort config loading instead of being ignored.
+ */
+#define ECEX_ARRAY_COUNT(a) (sizeof(a) / sizeof((a)[0]))
+#define ECEX_RGB8(r, g, b) ((float)(r) / 255.0f), ((float)(g) / 255.0f), ((float)(b) / 255.0f)
+#define ECEX_CONFIG_BEGIN int ecex_config_init(ecex_t *ed) {
+#define ECEX_CONFIG_END return 0; }
+#define ECEX_PLUGIN_BEGIN(name) int name(ecex_t *ed) {
+#define ECEX_PLUGIN_END return 0; }
+#define ECEX_CONFIG_TRY(expr) \
+ do { \
+ if ((expr) != 0) return -1; \
+ } while (0)
+#define ECEX_CONFIG_COMMAND(name, fn) ECEX_CONFIG_TRY(ecex_register_command(ed, (name), (fn)))
+#define ECEX_CONFIG_BIND(key, command) ECEX_CONFIG_TRY(ecex_bind_key(ed, (key), (command)))
+#define ECEX_CONFIG_MODE(name) \
+ do { \
+ if (ecex_define_major_mode(ed, (name)) == 0) return -1; \
+ } while (0)
+#define ECEX_CONFIG_MODE_BIND(mode, key, command) ECEX_CONFIG_TRY(ecex_bind_mode_key(ed, (mode), (key), (command)))
+#define ECEX_CONFIG_COMMANDS(commands) ECEX_CONFIG_TRY(ecex_config_register_commands(ed, (commands), ECEX_ARRAY_COUNT(commands)))
+#define ECEX_CONFIG_BINDS(bindings) ECEX_CONFIG_TRY(ecex_config_bind_keys(ed, (bindings), ECEX_ARRAY_COUNT(bindings)))
+#define ECEX_CONFIG_MODE_BINDS(bindings) ECEX_CONFIG_TRY(ecex_config_bind_mode_keys(ed, (bindings), ECEX_ARRAY_COUNT(bindings)))
+#define ECEX_CONFIG_MODES(modes) ECEX_CONFIG_TRY(ecex_config_define_modes(ed, (modes), ECEX_ARRAY_COUNT(modes)))
+#define ECEX_CONFIG_THEME(theme_ptr) ECEX_CONFIG_TRY(ecex_apply_theme(ed, (theme_ptr)))
+#define ECEX_CONFIG_INCLUDE(plugin_init_fn) ECEX_CONFIG_TRY((plugin_init_fn)(ed))
+
#endif
diff --git a/include/media.h b/include/media.h
new file mode 100644
index 0000000..1b8f88d
--- /dev/null
+++ b/include/media.h
@@ -0,0 +1,21 @@
+#ifndef ECEX_MEDIA_H
+#define ECEX_MEDIA_H
+
+#include "types.h"
+
+#define ECEX_MEDIA_MAX_DIMENSION 1600
+
+typedef enum ecex_media_kind {
+ ECEX_MEDIA_NONE = 0,
+ ECEX_MEDIA_IMAGE = 1,
+ ECEX_MEDIA_VIDEO = 2,
+} ecex_media_kind_t;
+
+int ecex_media_open(ecex_t *ed, const char *path);
+int ecex_media_load_into_buffer(ecex_t *ed, const char *path, buffer_t *buffer);
+int ecex_media_toggle_playback(ecex_t *ed);
+int ecex_media_tick(ecex_t *ed, double now_seconds);
+void ecex_media_buffer_clear(buffer_t *buffer);
+int ecex_media_buffer_has_pixels(buffer_t *buffer);
+
+#endif
diff --git a/include/path.h b/include/path.h
new file mode 100644
index 0000000..e76a654
--- /dev/null
+++ b/include/path.h
@@ -0,0 +1,22 @@
+#ifndef ECEX_PATH_H
+#define ECEX_PATH_H
+
+#include <stddef.h>
+
+int ecex_path_copy(char *out, size_t out_size, const char *text);
+char *ecex_path_expand_user(const char *path);
+char *ecex_path_join(const char *dir, const char *name);
+char *ecex_path_dirname(const char *path);
+char *ecex_path_basename_dup(const char *path);
+char *ecex_path_normalize(const char *path);
+int ecex_path_is_dir(const char *path);
+int ecex_path_is_file(const char *path);
+int ecex_path_exists(const char *path);
+long long ecex_path_file_size(const char *path);
+int ecex_path_is_image(const char *path);
+int ecex_path_is_previewable_image(const char *path);
+int ecex_path_is_video(const char *path);
+int ecex_path_is_media(const char *path);
+int ecex_path_cwd(char *out, size_t out_size);
+
+#endif
diff --git a/include/types.h b/include/types.h
index 1dc2158..800c3d6 100644
--- a/include/types.h
+++ b/include/types.h
@@ -6,11 +6,18 @@
typedef struct ecex ecex_t;
typedef struct buffer buffer_t;
typedef struct ecex_window ecex_window_t;
+typedef struct ecex_draw_context ecex_draw_context_t;
typedef int (*ecex_command_fn)(ecex_t *ed);
typedef int (*ecex_interactive_line_fn)(ecex_t *ed, buffer_t *buffer, size_t line, const char *payload, void *userdata);
typedef const char *(*ecex_clipboard_get_fn)(void *userdata);
typedef void (*ecex_clipboard_set_fn)(void *userdata, const char *text);
+typedef int (*ecex_buffer_render_fn)(ecex_t *ed, buffer_t *buffer, ecex_draw_context_t *ctx, void *userdata);
+typedef int (*ecex_buffer_tick_fn)(ecex_t *ed, buffer_t *buffer, double now_seconds, void *userdata);
+typedef int (*ecex_buffer_tick_ms_fn)(ecex_t *ed, buffer_t *buffer, int now_ms, void *userdata);
+typedef int (*ecex_buffer_mouse_fn)(ecex_t *ed, buffer_t *buffer, int event, int x, int y, int button, void *userdata);
+typedef int (*ecex_file_handler_fn)(ecex_t *ed, buffer_t *buffer);
+typedef void (*ecex_buffer_userdata_free_fn)(void *userdata);
typedef enum ecex_prompt_request {
ECEX_PROMPT_NONE = 0,
@@ -19,12 +26,48 @@ typedef enum ecex_prompt_request {
ECEX_PROMPT_EVAL_FILE,
ECEX_PROMPT_SWITCH_BUFFER,
ECEX_PROMPT_KILL_BUFFER,
+ ECEX_PROMPT_FORCE_KILL_BUFFER,
ECEX_PROMPT_COMPILE,
ECEX_PROMPT_GREP,
ECEX_PROMPT_ISEARCH_FORWARD,
ECEX_PROMPT_ISEARCH_BACKWARD,
} ecex_prompt_request_t;
+
+#define ECEX_RENDER_OVERLAY 0
+#define ECEX_RENDER_REPLACE_CONTENT 1
+
+#define ECEX_MOUSE_MOVE 0
+#define ECEX_MOUSE_PRESS 1
+#define ECEX_MOUSE_RELEASE 2
+#define ECEX_MOUSE_DRAG 3
+#define ECEX_MOUSE_BUTTON_LEFT 0
+#define ECEX_MOUSE_BUTTON_RIGHT 1
+#define ECEX_MOUSE_BUTTON_MIDDLE 2
+
+typedef enum ecex_draw_text_align {
+ ECEX_TEXT_ALIGN_LEFT = 0,
+ ECEX_TEXT_ALIGN_CENTER = 1,
+ ECEX_TEXT_ALIGN_RIGHT = 2,
+} ecex_draw_text_align_t;
+
+struct ecex_draw_context {
+ float x;
+ float y;
+ float w;
+ float h;
+ float content_x;
+ float content_y;
+ float content_w;
+ float content_h;
+ float font_size;
+ float line_height;
+ float char_width;
+ size_t window_index;
+ int active;
+ void *internal;
+};
+
typedef struct ecex_undo_entry {
char *data;
size_t len;
@@ -98,6 +141,38 @@ struct buffer {
struct ecex_interactive_line_action *interactive_actions;
size_t interactive_action_cap;
size_t interactive_action_count;
+
+ int media_kind;
+ char *media_path;
+ int media_width;
+ int media_height;
+ unsigned char *media_pixels;
+ int media_dirty;
+ unsigned int media_texture;
+ int media_texture_width;
+ int media_texture_height;
+ void *media_pipe;
+ double media_last_frame_time;
+ int media_playing;
+ char media_status[256];
+
+ ecex_buffer_render_fn render_fn;
+ void *render_userdata;
+ ecex_buffer_userdata_free_fn render_userdata_free;
+ int render_flags;
+
+ ecex_buffer_mouse_fn mouse_fn;
+ void *mouse_userdata;
+ ecex_buffer_userdata_free_fn mouse_userdata_free;
+
+ ecex_buffer_tick_fn tick_fn;
+ ecex_buffer_tick_ms_fn tick_ms_fn;
+ void *tick_userdata;
+ ecex_buffer_userdata_free_fn tick_userdata_free;
+ double tick_interval;
+ double tick_last_time;
+ int tick_enabled;
+ int tick_uses_ms;
};
typedef struct ecex_interactive_line_action {
@@ -128,6 +203,38 @@ typedef struct ecex_major_mode {
char *name;
} ecex_major_mode_t;
+typedef enum ecex_var_kind {
+ ECEX_VAR_BYTES = 0,
+ ECEX_VAR_I32 = 1,
+} ecex_var_kind_t;
+
+typedef struct ecex_var_entry {
+ void *owner;
+ char *name;
+ void *data;
+ size_t elem_size;
+ size_t count;
+ int kind;
+ int dynamic;
+} ecex_var_entry_t;
+
+typedef struct ecex_text_entry {
+ void *owner;
+ int id;
+ char *text;
+ size_t len;
+} ecex_text_entry_t;
+
+typedef struct ecex_file_handler {
+ char *extension;
+ ecex_file_handler_fn fn;
+} ecex_file_handler_t;
+
+typedef struct ecex_object_entry {
+ void *ptr;
+ size_t size;
+} ecex_object_entry_t;
+
struct ecex_window {
buffer_t *buffer;
float x;
@@ -143,6 +250,7 @@ struct ecex {
size_t current_buffer_index;
buffer_t *current_buffer;
+ buffer_t *previous_buffer;
ecex_window_t *windows;
size_t window_cap;
@@ -170,6 +278,22 @@ struct ecex {
size_t major_mode_count;
int next_major_mode_id;
+ ecex_var_entry_t *vars;
+ size_t var_cap;
+ size_t var_count;
+
+ ecex_text_entry_t *texts;
+ size_t text_cap;
+ size_t text_count;
+
+ ecex_file_handler_t *file_handlers;
+ size_t file_handler_cap;
+ size_t file_handler_count;
+
+ ecex_object_entry_t *objects;
+ size_t object_cap;
+ size_t object_count;
+
char *last_eval_source;
char *last_eval_filename;
int last_eval_wrap_as_statements;