/*****************************************************************************
 * Program		: LastLogin.c 					     *
 * Compiler		: SAS/C V5.10					     *
 * Compiler-Options	: -cafst -ma -v -O [-dGERMAN] LastLogin.c	     *
 * Linker-Options	: lc.lib + amiga.lib SC SD ND			     *
 * ------------------------------------------------------------------------- *
 * Subject		: Shows last interactive login.			     *
 * Author		: Stephan Holters				     *
 *									     *
 * Date       | Version | Remarks  					     *
 * -----------|---------|--------------------------------------------------- *
 * 21.04.91   |  v0.1	| first test version				     *
 * 25.04.91   |  v0.2   | workbench interface added			     *
 * 05.05.91   |  v0.3   | _main() modul added				     *
 * 08.05.91   |  v1.0   | final version					     *
 *****************************************************************************/

/*****************************************************************************
 *									     *
 * Includes:								     *
 *									     *
 *****************************************************************************/
#include <exec/types.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <workbench/workbench.h>
#include <workbench/icon.h>
#include <workbench/startup.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ios1.h>
#include <fcntl.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/icon.h>
#include "timer.h"	/* (c) by Timm Martin */

/*****************************************************************************
 *									     *
 * Defines:								     *
 *									     *
 *****************************************************************************/
#define LIB_VERSION	33L	/* Use at least Kickstart/Workbench 1.2 */
#define WINWIDTH	280
#define MAX_SECS	1000
#define FILENAME_LENGTH 100
#define DEFAULT_SECS	5
#define DEFAULT_FILE	"DEVS:LAST_LOGIN"
#define WINDOWTITLE	"LastLogin V1.0 (c) St. Holters"

/*****************************************************************************
 *									     *
 * External variables:							     *
 *									     *
 *****************************************************************************/
extern struct IntuitionBase 	*IntuitionBase;
extern struct WBStartup 	*WBenchMsg;
extern struct UFB 		_ufbs[];

/*****************************************************************************
 *									     *
 * Global variables:							     *
 *									     *
 *****************************************************************************/
struct Screen 	*scr;
struct Window 	*win;
SHORT 		delaysecs;
char		datestring[31];
char 		filename[FILENAME_LENGTH];
char		*version = "$VER: LastLogin v1.0 (8-May-91)";
BOOL 		wbstart = TRUE;
BPTR 		errfh;	/* standard I/O error */

/*
Fill out NewWindow structure:
*/
struct NewWindow new_window =
{
  /*  LeftEdge		*/ 0,
  /*  TopEdge		*/ 0,
  /*  Width		*/ WINWIDTH,
  /*  Height		*/ 56,
  /*  DetailPen		*/ 0,
  /*  BlockPen		*/ 1,
  /*  IDCMPFlags	*/ MOUSEBUTTONS,
  /*  Flags		*/ NOCAREREFRESH|SIMPLE_REFRESH,
  /*  FirstGadget	*/ NULL,
  /*  CheckMark		*/ NULL,
  /*  Title		*/ (UBYTE *)WINDOWTITLE,
  /*  Screen		*/ NULL,
  /*  BitMap		*/ NULL,
  /*  MinWidth		*/ 280,
  /*  MinHeight		*/ 56,
  /*  MaxWidth		*/ 640,
  /*  MaxHeight		*/ 200,
  /*  Type		*/ WBENCHSCREEN,
};

/*
Use Topaz80 font for our text:
*/
struct TextAttr my_font=
{
	(UBYTE *)"topaz.font",	/* Font Name */
	TOPAZ_EIGHTY,		/* Font Height */
	FS_NORMAL,		/* Style */
	FPF_ROMFONT		/* Preferences */
};

struct IntuiText itext3 =
{
	1, 2,		/* FrontPen, BackPen */
	JAM1,		/* DrawMode */
	0, 0,		/* LewftEdge, TopEdge will be set later*/
	&my_font,	/* *ITextFont */
	NULL,		/* *IText will be set later*/
	NULL		/* *NextText */
};

struct IntuiText itext2 =
{
	1, 2,		/* FrontPen, BackPen */
	JAM1,		/* DrawMode */
	0, 0,		/* LewftEdge, TopEdge will be set later*/
	&my_font,	/* *ITextFont */
	NULL,		/* *IText will be set later*/
	&itext3		/* *NextText */
};

struct IntuiText itext1 =
{
	1, 2,		/* FrontPen, BackPen */
	JAM1,		/* DrawMode */
	32, 0,		/* LeftEdge, TopEdge */
	&my_font,	/* *ITextFont */
#ifdef GERMAN
	(UBYTE *)"Letzte interaktive Nutzung:",/* *IText */
#else
	(UBYTE *)"  Last interactive login:", /* *IText */
#endif
	&itext2		/* *NextText */
};

/*
Declare a custom date structure, where we can put in computed values from
the »DateStamp« structure:
*/
struct c_Date
{
	char weekday[11];
	char monthname[4];
	USHORT day;
	USHORT year;
	USHORT hour;
	USHORT min;
	USHORT sec;
};

/*****************************************************************************
 *									     *
 * Prototypes:		 						     *
 *									     *
 *****************************************************************************/
void _main(char *);
void main(int argc, char *argv[]);
void ErrorMessage(char *);
void CloseAll(void);
void OpenAll(void);
void window_input(void);
void CheckCLIArgs(int argc, char *argv[]);
void CheckWBArgs(void);
char *GetTimePeriod(struct DateStamp *, struct DateStamp *);
void GetDateString(char dstring[31], struct c_Date *);
BOOL GetFileDate(struct DateStamp *);
struct c_Date CvtDate(struct DateStamp *);
BOOL WriteDateString(char *);
BOOL LeapYear(ULONG);
static struct Screen *FindWB(void);

/*****************************************************************************
 *									     *
 * Functions:           						     *
 *									     *
 *****************************************************************************/
/*
This function opens »Intuition« and everything we need for the timer:
*/
void OpenAll(void)
{
	if (!(IntuitionBase = (struct IntuitionBase *)OpenLibrary( "intuition.library", LIB_VERSION)))
	{
		ErrorMessage("Problems with intuition.");
		CloseAll();
	}

	/*
	open timer-stuff
	*/
	if (!timer_open())
	{
		ErrorMessage("Problems with timer");
		CloseAll();
	}
}

/*
Since AmigaOS/Exec does not support »Resource-Tracking« ability, like Unix,
we have to clean up everything:
*/
void CloseAll(void)
{
	timer_close();

	if (win)
		CloseWindow(win);
	if (IntuitionBase)
		CloseLibrary((struct Library *)IntuitionBase);

	exit(0);
}

/*
This function prints an error-message to standard I/O. This can be either
a new Output-Window, or the CLI-Window.
*/
void ErrorMessage(char *error)
{
	if (wbstart)
	{
		/* We must open a new window */
		if (!(errfh = Open("RAW:60/50/320/100/Error message:", MODE_NEWFILE)))
			CloseAll();
		else
		{
			/*
			Set up standard I/O
			*/
			_ufbs[2].ufbfh = (LONG)errfh;
			_ufbs[2].ufbflg |= UFB_WA|O_RAW|UFB_NC;
			stderr->_file = 2;
			stderr->_flag = _IOWRT;
			setbuf(stderr, NULL);

			fprintf(stderr, "LastLogin ERROR: %s\n", error);
			Delay(500L); /* wait 5 secs */
			Close(errfh);
		}
	}
	else
	{
		/* Use the current I/O stream (CLI) */
		if (!(errfh = Open("*", MODE_OLDFILE)))
			CloseAll();
		/*
		Set up standard I/O
		*/
		_ufbs[2].ufbfh = (LONG)errfh;
		_ufbs[2].ufbflg |= UFB_WA|O_RAW|UFB_NC;
		stderr->_file = 2;
		stderr->_flag = _IOWRT;
		setbuf(stderr, NULL);

		if (error)
			fprintf(stderr, "LastLogin ERROR: %s\n", error);

		fprintf(stderr,"\x1B[1mLastLogin\x1B[m V1.0\n");
		fprintf(stderr,"(c) Apr\'91 by Stephan Holters. All rights released.\n\n");
		fprintf(stderr,"USAGE  : LastLogin [-fFILENAME] [-dDELAY]\n");
		fprintf(stderr,"Example: LastLogin -fDEVS:LAST_LOGIN -d10\n");
		Close(errfh);
	}
}

/*
Search for Workbench-Screen to get its characteristics
MUST be called with IntuitionBase locked! (Thanks to Ralph Babel)
*/
static struct Screen *FindWB(void)
{
	struct Screen *s;
	for (s = IntuitionBase->FirstScreen; s != NULL; s = s->NextScreen)
		if ((s->Flags & SCREENTYPE) == WBENCHSCREEN)
			break;
	return s;
}

/*
Check Workbench-Arguments:
*/
void CheckWBArgs(void)
{
	struct WBArg *wbArg;
	char   **toolArray;
	char   *string;
	struct DiskObject *diskObj;
	struct IconBase	*IconBase;

	if(IconBase = (struct IconBase *) OpenLibrary("icon.library",LIB_VERSION))
	{
		wbArg = WBenchMsg->sm_ArgList;
		diskObj = (struct DiskObject *)GetDiskObject(wbArg->wa_Name);
		if(diskObj)
		{
			toolArray = diskObj->do_ToolTypes;
			if(string = (UBYTE *)FindToolType(toolArray,"DELAY"))
			{
				delaysecs = atoi(string);
				if (delaysecs < 1 || delaysecs > MAX_SECS)
					delaysecs = DEFAULT_SECS;
			}
			if(string = (UBYTE *)FindToolType(toolArray,"FILE"))
			{
				if (*string != '\0')
				{
					strncpy(filename, string, FILENAME_LENGTH-1);
					filename[FILENAME_LENGTH-1] = '\0';
				}
			}
			FreeDiskObject(diskObj);
		}
		CloseLibrary((struct Library *)IconBase);
	}
}

/*
Check CLI-Arguments:
*/
void CheckCLIArgs(int argc, char *argv[])
{
	char *p;

	if (argc-- >= 1)
		*argv++;

	while (argc > 0)
	{
		argc--;		/* Substract prog-name from argument count*/
		p = *argv++;	/* Get first argument pointer and point to next */

		if (*p != '-')  /* Error in command line? */
		{
			if (*p == '?')	/* Show usage */
			{
				ErrorMessage(NULL);
				CloseAll();
			}
			else
			{
				ErrorMessage("reading command line.");
				CloseAll();
			}
		}
		else
		{
			p++;
			switch (*p) {
				case 'f':	/* Filename */
				case 'F':
					strncpy(filename, ++p, FILENAME_LENGTH-1);
					filename[FILENAME_LENGTH-1] = '\0';
					break;
				case 'd':	/* DELAY_SECS */
				case 'D':
					delaysecs = atoi(++p);
					if (delaysecs < 1 || delaysecs > MAX_SECS)
						delaysecs = DEFAULT_SECS;
					break;
			    	default:	/* command line error */
					ErrorMessage("Unknown arguments.");
					CloseAll();
			}
		}
	}
}

/*
This function monitors for window input.  It returns when the user clicks on
the window close gadget. (Originally from Timm Martin.)
*/
void window_input(void)
{
	BOOL finished;
	struct IntuiMessage *imessage;
	BOOL winput;

	finished = FALSE;
	while (!finished)
	{
	/* ask the timer to notify you in 'delaysecs'-seconds */
	timer_start(delaysecs * MICROS_PER_SEC);
	/* assume there is no window input */
	winput = FALSE;

	/* wait for input from the window and the timer device */
	Wait(1L<<win->UserPort->mp_SigBit | 1L<<timer_port->mp_SigBit);

	/* for each window input message */
	while (imessage = (struct IntuiMessage *)GetMsg(win->UserPort))
	{
		switch (imessage->Class)
		{
			case MOUSEBUTTONS:
				/* end the program */
				if (imessage->Code == SELECTDOWN)
					finished = TRUE;
				break;
		}
		/* reply to the message to free its memory */
		ReplyMsg((struct Message *)imessage);
	}

	/* did the timer request elapse? */
	if (timer_test())
	{
		/* if 'winput' is FALSE, then the timer elapsed before there was any
		* window input. If 'winput' is TRUE, then the timer elapsed after
		* the window input but before it reached this test.
		*/
		if (!winput)
			finished = TRUE;
	}
	/* if the timer request didn't elapse, cancel it so we can issue another
	* request
	*/
	else
		timer_abort();
	}
}

/*
Write new date to file:
*/
BOOL WriteDateString(char writestring[31])
{
	FILE 	*fp;

	if (!(fp = fopen(filename,"w")))
		return(FALSE);
	else
	{
		fprintf(fp,"%s\n",writestring);
		fclose(fp);
	}
	return(TRUE);
}

/*
This function finds out the date of creation of a specific file:
*/
BOOL GetFileDate(struct DateStamp *dstamp)
{
	BPTR			*fl = 0L;
	struct FileInfoBlock	*fib = 0L;

	/* First, lock the file */
	if (!(fl = (BPTR *)Lock(filename, (ULONG)ACCESS_READ)))
	{
		/* File cannot be locked */
		return FALSE;
	}
	/* Get some momory for the FIB */
	if (!(fib = (struct FileInfoBlock *)AllocMem((ULONG)sizeof(struct FileInfoBlock),
			(ULONG)MEMF_CHIP)))
	{
		/* Can't get enough memory */
		UnLock((BPTR)fl);
		return FALSE;
	}
	/* Examine the file */
	if (!Examine((BPTR)fl, fib))
	{
		/* Error examine file */
		UnLock((BPTR)fl);
		FreeMem(fib, (ULONG)sizeof(struct FileInfoBlock));
		return FALSE;
	}
	/* If everything is ok, we can copy the date */
	dstamp->ds_Days = fib->fib_Date.ds_Days;
	dstamp->ds_Minute = fib->fib_Date.ds_Minute;
	dstamp->ds_Tick = fib->fib_Date.ds_Tick;

	/* Now clean up everything and return */
	UnLock((BPTR)fl);
	FreeMem(fib, (ULONG)sizeof(struct FileInfoBlock));
	return TRUE;
}

/*
This function simply creates a string of information from the c_Date structure:
*/
void GetDateString(char dstring[31], struct c_Date *cdate)
{
#ifdef GERMAN
	sprintf(dstring, "%s %02d-%s-%02d %02d:%02d:%02d",
		cdate->weekday, cdate->day, cdate->monthname, cdate->year,
		cdate->hour, cdate->min, cdate->sec);
#else
	sprintf(dstring, "%s %s-%02d-%02d %02d:%02d:%02d",
		cdate->weekday, cdate->monthname, cdate->day, cdate->year,
		cdate->hour, cdate->min, cdate->sec);
#endif
}

/*
Look, if it is a leap-year:
*/
BOOL LeapYear(ULONG Year)
{
	if ((((Year/4L)*4L) == Year) && (((Year/100L)*100L) != Year))
		return (TRUE);
	else
		return (FALSE);
}

/*
This function finds out the current date of the »DateStamp« structure, and puts
the computed values in our custom date structure:
*/
struct c_Date
CvtDate(struct DateStamp *dstamp)
{
	UBYTE		WeekDay;
	ULONG		Month, Days, Year;
	struct c_Date	cdate;

#ifdef GERMAN
	static char *MonthTable[12] = {
		"Jan", "Feb", "Mär", "Apr", "Mai", "Jun",
		"Jul", "Aug", "Sep", "Okt", "Nov", "Dez" };
	static char *DayTable[7] = {
		"Sonntag", "Montag", "Dienstag", "Mittwoch",
		"Donnerstag", "Freitag", "Samstag" };
#else
	static char *MonthTable[12] = {
		"Jan", "Feb", "Mar", "Apr", "May", "Jun",
		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
	static char *DayTable[7] = {
		"Sunday", "Monday", "Tuesday", "Wednesday",
		"Thursday", "Friday", "Saturday" };
#endif

	static ULONG DaysOfMonth[] = {
		31L,28L,31L,30L,31L,30L,31L,31L,30L,31L,30L,31L};

	Days 	= dstamp->ds_Days;
	WeekDay = Days % 7;
	Year 	= 78L;		/* Base year */

	while (Days >= 365L)
	{
		if(LeapYear(Year))
			 Days -= 366L;
		else
			 Days -= 365L;
		Year++;
	}

	if (Year >= 100L)	/* substract 100 if year > 1999 */
		Year -= 100;

	if (LeapYear(Year))
		DaysOfMonth[1] = 29L;
	else
		DaysOfMonth[1] = 28L;

	for (Month = 0L; Days >= DaysOfMonth[Month]; Month++)
		Days -= DaysOfMonth[Month];

	Days++;

	/* Copy DateStamp-structure to c_Date-structure */
	cdate.year	= (USHORT)Year;
	cdate.day 	= (USHORT)Days;
	cdate.hour	= (USHORT)(dstamp->ds_Minute / 60L);
	cdate.min	= (USHORT)(dstamp->ds_Minute % 60L);
	cdate.sec	= (USHORT)(dstamp->ds_Tick   / 50L);
	strncpy(cdate.weekday, DayTable[WeekDay], 11);
	strncpy(cdate.monthname, MonthTable[Month], 4);

	return cdate;
}

/*
Choose the right verbal comment of the period of time between
the old and the new date. (That means the period between last login and
the actual date):
*/
char *GetTimePeriod(struct DateStamp *new, struct DateStamp *old)
{
	LONG daydiff;		/* CAUTION: daydiff MUST be LONG (not ULONG)
					    because daydiff can be negative */
	char *timeperiod;
#ifdef GERMAN
	static char *const TimePeriodTable[12] = {
		" ",	/* if a date-error occured */
		"Heute", "Gestern", "Vorgestern", "Heute vor einer Woche",
		"Vor über einer Woche", "Heute vor zwei Wochen",
		"Vor mehr als zwei Wochen", "Heute vor drei Wochen",
		"Vor mehr als drei Wochen", "Vor über einem Monat",
		"Vor über einem Jahr"
	};
#else
	static char *const TimePeriodTable[12] = {
		" ",	/* if a date-error occured */
		"Today", "Yesterday", "The day before yesterday", "One week ago",
		"More than one week ago", "Two weeks ago",
		"More than two weeks ago", "Three weeks ago",
		"More than three weeks ago", "One month ago",
		"More than one year ago"
	};
#endif
	daydiff = new->ds_Days - old->ds_Days;

	if ((daydiff >= 0L) && (daydiff < 3L))
	{
		switch (daydiff)
		{
			case 0L:
				timeperiod = TimePeriodTable[1];
				break;
			case 1L:
				timeperiod = TimePeriodTable[2];
				break;
			case 2L:
				timeperiod = TimePeriodTable[3];
				break;
		}
		return timeperiod;
	}
	else if ((daydiff >= 3L) && (daydiff < 7L))
#ifdef GERMAN
		sprintf(timeperiod, "Vor %ld Tagen", daydiff);
#else
		sprintf(timeperiod, "%ld days ago", daydiff);
#endif
	else if (daydiff == 7L)
		timeperiod = TimePeriodTable[4];
	else if ((daydiff > 7L) && (daydiff < 14L))
		timeperiod = TimePeriodTable[5];
	else if (daydiff == 14L)
		timeperiod = TimePeriodTable[6];
	else if ((daydiff > 14L) && (daydiff < 21L))
		timeperiod = TimePeriodTable[7];
	else if (daydiff == 21L)
		timeperiod = TimePeriodTable[8];
	else if ((daydiff > 21L) && (daydiff < 31L))
		timeperiod = TimePeriodTable[9];
	else if ((daydiff >= 31L) && (daydiff < 61L))
		timeperiod = TimePeriodTable[10];
	else if ((daydiff >= 61L) && (daydiff <365L))
#ifdef GERMAN
		sprintf(timeperiod, "Vor mehr als %ld Monaten", daydiff/30L);
#else
		sprintf(timeperiod, "More than %ld months ago", daydiff/30L);
#endif
	else if ((daydiff >= 365L) && (daydiff < 730L))
		timeperiod = TimePeriodTable[11];
	else if (daydiff >= 730L)
#ifdef GERMAN
		sprintf(timeperiod, "Vor mehr als %ld Jahren", daydiff/365L);
#else
		sprintf(timeperiod, "More than %ld years ago", daydiff/365L);
#endif
	else
		timeperiod = TimePeriodTable[0];

	return timeperiod;
}

/*****************************************************************************
 *									     *
 * Std. preprocessing for the main module:				     *
 *									     *
 *****************************************************************************/
/*
I decided to add this SAS/C-specific main module, to avoid the disturbing Output-
Window of the »c.o« startup module. The »c.o« startup module opens a standard
I/O window (for stdin, stdout, stderr) each time you start the program from
the workbench. That is annoying.

»_main()« does not open a standard I/O window. The disadvantage of »_main()« is,
that it does not support the common »argc, *argv[]« parameters like »main«, but
a points to a simple string of the commandline. So it is necessary to extract
each argument from the commandline.

Another disadvantage is the inconvenient standard output. (very slow !?)

Is there anybody, who has a better idea to avoid the default I/O window?
*/

void _main(char *line)
{
	char *argv[81];
	int argc;

	argc = 0;
	if (line == NULL)
		goto mainline;
	/*
	Now examine the commandline, and extract each argument:
	*/
	for (;;)
	{
		while (*line == ' ' || *line == '\t' || *line == '\n')
			line++;
		if (*line == 0)
			break;
		if (argc == 32)
		{
			argc = 0;
			goto mainline;
		}
		if (*line == '"')
		{
			argv[argc] = ++line;
			while (*line != '"')
			{
				if (*line == 0)
				{
					argc = 0;
					goto mainline;
				}
				line++;
			}
		}
		else
		{
			argv[argc] = line;
			while (*line != ' ' && *line != '\t' && *line != '\n')
			{
				if (*line == 0)
				{
					argc++;
					goto mainline;
				}
				line++;
			}
		}
		*line++ = 0;
		argc++;
	}

mainline:
	/*
	Call the main program
	*/
	main(argc, argv);
}



/*****************************************************************************
 *									     *
 * Main:								     *
 *									     *
 *****************************************************************************/
void main(int argc, char *argv[])
{
	SHORT winheight;
	ULONG lock;
	char newdatestring[31], olddatestring[31];
	struct DateStamp sysnew, sysold;
	struct c_Date newdate, olddate;
	char *timeperiodstring = " ";
	BOOL filestatus = TRUE;

	strcpy(filename, DEFAULT_FILE);

	/*
	Set default values:
	*/
	delaysecs = DEFAULT_SECS;
	strcpy(filename, DEFAULT_FILE);

	/*
	Check out args:
	*/
	if (argc)	/* CLI - Args */
	{
		wbstart = FALSE;
		CheckCLIArgs(argc, argv);
	}
	else		/*  WB - Args */
		CheckWBArgs();

	/*
	Open Lib's and timer-stuff
	*/
	OpenAll();

	/*
	Get the date of last modification from the file:
	*/
	if (!(filestatus = GetFileDate(&sysold)))
	{
#ifdef GERMAN
		strcpy(olddatestring,"------- Kein Datum -------");
#else
		strcpy(olddatestring,"-------   No date  -------");
#endif
	}
	else
	{
		olddate = CvtDate(&sysold);	/* Convert DateStamp to CustomDateFormat */
		GetDateString(olddatestring, &olddate); /* Build string of date */
	}

	/*
	Find out actual system-date:
	*/
	DateStamp(&sysnew);
	newdate = CvtDate(&sysnew);
	GetDateString(newdatestring, &newdate);

	/*
	Get the period between last login and actual date:
	*/
	if (filestatus)
		timeperiodstring = GetTimePeriod(&sysnew, &sysold);

	/*
	Save new date to file
	*/
	if (!WriteDateString(newdatestring))
		ErrorMessage("Can't write date to file");

	/*
	If everything is ok so far, open the window and
	wait for user-mouseclick or timer-event.

	Find out window characteristics:
	*/
	lock = LockIBase(0); 	/* Lock IBase, before calling FindWB() */
	if ((scr = FindWB()) != NULL)
	{
		new_window.Height = winheight = (scr->BarHeight) + 45;
		new_window.LeftEdge = (scr->Width-280)/2;
		new_window.TopEdge = (scr->Height-winheight)/2;
	}
	else
	{
		/* If there is no WB-screen, exit silent */
		UnlockIBase(lock);
		CloseAll();
	}
	UnlockIBase(lock);

	/*
	Open output window:
	*/
	if (!(win = (struct Window *)OpenWindow( &new_window )))
	{
		ErrorMessage("Can't open window");
	  	CloseAll();
	}

	/*
	Print text in our window:
	*/
	itext1.TopEdge = win->BorderTop + 6;
	itext2.TopEdge = win->BorderTop + 20;
	itext2.LeftEdge = (WINWIDTH - (strlen(timeperiodstring)*8))/2;
	itext2.IText = timeperiodstring;
	itext3.TopEdge = win->BorderTop + 30;
	itext3.LeftEdge = (WINWIDTH - (strlen(olddatestring)*8))/2;
	itext3.IText = olddatestring;
	PrintIText(win->RPort, &itext1, 1L, 1L);

	/*
	Wait for user-mouseclick or timer-event:
	*/
	window_input();

	/*
	Finish all
	*/
	CloseAll();
}

