From 709879ee56d31fe543a0ad882713bd4e3d17d2d2 Mon Sep 17 00:00:00 2001 From: dam Date: Thu, 17 Aug 2023 20:28:47 +0100 Subject: Added kscurses and testing program. --- kscurses/events.jai | 256 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 256 insertions(+) create mode 100644 kscurses/events.jai (limited to 'kscurses/events.jai') diff --git a/kscurses/events.jai b/kscurses/events.jai new file mode 100644 index 0000000..603958e --- /dev/null +++ b/kscurses/events.jai @@ -0,0 +1,256 @@ +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 { + < 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 := < *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); + < s32 #foreign libc; + +#import "Thread"; \ No newline at end of file -- cgit v1.2.3