From ac36e94341ca73d581f0df39f1c7bbf2138b2845 Mon Sep 17 00:00:00 2001
From: Frederic Culot <calcurse@culot.org>
Date: Mon, 31 Jul 2006 21:00:02 +0000
Subject: Initial revision

---
 src/Makefile.am |   14 +
 src/apoint.c    |  235 +++++++++++
 src/apoint.h    |   56 +++
 src/args.c      |  431 +++++++++++++++++++++
 src/args.h      |   41 ++
 src/calcurse.1  |  158 ++++++++
 src/calcurse.c  | 1156 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/calendar.c  |  227 +++++++++++
 src/calendar.h  |   41 ++
 src/custom.c    |  178 +++++++++
 src/custom.h    |   42 ++
 src/day.c       |  362 +++++++++++++++++
 src/day.h       |   66 ++++
 src/event.c     |  135 +++++++
 src/event.h     |   48 +++
 src/help.c      |  375 ++++++++++++++++++
 src/help.h      |   41 ++
 src/i18n.h      |   54 +++
 src/io.c        |  484 +++++++++++++++++++++++
 src/io.h        |   42 ++
 src/recur.c     |  355 +++++++++++++++++
 src/recur.h     |   87 +++++
 src/todo.c      |   80 ++++
 src/todo.h      |   41 ++
 src/utils.c     |  614 +++++++++++++++++++++++++++++
 src/utils.h     |   55 +++
 src/vars.c      |   85 ++++
 src/vars.h      |   69 ++++
 28 files changed, 5572 insertions(+)
 create mode 100755 src/Makefile.am
 create mode 100755 src/apoint.c
 create mode 100755 src/apoint.h
 create mode 100755 src/args.c
 create mode 100755 src/args.h
 create mode 100755 src/calcurse.1
 create mode 100755 src/calcurse.c
 create mode 100755 src/calendar.c
 create mode 100755 src/calendar.h
 create mode 100755 src/custom.c
 create mode 100755 src/custom.h
 create mode 100755 src/day.c
 create mode 100755 src/day.h
 create mode 100755 src/event.c
 create mode 100755 src/event.h
 create mode 100755 src/help.c
 create mode 100755 src/help.h
 create mode 100755 src/i18n.h
 create mode 100755 src/io.c
 create mode 100755 src/io.h
 create mode 100755 src/recur.c
 create mode 100755 src/recur.h
 create mode 100755 src/todo.c
 create mode 100755 src/todo.h
 create mode 100755 src/utils.c
 create mode 100755 src/utils.h
 create mode 100755 src/vars.c
 create mode 100755 src/vars.h

(limited to 'src')

diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100755
index 0000000..1614db1
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,14 @@
+#	$calcurse: Makefile.am,v 1.1 2006/07/31 21:00:02 culot Exp $
+
+AUTOMAKE_OPTIONS= gnu 
+bin_PROGRAMS= calcurse
+calcurse_SOURCES= calcurse.c apoint.c event.c todo.c utils.c\
+			calendar.c vars.c io.c help.c custom.c args.c\
+			day.c recur.c\
+			apoint.h event.h todo.h utils.h calendar.h\
+			vars.h io.h help.h custom.h args.h i18n.h\
+			day.h recur.h
+LIBS= -lncurses -lm
+LDADD= @LTLIBINTL@
+man_MANS= calcurse.1
+EXTRA_DIST= calcurse.1
diff --git a/src/apoint.c b/src/apoint.c
new file mode 100755
index 0000000..5cbc62e
--- /dev/null
+++ b/src/apoint.c
@@ -0,0 +1,235 @@
+/*	$calcurse: apoint.c,v 1.1 2006/07/31 21:00:03 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
+ *
+ */
+
+#include <ncurses.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <time.h>
+
+#include "i18n.h"
+#include "vars.h"
+#include "event.h"
+#include "apoint.h"
+#include "day.h"
+#include "custom.h"
+#include "utils.h"
+
+struct apoint_s *apointlist;
+
+struct apoint_s *apoint_new(char *mesg, long start, long dur)
+{
+	struct apoint_s *o, **i;
+	o = (struct apoint_s *) malloc(sizeof(struct apoint_s));
+	o->mesg = (char *) malloc(strlen(mesg) + 1);
+	strcpy(o->mesg, mesg);
+	o->start = start;
+	o->dur = dur;
+	i = &apointlist;
+	for (;;) {
+		if (*i == 0 || (*i)->start > start) {
+			o->next = *i;
+			*i = o;
+			break;
+		}
+		i = &(*i)->next;
+	}
+	return o;
+}
+
+unsigned apoint_inday(struct apoint_s *i, long start)
+{
+	if (i->start <= start + 3600 * 24 && i->start + i->dur > start) {
+		return 1;
+	}
+	return 0;
+}
+
+void apoint_sec2str(struct apoint_s *o, int type, long day, char *start, char *end)
+{
+	struct tm *lt;
+	time_t t;
+
+	if (o->start < day && type == APPT) {
+		strcpy(start, "..:..");
+	} else {
+		t = o->start;
+		lt = localtime(&t);
+		snprintf(start, HRMIN_SIZE, "%02u:%02u", lt->tm_hour,
+			 lt->tm_min);
+	}
+	if (o->start + o->dur > day + 24 * 3600 && type == APPT) {
+		strcpy(end, "..:..");
+	} else {
+		t = o->start + o->dur;
+		lt = localtime(&t);
+		snprintf(end, HRMIN_SIZE, "%02u:%02u", lt->tm_hour,
+			 lt->tm_min);
+	}
+}
+
+void apoint_write(struct apoint_s *o, FILE * f)
+{
+	struct tm *lt;
+	time_t t;
+
+	t = o->start;
+	lt = localtime(&t);
+	fprintf(f, "%02u/%02u/%04u @ %02u:%02u",
+		lt->tm_mon + 1, lt->tm_mday, 1900 + lt->tm_year,
+		lt->tm_hour, lt->tm_min);
+
+	t = o->start + o->dur;
+	lt = localtime(&t);
+	fprintf(f, " -> %02u/%02u/%04u @ %02u:%02u |%s\n",
+		lt->tm_mon + 1, lt->tm_mday, 1900 + lt->tm_year,
+		lt->tm_hour, lt->tm_min, o->mesg);
+}
+
+struct apoint_s *apoint_scan(FILE * f, struct tm start, struct tm end)
+{
+	struct tm *lt;
+	char buf[MESG_MAXSIZE], *nl;
+	time_t tstart, tend, t;
+
+	t = time(NULL);
+	lt = localtime(&t);
+
+        /* Read the appointment description */
+	fgets(buf, MESG_MAXSIZE, f);
+	nl = strchr(buf, '\n');
+	if (nl) {
+		*nl = '\0';
+	}
+
+	start.tm_sec = end.tm_sec = 0;
+	start.tm_isdst = end.tm_isdst = -1;
+	start.tm_year -= 1900;
+	start.tm_mon--;
+	end.tm_year -= 1900;
+	end.tm_mon--;
+
+	tstart = mktime(&start);
+	tend = mktime(&end);
+	if (tstart == -1 || tend == -1 || tstart > tend) {
+		fputs(_("FATAL ERROR in apoint_scan: date error in the appointment\n"), stderr);
+		exit(EXIT_FAILURE);
+	}
+	return apoint_new(buf, tstart, tend - tstart);
+}
+
+void apoint_delete_bynum(long start, unsigned num)
+{
+	unsigned n;
+	struct apoint_s *i, **iptr;
+
+	n = 0;
+	iptr = &apointlist;
+	for (i = apointlist; i != 0; i = i->next) {
+		if (apoint_inday(i, start)) {
+			if (n == num) {
+				*iptr = i->next;
+				free(i->mesg);
+				free(i);
+				return;
+			}
+			n++;
+		}
+		iptr = &i->next;
+	}
+	/* NOTREACHED */
+	fputs(_("FATAL ERROR in apoint_delete_bynum: no such appointment\n"), stderr);
+	exit(EXIT_FAILURE);
+}
+
+/* 
+ * Print an item date in the appointment panel.
+ */
+void display_item_date(WINDOW *win, int incolor, struct apoint_s *i,
+			int type, long date, int y, int x)
+{
+	char a_st[100], a_end[100];
+
+	apoint_sec2str(i, type, date, a_st, a_end);
+
+	if (incolor == 0) 
+		custom_apply_attr(win, ATTR_HIGHEST);
+	mvwprintw(win, y, x, " - %s -> %s", a_st, a_end);
+	if (incolor == 0) 
+		custom_remove_attr(awin, ATTR_HIGHEST);
+}
+
+/*
+ * Return the line number of an item (either an appointment or an event) in
+ * the appointment panel. This is to help the appointment scroll function 
+ * to place beggining of the pad correctly.
+ */
+int get_item_line(int item_nb, int nb_events_inday)
+{
+	int separator = 2;
+	int line = 0;
+	
+	if (item_nb <= nb_events_inday)
+		line = item_nb - 1;
+	else 
+		line = nb_events_inday + separator + 
+			(item_nb - (nb_events_inday + 1))*3 - 1;	
+	return line;
+}
+
+/* 
+ * Update (if necessary) the first displayed pad line to make the
+ * appointment panel scroll down next time pnoutrefresh is called. 
+ */
+void scroll_pad_down(int item_nb, int nb_events_inday, int win_length) 
+{
+	int pad_last_line = 0;
+	int item_first_line = 0, item_last_line = 0;
+	int borders = 6;
+	int awin_length = win_length - borders;
+
+	item_first_line = get_item_line(item_nb, nb_events_inday);
+	if (item_nb < nb_events_inday)
+		item_last_line = item_first_line;
+	else
+		item_last_line = item_first_line + 1;
+	pad_last_line = apad->first_onscreen + awin_length;
+	if (item_last_line >= pad_last_line)
+		apad->first_onscreen = item_last_line - awin_length;
+}
+
+/* 
+ * Update (if necessary) the first displayed pad line to make the
+ * appointment panel scroll up next time pnoutrefresh is called. 
+ */
+void scroll_pad_up(int item_nb, int nb_events_inday)
+{
+	int item_first_line = 0;
+
+	item_first_line = get_item_line(item_nb, nb_events_inday);
+	if (item_first_line < apad->first_onscreen)
+		apad->first_onscreen = item_first_line;
+}
diff --git a/src/apoint.h b/src/apoint.h
new file mode 100755
index 0000000..e9dbe82
--- /dev/null
+++ b/src/apoint.h
@@ -0,0 +1,56 @@
+/*	$calcurse: apoint.h,v 1.1 2006/07/31 21:00:03 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
+ *
+ */
+
+#ifndef CALCURSE_APOINT_H
+#define CALCURSE_APOINT_H
+
+#include <ncurses.h>
+
+#define HRMIN_SIZE 6
+#define MESG_MAXSIZE 256
+
+struct apoint_s {
+	struct apoint_s *next;
+	long start;		/* seconds since 1 jan 1970 */
+	long dur;		/* duration of the appointment in seconds */
+	char *mesg;
+};
+
+extern struct apoint_s *apointlist;
+
+struct apoint_s *apoint_new(char *, long, long);
+unsigned apoint_inday(struct apoint_s *o, long start);
+void apoint_sec2str(struct apoint_s *o, int type, long day, char *start, char *end);
+void apoint_write(struct apoint_s *o, FILE * f);
+struct apoint_s *apoint_scan(FILE * f, struct tm start, struct tm end);
+void apoint_delete_bynum(long start, unsigned num);
+void display_item_date(WINDOW *win, int color, struct apoint_s *i,
+		int type, long date, int y, int x);
+int get_item_line(int item_nb, int nb_events_inday);
+void scroll_pad_down(int item_nb, int nb_events_inday, int win_length);
+void scroll_pad_up(int item_nb, int nb_events_inday);
+
+#endif /* CALCURSE_APOINT_H */
diff --git a/src/args.c b/src/args.c
new file mode 100755
index 0000000..2261640
--- /dev/null
+++ b/src/args.c
@@ -0,0 +1,431 @@
+/*	$calcurse: args.c,v 1.1 2006/07/31 21:00:03 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
+ *
+ */
+
+#include <ncurses.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdbool.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <time.h>
+
+#include "i18n.h"
+#include "utils.h"
+#include "args.h"
+#include "vars.h"
+#include "event.h"
+#include "apoint.h"
+#include "recur.h"
+#include "day.h"
+#include "todo.h"
+#include "io.h"
+
+/* 
+ * Parse the command-line arguments and call the appropriate
+ * routines to handle those arguments. Also initialize the data paths.
+ */
+int parse_args(int argc, char **argv, int colr)
+{
+	int ch, add_line = 0;
+	int unknown_flag = 0, app_found = 0;
+	int aflag = 0, cflag = 0, dflag = 0, vflag = 0, hflag = 0, tflag = 0;
+	int non_interactive = 0, multiple_flag = 0, load_data = 0;
+	int no_file = 1;
+	char *ddate = "", *cfile = NULL;
+
+	while ((ch = getopt(argc, argv, "hvtad:c:")) != -1) {
+		switch (ch) {
+		case 'a':
+			aflag = 1;
+			multiple_flag++;
+			load_data++;
+			break;
+		case 'd':
+			dflag = 1;
+			multiple_flag++;
+			load_data++;
+			ddate = optarg;
+			break;
+		case 'c':
+			cflag = 1;
+			multiple_flag++;
+			load_data++;
+			cfile = optarg;
+			break;
+		case 'h':
+			hflag = 1;
+			break;
+		case 't':
+			tflag = 1;
+			multiple_flag++;
+			load_data++;
+			add_line = 1;
+			break;
+		case 'v':
+			vflag = 1;
+			break;
+		default:
+			usage();
+                        usage_try();
+			unknown_flag = 1;
+			non_interactive = 1;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+	if (argc >= 1) {	/* incorrect arguments */
+		usage();
+                usage_try();
+		return 1;
+	} else {
+		if (unknown_flag) {
+			non_interactive = 1;
+		} else if (hflag) {
+			help_arg();
+			non_interactive = 1;
+		} else if (vflag) {
+			version_arg();
+			non_interactive = 1;
+		} else if (multiple_flag) {
+			if (load_data) {
+				io_init(cfile);
+				no_file = check_data_files();
+				if (dflag || aflag) 
+					load_app(colr);
+			}
+			if (tflag) {
+				todo_arg(colr);
+				non_interactive = 1;
+			}
+			if (dflag) {
+				date_arg(ddate, add_line);
+				non_interactive = 1;
+			} else if (aflag) {
+				app_found = app_arg(add_line,0,0,0,0);
+				non_interactive = 1;
+			}
+		} else {
+			non_interactive = 0;
+			io_init(cfile);
+			no_file = check_data_files();
+		}
+		return non_interactive;
+	}
+}
+
+/*
+ * Print Calcurse version with a short copyright text and exit.
+ */
+void version_arg()
+{
+	char vtitle[50];
+	char *vtext =
+	    _("\nCopyright (c) 2004-2006 Frederic Culot.\n"
+	    "This is free software; see the source for copying conditions.\n");
+
+	sprintf(vtitle, _("Calcurse %s - text-based organizer\n"), VERSION);
+	fputs(vtitle, stdout);
+	fputs(vtext, stdout);
+}
+
+/* 
+ * Print the command line options and exit.
+ */
+void help_arg()
+{
+	char htitle[50];
+	char *htext =
+		_("\nMiscellaneous:\n"
+		"  -h		print this help and exit.\n"
+		"  -v		print calcurse version and exit.\n"
+		"\nOptions:\n"
+		"  -c <file>	specify the calendar <file> to use.\n"
+		"\nNon-interactive:\n"
+		"  -a 		print events and appointments for current day and exit.\n"
+		"  -d <date|num>	print events and appointments for <date> "
+		"or <num> upcoming\n\t\tdays and exit. Possible formats are: "
+		"'mm/dd/yyyy' or 'n'.\n"
+		"  -t		print todo list and exit.\n"
+	    	"\nFor more information, type '?' from within Calcurse, "
+		"or read the manpage.\n"
+	    	"Mail bug reports and suggestions to <calcurse@culot.org>.\n");
+
+	sprintf(htitle, _("Calcurse %s - text-based organizer\n"), VERSION);
+	fputs(htitle, stdout);
+        usage();
+	fputs(htext, stdout);
+}
+
+/*
+ * Print todo list and exit.
+ */
+void todo_arg(int colr)
+{
+	struct todo_s *i;
+	int nb_tod;
+
+	nb_tod = load_todo(colr);
+	fputs(_("to do:\n"),stdout);
+	for (i = todolist; i != 0; i = i->next) {
+		fputs(" - ",stdout);
+		fputs(i->mesg,stdout);
+		fputs("\n",stdout);
+	}
+}
+
+/*
+ * Print appointments for given day and exit.
+ * If no year, month, and day is given, the given date is used.
+ * If there is also no date given, current date is considered.
+ */
+int app_arg(int add_line, int year, int month, int day, long date)
+{
+	struct recur_event_s *re;
+	struct event_s *j;
+	struct recur_apoint_s *ra;
+	struct apoint_s *i;
+	long today;
+	bool print_date = true;
+	int  app_found = 0;
+	char apoint_start_time[100];
+	char apoint_end_time[100];
+	
+	if (date == 0) {
+		today = get_sec_date(year, month, day);
+	} else today = date;
+
+	/* 
+	 * Calculate and print the selected date if there is an event for
+ 	 * that date and it is the first one, and then print all the events for
+ 	 * that date. 
+	 */
+	for (re = recur_elist; re != 0; re = re->next) {
+		if (recur_item_inday(re->day, re->rpt->type, re->rpt->freq,
+			re->rpt->until, today)) {
+			app_found = 1;
+			if (add_line) {
+				fputs("\n", stdout);
+				add_line = 0;
+			}
+			if (print_date) {
+				arg_print_date(today);
+				print_date = false;
+			}
+			fputs(" o ", stdout);
+			fputs(re->mesg, stdout); fputs("\n", stdout);
+		}
+	}
+
+	for (j = eventlist; j != 0; j = j->next) {
+		if (event_inday(j, today)) {
+			app_found = 1;
+			if (add_line) {
+				fputs("\n",stdout);
+				add_line = 0;
+			}
+			if (print_date) {
+				arg_print_date(today);
+				print_date = false;
+			}
+			fputs(" o ",stdout);
+			fputs(j->mesg,stdout); fputs("\n",stdout);
+		}	
+	}
+
+ 	 /* Same process is performed but this time on the appointments. */
+	for (ra = recur_alist; ra != 0; ra = ra->next) {
+		if (recur_item_inday(ra->start, ra->rpt->type, ra->rpt->freq,
+			ra->rpt->until, today)) {
+			app_found = 1;
+			if (add_line) {
+				fputs("\n",stdout);
+				add_line = 0;
+			}
+			if (print_date) {
+				arg_print_date(today);
+				print_date = false;
+			}
+			apoint_sec2str(recur_apoint_s2apoint_s(ra),
+				RECUR_APPT, today, apoint_start_time,
+				apoint_end_time);
+			fputs(" - ",stdout);
+			fputs(apoint_start_time,stdout);
+			fputs(" -> ",stdout);
+			fputs(apoint_end_time,stdout); fputs("\n\t",stdout);
+			fputs(ra->mesg,stdout); fputs("\n",stdout);
+		}
+	}
+
+	for (i = apointlist; i != 0; i = i->next) {
+		if (apoint_inday(i, today)) {
+			app_found = 1;
+			if (add_line) {
+				fputs("\n",stdout);
+				add_line = 0;
+			}
+			if (print_date) {
+				arg_print_date(today);
+				print_date = false;
+			}
+			apoint_sec2str(i, APPT, today, apoint_start_time,
+					apoint_end_time);
+			fputs(" - ",stdout);
+			fputs(apoint_start_time,stdout);
+			fputs(" -> ",stdout);
+			fputs(apoint_end_time,stdout); fputs("\n\t",stdout);
+			fputs(i->mesg,stdout); fputs("\n",stdout);
+		}	
+	}
+	return app_found;
+}
+
+/*
+ * Print appointment for the given date or for the given n upcoming
+ * days.
+ */
+void date_arg(char *ddate, int add_line)
+{
+	int i;
+	int year = 0, month = 0, day = 0;
+	int numdays = 0, num_digit = 0;
+	int arg_len = 0, app_found = 0;
+	int date_valid = 0;
+	long today, ind;
+	int sec_in_day = 86400;
+
+	/* 
+	 * Check (with the argument length) if a date or a number of days 
+	 * was entered, and then call app_arg() to print appointments
+	 */
+	arg_len = strlen(ddate);
+	if (arg_len <= 4) { 		/* a number of days was entered */
+		for (i = 0; i <= arg_len-1; i++) { 
+			if (isdigit(ddate[i])) num_digit++;	
+		}
+		if (num_digit == arg_len) numdays = atoi(ddate);
+
+		/* 
+		 * Get current date, and print appointments for each day
+ 		 * in the chosen interval. app_found and add_line are used
+ 		 * to format the output correctly. 
+		 */
+		today = get_sec_date(year, month, day);
+		ind = today;
+		for (i = 0; i < numdays; i++) {
+			app_found = app_arg(add_line, 0, 0, 0, ind);
+			add_line = app_found;
+			ind = ind + sec_in_day;
+		}
+	} else {			/* a date was entered */
+		date_valid = check_date(ddate);
+		if (date_valid) {
+			sscanf(ddate, "%d / %d / %d", &month, &day, &year);
+			app_found = app_arg(add_line, year, month, day, 0);
+		} else {
+			fputs(_("Argument to the '-d' flag is not valid\n"),stdout);
+			fputs(_("Possible argument formats are : 'mm/dd/yyyy' or 'n'\n"),stdout);
+			fputs(_("\nFor more information, type '?' from within Calcurse, or read the manpage.\n"),stdout);
+			fputs
+	    (_("Mail bug reports and suggestions to <calcurse@culot.org>.\n"),
+	     stdout);
+		}
+	}
+}
+
+/*
+ * Check if the entered date is of a valid format.
+ * First check the format by itself, and then check the 
+ * numbers correctness.
+ */
+int
+check_date(char *date)
+{
+	int ok = 0;
+	char month[] = "  ";
+	char day[] = "  ";
+	char year[] = "    ";
+	if ( 
+			(strlen(date) == 10) &
+			(isdigit(date[0]) != 0) &
+			(isdigit(date[1]) != 0) &
+			(date[2] == '/') &
+			(isdigit(date[3]) != 0) &
+			(isdigit(date[4]) != 0) &
+			(date[5] == '/') &
+			(isdigit(date[6])!=0) & (isdigit(date[7])!=0) & 
+			(isdigit(date[8])!=0) & (isdigit(date[9])!=0)
+	) {
+		strncpy(month, date, 2);
+		strncpy(day, date + 3, 2);
+		strncpy(year, date + 6, 4);
+		if ( (atoi(month) <= 12) & 
+		     (atoi(month) >= 1)  &
+		     (atoi(day) <= 31) &
+		     (atoi(day) >= 1) &
+		     (atoi(year) <= 9999) &
+		     (atoi(year) > 1))
+		ok = 1;		
+	}
+	return ok;
+}
+
+/* 
+ * Print the date on stdout.
+ */
+void arg_print_date(long date) 
+{
+		char date_str[30];
+		time_t t;
+		struct tm *lt;
+
+		t = date;
+		lt = localtime(&t);
+		sprintf(date_str,"%02u/%02u/%04u",lt->tm_mon+1, 
+		    lt->tm_mday, 1900+lt->tm_year);
+		fputs(date_str,stdout);
+		fputs(":\n",stdout);
+}
+
+/* 
+ * Print Calcurse usage and exit.
+ */
+void usage()
+{
+        char *arg_usage = 
+                _("Usage: calcurse [-h | -v] [-at] [-d date|num] [-c file]\n");
+	
+        fputs(arg_usage, stdout);
+}
+
+void usage_try()
+{
+        char *arg_usage_try =
+                _("Try 'calcurse -h' for more information.\n");
+
+        fputs(arg_usage_try, stdout);
+}
diff --git a/src/args.h b/src/args.h
new file mode 100755
index 0000000..995cc20
--- /dev/null
+++ b/src/args.h
@@ -0,0 +1,41 @@
+/*	$calcurse: args.h,v 1.1 2006/07/31 21:00:03 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
+ *
+ */
+
+#ifndef CALCURSE_ARGS_H
+#define CALCURSE_ARGS_H
+
+void usage();
+void usage_try();
+int parse_args(int argc, char **argv, int colr);
+void version_arg();
+void help_arg();
+void todo_arg(int colr);
+int app_arg(int add_line, int year, int month, int day, long date);
+void date_arg(char *ddate, int add_line);
+int check_date(char *date);
+void arg_print_date(long date);
+
+#endif /* CALCURSE_ARGS_H */
diff --git a/src/calcurse.1 b/src/calcurse.1
new file mode 100755
index 0000000..5ae929c
--- /dev/null
+++ b/src/calcurse.1
@@ -0,0 +1,158 @@
+.\" 	$calcurse: calcurse.1,v 1.1 2006/07/31 21:00:03 culot Exp $
+.\"
+.\" 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.
+.\"
+.TH CALCURSE 1 "May 07, 2006" "Version 1.4" "Calcurse Manual"
+.SH NAME
+Calcurse \- text-based organizer
+.PP
+.SH SYNOPSIS
+.B "calcurse "
+[
+.B "-h "
+|
+.B "-v " 
+] [ 
+.B "-at " 
+] [ 
+.B "-d " 
+\fIdate\fP|\fInum\fP ] [ 
+.B "-c "
+\fIfile\fP ]
+.PP
+.SH DESCRIPTION
+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.  
+.PP
+.SH OPTIONS
+The following options are supported:
+.TP
+.B \-a
+Print the appointments and events for the current day and exit. 
+.br
+\fINote:\fP the calendar from which to read the appointments can be specified using
+the '\-c' flag. 
+.TP
+.B \-c
+Specify the calendar file to use. The default calendar is 
+.B "'~/.calcurse/apts'" 
+(see section \fIFILES\fP below).
+.TP
+.B \-d
+Print the appointments and events for the given date or for 
+the given number of upcoming days, depending on the argument format. 
+Two possible formats are supported:
+.RS 9
+.TP 2
+\(bu  a date of the form 'mm/dd/yyyy'. 
+.TP 2
+\(bu  a number 'n'. 
+.RE
+.RS 7
+.LP
+In the first case, the appointments and events list for the specified 
+date will be returned, while in the second case the appointments and events 
+list for the 'n' upcoming days will be returned. 
+.br
+As an example, typing 'calcurse -d 3' will display your appointments 
+and events for today, tomorrow, and the day after tomorrow.   
+.br
+\fINote:\fP as for the '-a' flag, the calendar from which to read the 
+appointments can be specified using the '\-c' flag. 
+.RE
+.TP
+.B \-h
+Print a short help text describing the supported command-line options,
+and then exit. 
+.TP
+.B \-t
+Print the 'todo' list and exit.
+.TP
+.B \-v
+Display calcurse version and exit.
+.SH NOTES
+Calcurse interface contains three different panels (calendar,
+appointment list, and todo list) on which you can perform different
+actions. All the possible actions, together with their associated
+keystrokes, are listed on the status bar. This status bar
+takes place at the bottom of the screen.
+.PP
+At any time, the built-in help system can be invoked by pressing the '?'
+key. Once viewing the help screens, informations on a specific command
+can be accessed by pressing the keystroke corresponding to that command.
+.PP
+.SH CONFIGURATION
+The calcurse options can be changed from the configuration menu (shown
+when 'C' is hit). Three possible categories are to be chosen from : the
+color scheme, the layout (the location of the three panels on the
+screen), and more general options (such as automatic save before
+quitting). All of these options are detailed in the configuration menu.
+.PP
+.SH FILES
+The following structure is created in your $HOME directory the first
+time calcurse is run :
+.PP
+.HP 10
+$HOME/.calcurse/
+.br
+|___conf 
+.br
+|___apts 
+.br
+|___todo
+.PP
+The \fIconf\fP file contains the user configuration. The \fIapts\fP 
+file contains all of the user's appointments, and the \fItodo\fP 
+file contains the todo list.
+.PP
+.SH LICENCE
+Copyright (c) 2004-2006 by Frederic Culot. 
+.br
+This software is released under the GNU General Public License. Please
+read the COPYING file for more information. 
+.PP
+.SH BUGS
+Incorrect highlighting of items appear when using calcurse black and
+white theme together with a \fB$TERM\fP variable set to
+\fIxterm-color\fP. 
+To fix this bug, and as advised by Thomas E. Dickey (xterm maintainer),
+\fIxterm-xfree86\fP should be used instead of \fIxterm-color\fP to set 
+the \fB$TERM\fP variable:
+    "The xterm-color value for $TERM is a bad choice for XFree86 
+     xterm because it is commonly used for a terminfo entry which 
+     happens to not support bce. Use the xterm-xfree86 entry 
+     which is distributed with XFree86 xterm (or the similar one 
+     distributed with ncurses)."
+.PP
+If you find other bugs, please send a report to calcurse@culot.org or to the
+author, below.
+.PP
+.SH AUTHOR
+\fBFrederic Culot\fP <frederic@culot.org>.
+.PP
+.SH SEE ALSO
+ncurses(3), gettext(3)
+.br
+Calcurse home page : http://culot.org/calcurse/
+.br
+Calcurse manual found in the doc/ directory of the source package, or
+at:
+http://culot.org/calcurse/manual.html
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;
+	}
+}
diff --git a/src/calendar.c b/src/calendar.c
new file mode 100755
index 0000000..c147e47
--- /dev/null
+++ b/src/calendar.c
@@ -0,0 +1,227 @@
+/*	$calcurse: calendar.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
+ *
+ */
+
+#include <ncurses.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <time.h>
+
+#include "i18n.h"
+#include "day.h"
+#include "apoint.h"
+#include "event.h"
+#include "calendar.h"
+#include "custom.h"
+#include "vars.h"
+#include "utils.h"
+
+static unsigned months_to_days(unsigned);
+static long years_to_days(unsigned);
+
+  /* Load the calendar */
+void
+update_cal_panel(WINDOW *cwin, int nl_cal,
+		 int nc_cal, int sel_month, int sel_year, int sel_day,
+		 int day, int month, int year,
+                 bool monday_first)
+{
+	int c_day, c_day_1, day_1_sav, numdays, j;
+	unsigned yr, mo;
+	int ofs_x, ofs_y;
+	int item_this_day = 0;
+	int title_lines = 3;
+        int sunday_first = 0;
+
+	// Inits
+	erase_window_part(cwin, 1, title_lines, nc_cal - 2, nl_cal - 2);
+	mo = sel_month;
+	yr = sel_year;
+        if (!monday_first) sunday_first = 1;
+	
+	// Offset for centering calendar in window
+	ofs_y = 2 + (nl_cal - 9) / 2;
+	ofs_x = (nc_cal - 27) / 2;
+
+
+	//checking the number of days in february
+	numdays = days[mo - 1];
+	if (2 == mo && isBissextile(yr))
+		++numdays;
+
+	//the first calendar day will be monday or sunday, depending on the
+        //value of week_begins_on_monday
+	c_day_1 = (int) ((ymd_to_scalar(yr, mo, 1 + sunday_first) 
+                          - (long) 1) % 7L);
+
+	//Write the current month and year on top of the calendar
+	custom_apply_attr(cwin, ATTR_HIGH);
+	mvwprintw(cwin, ofs_y,
+		 (nc_cal - (strlen(_(monthnames[mo - 1])) + 5)) / 2,
+		 "%s %d", _(monthnames[mo - 1]), sel_year);
+	custom_remove_attr(cwin, ATTR_HIGH);
+	++ofs_y;
+
+	//prints the days, with regards to the first day of the week
+	custom_apply_attr(cwin, ATTR_HIGH);
+	for (j = 0; j < 7; j++) {
+		mvwprintw(cwin, ofs_y, ofs_x + 4 * j, "%s", 
+                          _(daynames[1 + j - sunday_first]));
+	}
+	custom_remove_attr(cwin, ATTR_HIGH);
+
+	day_1_sav = (c_day_1 + 1) * 3 + c_day_1 - 7;
+
+	for (c_day = 1; c_day <= numdays; ++c_day, ++c_day_1, c_day_1 %= 7) {
+		//check if the day contains an event or an appointment
+		item_this_day = day_check_if_item(sel_year, sel_month, c_day);
+
+		/* Go to next line, the week is over. */
+		if (!c_day_1 && 1 != c_day) {	
+			++ofs_y;
+			ofs_x = 2 - day_1_sav - 4 * c_day - 1;
+		}
+		/* This is today, so print it in yellow. */
+		if (c_day == day && month == sel_month 
+				&& year == sel_year && day != sel_day)
+		{
+			custom_apply_attr(cwin, ATTR_LOWEST);
+			mvwprintw(cwin, ofs_y + 1,
+				 ofs_x + day_1_sav + 4 * c_day + 1, "%2d",
+				 c_day);
+			custom_remove_attr(cwin, ATTR_LOWEST);
+		} else if (c_day == sel_day && ( (day != sel_day) | 
+				(month != sel_month) | (year != sel_year) ))	
+			/* This is the selected day, print it in red. */
+		{
+			custom_apply_attr(cwin, ATTR_MIDDLE);
+			mvwprintw(cwin, ofs_y + 1,
+				 ofs_x + day_1_sav + 4 * c_day + 1, "%2d",
+				 c_day);
+			custom_remove_attr(cwin, ATTR_MIDDLE);
+		} else if (c_day == sel_day && day == sel_day && month == sel_month && year == sel_year)	//today is the selected day
+		{
+			custom_apply_attr(cwin, ATTR_MIDDLE);
+			mvwprintw(cwin, ofs_y + 1,
+				 ofs_x + day_1_sav + 4 * c_day + 1, "%2d",
+				 c_day);
+			custom_remove_attr(cwin, ATTR_MIDDLE);
+		} else if (item_this_day) {
+			custom_apply_attr(cwin, ATTR_LOW);
+			mvwprintw(cwin, ofs_y + 1,
+				 ofs_x + day_1_sav + 4 * c_day + 1, "%2d",
+				 c_day);
+			custom_remove_attr(cwin, ATTR_LOW);
+		}
+
+		else		// otherwise, print normal days in black
+			mvwprintw(cwin, ofs_y + 1,
+				 ofs_x + day_1_sav + 4 * c_day + 1, "%2d",
+				 c_day);
+
+	}
+	wnoutrefresh(cwin);
+}
+
+int isBissextile(unsigned annee)
+{
+	return annee % 400 == 0 || (annee % 4 == 0 && annee % 100 != 0);
+}
+
+// convertion functions
+unsigned months_to_days(unsigned mois)
+{
+	return (mois * 3057 - 3007) / 100;
+}
+
+
+long years_to_days(unsigned annee)
+{
+	return annee * 365L + annee / 4 - annee / 100 + annee / 400;
+}
+
+long ymd_to_scalar(unsigned annee, unsigned mois, unsigned jour)
+{
+	long scalaire;
+	scalaire = jour + months_to_days(mois);
+	if (mois > 2)
+		scalaire -= isBissextile(annee) ? 1 : 2;
+	annee--;
+	scalaire += years_to_days(annee);
+	return scalaire;
+}
+
+/* 
+ * Ask for a date to jump to, then check the correctness of that date
+ * and jump to it.
+ * If the entered date is empty, automatically jump to the current date.
+ * day, month, year are the current day given to that routine, and
+ * sel_day, sel_month and sel_year represent the day given back.
+ */
+void
+goto_day(int colr, int day, int month, int year,
+	 int *sel_day, int *sel_month, int *sel_year)
+{
+	char selected_day[50] = "";
+	int dday, dmonth, dyear;
+	int wrong_day = 0;
+	char *mesg_line1 = _("The day you entered is not valid");
+	char *mesg_line2 = _("Press [ENTER] to continue");
+	char *request_date = _("Enter the day to go to [ENTER for today] : dd/mm/yyyy");
+
+	while (wrong_day != 1) {
+		status_mesg(request_date, "");
+		getstring(swin, colr, selected_day, 0, 1);
+		if (strlen(selected_day) == 0)	// go to today
+		{
+			*sel_day = day;
+			*sel_month = month;
+			*sel_year = year;
+			break;
+		} else {
+			sscanf(selected_day, "%u/%u/%u", &dday, &dmonth,
+			       &dyear);
+			//check if the entered day is correct
+			if ((dday <= 0) | (dday >= 32))
+				wrong_day = 1;
+			if ((dmonth <= 0) | (dmonth >= 13))
+				wrong_day = 1;
+			if ((dyear <= 0) | (dyear >= 3000))
+				wrong_day = 1;
+			//go to chosen day
+			if (wrong_day != 1) {
+				*sel_day = dday;
+				*sel_month = dmonth;
+				*sel_year = dyear;
+			} else {
+				status_mesg(mesg_line1, mesg_line2);
+				wgetch(swin);
+			}
+			break;
+		}
+	}
+	return;
+}
diff --git a/src/calendar.h b/src/calendar.h
new file mode 100755
index 0000000..a8cb3ea
--- /dev/null
+++ b/src/calendar.h
@@ -0,0 +1,41 @@
+/*	$calcurse: calendar.h,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
+ *
+ */
+
+#ifndef CALCURSE_CALENDAR_H
+#define CALCURSE_CALENDAR_H
+
+#include <stdbool.h>
+
+void update_cal_panel(WINDOW *cwin, int nl_cal,
+		      int nc_cal, int sel_month, int sel_year, int sel_day,
+		      int day, int month, int year,
+                      bool monday_first);
+int isBissextile(unsigned);
+long ymd_to_scalar(unsigned, unsigned, unsigned);
+void goto_day(int colr, int day, int month, int year,
+	      int *sel_day, int *sel_month, int *sel_year);
+
+#endif /* CALCURSE_CALENDAR_H */
diff --git a/src/custom.c b/src/custom.c
new file mode 100755
index 0000000..4a2ea72
--- /dev/null
+++ b/src/custom.c
@@ -0,0 +1,178 @@
+/*	$calcurse: custom.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
+ *
+ */
+
+#include <ncurses.h>
+
+#include "i18n.h"
+#include "utils.h"
+#include "custom.h"
+#include "vars.h"
+
+static struct attribute_s attr;
+
+/* 
+ * Define window attributes (for both color and non-color terminals):
+ * ATTR_HIGHEST are for window titles
+ * ATTR_HIGH are for month and days names
+ * ATTR_MIDDLE are for the selected day inside calendar panel
+ * ATTR_LOW are for days inside calendar panel which contains an event
+ * ATTR_LOWEST are for current day inside calendar panel
+ */
+void custom_init_attr(int colr)
+{
+	attr.color[ATTR_HIGHEST]   = COLOR_PAIR(colr);
+	attr.color[ATTR_HIGH]      = COLOR_PAIR(6);
+	attr.color[ATTR_MIDDLE]    = COLOR_PAIR(1);
+	attr.color[ATTR_LOW]       = COLOR_PAIR(4);
+	attr.color[ATTR_LOWEST]    = COLOR_PAIR(5);
+	attr.color[ATTR_TRUE]      = COLOR_PAIR(2);
+	attr.color[ATTR_FALSE]     = COLOR_PAIR(1);
+
+	attr.nocolor[ATTR_HIGHEST] = A_BOLD;
+	attr.nocolor[ATTR_HIGH]    = A_REVERSE;
+	attr.nocolor[ATTR_MIDDLE]  = A_REVERSE;
+	attr.nocolor[ATTR_LOW]     = A_UNDERLINE;
+	attr.nocolor[ATTR_LOWEST]  = A_BOLD;
+	attr.nocolor[ATTR_TRUE]    = A_BOLD;
+	attr.nocolor[ATTR_FALSE]   = A_DIM;
+}
+
+/* Apply window attribute */
+void custom_apply_attr(WINDOW *win, int attr_num)
+{
+	if (colorize)
+		wattron(win, attr.color[attr_num]);
+	else
+		wattron(win, attr.nocolor[attr_num]);
+}
+
+/* Remove window attribute */
+void custom_remove_attr(WINDOW *win, int attr_num)
+{
+	if (colorize)
+		wattroff(win, attr.color[attr_num]);
+	else
+		wattroff(win, attr.nocolor[attr_num]);
+}
+
+/* Draws the configuration bar */
+void config_bar()
+{
+	int smlspc, spc;
+
+	smlspc = 2;
+	spc = 15;
+
+	custom_apply_attr(swin, ATTR_HIGHEST);
+	mvwprintw(swin, 0, 2, "Q");
+	mvwprintw(swin, 1, 2, "G");
+	mvwprintw(swin, 0, 2 + spc, "L");
+	mvwprintw(swin, 1, 2 + spc, "C");
+	custom_remove_attr(swin, ATTR_HIGHEST);
+
+	mvwprintw(swin, 0, 2 + smlspc, _("Exit"));
+	mvwprintw(swin, 1, 2 + smlspc, _("General"));
+	mvwprintw(swin, 0, 2 + spc + smlspc, _("Layout"));
+	mvwprintw(swin, 1, 2 + spc + smlspc, _("Color"));
+	
+	wnoutrefresh(swin);
+        wmove(swin, 0, 0);
+	doupdate();
+}
+
+/* Choose the layout */
+int layout_config(int layout, int colr)
+{
+	int ch, old_layout;
+	char *layout_mesg = _("Pick the desired layout on next screen [press ENTER]");
+	char *choice_mesg = _("('A'= Appointment panel, 'c'= calendar panel, 't'= todo panel)");
+	char *layout_up_mesg   = _("   |Ac|      |At|      |cA|      |tA|");
+	char *layout_down_mesg = _("[1]|At|   [2]|Ac|   [3]|tA|   [4]|cA|");
+
+	old_layout = layout;
+	status_mesg(layout_mesg, choice_mesg);
+	wgetch(swin);
+	status_mesg(layout_up_mesg, layout_down_mesg);
+	wnoutrefresh(swin);
+	doupdate();
+	while ((ch = wgetch(swin)) != 'q') {
+		switch (ch) {
+		case '1':
+			layout = 1;
+			return layout;
+		case '2':
+			layout = 2;
+			return layout;
+		case '3':
+			layout = 3;
+			return layout;
+		case '4':
+			layout = 4;
+			return layout;
+		}
+	}
+	layout = old_layout;
+	return layout;
+}
+
+/* Choose the color theme */
+int color_config(int colr)
+{
+        int ascii2dec = 48;
+	int i, ch, old_colr;
+        int max_colors = 9;
+        int spc = 6;
+        char *choose_color = _("Pick the number corresponding to the color scheme "
+                "(Q to exit) :");
+
+	old_colr = colr;
+	erase_window_part(swin, 0, 0, col, 2);
+	for (i = 1; i < max_colors; i++) {
+		wattron(swin, COLOR_PAIR(i));
+		mvwprintw(swin, 1, (i - 1) * spc, "[>%d<]", i);
+		wattroff(swin, COLOR_PAIR(i));
+	}
+        mvwprintw(swin, 1, 50, _("([>0<] for black & white)"));
+	custom_apply_attr(swin, ATTR_HIGHEST);
+	mvwprintw(swin, 0, 0, choose_color);
+	custom_remove_attr(swin, ATTR_HIGHEST);
+	wnoutrefresh(swin);
+	doupdate();
+	while ((ch = wgetch(swin)) != 'q') {
+                ch = ch - ascii2dec;
+                if ( (ch > 0) && (ch <= max_colors) ) {
+                        colorize = true;
+                        return ch;
+                } else if (ch == 0) {
+                        colorize = false;
+                        return 0;
+                } else {
+                        colr = old_colr;
+                }
+        }
+        if (colr == 0) colorize = false;
+        return colr;
+}
diff --git a/src/custom.h b/src/custom.h
new file mode 100755
index 0000000..a7f133b
--- /dev/null
+++ b/src/custom.h
@@ -0,0 +1,42 @@
+/*	$calcurse: custom.h,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
+ *
+ */
+
+#ifndef CALCURSE_CUSTOM_H
+#define CALCURSE_CUSTOM_H
+
+struct attribute_s {
+	int color[7];
+	int nocolor[7];
+};
+
+void custom_init_attr(int colr);
+void custom_apply_attr(WINDOW *win, int attr_num);
+void custom_remove_attr(WINDOW *win, int attr_num);
+void config_bar();
+int layout_config(int layout, int colr);
+int color_config(int colr);
+
+#endif /* CALCURSE_CUSTOM_H */
diff --git a/src/day.c b/src/day.c
new file mode 100755
index 0000000..8fd7981
--- /dev/null
+++ b/src/day.c
@@ -0,0 +1,362 @@
+/*	$calcurse: day.c,v 1.1 2006/07/31 21:00:03 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
+ *
+ */
+
+#include <ncurses.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <stdbool.h>
+#include <time.h>
+
+#include "i18n.h"
+#include "utils.h"
+#include "apoint.h"
+#include "event.h"
+#include "recur.h"
+#include "day.h"
+#include "vars.h"
+
+static struct day_item_s *day_items_ptr;
+static struct day_saved_item_s *day_saved_item = NULL;
+
+/* 
+ * Store all of the items to be displayed for the selected day.
+ * Items are of four types: recursive events, normal events, 
+ * recursive appointments and normal appointments.
+ * The items are stored in the linked list pointed by *day_items_ptr
+ * and the length of the new pad to write is returned.
+ * The number of events and appointments in the current day are also updated.
+ */
+int day_store_items(long date, int *pnb_events, int *pnb_apoints)
+{
+	int pad_length;
+	int nb_events, nb_recur_events;
+	int nb_apoints, nb_recur_apoints;
+
+	pad_length = nb_events = nb_apoints = 0;
+	nb_recur_events = nb_recur_apoints = 0;
+
+	if (day_items_ptr != 0)
+		day_free_list();
+	nb_recur_events = day_store_recur_events(date);
+	nb_events = day_store_events(date);
+	*pnb_events = nb_events;
+	nb_recur_apoints = day_store_recur_apoints(date);
+	nb_apoints = day_store_apoints(date);
+	*pnb_apoints = nb_apoints;
+	pad_length = nb_recur_events + nb_events + 1 + 
+		3*(nb_recur_apoints + nb_apoints);
+	*pnb_apoints += nb_recur_apoints;
+	*pnb_events += nb_recur_events;
+
+	return pad_length;
+}
+
+/* Free the current day linked list containing the events and appointments. */
+void day_free_list(void)
+{
+	struct day_item_s *p, *q;
+
+	for (p = day_items_ptr; p != 0; p = q) {
+		q = p->next;
+		free(p->mesg);
+		free(p);
+	}
+	day_items_ptr = NULL;
+}
+
+/* 
+ * Store the recurrent events for the selected day in structure pointed
+ * by day_items_ptr. This is done by copying the recurrent events 
+ * from the general structure pointed by recur_elist to the structure
+ * dedicated to the selected day. 
+ * Returns the number of recurrent events for the selected day.
+ */
+int day_store_recur_events(long date)
+{
+	struct recur_event_s *j;
+	struct day_item_s *ptr;
+	int e_nb = 0;
+
+	for (j = recur_elist; j != 0; j = j->next) {
+		if (recur_item_inday(j->day, j->rpt->type, j->rpt->freq,
+			j->rpt->until, date)) {
+			e_nb++;
+			ptr = day_add_event(RECUR_EVNT, j->mesg, j->day, j->id);
+		}	
+	}
+
+	return e_nb;
+}
+
+/* 
+ * Store the events for the selected day in structure pointed
+ * by day_items_ptr. This is done by copying the events 
+ * from the general structure pointed by eventlist to the structure
+ * dedicated to the selected day. 
+ * Returns the number of events for the selected day.
+ */
+int day_store_events(long date)
+{
+	struct event_s *j;
+	struct day_item_s *ptr;
+	int e_nb = 0;
+
+	for (j = eventlist; j != 0; j = j->next) {
+		if (event_inday(j, date)) {
+			e_nb++;
+			ptr = day_add_event(EVNT, j->mesg, j->day, j->id);
+		}	
+	}
+
+	return e_nb;
+}
+
+/* 
+ * Store the recurrent apoints for the selected day in structure pointed
+ * by day_items_ptr. This is done by copying the appointments
+ * from the general structure pointed by recur_alist to the structure
+ * dedicated to the selected day. 
+ * Returns the number of recurrent appointments for the selected day.
+ */
+int day_store_recur_apoints(long date)
+{
+	struct recur_apoint_s *j;
+	struct day_item_s *ptr;
+	int a_nb = 0;
+
+	for (j = recur_alist; j != 0; j = j->next) {
+		if (recur_item_inday(j->start, j->rpt->type, j->rpt->freq,
+			j->rpt->until, date)) {
+			a_nb++;
+			ptr = day_add_apoint(RECUR_APPT, j->mesg, j->start, j->dur);
+		}	
+	}
+
+	return a_nb;
+}
+
+/* 
+ * Store the apoints for the selected day in structure pointed
+ * by day_items_ptr. This is done by copying the appointments
+ * from the general structure pointed by apointlist to the structure
+ * dedicated to the selected day. 
+ * Returns the number of appointments for the selected day.
+ */
+int day_store_apoints(long date)
+{
+	struct apoint_s *j;
+	struct day_item_s *ptr;
+	int a_nb = 0;
+
+	for (j = apointlist; j != 0; j = j->next) {
+		if (apoint_inday(j, date)) {
+			a_nb++;
+			ptr = day_add_apoint(APPT, j->mesg, j->start, j->dur);
+		}	
+	}
+
+	return a_nb;
+}
+
+/* Add an event in the current day list */
+struct day_item_s *day_add_event(int type, char *mesg, long day, int id)
+{
+	struct day_item_s *o, **i;
+	o = (struct day_item_s *) malloc(sizeof(struct day_item_s));
+	o->mesg = (char *) malloc(strlen(mesg) + 1);
+	strcpy(o->mesg, mesg);
+	o->type = type;
+	o->appt_dur = 0;
+	o->start = day;
+	o->evnt_id = id;
+	i = &day_items_ptr;
+	for (;;) {
+		if (*i == 0 || (*i)->start > day) {
+			o->next = *i;
+			*i = o;
+			break;
+		}
+		i = &(*i)->next;
+	}
+	return o;
+}
+
+/* Add an appointment in the current day list. */
+struct day_item_s *day_add_apoint(int type, char *mesg, long start, long dur)
+{
+	struct day_item_s *o, **i;
+	o = (struct day_item_s *) malloc(sizeof(struct day_item_s));
+	o->mesg = (char *) malloc(strlen(mesg) + 1);
+	strcpy(o->mesg, mesg);
+	o->start = start;
+	o->appt_dur = dur;
+	o->type = type;
+	o->evnt_id = 0;
+	i = &day_items_ptr;
+	for (;;) {
+		if (*i == 0 || (*i)->start > start) {
+			o->next = *i;
+			*i = o;
+			break;
+		}
+		i = &(*i)->next;
+	}
+	return o;
+}
+
+/* 
+ * Write the appointments and events for the selected day in a pad.
+ * An horizontal line is drawn between events and appointments, and the
+ * item selected by user is highlighted. This item is also saved inside
+ * structure (pointed by day_saved_item), to be later displayed in a
+ * popup window if requested.
+ */
+void day_write_pad(long date, int width, int length, int incolor, int colr)
+{
+	struct day_item_s *p;
+	int line, item_number, max_pos;
+	const int x_pos = 0;
+	bool draw_line = true;
+
+	line = item_number = 0;
+	max_pos = length;
+
+	/* Initialize the structure used to store highlited item. */
+	if (day_saved_item == NULL) {
+		day_saved_item = (struct day_saved_item_s *) 
+			malloc(sizeof(struct day_saved_item_s));	
+		day_saved_item->mesg = (char *) malloc(1);
+	} 
+
+	for (p = day_items_ptr; p != 0; p = p->next) {
+
+		/* First print the events for current day. */
+		if (p->type < RECUR_APPT) {
+			item_number++;		
+			if (item_number - incolor == 0) {
+				day_saved_item->type = p->type;
+				day_saved_item->mesg = (char *)
+					realloc(day_saved_item->mesg,
+						strlen(p->mesg) + 1);
+				day_saved_item->mesg = p->mesg;
+			}
+			display_item(apad->ptrwin, item_number - incolor, p->mesg, 
+			width - 4, line, x_pos);
+			line++;
+		} else {
+			/* Draw a line between events and appointments. */
+			if (line > 0 && draw_line){
+				wmove(apad->ptrwin, line, x_pos);
+				whline(apad->ptrwin, 0, width);
+				draw_line = false;
+			}
+
+			/* Last print the appointments for current day. */
+			item_number++;
+			if (item_number - incolor == 0) {
+				day_saved_item->type = p->type;
+				day_saved_item->mesg = (char *)
+					realloc(day_saved_item->mesg,
+						strlen(p->mesg) + 1);
+				day_saved_item->mesg = p->mesg;
+				apoint_sec2str(day_item_s2apoint_s(p), 
+					p->type, date,
+					day_saved_item->start,
+					day_saved_item->end);
+			}
+			display_item_date(apad->ptrwin, item_number - incolor, 
+				day_item_s2apoint_s(p), p->type, date, 
+				line + 1, x_pos);	
+			display_item(apad->ptrwin, item_number - incolor, p->mesg,
+			width - 6, line + 2, x_pos + 2);
+			line = line + 3;
+		}
+	}
+}
+
+/* Returns a structure of type apoint_s given a structure of type day_item_s */
+struct apoint_s *day_item_s2apoint_s(struct day_item_s *p)
+{
+	struct apoint_s *a;
+
+	a = (struct apoint_s *) malloc(sizeof(struct apoint_s));
+	a->mesg = (char *) malloc(strlen(p->mesg) + 1);
+	a->start = p->start;
+	a->dur = p->appt_dur;
+	a->mesg = p->mesg;
+	return a;
+}
+
+/* Display an item inside a popup window. */
+void day_popup_item(void)
+{
+	char *error = 
+		_("FATAL ERROR in day_popup_item: unknown item type\n");
+
+	if (day_saved_item->type == EVNT || day_saved_item->type == RECUR_EVNT)
+		item_in_popup(NULL, NULL, day_saved_item->mesg, _("Event :"));
+	else if (day_saved_item->type == APPT || 
+		day_saved_item->type == RECUR_APPT)
+		item_in_popup(day_saved_item->start, day_saved_item->end,
+			day_saved_item->mesg, _("Appointment :"));
+	else { /* NOT REACHED */
+		fputs(error, stderr);
+		exit(EXIT_FAILURE);
+	}
+}
+
+/* 
+ * Need to know if there is an item for the current selected day inside
+ * calendar. This is used to put the correct colors inside calendar panel.
+ */
+ int day_check_if_item(int year, int month, int day) {
+	struct recur_event_s  *re;
+	struct recur_apoint_s *ra;
+	struct event_s *e;
+	struct apoint_s *a;
+	const long date = date2sec(year, month, day, 0, 0);
+
+	for (re = recur_elist; re != 0; re = re->next)
+		if (recur_item_inday(re->day, re->rpt->type, re->rpt->freq,
+			re->rpt->until, date))
+			return 1;
+	
+	for (ra = recur_alist; ra != 0; ra = ra->next)
+		if (recur_item_inday(ra->start, ra->rpt->type, ra->rpt->freq,
+			ra->rpt->until, date))
+			return 1;
+
+	for (e = eventlist; e != 0; e = e->next)
+		if (event_inday(e, date))
+			return 1;
+
+	for (a = apointlist; a != 0; a = a->next)
+		if (apoint_inday(a, date)) 
+			return 1;
+
+	return 0;
+}
diff --git a/src/day.h b/src/day.h
new file mode 100755
index 0000000..8426704
--- /dev/null
+++ b/src/day.h
@@ -0,0 +1,66 @@
+/*	$calcurse: day.h,v 1.1 2006/07/31 21:00:03 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
+ *
+ */
+
+#ifndef CALCURSE_DAY_H
+#define CALCURSE_DAY_H
+
+#include "apoint.h"
+
+#define RECUR_EVNT	1
+#define EVNT		2
+#define RECUR_APPT	3
+#define APPT		4
+
+struct day_item_s {
+	struct day_item_s *next;
+	int type;		/* (recursive or normal) event or appointment */
+	long start;		/* seconds since 1 jan 1970 */
+	char *mesg;		/* item description */
+	int evnt_id;		/* event identifier */
+	long appt_dur;		/* appointment duration in seconds */
+};
+
+struct day_saved_item_s {
+	int type ;
+	char *mesg;
+	char start[100];
+	char end[100];
+};
+
+int day_store_items(long date, int *pnb_events, int *pnb_apoints);
+void day_free_list(void);
+int day_store_recur_events(long date);
+int day_store_events(long date);
+int day_store_recur_apoints(long date);
+int day_store_apoints(long date);
+struct day_item_s *day_add_event(int type, char *mesg, long day, int id);
+struct day_item_s *day_add_apoint(int type, char *mesg, long start, long dur);
+void day_write_pad(long date, int width, int length, int incolor, int colr);
+struct apoint_s *day_item_s2apoint_s(struct day_item_s *p);
+void day_popup_item(void);
+int day_check_if_item(int year, int month, int day);
+
+#endif /* CALCURSE_DAY_H */
diff --git a/src/event.c b/src/event.c
new file mode 100755
index 0000000..4cf3953
--- /dev/null
+++ b/src/event.c
@@ -0,0 +1,135 @@
+/*	$calcurse: event.c,v 1.1 2006/07/31 21:00:03 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
+ *
+ */
+
+#include <ncurses.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <time.h>
+
+#include "i18n.h"
+#include "event.h"
+#include "utils.h"
+
+struct event_s *eventlist;
+
+/* Create a new event */
+struct event_s *event_new(char *mesg, long day, int id)
+{
+	struct event_s *o, **i;
+	o = (struct event_s *) malloc(sizeof(struct event_s));
+	o->mesg = (char *) malloc(strlen(mesg) + 1);
+	strcpy(o->mesg, mesg);
+	o->day = day;
+	o->id = id;
+	i = &eventlist;
+	for (;;) {
+		if (*i == 0 || (*i)->day > day) {
+			o->next = *i;
+			*i = o;
+			break;
+		}
+		i = &(*i)->next;
+	}
+	return o;
+}
+
+/* Check if the event belongs to the selected day */
+unsigned event_inday(struct event_s *i, long start)
+{
+	if (i->day <= start + 3600 * 24 && i->day > start) {
+		return 1;
+	}
+	return 0;
+}
+
+/* Write to file the event in user-friendly format */
+void event_write(struct event_s *o, FILE * f)
+{
+	struct tm *lt;
+	time_t t;
+
+	t = o->day;
+	lt = localtime(&t);
+	fprintf(f, "%02u/%02u/%04u [%d] %s\n",
+		lt->tm_mon + 1, lt->tm_mday, 1900 + lt->tm_year, o->id, o->mesg);
+}
+
+/* Load the events from file */
+struct event_s *event_scan(FILE * f, struct tm start, int id)
+{
+	struct tm *lt;
+	char buf[MESG_MAXSIZE], *nl;
+	time_t tstart, t;
+
+	t = time(NULL);
+	lt = localtime(&t);
+
+        /* Read the event description */
+	fgets(buf, MESG_MAXSIZE, f);
+	nl = strchr(buf, '\n');
+	if (nl) {
+		*nl = '\0';
+	}
+        start.tm_hour = 12;
+        start.tm_min = 0;
+	start.tm_sec =  0;
+	start.tm_isdst = -1;
+	start.tm_year -= 1900;
+	start.tm_mon--;
+
+	tstart = mktime(&start);
+	if (tstart == -1) {
+		fputs(_("FATAL ERROR in event_scan: date error in the event\n"), stderr);
+		exit(EXIT_FAILURE);
+	}
+	return event_new(buf, tstart, id);
+}
+
+/* Delete an event from the list */
+void event_delete_bynum(long start, unsigned num)
+{
+	unsigned n;
+	struct event_s *i, **iptr;
+
+	n = 0;
+	iptr = &eventlist;
+	for (i = eventlist; i != 0; i = i->next) {
+		if (event_inday(i, start)) {
+			if (n == num) {
+				*iptr = i->next;
+				free(i->mesg);
+				free(i);
+				return;
+			}
+			n++;
+		}
+		iptr = &i->next;
+	}
+	/* NOTREACHED */
+	fputs(_("FATAL ERROR in event_delete_bynum: no such event\n"), stderr);
+	exit(EXIT_FAILURE);
+}
diff --git a/src/event.h b/src/event.h
new file mode 100755
index 0000000..6e06691
--- /dev/null
+++ b/src/event.h
@@ -0,0 +1,48 @@
+/*	$calcurse: event.h,v 1.1 2006/07/31 21:00:03 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
+ *
+ */
+
+#ifndef CALCURSE_EVENT_H
+#define CALCURSE_EVENT_H
+
+#define HRMIN_SIZE 6
+#define MESG_MAXSIZE 256
+
+struct event_s {
+	struct event_s *next;
+	int id;	        /* event identifier */
+        long day;	/* seconds since 1 jan 1970 */
+	char *mesg;
+};
+
+extern struct event_s *eventlist;
+
+struct event_s *event_new(char *, long, int);
+unsigned event_inday(struct event_s *o, long start);
+void event_write(struct event_s *o, FILE * f);
+struct event_s *event_scan(FILE * f, struct tm start, int id);
+void event_delete_bynum(long start, unsigned num);
+
+#endif /* CALCURSE_EVENT_H */
diff --git a/src/help.c b/src/help.c
new file mode 100755
index 0000000..f586e74
--- /dev/null
+++ b/src/help.c
@@ -0,0 +1,375 @@
+/*	$calcurse: help.c,v 1.1 2006/07/31 21:00:03 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
+ *
+ */
+
+#include <ncurses.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <sys/types.h>
+
+#include "i18n.h"
+#include "help.h"
+#include "custom.h"
+#include "vars.h"
+#include "utils.h"
+
+/* 
+ * Write the desired help text inside the help pad, and return the number
+ * of lines that were written. 
+ * */
+int write_help_pad(WINDOW *win, char *title, char *text, int pad_width)
+{
+	int nl_title = 0;
+	int nl_text = 0;
+	
+	nl_text = get_help_lines(text);
+	nl_title = get_help_lines(title);
+	erase_window_part(win, 0, 0, MAX_LENGTH, pad_width);
+	custom_apply_attr(win, ATTR_HIGHEST);
+	mvwprintw(win, 0, 0, "%s", title);
+	custom_remove_attr(win, ATTR_HIGHEST);
+	mvwprintw(win, nl_title, 0, "%s", text);
+	return nl_text + nl_title;
+}
+
+int get_help_lines(char *text)
+{
+	int i;
+	int nl = 0;
+
+	for (i = 0; text[i]; i++) {
+		if (text[i] == '\n') nl++;
+	}
+	return nl + 1;
+}
+
+/* Draws the help screen */
+void help_screen(int which_pan, int colr)
+{
+	WINDOW *help_win = NULL;
+	WINDOW *help_pad = NULL;
+	char label[80];
+	int ch = '?';
+	int help_row = row - 2;	//size of the help window
+	int help_col = col;
+        int title_lines = 3;
+	int pad_offset = 4;
+	int text_lines = help_row - (pad_offset + 1);
+	int pad_width = help_col - 2*pad_offset + 1; 
+	int first_line = 0, nl = 0;
+	
+	help_page_t help_main;
+	help_page_t help_redraw;
+	help_page_t help_save;
+	help_page_t help_displacement;
+	help_page_t help_view;
+	help_page_t help_tab;
+	help_page_t help_goto;
+	help_page_t help_delete;
+	help_page_t help_add;
+	help_page_t help_config;
+	help_page_t help_credits;
+
+	help_main.title = 
+     _("       Welcome to Calcurse. This is the main help screen.\n");
+	help_main.text  =
+    _(" Moving around:  Press CTRL-P or CTRL-N to scroll text upward or\n"
+    "                 downward inside help screens, if necessary.\n\n"
+    "     Exit help:  When finished, press 'Q' to exit help and go back\n"
+    "                 to the main Calcurse screen.\n\n"
+    "    Help topic:  At the bottom of this screen you can see a panel\n"
+    "                 with different fields, represented by a letter and\n"
+    "                 a short title. This panel contains all the available\n"
+    "                 actions you can perform when using Calcurse.\n"
+    "                 By pressing one of the letters appearing in this\n"
+    "                 panel, you will be shown a short description of the\n"
+    "                 corresponding action.\n\n"
+    "       Credits:  Press '@' for credits.");
+
+	help_redraw.title = _("Redraw:\n");
+	help_redraw.text  =
+    _("Pressing 'R' redraws the Calcurse panels.\n\n"
+    "You might want to use this function when you resize your terminal\n"
+    "screen for example, and you want Calcurse to take into account the new\n"
+    "size of the terminal.\n\n"
+    "This function can also be useful when garbage appears in the display,\n"
+    "and you want to clean it.");
+
+	help_save.title = _("Save:\n");
+    	help_save.text  =
+    _("Pressing 'S' saves the Calcurse data.\n\n"
+    "The data is splitted into three different files which contains :"
+    "\n\n"
+    "        /  ~/.calcurse/conf -> the user configuration\n"
+    "        |                      (layout, color, general options)\n"
+    "        |  ~/.calcurse/apts -> the data related to the appointments\n"
+    "        \\  ~/.calcurse/todo -> the data related to the todo list\n"
+    "\nIn the config menu, you can choose to save the Calcurse data\n"
+    "automatically before quitting.");
+
+	help_displacement.title = _("Displacement keys:\n");
+    	help_displacement.text  =
+    _("You can use either 'H','J','K','L' or the arrow keys '<','v','^','>'\n"
+    "to move into the calendar.\n\n"
+    "The following scheme explains how :\n\n"
+    "                      move to previous week\n"
+    "                              K ^  \n"
+    "  move to previous day   H <       > L   move to next day\n"
+    "                              J v  \n"
+    "                       move to next week\n"
+    "\nWhen the Appointment or ToDo panel is selected, the up and down keys\n"
+    "(respectively K or up arrow, and J or down arrow) allows you to select\n"
+    "an item from those lists.");
+
+	help_view.title = _("View:\n");
+    	help_view.text  =
+    _("Pressing 'V' allows you to view the item you select in either the ToDo\n"
+    "or Appointment panel.\n"
+    "\nThis is usefull when an event description is longer than the available\n"
+    "space to display it. If that is the case, the description will be\n"
+    "shortened and its end replaced by '...'. To be able to read the entire\n"
+    "description, just press 'V' and a popup window will appear, containing\n"
+    "the whole event.\n"
+    "\nPress any key to close the popup window and go back to the main\n"
+    "Calcurse screen.");
+
+	help_tab.title = _("Tab:\n");
+	help_tab.text  =
+    _("Pressing 'Tab' allows you to switch between panels.\n"
+    "The panel currently in use has its border colorized.\n"
+    "\nSome actions are possible only if the right panel is selected.\n"
+    "For example, if you want to add a task in the TODO list, you need first\n"
+    "to press the 'Tab' key to get the TODO panel selected. Then you can\n"
+    "press 'A' to add your item.\n"
+    "\nNotice that at the bottom of the screen the list of possible actions\n"
+    "change while pressing 'Tab', so you always know what action can be\n"
+    "performed on the selected panel.");
+
+	help_goto.title = _("Goto:\n");
+	help_goto.text  =
+    _("Pressing 'G' allows you to jump to a specific day in the calendar.\n"
+    "\nUsing this command, you do not need to travel to that day using\n"
+    "the displacement keys inside the calendar panel.\n"
+    "If you hit [ENTER] without specifying any date, Calcurse checks the\n"
+    "system current date and you will be taken to that date.");
+
+	help_delete.title = _("Delete:\n");
+	help_delete.text  =
+    _("Pressing 'D' deletes an element in the ToDo or Appointment list.\n"
+    "\nDepending on which panel is selected when you press the delete key,\n"
+    "the hilighted item of either the ToDo or Appointment list will be \n"
+    "removed from this list.\n"
+    "\nIf the general option 'confirm_delete' is set to 'YES', then you will\n"
+    "be asked for confirmation before deleting the selected event.\n"
+    "Do not forget to save the calendar data to retrieve the modifications\n"
+    "next time you launch Calcurse.");
+
+	help_add.title = _("Add:\n");
+	help_add.text  =
+    _("Pressing 'A' allows you to add an item in either the ToDo or Appointment\n"
+    "list, depending on which panel is selected when you press 'A'.\n"
+    "\nTo enter a new item in the TODO list, you only need to enter the\n"
+    "description of this new item.\n"
+    "\nIf the APPOINTMENT panel is selected while pressing 'A', you will be\n"
+    "able to enter either a new appointment or a new all-day long event.\n"
+    "To enter a new event, press [ENTER] instead of the item start time, and\n"
+    "just fill in the event description.\n"
+    "To enter a new appointment to be added in the APPOINTMENT list, you\n"
+    "will need to enter successively the time at which the appointment\n"
+    "begins, the appointment length (either by specifying the duration in\n"
+    "minutes, or the end time in [hh:mm] or [h:mm] format), and the\n"
+    "description of the event.\n"
+    "\nThe day at which occurs the event or appointment is the day currently\n"
+    "selected in the calendar, so you need to move to the desired day before\n"
+    "pressing 'A'.\n"
+    "\nNotes:\n"
+    "       o if an appointment lasts for such a long time that it continues\n"
+    "         on the next days, this event will be indicated on all the\n"
+    "         corresponding days, and the beginning or ending hour will be\n"
+    "         replaced by '..' if the event does not begin or end on the day.\n"
+    "       o if you only press [ENTER] at the APPOINTMENT or TODO event\n"
+    "         description prompt, without any description, no item will be\n"
+    "         added.\n"
+    "       o do not forget to save the calendar data to retrieve the new\n"
+    "         event next time you launch Calcurse.");
+
+	help_config.title = _("Config:\n");
+	help_config.text  =
+    _("Pressing 'C' leads to the configuration submenu, from which you can\n"
+    "select between color, layout, and general options.\n"
+    "\nThe color submenu lets you choose the color theme.\n"
+    "\nThe layout submenu lets you choose the Calcurse screen layout, in other\n"
+    "words where to place the three different panels on the screen.\n"
+    "\nThe general options submenu brings a screen with the different options\n"
+    "which modifies the way Calcurse interacts with the user.\n"
+    "\nDo not forget to save the calendar data to retrieve your configuration\n"
+    "next time you launch Calcurse.");
+
+	help_credits.title = _("Calcurse - text-based organizer");
+	help_credits.text  =
+    _("Copyright (c) 2004-2006 Frederic Culot\n"
+    "\n"
+    "This program is free software; you can redistribute it and/or modify\n"
+    "it under the terms of the GNU General Public License as published by\n"
+    "the Free Software Foundation; either version 2 of the License, or\n"
+    "(at your option) any later version.\n"
+    "\nThis program is distributed in the hope that it will be useful,\n"
+    "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+    "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
+    "GNU General Public License for more details.\n"
+    "\n\n"
+    "Send your feedback or comments to : calcurse@culot.org\n"
+    "Calcurse home page : http://culot.org/calcurse");
+
+	/* 
+	 * Create the help window and panel. The panel is used to make
+	 * the scrolling faster.
+	 */
+	help_win = newwin(help_row, help_col, 0, 0);
+	help_pad = newpad(MAX_LENGTH, pad_width);
+	box(help_win, 0, 0);
+	sprintf(label, _("CalCurse %s | help"), VERSION);
+	win_show(help_win, label);
+
+	/* Display the main help screen. */
+/*	nl = write_help_pad(help_pad, help_main.title, help_main.text, pad_width);
+	status_bar(which_pan, colr, col, 2);
+        wmove(swin, 0, 0);
+	wnoutrefresh(help_win);
+	pnoutrefresh(help_pad, first_line, 0, pad_offset, pad_offset, 
+			help_row - 2, help_col - pad_offset);
+        doupdate();
+*/
+
+	/* Display the help screen related to user input. */
+	while ( ch != 'q' ) {
+                erase_window_part(help_win, 1, title_lines, 
+                                  help_col - 2, help_row - 2);
+
+		switch (ch) {
+		
+		case CTRL('N') :
+			if (nl > first_line + text_lines) first_line++;
+			break;
+
+		case CTRL('P') :
+			if (first_line > 0) first_line--;
+			break;
+
+		case '?':
+			first_line = 0;
+			nl = write_help_pad(help_pad, help_main.title,
+					help_main.text, pad_width);
+			break;
+		case 'r':
+			first_line = 0;
+			nl = write_help_pad(help_pad, help_redraw.title,
+					help_redraw.text, pad_width);
+			break;
+		case 's':
+			first_line = 0;
+			nl = write_help_pad(help_pad, help_save.title,
+					help_save.text, pad_width);
+			break;
+		case 'h':
+		case 'l':
+		case 'j':
+		case 'k':
+		case 259:
+		case 258:
+		case 260:
+		case 261:
+			first_line = 0;
+			nl = write_help_pad(help_pad, help_displacement.title,
+					help_displacement.text, pad_width);
+			break;
+
+		case 'a':
+			first_line = 0;
+			nl = write_help_pad(help_pad, help_add.title,
+					help_add.text, pad_width);
+			break;
+
+		case 'g':
+			first_line = 0;
+			nl = write_help_pad(help_pad, help_goto.title,
+					help_goto.text, pad_width);
+			break;
+
+		case 'd':
+			first_line = 0;
+			nl = write_help_pad(help_pad, help_delete.title,
+					help_delete.text, pad_width);
+			break;
+
+		case 'c':
+			first_line = 0;
+			nl = write_help_pad(help_pad, help_config.title,
+					help_config.text, pad_width);
+			break;
+
+		case 'v':
+			first_line = 0;
+			nl = write_help_pad(help_pad, help_view.title,
+					help_view.text, pad_width);
+			break;
+
+		case 9:
+			first_line = 0;
+			nl = write_help_pad(help_pad, help_tab.title,
+					help_tab.text, pad_width);
+			break;
+
+		case '@':
+			first_line = 0;
+			nl = write_help_pad(help_pad, help_credits.title,
+					help_credits.text, pad_width); 
+			break;
+		}
+
+		/* Draw the scrollbar if necessary. */
+		if (nl > text_lines){
+			float ratio = ((float) text_lines + 1) / ((float) nl);
+			int sbar_length = (int) (ratio * text_lines);
+			int highend = (int) (ratio * first_line);
+			int sbar_top = highend + title_lines + 1;
+
+			draw_scrollbar(help_win, sbar_top, help_col - 2,
+					sbar_length, title_lines + 1, 
+					help_row - 1, true);
+		}
+
+                wmove(swin, 0, 0);
+		wnoutrefresh(help_win);
+		pnoutrefresh(help_pad, first_line, 0, 
+				pad_offset, pad_offset, 
+				help_row - 2, help_col - pad_offset);
+                doupdate();
+                ch = wgetch(swin);
+	}
+	delwin(help_pad);
+	delwin(help_win);
+}
diff --git a/src/help.h b/src/help.h
new file mode 100755
index 0000000..5aa830f
--- /dev/null
+++ b/src/help.h
@@ -0,0 +1,41 @@
+/*	$calcurse: help.h,v 1.1 2006/07/31 21:00:03 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
+ *
+ */
+
+#ifndef CALCURSE_HELP_H
+#define CALCURSE_HELP_H
+
+#include <ncurses.h>
+
+typedef struct {
+	char *title;
+	char *text;
+} help_page_t;
+
+int write_help_pad(WINDOW *win, char *title, char *text, int pad_width);
+int get_help_lines(char *text);
+void help_screen(int which_pan, int colr);
+
+#endif /* CALCURSE_HELP_H */
diff --git a/src/i18n.h b/src/i18n.h
new file mode 100755
index 0000000..454a084
--- /dev/null
+++ b/src/i18n.h
@@ -0,0 +1,54 @@
+/*	$calcurse: i18n.h,v 1.1 2006/07/31 21:00:03 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
+ *
+ */
+
+#ifndef CALCURSE_I18N_H
+#define CALCURSE_I18N_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#if ENABLE_NLS
+ #include <libintl.h>
+ #undef _
+ #define _(String) gettext(String)
+ #ifdef gettext_noop
+  #define N_(String) gettext_noop(String)
+ #else
+  #define N_(String) (String)
+ #endif
+#else /* NLS disabled */
+ #define _(String) (String)
+ #define N_(String) (String)
+ #define textdomain(String) (String)
+ #define gettext(String) (String)
+ #define dgettext(String) (String)
+ #define dcgettext(String) (String)
+ #define bindtextdomain(String) (String)
+ #define bind_textdomain_codeset(Domain,Codeset) (Codeset)
+#endif /* ENABLE_NLS */
+
+#endif /* CALCURSE_I18N_H */
diff --git a/src/io.c b/src/io.c
new file mode 100755
index 0000000..35c5802
--- /dev/null
+++ b/src/io.c
@@ -0,0 +1,484 @@
+/*	$calcurse: io.c,v 1.1 2006/07/31 21:00:03 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
+ *
+ */
+
+#include <ncurses.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <math.h>
+#include <unistd.h>
+
+#include "i18n.h"
+#include "utils.h"
+#include "custom.h"
+#include "todo.h"
+#include "event.h"
+#include "apoint.h"
+#include "recur.h"
+#include "io.h"
+#include "vars.h"
+
+/* 
+ * Initialization of data paths. The argument cfile is the variable
+ * which contains the calendar file. If none is given, then the default
+ * one (~/.calcurse/apts) is taken. If the one given does not exist, it
+ * is created.
+ */
+void
+io_init(char *cfile)
+{
+	FILE *data_file;
+	char *home;
+	char apts_file[MAX_LENGTH] = "";
+	int ch;
+
+	home = getenv("HOME");
+	if (home == NULL) {
+		home = ".";
+	}
+	snprintf(path_dir, MAX_LENGTH, "%s/" DIR_NAME, home);
+	snprintf(path_todo, MAX_LENGTH, "%s/" TODO_PATH, home);
+	snprintf(path_conf, MAX_LENGTH, "%s/" CONF_PATH, home);
+	if (cfile == NULL) {
+		snprintf(path_apts, MAX_LENGTH, "%s/" APTS_PATH, home);
+	} else {
+		snprintf(apts_file, MAX_LENGTH, "%s", cfile);
+		strncpy(path_apts, apts_file, MAX_LENGTH);
+		/* check if the file exists, otherwise create it */
+		data_file = fopen(path_apts, "r");
+		if (data_file == NULL) {
+			printf(_("%s does not exist, create it now [y or n] ? "), path_apts);
+			ch = getchar();
+			switch (ch) {
+				case 'N':
+				case 'n':
+					printf(_("aborting...\n"));
+					exit(EXIT_FAILURE);
+					break;
+
+				case 'Y':
+				case 'y':
+					data_file = fopen(path_apts, "w");
+					if (data_file == NULL) {
+						perror(path_apts);
+						exit(EXIT_FAILURE);
+					} else {
+						printf(_("%s successfully created\n"),path_apts);
+						printf(_("starting interactive mode...\n"));
+					}
+					break;
+
+				default:
+					printf(_("aborting...\n"));
+					exit(EXIT_FAILURE);
+					break;
+			} 
+		}
+		fclose(data_file);
+	}
+}
+
+  /* get data from file */
+void extract_data(char *dst_data, const char *org, int len)
+{
+	for (;;) {
+		if (*org == '\n' || *org == '\0')
+			break;
+		*dst_data++ = *org++;
+	}
+	*dst_data = '\0';
+}
+
+/* Save the calendar data */
+void
+save_cal(bool auto_save, bool confirm_quit, 
+	 bool confirm_delete, bool skip_system_dialogs, 
+         bool skip_progress_bar, bool week_begins_on_monday, 
+	 int colr, int layout)
+{
+	FILE *data_file;
+	struct event_s *k;
+	struct apoint_s *j;
+	struct todo_s *i;
+	char *access_pb = _("Problems accessing data file ...");
+	char *config_txt =
+	    "#\n# Calcurse configuration file\n#\n# This file sets the configuration options used by Calcurse. These\n# options are usually set from within Calcurse. A line beginning with \n# a space or tab is considered to be a continuation of the previous line.\n# For a variable to be unset its value must be blank.\n# To set a variable to the empty string its value should be \"\".\n# Lines beginning with \"#\" are comments, and ignored by Calcurse.\n";
+	char *save_success = _("The data files were successfully saved");
+	char *enter = _("Press [ENTER] to continue");
+	bool save = true, show_bar = false;
+
+	if (!skip_progress_bar) show_bar = true;
+
+	/* Save the user configuration. */
+	
+	if (show_bar) progress_bar(save, 1);
+	data_file = fopen(path_conf, "w");
+	if (data_file == (FILE *) 0)
+                status_mesg(access_pb, "");
+	else {
+		fprintf(data_file, "%s\n", config_txt);
+
+		fprintf(data_file,
+			"# If this option is set to yes, automatic save is done when quitting\n");
+		fprintf(data_file, "auto_save=\n");
+		fprintf(data_file, "%s\n", 
+			(auto_save) ? "yes" : "no");
+
+		fprintf(data_file,
+			"\n# If this option is set to yes, confirmation is required before quitting\n");
+		fprintf(data_file, "confirm_quit=\n");
+		fprintf(data_file, "%s\n", 
+			(confirm_quit) ? "yes" : "no");
+
+		fprintf(data_file,
+			"\n# If this option is set to yes, confirmation is required before deleting an event\n");
+		fprintf(data_file, "confirm_delete=\n");
+		fprintf(data_file, "%s\n", 
+			(confirm_delete) ? "yes" : "no");
+
+		fprintf(data_file,
+			"\n# If this option is set to yes, messages about loaded and saved data will not be displayed\n");
+		fprintf(data_file, "skip_system_dialogs=\n");
+		fprintf(data_file, "%s\n", 
+			(skip_system_dialogs) ? "yes" : "no");
+
+		fprintf(data_file,
+			"\n# If this option is set to yes, progress bar appearing when saving data will not be displayed\n");
+		fprintf(data_file, "skip_progress_bar=\n");
+		fprintf(data_file, "%s\n", 
+			(skip_progress_bar) ? "yes" : "no");
+
+		fprintf(data_file,
+			"\n# If this option is set to yes, monday is the first day of the week, else it is sunday\n");
+		fprintf(data_file, "week_begins_on_monday=\n");
+		fprintf(data_file, "%s\n", 
+			(week_begins_on_monday) ? "yes" : "no");
+
+		fprintf(data_file,
+			"\n# This is the color theme used for menus (1 to 8) :\n");
+		fprintf(data_file, "color-theme=\n");
+		fprintf(data_file, "%d\n", colr);
+
+		fprintf(data_file,
+			"\n# This is the layout of the calendar (1 to 4) :\n");
+		fprintf(data_file, "layout=\n");
+		fprintf(data_file, "%d\n", layout);
+		fclose(data_file);
+	}
+
+	/* Save the todo data file. */
+	if (show_bar) progress_bar(save, 2);
+	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, "%s\n", i->mesg);
+		fclose(data_file);
+	}
+
+	/* 
+         * Save the apts data file, which contains the 
+         * appointments first, and then the events. 
+	 * Recursive items are written first.
+         */
+	if (show_bar) progress_bar(save, 3);
+	data_file = fopen(path_apts, "w");
+	if (data_file == (FILE *) 0)
+	        status_mesg(access_pb, "");
+	else {
+		recur_save_data(data_file);
+		for (j = apointlist; j != 0; j = j->next)
+			apoint_write(j, data_file);
+		for (k = eventlist; k != 0; k = k->next)
+			event_write(k, data_file);
+		fclose(data_file);
+	}
+ 
+
+	/* Print a message telling data were saved */
+        if (!skip_system_dialogs){
+                status_mesg(save_success, enter);
+                wgetch(swin);
+        }
+}
+
+/* 
+ * Check what type of data is written in the appointment file, 
+ * and then load either: a new appointment, a new event, or a new
+ * recursive item (which can also be either an event or an appointment).
+ */ 
+void load_app()
+{
+	FILE *data_file;
+	int c, is_appointment, is_event, is_recursive;
+        struct tm start, end, until, *lt;
+        time_t t;
+        int id = 0;
+	int freq;
+	char type;
+	char *error = 
+		_("FATAL ERROR in load_app: wrong format in the appointment or event\n");
+
+        t = time(NULL);
+        lt = localtime(&t);
+        start = end = until = *lt;
+	
+	data_file = fopen(path_apts, "r");
+	for (;;) {
+                is_appointment = is_event = is_recursive = 0;
+		c = getc(data_file);
+		if (c == EOF)
+			break;
+		ungetc(c, data_file);
+
+                /* Read the date first: it is common to both events
+                 * and appointments. 
+                 */
+                if (fscanf(data_file, "%u / %u / %u ", 
+                           &start.tm_mon, &start.tm_mday, &start.tm_year) != 3) {
+                        fputs(_("FATAL ERROR in load_app: "
+				"syntax error in the item date\n"), stderr);
+                        exit(EXIT_FAILURE);
+                }
+
+                /* Read the next character : if it is an '@' then we have
+                 * an appointment, else if it is an '[' we have en event.
+                 */
+                c = getc(data_file);
+
+                if (c == '@')
+                        is_appointment = 1;
+                else if (c == '[')
+                        is_event = 1;
+                else {
+                        fputs(_("FATAL ERROR in load_app: "
+				"no event nor appointment found\n"), stderr);
+                        exit(EXIT_FAILURE);
+                }
+                ungetc(c, data_file);
+
+                /* Read the remaining informations. */
+                if (is_appointment) {
+                        fscanf(data_file, "@ %u : %u -> %u / %u / %u @ %u : %u ",
+                               &start.tm_hour, &start.tm_min,
+                               &end.tm_mon, &end.tm_mday, &end.tm_year,
+                               &end.tm_hour, &end.tm_min); 
+                } else if (is_event) {
+                        fscanf(data_file, "[%d] ", &id);
+                } else { /* NOT REACHED */
+                  	fputs(error, stderr);
+			exit(EXIT_FAILURE);
+                }
+		
+		/* Check if we have a recursive item. */
+		c = getc(data_file);
+
+		if (c == '{') {
+			ungetc(c, data_file);
+			is_recursive = 1;
+			fscanf(data_file, "{ %d%c ", &freq, &type);
+			/* Check if we have an endless recurrent item. */
+			c = getc(data_file);
+			if (c == '}') {
+				ungetc(c, data_file);
+				fscanf(data_file, "} ");
+				until.tm_year = 0;	
+				if (is_appointment) 
+					c = getc(data_file); // useless '|'
+			} else if (c == '-') {
+				ungetc(c, data_file);
+				fscanf(data_file, " -> %u / %u / %u } ",
+					&until.tm_mon, &until.tm_mday, 
+					&until.tm_year);
+				if (is_appointment) 
+					c = getc(data_file); // useless '|'
+			} else { /* NOT REACHED */
+				fputs(error, stderr);
+				exit(EXIT_FAILURE);
+			}
+		} else {
+			if (is_event) // if appointment we have a useless '|' 
+				ungetc(c, data_file);
+		}
+
+		/*
+		 * Last: read the item description and load it into its
+		 * corresponding linked list, depending on the item type.
+		 */
+		if (is_appointment) {
+			if (is_recursive) {
+				recur_apoint_scan(data_file, start, end,
+					type, freq, until);
+			} else {
+				apoint_scan(data_file, start, end);
+			}
+		} else if (is_event) {
+			if (is_recursive) {
+				recur_event_scan(data_file, start, id,
+					type, freq, until);
+			} else {
+				event_scan(data_file, start, id);
+			}
+		} else { /* NOT REACHED */
+			fputs(error, stderr);
+			exit(EXIT_FAILURE);	
+		}
+	}
+	fclose(data_file);
+}
+
+/* Load the todo data */
+int
+load_todo(int colr)
+{
+	FILE *data_file;
+	char *mesg_line1 = _("Failed to open todo file");
+	char *mesg_line2 = _("Press [ENTER] to continue");
+	int nb_tod = 0;
+	char buf[100], e_todo[100];
+
+	data_file = fopen(path_todo, "r");
+	if (data_file == NULL) {
+		status_mesg(mesg_line1, mesg_line2);
+		wgetch(swin);
+	}
+	for (;;) {
+		if (fgets(buf, 99, data_file) == NULL) {
+			break;
+		}
+		extract_data(e_todo, buf, strlen(buf));
+		todo_add(e_todo);
+		++nb_tod;
+	}
+	fclose(data_file);
+	return nb_tod;
+}
+
+/* Checks if data files exist. If not, create them */
+int check_data_files()
+{
+	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;
+		}
+	}
+	fclose(data_file);
+
+	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;
+		}
+	}
+	fclose(data_file);
+
+	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;
+}
+
+/* Draw the startup screen */
+void startup_screen(bool skip_dialogs, int no_data_file, int colr)
+{
+	char *welcome_mesg = _("Welcome to Calcurse. Missing data files were created.");
+	char *data_mesg = _("Data files found. Data will be loaded now.");
+	char *enter = _("Press [ENTER] to continue");
+
+	if (no_data_file != 0) {
+	  status_mesg(welcome_mesg, enter);
+          wgetch(swin);
+	} else if (!skip_dialogs){
+                        status_mesg(data_mesg, enter);
+                        wgetch(swin);
+	}
+}
+
+/* Draw a progress bar while saving or loading data. */
+void progress_bar(bool save, int progress)
+{
+	int i, nbd = 4;
+	char *mesg_sav  = _("Saving...");
+	char *mesg_load = _("Loading...");
+	char *barchar = "|";
+	char *data[4] = {
+		"[            ]",
+		"[    conf    ]", 
+		"[    todo    ]", 
+		"[    apts    ]"}; 
+	int ipos = strlen(data[1]) + 2;
+	int epos[4];
+	int sleep_time = 125000;
+	
+	/* progress bar length init. */
+	epos[0] = floor(col / nbd);
+	epos[1] = 2*epos[0]; 
+	epos[2] = 3*epos[0];
+	epos[3] = col - 2;
+
+	/* Display which data is being saved. */
+	if (save) 
+		status_mesg(mesg_sav, data[progress]);
+	else
+		status_mesg(mesg_load, data[progress]);
+
+	/* Draw the progress bar. */
+	mvwprintw(swin, 1, ipos, barchar);
+	mvwprintw(swin, 1, epos[nbd - 1], barchar);
+	custom_apply_attr(swin, ATTR_HIGHEST);
+	for (i = ipos + 1; i < epos[progress]; i++)
+		mvwaddch(swin, 1, i, ' ' | A_REVERSE);
+	custom_remove_attr(swin, ATTR_HIGHEST);
+	wmove(swin, 0, 0);
+	wrefresh(swin);
+	usleep(sleep_time); 
+}
diff --git a/src/io.h b/src/io.h
new file mode 100755
index 0000000..8cc7788
--- /dev/null
+++ b/src/io.h
@@ -0,0 +1,42 @@
+/*	$calcurse: io.h,v 1.1 2006/07/31 21:00:03 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
+ *
+ */
+
+#ifndef CALCURSE_IO_H
+#define CALCURSE_IO_H
+
+void io_init(char *cfile);
+void extract_data(char *dst_data, const char *org, int len);
+void save_cal(bool auto_save, bool confirm_quit, 
+	 bool confirm_delete, bool skip_system_dialogs, 
+         bool skip_progress_bar, bool week_begins_on_monday, 
+	 int colr, int layout);
+void load_app();
+int load_todo(int colr);
+int check_data_files();
+void startup_screen(bool skip_dialogs, int no_data_file, int colr);
+void progress_bar(bool save, int progress);
+
+#endif /* CALCURSE_IO_H */
diff --git a/src/recur.c b/src/recur.c
new file mode 100755
index 0000000..d0629aa
--- /dev/null
+++ b/src/recur.c
@@ -0,0 +1,355 @@
+/*	$calcurse: recur.c,v 1.1 2006/07/31 21:00:03 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
+ *
+ */
+
+#include <ncurses.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <time.h>
+
+#include "i18n.h"
+#include "utils.h"
+#include "apoint.h"
+#include "event.h"
+#include "recur.h"
+
+struct recur_apoint_s *recur_alist;
+struct recur_event_s *recur_elist;
+
+/* Insert a new recursive appointment in the general linked list */
+struct recur_apoint_s *recur_apoint_new(char *mesg, long start, long dur, 
+	int type, int freq, long until)
+{
+	struct recur_apoint_s *o, **i;
+	o = (struct recur_apoint_s *) malloc(sizeof(struct recur_apoint_s));
+	o->rpt = (struct rpt_s *) malloc(sizeof(struct rpt_s));
+	o->exc = (struct days_s *) malloc(sizeof(struct days_s));
+	o->mesg = (char *) malloc(strlen(mesg) + 1);
+	strcpy(o->mesg, mesg);
+	o->start = start;
+	o->dur = dur;
+	o->rpt->type = type;
+	o->rpt->freq = freq;
+	o->rpt->until = until;
+	i = &recur_alist;
+	for (;;) {
+		if (*i == 0 || (*i)->start > start) {
+			o->next = *i;
+			*i = o;
+			break;
+		}
+		i = &(*i)->next;
+	}
+	return o;
+}
+
+/* Insert a new recursive event in the general linked list */
+struct recur_event_s *recur_event_new(char *mesg, long day, int id, 
+	int type, int freq, long until)
+{
+	struct recur_event_s *o, **i;
+	o = (struct recur_event_s *) malloc(sizeof(struct recur_event_s));
+	o->rpt = (struct rpt_s *) malloc(sizeof(struct rpt_s));
+	o->exc = (struct days_s *) malloc(sizeof(struct days_s));
+	o->mesg = (char *) malloc(strlen(mesg) + 1);
+	strcpy(o->mesg, mesg);
+	o->day = day;
+	o->id = id;
+	o->rpt->type = type;
+	o->rpt->freq = freq;
+	o->rpt->until = until;
+	i = &recur_elist;
+	for (;;) {
+		if (*i == 0 || (*i)->day > day) {
+			o->next = *i;
+			*i = o;
+			break;
+		}
+		i = &(*i)->next;
+	}
+	return o;
+}
+
+/* 
+ * Correspondance between the defines on recursive type, 
+ * and the letter to be written in file. 
+ */
+char recur_def2char(int define){
+	char recur_char;
+
+	switch (define) {
+	case 1:
+		recur_char = 'D';
+		break;	
+	case 2:
+		recur_char = 'W';
+		break;
+	case 3:
+		recur_char = 'M';
+		break;
+	case 4:
+		recur_char = 'Y';
+		break;
+	}
+	return recur_char;
+}
+
+/* 
+ * Correspondance between the letters written in file and the defines
+ * concerning the recursive type.
+ */
+int recur_char2def(char type){
+	int recur_def;
+
+	switch (type) {
+	case 'D':
+		recur_def = RECUR_DAILY;
+		break;	
+	case 'W':
+		recur_def = RECUR_WEEKLY;
+		break;
+	case 'M':
+		recur_def = RECUR_MONTHLY;
+		break;
+	case 'Y':
+		recur_def = RECUR_YEARLY;
+		break;
+	}
+	return recur_def;
+}
+
+/* Writting of a recursive appointment into file. */
+void recur_apoint_write(struct recur_apoint_s *o, FILE *f)
+{
+	struct tm *lt;
+	time_t t;
+
+	t = o->start;
+	lt = localtime(&t);
+	fprintf(f, "%02u/%02u/%04u @ %02u:%02u",
+		lt->tm_mon + 1, lt->tm_mday, 1900 + lt->tm_year,
+		lt->tm_hour, lt->tm_min);
+
+	t = o->start + o->dur;
+	lt = localtime(&t);
+	fprintf(f, " -> %02u/%02u/%04u @ %02u:%02u",
+		lt->tm_mon + 1, lt->tm_mday, 1900 + lt->tm_year,
+		lt->tm_hour, lt->tm_min);
+
+	t = o->rpt->until;
+	if (t == 0) { /* We have an endless recurrent appointment. */
+		fprintf(f, " {%d%c} |%s\n", o->rpt->freq, 
+			recur_def2char(o->rpt->type), o->mesg);
+	} else {
+		lt = localtime(&t);
+		fprintf(f, " {%d%c -> %02u/%02u/%04u} |%s\n",
+			o->rpt->freq, recur_def2char(o->rpt->type),
+			lt->tm_mon + 1, lt->tm_mday, 1900 + lt->tm_year,
+			o->mesg);
+	}
+}
+
+/* Writting of a recursive event into file. */
+void recur_event_write(struct recur_event_s *o, FILE *f)
+{
+	struct tm *lt;
+	time_t t;
+	int st_mon, st_day, st_year;
+	int end_mon, end_day, end_year;
+
+	t = o->day;
+	lt = localtime(&t);
+	st_mon = lt->tm_mon + 1;
+	st_day = lt->tm_mday;
+	st_year = lt->tm_year + 1900;
+	t = o->rpt->until;
+	if (t == 0) { /* We have an endless recurrent event. */
+		fprintf(f, "%02u/%02u/%04u [%d] {%d%c} %s\n",
+			st_mon, st_day, st_year, o->id, o->rpt->freq,
+			recur_def2char(o->rpt->type), o->mesg);
+	} else {
+		lt = localtime(&t);
+		end_mon = lt->tm_mon + 1;
+		end_day = lt->tm_mday;
+		end_year = lt->tm_year + 1900;
+		fprintf(f, "%02u/%02u/%04u [%d] {%d%c -> %02u/%02u/%04u} %s\n",
+			st_mon, st_day, st_year, o->id, 
+			o->rpt->freq, recur_def2char(o->rpt->type),
+			end_mon, end_day, end_year, o->mesg);
+	}
+}
+
+/* Load the recursive appointment description */
+struct recur_apoint_s *recur_apoint_scan(FILE * f, struct tm start, 
+	struct tm end, char type, int freq, struct tm until)
+{
+	struct tm *lt;
+	char buf[MESG_MAXSIZE], *nl;
+	time_t tstart, tend, t, tuntil;
+
+	t = time(NULL);
+	lt = localtime(&t);
+
+        /* Read the appointment description */
+	fgets(buf, MESG_MAXSIZE, f);
+	nl = strchr(buf, '\n');
+	if (nl) {
+		*nl = '\0';
+	}
+
+	start.tm_sec = end.tm_sec = 0;
+	start.tm_isdst = end.tm_isdst = -1;
+	start.tm_year -= 1900;
+	start.tm_mon--;
+	end.tm_year -= 1900;
+	end.tm_mon--;
+	tstart = mktime(&start);
+	tend = mktime(&end);
+
+	if (until.tm_year != 0) {
+		until.tm_hour = 12;
+        	until.tm_min = 0;
+		until.tm_sec =  0;
+		until.tm_isdst = -1;
+		until.tm_year -= 1900;
+		until.tm_mon--;
+		tuntil = mktime(&until);
+	} else {
+		tuntil = 0;
+	}
+
+	if (tstart == -1 || tend == -1 || tstart > tend || tuntil == -1) {
+		fputs(_("FATAL ERROR in apoint_scan: date error in the appointment\n"), stderr);
+		exit(EXIT_FAILURE);
+	}
+      
+	return recur_apoint_new(buf, tstart, tend - tstart, 
+		recur_char2def(type), freq, tuntil);
+}
+
+/* Load the recursive events from file */
+struct recur_event_s *recur_event_scan(FILE * f, struct tm start, int id, 
+	char type, int freq, struct tm until)
+{
+	struct tm *lt;
+	char buf[MESG_MAXSIZE], *nl;
+	time_t tstart, t, tuntil;
+
+	t = time(NULL);
+	lt = localtime(&t);
+
+        /* Read the event description */
+	fgets(buf, MESG_MAXSIZE, f);
+	nl = strchr(buf, '\n');
+	if (nl) {
+		*nl = '\0';
+	}
+      
+      	start.tm_hour = until.tm_hour = 12;
+        start.tm_min = until.tm_min = 0;
+	start.tm_sec = until.tm_sec =  0;
+	start.tm_isdst = until.tm_isdst = -1;
+	start.tm_year -= 1900;
+	start.tm_mon--;
+	if (until.tm_year != 0) {
+		until.tm_year -= 1900;
+		until.tm_mon--;
+		tuntil = mktime(&until);
+	} else {
+		tuntil = 0;
+	}
+	tstart = mktime(&start);
+	if ( (tstart == -1) || (tuntil == -1) ) {
+		fputs(_("FATAL ERROR in recur_event_scan: date error in the event\n"), stderr);
+		exit(EXIT_FAILURE);
+	}
+	
+	return recur_event_new(buf, tstart, id, recur_char2def(type), freq, tuntil);
+}
+
+/* Write recursive items to file. */
+void recur_save_data(FILE *f)
+{
+	struct recur_event_s *re;
+	struct recur_apoint_s *ra;
+
+	for (re = recur_elist; re != 0; re = re->next)
+		recur_event_write(re, f);
+	for (ra = recur_alist; ra != 0; ra = ra->next)
+		recur_apoint_write(ra, f);
+}
+
+/* Check if the recurrent item belongs to the selected day. */
+unsigned recur_item_inday(long item_start, int rpt_type, int rpt_freq,
+			  long rpt_until, long day_start)
+{
+	const int DAYINSEC = 86400; 
+	long day_end = day_start + DAYINSEC;
+	int inday = 0;
+	struct tm *lt;
+	time_t t;
+	char *error = 
+		_("FATAL ERROR in recur_item_inday: unknown item type\n");
+
+	if (rpt_until == 0) /* we have an endless recurrent item */
+		rpt_until = day_end;
+	while (item_start <= day_end && item_start <= rpt_until) {
+		if (item_start < day_end && item_start >= day_start) {
+			inday = 1;
+			break;
+		}
+		t = item_start;
+		lt = localtime(&t);
+		if (rpt_type == RECUR_DAILY) {
+			lt->tm_mday += rpt_freq;
+		} else if (rpt_type == RECUR_WEEKLY) {
+			lt->tm_mday += rpt_freq * 7;
+		} else if (rpt_type == RECUR_MONTHLY) {
+			lt->tm_mon += rpt_freq;
+		} else if (rpt_type == RECUR_YEARLY) {
+			lt->tm_year += rpt_freq;
+		} else { /* NOT REACHED */
+			fputs(error, stderr);
+			exit(EXIT_FAILURE);
+		}
+		item_start = date2sec(lt->tm_year + 1900, lt->tm_mon + 1, 
+			lt->tm_mday, 0, 0);
+	}	
+	return inday;
+}
+
+/* Returns a structure of type apoint_s given a structure of type recur_apoint_s */
+struct apoint_s *recur_apoint_s2apoint_s(struct recur_apoint_s *p)
+{
+	struct apoint_s *a;
+
+	a = (struct apoint_s *) malloc(sizeof(struct apoint_s));
+	a->mesg = (char *) malloc(strlen(p->mesg) + 1);
+	a->start = p->start;
+	a->dur = p->dur;
+	a->mesg = p->mesg;
+	return a;
+}
diff --git a/src/recur.h b/src/recur.h
new file mode 100755
index 0000000..611197c
--- /dev/null
+++ b/src/recur.h
@@ -0,0 +1,87 @@
+/*	$calcurse: recur.h,v 1.1 2006/07/31 21:00:03 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
+ *
+ */
+
+#ifndef CALCURSE_RECUR_H
+#define CALCURSE_RECUR_H
+
+#include "apoint.h"
+
+#define RECUR_NO	0
+#define RECUR_DAILY	1
+#define RECUR_WEEKLY	2
+#define RECUR_MONTHLY	3
+#define RECUR_YEARLY	4
+
+struct days_s {
+	struct days_s *next;
+	long st;	/* beggining of the considered day, in seconds */
+};
+
+struct rpt_s {
+	int type; 	/* repetition type, see RECUR_* defines */
+	int freq;	/* repetition frequence */
+	long until;	/* ending date for repeated event */
+};
+
+struct recur_apoint_s {
+	struct recur_apoint_s *next;
+	struct rpt_s *rpt;	/* information about repetition */
+	struct days_s *exc;	/* days when the item should not be repeated */
+	long start;		/* beggining of the appointment */
+	long dur;		/* duration of the appointment */
+	char *mesg;		/* appointment description */
+};
+
+struct recur_event_s {
+	struct recur_event_s *next;
+	struct rpt_s *rpt;	/* information about repetition */
+	struct days_s *exc;	/* days when the item should not be repeated */
+	int id;			/* event type */
+	long day;		/* day at which event occurs */
+	char *mesg;		/* event description */
+};
+
+extern struct recur_apoint_s *recur_alist;
+extern struct recur_event_s *recur_elist;
+
+struct recur_apoint_s *recur_apoint_new(char *mesg, long start, long duration,
+	int type, int freq, long until); 
+struct recur_event_s *recur_event_new(char *mesg, long day, int id, 
+	int type, int freq, long until);
+char recur_def2char(int define);
+int recur_char2def(char type);
+void recur_apoint_write(struct recur_apoint_s *o, FILE * f);
+void recur_event_write(struct recur_event_s *o, FILE * f);
+struct recur_apoint_s *recur_apoint_scan(FILE * f, struct tm start,
+	struct tm end, char type, int freq, struct tm until);
+struct recur_event_s *recur_event_scan(FILE * f, struct tm start, int id, 
+	char type, int freq, struct tm until);
+void recur_save_data(FILE *f);
+unsigned recur_item_inday(long item_start, int rpt_type, int rpt_freq,
+			  long rpt_until, long day_start);
+struct apoint_s *recur_apoint_s2apoint_s(struct recur_apoint_s *p);
+
+#endif /* CALCURSE_RECUR_H */
diff --git a/src/todo.c b/src/todo.c
new file mode 100755
index 0000000..b9419ec
--- /dev/null
+++ b/src/todo.c
@@ -0,0 +1,80 @@
+/*	$calcurse: todo.c,v 1.1 2006/07/31 21:00:03 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
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "i18n.h"
+#include "todo.h"
+
+struct todo_s *todolist;
+
+struct todo_s *todo_insert(char *mesg)
+{
+	struct todo_s *o;
+	o = (struct todo_s *) malloc(sizeof(struct todo_s));
+	o->mesg = (char *) malloc(strlen(mesg) + 1);
+	strcpy(o->mesg, mesg);
+	o->next = todolist;
+	todolist = o;
+	return o;
+}
+
+struct todo_s *todo_add(char *mesg)
+{
+	struct todo_s *o, **i;
+	o = (struct todo_s *) malloc(sizeof(struct todo_s));
+	o->mesg = (char *) malloc(strlen(mesg) + 1);
+	strcpy(o->mesg, mesg);
+	for (i = &todolist; *i != 0; i = &(*i)->next) {
+	}
+	o->next = *i;
+	*i = o;
+	return o;
+}
+
+void todo_delete_bynum(unsigned num)
+{
+	unsigned n;
+	struct todo_s *i, **iptr;
+
+	n = 0;
+	iptr = &todolist;
+	for (i = todolist; i != 0; i = i->next) {
+		if (n == num) {
+			*iptr = i->next;
+			free(i->mesg);
+			free(i);
+			return;
+		}
+		iptr = &i->next;
+		n++;
+	}
+	/* not reached */
+	fputs(_("FATAL ERROR in todo_delete_bynum: no such todo\n"), stderr);
+	exit(EXIT_FAILURE);
+}
diff --git a/src/todo.h b/src/todo.h
new file mode 100755
index 0000000..9e2af31
--- /dev/null
+++ b/src/todo.h
@@ -0,0 +1,41 @@
+/*	$calcurse: todo.h,v 1.1 2006/07/31 21:00:03 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
+ *
+ */
+
+#ifndef CALCURSE_TODO_H
+#define CALCURSE_TODO_H
+
+struct todo_s {
+	struct todo_s *next;
+	char *mesg;
+};
+
+extern struct todo_s *todolist;
+
+struct todo_s *todo_insert(char *mesg);
+struct todo_s *todo_add(char *mesg);
+void todo_delete_bynum(unsigned num);
+
+#endif /* CALCURSE_TODO_H */
diff --git a/src/utils.c b/src/utils.c
new file mode 100755
index 0000000..ded00fb
--- /dev/null
+++ b/src/utils.c
@@ -0,0 +1,614 @@
+/*	$calcurse: utils.c,v 1.1 2006/07/31 21:00:03 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
+ *
+ */
+
+#include <ncurses.h>
+#include <time.h>	
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <stdbool.h>
+#include <sys/types.h>
+#include <math.h>
+
+#include "i18n.h"
+#include "utils.h"
+#include "custom.h"
+#include "vars.h"
+
+
+/* 
+ * Print a message in the status bar.
+ * Message texts for first line and second line are to be provided.
+ */
+
+void status_mesg(char *mesg_line1, char *mesg_line2)
+{
+	erase_window_part(swin, 0, 0, col, 2);
+	custom_apply_attr(swin, ATTR_HIGHEST);
+	mvwprintw(swin, 0, 0, mesg_line1);
+	mvwprintw(swin, 1, 0, mesg_line2);
+	custom_remove_attr(swin, ATTR_HIGHEST);
+}
+
+/* 
+ * Erase part of a window 
+ */
+void erase_window_part(WINDOW *win, int first_col, int first_row,
+			int last_col, int last_row)
+{
+	int c, r;
+
+	for (r = first_row; r <= last_row; r++){
+		for (c = first_col; c <= last_col; c++){
+			mvwprintw(win, r, c, " ");
+		}
+	}
+	wnoutrefresh(win);
+}
+
+/* draws a popup window */
+WINDOW * popup(int pop_row, int pop_col,
+	    int pop_y, int pop_x, char *pop_lab)
+{
+	char *txt_pop = _("Press any key to continue...");
+	char label[80];
+	WINDOW *popup_win;
+
+	popup_win = newwin(pop_row, pop_col, pop_y, pop_x);
+	custom_apply_attr(popup_win, ATTR_HIGHEST);
+	box(popup_win, 0, 0);
+	sprintf(label, "%s", pop_lab);
+	win_show(popup_win, label);
+	mvwprintw(popup_win, pop_row - 2, pop_col - (strlen(txt_pop) + 1), "%s",
+		 txt_pop);
+	custom_remove_attr(popup_win, ATTR_HIGHEST);
+	wnoutrefresh(popup_win);
+        doupdate();
+	return popup_win;
+}
+
+/* prints in middle of a panel */
+void
+print_in_middle(WINDOW * win, int starty, int startx, int width, char *string)
+{
+	int length, x, y;
+	float temp;
+
+	if (win == NULL)
+		win = stdscr;
+	getyx(win, y, x);
+	if (startx != 0)
+		x = startx;
+	if (starty != 0)
+		y = starty;
+	if (width == 0)
+		width = 80;
+
+	length = strlen(string);
+	temp = (width - length) / 2;
+	x = startx + (int) temp;
+	custom_apply_attr(win, ATTR_HIGHEST);
+	mvwprintw(win, y, x, "%s", string);
+	custom_remove_attr(win, ATTR_HIGHEST);
+}
+
+/* 
+ * Getstring allows to get user input and to print it on a window,
+ * even if noecho() is on.
+ */
+void getstring(win, colr, string, start_x, start_y)
+WINDOW *win;
+int colr;
+char *string;
+int start_x, start_y;
+{
+	int ch;
+	int charcount = 0;
+
+	custom_apply_attr(win, ATTR_HIGHEST);
+	if (start_x != -1)
+		wmove(win, start_y, start_x);
+
+	while ((ch = wgetch(win)) != '\n') {
+	        if ((ch == KEY_BACKSPACE) || 
+				(ch == 330) ||
+				(ch == 263) || 
+				(ch == 127) ||
+				(ch == CTRL('H')) ) {
+			if (charcount > 0) {
+				string--;
+				charcount--;
+				wmove(win, start_y, start_x + charcount);
+				waddch(win, ' ');
+				wmove(win, start_y, start_x + charcount);
+			}
+		} else {
+			*string++ = ch;
+			charcount++;
+			waddch(win, ch);
+		}
+		doupdate();
+	}
+	*string = 0;
+	custom_remove_attr(win, ATTR_HIGHEST);
+	return;
+}
+
+/* checks if a string is only made of digits */
+int is_all_digit(char *string)
+{
+	int digit, i;
+	int all_digit;
+
+	digit = 0;
+	all_digit = 0;
+
+	for (i = 0; i <= strlen(string); i++)
+		if (isdigit(string[i]) != 0)
+			digit++;
+	if (digit == strlen(string))
+		all_digit = 1;
+	return all_digit;
+}
+
+/* draw panel border in color */
+void border_color(WINDOW * window, int bcolr)
+{
+        int color_attr    = A_BOLD;
+        int no_color_attr = A_BOLD;
+
+        if (colorize) {
+                wattron(window, color_attr | COLOR_PAIR(bcolr));
+                box(window, 0, 0);
+        } else {
+                wattron(window, no_color_attr);
+                box(window, 0, 0);
+        }
+
+	if (colorize) {
+                wattroff(window, color_attr | COLOR_PAIR(bcolr));
+        } else {
+                wattroff(window, no_color_attr);
+        }
+
+	wnoutrefresh(window);
+}
+
+/* draw panel border without any color */
+void border_nocolor(WINDOW * window)
+{
+        int colr = 9;
+        int color_attr   = A_BOLD;
+        int no_color_attr = A_DIM;
+
+        if (colorize) {
+                wattron(window, color_attr | COLOR_PAIR(colr));
+        } else {
+                wattron(window, no_color_attr);
+        }
+        
+        box(window, 0, 0);
+        
+        if (colorize) {
+                wattroff(window, color_attr | COLOR_PAIR(colr));
+        } else {
+                wattroff(window, no_color_attr);
+        } 
+
+	wnoutrefresh(window);
+}
+
+ /* prints and scroll text in a window */
+void scroller(WINDOW *win, char *mesg, int x, int y, int nb_row, int nb_col)
+{
+	int x_offset = 3;
+	int y_offset = 3;
+	int text_len = nb_col - 2 * x_offset;
+	int text_max_row = nb_row - 3;
+	int nlin, i, j, k;
+	int last_blank_i, last_blank_j;
+	char buf[] = " ";
+	char *next_mesg = _("-- Press 'N' for next page --");
+	char *prev_mesg = _("-- Press 'P' for previous page --");
+	int ch;
+	int which_page;		//first page : 0, second page : 1
+
+	i = 0;			//position in the message
+	j = 0;			//x position on the current line
+	nlin = 1;		//line number 
+	last_blank_j = 0;
+	last_blank_i = 0;
+	which_page = 0;
+
+	while (i <= strlen(mesg)) {
+                if ((i == strlen(mesg)) & (which_page == 1)) {
+			// we have finished writing text and we are on second page
+			custom_apply_attr(win, ATTR_HIGHEST);
+			mvwprintw(win, nb_row - 2,
+				 nb_col - (strlen(prev_mesg) + 2), "%s",
+				 prev_mesg);
+			custom_remove_attr(win, ATTR_HIGHEST);
+                        wmove(swin, 0, 0);
+			wnoutrefresh(win);
+                        wnoutrefresh(swin);
+                        doupdate();
+			ch = wgetch(win);
+			if ( (ch == 'P') | (ch == 'p') ) {
+				erase_window_part(win, y + 1, x + 3, nb_col - 2, nb_row - 2);
+				nlin = 1;
+				j = 0;
+				i = 0;
+				which_page = 0;
+			} else {	//erase last line and exit next-prev page mode
+				for (k = 1; k < nb_col - 2; k++)
+					mvwprintw(win, nb_row - 2, k, " ");
+				break;
+			}
+		}
+		if (nlin == text_max_row - 2) {	// we reach the last line
+			custom_apply_attr(win, ATTR_HIGHEST);
+			mvwprintw(win, nb_row - 2,
+				 nb_col - (strlen(next_mesg) + 2), "%s",
+				 next_mesg);
+			custom_remove_attr(win, ATTR_HIGHEST);
+                        wmove(swin, 0, 0);
+			wnoutrefresh(win);
+                        wnoutrefresh(swin);
+                        doupdate();
+			ch = wgetch(win);
+			if ( (ch == 'N') | (ch == 'n') ) {
+				erase_window_part(win, y + 1, x + 3, nb_col - 2, nb_row - 2);
+				nlin = 1;
+				j = 0;
+				which_page = 1;
+			} else {
+				for (k = 1; k < nb_col - 2; k++)
+					mvwprintw(win, nb_row - 2, k, " ");
+				break;
+			}
+		}
+		//write text
+		strncpy(buf, mesg + i, 1);
+		i++;
+		j++;
+		if ((strncmp(buf, "�", 1) == 0)) {	//� is the character for a new line
+			buf[0] = '\0';
+			mvwprintw(win, x + x_offset + nlin, y + y_offset + j,
+				 "%s", buf);
+			nlin++;
+			j = 0;
+		} else {
+			if (j == text_len - 1) {	// if we reach the terminal border
+				for (k = last_blank_j; k <= text_len - 1;
+				     k++)
+					mvwprintw(win, x + x_offset + nlin,
+						 y + y_offset + k, " ");
+				nlin++;
+				i = last_blank_i;
+				j = 0;
+			} else {
+				if ((strncmp(buf, " ", 1) == 0))	//space between words
+				{
+					last_blank_j = j;	//save position
+					last_blank_i = i;
+				}
+				mvwprintw(win, x + x_offset + nlin,
+					 y + y_offset + j, "%s", buf);
+			}
+		}
+        }
+        wmove(swin, 0, 0);
+        wnoutrefresh(win);
+        wnoutrefresh(swin);
+}
+
+/* Draws the status bar */
+void status_bar(int which_pan, int colr, int nc_bar, int nl_bar)
+{
+	int nb_item_cal, nb_item_oth;
+	int len_let, len_des, spc_lad;
+	int spc_bet_cal_itm, spc_bet_oth_itm;
+	int len_cal_itm, len_oth_itm;
+
+	nb_item_cal = 10;	/* max item number to display in status bar */
+	nb_item_cal = ceil(nb_item_cal / 2);	/* two lines to display items */
+	nb_item_oth = 12;
+	nb_item_oth = ceil(nb_item_oth / 2);
+	len_let = 3;
+	len_des = 8;
+	spc_lad = 1;
+
+	spc_bet_cal_itm =
+	    floor((col -
+		   nb_item_cal * (len_let + len_des +
+				  spc_lad)) / nb_item_cal);
+	spc_bet_oth_itm =
+	    floor((col -
+		   nb_item_oth * (len_let + len_des +
+				  spc_lad)) / nb_item_oth);
+	len_cal_itm = len_let + spc_lad + len_des + spc_bet_cal_itm;
+	len_oth_itm = len_let + spc_lad + len_des + spc_bet_oth_itm;
+
+	erase_window_part(swin, 0, 0, nc_bar, nl_bar);
+	if (which_pan == 0) {
+		custom_apply_attr(swin, ATTR_HIGHEST);
+		mvwprintw(swin, 0, 0, "  ?");
+		mvwprintw(swin, 1, 0, "  Q");
+		mvwprintw(swin, 0, len_cal_itm, "  R");
+		mvwprintw(swin, 1, len_cal_itm, "  S");
+		mvwprintw(swin, 0, 2 * len_cal_itm, "H/L");
+		mvwprintw(swin, 1, 2 * len_cal_itm, "J/K");
+		mvwprintw(swin, 0, 3 * len_cal_itm, "  G");
+		mvwprintw(swin, 1, 3 * len_cal_itm, "Tab");
+		mvwprintw(swin, 0, 4 * len_cal_itm, "  C");
+		custom_remove_attr(swin, ATTR_HIGHEST);
+		wnoutrefresh(swin);
+
+		mvwprintw(swin, 0, len_let + spc_lad, _("Help"));
+		mvwprintw(swin, 1, len_let + spc_lad, _("Quit"));
+		mvwprintw(swin, 0, len_cal_itm + len_let + spc_lad,
+			 _("Redraw"));
+		mvwprintw(swin, 1, len_cal_itm + len_let + spc_lad, _("Save"));
+		mvwprintw(swin, 0, 2 * len_cal_itm + len_let + spc_lad,
+			 _("-/+1 Day"));
+		mvwprintw(swin, 1, 2 * len_cal_itm + len_let + spc_lad,
+			 _("-/+1 Week"));
+		mvwprintw(swin, 0, 3 * len_cal_itm + len_let + spc_lad,
+			 _("GoTo"));
+		mvwprintw(swin, 1, 3 * len_cal_itm + len_let + spc_lad,
+			 _("Chg View"));
+		mvwprintw(swin, 0, 4 * len_cal_itm + len_let + spc_lad,
+			 _("Config"));
+	} else {
+		custom_apply_attr(swin, ATTR_HIGHEST);
+		mvwprintw(swin, 0, 0, "  ?");
+		mvwprintw(swin, 1, 0, "  Q");
+		mvwprintw(swin, 0, len_oth_itm, "  R");
+		mvwprintw(swin, 1, len_oth_itm, "  S");
+		mvwprintw(swin, 0, 2 * len_oth_itm, "J/K");
+		mvwprintw(swin, 1, 2 * len_oth_itm, "Tab");
+		mvwprintw(swin, 0, 3 * len_oth_itm, "  A");
+		mvwprintw(swin, 1, 3 * len_oth_itm, "  D");
+		mvwprintw(swin, 0, 4 * len_oth_itm, "  G");
+		mvwprintw(swin, 1, 4 * len_oth_itm, "  V");
+		mvwprintw(swin, 0, 5 * len_oth_itm, "  C");
+		custom_remove_attr(swin, ATTR_HIGHEST);
+		wnoutrefresh(swin);
+
+		mvwprintw(swin, 0, len_let + spc_lad, _("Help"));
+		mvwprintw(swin, 1, len_let + spc_lad, _("Quit"));
+		mvwprintw(swin, 0, len_oth_itm + len_let + spc_lad,
+			 _("Redraw"));
+		mvwprintw(swin, 1, len_oth_itm + len_let + spc_lad, _("Save"));
+		mvwprintw(swin, 0, 2 * len_oth_itm + len_let + spc_lad,
+			 _("Up/Down"));
+		mvwprintw(swin, 1, 2 * len_oth_itm + len_let + spc_lad,
+			 _("Chg View"));
+		mvwprintw(swin, 0, 3 * len_oth_itm + len_let + spc_lad,
+			 _("Add Item"));
+		mvwprintw(swin, 1, 3 * len_oth_itm + len_let + spc_lad,
+			 _("Del Item"));
+		mvwprintw(swin, 0, 4 * len_oth_itm + len_let + spc_lad,
+			_( "GoTo"));
+		mvwprintw(swin, 1, 4 * len_oth_itm + len_let + spc_lad,
+			 _("View"));
+		mvwprintw(swin, 0, 5 * len_oth_itm + len_let + spc_lad,
+			 _("Config"));
+	}
+	wnoutrefresh(swin);
+}
+
+long date2sec(unsigned year, unsigned month, unsigned day, unsigned hour,
+	      unsigned min)
+{
+	struct tm start, *lt;
+	time_t tstart, t;
+
+	t = time(NULL);
+	lt = localtime(&t);
+	start = *lt;
+
+	start.tm_mon = month;
+	start.tm_mday = day;
+	start.tm_year = year;
+	start.tm_hour = hour;
+	start.tm_min = min;
+	start.tm_sec = 0;
+	start.tm_isdst = -1;
+	start.tm_year -= 1900;
+	start.tm_mon--;
+	tstart = mktime(&start);
+	if (tstart == -1) {
+		fputs(_("FATAL ERROR in date2sec: failure in mktime\n"), stderr);
+		fprintf(stderr, "%u %u %u %u %u\n", year, month, day, hour, min);
+		exit(EXIT_FAILURE);
+	}
+	return tstart;
+}
+
+/* 
+ * Returns the date in seconds from year 1900.
+ * If no date is entered, current date is chosen.
+ */
+long
+get_sec_date(int year, int month, int day)
+{
+	struct tm *ptrtime;
+	time_t timer;
+	long long_date;
+	char current_day[3], current_month[3] ,current_year[5];
+
+	if (year == 0 && month == 0 && day == 0) {
+		timer = time(NULL);
+		ptrtime = localtime(&timer);
+		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);
+		
+	} 
+	long_date = date2sec(year, month, day, 0, 0);
+	return long_date;
+}
+
+long min2sec(unsigned minutes)
+{
+	return minutes * 60;
+}
+
+/* 
+ * Checks if a time has a good format. 
+ * The format could be either HH:MM or H:MM or MM, and we should have:
+ * 0 <= HH <= 24 and 0 <= MM < 999.
+ * This function returns 1 if the entered time is correct and in 
+ * [h:mm] or [hh:mm] format, and 2 if the entered time is correct and entered
+ * in [mm] format.
+ */
+int check_time(char *string)
+{
+	int ok = 0;
+	char hour[] = "  ";
+	char minutes[] = "  ";
+
+	if (			// format test [MM]
+		   ((strlen(string) == 2) || (strlen(string) == 3)) &
+		   (isdigit(string[0]) != 0) &
+		   (isdigit(string[1]) != 0) 
+	    ) {			// check if we have a valid time
+		strncpy(minutes, string, 2);
+		if ( atoi(minutes) >= 0)
+			ok = 2;
+	}
+	
+	else if (		// format test [H:MM]
+		   (strlen(string) == 4) &
+		   (isdigit(string[0]) != 0) &
+		   (isdigit(string[2]) != 0) &
+		   (isdigit(string[3]) != 0) & (string[1] == ':')
+	    ) {			// check if we have a valid time
+		strncpy(hour, string, 1);
+		strncpy(minutes, string + 2, 2);
+		if ((atoi(hour) <= 24) & (atoi(hour) >=
+					  0) & (atoi(minutes) <
+						60) & (atoi(minutes) >= 0))
+			ok = 1;
+	}
+
+	else if (		//format test [HH:MM]
+		   (strlen(string) == 5) &
+		   (isdigit(string[0]) != 0) &
+		   (isdigit(string[1]) != 0) &
+		   (isdigit(string[3]) != 0) &
+		   (isdigit(string[4]) != 0) & (string[2] == ':')
+	    ) {			// check if we have a valid time
+		strncpy(hour, string, 2);
+		strncpy(minutes, string + 3, 2);
+		if ((atoi(hour) <= 24) & (atoi(hour) >=
+					  0) & (atoi(minutes) <
+						60) & (atoi(minutes) >= 0))
+			ok = 1;
+	}
+	
+	return ok;
+}
+
+/*
+ * Display a scroll bar when there are so many items that they
+ * can not be displayed inside the corresponding panel.
+ */
+void draw_scrollbar(WINDOW *win, int y, int x, int length, 
+		int bar_top, int bar_bottom, bool hilt)
+{
+	mvwvline(win, bar_top, x, ACS_VLINE, bar_bottom - bar_top);
+	if (hilt) 
+		custom_apply_attr(win, ATTR_HIGHEST);
+	wattron(win, A_REVERSE);
+	mvwvline(win, y, x, ' ', length);
+	wattroff(win, A_REVERSE);
+	if (hilt) 
+		custom_remove_attr(win, ATTR_HIGHEST);
+}
+
+/*
+ * Print an item (either an appointment, event, or todo) in a 
+ * popup window. This is useful if an item description is too 
+ * long to fit in its corresponding panel window.
+ */
+void item_in_popup(char *saved_a_start, char *saved_a_end, char *msg, 
+		char *pop_title)
+{
+	WINDOW *popup_win;
+
+	popup_win = popup(row - 4, col - 2, 1, 1, pop_title);
+	if (strncmp(pop_title, _("Appointment"), 11) == 0) {
+		mvwprintw(popup_win, 4, 4, " - %s -> %s", 
+				saved_a_start, saved_a_end);
+	}
+	scroller(popup_win, msg, 1, 1, row - 4, col - 2);
+	wmove(swin, 0, 0);
+	doupdate();
+	wgetch(popup_win);
+	delwin(popup_win);
+}
+
+/* Show the window with a border and a label */
+void win_show(WINDOW * win, char *label)
+{
+	int startx, starty, height, width;
+
+	getbegyx(win, starty, startx);
+	getmaxyx(win, height, width);
+
+	box(win, 0, 0);
+	mvwaddch(win, 2, 0, ACS_LTEE);
+	mvwhline(win, 2, 1, ACS_HLINE, width - 2);
+	mvwaddch(win, 2, width - 1, ACS_RTEE);
+
+	print_in_middle(win, 1, 0, width, label);
+}
+
+/* 
+ * Print an item description in the corresponding panel window.
+ */
+void display_item(WINDOW *win, int incolor, char *msg, int len, 
+			int y, int x)
+{
+	char buf[len];
+
+	if (incolor == 0) 
+		custom_apply_attr(win, ATTR_HIGHEST);
+	if (strlen(msg) < len) {
+		mvwprintw(win, y, x, "%s", msg);
+	} else {
+		strncpy(buf, msg, len - 1);
+		buf[len - 1] = '\0';
+		mvwprintw(win, y, x, "%s...", buf);
+	}
+	if (incolor == 0) 
+		custom_remove_attr(win, ATTR_HIGHEST);
+}
diff --git a/src/utils.h b/src/utils.h
new file mode 100755
index 0000000..e7bdeff
--- /dev/null
+++ b/src/utils.h
@@ -0,0 +1,55 @@
+/*	$calcurse: utils.h,v 1.1 2006/07/31 21:00:03 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
+ *
+ */
+
+#ifndef CALCURSE_UTILS_H
+#define CALCURSE_UTILS_H
+
+void status_mesg(char *mesg_line1, char *mesg_line2);
+void erase_window_part(WINDOW *win, int first_col, int first_row, 
+                       int last_col, int last_row);
+WINDOW *popup(int pop_row, int pop_col,
+	      int pop_y, int pop_x, char *pop_lab);
+void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string);
+void getstring(WINDOW *win, int colr, char *string, int start_x, int start_y);
+int is_all_digit(char *string);
+void border_color(WINDOW *window, int bcolr);
+void border_nocolor(WINDOW *window);
+void scroller(WINDOW *win, char *, int x, int y, int nb_row, int nb_col);
+void status_bar(int which_pan, int colr, int nc_bar, int nl_bar);
+long date2sec(unsigned year, unsigned month, unsigned day, unsigned hour,
+	      unsigned min);
+long get_sec_date(int year, int month, int day);
+long min2sec(unsigned minutes);
+int check_time(char *string);
+void draw_scrollbar(WINDOW *win, int y, int x, int length, 
+		int bar_top, int bar_bottom, bool hilt);
+void item_in_popup(char *saved_a_start, char *saved_a_end, char *msg, 
+		char *pop_title);
+void win_show(WINDOW * win, char *label);
+void display_item(WINDOW *win, int incolor, char *msg, 
+		int len, int y, int x);
+
+#endif /* CALCURSE_UTILS_H */
diff --git a/src/vars.c b/src/vars.c
new file mode 100755
index 0000000..524d944
--- /dev/null
+++ b/src/vars.c
@@ -0,0 +1,85 @@
+/*	$calcurse: vars.c,v 1.1 2006/07/31 21:00:03 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
+ *
+ */
+
+#include "i18n.h"
+#include "vars.h"
+
+/*
+ * variables to store window size
+ */
+int col = 0, row = 0;
+
+/* variable to tell if the terminal supports color */
+bool colorize = false;
+
+/*
+ * variables to store calendar names
+ */
+int days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+char *monthnames[12] =
+    { N_("January"), 
+      N_("February"), 
+      N_("March"), 
+      N_("April"), 
+      N_("May"), 
+      N_("June"),
+      N_("July"), 
+      N_("August"), 
+      N_("September"), 
+      N_("October"), 
+      N_("November"), 
+      N_("December") };
+
+char *daynames[8] =
+    { N_("Sun"), 
+      N_("Mon"), 
+      N_("Tue"), 
+      N_("Wed"), 
+      N_("Thu"), 
+      N_("Fri"), 
+      N_("Sat"), 
+      N_("Sun") };
+
+/* 
+ * variables to store data path names, which are initialized in
+ * io_init() 
+ */
+char path_dir[] = "";
+char path_todo[] = "";
+char path_apts[] = "";
+char path_conf[] = "";
+
+/* 
+ * Variables to handle calcurse windows: 
+ * cwin = calendar window
+ * awin = appointment window
+ * twin = todo window
+ * swin = status bar window
+ */
+WINDOW *awin = NULL, *cwin = NULL, *twin = NULL, *swin = NULL;
+
+/* Variable to handle pads. */
+struct pad_s *apad;
diff --git a/src/vars.h b/src/vars.h
new file mode 100755
index 0000000..d9bb13e
--- /dev/null
+++ b/src/vars.h
@@ -0,0 +1,69 @@
+/*	$calcurse: vars.h,v 1.1 2006/07/31 21:00:03 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
+ *
+ */
+
+#ifndef CALCURSE_VARS_H
+#define CALCURSE_VARS_H
+
+#include <ncurses.h> 
+#include <stdbool.h>
+
+#define DIR_NAME	".calcurse"
+#define TODO_PATH 	".calcurse/todo"
+#define APTS_PATH	".calcurse/apts"
+#define CONF_PATH	".calcurse/conf"
+
+#define MAX_LENGTH	512
+
+#define CTRL(x)         ((x) & 0x1f)
+
+#define ATTR_FALSE	0
+#define ATTR_TRUE	1
+#define ATTR_LOWEST	2
+#define ATTR_LOW	3
+#define ATTR_MIDDLE	4
+#define ATTR_HIGH	5
+#define ATTR_HIGHEST	6
+
+struct pad_s {
+	int width;
+	int length;
+	int first_onscreen;	/* first line to be displayed inside window */
+	WINDOW *ptrwin;		/* pointer to the pad window */
+};
+
+extern int col, row;
+extern bool colorize;
+extern int days[12];
+extern char *monthnames[12];
+extern char *daynames[8];
+extern char path_dir[MAX_LENGTH];
+extern char path_todo[MAX_LENGTH];
+extern char path_apts[MAX_LENGTH];
+extern char path_conf[MAX_LENGTH];
+extern WINDOW *awin, *cwin, *twin, *swin;
+extern struct pad_s *apad;
+
+#endif /* CALCURSE_VARS_H */
-- 
cgit v1.2.3-70-g09d2