buffer16 api work
This commit is contained in:
@@ -62,6 +62,7 @@
|
|||||||
#include "core_type_info.c"
|
#include "core_type_info.c"
|
||||||
#include "core_hash.c"
|
#include "core_hash.c"
|
||||||
#include "core_hash_table.c"
|
#include "core_hash_table.c"
|
||||||
|
#include "core_array.c"
|
||||||
#ifndef DONT_INCLUDE_GENERATED_MATH
|
#ifndef DONT_INCLUDE_GENERATED_MATH
|
||||||
#include "core_math.gen.c"
|
#include "core_math.gen.c"
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -15,3 +15,4 @@
|
|||||||
#include "core_platform.h"
|
#include "core_platform.h"
|
||||||
#include "core_hash_table.h"
|
#include "core_hash_table.h"
|
||||||
#include "core_ctx.h"
|
#include "core_ctx.h"
|
||||||
|
#include "core_array.h"
|
||||||
|
|||||||
@@ -1,63 +1,3 @@
|
|||||||
typedef enum {
|
|
||||||
alokind_alloc,
|
|
||||||
alokind_dealloc,
|
|
||||||
} alokind_t;
|
|
||||||
|
|
||||||
typedef struct alo_t alo_t;
|
|
||||||
struct alo_t {
|
|
||||||
void *object;
|
|
||||||
void *(*proc)(alo_t alo, alokind_t kind, void *ptr, size_t size);
|
|
||||||
};
|
|
||||||
|
|
||||||
fn void *arena_alo_proc(alo_t alo, alokind_t kind, void *ptr, size_t size) {
|
|
||||||
ma_arena_t *ma = alo.object;
|
|
||||||
if (kind == alokind_alloc) {
|
|
||||||
return ma_push_size(alo.object, size);
|
|
||||||
} else if (kind == alokind_dealloc) {
|
|
||||||
return NULL;
|
|
||||||
} else_is_invalid;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn alo_t ma_alo(ma_arena_t *arena) {
|
|
||||||
return (alo_t){arena, arena_alo_proc};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn alo_t ma_temp_alo(ma_temp_t temp) {
|
|
||||||
return ma_alo(temp.arena);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn void dealloc(alo_t alo, void *ptr) {
|
|
||||||
alo.proc(alo, alokind_dealloc, ptr, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn void *alloc_size(alo_t alo, size_t size) {
|
|
||||||
return alo.proc(alo, alokind_alloc, NULL, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define alloc_type(alo, type) (type *)alloc_size((aloc), sizeof(type))
|
|
||||||
#define alloc_array(alo, type, count) (type *)alloc_size((alo), sizeof(type) * (count))
|
|
||||||
|
|
||||||
#define array(type) struct { alo_t alo; type *data; i64 len; i64 cap; }
|
|
||||||
typedef array(void) array_void_t;
|
|
||||||
typedef array(i64) array_i64_t;
|
|
||||||
|
|
||||||
#define arrisz(x) sizeof((x)->data[0])
|
|
||||||
#define arrcst(x) ((array_void_t *)(x))
|
|
||||||
#define array_init(a, this, count) (array__init((a), arrcst(this), arrisz(this), (count)))
|
|
||||||
#define array_add(this, ...) (array__grow(arrcst(this), arrisz(this), 1), (this)->data[(this)->len++] = __VA_ARGS__)
|
|
||||||
#define array_pop(this) (assert_expr((this)->len > 0), (this)->data[--(this)->len])
|
|
||||||
#define array_dealloc(this) (dealloc((this)->alo, (this)->data))
|
|
||||||
#define array_addn(this, n) (array__grow(arrcst(this), arrisz(this), (n)), (this)->len += (n), &(this)->data[(this)->len - (n)])
|
|
||||||
#define array_insert(this, i, item) (array__insert(arrcst(this), arrisz(this), (i)), (this)->data[(i)] = (item))
|
|
||||||
#define array_swapdel(this, i) (assert_expr((i) < (this)->len), (this)->data[(i)] = (this)->data[--(this)->len])
|
|
||||||
#define array_del(this, i) (array__del(arrcst(this), arrisz(this), (i), 1))
|
|
||||||
#define array_deln(this, i, count) (array__del(arrcst(this), arrisz(this), (i), (count)))
|
|
||||||
#define array_copy(alo, dst, src) (array__copy((alo), arrcst(dst), (array_void_t *)(src), arrisz(dst)))
|
|
||||||
#define array_last(x) ((x)->data[(x)->len - 1])
|
|
||||||
|
|
||||||
#define array_for(type, it, array) for (type *it = (array)->data; it < (array)->data + (array)->len; it += 1)
|
|
||||||
|
|
||||||
fn void array__init(alo_t alo, array_void_t *this, size_t item_size, i64 count) {
|
fn void array__init(alo_t alo, array_void_t *this, size_t item_size, i64 count) {
|
||||||
assert(this->data == NULL);
|
assert(this->data == NULL);
|
||||||
this->data = alloc_size(alo, item_size * count);
|
this->data = alloc_size(alo, item_size * count);
|
||||||
@@ -112,7 +52,7 @@ fn void array__insert(array_void_t *this, size_t item_size, i64 idx) {
|
|||||||
fn_test void test_array(void) {
|
fn_test void test_array(void) {
|
||||||
ma_temp_t scratch = ma_begin_scratch();
|
ma_temp_t scratch = ma_begin_scratch();
|
||||||
{
|
{
|
||||||
array_i64_t arr = (array_i64_t){.alo = ma_temp_alo(scratch)};
|
array_i64_t arr = (array_i64_t){.alo = malot(scratch)};
|
||||||
for (int i = 0; i < 512; i += 1) {
|
for (int i = 0; i < 512; i += 1) {
|
||||||
array_add(&arr, i);
|
array_add(&arr, i);
|
||||||
}
|
}
|
||||||
@@ -130,7 +70,7 @@ fn_test void test_array(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
array_i64_t arr = (array_i64_t){.alo = ma_temp_alo(scratch)};
|
array_i64_t arr = (array_i64_t){.alo = malot(scratch)};
|
||||||
i64 *i = array_addn(&arr, 10);
|
i64 *i = array_addn(&arr, 10);
|
||||||
assert(arr.len == 10 && arr.cap == 16);
|
assert(arr.len == 10 && arr.cap == 16);
|
||||||
i64 *j = array_addn(&arr, 2);
|
i64 *j = array_addn(&arr, 2);
|
||||||
@@ -140,7 +80,7 @@ fn_test void test_array(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
array_i64_t arr = (array_i64_t){.alo = ma_temp_alo(scratch)};
|
array_i64_t arr = (array_i64_t){.alo = malot(scratch)};
|
||||||
for (int i = 0; i < 512; i += 1) {
|
for (int i = 0; i < 512; i += 1) {
|
||||||
array_add(&arr, i);
|
array_add(&arr, i);
|
||||||
}
|
}
|
||||||
@@ -164,7 +104,7 @@ fn_test void test_array(void) {
|
|||||||
assert(arr.data[3] == 3);
|
assert(arr.data[3] == 3);
|
||||||
|
|
||||||
array_i64_t copy = {0};
|
array_i64_t copy = {0};
|
||||||
array_copy(ma_temp_alo(scratch), ©, &arr);
|
array_copy(malot(scratch), ©, &arr);
|
||||||
for (i64 i = 0; i < arr.len; i += 1) {
|
for (i64 i = 0; i < arr.len; i += 1) {
|
||||||
assert(arr.data[i] == copy.data[i]);
|
assert(arr.data[i] == copy.data[i]);
|
||||||
}
|
}
|
||||||
@@ -174,12 +114,3 @@ fn_test void test_array(void) {
|
|||||||
|
|
||||||
ma_end_scratch(scratch);
|
ma_end_scratch(scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn s16_t s16_alo_copy(alo_t ma, s16_t string) {
|
|
||||||
i64 byte_size = sizeof(u16) * string.len;
|
|
||||||
u16 *copy = (u16 *)alloc_size(ma, byte_size + sizeof(u16));
|
|
||||||
memory_copy(copy, string.str, byte_size);
|
|
||||||
copy[string.len] = 0;
|
|
||||||
s16_t result = s16_make(copy, string.len);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
24
src/core/core_array.h
Normal file
24
src/core/core_array.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#define array(type) struct { alo_t alo; type *data; i64 len; i64 cap; }
|
||||||
|
typedef array(void) array_void_t;
|
||||||
|
typedef array(i64) array_i64_t;
|
||||||
|
|
||||||
|
#define arrisz(x) sizeof((x)->data[0])
|
||||||
|
#define arrcst(x) ((array_void_t *)(x))
|
||||||
|
#define array_init(a, this, count) (array__init((a), arrcst(this), arrisz(this), (count)))
|
||||||
|
#define array_add(this, ...) (array__grow(arrcst(this), arrisz(this), 1), (this)->data[(this)->len++] = __VA_ARGS__)
|
||||||
|
#define array_pop(this) (assert_expr((this)->len > 0), (this)->data[--(this)->len])
|
||||||
|
#define array_dealloc(this) (dealloc((this)->alo, (this)->data))
|
||||||
|
#define array_addn(this, n) (array__grow(arrcst(this), arrisz(this), (n)), (this)->len += (n), &(this)->data[(this)->len - (n)])
|
||||||
|
#define array_insert(this, i, item) (array__insert(arrcst(this), arrisz(this), (i)), (this)->data[(i)] = (item))
|
||||||
|
#define array_swapdel(this, i) (assert_expr((i) < (this)->len), (this)->data[(i)] = (this)->data[--(this)->len])
|
||||||
|
#define array_del(this, i) (array__del(arrcst(this), arrisz(this), (i), 1))
|
||||||
|
#define array_deln(this, i, count) (array__del(arrcst(this), arrisz(this), (i), (count)))
|
||||||
|
#define array_copy(alo, dst, src) (array__copy((alo), arrcst(dst), (array_void_t *)(src), arrisz(dst)))
|
||||||
|
#define array_last(x) ((x)->data[(x)->len - 1])
|
||||||
|
#define array_for(type, it, array) for (type *it = (array)->data; it < (array)->data + (array)->len; it += 1)
|
||||||
|
|
||||||
|
fn void array__init(alo_t alo, array_void_t *this, size_t item_size, i64 count);
|
||||||
|
fn void array__copy(alo_t alo, array_void_t *dst, array_void_t *src, size_t item_size);
|
||||||
|
fn void array__grow(array_void_t *this, size_t item_size, i64 item_count);
|
||||||
|
fn void array__del(array_void_t *this, size_t item_size, i64 idx, i64 count);
|
||||||
|
fn void array__insert(array_void_t *this, size_t item_size, i64 idx);
|
||||||
@@ -12,3 +12,29 @@ fn void core_init(void) {
|
|||||||
tcx = &global_thread_context;
|
tcx = &global_thread_context;
|
||||||
os_core_init();
|
os_core_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn void *ma_arena_alo_proc(alo_t alo, alokind_t kind, void *ptr, size_t size) {
|
||||||
|
ma_arena_t *ma = alo.object;
|
||||||
|
if (kind == alokind_alloc) {
|
||||||
|
return ma_push_size(alo.object, size);
|
||||||
|
} else if (kind == alokind_dealloc) {
|
||||||
|
return NULL;
|
||||||
|
} else_is_invalid;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn alo_t malo(ma_arena_t *arena) {
|
||||||
|
return (alo_t){arena, ma_arena_alo_proc};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn alo_t malot(ma_temp_t temp) {
|
||||||
|
return malo(temp.arena);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn void dealloc(alo_t alo, void *ptr) {
|
||||||
|
alo.proc(alo, alokind_dealloc, ptr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn void *alloc_size(alo_t alo, size_t size) {
|
||||||
|
return alo.proc(alo, alokind_alloc, NULL, size);
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,4 +19,22 @@ enum {
|
|||||||
tcx_slot_app,
|
tcx_slot_app,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
alokind_alloc,
|
||||||
|
alokind_dealloc,
|
||||||
|
} alokind_t;
|
||||||
|
|
||||||
|
typedef struct alo_t alo_t;
|
||||||
|
struct alo_t {
|
||||||
|
void *object;
|
||||||
|
void *(*proc)(alo_t alo, alokind_t kind, void *ptr, size_t size);
|
||||||
|
};
|
||||||
|
|
||||||
|
#define alloc_type(alo, type) (type *)alloc_size((aloc), sizeof(type))
|
||||||
|
#define alloc_array(alo, type, count) (type *)alloc_size((alo), sizeof(type) * (count))
|
||||||
|
fn alo_t malo(ma_arena_t *arena);
|
||||||
|
fn alo_t malot(ma_temp_t temp);
|
||||||
|
fn void dealloc(alo_t alo, void *ptr);
|
||||||
|
fn void *alloc_size(alo_t alo, size_t size);
|
||||||
|
|
||||||
gb_thread thread_ctx_t *tcx;
|
gb_thread thread_ctx_t *tcx;
|
||||||
|
|||||||
@@ -489,6 +489,15 @@ fn sb16_t s16_split(ma_arena_t *ma, s16_t string, s16_t find, s16_split_t flags)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn s16_t s16_copy_ex(alo_t ma, s16_t string) {
|
||||||
|
i64 byte_size = sizeof(u16) * string.len;
|
||||||
|
u16 *copy = (u16 *)alloc_size(ma, byte_size + sizeof(u16));
|
||||||
|
memory_copy(copy, string.str, byte_size);
|
||||||
|
copy[string.len] = 0;
|
||||||
|
s16_t result = s16_make(copy, string.len);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
fn_test void test_string16(void) {
|
fn_test void test_string16(void) {
|
||||||
ma_temp_t scratch = ma_begin_scratch();
|
ma_temp_t scratch = ma_begin_scratch();
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
void test_string16(void);
|
void test_string16(void);
|
||||||
void test_hash_table(void);
|
void test_hash_table(void);
|
||||||
void test_intern_table(void);
|
void test_intern_table(void);
|
||||||
|
void test_array(void);
|
||||||
fn void run_tests(void) {
|
fn void run_tests(void) {
|
||||||
test_string16();
|
test_string16();
|
||||||
test_hash_table();
|
test_hash_table();
|
||||||
test_intern_table();
|
test_intern_table();
|
||||||
|
test_array();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,74 +1,57 @@
|
|||||||
#define BUFFER_DEBUG 1
|
#define BUFFER_DEBUG 1
|
||||||
|
|
||||||
typedef struct caret_t caret_t;
|
|
||||||
struct caret_t {
|
|
||||||
i64 ifront;
|
|
||||||
union {
|
|
||||||
r1i64_t range;
|
|
||||||
i64 pos[2];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct xy_t xy_t;
|
|
||||||
struct xy_t {
|
|
||||||
i64 col;
|
|
||||||
i64 line;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct edit16_t edit16_t;
|
|
||||||
struct edit16_t {
|
|
||||||
r1i64_t range;
|
|
||||||
s16_t string;
|
|
||||||
};
|
|
||||||
|
|
||||||
// @todo: redo tree
|
|
||||||
typedef array(edit16_t) array_edit16_t;
|
|
||||||
typedef array(caret_t) array_caret_t;
|
|
||||||
typedef struct history16_t history16_t;
|
|
||||||
struct history16_t {
|
|
||||||
array_edit16_t edits;
|
|
||||||
array_caret_t carets;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef array(history16_t) array_history16_t;
|
|
||||||
typedef struct buffer16_id_t buffer16_id_t;
|
|
||||||
struct buffer16_id_t { i64 e; };
|
|
||||||
|
|
||||||
typedef struct buffer16_t buffer16_t;
|
|
||||||
struct buffer16_t {
|
|
||||||
s8_t name;
|
|
||||||
buffer16_id_t id;
|
|
||||||
|
|
||||||
i32 change_id;
|
|
||||||
i8 edit_phase;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
b8 dirty: 1;
|
|
||||||
b8 history: 1;
|
|
||||||
b8 line_starts: 1;
|
|
||||||
} flags;
|
|
||||||
|
|
||||||
union {
|
|
||||||
s16_t string;
|
|
||||||
u16 *data;
|
|
||||||
struct {
|
|
||||||
u16 *str;
|
|
||||||
i64 len;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
i64 cap;
|
|
||||||
array_i64_t line_starts;
|
|
||||||
|
|
||||||
array_history16_t undo_stack;
|
|
||||||
array_history16_t redo_stack;
|
|
||||||
alo_t alo;
|
|
||||||
};
|
|
||||||
|
|
||||||
gb i64 buffer_raw_ids;
|
gb i64 buffer_raw_ids;
|
||||||
const b32 dont_kill_selection = false;
|
|
||||||
const b32 kill_selection = true;
|
|
||||||
|
|
||||||
fn void buffer16_multi_cursor_apply_edits(buffer16_t *buffer, array_edit16_t edits);
|
|
||||||
|
///////////////////////////////
|
||||||
|
// caret helpers
|
||||||
|
///////////////////////////////
|
||||||
|
|
||||||
|
fn i64 caret_get_front(caret_t caret) {
|
||||||
|
i64 result = caret.pos[caret.ifront];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn i64 caret_get_back(caret_t caret) {
|
||||||
|
i64 result = caret.pos[(caret.ifront + 1) % 2];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn caret_t caret_make(i64 front, i64 back) {
|
||||||
|
caret_t result = {0};
|
||||||
|
if (front >= back) {
|
||||||
|
result.range.min = back;
|
||||||
|
result.range.max = front;
|
||||||
|
result.ifront = 1;
|
||||||
|
} else {
|
||||||
|
result.range.min = front;
|
||||||
|
result.range.max = back;
|
||||||
|
result.ifront = 0;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn caret_t caret_set_front(caret_t caret, i64 pos) {
|
||||||
|
i64 back = caret_get_back(caret);
|
||||||
|
caret_t result = caret_make(pos, back);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn caret_t caret_set_back(caret_t caret, i64 pos) {
|
||||||
|
i64 front = caret_get_front(caret);
|
||||||
|
caret_t result = caret_make(front, pos);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn b32 carets_are_equal(caret_t a, caret_t b) {
|
||||||
|
b32 result = r1i64_are_equal(a.range, b.range) && a.ifront == b.ifront;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn b32 carets_overlap(caret_t a, caret_t b) {
|
||||||
|
b32 result = r1i64_overlap(a.range, b.range);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
// buffer helpers
|
// buffer helpers
|
||||||
@@ -181,47 +164,6 @@ fn r1i64_t buffer16_clamp_range(buffer16_t *buffer, r1i64_t range) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn i64 caret_get_front(caret_t caret) {
|
|
||||||
i64 result = caret.pos[caret.ifront];
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn i64 caret_get_back(caret_t caret) {
|
|
||||||
i64 result = caret.pos[(caret.ifront + 1) % 2];
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn caret_t caret_make(i64 front, i64 back) {
|
|
||||||
caret_t result = {0};
|
|
||||||
if (front >= back) {
|
|
||||||
result.range.min = back;
|
|
||||||
result.range.max = front;
|
|
||||||
result.ifront = 1;
|
|
||||||
} else {
|
|
||||||
result.range.min = front;
|
|
||||||
result.range.max = back;
|
|
||||||
result.ifront = 0;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn caret_t caret_set_front(caret_t caret, i64 pos) {
|
|
||||||
i64 back = caret_get_back(caret);
|
|
||||||
caret_t result = caret_make(pos, back);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn caret_t caret_set_back(caret_t caret, i64 pos) {
|
|
||||||
i64 front = caret_get_front(caret);
|
|
||||||
caret_t result = caret_make(front, pos);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn b32 carets_are_equal(caret_t a, caret_t b) {
|
|
||||||
b32 result = r1i64_are_equal(a.range, b.range) && a.ifront == b.ifront;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn i64 buffer16_get_word_start(buffer16_t *buffer, i64 pos) {
|
fn i64 buffer16_get_word_start(buffer16_t *buffer, i64 pos) {
|
||||||
pos = CLAMP(pos, (i64)0, buffer->len);
|
pos = CLAMP(pos, (i64)0, buffer->len);
|
||||||
for (i64 i = pos - 1; i >= 0; i -= 1) {
|
for (i64 i = pos - 1; i >= 0; i -= 1) {
|
||||||
@@ -257,7 +199,7 @@ fn i64 buffer16_get_next_word_end(buffer16_t *buffer, i64 pos) {
|
|||||||
// semantics - proper max is one past last index
|
// semantics - proper max is one past last index
|
||||||
if (!(i < buffer->len))
|
if (!(i < buffer->len))
|
||||||
break;
|
break;
|
||||||
fn if (prev == L'\n' || (prev && prev != buffer->str[i]) || char16_is_word(buffer->str[i])) {
|
if (prev == L'\n' || (prev && prev != buffer->str[i]) || char16_is_word(buffer->str[i])) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
prev = buffer->str[i];
|
prev = buffer->str[i];
|
||||||
@@ -271,7 +213,7 @@ fn i64 buffer16_get_prev_word_start(buffer16_t *buffer, i64 pos) {
|
|||||||
u16 prev = 0;
|
u16 prev = 0;
|
||||||
i64 i = pos - 1;
|
i64 i = pos - 1;
|
||||||
for (; i >= 0; i -= 1) {
|
for (; i >= 0; i -= 1) {
|
||||||
fn if (prev == L'\n' || (prev && prev != buffer->str[i]) || char16_is_word(buffer->str[i])) {
|
if (prev == L'\n' || (prev && prev != buffer->str[i]) || char16_is_word(buffer->str[i])) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pos = i;
|
pos = i;
|
||||||
@@ -332,20 +274,6 @@ fn i64 buffer16_offset_pos_by_line(buffer16_t *buffer, i64 pos, i64 line_offset)
|
|||||||
// raw buffer operations
|
// raw buffer operations
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
|
|
||||||
fn void buffer16_raw_init(alo_t alo, buffer16_t *buffer, s8_t name, i64 size) {
|
|
||||||
buffer->id = (buffer16_id_t){++buffer_raw_ids};
|
|
||||||
buffer->name = name;
|
|
||||||
buffer->alo = alo;
|
|
||||||
buffer->cap = size;
|
|
||||||
buffer->data = alloc_array(alo, u16, size);
|
|
||||||
array_init(alo, &buffer->line_starts, 128);
|
|
||||||
array_init(alo, &buffer->undo_stack, 128);
|
|
||||||
array_init(alo, &buffer->redo_stack, 128);
|
|
||||||
buffer->flags.line_starts = true;
|
|
||||||
buffer->flags.history = true;
|
|
||||||
array_add(&buffer->line_starts, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn void buffer16_raw_grow(buffer16_t *buffer, i64 change_size) {
|
fn void buffer16_raw_grow(buffer16_t *buffer, i64 change_size) {
|
||||||
i64 new_size = buffer->len + change_size;
|
i64 new_size = buffer->len + change_size;
|
||||||
if (new_size > buffer->cap) {
|
if (new_size > buffer->cap) {
|
||||||
@@ -453,6 +381,32 @@ fn void buffer16_raw_replace_text(buffer16_t *buffer, r1i64_t range, s16_t strin
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
// buffer multicursor + history
|
||||||
|
///////////////////////////////
|
||||||
|
|
||||||
|
fn void buffer16_init(alo_t alo, buffer16_t *buffer, s8_t name, i64 size) {
|
||||||
|
buffer->id = (buffer16_id_t){++buffer_raw_ids};
|
||||||
|
buffer->name = name;
|
||||||
|
buffer->alo = alo;
|
||||||
|
buffer->cap = size;
|
||||||
|
buffer->data = alloc_array(alo, u16, size);
|
||||||
|
array_init(alo, &buffer->line_starts, 128);
|
||||||
|
array_init(alo, &buffer->undo_stack, 128);
|
||||||
|
array_init(alo, &buffer->redo_stack, 128);
|
||||||
|
buffer->flags.line_starts = true;
|
||||||
|
buffer->flags.history = true;
|
||||||
|
array_add(&buffer->line_starts, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn void buffer16_deinit(buffer16_t *buffer) {
|
||||||
|
// @todo: verify this works
|
||||||
|
array_dealloc(&buffer->line_starts);
|
||||||
|
dealloc(buffer->alo, buffer->data);
|
||||||
|
buffer16_dealloc_history_array(buffer, &buffer->undo_stack);
|
||||||
|
buffer16_dealloc_history_array(buffer, &buffer->redo_stack);
|
||||||
|
}
|
||||||
|
|
||||||
fn void buffer16_save_history_before_merge_cursor(buffer16_t *buffer, array_history16_t *stack, array_caret_t *carets) {
|
fn void buffer16_save_history_before_merge_cursor(buffer16_t *buffer, array_history16_t *stack, array_caret_t *carets) {
|
||||||
if (!buffer->flags.history) {
|
if (!buffer->flags.history) {
|
||||||
return;
|
return;
|
||||||
@@ -473,24 +427,25 @@ fn void buffer16_save_history_before_apply_edits(buffer16_t *buffer, array_histo
|
|||||||
|
|
||||||
// make reverse edits
|
// make reverse edits
|
||||||
array_for(edit16_t, it, &entry->edits) {
|
array_for(edit16_t, it, &entry->edits) {
|
||||||
it->range = (r1i64_t){it->range.min, it->range.min + it->string.len};
|
r1i64_t new_range = {it->range.min, it->range.min + it->string.len};
|
||||||
it->string = s16_alo_copy(buffer->alo, buffer16_get_string(buffer, it->range));
|
s16_t string = buffer16_get_string(buffer, it->range);
|
||||||
|
it->string = s16_copy_ex(buffer->alo, string);
|
||||||
|
it->range = new_range;
|
||||||
}
|
}
|
||||||
|
|
||||||
ma_temp_t scratch = ma_begin_scratch1(buffer->alo.object);
|
ma_temp_t scratch = ma_begin_scratch1(buffer->alo.object);
|
||||||
array_edit16_t temp_edit = {0};
|
array_edit16_t temp_edit = {0};
|
||||||
array_copy(ma_temp_alo(scratch), &temp_edit, &entry->edits);
|
array_copy(malot(scratch), &temp_edit, &entry->edits);
|
||||||
|
|
||||||
// fix reverse edits
|
// fix reverse edits
|
||||||
for (int i = 0; i < edits->len; i += 1) {
|
array_for(edit16_t, edit, edits) {
|
||||||
edit16_t *it = edits->data + i;
|
i64 remove_size = r1i64_size(edit->range);
|
||||||
i64 remove_size = r1i64_size(it->range);
|
i64 insert_size = edit->string.len;
|
||||||
i64 insert_size = it->string.len;
|
|
||||||
i64 offset = insert_size - remove_size;
|
i64 offset = insert_size - remove_size;
|
||||||
for (int j = 0; j < entry->edits.len; j += 1) {
|
for (i64 i = 0; i < entry->edits.len; i += 1) {
|
||||||
edit16_t *new_edit = entry->edits.data + i;
|
edit16_t *new_edit = entry->edits.data + i;
|
||||||
edit16_t *old_edit = temp_edit.data + i;
|
edit16_t *old_edit = temp_edit.data + i;
|
||||||
if (old_edit->range.min > it->range.min) {
|
if (old_edit->range.min > edit->range.min) {
|
||||||
new_edit->range.min += offset;
|
new_edit->range.min += offset;
|
||||||
new_edit->range.max += offset;
|
new_edit->range.max += offset;
|
||||||
}
|
}
|
||||||
@@ -520,11 +475,12 @@ fn void buffer16_redo_edit(buffer16_t *buffer, array_caret_t *carets) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn void buffer16_undo_edit(buffer16_t *buffer, array_caret_t *carets) {
|
fn void buffer16_undo_edit(buffer16_t *buffer, array_caret_t *carets) {
|
||||||
if (!buffer->flags.history || buffer->redo_stack.len <= 0) {
|
if (!buffer->flags.history || buffer->undo_stack.len <= 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
history16_t entry = array_pop(&buffer->undo_stack);
|
history16_t entry = array_pop(&buffer->undo_stack);
|
||||||
|
|
||||||
buffer16_save_history_before_merge_cursor(buffer, &buffer->redo_stack, carets);
|
buffer16_save_history_before_merge_cursor(buffer, &buffer->redo_stack, carets);
|
||||||
buffer16_save_history_before_apply_edits(buffer, &buffer->redo_stack, &entry.edits);
|
buffer16_save_history_before_apply_edits(buffer, &buffer->redo_stack, &entry.edits);
|
||||||
buffer16_multi_cursor_apply_edits(buffer, entry.edits);
|
buffer16_multi_cursor_apply_edits(buffer, entry.edits);
|
||||||
@@ -557,10 +513,6 @@ fn void buffer16_dealloc_history_entries(buffer16_t *buffer, array_history16_t *
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn void buffer16_clear_redo_stack(buffer16_t *buffer) {
|
|
||||||
buffer16_dealloc_history_entries(buffer, &buffer->redo_stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn void buffer16_dealloc_history_array(buffer16_t *buffer, array_history16_t *entries) {
|
fn void buffer16_dealloc_history_array(buffer16_t *buffer, array_history16_t *entries) {
|
||||||
buffer16_dealloc_history_entries(buffer, entries);
|
buffer16_dealloc_history_entries(buffer, entries);
|
||||||
array_dealloc(entries);
|
array_dealloc(entries);
|
||||||
@@ -575,7 +527,7 @@ fn array_edit16_t buffer16_begin_edit(alo_t alo, buffer16_t *buffer, array_caret
|
|||||||
buffer->edit_phase += 1;
|
buffer->edit_phase += 1;
|
||||||
assert(carets->len);
|
assert(carets->len);
|
||||||
buffer16_save_history_before_merge_cursor(buffer, &buffer->undo_stack, carets);
|
buffer16_save_history_before_merge_cursor(buffer, &buffer->undo_stack, carets);
|
||||||
buffer16_clear_redo_stack(buffer);
|
buffer16_dealloc_history_entries(buffer, &buffer->redo_stack);
|
||||||
}
|
}
|
||||||
array_edit16_t edits = (array_edit16_t){.alo = alo};
|
array_edit16_t edits = (array_edit16_t){.alo = alo};
|
||||||
return edits;
|
return edits;
|
||||||
@@ -596,7 +548,7 @@ fn void buffer16_adjust_carets(array_edit16_t *edits, array_caret_t *carets) {
|
|||||||
assert(edits->alo.object == carets->alo.object);
|
assert(edits->alo.object == carets->alo.object);
|
||||||
|
|
||||||
array_caret_t new_carets = {0};
|
array_caret_t new_carets = {0};
|
||||||
array_copy(ma_temp_alo(scratch), &new_carets, carets);
|
array_copy(malot(scratch), &new_carets, carets);
|
||||||
array_for(edit16_t, it, edits) {
|
array_for(edit16_t, it, edits) {
|
||||||
i64 remove_size = r1i64_size(it->range);
|
i64 remove_size = r1i64_size(it->range);
|
||||||
i64 insert_size = it->string.len;
|
i64 insert_size = it->string.len;
|
||||||
@@ -643,7 +595,7 @@ fn void buffer16_end_edit(buffer16_t *buffer, array_edit16_t *edits, array_caret
|
|||||||
assert(buffer->alo.object == edits->alo.object);
|
assert(buffer->alo.object == edits->alo.object);
|
||||||
|
|
||||||
array_caret_t new_carets = {0};
|
array_caret_t new_carets = {0};
|
||||||
array_copy(ma_temp_alo(scratch), &new_carets, carets);
|
array_copy(malot(scratch), &new_carets, carets);
|
||||||
array_for(edit16_t, it, edits) {
|
array_for(edit16_t, it, edits) {
|
||||||
i64 remove_size = r1i64_size(it->range);
|
i64 remove_size = r1i64_size(it->range);
|
||||||
i64 insert_size = it->string.len;
|
i64 insert_size = it->string.len;
|
||||||
@@ -679,7 +631,7 @@ fn void buffer16_end_edit(buffer16_t *buffer, array_edit16_t *edits, array_caret
|
|||||||
ma_end_scratch(scratch);
|
ma_end_scratch(scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
void caret_merge_sort(i64 Count, caret_t *First, caret_t *Temp) {
|
fn void caret_merge_sort(i64 Count, caret_t *First, caret_t *Temp) {
|
||||||
// SortKey = range.min
|
// SortKey = range.min
|
||||||
if (Count == 1) {
|
if (Count == 1) {
|
||||||
// NOTE(casey): No work to do.
|
// NOTE(casey): No work to do.
|
||||||
@@ -733,7 +685,7 @@ void caret_merge_sort(i64 Count, caret_t *First, caret_t *Temp) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void edit16_merge_sort(i64 Count, edit16_t *First, edit16_t *Temp) {
|
fn void edit16_merge_sort(i64 Count, edit16_t *First, edit16_t *Temp) {
|
||||||
// SortKey = range.min
|
// SortKey = range.min
|
||||||
if (Count == 1) {
|
if (Count == 1) {
|
||||||
// NOTE(casey): No work to do.
|
// NOTE(casey): No work to do.
|
||||||
@@ -814,7 +766,7 @@ fn void buffer16_multi_cursor_apply_edits(buffer16_t *buffer, array_edit16_t edi
|
|||||||
{
|
{
|
||||||
ma_temp_t scratch = ma_begin_scratch1(buffer->alo.object);
|
ma_temp_t scratch = ma_begin_scratch1(buffer->alo.object);
|
||||||
array_edit16_t edits_copy = {0};
|
array_edit16_t edits_copy = {0};
|
||||||
array_copy(ma_temp_alo(scratch), &edits_copy, &edits);
|
array_copy(malot(scratch), &edits_copy, &edits);
|
||||||
if (edits.len > 1) edit16_merge_sort(edits.len, edits_copy.data, edits.data);
|
if (edits.len > 1) edit16_merge_sort(edits.len, edits_copy.data, edits.data);
|
||||||
edits = edits_copy;
|
edits = edits_copy;
|
||||||
ma_end_scratch(scratch);
|
ma_end_scratch(scratch);
|
||||||
@@ -854,7 +806,7 @@ fn void buffer16_merge_carets(buffer16_t *buffer, array_caret_t *carets) {
|
|||||||
|
|
||||||
ma_temp_t scratch = ma_begin_scratch1(buffer->alo.object);
|
ma_temp_t scratch = ma_begin_scratch1(buffer->alo.object);
|
||||||
array_caret_t c1 = {0};
|
array_caret_t c1 = {0};
|
||||||
array_copy(ma_temp_alo(scratch), &c1, carets);
|
array_copy(malot(scratch), &c1, carets);
|
||||||
if (carets->len > 1) {
|
if (carets->len > 1) {
|
||||||
caret_merge_sort(carets->len, c1.data, carets->data);
|
caret_merge_sort(carets->len, c1.data, carets->data);
|
||||||
}
|
}
|
||||||
@@ -887,7 +839,7 @@ fn_test void buffer16_test(void) {
|
|||||||
{
|
{
|
||||||
s16_t string = s16("thing itself");
|
s16_t string = s16("thing itself");
|
||||||
buffer16_t *buffer = ma_push_type(scratch.arena, buffer16_t);
|
buffer16_t *buffer = ma_push_type(scratch.arena, buffer16_t);
|
||||||
buffer16_raw_init(ma_temp_alo(scratch), buffer, S8_FILE_AND_LINE, 16);
|
buffer16_init(malot(scratch), buffer, S8_FILE_AND_LINE, 16);
|
||||||
buffer16_raw_replace_text(buffer, r1i64_null, string);
|
buffer16_raw_replace_text(buffer, r1i64_null, string);
|
||||||
assert(s16_are_equal(buffer->string, string));
|
assert(s16_are_equal(buffer->string, string));
|
||||||
assert(buffer->cap == 16);
|
assert(buffer->cap == 16);
|
||||||
@@ -919,7 +871,7 @@ fn_test void buffer16_test(void) {
|
|||||||
{
|
{
|
||||||
s16_t string = s16("thing itself_and meme");
|
s16_t string = s16("thing itself_and meme");
|
||||||
buffer16_t *buffer = ma_push_type(scratch.arena, buffer16_t);
|
buffer16_t *buffer = ma_push_type(scratch.arena, buffer16_t);
|
||||||
buffer16_raw_init(ma_temp_alo(scratch), buffer, S8_FILE_AND_LINE, 10);
|
buffer16_init(malot(scratch), buffer, S8_FILE_AND_LINE, 10);
|
||||||
buffer16_raw_replace_text(buffer, r1i64_null, string);
|
buffer16_raw_replace_text(buffer, r1i64_null, string);
|
||||||
r1i64_t range = buffer16_enclose_word(buffer, 18);
|
r1i64_t range = buffer16_enclose_word(buffer, 18);
|
||||||
buffer16_raw_replace_text(buffer, range, s16("cat"));
|
buffer16_raw_replace_text(buffer, range, s16("cat"));
|
||||||
@@ -934,7 +886,7 @@ fn_test void buffer16_test(void) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
buffer16_t *buffer = ma_push_type(scratch.arena, buffer16_t);
|
buffer16_t *buffer = ma_push_type(scratch.arena, buffer16_t);
|
||||||
buffer16_raw_init(ma_temp_alo(scratch), buffer, S8_FILE_AND_LINE, 16);
|
buffer16_init(malot(scratch), buffer, S8_FILE_AND_LINE, 16);
|
||||||
for (int i = 0; i < 16; i += 1) {
|
for (int i = 0; i < 16; i += 1) {
|
||||||
buffer16_raw_replace_text(buffer, r1i64_null, s16("line of memes\n"));
|
buffer16_raw_replace_text(buffer, r1i64_null, s16("line of memes\n"));
|
||||||
}
|
}
|
||||||
@@ -942,14 +894,15 @@ fn_test void buffer16_test(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
s16_t string = s16("some thing or another and stuff like that");
|
||||||
|
s16_t meme_string = s16("meme meme or another and stuff like that");
|
||||||
buffer16_t *buffer = ma_push_type(scratch.arena, buffer16_t);
|
buffer16_t *buffer = ma_push_type(scratch.arena, buffer16_t);
|
||||||
buffer16_raw_init(ma_temp_alo(scratch), buffer, S8_FILE_AND_LINE, 128);
|
buffer16_init(malot(scratch), buffer, S8_FILE_AND_LINE, 128);
|
||||||
buffer16_raw_replace_text(buffer, r1i64_null, s16("some thing or another and stuff like that"));
|
buffer16_raw_replace_text(buffer, r1i64_null, string);
|
||||||
|
|
||||||
{
|
{
|
||||||
array_caret_t carets = {0};
|
array_caret_t carets = {0};
|
||||||
array_init(ma_temp_alo(scratch), &carets, 32);
|
array_init(malot(scratch), &carets, 32);
|
||||||
array_add(&carets, caret_make(0, 4));
|
array_add(&carets, caret_make(0, 4));
|
||||||
array_add(&carets, caret_make(3, 8));
|
array_add(&carets, caret_make(3, 8));
|
||||||
array_add(&carets, caret_make(3, 8));
|
array_add(&carets, caret_make(3, 8));
|
||||||
@@ -964,12 +917,12 @@ fn_test void buffer16_test(void) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
array_caret_t carets = {0};
|
array_caret_t carets = {0};
|
||||||
array_init(ma_temp_alo(scratch), &carets, 32);
|
array_init(malot(scratch), &carets, 32);
|
||||||
array_add(&carets, caret_make(0, 4));
|
array_add(&carets, caret_make(0, 4));
|
||||||
array_add(&carets, caret_make(0, 3));
|
array_add(&carets, caret_make(0, 3));
|
||||||
array_add(&carets, caret_make(5, 10));
|
array_add(&carets, caret_make(5, 10));
|
||||||
|
|
||||||
array_edit16_t edits = buffer16_begin_edit(ma_temp_alo(scratch), buffer, &carets);
|
array_edit16_t edits = buffer16_begin_edit(malot(scratch), buffer, &carets);
|
||||||
|
|
||||||
buffer16_merge_carets(buffer, &carets);
|
buffer16_merge_carets(buffer, &carets);
|
||||||
assert(carets.len == 2);
|
assert(carets.len == 2);
|
||||||
@@ -979,7 +932,14 @@ fn_test void buffer16_test(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
buffer16_end_edit(buffer, &edits, &carets, kill_selection);
|
buffer16_end_edit(buffer, &edits, &carets, kill_selection);
|
||||||
assert(s16_are_equal(buffer->string, s16("meme meme or another and stuff like that")));
|
assert(s16_are_equal(buffer->string, meme_string));
|
||||||
|
|
||||||
|
for (i32 i = 0; i < 32; i += 1) {
|
||||||
|
buffer16_undo_edit(buffer, &carets);
|
||||||
|
assert(s16_are_equal(buffer->string, string));
|
||||||
|
buffer16_redo_edit(buffer, &carets);
|
||||||
|
assert(s16_are_equal(buffer->string, meme_string));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
129
src/text_editor/buffer16.h
Normal file
129
src/text_editor/buffer16.h
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
typedef struct caret_t caret_t;
|
||||||
|
struct caret_t {
|
||||||
|
i64 ifront;
|
||||||
|
union {
|
||||||
|
r1i64_t range;
|
||||||
|
i64 pos[2];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct xy_t xy_t;
|
||||||
|
struct xy_t {
|
||||||
|
i64 col;
|
||||||
|
i64 line;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct edit16_t edit16_t;
|
||||||
|
struct edit16_t {
|
||||||
|
r1i64_t range;
|
||||||
|
s16_t string;
|
||||||
|
};
|
||||||
|
|
||||||
|
// @todo: redo tree
|
||||||
|
typedef array(edit16_t) array_edit16_t;
|
||||||
|
typedef array(caret_t) array_caret_t;
|
||||||
|
typedef struct history16_t history16_t;
|
||||||
|
struct history16_t {
|
||||||
|
array_edit16_t edits;
|
||||||
|
array_caret_t carets;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef array(history16_t) array_history16_t;
|
||||||
|
typedef struct buffer16_id_t buffer16_id_t;
|
||||||
|
struct buffer16_id_t { i64 e; };
|
||||||
|
|
||||||
|
typedef struct buffer16_t buffer16_t;
|
||||||
|
struct buffer16_t {
|
||||||
|
s8_t name;
|
||||||
|
buffer16_id_t id;
|
||||||
|
|
||||||
|
i32 change_id;
|
||||||
|
i8 edit_phase;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
b8 dirty: 1;
|
||||||
|
b8 history: 1;
|
||||||
|
b8 line_starts: 1;
|
||||||
|
} flags;
|
||||||
|
|
||||||
|
union {
|
||||||
|
s16_t string;
|
||||||
|
u16 *data;
|
||||||
|
struct {
|
||||||
|
u16 *str;
|
||||||
|
i64 len;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
i64 cap;
|
||||||
|
array_i64_t line_starts;
|
||||||
|
|
||||||
|
array_history16_t undo_stack;
|
||||||
|
array_history16_t redo_stack;
|
||||||
|
alo_t alo;
|
||||||
|
};
|
||||||
|
|
||||||
|
const b32 dont_kill_selection = false;
|
||||||
|
const b32 kill_selection = true;
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
// caret helpers
|
||||||
|
fn caret_t caret_make(i64 front, i64 back);
|
||||||
|
fn i64 caret_get_front(caret_t caret);
|
||||||
|
fn i64 caret_get_back(caret_t caret);
|
||||||
|
fn caret_t caret_set_front(caret_t caret, i64 pos);
|
||||||
|
fn caret_t caret_set_back(caret_t caret, i64 pos);
|
||||||
|
fn b32 carets_are_equal(caret_t a, caret_t b);
|
||||||
|
fn b32 carets_overlap(caret_t a, caret_t b);
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
// buffer helpers
|
||||||
|
fn i64 buffer16_pos_to_line(buffer16_t *buffer, i64 pos);
|
||||||
|
fn r1i64_t buffer16_get_line_range(buffer16_t *buffer, i64 line);
|
||||||
|
fn r1i64_t buffer16_get_line_range_full(buffer16_t *buffer, i64 line, i64 *eof);
|
||||||
|
fn xy_t buffer16_pos_to_xy(buffer16_t *buffer, i64 pos);
|
||||||
|
fn i64 buffer16_xy_to_pos(buffer16_t *buffer, xy_t xy);
|
||||||
|
fn i64 buffer16_xy_to_pos_without_new_line(buffer16_t *buffer, xy_t xy);
|
||||||
|
fn s16_t buffer16_get_string(buffer16_t *buffer, r1i64_t range);
|
||||||
|
fn s16_t buffer16_get_line_string(buffer16_t *buffer, i64 line);
|
||||||
|
fn r1i64_t buffer16_get_range_end(buffer16_t *buffer);
|
||||||
|
fn r1i64_t buffer16_get_range(buffer16_t *buffer);
|
||||||
|
fn i64 buffer16_clamp_pos(buffer16_t *buffer, i64 pos);
|
||||||
|
fn r1i64_t buffer16_clamp_range(buffer16_t *buffer, r1i64_t range);
|
||||||
|
fn i64 buffer16_get_word_start(buffer16_t *buffer, i64 pos);
|
||||||
|
fn i64 buffer16_get_word_end(buffer16_t *buffer, i64 pos);
|
||||||
|
fn i64 buffer16_get_next_word_end(buffer16_t *buffer, i64 pos);
|
||||||
|
fn i64 buffer16_get_prev_word_start(buffer16_t *buffer, i64 pos);
|
||||||
|
fn i64 buffer16_get_line_start(buffer16_t *buffer, i64 pos, i64 *eof);
|
||||||
|
fn i64 buffer16_get_line_end(buffer16_t *buffer, i64 pos, i64 *eof);
|
||||||
|
fn i64 buffer16_get_line_start_full(buffer16_t *buffer, i64 pos);
|
||||||
|
fn i64 buffer16_get_line_end_full(buffer16_t *buffer, i64 pos);
|
||||||
|
fn r1i64_t buffer16_enclose_word(buffer16_t *buffer, i64 pos);
|
||||||
|
fn u16 buffer16_get_char(buffer16_t *buffer, i64 pos);
|
||||||
|
fn i64 buffer16_offset_pos_by_line(buffer16_t *buffer, i64 pos, i64 line_offset);
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
// buffer raw textural operations. no history
|
||||||
|
fn void buffer16_raw_grow(buffer16_t *buffer, i64 change_size);
|
||||||
|
fn void buffer16_raw_replace_text(buffer16_t *buffer, r1i64_t range, s16_t string);
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
// buffer multicursor + history
|
||||||
|
fn void buffer16_init(alo_t alo, buffer16_t *buffer, s8_t name, i64 size);
|
||||||
|
fn void buffer16_deinit(buffer16_t *buffer);
|
||||||
|
fn void buffer16_add_edit(array_edit16_t *edits, r1i64_t range, s16_t string);
|
||||||
|
fn array_edit16_t buffer16_begin_edit(alo_t alo, buffer16_t *buffer, array_caret_t *carets);
|
||||||
|
fn void buffer16_end_edit(buffer16_t *buffer, array_edit16_t *edits, array_caret_t *carets, b32 kill_selection);
|
||||||
|
fn void buffer16_merge_carets(buffer16_t *buffer, array_caret_t *carets);
|
||||||
|
fn void buffer16_adjust_carets(array_edit16_t *edits, array_caret_t *carets);
|
||||||
|
|
||||||
|
fn void buffer16_redo_edit(buffer16_t *buffer, array_caret_t *carets);
|
||||||
|
fn void buffer16_undo_edit(buffer16_t *buffer, array_caret_t *carets);
|
||||||
|
|
||||||
|
fn void buffer16_save_history_before_merge_cursor(buffer16_t *buffer, array_history16_t *stack, array_caret_t *carets);
|
||||||
|
fn void buffer16_save_history_before_apply_edits(buffer16_t *buffer, array_history16_t *stack, array_edit16_t *edits);
|
||||||
|
fn void buffer16_pre_begin_edit_save_caret_history(buffer16_t *buffer, array_caret_t *carets);
|
||||||
|
|
||||||
|
fn void buffer16_dealloc_history_entries(buffer16_t *buffer, array_history16_t *entries);
|
||||||
|
fn void buffer16_dealloc_history_array(buffer16_t *buffer, array_history16_t *entries);
|
||||||
|
fn void buffer16_multi_cursor_apply_edits(buffer16_t *buffer, array_edit16_t edits);
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "os/os.h"
|
#include "os/os.h"
|
||||||
#include "app/app.h"
|
#include "app/app.h"
|
||||||
#include "profiler/profiler.h"
|
#include "profiler/profiler.h"
|
||||||
|
#include "buffer16.h"
|
||||||
// #include "ui/ui.h"
|
// #include "ui/ui.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -10,8 +11,7 @@
|
|||||||
#include "app/app.c"
|
#include "app/app.c"
|
||||||
#include "profiler/profiler.c"
|
#include "profiler/profiler.c"
|
||||||
#include "render/render.c"
|
#include "render/render.c"
|
||||||
#include "core_array.c"
|
#include "buffer16.c"
|
||||||
#include "text_editor_buffer.c"
|
|
||||||
// #include "ui/ui.c"
|
// #include "ui/ui.c"
|
||||||
|
|
||||||
#include "text_editor.gen.c"
|
#include "text_editor.gen.c"
|
||||||
|
|||||||
18
src/ui/ui.c
18
src/ui/ui.c
@@ -367,7 +367,7 @@ fn ui_signal_t ui_signal_from_box(ui_box_t *box) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn v2f32_t ui_aligned_text_pos(f32 offset, ui_text_align_t text_align, r2f32_t rect, s8_t string, v2f32_t string_size) {
|
fn v2f32_t ui_aligned_text_pos(f32 offset, ui_text_align_t text_align, r2f32_t rect, s8_t string, v2f32_t string_size) {
|
||||||
v2f32_t rect_size = r2f32_get_size(rect);
|
v2f32_t rect_size = r2f32_size(rect);
|
||||||
v2f32_t rect_string_diff = v2f32_sub(rect_size, string_size);
|
v2f32_t rect_string_diff = v2f32_sub(rect_size, string_size);
|
||||||
v2f32_t center_pos = v2f32_divs(rect_string_diff, 2);
|
v2f32_t center_pos = v2f32_divs(rect_string_diff, 2);
|
||||||
v2f32_t pos_in_rect = v2f32(0, center_pos.y);
|
v2f32_t pos_in_rect = v2f32(0, center_pos.y);
|
||||||
@@ -390,7 +390,7 @@ struct ui_draw_compute_t {
|
|||||||
fn r2f32_t ui_get_appear_rect(ui_box_t *box) {
|
fn r2f32_t ui_get_appear_rect(ui_box_t *box) {
|
||||||
r2f32_t result = box->rect;
|
r2f32_t result = box->rect;
|
||||||
if (box->flags.animate_appear && !ui_id_is_null(box->id)) {
|
if (box->flags.animate_appear && !ui_id_is_null(box->id)) {
|
||||||
v2f32_t size = v2f32_muls(r2f32_get_size(result), 0.15f);
|
v2f32_t size = v2f32_muls(r2f32_size(result), 0.15f);
|
||||||
r2f32_t smaller_rect = r2f32_shrink(result, size);
|
r2f32_t smaller_rect = r2f32_shrink(result, size);
|
||||||
f32 appear_t = f32_ease_out_n(f32_clamp01(box->appear_t * 2), 10);
|
f32 appear_t = f32_ease_out_n(f32_clamp01(box->appear_t * 2), 10);
|
||||||
result = r2f32_lerp(smaller_rect, result, appear_t);
|
result = r2f32_lerp(smaller_rect, result, appear_t);
|
||||||
@@ -634,7 +634,7 @@ fn void ui_tree_table_begin(ui_code_loc_t loc) {
|
|||||||
fn void ui_tree_table_end(void) {
|
fn void ui_tree_table_end(void) {
|
||||||
ui_box_t *box = ui_pop_top();
|
ui_box_t *box = ui_pop_top();
|
||||||
ui_set_children_sums(box);
|
ui_set_children_sums(box);
|
||||||
ui_next_rect(ui_top_lop(), ui_top_rectp(), r2f32_get_size(box->rect));
|
ui_next_rect(ui_top_lop(), ui_top_rectp(), r2f32_size(box->rect));
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ui_tree_table_expandable(...) defer_if (ui_tree_table_push_expandable(UILOC, __VA_ARGS__).clicked, ui_tree_table_pop_expandable())
|
#define ui_tree_table_expandable(...) defer_if (ui_tree_table_push_expandable(UILOC, __VA_ARGS__).clicked, ui_tree_table_pop_expandable())
|
||||||
@@ -998,7 +998,7 @@ struct ui_scroller_t {
|
|||||||
|
|
||||||
fn void ui_scroller_calc_vertical(ui_scroller_t s) {
|
fn void ui_scroller_calc_vertical(ui_scroller_t s) {
|
||||||
ui_set_top(s.verti.box) {
|
ui_set_top(s.verti.box) {
|
||||||
f32 scroller_rect_pixels = r2f32_get_size(s.verti.box->rect).y;
|
f32 scroller_rect_pixels = r2f32_size(s.verti.box->rect).y;
|
||||||
f32 all_items_size = s.p.verti.max_size;
|
f32 all_items_size = s.p.verti.max_size;
|
||||||
f32 scroller_size = f32_clamp01(s.verti.item_box_pixels / (all_items_size + s.verti.item_box_pixels));
|
f32 scroller_size = f32_clamp01(s.verti.item_box_pixels / (all_items_size + s.verti.item_box_pixels));
|
||||||
f32 scrollable_space = (1 - scroller_size);
|
f32 scrollable_space = (1 - scroller_size);
|
||||||
@@ -1023,7 +1023,7 @@ fn void ui_scroller_calc_vertical(ui_scroller_t s) {
|
|||||||
}
|
}
|
||||||
if (upper_box_signal.dragging || down_box_signal.dragging) {
|
if (upper_box_signal.dragging || down_box_signal.dragging) {
|
||||||
s.p.verti.value[0] = (ev->mouse_pos.y - upper_box->rect.min.y) * coef;
|
s.p.verti.value[0] = (ev->mouse_pos.y - upper_box->rect.min.y) * coef;
|
||||||
s.p.verti.value[0] -= (r2f32_get_size(slider_box->rect).y / 2) * coef;
|
s.p.verti.value[0] -= (r2f32_size(slider_box->rect).y / 2) * coef;
|
||||||
}
|
}
|
||||||
if (ev->kind == app_event_kind_mouse_wheel) {
|
if (ev->kind == app_event_kind_mouse_wheel) {
|
||||||
s.p.verti.value[0] -= ev->mouse_wheel_delta.y;
|
s.p.verti.value[0] -= ev->mouse_wheel_delta.y;
|
||||||
@@ -1038,7 +1038,7 @@ fn ui_scroller_t ui_begin_scroller(ui_code_loc_t loc, ui_scroller_params_t p) {
|
|||||||
if (p.verti.enabled) {
|
if (p.verti.enabled) {
|
||||||
s.verti.box = ui_box(.loc = loc, .rect = r2f32_cut_right(&p.parent->rect, ui_dm(0.5f)), .flags = {.draw_rect = true});
|
s.verti.box = ui_box(.loc = loc, .rect = r2f32_cut_right(&p.parent->rect, ui_dm(0.5f)), .flags = {.draw_rect = true});
|
||||||
r2f32_cut_bottom(&s.verti.box->rect, ui_dm(0.5f));
|
r2f32_cut_bottom(&s.verti.box->rect, ui_dm(0.5f));
|
||||||
s.verti.item_box_pixels = r2f32_get_size(p.parent->rect).y;
|
s.verti.item_box_pixels = r2f32_size(p.parent->rect).y;
|
||||||
if (p.verti.item_count) {
|
if (p.verti.item_count) {
|
||||||
s.p.verti.max_size = s.p.verti.item_pixels * s.p.verti.item_count;
|
s.p.verti.max_size = s.p.verti.item_pixels * s.p.verti.item_count;
|
||||||
ui_scroller_calc_vertical(s);
|
ui_scroller_calc_vertical(s);
|
||||||
@@ -1077,7 +1077,7 @@ fn void ui_end_scroller(ui_scroller_t s) {
|
|||||||
|
|
||||||
if (s.p.hori.enabled) {
|
if (s.p.hori.enabled) {
|
||||||
ui_set_top(s.hori.box) {
|
ui_set_top(s.hori.box) {
|
||||||
f32 scroller_rect_pixels = r2f32_get_size(s.hori.box->rect).x;
|
f32 scroller_rect_pixels = r2f32_size(s.hori.box->rect).x;
|
||||||
f32 scroller_button_size_norm = f32_clamp01(scroller_rect_pixels / s.p.hori.max_size);
|
f32 scroller_button_size_norm = f32_clamp01(scroller_rect_pixels / s.p.hori.max_size);
|
||||||
f32 scrollable_space = (1.f - scroller_button_size_norm);
|
f32 scrollable_space = (1.f - scroller_button_size_norm);
|
||||||
|
|
||||||
@@ -1101,7 +1101,7 @@ fn void ui_end_scroller(ui_scroller_t s) {
|
|||||||
}
|
}
|
||||||
if (left_box_sig.dragging || right_box_sig.dragging) {
|
if (left_box_sig.dragging || right_box_sig.dragging) {
|
||||||
s.p.hori.value[0] = (ev->mouse_pos.x - left_box->rect.min.x) * coef;
|
s.p.hori.value[0] = (ev->mouse_pos.x - left_box->rect.min.x) * coef;
|
||||||
s.p.hori.value[0] -= (r2f32_get_size(slider_box->rect).x / 2) * coef;
|
s.p.hori.value[0] -= (r2f32_size(slider_box->rect).x / 2) * coef;
|
||||||
}
|
}
|
||||||
if (ev->kind == app_event_kind_mouse_wheel) {
|
if (ev->kind == app_event_kind_mouse_wheel) {
|
||||||
s.p.hori.value[0] -= ev->mouse_wheel_delta.x;
|
s.p.hori.value[0] -= ev->mouse_wheel_delta.x;
|
||||||
@@ -1399,7 +1399,7 @@ fn void ui_demo_update(app_frame_t *frame, mt_tweak_t *tweak_table, i32 tweak_co
|
|||||||
ui_serial_type(UILOC, &ui_test_event, type(app_event_t));
|
ui_serial_type(UILOC, &ui_test_event, type(app_event_t));
|
||||||
|
|
||||||
r2f32_t scroll_rect = r2f32_fix(ui_top_rect());
|
r2f32_t scroll_rect = r2f32_fix(ui_top_rect());
|
||||||
scroller.p.verti.max_size = r2f32_get_size(scroll_rect).y;
|
scroller.p.verti.max_size = r2f32_size(scroll_rect).y;
|
||||||
}
|
}
|
||||||
|
|
||||||
ui_end_scroller(scroller);
|
ui_end_scroller(scroller);
|
||||||
|
|||||||
@@ -10,5 +10,6 @@ void run_all_tests(void) {
|
|||||||
test_string16();
|
test_string16();
|
||||||
test_hash_table();
|
test_hash_table();
|
||||||
test_intern_table();
|
test_intern_table();
|
||||||
|
test_array();
|
||||||
ui_test_text_replace();
|
ui_test_text_replace();
|
||||||
}// run_all_tests()
|
}// run_all_tests()
|
||||||
|
|||||||
Reference in New Issue
Block a user