; Copyright 1996 Acorn Computers Ltd
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
;     http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;
; > Sources.Module
        LEADR   Module_LoadAddr

        ASSERT  (.=Module_BaseAddr)

        DCD     Mod_Start               - Module_BaseAddr
        DCD     Mod_Init                - Module_BaseAddr
        DCD     Mod_Die                 - Module_BaseAddr
        DCD     Mod_Service             - Module_BaseAddr
        DCD     Mod_Title               - Module_BaseAddr
        DCD     Mod_Helpstr             - Module_BaseAddr
        DCD     Mod_Helptable           - Module_BaseAddr
        DCD     0
        DCD     0
        DCD     0
        DCD     0
 [ International_Help <> 0
        DCD     MsgTrans_FileName       - Module_BaseAddr
 |
        DCD     0
 ]

;---------------------------------------------------------------------------
Mod_Helptable
displaymanager_command
        Command Desktop_DisplayManager,0,0,International_Help
        DCB     0

 [ International_Help = 0
Desktop_DisplayManager_Help
        DCB     "The Display Manager module allows the selection of screen modes."
        DCB     13,10
        DCB     "Do not use *Desktop_DisplayManager, use *Desktop instead."
        DCB     0
Desktop_DisplayManager_Syntax
        DCB     "Syntax: *Desktop_"     ; Drop through to...
 |
Desktop_DisplayManager_Help
        DCB     "HDPMDSK",0
Desktop_DisplayManager_Syntax
        DCB     "SDPMDSK",0
 ]

Mod_Title       DCB     "DisplayManager",0
Mod_Helpstr     DCB     "DisplayManager",9
Mod_Version     DCB     "$VString ($Date)",0
                ALIGN


;---------------------------------------------------------------------------
;       Code to handle *Desktop_DisplayManager command.
;
Desktop_DisplayManager_Code
        ROUT
        ENTRY

        LDR     lr, [r12]
        CMP     lr, #0                  ; If not had Service_StartWimp or couldn't get workspace then
        BLE     %FT10                   ;   can't start up.

        LDR     lr, [lr, #:INDEX:task_handle]
        TEQ     lr, #0                  ; If we're not already a task then
        MOVEQ   r2, r0                  ;   start up as one.
        MOVEQ   r0, #ModHandReason_Enter
        ADREQ   r1, Mod_Title
        SWIEQ   XOS_Module
10
        ADR     r0, ErrorBlock_Modes_CantStart  ; Otherwise, can't start up.
        MOV     r1, #0
        MOV     r2, #0
        ADR     r4, Mod_Title
        MOV     r5, #0
        MOV     r6, #0
        MOV     r7, #0
        SWI     XMessageTrans_ErrorLookup

        EXIT

        MakeErrorBlock  Modes_CantStart


;---------------------------------------------------------------------------
;       Module initialisation.
;
Mod_Init
        ENTRY   "r1-r4"

 [ standalone
        Debug   mod,"Mod_Init"
        ADRL    r0, resourcefs_files
        SWI     XResourceFS_RegisterFiles
        EXIT    VS
 ]

        ADR     r0, Mod_Path
        MOV     r2, #-1
        MOV     r3, #0
        MOV     r4, #VarType_Expanded
        SWI     XOS_ReadVarVal
        CMP     r2, #0

        ADREQ   r0, Mod_Path
        ADREQ   r1, Mod_PathDefault
        MOVEQ   r2, #?Mod_PathDefault
        MOVEQ   r3, #0
        MOVEQ   r4, #VarType_String
        SWIEQ   XOS_SetVarVal

        EXIT

Mod_Path        DCB     "DisplayManager$Path",0
Mod_PathDefault DCB     "Resources:$.Resources.Display.",0
                ALIGN


;---------------------------------------------------------------------------
;       Service call handler.
;
Mod_Service
        TEQ     r1, #Service_StartWimp
        BEQ     svc_startwimp

        TEQ     r1, #Service_StartedWimp
        BEQ     svc_startedwimp

        TEQ     r1, #Service_Reset
        BEQ     svc_reset

        LDR     r12, [r12]              ; Make sure we have workspace for the following services.
        CMP     r12, #0
        MOVLES  pc, lr

        TEQ     r1, #Service_ModeChange
        BEQ     svc_modechange

        TEQ     r1, #Service_WimpPalette
        TEQNE   r1, #Service_CalibrationChanged
        BEQ     svc_wimppalette

        TEQ     r1, #Service_ModeFileChanged
        BEQ     svc_modefilechanged

 [ standalone
        TEQ     r1, #Service_ResourceFSStarting
        BEQ     svc_resourcefsstarting
 ]

        TEQ     r1, #Service_MessageFileClosed
        MOVNES  pc, lr


svc_messagefileclosed
        ENTRY   "r0"
        Debug   mod,"svc_messagefileclosed",r0
        LDR     lr, task_handle         ; Make sure we are a task.
        TEQ     lr, #0
        EXITS   EQ
 [ {FALSE}
        ; We don't actually have to re-open the message file using
        ; MessageTrans_OpenFile as it says in the PRM.  MessageTrans
        ; remembers the file block and will open the file for us when
        ; we next try to access it.
        LDRB    lr, flags
        BIC     lr, lr, #f_messagesopen
        STRB    lr, flags
 ]
        BL      Menu_Init               ; Re-open messages file and build all menus.
        LDRVC   lr, pollword
        ORRVC   lr, lr, #pf_modeinit :OR: pf_refreshicons
        STRVC   lr, pollword
        EXIT


svc_reset
        ENTRY   "r0-r3"

        Debug   mod,"Service_Reset"

        LDR     lr, [r12]
        CMP     lr, #0                  ; If couldn't get workspace on Service_StartWimp then
        MOVLT   lr, #0                  ;   clear flag so user can retry.
        STRLT   lr, [r12]

        MOVGT   r12, lr                 ; Otherwise, if we have workspace then
        MOVGT   lr, #0                  ;   free it (but don't call Wimp_CloseDown).
        STRGT   lr, task_handle
        BLGT    Mod_ShutDown

        EXITS


svc_startwimp
        ENTRY   "r2,r3"

        LDR     r2, [r12]
        TEQ     r2, #0
        EXITS   NE                      ; Don't claim service unless = 0.

        Debug   mod,"Service_StartWimp"

        MOV     r0, #ModHandReason_Claim        ; Try to claim workspace.
        LDR     r3, =max_running_work
        SWI     XOS_Module
        MOVVS   r2, #-1                 ; Avoid looping.
        STR     r2, [r12]

        Debug   mod," workspace at",r2

        MOVVC   r0, #0
        STRVC   r0, [r2, #:INDEX:task_handle]
        STRVC   r0, [r2, #:INDEX:indirected_data]
        STRVC   r0, [r2, #:INDEX:mode_space]
        STRVCB  r0, [r2, #:INDEX:flags]
        STRVC   r12, [r2, #:INDEX:private_word]
        ADRVC   r0, displaymanager_command

        MOVVC   r1, #0                  ; Claim service.
        EXITS


svc_startedwimp
        ENTRY

        Debug   mod,"Service_StartedWimp"

        LDR     lr, [r12]
        CMP     lr, #-1                 ; If failed to get workspace then
        MOVEQ   lr, #0                  ;   clear flag so user can try again.
        STREQ   lr, [r12]

        EXITS


svc_wimppalette
        ENTRY   "r0-r3"

        Debug   mod,"svc_wimppalette"
        LDR     lr, task_handle         ; Make sure we are a task.
        TEQ     lr, #0
        EXIT    EQ

        LDR     lr, pollword
        ORR     lr, lr, #pf_modeinit :OR: pf_refreshicons
        STR     lr, pollword

        SWI     XColourTrans_InvalidateCache
        BL      scanpalette
        MOVNE   r0, #-1                 ; Force redraw whole screen if wimp palette changed.
        MOVNE   r1, #-bignum
        MOVNE   r2, #-bignum
        MOVNE   r3, #bignum
        MOVNE   r4, #bignum
        SWINE   XWimp_ForceRedraw

        ASSERT  ms_data = 5*4           ; Send message like Palette utility used to.
        MOV     r0, #ms_data
        MOV     r3, #0
        MOV     lr, #Message_PaletteChange
        Push    "r0-r3,lr"
        MOV     r0, #User_Message
        MOV     r1, sp
        MOV     r2, #0
        SWI     XWimp_SendMessage
        ADD     sp, sp, #ms_data

        EXIT


scanpalette
        ENTRY   "r0-r4",80

        MOV     r1, sp                  ; Dump new palette into stack frame.
        SWI     XWimp_ReadPalette

        ADR     r0, wimp_palette        ; Compare against old palette.
        MOV     lr, #16
        MOV     r4, #0
10
        LDRB    r2, [r0]                ; Only bottom 8 bits stored.
        LDR     r3, [r1], #4
        STRB    r3, [r0], #1            ; Update current palette.
        EOR     r3, r3, r2
        ORR     r4, r4, r3, LSL #24     ; Only interested in bottom 8 bits.
        SUBS    lr, lr, #1
        BNE     %BT10

        TEQ     r4, #0                  ; EQ=>same, NE=>changed
        EXIT


svc_modechange
        ENTRY
        Debug   mod,"svc_modechange"
        LDR     lr, task_handle         ; Make sure we are a task.
        TEQ     lr, #0
        LDRNE   lr, pollword
        ORRNE   lr, lr, #pf_modeinit :OR: pf_refreshicons
        STRNE   lr, pollword
        EXIT


svc_modefilechanged
        ENTRY   "r0"
        Debug   mod,"svc_modefilechanged"
        LDR     lr, task_handle         ; Make sure we are a task.
        TEQ     lr, #0
        EXITS   EQ
        BL      Menu_Init               ; Build menus.
        LDR     lr, pollword
        ORR     lr, lr, #pf_modeinit :OR: pf_refreshicons :OR: pf_settitle
        STR     lr, pollword
        EXITS


 [ standalone
svc_resourcefsstarting
        ENTRY   "r0"
        ADRL    r0, resourcefs_files
        MOV     lr, pc
        MOV     pc, r2
        EXITS
 ]


;---------------------------------------------------------------------------
;       Killing the module.
;
Mod_Die
        ENTRY   "r0-r3"

        LDR     r12, [r12]
        BL      Mod_ShutDown

 [ standalone
        ADRL    r0, resourcefs_files
        SWI     XResourceFS_DeregisterFiles
 ]

        EXITS


;---------------------------------------------------------------------------
; Mod_ShutDown
;
;       In:     r12 -> workspace
;       Out:    r0-r3 corrupted
;               r12 -> private word
;
;       Shut down as a task or before dying.
;
Mod_ShutDown
        CMP     r12, #0                 ; If no workspace then
        MOVLE   pc, lr                  ;   nothing to do.

        Debug   mod,"Mod_ShutDown, workspace at",r12

        MOV     r3, lr                  ; Can't use stack on exit if USR mode.

        Debug   mod," closing down as a task"
        LDR     r0, task_handle
        CMP     r0, #0                  ; If we're running as a task then
        LDRGT   r1, task_identifier     ;   close down and ignore errors.
        SWIGT   XWimp_CloseDown

        Debug   mod," closing message file"
        LDRB    r0, flags               ; Close messages if open.
        TST     r0, #f_messagesopen
        ADRNE   r0, message_file_block
        SWINE   XMessageTrans_CloseFile

        Debug   mod," freeing indirect data"
        MOV     r0, #ModHandReason_Free ; Free indirected window data if we have it.
        LDR     r2, indirected_data
        TEQ     r2, #0
        SWINE   XOS_Module

        Debug   mod," freeing mode data"
        LDR     r2, mode_space          ; Free mode related data if we have it.
        TEQ     r2, #0
        SWINE   XOS_Module

        Debug   mod," freeing workspace"
        MOV     r2, r12                 ; Free workspace and zero private word.
        LDR     r12, private_word
        MOV     lr, #0
        STR     lr, [r12]
        SWI     XOS_Module

        Debug   mod," exiting to",r3
        MOV     pc, r3


;---------------------------------------------------------------------------
;       Start module as a Wimp task.
;
Mod_Start
        LDR     r12, [r12]              ; Get workspace pointer.
        CMP     r12, #0

        ADRLEL  r0, ErrorBlock_Modes_CantStart
        MOVLE   r1, #0
        MOVLE   r2, #0
        ADRLEL  r4, Mod_Title
        MOVLE   r5, #0
        MOVLE   r6, #0
        MOVLE   r7, #0
        SWILE   MessageTrans_ErrorLookup

        LDR     lr, task_handle
        CMP     lr, #0
        SWIGT   OS_GenerateError

        ADR     sp, stack_top           ; STACK IS NOW VALID!!

        Debug   mod,"Mod_Start"

        SUB     sp, sp, #max_banner_size        ; Look up banner for task display.
        ADR     r1, banner
        MOV     r2, sp
        MOV     r3, #max_banner_size
        BL      MsgTrans_Lookup
        SWIVS   OS_GenerateError

        MOV     r0, #300                ; Start up as Wimp task.
        LDR     r1, task_identifier
        ADR     r3, messages_list
        SWI     Wimp_Initialise

        ADD     sp, sp, #max_banner_size

        CMP     r0, #300                ; Make sure were running on RISC OS 3.
        BCC     error_old_wimp

        STR     r1, task_handle         ; Store task handle and initialise loads of stuff.
        BL      Icon_Init
        BLVC    Window_Init
        BLVC    Menu_Init
        BLVC    Mode_Init
        BVS     error_abort

        MOV     r0, #-1                 ; Remaining initialisation.
        STR     r0, scrap_ref
        MOV     r0, #0
        STR     r0, pollword

repoll_wimp
        Debug   mod,"Polling WIMP..."
        MOVVS   r1, #1                  ; Report any error with OK button.
        BLVS    Mod_ReportError

        LDR     r0, =poll_mask
        ADR     r1, user_data
        ADR     r3, pollword
        SWI     XWimp_Poll
        BVS     repoll_wimp

        ADR     lr, repoll_wimp
        CMP     r0, #(jump_table_end-jump_table)/4
        ADDCC   pc, pc, r0, ASL #2
        MOV     pc, lr

jump_table
        MOV     pc, lr                  ; Null event.
        MOV     pc, lr                  ; Redraw window.
        B       Window_Open
        B       Window_Close
        MOV     pc, lr                  ; Pointer leaving window.
        MOV     pc, lr                  ; Pointer entering window.
        B       Mouse_Click
        MOV     pc, lr                  ; User drag box.
        B       Mode_KeyPressed
        B       Menu_Selection
        MOV     pc, lr                  ; Scroll request.
        MOV     pc, lr                  ; Lose caret.
        MOV     pc, lr                  ; Gain caret.
        B       Mod_PollWord
        MOV     pc, lr                  ; 14
        MOV     pc, lr                  ; 15
        MOV     pc, lr                  ; 16
        B       Message_Received
        B       Message_Recorded
        MOV     pc, lr                  ; Message acknowledge.
jump_table_end


error_old_wimp
        SWI     XWimp_CloseDown
        SWI     XOS_WriteI+4            ; Just in case (old Wimp!)
        ADR     r0, ErrorBlock_Modes_NoWimp
        BL      MsgTrans_ErrorLookup
        SWI     OS_GenerateError        ; Don't return.

        MakeErrorBlock  Modes_NoWimp


error_abort
        MOV     r1, #2                  ; Cancel button only.
        BL      Mod_ReportError
        BL      Mod_ShutDown            ; On exit r12->private word
        MOV     lr, #-1                 ; Error in initialisation.
        STR     lr, [r12]
        SWI     OS_Exit


messages_list
        DCD     Message_MenuWarning
        DCD     Message_MenusDeleted
        DCD     Message_HelpRequest
 [ LoadModeFiles
        DCD     Message_DataLoad
        DCD     Message_DataSave
 ]
        DCD     0
task_identifier
        DCB     "TASK"
banner
        DCB     "Title",0
        ALIGN


;---------------------------------------------------------------------------
; Mod_ReportError
;
;       In:     r0 -> error block
;               r1 = flags for Wimp_ReportError
;       Out:    r1 = returned from Wimp_ReportError
;
;       Report the given error using the given flags.
;
Mod_ReportError
        ENTRY   "r0-r3",max_banner_size         ; Save regs and get local stack frame.

        Debug   mod,"Mod_ReportError"
        ADR     r1, banner                      ; Get module title.
        MOV     r2, sp
        MOV     r3, #max_banner_size
        BL      MsgTrans_Lookup
        ADD     r3, sp, #max_banner_size
        LDMIA   r3, {r0,r1}                     ; Get back original error and flags.
        SWI     XWimp_ReportError
        STR     r1, [r3, #4]                    ; Pass back returned flags.

        EXIT


;---------------------------------------------------------------------------
; Mod_CopyString
;
;       In:     r0 -> 0 terminated string to copy
;               r1 -> buffer to copy into
;               r2 = size of buffer (-1 if you don't care)
;       Out:    r0 preserved
;               r1 -> terminating 0 in buffer
;               r2 = space left in buffer
;
;       Copy a string.  If r2<>-1 then the buffer is of fixed length and
;       will not overflow.  The string copied into the buffer is always
;       0 terminated even if it didn't fit.
;
Mod_CopyString
        ROUT
        ENTRY   "r0"
        TEQ     r2, #0
        EXIT    EQ
10
        LDRB    lr, [r0], #1
        SUBS    r2, r2, #1
        MOVEQ   lr, #0
        TEQNE   lr, #0
        STRNEB  lr, [r1], #1
        BNE     %BT10
20
        STRB    lr, [r1]
        EXIT


;---------------------------------------------------------------------------
; Mod_PollWord
;
;       Poll word is non-zero.
;
Mod_PollWord
        ROUT
        ENTRY   "r1"

        LDR     r1, pollword

        TST     r1, #pf_settitle
        BLNE    Window_SetTitle

        TST     r1, #pf_modeinit
        BLNE    Mode_Init
        BVS     %FT10

        TST     r1, #pf_refreshicons
        BLNE    Icon_Refresh
10
        MOV     r1, #0                  ; It's the safest thing to do!
        STR     r1, pollword

        EXIT


;---------------------------------------------------------------------------
;       Neil's debugging routines
;
      [ debug
        InsertNDRDebugRoutines
      ]

        LTORG

        END