aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.c113
-rw-r--r--readme.md17
2 files changed, 63 insertions, 67 deletions
diff --git a/main.c b/main.c
index 1c0356f..e3f6248 100644
--- a/main.c
+++ b/main.c
@@ -107,9 +107,16 @@ bool is_file_accessible(const char *path) {
return is_file_accessible;
}
+// Returns true if string to_compare is equal to any of the other passed strings, false otherwise.
+bool inline static is_equal_to_any(const char *to_compare, const char *test_a, const char *test_b) {
+ return strncmp(to_compare, test_a, strlen(test_a)+1) == 0
+ || strncmp(to_compare, test_b, strlen(test_b)+1) == 0;
+}
+
// Given an UTF8 encoded string, truncate it to length without breaking any UTF8 character.
// The string should have capacity for at least length number of items.
// The terminating null byte ('\0') is included in length.
+// TODO null byte should not be part of the length.
// Returns the amount of items discarded.
size_t truncate_string_utf8(char *string, size_t length) {
@@ -120,7 +127,7 @@ size_t truncate_string_utf8(char *string, size_t length) {
// Search for a non-UTF8-sequence-item so we can truncate the string.
size_t idx = length - 1;
- while(idx > 0 && ((string[idx] & 0xC0) == 0x80)) {
+ while(idx > 0 && ((string[idx] & 0xC0) == 0x80)) { // TODO Only needs to back up 3 items... because of UTF8 being limited to 4bytes
idx--;
}
string[idx] = '\0';
@@ -156,61 +163,50 @@ char *replace_char(char *string, char find, char replace) {
return string;
}
-// Prints time into string using 5 characters centered according to length.
-// The string should have capacity for at least length number of items.
-// The terminating null byte ('\0') is included in length.
-// TODO Should the null byte be included int he length or not?
-char *sprint_time_5cc(char *string, intmax_t time, int length) {
- assert(length >= 6);
-
- int left_padding = (length - 6) / 2;
- int right_padding = length - 6 - left_padding;
-
- if (time >= (intmax_t)(9999.5 * SECONDS_IN_YEAR)) {
- snprintf(string, length, "%*s ∞ %*s",
- left_padding, "",
- right_padding, "");
+// Prints time into string using 5 characters centered on space.
+// The string buffer should be able to store space UTF8 characters plus '\0'.
+char *sprint_time5_utf8(char *string, intmax_t time, int space) {
+ const int TIME_CHARS = 5;
+ assert(space >= TIME_CHARS);
+
+ int buffer_space = space * 4 + 1; // Each that UTF8 char can have 4 bytes.
+ int left_padding = (space - TIME_CHARS) / 2;
+ int right_padding = space - TIME_CHARS - left_padding;
+
+ if (time < 0) {
+ snprintf(string, buffer_space, "%*s - %*s", left_padding, "", right_padding, "");
}
- else if (time >= (intmax_t)(9999.5 * SECONDS_IN_DAY)) {
- double value = (double)time / (double)SECONDS_IN_YEAR;
- int decimals =
- time >= 99.95 * SECONDS_IN_YEAR ? 0 :
- time >= 9.995 * SECONDS_IN_YEAR ? 1 :
- 2;
-
- snprintf(string, length, "%*s%4.*fy%*s",
- left_padding, "",
- decimals,
- value,
- right_padding, "");
+ else if (time == 0) {
+ snprintf(string, buffer_space, "%*s 0 %*s", left_padding, "", right_padding, "");
+ }
+ else if (time < SECONDS_IN_MINUTE) {
+ snprintf(string, buffer_space, "%*s%3jds %*s", left_padding, "", time, right_padding, "");
+ }
+ else if (time < (intmax_t)100 * SECONDS_IN_HOUR) {
+ intmax_t hours = (double)time / (double)SECONDS_IN_HOUR;
+ intmax_t minutes = (time - (hours * SECONDS_IN_HOUR) ) / SECONDS_IN_MINUTE;
+ snprintf(string, buffer_space, "%*s%02jd:%02jd%*s", left_padding, "", hours, minutes, right_padding, "");
}
- else if (time >= (intmax_t)100 * SECONDS_IN_HOUR) {
+ else if (time < (intmax_t)(9999.5 * SECONDS_IN_DAY)) {
double value = (double)time / (double)SECONDS_IN_DAY;
int decimals =
time >= 99.95 * SECONDS_IN_DAY ? 0 :
time >= 9.995 * SECONDS_IN_DAY ? 1 :
2;
-
- snprintf(string, length, "%*s%4.*fd%*s",
- left_padding, "",
- decimals,
- value,
- right_padding, "");
- }
- else if (time >= SECONDS_IN_MINUTE) {
- intmax_t hours = (double)time / (double)SECONDS_IN_HOUR;
- intmax_t minutes = (time - (hours * SECONDS_IN_HOUR) ) / SECONDS_IN_MINUTE;
- snprintf(string, length, "%*s%02jd:%02jd%*s", left_padding, "", hours, minutes, right_padding, "");
+ snprintf(string, buffer_space, "%*s%4.*fd%*s", left_padding, "", decimals, value, right_padding, "");
}
- else if (time > 0) {
- snprintf(string, length, "%*s%3jds %*s", left_padding, "", time, right_padding, "");
- }
- else if (time == 0) {
- snprintf(string, length, "%*s 0 %*s", left_padding, "", right_padding, "");
+ else if (time < (intmax_t)(9999.5 * SECONDS_IN_YEAR)) {
+ double value = (double)time / (double)SECONDS_IN_YEAR;
+ int decimals =
+ time >= 99.95 * SECONDS_IN_YEAR ? 0 :
+ time >= 9.995 * SECONDS_IN_YEAR ? 1 :
+ 2;
+ snprintf(string, buffer_space, "%*s%4.*fy%*s", left_padding, "", decimals, value, right_padding, "");
}
else {
- snprintf(string, length, "%*s - %*s", left_padding, "", right_padding, "");
+ snprintf(string, buffer_space, "%*s ∞ %*s", left_padding, "", right_padding, "");
}
+
return string;
}
@@ -989,14 +985,14 @@ void draw_tui(database_st *db, layout_st *layout) {
column_width = layout->columns[L_DAYS_IDX + day_idx].width;
int64_t task_stime = task->times[day_idx];
total_time = add_int64(total_time, task_stime);
- sprint_time_5cc(string_buffer, task_stime, column_width + 1);
+ sprint_time5_utf8(string_buffer, task_stime, column_width);
mvaddstr(y, x, string_buffer);
x += column_width;
}
// Task total.
x++;
- sprint_time_5cc(string_buffer, total_time, layout->columns[L_TOTAL_IDX].width + 1);
+ sprint_time5_utf8(string_buffer, total_time, layout->columns[L_TOTAL_IDX].width);
mvaddstr(y, x, string_buffer);
// Reset theme.
@@ -1024,7 +1020,7 @@ void draw_tui(database_st *db, layout_st *layout) {
column_width = layout->columns[L_DAYS_IDX + idx].width;
total_time = add_int64(total_time, daily_total);
- sprint_time_5cc(string_buffer, daily_total, column_width + 1);
+ sprint_time5_utf8(string_buffer, daily_total, column_width);
// Apply theme.
if (idx == now_week_day && active_task != NULL) {
@@ -1041,7 +1037,7 @@ void draw_tui(database_st *db, layout_st *layout) {
attrset(A_NORMAL);
}
x++;
- sprint_time_5cc(string_buffer, total_time, layout->columns[L_TOTAL_IDX].width + 1);
+ sprint_time5_utf8(string_buffer, total_time, layout->columns[L_TOTAL_IDX].width);
mvaddstr(y, x, string_buffer);
}
@@ -1116,15 +1112,6 @@ void exit_gracefully(int signal) {
ungetch('q');
}
-// Returns true if any of the action parameters is equal to arg, false otherwise.
-bool is_action_detected(const char *arg, const char *action_name, const char *action_abbreviation) {
- assert(arg != NULL);
- assert(action_name != NULL);
- assert(action_abbreviation != NULL);
-
- return strncmp(arg, action_name, strlen(action_name)+1) == 0
- || strncmp(arg, action_abbreviation, strlen(action_abbreviation)+1) == 0;
-}
int main(int argc, char *argv[]) {
@@ -1147,7 +1134,7 @@ int main(int argc, char *argv[]) {
if (argc > 1) {
bool is_exit_requested = false;
for (unsigned idx = 1; idx < argc; idx++) {
- if (is_action_detected(argv[idx], "--help", "-h")) {
+ if (is_equal_to_any(argv[idx], "--help", "-h")) {
// TODO Maybe rearrange the order of the command.
fprintf(stdout,
"Usage: ttt [OPTION]... [FILE]...\n"
@@ -1188,13 +1175,13 @@ int main(int argc, char *argv[]) {
return EXIT_SUCCESS;
}
- if (is_action_detected(argv[idx], "--version", "-v")) {
+ if (is_equal_to_any(argv[idx], "--version", "-v")) {
fprintf(stdout, "Task Time Tracker version " VERSION "\n");
free_memory();
return EXIT_SUCCESS;
}
- if (is_action_detected(argv[idx], "--import-csv", "-i")) {
+ if (is_equal_to_any(argv[idx], "--import-csv", "-i")) {
idx++;
if (idx >= argc) {
fprintf(stdout, "Missing CSV file path to import.\n");
@@ -1210,7 +1197,7 @@ int main(int argc, char *argv[]) {
continue;
}
- if (is_action_detected(argv[idx], "--export-csv", "-e")) {
+ if (is_equal_to_any(argv[idx], "--export-csv", "-e")) {
idx++;
if (idx >= argc) {
fprintf(stdout, "Missing CSV file path to export.\n");
@@ -1225,7 +1212,7 @@ int main(int argc, char *argv[]) {
continue;
}
- if (is_action_detected(argv[idx], "--no-autosave", "-n")) {
+ if (is_equal_to_any(argv[idx], "--no-autosave", "-n")) {
is_autosave_enabled = false;
continue;
}
diff --git a/readme.md b/readme.md
index 9ac479c..0d70120 100644
--- a/readme.md
+++ b/readme.md
@@ -59,9 +59,18 @@ Task Time Tracker
- [x] Check if string_buffer needs to be cleared. We may be leaking info on the string_buffer.
- [x] Replaced `sprintf` by `snprintf`;
- [x] Make sure that string_buffer bounds are respected;
-- [ ] Move database actions into functions:
- - [ ] select_by_id/delta/task
- - [ ] set_active(db, task)
-- [ ] Re-check if draw_tui may be simplified.
+- [ ] Compress code:
+ - [x] Re-do sprint_time5_utf8: -12 LOC;
+ - [ ] Re-do truncate_string_utf8: 1761 - XXXX = LOC;
+ - [ ] Get input using `get_input(char *input, size_t size, int row, int column)` (what does it returns???):
+ - [ ] wrap malloc (and maybe others) in a function with error checking
+ ```c
+ static inline void *MallocOrDie(size_t MemSize) { void *AllocMem = malloc(MemSize); /* Some implementations return null on a 0 length alloc, * we may as well allow this as it increases compatibility * with very few side effects */ if(!AllocMem && MemSize) { printf("Could not allocate memory!"); exit(-1); } return AllocMem; }
+ ```
+ - [ ] Move database actions into functions:
+ - `select_task_by_delta(database_st *db, ptrdiff???)`
+ - `select_task_by_index(database_st *db, size_t???)`
+ - `sect_active(database_st *db, task_st *task)`
+ - [ ] Check if draw_tui may be simplified by drawing entire lines of tasks at once and draw columns separators after;
- [ ] Review all code for bugs related to auto-cast on ptrdiff_t/size_t (signed/unsigned);
- [ ] Go over all `TODO` items;