*	SetPWKeys V1.0
*	By Preben Nielsen
*
*
*	  SetPWKeys is a program that lets you define key-function
*	bindings for use with the PWKeys program. So if you don't use
*	PWKeys then you won't have any use for SetPWKeys.
*
*	NOTE:	There's no need to 'RUN' or 'RUNBACK' this program from the
*		CLI. It is auto-detaching.
*
*HISTORY
*          Made with Hisoft V2.12
*
*  V1.0   20-Apr-91: The program has now existed for a long time, but I
*                    don't remember exactly when I started on it.

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

		include		"PWKeys.i"
		incdir		"AsmInc:"
		include		"exec/exec_lib.i"
		include		"exec/memory.i"
		include		"exec/interrupts.i"
		include		"libraries/dos_lib.i"
		include		"libraries/dosextens.i"
		include		"graphics/graphics_lib.i"
		include		"graphics/gfxbase.i"
		include		"intuition/intuition.i"
		include		"intuition/intuition_lib.i"

POPSCREEN			; If this is defined then the screen will
				; pop up from below
;CUSTOMCOLORS			; If you remove this then it uses WB-colors

PLANES			=1	; Bitplanes on screen
SWDIFF			=10	; Difference between screen and window y-coords

FUNCTEXTS		=17
GADTEXTS		=7
MSGTEXTS		=7

TITLE			=0
NOFILE			=-1
WRONGFILE		=-2
WRITEERR		=-3
NOHANDLER		=-4
DUPLICATES		=-5
ALLISOK			=-6

KEYMASK			=$FF

SELECTEDBOX		=0
GHOSTEDBOX		=1

Prepare		MACRO
		IFC		'\1','Exec_Call'
		movea.l		4.W,A6
		ENDC
		IFC		'\1','Intuition_Call'
		movea.l		IntBase(DB),A6
		ENDC
		IFC		'\1','Gfx_Call'
		movea.l		GraphBase(DB),A6
		ENDC
		IFC		'\1','Dos_Call'
		movea.l		DosBase(DB),A6
		ENDC
		ENDM
CallLib		MACRO
		jsr		_LVO\1(A6)
		ENDM
Call		MACRO
		bsr		\1
		ENDM
Push		MACRO		Push <reg list | all>
		IFC		'\1','all'
		movem.l		D0-D7/A0-A6,-(SP)
		ENDC
		IFNC		'\1','all'
		movem.l		\1,-(SP)
		ENDC
		ENDM
Pop		MACRO		Pop <reg list | all>
		IFC		'\1','all'
		movem.l		(SP)+,D0-D7/A0-A6
		ENDC
		IFNC		'\1','all'
		movem.l		(SP)+,\1
		ENDC
		ENDM
rAPtr		MACRO		Name
DefSiz		set		DefSiz+4
DefPtr		set		DefPtr-4
\1		=		DefPtr
		ENDM
rLong		MACRO		Name
DefSiz		set		DefSiz+4
DefPtr		set		DefPtr-4
\1		=		DefPtr
		ENDM
rWord		MACRO		Name
DefSiz		set		DefSiz+2
DefPtr		set		DefPtr-2
\1		=		DefPtr
		ENDM
rByte		MACRO		Name
DefSiz		set		DefSiz+1
DefPtr		set		DefPtr-1
\1		=		DefPtr
		ENDM
rStorage	MACRO		Name,Size	;def storage
DefSiz		set		DefSiz+\2
DefPtr		set		DefPtr-\2
\1		=		DefPtr
		ENDM
rEVEN		MACRO				;word boundary
		IFNE		DefPtr&1
DefPtr		set		DefPtr-1
DefSiz		set		DefSiz+1
		ENDC
		ENDM
rStart		MACRO				;def var section
DefPtr		set		0
DefSiz		set		0
		ENDM
rEnd		MACRO				;def var section
RelSize		=		DefSiz
		ENDM
rAlloc		MACRO
		link		DB,#-RelSize
		ENDM
rFree		MACRO				;De-allocate storage
		unlk		DB
		ENDM
rClear		MACRO				;reset all variables
		movem.l		D0/A0,-(SP)
		move.w		#RelSize-1,D0
		move.l		DB,A0
rClr.\@		clr.b		-(A0)
		dbf		D0,rClr.\@
		movem.l		(SP)+,D0/A0
		ENDM
Gadget		MACRO
		dc.l		\1
		dc.w		\2,\3,\4,\5,\6,\7,\8
		ENDM
Gadget2		MACRO
		dc.l		\1,\2,\3,\4,\5
		dc.w		\6
		dc.l		\7
		ENDM
Border		MACRO
		dc.w		\1,\2
		dc.b		\3,\4,\5,\6
		dc.l		\7,\8
		ENDM
Image		MACRO
		dc.w		\1,\2,\3,\4,\5
		dc.l		\6
		dc.b		\7,\8
		dc.l		\9
		ENDM
IntuiText	MACRO
		dc.b		\1,\2,\3,0
		dc.w		\4,\5
		dc.l		TxtAttr,\6,\7
		ENDM
Detach		MACRO		; Detach <'process name'>,stacksize,processpri
		SECTION		MultiSplit,CODE
Start		Prepare		Exec_Call
		suba.l		A1,A1
		CallLib		FindTask		; Find us
		move.l		D0,A0
		tst.l		pr_CLI(A0)
		bne.S		SegSplit
		jmp		ProcessStart		; from WorkBench
SegSplit	link		A4,#-100
		CallLib		Forbid			; From Dos
		lea		DName(PC),A1
		CallLib		OldOpenLibrary
		move.l		D0,D5
		beq		6$
		move.l		Start-4(PC),A1
		move.l		A1,D3
		moveq		#0,D6			; Number of segments
		moveq		#ML_SIZE,D7		; Size of memory to allocate
		move.l		SP,A0
1$		move.l		A1,D0			; Count segments and make MemEntries on the stack
		beq.S		2$
		adda.l		A1,A1
		adda.l		A1,A1
		subq.l		#4,A1
		move.l		A1,(A0)+		; MemList -> ml_me[0].me_Addr	= Segment
		move.l		(A1),(A0)+		; MemList -> ml_me[0].me_Length	= Length
		move.l		4(A1),A1
		addq.w		#1,D6
		addq.w		#ME_SIZE,D7
		bra.S		1$
2$		move.l		D7,D0
		move.l		#MEMF_PUBLIC|MEMF_CLEAR,D1
		CallLib		AllocMem		; Allocate Memlist
		move.l		D0,A2
		tst.l		D0
		beq.S		5$
		move.w		D6,ML_NUMENTRIES(A2)	; MemList -> ml_NumEntries = number of segments
		move.l		SP,A0
		lea		ML_ME(A2),A1
		move.l		D7,D0
		sub.w		#ML_SIZE+1,D0
3$		move.b		(A0)+,(A1)+
		dbf		D0,3$
		move.l		#ProcessName,D1
		moveq		#\3,D2			; Priority
		move.l		#\2,D4			; Stacksize
		move.l		D5,A6
		CallLib		CreateProc
		Prepare		Exec_Call
		move.l		D0,A0
		tst.l		D0
		beq.S		4$
		lea		-pr_MsgPort(A0),A0	; Now we have process
		not.l		pr_CLI(A0)		; All MY programs will now think they were started from the CLI
		lea		TC_MEMENTRY(A0),A0
		move.l		A2,A1
		CallLib		AddTail			; AddTail(&Process->pr_Task.tc_MemEntry,&MemList->ml_Node);
		lea		Start-4(PC),A1
		clr.l		(A1)			; Split the segments
		bra.S		5$
4$		move.l		A2,A1			; CreateProc failed. Can't do anything then
		move.l		D7,D0
		CallLib		FreeMem
5$		move.l		D5,A1
		CallLib		CloseLibrary
6$		CallLib		Permit
		unlk		A4
		moveq		#0,D0
		rts
DName		dc.b		'dos.library',0
ProcessName	dc.b		\1,0			; CreateProc makes a copy of this name
		SECTION		ProcessCode,CODE
ProcessStart
		ENDM

DB		EQUR		A4

InitProcess	Detach		<'SetPWKeys Process'>,4000,0
		rAlloc					; Allocate memory for variables
		rClear					; Clear the memory
		Prepare		Exec_Call
		suba.l		A1,A1
		CallLib		FindTask		; Find us
		move.l		D0,PProcess(DB)
		movea.l		D0,A2
		tst.l		pr_CLI(A2)
		bne.S		GetLibs
WBenchStartup	lea		pr_MsgPort(A2),A0
		CallLib		WaitPort		; wait for a message
		lea		pr_MsgPort(A2),A0
		CallLib		GetMsg			; then get it
		move.l		D0,WBenchMsg(DB)	; save it for later reply
GetLibs		lea		DosName(PC),A1
		CallLib		OldOpenLibrary
		move.l		D0,DosBase(DB)
		beq.S		Error
		lea		GfxName(PC),A1
		CallLib		OldOpenLibrary
		move.l		D0,GraphBase(DB)
		beq.S		Error
		lea		IntName(PC),A1
		CallLib		OldOpenLibrary
		move.l		D0,IntBase(DB)
		beq.S		Error
		Prepare		Intuition_Call
		lea		NewS(PC),A0
	IFD POPSCREEN
		move.l		GraphBase(DB),A1
		move.w		gb_NormalDisplayRows(A1),ns_TopEdge(A0)
		ori.w		#SCREENBEHIND,ns_Type(A0)
	ENDC
		CallLib		OpenScreen
		move.l		D0,DScreen(DB)
		beq.S		Error
		moveq		#sc_ViewPort,D1
		add.l		D0,D1
		move.l		D1,ScrVp(DB)
		moveq		#sc_RastPort,D1
		add.l		D0,D1
		move.l		D1,Rp(DB)

	IFD CUSTOMCOLORS
		Prepare		Gfx_Call
		move.l		ScrVp(DB),A0
		lea		ColorTable(PC),A1
		moveq		#2,D0
		CallLib		LoadRGB4
	ENDC
		Prepare		Intuition_Call
		lea		NewW(PC),A0
		move.l		DScreen(DB),nw_Screen(A0)
		CallLib		OpenWindow
		move.l		D0,DWindow(DB)
		movea.l		D0,A0
		beq.S		Error
		move.l		wd_UserPort(A0),Up(DB)
		Call		SetAPen1
		bra.S		Main

Exit
Error
FreeWindow	Prepare		Intuition_Call
		move.l		DWindow(DB),D0
		beq.S		FreeScreen
	IFD POPSCREEN
		Call		PushScreen
	ENDC
		move.l		DWindow(DB),A0
		CallLib		CloseWindow
FreeScreen	move.l		DScreen(DB),D0
		beq.S		FreeIntuition
		movea.l		D0,A0
		CallLib		CloseScreen
FreeIntuition	Prepare		Exec_Call
		move.l		IntBase(DB),D0
		beq.S		FreeGraphics
		movea.l		D0,A1
		CallLib		CloseLibrary
FreeGraphics	move.l		GraphBase(DB),D0
		beq.S		FreeDos
		movea.l		D0,A1
		CallLib		CloseLibrary
FreeDos		move.l		DosBase(DB),D0
		beq.S		ReplyWB
		movea.l		D0,A1
		CallLib		CloseLibrary
ReplyWB		move.l		WBenchMsg(DB),D2
		beq.S		AllDone
		CallLib		Forbid
		movea.l		D2,A1
		CallLib		ReplyMsg		; Reply WBenchMessage if we are started from WB
AllDone		rFree
		moveq		#0,D0
		rts

Main		Prepare		Intuition_Call
		move.w		#590,D0
		moveq		#0,D1
		move.l		Rp(DB),A0
		lea		ArrowImages(PC),A1
		CallLib		DrawImage
		moveq		#0,D0
		moveq		#0,D1
		move.l		Rp(DB),A0
		lea		TitleBorder(PC),A1
		CallLib		DrawBorder
		moveq		#0,D0
		moveq		#18,D1
		move.l		Rp(DB),A0
		lea		FuncBorder(PC),A1
		CallLib		DrawBorder
		moveq		#0,D0
		moveq		#KY-6,D1
		move.l		Rp(DB),A0
		lea		KeybBorder(PC),A1
		CallLib		DrawBorder
		moveq		#TITLE,D0
		Call		WriteMsg
		Call		WriteFuncs
		Call		DrawKeys
		Call		SetAPen0
		lea		ReturnKey2(PC),A2
		move.w		Box_x(A2),D2
		add.w		Box_Width(A2),D2
		move.w		Box_y(A2),D3
		move.w		D2,D0
		move.w		D3,D1
		move.l		Rp(DB),A1
		CallLib		Move
		move.w		D2,D0
		move.w		D3,D1
		subq.w		#1,D1
		add.w		Box_Height(A2),D1
		move.l		Rp(DB),A1
		CallLib		Draw
		subq.w		#1,D2
		move.w		D2,D0
		move.w		D3,D1
		addq.w		#1,D1
		move.l		Rp(DB),A1
		CallLib		Move
		move.w		D2,D0
		move.w		D3,D1
		add.w		Box_Height(A2),D1
		subq.w		#1,D1
		move.l		Rp(DB),A1
		CallLib		Draw
		Call		SetAPen1
		Prepare		Exec_Call
		CallLib		Forbid
		lea		PWKeysPortName(PC),A1
		CallLib		FindPort
		tst.l		D0
		beq.S		1$
		move.l		D0,A0			; Handler was installed
		move.l		ihs_Interrupt+IS_DATA(A0),A0
		lea		TempFile(PC),A1
		move.w		#FilePart,D0		; Copy keydefinition from the
		Call		MemCopy			; handlers memory
		Call		UnSortKeys
		Call		InitFuncs
1$		CallLib		Permit
		lea		Funcs(PC),A0
		bset		#SELECTEDBOX,Box_Flags(A0)
		move.l		A0,CurFunc(DB)
		Call		FillKeyboard
		Call		FillFunctions
	IFD POPSCREEN
		Call		PopScreen		; Bring screen up
	ENDC
EventLoop	tst.w		Quit(DB)
		bne		Exit
		movea.l		Up(DB),A0
		Prepare		Exec_Call
		CallLib		WaitPort
GetNextMsg	Call		GetAMessage
		beq.S		EventLoop
		move.l		Class(DB),D0
		cmpi.w		#GADGETUP,D0
		beq.S		DoGadget
		cmpi.w		#GADGETDOWN,D0
		beq.S		DoGadget
		cmpi.w		#MOUSEBUTTONS,D0
		beq		DoMouse
		bra.S		GetNextMsg

	IFD POPSCREEN
MOVESTEP	=10
PopScreen	Call		DoFront
		moveq		#-MOVESTEP,D2
		move.l		DScreen(DB),A0
		move.w		sc_TopEdge(A0),D1
		Call		PScreen
		rts

PushScreen	moveq		#MOVESTEP,D2
		move.l		GraphBase(DB),A0
		move.w		gb_NormalDisplayRows(A0),D1
		move.l		DScreen(DB),A0
		sub.w		sc_TopEdge(A0),D1
		Call		PScreen
		Call		DoBack
		rts

* Call: D1 = y-coordinates to move screen
*       D2 = delta-y
PScreen		ext.l		D1
		move.w		D1,D3
		divu		#MOVESTEP,D1
		swap		D1
		sub.w		D1,D3
		tst.w		D2
		bpl.S		1$
		neg.w		D1
1$		tst.w		D1
		beq.S		4$
		bra.S		3$
2$		move.w		D2,D1
3$		moveq		#0,D0
		move.l		DScreen(DB),A0
		Prepare		Intuition_Call
		CallLib		MoveScreen
4$		sub.w		#MOVESTEP,D3
		bge.S		2$
		rts
	ENDC

* A gadget was selected
DoGadget
GJ		movea.l		IAddress(DB),A1
		move.w		gg_GadgetID(A1),D0	; GadgetID is offset from GJ
		jsr		GJ(PC,D0.W)
		bra		GetNextMsg

DoQuit		not.w		Quit(DB)
DoGadgets	rts

* User clicked the 'Check' gadget
DoCheck		move.l		CurFunc(DB),A0
		Call		KeysToFunc
		Call		SortKeys
		moveq		#ALLISOK,D7
		Call		FindDuplicates
		bmi.S		1$
		moveq		#DUPLICATES,D7
1$		move.l		D7,D0
		Call		WriteMsg
		rts

* User clicked the 'Use' gadget
DoUse		move.l		CurFunc(DB),A0
		Call		KeysToFunc
		Call		SortKeys
		moveq		#DUPLICATES,D7
		Call		FindDuplicates
		bge.S		2$
		Call		MakeMasks
		Call		CountKeys
		lea		TempDefined(PC),A0
		move.w		D0,(A0)
		Prepare		Exec_Call
		CallLib		Forbid
		lea		PWKeysPortName(PC),A1
		moveq		#NOHANDLER,D7
		CallLib		FindPort
		tst.l		D0
		beq.S		1$
		move.l		D0,A1
		move.l		ihs_Interrupt+IS_DATA(A1),A1
		lea		TempFile(PC),A0
		move.w		#FilePart,D0		; Copy keydefinition into the
		Call		MemCopy			; PWKeys-handler memory
1$		CallLib		Permit
		moveq		#TITLE,D7
2$		move.l		D7,D0
		Call		WriteMsg
		rts

* User clicked the 'Undo' gadget
DoUndo		Call		ClearKeyboard
		move.l		CurFunc(DB),A0
		Call		FillKeyboard
		rts

* User clicked the 'Clear' gadget
DoClear		Call		ClearKeyboard
		rts

* User clicked the 'ScreentoBack' gadget
DoBack		Prepare		Intuition_Call
		move.l		DScreen(DB),A0
		CallLib		ScreenToBack
		rts

* User clicked the 'ScreentoFront' gadget
DoFront		Prepare		Intuition_Call
		move.l		DScreen(DB),A0
		CallLib		ScreenToFront
		rts

* User clicked the 'Save' gadget
DoSave		move.l		CurFunc(DB),A0
		Call		KeysToFunc
		Call		SortKeys
		moveq		#DUPLICATES,D7
		Call		FindDuplicates
		bge.S		2$
		Call		MakeMasks
		Prepare		Dos_Call
		lea		FBuffer(PC),A0
		move.l		A0,D1
		move.l		#MODE_NEWFILE,D2
		moveq		#NOFILE,D7
		CallLib		Open
		move.l		D0,FHandle(DB)
		beq.S		1$
		move.l		D0,D1
		lea		TempFile(PC),A0
		move.l		A0,D2
		move.w		#FilePart,D3
		moveq		#WRITEERR,D7
		CallLib		Write
		cmp.l		D0,D3
		bne.S		1$
		moveq		#TITLE,D7
1$		move.l		FHandle(DB),D1
		beq.S		2$
		CallLib		Close
2$		move.l		D7,D0
		Call		WriteMsg
		rts

* User clicked the 'Load' gadget
DoLoad		Prepare		Dos_Call
		lea		FBuffer(PC),A0
		move.l		A0,D1
		move.l		#MODE_OLDFILE,D2
		moveq		#NOFILE,D7
		CallLib		Open
		move.l		D0,FHandle(DB)
		beq.S		1$
		move.l		D0,D1
		lea		TempFile(PC),A0
		move.l		A0,D2
		move.w		#FilePart,D3
		moveq		#WRONGFILE,D7
		CallLib		Read
		cmp.l		D0,D3
		bne.S		1$
		movem.l		TempFile(PC),D0-D1
		movem.l		PWKVersionID(PC),D2-D3
		cmp.l		D0,D2
		bne.S		1$
		cmp.l		D1,D3
		bne.S		1$
		Call		ClearFunctions
		Call		ClearKeyboard
		Call		UnSortKeys
		Call		InitFuncs
		lea		Funcs(PC),A0
		bset		#SELECTEDBOX,Box_Flags(A0)
		move.l		A0,CurFunc(DB)
		Call		FillKeyboard
		Call		FillFunctions
		moveq		#TITLE,D7
1$		move.l		FHandle(DB),D1
		beq.S		2$
		CallLib		Close
2$		move.l		D7,D0
		Call		WriteMsg
		rts

* The user pressed/released a mousebutton
DoMouse		cmpi.w		#SELECTDOWN,Code(DB)
		beq.S		DoLB
		cmpi.w		#MENUDOWN,Code(DB)
		bne		DoM
* Perhaps the user clicked on a qualifier-key with RMB
DoRB		cmp.w		#KY-SWDIFF,MouseY(DB)
		blt		DoSelFunc
		Call		WhichKey
		bmi		DoM
		tst.w		KeyBox_Qual(A0)		; Is it a qual-key ?
		beq		DoM
		btst		#SELECTEDBOX,Box_Flags(A0)
		beq.S		1$
		btst		#GHOSTEDBOX,Box_Flags(A0)
		bne.S		1$
		Call		RawInvert		; Key was raw
		move.l		#-1,CurCode(DB)
1$		Call		QualInvert
		bra		DoM
* Perhaps the user clicked on a key with LMB
DoLB		cmp.w		#KY-SWDIFF,MouseY(DB)
		blt.S		DoSelFunc
		Call		WhichKey
		bmi		DoM
		move.l		CurCode(DB),D0
		move.l		A0,CurCode(DB)
		tst.l		D0
		bmi.S		5$
		lea		ReturnKey1(PC),A1	; Treat the two
		lea		ReturnKey2(PC),A2	; parts of the
		cmp.l		A1,A0			; RETURN-key as
		beq.S		1$			; if they were
		cmp.l		A2,A0			; one
		bne.S		3$
1$		cmp.l		A1,D0
		beq.S		2$
		cmp.l		A2,D0
		bne.S		3$
2$		move.l		A0,D0

3$		cmp.l		A0,D0
		beq.S		4$
		move.l		D0,A0			; Changed key
		Call		RawInvert
		move.l		CurCode(DB),A0
		bra.S		5$
4$		move.l		#-1,CurCode(DB)		; Unselected a key
5$		btst		#SELECTEDBOX,Box_Flags(A0)
		beq.S		6$
		btst		#GHOSTEDBOX,Box_Flags(A0)
		beq.S		6$
		Call		QualInvert		; Key was qual
6$		Call		RawInvert
		bra.S		DoM
* Perhaps the user clicked on a function
DoSelFunc	Call		WhichFunc
		bmi.S		DoM
		move.l		CurFunc(DB),A1
		cmp.l		A0,A1			; If the function is already selected
		beq.S		1$			; then this is click is a 'UNDO' click
		move.l		A0,CurFunc(DB)
		move.l		A1,A0
		Call		KeysToFunc		; Save the selected keys
		btst		#GHOSTEDBOX,Box_Flags(A0)
		beq.S		3$
		Call		RawInvert
		Call		QualInvert
		bset		#GHOSTEDBOX,Box_Flags(A0)
		bra.S		4$
3$		Call		RawInvert		; Unselect function
4$		move.l		CurFunc(DB),A0
		btst		#GHOSTEDBOX,Box_Flags(A0)
		beq.S		2$
		Call		QualInvert
2$		Call		RawInvert		; Select function
1$		Call		ClearKeyboard
		move.l		CurFunc(DB),A0
		Call		FillKeyboard
DoM		bra		GetNextMsg

* THE INVERT FUNCTONS ONLY PRESERVES A0
* Complements a key with a pattern
* Call: A0 = box
QualInvert	Push		A0
		bchg		#GHOSTEDBOX,Box_Flags(A0)
		movea.l		Rp(DB),A1
		move.l		#Mask,rp_AreaPtrn(A1)
		move.b		#2,rp_AreaPtSz(A1)
		bra.S		RI2
* Complements a key
* Call: A0 = box
RawInvert	cmp.l		#ReturnKey1,A0
		beq.S		1$
		cmp.l		#ReturnKey2,A0
		bne.S		RI
1$		Push		A0
		lea		ReturnKey1(PC),A0
		Call		RI
		lea		ReturnKey2(PC),A0
		Call		RI
		Pop		A0
		rts
RI		Push		A0
RI2		bchg		#SELECTEDBOX,Box_Flags(A0)
		move.l		A0,A2
		Prepare		Gfx_Call
		Call		SetDrMd2
		move.w		Box_x(A2),D0
		move.w		Box_y(A2),D1
		move.w		D0,D2
		move.w		D1,D3
		addq.w		#1,D0
		addq.w		#1,D1
		add.w		Box_Width(A2),D2
		add.w		Box_Height(A2),D3
		subq.w		#1,D2
		subq.w		#1,D3
		movea.l		Rp(DB),A1
		CallLib		RectFill
		Call		SetDrMd1
		movea.l		Rp(DB),A1
		clr.l		rp_AreaPtrn(A1)
		clr.b		rp_AreaPtSz(A1)
		Pop		A0
		rts

* Finds the selected function box (if any)
* Return: If D0=-1 then couldn't find anything, else A0=FuncBox
WhichFunc	lea		Funcs(PC),A0
		bra.S		WFK
* Finds the selected key (if any)
* Return: If D0=-1 then couldn't find anything, else A0=KeyBox
WhichKey	lea		Keys(PC),A0
WFK		move.w		MouseX(DB),D6
		move.w		MouseY(DB),D7
		add.w		#SWDIFF,D7
1$		move.w		Box_y(A0),D1
		bmi.S		3$
		cmp.w		D1,D7
		blt.S		2$
		add.w		Box_Height(A0),D1
		cmp.w		D1,D7
		bgt.S		2$
		move.w		Box_x(A0),D0
		cmp.w		D0,D6
		blt.S		2$
		add.w		Box_Width(A0),D0
		cmp.w		D0,D6
		bgt.S		2$
		moveq		#0,D0
		bra.S		4$
2$		add.l		#FKeyBox_SIZE,A0
		bra.S		1$
3$		moveq		#-1,D0
4$		rts

* Draw all the keys
DrawKeys	lea		Keys(PC),A2
DL		Prepare		Gfx_Call
1$		move.w		Box_x(A2),D0
		bmi		3$
		move.w		Box_y(A2),D1
		move.l		Rp(DB),A1
		CallLib		Move
		move.w		Box_x(A2),D0
		move.w		Box_y(A2),D1
		add.w		Box_Width(A2),D0
		move.l		Rp(DB),A1
		CallLib		Draw
		move.w		Box_x(A2),D0
		move.w		Box_y(A2),D1
		add.w		Box_Width(A2),D0
		add.w		Box_Height(A2),D1
		move.l		Rp(DB),A1
		CallLib		Draw
		move.w		Box_x(A2),D0
		move.w		Box_y(A2),D1
		add.w		Box_Height(A2),D1
		move.l		Rp(DB),A1
		CallLib		Draw
		move.w		Box_x(A2),D0
		move.w		Box_y(A2),D1
		move.l		Rp(DB),A1
		CallLib		Draw
		lea		StrBuf(PC),A0
		move.b		KeyBox_Char(A2),(A0)
		beq.S		2$
		move.w		Box_x(A2),D0
		addq.w		#7,D0
		move.w		Box_y(A2),D1
		addq.w		#8,D1
		move.l		Rp(DB),A1
		CallLib		Move
		lea		StrBuf(PC),A0
		moveq		#1,D0
		move.l		Rp(DB),A1
		CallLib		Text
2$		add.l		#FKeyBox_SIZE,A2
		bra		1$
3$		rts

* Call: A0 = FuncBox
FillFunctions	Call		KeysToFunc
		Push		A2
		lea		Funcs(PC),A2
		bclr		#GHOSTEDBOX,Box_Flags(A2)	;Just loaded new file, first item needs to be selected
		Pop		A2
* hilites/unhilites all functions with the 'SELECTEDBOX/GHOSTEDBOX' flag set
RefreshFunc	Push		D0-D3/A0-A2/A6
		lea		Funcs(PC),A2
		bra.S		RFK
* Call: A0 = FuncBox
FillKeyboard	Call		FuncToKeys
* hilites/unhilites all keys with the 'SELECTEDBOX'/'GHOSTEDBOX' flag set
RefreshKeys	Push		D0-D3/A0-A2/A6
		lea		Keys(PC),A2
RFK
1$		move.w		Box_x(A2),D0
		bmi.S		5$
		btst		#SELECTEDBOX,Box_Flags(A2)
		beq.S		4$
		move.l		A2,A0
		btst		#GHOSTEDBOX,Box_Flags(A2)
		beq.S		2$
		Call		QualInvert
		bset		#GHOSTEDBOX,Box_Flags(A2)
		bra.S		3$
2$		Call		RawInvert
3$		bset		#SELECTEDBOX,Box_Flags(A2)
4$		add.l		#FKeyBox_SIZE,A2
		bra.S		1$
5$		Pop		D0-D3/A0-A2/A6
		rts

* Clears all hilite-flags in the 'Funcs' array
ClearFunctions	move.l		CurFunc(DB),A0		; This is because the selected
		bclr		#GHOSTEDBOX,Box_Flags(A0); can be both selected and ghosted
		Call		RefreshFunc
		Push		A2
		lea		Funcs(PC),A2
		bra.S		CFK
* Clears all hilite-flags in the 'Keys' array
ClearKeyboard	Call		RefreshKeys
		move.l		#-1,CurCode(DB)
		Push		A2
		lea		Keys(PC),A2
CFK	* Clears all hilite-flags in the 'Keys/Funcs' array
1$		tst.w		Box_x(A2)
		bmi.S		2$
		bclr		#SELECTEDBOX,Box_Flags(A2)
		bclr		#GHOSTEDBOX,Box_Flags(A2)
		add.l		#FKeyBox_SIZE,A2
		bra.S		1$
2$		Pop		A2
		rts

* Call: A0 = FuncBox
* Collects all hilite-flags in the 'Keys' array
KeysToFunc	Push		D0-D2/A0-A2
		move.l		FuncBox_HotKey(A0),A1
		move.w		#U_CODE,D1
		moveq		#U_QUAL,D2
		lea		Keys(PC),A2
1$		move.w		Box_x(A2),D0
		bmi.S		4$
		btst		#SELECTEDBOX,Box_Flags(A2)
		beq.S		3$
		btst		#GHOSTEDBOX,Box_Flags(A2)
		bne.S		2$
		move.w		KeyBox_Code(A2),D1
		bra.S		3$
2$		or.w		KeyBox_Qual(A2),D2
3$		add.l		#FKeyBox_SIZE,A2
		bra.S		1$
4$		cmp.w		#U_CODE,D1
		bne.S		6$
		bset		#GHOSTEDBOX,Box_Flags(A0)	; If no code then function has to be ghosted
		moveq		#U_QUAL,D2			; If no code then no qualifier
6$		move.w		D1,HotKey_Code(A1)
		move.w		D2,HotKey_Qual(A1)
5$		Pop		D0-D2/A0-A2
		rts

* Call: A0 = FuncBox
* Set all hilite-flags in the 'Keys' array
FuncToKeys	Push		D0/A0/A2
		move.l		FuncBox_HotKey(A0),A0
		lea		Keys(PC),A2
1$		move.w		Box_x(A2),D0
		bmi.S		4$
		move.w		KeyBox_Code(A2),D0
		cmp.w		HotKey_Code(A0),D0
		bne.S		2$
		move.l		A2,CurCode(DB)
		bset		#SELECTEDBOX,Box_Flags(A2)
		bra.S		3$
2$		move.w		KeyBox_Qual(A2),D0
		and.w		HotKey_Qual(A0),D0
		beq.S		3$
		bset		#SELECTEDBOX,Box_Flags(A2)
		bset		#GHOSTEDBOX,Box_Flags(A2)
3$		add.l		#FKeyBox_SIZE,A2
		bra.S		1$
4$		Pop		D0/A0/A2
		rts

* Makes some masks
MakeMasks	Push		D0-D4/A0-A2
		lea		TempPWKeys(PC),A2
		moveq		#0,D0
		moveq		#-2,D2			; Code
ml		cmp.w		#KeyFuncNumber,D0
		bge.S		5$
		moveq		#0,D1			; Number
		moveq		#0,D3			; Qual
1$		move.l		D0,D4			; 'OR' qualifiers for all hotkeys with this code
		add.w		D1,D4
		cmp.w		#KeyFuncNumber,D4
		bge.S		2$
		mulu		#HotKey_SIZE,D4
		lea		0(A2,D4),A0
		cmp.w		HotKey_Code(A0),D2
		bne.S		2$
		addq.l		#1,D1
		or.w		HotKey_Qual(A0),D3
		bra.S		1$
2$		tst.w		D3
		bne.S		4$
		move.w		#KEYMASK,D3
		bra.S		4$
3$		move.l		D0,D4			;Store the 'OR'ed qualifiers in all hotkeys with this code
		mulu		#HotKey_SIZE,D4
		lea		0(A2,D4),A1
		move.w		D3,HotKey_QMask(A1)
		addq.l		#1,D0
4$		dbf		D1,3$
		move.w		HotKey_Code(A0),D2
		bra.S		ml
5$		Pop		D0-D4/A0-A2
		rts

InitFuncs	Push		D0/A0-A2
		lea		Funcs(PC),A2
1$		move.w		Box_x(A2),D0
		bmi.S		2$
		move.l		FuncBox_HotKey(A2),A0
		bclr		#SELECTEDBOX,Box_Flags(A2)
		bclr		#GHOSTEDBOX,Box_Flags(A2)
		cmp.w		#U_CODE,HotKey_Code(A0)
		bne.S		3$
		bset		#SELECTEDBOX,Box_Flags(A2)
		bset		#GHOSTEDBOX,Box_Flags(A2)
3$		add.l		#FKeyBox_SIZE,A2
		bra.S		1$
2$		Pop		D0/A0-A2
		rts

* Finds first pair of duplicates (HotKeys must be sorted)
* Return: D0 != -1 means D0 and D1 are the same (and not undefined)
FindDuplicates	Push		A2
		lea		TempPWKeys+HotKey_SIZE(PC),A2
		moveq		#DefFuncNumber,D0
		bra.S		3$
1$		move.l		-HotKey_SIZE+HotKey_ID(A2),D1
		cmp.l		HotKey_ID(A2),D1
		bne.S		2$
		cmp.l		#(U_CODE<<16)|U_QUAL,D1
		bne.S		4$
2$		addq.l		#HotKey_SIZE,A2
3$		dbf		D0,1$	
		moveq		#-1,D0
		bra.S		5$
4$		moveq		#0,D0
		moveq		#0,D1
		move.b		HotKey_Func(A2),D0
		move.b		-HotKey_SIZE+HotKey_Func(A2),D1
5$		Pop		A2
		tst.l		D0
		rts

* Counts the number of defined hotkeys (HotKeys must be sorted)
* Return: D0 = count
CountKeys	Push		D1-D2/A2
		lea		TempPWKeys(PC),A2
		moveq		#0,D0
		moveq		#DefFuncNumber,D1
		bra.S		2$
1$		move.w		HotKey_Code(A2),D2
		cmp.w		#U_CODE,D2
		beq.S		3$
		addq.l		#1,D0
		addq.l		#HotKey_SIZE,A2
2$		dbf		D1,1$
3$		Pop		D1-D2/A2
		rts

* Sorts HotKeys on 'Code|Qual'
SortKeys	Push		D0-D7/A0-A6
		lea		TempFile(PC),A1
		lea		PWKVersionID(PC),A0
		move.w		#FilePart,D0
		Call		MemCopy
		moveq		#0,D6
		lea		TempPWKeys(PC),A2
OuterLoop	moveq		#KeyFuncNumber,D5
		bra.S		ContSort
InnerLoop	moveq		#KeyFuncNumber,D0
		sub.w		D5,D0
		mulu		#HotKey_SIZE,D0
		lea		-HotKey_SIZE(A2,D0.L),A0
		lea		HotKey_SIZE(A0),A1
		move.l		HotKey_ID(A0),D0
		move.l		HotKey_ID(A1),D1
		cmp.l		D0,D1
		bge.S		ContSort
		move.l		D1,HotKey_ID(A0)
		move.l		D0,HotKey_ID(A1)
		move.l		HotKey_Mask(A0),D0
		move.l		HotKey_Mask(A1),HotKey_Mask(A0)
		move.l		D0,HotKey_Mask(A1)
ContSort	subq.w		#1,D5
		cmp.w		D5,D6
		blt.S		InnerLoop
		addq.w		#1,D6
		cmp.w		#KeyFuncNumber-1,D6
		blt.S		OuterLoop
		Pop		D0-D7/A0-A6
		rts

* Unsorts HotKeys on to 'Func'
UnSortKeys	Push		D0-D7/A0-A6
		lea		TempFile(PC),A0
		lea		PWKVersionID(PC),A1
		move.w		#FilePart,D0
		Call		MemCopy
		lea		TempPWKeys(PC),A2
		moveq		#DefFuncNumber,D0
		bra.S		2$
1$		moveq		#0,D1
		move.b		HotKey_Func(A2),D1
		mulu		#HotKey_SIZE,D1
		lea		KeyDefines(PC),A1
		add.l		D1,A1
		move.l		HotKey_ID(A2),HotKey_ID(A1)
		move.l		HotKey_Mask(A2),HotKey_Mask(A1)
		addq.l		#HotKey_SIZE,A2
2$		dbf		D0,1$
		Pop		D0-D7/A0-A6
		rts

		moveq		#0,D6
		lea		KeyDefines(PC),A2
UOuterLoop	moveq		#KeyFuncNumber,D5
		bra.S		ContUSort
UInnerLoop	moveq		#KeyFuncNumber,D0
		sub.w		D5,D0
		mulu		#HotKey_SIZE,D0
		lea		-HotKey_SIZE(A2,D0.L),A0
		lea		HotKey_SIZE(A0),A1
		moveq		#0,D0
		moveq		#0,D1
		move.b		HotKey_Func(A0),D0
		move.b		HotKey_Func(A1),D1
		cmp.w		D0,D1
		bge.S		ContUSort
		move.l		HotKey_ID(A0),D0
		move.l		HotKey_ID(A1),HotKey_ID(A0)
		move.l		D0,HotKey_ID(A1)
		move.l		HotKey_Mask(A0),D0
		move.l		HotKey_Mask(A1),HotKey_Mask(A0)
		move.l		D0,HotKey_Mask(A1)
ContUSort	subq.w		#1,D5
		cmp.w		D5,D6
		blt.S		UInnerLoop
		addq.w		#1,D6
		cmp.w		#KeyFuncNumber-1,D6
		blt.S		UOuterLoop
		Pop		D0-D7/A0-A6
		rts

* Writes the text in the function boxes
WriteFuncs	Push		D0-D1
		moveq		#FUNCTEXTS+GADTEXTS,D1
		bra.S		2$
1$		move.w		D1,D0
		Call		WriteTxt
2$		dbf		D1,1$
		Pop		D0-D1
		rts

* Call: D0 = Msg-number
WriteMsg	Push		D0-D4/A0-A1/A6
		neg.w		D0
		add.w		#FUNCTEXTS+GADTEXTS,D0
		move.l		D0,D5
		Call		SetAPen0
		moveq		#4,D0
		moveq		#2,D1
		move.w		#570,D2
		moveq		#10,D3
		movea.l		Rp(DB),A1
		CallLib		RectFill
		Call		SetAPen1
		move.l		D5,D0
		Call		WriteTxt
		Pop		D0-D4/A0-A1/A6
		rts

* Call: D0 = Msg-number
WriteTxt	Push		D0-D1/A0-A3/A6
		Prepare		Gfx_Call
		lea		TextTab(PC),A2
		move.l		A2,A3
		mulu		#TE_SIZE,D0
		add.l		D0,A2
		move.w		TE_x(A2),D0
		move.w		TE_y(A2),D1
		movea.l		Rp(DB),A1
		CallLib		Move
		move.w		TE_Offset(A2),A0
		add.l		A3,A0
		Call		StrLen
		movea.l		Rp(DB),A1
		CallLib		Text
		Pop		D0-D1/A0-A3/A6
		rts

* Sets the drawing pen.
* Destroys D0-D1/A0-A1/A6
SetAPen0	moveq		#0,D0
		bra.S		SetPenA
SetAPen1	moveq		#1,D0
SetPenA		movea.l		Rp(DB),A1		; D0=Color
		Prepare		Gfx_Call
		CallLib		SetAPen
		rts

SetDrMd1	moveq		#1,D0
		bra.S		SetMdDr
SetDrMd2	moveq		#2,D0
SetMdDr		movea.l		Rp(DB),A1		; D0=Drawmode
		Prepare		Gfx_Call
		CallLib		SetDrMd
		rts

* Call: A0    = Source
*       A1    = Destination
*       D0:16 = Count
MemCopy		Push		D0/A0-A1
		bra.S		2$
1$		move.b		(A0)+,(A1)+
2$		dbf		D0,1$
		Pop		D0/A0-A1
		rts

* Call:   A0 = String
* Return: D0 = length
StrLen		Push		A0
		moveq		#-1,D0
1$		addq.l		#1,D0
		tst.b		(A0)+
		bne.S		1$
		Pop		A0
		rts

* Return: D0 != means that we got a message
GetAMessage	Push		D0-D1/A0-A1/A6
		movea.l		Up(DB),A0
		Prepare		Exec_Call
		CallLib		GetMsg
		tst.l		D0
		beq.S		NoMessage
GotAMessage	movea.l		D0,A1
		move.l		im_Class(A1),Class(DB)
		move.w		im_Code(A1),Code(DB)
		move.w		im_Qualifier(A1),Qual(DB)
		move.l		im_IAddress(A1),IAddress(DB)
		move.w		im_MouseX(A1),MouseX(DB)
		move.w		im_MouseY(A1),MouseY(DB)
		CallLib		ReplyMsg
		moveq		#1,D0
NoMessage	Pop		D0-D1/A0-A1/A6
		rts

*====================== Data-definition start =======================
 rStart
 rWord		Quit
 rAPtr		PProcess
 rAPtr		DosBase
 rAPtr		GraphBase
 rAPtr		IntBase
 rLong		WBenchMsg
 rAPtr		FHandle
 rAPtr		DScreen
 rAPtr		DWindow
 rAPtr		ScrVp			; ViewPort
 rAPtr		Rp			; RastPort
 rAPtr		Up			; UserPort
 rLong		Class			; IDCMP->Class
 rWord		Code			; IDCMP->Code
 rWord		Qual			; IDCMP->Qualifier
 rLong		IAddress		; IDCMP->IAddress
 rWord		MouseX			; IDCMP->MouseX
 rWord		MouseY			; IDCMP->MouseY
 rAPtr		CurFunc			; Ptr to FuncBox
 rAPtr		CurCode			; Ptr to KeyBox
 rEnd
		EVEN
StrBuf		;Re-use space below after opening libraries
DosName		dc.b		'dos.library',0
GfxName		dc.b		'graphics.library',0
IntName		dc.b		'intuition.library',0
PWKeysPortName	dc.b		'PWKeys V1.0 Port',0
		EVEN

ScrW		=640
ScrH		=196
NewS		dc.w		0,0,ScrW,ScrH,PLANES
		dc.b		0,1
		dc.w		V_HIRES,CUSTOMSCREEN|SCREENQUIET
		dc.l		TxtAttr,0,0,0
IDCMP_Flags	=GADGETUP+MOUSEBUTTONS
Other_Flags	=NOCAREREFRESH+ACTIVATE+RMBTRAP+BORDERLESS
NewW		dc.w		0,SWDIFF,ScrW,ScrH-SWDIFF
		dc.b		0,1
		dc.l		IDCMP_Flags,Other_Flags,GadgetList,0,0,0,0
		dc.w		0,0,0,0,CUSTOMSCREEN
	IFD CUSTOMCOLORS
ColorTable	dc.w		$0BBC,$0000
	ENDC

GadgetList
Gad1		Gadget		Gad2,502,8,BWIDTH,BHEIGHT,GADGHCOMP,RELVERIFY,BOOLGADGET
		Gadget2		BBorder,0,0,0,0,DoQuit-GJ,0
Gad2		Gadget		Gad3,448,25,BWIDTH,BHEIGHT,GADGHCOMP,RELVERIFY,BOOLGADGET
		Gadget2		BBorder,0,0,0,0,DoCheck-GJ,0
Gad3		Gadget		Gad4,556,25,BWIDTH,BHEIGHT,GADGHCOMP,RELVERIFY,BOOLGADGET
		Gadget2		BBorder,0,0,0,0,DoUse-GJ,0
Gad4		Gadget		Gad5,448,42,BWIDTH,BHEIGHT,GADGHCOMP,RELVERIFY,BOOLGADGET
		Gadget2		BBorder,0,0,0,0,DoUndo-GJ,0
Gad5		Gadget		Gad6,556,42,BWIDTH,BHEIGHT,GADGHCOMP,RELVERIFY,BOOLGADGET
		Gadget2		BBorder,0,0,0,0,DoClear-GJ,0
Gad6		Gadget		Gad7,448,59,BWIDTH,BHEIGHT,GADGHCOMP,RELVERIFY,BOOLGADGET
		Gadget2		BBorder,0,0,0,0,DoSave-GJ,0
Gad7		Gadget		Gad8,556,59,BWIDTH,BHEIGHT,GADGHCOMP,RELVERIFY,BOOLGADGET
		Gadget2		BBorder,0,0,0,0,DoLoad-GJ,0
Gad8		Gadget		0,452,78,FWIDTH,FHEIGHT,GADGHCOMP,RELVERIFY,STRGADGET
		Gadget2		FBorder,0,0,0,FileInfo,DoGadgets-GJ,0

FileBufLen	=80
FileInfo	dc.l		FBuffer,0
		dc.w		0,FileBufLen,0,0,0,0,0,0
		dc.l		0,0,0
FBuffer		dc.b		'S:PWKeys.Config'
		dcb.b		FileBufLen-14,0
		EVEN

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

ArrowImages	Image		0,0,42,11,1,ArrowsData,%00000001,%00000000,0
FWIDTH		=188
FHEIGHT		=11
FBorder		Border		-6,-3,1,0,1,17,FVectors,0
FVectors	dc.w		2,0,FWIDTH+1,0,FWIDTH+3,2,FWIDTH+3,FHEIGHT-1,FWIDTH+1,FHEIGHT+1,2,FHEIGHT+1,0,FHEIGHT-1,0,2,2,0
		dc.w		1,0,-1,2,-1,FHEIGHT-1,1,FHEIGHT+1,FWIDTH+2,FHEIGHT+1,FWIDTH+4,FHEIGHT-1,FWIDTH+4,2,FWIDTH+2,0
FUNCW		=402
FUNCH		=84
FuncBorder	Border		1,0,1,0,1,17,FuncVectors,0
FuncVectors	dc.w		2,0,FUNCW+1,0,FUNCW+3,2,FUNCW+3,FUNCH-1,FUNCW+1,FUNCH+1,2,FUNCH+1,0,FUNCH-1,0,2,2,0
		dc.w		1,0,-1,2,-1,FUNCH-1,1,FUNCH+1,FUNCW+2,FUNCH+1,FUNCW+4,FUNCH-1,FUNCW+4,2,FUNCW+2,0
BWIDTH		=80
BHEIGHT		=11
BBorder		Border		-2,-1,1,0,1,17,BVectors,0
BVectors	dc.w		2,0,BWIDTH+1,0,BWIDTH+3,2,BWIDTH+3,BHEIGHT-1,BWIDTH+1,BHEIGHT+1,2,BHEIGHT+1,0,BHEIGHT-1,0,2,2,0
		dc.w		1,0,-1,2,-1,BHEIGHT-1,1,BHEIGHT+1,BWIDTH+2,BHEIGHT+1,BWIDTH+4,BHEIGHT-1,BWIDTH+4,2,BWIDTH+2,0
KEYBW		=ScrW-6
KEYBH		=85
KeybBorder	Border		1,0,1,0,1,17,KeybVectors,0
KeybVectors	dc.w		2,0,KEYBW+1,0,KEYBW+3,2,KEYBW+3,KEYBH-1,KEYBW+1,KEYBH+1,2,KEYBH+1,0,KEYBH-1,0,2,2,0
		dc.w		1,0,-1,2,-1,KEYBH-1,1,KEYBH+1,KEYBW+2,KEYBH+1,KEYBW+4,KEYBH-1,KEYBW+4,2,KEYBW+2,0
TITW		=570
TITH		=11
TitleBorder	Border		1,0,1,0,1,17,TitleVectors,0
TitleVectors	dc.w		2,0,TITW+1,0,TITW+3,2,TITW+3,TITH-1,TITW+1,TITH+1,2,TITH+1,0,TITH-1,0,2,2,0
		dc.w		1,0,-1,2,-1,TITH-1,1,TITH+1,TITW+2,TITH+1,TITW+4,TITH-1,TITW+4,2,TITW+2,0

TE_x		=0
TE_y		=2
TE_Offset	=4
TE_SIZE		=6
TEntry		MACRO		'TextEntry'
		dc.w		\1,\2,\3-TextTab
		ENDM
FySpace		=9
FTx1		=8
FTx2		=207
FTy		=27

TextTab		TEntry		FTx1,FTy+0*FySpace,1$
		TEntry		FTx1,FTy+1*FySpace,2$
		TEntry		FTx1,FTy+2*FySpace,3$
		TEntry		FTx1,FTy+3*FySpace,4$
		TEntry		FTx1,FTy+4*FySpace,5$
		TEntry		FTx1,FTy+5*FySpace,6$
		TEntry		FTx1,FTy+6*FySpace,7$
		TEntry		FTx1,FTy+7*FySpace,8$
		TEntry		FTx1,FTy+8*FySpace,9$
		TEntry		FTx2,FTy+0*FySpace,10$
		TEntry		FTx2,FTy+1*FySpace,11$
		TEntry		FTx2,FTy+2*FySpace,12$
		TEntry		FTx2,FTy+3*FySpace,13$
		TEntry		FTx2,FTy+4*FySpace,14$
		TEntry		FTx2,FTy+5*FySpace,15$
		TEntry		FTx2,FTy+6*FySpace,16$
		TEntry		FTx2,FTy+7*FySpace,17$

		TEntry		525,26,21$
		TEntry		470,43,22$
		TEntry		578,43,23$
		TEntry		470,60,24$
		TEntry		578,60,25$
		TEntry		470,77,26$
		TEntry		578,77,27$

		TEntry		10,9,28$
		TEntry		10,9,29$
		TEntry		10,9,30$
		TEntry		10,9,31$
		TEntry		10,9,32$
		TEntry		10,9,33$
		TEntry		10,9,34$

* Function texts
1$		dc.b		'Window to top',0
2$		dc.b		'Window to bottom',0
3$		dc.b		'Window to left',0
4$		dc.b		'Window to right',0
5$		dc.b		'Window to left-top',0
6$		dc.b		'Window to left-bottom',0
7$		dc.b		'Window to right-top',0
8$		dc.b		'Window to right-bottom',0
9$		dc.b		'Window to center',0
10$		dc.b		'Window to front',0
11$		dc.b		'Window to back',0
12$		dc.b		'Activate previous window',0
13$		dc.b		'Activate next window',0
14$		dc.b		'Back window to front',0
15$		dc.b		'Front window to back',0
16$		dc.b		'Back screen to front',0
17$		dc.b		'Front screen to back',0

* Gadget texts
21$		dc.b		'Quit',0
22$		dc.b		'Check',0
23$		dc.b		'Use',0
24$		dc.b		'Undo',0
25$		dc.b		'Clear',0
26$		dc.b		'Save',0
27$		dc.b		'Load',0

* Message texts
28$		dc.b		'SetPWKeys V1.0 1991 by Preben Nielsen',0
29$		dc.b		"Error: Can't open file",0
30$		dc.b		"Error: Not a PWKeys file",0
31$		dc.b		"Error: Can't write file",0
32$		dc.b		'Error: The PWKeys-handler is not installed',0
33$		dc.b		'Error: Duplicate hotkey definitions.',0
34$		dc.b		'There are no duplicate hotkey definitions',0
		EVEN

Box_x		=0
Box_y		=2
Box_Width	=4
Box_Height	=6
Box_Flags	=8
Box_SIZE	=9
Box		MACRO
		dc.w		\1,\2,\3,\4	; x,y,width,height
		dc.b		\5		; Flags
		ENDM

FuncBox_HotKey	=10
FuncBox_SIZE	=14
FuncBox		MACRO		'Functionbox'
		Box		\1,\2,\3,\4,\5	; Box definition
		dc.b		0		; Pad
		dc.l		\6		; Function
		ENDM

KeyBox_Char	=9
KeyBox_Code	=10
KeyBox_Qual	=12
KeyBox_SIZE	=14
FKeyBox_SIZE	=14
KeyBox		MACRO		'Keybox'
		Box		\1,\2,\3,\4,\5	; Box definition
		dc.b		\6		; Char
		dc.w		\7,\8		; Raw, Qual
		ENDM

FBx1		=FTx1-4
FBx2		=FTx2-4
FBy		=FTy-8
FBWidth		=200
FBHeight	=11

Funcs		FuncBox		FBx1,FBy+0*FySpace,FBWidth,FBHeight,0,HK1
		FuncBox		FBx1,FBy+1*FySpace,FBWidth,FBHeight,0,HK2
		FuncBox		FBx1,FBy+2*FySpace,FBWidth,FBHeight,0,HK3
		FuncBox		FBx1,FBy+3*FySpace,FBWidth,FBHeight,0,HK4
		FuncBox		FBx1,FBy+4*FySpace,FBWidth,FBHeight,0,HK5
		FuncBox		FBx1,FBy+5*FySpace,FBWidth,FBHeight,0,HK6
		FuncBox		FBx1,FBy+6*FySpace,FBWidth,FBHeight,0,HK7
		FuncBox		FBx1,FBy+7*FySpace,FBWidth,FBHeight,0,HK8
		FuncBox		FBx1,FBy+8*FySpace,FBWidth,FBHeight,0,HK9
		FuncBox		FBx2,FBy+0*FySpace,FBWidth,FBHeight,0,HK10
		FuncBox		FBx2,FBy+1*FySpace,FBWidth,FBHeight,0,HK11
		FuncBox		FBx2,FBy+2*FySpace,FBWidth,FBHeight,0,HK12
		FuncBox		FBx2,FBy+3*FySpace,FBWidth,FBHeight,0,HK13
		FuncBox		FBx2,FBy+4*FySpace,FBWidth,FBHeight,0,HK14
		FuncBox		FBx2,FBy+5*FySpace,FBWidth,FBHeight,0,HK15
		FuncBox		FBx2,FBy+6*FySpace,FBWidth,FBHeight,0,HK16
		FuncBox		FBx2,FBy+7*FySpace,FBWidth,FBHeight,0,HK17
		FuncBox		-1,-1,-1,-1,0,Funcs

Absx		=20
KH		=10
FM		=8
FW		=27
FSPACE		=6
FD		=FW+FSPACE
NW		=20
NSPACE		=6
ND		=NW+NSPACE
KPx		=Absx+498
Arx		=Absx+410
KY		=ScrH-81
R1x		=Absx+40
R2x		=Absx+40
R3x		=Absx+50
R4x		=Absx+56
R5x		=Absx+70	;62
R1y		=KY+0*(KH+3)
R2y		=KY+1*(KH+3)
R3y		=KY+2*(KH+3)
R4y		=KY+3*(KH+3)
R5y		=KY+4*(KH+3)
R6y		=KY+5*(KH+3)

Keys
ReturnKey1
 KeyBox		382,R3y,NW+16,KH*2+3,0,0,$44,0
ReturnKey2
 KeyBox		363,R3y+13,20,KH,0,0,$44,0
 KeyBox		Absx,R1y,NW,KH,0,0,$45,0		;ESC
 KeyBox		R1x+00*FD,R1y,FW,KH,0,0,$50,0		;F1
 KeyBox		R1x+01*FD,R1y,FW,KH,0,0,$51,0		;F2
 KeyBox		R1x+02*FD,R1y,FW,KH,0,0,$52,0		;F3
 KeyBox		R1x+03*FD,R1y,FW,KH,0,0,$53,0		;F4
 KeyBox		R1x+04*FD,R1y,FW,KH,0,0,$54,0		;F5
 KeyBox		R1x+FM+05*FD,R1y,FW,KH,0,0,$55,0	;F6
 KeyBox		R1x+FM+06*FD,R1y,FW,KH,0,0,$56,0	;F7
 KeyBox		R1x+FM+07*FD,R1y,FW,KH,0,0,$57,0	;F8
 KeyBox		R1x+FM+08*FD,R1y,FW,KH,0,0,$58,0	;F9
 KeyBox		R1x+FM+09*FD,R1y,FW,KH,0,0,$59,0	;F10
 KeyBox		Absx,R2y,FW+6,KH,0,'`',$00,0
 KeyBox		R2x+00*ND,R2y,NW,KH,0,'1',$01,0
 KeyBox		R2x+01*ND,R2y,NW,KH,0,'2',$02,0
 KeyBox		R2x+02*ND,R2y,NW,KH,0,'3',$03,0
 KeyBox		R2x+03*ND,R2y,NW,KH,0,'4',$04,0
 KeyBox		R2x+04*ND,R2y,NW,KH,0,'5',$05,0
 KeyBox		R2x+05*ND,R2y,NW,KH,0,'6',$06,0
 KeyBox		R2x+06*ND,R2y,NW,KH,0,'7',$07,0
 KeyBox		R2x+07*ND,R2y,NW,KH,0,'8',$08,0
 KeyBox		R2x+08*ND,R2y,NW,KH,0,'9',$09,0
 KeyBox		R2x+09*ND,R2y,NW,KH,0,'0',$0A,0
 KeyBox		R2x+10*ND,R2y,NW,KH,0,'-',$0B,0
 KeyBox		R2x+11*ND,R2y,NW,KH,0,'=',$0C,0
 KeyBox		R2x+12*ND,R2y,NW,KH,0,'\',$0D,0
 KeyBox		R2x+13*ND,R2y,NW,KH,0,0,$41,0		;Backspace
 KeyBox		Arx,R2y,FW+6,KH,0,0,$46,0		;Del
 KeyBox		Arx+8+FD,R2y,FW+6,KH,0,0,$5F,0		;Help
 KeyBox		KPx+00*ND,R2y,NW,KH,0,'[',$5A,0
 KeyBox		KPx+01*ND,R2y,NW,KH,0,']',$5B,0
 KeyBox		KPx+02*ND,R2y,NW,KH,0,'\',$5C,0
 KeyBox		KPx+03*ND,R2y,NW,KH,0,'*',$5D,0
 KeyBox		Absx,R3y,FW+16,KH,0,0,$42,0		;Tab
 KeyBox		R3x+00*ND,R3y,NW,KH,0,'q',$10,0
 KeyBox		R3x+01*ND,R3y,NW,KH,0,'w',$11,0
 KeyBox		R3x+02*ND,R3y,NW,KH,0,'e',$12,0
 KeyBox		R3x+03*ND,R3y,NW,KH,0,'r',$13,0
 KeyBox		R3x+04*ND,R3y,NW,KH,0,'t',$14,0
 KeyBox		R3x+05*ND,R3y,NW,KH,0,'y',$15,0
 KeyBox		R3x+06*ND,R3y,NW,KH,0,'u',$16,0
 KeyBox		R3x+07*ND,R3y,NW,KH,0,'i',$17,0
 KeyBox		R3x+08*ND,R3y,NW,KH,0,'o',$18,0
 KeyBox		R3x+09*ND,R3y,NW,KH,0,'p',$19,0
 KeyBox		R3x+10*ND,R3y,NW,KH,0,'[',$1A,0
 KeyBox		R3x+11*ND,R3y,NW,KH,0,']',$1B,0
 KeyBox		KPx+00*ND,R3y,NW,KH,0,'7',$3D,0
 KeyBox		KPx+01*ND,R3y,NW,KH,0,'8',$3E,0
 KeyBox		KPx+02*ND,R3y,NW,KH,0,'9',$3F,0
 KeyBox		KPx+03*ND,R3y,NW,KH,0,'-',$4A,0
 KeyBox		Absx,R4y,NW+3,KH,0,0,$63,IEQUALIFIER_CONTROL
 KeyBox		Absx+ND+3,R4y,NW,KH,0,0,$62,IEQUALIFIER_CAPSLOCK
 KeyBox		R4x+00*ND,R4y,NW,KH,0,'a',$20,0
 KeyBox		R4x+01*ND,R4y,NW,KH,0,'s',$21,0
 KeyBox		R4x+02*ND,R4y,NW,KH,0,'d',$22,0
 KeyBox		R4x+03*ND,R4y,NW,KH,0,'f',$23,0
 KeyBox		R4x+04*ND,R4y,NW,KH,0,'g',$24,0
 KeyBox		R4x+05*ND,R4y,NW,KH,0,'h',$25,0
 KeyBox		R4x+06*ND,R4y,NW,KH,0,'j',$26,0
 KeyBox		R4x+07*ND,R4y,NW,KH,0,'k',$27,0
 KeyBox		R4x+08*ND,R4y,NW,KH,0,'l',$28,0
 KeyBox		R4x+09*ND,R4y,NW,KH,0,';',$29,0
 KeyBox		R4x+10*ND,R4y,NW,KH,0,"'",$2A,0
 KeyBox		Arx+1*ND,R4y,NW,KH,0,0,$4C,0		;Uparrow
 KeyBox		KPx+00*ND,R4y,NW,KH,0,'4',$2D,0
 KeyBox		KPx+01*ND,R4y,NW,KH,0,'5',$2E,0
 KeyBox		KPx+02*ND,R4y,NW,KH,0,'6',$2F,0
 KeyBox		KPx+03*ND,R4y,NW,KH,0,'+',$5E,0
 KeyBox		Absx,R5y,63,KH,0,0,$60,IEQUALIFIER_LSHIFT
 KeyBox		R5x+00*ND,R5y,NW,KH,0,'z',$31,0
 KeyBox		R5x+01*ND,R5y,NW,KH,0,'x',$32,0
 KeyBox		R5x+02*ND,R5y,NW,KH,0,'c',$33,0
 KeyBox		R5x+03*ND,R5y,NW,KH,0,'v',$34,0
 KeyBox		R5x+04*ND,R5y,NW,KH,0,'b',$35,0
 KeyBox		R5x+05*ND,R5y,NW,KH,0,'n',$36,0
 KeyBox		R5x+06*ND,R5y,NW,KH,0,'m',$37,0
 KeyBox		R5x+07*ND,R5y,NW,KH,0,$2C,$38,0		;','
 KeyBox		R5x+08*ND,R5y,NW,KH,0,'.',$39,0
 KeyBox		R5x+09*ND,R5y,NW,KH,0,'/',$3A,0
 KeyBox		R5x+10*ND,R5y,67,KH,0,0,$61,IEQUALIFIER_RSHIFT
 KeyBox		Arx+00*ND,R5y,NW,KH,0,0,$4F,0		;Leftarrow
 KeyBox		Arx+01*ND,R5y,NW,KH,0,0,$4D,0		;Downarrow
 KeyBox		Arx+02*ND,R5y,NW,KH,0,0,$4E,0		;Rightarrow
 KeyBox		KPx+00*ND,R5y,NW,KH,0,'1',$1D,0
 KeyBox		KPx+01*ND,R5y,NW,KH,0,'2',$1E,0
 KeyBox		KPx+02*ND,R5y,NW,KH,0,'3',$1F,0
 KeyBox		KPx+03*ND,R5y,NW,KH*2+3,0,0,$43,0	;Enter
 KeyBox		Absx+10,R6y,FW+2,KH,0,0,$64,IEQUALIFIER_LALT
 KeyBox		Absx+10+FD+2,R6y,FW+2,KH,0,0,$66,IEQUALIFIER_LCOMMAND
 KeyBox		100,R6y,232,KH,0,0,$40,0		;Space
 KeyBox		338,R6y,FW+2,KH,0,0,$67,IEQUALIFIER_RCOMMAND
 KeyBox		338+FD+2,R6y,FW+2,KH,0,0,$65,IEQUALIFIER_RALT
 KeyBox		KPx+00*ND,R6y,NW+ND,KH,0,'0',$0F,0	;KeyPad 0
 KeyBox		KPx+02*ND,R6y,NW,KH,0,'.',$3C,0
 KeyBox		-1,-1,-1,-1,0,0,0,0

ihs_Port	=0
ihs_Interrupt	=MP_SIZE
ihs_ID		=MP_SIZE+IS_SIZE
ihs_Length	=MP_SIZE+IS_SIZE+4
ihs_Flags	=MP_SIZE+IS_SIZE+8
ihs_PortName	=MP_SIZE+IS_SIZE+10

PWKVersionID	dc.l		'PWKF'
PWKVersionNum	dc.w		PWKeysVersion,PWKeysRevision
PWKPri		dc.b		PWKeysPri,0
		dc.w		DefFuncNumber
KeyDefines
HK1		HotKey		KP8,LAMIGA,LAMIGA,AW_TO_TOP
HK2		HotKey		KP2,LAMIGA,LAMIGA,AW_TO_BOTTOM
HK3		HotKey		KP4,LAMIGA,LAMIGA,AW_TO_LEFT
HK4		HotKey		KP6,LAMIGA,LAMIGA,AW_TO_RIGHT
HK5		HotKey		KP7,LAMIGA,LAMIGA,AW_TO_LEFT_TOP
HK6		HotKey		KP1,LAMIGA,LAMIGA,AW_TO_LEFT_BOTTOM
HK7		HotKey		KP9,LAMIGA,LAMIGA,AW_TO_RIGHT_TOP
HK8		HotKey		KP3,LAMIGA,LAMIGA,AW_TO_RIGHT_BOTTOM
HK9		HotKey		KP5,LAMIGA,LAMIGA,AW_TO_CENTER
HK10		HotKey		DOWNARROW,LAMIGA,LSHIFT|LAMIGA|RAMIGA,AW_TO_FRONT
HK11		HotKey		UPARROW,LAMIGA,LSHIFT|LAMIGA|RAMIGA,AW_TO_BACK
HK12		HotKey		LEFTARROW,LAMIGA,LAMIGA,ACTIVATE_PREV_W
HK13		HotKey		RIGHTARROW,LAMIGA,LAMIGA,ACTIVATE_NEXT_W
HK14		HotKey		DOWNARROW,LSHIFT|LAMIGA,LSHIFT|LAMIGA|RAMIGA,BACK_W_TO_FRONT
HK15		HotKey		UPARROW,LSHIFT|LAMIGA,LSHIFT|LAMIGA|RAMIGA,FRONT_W_TO_BACK
HK16		HotKey		DOWNARROW,RAMIGA,LSHIFT|LAMIGA|RAMIGA,BACK_S_TO_FRONT
HK17		HotKey		UPARROW,RAMIGA,LSHIFT|LAMIGA|RAMIGA,FRONT_S_TO_BACK
HK18		HotKey		U_CODE,U_QUAL,U_QUAL,U_FUNC
HK19		HotKey		U_CODE,U_QUAL,U_QUAL,U_FUNC
HK20		HotKey		U_CODE,U_QUAL,U_QUAL,U_FUNC

* Area to use for sorting and IO
* This is buffer when trying to read file
TempFile	dc.l		'PWKF'
		dc.w		PWKeysVersion,PWKeysRevision
		dc.b		PWKeysPri,0
TempDefined	dc.w		DefFuncNumber
TempPWKeys	dcb.b		FilePart-12

		SECTION		IMAGEDATA,DATA_C	;Image-data has to be in CHIP-RAM
Mask		dc.w		%0011001100110011
		dc.w		%1100110011001100
		dc.w		%0011001100110011
		dc.w		%1100110011001100

ArrowsData	dc.w		%0000000001100000,%0000000001111111,%1111111110000000
		dc.w		%0000000011110000,%0000000011000000,%0000000011000000
		dc.w		%0000000110011000,%0000000011000000,%0000000011000000
		dc.w		%0000001100001100,%0000000001100000,%0000000110000000
		dc.w		%0000011000000110,%0000000000110000,%0000001100000000
		dc.w		%0000110000000011,%0000000000011000,%0000011000000000
		dc.w		%0001100000000001,%1000000000001100,%0000110000000000
		dc.w		%0011000000000000,%1100000000000110,%0001100000000000
		dc.w		%0110000000000000,%0110000000000011,%0011000000000000
		dc.w		%0110000000000000,%0110000000000001,%1110000000000000
		dc.w		%0011111111111111,%1100000000000000,%1100000000000000
		END

