aboutsummaryrefslogblamecommitdiffstats
path: root/src/calendar.c
blob: 7cc71edbd34171150af393c5b0e2cdfd06f8175f (plain) (tree)
1
                                                                          


































































































































































































                                                                                                                                           
                                                                                      




























                                                                        
/*	$calcurse: calendar.c,v 1.2 2006/10/28 10:33:15 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, "");
		if (getstring(swin, colr, selected_day, 0, 1) == 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;
}