diff options
| author | dam <dam@gudinoff> | 2024-05-05 00:31:46 +0100 |
|---|---|---|
| committer | dam <dam@gudinoff> | 2024-05-05 00:31:46 +0100 |
| commit | cb6c3caaa285bc8bd12c356d57bbfad86d70c0eb (patch) | |
| tree | beb732467422fea0edc55b1dd4069f06f632167a /modules/TUI/module.jai | |
| parent | b87e4a141da53cf903a0ab9fc9eb693c85a5c0b4 (diff) | |
| download | task-time-tracker-cb6c3caaa285bc8bd12c356d57bbfad86d70c0eb.tar.zst task-time-tracker-cb6c3caaa285bc8bd12c356d57bbfad86d70c0eb.zip | |
WIP : Cleanup TUI module scope.
Diffstat (limited to 'modules/TUI/module.jai')
| -rw-r--r-- | modules/TUI/module.jai | 222 |
1 files changed, 117 insertions, 105 deletions
diff --git a/modules/TUI/module.jai b/modules/TUI/module.jai index 772b30c..ab2567d 100644 --- a/modules/TUI/module.jai +++ b/modules/TUI/module.jai @@ -1,7 +1,9 @@ #module_parameters(COLOR_MODE_BITS := 24); + #scope_file + #if OS == { case .LINUX; #load "unix.jai"; @@ -26,8 +28,27 @@ KEY_SIZE :: #run type_info(Key).runtime_size; assert(input_buffer.count >= KEY_SIZE, "The input buffer size must be capable to hold an entire Key, which should be able to hold an UTF8 code (4 bytes) or a terminal escape code (6 bytes)."); } +active := false; +input_buffer : [1024] u8; +input_string : string; +input_override : Key; + +previous_logger : (message: string, data: *void, info: Log_Info); + +module_logger :: (message: string, data: *void, info: Log_Info) { + write_strings(Commands.SaveCursorPosition, Commands.MainScreenBuffer); + previous_logger(message, data, info); + write_strings(Commands.AlternateScreenBuffer, Commands.RestoreCursorPosition); +} + +assert_is_active :: inline () { + assert(active, "Please call setup_terminal() to start using this module."); +} + + #scope_export; + // Special Graphics Characters. Drawings :: struct #type_info_none { Blank :: "\x5F"; @@ -123,6 +144,12 @@ Commands :: struct #type_info_none { // TODO Check which procedures need the assert_is_active call. // TODO Review the error messages on the asserts. +//////////////////////////////////////////////////////////////////////////////// + + +#scope_file + + #if COLOR_MODE_BITS == 4 { #load "palette_4b.jai"; @@ -144,12 +171,6 @@ else #if COLOR_MODE_BITS == 8 { else { #load "palette_24b.jai"; - Color_24b :: struct { - r: u8; - g: u8; - b: u8; - } - set_colors :: inline (foreground: Color_24b, background: Color_24b) { print( #run sprint(Commands.SetGraphicsRendition, "38;2;%;%;%;48;2;%;%;%"), @@ -158,6 +179,19 @@ else { } } +set_font_style :: inline (bold: bool, underline: bool = false, strike_through: bool = false, negative: bool = false) { + print( + #run sprint(Commands.SetGraphicsRendition, "%;%;%;%"), + ifx bold then 1 else 22, + ifx underline then 4 else 24, + ifx strike_through then 9 else 29, + ifx negative then 7 else 27); +} + + +#scope_export + + Style :: struct { #if COLOR_MODE_BITS == 4 || COLOR_MODE_BITS == 8 { background: Palette; @@ -180,16 +214,9 @@ Style :: struct { negative: bool; } -set_font_style :: inline (bold: bool, underline: bool = false, strike_through: bool = false, negative: bool = false) { - print( - #run sprint(Commands.SetGraphicsRendition, "%;%;%;%"), - ifx bold then 1 else 22, - ifx underline then 4 else 24, - ifx strike_through then 9 else 29, - ifx negative then 7 else 27); -} +#add_context terminal_style: Style; -set_style :: (style: Style) { +set_style :: inline (style: Style) { set_font_style(style.bold, style.underline, style.strike_through, style.negative); set_colors(style.foreground, style.background); context.terminal_style = style; @@ -205,6 +232,9 @@ using_style :: (style: Style) #expand { `defer set_style(__style); } + +//////////////////////////////////////////////////////////////////////////////// + /* We wanted the Key type to represent either UTF-8 encoded characters and also keyboard keys. The UTF-8 only requires up to 4 bytes, but some keyboard keys return up to 6 bytes. @@ -216,34 +246,7 @@ using_style :: (style: Style) #expand { key/u64 |0|0|c|b|a| -> that in memory lays as (BE:|0|0|c|b|a|) and (LE:|a|b|c|0|0|) */ -Key :: u64; // Terminal key-codes have 1 to 6 bytes so we'll use 8 bytes. - -to_key :: (str: $T) -> Key #modify { return T == ([]u8) || T == string; } { - assert(str.count <= KEY_SIZE, "Invalid argument passed to to_key(): 'str.count' must be less-than or equal to %, but it was %.", KEY_SIZE, str.count); - - k: Key; - for 0..str.count-1 { - k |= ((cast(u64)str[it]) << (it*8)); - } - return k; -} - -to_string :: (key: Key) -> string { - str := alloc_string(KEY_SIZE); - str.count = 0; - while key != 0 { - str.count += 1; - str[str.count-1] = xx key & 0xFF; - key >>= 8; - } - return str; -} - -is_escape_code :: (key: Key) -> bool { - beginsWithEscape := ((key & 0xFF) ^ #char "#") == 0; - hasSomethingElse := (key & (~0xFF)) != 0; - return beginsWithEscape && hasSomethingElse; -} +Key :: u64; Keys :: struct #type_info_none { None : Key : #run to_key("#none"); @@ -282,29 +285,86 @@ Keys :: struct #type_info_none { F12 : Key : #run to_key("#f12"); } -#add_context terminal_style: Style; +to_key :: (str: $T) -> Key #modify { return T == ([]u8) || T == string; } { + assert(str.count <= KEY_SIZE, "Invalid argument passed to to_key(): 'str.count' must be less-than or equal to %, but it was %.", KEY_SIZE, str.count); + + k: Key; + for 0..str.count-1 { + k |= ((cast(u64)str[it]) << (it*8)); + } + return k; +} -active := false; +to_string :: (key: Key) -> string { + str := alloc_string(KEY_SIZE); + str.count = 0; + while key != 0 { + str.count += 1; + str[str.count-1] = xx key & 0xFF; + key >>= 8; + } + return str; +} -input_buffer : [1024] u8; -input_string : string; -input_override : Key; +is_escape_code :: (key: Key) -> bool { + beginsWithEscape := ((key & 0xFF) ^ #char "#") == 0; + hasSomethingElse := (key & (~0xFF)) != 0; + return beginsWithEscape && hasSomethingElse; +} -previous_logger : (message: string, data: *void, info: Log_Info); +//////////////////////////////////////////////////////////////////////////////// -module_logger :: (message: string, data: *void, info: Log_Info) { - write_strings(Commands.SaveCursorPosition, Commands.MainScreenBuffer); - previous_logger(message, data, info); - write_strings(Commands.AlternateScreenBuffer, Commands.RestoreCursorPosition); +is_active :: inline () -> bool { + return active; } -assert_is_active :: inline () { - assert(active, "Please call setup_terminal() to start using this module."); +setup_terminal :: () -> success := true #must { + if active == true return; + + input_string.data = input_buffer.data; + input_string.count = 0; + input_override = xx Keys.None; + + previous_logger = context.logger; + context.logger = module_logger; + + setup_key_map(); + + write_strings( + Commands.HideCursor, + Commands.SaveCursorPosition, + Commands.AlternateScreenBuffer, + Commands.EncodingUTF8, + Commands.CursorNormalMode, + Commands.KeypadNumMode + ); + + if !OS_prepare_terminal() then return false; + + active = true; + + return; } -//////////////////////////////////////////////////////////////////////////////// +reset_terminal :: () -> success := true #must { + if active == false return; + + active = false; -// #scope_export TODO Setup the scope_export and scope_file + clear_style(); + + if !OS_reset_terminal() then return false; + + context.logger = previous_logger; + + write_strings( + Commands.MainScreenBuffer, + Commands.RestoreCursorPosition, + Commands.ShowCursor + ); + + return; +} set_next_key :: inline (key: Key) { assert_is_active(); @@ -535,54 +595,6 @@ read_input_line :: (count_limit: int, is_visible: bool = true) -> string, Key { return result, key; } -setup_terminal :: () -> success := true #must { - if active == true return; - - input_string.data = input_buffer.data; - input_string.count = 0; - input_override = xx Keys.None; - - previous_logger = context.logger; - context.logger = module_logger; - - setup_key_map(); - - write_strings( - Commands.HideCursor, - Commands.SaveCursorPosition, - Commands.AlternateScreenBuffer, - Commands.EncodingUTF8, - Commands.CursorNormalMode, - Commands.KeypadNumMode - ); - - if !OS_prepare_terminal() then return false; - - active = true; - - return; -} - -reset_terminal :: () -> success := true #must { - if active == false return; - - active = false; - - clear_style(); - - if !OS_reset_terminal() then return false; - - context.logger = previous_logger; - - write_strings( - Commands.MainScreenBuffer, - Commands.RestoreCursorPosition, - Commands.ShowCursor - ); - - return; -} - flush_input :: () { assert_is_active(); OS_flush_input(); |
