; ; colourBox.s ; ; Gives you a nice box from which the user may choose a WIMP colour ; ; © 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:dbox GET sapphire:msgs GET sapphire:sapphire GET sapphire:keyMap ;----- Main code ------------------------------------------------------------ AREA |Sapphire$$Code|,CODE,READONLY ; --- colourBox --- ; ; On entry: R0 == pointer to a title string (message tag) ; R1 == the current colour in bottom byte, and flags: ; bit 8 == allow transparent colour ; R2 == event handler to call ; R3 == R10 value to pass to handler ; R4 == R12 value to pass to handle ; ; On exit: May return an error ; ; Use: Opens a dialogue box which allows the user to choose ; one of the wimp colours. A transparent colour is supported, ; and represented as colour 255. EXPORT colourBox colourBox ROUT STMFD R13!,{R0-R5,R12,R14} WSPACE cb__wSpace ; --- Set up some workspace --- STMIB R12,{R2-R4} ;Save useful information STRB R1,cb__defColour ;Store default colour ; --- Create my dialogue box --- ADR R0,cb__name ;Point to the dbox name BL dbox_create ;Try to create it BVS %90colourBox ;Return possible error MOV R4,R0 ;Look after dialogue handle ; --- Set up current and old colours --- MOV R2,#-1 ;No old icon yet BL cb__borderIcon ;Draw the border STRB R1,cb__currentCol ;Currently selected colour AND R14,R1,#&FF ;Get the actual colour CMP R14,#&FF ;Is colour transparent? MOVEQ R14,#7 ;Yes -- use black then STRB R14,cb__oldCol ;Make this last colour ; --- If necessary, delete the transparent icon --- TST R1,#256 ;Is the transparent bit set? BNE %10colourBox ;Yes -- leave it then BL dbox_window ;Find dialogue's window MOV R1,#cbIcon__trans ;Get transparent icon handle MOV R2,#1<<23 ;Set the deleted flag MOV R3,#1<<23 STMFD R13!,{R0-R3} ;Save that on the stack MOV R1,R13 ;Point to the block SWI Wimp_SetIconState ;And set the icons up ADD R13,R13,#16 ;Restore the stack ; --- Set up the dialogue box now --- 10colourBox MOV R0,R4 ;Fetch dialogue handle ADR R1,cb__eventHandler ;Point to the event handler MOV R2,#0 ;No R10 required MOV R3,R12 ;Pass workspace in R12 BL dbox_eventHandler ;Set up the event handler ; --- Fill in the dialogue title --- LDR R0,[R13,#0] ;Load title pointer BL msgs_lookup ;Translate the tag MOV R2,R0 ;Put this in R2 MOV R0,R4 ;Get handle back MOV R1,#-1 ;Change the title BL dbox_setField ;Set the title ; --- Display the dialogue --- MOV R1,#dbOpen_pointer ;Open over the pointer BL dbox_open ;Open the dbox then ; --- Move the caret out of the icon --- BL dbox_window ;Get the window handle MOV R1,#-1 ;Move out of any icons MOV R2,#&FFFFFF ;Move well away from visible MOV R3,#&FFFFFF ;area so no-one will see MOV R4,#16 ;Make the caret fairly small MOV R5,#-1 ;No sensible string index SWI Wimp_SetCaretPosition ;Set the caret position ; --- That's it, then --- LDMFD R13!,{R0-R5,R12,R14} ;Load back registers BICS PC,R14,#V_flag ;Return without error 90colourBox ADD R13,R13,#4 ;Skip over R0 LDMFD R13!,{R1-R5,R12,R14} ;Load back registers ORRS PC,R14,#V_flag ;Return with error cb__name DCB "colourBox",0 LTORG ; --- cb__borderIcon --- ; ; On entry: R0 == dbox handle ; R1 == colour to `border' ; R2 == old colour (-1 for none) ; ; On exit: -- ; ; Use: Removes the border from the old icon, and puts one on the ; new icon. cb__borderIcon ROUT CMP R1,R2 ;Are colours the same? MOVEQS PC,R14 ;Yes -- return then ; --- Sort out what to do now --- STMFD R13!,{R0-R5,R14} ;Save some registers SUB R13,R13,#80 ;Make a big block AND R5,R1,#&FF ;Clear extraneous flag bits MOV R4,R0 ;Look after dialogue handle CMP R2,#-1 ;Old colour to clear? BEQ %10cb__borderIcon ;No -- don't bother then ; --- Clear border from old colour --- CMP R2,#255 ;Is colour transparent? BEQ %05cb__borderIcon ;Yes -- handle that then BL dbox_window ;Get window handle of dbox ADD R1,R2,#cbIcon__colours ;Find icon handle of colour MOV R2,#0 ;Don't set any bits MOV R3,#5 ;Clear border and text bits STMIA R13,{R0-R3} ;Save them in my block MOV R1,R13 ;Point to the block SWI Wimp_SetIconState ;And change the icon B %10cb__borderIcon ;Now border the new colour ; --- Turn off the `transparent' switch --- 05 MOV R1,#cbIcon__trans ;Get the icon handle MOV R2,#0 ;Turn the icon off BL dbox_select ;And deselect the icon ; --- Now turn on the new colour --- 10 CMP R5,#&FF ;Is new colour transparent? BEQ %15cb__borderIcon ;Yes -- handle that then ; --- Sort out a contrasting colour --- ; ; This is actually quite hard. RISC_OSLib uses a hack ; to do this job. I use ColourTrans instead, because it's ; easier. The algorithm is simple: take the original ; colour, and decide which, out of black and white, is ; furthest away from it. Then try and find the closest ; match to that in the Wimp palette. MOV R1,R13 ;Point to my big block SWI Wimp_ReadPalette ;Read the Wimp's palette LDR R0,[R13,R5,LSL #2] ;Load the palette entry MOV R1,#0 ;Choose a two-colour mode ADR R2,cb__bwPal ;Point to black'n'white pal SWI ColourTrans_ReturnOppColourNumberForMode ;!!! LDR R0,[R2,R0,LSL #2] ;Load `black' or `white' MOV R1,#12 ;Choose a 16 colour mode MOV R2,R13 ;And point at Wimp palette SWI ColourTrans_ReturnColourNumberForMode ;!! ; --- Now set the icon border --- MOV R2,R0,LSL #24 ;Set this as foreground col MOV R0,R4 ;Get the dialogue handle BL dbox_window ;Get a window handle from it ADD R1,R5,#cbIcon__colours ;Find the icon handle ORR R2,R2,#5 ;Set the border and text bits MOV R3,#5 ;Change border and text ORR R3,R3,#&0F000000 ;Also change foreground col STMIA R13,{R0-R3} ;Save them in my block MOV R1,R13 ;Point to the block SWI Wimp_SetIconState ;And change the icon B %50cb__borderIcon ;Tidy up and go home cb__bwPal DCD &00000000 DCD &FFFFFF00 ; --- Turn on the `transparent' switch --- ; ; `Hey, transparent switch, I really dig you.' 15 MOV R0,R4 ;Get the dialogue handle MOV R1,#cbIcon__trans ;Get transparent icon handle MOV R2,#1 ;Turn the icon on BL dbox_select ;Select this icon ; --- Tidy up and return --- 50 ADD R13,R13,#80 ;Restore the stack LDMFD R13!,{R0-R5,PC}^ ;And return to caller LTORG ; --- cb__eventHandler --- ; ; On entry: R0 == dbox event ; R1-R8 depend on event code ; R9 == dbox handle ; ; On exit: -- ; ; Use: Handles events onthe colour box. cb__eventHandler ROUT CMP R0,#dbEvent_close ;Has the dbox been closed? BEQ %10cb__eventHandler ;Yes -- destroy it then CMP R0,#dbEvent_cancel ;Was cancel pressed? CMPNE R0,#cbIcon__cancel BEQ %20cb__eventHandler ;Yes -- do the right thing CMP R0,#dbEvent_OK ;How about OK? CMPNE R0,#cbIcon__ok ;Well -- it had to happen BEQ %30cb__eventHandler ;Yes -- do the right thing CMP R0,#cbIcon__trans ;Click on transparent switch? BEQ %40cb__eventHandler ;Yes -- do the right thing CMP R0,#dbEvent_key ;Was a key pressed? BEQ %50cb__eventHandler ;Yes -- deal with it then ; --- Must be a click on a colour --- STMFD R13!,{R0-R2,R14} ;Stack registers SUB R1,R0,#cbIcon__colours ;Turn into a colour CMP R1,#16 ;Is it in range? LDMCSFD R13!,{R0-R2,PC}^ ;No -- then ignore it LDRB R2,cb__currentCol ;Load the old colour MOV R0,R9 ;Get the handle BL cb__borderIcon ;Select it STRB R1,cb__currentCol ;Store back the new colour STRB R1,cb__oldCol ;Remember this LDMFD R13!,{R0-R2,PC}^ ;Return to caller ; --- Dialogue box has been closed --- 10 STMFD R13!,{R0,R14} ;Stack registers MOV R0,R9 ;Put handle in R0 BL dbox_destroy ;Destroy the dbox LDMFD R13!,{R0,PC}^ ;Return to caller ; --- User clicked the cancel button --- 20 STMFD R13!,{R0-R3,R14} ;Stack registers MOV R0,R9 ;Get the dbox handle MOV R3,R1 ;Remember the button status MOV R1,#cbIcon__cancel ;The cancel button BL dbox_slab ;Slab in the icon TST R3,#1 ;Was Adjust clicked? BEQ %25cb__eventHandler ;No -- jump ahead LDRB R2,cb__currentCol ;Load the old colour LDRB R1,cb__defColour ;And the default colour BL cb__borderIcon ;Select it STRB R1,cb__currentCol ;Store back the new colour CMP R1,#255 ;Is the colour transparent? MOVEQ R1,#7 ;Yes -- use black instead STRB R1,cb__oldCol ;Save old colour 25 TST R3,#1 ;Was Adjust clicked? BLEQ dbox_close ;No -- close the dbox BL dbox_unslab ;Unslab the icon BLEQ dbox_destroy ;No -- destroy the dbox LDMFD R13!,{R0-R3,PC} ;Return to caller ; --- User clicked OK --- 30 STMFD R13!,{R0-R3,R14} ;Stack registers MOV R0,R9 ;Get the dbox handle MOV R3,R1 ;Remember the button status MOV R1,#cbIcon__ok ;The OK button BL dbox_slab ;Slab in the icon LDRB R2,cb__currentCol ;Load the current colour STRB R2,cb__defColour ;Store this as default colour MOV R1,R2 ;Put the colour in R1 MOV R0,#cbEvent_select ;The event type BL cb__dispatch ;Dispatch the event MOV R0,R9 ;Get the handle back again TST R3,#1 ;Was `Adjust' clicked? BLEQ dbox_close ;No -- close the dbox BL dbox_unslab ;Unslab the icon BLEQ dbox_destroy ;No -- destroy the dbox LDMFD R13!,{R0-R3,PC}^ ;Return to caller ; --- User clicked on transparent --- 40 STMFD R13!,{R0-R2,R14} ;Save some registers MOV R0,R9 ;Fetch dialogue handle MOV R1,#cbIcon__trans ;Get transparent icon handle BL dbox_isSelected ;Is this icon selected? MOVCC R1,#255 ;No -- turn it on LDRCCB R2,cb__currentCol ;And get the old colour LDRCSB R1,cb__oldCol ;Otherwise get previous col MOVCS R2,#255 ;And say current is trans BL cb__borderIcon ;Border the icon nicely STRB R1,cb__currentCol ;And update current colour LDMFD R13!,{R0-R2,PC}^ ;Return to caller ; --- User pressed a key --- 50 CMP R1,#&100 ;Is the code in top half? MOVCCS PC,R14 ;No -- ignore the code STMFD R13!,{R0-R2,R14} ;Save some registers LDRB R2,cb__currentCol ;What's the current colour? CMP R2,#&FF ;Is it transparent? LDMEQFD R13!,{R0-R2,PC}^ ;And return to caller AND R1,R1,#&FF ;Keep only the bottom byte MOV R14,#0 ;Clear the mask value CMP R1,#key_Left :AND: &FF ;Is this a left cursor? MOVEQ R14,#2_1100 ;Yes -- check top bits MOVEQ R0,#-1 ;And subtract one CMP R1,#key_Right :AND: &FF ;Is this a right cursor? MOVEQ R14,#2_1100 ;Yes -- check top bits MOVEQ R0,#1 ;And add one CMP R1,#key_Up :AND: &FF ;Is this an up cursor? MVNEQ R14,#2_1100 ;Yes -- check bottom bits MOVEQ R0,#-4 ;And subtract four CMP R1,#key_Down :AND: &FF ;Is this a down cursor? MVNEQ R14,#2_1100 ;Yes -- check bottom bits MOVEQ R0,#4 ;And add four CMP R14,#0 ;Is R14 now set? LDMEQFD R13!,{R0-R2,PC}^ ;No -- then leave now ADD R1,R2,R0 ;Add the correct value EOR R0,R1,R2 ;Check which bits changed TST R0,R14 ;Did something wrong happen? MOVEQ R0,R9 ;Fetch dialogue handle BLEQ cb__borderIcon ;Border the correct icon STREQB R1,cb__currentCol ;And store the new colour STREQB R1,cb__oldCol ;And as the last non-trans LDMFD R13!,{R0-R2,R14} ;Restore registers ORRS PC,R14,#C_flag ;Claim the keypress LTORG ; --- cb__dispatch --- ; ; On entry: R0-R8 to be sent to event handler ; ; On exit: -- ; ; Use: Sends an event the owner of the colour box. cb__dispatch ROUT STMFD R13!,{R9,R10,R12,R14} ;Stak registers LDMIB R12,{R9,R10,R12} ;Load data things CMP R9,#0 ;Sanity check MOV R14,PC ;Set up return address MOVNE PC,R9 ;Call the handler LDMFD R13!,{R9,R10,R12,PC}^ ;Return to caller LTORG cb__wSpace DCD 0 ;----- Events --------------------------------------------------------------- ^ 0 cbEvent_select # 1 ;User selected a colour ;R1 == colour selected ;----- Icon numbers --------------------------------------------------------- cbIcon__ok EQU 0 ;The OK button cbIcon__cancel EQU 1 ;The Cancel button cbIcon__trans EQU 2 ;The Transparent switch cbIcon__colours EQU 4 ;Base of colour patches ;----- Workspace ------------------------------------------------------------ ^ 0,R12 cb__wStart # 0 cb__defColour # 1 ;The default colour cb__currentCol # 1 ;Currently selected colour cb__oldCol # 1 ;Last non-transparent colour cb__handler # 12 ;User handler information cb__wSize EQU {VAR}-cb__wStart AREA |Sapphire$$LibData|,CODE,READONLY DCD cb__wSize DCD cb__wSpace DCD 0 DCD 0 ;----- That's all, folks ---------------------------------------------------- END