aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ttt.jai241
1 files changed, 125 insertions, 116 deletions
diff --git a/ttt.jai b/ttt.jai
index 7690c68..1053ad7 100644
--- a/ttt.jai
+++ b/ttt.jai
@@ -33,17 +33,6 @@ TUI :: #import "TUI";
stdscr: *void; // TODO DAM
A_BOLD: s32 = 0; // TODO DAM
COLOR_PAIR :: (a: s32) -> s32 { return 0; } // TODO DAM
-KEY_RESIZE :: 410; // TODO DAM
-KEY_F2 :: 266; // TODO DAM
-KEY_F5 :: 269; // TODO DAM
-KEY_HOME :: 262; // TODO DAM
-KEY_UP :: 259; // TODO DAM
-KEY_DOWN :: 258; // TODO DAM
-KEY_NPAGE :: 338; // TODO DAM
-KEY_PPAGE :: 339; // TODO DAM
-KEY_END :: 360; // TODO DAM
-KEY_BACKSPACE :: 263; // TODO DAM
-KEY_DC :: 330; // TODO DAM
WINDOW :: struct { } // TODO DAM
@@ -90,10 +79,10 @@ app_directory : string;
db_file_path : string;
ar_file_path : string;
-size_x : s32;
-size_y : s32;
-pos_x : s32;
-pos_y : s32;
+size_x : int;
+size_y : int;
+pos_x : int;
+pos_y : int;
Styles :: enum s16 {
SELECTED :: 1;
@@ -118,8 +107,8 @@ print_error :: (format :string, args : .. Any) {
}
else {
CHAR_SPACE :: #char " ";
- w_size_x: s32 = ifx size_x > 120 then 120 else size_x - 2;
- w_size_y: s32 = 4;
+ w_size_x: int = ifx size_x > 120 then 120 else size_x - 2;
+ w_size_y: int = 4;
if (error_window == null) {
//error_window = newwin(w_size_y, w_size_x, (size_y - w_size_y) / 2, (size_x - w_size_x) / 2); TODO DAM
//wattron(error_window, COLOR_PAIR(xx Styles.ERROR)); TODO DAM
@@ -1175,23 +1164,27 @@ free_memory :: () {
//reset_temporary_storage();
}
-read_input_string_padded :: (row: int, column: int, style: s32, length: int, padding: int) -> string {
- str := talloc_string(length);
- memset(str.data, 0, str.count);
- // attron(style | A_UNDERLINE); TODO DAM
- // mvprintw(xx row, xx column, "%*s", padding, ""); TODO DAM
- //echo(); TODO DAM
- //curs_set(1); TODO DAM
- //mvgetnstr(xx row, xx column, str.data, xx length); TODO DAM
- truncate_string(str, length);
- //noecho(); TODO DAM
- //curs_set(0); TODO DAM
- //attrset(A_NORMAL); TODO DAM
- return str;
-}
+read_input_string :: (row: int, column: int, style: s32, input_limit: int, padding: int = 0) -> value: string, success: bool {
+
+ // TODO We still need to apply the style.
+
+ // TODO Draw padding (at end of inputbox)... padding was renamed to input_width... is this the best name?
+ // TODO Maybe add another optional arg with the placeholder text (to be preset on the input)?
+
+ // TODO WIPWIPWIP
+
+ column += 1; // TODO FIX THE NCURSES INDEXING CHAOS
+
+ TUI.set_cursor_position(row, column + input_limit);
+ write_string(TUI.Commands.DrawingMode);
+ for 1..padding {
+ write_string(TUI.Drawings.Checkerboard);
+ }
+ write_string(TUI.Commands.TextMode);
+ TUI.set_cursor_position(row, column);
+ value, key := TUI.read_input_line(input_limit);
+ return value, key == TUI.Keys.Enter;
-read_input_string :: (row: int, column: int, style: s32, length: int) -> string {
- return read_input_string_padded(row, column, style, length, length);
}
// Returns success.
@@ -1203,41 +1196,67 @@ read_input_int :: (row: int, style: s32, message: string) -> value: int, success
//attrset(A_NORMAL); TODO DAM
// Get line number.
- input_pos_x := 0;//getcurx(stdscr); TODO DAM
- input_width := size_x - input_pos_x - 1;
+ input_pos_x := 1;//getcurx(stdscr); TODO DAM
+ input_width := size_x - input_pos_x;
str := read_input_string(row, input_pos_x, style, input_width);
value, success := parse_int(*str);
return value, success;
}
-// Retuns true if user presses enter, false otherwise.
-read_input_char :: (row: int, style: int, message: string) -> s32 {
- assert(message.data != null, ASSERT_NOT_NULL, "message"); // TODO Improve this check?
-
- // attron(xx style); TODO DAM
- //move(xx row, 1); TODO DAM
+// Shows message to user and waits for user key press.
+prompt_user :: (row: int, style: int, message: string) -> TUI.Key {
+/*
+ assert(message.data != null, ASSERT_NOT_NULL, "message");
+ attron(xx style);
+ move(xx row, 1);
for 0..size_x-3 {
- //for (int idx = 0; idx < size_x - 2; idx++) { // TODO check what's going on here.
- //addch(ACS_CKBOARD); TODO DAM
+ // for (int idx = 0; idx < size_x - 2; idx++) {
+ addch(ACS_CKBOARD);
}
- //mvaddstr(xx row, 2, message.data); TODO DAM
- //attrset(A_NORMAL); TODO DAM
+ mvaddstr(xx row, 2, message.data);
+ attrset(A_NORMAL);
- //return getch(); TODO DAM
- return 0;
-}
+ return getch();
+*/
-// Retuns true if user presses enter, false otherwise.
-read_enter_confirmation :: inline (row: int, style: int, message: string) -> bool {
- return read_input_char(row, style, message) == #char "\n";
+ // TODO We still need to apply the style.
+
+ TUI.set_cursor_position(row, 2);
+ write_string(TUI.Commands.DrawingMode);
+ for 0..size_x-2 {
+ print(TUI.Drawings.Checkerboard);
+ }
+ write_string(TUI.Commands.TextMode);
+
+ TUI.set_cursor_position(row, 3);
+ write_strings(" ", message, " ");
+ return TUI.get_key();
}
main :: () {
// -- -- -- Testing TUI -- START
- if 1 {
+ perform_test := false;
+
+ assert_result :: (result: bool, error_message: string) {
+ if result == true {
+ print("- success\n", to_standard_error = true);
+ }
+ else {
+ TUI.stop();
+ print("- ERROR: %", error_message, to_standard_error = true);
+ exit(1);
+ }
+ }
+
+ next_line :: inline () {
+ r, c := TUI.get_cursor_position();
+ TUI.set_cursor_position(r+1, 1);
+ }
+
+ if perform_test && 1 {
print("TEST : set and get cursor position\n", to_standard_error = true);
TUI.start();
ROW :: 3;
@@ -1245,21 +1264,19 @@ main :: () {
TUI.set_cursor_position(ROW, COLUMN);
row, column := TUI.get_cursor_position();
TUI.stop();
- assert(row == ROW && column == COLUMN, "# Failed set/get cursor position.\n");
- print("- success\n", to_standard_error = true);
+ assert_result(row == ROW && column == COLUMN, "Failed set/get cursor position.\n");
}
- if 0 {
+ if perform_test && 1 {
print("TEST : test key input\n", to_standard_error = true);
auto_release_temp();
TUI.start();
TUI.clear_terminal();
TUI.set_cursor_position(1, 1);
write_string("Press q to exit, other key to print it to screen, wait 1s to see animation.");
- TUI.set_cursor_position(2, 1);
+ next_line();
key: TUI.Key;
while(key != #char "q") {
- __mark := get_temporary_storage_mark();
key = TUI.get_key(1000);
if key == TUI.Keys.None {
write_string("-");
@@ -1271,13 +1288,12 @@ main :: () {
// else if key >= 32 && key <= 128 then print_character(cast,force(u8)key)
write_string(TUI.to_string(key));
}
- set_temporary_storage_mark(__mark);
}
TUI.stop();
print("- success\n", to_standard_error = true);
}
- if 0 {
+ if perform_test && 1 {
print("TEST : draw box\n", to_standard_error = true);
auto_release_temp();
TUI.start(); // TODO Should start() call flush_input internally?
@@ -1288,11 +1304,10 @@ main :: () {
print("Can you see the box below? (y/n)");
key := TUI.get_key();
TUI.stop();
- assert(key == #char "y", "# Failed to draw box.\n");
- print("- success\n", to_standard_error = true);
+ assert_result(key == #char "y", "Failed to draw box.\n");
}
- if 0 {
+ if perform_test && 1 {
print("TEST : get terminal size\n", to_standard_error = true);
auto_release_temp();
TUI.start();
@@ -1305,11 +1320,10 @@ main :: () {
key = TUI.get_key();
}
TUI.stop();
- assert(key == #char "y", "# Failed to get terminal size.\n");
- print("- success\n", to_standard_error = true);
+ assert_result(key == #char "y", "Failed to get terminal size.\n");
}
- if 0 {
+ if perform_test && 1 {
print("TEST : set terminal title\n", to_standard_error = true);
TUI.start();
title := "BAZINGA";
@@ -1321,12 +1335,12 @@ main :: () {
key = TUI.get_key();
}
TUI.stop();
- assert(key == #char "y", "# Failed to set terminal title.\n");
- print("- success\n", to_standard_error = true);
+ assert_result(key == #char "y", "Failed to set terminal title.\n");
}
- if 0 {
+ if perform_test && 1 {
print("TEST : print keys and set terminal title\n", to_standard_error = true);
+ auto_release_temp();
TUI.start();
TUI.set_terminal_title("bazinga");
key: TUI.Key = #char "d";
@@ -1338,7 +1352,6 @@ main :: () {
drop_down := 0;
while(key != #char "q") {
- __mark := get_temporary_storage_mark();
if key == {
case TUI.Keys.None; {
@@ -1383,83 +1396,80 @@ main :: () {
TUI.set_cursor_position(x, y);
print("size(CxR): %x%\n", size_c, size_r);
key = TUI.get_key(1000);
-
- set_temporary_storage_mark(__mark);
+
+ // __mark := get_temporary_storage_mark();
+ // set_temporary_storage_mark(__mark);
}
+ print("- success");
TUI.stop();
}
- if 1 {
+ if perform_test && 1 {
print("TEST : user input\n", to_standard_error = true);
auto_release_temp();
TUI.start();
TUI.clear_terminal();
TUI.set_cursor_position(1, 1);
print("Enter some text (use Enter to finish, Esc to cancel, or resize to abort):");
- r, c := TUI.get_cursor_position();
- TUI.set_cursor_position(r+1, 1);
+ next_line();
str, key := TUI.read_input_line(15);
TUI.set_cursor_position(3, 1);
+ error_message: string;
if key == {
case TUI.Keys.Escape; {
print("Have you pressed Esc? (y/n)");
- assert(TUI.get_key() == #char "y", "Failed to read line on Esc.");
- print("- success\n", to_standard_error = true);
+ error_message = "Failed to read line on Esc.";
}
case TUI.Keys.Resize; {
print("Have you resized the terminal? (y/n)");
- assert(TUI.get_key() == #char "y", "Failed to read line on resize.");
- print("- success\n", to_standard_error = true);
+ error_message = "Failed to read line on resize.";
+
}
case; {
print("Have you entered '%'? (y/n)", str);
- assert(TUI.get_key() == #char "y", "Failed to read line.");
- print("- success\n", to_standard_error = true);
+ error_message = "Failed to read line.";
}
}
+ answer := TUI.get_key();
TUI.stop();
+ assert_result(answer == #char "y", error_message);
}
- if 1 {
+ if perform_test && 1 {
print("TEST : hidden user input\n", to_standard_error = true);
auto_release_temp();
TUI.start();
TUI.clear_terminal();
TUI.set_cursor_position(1, 1);
print("Enter some secret (use Enter to finish, Esc to cancel, or resize to abort):");
- r, c := TUI.get_cursor_position();
- TUI.set_cursor_position(r+1, 1);
+ next_line();
str, key := TUI.read_input_line(15, false);
TUI.set_cursor_position(3, 1);
+ error_message: string;
if key == {
case TUI.Keys.Escape; {
print("Have you pressed Esc? (y/n)");
- assert(TUI.get_key() == #char "y", "Failed to read line on Esc.");
- print("- success\n", to_standard_error = true);
+ error_message = "Failed to read line on Esc.";
}
case TUI.Keys.Resize; {
print("Have you resized the terminal? (y/n)");
- assert(TUI.get_key() == #char "y", "Failed to read line on resize.");
- print("- success\n", to_standard_error = true);
+ error_message = "Failed to read line on resize.";
}
case; {
print("Have you entered '%'? (y/n)", str);
- assert(TUI.get_key() == #char "y", "Failed to read line.");
- print("- success\n", to_standard_error = true);
+ error_message = "Failed to read line.";
}
}
+ answer := TUI.get_key();
TUI.stop();
+ assert_result(answer == #char "y", error_message);
}
- write_string("DONE\n");
- exit(0);
// -- -- -- Testing TUI -- STOP
- // TODO Implement signal handling and see modules/Debug.jai for examples.
-
defer report_memory_leaks(); // TODO Remove after final debug sessions.
defer free_memory();
@@ -1674,9 +1684,9 @@ main :: () {
ifx selected_idx == active_idx && selected_idx != -1 then Styles.ACTIVE
else Styles.SELECTED_INVERTED);
error_style = A_BOLD | COLOR_PAIR(xx Styles.ERROR);
- selected_task_row = ifx is_terminal_too_small then 0
+ selected_task_row = ifx is_terminal_too_small then 0
else ifx (selected_idx < 0) then 1
- else (selected_idx % layout_tasks_rows) + NUM_HEADER_ROWS;
+ else (selected_idx % layout_tasks_rows) + NUM_HEADER_ROWS + 1;
}
if key == {
@@ -1697,10 +1707,7 @@ main :: () {
// When terminal is resized.
case TUI.Keys.Resize;
TUI.clear_terminal();
- _y, _x := TUI.get_terminal_size();
- // TODO FIX ME
- size_y = xx _y;
- size_x = xx _x;
+ size_y, size_x = TUI.get_terminal_size();
is_terminal_too_small = size_x < 60 || size_y < 3;
update_layout();
layout = *layouts[ifx size_x > 100 then Layouts.NORMAL else Layouts.COMPACT];
@@ -1723,7 +1730,7 @@ main :: () {
case #char "n"; #through;
case #char "N";
if is_database_full(db) {
- read_enter_confirmation(selected_task_row, error_style, " Unable to create task: database is full. ");
+ prompt_user(selected_task_row, error_style, "Unable to create task: database is full.");
continue;
}
@@ -1743,29 +1750,31 @@ main :: () {
//flushinp(); TODO DAM
//ungetch(KEY_F(2)); TODO DAM
- case KEY_F2;
+ case TUI.Keys.F2;
if (selected_task == null) continue;
-
+
// Change task name.
- input := read_input_string_padded(selected_task_row, 1, action_style, Task.name.count, size_x - 2);
+ // TODO WIPWIPWIP
+ input := read_input_string(selected_task_row, 1, action_style, Task.name.count, size_x - 2 - Task.name.count);
if is_empty_string(input) == false {
- replace_chars(input, "\t\x0B\x0C\r", #char " ");
+ replace_chars(input, "\t\x0B\x0C\r", #char " "); // Replace weird spaces with space.
+ memset(selected_task.name.data, 0, Task.name.count);
memcpy(selected_task.name.data, input.data, min(Task.name.count, input.count));
trigger_autosave();
}
- case KEY_BACKSPACE;
+ case TUI.Keys.Backspace;
if (selected_task == null) continue;
- if (read_enter_confirmation(selected_task_row, action_style, " Press enter to reset task. ") == true) {
+ if (prompt_user(selected_task_row, action_style, "Press enter to reset task.") == TUI.Keys.Enter) {
reset_task_times(db, db.selected_idx);
trigger_autosave();
}
- case KEY_DC; // Delete
+ case TUI.Keys.Delete;
if (selected_task == null || selected_task == active_task) continue;
- if (read_enter_confirmation(selected_task_row, action_style, " Press enter to delete task. ") == true) {
+ if (prompt_user(selected_task_row, action_style, "Press enter to delete task.") == TUI.Keys.Enter) {
delete_task(db, db.selected_idx);
trigger_autosave();
}
@@ -1851,7 +1860,7 @@ main :: () {
if selected_task == null continue;
if is_database_full(db) {
- read_enter_confirmation(selected_task_row, error_style, " Unable to duplicate task: database is full. ");
+ prompt_user(selected_task_row, error_style, "Unable to duplicate task: database is full.");
continue;
}
@@ -1861,7 +1870,7 @@ main :: () {
}
trigger_autosave();
- case KEY_F5;
+ case TUI.Keys.F5;
update_total_times(db);
trigger_autosave();
@@ -1912,7 +1921,7 @@ main :: () {
if (db != *archive || selected_task == null) continue;
if is_database_full(*database) {
- read_enter_confirmation(selected_task_row, error_style, " Unable to restore task: database is full. ");
+ prompt_user(selected_task_row, error_style, "Unable to restore task: database is full.");
continue;
}
@@ -1927,7 +1936,7 @@ main :: () {
case #char "s"; #through;
case #char "S";
// TODO The initial part should only decide what's the sorting procedure... then we would would all in a single place.
- sort_by := read_input_char(selected_task_row, action_style, " Sort by (n) name, (1..7) day, or (t) total time. ");
+ sort_by := prompt_user(selected_task_row, action_style, "Sort by (n) name, (1..7) day, or (t) total time.");
show_processing();
sort_procedure: (a: Task, b: Task) -> s64;
@@ -1975,7 +1984,7 @@ main :: () {
case #char "w"; #through;
case #char "W";
if (db != *database || db.tasks.count <= 0) continue;
- if (read_enter_confirmation(selected_task_row, action_style, " Press enter to archive duplicates and reset all. ") == false) continue;
+ if (prompt_user(selected_task_row, action_style, "Press enter to archive duplicates and reset all.") != TUI.Keys.Enter) continue;
show_processing();
for db.tasks {
@@ -1990,7 +1999,7 @@ main :: () {
case #char "c"; #through;
case #char "C";
if (db.tasks.count <= 0) continue;
- if (read_enter_confirmation(selected_task_row, action_style, " Press enter to coalesce similar tasks. ") == false) continue;
+ if (prompt_user(selected_task_row, action_style, "Press enter to coalesce similar tasks.") != TUI.Keys.Enter) continue;
show_processing();
head_idx := 0;
@@ -2009,7 +2018,7 @@ main :: () {
}
trigger_autosave();
- case KEY_HOME;
+ case TUI.Keys.Home;
select_task(db, 0);
case TUI.Keys.Up;
@@ -2018,7 +2027,7 @@ main :: () {
case TUI.Keys.PgUp;
select_task_by_delta(db, -layout_tasks_rows);
- case KEY_END;
+ case TUI.Keys.End;
select_task(db, db.tasks.count-1);
case TUI.Keys.Down;