diary

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

export.c (5273B)


      1 #include "export.h"
      2 
      3 /* Export journal entries to an ics file */
      4 void ics_export(const char* ics_filepath, WINDOW* header, WINDOW* cal, WINDOW* aside, int* pad_pos, struct tm* curs_date, struct tm* cal_start, struct tm* cal_end){
      5     pthread_t progress_tid;
      6     int conf_ch;
      7 
      8     char* veventsr;
      9     char* vevent_format = "BEGIN:VEVENT\n"
     10                    "UID:%s\n"
     11                    "DTSTART;VALUE=DATE:%s\n"
     12                    "SUMMARY:%s\n"
     13                    "%s\n"
     14                    "END:VEVENT\n";
     15 
     16     size_t begin_size = strlen("BEGIN:VCALENDAR\n");
     17     char* vevents = calloc(begin_size + 1, sizeof(char));
     18     strcat(vevents, "BEGIN:VCALENDAR\n");
     19 
     20     // prepare header for confirmation dialogue
     21     curs_set(2);
     22     noecho();
     23     wclear(header);
     24 
     25     // ask for confirmation
     26     mvwprintw(header, 0, 0, "Export diary entries to file '%s' (overwrite)? [(Y)es/(n)o] ", ics_filepath);
     27 
     28     do {
     29         conf_ch = wgetch(header);
     30 
     31         if (conf_ch == 'n') {
     32             return;
     33         } else if (conf_ch == 'y' || conf_ch == 'Y' || conf_ch == '\n') {
     34             // open ics file for writing
     35             FILE* pfile = fopen(ics_filepath, "wb");
     36             if (pfile == NULL) {
     37                 perror("Error opening ics file for writing");
     38                 return;
     39             }
     40 
     41             pthread_create(&progress_tid, NULL, show_progress, (void*)header);
     42             pthread_detach(progress_tid);
     43 
     44             struct tm it = *cal_start;
     45             time_t it_time = mktime(&it);
     46             time_t end_time = mktime(cal_end);
     47             size_t dirs = strlen(CONFIG.dir);
     48 
     49             for( ; it_time <= end_time; it_time = mktime(&it)) {
     50                 localtime_r(&it_time, &it);
     51 
     52                 if (date_has_entry(CONFIG.dir, dirs, &it)) {
     53                     // get path of entry
     54                     char path[100];
     55                     char* ppath = path;
     56                     char* descr;
     57                     long descr_bytes;
     58 
     59                     fpath(CONFIG.dir, dirs, &it, &ppath, sizeof path);
     60 
     61                     if (ppath == NULL) {
     62                         tracepoint(diary, error_date, "Cannot get file path for entry", &it);
     63                         return;
     64                     }
     65 
     66                     FILE* fp = fopen(path, "r");
     67                     if (fp == NULL) perror("Error opening entry path for reading");
     68 
     69                     fseek(fp, 0, SEEK_END);
     70                     descr_bytes = ftell(fp);
     71                     rewind(fp);
     72 
     73                     size_t descr_label_size = strlen("DESCRIPTION:");
     74                     size_t descr_size = descr_bytes + descr_label_size;
     75                     descr = calloc(descr_size + 1, sizeof(char));
     76                     if (descr == NULL) {
     77                         perror("malloc failed");
     78                         return;
     79                     }
     80 
     81                     strcat(descr, "DESCRIPTION:");
     82 
     83                     // read description bytes from journal entry file and append to descr
     84                     int items_read = fread(descr + descr_label_size, sizeof(char), descr_bytes, fp);
     85                     if (items_read != descr_bytes) {
     86                         tracepoint(diary, error_int_long, "Read n items but expected m items, aborting.", items_read, descr_bytes);
     87                         return;
     88                     }
     89 
     90                     descr[descr_size] = '\0';
     91 
     92                     char* folded_descr = fold(descr);
     93 
     94                     char uid[9];
     95                     strftime(uid, sizeof uid, "%Y%m%d", &it);
     96 
     97                     char* vevent = calloc(strlen(vevent_format) + strlen(folded_descr) + 100, sizeof(char));
     98                     sprintf(vevent, vevent_format,
     99                             uid,
    100                             uid,
    101                             uid, // todo: display first few chars of DESCRIPTION as SUMMARY
    102                             folded_descr);
    103 
    104                     veventsr = realloc(vevents, strlen(vevents) + strlen(vevent) + 1);
    105                     if (veventsr == NULL) {
    106                         perror("failed to realloc vevents buffer");
    107                         free(vevents);
    108                         break;
    109                     } else {
    110                         // vevents ptr already freed by realloc if moved
    111                         vevents = (char*) veventsr;
    112                         // append vevent to vevents buffer
    113                         strcat(vevents, vevent);
    114                     }
    115 
    116                     free(folded_descr);
    117                     free(descr);
    118                     free(vevent);
    119                 } // end date_has_entry
    120 
    121                 it.tm_mday++;
    122             } // endfor each entry
    123 
    124             veventsr = realloc(vevents, strlen(vevents) + strlen("END:VCALENDAR\n") + 1);
    125             if (veventsr == NULL) {
    126                 perror("failed to realloc vevents buffer");
    127                 free(vevents);
    128                 break;
    129             } else {
    130                 vevents = (char*) veventsr;
    131                 strcat(vevents, "END:VCALENDAR\n");
    132             }
    133 
    134             fputs(vevents, pfile);
    135             fclose(pfile);
    136             pthread_cancel(progress_tid);
    137         } // end confirm to write
    138     } while (!(conf_ch == 'q' || conf_ch == 'n' || conf_ch == 'y' || conf_ch == 'Y' || conf_ch == '\n'));
    139 
    140     free(vevents);
    141 }