; 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.
;

; OSS Message file handling code, created for Internationalisation.
; I can't use the workspace in Sprite Extend as R12 does not always point at
; the workspace.
;
;
; Amusing rant censored by Big Brother at ROOL - sorry folks!
;
;
;

; The problem with all this is that "Sprite doesn't exist" is a very
; heavily used error. The Wimp uses it when searching through its different
; sprite pools (RAM and ROM). The Filer uses it when displaying small
; icons. In fact, it is so heavily used that it needs to be as fast as
; possible, so it is cached. All the other errors are real genuine errors
; and there is no problem with them being a bit slow.


; OSS Free the cached "Sprite doesn't exist" error block.
; MUST preserve R0 and the V flag.

free_sprite_doesnt_exist_error EntryS "r0-r2"
        LDR     r2, sprite_doesnt_exist_error
        TEQ     r2, #0                          ; Check if it needs freeing
        EXITS   EQ                              ; Doesn't need freeing
        MOV     r0, #ModHandReason_Free
        SWI     XOS_Module                      ; Free it
        MOV     r2, #0
        STR     r2, sprite_doesnt_exist_error   ; Ensure not freed again
        EXITS                                   ; Ignore errors


; OSS Cache (or re-cache) the "Sprite doesn't exist" error block

cache_sprite_doesnt_exist_error ENTRY "r0-r7"
        BL      free_sprite_doesnt_exist_error  ; Free it if already cached
        BLVC    open_message_file_stack         ; Open file on stack
        STRVS   r0, [sp]
        EXIT    VS                              ; We got an error

; From here on remember to unwind stack (ie. call close) on error

        MOV     r0, sp                          ; Pointer to file handle
        ADR     r1, ErrorBlock_DoesntExist+4    ; Pointer to token
        MOV     r2, #0                          ; No buffer - direct pointer
        MOV     r4, #0                          ; No %0 (should be Title)
        MOV     r5, #0                          ; No %1
        MOV     r6, #0                          ; No %2
        MOV     r7, #0                          ; No %3
        SWI     XMessageTrans_Lookup
        BVS     error_while_file_open

; R3 is now length not including termination. Need to add 1 for terminator,
; another 4 for the error number, subtract 2 for the %0, and add the length
; of the module title which will go in place of the %0. 1+4-2+title =
; 3+length of module title.

        ADD     r3, r3, #(3+EndTitle-Title)
        MOV     r0, #ModHandReason_Claim
        SWI     XOS_Module
        BVS     error_while_file_open
        STR     r2, sprite_doesnt_exist_error   ; Save pointer to block

        LDR     r0, ErrorBlock_DoesntExist      ; Get error number
        STR     r0, [r2]                        ; Put number in new block
        ADD     r2, r2, #4                      ; Skip past error number
        SUB     r3, r3, #4                      ; Reduce length for number

        MOV     r0, sp                          ; Pointer to file handle
        ADR     r1, ErrorBlock_DoesntExist+4    ; Pointer to token
        addr    r4, Title                       ; %0 -> Module title
        SWI     XMessageTrans_Lookup
        BVS     error_while_file_open           ; Implies got length wrong

        BL      close_message_file_stack        ; Close and unwind stack
        EXIT


; OSS Both of the functions called here preserve R0 and the V bit.

error_while_file_open
        BL      free_sprite_doesnt_exist_error  ; Free block if necessary
        BL      close_message_file_stack        ; Close and unwind stack
        STR     r0, [sp]                        ; Original error into stack R0
        EXIT


; OSS Special error block with a long meaningful token. This is in case
; we fail to cache it so the token returned is fairly helpful.

ErrorBlock_DoesntExist
        DCD     ErrorNumber_Sprite_DoesntExist
        DCB     "NoSprit", 0
        ALIGN


; OSS Function to return a "Sprite doesn't exist" error block. In the case
; that it is not cached, there was an error earlier. We do NOT try to
; re-cache it, because we will almost certainly get the same error again.
; Instead we return a pointer to the token error block. It is important
; that this error is ALWAYS returned with the correct error number, even
; when the Messages file is missing and similar problems. Otherwise the
; Wimp does not move onto the ROM sprite pool and hence the pointer and
; half the icons on the icon bar disappear! Fortunately this is not a problem,
; as the cached error always has the correct number and the default
; error block returned in the case it isn't cached (ie. file/token not
; found) has the correct error number in too.

get_sprite_doesnt_exist_error ROUT
        LDR     r0, sprite_doesnt_exist_error   ; Cached block
        TEQ     r0, #0
        ADREQ   r0, ErrorBlock_DoesntExist      ; Token block
        SETV
        MOV     pc, lr


; OSS Translate an error block, with one substituted parameter.

; In:   r0 -> Error block containing the token
;       r1 -> %0 parameter to substitute

; Out:  r0 -> Translated error block or another error (token no found etc.)
;       All other registers preserved, V always set, other flags undefined

copy_error_one Entry "r2-r7"
        MOV     r4, r1                          ; Move input %0
        BL      open_message_file_stack         ; Open the file
        EXIT    VS                              ; Return the error

        MOV     r1, sp                          ; Messages file handl on stack
        MOV     r2, #0                          ; Use MessageTrans buffer
        MOV     r5, #0                          ; No %1
        MOV     r6, #0                          ; No %2
        MOV     r7, #0                          ; No %3
        SWI     XMessageTrans_ErrorLookup       ; Always sets the V flag

        MOV     r1, r4                          ; Preserve input r1
        BL      close_message_file_stack        ; Close the file
        EXIT


message_filename
        [ localmessages
        DCB     "Resources.<Locale>.Messages", 0
        |
        DCB     "Resources:$.Resources.SprExtend.Messages", 0
        ]
        ALIGN


; Carve the message file block off the stack, open the Messages file,
; and exit with the open file block on the stack unless there was an error.
; Preserves r0 (token to be looked up) unless error. Trashes R1, R2, R6, R7.

open_message_file_stack ROUT
        MOV     r7, lr                  ; Save LR
        MOV     r6, r0                  ; Save token/error block
        SUB     sp, sp, #16             ; Carve message file handle off stack

        MOV     r0, sp                  ; File handle on stack
        ADR     r1, message_filename    ; Filename
        MOV     r2, #0                  ; Direct access/buffer in RMA
        SWI     XMessageTrans_OpenFile  ; Open the file

        ADDVS   sp, sp, #16             ; Error - put stack back
        MOVVC   r0, r6                  ; Not error - restore token block
        MOV     pc, r7                  ; Return


; Close the message file block on the stack, restore the stack, and return.
; Preserves R0 (error block) and V bit. Trashes R5-R7.

close_message_file_stack ROUT
        [ :LNOT: No32bitCode
        mrs    ,r5, CPSR                ; Save CPSR
        ]
        MOV     r7, lr                  ; Save LR (and V bit)
        MOV     r6, r0                  ; Save translated error block

        MOV     r0, sp                  ; Message file block is on stack
        SWI     XMessageTrans_CloseFile ; Close the file (ignore error)

        ADD     sp, sp, #16             ; Put stack back
        MOV     r0, r6                  ; Restore translated error
        [ No32bitCode
        MOVS    pc, r7                  ; Return and preserve V bit
        |
        msr    ,CPSR_f, r5              ; Preserve V bit
        MOV     pc, r7                  ; Return
        ]


        END