/****************************************************************************
*
* $RCSfile: ItemEditor.c $
* $Revision: 1.3 $
* $Date: 1997/09/05 14:46:39 $
* $Author: ssolie $
*
*****************************************************************************
*
* Copyright (c) 1997 Software Evolution.  All Rights Reserved.
*
*****************************************************************************
*
* ItemEditor.c -- ItemEditor class source file
*
* This file contains all the source code for ItemEditor objects.
*/

#include <classact.h>
#include <classes/window.h>
#include <exec/memory.h>
#include <gadgets/button.h>
#include <gadgets/chooser.h>
#include <gadgets/clicktab.h>
#include <gadgets/integer.h>
#include <gadgets/layout.h>
#include <gadgets/string.h>
#include <images/label.h>
#include <intuition/gadgetclass.h>
#include <intuition/icclass.h>
#include <intuition/intuition.h>
#include <intuition/screens.h>

#include <clib/alib_protos.h>
#include <proto/button.h>
#include <proto/chooser.h>
#include <proto/clicktab.h>
#include <proto/exec.h>
#include <proto/integer.h>
#include <proto/intuition.h>
#include <proto/label.h>
#include <proto/layout.h>
#include <proto/string.h>
#include <proto/window.h>

#include "Debug.h"
#include "ItemEditor.h"
#include "LocaleManager.h"
#include "ChooserNodes.h"
#include "ClickTabNodes.h"

#define GetString(x)	(getString(locale_mgr, x, x##_STR))


/*** Global variables ***/
IMPORT LocaleManager		locale_mgr;
IMPORT struct ExecBase		*SysBase;
IMPORT struct IntuitionBase	*IntuitionBase;
IMPORT struct ClassLibrary	*ButtonBase;
IMPORT struct ClassLibrary	*ChooserBase;
IMPORT struct ClassLibrary	*ClickTabBase;
IMPORT struct ClassLibrary	*IntegerBase;
IMPORT struct ClassLibrary	*LabelBase;
IMPORT struct ClassLibrary	*LayoutBase;
IMPORT struct ClassLibrary	*StringBase;
IMPORT struct ClassLibrary	*WindowBase;


/*** Local definitions ***/
#define MIN_CMD_VISIBLE		20		/* nominal size is 2 times this */
#define MAX_CMD_CHARS		(MAX_CMD_LEN - 1)

enum {
	GADGET_TYPES = 1,	/* types clicktab */
	GADGET_MONTH,		/* month chooser */
	GADGET_YDAY,		/* yearly month day integer */
	GADGET_MDAY,		/* monthly month day integer */
	GADGET_WDAY,		/* weekly chooser */
	GADGET_HOUR,		/* hour integer */
	GADGET_MINUTE,		/* minute integer */
	GADGET_SECOND,		/* second integer */
	GADGET_COMMAND,		/* command string */
	GADGET_OK,			/* ok button */
	GADGET_CANCEL		/* cancel button */
};

enum {
	PAGE_YEARLY,		/* yearly page */
	PAGE_MONTHLY,		/* monthly page */
	PAGE_WEEKLY,		/* weekly page */
	PAGE_DAILY,			/* daily page */
	PAGE_COUNT
};


/*** Local data types ***/
struct ItemEditorClass {
	DocketItem item;			/* docket item object reference */
	BOOL done;					/* quit flag */

	struct Screen *screen;		/* Screen pointer */
	struct DrawInfo *draw_info;	/* DrawInfo pointer */

	APTR editor_window;			/* editor window object */
	struct Window *window;		/* editor window pointer */
	APTR editor_layout;			/* editor root layout object */
	APTR types_clicktab;		/* item types clicktab object */
	APTR types_page;			/* item types page object */
	APTR month_chooser;			/* month chooser object */
	APTR yday_integer;			/* yearly month day integer object */
	APTR mday_integer;			/* monthly month day integer object */
	APTR wday_chooser;			/* week day chooser object */
	APTR hour_integer;			/* hour integer object */
	APTR minute_integer;		/* minute integer object */
	APTR second_integer;		/* second integer object */
	APTR command_string;		/* command string object */

	struct List *months_list;	/* months list */
	struct List *wdays_list;	/* week days list */
	struct List *types_list;	/* item types list */
};


/*** Local function prototypes ***/
STATIC VOID process_gadget_event(ItemEditor this, WORD gadget_id);
STATIC UWORD max_mday(UWORD month);


/*
 * newItemEditor -- New ItemEditor object
 *
 * Creates a new item editor window and displays it on the default public
 * screen.  Returns a reference to the ItemEditor object or NULL on error.
 */
ItemEditor newItemEditor(struct Screen *screen, struct DrawInfo *draw_info,
	struct MsgPort *msg_port)
{
	ItemEditor this;
	STRPTR months[MONTHS_PER_YEAR + 1];
	STRPTR wdays[DAYS_PER_WEEK + 1];
	STRPTR types[PAGE_COUNT + 1];
	APTR hour_label, minute_label, second_label, command_label;

	D(bug("newItemEditor(%08lx, %08lx, %08lx)\n",
		screen, draw_info, msg_port));

	if ( screen == NULL || draw_info == NULL || msg_port == NULL )
		return(NULL);

	/*** Create the object ***/
	this = AllocVec(sizeof(struct ItemEditorClass), MEMF_CLEAR);
	if ( this == NULL )
		return(NULL);

	/*** Initialize attributes ***/
	this->done = FALSE;

	/*** Create label lists ***/
	months[0]  = GetString(MSG_JANUARY);
	months[1]  = GetString(MSG_FEBRUARY);
	months[2]  = GetString(MSG_MARCH);
	months[3]  = GetString(MSG_APRIL);
	months[4]  = GetString(MSG_MAY);
	months[5]  = GetString(MSG_JUNE);
	months[6]  = GetString(MSG_JULY);
	months[7]  = GetString(MSG_AUGUST);
	months[8]  = GetString(MSG_SEPTEMBER);
	months[9]  = GetString(MSG_OCTOBER);
	months[10] = GetString(MSG_NOVEMBER);
	months[11] = GetString(MSG_DECEMBER);
	months[12] = NULL;
	this->months_list = createChooserNodes(months);

	wdays[0] = GetString(MSG_SUNDAY);
	wdays[1] = GetString(MSG_MONDAY);
	wdays[2] = GetString(MSG_TUESDAY);
	wdays[3] = GetString(MSG_WEDNESDAY);
	wdays[4] = GetString(MSG_THURSDAY);
	wdays[5] = GetString(MSG_FRIDAY);
	wdays[6] = GetString(MSG_SATURDAY);
	wdays[7] = NULL;
	this->wdays_list = createChooserNodes(wdays);

	types[0] = GetString(MSG_YEARLY_TAB);
	types[1] = GetString(MSG_MONTHLY_TAB);
	types[2] = GetString(MSG_WEEKLY_TAB);
	types[3] = GetString(MSG_DAILY_TAB);
	types[4] = NULL;
	this->types_list = createClickTabNodes(types);

	/*** Create GUI objects ***/
	this->editor_window = WindowObject,
		WA_Title, GetString(MSG_ITEM_EDITOR_TITLE),
		WA_Flags, WFLG_DEPTHGADGET | WFLG_DRAGBAR | WFLG_ACTIVATE |
			WFLG_SIZEGADGET,
		WA_PubScreen, screen,
		WINDOW_Position, WPOS_CENTERSCREEN,
		WINDOW_LockHeight, TRUE,
		WINDOW_SharedPort, msg_port,
		WINDOW_Layout, this->editor_layout = LayoutObject,
			GA_DrawInfo, draw_info,
			LAYOUT_DeferLayout, TRUE,
			LAYOUT_Orientation, LAYOUT_ORIENT_VERT,
			LAYOUT_SpaceOuter, TRUE,

			LAYOUT_AddChild, this->types_clicktab = ClickTabObject,
				GA_ID, GADGET_TYPES,
				GA_RelVerify, TRUE,
				CLICKTAB_Labels, this->types_list,
				CLICKTAB_PageGroup, this->types_page = PageObject,
					LAYOUT_DeferLayout, TRUE,	/* defers layout of pages */

					/*** Yearly page ***/
					PAGE_Add, LayoutObject,
						LAYOUT_Orientation, LAYOUT_ORIENT_VERT,
						LAYOUT_SpaceOuter, TRUE,
						LAYOUT_AddChild, this->month_chooser = ChooserObject,
							GA_ID, GADGET_MONTH,
							GA_RelVerify, TRUE,
							CHOOSER_PopUp, TRUE,
							CHOOSER_Labels, this->months_list,
							CHOOSER_AutoFit, TRUE,
						ChooserEnd,
						CHILD_Label, LabelObject,
							LABEL_Text, GetString(MSG_MONTH_LABEL),
						LabelEnd,
						CHILD_WeightedWidth, 0,
						LAYOUT_AddChild, this->yday_integer = IntegerObject,
							GA_ID, GADGET_YDAY,
							GA_RelVerify, TRUE,
							GA_TabCycle, TRUE,
							INTEGER_MaxChars, 2,
							INTEGER_Minimum, MIN_MDAY,
							INTEGER_MinVisible, 2,
						IntegerEnd,
						CHILD_Label, LabelObject,
							LABEL_Text, GetString(MSG_MDAY_LABEL),
						LabelEnd,
						CHILD_WeightedWidth, 0,
						LAYOUT_AddChild, this->hour_integer = IntegerObject,
							GA_ID, GADGET_HOUR,
							GA_RelVerify, TRUE,
							GA_TabCycle, TRUE,
							INTEGER_MaxChars, 2,
							INTEGER_Minimum, MIN_HOUR,
							INTEGER_Maximum, MAX_HOUR,
							INTEGER_MinVisible, 2,
						IntegerEnd,
						CHILD_Label, hour_label = LabelObject,
							LABEL_Text, GetString(MSG_HOUR_LABEL),
						LabelEnd,
						CHILD_WeightedWidth, 0,
						LAYOUT_AddChild, this->minute_integer = IntegerObject,
							GA_ID, GADGET_MINUTE,
							GA_RelVerify, TRUE,
							GA_TabCycle, TRUE,
							INTEGER_MaxChars, 2,
							INTEGER_Minimum, MIN_MINUTE,
							INTEGER_Maximum, MAX_MINUTE,
							INTEGER_MinVisible, 2,
						IntegerEnd,
						CHILD_Label, minute_label = LabelObject,
							LABEL_Text, GetString(MSG_MINUTE_LABEL),
						LabelEnd,
						CHILD_WeightedWidth, 0,
						LAYOUT_AddChild, this->second_integer = IntegerObject,
							GA_ID, GADGET_SECOND,
							GA_RelVerify, TRUE,
							GA_TabCycle, TRUE,
							INTEGER_MaxChars, 2,
							INTEGER_Minimum, MIN_SECOND,
							INTEGER_Maximum, MAX_SECOND,
							INTEGER_MinVisible, 2,
						IntegerEnd,
						CHILD_Label, second_label = LabelObject,
							LABEL_Text, GetString(MSG_SECOND_LABEL),
						LabelEnd,
						CHILD_WeightedWidth, 0,
						LAYOUT_AddChild, this->command_string = StringObject,
							GA_ID, GADGET_COMMAND,
							GA_RelVerify, TRUE,
							GA_TabCycle, TRUE,
							STRINGA_MinVisible, MIN_CMD_VISIBLE,
							STRINGA_MaxChars, MAX_CMD_CHARS,
						StringEnd,
						CHILD_Label, command_label = LabelObject,
							LABEL_Text, GetString(MSG_COMMAND_LABEL),
						LabelEnd,
					LayoutEnd,

					/*** Monthly page (note the object reuse) ***/
					PAGE_Add, LayoutObject,
						LAYOUT_Orientation, LAYOUT_ORIENT_VERT,
						LAYOUT_SpaceOuter, TRUE,
						LAYOUT_AddChild, this->mday_integer = IntegerObject,
							GA_ID, GADGET_MDAY,
							GA_RelVerify, TRUE,
							GA_TabCycle, TRUE,
							INTEGER_MaxChars, 2,
							INTEGER_Minimum, MIN_MDAY,
							INTEGER_Maximum, MAX_MDAY,
							INTEGER_MinVisible, 2,
						IntegerEnd,
						CHILD_Label, LabelObject,
							LABEL_Text, GetString(MSG_MDAY_LABEL),
						LabelEnd,
						CHILD_WeightedWidth, 0,
						LAYOUT_AddChild, this->hour_integer,
						CHILD_Label, hour_label,
						CHILD_NoDispose, TRUE,
						CHILD_WeightedWidth, 0,
						LAYOUT_AddChild, this->minute_integer,
						CHILD_Label, minute_label,
						CHILD_NoDispose, TRUE,
						CHILD_WeightedWidth, 0,
						LAYOUT_AddChild, this->second_integer,
						CHILD_Label, second_label,
						CHILD_NoDispose, TRUE,
						CHILD_WeightedWidth, 0,
						LAYOUT_AddChild, this->command_string,
						CHILD_Label, command_label,
						CHILD_NoDispose, TRUE,
					LayoutEnd,

					/*** Weekly page (note the object reuse) ***/
					PAGE_Add, LayoutObject,
						LAYOUT_Orientation, LAYOUT_ORIENT_VERT,
						LAYOUT_SpaceOuter, TRUE,
						LAYOUT_AddChild, this->wday_chooser = ChooserObject,
							GA_ID, GADGET_WDAY,
							GA_RelVerify, TRUE,
							CHOOSER_PopUp, TRUE,
							CHOOSER_Labels, this->wdays_list,
							CHOOSER_AutoFit, TRUE,
						ChooserEnd,
						CHILD_Label, LabelObject,
							LABEL_Text, GetString(MSG_WDAY_LABEL),
						LabelEnd,
						CHILD_WeightedWidth, 0,
						LAYOUT_AddChild, this->hour_integer,
						CHILD_Label, hour_label,
						CHILD_NoDispose, TRUE,
						CHILD_WeightedWidth, 0,
						LAYOUT_AddChild, this->minute_integer,
						CHILD_Label, minute_label,
						CHILD_NoDispose, TRUE,
						CHILD_WeightedWidth, 0,
						LAYOUT_AddChild, this->second_integer,
						CHILD_Label, second_label,
						CHILD_NoDispose, TRUE,
						CHILD_WeightedWidth, 0,
						LAYOUT_AddChild, this->command_string,
						CHILD_Label, command_label,
						CHILD_NoDispose, TRUE,
					LayoutEnd,

					/*** Daily page (note the object reuse) ***/
					PAGE_Add, LayoutObject,
						LAYOUT_Orientation, LAYOUT_ORIENT_VERT,
						LAYOUT_SpaceOuter, TRUE,
						LAYOUT_AddChild, this->hour_integer,
						CHILD_Label, hour_label,
						CHILD_NoDispose, TRUE,
						CHILD_WeightedWidth, 0,
						LAYOUT_AddChild, this->minute_integer,
						CHILD_Label, minute_label,
						CHILD_NoDispose, TRUE,
						CHILD_WeightedWidth, 0,
						LAYOUT_AddChild, this->second_integer,
						CHILD_Label, second_label,
						CHILD_NoDispose, TRUE,
						CHILD_WeightedWidth, 0,
						LAYOUT_AddChild, this->command_string,
						CHILD_Label, command_label,
						CHILD_NoDispose, TRUE,
					LayoutEnd,
				PageEnd,
			ClickTabEnd,

			LAYOUT_AddChild, LayoutObject,
				LAYOUT_EvenSize, TRUE,
				LAYOUT_SpaceOuter, TRUE,
				LAYOUT_AddChild, ButtonObject,
					GA_ID, GADGET_OK,
					GA_RelVerify, TRUE,
					GA_Text, GetString(MSG_OK_BUTTON),
				ButtonEnd,
				CHILD_NominalSize, TRUE,
				CHILD_WeightedWidth, 0,
				LAYOUT_AddChild, ButtonObject,
					GA_ID, GADGET_CANCEL,
					GA_RelVerify, TRUE,
					GA_Text, GetString(MSG_CANCEL_BUTTON),
				ButtonEnd,
				CHILD_NominalSize, TRUE,
				CHILD_WeightedWidth, 0,
			LayoutEnd,
		LayoutEnd,
	WindowEnd;

	if ( this->editor_window == NULL )  {
		D2(bug(" cannot create item editor window object\n"));
		deleteItemEditor(this);
		return(NULL);
	}

	return(this);
}


/*
 * deleteItemEditor -- Delete ItemEditor object
 *
 * Deletes an ItemEditor object and frees all its resources.
 */
VOID deleteItemEditor(ItemEditor this)
{
	D(bug("deleteItemEditor(%08lx)\n", this));

	if ( this == NULL )
		return;

	DisposeObject(this->editor_window);
	deleteChooserNodes(this->months_list);
	deleteChooserNodes(this->wdays_list);
	deleteClickTabNodes(this->types_list);

	FreeVec(this);
}


/*
 * openItemEditor -- Open ItemEditor window
 *
 * Opens the ItemEditor window for the given docket item.  Returns TRUE if
 * successful or FALSE on error.
 */
BOOL openItemEditor(ItemEditor this, DocketItem item)
{
	STRPTR command;
	LONG mday, wday, hour, minute, second;
	UWORD type;
	WORD page, month;

	D(bug("openItemEditor(%08lx, %08lx)\n", this, item));

	if ( this == NULL || item == NULL || this->window != NULL )
		return(FALSE);

	/*** Set gadget limits and values ***/
	type = getDocketItemType(item);
	switch ( type )  {
		case YEARLY:
			page  = PAGE_YEARLY;
			month = getDocketItemMonth(item);
			mday  = getDocketItemMonthDay(item);
			wday  = MONDAY;
			break;
		case MONTHLY:
			page  = PAGE_MONTHLY;
			month = JANUARY;
			mday  = getDocketItemMonthDay(item);
			wday  = MONDAY;
			break;
		case WEEKLY:
			page  = PAGE_WEEKLY;
			month = JANUARY;
			mday  = 1;
			wday  = getDocketItemWeekDay(item);
			break;
		case DAILY:
			page  = PAGE_DAILY;
			month = JANUARY;
			mday  = 1;
			wday  = MONDAY;
			break;
		default:
			D2(bug(" bad type=%lu\n", type));
			return(FALSE);
	}

	hour	= getDocketItemHour(item);
	minute	= getDocketItemMinute(item);
	second	= getDocketItemSecond(item);
	command	= getDocketItemCommand(item);

	SetGadgetAttrs((struct Gadget*)this->types_clicktab, NULL, NULL,
		CLICKTAB_Current, page,
		TAG_END);
	SetGadgetAttrs((struct Gadget*)this->types_page, NULL, NULL,
		PAGE_Current, page,
		TAG_END);
	SetPageGadgetAttrs(this->month_chooser, this->types_page, NULL, NULL,
		CHOOSER_Active, month - 1,		/* range 0..11 */
		TAG_END);
	SetPageGadgetAttrs(this->yday_integer, this->types_page, NULL, NULL,
		INTEGER_Number, mday,
		INTEGER_Maximum, max_mday(month),
		TAG_END);
	SetPageGadgetAttrs(this->mday_integer, this->types_page, NULL, NULL,
		INTEGER_Number, mday,
		TAG_END);
	SetPageGadgetAttrs(this->wday_chooser, this->types_page, NULL, NULL,
		CHOOSER_Active, wday,
		TAG_END);
	SetPageGadgetAttrs(this->hour_integer, this->types_page, NULL, NULL,
		INTEGER_Number, hour,
		TAG_END);
	SetPageGadgetAttrs(this->minute_integer, this->types_page, NULL, NULL,
		INTEGER_Number, minute,
		TAG_END);
	SetPageGadgetAttrs(this->second_integer, this->types_page, NULL, NULL,
		INTEGER_Number, second,
		TAG_END);
	SetPageGadgetAttrs(this->command_string, this->types_page, NULL, NULL,
		STRINGA_TextVal, command,
		TAG_END);

	RethinkLayout(this->editor_layout, this->window, NULL, FALSE);

	this->window = (struct Window*)DoMethod(this->editor_window, WM_OPEN);
	if ( this->window == NULL )
		return(FALSE);
	else  {
		this->item = item;
		return(TRUE);
	}
}


/*
 * closeItemEditor -- Close ItemEditor window
 *
 * Closes the ItemEditor window.  Resources will not be freed so that
 * the item editor can be opened again on a new docket item.
 */
VOID closeItemEditor(ItemEditor this)
{
	D(bug("closeItemEditor(%08lx)\n", this));

	if ( this == NULL || this->window == NULL )
		return;

	DoMethod(this->editor_window, WM_CLOSE);

	this->window = NULL;
	this->item = NULL;
}


/*
 * handleItemEditorSignal -- Handle ItemEditor signal
 *
 * Handles the an ItemEditor signal by processing all messages at the
 * message port.  Returns TRUE if the user is done or FALSE if not.
 */
BOOL handleItemEditorSignal(ItemEditor this)
{
	ULONG class, result;
	WORD code, gadget_id;

	D(bug("handleItemEditorSignal(%08lx)\n", this));

	if ( this == NULL || this->editor_window == NULL )
		return(FALSE);

	this->done = FALSE;
	result = DoMethod(this->editor_window, WM_HANDLEINPUT, &code);
	while ( result != WMHI_LASTMSG && !this->done )  {
		class = result & WMHI_CLASSMASK;
		switch ( class )  {
			case WMHI_GADGETUP:
				gadget_id = (WORD)(result & WMHI_GADGETMASK);
				process_gadget_event(this, gadget_id);
				break;
			default:
				D2(bug(" unknown class=%lx code=%lx\n", class, code));
		}

		result = DoMethod(this->editor_window, WM_HANDLEINPUT, &code);
	}

	return(this->done);
}


/*
 * process_gadget_event -- Process item editor gadget event
 *
 * This private function processes a gadget event and takes the appropriate
 * action.
 */
STATIC VOID process_gadget_event(ItemEditor this, WORD gadget_id)
{
	STRPTR command;
	ULONG page, month, mday, wday, hour, minute, second;
	ULONG new_mday;
	UWORD max_days;

	switch ( gadget_id )  {
		case GADGET_TYPES:
			D(bug(" GADGET_TYPES\n"));
			break;
		case GADGET_MONTH:
			GetAttr(CHOOSER_Active, this->month_chooser, &month);
			GetAttr(INTEGER_Number, this->yday_integer, &mday);
			month += 1;

			max_days = max_mday((UWORD)month);
			if ( mday > max_days )
				new_mday = max_days;
			else
				new_mday = mday;

			SetPageGadgetAttrs(this->yday_integer, this->types_page,
				this->window, NULL,
				INTEGER_Number, mday,
				INTEGER_Maximum, max_days,
				TAG_END);

			if ( mday != new_mday )  {
				RefreshPageGadget(this->yday_integer, this->types_page,
					this->window, NULL);
			}
			break;
		case GADGET_MDAY:
			D(bug(" GADGET_MDAY\n"));
			break;
		case GADGET_WDAY:
			D(bug(" GADGET_WDAY\n"));
			break;
		case GADGET_HOUR:
			D(bug(" GADGET_HOUR\n"));
			break;
		case GADGET_MINUTE:
			D(bug(" GADGET_MINUTE\n"));
			break;
		case GADGET_SECOND:
			D(bug(" GADGET_SECOND\n"));
			break;
		case GADGET_COMMAND:
			D(bug(" GADGET_COMMAND\n"));
			break;
		case GADGET_OK:
			GetAttr(PAGE_Current, this->types_page, &page);
			switch ( page )  {
				case PAGE_YEARLY:
					setDocketItemType(this->item, YEARLY);
					GetAttr(CHOOSER_Active, this->month_chooser, &month);
					month += 1;
					setDocketItemMonth(this->item, (UWORD)month);
					GetAttr(INTEGER_Number, this->yday_integer, &mday);
					setDocketItemMonthDay(this->item, (UWORD)mday);
					break;
				case PAGE_MONTHLY:
					setDocketItemType(this->item, MONTHLY);
					GetAttr(INTEGER_Number, this->mday_integer, &mday);
					setDocketItemMonthDay(this->item, (UWORD)mday);
					break;
				case PAGE_WEEKLY:
					setDocketItemType(this->item, WEEKLY);
					GetAttr(CHOOSER_Active, this->wday_chooser, &wday);
					setDocketItemWeekDay(this->item, (UWORD)wday);
					break;
				case PAGE_DAILY:
					setDocketItemType(this->item, DAILY);
					break;
				default:
					D2(bug(" invalid page=%lu\n", page));
					return;
			}

			GetAttr(INTEGER_Number, this->hour_integer, &hour);
			setDocketItemHour(this->item, (UWORD)hour);
			GetAttr(INTEGER_Number, this->minute_integer, &minute);
			setDocketItemMinute(this->item, (UWORD)minute);
			GetAttr(INTEGER_Number, this->second_integer, &second);
			setDocketItemSecond(this->item, (UWORD)second);
			GetAttr(STRINGA_TextVal, this->command_string, (ULONG*)&command);
			setDocketItemCommand(this->item, command);

			this->done = TRUE;
			break;
		case GADGET_CANCEL:
			this->done = TRUE;
			break;
		default:
			D2(bug(" bad gadget_id=%ld\n", gadget_id));
	}
}


/*
 * max_mday -- Get maximum month day
 *
 * This function gets the maximum month day for a given month.  Note that the
 * year is ignored so this function does not take into account leap years.
 * Returns the maximum days in the month or zero on error.
 */
STATIC UWORD max_mday(UWORD month)
{
	switch ( month )  {
		case FEBRUARY:
			return(29);
		case APRIL:
		case JUNE:
		case SEPTEMBER:
		case NOVEMBER:
			return(30);
		case JANUARY:
		case MARCH:
		case MAY:
		case JULY:
		case AUGUST:
		case OCTOBER:
		case DECEMBER:
			return(31);
		default:
			return(0);
	}
}
