/*

 CAL.c

 -- Einfacher Kalender für die Workbench --

 -- Aztec C 3.4a	Läuft *nicht* auf Lattice!

 by	Dietmar Till  11-Mar-89 - 14-May-89

*/




#include <exec/types.h>
#include <intuition/intuition.h>
#include <graphics/gfxbase.h>
#include <graphics/text.h>
#include <devices/timer.h>
#include <libraries/diskfont.h>

#include <functions.h> /* Aztec specific ! */
#include <time.h>

/* ======================================= */
/* ========== USER DEFINES =============== */
/* ======================================= */

#define SCREENTITLE "CALENDAR V1.2
					 (C) CopyRight 1989, MAXON\0"


#define MAX_TIME 250000L	 /* Zeit zwischen
										 Updates */

/* ======================================= */
/* ======================================= */
/* ======================================= */

struct IntuitionBase *IntuitionBase=NULL;
struct GfxBase *GfxBase=NULL;

struct Window *MyWin=NULL;

struct IntuiMessage *imess=NULL;
struct RastPort *MyRP;

struct TextFont *topaz9_font, *topaz8_font;

struct timerequest *tir=NULL, *CreateExtIO();
struct MsgPort *tirport=NULL, *CreatePort();
						/* Port für timer.device */

void OpenStuff(), CloseStuff();
							/* forward references */
void Mark_Current(), Update_Win();


char *mon_names[] = { /* Namen der einzelnen */
	 "January", 		 /* Monate					*/
	 "February",		 /* Wer will, kann sie	*/
	 "March",			 /* ins Deutsche über-	*/
	 "April",			 /* setzen					*/
	 "May",
	 "June",
	 "July",
	 "August",
	 "September",
	 "October",
	 "November",
	 "December"
};

struct TextAttr Topaz9Attr = {
									 /* Topaz 9 Font */
	 (STRPTR)"topaz.font", TOPAZ_SIXTY,
	 FS_NORMAL, FPF_ROMFONT
};

struct TextAttr Topaz8Attr = {
									 /* Topaz 8 Font */
	 (STRPTR)"topaz.font", TOPAZ_EIGHTY,
	 FSF_BOLD, FPF_ROMFONT
};

struct NewWindow MyNw = {			/* Window */
	 100,100, 231,95,-1,-1, CLOSEWINDOW,
	 SMART_REFRESH|NOCAREREFRESH|WINDOWDRAG|
	 WINDOWDEPTH|WINDOWCLOSE, NULL,
	 NULL, NULL, NULL, NULL,
	 0,0,0,0, WBENCHSCREEN
};

_main()
/* Keine Standard Ein-Ausgabe,
	darum Aztec _main() nicht er-*/

/* forderlich -> geringere Codegröße  */

{
	 int act_day1=0, act_day2=0, act_mon1=0,
		  act_mon2=0;
	 static struct tm *mytm;
	 ULONG mics, secs, class, sigmask;
	 USHORT code;
	 char ct[10];

	 OpenStuff(); /* Libaries öffnen ... etc */

	 CurrentTime(&secs,&mics);
					  /* aktuelle Zeit ermitteln */
	 mytm = localtime(&secs);
					  /* in tm-struct umwandeln  */
	 Update_Win(mytm); /* Windows updaten	  */
	 act_day1=mytm->tm_mday;

	 /* Wir warten jetzt auf den
		 Timer oder Intuition ... */

	 sigmask = 1L << MyWin->UserPort->mp_SigBit
				  | 1L << tirport->mp_SigBit;

	 FOREVER
	 {
	tir->tr_node.io_Command = (UWORD)TR_ADDREQUEST;
	tir->tr_time.tv_secs = 0L;
	tir->tr_time.tv_micro = MAX_TIME;

	SendIO(tir);		/* asynchroner i/o */

	Wait(sigmask);
			  /* auf timer/intui-msg warten */

	/* Timer-Message */
	if (GetMsg(tirport)) {
						/* Juhu !! eine Message */

		 CurrentTime(&secs,&mics);
						/* akt. Zeit */
		 mytm=localtime(&secs);
						/* ANSI-Funktion */

		 /* Überprüfen: ist der Fensterinhalt noch
		  * aktuell (Tag, Monat) ?
		  */

		 act_day2=mytm->tm_mday;
		 act_mon2=mytm->tm_mon;
		 if(act_day2 != act_day1 ||
			 act_mon2 != act_mon1)
		Update_Win(mytm); /* nicht mehr
									aktuell */
		 act_day1=act_day2;
		 act_mon1=act_mon2;

		 /* Aktuelle Zeit in Format hh:ss:mm
		  * ausdrucken in oberen Fensterrand
		  */

		 sprintf(ct,"%02d:%02d:%02d\0",
		 mytm->tm_hour,mytm->tm_min,
		 mytm->tm_sec);
						  /* in String ct */

		 SetFont(MyRP,topaz8_font);

		 SetAPen(MyRP,1L);
		 SetDrMd(MyRP,JAM2);
		 Move(MyRP,30L,7L);
		 Text(MyRP,ct,(LONG)strlen(ct));
				  /* In Rastport schreiben */

	}
	/* Intuition- Message */
	if(imess = (struct IntuiMessage *)
					GetMsg(MyWin->UserPort))  {


		 class = imess->Class;
		 code = imess->Code;

		 ReplyMsg(imess);

		 switch(class) { /* Close-Gadget ... */

		case CLOSEWINDOW:   CloseStuff();
					 break;
		 }
	}
	 }
}


VOID Mark_Current(x,y)
				  /* Aktuelles Datum markieren */
	 LONG x,y;
{
	 static SHORT bpairs[] = {
	0,0,30,0,30,10,0,10,0,0
	 };
	 static struct Border Mark_it = {
	0,0,3,1,JAM1,5,bpairs,NULL
	 };
	 DrawBorder(MyRP, &Mark_it,(long)x+4L,
					(long)y-8L);
					/* Einen Rahmen zeichnen */
}


VOID Update_Win(mytm)	 /* Routine, die den
						 Fensterinhalt zeichnet */
	 struct tm *mytm;
{
	 register int i, first_wd, days;
	 register long x,y;
	 static char buf[4], buf2[25];
	 static char title[]="Su Mo Tu We
								 Th Fr Sa\0";

	 /* Standard Einstellungen für den
		 Rastport */

	 Move(MyRP,0L,0L);
	 ClearScreen(MyRP);
	 SetRast(MyRP,2L);
	 SetAPen(MyRP,1L);
	 SetDrMd(MyRP, JAM1);
	 SetFont(MyRP,topaz9_font);
									/* lesbarer */

	 /* erster Tag im Monat war ein ?
		 Dazu wird eine ANSI-C Standard-
		 Struktur benutzt
		 Rechnen mit den AMIGA Zeitformaten
		 entfällt !!! */


	 first_wd=first_d_m(mytm->tm_wday,
							  mytm->tm_mday);

	 /* Wieviele Tage hat der Monat ? */

	 days= days_p_m(mytm->tm_mon,mytm
						 ->tm_year);

	 for(i=1;i<=days;i++)
					  /* Kalender printen */
	 {
	sprintf(buf,"%3d",i);
						/* jeweiliger Tag in
							String formatieren ... */

	/* Berechnung der x/y Koordinaten
		des jeweiligen Tages */

	x=((long)(first_wd+i-1)%7L)*30L+5L;
	y=((long)(first_wd+i-1)/7L)*10L+29L;

	/* Aktuelles Datum markieren */
	if(i == mytm->tm_mday) Mark_Current(x,y);

	if((first_wd+i-1) % 7)
							/* Werktage normal */
		 SetAPen(MyRP,1L);
	else			/* Sonntage in rot */
		 SetAPen(MyRP,3L);

	Move(MyRP,(long)x,(long)y);
	Text(MyRP,buf,3L);
					 /* Datum schreiben ... */
	 }

	 /* Titelzeile: So Mo Tu  ... */

	 Move(MyRP,15L,18L);
	 SetAPen(MyRP,1L);
	 Text(MyRP,title,(long)strlen(title));

	 /* Monat & Jahr printen (unten)*/

	 sprintf(buf2,"%-16s19%2d\0",mon_names[mytm
				->tm_mon],mytm->tm_year);
	 Move(MyRP,15L,90L);
	 Text(MyRP,buf2,(long)strlen(buf2));

	 RefreshWindowFrame(MyWin);
				 /* wegen SetRast(..,..) */
				 /* Schwarzer Hintergrund, Window-
					Begrenzungen refreshen */

}


int first_d_m(wday, mday)
		  /* Erster Tag im Monat war ein .. */
	 int wday, mday; /* Die Billig-Routine */
{
	 int i, f_wday=wday;

	 for(i=mday;i>1;i--) {
					 /* einfach herunterzählen */
	--f_wday;	/* Tage des aktuellen Datums
						und die */
	if(f_wday < 0) f_wday=6; /* Wochentage */
	 }
	 return(f_wday);
}

int days_p_m(mon, year)  /* Tage pro Monat */
	  int mon, year;
{
	 static int dpm[12] = /* Tage pro Monat */
	{31,28,31,30,31,30,31,31,30,31,30,31};

	 if(mon==1 && year%4==0 ) /* Schaltjahr */
	dpm[1] = 29;

	 return(dpm[mon]);
}



VOID OpenStuff()	  /* Das Übliche */
{
  if((IntuitionBase = (struct IntuitionBase *)
 OpenLibrary("intuition.library",0L)) == NULL)
		 exit(FALSE);

  if((GfxBase = (struct GfxBase *)OpenLibrary
					 ("graphics.library",0L)) == NULL)
	 CloseStuff();
  if(!(MyWin=(struct Window *)OpenWindow(&MyNw)))
	  CloseStuff();

	 tirport = CreatePort(0L,0L);
	 if(!tirport) CloseStuff();

	 tir = CreateExtIO(tirport,(long)sizeof(struct timerequest));
	 if(tir == NULL)	CloseStuff();

	 if (OpenDevice(TIMERNAME,UNIT_VBLANK,tir,0L))
	CloseStuff();

	 SetWindowTitles(MyWin,(LONG)-1,(UBYTE *)SCREENTITLE);

	 MyRP=MyWin->RPort;		 /* Rastport */

	 /* Default Font Settings : */

	 topaz9_font = (struct TextFont *)OpenFont(&Topaz9Attr);
	 topaz8_font = (struct TextFont *)OpenFont(&Topaz8Attr);

}


VOID CloseStuff()   /* Alles schliessen, ende ... */
{
	 if (tir) {
		 AbortIO(tir); 	 /* Wir warten brav */
		 WaitIO(tir);
		 CloseDevice(tir);
		 DeleteExtIO(tir);
	 }
	 if (tirport)		  DeletePort(tirport);
	 if (MyWin) 		  CloseWindow(MyWin);
	 if (IntuitionBase) CloseLibrary(IntuitionBase);
	 if (GfxBase)		  CloseLibrary(GfxBase);
	 exit(TRUE);
}


/**/

