diary

Text-based journaling program
git clone https://git.in0rdr.ch/diary.git
Log | Files | Refs | README | LICENSE

commit 451f5028e4c15584c5ca602a460261e92154a388
parent 74e6e2ac35359713fe7e5c2f5996202dd41b094a
Author: Andreas Gruhler <agruhl@gmx.ch>
Date:   Sun, 17 Oct 2021 23:17:13 +0200

confirm and write to files

Diffstat:
Msrc/import.c | 92++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
Msrc/import.h | 6+++++-
Msrc/utils.c | 57++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/utils.h | 3+++
4 files changed, 146 insertions(+), 12 deletions(-)

diff --git a/src/import.c b/src/import.c @@ -1,8 +1,14 @@ #include "import.h" /* Import journal entries from an ics file */ -void ics_import(const char* ics_input) { +void ics_import(const char* ics_input, WINDOW* header, WINDOW* cal, WINDOW* aside, int* pad_pos, struct tm* curs_date, struct tm* cal_start, struct tm* cal_end) { + pthread_t progress_tid; + FILE* pfile = fopen(ics_input, "r"); + if (pfile == NULL) { + perror("Error opening file"); + return; + } fseek(pfile, 0, SEEK_END); long ics_bytes = ftell(pfile) + 1; @@ -15,30 +21,96 @@ void ics_import(const char* ics_input) { ics[ics_bytes] = 0; // fprintf(stderr, "Import ICS file: %s\n", ics); - // find all VEVENTs + int conf_ch = 0; + char dstr[16]; + struct tm date; long search_pos = 0; char *i = ics; char* vevent; - char* date; - char* desc; + char* vevent_date; + char* vevent_desc; + // find all VEVENTs and write to files for (;;) { vevent = extract_ical_field(i, "BEGIN:VEVENT", &search_pos, false); + vevent_date = extract_ical_field(i, "DTSTART", &search_pos, false); + vevent_desc = extract_ical_field(i, "DESCRIPTION", &search_pos, true); if (vevent == NULL) { break; } - // date = extract_ical_field((ics+search_pos), "DTSTART", &search_pos, false); - desc = extract_ical_field(i, "DESCRIPTION", &search_pos, true); + + i += search_pos; + + fprintf(stderr, "VEVENT DESCRIPTION: \n\n%s\n\n", vevent_desc); + + // parse date + strptime(vevent_date, "%Y%m%dT%H%M%SZ", &date); + strftime(dstr, sizeof dstr, CONFIG.fmt, &date); + + // get path of entry + char path[100]; + char* ppath = path; + fpath(CONFIG.dir, strlen(CONFIG.dir), &date, &ppath, sizeof path); + fprintf(stderr, "Import date file path: %s\n", path); + + if (conf_ch != 'a') { + // prepare header for confirmation dialogue + curs_set(2); + noecho(); + wclear(header); + + // ask for confirmation + mvwprintw(header, 0, 0, "Import entry '%s' and overwrite local file? [(Y)es/(a)ll/(n)o/(c)ancel] ", dstr); + conf_ch = wgetch(header); + } + + if (conf_ch == 'y' || conf_ch == 'Y' || conf_ch == 'a' || conf_ch == '\n') { + pthread_create(&progress_tid, NULL, show_progress, (void*)header); + + // persist VEVENT to local file + FILE* cursordate_file = fopen(path, "wb"); + if (cursordate_file == NULL) { + perror("Failed to open import date file"); + } else { + for (char* j = vevent_desc; *j != '\0'; j++) { + if (vevent_desc[j-vevent_desc] == 0x5C) { // backslash + switch (*(j+1)) { + case 'n': + fputc('\n', cursordate_file); + j++; + break; + case 0x5c: // preserve real backslash + fputc(0x5c, cursordate_file); + j++; + break; + } + } else { + fputc(*j, cursordate_file); + } + } + fclose(cursordate_file); + + // add new entry highlight + go_to(cal, aside, mktime(&date), pad_pos, curs_date, cal_start, cal_end); + // update_date(header, curs_date); + chtype atrs = winch(cal) & A_ATTRIBUTES; + wchgat(cal, 2, atrs | A_BOLD, 0, NULL); + prefresh(cal, *pad_pos, 0, 1, ASIDE_WIDTH, LINES - 1, ASIDE_WIDTH + CAL_WIDTH); + pthread_cancel(progress_tid); + } + } else if (conf_ch == 'c') { + // cancel all + break; + } + // fprintf(stderr, "Import DTSTART: %s\n", desc); // fprintf(stderr, "Import DESCRIPTION: %s\n", desc); fprintf(stderr, "* * * * * * * * * * * * * \n"); free(vevent); - // free(date); - free(desc); - - i += search_pos; + free(vevent_date); + free(vevent_desc); } free(ics); } \ No newline at end of file diff --git a/src/import.h b/src/import.h @@ -1,12 +1,16 @@ #ifndef DIARY_IMPORT_H #define DIARY_IMPORT_H +#define __USE_XOPEN +#define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <regex.h> #include <stdbool.h> +#include <time.h> +#include <pthread.h> #include "utils.h" -void ics_import(const char* ics_input); +void ics_import(const char* ics_input, WINDOW* header, WINDOW* cal, WINDOW* aside, int* pad_pos, struct tm* curs_date, struct tm* cal_start, struct tm* cal_end); #endif \ No newline at end of file diff --git a/src/utils.c b/src/utils.c @@ -272,7 +272,7 @@ char* extract_ical_field(const char* ics, char* key, long* start_pos, bool multi // empty remote value buf = NULL; } else if (multiline) { - buf = unfold(icscp + *start_pos); + buf = unfold(ics + *start_pos); } else { buf = malloc(strlen(res) + 1); if (buf == NULL) { @@ -350,6 +350,61 @@ void fpath(const char* dir, size_t dir_size, const struct tm* date, char** rpath strcat(*rpath, dstr); } +bool go_to(WINDOW* calendar, WINDOW* aside, time_t date, int* cur_pad_pos, struct tm* curs_date, struct tm* cal_start, struct tm* cal_end) { + if (date < mktime(cal_start) || date > mktime(cal_end)) + return false; + + int diff_seconds = date - mktime(cal_start); + int diff_days = diff_seconds / 60 / 60 / 24; + int diff_weeks = diff_days / 7; + int diff_wdays = diff_days % 7; + + localtime_r(&date, curs_date); + + int cy, cx; + getyx(calendar, cy, cx); + + // remove the STANDOUT attribute from the day we are leaving + chtype current_attrs = mvwinch(calendar, cy, cx) & A_ATTRIBUTES; + // leave every attr as is, but turn off STANDOUT + current_attrs &= ~A_STANDOUT; + mvwchgat(calendar, cy, cx, 2, current_attrs, 0, NULL); + + // add the STANDOUT attribute to the day we are entering + chtype new_attrs = mvwinch(calendar, diff_weeks, diff_wdays * 3) & A_ATTRIBUTES; + new_attrs |= A_STANDOUT; + mvwchgat(calendar, diff_weeks, diff_wdays * 3, 2, new_attrs, 0, NULL); + + if (diff_weeks < *cur_pad_pos) + *cur_pad_pos = diff_weeks; + if (diff_weeks > *cur_pad_pos + LINES - 2) + *cur_pad_pos = diff_weeks - LINES + 2; + prefresh(aside, *cur_pad_pos, 0, 1, 0, LINES - 1, ASIDE_WIDTH); + prefresh(calendar, *cur_pad_pos, 0, 1, ASIDE_WIDTH, LINES - 1, ASIDE_WIDTH + CAL_WIDTH); + + return true; +} + + +void* show_progress(void* vargp){ + WINDOW* header = (WINDOW*) vargp; + mvwprintw(header, 0, COLS - CAL_WIDTH - ASIDE_WIDTH - 11, " syncing "); + for(;;) { + mvwprintw(header, 0, COLS - CAL_WIDTH - ASIDE_WIDTH - 10, "|"); + wrefresh(header); + usleep(200000); + mvwprintw(header, 0, COLS - CAL_WIDTH - ASIDE_WIDTH - 10, "/"); + wrefresh(header); + usleep(200000); + mvwprintw(header, 0, COLS - CAL_WIDTH - ASIDE_WIDTH - 10, "-"); + wrefresh(header); + usleep(200000); + mvwprintw(header, 0, COLS - CAL_WIDTH - ASIDE_WIDTH - 10, "\\"); + wrefresh(header); + usleep(200000); + } +} + config CONFIG = { .range = 1, .weekday = 1, diff --git a/src/utils.h b/src/utils.h @@ -3,6 +3,7 @@ #include <regex.h> #include <stdio.h> +#include <unistd.h> #include <stdlib.h> #include <time.h> #include <string.h> @@ -30,6 +31,8 @@ char* extract_ical_field(const char* ical, char* key, long* start_pos, bool mult char* expand_path(const char* str); char* strrstr(char *haystack, char *needle); void fpath(const char* dir, size_t dir_size, const struct tm* date, char** rpath, size_t rpath_size); +bool go_to(WINDOW* calendar, WINDOW* aside, time_t date, int* cur_pad_pos, struct tm* curs_date, struct tm* cal_start, struct tm* cal_end); +void* show_progress(void* vargp); typedef struct {