[comp.sys.amiga] MRBackup V1.3 Source, Part 4 of 5

mrr@softie.UUCP (09/26/87)

# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file"
# Created Fri Sep 25 07:26:29 1987
#
# This archive contains:
#		DateRequest.c
#		MRDates.c
#		MRDates.h
#		DiskMisc.c
#		FileMisc.c
echo "Creating DateRequest.c"
cat > DateRequest.c <<"***EOF DateRequest.c***"
/* Date Requester Package
 * Author:		Mark R. Rinfret
 * Description:
 *		This source file contains a canned date requester routine which
 * supports time and date entry in MM/DD/YY HH:MM:SS notation (time is
 * optional) to a DateStamp structure.  This package is dependent upon
 * the package "MRDates.c" (same author) for DateStamp/string conversions.
 *
 * History:		(most recent change first)
 *
 * 08/18/87 -MRR- Added up/down arrows to gadgetry
 * 07/20/87 -MRR- Created this file.
 */


#include <intuition/intuition.h> 
#include <intuition/intuitionbase.h> 
#include <libraries/dosextens.h> 
#include <graphics/gfxbase.h> 
#include <graphics/gfx.h> 
#include <graphics/display.h> 

#include <graphics/text.h> 
#include <functions.h>

#include <ctype.h> 
#include <MRDates.h>

#define DATEREQWIDTH	260
#define DATEREQHEIGHT	80

/**********************************************************************
 *                    Gadget Structure Definitions
 * 
 * Some of the following structures were defined using EGAD! 
 * (by the Programmer's Network) and further modified by the author.
 * 
 **********************************************************************/

/*  Gadget ID Definitions */

#define DATEGAD 		0
#define UPMONTHGAD		1
#define UPDAYGAD		2	
#define UPYEARGAD		3
#define UPHOURGAD		4
#define UPMINGAD		5
#define UPSECGAD		6
#define DOWNMONTHGAD	7
#define DOWNDAYGAD		8
#define DOWNYEARGAD		9
#define DOWNHOURGAD		10
#define DOWNMINGAD		11
#define DOWNSECGAD		12
#define NOWGAD			13
#define OKGAD			14

/**********************************************************************
 *  Text attribute structures used in rendering IntuiTexts
 **********************************************************************/


static char def_font[] ="topaz.font";

static struct TextAttr TxtAt_Plain = { 
	(UBYTE *)def_font, 8, FS_NORMAL, FPF_ROMFONT
	};




/**********************************************************************
 *  String information for the dategad string gadget.
 **********************************************************************/

static UBYTE dategad_sbuf_1[19] = "00/00/00 00:00:00";
static UBYTE dategad_ubuf_1[19];

static struct StringInfo dategad_txstr_1 = {
  dategad_sbuf_1, dategad_ubuf_1, 	/* Buffer, UndoBuffer  */
  0, 18, 0,  						/* BufferPos, MaxChars, DispPos   */
  0, 18,      						/* UndoPos, NumChars */
  0, 0, 0,  						/* DispCount, CLeft, CTop */
  0x0, 0,   						/* LayerPtr, LongInt */
  0x0        						/* AltKeyMap */
};


/**********************************************************************
 *  Gadget Structure definition for the dategad gadget.
 **********************************************************************/

static struct Gadget dategad = {
  NULL,     /* NextGadget pointer */
  64, 50,    /* LeftEdge, TopEdge  */
  8 * 17,						/* Width (8 pixels * 17 characters) */
  8,    						/* Height      */
   GADGHCOMP, 					/* Gadget Flags */
	RELVERIFY , 				/* Activation Flags */
  REQGADGET | STRGADGET, 		/* GadgetType */
	NULL,						/* GadgetRender - no border */
  NULL,    						/* SelectRender */
   NULL,    					/* GadgetText */
  0x0,    						/* MutualExclude */
  (APTR)&dategad_txstr_1,   	/* SpecialInfo */
  DATEGAD,    					/* GadgetID */
  NULL							/* UserData Pointer */
};

static struct IntuiText nowtext = {
	1, 0,						/* FrontPen / BackPen */
	JAM2,						/* DrawMode */
	0,							/* LeftEdge */
	0,							/* TopEdge */
	&TxtAt_Plain,				/* ITextFont */
	(UBYTE *) "NOW",			/* IText */
	NULL						/* NextText */
	};

static struct Gadget nowgad = {
  &dategad,	     				/* NextGadget pointer */
  220, 50,    					/* LeftEdge, TopEdge  */
  24, 8,    					/* Width, Height      */
   GADGHCOMP,					/* Gadget Flags */
	RELVERIFY , 				/* Activation Flags */
  REQGADGET | BOOLGADGET,		/* GadgetType */
  NULL,							/* GadgetRender */
  NULL,							/* SelectRender */
  &nowtext,						/* GadgetText */
  0x0,    						/* MutualExclude */
  NULL,   						/* SpecialInfo */
  NOWGAD,  						/* GadgetID */
  NULL							/* UserData Pointer */
};

static struct IntuiText oktext = {
	1, 0,						/* FrontPen / BackPen */
	JAM2,						/* DrawMode */
	0,							/* LeftEdge */
	0,							/* TopEdge */
	&TxtAt_Plain,				/* ITextFont */
	(UBYTE *) "OK",						/* IText */
	NULL						/* NextText */
	};
		
static struct Gadget okgad = {
  &nowgad,	     				/* NextGadget pointer */
  30, 50,    					/* LeftEdge, TopEdge  */
  16, 8,    					/* Width, Height      */
   GADGHNONE,					/* Gadget Flags */
	RELVERIFY , 				/* Activation Flags */
  REQGADGET | BOOLGADGET,		/* GadgetType */
  NULL,							/* GadgetRender */
  NULL,							/* SelectRender */
   &oktext,    					/* GadgetText */
  0x0,    						/* MutualExclude */
  NULL,   						/* SpecialInfo */
  OKGAD,   						/* GadgetID */
  NULL							/* UserData Pointer */
};

/* These coordinate pairs define the border of the up-arrow gadgets. */

static SHORT upborder_pairs[] = {
	7, 0,
	14, 7,
	0, 7,
	7, 0
	};


/* The up-arrow border definition. */

static struct Border upborder = {
	-1, -1,	/* LeftEdge, TopEdge */
	1, 2,   /* FrontPen, BackPen */
	JAM1,	/* DrawMode */
	4, 		/* number of pairs */
	(SHORT *) &upborder_pairs,
	NULL	/* NextBorder */
	};


/* These coordinate pairs define the border of the down-arrow gadgets. */

static SHORT downborder_pairs[] = {
	0, 0,
	14, 0,
	7, 7,
	0, 0
	};

/* The down-arrow border definition. */

static struct Border downborder = {
	-1, -1,	/* LeftEdge, TopEdge */
	1, 2,   /* FrontPen, BackPen */
	JAM1,	/* DrawMode */
	4, 		/* number of pairs */
	(SHORT *) &downborder_pairs,
	NULL	/* NextBorder */
	};


/**********************************************************************
 *  Gadget Structure definition for the upsec gadget.
 **********************************************************************/

/* Each component of the date and time can be incremented/decremented
 * by clicking on the appropriate up or down arrow gadgets.
 */

static struct Gadget downsecgad = {
  &okgad,     					/* NextGadget pointer */
  184, 60,    					/* LeftEdge, TopEdge  */
  15, 8,    					/* Width, Height      */
   NULL,						/* Gadget Flags */
	RELVERIFY , 				/* Activation Flags */
  REQGADGET | BOOLGADGET,		/* GadgetType */
  (APTR) &downborder,			/* GadgetRender */
  NULL,							/* SelectRender */
   NULL,    					/* GadgetText */
  0x0,    						/* MutualExclude */
  NULL,   						/* SpecialInfo */
  DOWNSECGAD,   				/* GadgetID */
  NULL							/* UserData Pointer */
};

/**********************************************************************
 *  Gadget Structure definition for the upmin gadget.
 **********************************************************************/

static struct Gadget downmingad = {
  &downsecgad,     				/* NextGadget pointer */
  160, 60,    					/* LeftEdge, TopEdge  */
  15, 8,    					/* Width, Height      */
   NULL,					/* Gadget Flags */
	RELVERIFY , 				/* Activation Flags */
  REQGADGET | BOOLGADGET,		/* GadgetType */
  (APTR) &downborder,			    /* GadgetRender */
  NULL,							/* SelectRender */
   NULL,    					/* GadgetText */
  0x0,    						/* MutualExclude */
  NULL,   						/* SpecialInfo */
  DOWNMINGAD,   					/* GadgetID */
  NULL							/* UserData Pointer */
};

/**********************************************************************
 *  Gadget Structure definition for the uphour gadget.
 **********************************************************************/

static struct Gadget downhourgad = {
  &downmingad,     				/* NextGadget pointer */
  136, 60,    					/* LeftEdge, TopEdge  */
  15, 8,    					/* Width, Height      */
   NULL,					/* Gadget Flags */
	RELVERIFY , 				/* Activation Flags */
  REQGADGET | BOOLGADGET,		/* GadgetType */
  (APTR) &downborder,			    /* GadgetRender */
  NULL,							/* SelectRender */
   NULL,    					/* GadgetText */
  0x0,    						/* MutualExclude */
  NULL,   						/* SpecialInfo */
  DOWNHOURGAD,   					/* GadgetID */
  NULL							/* UserData Pointer */
};

/**********************************************************************
 *  Gadget Structure definition for the upyear gadget.
 **********************************************************************/

static struct Gadget downyeargad = {
  &downhourgad,     				/* NextGadget pointer */
  112, 60,    					/* LeftEdge, TopEdge  */
  15, 8,    					/* Width, Height      */
   NULL,					/* Gadget Flags */
	RELVERIFY , 				/* Activation Flags */
  REQGADGET | BOOLGADGET,		/* GadgetType */
  (APTR) &downborder,			    /* GadgetRender */
  NULL,							/* SelectRender */
   NULL,    					/* GadgetText */
  0x0,    						/* MutualExclude */
  NULL,   						/* SpecialInfo */
  DOWNYEARGAD,   					/* GadgetID */
  NULL							/* UserData Pointer */
};

/**********************************************************************
 *  Gadget Structure definition for the upday gadget.
 **********************************************************************/

static struct Gadget downdaygad = {
  &downyeargad,     				/* NextGadget pointer */
  88, 60,    					/* LeftEdge, TopEdge  */
  15, 8,    					/* Width, Height      */
   NULL,					/* Gadget Flags */
	RELVERIFY , 				/* Activation Flags */
  REQGADGET | BOOLGADGET,		/* GadgetType */
  (APTR) &downborder,			    /* GadgetRender */
  NULL,							/* SelectRender */
   NULL,    					/* GadgetText */
  0x0,    						/* MutualExclude */
  NULL,   						/* SpecialInfo */
  DOWNDAYGAD,   					/* GadgetID */
  NULL							/* UserData Pointer */
};

/**********************************************************************
 *  Gadget Structure definition for the upmonth gadget.
 **********************************************************************/

static struct Gadget downmonthgad = {
  &downdaygad,     /* NextGadget pointer */
  64, 60,    /* LeftEdge, TopEdge  */
  15, 8,    /* Width, Height      */
  /* Gadget Flags */
   NULL,
	RELVERIFY , 				/* Activation Flags */
  REQGADGET | BOOLGADGET,		/* GadgetType */
  (APTR) &downborder,			    /* GadgetRender */
  NULL,							/* SelectRender */
   NULL,    					/* GadgetText */
  0x0,    						/* MutualExclude */
  NULL,   						/* SpecialInfo */
  DOWNMONTHGAD,   					/* GadgetID */
  NULL							/* UserData Pointer */
};

/**********************************************************************
 *  Gadget Structure definition for the upsec gadget.
 **********************************************************************/

static struct Gadget upsecgad = {
  &downmonthgad,    				/* NextGadget pointer */
  184, 40,    					/* LeftEdge, TopEdge  */
  15, 8,    					/* Width, Height      */
   NULL,					/* Gadget Flags */
	RELVERIFY , 				/* Activation Flags */
  REQGADGET | BOOLGADGET,		/* GadgetType */
  (APTR) &upborder,			    /* GadgetRender */
  NULL,							/* SelectRender */
   NULL,    					/* GadgetText */
  0x0,    						/* MutualExclude */
  NULL,   						/* SpecialInfo */
  UPSECGAD,   					/* GadgetID */
  NULL							/* UserData Pointer */
};

/**********************************************************************
 *  Gadget Structure definition for the upmin gadget.
 **********************************************************************/

static struct Gadget upmingad = {
  &upsecgad,     				/* NextGadget pointer */
  160, 40,    					/* LeftEdge, TopEdge  */
  15, 8,    					/* Width, Height      */
   NULL,					/* Gadget Flags */
	RELVERIFY , 				/* Activation Flags */
  REQGADGET | BOOLGADGET,		/* GadgetType */
  (APTR) &upborder,			    /* GadgetRender */
  NULL,							/* SelectRender */
   NULL,    					/* GadgetText */
  0x0,    						/* MutualExclude */
  NULL,   						/* SpecialInfo */
  UPMINGAD,   					/* GadgetID */
  NULL							/* UserData Pointer */
};
/**********************************************************************
 *  Gadget Structure definition for the uphour gadget.
 **********************************************************************/

static struct Gadget uphourgad = {
  &upmingad,     				/* NextGadget pointer */
  136, 40,    					/* LeftEdge, TopEdge  */
  15, 8,    					/* Width, Height      */
   NULL,					/* Gadget Flags */
	RELVERIFY , 				/* Activation Flags */
  REQGADGET | BOOLGADGET,		/* GadgetType */
  (APTR) &upborder,			    /* GadgetRender */
  NULL,							/* SelectRender */
   NULL,    					/* GadgetText */
  0x0,    						/* MutualExclude */
  NULL,   						/* SpecialInfo */
  UPHOURGAD,   					/* GadgetID */
  NULL							/* UserData Pointer */
};

/**********************************************************************
 *  Gadget Structure definition for the upyear gadget.
 **********************************************************************/

static struct Gadget upyeargad = {
  &uphourgad,     				/* NextGadget pointer */
  112, 40,    					/* LeftEdge, TopEdge  */
  15, 8,    					/* Width, Height      */
   NULL,					/* Gadget Flags */
	RELVERIFY , 				/* Activation Flags */
  REQGADGET | BOOLGADGET,		/* GadgetType */
  (APTR) &upborder,			    /* GadgetRender */
  NULL,							/* SelectRender */
   NULL,    					/* GadgetText */
  0x0,    						/* MutualExclude */
  NULL,   						/* SpecialInfo */
  UPYEARGAD,   					/* GadgetID */
  NULL							/* UserData Pointer */
};

/**********************************************************************
 *  Gadget Structure definition for the upday gadget.
 **********************************************************************/

static struct Gadget updaygad = {
  &upyeargad,     				/* NextGadget pointer */
  88, 40,    					/* LeftEdge, TopEdge  */
  15, 8,    					/* Width, Height      */
   NULL,					/* Gadget Flags */
	RELVERIFY , 				/* Activation Flags */
  REQGADGET | BOOLGADGET,		/* GadgetType */
  (APTR) &upborder,			    /* GadgetRender */
  NULL,							/* SelectRender */
   NULL,    					/* GadgetText */
  0x0,    						/* MutualExclude */
  NULL,   						/* SpecialInfo */
  UPDAYGAD,   					/* GadgetID */
  NULL							/* UserData Pointer */
};

/**********************************************************************
 *  Gadget Structure definition for the upmonth gadget.
 **********************************************************************/

static struct Gadget upmonthgad = {
  &updaygad,     /* NextGadget pointer */
  64, 40,    /* LeftEdge, TopEdge  */
  15, 8,    /* Width, Height      */
  /* Gadget Flags */
   NULL,
	RELVERIFY , 				/* Activation Flags */
  REQGADGET | BOOLGADGET,		/* GadgetType */
  (APTR) &upborder,			    /* GadgetRender */
  NULL,							/* SelectRender */
   NULL,    					/* GadgetText */
  0x0,    						/* MutualExclude */
  NULL,   						/* SpecialInfo */
  UPMONTHGAD,   					/* GadgetID */
  NULL							/* UserData Pointer */
};

static struct Requester daterequest;	/* requester for the date */

/* Date requester border 2 coordinate pairs. */

static SHORT datereq_pairs2[] = {
	8, 4, 
	DATEREQWIDTH - 8, 4, 
	DATEREQWIDTH - 8, DATEREQHEIGHT - 4,
	8, DATEREQHEIGHT - 4,
	8, 4
};

/* Date requester border 2 definition */

static struct Border datereq_bord2 = {
  -1,  -1,       /* LeftEdge, TopEdge */
  0,  2,  JAM2,  /* FrontPen, BackPen, DrawMode*/
  5,             /* Count of XY pairs */  
  (SHORT *)&datereq_pairs2, /* XY pairs */
  NULL           /* Next Border */
};

/* Date requester border 1 coordinate pairs. */

static SHORT datereq_pairs1[] = {
	4, 2, 
	DATEREQWIDTH - 4, 2, 
	DATEREQWIDTH - 4, DATEREQHEIGHT - 2,
	4, DATEREQHEIGHT - 2,
	4, 2
};

/* Date requester border 1 definition. */

static struct Border datereq_bord1 = {
  -1,  -1,       /* LeftEdge, TopEdge */
  0,  2,  JAM2,  /* FrontPen, BackPen, DrawMode*/
  5,             /* Count of XY pairs */  
  (SHORT *)&datereq_pairs1, /* XY pairs */
  &datereq_bord2 /* Next Border */
};

/* This is the definition for the prompt string (user-supplied) which
 * appears in the requester.
 */

static struct IntuiText datereqtext = {
	1, 0,						/* FrontPen / BackPen */
	JAM2,						/* DrawMode */
	20,							/* LeftEdge */
	15,							/* TopEdge */
	&TxtAt_Plain,				/* ITextFont */
	NULL,						/* IText */
	NULL						/* NextText */
	};

static initialized = 0;			/* set to 1 after initialization */

static InitDateRequest()
{
	InitRequester(&daterequest);
	daterequest.LeftEdge = 60;
	daterequest.TopEdge = 10;
	daterequest.Width = DATEREQWIDTH;
	daterequest.Height = DATEREQHEIGHT;
	daterequest.ReqGadget = &upmonthgad;
	daterequest.ReqText = &datereqtext;
	daterequest.ReqBorder = &datereq_bord1;
	daterequest.BackFill = 2;
	++initialized;
}

/* Request a date from the user.
 * Called with:
 *		window:			pointer to window structure
 *		prompt:			string to be used as the prompt text
 *		default_date:	pointer to default date or NULL
 *		date:			pointer to date result (returned)
 * Returns:
 *		status code:	0 => success, 1 => failure
 *		(actually, always returns 0 - can't leave without good date)
 */

DateRequest(window,prompt,default_date,date)
	struct Window *window; char *prompt; 
	struct DateStamp *default_date,*date;
{
	ULONG class;				/* message class */
	USHORT code;				/* message code */
	struct Gadget *gadget;		/* pointer to gadget affected */
	USHORT gadgid;				/* gadget ID */
	struct IntuiMessage *msg;	/* Intuition message pointer */
	UnpackedDS upd;				/* unpacked version of date */
	SHORT x,y;					/* mouse x and y position */

	if (!initialized)
		InitDateRequest();
	datereqtext.IText = (UBYTE *) prompt;
	if (default_date)			/* write default date in requester? */
		DS2Str(dategad_sbuf_1,"%02m/%02d/%02y %02h:%02n:%02s",
			default_date);
	else
		*dategad_sbuf_1 = '\0';

	Request(&daterequest, window);

	for (;;) {
		Wait(1L << window->UserPort->mp_SigBit);
		while (msg = (struct IntuiMessage *) GetMsg(window->UserPort)) {
			class = msg->Class;
			code = msg->Code;
			gadget = (struct Gadget *) msg->IAddress;
			x = msg->MouseX;
			y = msg->MouseY;
			ReplyMsg(msg);		/* acknowledge the message */

			switch (class) {

			case REQSET: 
				ActivateGadget(&dategad,window,&daterequest);
				break;
			
			case GADGETUP:
				gadgid = gadget->GadgetID;
				if (gadgid == NOWGAD)
					DateStamp(date);
				else if (gadgid == OKGAD)
					gadgid = DATEGAD;

				UnpackDS(date, &upd);

				switch (gadgid) {
				case DATEGAD:
					if ( ! Str2DS(dategad_sbuf_1, date) ) {
						EndRequest(&daterequest, window);
						return 0;
					}
					else
						DisplayBeep(window->WScreen); /* bad conversion */
					break;

				case UPYEARGAD:
					++upd.year;
					break;

				case DOWNYEARGAD:
					if (upd.year > 1978) --upd.year;
					break;

				case UPMONTHGAD:
					if (++upd.month > 12) upd.month = 1;
					break;

				case DOWNMONTHGAD:
					if (--upd.month < 1) upd.month = 12;
					break;

				case UPDAYGAD:
					if (upd.day < 31) ++upd.day;
					break;

				case DOWNDAYGAD:
					if (upd.day > 1) --upd.day;
					break;

				case UPHOURGAD:
					if (++upd.hour > 23) upd.hour = 0;
					break;

				case DOWNHOURGAD:
					if (--upd.hour < 0) upd.hour = 23;
					break;

				case UPMINGAD:
					if (++upd.minute > 59) upd.minute = 0;
					break;

				case DOWNMINGAD:
					if (--upd.minute < 0) upd.minute = 59;
					break;

				case UPSECGAD:
					if (++upd.second > 59) upd.second = 0;
					break;

				case DOWNSECGAD:
					if (--upd.second < 0) upd.second = 59;
					break;

				default:
					break;
				}					/* end switch(gadgid) */

				/* Reformat the new date value. */

				PackDS(date, &upd);
				if (upd.year)
					DS2Str(dategad_sbuf_1,"%02m/%02d/%02y %02h:%02n:%02s",
						date);
				else
					strcpy(dategad_sbuf_1,"00/00/00 00:00:00");
				RefreshGadgets(&dategad, window, &daterequest);
				break;

			default:
				break;			/* ignore the rest */
			}					/* end switch(class) */
		}
	}
}

/*#define DEBUG */

#ifdef DEBUG

/* --- Only compiled in the debug version --- */

#include <exec/memory.h>

/* New window structure */

struct NewWindow newwindow = {
	0,0,640,200,0,1,

/* IDCMP Flags */

	MOUSEMOVE | MENUPICK | MOUSEBUTTONS | 
	CLOSEWINDOW | GADGETDOWN | GADGETUP | REQSET, 

/* Flags */
	WINDOWCLOSE | WINDOWDEPTH | ACTIVATE | RMBTRAP | REPORTMOUSE,

	NULL,							/* First gadget */
	NULL,							/* Checkmark */
	(UBYTE *)"Date Requester Test Program",	/* Window title */
	NULL,							/* No custom streen */
	NULL,							/* Not a super bitmap window */
	0,0,640,200,					/* Not used, but set up anyway */
	WBENCHSCREEN
};
struct IntuitionBase *IntuitionBase;
struct Window *mywindow;
struct DateStamp *ds;

static struct IntuiText MoreText = {
	AUTOFRONTPEN,				/* FrontPen */
	AUTOBACKPEN,				/* BackPen */
	JAM2,						/* DrawMode */
	AUTOLEFTEDGE,				/* LeftEdge */
	AUTOTOPEDGE,				/* TopEdge */
	AUTOITEXTFONT,				/* ITextFont */
	(UBYTE *) "Want to play some more?", /* IText */
	NULL						/* NextText */
	};

static struct IntuiText YesText = {
	AUTOFRONTPEN,				/* FrontPen */
	AUTOBACKPEN,				/* BackPen */
	AUTODRAWMODE,				/* DrawMode */
	AUTOLEFTEDGE,				/* LeftEdge */
	AUTOTOPEDGE,				/* TopEdge */
	AUTOITEXTFONT,				/* ITextFont */
	(UBYTE *) "Sure!", 			/* IText */
	NULL						/* NextText */
	};

static struct IntuiText NoText = {
	AUTOFRONTPEN,				/* FrontPen */
	AUTOBACKPEN,				/* BackPen */
	JAM2,						/* DrawMode */
	AUTOLEFTEDGE,				/* LeftEdge */
	AUTOTOPEDGE,				/* TopEdge */
	AUTOITEXTFONT,				/* ITextFont */
	(UBYTE *) "Nope!", 			/* IText */
	NULL						/* NextText */
	};

main()
{
	short keep_going;

	if (!(IntuitionBase = (struct IntuitionBase *)
		OpenLibrary("intuition.library",33L))) {
		puts("Failed to open Intuition library!");
		exit(1);
	}

	ds = (struct DateStamp *)
		AllocMem((long) sizeof(struct DateStamp), MEMF_PUBLIC);
	DateStamp(ds);				/* get current date/time */

	mywindow = OpenWindow(&newwindow);

	do {
		DateRequest(mywindow, "Enter date and time", ds, ds);
		keep_going = AutoRequest(mywindow, &MoreText, &YesText, &NoText,
						NULL, NULL, 220L, 50L);
	} while (keep_going);

	if (mywindow)
		CloseWindow(mywindow);

	if (IntuitionBase)
		CloseLibrary(IntuitionBase);
}

#endif
***EOF DateRequest.c***
echo "Creating MRDates.c"
cat > MRDates.c <<"***EOF MRDates.c***"

/* General routines to provide date support for the DateStamp
 * date format.
 *
 * Author:		Mark R. Rinfret	(mark@unisec.usi.com)
 * Date:		07/18/87
 *
 * This source is released to the public domain by the author, without
 * restrictions.  However, it is requested that you give credit where
 * credit is due and share any bug fixes or enhancements with him.
 *
 * History:		(most recent change first)
 *
 * 08/20/87 -MRR- Gack!  I wrote this?  In the interests of orthogonality,
 *                I have replaced SetDateStamp with PackDS, the inverse
 *                of UnpackDS.  I have also renamed the package MRDates
 *                to provide a unique name, hopefully relieving conflicts
 *                with other packages providing date/time functions.  The
 *				  UnpackedDS type is now defined in MRDates.h and can
 *                be included by modules which require PackDS and UnpackDS.
 */

/* The following #define MUST be set to inhibit certain declarations in
 * the include file MRDates.h:
 */

#define MRDATES

#include <libraries/dos.h>
#include <exec/memory.h>
#include <ctype.h>
#include <functions.h>
#include "MRDates.h"

/* #define DEBUG */


char *daynames[] = {
	"Sunday", "Monday", "Tuesday", "Wednesday", 
	"Thursday", "Friday", "Saturday"
	};

USHORT monthdays[12] =  {0,31,59,90,120,151,181,212,243,273,304,334};

char *monthnames[12] = {
	"January", "February", "March", "April", "May", "June",
	"July", "August", "September", "October", "November", "December"
	};

/* Compare two DateStamp values.
 * Called with:
 *		d1,d2:		pointers to DateStamp structs
 * 
 * Returns:
 *		< 0 => d1 < d2
 *		  0 => d1 == d2
 *		> 0 => d1 > d2
 *
 * Note:
 *		This routine makes an assumption about the DateStamp structure,
 *		specifically that it can be viewed as an array of 3 long integers
 *		in days, minutes and ticks order.
 */

int 
CompareDS(d1, d2)
	long *d1, *d2;
{
	USHORT i;
	long compare;

	for (i = 0; i < 3; ++i) {
		if (compare = (d1[i] - d2[i])) {
			if (compare < 0) return -1;
			return 1;
		}
	}
	return 0;						/* dates match */
}

/* Convert a DateStamp to a formatted string.
 * Called with:
 *		fmt:	format string
 *			The format of the format string is very similar to that
 *			for printf, with the exception that the following letters
 *			have special significance:
 *				y => year minus 1900
 *				Y => full year value
 *				m => month value as integer
 *				M => month name
 *				d => day of month (1..31)
 *				D => day name ("Monday".."Sunday")
 *				h => hour in twenty-four hour notation
 *				H => hour in twelve hour notation
 *				i => 12 hour indicator for H notation (AM or PM)
 *				I => same as i
 *				n => minutes	(sorry...conflict with m = months)
 *				N => same as n
 *				s => seconds
 *				S => same as s
 *
 *			All other characters are passed through as part of the normal
 *			formatting process.  The following are some examples with
 *			Saturday, July 18, 1987, 13:53 as an input date:
 *
 *				"%y/%m/%d"			=> 87/7/18
 *				"%02m/%02d/%2y"		=> 07/18/87
 *				"%D, %M %d, %Y"		=> Saturday, July 18, 1987
 *				"%02H:%02m i"		=> 01:53 PM
 *				"Time now: %h%m"	=> Time now: 13:53
 *
 *		str:	string to write date on
 *		d:		pointer to DateStamp structure
 *		
 */
void
DS2Str(str,fmt,d)
	char *str, *fmt; struct DateStamp *d;
{
	UnpackedDS date;
	char fc,*fs,*out;
	USHORT ivalue;
	char new_fmt[256];			/* make it big to be "safe" */
	USHORT new_fmt_lng;
	char *svalue;

	UnpackDS(d, &date);			/* convert DateStamp to unpacked format */

	*str = '\0';				/* insure output is empty */
	out = str;
	fs = fmt;					/* make copy of format string pointer */

	while (fc = *fs++) {		/* get format characters */
		if (fc == '%') {		/* formatting meta-character? */
			new_fmt_lng = 0;
			new_fmt[new_fmt_lng++] = fc;
			/* copy width information */
			while (isdigit(fc = *fs++) || fc == '-')
				new_fmt[new_fmt_lng++] = fc;

			switch (fc) {		/* what are we trying to do? */
			case 'y':			/* year - 1980 */
				ivalue = date.year - 1900;
write_int:
				new_fmt[new_fmt_lng++] = 'd';
				new_fmt[new_fmt_lng] = '\0';
				sprintf(out,new_fmt,ivalue);
				out = str + strlen(str);
				break;
			case 'Y':			/* full year value */
				ivalue = date.year;
				goto write_int;

			case 'm':			/* month */
				ivalue = date.month;
				goto write_int;

			case 'M':			/* month name */
				svalue = monthnames[date.month - 1];
write_str:
				new_fmt[new_fmt_lng++] = 's';
				new_fmt[new_fmt_lng] = '\0';
				sprintf(out,new_fmt,svalue);
				out = str + strlen(str);
				break;

			case 'd':			/* day */
				ivalue = date.day;
				goto write_int;

			case 'D':			/* day name */
				svalue = daynames[d->ds_Days % 7];
				goto write_str;

			case 'h':			/* hour */
				ivalue = date.hour;
				goto write_int;

			case 'H':			/* hour in 12 hour notation */
				ivalue = date.hour;
				if (ivalue >= 12) ivalue -= 12;
				goto write_int;

			case 'i':			/* AM/PM indicator */
			case 'I':
				if (date.hour >= 12)
					svalue = "PM";
				else
					svalue = "AM";
				goto write_str;

			case 'n':			/* minutes */
			case 'N':
				ivalue = date.minute;
				goto write_int;

			case 's':			/* seconds */
			case 'S':
				ivalue = date.second;
				goto write_int;

			default:
				/* We are in deep caca - don't know what to do with this
				 * format character.  Copy the raw format string to the
				 * output as debugging information.
				 */
				new_fmt[new_fmt_lng++] = fc;
				new_fmt[new_fmt_lng] = '\0';
				strcat(out, new_fmt);
				out = out + strlen(out);	/* advance string pointer */
				break;
			}
		}
		else
			*out++ = fc;		/* copy literal character */
	}
	*out = '\0';				/* terminating null */
}

/* Convert a string to a DateStamp.
 * Called with:
 *		str:	string containing date in MM/DD/YY format		
 *		d:		pointer to DateStamp structure
 * Returns:
 *	    status code (0 => success, 1 => failure)
 */

int
Str2DS(str, d)
	char *str; struct DateStamp *d;
{
	register char c;
	int count;
	int i, item;
	UnpackedDS upd;				/* unpacked DateStamp */
	char *s;

	int values[3];
	int value;
	

	s = str;
	for (item = 0; item < 2; ++item) {	/* item = date, then time */
		for (i = 0; i < 3; ++i) values[i] = 0;
		count = 0;
		while (c = *s++) {			/* get date value */
			if (c <= ' ') 
				break;

			if (isdigit(c)) {
				value = 0;
				do {
					value = value*10 + c - '0';
					c = *s++;
				} while (isdigit(c));
				if (count == 3) {
	bad_value:
#ifdef DEBUG
					puts("Error in date-time format.\n");
					printf("at %s: values(%d) = %d, %d, %d\n",
						s, count, values[0], values[1], values[2]);
#endif
					return 1;
				}
				values[count++] = value;
				if (c <= ' ')
					break;
			}
		}							/* end while */
		if (item) {					/* getting time? */
			upd.hour = values[0];
			upd.minute = values[1];
			upd.second = values[2];
		}
		else {						/* getting date? */

/* It's OK to have a null date string, but it's not OK to specify only
 * 1 or 2 of the date components.
 */
			if (count && count != 3)
				goto bad_value;
			upd.month = values[0];
			upd.day = values[1];
			upd.year = values[2];
		}
	}								/* end for */
	PackDS(d,&upd);
	return 0;
}


/* Set a DateStamp structure, given the date/time components.
 * Called with:
 *		d:			pointer to DateStamp
 *      upd:		pointer to UnpackedDS
 */
PackDS(d,upd)
	struct DateStamp *d; UnpackedDS *upd;
{
	USHORT leapyear;
	short year,month,day,hour,minute,second;

	year = upd->year;			/* copy date components to locals */
	month = upd->month;
	day = upd->day;
	hour = upd->hour;
	minute = upd->minute;
	second = upd->second;

	if (year > 1900)
		year = year - 1900;

	leapyear = (year % 4 ? 0 : 1);

	year = year - 78;
	if (month < 1 || month > 12)	/* somebody goofed? */
		month = 1;

	day = day - 1 + monthdays[month-1];
	if (leapyear && (month > 2))
		++day;

	d->ds_Days = year * 365 + (year + 1) / 4 + day;
	d->ds_Minute = hour * 60 + minute;
	d->ds_Tick = second * TICKS_PER_SECOND;
}

/* Unpack a DateStamp structure into an UnpackedDS structure. 
 * Called with:
 *		ds:		pointer to DateStamp structure
 *		du:		pointer to UnpackedDS structure
 */
UnpackDS(ds, du)
	struct DateStamp *ds; UnpackedDS *du;
{
	USHORT i, leap_years, leap, temp, test_value;

	du->year = ds->ds_Days / 365 + 1978;
	
	/* is current year a leapyear? */
	leap = ( (du->year % 4) == 0); 

	/* how many leap years since "beginning of time"? */
	leap_years = (du->year - 1976 - 1) / 4;

	/* get days remaining in year */
	temp = ds->ds_Days % 365 - leap_years;

	/* find month */

	du->month = 0;
	du->day = 0;
	for (i = 11; i >= 0; --i) {
		test_value = monthdays[i];
		if (i > 2) test_value += leap;
		if (temp >= test_value) {
			du->month = i + 1;
			du->day = temp - test_value + 1;
			break;
		}
	}

	du->hour = ds->ds_Minute / 60;
	du->minute = ds->ds_Minute % 60;
	du->second = ds->ds_Tick / TICKS_PER_SECOND;
}


#ifdef DEBUG
main()
{
	int compflag;
	char datestr[81], instr[81];
	struct DateStamp *ds, *now;
	UnpackedDS du;

	now = (struct DateStamp *) 
		AllocMem((long) sizeof(struct DateStamp), MEMF_PUBLIC);

	ds = (struct DateStamp *) 
		AllocMem((long) sizeof(struct DateStamp), MEMF_PUBLIC);

	puts("Enter a date string and I will convert it.  To quit, hit RETURN");
	while (1) {
		DateStamp(now);
		UnpackDS(now, &du);

		printf("\nCurrent date and time: %02d/%02d/%02d %02d:%02d:%02d\n",
			du.month,du.day,du.year,du.hour,du.minute,du.second);

		puts("\nEnter the date [and time]:");
		gets(instr);
		if (*instr == '\0') break;
		if (Str2DS(instr,ds))
			puts("Error encountered in input string");
		else {
			DS2Str(datestr, "%02m/%02d/%02y %02h:%02n:%02s", ds);
			puts(datestr);

			DS2Str(datestr, "%D, %M %d, %Y", ds);
			puts(datestr);

			DS2Str(datestr, "The time entered is %02H:%02N %i", ds);
			puts(datestr);

			compflag = CompareDS(ds,now);
			printf("The date input is ");
			if (compflag < 0)
				printf("earlier than");
			else if (compflag == 0)
				printf("the same as");
			else
				printf("later than");
			puts(" the current date.");
		}
	}

	FreeMem(ds, (long) sizeof(struct DateStamp));
	FreeMem(now, (long) sizeof(struct DateStamp));
}
#endif
***EOF MRDates.c***
echo "Creating MRDates.h"
cat > MRDates.h <<"***EOF MRDates.h***"
/* Filename:	MRDates.h
 * Various definitions used to support the MRDates package.
 * 
 * Important note:
 *		If the preprocessor symbol MRDATES is undefined, certain
 *      useful structures will be declared for use by the module
 *      including this file.
 */

#include <exec/types.h>

typedef struct {
	short year,month,day,hour,minute,second;
	} UnpackedDS;

#ifndef MRDATES				/* This is not MRDates.c? */

extern char *daynames[7];	/* day name strings, [0] = "Sunday" */

extern USHORT monthdays[12];/* Number of days preceding each month, 
							 * requires diddling for leap years. 
							 */

extern char *monthnames[12];/* [0] = January */

#endif
***EOF MRDates.h***
echo "Creating DiskMisc.c"
cat > DiskMisc.c <<"***EOF DiskMisc.c***"
/* DiskMisc.c - miscellaneous disk support routines.
 * Mark Rinfret (et al), 1987
 */

/*#define DEBUG*/

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/ports.h>
#include <exec/io.h>
#include <libraries/dosextens.h>
#include <functions.h>

extern LONG 	sendpkt();

/* This routine returns the number of disk blocks remaining on the
 * drive specified by 'name'.  Though 'name' would typically be the
 * drive name or volume name, it can also be the name of any file
 * on the disk drive.
 * Called with:
 *		name:		disk device or volume name
 * Returns:
 *		> 0 => number of blocks available
 *		< 0 => error status
 */

long DiskBlocks(name)
	char *name;
{
	struct FileLock *lock = NULL;
	struct InfoData *info = NULL;
	long int blocks = -1L;
	long IoErr();

	if (lock = (struct FileLock *) Lock(name,ACCESS_READ)) {
		if (info = AllocMem((long)sizeof(struct InfoData),MEMF_PUBLIC)) {
			if (Info(lock,info)) {
				blocks = info->id_NumBlocks - info->id_NumBlocksUsed;
			}
			else {
				blocks = -IoErr();
#ifdef DEBUG
				printf("DiskBlocks: can't get Info on %s; error %ld\n",
					name, blocks);
#endif
				}
		}
		else {
			blocks = -ERROR_NO_FREE_STORE;
#ifdef DEBUG
			puts("DiskBlocks: no memory!");
#endif
		}
	}
	else {
		blocks = -IoErr();
#ifdef DEBUG
		printf("DiskBlocks: can't lock %s; error %ld\n",name,blocks);
#endif
	}

	if (lock)	UnLock(lock);
	if (info)	FreeMem(info,(long)sizeof(struct InfoData));
	return blocks;					/* bad status indicator */
}

/* Disk ACTION_INHIBIT support routine.
 * Author:		Mark R. Rinfret
 * Date:		06/29/87
 * 
 * This routine provides support for user-written disk formatting, copy
 * operations which benefit from suppressing/restoring disk validation.
 */

int
Inhibit(drivename, code)
	char *drivename; int code;
{
	struct MsgPort     *task;
	LONG 	arg[2];
	LONG 	rc;

	if (!(task=(struct MsgPort *) DeviceProc(drivename))) 
		return 1;						/* fail, darn it! */

	arg[0] = code;

	/* Now, cross all your fingers and toes... */

	return ( !sendpkt(task,ACTION_INHIBIT,arg,1));
}


#ifdef DEBUG
main()
{
	long blocks;

	blocks = DiskBlocks("df0:");
	if (blocks == -1L)
		puts("Bad status from DiskBlocks()");
	else
		printf("Disk blocks left on df0: %ld\n",blocks);
}
#endif
***EOF DiskMisc.c***
echo "Creating FileMisc.c"
cat > FileMisc.c <<"***EOF FileMisc.c***"
/* File date routines.
 * Filename:	FileDates.c
 * History:		(most recent change first)
 *
 * 09/24/87 -MRR- SetFileDate was allocating a BSTR of 68 bytes, rather
 *                than using the length of the file name string.  I don't
 *                have the foggiest notion why (that was DUMB!).
 */

#include "exec/types.h"
#include "exec/ports.h"
#include "exec/io.h"
#include "exec/memory.h"
#include "libraries/dosextens.h"
#include <stdio.h>
#define AZTEC 1
#ifdef AZTEC
#include "functions.h"				/* aztec C include */
#endif

#define ACTION_SETDATE_MODE 34L		/* Set creation date on file */
#define DOSTRUE 	    -1L			/* AmigaDos TRUE */
#define MAXARGS          7L			/* limit in packet structure
									   (dosextens.h) */
#define NARGS		     4L			/* Number of args for setdate */

long    sendpkt();


/*---------------------------------------------------------------------*/
/*  GetFileDate: get the datestamp the given file.			       	   */
/*---------------------------------------------------------------------*/

BOOL GetFileDate(name, date)
char   *name;
register struct DateStamp  *date;
{
	struct FileInfoBlock   *Fib;
	ULONG   FLock;
	int     result;
	register struct DateStamp  *d;

	if ((FLock = (ULONG)Lock(name,(long)(ACCESS_READ)))== NULL)
		return FALSE;

	Fib = (struct FileInfoBlock *)
		AllocMem((long)sizeof(struct FileInfoBlock),
					(long)(MEMF_CHIP|MEMF_PUBLIC));

	if (Fib == NULL )
		result = FALSE;
	else{
		if (!Examine(FLock,Fib ))
			result = FALSE;
		else 
			if (Fib->fib_DirEntryType > 0 )
				result = FALSE;		/* It's a directory */
			else{
				d = &Fib->fib_Date;
				date->ds_Days = d->ds_Days;
				date->ds_Minute = d->ds_Minute;
				date->ds_Tick = d->ds_Tick;
				result = TRUE;
			}
		FreeMem((void *)Fib,(long)sizeof(struct FileInfoBlock));
	}

	UnLock(FLock);
	return result;
}

/* Examine a pathname to determine if it is a device or directory name.
 * Called with:
 *		name:		pathname specification
 * Returns:
 *		0 =>		no
 *		1 => 		yes
 *	   <0 =>		-<system error number>
 */
int
IsDir(name)
	char *name;
{
	struct FileInfoBlock   *FIB = NULL;
    struct Lock *lock = NULL;	
	int status;


	if (!(FIB =
		AllocMem((long)sizeof(struct FileInfoBlock),
				 MEMF_CHIP|MEMF_CLEAR))) {
		return -ERROR_NO_FREE_STORE;
	}

	if (!(lock=Lock(name,SHARED_LOCK))) {
		status = -IoErr();
		goto done;
	}

	if ((Examine(lock,FIB))==0){
		status = -IoErr();
		goto done;
	}

	status = (FIB->fib_DirEntryType > 0);
done:
	if (FIB)
		FreeMem(FIB, (long) sizeof(struct FileInfoBlock));
	UnLock(lock);
	return status;
}

/*---------------------------------------------------------------------*/
/*  SetFileDate: datestamp the given file with the given date.	       */
/*---------------------------------------------------------------------*/

BOOL SetFileDate(name,date )
char   *name;
struct DateStamp   *date;
{
	struct MsgPort     *task;		/* for process id handler */
	ULONG   arg[4];					/* array of arguments     */
	int nameleng;
	char   *bstr, *strcpy();		/* of file to be set      */
	long    rc;
	char   *strchr();
	int     strlen();

	rc = 0;

	nameleng = strlen(name);
	if (!(bstr = (char *)AllocMem((long) (nameleng + 2),MEMF_PUBLIC)))
		goto exit2;

	if (!(task = (struct MsgPort *)DeviceProc(name )))
		goto exit1;

 /* Dos Packet needs the filename in Bstring format */

	(void) strcpy(bstr+1, name );
	*bstr = nameleng;

	arg[0]= (ULONG)NULL;
	arg[1]= (ULONG)IoErr();			/* lock on parent director set by
									   DeviceProc() */
	arg[2]= (ULONG)bstr >> 2;
	arg[3]= (ULONG)date;
	rc = sendpkt(task,ACTION_SETDATE_MODE,arg,4L );

exit1: if (bstr )
		FreeMem((void *)bstr, (long) (nameleng + 2));
exit2: if (rc == DOSTRUE )
		return TRUE;
	else
		return FALSE;
}
***EOF FileMisc.c***
-- 
< Mark R. Rinfret,        mrr@softie, ..rayssd!unisec!softie!mrr             >
< SofTech, Inc.           Home: 401-846-7639                                 >
< 1 Silva Lane,           Work: 401-849-4174                                 >
< Middletown, RI 02840    "The name has changed but I'm still guilty."       >