#pragma	title("Super Spin Button DLL  --  Version 1.0 -- (SpinBtn.C)")
#pragma	subtitle("   Resource Editor - Interface Definitions")

#pragma	info(noext)
	
#define	INCL_DOS		   /* Include OS/2 DOS Kernal		*/
#define	INCL_GPI		   /* Include OS/2 PM GPI Interface	*/
#define	INCL_WIN		   /* Include OS/2 PM Windows Interface	*/
#define	INCL_NLS		   /* Include OS/2 PM NLS Support	*/

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

#include <pmcx.h>

#include "spinbtn.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	SpinBtn.C				*/

/* Filename:   SpinBtn.C						*/

/*  Version:   1.0							*/
/*  Created:   1993-12-21						*/
/*  Revised:   1994-09-02						*/

/* Routines:   BOOL EXPENTRY SpinBtnRegister(HAB hAB);			*/
/*	       BOOL EXPENTRY SpinBtnQuery(PUSERINFO pUserInfo);		*/
/*	       MRESULT EXPENTRY	SpinBtnWndProc(HWND hWnd, ULONG	msg,	*/
/*					       MPARAM mp1, MPARAM mp2);	*/
/*	       MRESULT EXPENTRY	SpinBtnStyles(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.								*/
/************************************************************************/
/************************************************************************/

/* --- Spin Button Window Information Structures ----------------------	*/

typedef	struct _SPINBTN
   {
   HWND	     hWnd;		   /* Control Window Handle		*/
   ULONG     id;		   /* ID Value				*/
   HWND	     hwndOwner;		   /* Owner Window Handle		*/
   HWND	     hwndParent;	   /* Parent Window Handle		*/
   HWND	     hwndSpinBtn;	   /* Spin Button Window Handle		*/
   } SPINBTN ;

typedef	SPINBTN	*PSPINBTN;

/* --- Spin Button Support --------------------------------------------	*/

typedef	struct _SPINBTNCDATA
   {
   ULONG    cb;			   /* Structure	Size			*/
   ULONG    idMaster;		   /* Master ID				*/
   LONG	    lLimitLower;	   /* Lower Limit			*/
   LONG	    lLimitUpper;	   /* Upper Limit			*/
   LONG	    lCurrentValue;	   /* Current Value			*/
   ULONG    ulSize;		   /* Text Limits			*/
   ULONG    cItems;		   /* Items Count			*/
   BYTE	    abList[1];		   /* Array List Start			*/
   } SPINBTNCDATA ;

typedef	SPINBTNCDATA *PSPINBTNCDATA;

BOOL	EXPENTRY SpinBtnRegister(HAB hAB);
BOOL	EXPENTRY SpinBtnQuery(PUSERINFO	pUserInfo);
MRESULT	EXPENTRY SpinBtnDlgProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2);

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

#pragma	subtitle("   Super Spin Button DLL - Control Initialization Function")
#pragma	page ( )

/* --- SpinBtnRegister --------------------------------- [ Public ] ---	*/
/*									*/
/*     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:							*/
/*									*/
/*     SpinBtnRegister =  TRUE : Class Registration Successful		*/
/*		       = FALSE : Class Registration Failed		*/
/*									*/
/* --------------------------------------------------------------------	*/

BOOL EXPENTRY SpinBtnRegister(HAB hAB)

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

return(WinRegisterClass(hAB, "SpinBtn",	(PFNWP)SpinBtnWndProc,
			CS_MOVENOTIFY |	CS_PARENTCLIP |	CS_SIZEREDRAW |	CS_SYNCPAINT,
			USER_CWINDOWWORDS));

}
#pragma	subtitle("   Super Spin Button DLL - Query Control Information Function")
#pragma	page ( )

/* --- SpinBtnQuery ------------------------------------ [ Public ] ---	*/
/*									*/
/*     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:							*/
/*									*/
/*     SpinBtnQuery =  TRUE : User Information Being Returned		*/
/*		    = FALSE : No User Information Available		*/
/*									*/
/* --------------------------------------------------------------------	*/

BOOL EXPENTRY SpinBtnQuery(PUSERINFO pUserInfo)

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

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

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

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

pUserInfo->utDefined[0].cx	     = 42L;
pUserInfo->utDefined[0].cy	     = 12L;
pUserInfo->utDefined[0].flStyle	     = SPBS_MASTER | SPBS_NUMERICONLY |	WS_VISIBLE;

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

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

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

pUserInfo->utDefined[0].idDlg	     = DLG_CTRLUSER;
pUserInfo->utDefined[0].ulType	     = UTYPE_PRIVATE;
pUserInfo->utDefined[0].cCtlData     = sizeof(SPINBTNCDATA);
pUserInfo->utDefined[0].cMasks	     = 11UL;
pUserInfo->utDefined[0].flOptions    = PMCXOPT_VARICDATA | PMCXOPT_REFRESH;
pUserInfo->utDefined[0].flStyleType  = STYLETYPE_BITFLAGS;
pUserInfo->utDefined[0].stMasks[0].flStyleMask = SPBS_ALLCHARACTERS;
pUserInfo->utDefined[0].stMasks[0].idStyle     = IDS_SPBS_ALLCHARS;
pUserInfo->utDefined[0].stMasks[1].flStyleMask = SPBS_NUMERICONLY;
pUserInfo->utDefined[0].stMasks[1].idStyle     = IDS_SPBS_NUMERIC;
pUserInfo->utDefined[0].stMasks[2].flStyleMask = SPBS_READONLY;
pUserInfo->utDefined[0].stMasks[2].idStyle     = IDS_SPBS_READONLY;
pUserInfo->utDefined[0].stMasks[3].flStyleMask = SPBS_NOBORDER;
pUserInfo->utDefined[0].stMasks[3].idStyle     = IDS_SPBS_NOBORDER;
pUserInfo->utDefined[0].stMasks[4].flStyleMask = SPBS_FASTSPIN;
pUserInfo->utDefined[0].stMasks[4].idStyle     = IDS_SPBS_FASTSPIN;
pUserInfo->utDefined[0].stMasks[5].flStyleMask = SPBS_PADWITHZEROS;
pUserInfo->utDefined[0].stMasks[5].idStyle     = IDS_SPBS_ZEROPAD;
pUserInfo->utDefined[0].stMasks[6].flStyleMask = SPBS_MASTER;
pUserInfo->utDefined[0].stMasks[6].idStyle     = IDS_SPBS_MASTER;
pUserInfo->utDefined[0].stMasks[7].flStyleMask = SPBS_SERVANT;
pUserInfo->utDefined[0].stMasks[7].idStyle     = IDS_SPBS_SERVANT;
pUserInfo->utDefined[0].stMasks[8].flStyleMask = SPBS_JUSTLEFT;
pUserInfo->utDefined[0].stMasks[8].idStyle     = IDS_SPBS_JUSTLEFT;
pUserInfo->utDefined[0].stMasks[9].flStyleMask = SPBS_JUSTCENTER;
pUserInfo->utDefined[0].stMasks[9].idStyle     = IDS_SPBS_JUSTCENTER;
pUserInfo->utDefined[0].stMasks[10].flStyleMask	= SPBS_JUSTRIGHT;
pUserInfo->utDefined[0].stMasks[10].idStyle	= IDS_SPBS_JUSTRIGHT;

		       /* Save the description of the control		*/

memcpy(pUserInfo->utDefined[0].szDescription, "Spin Button", 12);

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

/* --- SpinBtnWndProc ---------------------------------	[ Private ] ---	*/
/*									*/
/*     This function is	used to	process	the messages for the Spin	*/
/*     Button control window.						*/
/*									*/
/*     Upon Entry:							*/
/*									*/
/*     HWND   hWnd; = Window Handle					*/
/*     ULONG  msg;  = PM Message					*/
/*     MPARAM mp1;  = Message Parameter	1				*/
/*     MPARAM mp2;  = Message Parameter	2				*/
/*									*/
/*     Upon Exit:							*/
/*									*/
/*     SpinBtnWndProc =	Message	Handling Result				*/
/*									*/
/* --------------------------------------------------------------------	*/

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

{
PSPINBTN      psb;		   /* Spin Button Internal Data	Pointer	*/
PSPINBTNCDATA psbd;		   /* Spin Button Data Pointer		*/
PCREATESTRUCT pcrst;		   /* Create Structure Pointer		*/
PSWP	      pswp;		   /* SWP Structure Pointer		*/
PSZ	      *apsz;		   /* psz Array				*/
register INT i,	n;		   /* Loop Counters			*/

switch ( msg )
   {

/************************************************************************/
/************************************************************************/
/*									*/
/* Part	1: Control creation coding					*/
/*									*/
/************************************************************************/
/************************************************************************/

   /*********************************************************************/
   /*  Control creation							*/
   /*********************************************************************/

   case	WM_CREATE :
		       /* Allocate memory for internal control data	*/

       DosAllocMem((PPVOID)(PVOID)&psb,	sizeof(SPINBTN),
		   PAG_READ | PAG_WRITE	| PAG_COMMIT);

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

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

		       /* Get the control's creation structure address  */
		       /* to copy the relevant information such	as the	*/
		       /* size,	position and text of the control into	*/
		       /* the internal control data			*/

       pcrst = (PCREATESTRUCT)PVOIDFROMMP(mp2);

		       /* Save the owner and parent of the control so	*/
		       /* notification messages	can be sent back to	*/
		       /* the proper locations within the owning	*/
		       /* application					*/

       psb->hWnd       = hWnd;
       psb->hwndOwner  = pcrst->hwndOwner;
       psb->hwndParent = pcrst->hwndParent;

       if ( !(psb->hwndSpinBtn = WinCreateWindow(hWnd, WC_SPINBUTTON, pcrst->pszText,
						 pcrst->flStyle,
						 1L, 1L, pcrst->cx - 2L, pcrst->cy - 2L,
						 hWnd, HWND_TOP, 0x1234UL,
						 (PVOID)NULL, (PVOID)pcrst->pPresParams)) )
	   return(MRFROMLONG(TRUE));

		       /* Get the address of the CTLDATA structure that	*/
		       /* may contain the bitmap information that the	*/
		       /* control can use during its creation instead	*/
		       /* of using messages to set the button images	*/

       if ( (psbd = (PSPINBTNCDATA)PVOIDFROMMP(mp1)) !=	NULL )
	   {
	   WinSendMsg(psb->hwndSpinBtn,	SPBM_SETTEXTLIMIT,
		      MPFROMLONG(psbd->ulSize),	0L);

	   if (	pcrst->flStyle & SPBS_SERVANT )
	       WinSendMsg(psb->hwndSpinBtn, SPBM_SETMASTER,
			  MPFROMLONG(WinWindowFromID(psb->hwndParent,
						     psbd->idMaster)), 0L);

	   if (	pcrst->flStyle & SPBS_NUMERICONLY )
	       WinSendMsg(psb->hwndSpinBtn, SPBM_SETLIMITS,
			  MPFROMLONG(psbd->lLimitUpper),
			  MPFROMLONG(psbd->lLimitLower));
	   else
	       if ( psbd->cItems )
		   {
		   DosAllocMem((PPVOID)(PVOID)&apsz, psbd->cItems * sizeof(PSZ),
			       PAG_READ	| PAG_WRITE | PAG_COMMIT);
		   for ( i = n = 0; i <	psbd->cItems; i++ )
		       {
		       apsz[i] = &psbd->abList[n];
		       n += (INT)strlen(&psbd->abList[n]) + 1;
		       }
		   WinSendMsg(psb->hwndSpinBtn,	SPBM_SETARRAY,
			      MPFROMP(apsz), MPFROMLONG(psbd->cItems));

		   DosFreeMem((PVOID)apsz);
		   }
	   WinSendMsg(psb->hwndSpinBtn,	SPBM_SETCURRENTVALUE,
		      MPFROMLONG(psbd->lCurrentValue), 0L);
	   }
       break;

/************************************************************************/
/************************************************************************/
/*									*/
/* Part	2: Control sizing and positioning coding			*/
/*									*/
/************************************************************************/
/************************************************************************/

   /*********************************************************************/
   /*  Control being sized						*/
   /*********************************************************************/

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

       psb = (PSPINBTN)WinQueryWindowPtr(hWnd, QWW_CDATA);
       pswp = (PSWP)PVOIDFROMMP(mp1);
       if ( pswp->fl & SWP_SIZE	)
	   WinSetWindowPos(psb->hwndSpinBtn, HWND_TOP, 1L, 1L,
			   pswp->cx - 2L, pswp->cy - 2L,
			   SWP_SIZE | SWP_MOVE | SWP_SHOW | SWP_ACTIVATE);
       break;

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

       psb = (PSPINBTN)WinQueryWindowPtr(hWnd, QWW_CDATA);
       WinSetWindowPos(psb->hwndSpinBtn, HWND_TOP, 1L, 1L,
		       (LONG)SHORT1FROMMP(mp2) - 4L, (LONG)SHORT2FROMMP(mp2) - 2L,
		       SWP_SIZE	| SWP_MOVE | SWP_SHOW |	SWP_ACTIVATE);
       break;

/************************************************************************/
/************************************************************************/
/*									*/
/* Part	3: Control sizing and positioning coding			*/
/*									*/
/************************************************************************/
/************************************************************************/

   /*********************************************************************/
   /*  Control notification messages					*/
   /*********************************************************************/

   case	WM_CONTROL :
       if ( SHORT1FROMMP(mp1) == 0x1234	)
	   {
		       /* Get the address of the control info from the	*/
		       /* control's reserved memory                     */

	   psb = (PSPINBTN)WinQueryWindowPtr(hWnd, QWW_CDATA);
	   WinSendMsg(psb->hwndOwner, msg,
		      MPFROM2SHORT(psb->id, SHORT2FROMMP(mp1)),
		      HWNDFROMMP(mp2) == psb->hwndSpinBtn ? MPFROMLONG(hWnd) : mp2);
	   }
       break;

/************************************************************************/
/************************************************************************/
/*									*/
/* Part	3: Control sizing and positioning coding			*/
/*									*/
/************************************************************************/
/************************************************************************/

   /*********************************************************************/
   /*  Control being sized						*/
   /*********************************************************************/

   case	WM_CONTROLPOINTER :

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

       psb = (PSPINBTN)WinQueryWindowPtr(hWnd, QWW_CDATA);
       return(WinSendMsg(psb->hwndOwner, msg, mp1, mp2));

/************************************************************************/
/************************************************************************/
/*									*/
/* Part	4: Control specific messages coding				*/
/*									*/
/************************************************************************/
/************************************************************************/

   /*********************************************************************/
   /*  Control specific	messages are simply passed to the Spin Button	*/
   /*********************************************************************/

   case	SPBM_OVERRIDESETLIMITS :
   case	SPBM_QUERYLIMITS :
   case	SPBM_QUERYVALUE	:
   case	SPBM_SETARRAY :
   case	SPBM_SETCURRENTVALUE :
   case	SPBM_SETLIMITS :
   case	SPBM_SETMASTER :
   case	SPBM_SETTEXTLIMIT :
   case	SPBM_SPINDOWN :
   case	SPBM_SPINUP :
		       /* Get the address of the control info from the	*/
		       /* control's reserved memory                     */

       psb = (PSPINBTN)WinQueryWindowPtr(hWnd, QWW_CDATA);
       return(WinSendMsg(psb->hwndSpinBtn, msg,	mp1, mp2));

/************************************************************************/
/************************************************************************/
/*									*/
/* Part	5: General window messages					*/
/*									*/
/************************************************************************/
/************************************************************************/

   /*********************************************************************/
   /*  General window messages are sent	to the Spin Button		*/
   /*********************************************************************/

   case	WM_QUERYWINDOWPARAMS :
   case	WM_SETWINDOWPARAMS :

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

       psb = (PSPINBTN)WinQueryWindowPtr(hWnd, QWW_CDATA);
       return(WinSendMsg(psb->hwndSpinBtn, msg,	mp1, mp2));

/************************************************************************/
/************************************************************************/
/*									*/
/* Part	6: Control destruction coding					*/
/*									*/
/************************************************************************/
/************************************************************************/

   /*********************************************************************/
   /*  Control being destroyed,	perform	clean-up			*/
   /*********************************************************************/

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

       psb = (PSPINBTN)WinQueryWindowPtr(hWnd, QWW_CDATA);
       WinDestroyWindow(psb->hwndSpinBtn);
       DosFreeMem((PVOID)psb);
       break;

/************************************************************************/
/************************************************************************/
/*									*/
/* Part	7: Default Processing						*/
/*									*/
/************************************************************************/
/************************************************************************/
		       /* Default message processing			*/
   default :
       return(WinDefWindowProc(hWnd, msg, mp1, mp2));
   }
return(0L);
}
#pragma	subtitle("   Super Spin Button DLL - Control Styles Dialogue Procedure")
#pragma	page ( )

/* --- SpinBtnStyles ----------------------------------- [ Public ] ---	*/
/*									*/
/*     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:							*/
/*									*/
/*     SpinBtnStyles = Message Handling	Result				*/
/*									*/
/* --------------------------------------------------------------------	*/

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

{
CHAR	      szBuffer[256];	   /* Buffer				*/
INT	      cItems;		   /* Items Count			*/
INT	      cLen;		   /* Text Length			*/
INT	      cLines;		   /* Lines Count			*/
INT	      cTextLen;		   /* Text Length			*/
IPT	      iptData;		   /* MLE Data Start Position		*/
PCHAR	      pch;		   /* Character	String Pointer		*/
PCHAR	      pchData;		   /* Data Pointer			*/
PSPINBTNCDATA psbd;		   /* Spin Button CTLDATA Pointer	*/
PUSERSTYLE    pust;		   /* User Style Pointer		*/
SWP	      swp;		   /* Screen Window Position Holder	*/
register INT i,	n;		   /* Loop Counter			*/

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					*/

	   pust->pfnSetSymbolID(hWnd, IDBX_SYMBOLVALUE,	pust);
	   psbd	= (PSPINBTNCDATA)pust->pbCtlData;

	   if (	psbd->cItems )
	       {
	       WinSendDlgItemMsg(hWnd, MLE_LIST, MLM_SETTEXTLIMIT,
				 MPFROMLONG(16384L), 0L);
	       WinSendDlgItemMsg(hWnd, MLE_LIST, MLM_DISABLEREFRESH, 0L, 0L);
	       WinSendDlgItemMsg(hWnd, MLE_LIST, MLM_RESETUNDO,	0L, 0L);
	       WinSendDlgItemMsg(hWnd, MLE_LIST, MLM_FORMAT,
				 MPFROMSHORT(MLFIE_NOTRANS), 0L);
	       for ( i = n = 0,	iptData	= 0L; i	< psbd->cItems;	i++ )
		   {
		   WinSendDlgItemMsg(hWnd, MLE_LIST, MLM_SETIMPORTEXPORT,
				     MPFROMP(szBuffer),
				     MPFROMLONG(cLen = (INT)strlen(strcat(strcpy(szBuffer,
										 &psbd->abList[n]),
									  "\n"))));
		   WinSendDlgItemMsg(hWnd, MLE_LIST, MLM_IMPORT, MPFROMP(&iptData),
				     MPFROMLONG(cLen));
		   n +=	(INT)strlen(&psbd->abList[n]) +	1;
		   }
	       WinSendDlgItemMsg(hWnd, MLE_LIST, MLM_ENABLEREFRESH, 0L,	0L);

	       }
	   WinSetDlgItemShort(hWnd, EF_IDMASTER,     (USHORT)psbd->idMaster,	  TRUE);
	   WinSetDlgItemShort(hWnd, EF_CURRENTVALUE, (USHORT)psbd->lCurrentValue, TRUE);
	   WinSetDlgItemShort(hWnd, EF_LOWER,	     (USHORT)psbd->lLimitLower,	  TRUE);
	   WinSetDlgItemShort(hWnd, EF_UPPER,	     (USHORT)psbd->lLimitUpper,	  TRUE);
	   WinSetDlgItemShort(hWnd, EF_SIZE,	     (USHORT)psbd->ulSize,	  TRUE);

		       /* Show the spin	button type			*/

	   if (	pust->flStyle &	SPBS_MASTER )
	       WinSendDlgItemMsg(hWnd, RB_SPBS_MASTER, BM_SETCHECK, MPFROMSHORT(TRUE), 0L);
	   else
	       WinSendDlgItemMsg(hWnd, RB_SPBS_SERVANT,	BM_SETCHECK, MPFROMSHORT(TRUE),	0L);

		       /* Show the spin	button entry area alignment	*/

	   if (	(pust->flStyle & SPBS_JUSTCENTER) == SPBS_JUSTCENTER )
	       WinSendDlgItemMsg(hWnd, RB_SPBS_JUSTCENTER, BM_SETCHECK,	MPFROMSHORT(TRUE), 0L);
	   else
	       if ( pust->flStyle & SPBS_JUSTLEFT )
		   WinSendDlgItemMsg(hWnd, RB_SPBS_JUSTLEFT, BM_SETCHECK, MPFROMSHORT(TRUE), 0L);
	       else
		   WinSendDlgItemMsg(hWnd, RB_SPBS_JUSTRIGHT, BM_SETCHECK, MPFROMSHORT(TRUE), 0L);

		       /* Set Numeric Only check box if	selected	*/

	   if (	pust->flStyle &	SPBS_NUMERICONLY )
	       WinSendDlgItemMsg(hWnd, RB_SPBS_NUMERIC,	BM_SETCHECK, MPFROMSHORT(TRUE),	0L);
	   else
		       /* Set Read Only	check box if selected		*/

	       if ( pust->flStyle & SPBS_READONLY )
		   WinSendDlgItemMsg(hWnd, RB_SPBS_READONLY, BM_SETCHECK, MPFROMSHORT(TRUE), 0L);
	       else
		   WinSendDlgItemMsg(hWnd, RB_SPBS_ALLCHARS, BM_SETCHECK, MPFROMSHORT(TRUE), 0L);

		       /* Set No Border	check box if selected		*/

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

		       /* Set Fast Spin	check box if selected		*/

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

		       /* Set Zero Pad check box if selected		*/

	   if (	pust->flStyle &	SPBS_PADWITHZEROS )
	       WinSendDlgItemMsg(hWnd, CB_SPBS_ZEROPAD,	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 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
		       {
		       pust->cText = 0;

		       cLines =	SHORT1FROMMR(WinSendDlgItemMsg(hWnd, MLE_LIST,
					     MLM_QUERYLINECOUNT, 0L, 0L));

		       DosAllocMem((PPVOID)(PVOID)&pchData, 16384UL, PAG_READ |	PAG_WRITE | PAG_COMMIT);
		       for ( i = n = cItems = 0, iptData = 0L; i < cLines; i++ )
			   if (	(cLen =	(INT)(cTextLen = (LONG)WinSendDlgItemMsg(hWnd, MLE_LIST,
										 MLM_QUERYLINELENGTH,
										 MPFROMLONG(iptData), 0L))) != 0 )
			       {
			       WinSendDlgItemMsg(hWnd, MLE_LIST, MLM_SETIMPORTEXPORT,
						 MPFROMP(szBuffer), MPFROMLONG((IPT)cTextLen));
			       WinSendDlgItemMsg(hWnd, MLE_LIST, MLM_EXPORT,
						 MPFROMP(&iptData), MPFROMP(&cTextLen));

			       szBuffer[cLen] =	0;
			       if ( (pch = strchr(szBuffer, '\r')) != NULL )
				   *pch	= 0;
			       else
				   if (	(pch = strchr(szBuffer,	'\n')) != NULL )
				       *pch = 0;

			       if ( szBuffer[0]	)
				   {
				   strcpy(&pchData[n], szBuffer);
				   n +=	(INT)strlen(szBuffer) +	1;
				   ++cItems;
				   }
			       }

		       if ( !(pust->pbCtlData =	(PBYTE)pust->pfnRealloc(pust->pbCtlData,
									n + sizeof(SPINBTNCDATA) - 1L))	)
			   {
			   WinMessageBox(HWND_DESKTOP, hWnd,
					 "Memory error on reallocating control data!",
					 "Super Spin Button Control", 0UL, MB_OK | MB_ICONEXCLAMATION);
			   return(0L);
			   }

		       pust->cbCtlData = (ULONG)(sizeof(SPINBTNCDATA) -	1 + n);

		       psbd = (PSPINBTNCDATA)pust->pbCtlData;
		       psbd->cb	= (ULONG)(sizeof(SPINBTNCDATA) - 1 + n);
		       psbd->cItems = (ULONG)cItems;
		       memcpy(psbd->abList, pchData, (UINT)n);
		       DosFreeMem((PVOID)pchData);

		       WinQueryDlgItemShort(hWnd, EF_IDMASTER,	   (PSHORT)(PVOID)&psbd->idMaster,	TRUE);
		       WinQueryDlgItemShort(hWnd, EF_CURRENTVALUE, (PSHORT)(PVOID)&psbd->lCurrentValue,	TRUE);
		       WinQueryDlgItemShort(hWnd, EF_LOWER,	   (PSHORT)(PVOID)&psbd->lLimitLower,	TRUE);
		       WinQueryDlgItemShort(hWnd, EF_UPPER,	   (PSHORT)(PVOID)&psbd->lLimitUpper,	TRUE);
		       WinQueryDlgItemShort(hWnd, EF_SIZE,	   (PSHORT)(PVOID)&psbd->ulSize,	TRUE);

		       pust->flStyle = 0UL;

		       if ( WinSendDlgItemMsg(hWnd, RB_SPBS_MASTER, BM_QUERYCHECK, 0L, 0L) )
			   pust->flStyle |= SPBS_MASTER;
		       else
			   pust->flStyle |= SPBS_SERVANT;

		       switch (	SHORT1FROMMR(WinSendDlgItemMsg(hWnd, RB_SPBS_JUSTLEFT, BM_QUERYCHECKINDEX,
							       0L, 0L))	+ RB_SPBS_JUSTLEFT )
			   {
			   case	RB_SPBS_JUSTLEFT :
			       pust->flStyle |=	SPBS_JUSTLEFT;
			       break;

			   case	RB_SPBS_JUSTCENTER :
			       pust->flStyle |=	SPBS_JUSTCENTER;
			       break;

			   case	RB_SPBS_JUSTRIGHT :
			       pust->flStyle |=	SPBS_JUSTRIGHT;
			       break;
			   }

		       /* Set Numeric Only style if selected		*/

		       if ( WinSendDlgItemMsg(hWnd, RB_SPBS_NUMERIC, BM_QUERYCHECK, 0L,	0L) )
			   pust->flStyle |= SPBS_NUMERICONLY;
		       else
		       /* Set Read Only	style if selected		*/

			   if (	WinSendDlgItemMsg(hWnd,	RB_SPBS_READONLY, BM_QUERYCHECK, 0L, 0L) )
			       pust->flStyle |=	SPBS_READONLY;
			   else
			       pust->flStyle |=	SPBS_ALLCHARACTERS;

		       /* Set No Border	style if selected		*/

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

		       /* Set Fast Spin	style if selected		*/

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

		       /* Set Zero Pad style if	selected		*/

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

		       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);

}
