aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tio.jai142
-rw-r--r--ttt.jai40
2 files changed, 148 insertions, 34 deletions
diff --git a/tio.jai b/tio.jai
index 37c7e4a..f6ee0cb 100644
--- a/tio.jai
+++ b/tio.jai
@@ -1,4 +1,10 @@
+#module_parameters(ENABLE_SIGINT := true, ENABLE_SIGQUIT := true);
+
+#import "Basic";
+
+// TODO Eventually, I'll need to add #scope_module ...
+
terminal_state : struct {
// size : ivec2;
width: s32;
@@ -15,18 +21,22 @@ terminal_state : struct {
__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;
+ c_iflag : u32; // Input mode flags.
+ c_oflag : u32; // Output mode flags.
+ c_cflag : u32; // Control mode flags.
+ c_lflag : u32; // Local mode flags.
+ c_line : u8; // Line discipline.
+ c_cc : [32]u8; // Control characters.
+ c_ispeed : u32; // Input speed.
+ c_ospeed : u32; // Output speed.
}
libc :: #system_library "libc";
+
+ // https://codebrowser.dev/glibc/glibc/sysdeps/unix/sysv/linux/tcsetattr.c.html
tcsetattr :: (fd : s32, optional_actions : s32, termios_p : *My_Termios) -> s32 #foreign libc;
+
+ // https://codebrowser.dev/glibc/glibc/sysdeps/unix/sysv/linux/tcgetattr.c.html
tcgetattr :: (fd : s32, termios_p : *My_Termios) -> s32 #foreign libc;
}
else {
@@ -57,6 +67,52 @@ Graphics_Mode :: struct {
bcol256 : u8;
}
+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;
+}
+
Color :: enum u8 {
RESET :: 0;
DEFAULT :: 39;
@@ -81,11 +137,40 @@ Color :: enum u8 {
BRIGHT_WHITE :: 97;
}
-__old_logger : type_of(context.logger);
+update_terminal_size :: () {
+ TIOCGWINSZ :: 0x5413;
+ winsize : struct {
+ ws_row, ws_col, ws_xpixel, ws_ypixel : u16;
+ }
+ ioctl(0, TIOCGWINSZ, *winsize);
+ terminal_state.width = xx winsize.ws_col;
+ terminal_state.height = xx winsize.ws_row;
+}
initialize :: () {
#if OS == .LINUX {
- tcgetattr(STDIN_FILENO, *__term);
+
+ tui_write("\e[?25l"); // hide cursor
+ tui_write("\e7"); // save cursor position
+ tui_write("\e[?1047h"); // switch screen
+ tui_write("\e[?30l"); // hide scrollbar
+
+ tui_write("\e[H"); // move to top left corner
+ tui_write("\e[0m"); // set default mode
+ tui_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");
}
@@ -95,22 +180,47 @@ terminate :: () {
#if OS == .LINUX {
tcsetattr(STDIN_FILENO, 0, *__term); // return echo
- tio_write("\e[?47l"); // restore screen
- tio_write("\e8"); // restore cursor
- tio_write("\e[?25h"); // show cursor
- tio_write("\e[?30h"); // show scrollbar
+ tui_write("\e[?47l"); // restore screen
+ tui_write("\e8"); // restore cursor
+ tui_write("\e[?25h"); // show cursor
+ tui_write("\e[?30h"); // show scrollbar
terminal_state = .{};
- context.logger = __old_logger;
} else {
assert(false, "procedure call on unsupported OS\n");
}
}
-tio_write :: (str : string) {
+tui_write :: (str : string) {
#if OS == .LINUX {
write(STDIN_FILENO, str.data, xx str.count);
} else {
assert(false, "procedure call on unsupported OS\n");
}
}
+
+buffer: [..] Key;
+
+tui_ungetch :: (key: Key) {
+ array_add(*buffer, key);
+}
+
+tui_getch :: (block := true) -> Key {
+ #if OS == .LINUX {
+ buf : Key = xx 0;
+ if buffer.count > 0 return pop(*buffer);
+ 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;
+ }
+}
+
+tui_clear_screen :: inline () {
+ tui_write("\e[2J");
+}
diff --git a/ttt.jai b/ttt.jai
index b3a1cd3..7431ac6 100644
--- a/ttt.jai
+++ b/ttt.jai
@@ -25,9 +25,9 @@
#import "File";
#import "File_Utilities";
#import "String";
-//#import "curses";
+// #import "curses";
// #import "kscurses";
-TIO :: #import "tio";
+TUI :: #import "tio"; // TODO Rename module to "tui.jai"
#load "Integer_Saturating_Arithmetic.jai";
@@ -36,7 +36,6 @@ TIO :: #import "tio";
stdscr: *void; // TODO DAM
A_BOLD: s32 = 0; // TODO DAM
COLOR_PAIR :: (a: s32) -> s32 { return 0; } // TODO DAM
-ERR :: -1; // TODO DAM
KEY_RESIZE :: 410; // TODO DAM
KEY_F2 :: 266; // TODO DAM
KEY_F5 :: 269; // TODO DAM
@@ -902,13 +901,12 @@ initialize_tui :: () {
}
// TODO DAM
- TIO.initialize();
- TIO.terminate(); // TODO DAM
- //stdscr = initscr(); // Start curses mode. TODO DAM
- //cbreak(); // Line buffering disabled; pass on everty thing to me. TODO DAM
- //keypad(stdscr, true); // I need those nifty F1..F12. TODO DAM
- //curs_set(0); // Set cursor invisible. TODO DAM
- //noecho(); // Disable echoing input characters. TODO DAM
+ TUI.initialize();
+ // stdscr = initscr(); // Start curses mode. TODO DAM
+ // cbreak(); // Line buffering disabled; pass on everty thing to me. TODO DAM
+ // keypad(stdscr, true); // I need those nifty F1..F12. TODO DAM
+ // curs_set(0); // Set cursor invisible. TODO DAM
+ // noecho(); // Disable echoing input characters. TODO DAM
// Initialize pairs of colors.
//start_color(); TODO DAM
@@ -957,10 +955,11 @@ draw_tui :: (db: *Database, layout: *Layout) {
// Reset theme and clear screen.
//attrset(A_NORMAL); TODO DAM
- //erase(); TODO DAM
+ TUI.tui_clear_screen();
// Draw outer border.
//box(stdscr, 0, 0); TODO DAM
+ // WIP
// Draw table grids.
// TODO Maybe this could be simplified?
@@ -1362,7 +1361,7 @@ main :: () {
layout := *layouts[Layouts.COMPACT];
//flushinp(); TODO DAM
- //ungetch(KEY_RESIZE); TODO DAM
+ TUI.tui_ungetch(KEY_RESIZE); // TODO DAM
while (true) {
if (is_terminal_too_small) {
@@ -1376,7 +1375,7 @@ main :: () {
reset_temporary_storage();
//timeout(INPUT_TIMEOUT_MS); TODO DAM
- key := 0; // getch(); TODO DAM
+ key := TUI.tui_getch(); // getch(); TODO DAM
if key == #char "q" || key == #char "Q" break;
update_times(*database);
//timeout(INPUT_AWAIT_INF); TODO DAM
@@ -1400,7 +1399,7 @@ main :: () {
if key == {
// When getch() times out.
- case ERR;
+ case .READ_ERROR;
if (is_autosave_enabled && countdown_to_autosave > 0) {
countdown_to_autosave -= INPUT_TIMEOUT_MS;
if (countdown_to_autosave <= 0) {
@@ -1414,8 +1413,13 @@ main :: () {
// When terminal is resized.
case KEY_RESIZE;
- //clear(); TODO DAM
- //getmaxyx(stdscr, *size_y, *size_x); TODO DAM
+ TUI.tui_clear_screen();
+ //getmaxyx(stdscr, *size_y, *size_x);
+ TUI.update_terminal_size(); // TODO DAM
+ size_x = TUI.terminal_state.width;
+ size_y = TUI.terminal_state.height;
+ print("resize:%x%", size_x, size_y);
+ asd := TUI.tui_getch();
is_terminal_too_small = size_x < 60 || size_y < 3;
update_layout();
layout = *layouts[ifx size_x > 100 then Layouts.NORMAL else Layouts.COMPACT];
@@ -1495,7 +1499,7 @@ main :: () {
if (selected_task == null) continue;
// Prepare position to input time operation.
- selected_day := key - #char "1";
+ selected_day := cast(int)(key - #char "1"); // TODO DAM this cast...
input_width := layout.columns[L_DAYS_IDX + selected_day].width;
input_pos_x := 1 + layout.columns[L_TITLE_IDX].width;
@@ -1766,7 +1770,7 @@ main :: () {
//getch(); TODO DAM
}
- //endwin(); TODO DAM
+ TUI.terminate(); // TODO DAM
exit(xx ifx error_saving then 1 else 0);
}