chiark / gitweb /
JPEG support and other fixes from Nick Clark
[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