aboutsummaryrefslogtreecommitdiff
path: root/kscurses
diff options
context:
space:
mode:
Diffstat (limited to 'kscurses')
-rw-r--r--kscurses/canvas.jai172
-rw-r--r--kscurses/events.jai256
-rw-r--r--kscurses/history_stack.jai69
-rw-r--r--kscurses/init.jai125
-rw-r--r--kscurses/io.jai81
-rw-r--r--kscurses/lambdas.jai255
-rw-r--r--kscurses/modes.jai179
-rw-r--r--kscurses/module.jai91
-rw-r--r--kscurses/print.jai148
-rw-r--r--kscurses/queue.jai57
-rw-r--r--kscurses/readme.md43
-rw-r--r--kscurses/ui/button.jai25
-rw-r--r--kscurses/ui/element.jai156
-rw-r--r--kscurses/ui/group.jai44
-rw-r--r--kscurses/ui/line_input.jai122
-rw-r--r--kscurses/ui/links.jai94
-rw-r--r--kscurses/ui/master.jai105
-rw-r--r--kscurses/ui/parent.jai33
-rw-r--r--kscurses/ui/popup_manager.jai65
-rw-r--r--kscurses/ui/progress_bar.jai37
-rw-r--r--kscurses/ui/scalable_group.jai88
-rw-r--r--kscurses/ui/scene_manager.jai48
-rw-r--r--kscurses/ui/select_list.jai79
-rw-r--r--kscurses/ui/style.jai118
-rw-r--r--kscurses/ui/table.jai87
-rw-r--r--kscurses/ui/text_buf.jai15
-rw-r--r--kscurses/ui/tilemap.jai20
-rw-r--r--kscurses/utils.jai53
-rw-r--r--kscurses/vectors.jai210
29 files changed, 0 insertions, 2875 deletions
diff --git a/kscurses/canvas.jai b/kscurses/canvas.jai
deleted file mode 100644
index df0b021..0000000
--- a/kscurses/canvas.jai
+++ /dev/null
@@ -1,172 +0,0 @@
-Canvas :: struct {
- zone : Ibox2;
-
- count : int;
- pixels_last_draw : []Char;
- pixels_buf : []Char;
- links : []Link;
-
- diff_count := 0;
- force_full_refresh := true;
-
- Link :: struct { prev, next : s32; }
-}
-
-deinit :: (using canvas : *Canvas) {
- array_free(pixels_last_draw);
- array_free(pixels_buf); pixels_buf = .[];
- array_free(links);
-}
-resize_clear :: (using canvas : *Canvas, new_zone : Ibox2, filler := Char.{}) {
- if new_zone != zone {
- array_free(pixels_last_draw);
- array_free(pixels_buf);
- array_free(links);
-
- zone = new_zone;
- count = zone.width * zone.height;
-
- pixels_last_draw = NewArray(count, Char);
- pixels_buf = NewArray(count, Char);
- links = NewArray(count + 1, Link);
- links[count] = .{xx count, xx count};
-
- if filler != .{} then {
- for * pixels_buf {
- <<it = filler;
- }
- }
- links[count] = .{-1, -1};
-
- force_full_refresh = true;
- } else {
- for y : 0..zone.height-1 {
- for x : 0..zone.width-1 {
- c_putchar(canvas, filler, .{xx x, xx y});
- }
- }
- }
-}
-// add *void to fill_function
-resize_fill :: (using canvas : *Canvas, new_zone : Ibox2, fill_function : (coord : ivec2, zone : Ibox2) -> Char) {
- if zone != new_zone {
- array_free(pixels_last_draw);
- array_free(pixels_buf);
- array_free(links);
-
- zone = new_zone;
- count = zone.width * zone.height;
-
- pixels_last_draw = NewArray(count, Char);
- pixels_buf = NewArray(count, Char);
- links = NewArray(count + 1, Link);
- links[count] = .{xx count, xx count};
- force_full_refresh = true;
- }
-
- c_fill(canvas, fill_function);
- // i := 0;
- // for y : 0..zone.height-1 {
- // for x : 0..zone.width-1 {
- // pixels_buf[i] = fill_function(.{x, y}, zone);
- // i += 1;
- // diff_count += 1;
- // }
- // }
-
- // for * links {
- // <<it = .{-1, -1};
- // }
-}
-b_draw_canvas :: (builder : *String_Builder, using canvas : *Canvas) {
- if force_full_refresh || diff_count * 4 > zone.width * zone.height {
- i := 0;
- for y : 0..zone.height-1 {
- b_move_cursor(builder, zone.corner + ivec2.{0, y});
- for x : 0..zone.width-1 {
- b_putchar(builder, pixels_buf[i]);
- pixels_last_draw[i] = pixels_buf[i];
- links[i] = .{-1, -1};
- i += 1;
- }
- }
- } else {
- last_pos := ivec2.{-1, -1};
- current := links[count].next;
- I := 0;
-
- while current != count {
- assert(I < count);
- assert(current >= 0);
-
- pos := ivec2.{xx(current % zone.width), xx(current / zone.width)} + zone.corner;
- if pos.x != last_pos.x + 1 || pos.y != last_pos.y {
- b_move_cursor(builder, pos);
- }
- b_putchar(builder, pixels_buf[current]);
- pixels_last_draw[current] = pixels_buf[current];
-
- next := links[current].next;
- links[current] = .{-1, -1};
- current = next;
- last_pos = pos;
- I += 1;
- }
- }
-
- diff_count = 0;
- force_full_refresh = false;
- links[count] = .{xx count, xx count};
-}
-c_putchar :: (using canvas : *Canvas, pixel : Char, pos_local : ivec2) {
- // pos_local := pos - zone.corner;
- if !point_inside(pos_local, .{size = zone.size}) return;
- current := pos_local.x + pos_local.y * zone.width;
-
- c_last_draw := pixels_last_draw[current];
- pixels_buf[current] = pixel;
-
- if links[current].prev == -1 {
- assert(links[current].next == -1);
- if c_last_draw != pixel {
- links[current] = .{links[count].prev, xx count};
- links[links[count].prev].next = current;
- links[count].prev = current;
- diff_count += 1;
- }
- } else {
- if c_last_draw == pixel {
- nbs := links[current];
- assert(links[nbs.prev].next == current && links[nbs.next].prev == current);
- links[nbs.prev].next = nbs.next;
- links[nbs.next].prev = nbs.prev;
- links[current] = .{-1, -1};
- diff_count -= 1;
- }
- }
-}
-
-c_fill :: (using canvas : *Canvas, fill_function : (coord : ivec2, zone : Ibox2) -> Char) {
- for y : 0..zone.height-1 {
- for x : 0..zone.width-1 {
- char := fill_function(.{x, y}, zone);
- c_putchar(canvas, char, .{x, y});
- }
- }
- // i := 0;
- // for y : 0..zone.height-1 {
- // for x : 0..zone.width-1 {
- // pixels_buf[i] = fill_function(.{x, y}, zone);
- // i += 1;
- // diff_count += 1;
- // }
- // }
- // refresh_all = true;
-}
-ks_draw_canvas :: (canvas : *Canvas) {
- builder := String_Builder.{allocator = temp};
- b_draw_canvas(*builder, canvas);
- ks_write(builder_to_string(*builder, allocator = temp));
-}
-
-
diff --git a/kscurses/events.jai b/kscurses/events.jai
deleted file mode 100644
index 603958e..0000000
--- a/kscurses/events.jai
+++ /dev/null
@@ -1,256 +0,0 @@
-Event :: struct {
- type : enum u8 {
- NONE :: 0;
- KEY :: 1;
- WINCH :: 2;
- TICK :: 3;
- INIT :: 4;
- USER :: 5;
- };
- union {
- key : Key;
- data : *void;
- }
-}
-
-__event_handler : struct {
- proc := (e : Event, __data : *void) {
- assert(__data != null);
- if e.type == {
- case .NONE;
- ks_write("empty_event!\n\r");
- case .KEY;
- ks_write(tprint("key = %\n\r", e.key));
- case .WINCH;
- ks_write(tprint("winch, size = %\n\r", terminal_state.size));
- case .TICK;
- ks_write(tprint("tick\n\r"));
- }
- if e.type == .KEY && e.key == .ESCAPE {
- <<cast(*bool)__data = true; // stop_main = true
- }
- };
- data : *void;
-}
-
-use_events :: (tick_duration_ms :s32= 1000, $use_clock := true, init_event := true) #expand {
- init_mutexes();
- #if use_clock clock_thread := start_clock_cycle(tick_duration_ms);
- input_thread := start_input_cycle();
- winlooker_thread := start_winlooker_cycle();
- set_handler();
- if init_event push_event(.{type = .INIT});
- `defer {
- restore_handler();
- stop_winlooker_cycle(winlooker_thread);
- stop_input_cycle(input_thread);
- #if use_clock stop_clock_cycle(clock_thread);
- deinit_mutexes();
- reset_globals();
- }
-}
-wait_and_process_events :: () -> bool {
- wait_for(*event_wait_sem);
- lock(*event_queue_mtx); defer unlock(*event_queue_mtx);
- processed := false;
- while 1 {
- e, ok := pop(*event_queue);
- if !ok break;
- processed = true;
- assert(e.type != .NONE);
- __event_handler.proc(e, __event_handler.data);
- }
- return processed;
-}
-pop_events :: () -> bool {
-}
-push_event :: (e : Event) {
- lock(*event_queue_mtx);
- push(*event_queue, e);
- unlock(*event_queue_mtx);
- signal(*event_wait_sem);
-}
-
-restart_clock_cycle :: () {
- if clock_state != .DISABLED {
- lock(*mtx_clock_state);
- if clock_state != .STOP {
- clock_state = .RESTART;
- }
- signal(*sem_clock_breaker);
- unlock(*mtx_clock_state);
- }
-}
-
-#scope_file
-// SIGWINCH --sigaction--> handler ---sem--> winlooker --push_event--|--> event_queue --pop_events--> master thread
-// stdin --read--> input --push_event--|
-// clock --push_event--|
-
-// event_queue
-event_queue_mtx : Mutex;
-event_queue : Queue(Event);
-event_wait_sem : Semaphore;
-
-// handler
-handler :: (sig : s32) #c_call {
- new_context : Context;
- push_context new_context {
- if sig == SIGWINCH {
- signal(*winch_wait_sem);
- } else {
- log("signal = %\n\r", sig);
- }
- }
-}
-set_handler :: () {
- sa : sigaction_t;
- sa.sa_handler = handler;
- sigemptyset(*(sa.sa_mask));
- sa.sa_flags = SA_RESTART;
- sigaction(SIGWINCH, *sa, null);
-}
-restore_handler :: () {
- sa : sigaction_t;
- sa.sa_handler = SIG_DFL;
- sigaction(SIGWINCH, null, *sa);
-}
-
-// winlooker
-winch_wait_sem : Semaphore;
-stop_winlooker := false;
-winlooker_cycle :: (thread : *Thread) -> s64 {
- while !stop_winlooker {
- wait_for(*winch_wait_sem);
- if stop_winlooker break;
- update_terminal_size();
- push_event(.{type = .WINCH});
- }
- return 0;
-}
-start_winlooker_cycle :: () -> *Thread #expand {
- init(*winch_wait_sem);
- winlooker_thread : Thread;
- thread_init(*winlooker_thread, winlooker_cycle);
- thread_start(*winlooker_thread);
- return *winlooker_thread;
-}
-stop_winlooker_cycle :: (winlooker_thread : *Thread) {
- stop_winlooker = true;
- signal(*winch_wait_sem);
- thread_deinit(winlooker_thread);
- destroy(*winch_wait_sem);
-}
-
-// input
-stop_input := false;
-input_cycle :: (thread : *Thread) -> s64 {
- tcflush(STDIN_FILENO, TCIFLUSH);
- while !stop_input {
- key := ks_getch();
- if stop_input break;
- push_event(.{type = .KEY, key = key});
- }
- return 0;
-}
-start_input_cycle :: () -> *Thread #expand {
- input_thread : Thread;
- thread_init(*input_thread, input_cycle);
- log("input = %\n\r", formatInt(input_thread.thread_handle, base = 16));
- thread_start(*input_thread);
- return *input_thread;
-}
-stop_input_cycle :: (input_thread : *Thread) {
- stop_input = true;
- pthread_cancel(input_thread.thread_handle);
- thread_deinit(input_thread);
-}
-
-// clock
-clock_state : enum u8 {
- NORMAL :: 0;
- STOP :: 1;
- RESTART :: 2;
- DISABLED:: 3;
-} = .DISABLED;
-sem_clock_breaker : Semaphore;
-mtx_clock_state : Mutex;
-
-clock_cycle :: (thread : *Thread) -> s64 {
- tick_duration_ms := <<cast(*s32)thread.data;
-
- while clock_state != .STOP {
- lock(*mtx_clock_state);
- destroy(*sem_clock_breaker);
- init(*sem_clock_breaker);
- clock_state = .NORMAL;
- unlock(*mtx_clock_state);
-
- while 1 {
- r := wait_for(*sem_clock_breaker, tick_duration_ms);
-
- lock(*mtx_clock_state); defer unlock(*mtx_clock_state);
- if clock_state != .NORMAL {
- assert(r == .SUCCESS);
- break;
- } else {
- push_event(.{type = .TICK});
- }
- }
- }
- return 0;
-}
-start_clock_cycle :: (tick_duration_ms : s32) -> *Thread #expand {
- clock_thread : Thread;
- init(*sem_clock_breaker);
- init(*mtx_clock_state);
- clock_state = .NORMAL;
-
- thread_init(*clock_thread, clock_cycle);
-
- tick_duration_ms_ptr := New(s32);
- <<tick_duration_ms_ptr = tick_duration_ms;
-
- clock_thread.data = tick_duration_ms_ptr;
- log("clock = %\n\r", formatInt(clock_thread.thread_handle, base = 16));
- thread_start(*clock_thread);
- return *clock_thread;
-}
-stop_clock_cycle :: (clock_thread : *Thread) {
- lock(*mtx_clock_state);
- clock_state = .STOP;
- signal(*sem_clock_breaker);
- unlock(*mtx_clock_state);
-
- thread_deinit(clock_thread);
- free(clock_thread.data);
- clock_state = .DISABLED;
- destroy(*sem_clock_breaker);
- destroy(*mtx_clock_state);
-}
-
-// utils
-reset_globals :: () {
- stop_input = false;
- clock_state = .NORMAL;
- // stop_clock = false;
- stop_winlooker = false;
- // fd_winch = .[0, 0];
- deinit(*event_queue);
-}
-init_mutexes :: () {
- init(*event_wait_sem);
- init(*event_queue_mtx);
-}
-deinit_mutexes :: () {
- destroy(*event_queue_mtx);
- destroy(*event_wait_sem);
-}
-
-
-TCIFLUSH :: 0;
-
-libc :: #system_library "libc";
-tcflush :: (fd : s32, queue_selector : s32) -> s32 #foreign libc;
-
-#import "Thread"; \ No newline at end of file
diff --git a/kscurses/history_stack.jai b/kscurses/history_stack.jai
deleted file mode 100644
index 3f73df4..0000000
--- a/kscurses/history_stack.jai
+++ /dev/null
@@ -1,69 +0,0 @@
-History_Stack :: struct(
- Action_Type : Type,
- destructor : (obj : Action_Type) = default_destructor
-){
- BUF_SIZE :: 100;
- buffer : [BUF_SIZE]Action_Type;
- offset, current, saved : int;
-}
-
-deinit :: (using history_stack : *History_Stack) {
- guard(history);
-
- for i : 0..saved-1 {
- j := (i + offset) % BUF_SIZE;
- destructor(buffer[offset]);
- }
- offset, current, saved = 0;
-}
-
-write :: (using history : *History_Stack, action : Edit_Action) {
- guard(history);
-
- for i : current..saved-1 {
- j := (i + offset) % BUF_SIZE;
- destructor(buffer[j]);
- }
-
- i0 := (offset + current) % BUF_SIZE;
- if current == BUF_SIZE {
- destructor(buffer[offset]);
- saved = current;
- offset = (offset + 1) % BUF_SIZE;
- } else {
- current += 1;
- saved = current;
- }
- i1 := (offset + current) % BUF_SIZE;
- assert(i0 == i1);
- buffer[i0] = action;
-}
-
-
-undo :: (using history : *History) -> bool, Action_Type {
- guard(history);
- action : Action_Type = ---;
- if current == 0 return false, action;
- current -= 1;
- action = buffer[(current + offset) % BUF_SIZE];
- return true, action;
-}
-redo :: (using history : *History) -> bool, Action_Type {
- guard(history);
- action : Action_Type = ---;
- if current == saved return false, action;
- action = buffer[(current + offset) % BUF_SIZE];
- current += 1;
- return true, action;
-}
-
-#scope_file
-default_destructor :: (obj : $T) { }
-
-guard :: (using history : *History) #expand {
- check :: (using history : *History) {
- assert(0 <= current && current <= saved && saved <= BUF_SIZE);
- assert(0 <= offset && offset <= BUF_SIZE);
- }
- check(history); defer check(history);
-} \ No newline at end of file
diff --git a/kscurses/init.jai b/kscurses/init.jai
deleted file mode 100644
index b67c52f..0000000
--- a/kscurses/init.jai
+++ /dev/null
@@ -1,125 +0,0 @@
-terminal_state : struct {
- size : ivec2;
- cursor := ivec2.{-1, -1}; // {-1, -1} if cursor hidden
- last_mode : Graphics_Mode;
-}
-update_terminal_size :: () {
- TIOCGWINSZ :: 0x5413;
- winsize : struct {
- ws_row, ws_col, ws_xpixel, ws_ypixel : u16;
- }
- ioctl(0, TIOCGWINSZ, *winsize);
- terminal_state.size = .{xx winsize.ws_col, xx winsize.ws_row};
-}
-
-ks_init :: () {
- #if OS == .LINUX {
- __old_logger = context.logger;
- context.logger = file_logger;
-
- ks_write("\e[?25l"); // hide cursor
- ks_write("\e7"); // save cursor position
- ks_write("\e[?1047h"); // switch screen
- ks_write("\e[?30l"); // hide scrollbar
-
- ks_write("\e[H"); // move to top left corner
- ks_write("\e[0m"); // set default mode
- ks_write("\e[2J"); // clear screen
- {
- tcgetattr(STDIN_FILENO, *__term);
- term_new := __term;
-
- term_new.c_iflag &= 0xFFFFFA14;// ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
- term_new.c_oflag &= 0xFFFFFFFE;// ~OPOST;
- term_new.c_lflag &= 0xFFFF7FB4;// ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
- term_new.c_cflag &= 0xFFFFFECF;// ~(CSIZE | PARENB);
- term_new.c_cflag |= 0x00000030;
-
- tcsetattr(STDIN_FILENO, 0, *term_new);
- }
- update_terminal_size();
- } else {
- assert(false, "procedure call on unsupported OS\n");
- }
-}
-ks_terminate :: () {
- #if OS == .LINUX {
- tcsetattr(STDIN_FILENO, 0, *__term); // return echo
-
- ks_write("\e[?47l"); // restore screen
- ks_write("\e8"); // restore cursor
- ks_write("\e[?25h"); // show cursor
- ks_write("\e[?30h"); // show scrollbar
- terminal_state = .{};
-
- context.logger = __old_logger;
- } else {
- assert(false, "procedure call on unsupported OS\n");
- }
-}
-use_ks_curses :: () #expand {
- ks_init();
- `defer {
- ks_terminate();
- }
-}
-use_default_winch_handler :: () #expand {
- init_default_winch_handler();
- `defer deinit_default_winch_handler();
-}
-init_default_winch_handler :: () {
- #if OS == .LINUX {
- act := sigaction_t.{
- sa_handler = (sig : s32) #c_call {
- new_context: Context;
- push_context new_context {
- update_terminal_size();
- }
- },
- sa_mask = sigset_t.{__val[0] = SIGWINCH}
- };
- sigaction(SIGWINCH, *act, null);
- } else {
- assert(false, "procedure call on unsupported OS\n");
- }
-}
-deinit_default_winch_handler :: () {
- #if OS == .LINUX {
- sa : sigaction_t;
- sa.sa_handler = SIG_DFL;
- sigaction(SIGWINCH, null, *sa);
- } else {
-
- }
-}
-
-#scope_file
-__old_logger : type_of(context.logger);
-
-#if OS == .LINUX {
- __term : My_Termios;
-
- My_Termios :: struct {
- c_iflag : u32;
- c_oflag : u32;
- c_cflag : u32;
- c_lflag : u32;
- unknown_pad : u8;
- c_cc : [32]u8;
- c_ispeed : u32;
- c_ospeed : u32;
- }
-
- libc :: #system_library "libc";
- tcsetattr :: (fd : s32, optional_actions : s32, termios_p : *My_Termios) -> s32 #foreign libc;
- tcgetattr :: (fd : s32, termios_p : *My_Termios) -> s32 #foreign libc;
-}
-
-#import "File";
-file_logger :: (message: string, data: *void, info: Log_Info) {
- file, ok := file_open("log.txt",for_writing=true, keep_existing_content=true);
- if !ok return;
-
- file_write(*file, tprint("[%] %", calendar_to_string(to_calendar(current_time_consensus())), message));
- file_close(*file);
-}
diff --git a/kscurses/io.jai b/kscurses/io.jai
deleted file mode 100644
index b2c2df9..0000000
--- a/kscurses/io.jai
+++ /dev/null
@@ -1,81 +0,0 @@
-Key :: enum u64 {
- READ_ERROR :: 0xffffffff_ffffffff;
-
- UP :: 0x41_5b1b;
- DOWN :: 0x42_5b1b;
- RIGHT :: 0x43_5b1b;
- LEFT :: 0x44_5b1b;
-
- CTRL_UP :: 0x4135_3b315b1b;
- CTRL_DOWN :: 0x4235_3b315b1b;
- CTRL_RIGHT :: 0x4335_3b315b1b;
- CTRL_LEFT :: 0x4435_3b315b1b;
-
- SHIFT_UP :: 0x4132_3b315b1b;
- SHIFT_DOWN :: 0x4232_3b315b1b;
- SHIFT_RIGHT :: 0x4332_3b315b1b;
- SHIFT_LEFT :: 0x4432_3b315b1b;
-
- CTRL_SHIFT_UP :: 0x4136_3b315b1b;
- CTRL_SHIFT_DOWN :: 0x4236_3b315b1b;
- CTRL_SHIFT_RIGHT:: 0x4336_3b315b1b;
- CTRL_SHIFT_LEFT :: 0x4436_3b315b1b;
-
- ALT_UP :: 0x4133_3b315b1b;
- ALT_DOWN :: 0x4233_3b315b1b;
- ALT_RIGHT :: 0x4333_3b315b1b;
- ALT_LEFT :: 0x4433_3b315b1b;
-
- CTRL_C :: 0x03;
- CTRL_V :: 0x16;
- CTRL_X :: 0x18;
- CTRL_Y :: 0x19;
- CTRL_Z :: 0x1A;
- CTRL_BACKSLASH :: 0x1C;
-
- // ALT_SHIFT_UP :: 0x4133_3b315b1b;
- // ALT_SHIFT_DOWN :: 0x4233_3b315b1b;
- // ALT_SHIFT_RIGHT :: 0x4333_3b315b1b;
- // ALT_SHIFT_LEFT :: 0x4433_3b315b1b;
-
- ENTER :: 0x0D;
- ESCAPE :: 0x1B;
- BACKSPACE :: 0x7F;
- DELETE :: 0x7E335B1B;
-}
-ks_getch :: (block := true) -> Key {
- #if OS == .LINUX {
- buf : Key = xx 0;
- l := read(STDIN_FILENO, (cast(*u8)*buf), 8); //!!!
- check_signal :: inline (key : Key) {
- #if ENABLE_SIGINT if key == .CTRL_C raise(SIGINT); //!!!
- #if ENABLE_SIGQUIT if key == .CTRL_BACKSLASH raise(SIGQUIT);
- }
- check_signal(buf);
- return ifx l <= 0 then Key.READ_ERROR else buf;
- } else {
- return .READ_ERROR;
- }
-}
-ks_write :: (str : string) {
- #if OS == .LINUX {
- printed := 0;
- // while 1 {
- r := write(STDIN_FILENO, str.data + printed, xx (str.count - printed));
- // if printed + r == str.count {
- // break;
- // } else if r >= 0 {
- // printed += r;
- // }
- // }
- } else {
-
- }
- __write_counter += str.count;
-}
-__write_counter := 0;
-write_counter_delta :: () -> int {
- result := __write_counter;
- __write_counter = 0;
- return result;
-} \ No newline at end of file
diff --git a/kscurses/lambdas.jai b/kscurses/lambdas.jai
deleted file mode 100644
index fd5ffa4..0000000
--- a/kscurses/lambdas.jai
+++ /dev/null
@@ -1,255 +0,0 @@
-decl_lambda :: ($code_src : Code) -> Code #expand {
- node_src := compiler_get_nodes(code_src);
- proc_node, data_node, names, names_field, node_header, node_block := split_src(false, node_src);
- pair_names, pair_srcs := get_lambda_pairs(proc_node, data_node, names, names_field, node_header, node_block);
- return compiler_get_code(*Code_Compound_Declaration.{
- kind = .COMPOUND_DECLARATION,
- comma_separated_assignment = xx pair_names,
- declaration_properties = *Code_Declaration.{
- kind = .DECLARATION,
- expression = pair_srcs
- }
- });
-}
-assign_lambda :: ($code_src : Code, parent_scope := #caller_code) #expand {
- #insert,scope(parent_scope) #run _assign_lambda(code_src);
-}
-struct_lambda :: ($code_src : Code, parent_scope := #caller_code) #expand {
- #insert,scope(parent_scope) #run _struct_lambda(code_src);
-}
-#scope_file
-#import "Compiler";
-#import "Basic";
-#import "Program_Print";
-debug_print_code :: (root : *Code_Node) {
- builder := String_Builder.{allocator = temp};
- print_expression(*builder, root);
- print("%\n", builder_to_string(*builder, allocator = temp));
-}
-_assign_lambda :: ($code_src : Code) -> Code {
- node_src := compiler_get_nodes(code_src);
- proc_node, data_node, names, names_field, node_header, node_block := split_src(false, node_src);
- pair_names, pair_srcs := get_lambda_pairs(proc_node, data_node, names, names_field, node_header, node_block);
- node_assign := Code_Binary_Operator.{
- kind = .BINARY_OPERATOR,
- operator_type = #char"=",
- left = pair_names,
- right = pair_srcs
- };
- return compiler_get_code(*node_assign);
-}
-_struct_lambda :: ($code_src : Code) -> Code {
- node_src := compiler_get_nodes(code_src);
- proc_node, data_node, names, names_field, node_header, node_block := split_src(true, node_src);
- pair_names, pair_srcs := get_lambda_pairs(proc_node, data_node, names, names_field, node_header, node_block);
- node_assign := Code_Binary_Operator.{
- kind = .BINARY_OPERATOR,
- operator_type = #char"=",
- left = pair_names,
- right = pair_srcs
- };
- debug_print_code(*node_assign);
- return compiler_get_code(*node_assign);
-}
-//TODO add support for non-"proc/data" names
-split_src :: (gen_pair : bool, node_src : *Code_Node) -> proc_node:*Code_Node, data_node:*Code_Node, names:[]string, names_field:[]string, node_header:*Code_Procedure_Header, node_block:*Code_Block #expand {
- offset := ifx gen_pair then 1 else 2;
- assert(node_src.kind == .BLOCK);
- node_src_block := cast(*Code_Block) node_src;
- node_src_statements := node_src_block.statements;
- captured_count := node_src_statements.count - 2 - offset;
- assert(captured_count >= 0);
- names := NewArray(captured_count, string);
- names_field := NewArray(captured_count, string);
- for i : offset..captured_count-1+offset {
- assert(node_src_statements[i].kind == .IDENT);
- }
- for i : 0..captured_count-1 {
- name := (cast(*Code_Ident)node_src_statements[i + offset]).name;
- names[i], names_field[i] = name, sprint("_%", name);
- }
- assert(node_src_statements[captured_count + offset].kind == .PROCEDURE_HEADER);
- node_header := cast(*Code_Procedure_Header) node_src_statements[captured_count + offset];
- assert(node_src_statements[captured_count + offset + 1].kind == .BLOCK);
- node_block := cast(*Code_Block) node_src_statements[captured_count + offset + 1];
- assert(node_block.block_type == .IMPERATIVE);
- proc_node, data_node : *Code_Node;
- if gen_pair {
- proc_node = *Code_Binary_Operator.{
- kind = .BINARY_OPERATOR,
- operator_type = #char".",
- left = node_src_statements[0],
- right = *Code_Ident.{
- kind = .IDENT,
- name = "proc"
- }
- };
- data_node = *Code_Binary_Operator.{
- kind = .BINARY_OPERATOR,
- operator_type = #char".",
- left = node_src_statements[0],
- right = *Code_Ident.{
- kind = .IDENT,
- name = "data"
- }
- };
- } else {
- proc_node, data_node = node_src_statements[0], node_src_statements[1];
- }
- return proc_node, data_node, names, names_field, node_header, node_block;
-}
-gen_struct_type_node :: (names : []string, names_field : []string) -> *Code_Node #expand {
- captured_count := names.count;
- nodes_ident := NewArray(captured_count, Code_Ident);
- nodes_ptr := NewArray(captured_count, Code_Unary_Operator);
- nodes_typeof := NewArray(captured_count, Code_Size_Or_Type_Info);
- nodes_type := NewArray(captured_count, Code_Type_Instantiation);
- nodes_declaration := NewArray(captured_count, Code_Declaration);
- nodes_declaration_ptr := NewArray(captured_count, *Code_Node);
- for i : 0..captured_count-1 {
- nodes_ident[i] = .{
- kind = .IDENT,
- name = names[i]
- };
- nodes_ptr[i] = .{
- kind = .UNARY_OPERATOR,
- operator_type = #char"*",
- subexpression = *(nodes_ident[i])
- };
- nodes_typeof[i] = .{
- kind = .SIZE_OR_TYPE_INFO,
- query_kind = .TYPE_OF,
- type_of_expression = *(nodes_ptr[i])
- };
- nodes_type[i] = .{
- kind = .TYPE_INSTANTIATION,
- type_valued_expression = *(nodes_typeof[i])
- };
- nodes_declaration[i] = .{
- kind = .DECLARATION,
- name = names_field[i],
- type_inst = *(nodes_type[i])
- };
- nodes_declaration_ptr[i] = *(nodes_declaration[i]);
- }
- node_struct := Code_Struct.{
- kind = .STRUCT,
- block = *Code_Block.{
- kind = .BLOCK,
- block_type = .DATA_DECLARATIONS,
- statements = nodes_declaration_ptr
- }
- };
- return *node_struct;
-}
-//TODO better assertions
-get_lambda_pairs :: (proc_node:*Code_Node, data_node:*Code_Node, names:[]string, names_field:[]string, node_header:*Code_Procedure_Header, node_block:*Code_Block) -> pair_names:*Code_Node, pair_srcs:*Code_Node #expand {
- node_0 := gen_struct_type_node(names, names_field);
- stat_count := node_block.statements.count;
- nodes_new_statements := NewArray(stat_count + 1, *Code_Node);
- for i : 0..stat_count-1 {
- nodes_new_statements[i + 1] = node_block.statements[i];
- }
- nodes_new_statements[0] = *Code_Using.{
- kind = .USING,
- expression = *Code_Cast.{
- kind = .CAST,
- target_type = *Code_Type_Instantiation.{
- kind = .TYPE_INSTANTIATION,
- type_valued_expression = *Code_Unary_Operator.{
- kind = .UNARY_OPERATOR,
- subexpression = node_0,
- operator_type = #char"*"
- }
- },
- expression = *Code_Ident.{
- kind = .IDENT,
- name = "__data"
- }
- }
- };
- arg_count := node_header.arguments.count;
- node_new_args := NewArray(arg_count + 1, *Code_Declaration);
- for i : 0..arg_count-1 {
- node_new_args[i] = node_header.arguments[i];
- }
- node_new_args[arg_count] = *Code_Declaration.{
- kind = .DECLARATION,
- name = "__data",
- type_inst = *Code_Type_Instantiation.{
- kind = .TYPE_INSTANTIATION,
- type_valued_expression = *Code_Unary_Operator.{
- kind = .UNARY_OPERATOR,
- operator_type = #char"*",
- subexpression = *Code_Ident.{
- kind = .IDENT,
- name = "void"
- }
- }
- }
- };
- nodes_13 := NewArray(names.count, Code_Ident);
- nodes_14 := NewArray(names.count, Code_Unary_Operator);
- nodes_14_ptr := NewArray(names.count, *Code_Node);
- for i : 0..names.count-1 {
- nodes_13[i] = Code_Ident.{
- kind = .IDENT,
- name = names[i]
- };
- nodes_14[i] = Code_Unary_Operator.{
- kind = .UNARY_OPERATOR,
- subexpression = *(nodes_13[i]),
- operator_type = #char"*"
- };
- nodes_14_ptr[i] = *(nodes_14[i]);
- }
- exprs : [2]*Code_Node;
- exprs[0] = *Code_Procedure_Header.{
- kind = .PROCEDURE_HEADER,
- arguments = node_new_args,
- returns = node_header.returns,
- body_or_null = *Code_Procedure_Body.{
- kind = .PROCEDURE_BODY,
- block = *Code_Block.{
- kind = .BLOCK,
- statements = nodes_new_statements
- }
- }
- };
- exprs[1] = *Code_Unary_Operator.{
- kind = .UNARY_OPERATOR,
- operator_type = #char"*",
- subexpression = *Code_Literal.{
- kind = .LITERAL,
- value_type = .STRUCT,
- struct_literal_info = *Code_Struct_Literal_Info.{
- type_expression = *Code_Type_Instantiation.{
- kind = .TYPE_INSTANTIATION,
- type_valued_expression = node_0
- },
- arguments = nodes_14_ptr
- }
- }
- };
- _exprs : [2]Code_Comma_Separated_Argument = .[
- .{exprs[0], .NONE},
- .{exprs[1], .NONE},
- ];
- node_19 := Code_Comma_Separated_Arguments.{
- kind = .COMMA_SEPARATED_ARGUMENTS,
- arguments = _exprs
- };
- exprs2 : [2]*Code_Node;
- exprs2[0] = proc_node;
- exprs2[1] = data_node;
- _exprs2 : [2]Code_Comma_Separated_Argument = .[
- .{exprs2[0], .NONE},
- .{exprs2[1], .NONE},
- ];
-
- node_22 := Code_Comma_Separated_Arguments.{
- kind = .COMMA_SEPARATED_ARGUMENTS,
- arg = _exprs2
- };
- return *node_22, *node_19;
-}
diff --git a/kscurses/modes.jai b/kscurses/modes.jai
deleted file mode 100644
index 8c167e0..0000000
--- a/kscurses/modes.jai
+++ /dev/null
@@ -1,179 +0,0 @@
-MAX_ATTRS :: 7;
-Graphics_Mode :: struct {
- foreground : Color;
- background : Color;
- attr_flags : enum_flags u8 {
- F_BOLD :: 0x1;
- F_DIM :: 0x2;
- F_ITALIC :: 0x4;
- F_UNDERLINE :: 0x8;
- F_BLINKING :: 0x10;
- F_INVERSE :: 0x20;
- F_STRIKETHROUGH :: 0x40;
- }
- // attrs : [MAX_ATTRS]bool;
- // 0 - bold (on/off/keep)
- // 1 - dim/faint
- // 2 - italic
- // 3 - underline
- // 4 - blinking
- // 5 - inverse
- // 6 - strikethrough
- fcol256 : u8;
- bcol256 : u8;
-}
-Color :: enum u8 {
- RESET :: 0;
- DEFAULT :: 39;
- COLOR256 :: 38;
-
- BLACK :: 30;
- RED :: 31;
- GREEN :: 32;
- YELLOW :: 33;
- BLUE :: 34;
- MAGENTA :: 35;
- CYAN :: 36;
- WHITE :: 37;
-
- BRIGHT_BLACK :: 90;
- BRIGHT_RED :: 91;
- BRIGHT_GREEN :: 92;
- BRIGHT_YELLOW :: 93;
- BRIGHT_BLUE :: 94;
- BRIGHT_MAGENTA :: 95;
- BRIGHT_CYAN :: 96;
- BRIGHT_WHITE :: 97;
-}
-Attr :: enum u8 {
- BOLD :: 1;
- DIM :: 2;
- ITALIC :: 3;
- UNDERLINE :: 4;
- BLINKING :: 5;
- INVERSE :: 7;
- STRIKETHROUGH :: 9;
-
- BOLD_AND_DIM_OFF :: 22;
- ITALIC_OFF :: 23;
- UNDERLINE_OFF :: 24;
- BLINKING_OFF :: 25;
- INVERSE_OFF :: 27;
- STRIKETHROUGH_OFF :: 29;
-}
-
-make_graphics_mode :: (foreground := Color.DEFAULT, background := Color.DEFAULT, bold := false, dim := false, italic := false, underline := false, blinking := false, inverse := false, strikethrough := false, fcol256 :u8= 0, bcol256 :u8= 0) -> Graphics_Mode {
- result : Graphics_Mode;
-
- result.foreground = foreground;
- result.background = xx (background + 10);
-
- if bold result.attr_flags |= .F_BOLD;
- if dim result.attr_flags |= .F_DIM;
- if italic result.attr_flags |= .F_ITALIC;
- if underline result.attr_flags |= .F_UNDERLINE;
- if blinking result.attr_flags |= .F_BLINKING;
- if inverse result.attr_flags |= .F_INVERSE;
- if strikethrough result.attr_flags |= .F_STRIKETHROUGH;
- //========
-
- // result.attrs[0] = bold;
- // result.attrs[1] = dim;
- // result.attrs[2] = italic;
- // result.attrs[3] = underline;
- // result.attrs[4] = blinking;
- // result.attrs[5] = inverse;
- // result.attrs[6] = strikethrough;
- result.fcol256 = fcol256;
- result.bcol256 = bcol256;
-
- return result;
-}
-
-Char :: struct {
- code : u32;
- #place code;
- codes : [4]u8 = ---;
- mode : Graphics_Mode;
-}
-make_char :: (code : u32, foreground := Color.DEFAULT, background := Color.DEFAULT, bold := false, dim := false, italic := false, underline := false, blinking := false, inverse := false, strikethrough := false, fcol256 :u8= 0, bcol256 :u8= 0) -> Char {
- return .{code = code, mode = make_graphics_mode(foreground, background, bold, dim, italic, underline, blinking, inverse, strikethrough, fcol256, bcol256)};
-}
-length :: inline (c : Char) -> u8 {
- return length_code(c.code);
-}
-operator== :: (c1 : Char, c2 : Char) -> bool {
- return c1.code == c2.code && c1.mode == c2.mode;
-}
-operator== :: (m1 : Graphics_Mode, m2 : Graphics_Mode) -> bool {
- if m1.foreground != m2.foreground return false;
- if m1.background != m2.background return false;
- if m1.fcol256 != m2.fcol256 return false;
- if m1.bcol256 != m2.bcol256 return false;
- if m1.attr_flags != m2.attr_flags return false;
- return true;
-}
-
-find_best_char :: (p : Vector3, use_mix : bool) -> Char {
- cast_255 :: (x : float) -> s32 {
- return clamp(cast(s32)(x * 255 + .5), 0, 255);
- }
- return find_best_char(ivec3.{cast_255(p.x), cast_255(p.y), cast_255(p.z)}, use_mix);
-}
-find_best_char :: (p : u8vec3, use_mix : bool) -> Char {
- return find_best_char(cast_vec(s32, p), use_mix);
-}
-find_best_char :: (_p : ivec3, use_mix : bool) -> Char {
- p := _p;
- to_6level :: (x : s32) -> u8, s32 {
- a := u8.[
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 3,
- 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 5, 5, 5, 5, 5,
- ][clamp(x, 0, 255) >> 2];
- return a, s32.[0, 87, 135, 175, 215, 255][a];
- }
-
- to_6level :: (v : ivec3) -> u8vec3, ivec3, dist:int {
- i : u8vec3;
- h : ivec3;
- i.x, h.x = to_6level(v.x);
- i.y, h.y = to_6level(v.y);
- i.z, h.z = to_6level(v.z);
- w := v - h;
- return i, h, w.x * w.x + w.y * w.y + w.z * w.z;
- }
- col_code :: (v : u8vec3) -> u8 { return 16 + 36 * v.x + 6 * v.y + v.z; }
-
- b_6, b_256 := to_6level(p);
- code_00, code_25, code_50, code_75 := #run utf8(" "), #run utf8("░"), #run utf8("▒"), #run utf8("▓");
-
- result := make_char(
- code_00,
- foreground = .COLOR256,
- background = .COLOR256,
- bcol256 = col_code(b_6)
- );
-
- if use_mix {
- f_6_25, f_256_25, dist_25 := to_6level(p * 4 - b_256 * 3);
- f_6_50, f_256_50, dist_50 := to_6level(p * 2 - b_256);
- f_6_75, f_256_75, dist_75 := to_6level((p * 4 - b_256) / 3);
-
-
- if dist_25 > dist_50 then f_6_25, code_25, dist_25 = f_6_50, code_50, dist_50;
- if dist_25 > dist_75 then f_6_25, code_25, dist_25 = f_6_75, code_75, dist_75;
-
- result.code = code_25;
- result.mode.fcol256 = col_code(f_6_25);
- }
- return result;
-}
-
-#scope_file
-#import "Math"; \ No newline at end of file
diff --git a/kscurses/module.jai b/kscurses/module.jai
deleted file mode 100644
index 23c0105..0000000
--- a/kscurses/module.jai
+++ /dev/null
@@ -1,91 +0,0 @@
-#module_parameters(
- ENABLE_SIGINT := true,
- ENABLE_SIGQUIT := true,
- TICK_DURATION_MS := 1000,
- ENABLE_UI_BELL := true,
- ENABLE_UI_BLINKING := true
-);
-
-#if OS == .LINUX {
- #import "POSIX";
-}
-
-// ivec2 :: Generic_Vector(s32, 2);
-// ivec3 :: Generic_Vector(s32, 3);
-// u8vec3 :: Generic_Vector(u8, 3);
-// Ibox2 :: Generic_Box(s32, 2);
-
-// #load "../Extra_Containers/module.jai";
-// #import "Extra_Containers";
-
-
-#import "Basic"();
-#import "Process";
-#import "String";
-
-#load "io.jai";
-#load "init.jai";
-#load "events.jai";
-
-#load "vectors.jai";
-#load "modes.jai";
-#load "print.jai";
-#load "utils.jai";
-#load "canvas.jai";
-
-#load "ui/style.jai";
-#load "ui/element.jai";
-#load "ui/master.jai";
-#load "ui/links.jai";
-
-#load "ui/button.jai";
-#load "ui/group.jai";
-#load "ui/text_buf.jai";
-#load "ui/select_list.jai";
-#load "ui/parent.jai";
-#load "ui/scene_manager.jai";
-#load "ui/popup_manager.jai";
-#load "ui/line_input.jai";
-#load "ui/table.jai";
-#load "ui/scalable_group.jai";
-#load "ui/progress_bar.jai";
-
-#load "lambdas.jai";
-#load "queue.jai";
-
-// TODO:
-// remake canvas:
-// -force full refresh only after resize / init
-// maybe_resize()
-// fill_by_proc()
-// clear()
-
-
-// in resize & fill: check if size same
-// add c_print_ascii_line, c_print_ascii_line_bounded
-
-// restart_clock && multiple clocks
-
-// in set_main_scene check if root is predecessor of active element
-// stop_clock -> clock_state
-
-// module overlap check / set minimum size of terminal
-
-// make generic_vec2/3
-// make better how_to
-// add meaningfull assertion text
-// UI_Scene <- UI_Popup
-// autogrow in line_input
-// detection of the element on which rendering breaks
-// extra debug lines on top
-// group view
-// + grid / group (maybe)
-// make text u8/u32 modes in text_buf, line_input & other
-// add block_input
-// (maybe) unset_active_recursive without arguments
-// plotter
-// tree/directory view
-// push graphics mode
-
-// add windows(os) support xd
-// (August 13, 2023). Fuck it, I don't want to deal with this shit anymore.
diff --git a/kscurses/print.jai b/kscurses/print.jai
deleted file mode 100644
index a023fea..0000000
--- a/kscurses/print.jai
+++ /dev/null
@@ -1,148 +0,0 @@
-ks_bell :: () {
- bell_str : string;
- bell := 7;
- bell_str.data, bell_str.count = xx *bell, 1;
- ks_write(bell_str);
-}
-
-ui_bell :: inline () {
- #if ENABLE_UI_BELL ks_bell();
-}
-
-
-b_move_cursor :: inline (builder : *String_Builder, coord : ivec2) {
- print_to_builder(builder, "\e[%;%H", coord.y + 1, coord.x + 1);
-}
-t_move_cursor :: inline (coord : ivec2) -> string {
- return tprint("\e[%;%H", coord.y, coord.x);
-}
-ks_move_cursor :: inline (coord : ivec2) {
- ks_write(tprint("\e[%;%H", coord.y + 1, coord.x + 1));
-}
-b_cursor_set_visibility :: inline (builder : *String_Builder, $$visible : bool) {
- append(builder, ifx visible "\e[?25h" else "\e[?25l");
-}
-
-b_print :: (builder : *String_Builder, coord : ivec2, mode : Graphics_Mode, fmt : string, args : ..Any) {
- if coord != .{-1, -1} b_move_cursor(builder, coord);
- b_mode_set(builder, mode);
- print_to_builder(builder, fmt, ..args);
-}
-t_print :: (coord : ivec2, mode : Graphics_Mode, fmt : string, args : ..Any) -> string {
- builder := String_Builder.{allocator = temp};
- b_print(*builder, coord, mode, fmt, ..args);
- return builder_to_string(*builder, temp);
-}
-ks_print :: inline (coord : ivec2, mode : Graphics_Mode, fmt : string, args : ..Any) {
- ks_write(t_print(coord, mode, fmt, ..args));
-}
-
-
-b_clear_screen :: (builder : *String_Builder) {
- append(builder, "\e[2J");
-}
-t_clear_screen :: inline () -> string {
- return "\e[2J";
-}
-ks_clear_screen :: inline () {
- ks_write("\e[2J");
-}
-
-
-b_esc_m :: inline (builder : *String_Builder, $$code : int) {
- print_to_builder(builder, "\e[%m", code);
-}
-t_esc_m :: inline ($$code : int) -> string {
- return tprint("\e[%m", code);
-}
-ks_esc_m :: inline ($$code : int) {
- ks_write(t_esc_m(code));
-}
-
-
-#scope_file
-b_mode_difference :: (builder : *String_Builder, prev : Graphics_Mode, using current : Graphics_Mode) {
- printed_first := false;
- add_code :: (code : u8) #expand {
- // assert(code != xx Attr.BOLD);
- // assert(code != xx Attr.DIM);
- if printed_first {
- print_to_builder(builder, ";%", code);
- } else {
- print_to_builder(builder, "\e[%", code);
- printed_first = true;
- }
- }
- add_code_on_off :: (prev : bool, current : bool, on_code : Attr, off_code : Attr) #expand {
- if prev != current add_code(xx(ifx current on_code else off_code));
- }
- if foreground != prev.foreground || fcol256 != prev.fcol256 {
- if foreground != Color.COLOR256 {
- add_code(xx foreground);
- } else {
- add_code(38); add_code(5); add_code(xx fcol256);
- }
- }
- if background != prev.background || bcol256 != prev.bcol256 {
- if background != (Color.COLOR256 + 10) {
- add_code(xx background);
- } else {
- add_code(48); add_code(5); add_code(xx bcol256);
- }
- }
- if (prev.attr_flags & 1) != (attr_flags & 1) || (prev.attr_flags & 2) != (attr_flags & 2) {
- off0 := (prev.attr_flags & 1) && !(attr_flags & 1);
- off1 := (prev.attr_flags & 2) && !(attr_flags & 2);
- if off0 || off1 {
- add_code(xx Attr.BOLD_AND_DIM_OFF);
- if (attr_flags & 1) add_code(xx Attr.BOLD);
- if (attr_flags & 2) add_code(xx Attr.DIM);
- } else {
- if (attr_flags & 1) && !(prev.attr_flags & 1) add_code(xx Attr.BOLD);
- if (attr_flags & 2) && !(prev.attr_flags & 2) add_code(xx Attr.DIM);
- }
- }
- add_code_on_off(xx prev.attr_flags & 4, xx attr_flags & 4, .ITALIC, .ITALIC_OFF);
- add_code_on_off(xx prev.attr_flags & 8, xx attr_flags & 8, .UNDERLINE, .UNDERLINE_OFF);
- add_code_on_off(xx prev.attr_flags & 16, xx attr_flags & 16, .BLINKING, .BLINKING_OFF);
- add_code_on_off(xx prev.attr_flags & 32, xx attr_flags & 32, .INVERSE, .INVERSE_OFF);
- add_code_on_off(xx prev.attr_flags & 64, xx attr_flags & 64, .STRIKETHROUGH, .STRIKETHROUGH_OFF);
- if printed_first append(builder, "m");
-}
-#scope_export
-
-//TODO update_state := true
-b_mode_set :: (builder : *String_Builder, using mode : Graphics_Mode, update_state := true) {
- b_mode_difference(builder, terminal_state.last_mode, mode);
- if update_state terminal_state.last_mode = mode;
-}
-t_mode_set :: (mode : Graphics_Mode, update_state := true) -> string {
- builder := String_Builder.{allocator = temp};
- b_mode_set(*builder, mode, update_state);
- return builder_to_string(*builder, temp);
-}
-
-ks_mode_reset :: (update_state := true) {
- ks_write("\e[0m");
- if update_state terminal_state.last_mode = .{};
-}
-t_mode_reset :: inline (update_state := true) -> string {
- if update_state terminal_state.last_mode = .{};
- return "\e[0m";
-}
-b_mode_reset :: inline (builder : *String_Builder, update_state := true) {
- if update_state terminal_state.last_mode = .{};
- append(builder, "\e[0m");
-}
-
-b_putchar :: (builder : *String_Builder, c : Char) {
- b_mode_set(builder, c.mode);
- b_putchar(builder, c.code);
-}
-
-b_putchar :: inline (builder : *String_Builder, code : u64) {
- char_str : string;
- char_str.data = xx *(code);
- char_str.count = length_code(code);
- append(builder, char_str);
-}
diff --git a/kscurses/queue.jai b/kscurses/queue.jai
deleted file mode 100644
index 86f5dc8..0000000
--- a/kscurses/queue.jai
+++ /dev/null
@@ -1,57 +0,0 @@
-Queue :: struct(Element_Type : Type) {
- buffer : []Element_Type;
- begin, count := 0;
-}
-pop :: (using queue : *Queue($Element_Type)) -> Element_Type, bool {
- elem : Element_Type;
- ok := true;
- if count {
- elem = buffer[begin];
- begin += 1;
- count -= 1;
- } else {
- ok = false;
- }
- return elem, ok;
-}
-get_space :: (using queue : *Queue($Element_Type), new_elements_count : int) {
- if begin + count + new_elements_count <= buffer.count return;
- if count <= begin && count + new_elements_count <= buffer.count {
- memcpy(buffer.data, buffer.data + begin, size_of(Element_Type) * count);
- begin = 0;
- } else {
- new_buf := NewArray(count + max(new_elements_count, count), Element_Type);
- memcpy(new_buf.data, buffer.data + begin, count * size_of(Element_Type));
- begin = 0;
- array_free(buffer);
- buffer = new_buf;
- }
-}
-push :: (using queue : *Queue($Element_Type), element : Element_Type) {
- get_space(queue, 1);
- assert(begin + count + 1 <= buffer.count);
- buffer[begin + count] = element;
- count += 1;
-}
-deinit :: (using queue : *Queue($Element_Type)) {
- array_free(buffer);
- <<queue = .{};
-}
-for_expansion :: (queue : Queue, body : Code, flags : For_Flags) #expand {
- for i : 0..queue.count-1 {
- `it_index := i;
- `it := queue.buffer[begin + i];
-
- #insert body;
- }
-}
-first :: (queue : Queue($Element_Type)) -> Element_Type, bool {
- result : Element_Type;
- if queue.count > 0 then result = queue.buffer[queue.begin];
- return result, queue.count > 0;
-}
-last :: (using queue : Queue($Element_Type)) -> Element_Type, bool {
- result : Element_Type;
- if queue.count > 0 then result = queue.buffer[queue.begin + queue.count - 1];
- return result, queue.count > 0;
-}
diff --git a/kscurses/readme.md b/kscurses/readme.md
deleted file mode 100644
index 7a2f6fc..0000000
--- a/kscurses/readme.md
+++ /dev/null
@@ -1,43 +0,0 @@
-# kscurses
-## _Curses replacement on jai for my needs. Use at your own risk._
-
-`tested on version 0.1.073`
-
-# setup & build
-1. download extra-containers module https://github.com/CyanMARgh/extra-containers
-2. move it to your extra modules folder
-3. specify this foder on top of demos/first.jai
-4. compile first.jai
-
-Currently works only on linux (tested on gnome terminal).
-
-# features list
-- character input
-- window resize handle
-- text modifiers (bold, italic, underline, blinking, inverse, strikethrough), color256 support
-- text/background color.
-- arrows, escape key and some
-- saving and restoring the terminal
-- exit with and crtl+C (optional).
-- ui elements (empty, button, text block, selection list)
-- multiple scenes and popups support
-- events (ticks, input, window resize and user-defined events)
-- ui can work both in single-thread mode and multi-thread mode
-- 4 print modes:
-- - ks_**method** : method prints directly terminal
-- - t_**method** : method returns temporary string or string from constant data section
-- - b_**method** : method prints to builder
-- - c_**method**: method prints to canvas
-
-# demos list
-- basic print methods, canvas and graphic modes usage
-- video (now uses events and color256 approximation with semi-transparent characters)
-- shorter canvas usage
-- ui : progress bars and extra events handler
-- ui : text buffer, buttons, selection list, groups, scenes
-- ui : popup
-- ui : line input
-- events processing without default ui
-- snake minigame
-- ui : table
-- ui : scalable group and anchors
diff --git a/kscurses/ui/button.jai b/kscurses/ui/button.jai
deleted file mode 100644
index 3866e03..0000000
--- a/kscurses/ui/button.jai
+++ /dev/null
@@ -1,25 +0,0 @@
-UI_Button :: struct {
- #as using base : UI_Elem = .{type = .BUTTON};
- text := "";
- on_click : struct {
- proc := (data : *void){};
- data : *void;
- };
-}
-
-handle_key_button :: (ui_elem : *UI_Elem, key : Key) -> handled:bool {
- using cast(*UI_Button) ui_elem;
- assert(cursor_state == .ON);
- assert(!links.inner);
- if key == .ENTER {
- on_click.proc(on_click.data);
- return true;
- }
- return false;
-}
-c_draw_button :: (canvas : *Canvas, ui_elem : *UI_Elem, zone : Ibox2, style : *UI_Style) -> bool {
- using cast(*UI_Button) ui_elem;
- mode := ifx cursor_state == .ON && box_type == .NONE then style.text.cursor else style.text.default;
- c_draw_line_ascii(canvas, text, zone, .{(zone.width - xx text.count) / 2, xx ((zone.height - 1) / 2)}, mode);
- return true;
-}
diff --git a/kscurses/ui/element.jai b/kscurses/ui/element.jai
deleted file mode 100644
index 3db8fcb..0000000
--- a/kscurses/ui/element.jai
+++ /dev/null
@@ -1,156 +0,0 @@
-UI_Elem :: struct {
- type : enum u8 {
- NONE :: 0;
- BUTTON :: 1;
- TEXT_BUF :: 2;
- GROUP :: 3;
- SELECT_LIST :: 4;
- SCENE_MANAGER :: 5;
- POPUP_MANAGER :: 6;
- LINE_INPUT :: 7;
- SCALABLE_GROUP :: 8;
- TABLE :: 9;
- PROGRESS_BAR :: 10;
- } = .NONE;
-
- using visual_data : struct {
- cursor_state : enum u8 { OUTSIDE :: 0; ON :: 1; IN :: 2; } = .OUTSIDE;
- box_type : enum u8 { NONE :: 0; BORDER :: 1; NO_BORDER :: 2; } = .BORDER;
- description_pos : enum u8 { TOP_LEFT :: 0; TOP_CENTER :: 1; TOP_RIGHT :: 2; BOTTOM_LEFT :: 4; BOTTOM_CENTER :: 5; BOTTOM_RIGHT :: 6; } = .TOP_LEFT;
- description := "";
- }
-
- using links : struct {
- left, right, bottom, top, inner, outer : *UI_Elem;
- parent : *UI_Parent;
- }
-
- extra_handler : struct {
- proc : (key : Key, data : *void) -> bool = null;
- data : *void;
- }
-}
-
-
-vtable_c_draw : []#type (*Canvas, *UI_Elem, Ibox2, *UI_Style) -> (bool) = .[
- c_draw_default,
- c_draw_button,
- c_draw_textbuf,
- c_draw_group,
- c_draw_select_list,
- c_draw_scene_manager,
- c_draw_popup_manager,
- c_draw_line_input,
- c_draw_scalable_group,
- c_draw_table,
- c_draw_progress_bar
-];
-c_draw :: (canvas : *Canvas, using ui_elem : *UI_Elem, zone : Ibox2, style : *UI_Style) -> bool {
- ok := box_type == .NONE || c_box(canvas, zone, ifx cursor_state == .ON && __ui_master.blink_stage != 1 then style.box.cursor else style.box.default, box_type == .BORDER);
- if !ok return false;
- ok = c_draw_description(canvas, ui_elem, zone, style);
- if !ok return false;
-
- content_zone := ifx box_type == .BORDER then cut_border(zone, 1) else zone;
-
- c_draw_proc := vtable_c_draw[xx ui_elem.type];
- assert(xx c_draw_proc);
- return c_draw_proc(canvas, ui_elem, content_zone, style);
-}
-c_draw_default :: (canvas : *Canvas, using ui_elem : *UI_Elem, zone : Ibox2, style : *UI_Style) -> bool { return true; };
-
-intersection_line :: (box : Ibox2, _line : string, _start : ivec2) -> line:string, start:ivec2 {
- line, start := _line, _start;
- if start.x < box.left {
- line.count += start.x - box.left;
- start.x = box.left;
- }
- if start.x + line.count > box.left + box.width {
- line.count = box.left + box.width - start.x;
- }
- return line, start;
-}
-
-c_draw_line_ascii_raw :: (canvas : *Canvas, line : string, start : ivec2, mode : Graphics_Mode) {
- for x : 0..line.count-1 c_putchar(canvas, .{code = xx line[x], mode = mode}, start + ivec2.{xx x, 0});
-}
-
-c_draw_line_ascii :: (canvas : *Canvas, _line : string, _start : ivec2, mode : Graphics_Mode) {
- line, start := intersection_line(canvas.zone, _line, _start);
- c_draw_line_ascii_raw(canvas, line, start, mode);
-}
-c_draw_line_ascii :: (canvas : *Canvas, _line : string, bounds : Ibox2, offset : ivec2, mode : Graphics_Mode) {
- assert(inside(bounds, canvas.zone));
- line, start := intersection_line(bounds, _line, bounds.corner + offset);
- c_draw_line_ascii_raw(canvas, line, start, mode);
-}
-c_draw_description :: (canvas : *Canvas, using ui_elem : *UI_Elem, zone : Ibox2, style : *UI_Style) -> bool {
- if !description return true;
- if description.count > zone.width - 2 return false;
-
- top_or_bottom := !(description_pos & 4);
- y := ifx top_or_bottom then zone.top else zone.top + zone.height - 1;
-
- mode := style.text.default;
- if description_pos & 3 == {
- case 0; c_draw_line_ascii(canvas, description, .{zone.left + 1, y}, mode);
- case 1; c_draw_line_ascii(canvas, description, .{xx (zone.left + (zone.width - description.count) / 2), y}, mode);
- case 2; c_draw_line_ascii(canvas, description, .{xx (zone.left + zone.width - description.count - 1), y}, mode);
- case; assert(false);
- }
- return true;
-}
-
-vtable_handle_key : []#type (*UI_Elem, Key) -> (bool) = .[
- handle_key_none,
- handle_key_button,
- handle_key_none,
- handle_key_group,
- handle_key_select_list,
- handle_key_scene_manager,
- handle_key_popup_manager,
- handle_key_line_input,
- handle_key_scalable_group,
- handle_key_table,
- handle_key_none
-];
-handle_key :: (using ui_elem : *UI_Elem, key : Key) -> handled:bool {
- handle_proc := vtable_handle_key[ui_elem.type];
- assert(xx handle_proc);
-
- handled := handle_proc(ui_elem, key);
- // assert(cursor_state == .ON || cursor_state == .IN);
- if !handled && cursor_state == .ON {
- handled = handle_key_move(ui_elem, key);
- }
-
- if !handled && extra_handler.proc {
- handled = extra_handler.proc(key, extra_handler.data);
- }
- return handled;
-}
-handle_key_none :: (using ui_elem : *UI_Elem, key : Key) -> handled:bool { return false; }
-handle_key_move :: (using ui_elem : *UI_Elem, key : Key) -> handled:bool {
- __ui_master.blink_stage = 0;
- restart_clock_cycle();
-
- active_elem := ui_elem;
- assert(active_elem.cursor_state == .ON);
- try_move :: (new_elem : *UI_Elem) #expand {
- if new_elem {
- unset_active_recursive(`active_elem);
- set_active_recursive(new_elem);
- `active_elem = new_elem;
- }
- }
- if key == {
- case .LEFT; try_move(links.left);
- case .RIGHT; try_move(links.right);
- case .UP; try_move(links.top);
- case .DOWN; try_move(links.bottom);
- case .ESCAPE; try_move(links.outer);
- case .ENTER; try_move(links.inner);;
- }
- assert(active_elem.cursor_state == .ON);
- return ui_elem != active_elem;
-} \ No newline at end of file
diff --git a/kscurses/ui/group.jai b/kscurses/ui/group.jai
deleted file mode 100644
index 366c513..0000000
--- a/kscurses/ui/group.jai
+++ /dev/null
@@ -1,44 +0,0 @@
-UI_Group :: struct {
- #as using base_parent : UI_Parent = .{type = .GROUP};
-
- Element :: struct {
- ptr : *UI_Elem;
- zone : Ibox2;
- }
-
- elements : []Element;
-}
-set_sub_elements :: (group : *UI_Group, elements : ..UI_Group.Element) {
- group.elements = elements;
- for e : elements {
- e.ptr.parent = group;
- }
-}
-c_draw_group :: (canvas : *Canvas, ui_elem : *UI_Elem, zone : Ibox2, style : *UI_Style) -> bool {
- using cast(*UI_Group) ui_elem;
- for e : elements {
- e_zone := e.zone;
- if !inside(e_zone, zone.size) return false;
- e_zone.corner += zone.corner;
- if !c_draw(canvas, e.ptr, e_zone, style) return false;
- }
- return true;
-}
-handle_key_group :: (ui_elem : *UI_Elem, key : Key) -> handled:bool {
- using cast(*UI_Group) ui_elem;
- assert(cursor_state == .ON || cursor_state == .OUTSIDE);
-
- handled := false;
- if cursor_state == .OUTSIDE {
- assert(xx active_element);
- {
- ok := false;
- for e : elements if e.ptr == active_element ok = true;
- assert(ok);
- }
- handled = handle_key(active_element, key);
- } else {
- assert(xx !active_element);
- }
- return handled;
-} \ No newline at end of file
diff --git a/kscurses/ui/line_input.jai b/kscurses/ui/line_input.jai
deleted file mode 100644
index 17823db..0000000
--- a/kscurses/ui/line_input.jai
+++ /dev/null
@@ -1,122 +0,0 @@
-Char_Type :: u8;
-UI_Line_Input :: struct {
- #as using base : UI_Elem = .{type = .LINE_INPUT};
- buffer : []Char_Type;
-
- // resizeable := false;
- ptr_left, ptr_right : int;
- offset : int;
-}
-
-handle_key_line_input :: (ui_elem : *UI_Elem, key : Key) -> bool {
- using ui_line_input := cast(*UI_Line_Input) ui_elem;
-
- handle_inner :: (using ui_line_input : *UI_Line_Input, key : Key) -> bool {
- if is_printable(key) {
- return add_char(ui_line_input, xx key);
- } else if key == {
- case .LEFT; #through;
- case .RIGHT;
- return move_ptr(ui_line_input, key);
- case .BACKSPACE;
- return remove_char_left(ui_line_input);
- case .ESCAPE;
- cursor_state = .ON;
- return true;
- }
- return false;
- }
-
- if cursor_state == .IN {
- return handle_inner(ui_line_input, key);
- } else if cursor_state == .ON && key == .ENTER {
- cursor_state = .IN;
- return true;
- }
-
- return false;
-}
-c_draw_line_input :: (canvas : *Canvas, ui_elem : *UI_Elem, zone : Ibox2, style : *UI_Style) -> bool {
- using cast(*UI_Line_Input) ui_elem;
-
- fix_offset :: () #expand {
- if ptr_left - offset < 0 {
- offset = ptr_left;
- } else if ptr_left - offset >= zone.width {
- offset = ptr_left - zone.width + 1;
- }
- }
- fix_offset();
-
- left_part, right_part : string;
- left_part.data, left_part.count = buffer.data, ptr_left;
-
- right_part.data, right_part.count = buffer.data + ptr_right + 1, (buffer.count - ptr_right - 1);
-
- c_draw_line_ascii(canvas, left_part, zone, .{xx -offset, 0}, style.text.default);
- c_draw_line_ascii(canvas, right_part, zone, .{xx (ptr_left - offset), 0}, style.text.default);
-
- terminal_state.cursor = ifx cursor_state == .IN then zone.corner + ivec2.{xx(ptr_left - offset), 0} else .{-1, -1};
-
- return true;
-}
-
-init :: (using ui_line_input : *UI_Line_Input, max_length := 100) {
- buffer = NewArray(max_length, Char_Type);
- ptr_left, ptr_right = 0, max_length - 1;
-}
-add_char :: (using ui_line_input : *UI_Line_Input, c : Char_Type) -> bool {
- if ptr_left > ptr_right return false;
- buffer[ptr_left] = c;
- ptr_left += 1;
- return true;
-}
-remove_char_left :: (using ui_line_input : *UI_Line_Input) -> bool {
- if ptr_left == 0 return false;
- ptr_left -= 1;
- return true;
-}
-move_ptr :: (using ui_line_input : *UI_Line_Input, key : Key) -> bool {
- if key == {
- case .LEFT;
- if ptr_left > 0 {
- ptr_left -= 1;
- buffer[ptr_right] = buffer[ptr_left];
- ptr_right -= 1;
- return true;
- }
- case .RIGHT;
- if ptr_right < buffer.count-1 {
- ptr_right += 1;
- buffer[ptr_left] = buffer[ptr_right];
- ptr_left += 1;
- return true;
- }
- case;
- assert(false);
- }
- return false;
-}
-deinit :: (using ui_line_input : *UI_Line_Input) {
- array_free(buffer);
-}
-
-is_printable :: (key : Key) -> bool {
- code := cast(u64) key;
- return (code >= #char" " && code <= #char"~");
-}
-
-get_string :: (using ui_line_input : *UI_Line_Input, allocator := context.allocator) -> string {
- result : string;
- size := ptr_left + (buffer.count - ptr_right - 1);
- result.count = size;
- result.data = alloc(size, allocator);
-
- memcpy(result.data, buffer.data, ptr_left);
- memcpy(result.data + ptr_left, buffer.data + ptr_right + 1, buffer.count - ptr_right - 1);
- return result;
-}
-reset :: (using ui_line_input : *UI_Line_Input) {
- ptr_left = 0;
- ptr_right = buffer.count - 1;
-} \ No newline at end of file
diff --git a/kscurses/ui/links.jai b/kscurses/ui/links.jai
deleted file mode 100644
index dc8c667..0000000
--- a/kscurses/ui/links.jai
+++ /dev/null
@@ -1,94 +0,0 @@
-link_lr :: (el : *UI_Elem, er : *UI_Elem) {
- el.right = er;
- er.left = el;
-}
-link_tb :: (et : *UI_Elem, eb : *UI_Elem) {
- et.bottom = eb;
- eb.top = et;
-}
-link_oi :: (eo : *UI_Elem, ei : *UI_Elem) {
- eo.inner = ei;
- ei.outer = eo;
-}
-
-link_grid :: (size : ivec2, elements : ..*UI_Elem) {
- assert(size.x * size.y == elements.count);
- for y : 0..size.y-1 {
- for x : 0..size.x-2 {
- i := x + size.x * y;
- link_lr(elements[i], elements[i + 1]);
- }
- }
- for y : 0..size.y-2 {
- for x : 0..size.x-1 {
- i := x + size.x * y;
- link_tb(elements[i], elements[i + size.x]);
- }
- }
-}
-link_grid :: (size : ivec2, elements : []UI_Elem) {
- assert(size.x * size.y == elements.count);
- for y : 0..size.y-1 {
- for x : 0..size.x-2 {
- i := x + size.x * y;
- link_lr(*elements[i], *elements[i + 1]);
- }
- }
- for y : 0..size.y-2 {
- for x : 0..size.x-1 {
- i := x + size.x * y;
- link_tb(*elements[i], *elements[i + size.x]);
- }
- }
-}
-link_row :: (elements : ..*UI_Elem) {
- for i : 0..elements.count-2 {
- link_lr(elements[i], elements[i + 1]);
- }
-}
-link_column :: (elements : ..*UI_Elem) {
- for i : 0..elements.count-2 {
- link_tb(elements[i], elements[i + 1]);
- }
-}
-link_to_outer :: (eo : *UI_Elem, ei : ..*UI_Elem) {
- if ei.count > 0 {
- for ei {
- it.outer = eo;
- }
- eo.inner = ei[0];
- }
-
-}
-link_to_bottom :: (eb : *UI_Elem, et : ..*UI_Elem) {
- if et.count > 0 {
- for et {
- it.bottom = eb;
- }
- eb.top = et[0];
- }
-}
-link_to_top :: (et : *UI_Elem, eb : ..*UI_Elem) {
- if eb.count > 0 {
- for eb {
- it.top = et;
- }
- et.bottom = eb[0];
- }
-}
-link_to_right :: (er : *UI_Elem, el : ..*UI_Elem) {
- if el.count > 0 {
- for el {
- it.right = er;
- }
- er.left = el[0];
- }
-}
-link_to_left :: (el : *UI_Elem, er : ..*UI_Elem) {
- if er.count > 0 {
- for er {
- it.left = el;
- }
- el.right = er[0];
- }
-} \ No newline at end of file
diff --git a/kscurses/ui/master.jai b/kscurses/ui/master.jai
deleted file mode 100644
index 9cb0702..0000000
--- a/kscurses/ui/master.jai
+++ /dev/null
@@ -1,105 +0,0 @@
-UI_Master :: struct {
- style : UI_Style;
- canvas : Canvas;
- root : *UI_Elem;
- should_exit := false;
-
- blink_stage := 0;
-
- before_draw : struct {
- proc := (data : *void) { };
- data : *void;
- };
- extra_handle : struct {
- proc := (e : Event, data : *void) { };
- data : *void;
- };
-}
-__ui_master : UI_Master;
-
-
-set_main_scene :: (scene : UI_Scene) {
- __ui_master.root = scene.root;
- set_active_recursive(scene.entry);
-}
-run_singlethread_ui :: () {
- use_default_winch_handler();
- using __ui_master;
- while 1 {
- before_draw.proc(before_draw.data);
- if should_exit break;
- draw(*__ui_master);
- reset_temporary_storage();
- handle_key(*__ui_master, ks_getch(block = false));
- if should_exit break;
- }
- deinit(*__ui_master);
-}
-run_multithread_ui :: () {
- use_events(tick_duration_ms = 530);
- __event_handler = .{
- proc = (e : Event, __data : *void) {
- using __ui_master;
- if e.type == {
- case .KEY;
- handle_key(*__ui_master, e.key);
- case .TICK;
- #if ENABLE_UI_BLINKING __ui_master.blink_stage = xx !__ui_master.blink_stage;
- }
- extra_handle.proc(e, extra_handle.data);
- },
- data = null
- }; defer __event_handler = .{};
-
- using __ui_master;
-
- while 1 {
- before_draw.proc(before_draw.data);
- if should_exit break;
- processed := wait_and_process_events();
- if should_exit break;
- if processed {
- draw(*__ui_master);
- reset_temporary_storage();
- }
- }
- deinit(*__ui_master);
-}
-
-#scope_file
-draw :: (using ui_master : *UI_Master) {
- new_zone := Ibox2.{size = terminal_state.size};
- builder : String_Builder;
-
- if new_zone != canvas.zone {
- resize_clear(*canvas, new_zone);
- }
- ok := c_draw(*canvas, root, canvas.zone, *style);
- if ok {
- ks_draw_canvas(*canvas);
- } else {
- b_mode_set(*builder, style.text.default);
- b_clear_screen(*builder);
- b_print(*builder, .{0, 0}, style.text.debug, "screen to small: %x%", terminal_state.size.x, terminal_state.size.y);
- }
- b_cursor_set_visibility(*builder, terminal_state.cursor != ivec2.{-1, -1});
- if terminal_state.cursor != ivec2.{-1, -1} then b_move_cursor(*builder, terminal_state.cursor);
-
- ks_write(builder_to_string(*builder, allocator = temp));
-}
-handle_key :: (using ui_master : *UI_Master, key : Key) {
- handled := handle_key(root, key);
- if handled return;
-
- if key == {
- case .ESCAPE; {
- should_exit = true;
- unset_active_recursive(__last_set);
- }
- case; if key != .READ_ERROR ui_bell();
- }
-}
-deinit :: (using ui_master : *UI_Master) {
- deinit(*canvas);
- __ui_master = .{};
-} \ No newline at end of file
diff --git a/kscurses/ui/parent.jai b/kscurses/ui/parent.jai
deleted file mode 100644
index af459de..0000000
--- a/kscurses/ui/parent.jai
+++ /dev/null
@@ -1,33 +0,0 @@
-UI_Parent :: struct {
- #as using base : UI_Elem;
- active_element : *UI_Elem;
-}
-
-__last_set : *UI_Elem;
-
-set_active_recursive :: (ui_elem : *UI_Elem) {
- assert(!__last_set); __last_set = ui_elem;
- assert(ui_elem.cursor_state == .OUTSIDE); ui_elem.cursor_state = .ON;
-
- current := ui_elem;
- while 1 {
- parent := current.parent;
- if !parent break;
- assert(!parent.active_element);
- parent.active_element = current;
- current = xx parent;
- }
-}
-unset_active_recursive :: (ui_elem : *UI_Elem) {
- assert(__last_set == ui_elem); __last_set = null;
- assert(ui_elem.cursor_state == .ON); ui_elem.cursor_state = .OUTSIDE;
-
- current := ui_elem;
- while 1 {
- parent := current.parent;
- if !parent break;
- assert(parent.active_element == current);
- parent.active_element = null;
- current = xx parent;
- }
-} \ No newline at end of file
diff --git a/kscurses/ui/popup_manager.jai b/kscurses/ui/popup_manager.jai
deleted file mode 100644
index 704ad49..0000000
--- a/kscurses/ui/popup_manager.jai
+++ /dev/null
@@ -1,65 +0,0 @@
-MAX_POPUP_LEVES :: 10;
-
-UI_Popup_Manager :: struct {
- #as using base_parent : UI_Parent = .{type = .POPUP_MANAGER, box_type = .NONE};
-
- layers : [MAX_POPUP_LEVES]UI_Popup;
-
- layers_count := 0;
-}
-
-set_background :: (using ui_popup_manager : *UI_Popup_Manager, scene : UI_Scene) {
- assert(layers_count == 0);
- layers[0] = .{root = scene.root, entry = scene.entry};
- scene.root.parent = xx ui_popup_manager;
- layers_count = 1;
-}
-
-handle_key_popup_manager :: (ui_elem : *UI_Elem, key : Key) -> handled:bool {
- using ui_popup_manager := cast(*UI_Popup_Manager) ui_elem;
- assert(layers_count > 0, "0 layers in popup manager");
- if !handle_key(active_element, key) {
- if key == .ESCAPE && layers_count > 1 {
- pop(ui_popup_manager);
- return true;
- } else {
- return false;
- }
- } else {
- return true;
- }
-}
-
-c_draw_popup_manager :: (canvas : *Canvas, ui_elem : *UI_Elem, zone : Ibox2, style : *UI_Style) -> bool {
- using ui_popup_manager := cast(*UI_Popup_Manager) ui_elem;
- assert(layers_count > 0, "0 layers in popup manager");
- for i : 0..layers_count-1 {
- popup_zone := zone;
- ok : bool;
- if layers[i].size != .{-1, -1} then {
- popup_zone, ok = fit_in_center(zone, layers[i].size);
- if !ok return false;
- }
- if !c_draw(canvas, layers[i].root, popup_zone, style) return false;
- }
- return true;
-}
-
-pop :: (using ui_popup_manager : *UI_Popup_Manager) {
- assert(layers_count > 1, "can't pop background");
- layers_count -= 1;
- unset_active_recursive(__last_set);
- layers[layers_count].root.parent = null;
- set_active_recursive(layers[layers_count - 1].entry);
-
-}
-push :: (using ui_popup_manager : *UI_Popup_Manager, scene : UI_Popup) {
- assert(layers_count < MAX_POPUP_LEVES, "too much popup layers");
- unset_active_recursive(__last_set);
-
- layers[layers_count] = scene;
- scene.root.parent = xx ui_popup_manager;
- set_active_recursive(layers[layers_count].entry);
-
- layers_count += 1;
-} \ No newline at end of file
diff --git a/kscurses/ui/progress_bar.jai b/kscurses/ui/progress_bar.jai
deleted file mode 100644
index 23d7dc9..0000000
--- a/kscurses/ui/progress_bar.jai
+++ /dev/null
@@ -1,37 +0,0 @@
-UI_Progress_Bar :: struct {
- #as using base : UI_Elem = .{type = .PROGRESS_BAR};
-
- value : float;
- value_ptr : *float;
-
- draw_proc := (percent : float, pix_coord : float) -> Vector3 { return ifx pix_coord < percent then Vector3.{0, 1, 0} else .{0, 0, 0}; }
- show_percent := true;
-}
-
-set_value :: (progress_bar : *UI_Progress_Bar, value : float) {
- progress_bar.value = value;
- progress_bar.value_ptr = null;
-}
-set_value_ptr :: (progress_bar : *UI_Progress_Bar, value_ptr : *float) {
- progress_bar.value_ptr = value_ptr;
-}
-
-c_draw_progress_bar :: (canvas : *Canvas, ui_elem : *UI_Elem, _zone : Ibox2, style : *UI_Style) -> bool {
- using progress_bar := cast(*UI_Progress_Bar) ui_elem;
- value_current := ifx value_ptr then <<value_ptr else value;
- zone := _zone;
- if zone.width < 6 return false;
- if show_percent {
- percent_str := tprint("%1%%", formatFloat(value_current * 100, width = 4, trailing_width = 1, zero_removal = .NO));
- c_draw_line_ascii(canvas, percent_str, zone, .{zone.width - 5, zone.height / 2}, style.text.default);
- zone.width -= 5;
- }
- for x : 0..zone.width-1 {
- pix_coord := (x + .5) / zone.width;
- char := find_best_char(draw_proc(value_current, pix_coord), true);
- for y : 0..zone.height-1 {
- c_putchar(canvas, char, zone.corner + ivec2.{x, y});
- }
- }
- return true;
-}
diff --git a/kscurses/ui/scalable_group.jai b/kscurses/ui/scalable_group.jai
deleted file mode 100644
index 6c12bcc..0000000
--- a/kscurses/ui/scalable_group.jai
+++ /dev/null
@@ -1,88 +0,0 @@
-UI_Scalable_Group :: struct {
- #as using base_parent : UI_Parent = .{type = .SCALABLE_GROUP};
-
- Scale_Params :: struct {
- // using metrics : struct {
- x1, y1, x2, y2 : s32;
- #place x1; v1 : ivec2;
- #place x2; v2 : ivec2;
- // };
- scale_mode : enum u8 {
- ANCHOR_TL :: 0; // v1 - size, v2 - offset from corner (both positive)
- ANCHOR_TR :: 1;
- ANCHOR_BL :: 2;
- ANCHOR_BR :: 3;
-
- STRETCH_T :: 4; // x1/2 - left/right offset, y1 - top offset, y2 - height
- STRETCH_B :: 5; // x1/2 - left/right offset, y1 - bottom offset, y2 - height
- STRETCH_L :: 6; // y1/2 - top/bottom offset, x1 - left offset, x2 - width
- STRETCH_R :: 7; // y1/2 - top/bottom offset, x1 - right offset, x2 - width
-
- STRETCH_C :: 8; // v1 - top-left offset, v2 - bottom-right offset
- CENTERIZE :: 9; // v1 - size, v2 - offset from center(signed)
-
- FIT_EXACT :: 10; //TODO
- FIT_ROUGH :: 11;
- } = .ANCHOR_TL;
- }
-
- Element :: struct {
- ptr : *UI_Elem;
- scale_params : Scale_Params;
- }
-
- elements : []Element;
-}
-
-get_zone :: (using zone : Ibox2, using scale_params : UI_Scalable_Group.Scale_Params) -> Ibox2 {
- if scale_mode == {
- case .ANCHOR_TL; return .{corner = corner + v2, size = v1};
- case .ANCHOR_TR; return .{corner = .{left + width - x2 - x1, top + y2}, size = v1};
- case .ANCHOR_BL; return .{corner = .{left + x2, top + height - y2 - y1}, size = v1};
- case .ANCHOR_BR; return .{corner = .{left + width - x2 - x1, top + height - y2 - y1}, size = v1};
-
- case .STRETCH_T; return .{corner = .{left + x1, top + y1}, size = .{width - x1 - x2, y2}};
- case .STRETCH_B; return .{corner = .{left + x1, top + height - y1 - y2}, size = .{width - x1 - x2, y2}};
- case .STRETCH_L; return .{corner = .{left + x1, top + y1}, size = .{x2, height - y1 - y2}};
- case .STRETCH_R; return .{corner = .{left + width - x1 - x2, top + y1}, size = .{x2, height - y1 - y2}};
-
- case .STRETCH_C; return .{corner = corner + v1, size = size - v1 - v2};
- case .CENTERIZE; return .{corner = corner + (size - v1) / 2 + v2 , size = v1};
- }
- assert(false);
- return .{};
-}
-
-set_sub_elements :: (group : *UI_Scalable_Group, elements : ..UI_Scalable_Group.Element) {
- group.elements = elements;
- for e : elements {
- e.ptr.parent = group;
- }
-}
-c_draw_scalable_group :: (canvas : *Canvas, ui_elem : *UI_Elem, zone : Ibox2, style : *UI_Style) -> bool {
- using cast(*UI_Scalable_Group) ui_elem;
- for e : elements {
- e_zone := get_zone(zone, e.scale_params);
- if !inside(e_zone, zone) return false;
- if !c_draw(canvas, e.ptr, e_zone, style) return false;
- }
- return true;
-}
-handle_key_scalable_group :: (ui_elem : *UI_Elem, key : Key) -> handled:bool {
- using cast(*UI_Scalable_Group) ui_elem;
- assert(cursor_state == .ON || cursor_state == .OUTSIDE);
-
- handled := false;
- if cursor_state == .OUTSIDE {
- assert(xx active_element);
- {
- ok := false;
- for e : elements if e.ptr == active_element ok = true;
- assert(ok);
- }
- handled = handle_key(active_element, key);
- } else {
- assert(xx !active_element);
- }
- return handled;
-} \ No newline at end of file
diff --git a/kscurses/ui/scene_manager.jai b/kscurses/ui/scene_manager.jai
deleted file mode 100644
index 1caff8b..0000000
--- a/kscurses/ui/scene_manager.jai
+++ /dev/null
@@ -1,48 +0,0 @@
-UI_Scene :: struct {
- root : *UI_Elem;
- entry : *UI_Elem;
-}
-UI_Popup :: struct {
- root : *UI_Elem;
- entry : *UI_Elem;
- size : ivec2 = .{-1, -1};
-}
-
-UI_Scene_Manager :: struct {
- #as using base_parent : UI_Parent = .{type = .SCENE_MANAGER, box_type = .NONE};
- scenes : []UI_Scene;
-}
-
-set_sub_elements :: (ui_scene_manager : *UI_Scene_Manager, scenes : ..UI_Scene) {
- ui_scene_manager.scenes = scenes;
- for ui_scene_manager.scenes it.root.parent = ui_scene_manager;
-}
-
-handle_key_scene_manager :: (ui_elem : *UI_Elem, key : Key) -> handled:bool {
- using cast(*UI_Scene_Manager) ui_elem;
- assert(cursor_state == .ON || cursor_state == .OUTSIDE);
-
- handled := false;
- if cursor_state == .OUTSIDE {
- assert(xx active_element);
- {
- ok := false;
- for s : scenes if s.root == active_element ok = true;
- assert(ok);
- }
- handled = handle_key(active_element, key);
- } else {
- assert(xx !active_element);
- }
- return handled;
-}
-
-c_draw_scene_manager :: (canvas : *Canvas, ui_elem : *UI_Elem, zone : Ibox2, style : *UI_Style) -> bool {
- using cast(*UI_Scene_Manager) ui_elem;
- return c_draw(canvas, active_element, zone, style);
-}
-
-switch_scene :: (using ui_scene_manager : *UI_Scene_Manager, id : int) {
- unset_active_recursive(__last_set);
- set_active_recursive(scenes[id].entry);
-}
diff --git a/kscurses/ui/select_list.jai b/kscurses/ui/select_list.jai
deleted file mode 100644
index 8c338c6..0000000
--- a/kscurses/ui/select_list.jai
+++ /dev/null
@@ -1,79 +0,0 @@
-UI_Select_List :: struct {
- #as using base : UI_Elem = .{type = .SELECT_LIST};
- only_one := true;
- options : []string;
- selected : []bool;
-
- selected_id := -1;
- cursor, offset := 0, 0;
-
- prefix_default := "[ ]";
- prefix_selected := "[+]";
-}
-handle_key_select_list :: (ui_elem : *UI_Elem, key : Key) -> handled:bool {
- using cast(*UI_Select_List) ui_elem;
- assert(cursor_state != .OUTSIDE);
- if cursor_state == .ON {
- if key == .ENTER {
- cursor_state = .IN;
- return true;
- }
- } else {
- if key == {
- case .DOWN;
- if cursor < options.count - 1 then cursor += 1;
- case .UP;
- if cursor > 0 then cursor -= 1;
- case .ESCAPE;
- cursor_state = .ON;
- case .ENTER;
- if only_one {
- if cursor == selected_id {
- selected_id = -1;
- } else {
- selected_id = cursor;
- }
- } else {
- selected[cursor] ^= true;
- }
- case;
- return false;
- }
- return true;
- }
- return false;
-}
-init :: (select_list : *UI_Select_List, only_one := true) {
- select_list.only_one = only_one;
- if !only_one select_list.selected = NewArray(select_list.options.count, bool);
-}
-deinit :: (using select_list : *UI_Select_List) {
- array_free(selected);
-}
-c_draw_select_list :: (canvas : *Canvas, ui_elem : *UI_Elem, zone : Ibox2, style : *UI_Style) -> bool {
- using cast(*UI_Select_List) ui_elem;
- rows := min(cast(int) zone.height, options.count - offset);
-
- fix_offset :: () #expand {
- if cursor - offset < 0 {
- offset = cursor;
- } else if cursor - offset >= zone.height {
- offset = cursor - zone.height + 1;
- }
- }
- fix_offset();
-
- for y : 0..rows-1 {
- i := y + offset;
- is_selected := ifx only_one then i == selected_id else selected[i];
- prefix := ifx is_selected then prefix_selected else prefix_default;
- mode := ifx i == cursor && cursor_state == .IN
- ifx is_selected style.text.cursor_and_selection else style.text.cursor
- else
- ifx is_selected style.text.selection else style.text.default;
-
- c_draw_line_ascii(canvas, prefix, zone, .{0, xx y}, mode);
- c_draw_line_ascii(canvas, options[i], zone, .{xx prefix.count, xx y}, mode);
- }
- return true;
-} \ No newline at end of file
diff --git a/kscurses/ui/style.jai b/kscurses/ui/style.jai
deleted file mode 100644
index 4715860..0000000
--- a/kscurses/ui/style.jai
+++ /dev/null
@@ -1,118 +0,0 @@
-mode_black_and_white :: #run make_graphics_mode(foreground = .BRIGHT_WHITE, background = .BLACK);
-
-Box_Style :: struct {
- c, tb, lr, tl, tr, bl, br, tbl, tbr, tlr, blr, tblr : u32;
- mode_border, mode_space, mode_no_border := mode_black_and_white;
-}
-
-box_style_active :: Box_Style.{
- c = #run utf8(" "),
- tb = #run utf8("║"),
- lr = #run utf8("═"),
- tl = #run utf8("╝"),
- tr = #run utf8("╚"),
- bl = #run utf8("╗"),
- br = #run utf8("╔"),
- tbl = #run utf8("╣"),
- tbr = #run utf8("╠"),
- tlr = #run utf8("╩"),
- blr = #run utf8("╦"),
- tblr = #run utf8("╬"),
- mode_no_border = #run make_graphics_mode(foreground = .BRIGHT_WHITE, background = .BRIGHT_BLACK)
-};
-box_style_passive :: Box_Style.{
- c = #run utf8(" "),
- tb = #run utf8("│"),
- lr = #run utf8("─"),
- tl = #run utf8("┘"),
- tr = #run utf8("└"),
- bl = #run utf8("┐"),
- br = #run utf8("┌"),
- tbl = #run utf8("┤"),
- tbr = #run utf8("├"),
- tlr = #run utf8("┴"),
- blr = #run utf8("┬"),
- tblr = #run utf8("┼")
-};
-
-UI_Style :: struct {
- box : struct {
- default := box_style_passive;
- cursor := box_style_active;
- }
-
- mode_main := mode_black_and_white;
-
- text : struct {
- default := mode_black_and_white;
- cursor := #run make_graphics_mode(background = .BRIGHT_BLACK);
- selection := #run make_graphics_mode(background = .YELLOW);
- cursor_and_selection := #run make_graphics_mode(background = .BRIGHT_YELLOW);
-
- debug := #run make_graphics_mode(foreground = .BLACK, background = .BRIGHT_GREEN);
- }
-}
-
-c_box :: (canvas : *Canvas, zone : Ibox2, using box_style : Box_Style, border := true) -> bool {
- if !inside(ifx border then ivec2.{2, 2} else ivec2.{0, 0}, zone.size) return false;
- assert(inside(zone, canvas.zone));
- charset : [9]u32;
- if border {
- charset[0], charset[1], charset[2], charset[3], charset[4], charset[5], charset[6], charset[7], charset[8] = br, lr, bl, tb, c, tb, tr, lr, tl;
- } else {
- charset[0], charset[1], charset[2], charset[3], charset[4], charset[5], charset[6], charset[7], charset[8] = c, c, c, c, c, c, c, c, c;
- }
-
- for y : 0..zone.height-1 {
- yi := ifx y == 0 then 0 else ifx y == zone.height - 1 then 2 else 1;
- for x : 0..zone.width-1 {
- xi := ifx x == 0 then 0 else ifx x == zone.width - 1 then 2 else 1;
- i := yi * 3 + xi;
- c_putchar(canvas, .{code = charset[i], mode = mode_border}, zone.corner + ivec2.{xx x, xx y});
- }
- }
- return true;
-}
-
-b_box :: (builder : *String_Builder, zone : Ibox2, using charset := box_style_passive, mode := Graphics_Mode.{}, clear_center := true, border := true) {
- //assert(inside(zone, terminal_state.size));
-
- charset : [9]u32;
- if border {
- charset = .[br, lr, bl, tb, c, tb, tr, lr, tl];
- } else {
- charset = .[c, c, c, c, c, c, c, c, c];
- }
-
- b_move_cursor(builder, zone.corner);
- b_mode_set(builder, mode);
-
- for y : 0..zone.height-1 {
- yi := ifx y == 0 then 0 else ifx y == zone.height - 1 then 2 else 1;
- b_move_cursor(builder, .{zone.corner.x, zone.corner.y + y});
-
- if !clear_center && yi == 1 {
- b_putchar(builder, charset[3]);
- b_move_cursor(builder, .{zone.corner.x + zone.width - 1, zone.corner.y + y});
- b_putchar(builder, charset[5]);
- } else {
- for x : 0..zone.width-1 {
- xi := ifx x == 0 then 0 else ifx x == zone.width - 1 then 2 else 1;
- i := yi * 3 + xi;
- b_putchar(builder, charset[i]);
- }
- }
-
- }
-}
-t_box :: (zone : Ibox2, charset := box_style_passive, clear_center := false) -> string {
- builder := String_Builder.{allocator=temp};
- b_box(*builder, zone, charset, make_graphics_mode(), clear_center);
- return builder_to_string(*builder, temp);
-}
-ks_box :: (zone : Ibox2, charset := box_style_passive, clear_center := false) {
- ks_write(t_box(zone, charset, clear_center));
-}
-
-
-
diff --git a/kscurses/ui/table.jai b/kscurses/ui/table.jai
deleted file mode 100644
index dadc1c3..0000000
--- a/kscurses/ui/table.jai
+++ /dev/null
@@ -1,87 +0,0 @@
-UI_Table :: struct {
- #as using base : UI_Elem = .{type = .TABLE};
-
- // auto_scale := false;
- // metrics : []int;
- columns := 0;
- rows := 0;
-
- // description : []string;
- content : [..]string;
-
- cursor, offset := 0;
- show_cursor := false;
-}
-
-handle_key_table :: (ui_elem : *UI_Elem, key : Key) -> handled:bool {
- return false;
-}
-
-c_draw_table_content :: (canvas : *Canvas, using ui_table : *UI_Table, zone : Ibox2, style : *UI_Style, rows_visible : int) -> bool {
- for y : 0..zone.height-1 {
- is_selected := y == cursor && show_cursor;
- mode := ifx is_selected then style.text.selection else style.text.default;
- separator_char := Char.{code = style.box.default.tb, mode = mode};
-
- if zone.width < columns {
- for x : 0..zone.width {
- c_putchar(canvas, separator_char, zone.corner + ivec2.{xx x, xx y});
- }
- } else {
- i := y + offset;
- for x : 0..columns-1 {
- l := (zone.width + 1) * x / columns;
- r := (zone.width + 1) * (x + 1) / columns - 1;
- if y < rows_visible {
- field_content := content[i * columns + x];
- field_content.count = min(field_content.count, r - l);
- c_draw_line_ascii(canvas, field_content, zone, .{xx l, xx y}, mode);
- }
- if x != columns-1 c_putchar(canvas, separator_char, zone.corner + ivec2.{xx r, xx y});
- }
- }
- }
- return true;
-}
-
-c_draw_table :: (canvas : *Canvas, ui_elem : *UI_Elem, zone : Ibox2, style : *UI_Style) -> bool {
- using ui_table := cast(*UI_Table) ui_elem;
- assert(rows * columns == content.count);
-
- rows_visible := min(cast(int) zone.height, rows - offset);
-
- fix_offset :: () #expand {
- if cursor - offset < 0 {
- offset = cursor;
- } else if cursor - offset >= zone.height {
- offset = cursor - zone.height + 1;
- }
- }
- fix_offset();
-
- ok := c_draw_table_content(canvas, ui_table, zone, style, rows_visible);
- return ok;
-}
-init :: (table : *UI_Table, description : []string) {
- table.columns = description.count;
- table.description = description;
-}
-init :: (table : *UI_Table, columns : int) {
- table.columns = columns;
-}
-
-add_line :: (using table : *UI_Table, line : ..string) {
- assert(line.count == columns);
- array_add(*content, ..line);
- rows += 1;
-}
-deinit :: (using table : *UI_Table) {
- array_free(content);
-}
-
-// TODO
-// variadic columns count, different content types
-// empty separator
-// automatic scale, as option
-// description
-// align content left/right/center \ No newline at end of file
diff --git a/kscurses/ui/text_buf.jai b/kscurses/ui/text_buf.jai
deleted file mode 100644
index 689bb98..0000000
--- a/kscurses/ui/text_buf.jai
+++ /dev/null
@@ -1,15 +0,0 @@
-UI_Text_Buf :: struct {
- #as using base : UI_Elem = .{type = .TEXT_BUF};
- lines : []string;
- lines_dynamic : *[]string;
-}
-c_draw_textbuf :: (canvas : *Canvas, ui_elem : *UI_Elem, zone : Ibox2, style : *UI_Style) -> bool {
- using cast(*UI_Text_Buf) ui_elem;
-
- lines_to_draw := ifx lines_dynamic then <<lines_dynamic else lines;
- for l, y : lines_to_draw {
- if y >= zone.height break;
- c_draw_line_ascii(canvas, l, zone, .{0, xx y}, style.text.default);
- }
- return true;
-}
diff --git a/kscurses/ui/tilemap.jai b/kscurses/ui/tilemap.jai
deleted file mode 100644
index 73f96e5..0000000
--- a/kscurses/ui/tilemap.jai
+++ /dev/null
@@ -1,20 +0,0 @@
-UI_Tilemap :: struct {
- #as using base : UI_Elem = .{type = .TILEMAP};
-
- map_size : ivec2;
- map : []u64;
- tileset : *Tileset;
-
- background : Char; // if not set, then box's filler instead
-}
-Tileset :: struct {
- tile_size : ivec2;
- tiles_count : int;
- data : []Char;
- // code = 0 -> skip entire character
- // fcol/bcol = .DEFAULT -> skip foreground/background
-}
-c_draw_tile :: (canvas : *Canvas, tileset : *Tileset, offset : ivec2, id : u64, cutoff : Ibox2) {
-
-}
-
diff --git a/kscurses/utils.jai b/kscurses/utils.jai
deleted file mode 100644
index 2b88e85..0000000
--- a/kscurses/utils.jai
+++ /dev/null
@@ -1,53 +0,0 @@
-// array_slice :: (array : []$T, left : int, right : int) -> []T {
-// assert(left <= right && left >= 0 && right <= array.count);
-// result : []T;
-// result.data, result.count = array.data + left, right - left;
-// return result;
-// }
-
-length_code :: inline (c : u64) -> u8 {
- for 0..7 {
- if !c return xx it;
- c >>= 8;
- }
- return 8;
-}
-utf8 :: (str : string) -> u32 {
- code : u32;
- assert(str.count <= 4);
- memcpy(*code, str.data, str.count);
- return code;
-}
-byteswap_64 :: (c : u64) -> u64 {
- c = ((0xFFFFFFFF00000000 & c) >> 32) | ((0x00000000FFFFFFFF & c) << 32);
- c = ((0xFFFF0000FFFF0000 & c) >> 16) | ((0x0000FFFF0000FFFF & c) << 16);
- c = ((0xFF00FF00FF00FF00 & c) >> 8) | ((0x00FF00FF00FF00FF & c) << 8);
- return c;
-}
-byteswap_32 :: (c : u32) -> u32 {
- c = ((0xFFFF0000 & c) >> 16) | ((0x0000FFFF & c) << 16);
- c = ((0xFF00FF00 & c) >> 8) | ((0x00FF00FF & c) << 8);
- return c;
-}
-char_bs :: (code : u32) -> u32 {
- l := length_code(code);
- return byteswap_32(code) >> ((8 - l) * 8);
-}
-utf8_bs :: (str : string) -> u32 {
- return char_bs(utf8(str));
-}
-arrow_code_to_ivec2 :: (key : Key, $swap_y := true) -> ivec2 {
- #if swap_y {
- return ifx key == .UP ivec2.{ 0, -1}
- else ifx key == .RIGHT ivec2.{ 1, 0}
- else ifx key == .DOWN ivec2.{ 0, 1}
- else ifx key == .LEFT ivec2.{-1, 0}
- else ivec2.{};
- } else {
- return ifx key == .UP ivec2.{ 0, 1}
- else ifx key == .RIGHT ivec2.{ 1, 0}
- else ifx key == .DOWN ivec2.{ 0, -1}
- else ifx key == .LEFT ivec2.{-1, 0}
- else ivec2.{};
- }
-}
diff --git a/kscurses/vectors.jai b/kscurses/vectors.jai
deleted file mode 100644
index f27d572..0000000
--- a/kscurses/vectors.jai
+++ /dev/null
@@ -1,210 +0,0 @@
-Generic_Vector :: struct(type : Type, N : int) {
- #assert N > 1;
- #if N < 5 {
- x, y : type;
- #if N > 2 {
- z : type;
- #place x; xy : Generic_Vector(type, 2);
- #place y; yz : Generic_Vector(type, 2);
- #place x; r : type;
- #place y; g : type;
- #place z; b : type;
- }
- #if N > 3 {
- w : type;
- #place z; zw : Generic_Vector(type, 2);
- #place x; xyz : Generic_Vector(type, 3);
- #place y; yzw : Generic_Vector(type, 3);
- #place w; a : type;
- }
- #place x;
- }
- values : [N]type;
-}
-generic_vector_binary_proc_vv :: (v1 : Generic_Vector($type, $N), v2 : Generic_Vector(type, N), proc : (s1 : type, s2 : type) -> (type)) -> Generic_Vector(type, N) {
- result : Generic_Vector(type, N) = ---;
- for i : 0..N-1 result.values[i] = proc(v1.values[i], v2.values[i]);
- return result;
-}
-generic_vector_binary_proc_vs :: (v : Generic_Vector($type, $N), s : type, proc : (s1 : type, s2 : type) -> (type)) -> Generic_Vector(type, N) {
- result : Generic_Vector(type, N) = ---;
- for i : 0..N-1 result.values[i] = proc(v.values[i], s);
- return result;
-}
-generic_vector_binary_proc_sv :: (s : type, v : Generic_Vector($type, $N), proc : (s1 : type, s2 : type) -> (type)) -> Generic_Vector(type, N) {
- result : Generic_Vector(type, N) = ---;
- for i : 0..N-1 result.values[i] = proc(s, v.values[i]);
- return result;
-}
-generic_vector_unary_proc :: (v : Generic_Vector($type, $N), proc : (s : type) -> (type)) -> Generic_Vector(type, N) {
- result : Generic_Vector(type, N) = ---;
- for i : 0..N-1 result.values[i] = proc(v.values[i]);
- return result;
-}
-
-operator- :: #bake_arguments generic_vector_unary_proc(proc = (s) => -s);
-
-operator+ :: #bake_arguments generic_vector_binary_proc_vv(proc = (s1, s2) => s1 + s2);
-operator- :: #bake_arguments generic_vector_binary_proc_vv(proc = (s1, s2) => s1 - s2);
-operator/ :: #bake_arguments generic_vector_binary_proc_vv(proc = (s1, s2) => s1 / s2);
-operator* :: #bake_arguments generic_vector_binary_proc_vv(proc = (s1, s2) => s1 * s2);
-
-operator+ :: #bake_arguments generic_vector_binary_proc_sv(proc = (s1, s2) => s1 + s2);
-operator- :: #bake_arguments generic_vector_binary_proc_sv(proc = (s1, s2) => s1 - s2);
-operator/ :: #bake_arguments generic_vector_binary_proc_sv(proc = (s1, s2) => s1 / s2);
-operator* :: #bake_arguments generic_vector_binary_proc_sv(proc = (s1, s2) => s1 * s2);
-
-operator+ :: #bake_arguments generic_vector_binary_proc_vs(proc = (s1, s2) => s1 + s2);
-operator- :: #bake_arguments generic_vector_binary_proc_vs(proc = (s1, s2) => s1 - s2);
-operator/ :: #bake_arguments generic_vector_binary_proc_vs(proc = (s1, s2) => s1 / s2);
-operator* :: #bake_arguments generic_vector_binary_proc_vs(proc = (s1, s2) => s1 * s2);
-
-operator== :: (v1 : Generic_Vector($type, $N), v2 : Generic_Vector(type, N)) -> bool {
- for i : 0..N-1 {
- if v1.values[i] != v2.values[i] return false;
- }
- return true;
-}
-
-// affects only on naming
-Generic_Box :: struct(type : Type, N : int, left_handed := false) {
- #assert N > 1;
- #if N <= 3 {
- width, height : type;
- #if N == 3 { length : type; }
-
- #if left_handed { right : type; } else { left : type; }
- top : type;
- #if N == 3 { front : type; }
- #place width;
- }
- size, corner : Generic_Vector(type, N);
-}
-operator== :: (a : Generic_Box($type, $N, $left_handed), b : Generic_Box(type, N, left_handed)) -> bool {
- return a.size == b.size && a.corner == b.corner;
-}
-is_empty :: (box : Generic_Box) -> bool {
- return box.size == .{0, 0};
-}
-is_invalid :: (box : Generic_Box) -> bool {
- return box.width < 0 || box.height < 0;
-}
-point_inside :: (point : Generic_Vector($type, $N), zone : Generic_Box(type, N)) -> bool {
- for i : 0..N-1 {
- p, l, w := point.values[i], zone.corner.values[i], zone.size.values[i];
- if p < l return false;
- if p > l + w return false;
- }
- return true;
-}
-inside :: (inner : Generic_Box($type, $N, $left_handed), outer : Generic_Box(type, N, left_handed)) -> bool {
- return point_inside(inner.corner, outer) && point_inside(inner.corner + inner.size, outer);
-}
-inside :: (inner : Generic_Box($type, $N, $left_handed), outer : Generic_Vector(type, N)) -> bool {
- return inside(inner, Generic_Box(type, N, left_handed).{size = outer});
-}
-inside :: (inner : Generic_Vector($type, $N), outer : Generic_Vector(type, N)) -> bool {
- for i : 0..N-1 {
- if inner.values[i] > outer.values[i] return false;
- }
- return true;
-}
-cut_border :: (box : Generic_Box($type, $N, $left_handed), gap : type) -> Generic_Box(type, N, left_handed) {
- result : Generic_Box(type, N, left_handed) = ---;
- for i : 0..N-1 {
- result.corner.values[i] = box.corner.values[i] + gap;
- result.size.values[i] = box.size.values[i] - gap * 2;
- }
- return result;
-}
-fit_in_center :: (zone : Generic_Box($type, $N, $left_handed), box_size : Generic_Vector(type, N)) -> Generic_Box(type, N, left_handed), fit:bool {
- return .{size = box_size, corner = zone.corner + (zone.size - zone.corner) / 2}, inside(box_size, zone.size);
-}
-intersection :: (box1 : Generic_Box($type, $N, $left_handed), box2 : Generic_Box(type, N, left_handed)) -> Ibox2 {
- result : Generic_Box(type, N, left_handed) = ---;
- for i : 0..N-1 {
- l1, w1 := box1.corner.values[i], box1.size.values[i];
- l2, w2 := box2.corner.values[i], box2.size.values[i];
- result.corner.values[i] = max(l1, l2);
- result.size.values[i] = min(l1 + w1, l2 + w2);
- }
- return result;
-}
-
-cast_vec :: ($type_out : Type, in : Generic_Vector($type_in, $N)) -> Generic_Vector(type_out, N) {
- result : Generic_Vector(type_out, N) = ---;
- for i : 0..N-1 {
- result.values[i] = xx in.values[i];
- }
- return result;
-}
-
-fract :: (x : float) -> float { return x - floor(x); }
-fract :: (using v : Vector2) -> Vector2 { return .{fract(x), fract(y)}; }
-fract :: (using v : Vector3) -> Vector3 { return .{fract(x), fract(y), fract(z)}; }
-fract :: (using v : Vector4) -> Vector4 { return .{fract(x), fract(y), fract(z), fract(w)}; }
-
-floor :: (v : Vector2) -> Vector2 { return .{floor(v.x), floor(v.y)}; }
-floor :: (v : Vector3) -> Vector3 { return .{floor(v.x), floor(v.y), floor(v.z)}; }
-floor :: (v : Vector4) -> Vector4 { return .{floor(v.x), floor(v.y), floor(v.z), floor(v.w)}; }
-
-mix :: (x : float, y : float, m : float) -> float { return x + (y - x) * m; }
-mix :: (x : Vector2, y : Vector2, m : float) -> Vector2 { return .{mix(x.x, y.x, m), mix(x.y, y.y, m)}; }
-mix :: (x : Vector3, y : Vector3, m : float) -> Vector3 { return .{mix(x.x, y.x, m), mix(x.y, y.y, m), mix(x.z, y.z, m)}; }
-mix :: (x : Vector4, y : Vector4, m : float) -> Vector4 { return .{mix(x.x, y.x, m), mix(x.y, y.y, m), mix(x.z, y.z, m), mix(x.w, y.w, m)}; }
-
-mix :: (x : Vector2, y : Vector2, m : Vector2) -> Vector2 { return .{mix(x.x, y.x, m.x), mix(x.y, y.y, m.y)}; }
-mix :: (x : Vector3, y : Vector3, m : Vector3) -> Vector3 { return .{mix(x.x, y.x, m.x), mix(x.y, y.y, m.y), mix(x.z, y.z, m.z)}; }
-mix :: (x : Vector4, y : Vector4, m : Vector4) -> Vector4 { return .{mix(x.x, y.x, m.x), mix(x.y, y.y, m.y), mix(x.z, y.z, m.z), mix(x.w, y.w, m.z)}; }
-
-clamp :: (a : Vector2, mi : float, ma : float) -> Vector2 { return .{clamp(a.x, mi, ma), clamp(a.y, mi, ma)}; }
-clamp :: (a : Vector3, mi : float, ma : float) -> Vector3 { return .{clamp(a.x, mi, ma), clamp(a.y, mi, ma), clamp(a.z, mi, ma)}; }
-clamp :: (a : Vector4, mi : float, ma : float) -> Vector4 { return .{clamp(a.x, mi, ma), clamp(a.y, mi, ma), clamp(a.z, mi, ma), clamp(a.w, mi, ma)}; }
-
-
-sin :: (v : Vector2) -> Vector2 { return .{sin(v.x), sin(v.y)}; }
-sin :: (v : Vector3) -> Vector3 { return .{sin(v.x), sin(v.y), sin(v.z)}; }
-sin :: (v : Vector4) -> Vector4 { return .{sin(v.x), sin(v.y), sin(v.z), sin(v.w)}; }
-
-hash22 :: (_p : Vector2, seed := Vector2.{}) -> Vector2 {
- p := multiply(Matrix2.{127.1, 311.7, 269.5, 183.3}, _p);
- p = Vector2.{-1., -1.} + 2. * fract(sin(p) * 43758.545);
- return sin(p * 6.283 + seed * Vector2.{124.1, 8123.1});
-}
-
-perlin_level :: (p : Vector2) -> float {
- pi := floor(p);
- pf := p - pi;
- w := pf * pf * (Vector2.{3., 3.} - Vector2.{2., 2.} * pf);
-
- f00 := dot(hash22(pi + Vector2.{0., 0.}), pf - Vector2.{0., 0.});
- f01 := dot(hash22(pi + Vector2.{0., 1.}), pf - Vector2.{0., 1.});
- f10 := dot(hash22(pi + Vector2.{1., 0.}), pf - Vector2.{1., 0.});
- f11 := dot(hash22(pi + Vector2.{1., 1.}), pf - Vector2.{1., 1.});
-
- return mix(mix(f00, f10, w.x), mix(f01, f11, w.x), w.y);
-}
-perlin :: (_p : Vector2) -> float {
- p := _p;
- M1 :: 4;
- a, r, s := 1., 0., 0.;
- for i : 0..M1 - 1 {
- r += a * perlin_level(p);
- s += a;
- p *= 2.;
- a *= .5;
- }
- return r / s;
-}
-
-hsv2rgb :: (c : Vector3) -> Vector3 {
- K := Vector4.{1, 2. / 3, 1. / 3, 3};
- p := abs(fract(Vector3.{c.x, c.x, c.x} + K.xyz) * 6.0 - Vector3.{K.w, K.w, K.w});
- return c.z * mix(Vector3.{K.x, K.x, K.x}, clamp(p - Vector3.{K.x, K.x, K.x}, 0, 1), c.y);
-}
-
-
-ivec2 :: Generic_Vector(s32, 2);
-ivec3 :: Generic_Vector(s32, 3);
-u8vec3 :: Generic_Vector(u8, 3);
-Ibox2 :: Generic_Box(s32, 2, false);