Initial revision
[ssr] / StraySrc / Libraries / Sapphire / s / colourBox
1 ;
2 ; colourBox.s
3 ;
4 ; Gives you a nice box from which the user may choose a WIMP colour
5 ;
6 ; © 1994-1998 Straylight
7 ;
8
9 ;----- Licensing note -------------------------------------------------------
10 ;
11 ; This file is part of Straylight's Sapphire library.
12 ;
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)
16 ; any later version.
17 ;
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.
22 ;
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.
26
27 ;----- Standard Header ------------------------------------------------------
28
29 GET libs:header
30 GET libs:swis
31
32 GET libs:stream
33
34 ;----- External dependencies ------------------------------------------------
35
36 GET sapphire:dbox
37 GET sapphire:msgs
38 GET sapphire:sapphire
39
40 GET sapphire:keyMap
41
42 ;----- Main code ------------------------------------------------------------
43
44 AREA |Sapphire$$Code|,CODE,READONLY
45
46 ; --- colourBox ---
47 ;
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
54 ;
55 ; On exit: May return an error
56 ;
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.
60
61 EXPORT colourBox
62 colourBox ROUT
63
64 STMFD R13!,{R0-R5,R12,R14}
65 WSPACE cb__wSpace
66
67 ; --- Set up some workspace ---
68
69 STMIB R12,{R2-R4} ;Save useful information
70 STRB R1,cb__defColour ;Store default colour
71
72 ; --- Create my dialogue box ---
73
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
78
79 ; --- Set up current and old colours ---
80
81 MOV R2,#-1 ;No old icon yet
82 BL cb__borderIcon ;Draw the border
83
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
89
90 ; --- If necessary, delete the transparent icon ---
91
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
97 MOV R3,#1<<23
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
102
103 ; --- Set up the dialogue box now ---
104
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
110
111 ; --- Fill in the dialogue title ---
112
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
119
120 ; --- Display the dialogue ---
121
122 MOV R1,#dbOpen_pointer ;Open over the pointer
123 BL dbox_open ;Open the dbox then
124
125 ; --- Move the caret out of the icon ---
126
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
134
135 ; --- That's it, then ---
136
137 LDMFD R13!,{R0-R5,R12,R14} ;Load back registers
138 BICS PC,R14,#V_flag ;Return without error
139
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
143
144 cb__name DCB "colourBox",0
145
146 LTORG
147
148 ; --- cb__borderIcon ---
149 ;
150 ; On entry: R0 == dbox handle
151 ; R1 == colour to `border'
152 ; R2 == old colour (-1 for none)
153 ;
154 ; On exit: --
155 ;
156 ; Use: Removes the border from the old icon, and puts one on the
157 ; new icon.
158
159 cb__borderIcon ROUT
160
161 CMP R1,R2 ;Are colours the same?
162 MOVEQS PC,R14 ;Yes -- return then
163
164 ; --- Sort out what to do now ---
165
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
172
173 ; --- Clear border from old colour ---
174
175 CMP R2,#255 ;Is colour transparent?
176 BEQ %05cb__borderIcon ;Yes -- handle that then
177
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
186
187 ; --- Turn off the `transparent' switch ---
188
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
192
193 ; --- Now turn on the new colour ---
194
195 10 CMP R5,#&FF ;Is new colour transparent?
196 BEQ %15cb__borderIcon ;Yes -- handle that then
197
198 ; --- Sort out a contrasting colour ---
199 ;
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.
206
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 ;!!
217
218 ; --- Now set the icon border ---
219
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
231
232 cb__bwPal DCD &00000000
233 DCD &FFFFFF00
234
235 ; --- Turn on the `transparent' switch ---
236 ;
237 ; `Hey, transparent switch, I really dig you.'
238
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
243
244 ; --- Tidy up and return ---
245
246 50 ADD R13,R13,#80 ;Restore the stack
247 LDMFD R13!,{R0-R5,PC}^ ;And return to caller
248
249 LTORG
250
251 ; --- cb__eventHandler ---
252 ;
253 ; On entry: R0 == dbox event
254 ; R1-R8 depend on event code
255 ; R9 == dbox handle
256 ;
257 ; On exit: --
258 ;
259 ; Use: Handles events onthe colour box.
260
261 cb__eventHandler ROUT
262
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
275
276 ; --- Must be a click on a colour ---
277
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
288
289 ; --- Dialogue box has been closed ---
290
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
295
296 ; --- User clicked the cancel button ---
297
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
305
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
313
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
319
320 ; --- User clicked OK ---
321
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
327
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
333
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
340
341 ; --- User clicked on transparent ---
342
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
354
355 ; --- User pressed a key ---
356
357 50 CMP R1,#&100 ;Is the code in top half?
358 MOVCCS PC,R14 ;No -- ignore the code
359
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
364
365 AND R1,R1,#&FF ;Keep only the bottom byte
366 MOV R14,#0 ;Clear the mask value
367
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
380
381 CMP R14,#0 ;Is R14 now set?
382 LDMEQFD R13!,{R0-R2,PC}^ ;No -- then leave now
383
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
393
394 LTORG
395
396 ; --- cb__dispatch ---
397 ;
398 ; On entry: R0-R8 to be sent to event handler
399 ;
400 ; On exit: --
401 ;
402 ; Use: Sends an event the owner of the colour box.
403
404 cb__dispatch ROUT
405
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
412
413 LTORG
414
415 cb__wSpace DCD 0
416
417 ;----- Events ---------------------------------------------------------------
418
419 ^ 0
420 cbEvent_select # 1 ;User selected a colour
421 ;R1 == colour selected
422
423 ;----- Icon numbers ---------------------------------------------------------
424
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
429
430 ;----- Workspace ------------------------------------------------------------
431
432 ^ 0,R12
433 cb__wStart # 0
434
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
439
440 cb__wSize EQU {VAR}-cb__wStart
441
442 AREA |Sapphire$$LibData|,CODE,READONLY
443
444 DCD cb__wSize
445 DCD cb__wSpace
446 DCD 0
447 DCD 0
448
449 ;----- That's all, folks ----------------------------------------------------
450
451 END