4 ; Gives you a nice box from which the user may choose a WIMP colour
6 ; © 1994-1998 Straylight
9 ;----- Licensing note -------------------------------------------------------
11 ; This file is part of Straylight's Sapphire library.
13 ; Sapphire is free software; you can redistribute it and/or modify
14 ; it under the terms of the GNU General Public License as published by
15 ; the Free Software Foundation; either version 2, or (at your option)
18 ; Sapphire is distributed in the hope that it will be useful,
19 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 ; GNU General Public License for more details.
23 ; You should have received a copy of the GNU General Public License
24 ; along with Sapphire. If not, write to the Free Software Foundation,
25 ; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 ;----- Standard Header ------------------------------------------------------
34 ;----- External dependencies ------------------------------------------------
42 ;----- Main code ------------------------------------------------------------
44 AREA |Sapphire$$Code|,CODE,READONLY
48 ; On entry: R0 == pointer to a title string (message tag)
49 ; R1 == the current colour in bottom byte, and flags:
50 ; bit 8 == allow transparent colour
51 ; R2 == event handler to call
52 ; R3 == R10 value to pass to handler
53 ; R4 == R12 value to pass to handle
55 ; On exit: May return an error
57 ; Use: Opens a dialogue box which allows the user to choose
58 ; one of the wimp colours. A transparent colour is supported,
59 ; and represented as colour 255.
64 STMFD R13!,{R0-R5,R12,R14}
67 ; --- Set up some workspace ---
69 STMIB R12,{R2-R4} ;Save useful information
70 STRB R1,cb__defColour ;Store default colour
72 ; --- Create my dialogue box ---
74 ADR R0,cb__name ;Point to the dbox name
75 BL dbox_create ;Try to create it
76 BVS %90colourBox ;Return possible error
77 MOV R4,R0 ;Look after dialogue handle
79 ; --- Set up current and old colours ---
81 MOV R2,#-1 ;No old icon yet
82 BL cb__borderIcon ;Draw the border
84 STRB R1,cb__currentCol ;Currently selected colour
85 AND R14,R1,#&FF ;Get the actual colour
86 CMP R14,#&FF ;Is colour transparent?
87 MOVEQ R14,#7 ;Yes -- use black then
88 STRB R14,cb__oldCol ;Make this last colour
90 ; --- If necessary, delete the transparent icon ---
92 TST R1,#256 ;Is the transparent bit set?
93 BNE %10colourBox ;Yes -- leave it then
94 BL dbox_window ;Find dialogue's window
95 MOV R1,#cbIcon__trans ;Get transparent icon handle
96 MOV R2,#1<<23 ;Set the deleted flag
98 STMFD R13!,{R0-R3} ;Save that on the stack
99 MOV R1,R13 ;Point to the block
100 SWI Wimp_SetIconState ;And set the icons up
101 ADD R13,R13,#16 ;Restore the stack
103 ; --- Set up the dialogue box now ---
105 10colourBox MOV R0,R4 ;Fetch dialogue handle
106 ADR R1,cb__eventHandler ;Point to the event handler
107 MOV R2,#0 ;No R10 required
108 MOV R3,R12 ;Pass workspace in R12
109 BL dbox_eventHandler ;Set up the event handler
111 ; --- Fill in the dialogue title ---
113 LDR R0,[R13,#0] ;Load title pointer
114 BL msgs_lookup ;Translate the tag
115 MOV R2,R0 ;Put this in R2
116 MOV R0,R4 ;Get handle back
117 MOV R1,#-1 ;Change the title
118 BL dbox_setField ;Set the title
120 ; --- Display the dialogue ---
122 MOV R1,#dbOpen_pointer ;Open over the pointer
123 BL dbox_open ;Open the dbox then
125 ; --- Move the caret out of the icon ---
127 BL dbox_window ;Get the window handle
128 MOV R1,#-1 ;Move out of any icons
129 MOV R2,#&FFFFFF ;Move well away from visible
130 MOV R3,#&FFFFFF ;area so no-one will see
131 MOV R4,#16 ;Make the caret fairly small
132 MOV R5,#-1 ;No sensible string index
133 SWI Wimp_SetCaretPosition ;Set the caret position
135 ; --- That's it, then ---
137 LDMFD R13!,{R0-R5,R12,R14} ;Load back registers
138 BICS PC,R14,#V_flag ;Return without error
140 90colourBox ADD R13,R13,#4 ;Skip over R0
141 LDMFD R13!,{R1-R5,R12,R14} ;Load back registers
142 ORRS PC,R14,#V_flag ;Return with error
144 cb__name DCB "colourBox",0
148 ; --- cb__borderIcon ---
150 ; On entry: R0 == dbox handle
151 ; R1 == colour to `border'
152 ; R2 == old colour (-1 for none)
156 ; Use: Removes the border from the old icon, and puts one on the
161 CMP R1,R2 ;Are colours the same?
162 MOVEQS PC,R14 ;Yes -- return then
164 ; --- Sort out what to do now ---
166 STMFD R13!,{R0-R5,R14} ;Save some registers
167 SUB R13,R13,#80 ;Make a big block
168 AND R5,R1,#&FF ;Clear extraneous flag bits
169 MOV R4,R0 ;Look after dialogue handle
170 CMP R2,#-1 ;Old colour to clear?
171 BEQ %10cb__borderIcon ;No -- don't bother then
173 ; --- Clear border from old colour ---
175 CMP R2,#255 ;Is colour transparent?
176 BEQ %05cb__borderIcon ;Yes -- handle that then
178 BL dbox_window ;Get window handle of dbox
179 ADD R1,R2,#cbIcon__colours ;Find icon handle of colour
180 MOV R2,#0 ;Don't set any bits
181 MOV R3,#5 ;Clear border and text bits
182 STMIA R13,{R0-R3} ;Save them in my block
183 MOV R1,R13 ;Point to the block
184 SWI Wimp_SetIconState ;And change the icon
185 B %10cb__borderIcon ;Now border the new colour
187 ; --- Turn off the `transparent' switch ---
189 05 MOV R1,#cbIcon__trans ;Get the icon handle
190 MOV R2,#0 ;Turn the icon off
191 BL dbox_select ;And deselect the icon
193 ; --- Now turn on the new colour ---
195 10 CMP R5,#&FF ;Is new colour transparent?
196 BEQ %15cb__borderIcon ;Yes -- handle that then
198 ; --- Sort out a contrasting colour ---
200 ; This is actually quite hard. RISC_OSLib uses a hack
201 ; to do this job. I use ColourTrans instead, because it's
202 ; easier. The algorithm is simple: take the original
203 ; colour, and decide which, out of black and white, is
204 ; furthest away from it. Then try and find the closest
205 ; match to that in the Wimp palette.
207 MOV R1,R13 ;Point to my big block
208 SWI Wimp_ReadPalette ;Read the Wimp's palette
209 LDR R0,[R13,R5,LSL #2] ;Load the palette entry
210 MOV R1,#0 ;Choose a two-colour mode
211 ADR R2,cb__bwPal ;Point to black'n'white pal
212 SWI ColourTrans_ReturnOppColourNumberForMode ;!!!
213 LDR R0,[R2,R0,LSL #2] ;Load `black' or `white'
214 MOV R1,#12 ;Choose a 16 colour mode
215 MOV R2,R13 ;And point at Wimp palette
216 SWI ColourTrans_ReturnColourNumberForMode ;!!
218 ; --- Now set the icon border ---
220 MOV R2,R0,LSL #24 ;Set this as foreground col
221 MOV R0,R4 ;Get the dialogue handle
222 BL dbox_window ;Get a window handle from it
223 ADD R1,R5,#cbIcon__colours ;Find the icon handle
224 ORR R2,R2,#5 ;Set the border and text bits
225 MOV R3,#5 ;Change border and text
226 ORR R3,R3,#&0F000000 ;Also change foreground col
227 STMIA R13,{R0-R3} ;Save them in my block
228 MOV R1,R13 ;Point to the block
229 SWI Wimp_SetIconState ;And change the icon
230 B %50cb__borderIcon ;Tidy up and go home
232 cb__bwPal DCD &00000000
235 ; --- Turn on the `transparent' switch ---
237 ; `Hey, transparent switch, I really dig you.'
239 15 MOV R0,R4 ;Get the dialogue handle
240 MOV R1,#cbIcon__trans ;Get transparent icon handle
241 MOV R2,#1 ;Turn the icon on
242 BL dbox_select ;Select this icon
244 ; --- Tidy up and return ---
246 50 ADD R13,R13,#80 ;Restore the stack
247 LDMFD R13!,{R0-R5,PC}^ ;And return to caller
251 ; --- cb__eventHandler ---
253 ; On entry: R0 == dbox event
254 ; R1-R8 depend on event code
259 ; Use: Handles events onthe colour box.
261 cb__eventHandler ROUT
263 CMP R0,#dbEvent_close ;Has the dbox been closed?
264 BEQ %10cb__eventHandler ;Yes -- destroy it then
265 CMP R0,#dbEvent_cancel ;Was cancel pressed?
266 CMPNE R0,#cbIcon__cancel
267 BEQ %20cb__eventHandler ;Yes -- do the right thing
268 CMP R0,#dbEvent_OK ;How about OK?
269 CMPNE R0,#cbIcon__ok ;Well -- it had to happen
270 BEQ %30cb__eventHandler ;Yes -- do the right thing
271 CMP R0,#cbIcon__trans ;Click on transparent switch?
272 BEQ %40cb__eventHandler ;Yes -- do the right thing
273 CMP R0,#dbEvent_key ;Was a key pressed?
274 BEQ %50cb__eventHandler ;Yes -- deal with it then
276 ; --- Must be a click on a colour ---
278 STMFD R13!,{R0-R2,R14} ;Stack registers
279 SUB R1,R0,#cbIcon__colours ;Turn into a colour
280 CMP R1,#16 ;Is it in range?
281 LDMCSFD R13!,{R0-R2,PC}^ ;No -- then ignore it
282 LDRB R2,cb__currentCol ;Load the old colour
283 MOV R0,R9 ;Get the handle
284 BL cb__borderIcon ;Select it
285 STRB R1,cb__currentCol ;Store back the new colour
286 STRB R1,cb__oldCol ;Remember this
287 LDMFD R13!,{R0-R2,PC}^ ;Return to caller
289 ; --- Dialogue box has been closed ---
291 10 STMFD R13!,{R0,R14} ;Stack registers
292 MOV R0,R9 ;Put handle in R0
293 BL dbox_destroy ;Destroy the dbox
294 LDMFD R13!,{R0,PC}^ ;Return to caller
296 ; --- User clicked the cancel button ---
298 20 STMFD R13!,{R0-R3,R14} ;Stack registers
299 MOV R0,R9 ;Get the dbox handle
300 MOV R3,R1 ;Remember the button status
301 MOV R1,#cbIcon__cancel ;The cancel button
302 BL dbox_slab ;Slab in the icon
303 TST R3,#1 ;Was Adjust clicked?
304 BEQ %25cb__eventHandler ;No -- jump ahead
306 LDRB R2,cb__currentCol ;Load the old colour
307 LDRB R1,cb__defColour ;And the default colour
308 BL cb__borderIcon ;Select it
309 STRB R1,cb__currentCol ;Store back the new colour
310 CMP R1,#255 ;Is the colour transparent?
311 MOVEQ R1,#7 ;Yes -- use black instead
312 STRB R1,cb__oldCol ;Save old colour
314 25 TST R3,#1 ;Was Adjust clicked?
315 BLEQ dbox_close ;No -- close the dbox
316 BL dbox_unslab ;Unslab the icon
317 BLEQ dbox_destroy ;No -- destroy the dbox
318 LDMFD R13!,{R0-R3,PC} ;Return to caller
320 ; --- User clicked OK ---
322 30 STMFD R13!,{R0-R3,R14} ;Stack registers
323 MOV R0,R9 ;Get the dbox handle
324 MOV R3,R1 ;Remember the button status
325 MOV R1,#cbIcon__ok ;The OK button
326 BL dbox_slab ;Slab in the icon
328 LDRB R2,cb__currentCol ;Load the current colour
329 STRB R2,cb__defColour ;Store this as default colour
330 MOV R1,R2 ;Put the colour in R1
331 MOV R0,#cbEvent_select ;The event type
332 BL cb__dispatch ;Dispatch the event
334 MOV R0,R9 ;Get the handle back again
335 TST R3,#1 ;Was `Adjust' clicked?
336 BLEQ dbox_close ;No -- close the dbox
337 BL dbox_unslab ;Unslab the icon
338 BLEQ dbox_destroy ;No -- destroy the dbox
339 LDMFD R13!,{R0-R3,PC}^ ;Return to caller
341 ; --- User clicked on transparent ---
343 40 STMFD R13!,{R0-R2,R14} ;Save some registers
344 MOV R0,R9 ;Fetch dialogue handle
345 MOV R1,#cbIcon__trans ;Get transparent icon handle
346 BL dbox_isSelected ;Is this icon selected?
347 MOVCC R1,#255 ;No -- turn it on
348 LDRCCB R2,cb__currentCol ;And get the old colour
349 LDRCSB R1,cb__oldCol ;Otherwise get previous col
350 MOVCS R2,#255 ;And say current is trans
351 BL cb__borderIcon ;Border the icon nicely
352 STRB R1,cb__currentCol ;And update current colour
353 LDMFD R13!,{R0-R2,PC}^ ;Return to caller
355 ; --- User pressed a key ---
357 50 CMP R1,#&100 ;Is the code in top half?
358 MOVCCS PC,R14 ;No -- ignore the code
360 STMFD R13!,{R0-R2,R14} ;Save some registers
361 LDRB R2,cb__currentCol ;What's the current colour?
362 CMP R2,#&FF ;Is it transparent?
363 LDMEQFD R13!,{R0-R2,PC}^ ;And return to caller
365 AND R1,R1,#&FF ;Keep only the bottom byte
366 MOV R14,#0 ;Clear the mask value
368 CMP R1,#key_Left :AND: &FF ;Is this a left cursor?
369 MOVEQ R14,#2_1100 ;Yes -- check top bits
370 MOVEQ R0,#-1 ;And subtract one
371 CMP R1,#key_Right :AND: &FF ;Is this a right cursor?
372 MOVEQ R14,#2_1100 ;Yes -- check top bits
373 MOVEQ R0,#1 ;And add one
374 CMP R1,#key_Up :AND: &FF ;Is this an up cursor?
375 MVNEQ R14,#2_1100 ;Yes -- check bottom bits
376 MOVEQ R0,#-4 ;And subtract four
377 CMP R1,#key_Down :AND: &FF ;Is this a down cursor?
378 MVNEQ R14,#2_1100 ;Yes -- check bottom bits
379 MOVEQ R0,#4 ;And add four
381 CMP R14,#0 ;Is R14 now set?
382 LDMEQFD R13!,{R0-R2,PC}^ ;No -- then leave now
384 ADD R1,R2,R0 ;Add the correct value
385 EOR R0,R1,R2 ;Check which bits changed
386 TST R0,R14 ;Did something wrong happen?
387 MOVEQ R0,R9 ;Fetch dialogue handle
388 BLEQ cb__borderIcon ;Border the correct icon
389 STREQB R1,cb__currentCol ;And store the new colour
390 STREQB R1,cb__oldCol ;And as the last non-trans
391 LDMFD R13!,{R0-R2,R14} ;Restore registers
392 ORRS PC,R14,#C_flag ;Claim the keypress
396 ; --- cb__dispatch ---
398 ; On entry: R0-R8 to be sent to event handler
402 ; Use: Sends an event the owner of the colour box.
406 STMFD R13!,{R9,R10,R12,R14} ;Stak registers
407 LDMIB R12,{R9,R10,R12} ;Load data things
408 CMP R9,#0 ;Sanity check
409 MOV R14,PC ;Set up return address
410 MOVNE PC,R9 ;Call the handler
411 LDMFD R13!,{R9,R10,R12,PC}^ ;Return to caller
417 ;----- Events ---------------------------------------------------------------
420 cbEvent_select # 1 ;User selected a colour
421 ;R1 == colour selected
423 ;----- Icon numbers ---------------------------------------------------------
425 cbIcon__ok EQU 0 ;The OK button
426 cbIcon__cancel EQU 1 ;The Cancel button
427 cbIcon__trans EQU 2 ;The Transparent switch
428 cbIcon__colours EQU 4 ;Base of colour patches
430 ;----- Workspace ------------------------------------------------------------
435 cb__defColour # 1 ;The default colour
436 cb__currentCol # 1 ;Currently selected colour
437 cb__oldCol # 1 ;Last non-transparent colour
438 cb__handler # 12 ;User handler information
440 cb__wSize EQU {VAR}-cb__wStart
442 AREA |Sapphire$$LibData|,CODE,READONLY
449 ;----- That's all, folks ----------------------------------------------------