; ; fontMenu.s ; ; Fontmenu creation ; ; © 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 GET libs:stream ;----- External dependencies ------------------------------------------------ GET sapphire:alloc GET sapphire:event GET sapphire:flex GET sapphire:menu GET sapphire:menuDefs GET sapphire:msgs GET sapphire:sapphire GET sapphire:string ;----- Main code ------------------------------------------------------------ AREA |Sapphire$$Code|,CODE,READONLY ; --- fm_create --- ; ; On entry: R0 == current font name ; R1 == handler to call when selection made ; R2 == R10 value to call with ; R3 == R12 value to call with ; R4 == pointer to routine to call to create submenu ; (ie. menu_create or tms_create) ; ; On exit: CS if any fonts exist and ; R0 == pointer to a menu definition ; R1 == event handler to call ; R2 == R10 value for event handler ; R3 == R12 value for event handler ; else CC and ; R0-R3 corrupted ; May return an error ; ; Use: Creates a user menu definition suitable for passing directly ; to (menu|tms)_create. Note however, that the menu defintion ; does *not* include any title; this must be created first. ; If you require items such as the system font, then ; add these to the menu before creating the menu returned ; from this call. EXPORT fm_create fm_create ROUT STMFD R13!,{R0,R4-R10,R12,R14} ;Save some registers WSPACE fm__wSpace ; --- Save the caller's handler --- ADR R14,fm__userHandler ;Point to the handler STMIA R14,{R1-R4} ;Store it away ; --- Ensure that we need to create it --- MOV R0,R11 ;Build path in scratchpad BL fm__fontPath ;Get the current fontpath BCC %70fm_create ;None found -- no fonts then LDR R14,fm__flags ;Load the flags word TST R14,#fmFlag__changed ;Have the fonts changed? BICNE R14,R14,#fmFlag__changed ;Yes -- clear the flag STRNE R14,fm__flags ;...store the flags BNE %00fm_create ;...and recreate the menu LDR R1,fm__block ;Load our block address MOVS R2,R1 ;Is it defined yet? ADRNE R1,fm__path ;Point to saved font path BLNE str_cmp ;Compare with current path MOVNE R2,#0 ;If not equal, clear pointer CMP R2,#0 ;So, do we recreate? BNE %40fm_create ;No -- return current menu MOV R1,R11 ;Point to font path string ADR R0,fm__path ;Point to font path buffer BL str_cpy ;Take a copy of the path 00fm_create LDR R0,fm__block ;Load address of menu block CMP R0,#0 ;Is it created currently? BLNE free ;Yes -- free it then ; --- Set up a flex block --- ; ; We will read the font names into this block, to make it ; easier to actually build our menu, and reduce heap ; fragmentation. ; ; The format of the data in the block is as follows: ; ; Size Use ; / 4 Number of variants (0 for regular only) ; | ? Name of this family ; \ [ ? Name of this variant SUB R13,R13,#12 ;Make a small anchor block MOV R0,R13 ;Point to the block MOV R1,#1024 ;Start it off at 256 bytes BL flex_alloc ;Allocate the block BLCS alloc_error ;If it failed, get error BCS %80fm_create ;And return to caller MOV R0,#0 ;Start at the beginning STMIB R13,{R0,R1} ;Save them in the block MOV R9,#4 ;No length for main menu MOV R10,#0 ;Or for the submenus ; --- Start building font names now --- MOV R2,#0 ;Start from the beginning MOV R1,R11 ;Build string in ScratchPad MOV R3,#256 ;Size of scratchpad buffer SWI Font_ListFonts ;Read a font name CMP R2,#-1 ;Is that the very end? BEQ %65fm_create ;Yes -- abort now then MOV R4,#0 ;Found one family so far MOV R6,#0 ;Clear a flags word MOV R1,R11 ;Point to the font name BL fm__parse ;Break the name up ORRCC R6,R6,#1 ;If `Regular', set a flag MOV R3,R1 ;Look after variant name MOV R8,R0 ;Look after the family name ; --- Set this family name up --- 10fm_create MOV R5,#0 ;This is the first variant MOV R0,R13 ;Point to the anchor block MOV R1,#4 ;Make space for count word BL fm__ensure ;Allocate space for it BVS %79fm_create ;If we couldn't, abort ADD R7,R0,#4 ;Point just past this word FSAVE R7 ;Save R7 on relocation stack MOV R1,R8 ;Get family name in R1 MOV R0,R13 ;Point to the anchor block BL fm__string ;Write the family name out BVS %79fm_create ;If it failed, abort now ADD R0,R0,#3+8 ;Word align returned length BIC R0,R0,#3 ;Tumtetiddlytumtetum ADD R9,R9,R0 ;Add on to main menu length ADD R9,R9,#4 ;Remember space for radio ADD R10,R10,R0 ;And add on submenu length ; --- Write this variant out --- 15fm_create MOV R0,R13 ;Point to anchor block MOV R1,R3 ;Point to variant name BL fm__string ;Add this on the end BVS %79fm_create ;If it failed, abort now ADD R0,R0,#3+12 ;Word align returned length BIC R0,R0,#3 ;Omtiddlyompepom ADD R10,R10,R0 ;Add this to submenu length ADD R5,R5,#1 ;Increment variant counter ; --- Get the next font name ready --- MOV R8,R6 ;Remember current flags MOV R1,R11 ;Build string in ScratchPad MOV R3,#256 ;Size of scratchpad buffer SWI Font_ListFonts ;Read a font name CMP R2,#-1 ;Is that the very end? BEQ %20fm_create ;Yes -- we've finished then BL fm__parse ;Break up the font name ORRCC R6,R6,#1 ;If `Regular', set a flag BICCS R6,R6,#1 ;Otherwise clear it MOV R3,R1 ;Look after the variant name FLOAD R1 ;Restore family name address BL str_cmp ;Do the strings match? FSAVE R1 ;Save the address back BEQ %15fm_create ;And loop round for more ; --- Finished a family --- 20fm_create FLOAD R7 ;Reload family name address CMP R5,R8 ;Is there only `Regular'? MOVEQ R5,#0 ;Yes -- claim no variants STR R5,[R7,#-4] ;Save it in the block MOV R8,R0 ;Look after the family name MOV R0,R13 ;Point to anchor block BL fm__align ;Word align output pointer ADD R4,R4,#1 ;Increment family counter CMP R2,#-1 ;Are there more font names? BNE %10fm_create ;Yes -- put them in the block ; --- Allocate a big heap block --- ADD R0,R9,R10 ;Add the menu sizes up ADD R0,R0,R4,LSL #2 ;And an indexing block BL alloc ;Allocate this block BLCS alloc_error ;If it failed, get error BCS %79fm_create ;And return to caller STR R0,fm__block ;Store this block address ; --- A note about register allocation --- ; ; Dear reader, ; I have decided, it being Saturday and all, to allocate ; registers thusly: ; ; R7 == pointer into submenu indexing table ; R8 == pointer into the main menu structure ; R9 == pointer into the submenu area ; R10 == pointer into our juicy big flex table ; ; Yours sincerely ; ; Mark Wooding (Straylight Dev Lab) MOV R7,R0 ;Point to indexing table ADD R8,R7,R4,LSL #2 ;Find the main menu area ADD R9,R8,R9 ;And find the submenu area LDR R10,[R13,#0] ;Load base of flex block STR R8,fm__menu ;Store the menu address ; --- Now the fun begins --- 22fm_create MOV R0,#mFlag_radio ;Get the flag ready ORR R0,R0,#mFlag_R12 ;And make data R12-relative LDR R6,[R10],#4 ;Load the number of variants CMP R6,#0 ;Do we want a submenu? ORRNE R0,R0,#mFlag_subWarn ;Yes -- set the flag then STR R0,[R8],#4 ;Save it in the menu block MOVEQ R14,#0 ;No submenu -- get null ptr STREQ R14,[R7],#4 ;And clear submenu address STRNE R9,[R7],#4 ;Save this submenu address MOV R0,R10 ;Look after this address 23fm_create LDRB R14,[R10],#1 ;Load a family name byte CMP R14,#0 ;Is this the end yet? STRB R14,[R8],#1 ;Save it in the menu block BNE %23fm_create ;And go round for the rest ADD R8,R8,#3 ;Word align the output addr BIC R8,R8,#3 ;Yingtongiddleipo MOV R1,#4 ;Offset 0 in radio block MOV R2,R8 ;Magic radio group tag STMIA R8!,{R1,R2} ;Save these in the block ; --- Now build the variants submenu --- CMP R6,#0 ;Do we want a submenu BEQ %28fm_create ;No -- *still skip past name* MOV R14,#0 ;Title flags STR R14,[R9],#4 ;Save in submenu block 24fm_create LDRB R14,[R0],#1 ;Load a family name byte STRB R14,[R9],#1 ;Save it in the menu block CMP R14,#0 ;Is this the end yet? BNE %24fm_create ;And go round for the rest ADD R9,R9,#3 ;Word align the output addr BIC R9,R9,#3 ;Obblyjobblywibbledidee ; --- Create an item for each variant --- 25fm_create MOV R0,#mFlag_radio ;Get the flag ready ORR R0,R0,#mFlag_R12 ;And make data R12-relative STR R0,[R9],#4 ;Save in submenu block 26fm_create LDRB R14,[R10],#1 ;Load a variant name byte CMP R14,#0 ;Is this the end yet? STRB R14,[R9],#1 ;Save it in the menu block BNE %26fm_create ;And go round for the rest ADD R9,R9,#3 ;Word align the output addr BIC R9,R9,#3 ;Obblyjobblywibbledidee MOV R1,#8 ;Offset 8 in radio block MOV R2,R9 ;Magic radio group tag STMIA R9!,{R1,R2} ;Save these in the block SUBS R6,R6,#1 ;Decrement the counter BGT %25fm_create ;And do the rest of them MOV R14,#mFlag_end ;Terminate the menu STR R14,[R9],#4 ;Save that at the end B %30fm_create ;Skip to end of family stuff ; --- No variants -- omit the submenu --- ; ; For odd reasons, we actually leave a `(Regular)' item ; in the flex block. We need to skip over this here. 28fm_create LDRB R14,[R10],#1 ;Load a variant name byte CMP R14,#0 ;Is this the end yet? BNE %28fm_create ;And go round for the rest 30fm_create ADD R10,R10,#3 ;Word align flex block ptr BIC R10,R10,#3 ;[Silly comment omitted] SUBS R4,R4,#1 ;Done another family BGT %22fm_create ;And go round for the rest MOV R14,#mFlag_end ;Terminate the menu STR R14,[R8],#4 ;Save that at the end ; --- Destroy the flex block --- MOV R0,R13 ;Point to the flex anchor BL flex_free ;Free the block ADD R13,R13,#12 ;Restore stack pointer ; --- Now return the menu and things --- 40fm_create LDR R0,[R13],#4 ;Load the name to tick BL fm_tickFont ;Tick that font LDR R0,fm__menu ;Find the menu address ADR R1,fm__handler1 ;I don't have a handler :-( MOV R2,#0 ;No R10 value either :~-( MOV R3,R12 ;And pass workspace in R12 LDMFD R13!,{R4-R10,R12,R14} ;Restore registers ORR R14,R14,#C_flag ;Set C to say we did it BICS PC,R14,#V_flag ;And return errorless ; --- Couldn't find any fonts (oops) --- 65fm_create ADD R13,R13,#12 ;Restore stack pointer 70fm_create LDMFD R13!,{R0,R4-R10,R12,R14} ;Restore registers BICS PC,R14,#V_flag+C_flag ;And return CC ; --- Tidy up after catastrophes --- 79fm_create MOV R10,R0 ;Look after the error MOV R0,R13 ;Point to the flex anchor BL flex_free ;Free the flex block MOV R0,R10 ;Restore the error pointer 80fm_create ADD R13,R13,#12+4 ;Restore the stack nicely LDMFD R13!,{R4-R10,R12,R14} ;Restore registers ORRS PC,R14,#V_flag ;And return the error LTORG ; --- fm__handler1 --- ; ; On entry: R0 == menu event ; R1 == menu item ; R12 == pointer to private workspace ; ; On exit: -- ; ; Use: Handles events on the first level menu. fm__handler1 ROUT CMP R0,#mEvent_select ;Is it a menu selection CMPNE R0,#mEvent_subMenu ;Or a submenu event? MOVNES PC,R14 ;Nope -- return STMFD R13!,{R1-R4,R14} ;Stack registers CMP R0,#mEvent_select ;A selection? BEQ %50fm__handler1 ;Yes -- jump ahead ; --- Handle submenu events --- LDR R0,fm__block ;Point to useful table LDR R0,[R0,R1,LSL #2] ;Load submenu address MOV R2,R1 ;Pass item number in R10 ADR R1,fm__handler2 ;And point to second handler MOV R3,R12 ;And workspace in R12 LDR R4,fm__creator ;Load address of creator MOV R14,PC ;Set up return address MOV PC,R4 ;Call the creator B %90fm__handler1 ;Return to caller ; --- User selected an item --- 50fm__handler1 MOV R3,R1 ;Remember index value BL fm__familyName ;Get family name pointer MOV R1,R0 ;Put it in R1 ADR R0,fm__name ;Write the name here BL str_cpy ;Copy over family name MOV R2,R0 ;Put terminator ptr in R2 LDR R0,fm__block ;Load table pointer LDR R0,[R0,R3,LSL #2] ;Load submenu pointer CMP R0,#0 ;Is there a submenu? BEQ %60fm__handler1 ;No -- jump ahead MOV R1,#0 ;Just choose first index BL fm__variantName ;Find the first variant name CMP R0,#0 ;Is there one? BEQ %60fm__handler1 ;No -- return now then MOV R1,R0 ;Put it in R1 MOV R0,R2 ;Copy it to here MOV R14,#'.' ;We want a '.' first STRB R14,[R0],#1 ;Store in the string BL str_cpy ;Copy over the string 60fm__handler1 MOV R0,#fmEvent_select ;The event type ADR R1,fm__name ;Point to the name BL fm__dispatch ;Dispatch the event 90fm__handler1 LDMFD R13!,{R1-R4,PC}^ ;Load back registers LTORG ; --- fm__handler2 --- ; ; On entry: R0 == menu event ; R1 == menu item ; R10 == menu item submenu came from ; R12 == pointer to workspace ; ; On exit: -- ; ; Use: Handles events for a second level submenu fm__handler2 ROUT CMP R0,#mEvent_select ;Is it a menu selection MOVNES PC,R14 ;Nope -- return STMFD R13!,{R1-R3,R14} ;Stack registers MOV R3,R1 ;Remember index value MOV R1,R10 ;Get previous index BL fm__familyName ;Get family name pointer MOV R1,R0 ;Put it in R1 ADR R0,fm__name ;Write the name here BL str_cpy ;Copy over family name MOV R2,R0 ;Put terminator ptr in R2 LDR R0,fm__block ;Load table pointer LDR R0,[R0,R10,LSL #2] ;Load submenu pointer MOV R1,R3 ;Put index in R1 BL fm__variantName ;Find the variant name CMP R0,#0 ;Is there a name? BEQ %10fm__handler2 ;No -- retur now then MOV R1,R0 ;Put it in R1 MOV R0,R2 ;Copy it to here MOV R14,#'.' ;We want a '.' first STRB R14,[R0],#1 ;Store in the string BL str_cpy ;Copy over the string 10fm__handler2 MOV R0,#fmEvent_select ;The event type ADR R1,fm__name ;Point to the name BL fm__dispatch ;Dispatch the event LDMFD R13!,{R1-R3,PC}^ ;Load back registers LTORG ; --- fm__dispatch --- ; ; On entry: R0-R9 == event data ; R12 == workspace pointer ; ; On exit: -- ; ; Use: Sends an event to the users font menu handler. fm__dispatch ROUT STMFD R13!,{R9,R10,R12,R14} ;Stack registers ADR R14,fm__userHandler ;Point to the handler LDMIA R14,{R9,R10,R12} ;Load registers CMP R9,#0 ;Sanity check MOV R14,PC ;Sey up return address MOVNE PC,R9 ;Call the handler LDMFD R13!,{R9,R10,R12,PC}^ ;Return to caller LTORG ; --- fm_tickFont --- ; ; On entry: R0 == name to tick ; ; On exit: -- ; ; Use: Ticks the font with tht given name in the fontmenu. If ; no font exists then the existing ticks are removed EXPORT fm_tickFont fm_tickFont ROUT CMP R0,#0 ;Is R0 NULL? MOVEQS PC,R14 ;Yes -- return now STMFD R13!,{R0-R4,R14} ;Stack some registers WSPACE fm__wSpace ;Locate my workspace MOV R1,R0 ;Put the name in R1 MOV R0,R11 ;Point to the scratchpad BL str_cpy ;Copy the string over MOV R1,R11 ;Put the pointer in R1 BL fm__parse ;Parse up the string MOVCS R4,#1 ;Not regular MOVCC R4,#0 ;Yes it is sir MOV R3,R1 ;Put variant name in R3 ; --- Clear the existing ticks --- MOV R14,#0 ;Get a NULL word STR R14,fm__ticks ;Clear first tick STR R14,fm__ticks+4 ;And second tick ; --- Search for the font name --- LDR R1,fm__menu ;Point to the menu definition MOV R2,#0 ;Index so far 00fm_tickFont LDR R14,[R1],#4 ;Load the flags word TST R14,#mFlag_end ;Have we reached the end? BNE %90fm_tickFont ;Yes -- return BL str_icmp ;Does this name match BEQ %50fm_tickFont ;Yes -- jump ahead 10fm_tickFont LDRB R14,[R1],#1 ;Load a character CMP R14,#0 ;Is it a terminator? BNE %10fm_tickFont ;No -- keep on looking ADD R1,R1,#3+8 ;Word align, skip over data BIC R1,R1,#3 ADD R2,R2,#1 ;Increment the index B %00fm_tickFont ;Keep on looking ; --- We have found a match --- ; ; First we must get the tick word thing 50fm_tickFont LDRB R14,[R1],#1 ;Load a character CMP R14,#0 ;Is it a terminator? BNE %50fm_tickFont ;No -- keep on looking ADD R1,R1,#3+4 ;Word align, pount to thing BIC R1,R1,#3 LDR R14,[R1] ;Load the data word thing STR R14,fm__ticks ;Store as first level tick ; --- Now search the submenu --- LDR R1,fm__block ;Point to table LDR R1,[R1,R2,LSL #2] ;Load submenu pointer CMP R1,#0 ;Is there one? BEQ %90fm_tickFont ;Nope -- return MOV R0,R3 ;Put variant name in R0 ; --- Skip over title data --- ADD R1,R1,#4 ;Skip over flags word 52fm_tickFont LDRB R14,[R1],#1 ;Load a byte CMP R14,#0 ;Have we reach the end? BNE %52fm_tickFont ;No -- keep looking ADD R1,R1,#3 ;Word align BIC R1,R1,#3 ; --- Select 'Regular' if appropriate --- CMP R4,#0 ;Did user select 'Regular'? ADDEQ R1,R1,#4 ;Yes -- skip over glags BEQ %58fm_tickFont ;...and tick this one then ; --- Now search for the family name --- 54fm_tickFont LDR R14,[R1],#4 ;Load the flags word TST R14,#mFlag_end ;Have we reached the end? BNE %90fm_tickFont ;Yes -- return BL str_icmp ;Does this name match BEQ %58fm_tickFont ;Yes -- jump ahead 56fm_tickFont LDRB R14,[R1],#1 ;Load a character CMP R14,#0 ;Is it a terminator? BNE %56fm_tickFont ;No -- keep on looking ADD R1,R1,#3+8 ;Word align, skip over data BIC R1,R1,#3 B %54fm_tickFont ;Keep on looking ; --- We have found a match --- 58fm_tickFont LDRB R14,[R1],#1 ;Load a character CMP R14,#0 ;Is it a terminator? BNE %58fm_tickFont ;No -- keep on looking ADD R1,R1,#3+4 ;Word align, pount to thing BIC R1,R1,#3 LDR R14,[R1] ;Load the data word thing STR R14,fm__ticks+4 ;Store as first level tick ; --- Return to caller --- 90fm_tickFont LDMFD R13!,{R0-R4,PC}^ ;Return to caller LTORG ; --- fm__familyName --- ; ; On entry: R1 == index of name ; R12 == workspace pointer ; ; On exit: R0 == poiner to family name ; ; Use: Points to the family name for the given menu index fm__familyName ROUT STMFD R13!,{R1,R14} ;Stack registers LDR R0,fm__menu ;Point to the menu block ADD R0,R0,#4 ;Skip over flags word CMP R1,#0 ;Is this index 0? BEQ %90fm__familyName ;Yes -- return happy then 00 LDRB R14,[R0],#1 ;Load a byte CMP R14,#0 ;Is it the end? BNE %00fm__familyName ;No -- keep looking ADD R0,R0,#3+8+4 ;Word align and point to next BIC R0,R0,#3 SUBS R1,R1,#1 ;Decrement the count BNE %00fm__familyName ;And keep on looking 90 LDMFD R13!,{R1,PC}^ ;Return to caller LTORG ; --- fm__variantName --- ; ; On entry: R0 == pointer to submenu ; R1 == index of name ; R12 == workspace pointer ; ; On exit: R0 == poiner to family name, or 0 for regular ; ; Use: Points to the family name for the given menu index fm__variantName ROUT STMFD R13!,{R1,R14} ;Stack registers ADD R0,R0,#4 ;Skip over flags word 00 LDRB R14,[R0],#1 ;Load a byte CMP R14,#0 ;Is it the end? BNE %00fm__variantName ;No -- keep looking ADD R0,R0,#3+4 ;Word align and point to fst BIC R0,R0,#3 CMP R1,#0 ;Is this index 0? BEQ %90fm__variantName ;Yes -- return happy then 10 LDRB R14,[R0],#1 ;Load a byte CMP R14,#0 ;Is it the end? BNE %10fm__variantName ;No -- keep looking ADD R0,R0,#3+8+4 ;Word align and point to next BIC R0,R0,#3 SUBS R1,R1,#1 ;Decrement the count BNE %10fm__variantName ;And keep on looking 90 MOV R1,R0 ;Put string in R1 ADR R0,fm__regular ;Point to regular name BL msgs_lookup ;Translate it BL str_cmp ;Is this a match? MOVNE R0,R1 ;No -- return name then MOVEQ R0,#0 ;Yes -- return 0 then LDMFD R13!,{R1,PC}^ ;Return to caller LTORG ; --- fm__parse --- ; ; On entry: R1 == pointer to font name ; ; On exit: R0 == pointer to font family name (R1 on entry) ; R1 == pointer to font variant name ; CS if variant spcified explicitly, CC if `Regular' ; ; Use: Parses a font name into a family and variant. fm__parse ROUT STMFD R13!,{R2,R3,R14} ;Save some registers MOV R2,R1 ;Look after start pointer 00fm__parse LDRB R14,[R1],#1 ;Load next byte from name CMP R14,#'.' ;Is this a dot? BEQ %10fm__parse ;Yes -- found the variant CMP R14,#32 ;Is this the end? BCS %00fm__parse ;No -- keep looking then ; --- Reached end of name -- must be (Regular) --- MOV R14,#0 ;Zero terminate for luck STRB R14,[R1,#-1] ;Save it over the terminator ADR R0,fm__regular ;Find the regular message BL msgs_lookup ;Translate it nicely MOV R3,R1 ;Point to variant buffer 05fm__parse LDRB R14,[R0],#1 ;Load a byte from `Regular' CMP R14,#32 ;Is this a control char? MOVCC R14,#0 ;Yes -- zero terminate then STRB R14,[R3],#1 ;Store in destination BCS %05fm__parse ;And loop round for the rest MOV R0,R2 ;Point to family name again LDMFD R13!,{R2,R3,R14} ;Unstack registers BICS PC,R14,#C_flag ;And return to caller ; --- Found a variant --- 10fm__parse MOV R14,#0 ;Zero terminate for luck STRB R14,[R1,#-1] ;Save it over the terminator MOV R0,R2 ;Point to family name again LDMFD R13!,{R2,R3,R14} ;Unstack registers ORRS PC,R14,#C_flag ;And return to caller fm__regular DCB "fmREG:(Regular)",0 LTORG ; --- fm__ensure --- ; ; On entry: R0 == address of anchor and size info ; R1 == free space required ; ; On exit: R0 == address of first free byte in area ; May return an error ; ; Use: Ensures that there is the requested quantity of memory free ; in the given block. fm__ensure ROUT STMFD R13!,{R1,R2,R14} ;Save some registers LDMIB R0,{R2,R14} ;Load used and size words ADD R1,R1,R2 ;Find new total size STR R1,[R0,#4] ;Save this back ADD R1,R1,#255 ;Align up to next 256 BIC R1,R1,#255 ;For niceness's sake CMP R1,R14 ;Do we already have enough? BHI %50fm__ensure ;No -- allocate some more 10fm__ensure STR R1,[R0,#8] ;Save new total size LDR R0,[R0,#0] ;Load address of block ADD R0,R0,R2 ;Point to first free byte LDMFD R13!,{R1,R2,R14} ;And return to caller BICS PC,R14,#V_flag 50fm__ensure BL flex_extend ;No -- then extend the block BCC %10fm__ensure ;If OK, rejoin the main thing BL alloc_error ;Find an error message LDMFD R13!,{R1,R2,R14} ;Restore registers ORRS PC,R14,#V_flag ;And return the error LTORG ; --- fm__string --- ; ; On entry: R0 == pointer to anchor and size info ; R1 == pointer to null terminated string ; ; On exit: R0 == length of the string+1 ; May return an error ; ; Use: Writes a string on the end of the given block. fm__string ROUT STMFD R13!,{R0-R3,R14} ;Save some registers MOV R2,R0 ;Look after the anchor ptr MOV R3,R1 ;Keep the string address MOV R0,R1 ;Point to the string BL str_len ;Find the length of it ADD R1,R0,#1 ;Allow space for terminator STR R1,[R13,#0] ;Save this as return value MOV R0,R2 ;Point to the anchor BL fm__ensure ;Make sure there's enough MOVVC R1,R3 ;Point to string to write BLVC str_cpy ;Copy the string over STRVS R0,[R13,#0] ;If it failed, return error LDMFD R13!,{R0-R3,PC} ;And return to caller LTORG ; --- fm__align --- ; ; On entry: R0 == pointer to anchor and size info ; ; On exit: -- ; ; Use: Word aligns the block output address. fm__align ROUT STMFD R13!,{R14} ;Save a register LDR R14,[R0,#4] ;Load the current used offset ADD R14,R14,#3 ;Round up to word boundary BIC R14,R14,#3 ;And do the round op STR R14,[R0,#4] ;Save the offset back again LDMFD R13!,{PC}^ ;And return to caller LTORG ; --- fm__fontPath --- ; ; On entry: R0 == pointer to buffer ; ; On exit: CS if there is a font path ; CC otherwise ; ; Use: Reads the environmental variable font$path and copies ; it into the buffer given. The buffer must be at least 256 ; bytes long. fm__fontPath ROUT STMFD R13!,{R0-R4,R14} MOV R1,R0 ;But buffer ptr in R1 ADR R0,fm__varName ;Point to the name MOV R2,#256 ;Length of buffer MOV R3,#0 ;First (and last) call MOV R4,#0 ;Don't expand the string SWI XOS_ReadVarVal ;Read the variable MOV R14,#0 ;We need a NULL byte STRVCB R14,[R1,R2] ;Store the terminator LDMFD R13!,{R0-R4,R14} ;Load registers ORRVCS PC,R14,#C_flag ;Return C set if exists BICVSS PC,R14,#C_flag ;Or clear otherwise fm__varName DCB "Font$Path",0 LTORG fm__wSpace DCD 0 ; --- fm__postFilter --- ; ; On entry: R0 == wimp event ; R1 == wimp poll block pointer ; ; On exit: -- ; ; Use: Looks out for font changed events. fm__postFilter ROUT CMP R0,#17 ;Is it a message? CMPNE R0,#18 MOVNES PC,R14 ;Nope -- return STMFD R13!,{R0,R14} ;Stack registers LDR R0,[R1,#16] ;Load the message type LDR R14,=&4A2C0 ;Fonts changed message number CMP R14,R0 ;Is that the message? LDMNEFD R13!,{R0,PC}^ ;No -- return now LDR R14,fm__flags ;Load flags word ORR R14,R14,#fmFlag__changed STR R14,fm__flags ;Store back flags LDMFD R13!,{R0,PC}^ ;Return to caller LTORG ; --- fm_init --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Initialises the font menu system. EXPORT fm_init fm_init ROUT STMFD R13!,{R0,R1,R12,R14} ;Stack some registers WSPACE fm__wSpace MOV R14,#0 STR R14,fm__flags ;No flags set yet ; --- Set up the post filter --- BL event_init ;Ensure event is ready ADR R0,fm__postFilter ;Point to the handler MOV R1,R12 ;R12 value to pass BL event_postFilter ;Add in the post filter SWIVS OS_GenerateError ;Generate the error LDMFD R13!,{R0,R1,R12,PC}^ ;Return to caller LTORG ;----- Events --------------------------------------------------------------- ^ 0 fmEvent_select # 1 ;User selected a font ;R1 == pointer to name ;----- Workspace ------------------------------------------------------------ ^ 0,R12 fm__wStart # 0 fm__block # 4 ;Address of our heap block fm__ticks # 8 ;Tick blocks fm__menu # 4 ;Pointer to existing menu fm__name # 40 ;Static buffer to return name fm__userHandler # 4 ;User handler function fm__R10 # 4 ;R10 value to call with fm__R12 # 4 ;R12 value to call with fm__creator # 4 ;Menu creation routine fm__flags # 4 ;Useful flags word fm__path # 256 ;Current font path fm__wSize EQU {VAR}-fm__wStart fmFlag__changed EQU (1<<0) ;The fonts have changed AREA |Sapphire$$LibData|,CODE,READONLY DCD fm__wSize DCD fm__wSpace DCD 256 DCD fm_init ;----- That's all, folks ---------------------------------------------------- END