diff options
Diffstat (limited to 'modules')
| -rw-r--r-- | modules/TUI/module.jai | 122 |
1 files changed, 82 insertions, 40 deletions
diff --git a/modules/TUI/module.jai b/modules/TUI/module.jai index a5db3bf..f2a3a23 100644 --- a/modules/TUI/module.jai +++ b/modules/TUI/module.jai @@ -32,14 +32,17 @@ #import "UTF8"; #load "key_map.jai"; +#add_context tui_style : Style; // This contains the last style applied by the module. +#add_context tui_buffer : *String_Builder; // If set, this buffer will be used as output target of module procedures. + +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. + active := false; input_override : Key; input_string : string; input_buffer : [1024] u8; - -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. +temp_buffer := String_Builder.{ allocator = temporary_allocator }; #scope_module @@ -51,7 +54,7 @@ assert_is_active :: inline () { log_tui_error :: (format_string: string, args: .. Any) { write_strings(Commands.SaveCursorPosition, Commands.MainScreenBuffer); - log_error(format_string, args); + log_error(format_string, ..args); write_strings(Commands.AlternateScreenBuffer, Commands.RestoreCursorPosition); } @@ -151,8 +154,6 @@ Commands :: struct #type_info_none { CursorNormalMode :: "\e[?1l"; } -#add_context terminal_style: Style; - Style :: struct { #if COLOR_MODE_BITS == 4 || COLOR_MODE_BITS == 8 { background: Palette; @@ -175,25 +176,26 @@ Style :: struct { } set_style :: (style: Style) { - auto_release_temp(); - builder := String_Builder.{ allocator = temporary_allocator }; + auto_release_temp(); + + builder := ifx context.tui_buffer != null then context.tui_buffer else *temp_buffer; #if COLOR_MODE_BITS == { case 4; - print_to_builder(*builder, + print_to_builder(builder, #run sprint("%0%0", Commands.SetGraphicsRendition, Commands.SetGraphicsRendition), cast(u8)style.foreground + 30, cast(u8)style.background + 40 ); case 8; - print_to_builder(*builder, + print_to_builder(builder, #run sprint(Commands.SetGraphicsRendition, "38;5;%;48;5;%"), cast(u8)style.foreground, cast(u8)style.background ); case 24; - print_to_builder(*builder, + print_to_builder(builder, #run sprint(Commands.SetGraphicsRendition, "38;2;%;%;%;48;2;%;%;%"), style.foreground.r, style.foreground.g, style.foreground.b, style.background.r, style.background.g, style.background.b @@ -201,25 +203,27 @@ set_style :: (style: Style) { } if style.use_default_foreground_color { - append(*builder, #run sprint(Commands.SetGraphicsRendition, "39")); + append(builder, #run sprint(Commands.SetGraphicsRendition, "39")); } if style.use_default_background_color { - append(*builder, #run sprint(Commands.SetGraphicsRendition, "49")); + append(builder, #run sprint(Commands.SetGraphicsRendition, "49")); } - write_string(builder_to_string(*builder,, allocator = temporary_allocator)); + if context.tui_buffer == null { + write_builder(builder); + } - context.terminal_style = style; + context.tui_style = style; } clear_style :: () { write_string(#run sprint(Commands.SetGraphicsRendition, "0")); - context.terminal_style = .{ }; + context.tui_style = .{ }; } using_style :: (style: Style) #expand { - __style := context.terminal_style; + __style := context.tui_style; set_style(style); `defer set_style(__style); } @@ -493,7 +497,11 @@ read_input_line :: (count_limit: int, is_visible: bool = true) -> string, Key { assert_is_active(); assert(count_limit >= 0, "Invalid arguments passed to read_input_line(): 'count_limit' must be greater-than or equal to 0."); - builder := String_Builder.{ allocator = temporary_allocator }; + // builder := String_Builder.{ allocator = temporary_allocator }; + // builder := String_Builder.{}; + // init_string_builder(*builder, 10000); + // reset(*builder); + builder := temp_buffer; str := alloc_string(count_limit); str.count = 0; @@ -509,7 +517,7 @@ read_input_line :: (count_limit: int, is_visible: bool = true) -> string, Key { chars_count := count_characters(str); - // Draw preview. + // Preview input line. if is_visible { print_to_builder(*builder, Commands.SetCursorPosition, y, x); append(*builder, str); @@ -521,6 +529,7 @@ read_input_line :: (count_limit: int, is_visible: bool = true) -> string, Key { for chars_count..count_limit-1 append(*builder, " "); } print_to_builder(*builder, Commands.SetCursorPosition, y, x+idx); + // write_builder(*builder); // TODO Not sure why this is not working... write_string(builder_to_string(*builder,, allocator = temporary_allocator)); // Process input key. @@ -594,38 +603,40 @@ draw_box :: (x: int, y: int, width: int, height: int) { assert(x > 0 && y > 0 && width > 1 && height > 1, "Invalid arguments passed to draw_box(): 'x' and 'y' must be greater-than 0; 'width' and 'height' must be greater-than 1."); auto_release_temp(); - - builder := String_Builder.{ allocator = temporary_allocator }; - - append(*builder, Commands.DrawingMode); + + builder := ifx context.tui_buffer != null then context.tui_buffer else *temp_buffer; + + append(builder, Commands.DrawingMode); // Draw top line - print_to_builder(*builder, Commands.SetCursorPosition, y, x); - append(*builder, Drawings.CornerTL); + print_to_builder(builder, Commands.SetCursorPosition, y, x); + append(builder, Drawings.CornerTL); for 1..width-2 { - append(*builder, Drawings.LineH); + append(builder, Drawings.LineH); } - append(*builder, Drawings.CornerTR); + append(builder, Drawings.CornerTR); // Draw left and right sides. for idx: y+1..y+height-2 { - print_to_builder(*builder, Commands.SetCursorPosition, idx, x); - append(*builder, Drawings.LineV); - print_to_builder(*builder, Commands.SetCursorPosition, idx, x+width-1); - append(*builder, Drawings.LineV); + print_to_builder(builder, Commands.SetCursorPosition, idx, x); + append(builder, Drawings.LineV); + print_to_builder(builder, Commands.SetCursorPosition, idx, x+width-1); + append(builder, Drawings.LineV); } // Draw bottom line. - print_to_builder(*builder, Commands.SetCursorPosition, y+height-1, x); - append(*builder, Drawings.CornerBL); + print_to_builder(builder, Commands.SetCursorPosition, y+height-1, x); + append(builder, Drawings.CornerBL); for 1..width-2 { - append(*builder, Drawings.LineH); + append(builder, Drawings.LineH); } - append(*builder, Drawings.CornerBR); + append(builder, Drawings.CornerBR); - append(*builder, Commands.TextMode); - - write_string(builder_to_string(*builder,, allocator = temporary_allocator)); + append(builder, Commands.TextMode); + + if context.tui_buffer == null { + write_builder(builder); + } } clear_terminal :: inline () { @@ -682,7 +693,12 @@ get_terminal_size :: () -> width: int, height: int { set_cursor_position :: inline (x: int, y: int) { assert_is_active(); - print(Commands.SetCursorPosition, y, x); + if context.tui_buffer == null { + print(Commands.SetCursorPosition, y, x); + } + else { + print_to_builder(context.tui_buffer, Commands.SetCursorPosition, y, x); + } } get_cursor_position :: () -> x: int, y: int { @@ -723,3 +739,29 @@ set_terminal_title :: inline (title: string) { assert_is_active(); print(Commands.SetWindowTitle, title); } + +using_buffer :: (buffer: *String_Builder) #expand { + __buffer := context.tui_buffer; + context.tui_buffer = buffer; + `defer context.tui_buffer = __buffer; +} + +// TODO Maybe we should have a different name for this...? +tui_print :: inline (format_string: string, args: .. Any) { + if context.tui_buffer == null { + print(format_string, ..args, to_standard_error = false); + } + else { + print_to_builder(context.tui_buffer, format_string, ..args); + } +} + +// TODO Maybe we should have a different name for this...? +tui_write :: inline (format_string: string) { + if context.tui_buffer == null { + write_string(format_string); + } + else { + append(context.tui_buffer, format_string); + } +} |
