From 478b2762e61cee2aa2b073e37cfcdaf220692acf Mon Sep 17 00:00:00 2001 From: Frederic Culot Date: Sun, 30 Dec 2007 16:27:58 +0000 Subject: Ability to attach notes to todo items added --- ChangeLog | 6 +++ src/apoint.c | 54 ++++++++++--------------- src/apoint.h | 7 ++-- src/calcurse.c | 20 +++++++++- src/day.c | 74 +++++++++++++++++++++++++++++++---- src/event.h | 3 +- src/io.c | 121 ++++++++++++++++++++++++++++++++++++--------------------- src/notify.c | 8 ++-- src/todo.c | 81 +++++++++++++++++++++++++++++++++----- src/todo.h | 13 ++++--- src/utils.c | 112 ++++++++++++++++++++++++++++++++++------------------ src/utils.h | 12 ++++-- src/vars.c | 21 +++++++++- src/vars.h | 7 +++- src/wins.c | 33 +++++++++++++++- src/wins.h | 3 +- 16 files changed, 419 insertions(+), 156 deletions(-) diff --git a/ChangeLog b/ChangeLog index 89e75fb..6cf7e20 100755 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +30 Dec 2007: + Ability to attach notes to todo items added + Call to an external editor or pager to edit/view notes implemented + 'N' and '>' keystrokes added to edit or view notes + ierror() function improved + 09 Dec 2007: bugfix in recur_item_inday(): leap years should now be properly handled calendar_move_up(), calendar_move_down(), calendar_move_left(), diff --git a/src/apoint.c b/src/apoint.c index 7a87e6e..d963cd8 100755 --- a/src/apoint.c +++ b/src/apoint.c @@ -1,4 +1,4 @@ -/* $calcurse: apoint.c,v 1.18 2007/10/21 13:42:34 culot Exp $ */ +/* $calcurse: apoint.c,v 1.19 2007/12/30 16:27:58 culot Exp $ */ /* * Calcurse - text-based organizer @@ -250,7 +250,7 @@ apoint_delete(conf_t *conf, unsigned *nb_events, unsigned *nb_apoints) } else if (deleted_item_type == 0) { to_be_removed = 0; } else - ierror(errmsg); + ierror(errmsg, IERROR_FATAL); /* NOTREACHED */ if (hilt > 1) @@ -265,8 +265,6 @@ apoint_delete(conf_t *conf, unsigned *nb_events, unsigned *nb_apoints) } } - - unsigned apoint_inday(apoint_llist_node_t *i, long start) { @@ -389,35 +387,8 @@ void apoint_delete_bynum(long start, unsigned num) pthread_mutex_unlock(&(alist_p->mutex)); /* NOTREACHED */ - ierror(_("FATAL ERROR in apoint_delete_bynum: no such appointment")); -} - -/* - * Print an item date in the appointment panel. - */ -void display_item_date(WINDOW *win, int incolor, apoint_llist_node_t *i, - int type, long date, int y, int x) -{ - char a_st[100], a_end[100]; - int recur = 0; - - apoint_sec2str(i, type, date, a_st, a_end); - if (type == RECUR_EVNT || type == RECUR_APPT) - recur = 1; - if (incolor == 0) - custom_apply_attr(win, ATTR_HIGHEST); - if (recur) - if (i->state & APOINT_NOTIFY) - mvwprintw(win, y, x, " *!%s -> %s", a_st, a_end); - else - mvwprintw(win, y, x, " * %s -> %s", a_st, a_end); - else - if (i->state & APOINT_NOTIFY) - mvwprintw(win, y, x, " -!%s -> %s", a_st, a_end); - else - mvwprintw(win, y, x, " - %s -> %s", a_st, a_end); - if (incolor == 0) - custom_remove_attr(win, ATTR_HIGHEST); + ierror(_("FATAL ERROR in apoint_delete_bynum: no such appointment"), + IERROR_FATAL); } /* @@ -566,7 +537,8 @@ apoint_switch_notify(void) /* NOTREACHED */ ierror( - _("FATAL ERROR in apoint_switch_notify: no such appointment")); + _("FATAL ERROR in apoint_switch_notify: no such appointment"), + IERROR_FATAL); } /* Updates the Appointment panel */ @@ -617,3 +589,17 @@ apoint_update_panel(window_t *winapp, int which_pan) winapp->y + title_lines + 1, winapp->x + bordr, winapp->y + winapp->h - 2*bordr, winapp->x + winapp->w - 3*bordr); } + +/* Attach a note to an appointment or event */ +void +apoint_edit_note(void) +{ + +} + +/* View a note previously attached to an appointment or event */ +void +apoint_view_note(void) +{ + +} diff --git a/src/apoint.h b/src/apoint.h index c77ca70..182f03d 100755 --- a/src/apoint.h +++ b/src/apoint.h @@ -1,4 +1,4 @@ -/* $calcurse: apoint.h,v 1.9 2007/08/15 15:33:54 culot Exp $ */ +/* $calcurse: apoint.h,v 1.10 2007/12/30 16:27:58 culot Exp $ */ /* * Calcurse - text-based organizer @@ -44,6 +44,7 @@ typedef struct apoint_llist_node { long dur; /* duration of the appointment in seconds */ char state; /* 8 bits to store item state */ char *mesg; + char *note; } apoint_llist_node_t; typedef struct apoint_llist { @@ -67,13 +68,13 @@ void apoint_sec2str(apoint_llist_node_t *, int, long, void apoint_write(apoint_llist_node_t *, FILE *); apoint_llist_node_t *apoint_scan(FILE *, struct tm, struct tm, char); void apoint_delete_bynum(long, unsigned); -void display_item_date(WINDOW *, int, apoint_llist_node_t *, - int, long, int, int); void apoint_scroll_pad_down(int, int); void apoint_scroll_pad_up(int); struct notify_app_s *apoint_check_next(struct notify_app_s *, long); apoint_llist_node_t *apoint_recur_s2apoint_s(recur_apoint_llist_node_t *); void apoint_switch_notify(void); void apoint_update_panel(window_t *, int); +void apoint_edit_note(void); +void apoint_view_note(void); #endif /* CALCURSE_APOINT_H */ diff --git a/src/calcurse.c b/src/calcurse.c index b62f9b9..ab25298 100755 --- a/src/calcurse.c +++ b/src/calcurse.c @@ -1,4 +1,4 @@ -/* $calcurse: calcurse.c,v 1.58 2007/12/10 18:56:08 culot Exp $ */ +/* $calcurse: calcurse.c,v 1.59 2007/12/30 16:27:58 culot Exp $ */ /* * Calcurse - text-based organizer @@ -346,6 +346,24 @@ main(int argc, char **argv) } break; + case 'N': + case 'n': + /* Attach a note to an item, create it if necessary */ + if (wins_slctd() == APP && apoint_hilt() != 0) + apoint_edit_note(); + else if (wins_slctd() == TOD && todo_hilt() != 0) + todo_edit_note(conf.editor); + do_storage = true; + break; + + case '>': + /* View a note previously attached to an item */ + if (wins_slctd() == APP && apoint_hilt() != 0) + apoint_view_note(); + else if (wins_slctd() == TOD && todo_hilt() != 0) + todo_view_note(conf.pager); + break; + case '?': /* Online help system */ status_bar(); help_screen(); diff --git a/src/day.c b/src/day.c index 95635f9..0d27bee 100755 --- a/src/day.c +++ b/src/day.c @@ -1,4 +1,4 @@ -/* $calcurse: day.c,v 1.30 2007/10/21 13:42:34 culot Exp $ */ +/* $calcurse: day.c,v 1.31 2007/12/30 16:27:59 culot Exp $ */ /* * Calcurse - text-based organizer @@ -34,6 +34,7 @@ #include "utils.h" #include "apoint.h" #include "event.h" +#include "custom.h" #include "day.h" static struct day_item_s *day_items_ptr; @@ -301,6 +302,63 @@ day_item_s2apoint_s(apoint_llist_node_t *a, struct day_item_s *p) a->mesg = p->mesg; } +/* + * Print an item date in the appointment panel. + */ +static void +display_item_date(int incolor, apoint_llist_node_t *i, int type, long date, + int y, int x) +{ + WINDOW *win; + char a_st[100], a_end[100]; + int recur = 0; + + win = apad->ptrwin; + apoint_sec2str(i, type, date, a_st, a_end); + if (type == RECUR_EVNT || type == RECUR_APPT) + recur = 1; + if (incolor == 0) + custom_apply_attr(win, ATTR_HIGHEST); + if (recur) + if (i->state & APOINT_NOTIFY) + mvwprintw(win, y, x, " *!%s -> %s", a_st, a_end); + else + mvwprintw(win, y, x, " * %s -> %s", a_st, a_end); + else + if (i->state & APOINT_NOTIFY) + mvwprintw(win, y, x, " -!%s -> %s", a_st, a_end); + else + mvwprintw(win, y, x, " - %s -> %s", a_st, a_end); + if (incolor == 0) + custom_remove_attr(win, ATTR_HIGHEST); +} + +/* + * Print an item description in the corresponding panel window. + */ +static void +display_item(int incolor, char *msg, int recur, int note, int len, int y, int x) +{ + WINDOW *win; + int ch_recur, ch_note; + char buf[len]; + + win = apad->ptrwin; + ch_recur = (recur) ? '*' : ' '; + ch_note = (note) ? '>' : ' '; + if (incolor == 0) + custom_apply_attr(win, ATTR_HIGHEST); + if (strlen(msg) < len) + mvwprintw(win, y, x, " %c%c%s", ch_recur, ch_note, msg); + else { + strncpy(buf, msg, len - 1); + buf[len - 1] = '\0'; + mvwprintw(win, y, x, " %c%c%s...", ch_recur, ch_note, buf); + } + if (incolor == 0) + custom_remove_attr(win, ATTR_HIGHEST); +} + /* * Write the appointments and events for the selected day in a pad. * An horizontal line is drawn between events and appointments, and the @@ -339,8 +397,8 @@ day_write_pad(long date, int width, int length, int incolor) day_saved_item->type = p->type; day_saved_item->mesg = p->mesg; } - display_item(apad->ptrwin, item_number - incolor, p->mesg, - recur, width - 5, line, x_pos); + display_item(item_number - incolor, p->mesg, recur, 0, + width - 7, line, x_pos); line++; draw_line = true; } else { @@ -360,10 +418,10 @@ day_write_pad(long date, int width, int length, int incolor) apoint_sec2str(&a, p->type, date, day_saved_item->start, day_saved_item->end); } - display_item_date(apad->ptrwin, item_number - incolor, - &a, p->type, date, line + 1, x_pos); - display_item(apad->ptrwin, item_number - incolor, p->mesg, - 0, width - 7, line + 2, x_pos + 2); + display_item_date(item_number - incolor, &a, p->type, + date, line + 1, x_pos); + display_item(item_number - incolor, p->mesg, 0, 0, + width - 7, line + 2, x_pos); line = line + 3; } } @@ -382,7 +440,7 @@ void day_popup_item(void) item_in_popup(day_saved_item->start, day_saved_item->end, day_saved_item->mesg, _("Appointment :")); else - ierror(error); + ierror(error, IERROR_FATAL); /* NOTREACHED */ } diff --git a/src/event.h b/src/event.h index 3b2e794..48e2ac5 100755 --- a/src/event.h +++ b/src/event.h @@ -1,4 +1,4 @@ -/* $calcurse: event.h,v 1.2 2007/07/28 13:11:42 culot Exp $ */ +/* $calcurse: event.h,v 1.3 2007/12/30 16:27:59 culot Exp $ */ /* * Calcurse - text-based organizer @@ -35,6 +35,7 @@ struct event_s { int id; /* event identifier */ long day; /* seconds since 1 jan 1970 */ char *mesg; + char *note; }; extern struct event_s *eventlist; diff --git a/src/io.c b/src/io.c index 704b007..00625a3 100755 --- a/src/io.c +++ b/src/io.c @@ -1,4 +1,4 @@ -/* $calcurse: io.c,v 1.23 2007/10/21 13:42:34 culot Exp $ */ +/* $calcurse: io.c,v 1.24 2007/12/30 16:27:59 culot Exp $ */ /* * Calcurse - text-based organizer @@ -30,6 +30,7 @@ #include #include #include +#include #include "i18n.h" #include "utils.h" @@ -327,6 +328,7 @@ io_init(char *cfile) snprintf(path_dir, BUFSIZ, "%s/" DIR_NAME, home); snprintf(path_todo, BUFSIZ, "%s/" TODO_PATH, home); snprintf(path_conf, BUFSIZ, "%s/" CONF_PATH, home); + snprintf(path_notes, BUFSIZ, "%s/" NOTES_DIR, home); if (cfile == NULL) { snprintf(path_apts, BUFSIZ, "%s/" APTS_PATH, home); } else { @@ -485,13 +487,19 @@ io_save_cal(conf_t *conf) } /* Save the todo data file. */ - if (show_bar) progress_bar(PROGRESS_BAR_SAVE, 1); + if (show_bar) + progress_bar(PROGRESS_BAR_SAVE, 1); data_file = fopen(path_todo, "w"); if (data_file == (FILE *) 0) status_mesg(access_pb, ""); else { - for (i = todolist; i != 0; i = i->next) - fprintf(data_file, "[%d] %s\n", i->id, i->mesg); + for (i = todolist; i != 0; i = i->next) { + if (i->note != NULL) + fprintf(data_file, "[%d]>%s %s\n", i->id, + i->note, i->mesg); + else + fprintf(data_file, "[%d] %s\n", i->id, i->mesg); + } fclose(data_file); } @@ -680,7 +688,7 @@ io_load_todo(void) char *nl; int nb_tod = 0; int c, id; - char buf[BUFSIZ], e_todo[BUFSIZ]; + char buf[BUFSIZ], e_todo[BUFSIZ], note[NOTESIZ + 1]; data_file = fopen(path_todo, "r"); if (data_file == NULL) { @@ -692,68 +700,91 @@ io_load_todo(void) if (c == EOF) { break; } else if (c == '[') { /* new style with id */ - fscanf(data_file, "%d] ", &id); + fscanf(data_file, "%d]", &id); } else { id = 9; ungetc(c, data_file); } + /* Now read the attached note, if any. */ + c = getc(data_file); + if (c == '>') { + fgets(note, NOTESIZ + 1, data_file); + note[NOTESIZ] = '\0'; + fprintf(stderr, "note: [%s]\n", note); + getc(data_file); + } else + note[0] = '\0'; + /* Then read todo description. */ fgets(buf, BUFSIZ, data_file); nl = strchr(buf, '\n'); if (nl) { *nl = '\0'; } io_extract_data(e_todo, buf, strlen(buf)); - todo_add(e_todo, id); + todo_add(e_todo, id, note); ++nb_tod; } fclose(data_file); todo_set_nb(nb_tod); } -/* Checks if data files exist. If not, create them */ -int -io_check_data_files(void) +static void +check_directory(char *dir, int *missing) { - FILE *data_file; - int no_data_file; - - no_data_file = 0; - /* Create the calcurse repertory if not present. */ - mkdir(path_dir, 0700); - - data_file = fopen(path_todo, "r"); - if (data_file == NULL) { - no_data_file++; - data_file = fopen(path_todo, "w"); - if (data_file == NULL) { - perror(path_todo); - return no_data_file; + errno = 0; + if (mkdir(dir, 0700) != 0) { + if (errno != EEXIST) { + fprintf(stderr, + _("FATAL ERROR: could not create %s: %s\n"), + dir, strerror(errno)); + exit(EXIT_FAILURE); } - } - fclose(data_file); + } else + (*missing)++; +} - data_file = fopen(path_apts, "r"); - if (data_file == NULL) { - no_data_file++; - data_file = fopen(path_apts, "w"); - if (data_file == NULL) { - perror(path_apts); - return no_data_file; +static void +check_file(char *file, int *missing) +{ + FILE *fd; + + errno = 0; + if ((fd = fopen(file, "r")) == NULL) { + (*missing)++; + if ((fd = fopen(file, "w")) == NULL) { + fprintf(stderr, + _("FATAL ERROR: could not create %s: %s\n"), + file, strerror(errno)); + exit(EXIT_FAILURE); } } - fclose(data_file); + fclose(fd); +} - data_file = fopen(path_conf, "r"); - if (data_file == NULL) { - no_data_file++; - data_file = fopen(path_conf, "w"); - if (data_file == NULL) { - perror(path_conf); - return no_data_file; - } - } - fclose(data_file); - return no_data_file; +/* + * Checks if data files exist. If not, create them. + * The following structure has to be created: + * + * $HOME/.calcurse/ + * | + * +--- notes/ + * |___ conf + * |___ apts + * |___ todo + */ +int +io_check_data_files(void) +{ + int missing; + + missing = 0; + errno = 0; + check_directory(path_dir, &missing); + check_directory(path_notes, &missing); + check_file(path_todo, &missing); + check_file(path_apts, &missing); + check_file(path_conf, &missing); + return (missing); } /* Draw the startup screen */ diff --git a/src/notify.c b/src/notify.c index b4b60b7..3531a02 100755 --- a/src/notify.c +++ b/src/notify.c @@ -1,4 +1,4 @@ -/* $calcurse: notify.c,v 1.22 2007/10/21 13:41:51 culot Exp $ */ +/* $calcurse: notify.c,v 1.23 2007/12/30 16:27:59 culot Exp $ */ /* * Calcurse - text-based organizer @@ -132,11 +132,13 @@ launch_cmd(char *cmd, char *shell) pid = fork(); if (pid < 0) - ierror(_("FATAL ERROR in launch_cmd: could not fork")); + ierror(_("FATAL ERROR in launch_cmd: could not fork"), + IERROR_WARN); else if (pid == 0) /* Child: launch user defined command */ if (execlp(shell, shell, "-c", cmd, (char *)NULL) < 0) ierror(_("FATAL ERROR in launch_cmd: could not " - "launch user command")); + "launch user command"), + IERROR_WARN); } /* diff --git a/src/todo.c b/src/todo.c index d56819a..5f1160d 100755 --- a/src/todo.c +++ b/src/todo.c @@ -1,4 +1,4 @@ -/* $calcurse: todo.c,v 1.15 2007/10/21 13:42:34 culot Exp $ */ +/* $calcurse: todo.c,v 1.16 2007/12/30 16:27:59 culot Exp $ */ /* * Calcurse - text-based organizer @@ -28,6 +28,7 @@ #include #include "utils.h" +#include "custom.h" #include "i18n.h" #include "todo.h" @@ -130,20 +131,21 @@ todo_new_item(void) status_mesg(mesg_id, ""); ch = wgetch(win[STA].p); } - todo_add(todo_input, ch - '0'); + todo_add(todo_input, ch - '0', NULL); todos++; } } /* Add an item in the todo linked list. */ struct todo_s * -todo_add(char *mesg, int id) +todo_add(char *mesg, int id, char *note) { struct todo_s *o, **i; o = (struct todo_s *) malloc(sizeof(struct todo_s)); o->mesg = (char *) malloc(strlen(mesg) + 1); strncpy(o->mesg, mesg, strlen(mesg) + 1); o->id = id; + o->note = (note != NULL && note[0] != '\0') ? strdup(note) : NULL; i = &todolist; for (;;) { if (*i == 0 || (*i)->id > id) { @@ -169,6 +171,8 @@ todo_delete_bynum(unsigned num) if (n == num) { *iptr = i->next; free(i->mesg); + if (i->note != NULL) + free(i->note); free(i); return; } @@ -261,11 +265,13 @@ todo_chg_priority(int action) struct todo_s *backup; char backup_mesg[BUFSIZ]; int backup_id; + char backup_note[NOTESIZ + 1]; int do_chg = 1; backup = todo_get_item(hilt); strncpy(backup_mesg, backup->mesg, strlen(backup->mesg) + 1); backup_id = backup->id; + strncpy(backup_note, backup->note, NOTESIZ + 1); if (action == '+') { (backup_id > 1) ? backup_id-- : do_chg--; } else if (action == '-') { @@ -276,7 +282,7 @@ todo_chg_priority(int action) } if (do_chg) { todo_delete_bynum(hilt - 1); - backup = todo_add(backup_mesg, backup_id); + backup = todo_add(backup_mesg, backup_id, backup_note); hilt = todo_get_position(backup); } } @@ -293,12 +299,36 @@ todo_edit_item(void) updatestring(win[STA].p, &i->mesg, 0, 1); } +/* Display todo items in the corresponding panel. */ +static void +display_todo_item(int incolor, char *msg, int prio, int note, int len, int y, + int x) +{ + WINDOW *w; + int ch_note; + char buf[len]; + + w = win[TOD].p; + ch_note = (note) ? '>' : '.'; + if (incolor == 0) + custom_apply_attr(w, ATTR_HIGHEST); + if (strlen(msg) < len) + mvwprintw(w, y, x, "%d%c %s", prio, ch_note, msg); + else { + strncpy(buf, msg, len - 1); + buf[len - 1] = '\0'; + mvwprintw(w, y, x, "%d%c %s...", prio, ch_note, buf); + } + if (incolor == 0) + custom_remove_attr(w, ATTR_HIGHEST); +} + /* Updates the ToDo panel. */ void todo_update_panel(window_t *wintod, int which_pan) { struct todo_s *i; - int len = wintod->w - 6; + int len = wintod->w - 8; int num_todo = 0; int y_offset = 3, x_offset = 1; int t_realpos = -1; @@ -306,7 +336,6 @@ todo_update_panel(window_t *wintod, int which_pan) int todo_lines = 1; int max_items = wintod->h - 4; int incolor = -1; - char mesg[BUFSIZ] = ""; /* Print todo item in the panel. */ erase_window_part(win[TOD].p, 1, title_lines, wintod->w - 2, @@ -318,10 +347,8 @@ todo_update_panel(window_t *wintod, int which_pan) if (incolor == 0) msgsav = i->mesg; if (t_realpos >= 0 && t_realpos < max_items) { - snprintf(mesg, BUFSIZ, "%d. ", i->id); - strncat(mesg, i->mesg, strlen(i->mesg)); - display_item(win[TOD].p, incolor, mesg, 0, - len, y_offset, x_offset); + display_todo_item(incolor, i->mesg, i->id, + (i->note != NULL) ? 1 : 0, len, y_offset, x_offset); y_offset = y_offset + todo_lines; } } @@ -342,3 +369,37 @@ todo_update_panel(window_t *wintod, int which_pan) wnoutrefresh(win[TOD].p); } + +/* Attach a note to a todo */ +void +todo_edit_note(char *editor) +{ + struct todo_s *i; + char fullname[BUFSIZ]; + char *filename; + + i = todo_get_item(hilt); + if (i->note == NULL) { + if ((filename = new_tempfile(path_notes, NOTESIZ)) + != NULL) + i->note = filename; + else + return; + } + snprintf(fullname, BUFSIZ, "%s%s", path_notes, i->note); + wins_launch_external(fullname, editor); +} + +/* View a note previously attached to a todo */ +void +todo_view_note(char *pager) +{ + struct todo_s *i; + char fullname[BUFSIZ]; + + i = todo_get_item(hilt); + if (i->note == NULL) + return; + snprintf(fullname, BUFSIZ, "%s%s", path_notes, i->note); + wins_launch_external(fullname, pager); +} diff --git a/src/todo.h b/src/todo.h index e8d128b..2620ef7 100755 --- a/src/todo.h +++ b/src/todo.h @@ -1,4 +1,4 @@ -/* $calcurse: todo.h,v 1.9 2007/08/15 15:35:25 culot Exp $ */ +/* $calcurse: todo.h,v 1.10 2007/12/30 16:27:59 culot Exp $ */ /* * Calcurse - text-based organizer @@ -30,9 +30,10 @@ #include "wins.h" struct todo_s { - struct todo_s *next; - char *mesg; - int id; + struct todo_s *next; + char *mesg; + int id; + char *note; }; extern struct todo_s *todolist; @@ -49,10 +50,12 @@ void todo_first_decrease(void); int todo_hilt_pos(void); char *todo_saved_mesg(void); void todo_new_item(void); -struct todo_s *todo_add(char *, int); +struct todo_s *todo_add(char *, int, char *); void todo_delete(conf_t *); void todo_chg_priority(int); void todo_edit_item(void); void todo_update_panel(window_t *, int); +void todo_edit_note(char *); +void todo_view_note(char *); #endif /* CALCURSE_TODO_H */ diff --git a/src/utils.c b/src/utils.c index a571fae..d2963a5 100755 --- a/src/utils.c +++ b/src/utils.c @@ -1,4 +1,4 @@ -/* $calcurse: utils.c,v 1.37 2007/10/21 13:42:34 culot Exp $ */ +/* $calcurse: utils.c,v 1.38 2007/12/30 16:27:59 culot Exp $ */ /* * Calcurse - text-based organizer @@ -27,9 +27,11 @@ #include #include #include +#include #include #include #include +#include #include "i18n.h" #include "wins.h" @@ -50,7 +52,7 @@ exit_calcurse(int status) /* Function to exit on internal error. */ void -ierror(const char *errmsg) +ierror(const char *errmsg, ierror_sev_e sev) { WINDOW *errwin; char *label = _("INTERNAL ERROR"); @@ -66,14 +68,17 @@ ierror(const char *errmsg) custom_apply_attr(errwin, ATTR_HIGHEST); box(errwin, 0, 0); wins_show(errwin, label); - mvwprintw(errwin, 3, 1, reportmsg); + if (sev == IERROR_FATAL) + mvwprintw(errwin, 3, 1, reportmsg); mvwprintw(errwin, 5, (wincol - strlen(msg)) / 2, "%s", msg); - mvwprintw(errwin, winrow - 2, wincol - strlen(exitmsg) - 1, "%s", - exitmsg); + if (sev == IERROR_FATAL) + mvwprintw(errwin, winrow - 2, wincol - strlen(exitmsg) - 1, "%s", + exitmsg); custom_remove_attr(errwin, ATTR_HIGHEST); wrefresh(errwin); wgetch(errwin); - exit_calcurse(EXIT_FAILURE); + if (sev == IERROR_FATAL) + exit_calcurse(EXIT_FAILURE); } /* Function to handle an assertion failure. */ @@ -84,7 +89,7 @@ aerror(const char *file, int line, const char *assertion) snprintf(errmsg, BUFSIZ, "assert \"%s\" failed: file \"%s\", line %d", assertion, file, line); - ierror(errmsg); + ierror(errmsg, IERROR_FATAL); } /* @@ -94,7 +99,7 @@ aerror(const char *file, int line, const char *assertion) void status_mesg(char *mesg_line1, char *mesg_line2) { - erase_window_part(win[STA].p, 0, 0, col, 2); + erase_status_bar(); custom_apply_attr(win[STA].p, ATTR_HIGHEST); mvwprintw(win[STA].p, 0, 0, mesg_line1); mvwprintw(win[STA].p, 1, 0, mesg_line2); @@ -350,7 +355,8 @@ updatestring(WINDOW *win, char **str, int x, int y) len = strlen(newstr) + 1; if ((*str = (char *) realloc(*str, len)) == NULL) { /* NOTREACHED */ - ierror(_("FATAL ERROR in updatestring: out of memory")); + ierror(_("FATAL ERROR in updatestring: out of memory"), + IERROR_FATAL); } else (void)memcpy(*str, newstr, len); } @@ -742,33 +748,6 @@ void item_in_popup(char *saved_a_start, char *saved_a_end, char *msg, delwin(popup_win); } -/* - * Print an item description in the corresponding panel window. - */ -void display_item(WINDOW *win, int incolor, char *msg, int recur, - int len, int y, int x) -{ - char buf[len]; - - if (incolor == 0) - custom_apply_attr(win, ATTR_HIGHEST); - if (strlen(msg) < len) { - if (recur) - mvwprintw(win, y, x, "*%s", msg); - else - mvwprintw(win, y, x, " %s", msg); - } else { - strncpy(buf, msg, len - 1); - buf[len - 1] = '\0'; - if (recur) - mvwprintw(win, y, x, "*%s...", buf); - else - mvwprintw(win, y, x, " %s...", buf); - } - if (incolor == 0) - custom_remove_attr(win, ATTR_HIGHEST); -} - /* Reset the status bar page. */ void reset_status_page(void) { @@ -792,7 +771,7 @@ void other_status_page(int panel) nb_item = NB_TOD_CMDS; break; default: - ierror(error); + ierror(error, IERROR_FATAL); } max_page = ceil( nb_item / (2*CMDS_PER_LINE) ) + 1; if (status_page < max_page) { @@ -841,6 +820,26 @@ char *mycpy(const char *src) return NULL; } +long +mystrtol(const char *str) +{ + char *ep; + long lval; + const char *not_a_number = + _("FATAL ERROR in mystrtol: could not convert string"); + const char *out_of_range = + _("FATAL ERROR in mystrtol: number is out of range"); + + errno = 0; + lval = strtol(str, &ep, 10); + if (str[0] == '\0' || *ep != '\0') + ierror(not_a_number, IERROR_FATAL); + if (errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN)) + ierror(out_of_range, IERROR_FATAL); + + return (lval); +} + /* Print the given option value with appropriate color. */ void print_option_incolor(WINDOW *win, bool option, int pos_y, int pos_x) @@ -856,7 +855,8 @@ print_option_incolor(WINDOW *win, bool option, int pos_y, int pos_x) strncpy(option_value, _("no"), BUFSIZ); } else { ierror( - _("option not defined - Problem in print_option_incolor()")); + _("option not defined - Problem in print_option_incolor()"), + IERROR_FATAL); } custom_apply_attr(win, color); mvwprintw(win, pos_y, pos_x, "%s", option_value); @@ -864,3 +864,39 @@ print_option_incolor(WINDOW *win, bool option, int pos_y, int pos_x) wnoutrefresh(win); doupdate(); } + +/* + * Create a new unique file, and return a newly allocated string which contains + * the random part of the file name. + */ +char * +new_tempfile(const char *prefix, int trailing_len) +{ + char fullname[BUFSIZ]; + int prefix_len, fd; + FILE *file; + + if (prefix == NULL) + return (NULL); + + prefix_len = strlen(prefix); + if (prefix_len + trailing_len >= BUFSIZ) + return (NULL); + memcpy(fullname, prefix, prefix_len); + memset(fullname + prefix_len, 'X', trailing_len); + fullname[prefix_len + trailing_len] = '\0'; + if ((fd = mkstemp(fullname)) == -1 || + (file = fdopen(fd, "w+")) == NULL) { + if (fd != -1) { + unlink(fullname); + close(fd); + } + ierror( + _("FATAL ERROR: temporary file could not be created!"), + IERROR_WARN); + return (NULL); + } + fclose(file); + + return (strdup(fullname + prefix_len)); +} diff --git a/src/utils.h b/src/utils.h index 396fb9c..4d57a66 100755 --- a/src/utils.h +++ b/src/utils.h @@ -1,4 +1,4 @@ -/* $calcurse: utils.h,v 1.23 2007/08/04 14:32:31 culot Exp $ */ +/* $calcurse: utils.h,v 1.24 2007/12/30 16:27:59 culot Exp $ */ /* * Calcurse - text-based organizer @@ -56,8 +56,13 @@ typedef struct { /* structure defining a keybinding */ char *label; } binding_t; +typedef enum { + IERROR_FATAL, + IERROR_WARN +} ierror_sev_e; + void exit_calcurse(int); -void ierror(const char *); +void ierror(const char *, ierror_sev_e); void aerror(const char *, int, const char *); void status_mesg(char *, char *); void erase_status_bar(void); @@ -80,12 +85,13 @@ long min2sec(unsigned); int check_time(char *); void draw_scrollbar(WINDOW *, int, int, int, int, int, bool); void item_in_popup(char *, char *, char *, char *); -void display_item(WINDOW *, int, char *, int, int, int, int); void reset_status_page(void); void other_status_page(int); long get_today(void); long now(void); char *mycpy(const char *); +long mystrtol(const char *); void print_option_incolor(WINDOW *, bool, int, int); +char *new_tempfile(const char *, int); #endif /* CALCURSE_UTILS_H */ diff --git a/src/vars.c b/src/vars.c index fbbb666..6dab20b 100755 --- a/src/vars.c +++ b/src/vars.c @@ -1,4 +1,4 @@ -/* $calcurse: vars.c,v 1.5 2007/10/21 13:40:13 culot Exp $ */ +/* $calcurse: vars.c,v 1.6 2007/12/30 16:27:59 culot Exp $ */ /* * Calcurse - text-based organizer @@ -76,6 +76,7 @@ char path_dir[] = ""; char path_todo[] = ""; char path_apts[] = ""; char path_conf[] = ""; +char path_notes[] = ""; /* Variable to handle pads. */ struct pad_s *apad; @@ -90,12 +91,30 @@ struct nbar_s *nbar; void vars_init(conf_t *conf) { + char *PATH_VI = "/usr/bin/vi"; + char *PATH_LESS = "/usr/bin/less"; + char *ed, *pg; + /* Variables for user configuration */ conf->confirm_quit = true; conf->confirm_delete = true; conf->auto_save = true; conf->skip_system_dialogs = false; conf->skip_progress_bar = false; + + /* Default external editor and pager */ + ed = getenv("VISUAL"); + if (ed == NULL || ed[0] == '\0') + ed = getenv("EDITOR"); + if (ed == NULL || ed[0] == '\0') + ed = PATH_VI; + conf->editor = ed; + + pg = getenv("PAGER"); + if (pg == NULL || pg[0] == '\0') + pg = PATH_LESS; + conf->pager = pg; + wins_set_layout(1); calendar_set_first_day_of_week(MONDAY); diff --git a/src/vars.h b/src/vars.h index 2f7064a..3cedf83 100755 --- a/src/vars.h +++ b/src/vars.h @@ -1,4 +1,4 @@ -/* $calcurse: vars.h,v 1.18 2007/12/10 19:04:08 culot Exp $ */ +/* $calcurse: vars.h,v 1.19 2007/12/30 16:27:59 culot Exp $ */ /* * Calcurse - text-based organizer @@ -35,6 +35,7 @@ #define TODO_PATH ".calcurse/todo" #define APTS_PATH ".calcurse/apts" #define CONF_PATH ".calcurse/conf" +#define NOTES_DIR ".calcurse/notes/" #define CTRL(x) ((x) & 0x1f) #define ESCAPE 27 @@ -52,6 +53,7 @@ #define WEEKINDAYS 7 #define STATUSHEIGHT 2 +#define NOTESIZ 10 struct pad_s { int width; @@ -78,6 +80,8 @@ typedef struct { bool confirm_delete; bool skip_system_dialogs; bool skip_progress_bar; + char *editor; + char *pager; } conf_t; extern int col, row; @@ -89,6 +93,7 @@ extern char path_dir[BUFSIZ]; extern char path_todo[BUFSIZ]; extern char path_apts[BUFSIZ]; extern char path_conf[BUFSIZ]; +extern char path_notes[BUFSIZ]; extern struct pad_s *apad; extern struct nbar_s *nbar; diff --git a/src/wins.c b/src/wins.c index b238996..fe79588 100755 --- a/src/wins.c +++ b/src/wins.c @@ -1,4 +1,4 @@ -/* $Id: wins.c,v 1.8 2007/10/21 13:39:49 culot Exp $ */ +/* $Id: wins.c,v 1.9 2007/12/30 16:27:59 culot Exp $ */ /* * Calcurse - text-based organizer @@ -337,7 +337,8 @@ wins_update(void) break; default: - ierror(_("FATAL ERROR in wins_update: no window selected\n")); + ierror(_("FATAL ERROR in wins_update: no window selected\n"), + IERROR_FATAL); /* NOTREACHED */ } @@ -361,3 +362,31 @@ wins_reset(void) wins_reinit(); wins_update(); } + +/* + * While inside interactive mode, launch the external command cmd on the given + * file. + */ +void +wins_launch_external(const char *file, const char *cmd) +{ + char *p; + + if (asprintf(&p, "%s %s", cmd, file) == -1) + return; + + if (notify_bar()) + notify_stop_main_thread(); + def_prog_mode(); + endwin(); + clear(); + refresh(); + system(p); + reset_prog_mode(); + clearok(curscr, TRUE); + curs_set(0); + refresh(); + if (notify_bar()) + notify_start_main_thread(); + free(p); +} diff --git a/src/wins.h b/src/wins.h index 629a6e4..6bc04ed 100755 --- a/src/wins.h +++ b/src/wins.h @@ -1,4 +1,4 @@ -/* $Id: wins.h,v 1.4 2007/10/21 13:39:07 culot Exp $ */ +/* $Id: wins.h,v 1.5 2007/12/30 16:27:59 culot Exp $ */ /* * Calcurse - text-based organizer @@ -61,5 +61,6 @@ void wins_show(WINDOW *, char *); void wins_get_config(void); void wins_update(void); void wins_reset(void); +void wins_launch_external(const char *, const char *); #endif /* CALCURSE_WINS_H */ -- cgit v1.2.3-54-g00ecf