From a18b0259336d716ecc0e5bced1817220eae6bdef Mon Sep 17 00:00:00 2001
From: Frederic Culot <calcurse@culot.org>
Date: Sun, 1 Jul 2007 17:48:50 +0000
Subject: calendar_date_thread implemented to check for day changes (thanks
 Jupp for reporting the problem) code cleanup in goto_day() and
 update_cal_panel() static variables today and slctd_day added
 calendar_store_current_date(), calendar_get_slctd_day(),
 calendar_get_slctd_day_sec(), calendar_init_slctd_day() created
 calendar_move_up(), calendar_move_down(), calendar_move_left() and
 calendar_move_right() created calendar_set_first_day_of_week(),
 calendar_change_first_day_of_week() and calendar_week_begins_on_monday()
 created

---
 src/calendar.c | 404 +++++++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 306 insertions(+), 98 deletions(-)

(limited to 'src')

diff --git a/src/calendar.c b/src/calendar.c
index 5d127bd..3869e68 100755
--- a/src/calendar.c
+++ b/src/calendar.c
@@ -1,4 +1,4 @@
-/*	$calcurse: calendar.c,v 1.7 2007/03/10 15:54:59 culot Exp $	*/
+/*	$calcurse: calendar.c,v 1.8 2007/07/01 17:48:50 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -25,9 +25,12 @@
  */
 
 #include <ncurses.h>
+#include <pthread.h>
+#include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
+#include <stdbool.h>
 #include <time.h>
 
 #include "i18n.h"
@@ -39,16 +42,165 @@
 #include "vars.h"
 #include "utils.h"
 
-static unsigned months_to_days(unsigned);
-static long years_to_days(unsigned);
+static date_t		today, slctd_day;
+static bool		week_begins_on_monday;
+static pthread_mutex_t 	date_thread_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_t 	calendar_t_date;
 
-  /* Load the calendar */
+
+/* Thread needed to update current date in calendar. */
+static void *
+calendar_date_thread(void *arg)
+{
+	time_t now, tomorrow;
+
+	for (;;) {
+		tomorrow = (time_t)(get_today() + DAYINSEC);
+
+		while ((now = time(NULL)) < tomorrow) {
+			sleep(tomorrow - now);
+		}
+
+		calendar_set_current_date();
+		calendar_update_panel(cwin);
+	}
+
+	pthread_exit((void*) 0);
+}
+
+/* Launch the calendar date thread. */
+void 
+calendar_start_date_thread(void) 
+{
+	pthread_create(&calendar_t_date, NULL, calendar_date_thread, NULL);
+	return;
+}
+
+/* Stop the calendar date thread. */
+void 
+calendar_stop_date_thread(void)
+{
+	pthread_cancel(calendar_t_date);
+	return;
+}
+
+/* Set static variable today to current date */
+void 
+calendar_set_current_date(void)
+{
+	time_t	  timer;
+	struct tm *tm;
+
+	timer = time(NULL);
+	tm = localtime(&timer);
+
+	pthread_mutex_lock(&date_thread_mutex);
+	today.dd = tm->tm_mday;
+	today.mm = tm->tm_mon + 1;
+	today.yyyy = tm->tm_year + 1900;
+	pthread_mutex_unlock(&date_thread_mutex);
+}
+
+/* Needed to display sunday or monday as the first day of week in calendar. */
+void
+calendar_set_first_day_of_week(wday_t first_day)
+{
+	switch (first_day) {
+	case SUNDAY:
+		week_begins_on_monday = false;
+		break;
+	case MONDAY:
+		week_begins_on_monday = true;
+		break;
+	default:
+		fputs(_("ERROR in calendar_set_first_day_of_week\n"), stderr);
+		week_begins_on_monday = false; 
+		/* NOTREACHED */
+	}
+}
+
+/* Swap first day of week in calendar. */
+void
+calendar_change_first_day_of_week(void)
+{
+	week_begins_on_monday = !week_begins_on_monday;
+}
+
+/* Return true if week begins on monday, false otherwise. */
+bool
+calendar_week_begins_on_monday(void)
+{
+	return (week_begins_on_monday);
+}
+
+/* Fill in the given variable with the current date. */
+void
+calendar_store_current_date(date_t *date)
+{
+	pthread_mutex_lock(&date_thread_mutex);
+	*date = today;
+	pthread_mutex_unlock(&date_thread_mutex);
+}
+
+/* This is to start at the current date in calendar. */
+void
+calendar_init_slctd_day(void)
+{
+	calendar_store_current_date(&slctd_day);
+}
+
+/* Return the selected day in calendar */
+date_t *
+calendar_get_slctd_day(void)
+{
+	return (&slctd_day);
+}
+
+/* Returned value represents the selected day in calendar (in seconds) */
+long
+calendar_get_slctd_day_sec(void)
+{
+	return (date2sec(slctd_day, 0, 0));
+}
+
+static int 
+isBissextile(unsigned year)
+{
+	return (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0));
+}
+
+static unsigned 
+months_to_days(unsigned month)
+{
+	return ((month * 3057 - 3007) / 100);
+}
+
+
+static long 
+years_to_days(unsigned year)
+{
+	return (year * 365L + year / 4 - year / 100 + year / 400);
+}
+
+static long 
+ymd_to_scalar(unsigned year, unsigned month, unsigned day)
+{
+	long scalar;
+
+	scalar = day + months_to_days(month);
+	if (month > 2)
+		scalar -= isBissextile(year) ? 1 : 2;
+	year--;
+	scalar += years_to_days(year);
+
+	return (scalar);
+}
+
+/* Function used to display the calendar panel. */
 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)
+calendar_update_panel(WINDOW *cwin)
 {
+	date_t current_day, check_day;
 	int c_day, c_day_1, day_1_sav, numdays, j;
 	unsigned yr, mo;
 	int ofs_x, ofs_y;
@@ -56,142 +208,128 @@ update_cal_panel(WINDOW *cwin, int nl_cal,
 	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;
+	/* inits */
+	calendar_store_current_date(&current_day);
+	erase_window_part(cwin, 1, title_lines, CALWIDTH - 2, CALHEIGHT - 2);
+	mo = slctd_day.mm;
+	yr = slctd_day.yyyy;
+        if (!calendar_week_begins_on_monday()) 
+		sunday_first = 1;
 	
-	// Offset for centering calendar in window
-	ofs_y = 2 + (nl_cal - 9) / 2;
-	ofs_x = (nc_cal - 27) / 2;
-
+	/* offset for centering calendar in window */
+	ofs_y = 2 + (CALHEIGHT - 9) / 2;
+	ofs_x = (CALWIDTH - 27) / 2;
 
-	//checking the number of days in february
+	/* 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);
+	/*
+	 * the first calendar day will be monday or sunday, depending on
+         * 'week_begins_on_monday' value
+	 */
+	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
+	/* 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);
+	    (CALWIDTH - (strlen(_(monthnames[mo - 1])) + 5)) / 2,
+	    "%s %d", _(monthnames[mo - 1]), slctd_day.yyyy);
 	custom_remove_attr(cwin, ATTR_HIGH);
 	++ofs_y;
 
-	//prints the days, with regards to the first day of the week
+	/* print 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]));
+		    _(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);
+		check_day.dd = c_day;
+		check_day.mm = slctd_day.mm;
+		check_day.yyyy = slctd_day.yyyy;
+
+		/* check if the day contains an event or an appointment */
+		item_this_day = 
+		    day_check_if_item(check_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)
-		{
+		if (c_day == current_day.dd && current_day.mm == slctd_day.mm 
+    		    && current_day.yyyy == slctd_day.yyyy && 
+		    current_day.dd != slctd_day.dd) {
+
 			custom_apply_attr(cwin, ATTR_LOWEST);
 			mvwprintw(cwin, ofs_y + 1,
-				 ofs_x + day_1_sav + 4 * c_day + 1, "%2d",
-				 c_day);
+			    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) ))	
+
+		} else if (c_day == slctd_day.dd && 
+		    ( (current_day.dd != slctd_day.dd) || 
+		      (current_day.mm != slctd_day.mm) 
+		      || (current_day.yyyy != slctd_day.yyyy))) {
+
 			/* 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);
+		   	    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
-		{
+
+		} else if (c_day == slctd_day.dd && 
+		    current_day.dd == slctd_day.dd && 
+		    current_day.mm == slctd_day.mm && 
+		    current_day.yyyy == slctd_day.yyyy) {
+			
+			/* 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);
+		   	    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);
+		   	    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
+		} else		
+			/* otherwise, print normal days in black */
 			mvwprintw(cwin, ofs_y + 1,
-				 ofs_x + day_1_sav + 4 * c_day + 1, "%2d",
-				 c_day);
+			    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.
+ * today is the current day given to that routine, and slctd_day is updated 
+ * with the newly selected date.
  */
 void
-goto_day(int day, int month, int year, int *sel_day, int *sel_month, 
-    int *sel_year)
+calendar_change_day(void)
 {
 #define LDAY 11
 	char selected_day[LDAY] = "";
+	date_t today;
 	int dday, dmonth, dyear;
 	int wrong_day = 1;
 	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] : mm/dd/yyyy");
+	char *request_date = 
+	    _("Enter the day to go to [ENTER for today] : mm/dd/yyyy");
 
 	while (wrong_day) {
 		status_mesg(request_date, "");
@@ -199,36 +337,106 @@ goto_day(int day, int month, int year, int *sel_day, int *sel_month,
 			return;
 		else {
 			if (strlen(selected_day) == 0) {
-			// go to today
+				calendar_store_current_date(&today);
+
+				/* go to today */
 				wrong_day = 0;
-				*sel_day = day;
-				*sel_month = month;
-				*sel_year = year;
+				slctd_day.dd = today.dd;
+				slctd_day.mm = today.mm;
+				slctd_day.yyyy = today.yyyy;
+
 			} else if (strlen(selected_day) != LDAY - 1) {
+
 				wrong_day = 1;	
+
 			} else {
+
 				sscanf(selected_day, "%u/%u/%u", 
-					&dmonth, &dday, &dyear);
+			    	    &dmonth, &dday, &dyear);
 				wrong_day = 0;
-				//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))
+
+				/* basic check on entered date */
+				if ((dday <= 0) || (dday >= 32) || 
+				    (dmonth <= 0) || (dmonth >= 13) || 
+				    (dyear <= 0) || (dyear >= 3000))
 					wrong_day = 1;
-				//go to chosen day
+
+				/* go to chosen day */
 				if (wrong_day != 1) {
-					*sel_day = dday;
-					*sel_month = dmonth;
-					*sel_year = dyear;
+					slctd_day.dd = dday;
+					slctd_day.mm = dmonth;
+					slctd_day.yyyy = dyear;
 				} 
 			}
+
 			if (wrong_day) {
 				status_mesg(mesg_line1, mesg_line2);
 				wgetch(swin);
 			}
 		}
 	}
+
 	return;
 }
+
+/* Move to next day, next month or next year in calendar. */
+void
+calendar_move_right(void)
+{
+	if ((slctd_day.dd == 31) && (slctd_day.mm == 12)) {
+		slctd_day.dd = 0;
+		slctd_day.mm = 1;
+		slctd_day.yyyy++; 
+	} else if (slctd_day.dd == days[slctd_day.mm - 1]) { 
+		slctd_day.mm++;
+		slctd_day.dd = 1;
+	} else
+		slctd_day.dd++;
+}
+
+/* Move to previous day, previous month or previous year in calendar. */
+void
+calendar_move_left(void)
+{
+	if ((slctd_day.dd == 1) && (slctd_day.mm == 1)) { 
+		slctd_day.dd = 32;
+		slctd_day.mm = 12;
+		slctd_day.yyyy--;
+	} else if (slctd_day.dd == 1) { 
+		slctd_day.dd = days[slctd_day.mm - 2];
+		slctd_day.mm--;
+	} else
+		slctd_day.dd--;
+}
+
+/* Move to previous week, previous month or previous year in calendar. */
+void
+calendar_move_up(void)
+{
+	if ((slctd_day.dd <= 7) && (slctd_day.mm == 1)) { 
+		slctd_day.dd = 31 - (7 - slctd_day.dd);
+		slctd_day.mm = 12;
+		slctd_day.yyyy--;
+	} else if (slctd_day.dd <= 7) { 
+		slctd_day.dd = days[slctd_day.mm - 2] -
+		    (7 - slctd_day.dd);
+		slctd_day.mm--;
+	} else 
+		slctd_day.dd -= 7;
+}
+
+/* Move to next week, next month or next year in calendar. */
+void
+calendar_move_down(void)
+{
+	if ((slctd_day.dd > days[slctd_day.mm - 1] - 7)
+	    && (slctd_day.mm == 12)) { 
+		slctd_day.dd = (7 - (31 - slctd_day.dd));
+		slctd_day.mm = 1;
+		slctd_day.yyyy++;
+	} else if (slctd_day.dd > days[slctd_day.mm - 1] - 7) { 
+		slctd_day.dd = (7 - (days[slctd_day.mm - 1] - slctd_day.dd));
+		slctd_day.mm++;
+	} else 
+		slctd_day.dd += 7;
+}
-- 
cgit v1.2.3-70-g09d2