aboutsummaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/TUI/module.jai122
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);
+ }
+}