;*******************************************************************************
; Director - ModuleHead
;
; Copyright (C) 2003, Nick Craig-Wood and Philip Ludlam
;
;This program is free software; you can redistribute it and/or modify it under
;the terms of the GNU General Public License as published by the Free Software
;Foundation; either version 2 of the License, or (at your option) any later
;version.
;
;This program is distributed in the hope that it will be useful, but WITHOUT ANY
;WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
;PARTICULAR PURPOSE. See the GNU General Public License for more details.
;
;You should have received a copy of the GNU General Public License along with
;this program; if not, write to the Free Software Foundation, Inc., 59 Temple
;Place - Suite 330, Boston, MA 02111-1307, USA
;
;*******************************************************************************
;----h- Director.s.ModuleHead
; Name
;   ModuleHead
;
; Purpose
;   ModuleHead
;------
;*******************************************************************************


		TTL	> ModuleHead

		GET	OSLib:oslib.hdr.Wimp
		GET	OSLib:oslib.hdr.OS
		GET	OSLib:oslib.hdr.OSModule
		GET	OSLib:oslib.hdr.Filter
		GET	AsmLib2:hdr.RegsBoth
		GET	AsmLib2:hdr.MacrosBoth
		GET	h.WorkSpace
		GET	h.Constants
		GET	h.ListMacros
		GET	h.Memory
		GET	h.Task
		GET	h.Messages
		GET	h.ModuleTail
		GET	h.Version
		GET	h.Filter
		GET	h.Sort
		GET	h.URL

		AREA	|!!!Module$$Header|, CODE, READONLY

		ENTRY
Module_BaseAddr
		DCD	Enter
		DCD	Initialise
		DCD	Finalise
		DCD	Service
		DCD	Title
		DCD	Help
		DCD	StarCommands
		DCD	SwiChunk
		DCD	SwiHandler
		DCD	SwiNames
		DCD	SwiNameDecoder
		[	OSVersion /= 310
		DCD	MessageTrans			; for MessageTrans file
		DCD	ModuleFlags

MessageTrans	DCB	"<Director$Resources>Messages", 0
		ALIGN

ModuleFlags	DCD	1
		]

SwiNameDecoder	EQU	0

Title		FOREXPORT
		DCB	"$Name", 0
		ALIGN

		MACRO
$label		AddStar0	$name, $min, $max, $GST
;$label		AddStar0	$name, $min, $max, $GST, $flags
		IMPORT		Help_$name
		IMPORT		Syntax_$name
		IMPORT		Star_$name
		[	OSVersion = 310
$label		AddStar_	"$name", "$min", "$max", "$GST"
		|
$label		AddStar_	"$name", "$min", "$max", "$GST", "16"
		]
		MEND

StarCommands
StartUpName
		AddStar0	"DeskTop_$Name", 0, 0
;		AddStar0	"$Name.Memory", 0, 0
		AddStar0	"$Name.Obey", 1, 255
		AddStar0	"$Name.Do", 0, 255
		AddStar0	"Menu", 1, 255
		AddStar0	"EndMenu", 0, 255
		AddStar0	"Option", 1, 255
		AddStar0	"Dash", 0, 0
		AddStar0	"Command", 1, 255
		AddStar0	"MenuProcessing", 1, 1
;		AddStar0	"ListMenus", 0, 0
		AddStar0	"$Name.Icon", 1, 255
		AddStar0	"MemoriserItems", 1, 255
		AddStar0	"ProcessKeys", 0, 255
		AddStar0	"$Name.Edit", 1, 255
		AddStar0	"$Name.ParsePath", 1, 1
		AddStar0	"$Name.MouseDir", 1, 255
		AddStar0	"MemoriserSave", 1, 1
		AddStar0	"MemoriserLoad", 1, 1
		AddStar0	"$Name.ShowMenu", 1, 255
		AddStar0	"$Name.Filter", 1, 255
		AddStar0	"$Name.SortMenu", 1, 255
		AddStar0	"$Name.Window", 1, 255
		AddStar0	"MemoriserClear", 0, 0
		AddStar0	"$Name.URL", 1, 255
		AddStar0	"$Name.Options", 1, 255
		AddStar0	"$Name.FilerFilter", 1, 255
		DCD		0			; end of table


;*******************************************************************************
;----f- Director.s.ModuleHead.InitialRegs
; Name
;   InitialRegs
;
; Purpose
;   This is the Initialise Module entry point
;   It reserves memory from the RMA for workspace variables
;   IRQs are enabled, FIQs are enabled
;   It may corrupt r0-r6, wp, lr, and the flags (error is returned in v)
;   It must preserve r7-r11, sp, processor mode, IRQ, FIQ
;
; Entry
;
;
; Exit
;
;------
;*******************************************************************************


		GBLS	InitialRegs
InitialRegs	SETS	"r7-r11, lr"

Initialise	DOSIGNATURE
		STMFD	sp!, {$InitialRegs}

		ADRL	r0, ModuleEnd			; r0 = end address of module
		MOV	r3, #1
		ADD	r2, r0, #2			; include CRC in check
		ADRL	r1, Module_BaseAddr
		MOV	r6, r1				; r6 = pointer to the start of module
		MOV	r0, #0
		SWI	XOS_CRC				; r0 = CRC of the module code
		BVS	InitialError
		TEQ	r0, #0				; If CRC <> 0 then is bad
		BNE	Corrupted

		MOV	r0, #OSModule_Alloc
		LDR	r3, =WorkSpaceSize
		SWI	XOS_Module			; reserve RMA space for module
		BVS	InitialError

		MOV	r5, wp				; r5 = private word pointer
		STR	r2, [wp]			; store pointer to workspace
		MOV	wp, r2				; set workspace pointer

		MOV	r0, wp
		LDR	r1, =WorkSpaceSize
		BL	memclear			; clear the workspace

		STR	r5, PrivateWord			; store the address of the private
		STR	r6, StartModule			; store the start of the module

		LDMFD	sp!, {$InitialRegs}
		SaveRegs

		BL	MemoryInitialise
		BVS	ErrorReturn

		RestoreRegs	r0
		MOV	pc, lr				; return with no error

		; This deals with errors in initialise where we don't have ErrorReturn
		; set up because we have no workspace

Corrupted	ADR	r0, ErrCorrupted
		SetV
InitialError	LDMFD	sp!, {$InitialRegs}
		MOV	pc, lr				; return with an error

		; Embed the error text as MessageTrans hasn't been setup
ErrCorrupted	DCD	ErrorBase + Error_ModuleCorrupted
		DCB	"Module has become corrupted.", 0
		ALIGN

		LTORG


;*******************************************************************************
;----f- Director.s.ModuleHead.Finalise
; Name
;   Finalise
;
; Purpose
;   This is the Finalise Module entry point
;   IRQs are as called, FIQs are enabled
;   It may corrupt r0-r6, wp, lr, and the flags (error is returned in v)
;   It must preserve r7-r11, sp, processor mode, IRQ, FIQ
;
; Entry
;
;
; Exit
;
;------
;*******************************************************************************


Finalise	DOSIGNATURE

		ModuleVeneer

		BL	TaskShutDown
		BL	MemoryFinalise

		LDR	r0, MallocBlocks
		CMP	r0, #0
		BEQ	ok$l
		ADD     r0, r0, #48			; This will only work nicely
		SWI	XOS_WriteC			; if there are less than 10
		SWI	XOS_WriteS			; blocks not freed.
		DCB	" heap block(s) not freed", 7, 10, 13, 0
		ALIGN
ok$l

		RestoreRegs	r0			; restore registers before releasing workspace
		MOV	r4, lr				; preserve lr
		MOV	r0, #OSModule_Free		; Release main workspace
		MOV	r2, wp
		SWI	XOS_Module			; ignore errors
		ClearV
		MOV	pc, r4				; return with no error

;*******************************************************************************
;----f- Director.s.ModuleHead.SwiNames
; Name
;   SwiNames
;
; Purpose
;   Here are all the SWIs that the module provides
;
; Entry
;
;
; Exit
;
;------
;*******************************************************************************

SwiNames
		SWIInit	"$Name"

		AddSWI	"Menu"
		AddSWI	"EndMenu"
		AddSWI	"Option"
		AddSWI	"Dash"
		AddSWI	"Command"
		AddSWI	"Enumerate"
		AddSWI	"Memory"
		AddSWI	"QuickSort"
		AddSWI	"SortMenu"

		SWIEnd


;*******************************************************************************
;----f- Director.s.ModuleHead.SwiHandler
; Name
;   SwiHandler
;
; Purpose
;   This is the SWI Handler Module entry point
;
; Entry
;   r11 = Swi number modulo 64
;   wp = private word pointer
;   sp = supervisor stack
;   lr = contains flags of the Swi caller
;   IRQs are disabled, FIQs are enabled
;
; Exit
;   It may corrupt r0-r11, wp, and the flags (error is returned in v)
;------
;*******************************************************************************


SwiHandler	CMP	r11, #SwiN
		ADDCC	pc, pc, r11, LSL #2
		B	UnknownSwi

		GBLA	i
		GBLS	t
		[	SwiN > 0
			WHILE	i<SwiN
t				SETS	swi$i
				B	Star_$t
i				SETA	i+1
			WEND
		]

UnknownSwi	ADR	r0, ErrorUnknownSWI
		SetV
		MOV	pc, lr

ErrorUnknownSWI	ERROR	"Unknown SWI", Error_NoSuchSWI

; This returns from an unstructured error, popping the return stack
; to it's call level, and getting the return address from the
; workspace.  It assumes that r0 points to an error block.

ErrorReturnMT	FOREXPORT
		BL	MessageErrorLookup

ErrorReturn	FOREXPORT
		RestoreRegs	r1
		SetV
		MOV	pc, lr

NormalReturn	FOREXPORT
		RestoreRegs	r0
		ClearV
		MOV	pc, lr


;*******************************************************************************
;----f- Director.s.ModuleHead.Service
; Name
;   Service
;
; Purpose
;   Service call entry
;
; Entry
;
;
; Exit
;
;------
;*******************************************************************************

		[	OSVersion /= 310
		; RISC OS 4 module service
ServiceTable	DOSIGNATURE
		DCD	0
		DCD	ServiceDo
		DCD	Service_FilterManagerInstalled	; &87
		DCD	Service_FilterManagerDying	; &88
		DCD	Service_SyntaxError		; &8C
		DCD	0

		DCD	ServiceTable

Service		MOV	r0, r0				; RISC OS 4 module service table
		|
Service		DOSIGNATURE
		]

		TEQ	r1, #Service_FilterManagerInstalled ; &87
		TEQNE	r1, #Service_FilterManagerDying	; &88
		[	OSVersion /= 310
		TEQNE	r1, #Service_SyntaxError	; &8C
		]
		MOVNE	pc, lr

		[	OSVersion /= 310
ServiceDo	TEQ	r1, #Service_SyntaxError	; &8C
		BEQ	DoSyntaxError
		|
ServiceDo
		]

		ROUTINE	"r0-r1, wp",,, NOSIGNATURE

		LDR	wp, [r12]			; get workspace pointer

		TEQ	r1, #Service_FilterManagerInstalled ; &87
		TEQNE	r1, #Service_FilterManagerDying	; &88
		MOVEQ	r0, #0
		STREQ	r0, FiltersRunning		; show no filters running

		TEQ	r1, #Service_FilterManagerInstalled
		BLEQ	FilterInitialiseFilters		; start the filters off

		EXIT

		[	OSVersion /= 310
; If it's us
;   make r0 on the stack  Error_Block
;   make r1 on stack = 0 (we've claimed it)

DoSyntaxError	ROUTINE	"r2-r5, wp"
		LDR	wp, [r12]			; get workspace pointer
		ADRL	r5, Module_BaseAddr
		CMP	r5, r3
		BNE	exit$l				; It's not us.

		LDR	r0, [r2, #8]			; r0 = offset within module
		ADD	r0, r0, r5			; r0 = absolute address
		BL	MessageLookupAddr
		ADR	r1, Error_Block+4
		BL	PrettyTrans
		ADR	r0, Error_Block
		MOV	r1, #0
		STR	r1, Error_Block
exit$l		EXIT


; r1  output
; r0  input
PrettyTrans	ROUTINE

		LDR	r2, =StringSize - 1 - 4		; max bytes to transfer

loop$l		LDRB	r3, [r0], #1
		CMP	r3, #&1F
		MOVEQ	r3, #160			; #31 -> hard space
		CMP	r3, #&0D
		MOVEQ	r3, #32				; CR -> space
		STRB	r3, [r1], #1
		CMP	r3, #10				; end of line?
		BEQ	exit$l				; yes, exit
		SUBS	r2, r2, #1			; can't output anymore?
		BNE	loop$l				; no, loop
		MOV	r0, #0				; terminate
		STR	r0, [r1]
		BLE	loop$l
exit$l		EXIT

		]


;*******************************************************************************
;----f- Director.s.ModuleHead.Enter
; Name
;   Enter
;
; Purpose
;   Jump to the Filer start routine on language entry
;
; Entry
;
;
; Exit
;
;------
;*******************************************************************************


Enter		B	TaskStart


;*******************************************************************************
;This enumerates a list
;
;Entry
;	r0 = pointer to block or to start
;		0 = stored menus
;		1 = displayed menus
;		2 = icons
;		3 = filters
;		4 = windows
;Exit
;	r0 = new pointer to block (0 for end)
;	r1  name of block
;*******************************************************************************


Star_Enumerate	FOREXPORT
		LDR	wp, [r12]
		SaveRegs
		ROUTINE	NONE

		CMP	r0, #5
		ADRLO	lr, MenuStoredAnchor
		ADDLO	r0, lr, r0, LSL#2

		ListWalk	r0, lr
		MOVEQ	r0, #0
                LDRNE	r1, [r0, #4]			; get pointer to name

		TEQ	r1, #0
		ADREQ	r1, UnNamed			; point to no name if 0

		RestoreRegs	r2
		ClearV
		MOV	pc, lr				; return with r0, r1

UnNamed		DCB	"[NoName]", 0
		ALIGN


;*******************************************************************************

		END
