; ShiftResize module, written by Vincent Lefvre
; Freeware.

; $Id: sresize 3.0 2003/05/25 11:29:17 vlefevre Exp $

		GET	h:RegNames
		GET	h:SWINames
		GET	h:RCSsupport

		GETVERS	"$Revision: 3.0 $"
		GETDATE	"$Date: 2003/05/25 11:29:17 $"

		GBLS	NAME
NAME		SETS	"ShiftResize"
		GBLS	AUTHOR
AUTHOR		SETS	"Vincent Lefvre"
		GBLS	VERSION
VERSION		SETS	VERS:CC:" (":CC:DATE:CC:")"

IBTOP		EQU	116	;Top of the icon bar.

		^	0
		#	4	;Task handle or 0.
FREG		#	4	;Filter routine or 0.
BUFFER		#	256	;Buffer.
SIZE		#	0	;--> size of workspace.

Service_FMI	EQU	&87	;Service: Filter Manager Installed.
Service_FMD	EQU	&88	;Service: Filter Manager Dying.

TaskInitialise	EQU	&400C2	;Message: TaskInitialise.

		AREA	ShiftResize, CODE, PIC, READONLY
		ENTRY

BaseAddr	DCD	RM_Start  -BaseAddr
		DCD	RM_Init   -BaseAddr
		DCD	RM_Die    -BaseAddr
		DCD	RM_Service-BaseAddr
		DCD	RM_Title  -BaseAddr
		DCD	RM_Help   -BaseAddr
		DCD	RM_HCtable-BaseAddr
		DCD	0,0,0,0,0
		DCD	RM_Flags  -BaseAddr

RM_Flags	DCD	1		;32-bit compatible.

task		DCB	"TASK"

RM_Help		DCB	NAME,9,VERSION," by ",AUTHOR,0

Help_Desktop	DCB	"Do not use *",27,0,", use *Desktop instead.",0
Help_RBreset	DCB	"*",27,0," re",27,19,"toggle-size CMOS bit.",0
Help_RBset	DCB	"*",27,0," ",27,19,"toggle-size CMOS bit.",0

		ALIGN

RM_HCtable	DCB	"Desktop_"
RM_Title	DCB	NAME,0
		ALIGN
		DCD	Desktop-BaseAddr,0,0,Help_Desktop-BaseAddr

		DCB	"ResizeBit_Reset",0
		ALIGN
		DCD	RBreset-BaseAddr,0,0,Help_RBreset-BaseAddr

		DCB	"ResizeBit_Set",0
		ALIGN
		DCD	RBset-BaseAddr,0,0,Help_RBset-BaseAddr

; Note: zero byte follows.

ServiceTable	DCD	0, RM_FastServ-BaseAddr, Service_FMI, Service_FMD, 0
messages	DCD	TaskInitialise, 0

Desktop		MOV	R6, LR
		MOV	R2, R0
		ADR	R1, RM_Title
		MOV	R0, #2
		SWI	XOS_Module	;Enter ShiftResize.
		MOV	PC, R6

RM_Start	LDR	R6, [R12]	;Pointer to workspace.
		LDR	R0, [R6]	;Task handle or 0.
		LDR	R1, task	;"TASK".
		TEQ	R0, #0
		BEQ	start2
		SWI	Wimp_CloseDown
		MOV	R0, #0
		STR	R0, [R6]	;Reset task handle.
start2		MOV	R0, #300	;Last Wimp version known: 3.00.
		ADR	R2, RM_Title
		ADR	R3, messages	;List of the accepted user messages.
		SWI	XWimp_Initialise
		ADRVS	R3, RM_Title
		SWIVS	OS_ExitAndDie
		STR	R1, [R6]	;Store task handle.
loop0		ADR	R3, RM_Title	;Module title for OS_ExitAndDie...
loop		MOV	R0, #&31	;Mask = &3831.
		ORR	R0, R0, #&3800
		ADD	R1, R6, #BUFFER	;256-byte buffer for Wimp_Poll.
		SWI	XWimp_Poll
		SWIVS	OS_ExitAndDie
		TEQ	R0, #17		;UserMessage?
		TEQNE	R0, #18		;UserMessage_Recorded?
		BNE	loop		;No, loop.
		LDR	R0, [R1, #16]	;Message code.
		TEQ	R0, #0		;Quit?
		SWIEQ	OS_ExitAndDie	;Die if quit.
		SUB	R0, R0, #&40000
		TEQ	R0, #&C2	;TaskInitialise?
		BNE	loop		;No, loop.
		LDR	R1, [R6, #FREG]	;Filter routine or 0.
		MOV	R2, R6
		TEQ	R1, #0		;Filter registered?
		BEQ	loop		;No, loop.
		BL	params2		;Reregister because of the toolbox...
		SWI	XFilter_DeRegisterPostFilter
		BVS	loop0		;Loop if can't deregister.
		SWI	XFilter_RegisterPostFilter
		MOVVS	R1, #0
		STRVS	R1, [R2, #FREG]
		B	loop0

params1		ADR	R1, filter	;Filter routine.
params2		ADR	R0, RM_Title	;Filter name.
		MOV	R3, #0		;Apply filter to all tasks.
		MVN	R4, #1<<2	;Event mask: Open Window Request.
		MOV	PC, LR		;Return.

RM_Init		LDR	R2, [R12]	;Pointer to workspace or 0.
		MOV	R6, LR
		TEQ	R2, #0
		BNE	init2
		MOV	R0, #6		;Executed unless re-init.
		MOV	R3, #SIZE
		SWI	XOS_Module	;Claim.
		MOVVS	PC, R6		;Return with V=1 if not enough memory.
		STR	R2, [R12]	;Pointer to workspace.
init2		BL	params1
		SWI	XFilter_RegisterPostFilter
		MOVVS	R1, #0		;R1 = 0 if error (FM not present?).
		STR	R1, [R2, #FREG]
		SUBS	R0, R0, R0	;R0 = 0 and clear V flag.
		STR	R0, [R2]	;Reset task handle.
		MOV	PC, R6		;Return with no error.

RM_Die		LDR	R2, [R12]	;Pointer to workspace.
		MOV	R6, LR
		LDR	R1, [R2, #FREG]	;Filter routine or 0.
		BL	params2
		CMP	R1, #0		;Filter registered?
		SWINE	XFilter_DeRegisterPostFilter
		MOVVS	PC, R6		;Return with V=1 if can't deregister.
		LDR	R0, [R2]	;Task handle or 0.
		TEQ	R0, #0
		LDRNE	R1, task	;"TASK".
		SWINE	XWimp_CloseDown
		MOV	PC, R6

		DCD	ServiceTable-BaseAddr
RM_Service	MOV	R0, R0		;Magic instruction for Ursula kernel.
		TEQ	R1, #Service_FMI
		TEQNE	R1, #Service_FMD
		MOVNE	PC, LR		;Return if neither FMI nor FMD.
RM_FastServ	TEQ	R1, #Service_FMI
		BEQ	FM_Installed
FM_Dying	STMFD	SP!, {R2,LR}	;Filter Manager Dying.
		LDR	R2, [R12]
		MOV	R14, #0
		STR	R14, [R2, #FREG]
		LDMFD	SP!, {R2,PC}
FM_Installed	STMFD	SP!, {R0-R4,LR}	;Filter Manager Installed.
		LDR	R2, [R12]	;Pointer to workspace.
		BL	params1
		SWI	XFilter_RegisterPostFilter
		MOVVS	R1, #0		;R1 = 0 if error.
		STR	R1, [R2, #FREG]
		LDMFD	SP!, {R0-R4,PC}

filter		STMFD	SP!, {R0-R8,LR}	;Filter routine...
		MOV	R8, R1		;R8: OpenWindow block.
		MOV	R0, #161
		MOV	R1, #28
		SWI	XOS_Byte
		LDMVSFD	SP!, {R0-R8,PC}
		AND	R3, R2, #1<<4	;Shift toggle size bit.
		MOV	R0, #202
		MOV	R1, #0
		MOV	R2, #255
		SWI	XOS_Byte
		LDMVSFD	SP!, {R0-R8,PC}
		AND	R1, R1, #1<<3	;Shift status.
		TEQ	R3, R1, LSL #1
		LDMEQFD	SP!, {R0-R8,PC}	;Return if icon bar may be obscured.
		LDMIA	R8, {R0,R2-R5}	;Window handle and new coordinates.
		ADD	R1, R12, #BUFFER
		SUB	R6, R4, R2	;R6 = new X-size.
		SUB	R7, R5, R3	;R7 = new Y-size.
		STR	R0, [R1]
		SWI	XWimp_GetWindowState
		LDMVSFD	SP!, {R0-R8,PC}
		LDR	R0, [R1, #32]	;Window flags.
		TST	R0, #1<<16
		LDMEQFD	SP!, {R0-R8,PC}	;Return if window is not open.
		TST	R0, #1<<19
		LDMNEFD	SP!, {R0-R8,PC}	;Return if caused by toggle size.
		LDMIA	R1, {R0,R2-R5}	;Window handle and old coordinates.
		SUB	R4, R4, R2	;R4 = old X-size.
		SUB	R0, R5, R3	;R0 = old Y-size.
		TEQ	R4, R6
		TEQEQ	R0, R7
		LDMEQFD	SP!, {R0-R8,PC}	;Return if window is not resized.
		SWI	XWimp_GetWindowOutline
		LDMVSFD	SP!, {R0-R8,PC}
		LDR	R0, [R1, #8]	;Minimum Y of the bounding box.
		ADD	R6, R3, #IBTOP
		LDR	R2, [R8, #8]	;New minimum Y.
		SUB	R6, R6, R0	;Upper bound for minimum Y.
		CMP	R2, R6
		LDMGEFD	SP!, {R0-R8,PC}	;Return if icon bar not obscured.
		LDR	R0, [R1, #16]	;Maximum Y of the bounding box.
		STR	R6, [R8, #8]	;Update new minimum Y.
		SUB	R5, R5, R0
		MOV	R0, #-1
		MOV	R1, #12
		SWI	XOS_ReadModeVariable
		ADD	R3, R2, #1	;Y-resolution in pixels.
		MOV	R1, #5
		SWI	XOS_ReadModeVariable
		ADD	R5, R5, R3, LSL R2 ;Lower bound for maximum Y.
		ADD	R7, R7, R6
		CMP	R5, R7		;Update new maximum Y...
		STRLT	R5, [R8, #16]
		STRGE	R7, [R8, #16]
		LDMFD	SP!, {R0-R8,PC}

RBreset		MOV	R6, LR
		MOV	R0, #161
		MOV	R1, #28
		SWI	XOS_Byte	;Read the CMOS memory, byte 28.
		BICVC	R2, R2, #1<<4	;Clear bit 4.
		MOVVC	R0, #162
		SWIVC	XOS_Byte	;Write to the CMOS memory, byte 28.
		MOV	PC, R6

RBset		MOV	R6, LR
		MOV	R0, #161
		MOV	R1, #28
		SWI	XOS_Byte	;Read the CMOS memory, byte 28.
		ORRVC	R2, R2, #1<<4	;Set bit 4.
		MOVVC	R0, #162
		SWIVC	XOS_Byte	;Write to the CMOS memory, byte 28.
		MOV	PC, R6

		END
