/* $XConsortium: spin_box.c /main/5 1995/07/15 20:39:47 drk $ */
/*
 * @OPENGROUP_COPYRIGHT@
 * COPYRIGHT NOTICE
 * Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, Inc.
 * Copyright (c) 1996, 1997, 1998, 1999, 2000 The Open Group
 * ALL RIGHTS RESERVED (MOTIF).  See the file named COPYRIGHT.MOTIF for
 * the full copyright text.
 * 
 * This software is subject to an open license. It may only be
 * used on, with or for operating systems which are themselves open
 * source systems. You must contact The Open Group for a license
 * allowing distribution and sublicensing of this software on, with,
 * or for operating systems which are not Open Source programs.
 * 
 * See http://www.opengroup.org/openmotif/license for full
 * details of the license agreement. Any use, reproduction, or
 * distribution of the program constitutes recipient's acceptance of
 * this agreement.
 * 
 * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
 * PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
 * WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
 * OR FITNESS FOR A PARTICULAR PURPOSE
 * 
 * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT
 * NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
 * EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
 * 
 */
/*
 * HISTORY
 */
#include <stdio.h>
/* #include <X11/Xos.h>  */
#include <Xm/XmAll.h>
#include <Xmd/RegEdit.h>

#define NUM_MONTHS	12
#define NUM_LETTERS	10
#define Y_OFFSET	50

#define SPIN1_MIN	 0
#define SPIN1_MAX	 6

void setMonths(void);
void setLetters(void);
void printReason(int reason);
void setMaxDay(Widget monthWidget, int nextMM);
void changedSpin0(Widget w, XtPointer client, XtPointer call);
void changedSpin1(Widget w, XtPointer client, XtPointer call);
void changedSpin6(Widget w, XtPointer client, XtPointer call);
void modifySpin1(Widget w, XtPointer client, XtPointer call);
void modifySpin4(Widget w, XtPointer client, XtPointer call);
void demoExit(Widget w, XtPointer client, XtPointer call);
int  main(int argc, char **argv);
void CreateSpinBoxes(Widget parent_of_spin_box);

int thisMM = 3;
int thisDD = 27;
int thisYY = 94; 

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

static char *letters[NUM_LETTERS] =
  {
  "a", "b", "c", "d", "e", "f", "g", "f", "h", "i" 
  };

XmString monthValues[NUM_MONTHS];
XmString letterValues[NUM_LETTERS];

/*****		SpinBox Widgets		*****/

Widget spin0, spin0_text, spin1, spin1_text, spin2, spin2_text; 
Widget spin3, spin3_text, spin4, spin4_text, spin5, spin5_text;

Widget spin6, spin6_text1, spin6_deco1, spin6_text2, spin6_deco2;
Widget spin6_text3;
Widget top_level;


#define APP_CLASS "XmdSpinBox"

static String fallbacks[] = {
"spinbox.allowShellResize: True",
"spinbox*fontList: fixed",
NULL
};


/* main() */
int
main (int argc, char **argv)
{
 XtAppContext  app;
 Display      *display;

 XtAppContext app_context;
 Widget       main_window;

   XtSetLanguageProc(NULL, NULL, NULL);
   top_level = XtVaAppInitialize(&app_context, APP_CLASS, 
                                NULL, 0, &argc, argv, 
                                fallbacks, NULL);
   XmdRegisterEditres(top_level);
   main_window = XtVaCreateManagedWidget("main_window", 
                                xmMainWindowWidgetClass, top_level,
                                NULL);

   CreateMenus(main_window);
   CreateSpinBoxes(main_window);

   XtRealizeWidget(top_level);
   XtAppMainLoop(app_context);
   exit(0);
}



void
CreateSpinBoxes(Widget parent_of_spin_box)
{
Cardinal     n;
Position     nextY;
Arg	     argList[25];
Widget       parent;
XmString     decoString;

    /*****  Set Y position for next SpinBox  *****/
    nextY = 10;

    /*****  Create BulletinBoard parent for SpinBox widgets  *****/
    n = 0;
    XtSetArg(argList[n], XmNwidth, 250); n++;
    XtSetArg(argList[n], XmNheight, 400); n++;

    parent = XmCreateBulletinBoard(parent_of_spin_box, "Parent", 
                                   argList, n);
    XtManageChild(parent);

    /****************************************************************/

    /*****
     *****  Create SpinBox spin0
     *****
     *****  Choices:  months of the year
     *****
     *****  Callbacks:
     *****    - changedSpin0 Prints string desription of callback
     *****        reason, and prints 'new' year when boundary
     *****        is crossed (January to December, decrement year;
     *****        December to January, increment year);
     *****/

    /*****  Create SpinBox parent  *****/
    n = 0;
    XtSetArg(argList[n], XmNy, nextY); n++;

    spin0 = XmCreateSpinBox(parent, "spin0", argList, n);

    /*****  Increment Y position for next SpinBox  *****/
    nextY += Y_OFFSET;

    /*****  Create XmString array of month names  *****/
    setMonths();

    /*****  Create TextField child  *****/
    n = 0;

    XtSetArg(argList[n], XmNvalues, monthValues); n++;
    XtSetArg(argList[n], XmNnumValues, 12); n++;
    XtSetArg(argList[n], XmNspinBoxChildType, XmSTRING); n++;
    XtSetArg(argList[n], XmNselectionPolicy, XmSINGLE_SELECT); n++;
    XtSetArg(argList[n], XmNeditable, False); n++;

    spin0_text = XmCreateTextField(spin0, "spin0_text", argList, n);

    /*****  Manage SpinBox  *****/
    XtManageChild(spin0);

    /*****  Call changedSpin0 AFTER displayed value has changed  *****/
    XtAddCallback(spin0, XmNvalueChangedCallback, changedSpin0, (XtPointer) 0);

    /*****  Manage SpinBox child  *****/
    XtManageChild(spin0_text);

    /*****  End of SpinBox spin0  *****/



    /*****
     *****  Create SpinBox spin1
     *****
     *****  Choices:  letters of the alphabet
     *****
     *****  Callbacks:
     *****    - modifySpin1 Callback prevents spinning beyond
     *****        positions 0 (letter a) and 6 (letter g)
     *****
     *****    - changedSpin1 Sets arrow sensitivity to inhibit wrapping
     *****
     *****/

    /*****  Create SpinBox parent  *****/
    n = 0;
    XtSetArg(argList[n], XmNy, nextY); n++;
    XtSetArg(argList[n], XmNdefaultArrowSensitivity, 
                         XmARROWS_DECREMENT_SENSITIVE); n++;
    spin1 = XmCreateSpinBox(parent, "spin1", argList, n);
			   

    /*****  Increment Y position for next SpinBox  *****/
    nextY += Y_OFFSET;

    /*****  Create XmString array of single letters  *****/
    setLetters();

    /*****  Create SpinBox child  *****/
    n = 0;
    XtSetArg(argList[n], XmNvalues, letterValues); n++;
    XtSetArg(argList[n], XmNnumValues, NUM_LETTERS); n++;
    XtSetArg(argList[n], XmNspinBoxChildType, XmSTRING); n++;
    XtSetArg(argList[n], XmNarrowSensitivity, 
                         XmARROWS_INCREMENT_SENSITIVE); n++;
    XtSetArg(argList[n], XmNeditable, False); n++;

    spin1_text = XmCreateTextField(spin1, "spin0_text", argList, n);
				  

    /*****  Manage SpinBox  *****/
    XtManageChild(spin1);

    /*****  Call modifySpin1 BEFORE displayed value is changed  *****/
    XtAddCallback(spin1, XmNmodifyVerifyCallback, modifySpin1, (XtPointer) 0);

    /*****  Call changedSpin1 AFTER displayed value has changed  *****/
    XtAddCallback(spin1, XmNvalueChangedCallback, changedSpin1, (XtPointer) 0);

    /*****  Manage SpinBox child  *****/
    XtManageChild(spin1_text);

    /*****  End of SpinBox spin1  *****/



    /*****
     *****  Create SpinBox spin2
     *****
     *****  Choices:  0.0000 to 0.0010 by .0002
     *****
     *****  Initial Position:  4 (displays 0.0008)
     *****
     *****  Callbacks:  none
     *****
     *****/

    /*****  Create SpinBox parent  *****/
    n = 0;
    XtSetArg(argList[n], XmNy, nextY); n++;

    spin2 = XmCreateSpinBox( parent, "spin2", argList, n );

    /*****  Increment Y position for next SpinBox  *****/
    nextY +=  Y_OFFSET;

    n = 0;
    XtSetArg(argList[n], XmNposition, 4); n++;
    XtSetArg(argList[n], XmNdecimalPoints, 4); n++;
    XtSetArg(argList[n], XmNincrementValue, 2); n++;
    XtSetArg(argList[n], XmNspinBoxChildType, XmNUMERIC); n++;
    XtSetArg(argList[n], XmNeditable, False); n++;

    spin2_text = XmCreateTextField( spin2,
				    "spin2_text",
				    argList,
				    n ); 
				  

    /*****  Manage SpinBox  *****/
    XtManageChild(spin2);

    /*****  Manage SpinBox child  *****/
    XtManageChild(spin2_text);

    /*****  End of SpinBox spin2  *****/



    /*****
     *****  Create SpinBox spin3
     *****
     *****  Choices:  0.000 to 121.500 by 0.002
     *****
     *****  Callbacks:  none
     *****
     *****/

    /*****  Create SpinBox parent  *****/
    n = 0;
    XtSetArg(argList[n], XmNy, nextY); n++;
    XtSetArg(argList[n], XmNrepeatDelay, 250); n++;
    XtSetArg(argList[n], XmNarrowLayout, XmARROWS_BEGINNING); n++;

    spin3 = XmCreateSpinBox( parent,
			     "spin3",
			     argList,
			     n );
			   

    /*****  Increment Y position for next SpinBox  *****/
    nextY +=  Y_OFFSET;

    n = 0;
    XtSetArg(argList[n], XmNminimumValue, 0); n++;
    XtSetArg(argList[n], XmNdecimalPoints, 3); n++;
    XtSetArg(argList[n], XmNincrementValue, 2); n++;
    XtSetArg(argList[n], XmNmaximumValue, 121500); n++;
    XtSetArg(argList[n], XmNspinBoxChildType, XmNUMERIC); n++;

    spin3_text = XmCreateTextField( spin3,
				    "spin3_text",
				    argList,
				    n ); 
				  

    /*****  Manage SpinBox  *****/
    XtManageChild(spin3);

    /*****  Manage SpinBox child  *****/
    XtManageChild(spin3_text);

    /*****  End of SpinBox spin3  *****/



    /*****
     *****  Create SpinBox spin4
     *****
     *****  Choices:  0 to 10 by 1
     *****
     *****  Callbacks:
     *****    - modifySpin4 Callback inhibits spinning below 0
     *****      at all times.  Wrapping increments the maximum value.
     *****
     *****/

    /*****  Create SpinBox parent  *****/
    n = 0;
    XtSetArg(argList[n], XmNy, nextY); n++;
    XtSetArg(argList[n], XmNarrowSize, 35); n++;
    XtSetArg(argList[n], XmNrepeatDelay, 250); n++;
    XtSetArg(argList[n], XmNinitialDelay, 500); n++;
    XtSetArg(argList[n], XmNarrowLayout, XmARROWS_SPLIT); n++;

    spin4 = XmCreateSpinBox( parent,
			     "spin4",
			     argList,
			     n );

    /*****  Increment Y position for next SpinBox  *****/
    nextY +=  Y_OFFSET;

    n = 0;
    XtSetArg(argList[n], XmNmaximumValue, 4); n++;
    XtSetArg(argList[n], XmNspinBoxChildType, XmNUMERIC); n++;

    spin4_text = XmCreateTextField( spin4,
				    "spin4_text",
				    argList,
				    n ); 
				  

    /*****  Manage SpinBox  *****/
    XtManageChild(spin4);

    /*****  Call modifySpin4 BEFORE displayed value is changed  *****/
    XtAddCallback(spin4, XmNmodifyVerifyCallback, modifySpin4, (XtPointer) 0);

    /*****  Manage SpinBox child  *****/
    XtManageChild(spin4_text);

    /*****  End of SpinBox spin4  *****/



    /*****
     *****  Create SpinBox spin5
     *****
     *****  Choices:  0 to 10 by 1
     *****
     *****  Delay:  Repeat delay is 0 - displayed value only increments
     *****          or decrements ONCE each time arrow is armed
     *****
     *****  Callbacks:  none
     *****
     *****/

    /*****  Create SpinBox parent  *****/
    n = 0;
    XtSetArg(argList[n], XmNy, nextY); n++;
    XtSetArg(argList[n], XmNarrowSize, 20); n++;
    XtSetArg(argList[n], XmNrepeatDelay, 0); n++;
    XtSetArg(argList[n], XmNarrowLayout, XmARROWS_BEGINNING); n++;

    spin5 = XmCreateSpinBox( parent,
			     "spin5",
			     argList,
			     n );
			   

    /*****  Increment Y position for next SpinBox  *****/
    nextY +=  Y_OFFSET;

    n = 0;
    XtSetArg(argList[n], XmNminimumValue, 1); n++;
    XtSetArg(argList[n], XmNposition, 1); n++;
    XtSetArg(argList[n], XmNspinBoxChildType, XmNUMERIC); n++;
    XtSetArg(argList[n], XmNeditable, False); n++;

    spin5_text = XmCreateTextField( spin5,
				    "spin5_text",
				    argList,
				    n ); 
				  

    /*****  Manage SpinBox  *****/
    XtManageChild(spin5);

    /*****  Manage SpinBox child  *****/
    XtManageChild(spin5_text);

    /*****  End of SpinBox spin5  *****/



    /*****
     *****  Create SpinBox spin6
     *****
     *****  This example has multiple children, including two
     *****  decoration children.  In addition, this SpinBox
     *****  includes 'chaining', the process where a change
     *****  in one child causes values to change in the child
     *****  and on or more other children.  Chaining is performed
     *****  by the valueChanged callback.
     *****
     *****  Choices:  spin6_text1 1 to 12 (months)
     *****            spin6_deco1 '/' decoration
     *****            spin6_text2 1 to 28-31 (max days varies by month)
     *****            spin6_deco2 '/' decoration
     *****            spin6_text3 0 to 99 (years)
     *****
     *****  Callbacks:
     *****    - changedSpin6 sets maximum days in month.  The month field
     *****          is chained to the day field, and the year field is
     *****          chained to the month field.  (When the day child
     *****          wraps, the month child is also changed.  When the
     *****          month child wraps, the year child is also changed.)
     *****
     *****/

    /*****  Create SpinBox parent  *****/
    n = 0;
    XtSetArg(argList[n], XmNy, nextY); n++;
    XtSetArg(argList[n], XmNinitialDelay, 0); n++;
    XtSetArg(argList[n], XmNrepeatDelay, 150); n++;

    spin6 = XmCreateSpinBox( parent,
			     "spin6",
			     argList,
			     n );
			   

    /*****  Increment Y position for next SpinBox  *****/
    nextY +=  Y_OFFSET;

    /*****  Create SpinBox child  *****/
    n = 0;
    XtSetArg(argList[n], XmNwidth, 30); n++;
    XtSetArg(argList[n], XmNposition, thisMM - 1); n++;
    XtSetArg(argList[n], XmNminimumValue, 1); n++;
    XtSetArg(argList[n], XmNmaximumValue, 12); n++;
    XtSetArg(argList[n], XmNspinBoxChildType, XmNUMERIC); n++;

    spin6_text1 = XmCreateTextField( spin6,
				     "spin6_text1",
				     argList,
				     n ); 
				   

    /*****  Create SpinBox decoration child  *****/
    n = 0;
    decoString = XmStringCreateLtoR("/", XmSTRING_DEFAULT_CHARSET);
    XtSetArg(argList[n], XmNlabelString, decoString); n++;

    spin6_deco1 = XmCreateLabel( spin6,
			         "spin6_deco1",
			         argList,
			         n );

    /*****  Create SpinBox child  *****/
    n = 0;
    XtSetArg(argList[n], XmNwidth, 30); n++;
    XtSetArg(argList[n], XmNposition, thisDD - 1); n++;
    XtSetArg(argList[n], XmNminimumValue, 1); n++;
    XtSetArg(argList[n], XmNmaximumValue, 31); n++;
    XtSetArg(argList[n], XmNspinBoxChildType, XmNUMERIC); n++;

    spin6_text2 = XmCreateTextField( spin6,
				     "spin6_text2",
				     argList,
				     n ); 

    /*****  Create SpinBox decoration child  *****/
    n = 0;
    decoString = XmStringCreateLtoR("/", XmSTRING_DEFAULT_CHARSET);
    XtSetArg(argList[n], XmNlabelString, decoString); n++;
    spin6_deco2 = XmCreateLabel( spin6,
			         "spin6_deco2",
			         argList,
			         n );
			       

    XmStringFree(decoString);

    /*****  Create SpinBox child  *****/
    n = 0;
    XtSetArg(argList[n], XmNwidth, 30); n++;
    XtSetArg(argList[n], XmNposition, thisYY); n++;
    XtSetArg(argList[n], XmNmaximumValue, 99); n++;
    XtSetArg(argList[n], XmNspinBoxChildType, XmNUMERIC); n++;
    

    spin6_text3 = XmCreateTextField( spin6,
				     "spin6_text3",
				     argList,
				     n ); 

    /*****  Manage SpinBox  *****/
    XtManageChild(spin6);

    /*****  Call changedSpin6 AFTER displayed value has changed  *****/
    XtAddCallback(spin6, XmNvalueChangedCallback, changedSpin6, (XtPointer) 0);

    /*****  Manage SpinBox children  *****/
    XtManageChild(spin6_text1);
    XtManageChild(spin6_deco1);
    XtManageChild(spin6_text2);
    XtManageChild(spin6_deco2);
    XtManageChild(spin6_text3);

    /*****  End of SpinBox spin6  *****/
}



/*****							*****/
/*****			Utility Functions		*****/
/*****							*****/

/*****
 *****	setMonths - create XmString array of month names
 *****/
void
setMonths()
{
XmString tempString;
int	 monthLoop;

    for (monthLoop = 0; monthLoop < NUM_MONTHS; monthLoop++)
	{
	tempString = XmStringCreate(months[monthLoop], XmFONTLIST_DEFAULT_TAG);
	monthValues[monthLoop] = tempString;
	}
}

/*****
 *****	setLetters - create XmString array of single letters
 *****/
void
setLetters()
{
XmString tempString;
int	 letterLoop;

    for (letterLoop = 0; letterLoop < NUM_LETTERS; letterLoop++)
	{
	tempString = XmStringCreate(letters[letterLoop], XmFONTLIST_DEFAULT_TAG);
	letterValues[letterLoop] = tempString;
	}
}

/*****
 *****	printReason - print string description of callback reason
 *****/
void
printReason(int reason)
{

    printf("reason = ");

    switch(reason)
	{
	case XmCR_SPIN_NEXT:
	    printf("XmCR_SPIN_NEXT");
	    break;

	case XmCR_SPIN_PRIOR:
	    printf("XmCR_SPIN_PRIOR");
	    break;

	case XmCR_SPIN_FIRST:
	    printf("XmCR_SPIN_FIRST");
	    break;

	case XmCR_SPIN_LAST:
	    printf("XmCR_SPIN_LAST");
	    break;

	case XmCR_OK:
	    printf("XmCR_OK");
	    break;

	default:
	    printf("** unknown ** (%d)", reason);
	    break;
	}

    printf("\n");
}

/*****
 *****	setMaxDay - set maximumValue for day widget
 *****/
void
setMaxDay(Widget monthWidget, int nextMM)
{
Cardinal n;
Arg      argList[5];
int	 lastDay;

    if (nextMM == 2)
	{
	if (thisYY %4 == 0 && thisYY %400 != 0)
	    lastDay = 29;
	else
	    lastDay = 28;
	}
    else if (nextMM ==  4
	 ||  nextMM ==  6
	 ||  nextMM ==  9
	 ||  nextMM == 11)
	lastDay = 30;
    else
	lastDay = 31;

    n = 0;

    XtSetArg(argList[n], XmNmaximumValue, lastDay);
    n++;

    XtSetValues(monthWidget, argList, n);
}

/*****							*****/
/*****			Callback Functions		*****/
/*****							*****/

void
changedSpin0(Widget w, XtPointer client, XtPointer call)
{
XmSpinBoxCallbackStruct *user;
static int		thisYear = 1994;

    user = (XmSpinBoxCallbackStruct *)call;

    /*****  Print string description of reason  *****/
    printReason(user->reason);

    if (user->crossed_boundary)
	{
	if (user->reason == XmCR_SPIN_NEXT)
	  thisYear++;
	else
	  thisYear--;

	printf("Year Now: %d\n", thisYear);
	}
}

void
changedSpin1(Widget w, XtPointer client, XtPointer call)
{
XmSpinBoxCallbackStruct *user;
Cardinal		n;
Arg		   	argList[5];

    user = (XmSpinBoxCallbackStruct *)call;

    n = 0;

    if (user->position == SPIN1_MAX)
	XtSetArg(
		argList[n],
		XmNarrowSensitivity,
		XmARROWS_DECREMENT_SENSITIVE
		);
    else if (user->position == SPIN1_MIN)
	XtSetArg(
		argList[n],
		XmNarrowSensitivity,
		XmARROWS_INCREMENT_SENSITIVE
		);
    else
	XtSetArg(argList[n], XmNarrowSensitivity, XmARROWS_SENSITIVE);

    n++;

    XtSetValues(user->widget, argList, n);
}

void
changedSpin6(Widget w, XtPointer client, XtPointer call)
{
XmSpinBoxCallbackStruct *user;
Cardinal		n;
Arg		   	argList[5];
int			saveMM;
int			saveDD;
int			saveYY;

    user = (XmSpinBoxCallbackStruct *)call;

    if (user->widget == spin6_text1)
	{
	thisMM = user->position + 1;

        if (thisDD <=3 )
	    setMaxDay(spin6_text2, thisMM -1);
	else if (thisDD > 27)
	    setMaxDay(spin6_text2, thisMM);

	saveYY = thisYY;

	if (user->crossed_boundary)
	    if (user->reason == XmCR_SPIN_NEXT)
		thisYY++;
	    else
		thisYY--;

	if (thisYY != saveYY)
	    {
	    if (thisYY < 0)
		thisYY = 99;
	    else if (thisYY > 99)
		thisYY %= 100;

	    n = 0;
	    XtSetArg(argList[n], XmNposition, thisYY);
	    n++;

	    XtSetValues(spin6_text3, argList, n);
	    }
	}
    else if (user->widget == spin6_text2)
	{
        thisDD = user->position + 1;

        if (thisDD <=3 && user->reason == XmCR_SPIN_PRIOR)
            setMaxDay(spin6_text2, thisMM -1);
        else if (thisDD > 27 && user->reason == XmCR_SPIN_NEXT)
            setMaxDay(spin6_text2, thisMM);

        saveMM = thisMM;
        saveYY = thisYY;

        if (user->crossed_boundary)
            if (user->reason == XmCR_SPIN_NEXT)
                thisMM++;
            else
                thisMM--;

        if (thisMM != saveMM)
            {
            if (thisMM < 1)
		{
		thisMM = 12;
		thisYY--;
		}
            else if (thisMM > 12)
		{
		thisMM = 1;
		thisYY++;
		}

            n = 0;
            XtSetArg(argList[n], XmNposition, thisMM - 1);
            n++;

            XtSetValues(spin6_text1, argList, n);

	    if (thisYY != saveYY)
		{
		n = 0;
		XtSetArg(argList[n], XmNposition, thisYY);
		n++;

		XtSetValues(spin6_text3, argList, n);
		}
            }
        }
    else if (user->widget == spin6_text3)
	{
	thisYY = user->position;

        if (user->reason == XmCR_OK)
	    {
	    if (thisDD <= 3)
		setMaxDay(spin6_text2, thisMM - 1);
	    else if (thisDD > 27)
		setMaxDay(spin6_text2, thisMM);
	    }
	}
}

void
modifySpin1(Widget w, XtPointer client, XtPointer call)
{
XmSpinBoxCallbackStruct *user;

    user = (XmSpinBoxCallbackStruct *)call;

    if (user->position > SPIN1_MAX)
	user->doit = False;
    else
        /*****  Print string description of reason  *****/
	printReason(user->reason);
}

void
modifySpin4(Widget w, XtPointer client, XtPointer call)
{
XmSpinBoxCallbackStruct *user;
int			newHigh;
Cardinal		n;
Arg		   	argList[5];

    user = (XmSpinBoxCallbackStruct *)call;

    if (user->crossed_boundary)
	{
        if (user->reason == XmCR_SPIN_NEXT)
	    {
	    n = 0;
	    XtSetArg(argList[n], XmNmaximumValue, &newHigh); n++;
	    XtGetValues(user->widget, argList, n);

	    newHigh++;

	    n = 0;
	    XtSetArg(argList[n], XmNmaximumValue, newHigh); n++;
	    XtSetValues(user->widget, argList, n);
            user->position = 0;
	    }
	else if (user->reason == XmCR_SPIN_PRIOR)
		user->doit = False;
	}
}

