; ; template.s ; ; Load window template resources (MDW) ; ; © 1994-1998 Straylight ; ;----- Licensing note ------------------------------------------------------- ; ; This file is part of Straylight's Sapphire library. ; ; Sapphire 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, or (at your option) ; any later version. ; ; Sapphire 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 Sapphire. If not, write to the Free Software Foundation, ; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;----- Standard header ------------------------------------------------------ GET libs:header GET libs:swis ;----- External dependencies ------------------------------------------------ GET sapphire:alloc GET sapphire:fastMove GET sapphire:except GET sapphire:mem GET sapphire:msgs GET sapphire:res GET sapphire:resources GET sapphire:resspr GET sapphire:sapphire GET sapphire:string ;----- Main code ------------------------------------------------------------ AREA |Sapphire$$Code|,CODE,READONLY ; --- tpl__find --- ; ; On entry: R0 == pointer to name to find ; ; On exit: CS if template found in list, and ; R0 == pointer to template block (internal format) ; else CC if in shared resource ; R0 == pointer to embedded template definition ; May return an error ; ; Use: Finds a named template in the list. tpl__find ROUT ORRS R14,R14,#C_flag ;Set C initially STMFD R13!,{R1,R2,R12,R14} ;Stack some registers WSPACE template_wspace ;Find my workspace LDR R2,template_list ;Find the list head ; --- Go through the list trying to find one --- 00 CMP R2,#0 ;Is this the list end? BEQ %10tpl__find ;Yes -- return the error ADD R1,R2,#tlist_name ;Find this template's name BL str_icmp ;Compare the names LDRNE R2,[R2,#tlist_next] ;If no match, get next one... BNE %b00 ;And go round again ; --- We found a match!!! --- MOV R0,R2 ;Point to the template LDMFD R13!,{R1,R2,R12,R14} ;Unstack some registers BICS PC,R14,#V_flag ;Return with no error ; --- No match -- try shared resource --- 10tpl__find MOV R1,R0 ;Point to the template name MOV R0,#rsType_template ;Search for template resource BL resources_find ;Try to find the resource LDMCSFD R13!,{R1,R2,R12,R14} ;If it worked, get registers BICCSS PC,R14,#C_flag + V_flag ;And return with no error ; --- Couldn't find it then --- 20tpl__find MOV R2,R1 ;Point to the template name ADR R0,tpl__notfound ;Point to error message BL msgs_error ;Translate the message LDMFD R13!,{R1,R2,R12,R14} ;Unstack some registers ORRS PC,R14,#V_flag ;Return with the error tpl__notfound DCD 1 DCB "tplTNF",0 LTORG ; --- template_find --- ; ; On entry: R0 == pointer to name to match ; ; On exit: R0 == pointer to window definition if found ; May return an error ; ; Use: Locates a template in the list and gives you a pointer to ; the corresponding window defintion. You may update the ; definition to store an updated window state if you really ; want to. ; ; Note that this call will fail if you attempt to find a ; template which is held in the shared resources DLL. EXPORT template_find template_find ROUT STMFD R13!,{R1,R2,R14} ;Save return address MOV R2,R0 ;Remember the name BL tpl__find ;Find the definition BVS %10template_find ;If failed, skip onwards BCC %05template_find ;If in resource DLL, skip ADD R0,R0,#tlist_size ;Point to window def LDMFD R13!,{R1,R2,R14} ;Return to caller BICS PC,R14,#V_flag ; --- It's in the resources DLL --- 05template_find ADR R0,tpl__notfound ;Point to error message BL msgs_error ;Translate the message ; --- Couldn't find the template --- 10template_find LDMFD R13!,{R1,R2,R14} ;Restore registers ORRS PC,R14,#V_flag ;And return the error LTORG ; --- template_copy --- ; ; On entry: R0 == pointer to name to match ; ; On exit: R0 == pointer to copy of a window definition ; May return an error ; ; Use: Returns a copy of a window template (for the use of the ; dialogue box system mainly), including all indirected data ; set up properly and everything. The copy is writable. To ; get rid of the copy, call template_free. EXPORT template_copy template_copy ROUT ; --- Find the copy first --- STMFD R13!,{R1-R5,R14} ;Save some registers BL tpl__find ;Find the definition BVS %99template_copy ;If it failed, tidy up BCC %50template_copy ;In resources -- handle it MOV R5,R0 ;Keep pointer to definition ; --- Now allocate the memory we need --- LDR R0,[R5,#84+tlist_size] ;Get the number of icons MOV R0,R0,LSL #5 ;Multiply by 32 for size ADD R0,R0,#88+tlist_size ;Bump up by overhead MOV R2,R0 ;Keep the size safe BL alloc ;Allocate the memory BCS %98template_copy ;If that failed, skip ahead MOV R4,R0 ;Keep that pointer safe ; --- Copy the window defintion over --- MOV R1,R5 ;Point to the definition MOV R0,R4 ;And my new block BL fastMove ;Copy that data across ; --- Now see if we need do anything else LDR R0,[R5,#tlist_indsize] ;Get indirected data size CMP R0,#0 ;Is there any? BEQ %10template_copy ;If not, skip past this bit ; --- Allocate the indirected space --- MOV R2,R0 ;Look after the size BL alloc ;Allocate the new block BCS %97template_copy ;And tidy up if it failed ; --- Copy indirected data over --- LDR R1,[R5,#tlist_indptr] ;Find the old indirect block BL fastMove ;Copy it over very quickly STR R0,[R4,#tlist_indptr] ;Store the new block pointer ; --- Now fix up all the references --- SUB R5,R0,R1 ;Get the relocation offset LDR R0,[R4,#56+tlist_size] ;Get the title bar flags ADD R1,R4,#72+tlist_size ;Point to the title data BL tpl__fixData ;Fix up that data LDR R3,[R4,#84+tlist_size] ;Get the number of icons ADD R2,R4,#88+tlist_size ;Point to the first icon 00template_copy SUBS R3,R3,#1 ;Decrement the icon counter LDRGE R0,[R2,#16] ;Get the icon flags word ADDGE R1,R2,#20 ;Point to the icon data BLGE tpl__fixData ;And fix up the icon data ADDGE R2,R2,#32 ;Move onto the next icon BGE %00template_copy ;And move onto the next one ; --- All done -- return the pointer --- 10template_copy ADD R0,R4,#tlist_size ;Point to the actual defn LDMFD R13!,{R1-R5,R14} ;Unstack a load of registers BICS PC,R14,#V_flag ;Return to caller ; --- It's in the resources DLL --- 50template_copy LDMFD R13!,{R1-R5,R14} ;Restore these registers B template_embedded ;Extract embedded definition ; --- Error -- free the template block --- 97template_copy MOV R0,R4 ;Point to the template block BL free ;Free up the block ; --- Return the error --- 98template_copy BL alloc_error ;Find the correct error mesg 99template_copy LDMFD R13!,{R1-R5,R14} ;Restore the registers ORRS PC,R14,#V_flag ;Return to caller LTORG ; --- tpl__fixData --- ; ; On entry: R0 == icon flags ; R1 == pointer to icon data to fix ; R5 == offset to bodge data by ; ; On exit: Registers preserved ; ; Use: Relocates indirected data by a given amount tpl__fixData ROUT TST R0,#&00000100 ;Is it indirected? MOVEQS PC,R14 ;No -- return right now ; --- Fix up icon data --- STMFD R13!,{R14} ;Save the link register LDR R14,[R1,#0] ;Get the data pointer ADD R14,R14,R5 ;Relocate it STR R14,[R1,#0] ;And store it back again ; --- Is there validation data too? --- TST R0,#&00000001 ;Does it contain text data? LDRNE R14,[R1,#4] ;Yes -- get validation ptr CMPNE R14,#-1 ;If the pointer sensible? LDMEQFD R13!,{PC}^ ;No -- return ; --- Relocate validation string pointer --- ADD R14,R14,R5 ;Relocate it STR R14,[R1,#4] ;Store it back in the block LDMFD R13!,{PC}^ ;Return to caller LTORG ; --- template_embedded --- ; ; On entry: R0 == pointer to embedded template definition ; ; On exit: R0 == pointer to copy (as for template_copy) ; ; Use: Extracts an embedded template into a template block. ; Embedded templates can be generated using the templAOF ; program, and then linked into your application. EXPORT template_embedded template_embedded ROUT STMFD R13!,{R1-R7,R14} ;Save some registers ; --- First load the header out --- LDMIA R0,{R3-R5} ;Load the three pointers out ADD R3,R3,R0 ;Relocate the window pointer ADD R4,R4,R0 ;Relocate the ind base ptr ADD R5,R5,R0 ;Relocate the ind limit ptr ADD R6,R0,#12 ;And find the relocation tbl ; --- Allocate a block for the window definition --- LDR R14,[R3,#84] ;Load the number of icons MOV R0,#88+tlist_size ;Get the base memory req ADD R0,R0,R14,LSL #5 ;Add space for the icons SUB R2,R0,#tlist_size ;Keep size without extras BL alloc ;Try to allocate the space BLCS alloc_error ;If it failed, get error BCS %99template_embedded ;And skip onwards MOV R7,R0 ;Look after this pointer ; --- Copy the window data over --- ADD R0,R7,#tlist_size ;Point to window def area MOV R1,R3 ;Point to the original def BL fastMove ;Copy that over ; --- Now handle the data --- SUBS R0,R5,R4 ;Find indirected data size STR R0,[R7,#tlist_indsize] ;Store the size away STREQ R0,[R7,#tlist_indptr] ;If none, store null ptr BEQ %10template_embedded ;And skip on to relocate BL alloc ;Allocate the space BLCS alloc_error ;If it failed, get error BCS %98template_embedded ;And skip onwards STR R0,[R7,#tlist_indptr] ;Store the pointer ; --- Copy the data over --- MOV R1,R4 ;Point to original data SUB R2,R5,R4 ;Find the data size BL fastMove ;Copy it over nicely ; --- Finally do the relocation --- 10 MOV R5,R0 ;Look after indirected addr BL resspr_area ;Find the sprite area MOV R4,R0 ;Look after that too ADD R0,R7,#tlist_size ;Find window definition 00 CMP R6,R3 ;Finished yet? BCS %90template_embedded ;Yes -- wrap things up LDR R14,[R6],#4 ;Load next directive MOV R2,R14,LSR #28 ;Get the directive type BIC R14,R14,#&F0000000 ;And the offset ADD PC,PC,R2,LSL #2 ;Dispatch to handler DCB "MDW!" B %15template_embedded B %20template_embedded B %b00 15 LDR R2,[R0,R14] ;Load the word ADD R2,R2,R5 ;Relocate for indirectedness STR R2,[R0,R14] ;Store it back again B %b00 ;Loop 20 STR R4,[R0,R14] ;Store the sprite area B %b00 ;Loop ; --- Finished -- return --- 90 LDMFD R13!,{R1-R7,R14} ;Load lots of registers BICS PC,R14,#V_flag ;And return errorless ; --- Errors -- tidy up --- 98 MOV R6,R0 ;Look after error pointer MOV R0,R7 ;Get the template block BL free ;Free it MOV R0,R6 ;Restore error pointer 99 LDMFD R13!,{R1-R7,R14} ;Load lots of registers ORRS PC,R14,#V_flag ;And return the error LTORG ; --- template_free --- ; ; On entry: R0 == pointer to block allocated with template_copy ; ; On exit: -- ; ; Use: Frees a template copy created using template_copy. EXPORT template_free template_free ROUT STMFD R13!,{R0,R1,R14} ;Save some registers SUB R1,R0,#tlist_size ;Find base of block LDR R0,[R1,#tlist_indptr] ;Get indirect data pointer CMP R0,#0 ;Is there any indirect data? BLNE free ;Yes -- free the memory MOV R0,R1 ;Get the block pointer BL free ;Free that too LDMFD R13!,{R0,R1,PC}^ ;Return to caller LTORG ; --- template_load --- ; ; On entry: R0 == pointer to name of template file to load ; ; On exit: May return an error ; ; Use: Loads the specified template file, and adds its window ; definitions into the template list so they can be used when ; creating dialogue boxes or windows. ; ; If the templates can't be loaded (e.g. there isn't enough ; memory) an error is generated (and can be caught using the ; standard Sapphire except mechanism). EXPORT template_load template_load ROUT ; --- We need a lot of registers! --- STMFD R13!,{R0-R12,R14} ;Save the registers we want WSPACE template_wspace ;Find my workspace ; --- Find out how big the file is --- MOV R1,R0 ;Point to the filename MOV R0,#17 ;Info about file please SWI XOS_File ;Try to load the file BVS %99template_load ;If no luck, make the error ; --- Allocate a heap block for it --- MOV R0,R4 ;Get the template file size BL alloc ;Allocate the block BLCS alloc_error ;If it failed, get error BCS %99template_load ;If no luck, make the error MOV R8,R0 ;Guard pointer with life :-) ; --- Load template file into buffer --- MOV R0,#16 ;Load a file into memory LDR R1,[R13,#0] ;Get the filename back MOV R2,R8 ;Point to my buffer MOV R3,#0 ;Load into my buffer SWI XOS_File ;Load the file now BVS %98template_load ;Bad news -- free block first ; --- Now we can parse the file up --- ADD R10,R8,#16 ;Find the first index entry 00template_load LDR R0,[R10,#0] ;Is this an empty entry? CMP R0,#0 ;Just check quickly BEQ %05template_load ;Yes -- we've finished ADD R9,R8,R0 ;Point to the actual entry LDR R1,[R10,#8] ;Get the entry type number SUB R1,R1,#1 ;Convert it to zero-indexed CMP R1,#(%11-%10)/4 ;Make sure it's recognised BCS %02template_load ;No -- don't to it then STMFD R13!,{R8,R12} ;Save workspace and base MOV R12,R13 ;Point to this pair MOV R14,PC ;Set up return address ADD PC,PC,R1,LSL #2 ;Branch table dispatch B %01template_load ;And link in the block 10template_load B tpl__loadWind ;Load a window definition 11template_load 01template_load LDMFD R13!,{R8,R12} ;Find workspace too BVS %98template_load ;It failed miserably ; --- Link the returned block into the list --- LDR R1,template_list ;Find the list head STR R1,[R0,#tlist_next] ;Make it this one's next ptr STR R0,template_list ;And make this the list head ; --- Move on to the next entry --- 02template_load ADD R10,R10,#24 ;Move to the next entry B %00template_load ;And go back again ; --- We finished loading the file -- free buffer --- 05template_load MOV R0,R8 ;Point to the file buffer BL free ;Free the memory now ; --- Now we can leave --- LDMFD R13!,{R0-R12,R14} ;Return to caller BICS PC,R14,#V_flag ; --- Error encountered after block allocation --- 98template_load MOV R9,R0 ;Keep error pointer MOV R0,R8 ;Point to the file buffer BL free ;Free the memory now MOV R0,R9 ;Restore error pointer ; --- Error encountered before block allocation --- 99template_load ADD R2,R0,#4 ;Point to error message ADR R0,tload__error ;Point to error skeleton BL msgs_error ;Create the error message ADD R13,R13,#4 ;Skip past stacked R0 LDMFD R13!,{R1-R12,R14} ;Return to caller ORRS PC,R14,#V_flag ;With error indicator set tload__error DCD 1 DCB "tplTLE",0 LTORG template_wspace DCD 0 ; --- template_init --- ; ; On entry: R0 == pointer to application name ; ; On exit: -- ; ; Use: Initialises the template list and font array, and loads the ; `Templates' resource file. EXPORT template_init template_init ROUT STMFD R13!,{R0,R1,R12,R14} ;Store some registers WSPACE template_wspace ;Find my workspace LDR R14,template_list ;Get the current list CMP R14,#0 ;Is it silly? LDMNEFD R13!,{R0,R1,R12,PC}^ ;No -- we're already running BL alloc_init ;Make sure we can find memory BL resspr_init ;This will initialise res too BL except_init ;For atexit to tidy up later ; --- Set up the workspace nicely --- MOV R0,#0 ;Store null pointers STR R0,template_list ;No templates yet STR R0,template_fonts ;No fonts found either ; --- Build the name in the scratchpad --- ADR R0,tpl__templates ;Point to the resource name MOV R1,R11 ;Point to scratchpad buffer ADDS R0,R0,#0 ;Clear C and V flags BL res_find ;Find the resource file ; --- Load the file and return --- BLCS template_load ;Load the file if it's there SWIVS OS_GenerateError ;If it failed, make an error LDMFD R13!,{R0,R1,R12,PC}^ ;Return to the caller tpl__templates DCB "Templates",0 LTORG ; --- tpl__killFont --- ; ; On entry: R12 == pointer to template workspace ; ; On exit: -- ; ; Use: Loses loads of fonts when the application quits tpl__killFont ROUT STMFD R13!,{R0-R2,R14} ;Save some registers LDR R1,template_fonts ;Find the font array MOV R0,#255 ;Start at the top for this 00tpl__killFont LDRB R2,[R1,R0] ;Get the reference counter 01tpl__killFont SUBS R2,R2,#1 ;Decrement the counter SWIGE Font_LoseFont ;Lose the font BGE %01tpl__killFont ;And go round again SUBS R0,R0,#1 ;Decrement the handle BGE %00tpl__killFont ;And go round again LDMFD R13!,{R0-R2,PC}^ ;And return to caller LTORG ;----- Template loading routines -------------------------------------------- ; ; For all routines: ; ; On entry: R9 == pointer to entry in memory ; R10 == pointer to index entry for this object ; R12 == pointer to template base and workspace block ; ; On exit: If successful: ; R0 == pointer to template entry to add into the list ; V flag clear ; If an error occurred: ; R0 == pointer to standard error block ; V flag set ; R1-R9 may be corrupted ; --- tpl__loadWind --- ; ; Use: Loads a window definition and converts it into a template ; list item tpl__loadWind ROUT STMFD R13!,{R14} ;Just stack the return addr ; --- Find out how many icons there are --- ADD R0,R9,#84 ;Point to the right place AND R1,R0,#3 ;Get the non-word-alignedness BIC R0,R0,#3 ;And round down to word LDMIA R0,{R2,R3} ;Get the two words we want MOV R1,R1,LSL #3 ;Turn bytes into bits MOV R8,R2,LSR R1 ;Get the bottom few bytes RSB R1,R1,#32 ;Get the shift the other way ORR R8,R8,R3,LSL R1 ;And copy in the top bytes ; --- R8 now contains the number of icons --- ; --- Allocate a template block --- MOV R3,R8,LSL #5 ;Multiply the number by 32 ADD R3,R3,#88+tlist_size ;Add on window and list block MOV R0,R3 ;I want to allocate memory BL alloc ;Allocate the space BLCS alloc_error ;If it failed, get error BCS %99tpl__loadWind ;If it failed, return error MOV R7,R0 ;Keep the pointer ; --- Copy the window definition into the block --- ADD R0,R7,#tlist_size ;Where to store definition SUB R2,R3,#tlist_size ;Size of block to copy MOV R1,R9 ;Point to the window def BL fastMove ;And shunt the bytes over ; --- We may as well copy the name over now too --- ADD R1,R10,#12 ;Point to the template name ADD R0,R7,#tlist_name ;Point to my block section LDMIA R1,{R2-R4} ;Get the twelve bytes STMIA R0,{R2-R4} ;Store them in my block MOV R1,#0 ;And zero terminate STRB R1,[R0,#12] ;Stop the string off nicely ; --- Widge the sprite area --- BL resspr_area ;Load the sprite area ptr STR R0,[R7,#64+tlist_size] ;Store sprite area pointer ; --- Now count the amount of indirected data --- MOV R6,#0 ;Currently no indirected size LDR R5,[R7,#56+tlist_size] ;Get the title bar flags ADD R4,R7,#72+tlist_size ;Point to the title bar data BL tpl__dataSize ;Add in the space required MOV R0,R8 ;The number of icons I have ADD R1,R7,#88+tlist_size ;Point to the first icon 00tpl__loadWind SUBS R0,R0,#1 ;Decrement the counter LDRGE R5,[R1,#16] ;Get the flags word here ADDGE R4,R1,#20 ;Point to the icon data BLGE tpl__dataSize ;Add in the extra data ADDGE R1,R1,#32 ;Point to the next icon defn BGE %00tpl__loadWind ;And go back for the rest ; --- We now have the data size in R6 --- STR R6,[R7,#tlist_indsize] ;Store the buffer size away CMP R6,#0 ;Is there any indirect space? STREQ R6,[R7,#tlist_indptr] ;No -- store a null pointer BEQ %01tpl__loadWind ;... and skip past allocation ; --- Allocate the buffer properly --- MOV R0,R6 ;Get the size of the block BL alloc ;Allocate yet more memory BLCS alloc_error ;If failed, get error BCS %98tpl__loadWind ;If it failed, report error MOV R6,R0 ;Point to the new buffer STR R6,[R7,#tlist_indptr] ;Save indirected size away ; --- Now copy the indirected data across --- ; ; We also fix up the pointers at the same time, and set up ; any fonts that need loading. 01tpl__loadWind LDR R5,[R7,#56+tlist_size] ;Get the title bar flags ADD R4,R7,#72+tlist_size ;Point to the title bar data BL tpl__copyData ;Process the indirect data ADD R5,R7,#56+tlist_size ;Point to the flags now BL tpl__findFont ;And handle any fonts BVS %97tpl__loadWind ;Quit if something went wrong MOV R0,R8 ;The number of icons I have ADD R1,R7,#88+tlist_size ;Point to the first icon 02tpl__loadWind SUBS R0,R0,#1 ;Decrement the counter BLT %03tpl__loadWind ;If no more, skip ahead LDR R5,[R1,#16] ;Get the flags word here ADD R4,R1,#20 ;Point to the icon data BL tpl__copyData ;Copy over the indirect data ADD R5,R1,#16 ;Point to the flags now BL tpl__findFont ;And handle any fonts BVS %97tpl__loadWind ;Quit if something went wrong ADD R1,R1,#32 ;Point to the next icon defn B %02tpl__loadWind ;Now go back for the rest ; --- The excitement's over now, so that's it --- 03tpl__loadWind MOV R0,R7 ;Point at the template block LDMFD R13!,{R14} ;Get the link register out BICS PC,R14,#V_flag ;And return no errors ; --- Something screwed up -- deallocate both blocks --- 97tpl__loadWind MOV R9,R0 ;Save error pointer LDR R0,[R7,#tlist_indptr] ;Find the indirect block addr BL free ;Free indirect data block MOV R0,R9 ;Restore error pointer ; --- Error occurred -- free the template block --- 98tpl__loadWind MOV R9,R0 ;Save error pointer MOV R0,R7 ;Point to template block BL free ;Free the template block MOV R0,R9 ;Restore error pointer ; --- Error occurred -- return with V set --- 99tpl__loadWind LDMFD R13!,{R14} ;Get the link register ORRS PC,R14,#V_flag ;Set the error indicator LTORG ;----- Support functions ---------------------------------------------------- ; --- tpl__dataSize --- ; ; On entry: R4 == pointer to icon data ; R5 == icon flags word ; R6 == counter to increment ; R7 == pointer to window block ; R8 == number of icons in the window ; R9 == pointer to the window definition in the template file ; R10 == pointer to index for current window ; R12 == pointer to template base and workspace block ; ; On exit: R6 incremented by an appropriate amount ; Everything else preserved (except R14, obviously!) ; ; Use: Counts the amount of indirected space required for a given ; icon flags/data pair and adds it into a running total tpl__dataSize ROUT ; --- Make sure there's something to do --- TST R5,#&00000100 ;Test indirected bit MOVEQS PC,R14 ;If not indirected, go away ; --- Locate and count the indirected data string --- STMFD R13!,{R14} ;Save some registers LDR R14,[R4,#8] ;Get the indirect buffer size ADD R6,R6,R14 ;And add this onto the count ; --- Check if there's a validation string --- TST R5,#&00000001 ;Is the `Is text' bit on? LDRNE R14,[R4,#4] ;Yes -- get validation ptr CMPNE R14,#-1 ;Is it a sensible pointer? LDMEQFD R13!,{PC}^ ;If not, we're done for now ; --- Count length of validation string --- STMFD R13!,{R0} ;Save another register ADD R0,R14,R9 ;Point to string in memory BL str_len ;Find its length ADD R0,R0,#1 ;Account for the terminator ADD R6,R6,R0 ;Add this to the counter LDMFD R13!,{R0,PC}^ ;And return to the caller LTORG ; --- tpl__copyData --- ; ; On entry: R4 == pointer to icon data ; R5 == icon flags word ; R6 == pointer to free part of buffer ; R7 == pointer to window block ; R8 == number of icons in the window ; R9 == pointer to the window definition in the template file ; R10 == pointer to index for current window ; R12 == pointer to template base and workspace block ; ; On exit: R6 incremented by an appropriate amount ; Everything else preserved (except R14, obviously!) ; ; Use: Copies indirected data from an icon definition into the ; buffer given and fixes up pointers in the definition tpl__copyData ROUT ; --- Make sure there's something to do here --- TST R5,#&00000100 ;Check the indirected bit MOVEQS PC,R14 ;If unset, return right now ; --- Handle basic indirected data --- STMFD R13!,{R0,R1,R14} ;Stack some registers LDR R1,[R4,#0] ;Get the indirected pointer STR R6,[R4,#0] ;Store the new pointer in ADD R1,R9,R1 ;Offset by window address MOV R0,R6 ;Point to free bit of bufffer BL str_cpy ;Copy (and null-terminate) LDR R14,[R4,#8] ;Get the indirect buffer size ADD R6,R6,R14 ;Move buffer pointer on by it ; --- Check for validation string presence --- TST R5,#&00000001 ;Is the `Is text' bit on? LDRNE R14,[R4,#4] ;Yes -- get validation ptr CMPNE R14,#-1 ;Is it a sensible pointer? LDMEQFD R13!,{R0,R1,PC}^ ;If not, we're done ; --- Handle the validation string --- STR R6,[R4,#4] ;Store the new pointer ADD R1,R9,R14 ;Point to the validation str MOV R0,R6 ;Point to the bit of buffer BL str_cpy ;And copy the string across ADD R6,R0,#1 ;Point R6 past string term LDMFD R13!,{R0,R1,PC}^ ;That's it from us, then LTORG ; --- tpl__findFont --- ; ; On entry: R5 == pointer to icon flags word ; R6 == pointer to free part of buffer ; R7 == pointer to window block ; R8 == number of icons in the window ; R9 == pointer to the window definition in the template file ; R10 == pointer to index for current window ; R12 == pointer to template base and workspace block ; ; On exit: Everything preserved except R4 (and R14, obviously!) ; ; Use: Fixes up an icon's anti-aliased font data. tpl__findFont ROUT LDR R4,[R5] ;Get the icon flags word TST R4,#&00000040 ;Is it antialiased? TSTNE R4,#&00000001 ;Make sure it's text too BICEQS PC,R14,#V_flag ;If not, return no error ; --- Now to business -- ensure we have a font table --- STMFD R13!,{R0-R3,R5,R12,R14} ;Save some registers LDMIA R12,{R5,R12} ;Load base and workspace LDR R0,template_fonts ;Find font array pointer CMP R0,#0 ;Is it null? BEQ %00tpl__findFont ;Yes -- allocate it ; --- Now locate the font table in the file --- 01tpl__findFont LDR R3,[R5,#0] ;Get the font table offset ADD R3,R5,R3 ;Convert it to a pointer ; --- Find internal font handle and get table entry --- MOV R0,R4,LSR #24 ;Leave only the font handle SUB R0,R0,#1 ;Convert to 0-indexed STMFD R13!,{R4,R5} ;Need some more registers!! ADD R4,R3,R0,LSL #4 ;R4 = R3 + R0 * 16 ADD R4,R4,R0,LSL #5 ;Now R4 = R3 + R0 * 48 ; --- Now we must load the font width and height --- ; ; The problem is that they're not on word boundaries, so ; we must do clever-dick things with the barrel shifter. AND R0,R3,#3 ;Get the bottom two bits BIC R1,R3,#3 ;Word align the base address LDMIA R1,{R2,R3,R14} ;Get the width and height MOV R0,R0,LSL #3 ;Convert bits to bytes RSB R1,R0,#32 ;Get the other shift too MOV R2,R2,LSR R0 ;Shift the bits down here ORR R2,R2,R3,LSL R1 ;And add in the top bits MOV R3,R3,LSR R0 ;Shift down bottom bits ORR R3,R3,R14,LSL R1 ;And add in the top bits ; --- We are now in a position to find the font --- ADD R1,R4,#8 ;Point to the font name MOV R4,#0 ;Default x scaling MOV R5,#0 ;Default y scaling SWI Font_FindFont ;Try very hard to find it LDMFD R13!,{R4,R5} ;Restore these registers ADDVS R13,R13,#4 ;If it failed, skip R0, LDMVSFD R13!,{R1-R3,PC} ;... and restore regs ; --- Now bump the item in the font array --- LDR R1,template_fonts ;Find the font array LDRB R2,[R1,R0] ;Get counter for the handle ADD R2,R2,#1 ;Bump the counter a bit STRB R2,[R1,R0] ;And store it away again ; --- Bodge the icon flags word for the new handle --- BIC R4,R4,#&FF000000 ;Clear out the old handle ORR R4,R4,R0,LSL #24 ;Bring in the new... STR R4,[R5] ;Store the new flags word LDMFD R13!,{R0-R3,R5,R12,R14} ;Restore the registers BICS PC,R14,#V_flag ;And return with no error ; --- Create the font array if it's not there --- 00tpl__findFont MOV R0,#256 ;One byte for each font BL alloc ;Allocate the memory BLCS alloc_error ;If failed, get error ADDCS R13,R13,#4 ;If it failed, bump R13 LDMCSFD R13!,{R1-R3,R5,R12,PC} ;... and return with error STR R0,template_fonts ;Store the new pointer ; --- Clear the font array to 0s --- MOV R1,#256 ;The size of the array MOV R2,#0 ;Value to initialise with BL mem_set ;Clear out the array ; --- Register our tidy-up routine --- ADR R0,tpl__killFont ;Point to tidy up function MOV R1,R12 ;Point to my workspace BL except_atExit ;Register it properly B %01tpl__findFont ;Return to the main proc LTORG ;----- The list structure --------------------------------------------------- ^ 0 tlist_start # 0 tlist_next # 4 ;Pointer to the next one tlist_name # 16 ;Name of this template tlist_indptr # 4 ;Pointer to indirect data tlist_indsize # 4 ;Size of indirect data ; Window definition follows tlist_size # 0 ;Size of that structure ;----- Workspace ------------------------------------------------------------ ^ 0,R12 template_wstart # 0 template_list # 4 ;List head for templates template_fonts # 4 ;Font array if we need one template_wsize EQU {VAR}-template_wstart AREA |Sapphire$$LibData|,CODE,READONLY DCD template_wsize DCD template_wspace DCD 256 DCD template_init ;----- That's all, folks ---------------------------------------------------- END