#pragma	title("Date Entry Field Control  --  Version 1.0 -- (DateFld.C)")
#pragma	subtitle("  Date Entry Field Control Control DLL - Interface Definitions")

#pragma	info(noext)

#define	INCL_GPI		   /* Include OS/2 PM GPI Interface	*/
#define	INCL_WIN		   /* Include OS/2 PM Windows Interface	*/

#include <os2.h>
#include <stdlib.h>
#include <string.h>

#include <pmcx.h>

#include "datefld.h"

/* This	module contains	an example installable control that can	be used	*/
/* within applications where additional	facilities are provided	that	*/
/* are not found within	the default controls of	OS/2 PM.		*/
/*									*/
/* For complete	details	regarding the PM Control Extensions (PMCX)	*/
/* consult the User's Guide.                                            */
/*									*/
/* The DLL is created using the	following command line invocation:	*/
/*									*/
/*     Icc -G3e- -O+ -Rn -W3 -C	DateFld.C				*/

/* Filename:   DateFld.C						*/

/*  Version:   1.00							*/
/*  Created:   1993-12-21						*/
/*  Revised:   1994-06-26						*/

/* Routines:   BOOL EXPENTRY DateFldRegister(HAB hAB);			*/
/*	       BOOL EXPENTRY DateFldQuery(PUSERINFO pControlInfo);	*/
/*	       MRESULT EXPENTRY	DateFldWndProc(HWND hWnd, ULONG	msg,	*/
/*					      MPARAM mp1, MPARAM mp2);	*/
/*	       MRESULT EXPENTRY	DateFldStyles(HWND hWnd, ULONG msg,	*/
/*					      MPARAM mp1, MPARAM mp2);	*/


/* Copyright ¸ 1989-1994  Prominare Inc.  All Rights Reserved.		*/

/* --------------------------------------------------------------------	*/

/************************************************************************/
/************************************************************************/
/*		       DISCLAIMER OF WARRANTIES.			*/
/************************************************************************/
/************************************************************************/
/*     The following [enclosed]	code is	library	code created by		*/
/*     Prominare Inc.  This library code is  provided to you solely	*/
/*     for the purpose of assisting you	in the development of your	*/
/*     applications.  The code is provided "AS IS", without		*/
/*     warranty	of any kind.  Prominare	Inc. shall not be liable	*/
/*     for any damages arising out of your use of the library code,	*/
/*     even if they have been advised of the possibility of such	*/
/*     damages.								*/
/************************************************************************/
/************************************************************************/

/* --- Window Information Structures ----------------------------------	*/

typedef	struct _DATEFIELD	   /* tf */
   {
   HWND	  hwndDay;		   /* Day Entry	Fiild Handle		*/
   HWND	  hwndMonth;		   /* Month Entry Fiild	Handle		*/
   HWND	  hwndYear;		   /* Year Entry Fiild Handle		*/
   HWND	  hwndOwner;		   /* Owner Window Handle		*/
   SWP	  aswp[3];		   /* Raised Field Flag			*/
   LONG	  cxSep;		   /* Separator	Width			*/
   LONG	  cxDayMonth;		   /* Day/Month	Width			*/
   LONG	  cxYear;		   /* Year Width			*/
   LONG	  iDay;			   /* Day Index				*/
   LONG	  iMonth;		   /* Month Index			*/
   LONG	  iYear;		   /* Year Index			*/
   LONG	  aClr[7];		   /* Presentation Colours Array	*/
   CHAR	  szSep[4];		   /* Separator				*/
   ULONG  flStyle;		   /* Style Flag			*/
   CHAR	  szText[16];		   /* Date String Holder		*/
   ULONG  ulDateType;		   /* Date Type				*/
   } DATEFIELD ;

typedef	DATEFIELD *PDATEFIELD;

#define	DATE_YMD       0
#define	DATE_MDY       1
#define	DATE_DMY       2

/* --- Module Prototype	Definitions -----------------------------------	*/

static VOID CalcSize(PRECTL prcl, PDATEFIELD pdf);
static VOID SetDefaultColours(HWND hWnd, PDATEFIELD pdf);
static LONG lGetPresParam(HWND hWnd, ULONG ulID1, ULONG	ulID2, LONG lDefault);

BOOL	EXPENTRY DateFldRegister(HAB hAB);
BOOL	EXPENTRY DateFldQuery(PUSERINFO	pUserInfo);
MRESULT	EXPENTRY DateFldWndProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2);
MRESULT	EXPENTRY DateFldDlgProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2);

#pragma	subtitle("   Date Entry Field Control DLL - Control Initialization Function")
#pragma	page ( )

/* --- DateFldRegister ------------------------------------------------	*/
/*									*/
/*     This function is	used to	register the installable control class	*/
/*     with OS/2 Presentation Manager.	The registration must use the	*/
/*     USER_CWINDOWWORDS to reserve memory for the control to allow for	*/
/*     proper usage by Resource	Editor and for use by the control	*/
/*     dialog and window procedures.  The information for the control	*/
/*     containing the style, presentation parameters and control data	*/
/*     is pointed to by	a pointer that can be referenced by the		*/
/*     control's dialog and window procedure as required.  The memory   */
/*     for the structure is allocated and controlled through Resource	*/
/*     Editor.	 The control can reserve more memory for its use	*/
/*     by adding the memory required to	that of	the USER_CWINDOWWORDS	*/
/*     constant.							*/
/*									*/
/*     Upon Entry:							*/
/*									*/
/*     HAB hAB;	= Application Anchor Block Handle			*/
/*									*/
/*     Upon Exit:							*/
/*									*/
/*     DateFldRegister =  TRUE : Class Registration Successful		*/
/*		       = FALSE : Class Registration Failed		*/
/*									*/
/* --------------------------------------------------------------------	*/

BOOL EXPENTRY DateFldRegister(HAB hAB)

{
		       /* Register the control class with OS/2		*/
		       /* Presentation Manager and return registration	*/
		       /* result					*/

return(WinRegisterClass(hAB, "DateField", DateFldWndProc,
			CS_SYNCPAINT | CS_SIZEREDRAW, USER_CWINDOWWORDS));

}
#pragma	subtitle("   Date Entry Field Control DLL - Query Control Information Function")
#pragma	page ( )

/* --- DateFldQuery ---------------------------------------------------	*/
/*									*/
/*     This function is	used to	return to the caller information	*/
/*     regarding the installable control and its capabilities.	The	*/
/*     function	should return a	true value otherwise Resource		*/
/*     Editor will not register	the control as being usable.		*/
/*									*/
/*     Upon Entry:							*/
/*									*/
/*     PUSERINFO pUserInfo; = User Information Pointer			*/
/*									*/
/*     Upon Exit:							*/
/*									*/
/*     DateFldQuery =  TRUE : User Information Being Returned		*/
/*		    = FALSE : No User Information Available		*/
/*									*/
/* --------------------------------------------------------------------	*/

BOOL EXPENTRY DateFldQuery(PUSERINFO pUserInfo)

{
		       /* Complete the User Information	structure	*/
		       /* passed to the	function by Resource Editor  */

		       /* Complete the version and number of control	*/
		       /* types.  In Version 2.10 of CCSL, only	one	*/
		       /* control type is used.				*/
pUserInfo->ulMajor = 2UL;
pUserInfo->ulMinor = 0UL;
		       /* Complete the author and control classname	*/

memcpy(pUserInfo->szAuthor,    "Prominare Inc.", 15);
memcpy(pUserInfo->szClassname, "DateField", 10);
memcpy(pUserInfo->szName,      "DateFld", 8);

		       /* Complete the default size and	style of the	*/
		       /* first	user control type			*/

pUserInfo->utDefined[0].cx	     = 77L;
pUserInfo->utDefined[0].cy	     = 12L;
pUserInfo->utDefined[0].flStyle	     = WS_VISIBLE | DFS_DASH | DFS_MDY | DFS_CURRENTDATE;

		       /* Set the maximum amount of text control can	*/
		       /* accept including NULL	termination byte	*/

pUserInfo->utDefined[0].cMaxText     = 16UL;

		       /* Save the style's dialogue ID, type, control   */
		       /* data size and	count of style masks		*/

pUserInfo->utDefined[0].idDlg	     = DLG_CTRLUSER;
pUserInfo->utDefined[0].flOptions    = PMCXOPT_REFRESH;
pUserInfo->utDefined[0].ulType	     = UTYPE_PRIVATE;
pUserInfo->utDefined[0].cCtlData     = 0UL;
pUserInfo->utDefined[0].cMasks	     = 6UL;
pUserInfo->utDefined[0].flStyleType  = STYLETYPE_BITFLAGS;
pUserInfo->utDefined[0].stMasks[0].flStyleMask = DFS_DASH;
pUserInfo->utDefined[0].stMasks[0].idStyle     = IDS_DFS_DASH;
pUserInfo->utDefined[0].stMasks[1].flStyleMask = DFS_SLASH;
pUserInfo->utDefined[0].stMasks[1].idStyle     = IDS_DFS_SLASH;
pUserInfo->utDefined[0].stMasks[2].flStyleMask = DFS_YMD;
pUserInfo->utDefined[0].stMasks[2].idStyle     = IDS_DFS_YMD;
pUserInfo->utDefined[0].stMasks[3].flStyleMask = DFS_DMY;
pUserInfo->utDefined[0].stMasks[3].idStyle     = IDS_DFS_DMY;
pUserInfo->utDefined[0].stMasks[4].flStyleMask = DFS_MDY;
pUserInfo->utDefined[0].stMasks[4].idStyle     = IDS_DFS_MDY;
pUserInfo->utDefined[0].stMasks[5].flStyleMask = DFS_CURRENTDATE;
pUserInfo->utDefined[0].stMasks[5].idStyle     = IDS_DFS_CURRENTDATE;

		       /* Save the description of the control		*/

memcpy(pUserInfo->utDefined[0].szDescription, "Date Entry Field", 17);

		       /* Return the success flag back to Resource	*/
		       /* Editor					*/
return(TRUE);
}
#pragma	subtitle("   Date Entry Field Control DLL - Control Window Procedure")
#pragma	page( )

/* --- lGetPresParam ----------------------------------	[ Private } ---	*/
/*									*/
/*     This function is	used to	retrieve a presentation	parameter	*/
/*     that may	be present.  If	the presentation parameter is not,	*/
/*     the default colour passed to the	function will be used.		*/
/*									*/
/*     Upon Entry:							*/
/*									*/
/*     HWND  hWnd;     = Window	Handle					*/
/*     ULONG ulID1;    = Presentation Parameter	1 ID			*/
/*     ULONG ulID2;    = Presentation Parameter	2 ID			*/
/*     LONG  lDefault; = Default Colour					*/
/*									*/
/*     Upon Exit:							*/
/*									*/
/*     lGetPresParam = Colour to Use					*/
/*									*/
/* --------------------------------------------------------------------	*/

LONG lGetPresParam(HWND	hWnd, ULONG ulID1, ULONG ulID2,	LONG lDefault)

{
HPS   hPS;			   /* Presentation Space Handle		*/
LONG  lClr;			   /* Presentation Parameter Colour	*/
ULONG ulID;			   /* Presentation Parameter ID		*/

if ( WinQueryPresParam(hWnd, ulID1, ulID2, &ulID, 4UL, (PVOID)&lClr,
		       QPF_NOINHERIT | QPF_ID2COLORINDEX | QPF_PURERGBCOLOR) )
   return(lClr);
else
   if (	(lDefault >= SYSCLR_SHADOWHILITEBGND) &&
	(lDefault <= SYSCLR_HELPHILITE)	)
       return(WinQuerySysColor(HWND_DESKTOP, lDefault, 0L));
   else
       if ( (lClr = GpiQueryRGBColor(hPS = WinGetPS(hWnd),
				     LCOLOPT_REALIZED, lDefault)) == GPI_ALTERROR )
	   {
	   WinReleasePS(hPS);
	   return(lDefault);
	   }
       else
	   {
	   WinReleasePS(hPS);
	   return(lClr);
	   }
}
#pragma	subtitle("   Date Entry Field Control DLL - Control Window Sizing Procedure")
#pragma	page ( )

/* --- CalcSize	---------------------------------------	[ Private ] ---	*/
/*									*/
/*     This function is	used to	calculate the sizes and	positions	*/
/*     of the various elements that are	used to	make up	a shadowed	*/
/*     text field.							*/
/*									*/
/*     Upon Entry:							*/
/*									*/
/*     HWND	  hWnd;	= Window Handle					*/
/*     PRECTL	  prcl;	= Control Rectangle Pointer			*/
/*     PDATEFIELD pdf;	= Group	Box Information	Pointer			*/
/*									*/
/*     Upon Exit:							*/
/*									*/
/*     Nothing								*/
/*									*/
/* --------------------------------------------------------------------	*/

static VOID CalcSize(PRECTL prcl, PDATEFIELD pdf)

{

pdf->aswp[0].x	= prcl->xLeft +	3L;
pdf->aswp[0].y	= prcl->yBottom	+ 3L;
pdf->aswp[0].cy	= prcl->yTop - prcl->yBottom - 6L;

pdf->aswp[1].x	= pdf->aswp[0].x + pdf->aswp[0].cx + pdf->cxSep	+ 3L;
pdf->aswp[1].y	= prcl->yBottom	+ 3L;
pdf->aswp[1].cy	= prcl->yTop - prcl->yBottom - 6L;

pdf->aswp[2].x	= pdf->aswp[1].x + pdf->aswp[1].cx + pdf->cxSep	+ 3L;
pdf->aswp[2].y	= prcl->yBottom	+ 3L;
pdf->aswp[2].cy	= prcl->yTop - prcl->yBottom - 6L;

WinSetMultWindowPos((HAB)NULL, pdf->aswp, 3UL);
}
#pragma	subtitle("   Date Entry Field Control DLL - Default Colours Procedure")
#pragma	page( )

/* --- SetDefaultColours ------------------------------	[ Private ] ---	*/
/*									*/
/*     This function is	used to	set the	default	colours	that the	*/
/*     image button should use within the internal paint routines.	*/
/*     The colour can either be	a presentation parameter that has	*/
/*     been set	or it can be the default colour	as defined within	*/
/*     control.								*/
/*									*/
/*     Upon Entry:							*/
/*									*/
/*     HWND    hWnd;	= Window Handle					*/
/*     PIMGBTN pimgbtn;	= Image	Button Structure Pointer		*/
/*									*/
/*     Upon Exit:							*/
/*									*/
/*     Nothing								*/
/*									*/
/* --------------------------------------------------------------------	*/

static VOID SetDefaultColours(HWND hWnd, PDATEFIELD pdf)

{
		       /* Set up the colours that will be used within	*/
		       /* the painting of the control.	The colour	*/
		       /* indices are:					*/
		       /*						*/
		       /* 0 : Foreground (PP_FOREGROUND*)		*/
		       /* 1 : Background (PP_BACKGROUND*)		*/
		       /* 2 : Hilight Foreground (PP_HILITEFOREGROUND*)	*/
		       /* 3 : Hilight Background (PP_HILITEBACKGROUND*)	*/
		       /* 4 : Disabled Foreground (PP_DISABLEDFORE*)	*/
		       /* 5 : Disabled Foreground (PP_DISABLEDFORE*)	*/
		       /* 6 : Border (PP_BORDER*)			*/

pdf->aClr[0] = lGetPresParam(hWnd, PP_FOREGROUNDCOLOR,
			     PP_FOREGROUNDCOLORINDEX,
			     SYSCLR_OUTPUTTEXT);
pdf->aClr[1] = lGetPresParam(hWnd, PP_BACKGROUNDCOLOR,
			     PP_BACKGROUNDCOLORINDEX,
			     SYSCLR_FIELDBACKGROUND);
pdf->aClr[2] = lGetPresParam(hWnd, PP_HILITEFOREGROUNDCOLOR,
			     PP_HILITEFOREGROUNDCOLORINDEX,
			     SYSCLR_OUTPUTTEXT);
pdf->aClr[3] = lGetPresParam(hWnd, PP_HILITEBACKGROUNDCOLOR,
			     PP_HILITEBACKGROUNDCOLORINDEX,
			     SYSCLR_BACKGROUND);
pdf->aClr[4] = lGetPresParam(hWnd, PP_DISABLEDFOREGROUNDCOLOR,
			     PP_DISABLEDFOREGROUNDCOLORINDEX,
			     SYSCLR_OUTPUTTEXT);
pdf->aClr[5] = lGetPresParam(hWnd, PP_DISABLEDBACKGROUNDCOLOR,
			     PP_DISABLEDBACKGROUNDCOLORINDEX,
			     SYSCLR_BACKGROUND);
pdf->aClr[6] = lGetPresParam(hWnd, PP_BORDERCOLOR,
			     PP_BORDERCOLORINDEX,
			     SYSCLR_BUTTONDARK);
}
#pragma	subtitle("   Date Entry Field Control DLL - Parse Date Function")
#pragma	page( )

/* --- fParseDate -------------------------------------	[ Private ] ---	*/
/*									*/
/*     This function is	used to	parse a	submitted date from a		*/
/*     INT a year, month, day integer format.				*/
/*									*/
/*     Upon Entry:							*/
/*									*/
/*     CHAR *pszDateStr; = Date	String to Decode			*/
/*     PLONG plYear;	 = Pointer to Year Holder			*/
/*     PLONG plMonth;	 = Pointer to Month Holder			*/
/*     PLONG plDay;	 = Pointer to Day Holder			*/
/*									*/
/*     Upon Exit:							*/
/*									*/
/*     fParseDate =  TRUE : Date String	Successfully Parsed		*/
/*		  = FALSE : Date String	Invalid				*/
/*									*/
/* --------------------------------------------------------------------	*/

BOOL fParseDate(CHAR *pszDateStr, PLONG	plYear,	PLONG plMonth, PLONG plDay, ULONG ulType)

{
PCH  pch;			   /* Character	String Pointer		*/
PCH  pchDate;			   /* Date Character String Pointer	*/
register INT i;			   /* Loop Counter			*/

		       /* Replace "-" separators with "/"		*/

for ( i	= 0; i < 7; i++)
   if (	pszDateStr[i] == '-' )
       pszDateStr[i] = '/';

if ( (pch = strchr(pszDateStr, '/')) &&	(strlen(pszDateStr) >= 6) )
   {
   switch ( ulType )
       {
       case DATE_YMD :
		       /* Extract month	from date string submitted	*/

	   *pch	= 0;
	   *plYear = (LONG)atol(pszDateStr);

		       /* Determine day/year separator			*/

	   if (	!(pch =	strchr(pchDate = ++pch,	'/')) )
	       return(FALSE);

		       /* Extract day from date	string submitted	*/

	   *pch	= 0;
	   *plMonth = (LONG)atol(pchDate);
	   if (	(*plMonth < 1L)	|| (*plMonth > 12L) )

		       /* Illegal month	value, return with not		*/
		       /* successful flag				*/

	       return(FALSE);

		       /* Extract year from date string	submitted	*/

	   *plDay = (LONG)atol(++pch);
	   if (	(*plDay	< 1L) || (*plDay > 31L)	)

		       /* Illegal day value, return with not		*/
		       /* successful flag				*/

	       return(FALSE);
	   return(TRUE);

       case DATE_MDY :
		       /* Extract month	from date string submitted	*/

	   *pch	= 0;
	   *plMonth = (LONG)atol(pszDateStr);
	   if (	(*plMonth < 1L)	|| (*plMonth > 12L) )

		       /* Illegal month	value, return with not		*/
		       /* successful flag				*/

	       return(FALSE);

		       /* Determine day/year separator			*/

	   if (	!(pch =	strchr(pchDate = ++pch,	'/')) )
	       return(FALSE);

		       /* Extract day from date	string submitted	*/

	   *pch	= 0;
	   *plDay = (LONG)atol(pchDate);
	   if (	(*plDay	< 1L) || (*plDay > 31L)	)

		       /* Illegal day value, return with not		*/
		       /* successful flag				*/

	       return(FALSE);

		       /* Extract year from date string	submitted	*/

	   *plYear = (LONG)atol(++pch);
	   return(TRUE);

       case DATE_DMY :
		       /* Extract month	from date string submitted	*/

	   *pch	= 0;
	   *plDay = (LONG)atol(pszDateStr);
	   if (	(*plDay	< 1L) || (*plDay > 31L)	)

		       /* Illegal day value, return with not		*/
		       /* successful flag				*/

	       return(FALSE);

		       /* Determine day/year separator			*/

	   if (	!(pch =	strchr(pchDate = ++pch,	'/')) )
	       return(FALSE);

		       /* Extract day from date	string submitted	*/

	   *pch	= 0;
	   *plMonth = (LONG)atol(pchDate);
	   if (	(*plMonth < 1L)	|| (*plMonth > 12L) )

		       /* Illegal month	value, return with not		*/
		       /* successful flag				*/

	       return(FALSE);

		       /* Extract year from date string	submitted	*/

	   *plYear = (LONG)atol(++pch);
	   return(TRUE);
       }
   }
return(FALSE);
}
#pragma	subtitle("   Date Entry Field Control DLL - Control Window Procedure")
#pragma	page ( )

/* --- DateFldWndProc ---------------------------------	[ Private ] ---	*/
/*									*/
/*     This function is	used to	handle the messages sent to the		*/
/*     installed control.  The window procedure	is designed to		*/
/*     allow for multiple instances and	to be totally re-entrant.	*/
/*									*/
/*     Upon Entry:							*/
/*									*/
/*     HWND   hWnd; = Window Handle					*/
/*     ULONG  msg;  = PM Message					*/
/*     MPARAM mp1;  = Message Parameter	1				*/
/*     MPARAM mp2;  = Message Parameter	2				*/
/*									*/
/*     Upon Exit:							*/
/*									*/
/*     DateFldWndProc =	Message	Handling Result				*/
/*									*/
/* --------------------------------------------------------------------	*/

MRESULT	EXPENTRY DateFldWndProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2)

{
CHAR	      szBuffer[16];	   /* String Buffer			*/
DATETIME      dt;		   /* Date/Time	Holder			*/
HPS	      hPS;		   /* Presentation Space Handle		*/
LONG	      lClr;		   /* Presentation Parameter Colour	*/
LONG	      lDay;		   /* Day Holder			*/
LONG	      lMonth;		   /* Month Holder			*/
LONG	      lYear;		   /* Year Holder			*/
PCREATESTRUCT pcrst;		   /* Create Structure Pointer		*/
PDATEFIELD    pdf;		   /* Text Field Structure Pointer	*/
PWNDPARAMS    pwprm;		   /* Window Parameters	Pointer		*/
RECTL	      rcl;		   /* Rectangle	Holder			*/
ULONG	      ulID;		   /* Presentation Parameter ID		*/
register INT i,	n;		   /* Loop/Index Counters		*/

switch ( msg )
   {
		       /* Perform control initialization when the	*/
		       /* control is created				*/
   case	WM_CREATE :
		       /* Create a heap	for the	control	using a		*/
		       /* segment					*/

       DosAllocMem((PPVOID)(PVOID)&pdf,	4096UL,	PAG_READ | PAG_WRITE | PAG_COMMIT);

		       /* Save the address of the text string pointer	*/
		       /* in the control's reserved memory to allow it  */
		       /* to be	referenced as required by the control	*/

       WinSetWindowPtr(hWnd, QWW_CDATA,	(PVOID)pdf);

		       /* Get the control's creation structure address  */
		       /* to copy the default text of the control to	*/
		       /* the memory in	the heap			*/

       pcrst = (PCREATESTRUCT)PVOIDFROMMP(mp2);

       pdf->hwndOwner =	pcrst->hwndOwner;
       pdf->hwndDay  = WinCreateWindow(hWnd, WC_ENTRYFIELD, NULL,
				       ES_CENTER | ES_MARGIN | ES_AUTOSCROLL | ES_AUTOTAB | WS_GROUP | WS_TABSTOP,
				       0L, 0L, 0L, 0L, hWnd,
				       HWND_TOP, EF_DAY,
				       pcrst->pCtlData,	pcrst->pPresParams);
       WinSendMsg(pdf->hwndDay,	EM_SETTEXTLIMIT, MPFROMSHORT(2), 0L);

       pdf->hwndMonth  = WinCreateWindow(hWnd, WC_ENTRYFIELD, NULL,
					 ES_CENTER | ES_MARGIN | ES_AUTOSCROLL | ES_AUTOTAB | WS_TABSTOP,
					 0L, 0L, 0L, 0L, hWnd,
					 HWND_TOP, EF_MONTH,
					 pcrst->pCtlData, pcrst->pPresParams);
       WinSendMsg(pdf->hwndMonth, EM_SETTEXTLIMIT, MPFROMSHORT(2), 0L);

       pdf->hwndYear  =	WinCreateWindow(hWnd, WC_ENTRYFIELD, NULL,
					ES_CENTER | ES_MARGIN |	ES_AUTOSCROLL |	ES_AUTOTAB | WS_TABSTOP,
					0L, 0L,	0L, 0L,	hWnd,
					HWND_TOP, EF_YEAR,
					pcrst->pCtlData, pcrst->pPresParams);
       WinSendMsg(pdf->hwndYear, EM_SETTEXTLIMIT, MPFROMSHORT(4), 0L);

       if ( pcrst->flStyle & DFS_DASH )
	   strcpy(pdf->szSep, " - ");
       else
	   strcpy(pdf->szSep, " / ");

       rcl.xLeft = rcl.yBottom = 0L;
       rcl.xRight = rcl.yTop = 200L;

       WinDrawText(hPS = WinGetPS(hWnd), -1L, pdf->szSep, &rcl,	0L, 0L,
		   DT_LEFT | DT_TOP | DT_QUERYEXTENT);

       pdf->cxSep = rcl.xRight - rcl.xLeft;

       rcl.xLeft = rcl.yBottom = 0L;
       rcl.xRight = rcl.yTop = 200L;

       WinDrawText(hPS,	-1L, "444", &rcl, 0L, 0L,
		   DT_LEFT | DT_TOP | DT_QUERYEXTENT);

       pdf->cxDayMonth = rcl.xRight - rcl.xLeft;

       rcl.xLeft = rcl.yBottom = 0L;
       rcl.xRight = rcl.yTop = 200L;

       WinDrawText(hPS,	-1L, "44444", &rcl, 0L,	0L,
		   DT_LEFT | DT_TOP | DT_QUERYEXTENT);

       WinReleasePS(hPS);

       pdf->cxYear = rcl.xRight	- rcl.xLeft;

		       /* Set up the colours that will be used within	*/
		       /* the painting of the control.	The colour	*/
		       /* indices are:					*/
		       /*						*/
		       /* 0 : Foreground (PP_FOREGROUND*)		*/
		       /* 1 : Background (PP_BACKGROUND*)		*/
		       /* 2 : Hilight Foreground (PP_HILITEFOREGROUND*)	*/
		       /* 3 : Hilight Background (PP_HILITEBACKGROUND*)	*/
		       /* 4 : Disabled Foreground (PP_DISABLEDFORE*)	*/
		       /* 5 : Disabled Foreground (PP_DISABLEDFORE*)	*/
		       /* 6 : Border (PP_BORDER*)			*/

       SetDefaultColours(hWnd, pdf);

       if ( pcrst->flStyle & DFS_YMD )
	   {
	   pdf->iDay   = 2;
	   pdf->iMonth = 1;
	   pdf->iYear  = 0;
	   pdf->aswp[0].hwnd		 = pdf->hwndYear;
	   pdf->aswp[0].hwndInsertBehind = HWND_TOP;
	   pdf->aswp[1].hwnd		 = pdf->hwndMonth;
	   pdf->aswp[2].hwnd		 = pdf->hwndDay;
	   pdf->ulDateType = DATE_YMD;
	   }
       else
	   if (	pcrst->flStyle & DFS_DMY )
	       {
	       pdf->iDay   = 0;
	       pdf->iMonth = 1;
	       pdf->iYear  = 2;
	       pdf->aswp[0].hwnd	     = pdf->hwndDay;
	       pdf->aswp[0].hwndInsertBehind = HWND_TOP;
	       pdf->aswp[1].hwnd	     = pdf->hwndMonth;
	       pdf->aswp[2].hwnd	     = pdf->hwndYear;
	       pdf->ulDateType = DATE_DMY;
	       }
	   else
	       {
	       pdf->iDay   = 1;
	       pdf->iMonth = 0;
	       pdf->iYear  = 2;
	       pdf->aswp[0].hwnd	     = pdf->hwndMonth;
	       pdf->aswp[0].hwndInsertBehind = HWND_TOP;
	       pdf->aswp[1].hwnd	     = pdf->hwndDay;
	       pdf->aswp[2].hwnd	     = pdf->hwndYear;
	       pdf->ulDateType = DATE_MDY;
	       }

       pdf->aswp[pdf->iDay].fl	 = SWP_MOVE | SWP_SIZE | SWP_SHOW | SWP_ZORDER;
       pdf->aswp[pdf->iMonth].fl = SWP_MOVE | SWP_SIZE | SWP_SHOW | SWP_ZORDER;
       pdf->aswp[pdf->iYear].fl	 = SWP_MOVE | SWP_SIZE | SWP_SHOW | SWP_ZORDER;
       pdf->aswp[pdf->iDay].cx	 = pdf->cxDayMonth;
       pdf->aswp[pdf->iMonth].cx = pdf->cxDayMonth;
       pdf->aswp[pdf->iYear].cx	 = pdf->cxYear;

       pdf->aswp[1].hwndInsertBehind = pdf->aswp[0].hwnd;
       pdf->aswp[2].hwndInsertBehind = pdf->aswp[1].hwnd;


       if ( pcrst->flStyle & DFS_CURRENTDATE )
	   {
	   DosGetDateTime(&dt);
	   WinSetWindowText(pdf->hwndDay,   _ltoa(dt.day,   szBuffer, 10));
	   WinSetWindowText(pdf->hwndMonth, _ltoa(dt.month, szBuffer, 10));
	   WinSetWindowText(pdf->hwndYear,  _ltoa(dt.year,  szBuffer, 10));
	   }
       else
	   if (	pcrst->pszText && pcrst->pszText[0] )
	       if ( fParseDate(strcpy(pdf->szText, pcrst->pszText), &lYear, &lMonth, &lDay, pdf->ulDateType) )
		   {
		   WinSetWindowText(pdf->hwndDay,   _ltoa(lDay,	  szBuffer, 10));
		   WinSetWindowText(pdf->hwndMonth, _ltoa(lMonth, szBuffer, 10));
		   WinSetWindowText(pdf->hwndYear,  _ltoa(lYear,  szBuffer, 10));
		   }

       pdf->flStyle = pcrst->flStyle;

       rcl.xLeft   =\
       rcl.yBottom = 0L;
       rcl.xRight  = pcrst->cx;
       rcl.yTop	   = pcrst->cy;
       CalcSize(&rcl, pdf);
       break;
		       /* Control size changing, update	the rectangle	*/
		       /* points for the Date Entry Field Control	*/
   case	WM_SIZE	:
       WinQueryWindowRect(hWnd,	&rcl);
       CalcSize(&rcl,
		pdf = (PDATEFIELD)WinQueryWindowPtr(hWnd, QWW_CDATA));
       break;
		       /* Process control notification messages	sent by	*/
		       /* the "roving" entry field.  In	most cases the	*/
		       /* the notification message will	be "repackaged"	*/
		       /* and sent to the owner	of the table for	*/
		       /* processing.					*/
   case	WM_CONTROL :
		       /* Determine the	control	sending	the		*/
		       /* notification message				*/

       switch (	SHORT1FROMMP(mp1) )
	   {
	   case	EF_DAY :
	       switch (	SHORT2FROMMP(mp1) )
		   {
		       /* Entry	field data changed message received	*/

		   case	EN_CHANGE :
		
		       /* Get the address of the control info from the	*/
		       /* control's reserved memory                     */

		       pdf = (PDATEFIELD)WinQueryWindowPtr(hWnd, QWW_CDATA);

		       /* Get the text of the entry field and save	*/
		       /* while	it is being entered to ensure that it	*/
		       /* is always current				*/

		       if ( (n = WinQueryWindowText(pdf->hwndDay, 3L, szBuffer)) != 0 )
			   {
			   for ( i = 0;	i < n; i++ )
			       if ( (szBuffer[i] < '0')	|| (szBuffer[i]	> '9') )
				   {
				   WinSendMsg(pdf->hwndDay, EM_SETSEL,
					      MPFROM2SHORT(i, i	+ 1), 0L);
				   WinAlarm(HWND_DESKTOP, WA_NOTE);
				   WinSetFocus(HWND_DESKTOP, pdf->hwndDay);
				   return(0L);
				   }
			   n = atoi(szBuffer);
			   if (	WinQueryWindowText(pdf->hwndMonth, 3L, szBuffer) )
			       switch (	atoi(szBuffer) )
				   {
				   case	 1 :
				   case	 3 :
				   case	 5 :
				   case	 7 :
				   case	 8 :
				   case	10 :
				   case	12 :
				       if ( n >	31 )
					   {
					   WinAlarm(HWND_DESKTOP, WA_ERROR);
					   WinSendMsg(pdf->hwndDay, EM_SETSEL,
						      MPFROM2SHORT(0, 2), 0L);
					   WinSetFocus(HWND_DESKTOP, pdf->hwndDay);
					   }
				       break;

				   case	 2 :
				       if ( WinQueryWindowText(pdf->hwndYear, 5L, szBuffer) )
					   if (	atoi(szBuffer) % 4 )
					       {
					       if ( n >	28 )
						   {
						   WinAlarm(HWND_DESKTOP, WA_ERROR);
						   WinSendMsg(pdf->hwndDay, EM_SETSEL,
							      MPFROM2SHORT(0, 2), 0L);
						   WinSetFocus(HWND_DESKTOP, pdf->hwndDay);
						   }
					       }
					   else
					       if ( n >	29 )
						   {
						   WinAlarm(HWND_DESKTOP, WA_ERROR);
						   WinSendMsg(pdf->hwndDay, EM_SETSEL,
							      MPFROM2SHORT(0, 2), 0L);
						   WinSetFocus(HWND_DESKTOP, pdf->hwndDay);
						   }
				       break;

				   case	 4 :
				   case	 6 :
				   case	 9 :
				   case	11 :
				       if ( n >	30 )
					   {
					   WinAlarm(HWND_DESKTOP, WA_ERROR);
					   WinSendMsg(pdf->hwndDay, EM_SETSEL,
						      MPFROM2SHORT(0, 2), 0L);
					   WinSetFocus(HWND_DESKTOP, pdf->hwndDay);
					   }
				       break;
				   }
			   }
		       break;

		       /* Allow	all other messages to pass through	*/
		       /* unprocessed by the table control owner	*/

		   default :
		       break;
		   }
	       break;

	   case	EF_MONTH :
	       switch (	SHORT2FROMMP(mp1) )
		   {
		       /* Entry	field data changed message received	*/

		   case	EN_CHANGE :
		
		       /* Get the address of the control info from the	*/
		       /* control's reserved memory                     */

		       pdf = (PDATEFIELD)WinQueryWindowPtr(hWnd, QWW_CDATA);

		       /* Get the text of the entry field and save	*/
		       /* while	it is being entered to ensure that it	*/
		       /* is always current				*/

		       if ( (n = WinQueryWindowText(pdf->hwndMonth, 3L,	szBuffer)) != 0	)
			   {
			   for ( i = 0;	i < n; i++ )
			       if ( (szBuffer[i] < '0')	|| (szBuffer[i]	> '9') )
				   {
				   WinAlarm(HWND_DESKTOP, WA_NOTE);
				   WinSendMsg(pdf->hwndMonth, EM_SETSEL,
					      MPFROM2SHORT(i, i	+ 1), 0L);
				   WinSetFocus(HWND_DESKTOP, pdf->hwndMonth);
				   return(0L);
				   }
			   n = atoi(szBuffer);
			   if (	(n < 1)	|| (n >	12)  )
			       {
			       WinAlarm(HWND_DESKTOP, WA_ERROR);
			       WinSendMsg(pdf->hwndMonth, EM_SETSEL,
					  MPFROM2SHORT(0, 2), 0L);
			       WinSetFocus(HWND_DESKTOP, pdf->hwndMonth);
			       }
			   }
		       break;

		       /* Allow	all other messages to pass through	*/
		       /* unprocessed by the table control owner	*/

		   default :
		       break;
		   }
	       break;


	   case	EF_YEAR	:
	       switch (	SHORT2FROMMP(mp1) )
		   {
		       /* Entry	field data changed message received	*/

		   case	EN_CHANGE :
		
		       /* Get the address of the control info from the	*/
		       /* control's reserved memory                     */

		       pdf = (PDATEFIELD)WinQueryWindowPtr(hWnd, QWW_CDATA);

		       /* Get the text of the entry field and save	*/
		       /* while	it is being entered to ensure that it	*/
		       /* is always current				*/

		       if ( (n = WinQueryWindowText(pdf->hwndYear, 5L, szBuffer)) != 0 )
			   for ( i = 0;	i < n; i++ )
			       if ( (szBuffer[i] < '0')	|| (szBuffer[i]	> '9') )
				   {
				   WinAlarm(HWND_DESKTOP, WA_NOTE);
				   WinSendMsg(pdf->hwndYear, EM_SETSEL,
					      MPFROM2SHORT(i, i	+ 1), 0L);
				   WinSetFocus(HWND_DESKTOP, pdf->hwndYear);
				   return(0L);
				   }
		       break;

		       /* Allow	all other messages to pass through	*/
		       /* unprocessed by the table control owner	*/

		   default :
		       break;
		   }
	       break;

	   default :
	       break;
	   }
       break;
		       /* Process window parameters setting		*/

   case	WM_SETWINDOWPARAMS :

		       /* Get the address for the windows parameters	*/
		       /* structure					*/

       pwprm = (PWNDPARAMS)PVOIDFROMMP(mp1);

		       /* Check	to see if the text for the control is	*/
		       /* being	set					*/

       if ( pwprm->fsStatus & WPM_TEXT )
	   {
		       /* Text being set, get the address of the text	*/
		       /* string stored	in the heap			*/

	   pdf = (PDATEFIELD)WinQueryWindowPtr(hWnd, QWW_CDATA);

		       /* Check	to see if any text is being set		*/

	   if (	pwprm->cchText )
	       {
		       /* Check	to make	sure that the text that	is to	*/
		       /* be set is not	greater	than the memory		*/
		       /* allocated					*/

	       if ( pwprm->cchText > 15	)
		   {
		   strncpy(pdf->szText,	pwprm->pszText,	15);
		   pdf->szText[16] = 0;
		   }
	       else
		   strcpy(pdf->szText, pwprm->pszText);

	       if ( fParseDate(pdf->szText, &lYear, &lMonth, &lDay, pdf->ulDateType) )
		   {
		   WinSetWindowText(pdf->hwndDay,   _ltoa(lDay,	  szBuffer, 10));
		   WinSetWindowText(pdf->hwndMonth, _ltoa(lMonth, szBuffer, 10));
		   WinSetWindowText(pdf->hwndYear,  _ltoa(lYear,  szBuffer, 10));
		   }
	       }
	   else
	       {
		       /* No text is being set,	clear any existing text	*/

	       pdf->szText[0] =	0;
	       WinSetWindowText(pdf->hwndDay  ,	"");
	       WinSetWindowText(pdf->hwndMonth,	"");
	       WinSetWindowText(pdf->hwndYear ,	"");
	       }
	   }
       break;
		       /* Process window parameters query		*/

   case	WM_QUERYWINDOWPARAMS :

		       /* Get the address for the windows parameters	*/
		       /* structure					*/

       pwprm = (PWNDPARAMS)PVOIDFROMMP(mp1);

		       /* Determine the	type of	query			*/

       switch (	pwprm->fsStatus	)
	   {
		       /* Query	type:  get text				*/

	   case	WPM_TEXT :

		       /* Text being asked for,	get the	address	of the	*/
		       /* text string stored in	the heap		*/

	       pdf = (PDATEFIELD)WinQueryWindowPtr(hWnd, QWW_CDATA);

	       if ( pdf->flStyle & DFS_YMD )
		   {
		   WinQueryWindowText(pdf->hwndYear,  5L, szBuffer);
		   strcat(szBuffer, pdf->szSep);
		   WinQueryWindowText(pdf->hwndMonth, 3L, &szBuffer[strlen(szBuffer)]);
		   strcat(szBuffer, pdf->szSep);
		   WinQueryWindowText(pdf->hwndDay,   3L, &szBuffer[strlen(szBuffer)]);
		   }
	       else
		   if (	pcrst->flStyle & DFS_DMY )
		       {
		       WinQueryWindowText(pdf->hwndDay,	  3L, szBuffer);
		       strcat(szBuffer,	pdf->szSep);
		       WinQueryWindowText(pdf->hwndMonth, 3L, &szBuffer[strlen(szBuffer)]);
		       strcat(szBuffer,	pdf->szSep);
		       WinQueryWindowText(pdf->hwndYear,  5L, &szBuffer[strlen(szBuffer)]);
		       }
		   else
		       {
		       WinQueryWindowText(pdf->hwndMonth, 3L, szBuffer);
		       strcat(szBuffer,	pdf->szSep);
		       WinQueryWindowText(pdf->hwndDay,	  3L, &szBuffer[strlen(szBuffer)]);
		       strcat(szBuffer,	pdf->szSep);
		       WinQueryWindowText(pdf->hwndDay,	  5L, &szBuffer[strlen(szBuffer)]);
		       }
		       /* Copy the text	from the string	to the		*/
		       /* structure					*/

	       strcpy(pwprm->pszText, szBuffer);
	       break;
		       /* Query	type:  get text	length			*/

	   case	WPM_CCHTEXT :

		       /* Place	the length the string within the	*/
		       /* structure					*/

	       WinQueryWindowText(pdf->hwndYear,  5L, szBuffer);
	       strcat(szBuffer,	pdf->szSep);
	       WinQueryWindowText(pdf->hwndMonth, 3L, &szBuffer[strlen(szBuffer)]);
	       strcat(szBuffer,	pdf->szSep);
	       WinQueryWindowText(pdf->hwndDay,	  3L, &szBuffer[strlen(szBuffer)]);
	       pwprm->cchText =	strlen(szBuffer);
	       break;
		       /* Query	type:  get control data	length		*/

	   case	WPM_CBCTLDATA :

		       /* Set the control data length to zero		*/

	       pwprm->cbCtlData	= 0;
	       break;

	   default :
	       return(WinDefWindowProc(hWnd, msg, mp1, mp2));
	   }
       break;
		       /* Presentation parameters changed, record the	*/
		       /* change internally				*/

   case	WM_PRESPARAMCHANGED :
       if ( LONGFROMMP(mp1) < PP_FONTNAMESIZE )
	   {
	   pdf = (PDATEFIELD)WinQueryWindowPtr(hWnd, QWW_CDATA);
	   if (	WinQueryPresParam(hWnd,	(ULONG)LONGFROMMP(mp1),
				  (ULONG)((LONGFROMMP(mp1) % 2)	? LONGFROMMP(mp1) + 1L : 0L),
				  &ulID, 4UL, (PVOID)&lClr,
				  QPF_NOINHERIT	| QPF_ID1COLORINDEX | QPF_ID2COLORINDEX) )
	       pdf->aClr[(LONGFROMMP(mp1) - 1L)	/ 2L] =	lClr;

	   WinInvalidateRect(hWnd, (PRECTL)NULL, TRUE);
	   }
		       /* Check	to see if an individual	presentation	*/
		       /* parameter has	changed	if so, get the new	*/
		       /* colour value for use by the painting routines	*/

       if ( LONGFROMMP(mp1) && (LONGFROMMP(mp1)	< PP_FONTNAMESIZE) )
	   {
		       /* Get the address of the control info from the	*/
		       /* control's reserved memory                     */

	   pdf = (PDATEFIELD)WinQueryWindowPtr(hWnd, QWW_CDATA);

		       /* Get the new presentation parameter colour for	*/
		       /* the presentation parameter that has changed.	*/
		       /* Get the colour as a RGB value	so as to be	*/
		       /* able to get an exact value and not an		*/
		       /* approximation	which could happen if the	*/
		       /* presentation parameter was set as a RGB but	*/
		       /* queried as an	index.	When WinQueryPresParam	*/
		       /* returns a 0, it indicates that no		*/
		       /* presentation parameter set and the default	*/
		       /* colours should be used.			*/

	   switch ( LONGFROMMP(mp1) )
	       {
	       case PP_FOREGROUNDCOLOR :
	       case PP_FOREGROUNDCOLORINDEX :
		   pdf->aClr[0]	= lGetPresParam(hWnd, PP_FOREGROUNDCOLOR,
						PP_FOREGROUNDCOLORINDEX,
						SYSCLR_OUTPUTTEXT);
		   WinSetPresParam(pdf->hwndDay,
				   PP_FOREGROUNDCOLOR,
				   4L, (PVOID)&pdf->aClr[0]);
		   WinSetPresParam(pdf->hwndMonth,
				   PP_FOREGROUNDCOLOR,
				   4L, (PVOID)&pdf->aClr[0]);
		   WinSetPresParam(pdf->hwndYear,
				   PP_FOREGROUNDCOLOR,
				   4L, (PVOID)&pdf->aClr[0]);
		   break;

	       case PP_BACKGROUNDCOLOR :
	       case PP_BACKGROUNDCOLORINDEX :
		   pdf->aClr[1]	= lGetPresParam(hWnd, PP_BACKGROUNDCOLOR,
						PP_BACKGROUNDCOLORINDEX,
						SYSCLR_BACKGROUND);
		   WinSetPresParam(pdf->hwndDay,
				   PP_BACKGROUNDCOLOR,
				   4L, (PVOID)&pdf->aClr[1]);
		   WinSetPresParam(pdf->hwndMonth,
				   PP_BACKGROUNDCOLOR,
				   4L, (PVOID)&pdf->aClr[1]);
		   WinSetPresParam(pdf->hwndYear,
				   PP_BACKGROUNDCOLOR,
				   4L, (PVOID)&pdf->aClr[1]);
		   break;

	       case PP_HILITEFOREGROUNDCOLOR :
	       case PP_HILITEFOREGROUNDCOLORINDEX :
		   pdf->aClr[2]	= lGetPresParam(hWnd, PP_HILITEFOREGROUNDCOLOR,
						PP_HILITEFOREGROUNDCOLORINDEX,
						SYSCLR_OUTPUTTEXT);
		   break;

	       case PP_HILITEBACKGROUNDCOLOR :
	       case PP_HILITEBACKGROUNDCOLORINDEX :
		   pdf->aClr[3]	= lGetPresParam(hWnd, PP_HILITEBACKGROUNDCOLOR,
						PP_HILITEBACKGROUNDCOLORINDEX,
						SYSCLR_BACKGROUND);
		   break;

	       case PP_DISABLEDFOREGROUNDCOLOR :
	       case PP_DISABLEDFOREGROUNDCOLORINDEX :
		   pdf->aClr[4]	= lGetPresParam(hWnd, PP_DISABLEDFOREGROUNDCOLOR,
						PP_DISABLEDFOREGROUNDCOLORINDEX,
						SYSCLR_OUTPUTTEXT);
		   break;

	       case PP_DISABLEDBACKGROUNDCOLOR :
	       case PP_DISABLEDBACKGROUNDCOLORINDEX :
		   pdf->aClr[5]	= lGetPresParam(hWnd, PP_BACKGROUNDCOLOR,
						PP_BACKGROUNDCOLORINDEX,
						SYSCLR_BACKGROUND);
		   break;

	       case PP_BORDERCOLOR :
	       case PP_BORDERCOLORINDEX	:
		   pdf->aClr[6]	= lGetPresParam(hWnd, PP_BORDERCOLOR,
						PP_BORDERCOLORINDEX,
						SYSCLR_BUTTONDARK);
		   break;
	       }
		       /* Invalidate the button	to force to use	the	*/
		       /* new colours just set or removed		*/

	   WinInvalidateRect(hWnd, (PRECTL)NULL, TRUE);
	   }
       else
		       /* Determine if the Scheme Palette has forced a	*/
		       /* global scheme	update in which	case, check all	*/
		       /* of the presentation parameters to see	if they	*/
		       /* have been added or removed			*/

	   if (	LONGFROMMP(mp1)	== 0L )

		       /* Set up the colours that will be used within	*/
		       /* the painting of the control.			*/

	       SetDefaultColours(hWnd,
				 pdf = (PDATEFIELD)WinQueryWindowPtr(hWnd, QWW_CDATA));
       break;
		       /* Erase	control	background			*/

   case	WM_ERASEBACKGROUND :
       return(MRFROMLONG(TRUE));

		       /* Paint	the Control				*/
   case	WM_PAINT :
		       /* Get the address of the text from the		*/
		       /* control's reserved memory                     */

       pdf = (PDATEFIELD)WinQueryWindowPtr(hWnd, QWW_CDATA);

		       /* Get the presentation space for the control	*/
		       /* and set the colour table to RGB mode		*/

       GpiCreateLogColorTable(hPS = WinBeginPaint(hWnd,	(HPS)NULL, (PRECTL)NULL),
			      0L, LCOLF_RGB, 0L, 0L, (PLONG)NULL);

       rcl.xRight = (rcl.xLeft = pdf->aswp[0].x	+ pdf->aswp[0].cx) + pdf->cxSep;
       rcl.yTop	= (rcl.yBottom = pdf->aswp[0].y) + pdf->aswp[0].cy;

       WinDrawText(hPS,	-1L, pdf->szSep, &rcl, 0L, 0L,
		   DT_CENTER | DT_VCENTER | DT_TEXTATTRS);

       rcl.xRight = (rcl.xLeft = pdf->aswp[1].x	+ pdf->aswp[1].cx) + pdf->cxSep;
       rcl.yTop	= (rcl.yBottom = pdf->aswp[1].y) + pdf->aswp[1].cy;

       WinDrawText(hPS,	-1L, pdf->szSep, &rcl, 0L, 0L,
		   DT_CENTER | DT_VCENTER | DT_TEXTATTRS);

       WinEndPaint(hPS);
       break;
		       /* Control being	destroyed			*/
   case	WM_DESTROY :
		       /* Get the address of the text from the		*/
		       /* control's reserved memory                     */

       pdf = (PDATEFIELD)WinQueryWindowPtr(hWnd, QWW_CDATA);
       WinDestroyWindow(pdf->hwndDay);
       WinDestroyWindow(pdf->hwndMonth);
       WinDestroyWindow(pdf->hwndYear);

		       /* Release the heap allocated for use by	the	*/
		       /* control					*/

       DosFreeMem((PVOID)pdf);
       break;
		       /* Default message processing			*/
   default :
       return(WinDefWindowProc(hWnd, msg, mp1, mp2));
   }

return(0L);
}
#pragma	subtitle("   Date Entry Field Control DLL - Control Styles Dialogue Procedure")
#pragma	page ( )

/* --- DateFldStyles --------------------------------------------------	*/
/*									*/
/*     This function is	used for the custom control's styles dialogue   */
/*     box procedure.							*/
/*									*/
/*     When the	dialogue is invoked from Resource Editor, the		*/
/*     address of the user style information is	contained in message	*/
/*     parameter 2.  The dialogue is responsible for saving the		*/
/*     address.	 The best method to do this is to save the pointer	*/
/*     in the dialogue's reserved memory where it can be retrieved as   */
/*     needed.								*/
/*									*/
/*     Upon Entry:							*/
/*									*/
/*     HWND   hWnd; = Dialog Window Handle				*/
/*     ULONG  msg;  = PM Message					*/
/*     MPARAM mp1;  = Message Parameter	1				*/
/*     MPARAM mp2;  = Message Parameter	2				*/
/*									*/
/*     Upon Exit:							*/
/*									*/
/*     DateFldStyles = Message Handling	Result				*/
/*									*/
/* --------------------------------------------------------------------	*/

MRESULT	EXPENTRY DateFldStyles(HWND hWnd, ULONG	msg, MPARAM mp1, MPARAM	mp2)

{
PUSERSTYLE   pust;		   /* User Style Pointer		*/
SWP	     swp;		   /* Screen Window Position Holder	*/

switch ( msg )
   {
		       /* Perform dialogue initialization		*/
   case	WM_INITDLG :
		       /* Save the pointer to user style information	*/
		       /* within the dialog's reserved memory           */

       WinSetWindowPtr(hWnd, QWL_USER, (PVOID)mp2);

		       /* Get the pointer to the user style information	*/

       if ( (pust = (PUSERSTYLE	 )mp2) != NULL )
	   {
		       /* Set the text,	ID symbol and value for	the	*/
		       /* control					*/

	   WinSetDlgItemText(hWnd, EF_TEXT, pust->pszText);
	   pust->pfnSetSymbolID(hWnd, IDBX_SYMBOLVALUE,	pust);

	   if (	pust->flStyle &	DFS_DASH )
	       WinSendDlgItemMsg(hWnd, RB_DASH,	BM_SETCHECK,
				 MPFROMSHORT(TRUE), 0L);
	   else
	       WinSendDlgItemMsg(hWnd, RB_SLASH, BM_SETCHECK,
				 MPFROMSHORT(TRUE), 0L);

	   if (	pust->flStyle &	DFS_YMD	)
	       WinSendDlgItemMsg(hWnd, RB_YMD, BM_SETCHECK,
				 MPFROMSHORT(TRUE), 0L);
	   else
	       if ( pust->flStyle & DFS_DMY )
		   WinSendDlgItemMsg(hWnd, RB_DMY, BM_SETCHECK,
				     MPFROMSHORT(TRUE),	0L);
	       else
		   WinSendDlgItemMsg(hWnd, RB_MDY, BM_SETCHECK,
				     MPFROMSHORT(TRUE),	0L);

	   if (	pust->flStyle &	DFS_CURRENTDATE	)
	       WinSendDlgItemMsg(hWnd, CB_CURRENTDATE, BM_SETCHECK,
				 MPFROMSHORT(TRUE), 0L);

	   if (	pust->flStyle &	WS_VISIBLE )
	       WinSendDlgItemMsg(hWnd, CB_VISIBLE, BM_SETCHECK,
				 MPFROMSHORT(TRUE), 0L);

	   if (	pust->flStyle &	WS_GROUP )
	       WinSendDlgItemMsg(hWnd, CB_GROUP, BM_SETCHECK,
				 MPFROMSHORT(TRUE), 0L);

	   if (	pust->flStyle &	WS_DISABLED )
	       WinSendDlgItemMsg(hWnd, CB_DISABLED, BM_SETCHECK,
				 MPFROMSHORT(TRUE), 0L);

	   if (	pust->flStyle &	WS_TABSTOP )
	       WinSendDlgItemMsg(hWnd, CB_TABSTOP, BM_SETCHECK,
				 MPFROMSHORT(TRUE), 0L);
	   }
		       /* Centre dialog	on the screen			*/

       WinQueryWindowPos(hWnd, (PSWP)&swp);
       WinSetWindowPos(hWnd, HWND_TOP,
		       (WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN) - swp.cx) /	2L,
		       (WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN) - swp.cy) /	2L,
		       0L, 0L, SWP_MOVE);
       break;
		       /* Process push button selections		*/
   case	WM_COMMAND :
       switch (	SHORT1FROMMP(mp1) )
	   {
		       /* Presentation push button selected		*/

	   case	DID_FONTCLR :

		       /* Get the pointer to the user style information	*/

	       if ( (pust = PDATAFROMDLG(hWnd))	!= NULL	)

		       /* Get the address of the look up function from	*/
		       /* user style information structure and display	*/
		       /* the dialog.  The value selected within the	*/
		       /* dialog will be automatically placed within	*/
		       /* the required entry fields			*/

		   pust->pfnGetFontClr(hWnd);
	       break;
		       /* Enter	pushbutton selected get	the definitions	*/
		       /* for the control				*/
	   case	DID_OK :

		       /* Get the pointer to the user style information	*/

	       if ( (pust = PDATAFROMDLG(hWnd))	!= NULL	)
		   {
		       /* Get the address of the CUA compliance		*/
		       /* function from	the user style information	*/
		       /* structure.  The function will	check the text	*/
		       /* for CUA compliance according to index	value	*/
		       /* selected.  A return value of TRUE from the	*/
		       /* compliance function indicates	that the text	*/
		       /* entered is acceptable.  Conversely, a	FALSE	*/
		       /* return value indicates that text is non-	*/
		       /* compliant.  In this case, the	dialog should	*/
		       /* not be exited	from and the values within the	*/
		       /* the entry fields should not be saved.		*/

		   if (	!pust->pfnCUACheck(hWnd, EF_TEXT, CUACHK_CAPS) )
		       break;

		       /* Get the address of the symbol	validation	*/
		       /* function from	the user style information	*/
		       /* structure.  The function will	validate the	*/
		       /* symbol and will check	for duplications of	*/
		       /* values.  A return value of TRUE from the	*/
		       /* validation function indicates	that the symbol	*/
		       /* and value are	acceptable.  Conversely, a	*/
		       /* FALSE	return value indicates that symbol or	*/
		       /* value	was not	acceptable.  In	this case,	*/
		       /* the dialog should not	be exited from and the	*/
		       /* values within	the entry fields should	not be	*/
		       /* saved.					*/

		   if (	!pust->pfnGetSymbolID(hWnd, IDBX_SYMBOLVALUE, pust) )
		       break;
		   else
		       {
		       /* Symbol and value validated, get the text of	*/
		       /* the control and save within the user style	*/
		       /* information structure	for use	by Resource	*/
		       /* Editor					*/

		       pust->cText = WinQueryDlgItemText(hWnd, EF_TEXT,
							 16UL, pust->pszText);

		       /* Mask out current edit	field styles clearing	*/
		       /* selectable styles and	save new style		*/

		       pust->flStyle &=	0xffff8000L;

		       if ( WinSendDlgItemMsg(hWnd, RB_DASH,
					      BM_QUERYCHECK, 0L, 0L) )
			   pust->flStyle |= DFS_DASH;
		       else
			   pust->flStyle |= DFS_SLASH;

		       if ( WinSendDlgItemMsg(hWnd, RB_YMD,
					      BM_QUERYCHECK, 0L, 0L) )
			   pust->flStyle |= DFS_YMD;
		       else
			   if (	WinSendDlgItemMsg(hWnd,	RB_DMY,
						  BM_QUERYCHECK, 0L, 0L) )
			       pust->flStyle |=	DFS_DMY;
			   else
			       pust->flStyle |=	DFS_MDY;

		       if ( WinSendDlgItemMsg(hWnd, CB_CURRENTDATE,
					      BM_QUERYCHECK, 0L, 0L) )
			   pust->flStyle |= DFS_CURRENTDATE;

		       /* Save completed edit field style in internal	*/
		       /* window information				*/

		       pust->flStyle &=	~(WS_VISIBLE | WS_GROUP	| WS_DISABLED |	WS_TABSTOP);
		       if ( WinSendDlgItemMsg(hWnd, CB_VISIBLE,
					      BM_QUERYCHECK, 0L, 0L) )
			   pust->flStyle |= WS_VISIBLE;

		       if ( WinSendDlgItemMsg(hWnd, CB_GROUP,
					      BM_QUERYCHECK, 0L, 0L) )
			   pust->flStyle |= WS_GROUP;

		       if ( WinSendDlgItemMsg(hWnd, CB_DISABLED,
					      BM_QUERYCHECK, 0L, 0L) )
			   pust->flStyle |= WS_DISABLED;

		       if ( WinSendDlgItemMsg(hWnd, CB_TABSTOP,
					      BM_QUERYCHECK, 0L, 0L) )
			   pust->flStyle |= WS_TABSTOP;
		       }
		   }
		       /* Exit the dialogue indicating changes made	*/

	       WinDismissDlg(hWnd, TRUE);
	       break;
		       /* Cancel selected, exit	the dialogue without	*/
		       /* changing anything				*/

	   case	DID_CANCEL :
	       WinDismissDlg(hWnd, FALSE);
	       break;
	   }
       break;
		       /* Close	received, exit dialog			*/
   case	WM_CLOSE :
       WinDismissDlg(hWnd, FALSE);
       break;
		       /* Pass through unhandled messages		*/
   default :
       return(WinDefDlgProc(hWnd, msg, mp1, mp2));
   }
return(0L);

}
