diff options
Diffstat (limited to 'main.c')
| -rw-r--r-- | main.c | 64 |
1 files changed, 52 insertions, 12 deletions
@@ -52,7 +52,6 @@ typedef struct { } task_st; typedef struct { - // TODO Validate usage of size_t and ptrdiff_t variables. task_st *tasks; size_t count; // Will always be equal or less than capacity. size_t capacity; // Will always be equal or less than PTRDIFF_MAX (see MAX_DATABASE_TASKS). @@ -86,7 +85,7 @@ char *db_file_path = NULL; char *ar_file_path = NULL; char *string_buffer = NULL; // A temporary buffer for localized actions. Please avoid data leaks and out-of-bounds errors. size_t string_buffer_size = 0; -int size_x, size_y, pos_x, pos_y; // WIP Validating usage of size_t variables. +int size_x, size_y, pos_x, pos_y; void trigger_autosave() { countdown_to_autosave = 13375; // ms @@ -122,6 +121,8 @@ bool is_equal_to_any(const char *to_compare, const char *test_a, const char *tes size_t truncate_string_utf8(char *string, size_t length) { // TODO Rename to truncate_utf_string assert(string != NULL); + // TODO Review this function... + // Count continuation bytes. size_t idx = length; while (idx > 0 && ((string[idx - 1] & 0xC0) == 0x80)) { @@ -129,14 +130,18 @@ size_t truncate_string_utf8(char *string, size_t length) { // TODO Rename to tru } int continuation_bytes = length - idx; - // Adjust length if missing continuation bytes. - if (idx > 0 // Not empty. - // Continuation bytes are not complete. - && (!(continuation_bytes == 0 && (string[idx - 1] & 0x80) == 0x00) - && !(continuation_bytes == 1 && (string[idx - 1] & 0xE0) == 0xC0) - && !(continuation_bytes == 2 && (string[idx - 1] & 0xF0) == 0xE0) - && !(continuation_bytes == 3 && (string[idx - 1] & 0xF8) == 0xF0)) - ) { + // If string starts with continuation bytes, it's an invalid UTF8 string. + if (idx == 0 && continuation_bytes > 0) { + length = 0; + } + // If length truncates some continuation bytes, remove incomplete UTF8 character. + else if (idx > 0 // string is not empty + // continuation bytes are not complete + && !(continuation_bytes == 0 && (string[idx - 1] & 0x80) == 0x00) + && !(continuation_bytes == 1 && (string[idx - 1] & 0xE0) == 0xC0) + && !(continuation_bytes == 2 && (string[idx - 1] & 0xF0) == 0xE0) + && !(continuation_bytes == 3 && (string[idx - 1] & 0xF8) == 0xF0) + ) { length -= (continuation_bytes + 1); } @@ -144,6 +149,41 @@ size_t truncate_string_utf8(char *string, size_t length) { // TODO Rename to tru return length; } +// TODO Used to test the truncate_string_utf8 +void test_truncate_string_utf8() { + char t_a[] = { (char)0x61, (char)0x3A, (char)0xC3, (char)0xB3, 'a', 0 }; + char t_b[] = { (char)0xC3, (char)0xB3, 0 }; + char t_c[] = { (char)0xB3, 0 }; + char t[1024]; + + fprintf(stderr, "a --- --- ---\n"); + for (int l = 5; l >= 0; l--) { + memset(t, 0, 1024); + memcpy(t, t_a, 6); + fprintf(stderr, "%d : '%s'", l , t); + truncate_string_utf8(t, l); + fprintf(stderr, " '%s'\n", t); + } + + fprintf(stderr, "b --- --- ---\n"); + for (int l = 2; l >= 0; l--) { + memset(t, 0, 1024); + memcpy(t, t_b, 3); + fprintf(stderr, "%d : '%s'", l , t); + truncate_string_utf8(t, l); + fprintf(stderr, " '%s'\n", t); + } + + fprintf(stderr, "c --- --- ---\n"); + for (int l = 1; l >= 0; l--) { + memset(t, 0, 1024); + memcpy(t, t_c, 2); + fprintf(stderr, "%d : '%s'", l , t); + truncate_string_utf8(t, l); + fprintf(stderr, " '%s'\n", t); + } +} + // Returns true when the string is empty or consists of white space characters. bool is_empty_string(char *string) { for (int idx = 0; string[idx] != '\0'; idx++) { @@ -473,7 +513,7 @@ void update_total_times(database_st *db) { int64_t *totals = db->total_times; memset(totals, 0, NUM_WEEK_DAYS * SIZEOF_INT64); - for (size_t idx = 0; idx < db->count; idx++) { // TODO WIP Here may be dragons because of for loop on an unsigned var. + for (size_t idx = 0; idx < db->count; idx++) { int64_t *times = db->tasks[idx].times; totals[0] = add_int64(totals[0], times[0]); totals[1] = add_int64(totals[1], times[1]); @@ -962,7 +1002,7 @@ void draw_tui(database_st *db, layout_st *layout) { int column_width; // TODO This is some sort of pagination to allow scrolling through the tasks. - // TODO How does this behaves when no task is selected? Well! + // TODO Review this code. y = 0; size_t idx_start = (db->selected_task / layout_tasks_rows) * layout_tasks_rows; size_t idx_stop = idx_start + (layout_tasks_rows > db->count - idx_start ? db->count - idx_start : layout_tasks_rows); |
