*
*	EasyColor
*	by Preben Nielsen
*
*
*  Made with Hisoft Devpac V2.12
*
*  HISTORY
*
*  V1.0   13-Sep-91: First attempt.
*         16-Sep-91: Now it works absolutely perfect in any way.
*  V1.1   28-Sep-91: Changed the way 'Undo' works when editing single colors.

	OPT O+
	OPT O1+		; Tells when a branch could be optimised to short
	OPT i+		; Tells when '#' is probably missing

		incdir		"AsmInc:"
		include		"EasyColor.i"
		include		"P.i"
		include		"intui.i"
		include		"relMacros.i"
		include		"exec/exec_lib.i"
		include		"graphics/graphics_lib.i"
		include		"intuition/intuition_lib.i"
		include		"intuition/intuition.i"

		XDEF		_EasyColor
		XDEF		_EasyColorA

BACKPEN		=0
FRONTPEN	=1
BORDERPEN	=1

DB		EQUR		A5
*»»» A few local variables
 dcDeclare	A5
 dcAPtr		TitlePtr
 dcAPtr		GraphBase
 dcAPtr		IntuiBase
 dcAPtr		DWindow
 dcAPtr		DScreen
 dcAPtr		Vp		; ViewPort
 dcAPtr		Rp		; RastPort
 dcAPtr		Up		; UserPort
 dcLong		Class		; IDCMP->Class
 dcLong		IAddress	; IDCMP->IAddress
 dcWord		Mousex
 dcWord		Mousey
 dcWord		Mode
 dcWord		ColorsPerRow
 dcWord		ColorRows
 dcWord		CBoxW
 dcWord		CBoxH
 dcWord		UndoMode
 dcWord		oRed
 dcWord		oGreen
 dcWord		oBlue
 dcWord		lRed
 dcWord		lGreen
 dcWord		lBlue
 dcWord		Color
 dcWord		oColor
 dcLong		rDiff
 dcLong		gDiff
 dcLong		bDiff
 dcLong		rStart
 dcLong		gStart
 dcLong		bStart
 dcArea		StrBuf,6
 dcArea		RestoreBuf,2*32
 dcArea		UndoBuf,2*32
 dcArea		TempBuf,2*32
 dcArea		RedKnob,ig_SIZEOF
 dcArea		GreenKnob,ig_SIZEOF
 dcArea		BlueKnob,ig_SIZEOF
 dcEnd

*»»» Modes
NOTHING		=0
COPY		=1
EXCHANGE	=2
SPREAD		=3

*»»» Undo-modes
UNDOALL		=0
UNDOORIG	=1
UNDOLAST	=-1

*»»» Gadget refreshing flags
FIX_R_BIT	=0
FIX_G_BIT	=1
FIX_B_BIT	=2
FIXNOTHING	=0
FIX_R_FLAG	=1<<FIX_R_BIT
FIX_G_FLAG	=1<<FIX_G_BIT
FIX_B_FLAG	=1<<FIX_B_BIT

*»»» Call:	EasyColor ( screen, title, x, y);
*»»»		struct Screen *screen;
*»»»		char          *title;
*»»»		Word          x;
*»»»		Word          y;
_EasyColor	Push		D1-D7/A0-A6
		movem.l		4*15+0(SP),A0-A1
		movem.l		4*15+8(SP),D0-D1
		bra.S		ECStart
*»»» Call:	A0    = Screen or NULL
*»»»		A1    = Title string or NULL
*»»»		D0:16 = Left edge of window
*»»»		D1:16 = Top edge of window
*»»» Return:	D0    = CK_OK if the user clicked the 'Ok' gadget
*»»»			CK_CANCEL if the user clicked the 'Cancel' gadget or
*»»»			          the CLOSEWINDOW gadget.
*»»»			CK_ERROR if window couldn't be opened
_EasyColorA	Push		D1-D7/A0-A6
ECStart		dcAlloc					; Allocate memory for variables
		dcReset					; Clear the memory
		move.l		A1,TitlePtr(DB)
		lea		CPNW(PC),A2
		move.l		A1,nw_Title(A2)
		movem.w		D0-D1,nw_LeftEdge(A2)
		move.w		#CUSTOMSCREEN,nw_Type(A2)
		move.l		A0,nw_Screen(A2)
		bne.S		1$
		move.w		#WBENCHSCREEN,nw_Type(A2)
1$		lea		RedGad+gg_GadgetRender(PC),A0
		lea		RedKnob(DB),A1
		move.l		A1,(A0)
		lea		GreenGad+gg_GadgetRender(PC),A0
		lea		GreenKnob(DB),A1
		move.l		A1,(A0)
		lea		BlueGad+gg_GadgetRender(PC),A0
		lea		BlueKnob(DB),A1
		move.l		A1,(A0)
		Prepare		Exec_Call
		lea		GfxName(PC),A1
		CallLib		OldOpenLibrary
		move.l		D0,GraphBase(DB)
		beq		Error
		lea		IntuiName(PC),A1
		CallLib		OldOpenLibrary
		move.l		D0,IntuiBase(DB)
		beq		Error
		Prepare		Intuition_Call
		lea		CPNW(PC),A0
		CallLib		OpenWindow
		move.l		D0,DWindow(DB)
		move.l		D0,A0
		beq		Error
		move.l		wd_RPort(A0),Rp(DB)
		move.l		wd_UserPort(A0),Up(DB)
		move.l		wd_WScreen(A0),A0
		move.l		A0,DScreen(DB)
		lea		sc_ViewPort(A0),A0
		move.l		A0,Vp(DB)

		Prepare		Intuition_Call
		move.l		Rp(DB),A2
		move.l		A2,A0
		lea		PropBorder(PC),A1
		moveq		#PRX,D0
		moveq		#PRY+0*PRS,D1
		CallLib		DrawBorder
		move.l		A2,A0
		lea		PropBorder(PC),A1
		moveq		#PRX,D0
		moveq		#PRY+1*PRS,D1
		CallLib		DrawBorder
		move.l		A2,A0
		lea		PropBorder(PC),A1
		moveq		#PRX,D0
		moveq		#PRY+2*PRS,D1
		CallLib		DrawBorder
		move.l		A2,A0
		lea		CBoxBorder(PC),A1
		moveq		#CBX,D0
		moveq		#CBY,D1
		CallLib		DrawBorder
		move.l		A2,A0
		lea		CSelBorder(PC),A1
		move.w		#CSX,D0
		moveq		#CSY,D1
		CallLib		DrawBorder
		Prepare		Gfx_Call
		lea		TxtAttr(PC),A0
		CallLib		OpenFont		; Open Topaz-80
		move.l		D0,A0
		move.l		A2,A1
		CallLib		SetFont			; Use Topaz-80
*»»» Calculate the number of colorboxes and their sizes
		move.l		DScreen(DB),A0
		moveq		#0,D0
		move.b		sc_BitMap+bm_Depth(A0),D0
		cmp.b		#5,D0
		ble.S		2$
		moveq		#5,D0			; EHB or HAM
		move.w		sc_ViewPort+vp_Modes(A0),D1
		and.w		#V_HAM,D1
		beq.S		2$
		moveq		#4,D0			; HAM !!
2$		moveq		#0,D1
		bset		D0,D1
		divu		#16,D1
		move.w		D1,D0			; Rows
		swap		D1			; Colors per row
		tst.w		D0
		bne.S		3$
		moveq		#1,D0
3$		tst.w		D1
		bne.S		4$
		moveq		#16,D1
4$		move.w		D0,ColorRows(DB)
		move.w		D1,ColorsPerRow(DB)
		move.w		D0,D2
		move.w		D1,D3
		addq.w		#1,D2
		addq.w		#1,D3
		muls		#-CFY,D2
		muls		#-CFX,D3
		add.w		#CBH,D2
		add.w		#CBW,D3
		ext.l		D2
		ext.l		D3
		divu		D0,D2
		divu		D1,D3
		move.w		D2,CBoxH(DB)
		move.w		D3,CBoxW(DB)
*»»» Here we go
		Call		GetRColors
		Call		GetUColors
		Call		AdjustAllProps
		Call		DrawColors
		Call		PrintVal
		moveq		#0,D0
		Call		SetFrame
		Call		RestoreMode
		bra.S		ColorMain

ExitCancel	Call		SetRColors
		moveq		#EC_CANCEL,D7
		bra.S		FreeWindow
ExitOk		moveq		#EC_OK,D7
		bra.S		FreeWindow
Error		moveq		#EC_ERROR,D7
FreeWindow	Prepare		Intuition_Call
		move.l		DWindow(DB),D0
		beq.S		FreeIntui
		move.l		D0,A0
		CallLib		CloseWindow
FreeIntui	Prepare		Exec_Call
		move.l		IntuiBase(DB),D0
		beq.S		FreeGfx
		move.l		D0,A1
		CallLib		CloseLibrary
FreeGfx		move.l		GraphBase(DB),D0
		beq.S		ColorEnd
		move.l		D0,A1
		CallLib		CloseLibrary
ColorEnd	dcFree
		move.l		D7,D0			; Set return-code
		Pop		D1-D7/A0-A6
		rts

ColorMain
EventLoop	move.l		Up(DB),A0
		Prepare		Exec_Call
		CallLib		WaitPort
GetNextMsg	Prepare		Exec_Call
		move.l		Up(DB),A0
		CallLib		GetMsg
		tst.l		D0
		beq.S		EventLoop
		move.l		D0,A1
		move.l		im_Class(A1),Class(DB)
		move.l		im_IAddress(A1),IAddress(DB)
		move.w		im_MouseX(A1),Mousex(DB)
		move.w		im_MouseY(A1),Mousey(DB)
		CallLib		ReplyMsg
		move.l		Class(DB),D0
		cmp.l		#CLOSEWINDOW,D0
		beq		ExitCancel
		cmp.l		#MOUSEMOVE,D0
		bne.S		1$
		Call		DoSlide
		bra.S		GetNextMsg
1$		andi.w		#GADGETDOWN+GADGETUP,D0
		beq.S		GetNextMsg
GJ		move.l		IAddress(DB),A1
		move.w		gg_GadgetID(A1),D0	; GadgetID is offset from GJ
		jsr		GJ(PC,D0.W)
		bra.S		GetNextMsg

*»»» The user clicked on the 'Undo' gadget.
*»»» Lets put back the previous colors.
DoUndo		Call		SetUColors
		bra.S		PutColorsBack
*»»» The user clicked on the 'Reset' gadget.
*»»» Lets put back the original colors.
DoReset		Call		SetRColors
PutColorsBack	Call		AdjustAllProps
		Call		PrintVal
		Call		RestoreMode
		rts

*»»» The user clicked on the 'Copy' gadget.
DoCopy		move.w		#COPY,Mode(DB)
		lea		TxtCopyMode(PC),A1
		Call		SetTitle
		rts

*»»» The user clicked on the 'Exchange' gadget.
DoExchange	move.w		#EXCHANGE,Mode(DB)
		lea		TxtExgMode(PC),A1
		Call		SetTitle
		rts

*»»» The user clicked on the 'Spread' gadget.
DoSpread	move.w		#SPREAD,Mode(DB)
		lea		TxtSpreadMode(PC),A1
		Call		SetTitle
		rts

*»»» The user clicked on one of the color.
*»»» The action taken depends on the currens mode (NOTHING,
*»»» COPY, EXCHANGE or SPREAD.
DoSelect	Prepare		Gfx_Call
		move.l		Rp(DB),A1
		move.w		Mousex(DB),D0
		move.w		Mousey(DB),D1
		sub.w		#CBX,D0
		sub.w		#CBY,D1
		ext.l		D0
		ext.l		D1
		move.l		#CBW,D2
		move.l		#CBH,D3
		divu		ColorsPerRow(DB),D2
		divu		ColorRows(DB),D3
		divu		D2,D0
		divu		D3,D1
		mulu		#16,D1
		add.w		D1,D0
		cmp.w		Color(DB),D0
		beq		6$
		move.w		Color(DB),oColor(DB)
		move.w		D0,Color(DB)
		move.w		oColor(DB),D0
		Call		ClrFrame
		Call		DrawCRect
		Call		GetUColors
		move.w		Mode(DB),D1
		cmp.w		#COPY,D1
		bne.S		1$
*»»» We were in the COPY mode
		move.w		oColor(DB),D0
		Call		GetRGB
		move.w		D2,D3
		move.w		D1,D2
		move.w		D0,D1
		move.w		Color(DB),D0
		Call		SetRGB
		bra		5$
                  
1$		cmp.w		#EXCHANGE,D1
		bne.S		2$
*»»» We were in the EXCHANGE mode
		move.w		oColor(DB),D0
		Call		GetRGB
		move.w		D0,D4
		move.w		D1,D5
		move.w		D2,D6
		move.w		Color(DB),D0
		Call		GetRGB
		move.w		D2,D3
		move.w		D1,D2
		move.w		D0,D1
		move.w		oColor(DB),D0
		Call		SetRGB
		move.w		D4,D1
		move.w		D5,D2
		move.w		D6,D3
		move.w		Color(DB),D0
		Call		SetRGB
		bra		5$

2$              cmp.w		#SPREAD,D1
		bne		5$
*»»» We were in the SPREAD mode
*»»» I do a lot of shifts here because I try not to loose
*»»» precision when doing integer calculations.
		move.w		Color(DB),D6
		move.w		oColor(DB),D7
		cmp.w		D6,D7
		bge.S		3$
		exg		D6,D7
3$		move.w		D6,D0
		Call		GetRGB
		move.w		D0,D3
		move.w		D1,D4
		move.w		D2,D5
		ext.l		D0
		ext.l		D1
		ext.l		D2
		lsl.l		#4,D0
		lsl.l		#4,D1
		lsl.l		#4,D2
		move.l		D0,rStart(DB)
		move.l		D1,gStart(DB)
		move.l		D2,bStart(DB)
		move.w		D7,D0
		Call		GetRGB
		sub.w		D3,D0
		sub.w		D4,D1
		sub.w		D5,D2
		ext.l		D0
		ext.l		D1
		ext.l		D2
		lsl.l		#4,D0
		lsl.l		#4,D1
		lsl.l		#4,D2
		move.w		D7,D5
		sub.w		D6,D5
		divs		D5,D0
		divs		D5,D1
		divs		D5,D2
		ext.l		D0
		ext.l		D1
		ext.l		D2
		move.l		D0,rDiff(DB)
		move.l		D1,gDiff(DB)
		move.l		D2,bDiff(DB)
4$		addq.w		#1,D6
		cmp.w		D6,D7
		ble.S		5$
		move.l		rStart(DB),D1
		move.l		gStart(DB),D2
		move.l		bStart(DB),D3
		add.l		rDiff(DB),D1
		add.l		gDiff(DB),D2
		add.l		bDiff(DB),D3
		move.l		D1,rStart(DB)
		move.l		D2,gStart(DB)
		move.l		D3,bStart(DB)
		addq.l		#8,D1
		addq.l		#8,D2
		addq.l		#8,D3
		lsr.l		#4,D1
		lsr.l		#4,D2
		lsr.l		#4,D3
		move.w		D6,D0
		Call		SetRGB
		bra.S		4$
5$		Call		AdjustAllProps
		Call		PrintVal
		move.w		Color(DB),D0
		Call		SetFrame
6$		move.w		#UNDOALL,UndoMode(DB)
		Call		RestoreMode
		rts

*»»» The user is dragging one of the slider-knobs. We will update
*»»» the colors but NOT try to reposition the knob (yet).
DoSlide		moveq		#FIXNOTHING,D7
		bra.S		ChangeColor
*»»» The user clicked in the 'R' slide gadget. We will now update
*»»» the colors and reposition the knob.
ChangeRed	moveq		#FIX_R_FLAG,D7
		bra.S		ChangeColor
*»»» The user clicked in the 'B' slide gadget. We will now update
*»»» the colors and reposition the knob.
ChangeGreen	moveq		#FIX_G_FLAG,D7
		bra.S		ChangeColor
*»»» The user clicked in the 'B' slide gadget. We will now update
*»»» the colors and reposition the knob.
ChangeBlue	moveq		#FIX_B_FLAG,D7
ChangeColor	tst.w		UndoMode(DB)
		bmi.S		1$			; UNDOLAST ?
		bgt.S		2$			; UNDOORIG ?
		move.w		Color(DB),D0		; UNDOALL !
		Call		GetRGB
		move.w		D0,oRed(DB)
		move.w		D1,oGreen(DB)
		move.w		D2,oBlue(DB)
1$		move.w		#UNDOORIG,UndoMode(DB)	; UNDOALL or UNDOLAST !
2$		move.w		RedInfo+pi_HorizPot(PC),D1
		move.w		GreenInfo+pi_HorizPot(PC),D2
		move.w		BlueInfo+pi_HorizPot(PC),D3
		moveq		#12,D0
		lsr.w		D0,D1
		lsr.w		D0,D2
		lsr.w		D0,D3
		move.w		Color(DB),D0
		Call		SetRGB
		Call		PrintVal
		Call		RestoreMode
		move.w		D7,D0
		beq.S		3$
		Call		AdjustProps
3$		rts

*»»» Terminate the COPY, EXCHANGE or SPREAD mode
RestoreMode	tst.w		Mode(DB)
		beq.S		1$
		Push		A0
		move.w		#NOTHING,Mode(DB)
		move.l		TitlePtr(DB),A1
		Call		SetTitle
		Pop		A0
1$		rts

*»»» Grab a temporary copy of the colormap
GetTColors	Push		D0-D1/A0-A1/A6
		lea		TempBuf(DB),A1
		bra.S		GetColors
*»»» Fill the undo-buffer
GetUColors	Push		D0-D1/A0-A1/A6
		lea		UndoBuf(DB),A1
		bra.S		GetColors
*»»» Fill the restore-buffer
GetRColors	Push		D0-D1/A0-A1/A6
		lea		RestoreBuf(DB),A1
GetColors	move.l		Vp(DB),A0
		move.l		vp_ColorMap(A0),A0
		move.l		cm_ColorTable(A0),A0
		moveq		#31,D0
1$		move.w		(A0)+,(A1)+
		dbf		D0,1$
		Pop		D0-D1/A0-A1/A6
		rts

*»»» Put the undo colors back on display
SetUColors	Push		D0-D3/A0-A1/A6
		lea		UndoBuf(DB),A1
		move.w		UndoMode(DB),D0
		beq.S		SetColors
		cmp.w		#UNDOORIG,D0
		beq.S		PutBackOrig
PutBackLast	move.w		Color(DB),D0
		move.w		lRed(DB),D1
		move.w		lGreen(DB),D2
		move.w		lBlue(DB),D3
		Call		SetRGB
		move.w		#UNDOORIG,UndoMode(DB)
		bra.S		ColorsInPlace
PutBackOrig	move.w		Color(DB),D0	
		Call		GetRGB
		move.w		D0,lRed(DB)
		move.w		D1,lGreen(DB)
		move.w		D2,lBlue(DB)
		move.w		Color(DB),D0
		move.w		oRed(DB),D1
		move.w		oGreen(DB),D2
		move.w		oBlue(DB),D3
		Call		SetRGB
		move.w		#UNDOLAST,UndoMode(DB)
		bra.S		ColorsInPlace
*»»» Put the restore colors back on display
SetRColors	Push		D0-D3/A0-A1/A6
		lea		RestoreBuf(DB),A1
		move.w		#UNDOALL,UndoMode(DB)
SetColors	Call		GetTColors
		move.l		Vp(DB),A0
		Prepare		Gfx_Call
		moveq		#32,D0
		CallLib		LoadRGB4
		lea		TempBuf(DB),A0
		lea		UndoBuf(DB),A1
		moveq		#31,D0
1$		move.w		(A0)+,(A1)+
		dbf		D0,1$
ColorsInPlace	Pop		D0-D3/A0-A1/A6
		rts

*»»» Print the RGB color values
PrintVal	Push		D0-D2/A0-A1/A6
		move.w		Color(DB),D0
		Call		GetRGB
		lea		StrBuf(DB),A0
		Call		MakeTwoDigits		
		move.l		D1,D0
		Call		MakeTwoDigits		
		move.l		D2,D0
		Call		MakeTwoDigits		
		lea		StrBuf(DB),A0
		move.w		#PRX+PRW+8,D0
		moveq		#PRY+0*PRS+7,D1
		moveq		#2,D2
		Call		Txt
		lea		StrBuf+2(DB),A0
		move.w		#PRX+PRW+8,D0
		moveq		#PRY+1*PRS+7,D1
		moveq		#2,D2
		Call		Txt
		lea		StrBuf+4(DB),A0
		move.w		#PRX+PRW+8,D0
		moveq		#PRY+2*PRS+7,D1
		moveq		#2,D2
		Call		Txt
1$		Pop		D0-D2/A0-A1/A6
		rts

*»»» Call:	A0 = where to put string
*»»»		D0 = number
*»»» Convert number in D0 into two-digit decimal string
MakeTwoDigits	divu		#10,D0
		add.b		#'0',D0
		move.b		D0,(A0)+
		swap		D0
		add.b		#'0',D0
		move.b		D0,(A0)+
		rts

*»»» Call:	D0:16 = x
*»»»		D1:16 = y
*»»»		D2:16 = count
*»»»		A0    = String
Txt		move.l		A0,-(SP)
		Prepare		Gfx_Call
		move.l		Rp(DB),A1
		CallLib		Move
		move.l		(SP)+,A0
		move.l		D2,D0
		move.l		Rp(DB),A1
		CallLib		Text
		rts

*»»» Call:	D0 = color no.
*»»» Return:	D0 = red
*»»»		D1 = green
*»»»		D2 = blue
*»»» Get a RGB value from the screens colormap
GetRGB		Push		A0-A1/A6
		move.l		Vp(DB),A0
		move.l		vp_ColorMap(A0),A0
		Prepare		Gfx_Call
		CallLib		GetRGB4
		move.l		D0,D1
		move.l		D0,D2
		andi.l		#$0F00,D0
		andi.l		#$00F0,D1
		andi.l		#$000F,D2
		lsr.l		#8,D0
		lsr.l		#4,D1
		Pop		A0-A1/A6
		rts

*»»» Call:	D0 = color no.
*»»»		D1 = red
*»»»		D2 = green
*»»»		D3 = blue
*»»» Put a RGB value into the screens colormap
SetRGB		Push		D0-D1/A0-A1/A6
		move.l		Vp(DB),A0
		Prepare		Gfx_Call
		CallLib		SetRGB4
		Pop		D0-D1/A0-A1/A6
		rts

*»»» Adjust all three proportional gadgets.
AdjustAllProps	Push		D0-D4/A0
		moveq		#FIX_R_FLAG|FIX_G_FLAG|FIX_B_FLAG,D0
		bra.S		FixProps
*»»» Call:	D0 = mask telling which gadgets to modify.
*»»» Adjust some proportional gadgets.
AdjustProps	Push		D0-D4/A0
FixProps	move.w		D0,D4
		move.w		Color(DB),D0
		Call		GetRGB
		move.w		#MAXPOT/15,D3
		mulu		D3,D0
		mulu		D3,D1
		mulu		D3,D2
		btst		#FIX_R_BIT,D4
		beq.S		1$
		lea		RedGad(PC),A0
		Call		AdjustProp
1$		btst		#FIX_G_BIT,D4
		beq.S		2$
		lea		GreenGad(PC),A0
		move.l		D1,D0
		Call		AdjustProp
2$		btst		#FIX_B_BIT,D4
		beq.S		3$
		lea		BlueGad(PC),A0
		move.l		D2,D0
		Call		AdjustProp
3$		Pop		D0-D4/A0
		rts

*»»» Call:	A0 = Gadget
*»»»		D0 = HorizPot
*»»» Adjust a proportional gadget.
AdjustProp	Push		D0-D5/A0-A2/A6
		Prepare		Intuition_Call
		move.l		DWindow(DB),A1
		suba.l		A2,A2
		move.l		D0,D1
		moveq		#PropFlags,D0
		moveq		#0,D2
		move.w		#KnobW,D3
		moveq		#0,D4
		moveq		#1,D5
		CallLib		NewModifyProp
		Pop		D0-D5/A0-A2/A6
		rts

*»»» Draw the colorboxes
DrawColors	Push		D0-D3/D5-D7/A0-A2/A6
		Prepare		Gfx_Call
		move.l		Rp(DB),A2
		moveq		#0,D5
		moveq		#0,D7
1$		cmp.w		ColorRows(DB),D7
		bge.S		6$
		moveq		#0,D6
2$		cmp.w		ColorsPerRow(DB),D6
		bge.S		5$
		move.w		D5,D0
		move.l		A2,A1
		CallLib		SetAPen
		move.w		D6,D0
		move.w		D6,D2
		move.w		D7,D1
		move.w		D7,D3
		addq.w		#1,D2
		addq.w		#1,D3
		mulu		#CFX,D2
		mulu		#CFY,D3
		mulu		CBoxW(DB),D0
		mulu		CBoxH(DB),D1
		add.w		D2,D0
		add.w		D3,D1
		add.w		#CBX,D0
		add.w		#CBY,D1
		move.w		D0,D2
		move.w		D1,D3
		add.w		CBoxW(DB),D2
		add.w		CBoxH(DB),D3
		subq.w		#1,D2
		subq.w		#1,D3
		move.l		A2,A1
		CallLib		RectFill
		addq.w		#1,D5
		addq.w		#1,D6
		bra.S		2$
5$		addq.w		#1,D7
		bra.S		1$
6$		Prepare		Gfx_Call
		moveq		#FRONTPEN,D0
		move.l		A2,A1
		CallLib		SetAPen
		moveq		#BACKPEN,D0
		move.l		A2,A1
		CallLib		SetBPen
		moveq		#1,D0
		move.l		A2,A1
		CallLib		SetDrMd
		Pop		D0-D3/D5-D7/A0-A2/A6
		rts

*»»» Draw the Color rectangle
DrawCRect	Push		D0-D3/A0-A2/A6
		Prepare		Gfx_Call
		move.l		Rp(DB),A2
		move.w		Color(DB),D0
		move.l		A2,A1
		CallLib		SetAPen
		move.w		#CSX,D0
		moveq		#CSY+1,D1
		move.w		#CSX+CSW-1,D2
		moveq		#CSY+CSH-2,D3
		move.l		Rp(DB),A2
		CallLib		RectFill
		moveq		#FRONTPEN,D0
		move.l		A2,A1
		CallLib		SetAPen
		Pop		D0-D3/A0-A2/A6
		rts

*»»» Call:	D0 = Color to set frame around
SetFrame	Push		D0-D7/A0-A2/A6
		moveq		#FRONTPEN,D1
		bra.S		FColor
*»»» Call:	D0 = Color to clear frame around
ClrFrame	Push		D0-D7/A0-A2/A6
		moveq		#BACKPEN,D1
FColor		ext.l		D0
		move.l		D0,D4
		Prepare		Gfx_Call
		move.l		Rp(DB),A2
		move.w		D1,D0
		move.l		A2,A1
		CallLib		SetAPen
		move.l		D4,D6
		divu		#16,D6
		move.w		D6,D7			; Row
		swap		D6			; Col
		move.w		D6,D0
		move.w		D7,D1
		addq.w		#1,D0
		addq.w		#1,D1
		mulu		#CFX,D0
		mulu		#CFY,D1
		mulu		CBoxW(DB),D6
		mulu		CBoxH(DB),D7
		add.w		D0,D6
		add.w		D1,D7
		add.w		#CBX,D6
		add.w		#CBY,D7
		move.w		D6,D0
		move.w		D7,D1
		move.w		D6,D2
		move.w		D7,D3
		subq.w		#CFX,D0
		subq.w		#CFY,D1
		add.w		CBoxW(DB),D2
		add.w		CBoxH(DB),D3
		addq.w		#CFX-1,D2
		addq.w		#CFY-1,D3
		move.l		Rp(DB),A2
		CallLib		RectFill
		move.w		D4,D0
		move.l		A2,A1
		CallLib		SetAPen
		move.w		D6,D0
		move.w		D7,D1
		move.w		D6,D2
		move.w		D7,D3
		add.w		CBoxW(DB),D2
		add.w		CBoxH(DB),D3
		subq.w		#1,D2
		subq.w		#1,D3
		move.l		Rp(DB),A2
		CallLib		RectFill
		move.w		#FRONTPEN,D0
		move.l		A2,A1
		CallLib		SetAPen
		Pop		D0-D7/A0-A2/A6
		rts

*»»» Call:	A1 = Title string
SetTitle	Push		D0-D1/A0-A2/A6
		move.l		DWindow(DB),A0
		suba.l		A2,A2
		Prepare		Intuition_Call
		CallLib		SetWindowTitles
		Pop		D0-D1/A0-A2/A6
		rts

*»»» Data »»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
GfxName		dc.b		'graphics.library',0
IntuiName	dc.b		'intuition.library',0
		EVEN

WW		=254		; Window width
WH		=119		; Window height

IDCMPFlags	=GADGETUP|GADGETDOWN|CLOSEWINDOW|MOUSEMOVE
OtherFlags	=WINDOWDRAG|WINDOWDEPTH|WINDOWCLOSE|NOCAREREFRESH|ACTIVATE
CPNW		dc.w		0,0,WW,WH
		dc.b		0,1
		dc.l		IDCMPFlags,OtherFlags
		dc.l		GadgetList,0,0,0,0
		dc.w		0,0,0,0,WBENCHSCREEN

*»»» Frame thickness
CFX		=2		; Frame thickness in x-pixels
CFY		=2		; Frame thickness in y-pixels

*»»» Boolean text gadgets
GLX		=14		; Gadget x-pos
GLY		=85		; Gadget y-pos
GLSX		=57		; Gadget x-spacing
GLSY		=16		; Gadget y-spacing
GLW		=55		; Gadget width
GLH		=11		; Gadget height

*»»» Proportional gadgets
PRX		=26		; Gadget x-pos
PRY		=17		; Gadget y-pos
PRS		=11		; Gadget y-spacing
PRW		=130		; Gadget width
PRH		=10		; Gadget height7

*»»» Boolean colorbox gadget
CBX		=14
CBY		=56
CBW		=226		; (CBX-(ColorsPerRow+1)*CFX) MOD ColorsPerRow should be 0
CBH		=22		; (CBY-(ColorRows+1)*CFY) MOD ColorRows should be 0

*»»» Current colors box
CSX		=PRX+PRW+34
CSY		=17
CSW		=50
CSH		=32

GadgetList
CopyGad		Gadget		ExchangeGad,GLX+0*GLSX,GLY+0*GLSY,GLW,GLH,GADGHCOMP,RELVERIFY,BOOLGADGET
		Gadget2		ButBorder,0,ITxtCopy,0,0,DoCopy-GJ,0
ExchangeGad	Gadget		UndoGad,GLX+1*GLSX,GLY+0*GLSY,GLW,GLH,GADGHCOMP,RELVERIFY,BOOLGADGET
		Gadget2		ButBorder,0,ITxtExchange,0,0,DoExchange-GJ,0
UndoGad		Gadget		ResetGad,GLX+2*GLSX,GLY+0*GLSY,GLW,GLH,GADGHCOMP,RELVERIFY,BOOLGADGET
		Gadget2		ButBorder,0,ITxtUndo,0,0,DoUndo-GJ,0
ResetGad	Gadget		OkGad,GLX+3*GLSX,GLY+0*GLSY,GLW,GLH,GADGHCOMP,RELVERIFY,BOOLGADGET
		Gadget2		ButBorder,0,ITxtReset,0,0,DoReset-GJ,0
OkGad		Gadget		SpreadGad,GLX+0*GLSX,GLY+1*GLSY,GLW,GLH,GADGHCOMP,RELVERIFY,BOOLGADGET
		Gadget2		ButBorder,0,ITxtOk,0,0,ExitOk-GJ,0
SpreadGad	Gadget		CancelGad,GLX+1*GLSX+GLSX/2,GLY+1*GLSY,GLW,GLH,GADGHCOMP,RELVERIFY,BOOLGADGET
		Gadget2		ButBorder,0,ITxtSpread,0,0,DoSpread-GJ,0
CancelGad	Gadget		RedGad,GLX+3*GLSX,GLY+1*GLSY,GLW,GLH,GADGHCOMP,RELVERIFY,BOOLGADGET
		Gadget2		ButBorder,0,ITxtCancel,0,0,ExitCancel-GJ,0
RedGad		Gadget		GreenGad,PRX,PRY+0*PRS,PRW,PRH,GADGHCOMP,RELVERIFY|FOLLOWMOUSE,PROPGADGET
		Gadget2		0,0,ITxtRed,0,RedInfo,ChangeRed-GJ,0
GreenGad	Gadget		BlueGad,PRX,PRY+1*PRS,PRW,PRH,GADGHCOMP,RELVERIFY|FOLLOWMOUSE,PROPGADGET
		Gadget2		0,0,ITxtGreen,0,GreenInfo,ChangeGreen-GJ,0
BlueGad		Gadget		ColorGad,PRX,PRY+2*PRS,PRW,PRH,GADGHCOMP,RELVERIFY|FOLLOWMOUSE,PROPGADGET
		Gadget2		0,0,ITxtBlue,0,BlueInfo,ChangeBlue-GJ,0
ColorGad	Gadget		0,CBX,CBY,CBW,CBH,GADGHNONE,GADGIMMEDIATE,BOOLGADGET
		Gadget2		0,0,0,0,0,DoSelect-GJ,0

PropFlags	=AUTOKNOB|FREEHORIZ|PROPBORDERLESS
KnobW		=MAXBODY/16
RedInfo		dc.w		PropFlags,0,0,KnobW,0
		dc.w		0,0,0,0,0,0
GreenInfo	dc.w		PropFlags,0,0,KnobW,0
		dc.w		0,0,0,0,0,0
BlueInfo	dc.w		PropFlags,0,0,KnobW,0
		dc.w		0,0,0,0,0,0

ButBorder	Border		-2,-1,BORDERPEN,0,1,9,ButVectors,0
ButVectors	dc.w		2,0,GLW+1,0,GLW+3,2,GLW+3,GLH-1,GLW+1,GLH+1,2,GLH+1,0,GLH-1,0,2,2,0

PropBorder	Border		-2,-1,BORDERPEN,0,1,9,PropVectors,0
PropVectors	dc.w		2,0,PRW+1,0,PRW+3,2,PRW+3,PRH-1,PRW+1,PRH+1,2,PRH+1,0,PRH-1,0,2,2,0

CBoxBorder	Border		-2,-1,BORDERPEN,0,1,9,CBoxVectors,0
CBoxVectors	dc.w		2,0,CBW+1,0,CBW+3,2,CBW+3,CBH-1,CBW+1,CBH+1,2,CBH+1,0,CBH-1,0,2,2,0

CSelBorder	Border		-2,-1,BORDERPEN,0,1,9,CSelVectors,0
CSelVectors	dc.w		2,0,CSW+1,0,CSW+3,2,CSW+3,CSH-1,CSW+1,CSH+1,2,CSH+1,0,CSH-1,0,2,2,0

ITxtCopy	IntuiText	FRONTPEN,BACKPEN,1,11,2,TxtCopy,0
ITxtExchange	IntuiText	FRONTPEN,BACKPEN,1,15,2,TxtExchange,0
ITxtSpread	IntuiText	FRONTPEN,BACKPEN,1,3,2,TxtSpread,0
ITxtUndo	IntuiText	FRONTPEN,BACKPEN,1,11,2,TxtUndo,0
ITxtReset	IntuiText	FRONTPEN,BACKPEN,1,9,2,TxtReset,0
ITxtOk		IntuiText	FRONTPEN,BACKPEN,1,19,2,TxtOk,0
ITxtCancel	IntuiText	FRONTPEN,BACKPEN,1,3,2,TxtCancel,0
ITxtRed		IntuiText	FRONTPEN,BACKPEN,1,-14,2,TxtRed,0
ITxtGreen	IntuiText	FRONTPEN,BACKPEN,1,-14,2,TxtGreen,0
ITxtBlue	IntuiText	FRONTPEN,BACKPEN,1,-14,2,TxtBlue,0

TxtCopy		dc.b		'Copy',0
TxtExchange	dc.b		'Exg',0
TxtSpread	dc.b		'Spread',0
TxtUndo		dc.b		'Undo',0
TxtReset	dc.b		'Reset',0
TxtOk		dc.b		'Ok',0
TxtCancel	dc.b		'Cancel',0
TxtRed		dc.b		'R',0
TxtGreen	dc.b		'G',0
TxtBlue		dc.b		'B',0
TxtCopyMode	dc.b		'Copy: Select color',0
TxtExgMode	dc.b		'Exchange: Select color',0
TxtSpreadMode	dc.b		'Spread: Select color',0
		EVEN

TxtAttr		dc.l		FontName
		dc.w		TOPAZ_EIGHTY
		dc.b		FS_NORMAL,FPB_ROMFONT
FontName	dc.b		'topaz.font',0
		END

