235 lines
6.5 KiB
C
Executable File
235 lines
6.5 KiB
C
Executable File
/* $calcurse: calendar.c,v 1.7 2007/03/10 15:54:59 culot Exp $ */
|
|
|
|
/*
|
|
* Calcurse - text-based organizer
|
|
* Copyright (c) 2004-2007 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 day, int month, int year, int *sel_day, int *sel_month,
|
|
int *sel_year)
|
|
{
|
|
#define LDAY 11
|
|
char selected_day[LDAY] = "";
|
|
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");
|
|
|
|
while (wrong_day) {
|
|
status_mesg(request_date, "");
|
|
if (getstring(swin, selected_day, LDAY, 0, 1) == GETSTRING_ESC)
|
|
return;
|
|
else {
|
|
if (strlen(selected_day) == 0) {
|
|
// go to today
|
|
wrong_day = 0;
|
|
*sel_day = day;
|
|
*sel_month = month;
|
|
*sel_year = year;
|
|
} else if (strlen(selected_day) != LDAY - 1) {
|
|
wrong_day = 1;
|
|
} else {
|
|
sscanf(selected_day, "%u/%u/%u",
|
|
&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))
|
|
wrong_day = 1;
|
|
//go to chosen day
|
|
if (wrong_day != 1) {
|
|
*sel_day = dday;
|
|
*sel_month = dmonth;
|
|
*sel_year = dyear;
|
|
}
|
|
}
|
|
if (wrong_day) {
|
|
status_mesg(mesg_line1, mesg_line2);
|
|
wgetch(swin);
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|