[comp.sources.sun] v01i012: Calendar/planning tool: Part 03/09

mcgrew@dartagnan.rutgers.edu (Charles Mcgrew) (05/28/89)

Submitted-by: Bill Randle <billr@saab.cna.tek.com>
Posting-number: Volume 1, Issue 12
Archive-name: calentool/part03

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	datelib.c
#	day.cursor
#	event.c
#	event.h
# This archive created: Sat May 27 13:11:31 1989
export PATH; PATH=/bin:$PATH
echo shar: extracting "'datelib.c'" '(44349 characters)'
if test -f 'datelib.c'
then
	echo shar: will not over-write existing file "'datelib.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'datelib.c'
	X/*
	X * $Header: datelib.c,v 2.1 89/05/09 14:18:52 billr Exp $
	X *
	X * datelib.c - Calendar (date) computation library
	X *
	X * R. P. C. Rodgers, UCSF, November 1988
	X * (with thanks to Greg Couch, Conrad Huang, and Dave Yee for their helpful
	X *  suggestions)
	X *
	X *        Copyright 1988, 1989 R. P. C. Rodgers,  All Rights Reserved
	X * Permission is granted by the author for use of this code under the following
	X * conditions: 1) improvements and corrections to this code are shared with the
	X * author; 2) the code is made freely available to anyone requesting it; 3) the
	X * code is not used for any profit-making venture without the express
	X * permission of the author; and, 3) all copies of the code will preserve the
	X * above authorship and copyright information and this notice.
	X *
	X * (requires math library)
	X * 
	X * Source of formulae:
	X * 
	X * 1) Schocken, Wolfgang Alexander
	X *    The calculated confusion of calendars; puzzles in Christian, Jewish and
	X *       Moslem calendars.
	X *    1st Ed.
	X *    Vantage Press
	X *    New York
	X *    1976
	X * 
	X * 2) Meeus, Jean
	X *    Astronomical Formulae for Calculators
	X *    Monografieen over Astronomie en Astrofysica
	X *    Volkssterrenwacht Urania V.Z.W.
	X *    Mattheessensstraat 62, B 2540 Hove, Belgium
	X *    Vereniging voor Sterrenkunde V.Z.W.
	X *    Ringlaan 3, B 1180 Brussel, Belgium
	X *    Vol. 4
	X *    Derde Druk
	X *    October 1980
	X *    (3rd edition of 1985 available from Willmann-Bell, address below)
	X *    (formulae for Easter, Julian and Gregorian date formation, and
	X *     solstices/equinoxes)
	X * 
	X * 3) Assorted contributions to the Hewlett-Packard HP-41C Software Library
	X * 
	X * In his 1987 Sun program "moontool," John Walker (Autodesk, Sausalito, CA)
	X * mentions several other potentially useful references:
	X * 
	X * 4) Pierre Bretagnon and Jean-Louis Simon
	X *    Planetary Programs and Tables from -4000 to +2800
	X *    Willmann-Bell
	X *    1986
	X *    (for utmost accuracy in planetary computations)
	X * 
	X * 5) Eric Burgess
	X *    Celestial BASIC
	X *    Revised Edition
	X *    Sybex
	X *    1985
	X *    (cookbook oriented, many algorithms hard to dig out of turgid BASIC)
	X * 
	X * Many of these references can be obtained from Willmann-Bell, P.O. Box
	X * 35025, Richmond, VA 23235, USA.  Phone: (804) 320-7016.  In addition
	X * to their own publications, they stock most of the standard references
	X * for mathematical and positional astronomy.
	X * 
	X * NOTES:
	X * check ranges on days (0-365)
	X * islamic new year and jewish dates not thoroughly tested
	X * 
	X */
	X
	X#include "ct.h"		/* for the NO_HOLIDAYS #define */
	X
	X#include	<stdio.h>	/* for NULL */
	X#include	<math.h>
	X
	Xdouble	julian_day();
	X
	X#ifndef NO_HOLIDAYS
	Xextern	char	*malloc();
	Xdouble  easter_offset(), passover_offset();
	X
	Xstatic char	*monthname[] = { 
	X		"January", "February", "March", "April", "May",
	X		"June", "July", "August", "September",
	X		"October", "November", "December"	};
	Xstatic char	*dayname[] = { 
	X		"Sunday", "Monday", "Tuesday", "Wednesday",
	X		"Thursday", "Friday", "Saturday"	};
	Xstatic char	timebuf[16];
	X
	X/*
	X * date_string:
	X * Return date string of form: "Monday 12 December 1988"
	X * given day of week (0-6), day (1-31), month (1-12), year
	X */
	Xchar *
	Xdate_string(day_of_week, day, month, year)
	X	double	day;
	X	int	day_of_week, month, year;
	X{
	X	char *date;
	X
	X	date = (char *) malloc(81 * sizeof(char));
	X	if (date == NULL)
	X		err_rpt("out of memory", FATAL);
	X	(void) sprintf(date, "%s %d %s %d",
	X		dayname[day_of_week], (int) day, monthname[--month], year);
	X	return date;
	X}
	X
	X/*
	X * date_string_2:
	X * Return date string of form: "Monday 12 December 1988 (NYEAR)"
	X * given day of week (0-6), day (1-31), month (1-12), year, and alternate
	X * (that is, non-Gregorian) year, NYEAR
	X */
	Xchar *
	Xdate_string_2(day_of_week, day, month, year, nyear)
	X	double	day;
	X	int	day_of_week, month, nyear, year;
	X{
	X	char *date;
	X
	X	date = (char *) malloc(81 * sizeof(char));
	X	if (date == NULL)
	X		err_rpt("out of memory", FATAL);
	X	(void) sprintf(date, "%s %d %s %d (%d)",
	X		dayname[day_of_week], (int) day, monthname[--month],
	X			year, nyear);
	X	return date;
	X}
	X
	X/*
	X * date_time_string:
	X * Return date/time string of form: "10:42 Monday 12 December 1988"
	X * given hour (0-24), minute (0-59), day of week (0-6), day (1-31),
	X * month (1-12), year
	X */
	Xchar *
	Xdate_time_string(hour, min, day_of_week, day, month, year)
	X	double	day;
	X	int	day_of_week, hour, min, month, year;
	X{
	X	char *date;
	X
	X	date = (char *) malloc(81 * sizeof(char));
	X	if (date == NULL)
	X		err_rpt("out of memory", FATAL);
	X	(void) sprintf(date, "%02d:%02d %s %d %s %d",
	X		hour, min, dayname[day_of_week], (int) day,
	X		monthname[--month], year);
	X	return date;
	X}
	X
	X/*
	X * election_day:
	X * Compute date of Election Day given year (1584-9999)
	X * Election day is defined as the first Tuesday following the first
	X * Monday in November.
	X */
	Xdouble
	Xelection_day(year)
	X	int	year;
	X{
	X	double day, nth_mday_of_month();
	X
	X	/* find first Tuesday in Nov. */
	X	day = nth_mday_of_month(1, 2, 11, year);
	X	/* if it's the first day of the month then Election day is next week */
	X	if (day == 1.)
	X		day = 8.;
	X	return julian_day(day, 11, year);
	X}
	X
	X/*
	X * dday2:
	X * Compute dday2 for various holiday routines given x value, year (>1583)
	X */
	Xdday2(x, year)
	X	int	x, year;
	X{
	X	int	atmp, btmp;
	X
	X	atmp = 1.25 * year;
	X	btmp = year / 100;
	X	btmp = 0.75 * (1 + btmp);
	X	return (x + atmp - btmp) % 7;
	X}
	X#endif	/* NO_HOLIDAYS */
	X
	X/*
	X * days_remaining_in_year:
	X * Compute remaining days of year (0-366)
	X * given day (1-31), month (1-12), year (1901-2009)
	X */
	Xdays_remaining_in_year(day, month, year)
	X	double	day;
	X	int	month, year;
	X{
	X	int	length_of_year(), day_of_year();
	X
	X	return length_of_year(year) - day_of_year(day, month, year);
	X}
	X
	X/*
	X * length_of_year:
	X * Compute days in year (0-366)
	X * given year (1901-2009)
	X */
	Xlength_of_year(year)
	X	int	year;
	X{
	X	int	ylength;
	X
	X	if ((year % 400) == 0)
	X		ylength = 366;
	X	else if ((year % 100) == 0)
	X		ylength = 365;
	X	else if ((year % 4) == 0)
	X		ylength = 366;
	X	else
	X		ylength = 365;
	X	return ylength;
	X}
	X
	X/*
	X * get_day_of_week:
	X * Compute day of week (0-6 for Sunday-Saturday)
	X * given day (1-31), month (1-12), year (1901-2009)
	X */
	Xget_day_of_week(day, month, year)
	X	double	day;
	X	int	month, year;
	X{
	X	int	atmp;
	X
	X	atmp = julian_day(day, month, year) + 1.5;
	X	return atmp % 7;
	X}
	X
	X/*
	X * day_ of_year:
	X * Compute day of year (0-366)
	X * given day (1-31), month (1-12), year (1901-2009)
	X */
	Xday_of_year(day, month, year)
	X	double	day;
	X	int	month, year;
	X{
	X	return (int) julian_day(day, month, year)
	X		- (int) julian_day(0.0, 1, year);
	X}
	X
	X/*
	X * julian_day:
	X * Compute Julian day (>=1)
	X * given day (1-31), month (1-12), year (1901-2009)
	X *
	X * Notes: The Gregorian reform is taken into account (that is, the day
	X * following 4 October 1582 is 15 October 1582; dates on this latter day or
	X * later are said to be in the Gregorian calendar).  B.C. years are counted
	X * astronomically (the year prior to year 1 is year 0).  The Julian day
	X * begins at GMT noon (the day is expressed in floating point).
	X * Example: to obtain Julian day for 4 Jul 1979: julian_day(4.0, 7, 1979)
	X */
	Xdouble
	Xjulian_day(day, month, year)
	X	double	day;
	X	int	month, year;
	X{
	X	int	atmp, btmp, monthp, yearp;
	X	double	ctmp;
	X
	X	if (month > 2) {
	X		monthp = month + 1;
	X		yearp = year;
	X	}
	X	else {
	X		monthp = month + 13;
	X		yearp = year - 1;
	X	}
	X	if ((year > 1582) || (year == 1582 && month >= 10)
	X		|| (year == 1582 && month ==10 && day >= 15)) {
	X		atmp = year / 100;
	X		btmp = 2 - atmp + (atmp / 4);
	X	}
	X	else
	X		btmp = 0;
	X	atmp = 365.25 * yearp;
	X	ctmp = atmp;
	X	atmp = 30.6001 * monthp;
	X	ctmp =  ctmp + atmp;
	X	return ctmp + day + 1720994.5 + btmp;
	X}
	X
	X#ifndef NO_HOLIDAYS
	X/*
	X * corrected_julian_day:
	X * Correct Julian day (>=1) for conversion from JULIAN CALENDAR
	X * to GREGORIAN CALENDAR.
	X */
	Xdouble
	Xcorrected_julian_day(jday)
	X	double	jday;
	X{
	X	double	day;
	X	int	atmp, btmp, month, year;
	X
	X	gregorian_date(&day, &month, &year, jday);
	X	atmp = year / 100;
	X	btmp = ((3 * atmp) - 5) / 4;
	X	return julian_day(day, month, year) + btmp;
	X}
	X
	X/*
	X * gregorian_date:
	X * Return pointers to day (1-31), month (1-12), year (1901-2009),
	X * given Julian day (>=0)
	X *
	X * Notes: The Gregorian reform is taken into account (that is, the day
	X * following 4 October 1582 is 15 October 1582; dates on this latter day or
	X * later are said to be in the Gregorian calendar).  B.C. years are counted
	X * astronomically (the year prior to year 1 is year 0).  The Julian day
	X * begins at GMT noon.  The Julian day can be expressed in
	X * floating point below to get a day result with decimal places.  This method
	X * is valid only for positive Julian day numbers.
	X */
	Xgregorian_date(p_day, p_month, p_year, jday)
	X	int	*p_month, *p_year;
	X	double	*p_day, jday;
	X{
	X	int	atmp, btmp, ctmp, dtmp, etmp, gtmp, ztmp;
	X	double	ftmp;
	X
	X	ztmp = jday + 0.5;
	X	ftmp = (jday + 0.5) - ztmp;
	X	if (ztmp >= 2299161) {
	X		gtmp = (ztmp - 1867216.25) / 36524.25;
	X		ctmp = gtmp / 4;
	X		atmp = ztmp + 1 + gtmp - ctmp;
	X	}
	X	else
	X		atmp = ztmp;
	X	btmp = atmp + 1524;
	X	ctmp = (btmp - 122.1) / 365.25;
	X	dtmp = 365.25 * ctmp;
	X	etmp = ((btmp - dtmp) / 30.6001);
	X	ztmp = 30.6001 * etmp;
	X	*p_day = btmp - dtmp - ztmp + ftmp;
	X	if (etmp > 13.5)
	X		*p_month = etmp - 13;
	X	else
	X		*p_month = etmp - 1;
	X	if (*p_month > 2.5)
	X		*p_year = ctmp - 4716;
	X	else
	X		*p_year = ctmp - 4715;
	X}
	X
	X/*
	X * mdays_between_dates:
	X * Compute number of mdays between two dates (exclusive: don't count the
	X * days themselves) given day of week (0-6, O for Sunday),
	X * two sets of day (1-31), month (1-12), year (1583-9999)
	X */
	Xmdays_between_dates(day_of_week, day1, month1, year1, day2, month2, year2)
	X	int	day_of_week, month1, year1, month2, year2;
	X	double	day1, day2;
	X{
	X	return wday(day_of_week, day2, month2, year2)
	X		- wday(day_of_week, day1, month1, year1);
	X}
	X
	X/*
	X * nth_mday_of_month:
	X * Compute nth m-day of the month (1-31)
	X * given n (1-5), day of week (0-6, 0 for Sunday), month (1-12),
	X * year (1583-9999)
	X */
	Xdouble
	Xnth_mday_of_month(n, day_of_week, month, year)
	X	int	day_of_week, month, n, year;
	X{
	X	int	atmp, btmp, ctmp, dtmp, etmp, ftmp, tmonth, tyear;
	X
	X	if (month > 2) {
	X		tmonth = month + 1;
	X		tyear = year;
	X	}
	X	else {
	X		tmonth = month + 13;
	X		tyear = year - 1;
	X	}
	X	atmp = 2.6 * tmonth;
	X	btmp = 1.25 * tyear;
	X	ctmp = (tyear / 100) - 7;
	X	dtmp = 0.75 * ctmp;
	X	etmp = (day_of_week - atmp - btmp + dtmp) % 7;
	X	if (etmp == 0)
	X		ftmp = 7;
	X	else
	X		ftmp = etmp;
	X	return (double) (ftmp + (n * 7));
	X}
	X
	X/*
	X * years_date_is_mday:
	X * Compute year(s) for which a given date is an m-day
	X * given starting year, ending year,
	X * day of week (0-6, 0 for Sunday), day, and month
	X * algorithm said to be valid for 1 Mar 1900 to 28 Feb 2100.
	X */
	Xyears_date_is_mday(day_of_week, day, month, start_year, end_year, yearlist,
	X	number_of_years)
	X	int	day_of_week, end_year, month, *number_of_years, yearlist[],
	X		start_year;
	X	double	day;
	X{
	X	int		diff, index, year, tdow;
	X	static int	augment[] = {6, 11, 6, 5}; 
	X
	X	*number_of_years = 0;
	X	if (start_year > end_year) return -1;
	X	for (year = start_year; year <= end_year; year++ ) {
	X		tdow = get_day_of_week(day, month, year);
	X		if (tdow == day_of_week) {
	X			yearlist[(*number_of_years)++] = year;
	X		}
	X		if (*number_of_years == 2 || *number_of_years == 3) {
	X			diff = yearlist[*number_of_years]
	X				- yearlist[*number_of_years - 1];
	X			if (diff == 5) {
	X				year++;
	X				index = 0;
	X				break;
	X			}
	X			else if (diff == 11) {
	X				year++;
	X				index = 2;
	X				break;
	X			}
	X		}
	X	}
	X	for ( ; year <= end_year; year++ ) {
	X		yearlist[(*number_of_years + 1)] =
	X			yearlist[*number_of_years] + augment[index++ % 4];
	X		(*number_of_years)++;
	X	}
	X	return 0;
	X}
	X
	X/*
	X * weekdays_between_dates:
	X * Compute weekdays between any two dates
	X * given two sets of day (1-31), month (1-12), year (1901-2009)
	X */
	Xweekdays_between_dates(day1, month1, year1, day2, month2, year2)
	X	int	month1, month2, year1, year2;
	X	double	day1, day2;
	X{
	X	return wday2(day2, month2, year2) - wday2(day1, month1, year1);
	X}
	X
	X/*
	X * wday:
	X * Compute wday for mdays_between_dates routine
	X * given day of week, day, month, year
	X */
	Xwday(day_of_week, day, month, year)
	X	int	day_of_week, month, year;
	X	double	day;
	X{
	X	int	atmp, btmp, ctmp, dtmp;
	X
	X	atmp = dday(day, month, year) - day_of_week;
	X	btmp = atmp / 7;
	X	ctmp = atmp % 7;
	X	dtmp = 0.11 * ctmp + 0.9;
	X	return btmp + (0.5 * dtmp);
	X}
	X
	X/*
	X * wday2:
	X * Compute wday2 for weekdays_between_dates routine
	X * given day, month, year
	X */
	Xwday2(day, month, year)
	X	int	month, year;
	X	double	day;
	X{
	X	int	atmp, btmp, ctmp, dtmp;
	X
	X	atmp = dday(day, month, year);
	X	btmp = atmp / 7;
	X	ctmp = atmp % 7;
	X	dtmp = 1.801 * ctmp;
	X	return (5 * btmp) + (0.5 * dtmp);
	X}
	X
	X/*
	X * dday:
	X * Compute dday for other routines
	X * given day (1-31), month (1-12), year (1901-2009)
	X */
	Xdday(day, month, year)
	X	int	month, year;
	X	double	day;
	X{
	X	int	atmp, btmp, ctmp, dtmp, tmonth, tyear;
	X
	X	if (month > 2) {
	X		tmonth = month + 1;
	X		tyear = year;
	X	}
	X	else {
	X		tmonth = month + 13;
	X		tyear = year - 1;
	X	}
	X	atmp = tyear / 100;
	X	btmp = 0.75 * (atmp - 7);
	X	ctmp = 365.25 * tyear;
	X	dtmp = 30.6001 * tmonth;
	X	return (int) day - btmp + ctmp + dtmp;
	X}
	X
	X/*
	X * vernal_equinox:
	X * Compute Julian day for Vernal (March) Equinox given year (1901-2009)
	X */
	Xdouble
	Xvernal_equinox(year)
	X	int	year;
	X{
	X	double	solstice_equinox_exact();
	X
	X	return solstice_equinox_exact(0, year);
	X}
	X
	X/*
	X * summer_solstice:
	X * Compute Julian day for Summer Solstice (June) given year (1901-2009)
	X */
	Xdouble
	Xsummer_solstice(year)
	X	int	year;
	X{
	X	double	solstice_equinox_exact();
	X
	X	return solstice_equinox_exact(1, year);
	X}
	X
	X/*
	X * autumn_equinox:
	X * Compute Julian day for Autumnal (September) Equinox given year (1901-2009)
	X */
	Xdouble
	Xautumn_equinox(year)
	X	int	year;
	X{
	X	double	solstice_equinox_exact();
	X
	X	return solstice_equinox_exact(2, year);
	X}
	X
	X/*
	X * winter_solstice:
	X * Compute Julian day for Winter (December) Solstice given year (1901-2009)
	X */
	Xdouble
	Xwinter_solstice(year)
	X	int	year;
	X{
	X	double	day, jday;
	X	int	month, nyear;
	X	double	solstice_equinox_exact();
	X
	X	jday = solstice_equinox_exact(3, year);
	X	gregorian_date(&day, &month, &nyear, jday);
	X	if (nyear == year)
	X		return jday;
	X	else
	X		return solstice_equinox_exact(3, (year + 1));
	X}
	X
	X/*
	X * solstice_equinox__exact:
	X * Compute more precise date for Solstice/Equinox
	X * given code (1-4, 1 for Vernal Equinox), year (1901-2009)
	X */
	Xdouble
	Xsolstice_equinox_exact(code, year)
	X	int	code, year;
	X{
	X	int	count;
	X
	X	double	corr, jday_app;
	X	double	solstice_equinox_approx(), solstice_equinox_correction();
	X
	X	/* compute first approximation to Julian day */
	X	jday_app = solstice_equinox_approx(code, year);
	X	/* iteratively recompute corrected Julian day */
	X	for(count = 0; count < 15; count++) {
	X		corr = solstice_equinox_correction(jday_app, code);
	X		jday_app += corr;
	X		if (fabs(corr) < 0.00001)
	X			break;
	X	}
	X	return jday_app;
	X}
	X
	X/*
	X * solstice_equinox_correction:
	X * Compute correction for Solstice/Equinox Julian day
	X * approximate Julian day, code (1-4, 1 for Vernal Equinox)
	X */
	Xdouble
	Xsolstice_equinox_correction(jday, code)
	X	int	code;
	X	double	jday;
	X{
	X	double	apparent_longitude(), sin_degrees();
	X
	X	return(58.0 * sin_degrees((code * 90.0) - apparent_longitude(jday)));
	X}
	X
	X/*
	X * apparent_longitude:
	X * Compute apparent longitude (true equinox) of Sun for
	X * Solstice/Equinox given approximate Julian day
	X */
	Xdouble
	Xapparent_longitude(jday)
	X	double	jday;
	X{
	X	double	btmp, ctmp, dtmp, etmp, ftmp;
	X	double	sin_degrees();
	X
	X	btmp = (jday - 2415020.0) / 36525.0;	/* time in Julian centuries: */
	X						/* epoch 0.5 January 1900 */
	X	ctmp = 279.69668 + (36000.76892 * btmp) /* geometric mean longitude */
	X		+ (0.0003025 * btmp * btmp);	/* (mean equinox of the date) */
	X	dtmp = 358.47583 + (35999.04975 * btmp)	/* mean anomaly of Sun */
	X		+ (0.00015 * btmp * btmp)
	X		+ (0.0000033 * btmp * btmp * btmp);
	X	etmp = (1.919460 - (0.004789 * btmp)	/* Sun's eqn of the center */
	X		- (0.000014 * btmp)) * sin_degrees(dtmp)
	X		+ (0.020094 - (0.0001 * btmp)) * sin_degrees(2 * dtmp)
	X		+ 0.000293 * sin_degrees(3 * dtmp);
	X	ftmp = ctmp + etmp;			/* Sun's true longitude */
	X	return ftmp - 0.00569			/* app. long. of Sun */
	X		- 0.00479 * sin_degrees(259.18	/* (true equinox of the date) */
	X		- (1934.142 * btmp));
	X}
	X
	X/*
	X * sin_degrees:
	X * Compute sin for argument in degrees
	X */
	Xdouble
	Xsin_degrees(degrees)
	X#define	PI_CORR	0.01745329252				/* pi / 180 */
	X	double	degrees;
	X{
	X	return sin(degrees * PI_CORR);
	X}
	X
	X/*
	X * solstice_equinox_approx:
	X * Compute approximate date for Solstice/Equinox
	X * given code (1-4, 1 for Vernal Equinox), year (1901-2009)
	X */
	Xdouble
	Xsolstice_equinox_approx(code, year)
	X	int	code, year;
	X{
	X	return (365.2422 * (year + (code / 4))) + 1721141.3;
	X}
	X
	X/*
	X * easter:
	X * Return Julian date for Easter, given year (1901-2009)
	X *
	X * Offered in the book of Meeus, which cites:
	X *
	X * 1) Spencer Jones
	X *    General Astronomy
	X *    1922
	X *    pg. 73-74
	X *
	X * 2) Journal of the British Astronomical Association
	X *    Vol. 8
	X *    Pg. 91
	X *    Dec. 1977
	X *    (which attributes method to Butcher's Ecclesiastical Calendar of 1876)
	X *
	X * Method valid for all dates in the Gregorian calendar
	X * (from 15 October 1583 on)
	X */
	Xdouble
	Xeaster(year)
	X	int	year;
	X{
	X	double	day;
	X	int	atmp, btmp, ctmp, dtmp, etmp, ftmp,
	X		gtmp, htmp, itmp, ktmp, ltmp, mtmp;
	X	int	month;
	X
	X	atmp = year % 19;
	X	btmp = year / 100;
	X	ctmp = year % 100;
	X	dtmp = btmp / 4;
	X	etmp = btmp % 4;
	X	ftmp = (btmp + 8) / 25;
	X	gtmp = (btmp - ftmp + 1) / 3;
	X	htmp = ((19 * atmp) + btmp - dtmp - gtmp + 15) % 30;
	X	itmp = ctmp / 4;
	X	ktmp = ctmp % 4;
	X	ltmp = (32 + (2 * etmp) + (2 * itmp) - htmp - ktmp) % 7;
	X	mtmp = (atmp + (11 * htmp) + (22 * ltmp)) / 451;
	X	month = (htmp + ltmp - (7 * mtmp) + 114) / 31;
	X	day = ((htmp + ltmp - (7 * mtmp) + 114) % 31) + 1;
	X	return julian_day(day, month, year);
	X}
	X
	X/*
	X * first_sunday_advent:
	X * Christian holidays: compute Julian day for First Sunday in Advent
	X * (closest Sunday to St. Andrew's day, the last day in November)
	X * given year (>1583)
	X */
	Xdouble
	Xfirst_sunday_advent(year)
	X	int	year;
	X{
	X	int	atmp;
	X
	X	atmp = get_day_of_week(30.0, 11, year);
	X	if (atmp <= 3) {
	X		return julian_day((30.0 - (double) atmp), 11, year);
	X	}
	X	else {
	X		return julian_day(30.0, 11, year) + (7 - atmp);
	X	}
	X}
	X
	X/*
	X * easter_offset:
	X * Christian holidays: compute Julian day as offset from Easter
	X * given year (>1583)
	X */
	Xdouble
	Xeaster_offset(offset, year)
	X	double	offset;
	X	int	year;
	X{
	X	double	easter();
	X
	X	return easter(year) + offset;
	X}
	X
	X/*
	X * septuagesima:
	X * Christian holidays: compute Julian day for Septuagesima Sunday
	X * (Third Sunday before Lent)
	X * given year (>1583)
	X */
	Xdouble
	Xseptuagesima(year)
	X	int	year;
	X{
	X	return easter_offset(-63.0, year);
	X}
	X
	X/*
	X * sexagesima:
	X * Christian holidays: compute Julian day for Sexagesima Sunday
	X * (Second Sunday before Lent)
	X * given year (>1583)
	X */
	Xdouble
	Xsexagesima(year)
	X	int	year;
	X{
	X	return easter_offset(-56.0, year);
	X}
	X
	X/*
	X * quinquagesima:
	X * Christian holidays: compute Julian day for Quinquagesima (Shrove) Sunday
	X * (Sunday before Lent begins on Ash Wednesday)
	X * given year (>1583)
	X */
	Xdouble
	Xquinquagesima(year)
	X	int	year;
	X{
	X	return easter_offset(-49.0, year);
	X}
	X
	X/*
	X * shrove_monday:
	X * Christian holidays: compute Julian day for Shrove Monday
	X * (Two days before Lent begins on Ash Wednesday)
	X * given year (>1583)
	X */
	Xdouble
	Xshrove_monday(year)
	X	int	year;
	X{
	X	return easter_offset(-48.0, year);
	X}
	X
	X/*
	X * shrove_tuesday:
	X * Christian holidays: compute Julian day for Shrove Tuesday
	X * (Day before Lent begins on Ash Wednesday; Mardi Gras)
	X * given year (>1583)
	X */
	Xdouble
	Xshrove_tuesday(year)
	X	int	year;
	X{
	X	return easter_offset(-47.0, year);
	X}
	X
	X/*
	X * ash_wednesday:
	X * Christian holidays: compute Julian day for Ash Wednesday
	X * given year (>1583)
	X */
	Xdouble
	Xash_wednesday(year)
	X	int	year;
	X{
	X	return easter_offset(-46.0, year);
	X}
	X
	X/*
	X * first_sunday_lent:
	X * Christian holidays: compute Julian day for First Sunday in Lent
	X * given year (>1583)
	X */
	Xdouble
	Xfirst_sunday_lent(year)
	X	int	year;
	X{
	X	return easter_offset(-42.0, year);
	X}
	X
	X/*
	X * second_sunday_lent:
	X * Christian holidays: compute Julian day for Second Sunday in Lent
	X * given year (>1583)
	X */
	Xdouble
	Xsecond_sunday_lent(year)
	X	int	year;
	X{
	X	return easter_offset(-35.0, year);
	X}
	X
	X/*
	X * third_sunday_lent:
	X * Christian holidays: compute Julian day for Third Sunday in Lent
	X * given year (>1583)
	X */
	Xdouble
	Xthird_sunday_lent(year)
	X	int	year;
	X{
	X	return easter_offset(-28.0, year);
	X}
	X
	X/*
	X * fourth_sunday_lent:
	X * Christian holidays: compute Julian day for Fourth Sunday in Lent
	X * given year (>1583)
	X */
	Xdouble
	Xfourth_sunday_lent(year)
	X	int	year;
	X{
	X	return easter_offset(-21.0, year);
	X}
	X
	X/*
	X * passion_sunday:
	X * Christian holidays: compute Julian day for Passion Sunday
	X * (Second Sunday before Easter)
	X * given year (>1583)
	X */
	Xdouble
	Xpassion_sunday(year)
	X	int	year;
	X{
	X	return easter_offset(-14.0, year);
	X}
	X
	X/*
	X * palm_sunday:
	X * Christian holidays: compute Julian day for Palm Sunday
	X * (Sunday before Easter)
	X * given year (>1583)
	X */
	Xdouble
	Xpalm_sunday(year)
	X	int	year;
	X{
	X	return easter_offset(-7.0, year);
	X}
	X
	X/*
	X * maundy_thursday:
	X * Christian holidays: compute Julian day for Maundy Thursday
	X * (Three days prior to Easter)
	X * given year (>1583)
	X */
	Xdouble
	Xmaundy_thursday(year)
	X	int	year;
	X{
	X	return easter_offset(-3.0, year);
	X}
	X
	X/*
	X * good_friday:
	X * Christian holidays: compute Julian day for Good Friday
	X * (Two days prior to Easter)
	X * given year (>1583)
	X */
	Xdouble
	Xgood_friday(year)
	X	int	year;
	X{
	X	return easter_offset(-2.0, year);
	X}
	X
	X/*
	X * easter_monday:
	X * Christian holidays: compute Julian day for Easter Monday (Canada)
	X * given year (>1583)
	X */
	Xdouble
	Xeaster_monday(year)
	X	int	year;
	X{
	X	return easter_offset(1.0, year);
	X}
	X
	X/*
	X * rogation_sunday:
	X * Christian holidays: compute Julian day for Rogation Sunday
	X * (Rogation is the period of three days prior to Ascension Day; strictly
	X * speaking, this is the period Mon-Wed)
	X * given year (>1583)
	X */
	Xdouble
	Xrogation_sunday(year)
	X	int	year;
	X{
	X	return easter_offset(35.0, year);
	X}
	X
	X/*
	X * ascension_day:
	X * Christian holidays: compute Julian day for Ascension Day
	X * (Holy Thursday; fortieth day after Easter, inclusive)
	X * given year (>1583)
	X */
	Xdouble
	Xascension_day(year)
	X	int	year;
	X{
	X	return easter_offset(39.0, year);
	X}
	X
	X/*
	X * whitsunday:
	X * Christian holidays: compute Julian day for Whitsunday (Pentecost)
	X * (Seventh Sunday after Easter)
	X * given year (>1583)
	X */
	Xdouble
	Xwhitsunday(year)
	X	int	year;
	X{
	X	return easter_offset(49.0, year);
	X}
	X
	X/*
	X * trinity_sunday:
	X * Christian holidays: compute Julian day for Trinity Sunday
	X * (Eighth Sunday after Easter)
	X * given year (>1583)
	X */
	Xdouble
	Xtrinity_sunday(year)
	X	int	year;
	X{
	X	return easter_offset(56.0, year);
	X}
	X
	X/*
	X * corpus_christi:
	X * Christian holidays: compute Julian day for Corpus Christi
	X * (First Thursday after Trinity Sunday)
	X * given year (>1583)
	X */
	Xdouble
	Xcorpus_christi(year)
	X	int	year;
	X{
	X	return easter_offset(60.0, year);
	X}
	X
	X/*
	X * passover:
	X * Jewish holidays: compute Julian day of Pesach (first day of Passover)
	X * and establish the Gregorian day of month and month, and Jewish year,
	X * given Julian year (>1583)
	X * This formula, due to Karl Friedrich Gauss (1777-1855) is described in
	X * excruciating detail in the book by Schocken P. 51-61).  Note that it
	X * computes the Julian date, which has to be corrected to a Gregorian date,
	X * and that it exhibits the eccentricity of always computing the day
	X * relative to March, so that April 2 appears as March 33, which is also
	X * corrected below.
	X * This formula is probably only accurate for years up to and including
	X * 2000 (tested); I know that it fails for 2011.
	X */
	Xdouble
	Xpassover(year, jyear)
	X	int	*jyear, year;
	X{
	X	double	etmp, p_day;
	X	int	atmp, btmp, ctmp, day_of_week, dtmp, ftmp, gtmp;
	X	int	p_month;
	X
	X	atmp = year + 3760;
	X	*jyear = atmp;
	X	btmp = (12 * atmp + 17) % 19;
	X	ctmp = atmp % 4;
	X	etmp = (1.55424180 * btmp) - (0.003177794 * atmp)
	X		+ (ctmp / 4) + 32.04409316;
	X	dtmp = etmp;
	X	etmp = etmp - dtmp;
	X		/* day_of_week is not to be confused with the
	X		 value returned by the day_of_week routine; here, Sunday = 1 */
	X	day_of_week = ((3 * atmp) + (5 * ctmp) + dtmp + 5) % 7;
	X	if (day_of_week == 0 && btmp > 11 && etmp >= 0.89772377)
	X		p_day = dtmp + 1.0;
	X	else if (day_of_week == 1 && btmp > 6 && etmp >= 0.63287037)
	X		p_day = dtmp + 2.0;
	X	else if (day_of_week == 2 || day_of_week == 4 || day_of_week ==6)
	X		p_day = dtmp + 1.0;
	X	else {
	X		p_day = dtmp;
	X	}
	X	ftmp = year / 100;		/* Correct to Gregorian date */
	X	gtmp = ((3 * ftmp) - 5) / 4;
	X	p_day += gtmp;
	X	if (p_day > 31) {		/* Correct for March days > 31 */
	X		p_day -= 31;
	X		p_month = 4;
	X		}
	X	else
	X		p_month = 3;
	X	return julian_day(p_day, p_month, year);
	X}
	X
	X/*
	X * passover_offset:
	X * Jewish holidays: compute Julian day as offset from Passover
	X * given year (>1583)
	X */
	Xdouble
	Xpassover_offset(offset, year, jyear)
	X	double	offset;
	X	int	*jyear, year;
	X{
	X	double	passover();
	X
	X	return passover(year, jyear) + offset;
	X}
	X
	X/*
	X * purim:
	X * Jewish holidays: compute Julian day and Jewish year for Purim (Feast of Lots)
	X * given year (>1583)
	X */
	Xdouble
	Xpurim(year, jyear)
	X	int	*jyear, year;
	X{
	X	return passover_offset(-30.0, year, jyear);
	X}
	X
	X/*
	X * shavuot:
	X * Jewish holidays: compute Julian day and Jewish year for First day of Shavuot
	X * given year (>1583)
	X */
	Xdouble
	Xshavuot(year, jyear)
	X	int	*jyear, year;
	X{
	X	return passover_offset(50.0, year, jyear);
	X}
	X
	X/*
	X * rosh_hashanah:
	X * Jewish holidays: compute Julian day and Jewish year for first day of
	X * Rosh Hashanah (New Year) given year (>1583)
	X */
	Xdouble
	Xrosh_hashanah(year, jyear)
	X	int	*jyear, year;
	X{
	X	double	atmp;
	X	atmp = passover_offset(163.0, year, jyear);
	X	(*jyear)++;
	X	return atmp;
	X}
	X
	X/*
	X * yom_kippur:
	X * Jewish holidays: compute Julian day and Jewish year for Yom Kippur
	X * given year (>1583)
	X */
	Xdouble
	Xyom_kippur(year, jyear)
	X	int	*jyear, year;
	X{
	X	double	atmp;
	X	atmp = passover_offset(172.0, year, jyear);
	X	(*jyear)++;
	X	return atmp;
	X}
	X
	X/*
	X * sukkot:
	X * Jewish holidays: compute Julian day and Jewish year for
	X * First day of Sukkot (9 days) given year (>1583)
	X */
	Xdouble
	Xsukkot(year, jyear)
	X	int	*jyear, year;
	X{
	X	double	atmp;
	X	atmp = passover_offset(177.0, year, jyear);
	X	(*jyear)++;
	X	return atmp;
	X}
	X
	X/*
	X * simchat_torah:
	X * Jewish holidays: compute Julian day and Jewish year for Simchat Torah
	X * (in Diapsora) given year (>1583)
	X */
	Xdouble
	Xsimchat_torah(year, jyear)
	X	int	*jyear, year;
	X{
	X	double	atmp;
	X	atmp = passover_offset(185.0, year, jyear);
	X	(*jyear)++;
	X	return atmp;
	X}
	X
	X/*
	X * chanukah:
	X * Jewish holidays: compute Julian day and Jewish year for
	X * first day of Chanukah (8 days) given year (>1583)
	X */
	Xdouble
	Xchanukah(year, jyear)
	X	int	*jyear, year;
	X{
	X	double	atmp;
	X	int	btmp, dummy;
	X
	X	atmp = passover(year, jyear);
	X	btmp = passover((year + 1), &dummy) - atmp;
	X	(*jyear)++;
	X	if (btmp == 355 || btmp == 385)
	X		return atmp + 247.0;
	X	else
	X		return atmp + 246.0;
	X}
	X
	X/*
	X * islamic_date:
	X * Islamic holidays: compute Gregorian date(s) and Islamic year for any
	X * Islamic day, given ISLAMIC day (1-30), ISLAMIC month(1-12),
	X * and GREGORIAN year (>1583)
	X * This is complicated by the fact that a given Islamic date can appear as
	X * often as twice within the same Gregorian year.
	X */
	Xislamic_date(
	X	mday, mmonth, number_of_days, day1, month1, day2, month2, year, myear1,
	X	myear2)
	X	double	*day1, *day2, mday;
	X	int	mmonth, *month1, *month2, *myear1, *myear2,
	X		*number_of_days, year;
	X{
	X	double	day;
	X	int	count, month, nyear;
	X	double	islamic_to_julian();
	X
	X	*myear1 = year - 621;		/* approx. >= Muslim year */
	X	nyear = year - 1;
	X	for (count = 0; nyear != year && count <= 100; count++) {
	X		gregorian_date(&day, &month, &nyear,
	X			islamic_to_julian(mday, mmonth, *myear1));
	X		*myear1 = *myear1 + (year - nyear);
	X	}
	X	if (nyear == year) {
	X		*day1 = day;
	X		*month1 = month;
	X		/*
	X		 * See if there is a second occurrence in same Gregorian year
	X		 */
	X		gregorian_date(&day, &month, &nyear,
	X			islamic_to_julian(mday, mmonth, (*myear1 + 1)));
	X		if (nyear == year) {
	X			*day2 = day;
	X			*month2 = month;
	X			*number_of_days = 2;
	X			*myear2 = *myear1 + 1;
	X		}
	X		else {
	X			*number_of_days = 1;
	X			gregorian_date(&day, &month, &nyear,
	X				islamic_to_julian(mday, mmonth, (*myear1 - 1)));
	X			if (nyear == year) {
	X				*day2 = day;
	X				*month2 = month;
	X				*number_of_days = 2;
	X				*myear2 = *myear1 + 1;
	X			}
	X		}
	X	}
	X/*	else return -1; */
	X	return 0;
	X}
	X
	X/*
	X * islamic_to_julian:
	X * Islamic holidays: compute Julian day for any Islamic day,
	X * given ISLAMIC day (1-30), ISLAMIC month(1-12), and ISLAMIC year (>962)
	X * Formula from Schocken (p. 66)
	X */
	Xdouble
	Xislamic_to_julian(mday, mmonth, myear)
	X	double	mday;
	X	int	mmonth, myear;
	X{
	X	double	etmp, ftmp, jday;
	X	int	atmp, btmp, ctmp, dtmp, nyear;
	X	double	corrected_julian_day();
	X
	X	nyear = myear + 621;		/* approx. Julian year */
	X	atmp = ((19 * myear) - 4) % 30;
	X	btmp = nyear % 4;
	X	ctmp = (mmonth - 1) / 2;
	X	dtmp = (mmonth - 1) % 2;
	X	etmp = mday + (59.0 * ctmp) + (30.0 * dtmp) + (atmp / 30.0)
	X	 	+ (btmp / 4.0) - (10.8833333 * myear) + 146.8833333;
	X	if (etmp < 0.0) {
	X		ftmp = (4.0 * fabs(etmp)) / 1461.0;
	X		atmp = ftmp;
	X		dtmp = (4.0 * fabs(etmp));
	X		dtmp = dtmp % 1461;
	X		nyear -= (atmp + 1);
	X		ctmp = nyear % 4;
	X		jday = julian_day(1.0, 3, nyear)
	X			+ (((1461.0 - dtmp) + ctmp - btmp) / 4.0)
	X			- 1.0;
	X		return corrected_julian_day(jday);
	X	}
	X	jday = julian_day(1.0, 3, nyear) + etmp - 1.0;
	X	return corrected_julian_day(jday);
	X}
	X
	X/*
	X * islamic_new_year:
	X * Islamic holidays: compute Julian date(s) and Islamic year(s)
	X * for Islamic New Year given JULIAN year (>1583)
	X * (note: due to the length of the Islamic year (355 d), there can be portions
	X * of as many as two Islamic New Years within a given Gregorian year; for
	X * example, according to the algorithm below, the Islamic New Year occured
	X * twice in 1975: Wednesday 1 January, Sunday 21 December)
	X *
	X * Algorithm: Schocken, page 66, which agrees with dates I have obtained for
	X * the (Gregorian) years 1962-2000.  Schocken outlines a Muslim calendar
	X * consisting of 12 months which are alternately 30 and 29 days in length
	X * (the first month, Muharram, is 30 days in length).  In a 30-year cycle,
	X * there are 11 leap years in which a 30th day is added to the final month
	X * of the year.  See full details below.
	X *
	X * According to Dr. Omar Afzal of Cornell University ((607)255-5118,
	X * 277-6707; Chairman of the Committee for Crescent Observation;
	X * irfan@mvax.ee.cornell.edu), this is an antiquated system which has been
	X * in use for some 400 years, but today the Muslim calendar follows a more
	X * strictly lunar basis.  I wish to acknowledge the Pakistani Consular
	X * Office of San Francisco (415)788-0677, who referred me to Dr. Muzammil
	X * Siddiqui of the Orange County Islamic Center, (714)531-1722, who in turn
	X * referred me to to Dr. Afzal.  I thank Dr. Afzal for his patient and lucid
	X * explanations of the Islamic calendar, and for providing printed matter and
	X * tables of dates to assist me.  Among the sources he provided:
	X *
	X * %A U. V. Tsybulsky
	X * %B Calendar of Middle Eastern Countries
	X * %I Nauka Publishing House
	X * %C Moscow
	X * %L English
	X * %D 1979
	X *
	X * which provides a scholarly discussion of calendrical conventions in various
	X * Muslim countries, as well as simple formulas for conversion between
	X * Gregorian and Islamic dates.  It also includes translations of tables which
	X * originally appeared in:
	X *
	X * %A F. R. Unat
	X * %B Hicri Tarihleri
	X * %I Turktarih Kurumu Basimevi
	X * %C Ankara
	X * %L Turkish
	X * %D 1959
	X *
	X * Additional tabular material is available in:
	X *
	X * %A G. S. P. Freeman-Grenville
	X * %B The Muslim and Christian Calendars
	X * %I Oxford University Press
	X * %C London
	X * %D 1963
	X *
	X * The Islamic calendar is also known as the Hijri calendar, and dates often
	X * have "A.H." or "a.h." appended to them to indicate "Anno Hijri."  A
	X * listing of the months and their lengths (in the old scheme):
	X *
	X *    Month Name     Days         Days to add to 1 Muharram to get 1st of month
	X * 1  Muharram        30          0
	X * 2  Safar           29         30
	X * 3  Rabi' al-Awwal  30         59
	X * 4  Rabi' ath-Thani 29         89
	X * 5  Jumada al-Ula   30        118
	X * 6  Jumada al-Akhir 29        148
	X * 7  Rajab           30        177
	X * 8  Sha'ban         29        207
	X * 9  Ramadan         30        236
	X * 10 Shawwal         29        266
	X * 11 Dhul-Qa'da      30        295
	X * 12 Dhul-Hijja      29 (30)   325
	X *
	X * In the old scheme, used here for simplicity, adherence to this set of rules
	X * led to a gradual lag of the month behind the actual crescent moon.  Thus,
	X * a leap day was appended to the final month in each of 11 years out of every
	X * 30 year cycle: (2, 5, 7, 10, 13, 16, 18, 21, 24, 26, 29).  If the Hijra year
	X * is divided by 30, and the remainder is equal to one of these numbers, it is
	X * a leap year.
	X *
	X * The Islamic day begins after sunset, and the beginning of the month is tied
	X * to the first VISIBLE appearance of the crescent moon, which often lags behind
	X * the astronomical new moon.  Also, the crescent was sometimes computed
	X * according to Mecca time.  There are numerous methods for defining the date
	X * of the crescent moon (and hence calendar dates) among the various Muslim
	X * regions of the world.  Given these uncertainties, the dates computed here are
	X * likely to be accurate to only +/- 2 days.
	X *
	X * Any errors in this code are my own fault, and
	X * not intended to offend any members of the Islamic faith.
	X */
	Xislamic_new_year(year, number_of_dates, date1, date2, myear1, myear2)
	X	double	*date1, *date2;
	X	int	*number_of_dates, *myear1, *myear2, year;
	X{
	X	double	day1, day2;
	X	int	month1, month2;
	X
	X	if (islamic_date(1.0, 1, number_of_dates, &day1, &month1, &day2,
	X		&month2, year, myear1, myear2) < 0) return -1;
	X	*date1 = julian_day(day1, month1, year);
	X	if (*number_of_dates == 2) *date2 = julian_day(day2, month2, year);
	X	return 0;
	X}
	X
	X/*
	X * islamic_offset:
	X * Islamic holidays: compute Julian day(s) for an Islamic date as an offset
	X * from the Islamic New Year, given (Gregorian) year
	X */
	Xislamic_offset(offset, year, number_of_dates, date1, date2, myear1, myear2)
	X	double	*date1, *date2, offset;
	X	int	*number_of_dates, *myear1, *myear2, year;
	X{
	X	double	day, tdate1, tdate2;
	X	int	month, tyear1, tyear2;
	X
	X	(void) islamic_new_year(year, number_of_dates, date1, date2,
	X		myear1, myear2);
	X	if (*number_of_dates == 2) {
	X		tdate2 = *date2 + offset;
	X		gregorian_date(&day, &month, &tyear2, tdate2);
	X		if (tyear2 > year) {
	X			tdate2 = *date1 + offset;
	X			(void) islamic_new_year((year - 1), number_of_dates,
	X				date1, date2, myear1, myear2);
	X			tdate1 = *date1 + offset;
	X			gregorian_date(&day, &month, &tyear1, tdate1);
	X			if (tyear1 == year) {
	X				*date1 = tdate1;
	X				*date2 = tdate2;
	X				*number_of_dates = 2;
	X				*myear2 = *myear1 + 1;
	X			}
	X			else {
	X				*date1 = tdate2;
	X				*number_of_dates = 1;
	X				*myear1 = *myear1 + 1;
	X			}
	X		}
	X		else {
	X			*date1 += offset;
	X			*date2 = tdate2;
	X		}
	X	}
	X	else {
	X		tdate2 = *date1 + offset;
	X		gregorian_date(&day, &month, &tyear2, tdate2);
	X		if (tyear2 > year) {
	X			(void) islamic_new_year((year - 1), number_of_dates,
	X				date1, date2, myear1, myear2);
	X			if (*number_of_dates == 2) {
	X				*date1 = *date2 + offset;
	X				*number_of_dates = 1;
	X				*myear1 = *myear2;
	X			}
	X			else {
	X				*date1 = *date1 + offset;
	X			}
	X		}
	X		else {
	X			(void) islamic_new_year((year - 1), number_of_dates,
	X				date1, date2, myear1, myear2);
	X			if (*number_of_dates == 2) {
	X				tdate1 = *date2 + offset;
	X				*myear1 = *myear2;
	X			}
	X			else {
	X				tdate1 = *date1 + offset;
	X			}
	X			gregorian_date(&day, &month, &tyear1, tdate1);
	X			if (tyear1 == year) {
	X				*date1 = tdate1;
	X				*date2 = tdate2;
	X				*number_of_dates = 2;
	X				*myear2 = *myear1 + 1;
	X			}
	X			else {
	X				*date1 = tdate2;
	X				*myear1 = *myear1 + 1;
	X				*number_of_dates = 1;
	X			}
	X		}
	X	}
	X}
	X
	X/*
	X * muharram_9:
	X * Islamic holidays: compute Julian day(s) and Islamic year(s) for
	X * Muharram 9 (Day of fasting) given year (>1583)
	X */
	Xmuharram_9(year, number_of_dates, date1, date2, myear1, myear2)
	X	double	*date1, *date2;
	X	int	*number_of_dates, *myear1, *myear2, year;
	X{
	X	islamic_offset(
	X		8.0, year, number_of_dates, date1, date2, myear1, myear2);
	X}
	X
	X/*
	X * muharram_10:
	X * Islamic holidays: compute Julian day(s) and Islamic year(s) for
	X * Muharram 10 (Day of deliverance of Moses from the Pharoah; for Shia Islam,
	X * martyrdom of Husain) given year (>1583)
	X */
	Xmuharram_10(year, number_of_dates, date1, date2, myear1, myear2)
	X	double	*date1, *date2;
	X	int	*number_of_dates, *myear1, *myear2, year;
	X{
	X	islamic_offset(
	X		9.0, year, number_of_dates, date1, date2, myear1, myear2);
	X}
	X
	X/*
	X * muharram_16:
	X * Islamic holidays: compute Julian day(s) and Islamic year(s) for
	X * Muharram 16 (Imamat Day; Ismaili Khoja) given year (>1583)
	X */
	Xmuharram_16(year, number_of_dates, date1, date2, myear1, myear2)
	X	double	*date1, *date2;
	X	int	*number_of_dates, *myear1, *myear2, year;
	X{
	X	islamic_offset(
	X		15.0, year, number_of_dates, date1, date2, myear1, myear2);
	X}
	X
	X/*
	X * eid_i_milad_un_nabi:
	X * Islamic holidays: compute Julian day(s) and Islamic year(s) for
	X * Rabi I 12 (Eid-i-Milad-un-Nabi: The Prophet's Birthday) given year (>1583)
	X */
	Xeid_i_milad_un_nabi(year, number_of_dates, date1, date2, myear1, myear2)
	X	double	*date1, *date2;
	X	int	*number_of_dates, *myear1, *myear2, year;
	X{
	X	islamic_offset(
	X		70.0, year, number_of_dates, date1, date2, myear1, myear2);
	X}
	X
	X/*
	X * jumada_al_akhir_23:
	X * Islamic holidays: compute Julian day(s) and Islamic year(s) for
	X * Jumada al-Akhir 23 (Birth of Agha Khan IV, Ismaili) given year (>1583)
	X */
	Xjumada_al_akhir_23(year, number_of_dates, date1, date2, myear1, myear2)
	X	double	*date1, *date2;
	X	int	*number_of_dates, *myear1, *myear2, year;
	X{
	X	islamic_offset(
	X		170.0, year, number_of_dates, date1, date2, myear1, myear2);
	X}
	X
	X/*
	X * shab_e_miraj:
	X * Islamic holidays: compute Julian day(s) and Islamic year(s) for
	X * Rajab 27 (Shab-e-Mi'raj: The Prophet's Ascension) given year (>1583)
	X */
	Xshab_e_miraj(year, number_of_dates, date1, date2, myear1, myear2)
	X	double	*date1, *date2;
	X	int	*number_of_dates, *myear1, *myear2, year;
	X{
	X	islamic_offset(
	X		203.0, year, number_of_dates, date1, date2, myear1, myear2);
	X}
	X
	X/*
	X * shab_e_barat:
	X * Islamic holidays: compute Julian day(s) and Islamic year(s) for
	X * Shaban 15 (Shab-e-Bara't: Night, followed by day of fasting) given year (>1583)
	X */
	Xshab_e_barat(year, number_of_dates, date1, date2, myear1, myear2)
	X	double	*date1, *date2;
	X	int	*number_of_dates, *myear1, *myear2, year;
	X{
	X	islamic_offset(
	X		221.0, year, number_of_dates, date1, date2, myear1, myear2);
	X}
	X
	X/*
	X * ramadan:
	X * Islamic holidays: compute Julian day(s) and Islamic year(s) for
	X * Ramadan 1 (Fasting month begins) given year (>1583)
	X */
	Xramadan(year, number_of_dates, date1, date2, myear1, myear2)
	X	double	*date1, *date2;
	X	int	*number_of_dates, *myear1, *myear2, year;
	X{
	X	islamic_offset(
	X		236.0, year, number_of_dates, date1, date2, myear1, myear2);
	X}
	X
	X/*
	X * shab_e_qadr:
	X * Islamic holidays: compute Julian day(s) and Islamic year(s) for
	X * Ramadan 27 (Shab-e Qadr: Night vigil) given year (>1583)
	X */
	Xshab_e_qadr(year, number_of_dates, date1, date2, myear1, myear2)
	X	double	*date1, *date2;
	X	int	*number_of_dates, *myear1, *myear2, year;
	X{
	X	islamic_offset(
	X		262.0, year, number_of_dates, date1, date2, myear1, myear2);
	X}
	X
	X/*
	X * eid_al_fitr:
	X * Islamic holidays: compute Julian day(s) and Islamic year(s) for
	X * Shawwal 1 (Eid-al-Fitr: Day of Feast) given year (>1583)
	X */
	Xeid_al_fitr(year, number_of_dates, date1, date2, myear1, myear2)
	X	double	*date1, *date2;
	X	int	*number_of_dates, *myear1, *myear2, year;
	X{
	X	islamic_offset(
	X		266.0, year, number_of_dates, date1, date2, myear1, myear2);
	X}
	X
	X/*
	X * dhul_hijja_9:
	X * Islamic holidays: compute Julian day(s) and Islamic year(s) for
	X * Dhul-Hijj 9 (Day of Pilgrimage at Arafat, Mecca) given year (>1583)
	X */
	Xdhul_hijja_9(year, number_of_dates, date1, date2, myear1, myear2)
	X	double	*date1, *date2;
	X	int	*number_of_dates, *myear1, *myear2, year;
	X{
	X	islamic_offset(
	X		333.0, year, number_of_dates, date1, date2, myear1, myear2);
	X}
	X
	X/*
	X * eid_al_adha:
	X * Islamic holidays: compute Julian day(s) and Islamic year(s) for
	X * Dhul-Hijj 10 (Eid-al-Adha: Day of Abraham's Sacrifice) given year (>1583)
	X */
	Xeid_al_adha(year, number_of_dates, date1, date2, myear1, myear2)
	X	double	*date1, *date2;
	X	int	*number_of_dates, *myear1, *myear2, year;
	X{
	X	islamic_offset(
	X		334.0, year, number_of_dates, date1, date2, myear1, myear2);
	X}
	X
	X/*
	X * ghadir:
	X * Islamic holidays: compute Julian day(s) and Islamic year(s) for
	X * Dhul-Hijj 18 (Ghadir: Ali's Nomination) given year (>1583)
	X */
	Xghadir(year, number_of_dates, date1, date2, myear1, myear2)
	X	double	*date1, *date2;
	X	int	*number_of_dates, *myear1, *myear2, year;
	X{
	X	islamic_offset(
	X		342.0, year, number_of_dates, date1, date2, myear1, myear2);
	X}
	X
	X/*
	X * print_islamic_string:
	X * Print formatted date string(s) of form:
	X *    Monday 1 August 1988 (Islamic year 1409)
	X * given string labelling date, (Gregorian) year of event, and function which
	X * takes (Gregorian) year as an argument and produces: the (integer) number of
	X * Gregorian dates (1 or 2), the first and second (Julian) days, and the first
	X * and second Islamic years.
	X */
	Xprint_islamic_string(string, year, func)
	X	char	*string;
	X	int	year;
	X	int	(*func) ();
	X{
	X
	X	char	*date;
	X	double	date1, date2, day, holiday;
	X	int	month, myear1, myear2, number_of_dates;
	X	char	*date_string();
	X
	X	holiday = (*func) (
	X		year, &number_of_dates, &date1, &date2, &myear1, &myear2);
	X	if (holiday < 0)
	X		(void) printf("Can not determine requested date\n");
	X	else {
	X		(void) printf("%s (%d) Julian day: %f\n", string, year, date1);
	X		gregorian_date(&day, &month, &year, date1);
	X		date = date_string(get_day_of_week(day, month, year),
	X			day, month, year);
	X		(void) printf("%s (%d): %s", string, year, date);
	X		(void) printf(" (Islamic year %d)\n", myear1);
	X		if (number_of_dates == 2) {
	X			(void) printf(
	X				"%s (%d) Julian day: %f\n", string, year,
	X				date2);
	X			gregorian_date(&day, &month, &year, date2);
	X			date = date_string(get_day_of_week(day, month, year),
	X				day, month, year);
	X			(void) printf("%s (%d): %s", string, year, date);
	X			(void) printf(" (Islamic year %d)\n",
	X				myear2);
	X		}
	X	}
	X}
	X
	X/*
	X * print_date_and_time_string:
	X * Print formatted date/time string of form: 10:42 Thursday 8 December 1988
	X * given string labelling date, year of event, and function which takes year
	X * as an argument and produces Julian day, 
	X */
	Xprint_date_and_time_string(string, year, func)
	X	char	*string;
	X	int	year;
	X	double	(*func)();
	X{
	X	char	*date;
	X	double	btmp, ctmp, day, holiday;
	X	int	atmp, hour, min, month;
	X	char	*date_time_string();
	X
	X	holiday = (*func) (year);
	X	(void) printf("%s (%d) Julian day: %f\n", string, year, holiday);
	X	gregorian_date(&day, &month, &year, holiday);
	X	atmp = day;
	X	btmp = day - atmp;
	X	hour = btmp * 24.0;
	X	ctmp = (btmp - (hour / 24.0)) * 1440.0;
	X	min = ctmp;
	X	date = date_time_string(hour, min, get_day_of_week(day, month, year),
	X		day, month, year);
	X	(void) printf("%s (%d): %s\n", string, year, date);
	X}
	X
	X/*
	X * print_date_string:
	X * Print formatted date string of form: Thursday 8 December 1988
	X * given string labelling date, year of event, and function which takes year
	X * as an argument and produces Julian day. 
	X */
	Xprint_date_string(string, year, func)
	X	char	*string;
	X	int	year;
	X	double	(*func) ();
	X{
	X	char	*date;
	X	double	day, holiday;
	X	int	month;
	X	char	*date_string();
	X
	X	holiday = (*func) (year);
	X	(void) printf("%s (%d) Julian day: %f\n", string, year, holiday);
	X	gregorian_date(&day, &month, &year, holiday);
	X	date = date_string(get_day_of_week(day, month, year), day, month, year);
	X	(void) printf("%s (%d): %s\n", string, year, date);
	X}
	X
	X/*
	X * print_jewish_string:
	X * Print formatted date string of form: Thursday 8 December 1988 (NYEAR)
	X * given string labelling date, year of event, and function which takes year
	X * as an argument, sets the value of a non-Gregorian year (NYEAR), and produces
	X * the Julian day.
	X */
	Xprint_jewish_string(string, year, func)
	X	char	*string;
	X	int	year;
	X	double	(*func) ();
	X{
	X	char	*date;
	X	double	day, holiday;
	X	int	month, nyear;
	X	char	*date_string();
	X
	X	holiday = (*func) (year, &nyear);
	X	(void) printf("%s (%d) Julian day: %f\n", string, year, holiday);
	X	gregorian_date(&day, &month, &year, holiday);
	X	date = date_string_2(get_day_of_week(day, month, year), day, month,
	X		year, nyear);
	X	(void) printf("%s (%d): %s\n", string, year, date);
	X}
	X
	X/*
	X * extract time of day from Julian day
	X */
	Xchar *
	Xjulian_time(jday)
	Xdouble jday;
	X{
	X	double	h1, floor();
	X	int	hours, minutes;
	X
	X	h1 = (jday - floor(jday)) * 24.; /* number of hours & frac of hours */
	X	hours = (int) floor(h1);
	X	minutes = (int) ((h1 - (double) hours) * 60.);
	X	sprintf(timebuf, " at %d:%02d", hours, minutes);
	X	return(timebuf);
	X}
	X
	X/*
	X * End of code
	X */
	X#endif	/* NO_HOLIDAYS */
SHAR_EOF
if test 44349 -ne "`wc -c < 'datelib.c'`"
then
	echo shar: error transmitting "'datelib.c'" '(should have been 44349 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'day.cursor'" '(283 characters)'
if test -f 'day.cursor'
then
	echo shar: will not over-write existing file "'day.cursor'"
else
sed 's/^	X//' << \SHAR_EOF > 'day.cursor'
	X/* $Header: day.cursor,v 2.1 89/05/09 14:31:03 billr Exp $ */
	X/* Format_version=1, Width=16, Height=16, Depth=1, Valid_bits_per_item=16
	X */
	X        0x0000, 0x0000, 0x0000, 0x01F0, 0x0700, 0x1DFF, 0x7000, 0xC000,
	X        0x7000, 0x1DFF, 0x0700, 0x01F0, 0x0000, 0x0000, 0x0000, 0x0000
SHAR_EOF
if test 283 -ne "`wc -c < 'day.cursor'`"
then
	echo shar: error transmitting "'day.cursor'" '(should have been 283 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'event.c'" '(6577 characters)'
if test -f 'event.c'
then
	echo shar: will not over-write existing file "'event.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'event.c'
	X/*
	X * $Header: event.c,v 2.1 89/05/09 14:23:23 billr Exp $
	X */
	X/*
	X * event.c
	X *
	X * Author: Philip Heller, Sun Microsystems. Inc. <terrapin!heller@sun.com>
	X *
	X * Original source Copyright (C) 1987, Sun Microsystems, Inc.
	X *	All Rights Reserved
	X * Permission is hereby granted to use and modify this program in source
	X * or binary form as long as it is not sold for profit and this copyright
	X * notice remains intact.
	X *
	X *
	X * Changes/additions by: Bill Randle, Tektronix, Inc. <billr@saab.CNA.TEK.COM>
	X *
	X * Changes and additions Copyright (C) 1988, 1989 Tektronix, Inc.
	X *	All Rights Reserved
	X * Permission is hereby granted to use and modify the modifications in source
	X * or binary form as long as they are not sold for profit and this copyright
	X * notice remains intact.
	X */
	X/********************************************************
	X *							*
	X *    Main driver and month and year event routines	*
	X *    for main subwindow  				*
	X *							*
	X ********************************************************/
	X
	X
	X#include <stdio.h>
	X#include <suntool/sunview.h>
	X#include <suntool/panel.h>
	X#include <suntool/canvas.h>
	X#include "ct.h"
	X#include "event.h"
	X
	Xextern Frame frame;
	Xextern Frame fframe, sframe, mframe;
	Xextern struct tm olddate;
	Xextern int update_interval, show_time;
	Xextern char timestr[], todays_date[];
	Xextern Icon icon;
	XNotify_value myframe_interposer();
	X
	Xvoid
	Xmainsw_inputevent(canvas, event)
	XCanvas canvas;
	XEvent *event;
	X{
	X	/* check for L7 key and close frame if found */
	X	if (event_id(event) == KEY_LEFT(7) && event_is_up(event))
	X		close_frame();
	X	else
	X		switch (mainsw_state) {
	X			case DISPLAYING_DAY:
	X				day_inputevent(canvas, event);
	X				break;
	X			case DISPLAYING_WEEK:
	X				week_inputevent(canvas, event);
	X				break;
	X			case DISPLAYING_MONTH:
	X				month_inputevent(canvas, event);
	X				break;
	X			case DISPLAYING_YEAR:
	X				year_inputevent(canvas, event);
	X				break;
	X		}
	X}
	X
	Xmonth_inputevent(canvas, event)
	XCanvas canvas;
	XEvent *event;
	X{
	X        int i, x, y, week_index, new_day;
	X
	X	/* translate coordinates to pixwin space */
	X	event = canvas_window_event(canvas, event);
	X        x = event_x(event);
	X        y = event_y(event);          
	X        if (event_id(event) != MS_LEFT)
	X                return;
	X
	X        if (event_is_up(event))  {   /* Button up. */
	X		fix_current_day();
	X                if (selected_type == DAY) {
	X                        mainsw_state = DISPLAYING_DAY;
	X                        window_set(canvas, WIN_CURSOR, day_cursor, 0);
	X			draw_day();
	X                }
	X                else if (selected_type == WEEK) {
	X			mainsw_state = DISPLAYING_WEEK;
	X			window_set(canvas, WIN_CURSOR, week_cursor, 0);
	X			draw_week();
	X		}
	X		return;
	X	}
	X
	X	/* Button down. */
	X        selected_type = NONE;
	X        for (i=0; i<monthlength(current.tm_mon); i++) {   /* In a day? */
	X                if ((x >= boxlims[i].lowx) &&
	X                    (x <= boxlims[i].highx) &&
	X                    (y >= boxlims[i].lowy) &&
	X                    (y <= boxlims[i].highy)) {
	X				current.tm_mday = i + 1;
	X                                selected_type = DAY;
	X                                pw_write(main_pixwin,boxlims[i].lowx+3,
	X                                  boxlims[i].lowy+3,58,58,PIX_NOT(PIX_DST),NULL,0,0);
	X                                return;
	X                }              
	X        }                      
	X        for (i=0; i<6; i++) {              /* No.  In a week? */
	X                if (week_arrows[i].active == 0)
	X                        return;
	X                if ((x >= week_arrows[i].left) &&
	X                    (x <= week_arrows[i].right) &&
	X                    (y >= week_arrows[i].top) &&
	X                    (y <= week_arrows[i].bottom))  {
	X			week_index = i;
	X			current.tm_mday = -current.tm_wday + 1 + (7 * week_index);
	X                        selected_type = WEEK;
	X                        pw_write(main_pixwin,week_arrows[week_index].left,
	X                          week_arrows[week_index].top,smallarrow_pr->pr_size.x,
	X			  smallarrow_pr->pr_size.y,PIX_SRC^PIX_DST,
	X                          smallarrow_pr,0,0);
	X                        return;
	X                }              
	X        }                      
	X}                               
	X
	Xyear_inputevent(canvas, event)
	XCanvas canvas;
	XEvent *event;
	X{
	X	int x, y, i;
	X	static int mday;
	X
	X	/* translate coordinates to pixwin space */
	X	event = canvas_window_event(canvas, event);
	X        x = event_x(event);
	X        y = event_y(event);          
	X        if (event_id(event) != MS_LEFT)
	X                return;
	X        if (event_is_up(event))  {       /* Button up. */
	X		if (selected_type == MONTH) {
	X			mainsw_state = DISPLAYING_MONTH;
	X			window_set(canvas, WIN_CURSOR, month_cursor, 0);
	X			draw_month();
	X		}
	X		return;
	X	}
	X
	X	/* Button down. */
	X	selected_type = NONE;
	X        for (i=0; i<12; i++) {                   /* In a month? */
	X                if ((x >= mboxlims[i].lowx) &&
	X                    (x <= mboxlims[i].highx) &&
	X                    (y >= mboxlims[i].lowy) &&
	X                    (y <= mboxlims[i].highy)) {
	X			selected_type = MONTH;
	X			current.tm_mday = 1;
	X			current.tm_mon = i;
	X			pw_write(main_pixwin,mboxlims[i].lowx,
	X			  mboxlims[i].lowy,7*ybox_width,ybox_height-1,PIX_NOT(PIX_DST),NULL,0,0);
	X			break;
	X		}
	X	}
	X}
	X
	XNotify_value
	Xcheck_close(client, event, arg, when)
	XNotify_client client;
	XEvent *event;
	XNotify_arg arg;
	XNotify_event_type when;
	X{
	X	/* check for L7 key and close frame if found */
	X	/*** DEBUG ***/
	X	/*
	X	fprintf(stderr, "checking for L7: event = %d\n", event_id(event));
	X	*/
	X	if (event_id(event) == KEY_LEFT(7) && event_is_up(event))
	X		return (myframe_interposer(client, event, arg, when));
	X	else
	X		return (notify_next_event_func(client, event, arg, when));
	X}
	X
	Xclose_frame()
	X{
	X	Icon cur_icon;
	X
	X	/* save some information as we close */
	X	if (mainsw_state == DISPLAYING_DAY && day_is_open)
	X		close_day();
	X	/* if frame not closed yet, close it now (for the canvas) */
	X	if (!(int)window_get(frame, FRAME_CLOSED))
	X		window_set(frame, FRAME_CLOSED, TRUE, 0);
	X	olddate = current;
	X	if (fframe) {
	X		/* kill off future appt popup */
	X		window_destroy(fframe);
	X		fframe = 0;
	X	}
	X#ifndef NO_SUN_MOON
	X	/* kill sun/moon data frames */
	X	if (mframe)
	X		mframe_done(0);
	X	if (sframe)
	X		sframe_done(0);
	X#endif
	X	check_calendar();	/* update icon */
	X	if (show_time) {
	X		/* update time label */
	X		strcpy(timestr, todays_date+10);
	X		if (update_interval == 60)
	X			/* display hh:mm */
	X			timestr[6] = '\0';
	X		else
	X			/* display hh:mm:ss */
	X			timestr[9] = '\0';
	X		cur_icon = (Icon) window_get(frame, FRAME_ICON);
	X		icon_set(cur_icon, ICON_LABEL, timestr, 0);
	X		window_set(frame, FRAME_ICON, cur_icon, 0);
	X	}
	X}
SHAR_EOF
if test 6577 -ne "`wc -c < 'event.c'`"
then
	echo shar: error transmitting "'event.c'" '(should have been 6577 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'event.h'" '(1462 characters)'
if test -f 'event.h'
then
	echo shar: will not over-write existing file "'event.h'"
else
sed 's/^	X//' << \SHAR_EOF > 'event.h'
	X/*
	X * $Header: event.h,v 2.1 89/05/09 14:25:16 billr Exp $
	X */
	X/*
	X * event.h
	X *
	X * Author: Philip Heller, Sun Microsystems. Inc. <terrapin!heller@sun.com>
	X *
	X * Original source Copyright (C) 1987, Sun Microsystems, Inc.
	X *	All Rights Reserved
	X * Permission is hereby granted to use and modify this program in source
	X * or binary form as long as it is not sold for profit and this copyright
	X * notice remains intact.
	X *
	X *
	X * Changes/additions by: Bill Randle, Tektronix, Inc. <billr@saab.CNA.TEK.COM>
	X *
	X * Changes and additions Copyright (C) 1988, 1989 Tektronix, Inc.
	X *	All Rights Reserved
	X * Permission is hereby granted to use and modify the modifications in source
	X * or binary form as long as they are not sold for profit and this copyright
	X * notice remains intact.
	X */
	X
	Xextern struct dayslot slots[];
	Xextern int mainsw_state, day_is_open;
	Xextern struct rect_limits boxlims[];
	Xextern struct rect_limits mboxlims[];
	Xextern int selected_type, read_only, new_entry;
	Xextern int dayslot_width, nr_weekdays, day_message_size;
	Xextern int dayslot_height, weekslot_height, weekslot_width;
	Xextern int ybox_height, ybox_width;
	Xextern struct weekrect week_boxes[];
	Xextern Pixwin *main_pixwin;
	Xextern Pixfont *font;
	Xextern Cursor month_cursor, week_cursor, day_cursor;
	Xextern Pixrect *smallarrow_pr, *arrowhead_pr, *arrowshaft_pr;
	Xextern struct week_arrow week_arrows[];
	Xextern struct tm current;
	Xextern struct tm today;
	Xextern Pixrect *timeslot_td_pr, *morebutton;
	X
SHAR_EOF
if test 1462 -ne "`wc -c < 'event.h'`"
then
	echo shar: error transmitting "'event.h'" '(should have been 1462 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0