{
return (date_t){
.year = time.year,
- .month = time.month-1,
- .day = time.day-1,
+ .month = time.month ? time.month-1 : 0,
+ .day = time.day ? time.day -1 : 0,
.hour = time.hour,
.min = time.minute,
};
}
-static event_t *to_event(ical_inst *inst)
-{
- icalproperty *prop = icalcomponent_get_first_property(inst->comp, ICAL_CATEGORIES_PROPERTY);
-
- event_t *event = calloc(1, sizeof(event_t));
- event->name = icalcomponent_get_summary(inst->comp);
- event->desc = icalcomponent_get_description(inst->comp);
- event->loc = icalcomponent_get_location(inst->comp);
- event->cat = icalproperty_get_value_as_string(prop);
- event->start = to_date(inst->start);
- event->end = to_date(inst->end);
- return event;
-}
-
-static event_t *to_list(icalarray *array)
-{
- event_t list = {};
- event_t *tail = &list;
- for (int i = 0; i < array->num_elements; i++) {
- ical_inst *inst = icalarray_element_at(array, i);
- tail->next = to_event(inst);
- tail = tail->next;
- }
- return list.next;
-}
-
-static void print_list(event_t *start)
-{
- for (event_t *cur = start; cur; cur = cur->next)
- printf("%04d-%02d-%02d %02d:%02d - %s\n",
- cur->start.year, cur->start.month, cur->start.day,
- cur->start.hour, cur->start.min,
- cur->name ?: cur->desc ?: "[no summary]");
-}
-
-static void add_events(icalarray *array, icalcomponent *comp,
- icaltimetype start, icaltimetype end)
+static void add_recur(icalarray *array, icalcomponent *comp,
+ icaltimetype start, icaltimetype end,
+ icalcomponent_kind which)
{
icalcomponent_kind kind = icalcomponent_isa(comp);
- if (kind == ICAL_VEVENT_COMPONENT ||
- kind == ICAL_VTODO_COMPONENT) {
+ if (kind == which) {
/* Get recurrence data */
struct icaltimetype cstart, cend; // Component times
struct icaltimetype istart, iend; // Instance times
iter = icalrecur_iterator_new(recur, cstart);
/* Add recurrences */
- while (1) {
- istart = icalrecur_iterator_next(iter);
+ if (icaltime_is_null_time(cstart) ||
+ which == ICAL_VTODO_COMPONENT) {
+ icalarray_append(array, &(ical_inst){
+ .comp = comp,
+ .start = cstart,
+ .end = cend,
+ });
+ } else while (1) {
+ istart = iend = icalrecur_iterator_next(iter);
if (icaltime_is_null_time(istart))
break; // no more instances
- iend = icaltime_add(istart, length);
+ if (!icaltime_is_null_time(cend))
+ iend = icaltime_add(iend, length);
+
if (icaltime_compare(iend, start) <= 0)
continue; // instance ends before start time
if (icaltime_compare(istart, end) >= 0)
break; // instance begins after stop time
+
icalarray_append(array, &(ical_inst){
.comp = comp,
.start = istart,
icalcomponent_kind find = ICAL_ANY_COMPONENT;
icalcomponent *child = icalcomponent_get_first_component(comp, find);
while (child) {
- add_events(array, child, start, end);
+ add_recur(array, child, start, end, which);
child = icalcomponent_get_next_component(comp, find);
}
}
+/* Event functions */
+static event_t *to_event(ical_inst *inst)
+{
+ icalproperty *prop = icalcomponent_get_first_property(inst->comp, ICAL_CATEGORIES_PROPERTY);
+
+ event_t *event = calloc(1, sizeof(event_t));
+ event->name = icalcomponent_get_summary(inst->comp);
+ event->desc = icalcomponent_get_description(inst->comp);
+ event->loc = icalcomponent_get_location(inst->comp);
+ event->cat = icalproperty_get_value_as_string(prop);
+ event->start = to_date(inst->start);
+ event->end = to_date(inst->end);
+ return event;
+}
+
+static event_t *to_events(icalarray *array)
+{
+ event_t list = {};
+ event_t *tail = &list;
+ for (int i = 0; i < array->num_elements; i++) {
+ ical_inst *inst = icalarray_element_at(array, i);
+ tail->next = to_event(inst);
+ tail = tail->next;
+ }
+ return list.next;
+}
+
+static void print_events(event_t *start)
+{
+ for (event_t *cur = start; cur; cur = cur->next)
+ printf("%04d-%02d-%02d %02d:%02d - %s\n",
+ cur->start.year, cur->start.month, cur->start.day,
+ cur->start.hour, cur->start.min,
+ cur->name ?: cur->desc ?: "[no summary]");
+}
+
+/* Todo functions */
+static todo_t *to_todo(ical_inst *inst)
+{
+ icalproperty *cat = icalcomponent_get_first_property(inst->comp, ICAL_CATEGORIES_PROPERTY);
+ icalproperty *perc = icalcomponent_get_first_property(inst->comp, ICAL_PERCENTCOMPLETE_PROPERTY);
+
+ todo_t *todo = calloc(1, sizeof(todo_t));
+ todo->name = icalcomponent_get_summary(inst->comp);
+ todo->desc = icalcomponent_get_description(inst->comp);
+ todo->cat = icalproperty_get_value_as_string(cat);
+ todo->status = icalcomponent_get_status(inst->comp) == ICAL_STATUS_COMPLETED ? 100 :
+ perc ? icalproperty_get_percentcomplete(perc) : 0;
+ todo->start = to_date(inst->start);
+ todo->due = to_date(icalcomponent_get_due(inst->comp));
+ return todo;
+}
+
+static todo_t *to_todos(icalarray *array)
+{
+ todo_t list = {};
+ todo_t *tail = &list;
+ for (int i = 0; i < array->num_elements; i++) {
+ ical_inst *inst = icalarray_element_at(array, i);
+ tail->next = to_todo(inst);
+ tail = tail->next;
+ }
+ return list.next;
+}
+
+static void print_todos(todo_t *start)
+{
+ for (todo_t *cur = start; cur; cur = cur->next)
+ printf("%04d-%02d-%02d %02d:%02d - %d%% - %s\n",
+ cur->due.year, cur->due.month, cur->due.day,
+ cur->due.hour, cur->due.min, cur->status,
+ cur->name ?: cur->desc ?: "[no summary]");
+}
+
/* Event functions */
event_t *ical_events(cal_t *cal, year_t year, month_t month, day_t day, int days)
{
icalarray *array = icalarray_new(sizeof(ical_inst), 1);
icaltimetype start = {.year = 2000};
icaltimetype end = {.year = 2020};
- add_events(array, ical, start, end);
+ add_recur(array, ical, start, end, ICAL_VEVENT_COMPONENT);
icalarray_sort(array, ical_compare);
- return to_list(array);
+ return to_events(array);
/* Todo, memory management */
}
/* Todo functions */
todo_t *ical_todos(cal_t *cal, year_t year, month_t month, day_t day, int days)
{
- return NULL;
+ /* Load ical */
+ FILE *file = fopen("data/all.ics", "r");
+ if (!file)
+ return NULL;
+ icalparser *parser = icalparser_new();
+ icalparser_set_gen_data(parser, file);
+ icalcomponent *ical = icalparser_parse(parser, (void*)fgets);
+
+ /* Add todos */
+ icalarray *array = icalarray_new(sizeof(ical_inst), 1);
+ icaltimetype start = {.year = 2000};
+ icaltimetype end = {.year = 2020};
+ add_recur(array, ical, start, end, ICAL_VTODO_COMPONENT);
+ icalarray_sort(array, ical_compare);
+ return to_todos(array);
+
+ /* Todo, memory management */
}
/* Test functions */
icalparser_set_gen_data(parser, file);
icalcomponent *ical = icalparser_parse(parser, (void*)fgets);
- /* Test print */
- ical_printr(ical, 0);
-
- /* Test Add */
- icalarray *array = icalarray_new(sizeof(ical_inst), 1);
+ /* Misc */
+ icalarray *array;
icaltimetype start = {.year = 2000};
icaltimetype end = {.year = 2020};
- add_events(array, ical, start, end);
+
+ /* Find events */
+ array = icalarray_new(sizeof(ical_inst), 1);
+ add_recur(array, ical, start, end, ICAL_VEVENT_COMPONENT);
+ icalarray_sort(array, ical_compare);
+ event_t *events = to_events(array);
+
+ /* Find Todos */
+ array = icalarray_new(sizeof(ical_inst), 1);
+ add_recur(array, ical, start, end, ICAL_VTODO_COMPONENT);
icalarray_sort(array, ical_compare);
- event_t *events = to_list(array);
- print_list(events);
+ todo_t *todos = to_todos(array);
+
+ /* Print */
+ //ical_printr(ical, 0);
+ //print_events(events);
+ print_todos(todos);
+
+ (void)print_events;
+ (void)print_todos;
+ (void)events;
+ (void)todos;
/* Cleanup */
icalparser_free(parser);
void todo_line(WINDOW *win, todo_t *todo, int y, int x, int w, int full)
{
char perc[16];
+ char desc[LINES];
sprintf(perc, "%2d%%", todo->status);
- int color = get_color(todo->cat);
- if (color) wattron(win, COLOR_PAIR(color));
- mvwaddch(win, y, 2, ACS_BLOCK);
- if (color) wattroff(win, COLOR_PAIR(color));
+ int cat = get_color(todo->cat);
+ int status = todo->status == NEW ? COLOR_NEW :
+ todo->status == DONE ? COLOR_DONE : COLOR_WIP;
+
+ sprintf(desc, "%s", todo->name ?: todo->desc ?: "");
+ strsub(desc, '\n', ';');
+
+ /* Print category */
+ if (cat) wattron(win, COLOR_PAIR(cat));
+ mvwaddch(win, y, x, ACS_BLOCK);
+ if (cat) wattroff(win, COLOR_PAIR(cat));
+ x += 2;
- mvwprintw(win, y, 4, "%04d-%02d-%02d %2d:%02d",
+ /* Print time */
+ mvwprintw(win, y, x, "%04d-%02d-%02d %2d:%02d",
todo->due.year, todo->due.month+1, todo->due.day+1,
todo->due.hour, todo->due.min);
- mvwprintw(win, y, 22, "%s",
- todo->status == NEW ? "new" :
- todo->status == DONE ? "done" : perc);
- mvwprintw(win, y, 30, "%s: %s", todo->name, todo->desc);
+ x += 18;
+
+ /* Print status */
+ if (status) wattron(win, COLOR_PAIR(status));
+ mvwprintw(win, y, x, "%s",
+ todo->status == NEW ? "new" :
+ todo->status == DONE ? "done" : perc);
+ if (status) wattroff(win, COLOR_PAIR(status));
+ x += 6;
+
+ /* Print description */
+ mvwprintw(win, y, x, "%s", desc);
}
/* View init */
/* Static data */
static WINDOW *win;
+static int line;
+static int rows;
static int show_new = 1;
static int show_started = 1;
static int show_finished = 1;
/* Helper functions */
-static int print_todos(WINDOW *win, int y, todo_t *todos, status_t low, status_t high)
+static int print_todos(WINDOW *win, int row, todo_t *todos, status_t low, status_t high)
{
int n = 0;
for (todo_t *cur = todos; cur; cur = cur->next)
if (low <= cur->status && cur->status <= high)
- todo_line(win, cur, y+n++, 2, COLS-2, 1);
+ todo_line(win, cur, row+n++, 4, COLS-4, 1);
return n;
}
-static int print_group(WINDOW *win, int y, todo_t *todos,
+static int print_group(WINDOW *win, int row, todo_t *todos,
int show, const char *label, status_t low, status_t high)
{
int n = 1;
/* Label */
- mvwprintw(win, y, 0, "%s", label);
+ mvwprintw(win, row, 0, "%s", label);
/* Todos */
if (show)
- n = print_todos(win, y+1, todos, low, high);
+ n = print_todos(win, row+1, todos, low, high);
/* Status */
if (!show)
- mvwprintw(win, y+1, 4, "[hidden]");
+ mvwprintw(win, row+1, 4, "[hidden]");
if (n == 0)
- mvwprintw(win, y+1, 4, "[no tasks]");
+ mvwprintw(win, row+1, 4, "[no tasks]");
- return y+1+MAX(n,1)+1;
+ return row+1+MAX(n,1)+1;
}
/* Todo init */
/* Todo draw */
void todo_draw(void)
{
- int y = 0;
+ int row = -line;
- y = print_group(win, y, TODOS,
+ row = print_group(win, row, TODOS,
show_new, "New Tasks", NEW, NEW);
- y = print_group(win, y, TODOS,
+ row = print_group(win, row, TODOS,
show_started, "Started Tasks", NEW+1, DONE-1);
- y = print_group(win, y, TODOS,
+ row = print_group(win, row, TODOS,
show_finished, "Finished Tasks", DONE, DONE);
+
+ rows = row+line-1;
}
/* Todo run */
int todo_run(int key, mmask_t btn, int row, int col)
{
- int ref = 0;
+ int scroll = 0, ref = 0;
switch (key)
{
+ case 'g': ref = 1; scroll = -line; break;
+ case 'G': ref = 1; scroll = rows; break;
+ case 'j': ref = 1; scroll = 1; break;
+ case 'k': ref = 1; scroll = -1; break;
case 'n': ref = 1; show_new ^= 1; break;
case 's': ref = 1; show_started ^= 1; break;
case 'f': ref = 1; show_finished ^= 1; break;
}
+ line = CLAMP(line+scroll, 0, rows-1);
if (ref) {
werase(win);
todo_draw();