/*
**	PattPrefsWin.c
**
**	Copyright (C) 1995,96 Bernardo Innocenti
**
**	Pattern preferences panel and pattern size panel handling functions.
*/

#include <intuition/intuition.h>
#include <libraries/gadtools.h>
#include <libraries/patteditclass.h>
#include <libraries/asl.h>

#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/gadtools.h>
#include <proto/utility.h>
#include <proto/xmodule.h>

#include "XModulePriv.h"
#include "CustomClasses.h"
#include "Gui.h"


static LONG PattPrefsPreOpen		(struct WinUserData *wud);
static void PattPrefsPostClose		(void);
static void ReopenPatternWindow		(void);

static void AdvanceTracksClicked	(struct WinUserData *wud);
static void AdvanceLinesClicked		(struct WinUserData *wud);
static void MaxUndoLevelsClicked	(struct WinUserData *wud);
static void MaxUndoMemClicked		(struct WinUserData *wud);
static void ClipUnitClicked			(struct WinUserData *wud);
static void VScrollerPlaceClicked	(struct WinUserData *wud);
static void HScrollerPlaceClicked	(struct WinUserData *wud);
static void WrapVertClicked			(struct WinUserData *wud);
static void WrapHorizClicked		(struct WinUserData *wud);
static void HexLineNumbersClicked	(struct WinUserData *wud);
static void BlankZeroClicked		(struct WinUserData *wud);
static void DoRulerClicked			(struct WinUserData *wud);
static void DoTinyLinesClicked		(struct WinUserData *wud);
static void GetEditorFontClicked	(struct WinUserData *wud);
static void BGPenClicked			(struct WinUserData *wud);
static void TextPenClicked			(struct WinUserData *wud);
static void LinesPenClicked			(struct WinUserData *wud);
static void TinyLinesPenClicked		(struct WinUserData *wud);
static void PattPrefsOkClicked		(struct WinUserData *wud);
static void PattPrefsCancelClicked	(struct WinUserData *wud);

static void PattSizePostClose		(void);

static void PattSizeLinesClicked	(struct WinUserData *wud);
static void PattSizeTracksClicked	(struct WinUserData *wud);
static void PattSizeDoubleClicked	(struct WinUserData *wud);
static void PattSizeHalveClicked	(struct WinUserData *wud);
static void PattSizeOkClicked		(struct WinUserData *wud);
static void PattSizeCancelClicked	(struct WinUserData *wud);



enum {
	GD_PattPrefsGroup0,
		GD_PattPrefsGroup1,
			GD_PattPrefsGroup2,
				GD_AdvanceTracks,
				GD_AdvanceLines,
				GD_MaxUndoLevels,
				GD_MaxUndoMem,
				GD_ClipUnit,
				GD_VertScroller,
				GD_HorizScroller,
			GD_PattPrefsGroup3,
				GD_WrapVert,
				GD_WrapHoriz,
				GD_HexLineNumbers,
				GD_BlankZero,
				GD_DoRuler,
				GD_DoTinyLines,
				GD_Backdrop,
		GD_PattPrefsGroup4,
			GD_PattPrefsGroup5,
				GD_EditorFont,
				GD_GetEditorFont,
			GD_PattPrefsGroup6,
				GD_PattPrefsGroup7,
					GD_BGPen,
					GD_TextPen,
				GD_PattPrefsGroup8,
					GD_LinesPen,
					GD_TinyLinesPen,
		GD_PattPrefsGroup9,
			GD_PattPrefsOk,
			GD_PattPrefsCancel,

	PattPrefs_CNT
};



enum {
	GD_PattSizeGroup0,
		GD_PattSizeGroup1,
			GD_PattSizeGroup2,
				GD_PattSizeLines,
				GD_PattSizeTracks,
			GD_PattSizeGroup3,
				GD_PattSizeDouble,
			GD_PattSizeGroup4,
				GD_PattSizeHalve,
		GD_PattSizeGroup5,
			GD_PattSizeOk,
			GD_PattSizeCancel,

	PattSize_CNT
};



static struct PattSwitches OldPattSwitches;
static struct Pattern	*OldPatt = NULL;
static struct SongInfo	*OldSong = NULL;
static ULONG OldPattNum = 0;
static UBYTE *ColorTable;
static LONG BGPenTags[] = {
	GTPA_Color, 0,
	GTPA_ColorTable, NULL,
	GTPA_NumColors, 2,
	TAG_DONE
};
static LONG TextPenTags[] = {
	GTPA_Color, 0,
	GTPA_NumColors, 2,
	GTPA_ColorOffset, 1,
	TAG_DONE };



static STRPTR ScrollerPosLabels[] =
{
	(STRPTR)MSG_OFF_GAD,
	(STRPTR)MSG_RIGHT_GAD,
	(STRPTR)MSG_LEFT_GAD,
	(STRPTR)NULL
};



static LONG PattPrefsArgs[] =
{
	HGROUP_KIND, BBFT_RIDGE,
		VGROUP_KIND, 0,
			INTEGER_KIND,	(LONG)AdvanceTracksClicked, MSG_ADVANCE_TRACKS_GAD,		3,	TAG_DONE,
			INTEGER_KIND,	(LONG)AdvanceLinesClicked,	MSG_ADVANCE_LINES_GAD,		5,	TAG_DONE,
			INTEGER_KIND,	(LONG)MaxUndoLevelsClicked,	MSG_MAX_UNDO_LEVELS_GAD,	6,	TAG_DONE,
			INTEGER_KIND,	(LONG)MaxUndoMemClicked,	MSG_MAX_UNDO_MEM_GAD,		10,	TAG_DONE,
			INTEGER_KIND,	(LONG)ClipUnitClicked,		MSG_CLIPBOARD_UNIT_GAD,		3,	TAG_DONE,
			CYCLE_KIND,		(LONG)VScrollerPlaceClicked,MSG_SCROLLER_POS_GAD,	(LONG)ScrollerPosLabels,	TAG_DONE,
			CHECKBOX_KIND,	(LONG)HScrollerPlaceClicked,MSG_HORIZ_SCROLLER_GAD,		NULL,	TAG_DONE,
			ENDGROUP_KIND,
		VGROUP_KIND, 0,
			CHECKBOX_KIND,	(LONG)WrapVertClicked,			MSG_VERT_WRAP_GAD,			NULL,	TAG_DONE,
			CHECKBOX_KIND,	(LONG)WrapHorizClicked,			MSG_HORIZ_WRAP_GAD,			NULL,	TAG_DONE,
			CHECKBOX_KIND,	(LONG)HexLineNumbersClicked,	MSG_HEX_LINE_NUMBERS_GAD,	NULL,	TAG_DONE,
			CHECKBOX_KIND,	(LONG)BlankZeroClicked,			MSG_BLANK_ZERO_GAD,			NULL,	TAG_DONE,
			CHECKBOX_KIND,	(LONG)DoRulerClicked,			MSG_DO_RULER_GAD,			NULL,	TAG_DONE,
			CHECKBOX_KIND,	(LONG)DoTinyLinesClicked,		MSG_DO_TINY_LINES_GAD,		NULL,	TAG_DONE,
			CHECKBOX_KIND,	NULL,							MSG_BACKDROP_GAD,			NULL,	TAG_DONE,
			ENDGROUP_KIND,
		ENDGROUP_KIND,
	VGROUP_KIND, BBFT_RIDGE,
		HGROUP_KIND, 0,
			TEXT_KIND,			MSG_EDITOR_FONT_GAD,			0,		GTTX_Border,	TRUE,	TAG_DONE,
			IMAGEBUTTON_KIND,	(ULONG)GetEditorFontClicked,	IM_PICK,	TAG_DONE,
			ENDGROUP_KIND,
		HGROUP_KIND, 0,
			VGROUP_KIND, 0,
				PALETTE_KIND,	(LONG)BGPenClicked,			MSG_BACKGROUND_PEN_GAD,	TAG_MORE,	(LONG)BGPenTags, TAG_DONE,
				PALETTE_KIND,	(LONG)TextPenClicked,		MSG_TEXT_PEN_GAD,		TAG_MORE,	(LONG)TextPenTags, TAG_DONE,
				ENDGROUP_KIND,
			VGROUP_KIND, 0,
				PALETTE_KIND,	(LONG)LinesPenClicked,		MSG_LINES_PEN_GAD,		TAG_MORE,	(LONG)TextPenTags, TAG_DONE,
				PALETTE_KIND,	(LONG)TinyLinesPenClicked,	MSG_TINY_LINES_PEN_GAD,	TAG_MORE,	(LONG)TextPenTags, TAG_DONE,
				ENDGROUP_KIND,
			ENDGROUP_KIND,
		ENDGROUP_KIND,
	HGROUP_KIND,	0,
		BUTTON_KIND,	(LONG)PattPrefsOkClicked,		MSG_UNDERSCORE_OK_GAD,		TAG_DONE,
		BUTTON_KIND,	(LONG)PattPrefsCancelClicked,	MSG_UNDERSCORE_CANCEL_GAD,	TAG_DONE,
		ENDGROUP_KIND,
	ENDGROUP_KIND
};



static LONG PattSizeArgs[] =
{
	HGROUP_KIND, BBFT_RIDGE,
		VGROUP_KIND, 0,
			INTEGER_KIND,	(LONG)PattSizeLinesClicked,		MSG_LINES_GAD,	5, TAG_DONE,
			INTEGER_KIND,	(LONG)PattSizeTracksClicked,	MSG_TRACKS_GAD,	3, TAG_DONE,
			ENDGROUP_KIND,
		VGROUP_KIND, 0,
			BUTTON_KIND,	(LONG)PattSizeDoubleClicked,	MSG_DOUBLE_GAD,	TAG_DONE,
			ENDGROUP_KIND,
		VGROUP_KIND, 0,
			BUTTON_KIND,	(LONG)PattSizeHalveClicked,		MSG_HALVE_GAD,	TAG_DONE,
			ENDGROUP_KIND,
		ENDGROUP_KIND,
	HGROUP_KIND, 0,
		BUTTON_KIND,	(LONG)PattSizeOkClicked,		MSG_UNDERSCORE_OK_GAD,		TAG_DONE,
		BUTTON_KIND,	(LONG)PattSizeCancelClicked,	MSG_UNDERSCORE_CANCEL_GAD,	TAG_DONE,
		ENDGROUP_KIND,
	ENDGROUP_KIND
};



XDEF LONG PattPrefsWinTags[] =
{
	XMWIN_LayoutArgs,	(LONG)PattPrefsArgs,
	XMWIN_GCount,		PattPrefs_CNT,
	XMWIN_Title,		MSG_PATTPREFS_TITLE,
	XMWIN_WindowFlags,	WFLG_CLOSEGADGET,
	XMWIN_IDCMPFlags,	BUTTONIDCMP|INTEGERIDCMP|PALETTEIDCMP|CHECKBOXIDCMP|IDCMP_CLOSEWINDOW|IDCMP_REFRESHWINDOW,
	XMWIN_PreOpenFunc,	(LONG)PattPrefsPreOpen,
	XMWIN_PostOpenFunc,	(LONG)UpdatePattPrefs,
	XMWIN_PostCloseFunc,(LONG)PattPrefsPostClose,
	XMWIN_HelpNode,		(LONG)"PattPrefs",
	TAG_DONE
};



XDEF LONG PattSizeWinTags[] =
{
	XMWIN_LayoutArgs,	(LONG)PattSizeArgs,
	XMWIN_GCount,		PattSize_CNT,
	XMWIN_Title,		MSG_PATTSIZE_TITLE,
	XMWIN_WindowFlags,	WFLG_CLOSEGADGET,
	XMWIN_IDCMPFlags,	BUTTONIDCMP|INTEGERIDCMP|IDCMP_CLOSEWINDOW|IDCMP_REFRESHWINDOW,
	XMWIN_PostOpenFunc,	(LONG)UpdatePattSize,
	XMWIN_PostCloseFunc,(LONG)PattSizePostClose,
	XMWIN_HelpNode,		(LONG)"PattSize",
	TAG_DONE
};



static LONG PattPrefsPreOpen (struct WinUserData *wud)
{
	ULONG i, j, numcols;

	numcols = 1 << Scr->RastPort.BitMap->Depth;

	if (!ColorTable)
	{
		if (!(ColorTable = AllocVecPooled (Pool, numcols)))
			return 1;

		/* Fill ColorTable */
		for (i = 0, j = 0; i < numcols; i++)
			if (!(i & PattSwitches.TextPen))
				ColorTable[j++] = i;

		/* Clear remaining colors */
		for (i = j ; i < numcols; i++)
			ColorTable[i] = 0;

		BGPenTags[1]	= PattSwitches.LinesPen;
		BGPenTags[3]	= (ULONG) ColorTable;
		BGPenTags[5]	= j;
		TextPenTags[1]	= PattSwitches.TextPen;
		TextPenTags[3]	= numcols - 1;

		memcpy (&OldPattSwitches, &PattSwitches, sizeof (PattSwitches));
	}

	return RETURN_OK;
}



static void PattPrefsPostClose (void)
{
	FreeVecPooled (Pool, ColorTable); ColorTable = NULL;
}


static void ReopenPatternWindow (void)

/* Closes all editor windows and reopens one */
{
	if (WDescr[WID_PATTERN].Wud)
	{
		if (WDescr[WID_PATTERN].Wud->Win)
		{
			/* Close all pattern editors... */
			while (WDescr[WID_PATTERN].UseCnt > 1)
				MyCloseWindow (WDescr[WID_PATTERN].Wud);

			/* And close last window too... */
			MyCloseWindow (WDescr[WID_PATTERN].Wud);

			/* Now ensure the LayoutInfo for this window gets flushed... */
			DeleteLayoutInfo (WDescr[WID_PATTERN].Wud);

			/* And reopen one pattern editor to show changes! */
			NewWindow (WID_PATTERN);
		}
		else DeleteLayoutInfo (WDescr[WID_PATTERN].Wud);
	}
}



void UpdatePattPrefs (void)
{
	/* This variable is declared static because gadtools text
	 * gadgets do not buffer their texts and require them to be
	 * accessible whenever a refresh is needed :-(.
	 */
	static UBYTE editorfont[40];

	struct WinUserData *wud = WDescr[WID_PATTPREFS].Wud;

	if (wud && wud->Win)
	{
		SPrintf (editorfont, "%s/%ld", EditorAttr.ta_Name, EditorAttr.ta_YSize);

		SetGadgets (wud,
			GD_AdvanceTracks,	PattSwitches.AdvanceTracks,
			GD_AdvanceLines,	PattSwitches.AdvanceLines,
			GD_MaxUndoLevels,	PattSwitches.MaxUndoLevels,
			GD_MaxUndoMem,		PattSwitches.MaxUndoMem,
			GD_VertScroller,	PattSwitches.VScrollerPlace,
			GD_HorizScroller,	PattSwitches.HScrollerPlace,
			GD_WrapHoriz,		PattSwitches.Flags & PEF_HWRAP,
			GD_WrapVert,		PattSwitches.Flags & PEF_VWRAP,
			GD_HexLineNumbers,	PattSwitches.Flags & PEF_HEXMODE,
			GD_BlankZero,		PattSwitches.Flags & PEF_BLANKZERO,
			GD_DoRuler,			PattSwitches.Flags & PEF_DOCURSORRULER,
			GD_DoTinyLines,		PattSwitches.Flags & PEF_DOTINYLINES,
			GD_EditorFont,		editorfont,
			GD_BGPen,			PattSwitches.BGPen,
			GD_TextPen,			PattSwitches.TextPen,
			GD_LinesPen,		PattSwitches.LinesPen,
			GD_TinyLinesPen,	PattSwitches.TinyLinesPen,
			-1);
	}
}



static void PattSizePostClose (void)
{
	xmRemPattern (OldSong, -1, (ULONG)OldPatt);
	OldPatt = NULL;
}



GLOBALCALL void UpdatePattSize (void)
{
	struct WinUserData *wud = WDescr[WID_PATTSIZE].Wud;

	if (wud && wud->Win)
	{
		struct SongInfo *si;
		struct Pattern *patt;

		if (si = xmLockActiveSong (SM_SHARED))
		{
			patt = si->Patt[si->CurrentPatt];

			/* Free previous backup copy, if any */

			if (OldPatt) xmRemPattern (OldSong, -1, (ULONG)OldPatt);

			/* Make a local backup copy of the current pattern (it may fail) */

			OldSong		= si;
			OldPattNum	= si->CurrentPatt;
			OldPatt		= CopyPattern (si, si->Patt[si->CurrentPatt], -1);

			/* Update gadgets */
			SetGadgets (wud,
				GD_PattSizeLines, patt->Lines,
				GD_PattSizeTracks, patt->Tracks,
				-1);

			ReleaseSemaphore (&si->Lock);
		}
	}
}



static void AdvanceTracksClicked (struct WinUserData *wud)
{
	struct WinUserData *patternwud = WDescr[WID_PATTERN].Wud;
	PattSwitches.AdvanceTracks = (WORD) GetNumber (wud->Gadgets[GD_AdvanceTracks]);

	if (patternwud  && patternwud->Win)
		SetGadgetAttrs (patternwud->Gadgets[0], patternwud->Win, NULL,
			PEA_AdvanceCurs,	(PattSwitches.AdvanceTracks << 16) |
								((UWORD)PattSwitches.AdvanceLines),
			TAG_DONE);
}



static void AdvanceLinesClicked (struct WinUserData *wud)
{
	struct WinUserData *patternwud = WDescr[WID_PATTERN].Wud;

	PattSwitches.AdvanceLines = (WORD) GetNumber(wud->Gadgets[GD_AdvanceLines]);

	if (patternwud && patternwud->Win)
		SetGadgetAttrs (patternwud->Gadgets[0], patternwud->Win, NULL,
			PEA_AdvanceCurs,	(PattSwitches.AdvanceTracks << 16) |
								((UWORD)PattSwitches.AdvanceLines),
			TAG_DONE);
}



static void MaxUndoLevelsClicked (struct WinUserData *wud)
{
	struct WinUserData *patternwud = WDescr[WID_PATTERN].Wud;

	PattSwitches.MaxUndoLevels = (WORD) GetNumber (wud->Gadgets[GD_MaxUndoLevels]);

	if (patternwud && patternwud->Win)
		SetGadgetAttrs (patternwud->Gadgets[0], patternwud->Win, NULL,
			PEA_MaxUndoLevels,	PattSwitches.MaxUndoLevels,
			TAG_DONE);
}



static void MaxUndoMemClicked (struct WinUserData *wud)
{
	struct WinUserData *patternwud = WDescr[WID_PATTERN].Wud;

	PattSwitches.MaxUndoMem = (WORD) GetNumber (wud->Gadgets[GD_MaxUndoMem]);

	if (patternwud && patternwud->Win)
		SetGadgetAttrs (patternwud->Gadgets[0], patternwud->Win, NULL,
			PEA_MaxUndoMem,	PattSwitches.MaxUndoMem,
			TAG_DONE);
}



static void VScrollerPlaceClicked (struct WinUserData *wud)
{
	PattSwitches.VScrollerPlace = IntuiMsg.Code;
	ReopenPatternWindow ();
}


static void HScrollerPlaceClicked (struct WinUserData *wud)
{
	PattSwitches.HScrollerPlace ^= SCROLLERPLACE_BOTTOM;
	ReopenPatternWindow ();
}


static void WrapVertClicked (struct WinUserData *wud)
{
	struct WinUserData *patternwud = WDescr[WID_PATTERN].Wud;

	PattSwitches.Flags ^= PEF_VWRAP;

	if (patternwud && patternwud->Win)
		SetGadgetAttrs (patternwud->Gadgets[0], patternwud->Win, NULL,
			PEA_Flags,	PattSwitches.Flags,
			TAG_DONE);
}



static void WrapHorizClicked (struct WinUserData *wud)
{
	struct WinUserData *patternwud = WDescr[WID_PATTERN].Wud;

	PattSwitches.Flags ^= PEF_HWRAP;

	if (patternwud && patternwud->Win)
		SetGadgetAttrs (patternwud->Gadgets[0], patternwud->Win, NULL,
			PEA_Flags,	PattSwitches.Flags,
			TAG_DONE);
}



static void HexLineNumbersClicked (struct WinUserData *wud)
{
	struct WinUserData *patternwud = WDescr[WID_PATTERN].Wud;

	PattSwitches.Flags ^= PEF_HEXMODE;

	if (patternwud && patternwud->Win)
		SetGadgetAttrs (patternwud->Gadgets[0], patternwud->Win, NULL,
			PEA_Flags,	PattSwitches.Flags,
			TAG_DONE);
}



static void BlankZeroClicked (struct WinUserData *wud)
{
	struct WinUserData *patternwud = WDescr[WID_PATTERN].Wud;

	PattSwitches.Flags ^= PEF_BLANKZERO;

	if (patternwud && patternwud->Win)
		SetGadgetAttrs (patternwud->Gadgets[0], patternwud->Win, NULL,
			PEA_Flags,	PattSwitches.Flags,
			TAG_DONE);
}


static void DoRulerClicked (struct WinUserData *wud)
{
	struct WinUserData *patternwud = WDescr[WID_PATTERN].Wud;

	PattSwitches.Flags ^= PEF_DOCURSORRULER;

	if (patternwud && patternwud->Win)
		SetGadgetAttrs (patternwud->Gadgets[0], patternwud->Win, NULL,
			PEA_Flags,	PattSwitches.Flags,
			TAG_DONE);
}



static void DoTinyLinesClicked (struct WinUserData *wud)
{
	struct WinUserData *patternwud = WDescr[WID_PATTERN].Wud;

	PattSwitches.Flags ^= PEF_DOTINYLINES;

	if (patternwud && patternwud->Win)
		SetGadgetAttrs (patternwud->Gadgets[0], patternwud->Win, NULL,
			PEA_Flags,	PattSwitches.Flags,
			TAG_DONE);
}



static void ClipUnitClicked (struct WinUserData *wud)
{
	PattSwitches.ClipboardUnit = (UBYTE) GetNumber (wud->Gadgets[GD_ClipUnit]);
}



static void GetEditorFontClicked (struct WinUserData *wud)
{
	FontRequest (&EditorAttr, FOF_FIXEDWIDTHONLY);
	ReopenPatternWindow ();
	UpdatePattPrefs();
}



static void BGPenClicked (struct WinUserData *wud)
{
	struct WinUserData *patternwud = WDescr[WID_PATTERN].Wud;

	PattSwitches.BGPen = (UWORD) IntuiMsg.Code;

	if (patternwud && patternwud->Win)
		SetGadgetAttrs (patternwud->Gadgets[0], patternwud->Win, NULL,
			PEA_BGPen,	PattSwitches.BGPen,
			TAG_DONE);
}



static void TextPenClicked (struct WinUserData *wud)
{
	ULONG i, j, numcols = 1 << Scr->RastPort.BitMap->Depth;
	struct WinUserData *patternwud = WDescr[WID_PATTERN].Wud;

	PattSwitches.TextPen = (UWORD) IntuiMsg.Code;

	/* Recalculate Lines colors */
	for (i = 0, j = 0; i < numcols; i++)
		if (!(i & PattSwitches.TextPen))
			ColorTable[j++] = i;

	/* Clear remaining colors */
	for (i = j ; i < numcols; i++)
		ColorTable[i] = 0;

	if (PattSwitches.LinesPen & PattSwitches.TextPen)
		PattSwitches.LinesPen = ColorTable[(j > 1) ? 1 : 0];

	if (PattSwitches.TinyLinesPen & PattSwitches.TextPen)
		PattSwitches.TinyLinesPen = ColorTable[(j > 1) ? 1 : 0];

	GT_SetGadgetAttrs (wud->Gadgets[GD_LinesPen], wud->Win, NULL,
		GTPA_Color,			PattSwitches.LinesPen,
		GTPA_ColorTable,	ColorTable,
		GTPA_NumColors,		j,
		TAG_DONE);

	GT_SetGadgetAttrs (wud->Gadgets[GD_TinyLinesPen], wud->Win, NULL,
		GTPA_Color,			PattSwitches.TinyLinesPen,
		GTPA_ColorTable,	ColorTable,
		GTPA_NumColors,		j,
		TAG_DONE);

	if (patternwud && patternwud->Win)
		SetGadgetAttrs (patternwud->Gadgets[0], patternwud->Win, NULL,
			PEA_TextPen,		PattSwitches.TextPen,
			PEA_LinesPen,		PattSwitches.LinesPen,
			PEA_TinyLinesPen,	PattSwitches.TinyLinesPen,
			TAG_DONE);
}



static void LinesPenClicked (struct WinUserData *wud)
{
	struct WinUserData *patternwud = WDescr[WID_PATTERN].Wud;

	PattSwitches.LinesPen = (UWORD) IntuiMsg.Code;

	if (patternwud && patternwud->Win)
		SetGadgetAttrs (patternwud->Gadgets[0], patternwud->Win, NULL,
			PEA_LinesPen,	PattSwitches.LinesPen,
			TAG_DONE);
}



static void TinyLinesPenClicked (struct WinUserData *wud)
{
	struct WinUserData *patternwud = WDescr[WID_PATTERN].Wud;

	PattSwitches.TinyLinesPen = (UWORD) IntuiMsg.Code;

	if (patternwud && patternwud->Win)
		SetGadgetAttrs (patternwud->Gadgets[0], patternwud->Win, NULL,
			PEA_TinyLinesPen,	PattSwitches.TinyLinesPen,
			TAG_DONE);
}



static void PattPrefsOkClicked (struct WinUserData *wud)
{
	MyCloseWindow (wud);
}



static void PattPrefsCancelClicked (struct WinUserData *wud)
{
	MyCloseWindow (wud);
}



static void PattSizeLinesClicked (struct WinUserData *wud)
{
}



static void PattSizeTracksClicked (struct WinUserData *wud)
{
}



static void PattSizeDoubleClicked (struct WinUserData *wud)
{
	struct SongInfo *si;

	if (si = xmLockActiveSong (SM_EXCLUSIVE))
	{
		struct Pattern *patt = si->Patt[si->CurrentPatt];
		struct Pattern *newpatt;
		UWORD i, j;

		if (patt->Lines > MAXPATTLINES/2)
			ShowMessage (MSG_PATT_TOO_LONG);

		if (newpatt = xmAddPattern (si,
			PATTA_Lines,	patt->Lines << 1,
			PATTA_Tracks,	patt->Tracks,
			PATTA_Name,		patt->Name,
			PATTA_Num,		-1,
			TAG_DONE))
		{
			for (i = 0; i < patt->Tracks; i++)
				for (j = 0; j < patt->Lines; j++)
					memcpy (&newpatt->Notes[i][j*2], &patt->Notes[i][j], sizeof (struct Note));

			xmAddPattern (si,
				PATTA_Num,		si->CurrentPatt,
				PATTA_Pattern,	newpatt,
				PATTA_Replace,	TRUE,
				TAG_DONE);

			UpdatePattern();
		}
		else LastErr = ERROR_NO_FREE_STORE;

		ReleaseSemaphore (&si->Lock);
	}
}



static void PattSizeHalveClicked (struct WinUserData *wud)
{
	struct SongInfo *si;

	if (si = xmLockActiveSong (SM_EXCLUSIVE))
	{
		struct Pattern *patt = si->Patt[si->CurrentPatt];
		struct Pattern *newpatt;
		UWORD i, j;


		if (newpatt = xmAddPattern (si,
			PATTA_Lines,	patt->Lines >> 1,
			PATTA_Tracks,	patt->Tracks,
			PATTA_Name,		patt->Name,
			PATTA_Num,		-1,
			TAG_DONE))
		{
			for (i = 0; i < newpatt->Tracks; i++)
				for (j = 0; j < newpatt->Lines; j++)
					memcpy (&newpatt->Notes[i][j], &patt->Notes[i][j*2], sizeof (struct Note));

			xmAddPattern (si,
				PATTA_Num,		si->CurrentPatt,
				PATTA_Pattern,	newpatt,
				PATTA_Replace,	TRUE,
				TAG_DONE);

			UpdatePattern();
		}
		else LastErr = ERROR_NO_FREE_STORE;

		ReleaseSemaphore (&si->Lock);
	}
}



static void PattSizeOkClicked (struct WinUserData *wud)
{
	MyCloseWindow (wud);
}



static void PattSizeCancelClicked (struct WinUserData *wud)
{
	if (OldPatt)
	{
		struct SongInfo *si;

		if (si = xmLockActiveSong (SM_EXCLUSIVE))
		{
			if (OldSong == si)
			{
				/* Restore original pattern */
				CopyPattern (si, OldPatt, OldPattNum);

				/* Free backup copy */
				xmRemPattern (OldSong, -1, (ULONG)OldPatt);
				OldPatt = NULL;
			}
		}

		ReleaseSemaphore (&si->Lock);
	}

	UpdatePattern();

	MyCloseWindow (wud);
}

