aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordam <dam@gudinoff>2022-12-15 01:19:59 +0000
committerdam <dam@gudinoff>2022-12-15 01:19:59 +0000
commitb968cf38d0c69827dfd1a1a25b4c940b1189df95 (patch)
treec31722d58b7d2d3d7d66a60a033e44a9e32b2bff
parent8663d6db7fcec2b796d2fbcce0b55f9c10d896e1 (diff)
downloadtask-time-tracker-b968cf38d0c69827dfd1a1a25b4c940b1189df95.tar.zst
task-time-tracker-b968cf38d0c69827dfd1a1a25b4c940b1189df95.zip
Simplified code.
-rw-r--r--main.c160
1 files changed, 72 insertions, 88 deletions
diff --git a/main.c b/main.c
index 6cf24a5..3d6ca66 100644
--- a/main.c
+++ b/main.c
@@ -970,10 +970,10 @@ void draw_tui(database_st *db, layout_st *layout) {
uint64_t total_time = 0;
int column_width;
- // TODO This is some sort of pagination to allow scrolling through the tasks.
- // TODO Review this code.
y = 0;
+ // Pagination based on currently selected task (show page where selected task is).
size_t idx_start = (db->selected_task / layout_tasks_rows) * layout_tasks_rows;
+ // Display up to rows allowed by the layout, or less if reached end of database.
size_t idx_stop = idx_start + (layout_tasks_rows > db->count - idx_start ? db->count - idx_start : layout_tasks_rows);
for (size_t idx = idx_start; idx < idx_stop; idx++) {
task_st *task = &db->tasks[idx];
@@ -1120,12 +1120,12 @@ void exit_gracefully(int signal) {
ungetch('q');
}
-void read_input_to_string_buffer_with_space(int row, int column, int length, int space) {
+void read_input_to_string_buffer_with_space(int row, int column, int style, int length, int space) {
assert(length < string_buffer_size);
assert(space < string_buffer_size);
snprintf(string_buffer, string_buffer_size, "%*s", space, "");
- attron(A_UNDERLINE);
+ attron(style | A_UNDERLINE);
mvaddstr(row, column, string_buffer);
echo();
curs_set(1);
@@ -1133,11 +1133,50 @@ void read_input_to_string_buffer_with_space(int row, int column, int length, int
truncate_string_utf8(string_buffer, length);
noecho();
curs_set(0);
- attroff(A_UNDERLINE);
+ attrset(A_NORMAL);
+}
+
+void read_input_to_string_buffer(int row, int column, int style, int length) {
+ read_input_to_string_buffer_with_space(row, column, style, length, length);
+}
+
+// Returns success.
+bool read_input_to_int(int row, int style, const char *message, intmax_t *result) {
+ assert(message != NULL);
+ assert(result != NULL);
+
+ attron(style);
+ move(row, 1);
+ addch(ACS_CKBOARD);
+ addstr(message);
+ attrset(A_NORMAL);
+
+ // Get line number.
+ int input_pos_x = getcurx(stdscr);
+ int input_width = size_x - input_pos_x - 1;
+ read_input_to_string_buffer(row, input_pos_x, style, input_width);
+
+ char *parser;
+ *result = strtoimax(string_buffer, &parser, 10);
+
+ // TODO Add comment about this comparison... is checking what? - ALSO ADD THIS BELOW
+ // If endptr is not NULL, strtol() stores the address of the first invalid character in *endptr. If there were no digits at all, strtol() stores the original value of nptr in *endptr (and returns 0). In particular, if *nptr is not '\0' but **endptr is '\0' on return, the entire string is valid.
+ return parser != string_buffer;
}
-void read_input_to_string_buffer(int row, int column, int length) {
- read_input_to_string_buffer_with_space(row, column, length, length);
+// Retuns true if user presses enter, false otherwise.
+bool read_enter_confirmation(int row, int style, const char *message) {
+ assert(message != NULL);
+
+ attron(style);
+ move(row, 1);
+ for (int idx = 0; idx < size_x - 2; idx++) {
+ addch(ACS_CKBOARD);
+ }
+ mvaddstr(row, 2, message);
+ attrset(A_NORMAL);
+
+ return getch() == '\n';
}
int main(int argc, char *argv[]) {
@@ -1297,7 +1336,7 @@ int main(int argc, char *argv[]) {
task_st *active_task = get_active_task(db);
task_st *selected_task = get_selected_task(db);
int selected_task_row = is_terminal_too_small ? 0 : (db->selected_task % layout_tasks_rows) + NUM_HEADER_ROWS;
- int selected_task_theme = selected_task == active_task ? STYLE_ACTIVE : STYLE_SELECTED_INVERTED;
+ int action_style = A_BOLD | COLOR_PAIR(selected_task == active_task ? STYLE_ACTIVE : STYLE_SELECTED_INVERTED);
timeout(INPUT_AWAIT_INF);
update_times(&database);
@@ -1370,9 +1409,7 @@ int main(int argc, char *argv[]) {
break;
}
- attron(COLOR_PAIR(selected_task_theme) | A_BOLD);
- read_input_to_string_buffer_with_space(selected_task_row, 1, TASK_NAME_LENGTH, size_x - 2);
- attrset(A_NORMAL);
+ read_input_to_string_buffer_with_space(selected_task_row, 1, action_style, TASK_NAME_LENGTH, size_x - 2);
if (is_empty_string(string_buffer) == false) {
replace_char(string_buffer, '\t', ' ');
@@ -1392,18 +1429,20 @@ int main(int argc, char *argv[]) {
break;
}
- attron(COLOR_PAIR(selected_task_theme) | A_BOLD);
-
- move(selected_task_row, 1);
- for (int idx = 0; idx < size_x - 2; idx++) {
- addch(ACS_CKBOARD);
+ if (read_enter_confirmation(selected_task_row, action_style, " Press enter to reset task. ") == true) {
+ reset_task_times(db, selected_task);
+ trigger_autosave();
+ }
+ break;
+ }
+
+ case KEY_DC: { // Delete
+ if (selected_task == NULL || selected_task == active_task) {
+ break;
}
- mvaddstr(selected_task_row, 2, " Press enter to reset task. ");
-
- attrset(A_NORMAL);
- if (getch() == '\n') {
- reset_task_times(db, selected_task);
+ if (read_enter_confirmation(selected_task_row, action_style, " Press enter to delete task. ") == true) {
+ delete_task(db, selected_task);
trigger_autosave();
}
break;
@@ -1430,20 +1469,19 @@ int main(int argc, char *argv[]) {
input_pos_x++;
// Get time delta.
- attron(COLOR_PAIR(selected_task_theme) | A_BOLD);
- read_input_to_string_buffer(selected_task_row, input_pos_x, input_width);
- attrset(A_NORMAL);
+ read_input_to_string_buffer(selected_task_row, input_pos_x, action_style, input_width);
- // TODO Check if parsed OK. For that, I need to read the manual to know what strtoX returns.
- // TODO It seems that the float parsing may return INF or NAN. Take special care with those.
- // TODO Once I know the parse was OK, I'll check the remaining of the string for multipliers:
+ // TODO Review code
+ /* Check if parsed OK. For that, I need to read the manual to know what strtoX returns.
+ // It seems that the float parsing may return INF or NAN. Take special care with those.
+ // Once I know the parse was OK, I'll check the remaining of the string for multipliers:
// s/S - second (default if none is found)
// m/M - minute
// h/H - hour
// d/D - day
// y/Y - year
+ */
- // TODO Review code
char *input = string_buffer;
if (is_empty_string(input) == true) {
@@ -1510,59 +1548,20 @@ int main(int argc, char *argv[]) {
break;
}
- case KEY_DC: { // Delete
- if (selected_task == NULL || selected_task == active_task) {
- break;
- }
-
- attron(COLOR_PAIR(selected_task_theme) | A_BOLD);
-
- move(selected_task_row, 1);
- for (int idx = 0; idx < size_x - 2; idx++) {
- addch(ACS_CKBOARD);
- }
- mvaddstr(selected_task_row, 2, " Press enter to delete task. ");
-
- attrset(A_NORMAL);
-
- if (getch() == '\n') {
- delete_task(db, selected_task);
- trigger_autosave();
- }
- break;
- }
-
case 'm':
case 'M': {
if (selected_task == NULL) {
break;
}
- attron(COLOR_PAIR(selected_task_theme) | A_BOLD);
- move(selected_task_row, 1);
- addch(ACS_CKBOARD);
- addstr(" Move to: ");
-
- // Get line number.
- int input_pos_x = getcurx(stdscr);
- int input_width = size_x - input_pos_x - 1;
- read_input_to_string_buffer(selected_task_row, input_pos_x, input_width);
- attrset(A_NORMAL);
-
- char *parser; // TODO Rename var.
- intmax_t input = strtoimax(string_buffer, &parser, 10);
-
- // TODO Add comment about this comparison... is checking what? - ALSO ADD THIS BELOW
- // If endptr is not NULL, strtol() stores the address of the first invalid character in *endptr. If there were no digits at all, strtol() stores the original value of nptr in *endptr (and returns 0). In particular, if *nptr is not '\0' but **endptr is '\0' on return, the entire string is valid.
- if (parser == string_buffer) {
+ intmax_t value;
+ if (read_input_to_int(selected_task_row, action_style, " Move to: ", &value) == false) {
break;
}
- ptrdiff_t target_index = (input < 1 ? 1 : input > MAX_DATABASE_TASKS ? MAX_DATABASE_TASKS : input) - 1;
+ ptrdiff_t target_index = (value < 1 ? 1 : value > MAX_DATABASE_TASKS ? MAX_DATABASE_TASKS : value) - 1;
move_task_to_index(db, selected_task, target_index);
-
trigger_autosave();
-
break;
}
@@ -1572,27 +1571,12 @@ int main(int argc, char *argv[]) {
break;
}
- attron(COLOR_PAIR(selected_task_theme) | A_BOLD);
- move(selected_task_row, 1);
- addch(ACS_CKBOARD);
- addstr(" Go to: ");
-
- // Get line number.
- int input_pos_x = getcurx(stdscr);
- int input_width = size_x - input_pos_x - 1;
- read_input_to_string_buffer(selected_task_row, input_pos_x, input_width);
- attrset(A_NORMAL);
-
- char *parser;
- intmax_t input = strtoimax(string_buffer, &parser, 10);
-
- // TODO Add comment about this comparison... is checking what? - ALSO ADD THIS BELOW
- // If endptr is not NULL, strtol() stores the address of the first invalid character in *endptr. If there were no digits at all, strtol() stores the original value of nptr in *endptr (and returns 0). In particular, if *nptr is not '\0' but **endptr is '\0' on return, the entire string is valid.
- if (parser == string_buffer) {
+ intmax_t value;
+ if (read_input_to_int(selected_task_row, action_style, " Go to: ", &value) == false) {
break;
}
- ptrdiff_t target_index = (input < 1 ? 1 : input > MAX_DATABASE_TASKS ? MAX_DATABASE_TASKS : input) - 1;
+ ptrdiff_t target_index = (value < 1 ? 1 : value > MAX_DATABASE_TASKS ? MAX_DATABASE_TASKS : value) - 1;
select_task_by_index(db, target_index);
break;
}