#include #include #include "todo_list_opaque.h" #include "task.h" typedef struct todo_list_node { task data; struct todo_list_node *prev; struct todo_list_node *next; } todo_list_node; struct todo_list { int size; int completed; todo_list_node *head; todo_list_node *tail; todo_list_node *last_completed; }; todo_list *todo_list_create() { todo_list *list = (todo_list *)malloc(sizeof(todo_list)); if (list != NULL) { list->size = 0; list->completed = 0; list->head = (todo_list_node *)malloc(sizeof(todo_list_node)); // had size of * before! list->tail = (todo_list_node *)malloc(sizeof(todo_list_node)); list->last_completed = list->head; if (list->head != NULL && list->tail != NULL) { list->head->prev = NULL; list->head->next = list->tail; list->tail->prev = list->head; list->tail->next = NULL; } else { free(list->head); free(list->tail); free(list); return NULL; } } return list; } void todo_list_destroy(todo_list *list) { // free all the list nodes todo_list_node *curr = list->head; while (curr != NULL) { todo_list_node *after = curr->next; free(curr); curr = after; } // free the list metadata free(list); } void todo_list_add(todo_list *list, const task *t) { todo_list_node *extra = (todo_list_node *)malloc(sizeof(todo_list_node)); if (extra != NULL) { extra->data = *t; extra->next = list->tail; extra->prev = list->tail->prev; list->tail->prev->next = extra; list->tail->prev = extra; list->size++; } } void todo_list_current(const todo_list *list, task *t) { if (list->completed < list->size) { *t = list->last_completed->next->data; } } bool todo_list_incomplete(const todo_list *list) { return list->size > list->completed; } void todo_list_complete_current(todo_list *list) { list->last_completed = list->last_completed->next; task_complete(&list->last_completed->data); list->completed++; } void todo_list_delay_current(todo_list *list) { if (list->size - list->completed >= 2) { todo_list_node *before = list->last_completed; todo_list_node *curr = list->last_completed->next; todo_list_node *next = curr->next; todo_list_node *after = next->next; before->next = next; next->prev = before; next->next = curr; curr->prev = next; curr->next = after; after->prev = curr; } } void todo_list_postpone_current(todo_list *list) { if (list->size - list->completed >= 2) { todo_list_node *before = list->last_completed; todo_list_node *curr = list->last_completed->next; todo_list_node *after = curr->next; // remove current from list before->next = after; after->prev = before; // place current at end of list curr->prev = list->tail->prev; curr->next = list->tail; list->tail->prev->next = curr; list->tail->prev = curr; } } int todo_list_estimated_time(const todo_list *list) { int tot = 0; todo_list_node *n = list->last_completed->next; while (n != list->tail) { tot += task_time(&n->data); n = n->next; // forgot this 1st time! } return tot; } int todo_list_incomplete_count(const todo_list *list) { return list->size - list->completed; }