diff options
Diffstat (limited to 'src/calcurse.c')
-rwxr-xr-x | src/calcurse.c | 1156 |
1 files changed, 1156 insertions, 0 deletions
diff --git a/src/calcurse.c b/src/calcurse.c new file mode 100755 index 0000000..7432daf --- /dev/null +++ b/src/calcurse.c @@ -0,0 +1,1156 @@ +/* $calcurse: calcurse.c,v 1.1 2006/07/31 21:00:02 culot Exp $ */ + +/* + * Calcurse - text-based organizer + * Copyright (c) 2004-2006 Frederic Culot + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Send your feedback or comments to : calcurse@culot.org + * Calcurse home page : http://culot.org/calcurse + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif /* HAVE_CONFIG_H */ + +#include <ncurses.h> +#include <time.h> +#include <string.h> +#include <stdlib.h> +#include <stdbool.h> +#include <math.h> +#include <locale.h> + +#include "i18n.h" +#include "io.h" +#include "help.h" +#include "calendar.h" +#include "custom.h" +#include "utils.h" +#include "vars.h" +#include "day.h" +#include "apoint.h" +#include "event.h" +#include "todo.h" +#include "args.h" + + +/* Variables for calendar */ +struct tm *ptrtime; +time_t timer; +char current_day[3]; +char current_month[3]; +char current_year[5]; +char current_time[15]; +char cal_date[30]; +int year, month, day; +int sel_year, sel_month, sel_day; + +/* Variables for appointments */ +int number_apoints_inday; +int number_events_inday; +int first_app_onscreen = 0; +int hilt_app = 0, sav_hilt_app; + +/* Variables for todo list */ +int nb_tod = 0, hilt_tod = 0, sav_hilt_tod; +int first_todo_onscreen = 1; +char *saved_t_mesg; + +/* Variables for user configuration */ +int colr = 1, layout = 1; +int no_data_file = 1; +int really_quit = 0; +bool confirm_quit; +bool confirm_delete; +bool auto_save; +bool skip_system_dialogs; +bool skip_progress_bar; +bool week_begins_on_monday; + +/* + * Variables to handle calcurse windows + */ +int x_cal, y_cal, x_app, y_app, x_tod, y_tod, x_bar, y_bar; +int nl_cal, nc_cal, nl_app, nc_app, nl_tod, nc_tod, nl_bar, nc_bar; +int which_pan = 0; +enum window_number {CALENDAR, APPOINTMENT, TODO}; + +/* External functions */ +void get_date(void); +void init_vars(int colr); +void init_wins(void), reinit_wins(void); +void add_item(void); +void add_todo(void); +void load_conf(void); +bool fill_config_var(char *string); +void update_todo_panel(void); +void update_app_panel(int yeat, int month, int day); +void store_day(int year, int month, int day, bool day_changed); +void get_screen_config(void); +void update_windows(int surrounded_window); +void general_config(void); +void print_general_options(WINDOW *win); +void print_option_incolor(WINDOW *win, bool option, int pos_x, int pos_y); +void del_apoint(void); + +/* + * Calcurse is a text-based personal organizer which helps keeping track + * of events and everyday tasks. It contains a calendar, a 'todo' list, + * and puts your appointments in order. The user interface is configurable, + * and one can choose between different color schemes and layouts. + * All of the commands are documented within an online help system. + */ +int main(int argc, char **argv) +{ + int ch; + int non_interactive; + bool do_storage = false; + bool day_changed = false; + char *no_color_support = + _("Sorry, colors are not supported by your terminal\n" + "(Press [ENTER] to continue)"); + char *quit_message = _("Do you really want to quit ?"); + char choices[] = "[y/n] "; + +#if ENABLE_NLS + setlocale (LC_ALL, ""); + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); +#endif /* ENABLE_NLS */ + + /* + * Begin by parsing and handling command line arguments. + * The data path is also initialized here. + */ + non_interactive = parse_args(argc, argv, colr); + if (non_interactive) return EXIT_SUCCESS; + + /* Begin of interactive mode with ncurses interface. */ + initscr(); /* start the curses mode */ + cbreak(); /* control chars generate a signal */ + noecho(); /* controls echoing of typed chars */ + curs_set(0); /* make cursor invisible */ + get_date(); + get_screen_config(); + + /* Check if terminal supports color. */ + if (has_colors()) { + colorize = true; + start_color(); + + /* Color assignment */ + init_pair(1, COLOR_RED, COLOR_BLACK); + init_pair(2, COLOR_GREEN, COLOR_BLACK); + init_pair(3, COLOR_BLUE, COLOR_BLACK); + init_pair(4, COLOR_CYAN, COLOR_BLACK); + init_pair(5, COLOR_YELLOW, COLOR_BLACK); + init_pair(6, COLOR_BLACK, COLOR_GREEN); + init_pair(7, COLOR_BLACK, COLOR_YELLOW); + init_pair(8, COLOR_RED, COLOR_BLUE); + init_pair(9, COLOR_WHITE, COLOR_BLACK); + } else { + colorize = false; + use_default_colors(); + } + + init_vars(colr); + init_wins(); + update_windows(which_pan); + + /* + * Read the data from files : first the user + * configuration (the display is then updated), and then + * the todo list, appointments and events. + */ + no_data_file = check_data_files(); + load_conf(); + custom_init_attr(colr); + nb_tod = load_todo(colr); + load_app(); + get_screen_config(); + reinit_wins(); + startup_screen(skip_system_dialogs, no_data_file, colr); + store_day(year, month, day, day_changed); + update_windows(CALENDAR); + + /* User input */ + for (;;) { + + /* Check terminal size. */ + getmaxyx(stdscr, row, col); + if ((col < 80) | (row < 24)) { + endwin(); + fputs(_("Please resize your terminal screen\n" + "(to at least 80x24),\n" + "and restart calcurse.\n"), stderr); + return EXIT_FAILURE; + } + + /* Get user input. */ + ch = wgetch(swin); + switch (ch) { + + case 9: /* The TAB key was hit. */ + /* Save previously highlighted event. */ + if (which_pan == TODO) { + sav_hilt_tod = hilt_tod; + hilt_tod = 0; + } + if (which_pan == APPOINTMENT) { + sav_hilt_app = hilt_app; + hilt_app = 0; + } + /* Switch to the selected panel. */ + if (which_pan == TODO) which_pan = CALENDAR; + else ++which_pan; + + /* Select the event to highlight. */ + if (which_pan == APPOINTMENT) { + if ((sav_hilt_app == 0) + & ( (number_events_inday + + number_apoints_inday) != 0)) + hilt_app = 1; + else + hilt_app = sav_hilt_app; + } else if (which_pan == TODO) { + if ((sav_hilt_tod == 0) & (nb_tod != 0)) + hilt_tod = 1; + else + hilt_tod = sav_hilt_tod; + } + break; + + case 'R': + case 'r': + reinit_wins(); + break; + + case 'G': + case 'g': /* Goto function */ + erase_window_part(swin, 0, 0, nc_bar, nl_bar); + get_date(); + goto_day(colr, day, month, year, + &sel_day, &sel_month, &sel_year); + do_storage = true; + day_changed = true; + break; + + case 'V': + case 'v': /* View function */ + if ((which_pan == APPOINTMENT) & (hilt_app != 0)) + day_popup_item(); + else if ((which_pan == TODO) & (hilt_tod != 0)) + item_in_popup(NULL, NULL, saved_t_mesg, + _("To do :")); + break; + + case 'C': + case 'c': /* Configuration menu */ + erase_window_part(swin, 0, 0, nc_bar, nl_bar); + config_bar(); + while ((ch = wgetch(swin)) != 'q') { + switch (ch) { + case 'C': + case 'c': + if (has_colors()) { + colorize = true; + colr = color_config(colr); + custom_init_attr(colr); + } else { + colorize = false; + erase_window_part(swin, 0, 0, + nc_bar, + nl_bar); + mvwprintw(swin, 0, 0, + _(no_color_support)); + wgetch(swin); + } + break; + case 'L': + case 'l': + layout = layout_config(layout, colr); + break; + case 'G': + case 'g': + general_config(); + break; + } + reinit_wins(); + erase_window_part(swin, 0, 0, nc_bar, nl_bar); + config_bar(); + } + update_windows(which_pan); + break; + + case 'A': + case 'a': /* Add an item */ + if (which_pan == APPOINTMENT) { + add_item(); + do_storage = true; + } + if (which_pan == TODO) add_todo(); + break; + + case 'D': + case 'd': /* Delete an item */ + del_apoint(); + do_storage = true; + break; + + case '?': /* Online help system */ + status_bar(which_pan, colr, nc_bar, nl_bar); + help_screen(which_pan, colr); + break; + + case 'S': + case 's': /* Save function */ + save_cal(auto_save, confirm_quit, + confirm_delete, skip_system_dialogs, + skip_progress_bar, week_begins_on_monday, + colr, layout); + break; + + case (261): /* right arrow */ + case ('L'): + case ('l'): + if (which_pan == CALENDAR) { + do_storage = true; + day_changed = true; + if ((sel_day == 31) & (sel_month == 12)) + { /* goto next year */ + sel_day = 0; + sel_month = 1; + sel_year++; + } + if (sel_day == days[sel_month - 1]) + { /* goto next month */ + sel_month = sel_month + 1; + sel_day = 1; + } else + sel_day = sel_day + 1; + } + break; + + case (260): /* left arrow */ + case ('H'): + case ('h'): + if (which_pan == CALENDAR) { + do_storage = true; + day_changed = true; + if ((sel_day == 1) & (sel_month == 1)) + { /* goto previous year */ + sel_day = 32; + sel_month = 12; + sel_year--; + } + if (sel_day == 1) + { /* goto previous month */ + sel_day = days[sel_month - 2]; + sel_month = sel_month - 1; + } else + sel_day = sel_day - 1; + } + break; + + case (259): /* up arrow */ + case ('K'): + case ('k'): + if (which_pan == CALENDAR) { + do_storage = true; + day_changed = true; + if ((sel_day <= 7) & (sel_month == 1)) + { /* goto previous year */ + sel_day = 31 - (7 - sel_day); + sel_month = 12; + sel_year--; + break; + } + if (sel_day <= 7) + { /* goto previous month */ + sel_day = days[sel_month - 2] - + (7 - sel_day); + sel_month = sel_month - 1; + } else /* previous week */ + sel_day = sel_day - 7; + } else { + if ((which_pan == APPOINTMENT) & (hilt_app > 1)) { + hilt_app--; + scroll_pad_up(hilt_app, + number_events_inday); + } + if ((which_pan == TODO) & (hilt_tod > 1)) { + hilt_tod--; + if (hilt_tod < first_todo_onscreen) + first_todo_onscreen--; + } + } + break; + + case (258): /* down arrow */ + case ('J'): + case ('j'): + if (which_pan == CALENDAR) { + do_storage = true; + day_changed = true; + if ((sel_day > days[sel_month - 1] - 7) & + (sel_month == 12)) + { /* next year */ + sel_day = (7 - (31 - sel_day)); + sel_month = 1; + sel_year++; + break; + } + if (sel_day > days[sel_month - 1] - 7) + { /* next month */ + sel_day = (7 - (days[sel_month - 1] - + sel_day)); + sel_month = sel_month + 1; + } else /* next week */ + sel_day = sel_day + 7; + } else { + if ((which_pan == APPOINTMENT) & (hilt_app < number_events_inday + number_apoints_inday)) + { + hilt_app++; + scroll_pad_down(hilt_app, + number_events_inday, + nl_app); + } + if ((which_pan == TODO) & (hilt_tod < nb_tod)) { + ++hilt_tod; + if (hilt_tod - first_todo_onscreen == + nl_tod - 4) + ++first_todo_onscreen; + } + } + break; + + case ('Q'): /* Quit calcurse :-( */ + case ('q'): + if (auto_save) + save_cal(auto_save,confirm_quit, + confirm_delete, skip_system_dialogs, + skip_progress_bar, + week_begins_on_monday, + colr, layout); + if (confirm_quit) { + status_mesg(_(quit_message), choices); + ch = wgetch(swin); + if ( ch == 'y' ) { + endwin(); + erase(); + return EXIT_SUCCESS; + } else { + erase_window_part(swin, 0, 0, nc_bar, nl_bar); + break; + } + } else { + endwin(); + erase(); + return EXIT_SUCCESS; + } + break; + + } /* end case statement */ + if (do_storage) { + store_day(sel_year, sel_month, sel_day, day_changed); + do_storage = !do_storage; + if (day_changed) { + sav_hilt_app = 0; + day_changed = !day_changed; + } + } + update_windows(which_pan); + } +} /* end of interactive mode */ + +/* + * EXTERNAL FUNCTIONS + */ + +/* + * Variables init + */ +void init_vars(int colr) +{ + // Variables for user configuration + confirm_quit = true; + confirm_delete = true; + auto_save = true; + skip_system_dialogs = false; + skip_progress_bar = false; + week_begins_on_monday = true; + + // Pad structure for scrolling text inside the appointment panel + apad = (struct pad_s *) malloc(sizeof(struct pad_s)); + apad->width = nc_app - 3; + apad->length = 1; + apad->first_onscreen = 0; + apad->ptrwin = newpad(apad->length, apad->width); + + // Attribute definitions for color and non-color terminals + custom_init_attr(colr); +} + +/* + * Update all of the three windows and put a border around the + * selected window. + */ +void update_windows(int surrounded_window) +{ + if (surrounded_window == CALENDAR) { + border_color(cwin, colr); + border_nocolor(awin); + border_nocolor(twin); + } else if (surrounded_window == APPOINTMENT) { + border_color(awin, colr); + border_nocolor(cwin); + border_nocolor(twin); + } else if (surrounded_window == TODO) { + border_color(twin, colr); + border_nocolor(awin); + border_nocolor(cwin); + } else { + /* NOTREACHED */ + fputs(_("FATAL ERROR in update_windows: no window selected\n"),stderr); + exit(EXIT_FAILURE); + } + update_app_panel(sel_year, sel_month, sel_day); + update_todo_panel(); + update_cal_panel(cwin, nl_cal, nc_cal, sel_month, + sel_year, sel_day, day, month, year, + week_begins_on_monday); + status_bar(surrounded_window, colr, nc_bar, nl_bar); + wmove(swin, 0, 0); + doupdate(); +} + +/* + * Get the screen size and recalculate the windows configurations. + */ +void get_screen_config(void) +{ + /* Get the screen configuration */ + getmaxyx(stdscr, row, col); + + /* window size definition */ + nl_cal = 12; + nc_cal = 30; + nc_app = col - nc_cal; + nl_app = row - 2; + nc_tod = nc_cal; + nl_tod = row - (nl_cal + 2); + nl_app = row - 2; + nl_bar = 2; y_bar = row - 2; + nc_bar = col; x_bar = 0; + + /* defining the layout */ + switch (layout) { + case 1: + y_app = 0; x_app = 0; y_cal = 0; + x_tod = nc_app; y_tod = nl_cal; x_cal = nc_app; + break; + case 2: + y_app = 0; x_app = 0; y_tod = 0; + x_tod = nc_app; x_cal = nc_app; y_cal = nl_tod; + break; + case 3: + y_app = 0; x_tod = 0; x_cal = 0; y_cal = 0; + x_app = nc_cal; y_tod = nl_cal; + break; + case 4: + y_app = 0; x_tod = 0; y_tod = 0; x_cal = 0; + x_app = nc_cal; y_cal = nl_tod; + break; + } +} + + + +/* Get current date */ +void get_date(void) +{ + timer = time(NULL); + ptrtime = localtime(&timer); + strftime(current_time, 15, "%H:%M%p", ptrtime); + strftime(cal_date, 30, "%a %B %Y", ptrtime); + strftime(current_day, 3, "%d", ptrtime); + strftime(current_month, 3, "%m", ptrtime); + strftime(current_year, 5, "%Y", ptrtime); + month = atoi(current_month); + day = atoi(current_day); + year = atoi(current_year); + sel_year = year; + sel_month = month; + sel_day = day; +} + +/* Create all the windows */ +void init_wins(void) +{ + char label[80]; + + /* Create the three main windows plus the status bar. */ + cwin = newwin(nl_cal, nc_cal, y_cal, x_cal); + sprintf(label, _("Calendar")); + win_show(cwin, label); + awin = newwin(nl_app, nc_app, y_app, x_app); + sprintf(label, _("Appointments")); + win_show(awin, label); + twin = newwin(nl_tod, nc_tod, y_tod, x_tod); + sprintf(label, _("ToDo")); + win_show(twin, label); + swin = newwin(nl_bar, nc_bar, y_bar, x_bar); + + /* Enable function keys (i.e. arrow keys) in those windows */ + keypad(swin, TRUE); + keypad(twin, TRUE); + keypad(awin, TRUE); + keypad(cwin, TRUE); +} + +/* + * Delete the existing windows and recreate them with their new + * size and placement. + */ +void reinit_wins(void) +{ + clear(); + delwin(swin); + delwin(cwin); + delwin(awin); + delwin(twin); + get_screen_config(); + init_wins(); + update_windows(which_pan); +} + +/* General configuration */ +void general_config(void) +{ + WINDOW *conf_win; + char label[80]; + char *number_str = _("Enter an option number to change its value [Q to quit] "); + int ch; + + clear(); + conf_win = newwin(row - 2, col, 0, 0); + box(conf_win, 0, 0); + sprintf(label, _("CalCurse %s | general options"), VERSION); + win_show(conf_win, label); + status_mesg(number_str, ""); + print_general_options(conf_win); + while ((ch = wgetch(swin)) != 'q') { + switch (ch) { + case '1': + auto_save = !auto_save; + break; + case '2': + confirm_quit = !confirm_quit; + break; + case '3': + confirm_delete = !confirm_delete; + break; + case '4': + skip_system_dialogs = + !skip_system_dialogs; + break; + case '5': + skip_progress_bar = + !skip_progress_bar; + break; + case '6': + week_begins_on_monday = + !week_begins_on_monday; + break; + } + print_general_options(conf_win); + } + delwin(conf_win); +} + +/* prints the general options */ +void print_general_options(WINDOW *win) +{ + int x_pos, y_pos; + char *option1 = _("auto_save = "); + char *option2 = _("confirm_quit = "); + char *option3 = _("confirm_delete = "); + char *option4 = _("skip_system_dialogs = "); + char *option5 = _("skip_progress_bar = "); + char *option6 = _("week_begins_on_monday = "); + + x_pos = 3; + y_pos = 4; + + mvwprintw(win, y_pos, x_pos, "[1] %s ", option1); + print_option_incolor(win, auto_save, y_pos, + x_pos + 4 + strlen(option1)); + mvwprintw(win, y_pos + 1, x_pos, + _("(if set to YES, automatic save is done when quitting)")); + + mvwprintw(win, y_pos + 3, x_pos, "[2] %s ", option2); + print_option_incolor(win, confirm_quit, y_pos + 3, + x_pos + 4 + strlen(option2)); + mvwprintw(win, y_pos + 4, x_pos, + _("(if set to YES, confirmation is required before quitting)")); + + mvwprintw(win, y_pos + 6, x_pos, "[3] %s ", option3); + print_option_incolor(win, confirm_delete, y_pos + 6, + x_pos + 4 + strlen(option3)); + mvwprintw(win, y_pos + 7, x_pos, + _("(if set to YES, confirmation is required before deleting an event)")); + + mvwprintw(win, y_pos + 9, x_pos, "[4] %s ", option4); + print_option_incolor(win, skip_system_dialogs, y_pos + 9, + x_pos + 4 + strlen(option4)); + mvwprintw(win, y_pos + 10, x_pos, + _("(if set to YES, messages about loaded and saved data will not be displayed)")); + + mvwprintw(win, y_pos + 12, x_pos, "[5] %s ", option5); + print_option_incolor(win, skip_progress_bar , y_pos + 12, + x_pos + 4 + strlen(option5)); + mvwprintw(win, y_pos + 13, x_pos, + _("(if set to YES, progress bar will not be displayed when saving data)")); + + mvwprintw(win, y_pos + 15, x_pos, "[6] %s ", option6); + print_option_incolor(win, week_begins_on_monday , y_pos + 15, + x_pos + 4 + strlen(option6)); + mvwprintw(win, y_pos + 16, x_pos, + _("(if set to YES, monday is the first day of the week, else it is sunday)")); + + wmove(swin, 1, 0); + wnoutrefresh(win); + doupdate(); +} + +/* print the option value with appropriate color */ +void print_option_incolor(WINDOW *win, bool option, int pos_y, int pos_x) +{ + int color; + char *option_value; + + if (option == true) { + color = ATTR_TRUE; + option_value = _("yes"); + } else if (option == false) { + color = ATTR_FALSE; + option_value = _("no"); + } else { + erase_window_part(win, 0, 0, col, row - 2); + mvwprintw(win, 1, 1, + _("option not defined - Problem in print_option_incolor()")); + wnoutrefresh(win); + doupdate(); + wgetch(win); + exit(EXIT_FAILURE); + } + custom_apply_attr(win, color); + mvwprintw(win, pos_y, pos_x, "%s", option_value); + custom_remove_attr(win, color); + wnoutrefresh(win); + doupdate(); +} + + /* Delete an event from the ToDo or Appointment lists */ +void del_apoint(void) +{ + char *choices = "[y/n] "; + char *del_app_str = _("Do you really want to delete this item ?"); + char *del_todo_str = _("Do you really want to delete this task ?"); + long date; + int nb_items = number_apoints_inday + number_events_inday; + bool go_for_deletion = false; + bool go_for_todo_del = false; + int to_be_removed = 0; + int answer = 0; + + /* delete an appointment */ + if (which_pan == APPOINTMENT && hilt_app != 0) { + date = date2sec(sel_year, sel_month, sel_day, 0, 0); + + if (confirm_delete) { + status_mesg(del_app_str, choices); + answer = wgetch(swin); + if ( (answer == 'y') && (nb_items != 0) ) + go_for_deletion = true; + else { + erase_window_part(swin, 0, 0, nc_bar, nl_bar); + return; + } + } else + if (nb_items != 0) + go_for_deletion = true; + + if (go_for_deletion) { + if (nb_items != 0) { + if (hilt_app <= number_events_inday) { + event_delete_bynum(date, hilt_app - 1); + number_events_inday--; + to_be_removed = 1; + } else { + apoint_delete_bynum(date, + hilt_app - + number_events_inday - 1); + number_apoints_inday--; + to_be_removed = 3; + } + if (hilt_app > 1) --hilt_app; + if (apad->first_onscreen >= to_be_removed) + apad->first_onscreen = + apad->first_onscreen - + to_be_removed; + } + } + + /* delete a todo */ + } else if (which_pan == TODO && hilt_tod != 0) { + if (confirm_delete) { + status_mesg(del_todo_str, choices); + answer = wgetch(swin); + if ( (answer == 'y') && (nb_tod > 0) ) { + go_for_todo_del = true; + } else { + erase_window_part(swin, 0, 0, nc_bar, nl_bar); + return; + } + } else + if (nb_tod > 0) + go_for_todo_del = true; + + if (go_for_todo_del) { + todo_delete_bynum(hilt_tod - 1); + nb_tod--; + if (hilt_tod > 1) hilt_tod--; + } + } +} + + /* Add an item in the ToDo list */ +void add_todo(void) +{ + char *mesg = _("Enter the new ToDo item : "); + char todo_input[500]; + + status_mesg(mesg, ""); + getstring(swin, colr, todo_input, 0, 1); + if (strlen(todo_input) != 0) { + todo_insert(todo_input); + ++nb_tod; + update_todo_panel(); + } + erase_window_part(swin, 0, 0, nc_bar, nl_bar); + status_bar(which_pan, colr, nc_bar, nl_bar); + doupdate(); +} + +/* + * Add an item in either the appointment or the event list, + * depending if the start time is entered or not. + */ +void add_item(void) +{ + char *mesg_1 = _("Enter start time ([hh:mm] or [h:mm]), leave blank for an all-day event : "); + char *mesg_2 = _("Enter end time ([hh:mm] or [h:mm]) or duration (in minutes) : "); + char *mesg_3 = _("Enter description :"); + char *format_message_1 = _("You entered an invalid start time, should be [h:mm] or [hh:mm]"); + char *format_message_2 = _("You entered an invalid end time, should be [h:mm] or [hh:mm] or [mm]"); + char *enter_str = _("Press [Enter] to continue"); + int Id; + char item_time[500]; + char item_mesg[500]; + long apoint_duration; + struct apoint_s *apoint_pointeur; + struct event_s *event_pointeur; + unsigned heures, minutes; + unsigned end_h, end_m; + int is_appointment = 1; + + /* Get the starting time */ + strcpy(item_time, " "); + while (check_time(item_time) == 0) { + status_mesg(mesg_1, ""); + getstring(swin, colr, item_time, 0, 1); + if (strlen(item_time) == 0){ + is_appointment = 0; + break; + } else if (check_time(item_time) != 1) { + status_mesg(format_message_1, enter_str); + wgetch(swin); + } else + sscanf(item_time, "%u:%u", &heures, &minutes); + } + /* + * Check if an event or appointment is entered, + * depending on the starting time, and record the + * corresponding item. + */ + if (is_appointment){ /* Get the appointment duration */ + strcpy(item_time, " "); + while (check_time(item_time) == 0) { + status_mesg(mesg_2, ""); + getstring(swin, colr, item_time, 0, 1); + if (strlen(item_time) == 0) + return; //nothing entered, cancel adding of event + else if (check_time(item_time) == 0) { + status_mesg(format_message_2, enter_str); + wgetch(swin); + } else { + if (check_time(item_time) == 2) + apoint_duration = atoi(item_time); + else if (check_time(item_time) == 1) { + sscanf(item_time, "%u:%u", + &end_h, &end_m); + if (end_h < heures){ + apoint_duration = + (60 - minutes + end_m) + + (24 + end_h - (heures + 1))*60; + } else { + apoint_duration = + (60 - minutes + end_m) + + (end_h - (heures + 1))*60; + } + } + } + } + } else { /* Insert the event Id */ + Id = 1; + } + // get the item description + status_mesg(mesg_3, ""); + getstring(swin, colr, item_mesg, 0, 1); + if (strlen(item_mesg) != 0) { + if (is_appointment){ + // insert the appointment in list + apoint_pointeur = + apoint_new(item_mesg, + date2sec(sel_year, sel_month, sel_day, + heures, minutes), + min2sec(apoint_duration)); + // insert the event in list + } else { + event_pointeur = event_new(item_mesg, date2sec( + sel_year, + sel_month, + sel_day, + 12, 0), + Id); + } + update_app_panel(sel_year, sel_month, sel_day); + } + erase_window_part(swin, 0, 0, nc_bar, nl_bar); + status_bar(which_pan, colr, nc_bar, nl_bar); + doupdate(); +} + +/* Updates the ToDo panel */ +void update_todo_panel(void) +{ + struct todo_s *i; + int len = nc_tod - 5; + int num_todo = 0; + int y_offset = 3, x_offset = 1; + int t_realpos = -1; + int title_lines = 3; + int todo_lines = 1; + int max_items = nl_tod - 4; + int incolor = -1; + + /* Print todo item in the panel. */ + erase_window_part(twin, 1, title_lines, nc_tod - 2, nl_tod - 2); + for (i = todolist; i != 0; i = i->next) { + num_todo++; + t_realpos = num_todo - first_todo_onscreen; + incolor = num_todo - hilt_tod; + if (incolor == 0) saved_t_mesg = i->mesg; + if (t_realpos >= 0 && t_realpos < max_items) { + display_item(twin, incolor, i->mesg, + len, y_offset, x_offset); + y_offset = y_offset + todo_lines; + } + } + + /* Draw the scrollbar if necessary. */ + if (nb_tod > max_items){ + float ratio = ((float) max_items) / ((float) nb_tod); + int sbar_length = (int) (ratio * (max_items + 1)); + int highend = (int) (ratio * first_todo_onscreen); + bool hilt_bar = (which_pan == TODO) ? true : false; + int sbar_top = highend + title_lines; + + if ((sbar_top + sbar_length) > nl_tod - 1) + sbar_length = nl_tod - 1 - sbar_top; + draw_scrollbar(twin, sbar_top, nc_tod - 2, + sbar_length, title_lines, nl_tod - 1, hilt_bar); + } + + wnoutrefresh(twin); +} + +/* Updates the Appointment panel */ +void update_app_panel(int year, int month, int day) +{ + int title_xpos; + int bordr = 1; + int title_lines = 3; + int app_width = nc_app - bordr; + int app_length = nl_app - bordr - title_lines; + long date; + + /* variable inits */ + title_xpos = nc_app - (strlen(_(monthnames[sel_month - 1])) + 11); + if (sel_day < 10) title_xpos++; + date = date2sec(year, month, day, 0, 0); + day_write_pad(date, app_width, app_length, hilt_app, colr); + + /* Print current date in the top right window corner. */ + erase_window_part(awin, 1, title_lines, nc_app - 2, nl_app - 2); + custom_apply_attr(awin, ATTR_HIGHEST); + mvwprintw(awin, title_lines, title_xpos, "%s %d, %d", + _(monthnames[sel_month - 1]), sel_day, sel_year); + custom_remove_attr(awin, ATTR_HIGHEST); + + /* Draw the scrollbar if necessary. */ + if ((apad->length >= app_length)||(apad->first_onscreen > 0)) { + float ratio = ((float) app_length) / ((float) apad->length); + int sbar_length = (int) (ratio * app_length); + int highend = (int) (ratio * apad->first_onscreen); + bool hilt_bar = (which_pan == APPOINTMENT) ? true : false; + int sbar_top = highend + title_lines + 1; + + if ((sbar_top + sbar_length) > nl_app - 1) + sbar_length = nl_app - 1 - sbar_top; + draw_scrollbar(awin, sbar_top, nc_app - 2, sbar_length, + title_lines + 1, nl_app - 1, hilt_bar); + } + + wnoutrefresh(awin); + pnoutrefresh(apad->ptrwin, apad->first_onscreen, 0, + y_app + title_lines + 1, x_app + bordr, + y_app + nl_app - 2*bordr, x_app + nc_app - 2*bordr); +} + +/* + * Store the events and appointments for the selected day, and write + * those items in a pad. + * This is useful to speed up the appointment panel update. + */ +void store_day(int year, int month, int day, bool day_changed) +{ + long date; + date = date2sec(year, month, day, 0, 0); + + /* Inits */ + if (apad->length != 0) + delwin(apad->ptrwin); + + /* Store the events and appointments (recursive and normal items). */ + apad->length = day_store_items(date, + &number_events_inday, &number_apoints_inday); + + /* Create the new pad with its new length. */ + if (day_changed) apad->first_onscreen = 0; + apad->ptrwin = newpad(apad->length, apad->width); +} + +/* Load the user configuration */ +void load_conf(void) +{ + FILE *data_file; + char *mesg_line1 = _("Failed to open config file"); + char *mesg_line2 = _("Press [ENTER] to continue"); + char buf[100], e_conf[100]; + int var; + + data_file = fopen(path_conf, "r"); + if (data_file == NULL) { + status_mesg(mesg_line1, mesg_line2); + wnoutrefresh(swin); + doupdate(); + wgetch(swin); + } + var = 0; + for (;;) { + if (fgets(buf, 99, data_file) == NULL) { + break; + } + extract_data(e_conf, buf, strlen(buf)); + if (var == 1) { + auto_save = + fill_config_var(e_conf); + var = 0; + } else if (var == 2) { + confirm_quit = + fill_config_var(e_conf); + var = 0; + } else if (var == 3) { + confirm_delete = + fill_config_var(e_conf); + var = 0; + } else if (var == 4) { + skip_system_dialogs = + fill_config_var(e_conf); + var = 0; + } else if (var == 5) { + skip_progress_bar = + fill_config_var(e_conf); + var = 0; + } else if (var == 6) { + week_begins_on_monday = + fill_config_var(e_conf); + var = 0; + } else if (var == 7) { + colr = atoi(e_conf); + if (colr == 0) colorize = false; + var = 0; + } else if (var == 8) { + layout = atoi(e_conf); + var = 0; + } + if (strncmp(e_conf, "auto_save=", 10) == 0) + var = 1; + else if (strncmp(e_conf, "confirm_quit=", 13) == 0) + var = 2; + else if (strncmp(e_conf, "confirm_delete=", 15) == 0) + var = 3; + else if (strncmp(e_conf, "skip_system_dialogs=", 20) == 0) + var = 4; + else if (strncmp(e_conf, "skip_progress_bar=", 18) == 0) + var = 5; + else if (strncmp(e_conf, "week_begins_on_monday=", 23) == 0) + var = 6; + else if (strncmp(e_conf, "color-theme=", 12) == 0) + var = 7; + else if (strncmp(e_conf, "layout=", 7) == 0) + var = 8; + } + fclose(data_file); + erase_window_part(swin, 0, 0, nc_bar, nl_bar); +} + +bool fill_config_var (char *string) { + if (strncmp(string, "yes", 3) == 0) + return true; + else if (strncmp(string, "no", 2) == 0) + return false; + else { + fputs(_("FATAL ERROR in fill_config_var: " + "wrong configuration variable format.\n"), stderr); + return EXIT_FAILURE; + } +} |